diff --git a/previews/containerView.png b/previews/containerView.png
deleted file mode 100644
index e95928c..0000000
Binary files a/previews/containerView.png and /dev/null differ
diff --git a/previews/createCt.png b/previews/createCt.png
deleted file mode 100644
index b181615..0000000
Binary files a/previews/createCt.png and /dev/null differ
diff --git a/previews/dcView.png b/previews/dcView.png
deleted file mode 100644
index 0d932ec..0000000
Binary files a/previews/dcView.png and /dev/null differ
diff --git a/previews/folderView.png b/previews/folderView.png
deleted file mode 100644
index f0676b2..0000000
Binary files a/previews/folderView.png and /dev/null differ
diff --git a/previews/nodeView.png b/previews/nodeView.png
deleted file mode 100644
index f5969cc..0000000
Binary files a/previews/nodeView.png and /dev/null differ
diff --git a/previews/placeholder b/previews/placeholder
deleted file mode 100644
index 8b13789..0000000
--- a/previews/placeholder
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/previews/serverView.png b/previews/serverView.png
deleted file mode 100644
index 64080cb..0000000
Binary files a/previews/serverView.png and /dev/null differ
diff --git a/previews/serverViewOptions.png b/previews/serverViewOptions.png
deleted file mode 100644
index 8babf3a..0000000
Binary files a/previews/serverViewOptions.png and /dev/null differ
diff --git a/previews/storageView.png b/previews/storageView.png
deleted file mode 100644
index e1f505e..0000000
Binary files a/previews/storageView.png and /dev/null differ
diff --git a/previews/tasks.png b/previews/tasks.png
deleted file mode 100644
index 74534d0..0000000
Binary files a/previews/tasks.png and /dev/null differ
diff --git a/previews/topView.png b/previews/topView.png
deleted file mode 100644
index 585c885..0000000
Binary files a/previews/topView.png and /dev/null differ
diff --git a/serverside/ddInstall.sh b/serverside/ddInstall.sh
deleted file mode 100644
index a82d1a0..0000000
--- a/serverside/ddInstall.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash
-
-Say () {
- printf "\e[1;34m $1 \e[0m \n";
-}
-
-DotSay () {
- printf "[\e[1;34m*\e[0m] \e[1;34m $1 \e[0m \n";
-}
-
-
-Say '[PVE Discord Dark UI Theme Installer]'
-Say 'Internet connection required to download files'
-Say '>Press any key to begin installation'
-read -p ""
-Say ' '
-DotSay 'Backing up index template file'
-cp /usr/share/pve-manager/index.html.tpl /usr/share/pve-manager/index.html.tpl.bak
-DotSay 'Applying stylesheet..'
-echo " " >> /usr/share/pve-manager/index.html.tpl
-cd /usr/share/pve-manager/css
-wget -O dd_style.css https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/serverside/style.css &> /dev/null
-DotSay 'Applied stylesheet!'
-DotSay 'Downloading images..'
-cd /usr/share/pve-manager/images
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_cephblurp.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_cephwhite.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-cpu.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-hdd.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-ram.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-swap.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-cd.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-display.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-network.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-cloud.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-serial.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-usb.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_icon-pci.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_logo.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_mini-bottom.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_mini-top.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_readme &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_tool-sprites.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_trigger.png &> /dev/null
-wget https://github.com/Weilbyte/PVEDiscordDark/raw/master/images/dd_loading.svg &> /dev/null
-
-DotSay 'Downloaded images!'
-Say ''
-Say 'Installation finished!'
-Say 'o7'
diff --git a/serverside/jsmod/5.4-3.sh b/serverside/jsmod/5.4-3.sh
deleted file mode 100644
index 98b9a8f..0000000
--- a/serverside/jsmod/5.4-3.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-
-Say () {
- printf "\e[1;34m $1 \e[0m \n";
-}
-
-DotSay () {
- printf "[\e[1;34m*\e[0m] \e[1;34m $1 \e[0m \n";
-}
-
-
-Say '[PVE Discord Dark UI Theme JSMOD Installer]'
-Say 'Internet connection REQUIRED.'
-Say '!!ONLY FOR PVE 5.4-3!!'
-Say '>Press any key to begin installation'
-read -p ""
-Say ' '
-DotSay 'Backing up files'
-cp /usr/share/pve-manager/js/pvemanagerlib.js /usr/share/pve-manager/js/pvemanagerlib.js.bak
-cp /usr/share/javascript/extjs/charts.js /usr/share/javascript/extjs/charts.js.bak
-cp /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.bak
-DotSay 'Replacing files with modded versions'
-rm /usr/share/pve-manager/js/pvemanagerlib.js
-wget https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/serverside/jsmod/5.4-3/pvemanagerlib.js -P /usr/share/pve-manager/js/ &> /dev/null
-rm /usr/share/javascript/extjs/charts.js
-wget https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/serverside/jsmod/5.4-3/charts.js -P /usr/share/javascript/extjs/ &> /dev/null
-rm /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
-wget https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/serverside/jsmod/5.4-3/proxmoxlib.js -P /usr/share/javascript/proxmox-widget-toolkit/ &> /dev/null
-DotSay 'Applied successfully.'
-Say ''
-Say 'Installation finished!'
-Say 'o7'
diff --git a/serverside/jsmod/5.4-3/charts.js b/serverside/jsmod/5.4-3/charts.js
deleted file mode 100644
index bc45966..0000000
--- a/serverside/jsmod/5.4-3/charts.js
+++ /dev/null
@@ -1,22013 +0,0 @@
-Ext.define("Ext.draw.ContainerBase", {
- extend: "Ext.panel.Panel",
- requires: ["Ext.window.Window"],
- previewTitleText: "Chart Preview",
- previewAltText: "Chart preview",
- layout: "container",
- addElementListener: function() {
- var b = this,
- a = arguments;
- if (b.rendered) {
- b.el.on.apply(b.el, a)
- } else {
- b.on("render", function() {
- b.el.on.apply(b.el, a)
- })
- }
- },
- removeElementListener: function() {
- var b = this,
- a = arguments;
- if (b.rendered) {
- b.el.un.apply(b.el, a)
- }
- },
- afterRender: function() {
- this.callParent(arguments);
- this.initAnimator()
- },
- getItems: function() {
- var b = this,
- a = b.items;
- if (!a || !a.isMixedCollection) {
- b.initItems()
- }
- return b.items
- },
- onRender: function() {
- this.callParent(arguments);
- this.element = this.el;
- this.innerElement = this.body
- },
- setItems: function(a) {
- this.items = a;
- return a
- },
- setSurfaceSize: function(b, a) {
- this.resizeHandler({
- width: b,
- height: a
- });
- this.renderFrame()
- },
- onResize: function(c, a, b, e) {
- var d = this;
- d.callParent([c, a, b, e]);
- d.setBodySize({
- width: c,
- height: a
- })
- },
- preview: function() {
- var a = this.getImage();
- new Ext.window.Window({
- title: this.previewTitleText,
- closeable: true,
- renderTo: Ext.getBody(),
- autoShow: true,
- maximizeable: true,
- maximized: true,
- border: true,
- layout: {
- type: "hbox",
- pack: "center",
- align: "middle"
- },
- items: {
- xtype: "container",
- items: {
- xtype: "image",
- mode: "img",
- cls: Ext.baseCSSPrefix + "chart-image",
- alt: this.previewAltText,
- src: a.data,
- listeners: {
- afterrender: function() {
- var e = this,
- b = e.imgEl.dom,
- d = a.type === "svg" ? 1 : (window.devicePixelRatio || 1),
- c;
- if (!b.naturalWidth || !b.naturalHeight) {
- b.onload = function() {
- var g = b.naturalWidth,
- f = b.naturalHeight;
- e.setWidth(Math.floor(g / d));
- e.setHeight(Math.floor(f / d))
- }
- } else {
- c = e.getSize();
- e.setWidth(Math.floor(c.width / d));
- e.setHeight(Math.floor(c.height / d))
- }
- }
- }
- }
- }
- })
- },
- privates: {
- getTargetEl: function() {
- return this.innerElement
- },
- reattachToBody: function() {
- var a = this;
- if (a.pendingDetachSize) {
- a.onBodyResize()
- }
- a.pendingDetachSize = false;
- a.callParent()
- }
- }
-});
-Ext.define("Ext.draw.SurfaceBase", {
- extend: "Ext.Widget",
- getOwnerBody: function() {
- return this.ownerCt.body
- },
- destroy: function() {
- var a = this;
- if (a.hasListeners.destroy) {
- a.fireEvent("destroy", a)
- }
- a.callParent()
- }
-});
-Ext.define("Ext.draw.Color", {
- statics: {
- colorToHexRe: /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
- rgbToHexRe: /\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
- rgbaToHexRe: /\s*rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\.\d]+)\)/,
- hexRe: /\s*#([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)\s*/,
- NONE: "none",
- RGBA_NONE: "rgba(0, 0, 0, 0)"
- },
- isColor: true,
- lightnessFactor: 0.2,
- constructor: function(d, b, a, c) {
- this.setRGB(d, b, a, c)
- },
- setRGB: function(e, c, a, d) {
- var b = this;
- b.r = Math.min(255, Math.max(0, e));
- b.g = Math.min(255, Math.max(0, c));
- b.b = Math.min(255, Math.max(0, a));
- if (d === undefined) {
- b.a = 1
- } else {
- b.a = Math.min(1, Math.max(0, d))
- }
- },
- getGrayscale: function() {
- return this.r * 0.3 + this.g * 0.59 + this.b * 0.11
- },
- getHSL: function() {
- var i = this,
- a = i.r / 255,
- f = i.g / 255,
- j = i.b / 255,
- k = Math.max(a, f, j),
- d = Math.min(a, f, j),
- m = k - d,
- e, n = 0,
- c = 0.5 * (k + d);
- if (d !== k) {
- n = (c <= 0.5) ? m / (k + d) : m / (2 - k - d);
- if (a === k) {
- e = 60 * (f - j) / m
- } else {
- if (f === k) {
- e = 120 + 60 * (j - a) / m
- } else {
- e = 240 + 60 * (a - f) / m
- }
- }
- if (e < 0) {
- e += 360
- }
- if (e >= 360) {
- e -= 360
- }
- }
- return [e, n, c]
- },
- getHSV: function() {
- var i = this,
- a = i.r / 255,
- f = i.g / 255,
- j = i.b / 255,
- k = Math.max(a, f, j),
- d = Math.min(a, f, j),
- c = k - d,
- e, m = 0,
- l = k;
- if (d != k) {
- m = l ? c / l : 0;
- if (a === k) {
- e = 60 * (f - j) / c
- } else {
- if (f === k) {
- e = 60 * (j - a) / c + 120
- } else {
- e = 60 * (a - f) / c + 240
- }
- }
- if (e < 0) {
- e += 360
- }
- if (e >= 360) {
- e -= 360
- }
- }
- return [e, m, l]
- },
- setHSL: function(g, f, e) {
- var i = this,
- d = Math.abs,
- j, b, a;
- g = (g % 360 + 360) % 360;
- f = f > 1 ? 1 : f < 0 ? 0 : f;
- e = e > 1 ? 1 : e < 0 ? 0 : e;
- if (f === 0 || g === null) {
- e *= 255;
- i.setRGB(e, e, e)
- } else {
- g /= 60;
- j = f * (1 - d(2 * e - 1));
- b = j * (1 - d(g % 2 - 1));
- a = e - j / 2;
- a *= 255;
- j *= 255;
- b *= 255;
- switch (Math.floor(g)) {
- case 0:
- i.setRGB(j + a, b + a, a);
- break;
- case 1:
- i.setRGB(b + a, j + a, a);
- break;
- case 2:
- i.setRGB(a, j + a, b + a);
- break;
- case 3:
- i.setRGB(a, b + a, j + a);
- break;
- case 4:
- i.setRGB(b + a, a, j + a);
- break;
- case 5:
- i.setRGB(j + a, a, b + a);
- break
- }
- }
- return i
- },
- setHSV: function(f, e, d) {
- var g = this,
- i, b, a;
- f = (f % 360 + 360) % 360;
- e = e > 1 ? 1 : e < 0 ? 0 : e;
- d = d > 1 ? 1 : d < 0 ? 0 : d;
- if (e === 0 || f === null) {
- d *= 255;
- g.setRGB(d, d, d)
- } else {
- f /= 60;
- i = d * e;
- b = i * (1 - Math.abs(f % 2 - 1));
- a = d - i;
- a *= 255;
- i *= 255;
- b *= 255;
- switch (Math.floor(f)) {
- case 0:
- g.setRGB(i + a, b + a, a);
- break;
- case 1:
- g.setRGB(b + a, i + a, a);
- break;
- case 2:
- g.setRGB(a, i + a, b + a);
- break;
- case 3:
- g.setRGB(a, b + a, i + a);
- break;
- case 4:
- g.setRGB(b + a, a, i + a);
- break;
- case 5:
- g.setRGB(i + a, a, b + a);
- break
- }
- }
- return g
- },
- createLighter: function(b) {
- if (!b && b !== 0) {
- b = this.lightnessFactor
- }
- var a = this.getHSL();
- a[2] = Ext.Number.constrain(a[2] + b, 0, 1);
- return Ext.draw.Color.fromHSL(a[0], a[1], a[2])
- },
- createDarker: function(a) {
- if (!a && a !== 0) {
- a = this.lightnessFactor
- }
- return this.createLighter(-a)
- },
- toString: function() {
- var f = this,
- c = Math.round;
- if (f.a === 1) {
- var e = c(f.r).toString(16),
- d = c(f.g).toString(16),
- a = c(f.b).toString(16);
- e = (e.length === 1) ? "0" + e : e;
- d = (d.length === 1) ? "0" + d : d;
- a = (a.length === 1) ? "0" + a : a;
- return ["#", e, d, a].join("")
- } else {
- return "rgba(" + [c(f.r), c(f.g), c(f.b), f.a === 0 ? 0 : f.a.toFixed(15)].join(", ") + ")"
- }
- },
- toHex: function(b) {
- if (Ext.isArray(b)) {
- b = b[0]
- }
- if (!Ext.isString(b)) {
- return ""
- }
- if (b.substr(0, 1) === "#") {
- return b
- }
- var e = Ext.draw.Color.colorToHexRe.exec(b);
- if (Ext.isArray(e)) {
- var f = parseInt(e[2], 10),
- d = parseInt(e[3], 10),
- a = parseInt(e[4], 10),
- c = a | (d << 8) | (f << 16);
- return e[1] + "#" + ("000000" + c.toString(16)).slice(-6)
- } else {
- return ""
- }
- },
- setFromString: function(j) {
- var e, h, f, c, d = 1,
- i = parseInt;
- if (j === Ext.draw.Color.NONE) {
- this.r = this.g = this.b = this.a = 0;
- return this
- }
- if ((j.length === 4 || j.length === 7) && j.substr(0, 1) === "#") {
- e = j.match(Ext.draw.Color.hexRe);
- if (e) {
- h = i(e[1], 16) >> 0;
- f = i(e[2], 16) >> 0;
- c = i(e[3], 16) >> 0;
- if (j.length === 4) {
- h += (h * 16);
- f += (f * 16);
- c += (c * 16)
- }
- }
- } else {
- if ((e = j.match(Ext.draw.Color.rgbToHexRe))) {
- h = +e[1];
- f = +e[2];
- c = +e[3]
- } else {
- if ((e = j.match(Ext.draw.Color.rgbaToHexRe))) {
- h = +e[1];
- f = +e[2];
- c = +e[3];
- d = +e[4]
- } else {
- if (Ext.draw.Color.ColorList.hasOwnProperty(j.toLowerCase())) {
- return this.setFromString(Ext.draw.Color.ColorList[j.toLowerCase()])
- }
- }
- }
- }
- if (typeof h === "undefined") {
- return this
- }
- this.r = h;
- this.g = f;
- this.b = c;
- this.a = d;
- return this
- }
-}, function() {
- var a = new this();
- this.addStatics({
- fly: function(f, e, c, d) {
- switch (arguments.length) {
- case 1:
- a.setFromString(f);
- break;
- case 3:
- case 4:
- a.setRGB(f, e, c, d);
- break;
- default:
- return null
- }
- return a
- },
- ColorList: {
- aliceblue: "#f0f8ff",
- antiquewhite: "#faebd7",
- aqua: "#00ffff",
- aquamarine: "#7fffd4",
- azure: "#f0ffff",
- beige: "#f5f5dc",
- bisque: "#ffe4c4",
- black: "#000000",
- blanchedalmond: "#ffebcd",
- blue: "#0000ff",
- blueviolet: "#8a2be2",
- brown: "#a52a2a",
- burlywood: "#deb887",
- cadetblue: "#5f9ea0",
- chartreuse: "#7fff00",
- chocolate: "#d2691e",
- coral: "#ff7f50",
- cornflowerblue: "#6495ed",
- cornsilk: "#fff8dc",
- crimson: "#dc143c",
- cyan: "#00ffff",
- darkblue: "#00008b",
- darkcyan: "#008b8b",
- darkgoldenrod: "#b8860b",
- darkgray: "#a9a9a9",
- darkgreen: "#006400",
- darkkhaki: "#bdb76b",
- darkmagenta: "#8b008b",
- darkolivegreen: "#556b2f",
- darkorange: "#ff8c00",
- darkorchid: "#9932cc",
- darkred: "#8b0000",
- darksalmon: "#e9967a",
- darkseagreen: "#8fbc8f",
- darkslateblue: "#483d8b",
- darkslategray: "#2f4f4f",
- darkturquoise: "#00ced1",
- darkviolet: "#9400d3",
- deeppink: "#ff1493",
- deepskyblue: "#00bfff",
- dimgray: "#696969",
- dodgerblue: "#1e90ff",
- firebrick: "#b22222",
- floralwhite: "#fffaf0",
- forestgreen: "#228b22",
- fuchsia: "#ff00ff",
- gainsboro: "#dcdcdc",
- ghostwhite: "#f8f8ff",
- gold: "#ffd700",
- goldenrod: "#daa520",
- gray: "#808080",
- green: "#008000",
- greenyellow: "#adff2f",
- honeydew: "#f0fff0",
- hotpink: "#ff69b4",
- indianred: "#cd5c5c",
- indigo: "#4b0082",
- ivory: "#fffff0",
- khaki: "#f0e68c",
- lavender: "#e6e6fa",
- lavenderblush: "#fff0f5",
- lawngreen: "#7cfc00",
- lemonchiffon: "#fffacd",
- lightblue: "#add8e6",
- lightcoral: "#f08080",
- lightcyan: "#e0ffff",
- lightgoldenrodyellow: "#fafad2",
- lightgray: "#d3d3d3",
- lightgrey: "#d3d3d3",
- lightgreen: "#90ee90",
- lightpink: "#ffb6c1",
- lightsalmon: "#ffa07a",
- lightseagreen: "#20b2aa",
- lightskyblue: "#87cefa",
- lightslategray: "#778899",
- lightsteelblue: "#b0c4de",
- lightyellow: "#ffffe0",
- lime: "#00ff00",
- limegreen: "#32cd32",
- linen: "#faf0e6",
- magenta: "#ff00ff",
- maroon: "#800000",
- mediumaquamarine: "#66cdaa",
- mediumblue: "#0000cd",
- mediumorchid: "#ba55d3",
- mediumpurple: "#9370d8",
- mediumseagreen: "#3cb371",
- mediumslateblue: "#7b68ee",
- mediumspringgreen: "#00fa9a",
- mediumturquoise: "#48d1cc",
- mediumvioletred: "#c71585",
- midnightblue: "#191970",
- mintcream: "#f5fffa",
- mistyrose: "#ffe4e1",
- moccasin: "#ffe4b5",
- navajowhite: "#ffdead",
- navy: "#000080",
- oldlace: "#fdf5e6",
- olive: "#808000",
- olivedrab: "#6b8e23",
- orange: "#ffa500",
- orangered: "#ff4500",
- orchid: "#da70d6",
- palegoldenrod: "#eee8aa",
- palegreen: "#98fb98",
- paleturquoise: "#afeeee",
- palevioletred: "#d87093",
- papayawhip: "#ffefd5",
- peachpuff: "#ffdab9",
- peru: "#cd853f",
- pink: "#ffc0cb",
- plum: "#dda0dd",
- powderblue: "#b0e0e6",
- purple: "#800080",
- red: "#ff0000",
- rosybrown: "#bc8f8f",
- royalblue: "#4169e1",
- saddlebrown: "#8b4513",
- salmon: "#fa8072",
- sandybrown: "#f4a460",
- seagreen: "#2e8b57",
- seashell: "#fff5ee",
- sienna: "#a0522d",
- silver: "#c0c0c0",
- skyblue: "#87ceeb",
- slateblue: "#6a5acd",
- slategray: "#708090",
- snow: "#fffafa",
- springgreen: "#00ff7f",
- steelblue: "#4682b4",
- tan: "#d2b48c",
- teal: "#008080",
- thistle: "#d8bfd8",
- tomato: "#ff6347",
- turquoise: "#40e0d0",
- violet: "#ee82ee",
- wheat: "#f5deb3",
- white: "#ffffff",
- whitesmoke: "#f5f5f5",
- yellow: "#ffff00",
- yellowgreen: "#9acd32"
- },
- fromHSL: function(d, c, b) {
- return (new this(0, 0, 0, 0)).setHSL(d, c, b)
- },
- fromHSV: function(d, c, b) {
- return (new this(0, 0, 0, 0)).setHSL(d, c, b)
- },
- fromString: function(b) {
- return (new this(0, 0, 0, 0)).setFromString(b)
- },
- create: function(b) {
- if (b instanceof this) {
- return b
- } else {
- if (Ext.isArray(b)) {
- return new Ext.draw.Color(b[0], b[1], b[2], b[3])
- } else {
- if (Ext.isString(b)) {
- return Ext.draw.Color.fromString(b)
- } else {
- if (arguments.length > 2) {
- return new Ext.draw.Color(arguments[0], arguments[1], arguments[2], arguments[3])
- } else {
- return new Ext.draw.Color(0, 0, 0, 0)
- }
- }
- }
- }
- }
- })
-});
-Ext.define("Ext.draw.sprite.AnimationParser", function() {
- function a(d, c, b) {
- return d + (c - d) * b
- }
- return {
- singleton: true,
- attributeRe: /^url\(#([a-zA-Z\-]+)\)$/,
- requires: ["Ext.draw.Color"],
- color: {
- parseInitial: function(c, b) {
- if (Ext.isString(c)) {
- c = Ext.draw.Color.create(c)
- }
- if (Ext.isString(b)) {
- b = Ext.draw.Color.create(b)
- }
- if ((c instanceof Ext.draw.Color) && (b instanceof Ext.draw.Color)) {
- return [
- [c.r, c.g, c.b, c.a],
- [b.r, b.g, b.b, b.a]
- ]
- } else {
- return [c || b, b || c]
- }
- },
- compute: function(d, c, b) {
- if (!Ext.isArray(d) || !Ext.isArray(c)) {
- return c || d
- } else {
- return [a(d[0], c[0], b), a(d[1], c[1], b), a(d[2], c[2], b), a(d[3], c[3], b)]
- }
- },
- serve: function(c) {
- var b = Ext.draw.Color.fly(c[0], c[1], c[2], c[3]);
- return b.toString()
- }
- },
- number: {
- parse: function(b) {
- return b === null ? null : +b
- },
- compute: function(d, c, b) {
- if (!Ext.isNumber(d) || !Ext.isNumber(c)) {
- return c || d
- } else {
- return a(d, c, b)
- }
- }
- },
- angle: {
- parseInitial: function(c, b) {
- if (b - c > Math.PI) {
- b -= Math.PI * 2
- } else {
- if (b - c < -Math.PI) {
- b += Math.PI * 2
- }
- }
- return [c, b]
- },
- compute: function(d, c, b) {
- if (!Ext.isNumber(d) || !Ext.isNumber(c)) {
- return c || d
- } else {
- return a(d, c, b)
- }
- }
- },
- path: {
- parseInitial: function(m, n) {
- var c = m.toStripes(),
- o = n.toStripes(),
- e, d, k = c.length,
- p = o.length,
- h, f, b, g = o[p - 1],
- l = [g[g.length - 2], g[g.length - 1]];
- for (e = k; e < p; e++) {
- c.push(c[k - 1].slice(0))
- }
- for (e = p; e < k; e++) {
- o.push(l.slice(0))
- }
- b = c.length;
- o.path = n;
- o.temp = new Ext.draw.Path();
- for (e = 0; e < b; e++) {
- h = c[e];
- f = o[e];
- k = h.length;
- p = f.length;
- o.temp.commands.push("M");
- for (d = p; d < k; d += 6) {
- f.push(l[0], l[1], l[0], l[1], l[0], l[1])
- }
- g = o[o.length - 1];
- l = [g[g.length - 2], g[g.length - 1]];
- for (d = k; d < p; d += 6) {
- h.push(l[0], l[1], l[0], l[1], l[0], l[1])
- }
- for (e = 0; e < f.length; e++) {
- f[e] -= h[e]
- }
- for (e = 2; e < f.length; e += 6) {
- o.temp.commands.push("C")
- }
- }
- return [c, o]
- },
- compute: function(c, l, m) {
- if (m >= 1) {
- return l.path
- }
- var e = 0,
- f = c.length,
- d = 0,
- b, k, h, n = l.temp.params,
- g = 0;
- for (; e < f; e++) {
- k = c[e];
- h = l[e];
- b = k.length;
- for (d = 0; d < b; d++) {
- n[g++] = h[d] * m + k[d]
- }
- }
- return l.temp
- }
- },
- data: {
- compute: function(h, j, k, g) {
- var m = h.length - 1,
- b = j.length - 1,
- e = Math.max(m, b),
- d, l, c;
- if (!g || g === h) {
- g = []
- }
- g.length = e + 1;
- for (c = 0; c <= e; c++) {
- d = h[Math.min(c, m)];
- l = j[Math.min(c, b)];
- if (Ext.isNumber(d)) {
- if (!Ext.isNumber(l)) {
- l = 0
- }
- g[c] = (l - d) * k + d
- } else {
- g[c] = l
- }
- }
- return g
- }
- },
- text: {
- compute: function(d, c, b) {
- return d.substr(0, Math.round(d.length * (1 - b))) + c.substr(Math.round(c.length * (1 - b)))
- }
- },
- limited: "number",
- limited01: "number"
- }
-});
-(function() {
- if (!Ext.global.Float32Array) {
- var a = function(d) {
- if (typeof d === "number") {
- this.length = d
- } else {
- if ("length" in d) {
- this.length = d.length;
- for (var c = 0, b = d.length; c < b; c++) {
- this[c] = +d[c]
- }
- }
- }
- };
- a.prototype = [];
- Ext.global.Float32Array = a
- }
-})();
-Ext.define("Ext.draw.Draw", {
- singleton: true,
- radian: Math.PI / 180,
- pi2: Math.PI * 2,
- reflectFn: function(b) {
- return b
- },
- rad: function(a) {
- return (a % 360) * this.radian
- },
- degrees: function(a) {
- return (a / this.radian) % 360
- },
- isBBoxIntersect: function(b, a, c) {
- c = c || 0;
- return (Math.max(b.x, a.x) - c > Math.min(b.x + b.width, a.x + a.width)) || (Math.max(b.y, a.y) - c > Math.min(b.y + b.height, a.y + a.height))
- },
- isPointInBBox: function(a, c, b) {
- return !!b && a >= b.x && a <= (b.x + b.width) && c >= b.y && c <= (b.y + b.height)
- },
- spline: function(m) {
- var e, c, k = m.length,
- b, h, l, f, a = 0,
- g = new Float32Array(m.length),
- n = new Float32Array(m.length * 3 - 2);
- g[0] = 0;
- g[k - 1] = 0;
- for (e = 1; e < k - 1; e++) {
- g[e] = (m[e + 1] + m[e - 1] - 2 * m[e]) - g[e - 1];
- a = 1 / (4 - a);
- g[e] *= a
- }
- for (e = k - 2; e > 0; e--) {
- a = 3.732050807568877 + 48.248711305964385 / (-13.928203230275537 + Math.pow(0.07179676972449123, e));
- g[e] -= g[e + 1] * a
- }
- f = m[0];
- b = f - g[0];
- for (e = 0, c = 0; e < k - 1; c += 3) {
- l = f;
- h = b;
- e++;
- f = m[e];
- b = f - g[e];
- n[c] = l;
- n[c + 1] = (b + 2 * h) / 3;
- n[c + 2] = (b * 2 + h) / 3
- }
- n[c] = f;
- return n
- },
- getAnchors: function(e, d, i, h, t, s, o) {
- o = o || 4;
- var n = Math.PI,
- p = n / 2,
- k = Math.abs,
- a = Math.sin,
- b = Math.cos,
- f = Math.atan,
- r, q, g, j, m, l, v, u, c;
- r = (i - e) / o;
- q = (t - i) / o;
- if ((h >= d && h >= s) || (h <= d && h <= s)) {
- g = j = p
- } else {
- g = f((i - e) / k(h - d));
- if (d < h) {
- g = n - g
- }
- j = f((t - i) / k(h - s));
- if (s < h) {
- j = n - j
- }
- }
- c = p - ((g + j) % (n * 2)) / 2;
- if (c > p) {
- c -= n
- }
- g += c;
- j += c;
- m = i - r * a(g);
- l = h + r * b(g);
- v = i + q * a(j);
- u = h + q * b(j);
- if ((h > d && l < d) || (h < d && l > d)) {
- m += k(d - l) * (m - i) / (l - h);
- l = d
- }
- if ((h > s && u < s) || (h < s && u > s)) {
- v -= k(s - u) * (v - i) / (u - h);
- u = s
- }
- return {
- x1: m,
- y1: l,
- x2: v,
- y2: u
- }
- },
- smooth: function(l, j, o) {
- var k = l.length,
- h, g, c, b, q, p, n, m, f = [],
- e = [],
- d, a;
- for (d = 0; d < k - 1; d++) {
- h = l[d];
- g = j[d];
- if (d === 0) {
- n = h;
- m = g;
- f.push(n);
- e.push(m);
- if (k === 1) {
- break
- }
- }
- c = l[d + 1];
- b = j[d + 1];
- q = l[d + 2];
- p = j[d + 2];
- if (!Ext.isNumber(q + p)) {
- f.push(n, c, c);
- e.push(m, b, b);
- break
- }
- a = this.getAnchors(h, g, c, b, q, p, o);
- f.push(n, a.x1, c);
- e.push(m, a.y1, b);
- n = a.x2;
- m = a.y2
- }
- return {
- smoothX: f,
- smoothY: e
- }
- },
- beginUpdateIOS: Ext.os.is.iOS ? function() {
- this.iosUpdateEl = Ext.getBody().createChild({
- style: "position: absolute; top: 0px; bottom: 0px; left: 0px; right: 0px; background: rgba(0,0,0,0.001); z-index: 100000"
- })
- } : Ext.emptyFn,
- endUpdateIOS: function() {
- this.iosUpdateEl = Ext.destroy(this.iosUpdateEl)
- }
-});
-Ext.define("Ext.draw.gradient.Gradient", {
- requires: ["Ext.draw.Color"],
- isGradient: true,
- config: {
- stops: []
- },
- applyStops: function(f) {
- var e = [],
- d = f.length,
- c, b, a;
- for (c = 0; c < d; c++) {
- b = f[c];
- a = b.color;
- if (!(a && a.isColor)) {
- a = Ext.draw.Color.fly(a || Ext.draw.Color.NONE)
- }
- e.push({
- offset: Math.min(1, Math.max(0, "offset" in b ? b.offset : b.position || 0)),
- color: a.toString()
- })
- }
- e.sort(function(h, g) {
- return h.offset - g.offset
- });
- return e
- },
- onClassExtended: function(a, b) {
- if (!b.alias && b.type) {
- b.alias = "gradient." + b.type
- }
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- generateGradient: Ext.emptyFn
-});
-Ext.define("Ext.draw.gradient.GradientDefinition", {
- singleton: true,
- urlStringRe: /^url\(#([\w\-]+)\)$/,
- gradients: {},
- add: function(a) {
- var b = this.gradients,
- c, e, d;
- for (c = 0, e = a.length; c < e; c++) {
- d = a[c];
- if (Ext.isString(d.id)) {
- b[d.id] = d
- }
- }
- },
- get: function(d) {
- var a = this.gradients,
- b = d.match(this.urlStringRe),
- c;
- if (b && b[1] && (c = a[b[1]])) {
- return c || d
- }
- return d
- }
-});
-Ext.define("Ext.draw.sprite.AttributeParser", {
- singleton: true,
- attributeRe: /^url\(#([a-zA-Z\-]+)\)$/,
- requires: ["Ext.draw.Color", "Ext.draw.gradient.GradientDefinition"],
- "default": Ext.identityFn,
- string: function(a) {
- return String(a)
- },
- number: function(a) {
- if (Ext.isNumber(+a)) {
- return a
- }
- },
- angle: function(a) {
- if (Ext.isNumber(a)) {
- a %= Math.PI * 2;
- if (a < -Math.PI) {
- a += Math.PI * 2
- } else {
- if (a >= Math.PI) {
- a -= Math.PI * 2
- }
- }
- return a
- }
- },
- data: function(a) {
- if (Ext.isArray(a)) {
- return a.slice()
- } else {
- if (a instanceof Float32Array) {
- return new Float32Array(a)
- }
- }
- },
- bool: function(a) {
- return !!a
- },
- color: function(a) {
- if (a instanceof Ext.draw.Color) {
- return a.toString()
- } else {
- if (a instanceof Ext.draw.gradient.Gradient) {
- return a
- } else {
- if (!a) {
- return Ext.draw.Color.NONE
- } else {
- if (Ext.isString(a)) {
- if (a.substr(0, 3) === "url") {
- a = Ext.draw.gradient.GradientDefinition.get(a);
- if (Ext.isString(a)) {
- return a
- }
- } else {
- return Ext.draw.Color.fly(a).toString()
- }
- }
- }
- }
- }
- if (a.type === "linear") {
- return Ext.create("Ext.draw.gradient.Linear", a)
- } else {
- if (a.type === "radial") {
- return Ext.create("Ext.draw.gradient.Radial", a)
- } else {
- if (a.type === "pattern") {
- return Ext.create("Ext.draw.gradient.Pattern", a)
- } else {
- return Ext.draw.Color.NONE
- }
- }
- }
- },
- limited: function(a, b) {
- return function(c) {
- c = +c;
- return Ext.isNumber(c) ? Math.min(Math.max(c, a), b) : undefined
- }
- },
- limited01: function(a) {
- a = +a;
- return Ext.isNumber(a) ? Math.min(Math.max(a, 0), 1) : undefined
- },
- enums: function() {
- var d = {},
- a = Array.prototype.slice.call(arguments, 0),
- b, c;
- for (b = 0, c = a.length; b < c; b++) {
- d[a[b]] = true
- }
- return function(e) {
- return e in d ? e : undefined
- }
- }
-});
-Ext.define("Ext.draw.sprite.AttributeDefinition", {
- requires: ["Ext.draw.sprite.AttributeParser", "Ext.draw.sprite.AnimationParser"],
- config: {
- defaults: {
- $value: {},
- lazy: true
- },
- aliases: {},
- animationProcessors: {},
- processors: {
- $value: {},
- lazy: true
- },
- dirtyTriggers: {},
- triggers: {},
- updaters: {}
- },
- inheritableStatics: {
- processorFactoryRe: /^(\w+)\(([\w\-,]*)\)$/
- },
- spriteClass: null,
- constructor: function(a) {
- var b = this;
- b.initConfig(a)
- },
- applyDefaults: function(b, a) {
- a = Ext.apply(a || {}, this.normalize(b));
- return a
- },
- applyAliases: function(b, a) {
- return Ext.apply(a || {}, b)
- },
- applyProcessors: function(e, i) {
- this.getAnimationProcessors();
- var j = i || {},
- h = Ext.draw.sprite.AttributeParser,
- a = this.self.processorFactoryRe,
- g = {},
- d, b, c, f;
- for (b in e) {
- f = e[b];
- if (typeof f === "string") {
- c = f.match(a);
- if (c) {
- f = h[c[1]].apply(h, c[2].split(","))
- } else {
- if (h[f]) {
- g[b] = f;
- d = true;
- f = h[f]
- }
- }
- }
- j[b] = f
- }
- if (d) {
- this.setAnimationProcessors(g)
- }
- return j
- },
- applyAnimationProcessors: function(c, a) {
- var e = Ext.draw.sprite.AnimationParser,
- b, d;
- if (!a) {
- a = {}
- }
- for (b in c) {
- d = c[b];
- if (d === "none") {
- a[b] = null
- } else {
- if (Ext.isString(d) && !(b in a)) {
- if (d in e) {
- while (Ext.isString(e[d])) {
- d = e[d]
- }
- a[b] = e[d]
- }
- } else {
- if (Ext.isObject(d)) {
- a[b] = d
- }
- }
- }
- }
- return a
- },
- updateDirtyTriggers: function(a) {
- this.setTriggers(a)
- },
- applyTriggers: function(b, c) {
- if (!c) {
- c = {}
- }
- for (var a in b) {
- c[a] = b[a].split(",")
- }
- return c
- },
- applyUpdaters: function(b, a) {
- return Ext.apply(a || {}, b)
- },
- batchedNormalize: function(f, n) {
- if (!f) {
- return {}
- }
- var j = this.getProcessors(),
- d = this.getAliases(),
- a = f.translation || f.translate,
- o = {},
- g, h, b, e, p, c, m, l, k;
- if ("rotation" in f) {
- p = f.rotation
- } else {
- p = ("rotate" in f) ? f.rotate : undefined
- }
- if ("scaling" in f) {
- c = f.scaling
- } else {
- c = ("scale" in f) ? f.scale : undefined
- }
- if (typeof c !== "undefined") {
- if (Ext.isNumber(c)) {
- o.scalingX = c;
- o.scalingY = c
- } else {
- if ("x" in c) {
- o.scalingX = c.x
- }
- if ("y" in c) {
- o.scalingY = c.y
- }
- if ("centerX" in c) {
- o.scalingCenterX = c.centerX
- }
- if ("centerY" in c) {
- o.scalingCenterY = c.centerY
- }
- }
- }
- if (typeof p !== "undefined") {
- if (Ext.isNumber(p)) {
- p = Ext.draw.Draw.rad(p);
- o.rotationRads = p
- } else {
- if ("rads" in p) {
- o.rotationRads = p.rads
- } else {
- if ("degrees" in p) {
- if (Ext.isArray(p.degrees)) {
- o.rotationRads = Ext.Array.map(p.degrees, function(i) {
- return Ext.draw.Draw.rad(i)
- })
- } else {
- o.rotationRads = Ext.draw.Draw.rad(p.degrees)
- }
- }
- }
- if ("centerX" in p) {
- o.rotationCenterX = p.centerX
- }
- if ("centerY" in p) {
- o.rotationCenterY = p.centerY
- }
- }
- }
- if (typeof a !== "undefined") {
- if ("x" in a) {
- o.translationX = a.x
- }
- if ("y" in a) {
- o.translationY = a.y
- }
- }
- if ("matrix" in f) {
- m = Ext.draw.Matrix.create(f.matrix);
- k = m.split();
- o.matrix = m;
- o.rotationRads = k.rotation;
- o.rotationCenterX = 0;
- o.rotationCenterY = 0;
- o.scalingX = k.scaleX;
- o.scalingY = k.scaleY;
- o.scalingCenterX = 0;
- o.scalingCenterY = 0;
- o.translationX = k.translateX;
- o.translationY = k.translateY
- }
- for (b in f) {
- e = f[b];
- if (typeof e === "undefined") {
- continue
- } else {
- if (Ext.isArray(e)) {
- if (b in d) {
- b = d[b]
- }
- if (b in j) {
- o[b] = [];
- for (g = 0, h = e.length; g < h; g++) {
- l = j[b].call(this, e[g]);
- if (typeof l !== "undefined") {
- o[b][g] = l
- }
- }
- } else {
- if (n) {
- o[b] = e
- }
- }
- } else {
- if (b in d) {
- b = d[b]
- }
- if (b in j) {
- e = j[b].call(this, e);
- if (typeof e !== "undefined") {
- o[b] = e
- }
- } else {
- if (n) {
- o[b] = e
- }
- }
- }
- }
- }
- return o
- },
- normalize: function(i, j) {
- if (!i) {
- return {}
- }
- var f = this.getProcessors(),
- d = this.getAliases(),
- a = i.translation || i.translate,
- k = {},
- b, e, l, c, h, g;
- if ("rotation" in i) {
- l = i.rotation
- } else {
- l = ("rotate" in i) ? i.rotate : undefined
- }
- if ("scaling" in i) {
- c = i.scaling
- } else {
- c = ("scale" in i) ? i.scale : undefined
- }
- if (a) {
- if ("x" in a) {
- k.translationX = a.x
- }
- if ("y" in a) {
- k.translationY = a.y
- }
- }
- if (typeof c !== "undefined") {
- if (Ext.isNumber(c)) {
- k.scalingX = c;
- k.scalingY = c
- } else {
- if ("x" in c) {
- k.scalingX = c.x
- }
- if ("y" in c) {
- k.scalingY = c.y
- }
- if ("centerX" in c) {
- k.scalingCenterX = c.centerX
- }
- if ("centerY" in c) {
- k.scalingCenterY = c.centerY
- }
- }
- }
- if (typeof l !== "undefined") {
- if (Ext.isNumber(l)) {
- l = Ext.draw.Draw.rad(l);
- k.rotationRads = l
- } else {
- if ("rads" in l) {
- k.rotationRads = l.rads
- } else {
- if ("degrees" in l) {
- k.rotationRads = Ext.draw.Draw.rad(l.degrees)
- }
- }
- if ("centerX" in l) {
- k.rotationCenterX = l.centerX
- }
- if ("centerY" in l) {
- k.rotationCenterY = l.centerY
- }
- }
- }
- if ("matrix" in i) {
- h = Ext.draw.Matrix.create(i.matrix);
- g = h.split();
- k.matrix = h;
- k.rotationRads = g.rotation;
- k.rotationCenterX = 0;
- k.rotationCenterY = 0;
- k.scalingX = g.scaleX;
- k.scalingY = g.scaleY;
- k.scalingCenterX = 0;
- k.scalingCenterY = 0;
- k.translationX = g.translateX;
- k.translationY = g.translateY
- }
- for (b in i) {
- e = i[b];
- if (typeof e === "undefined") {
- continue
- }
- if (b in d) {
- b = d[b]
- }
- if (b in f) {
- e = f[b].call(this, e);
- if (typeof e !== "undefined") {
- k[b] = e
- }
- } else {
- if (j) {
- k[b] = e
- }
- }
- }
- return k
- },
- setBypassingNormalization: function(a, c, b) {
- return c.pushDown(a, b)
- },
- set: function(a, c, b) {
- b = this.normalize(b);
- return this.setBypassingNormalization(a, c, b)
- }
-});
-Ext.define("Ext.draw.Matrix", {
- isMatrix: true,
- statics: {
- createAffineMatrixFromTwoPair: function(h, t, g, s, k, o, i, j) {
- var v = g - h,
- u = s - t,
- e = i - k,
- q = j - o,
- d = 1 / (v * v + u * u),
- p = v * e + u * q,
- n = e * u - v * q,
- m = -p * h - n * t,
- l = n * h - p * t;
- return new this(p * d, -n * d, n * d, p * d, m * d + k, l * d + o)
- },
- createPanZoomFromTwoPair: function(q, e, p, c, h, s, n, g) {
- if (arguments.length === 2) {
- return this.createPanZoomFromTwoPair.apply(this, q.concat(e))
- }
- var k = p - q,
- j = c - e,
- d = (q + p) * 0.5,
- b = (e + c) * 0.5,
- o = n - h,
- a = g - s,
- f = (h + n) * 0.5,
- l = (s + g) * 0.5,
- m = k * k + j * j,
- i = o * o + a * a,
- t = Math.sqrt(i / m);
- return new this(t, 0, 0, t, f - t * d, l - t * b)
- },
- fly: (function() {
- var a = null,
- b = function(c) {
- a.elements = c;
- return a
- };
- return function(c) {
- if (!a) {
- a = new Ext.draw.Matrix()
- }
- a.elements = c;
- Ext.draw.Matrix.fly = b;
- return a
- }
- })(),
- create: function(a) {
- if (a instanceof this) {
- return a
- }
- return new this(a)
- }
- },
- constructor: function(e, d, a, f, c, b) {
- if (e && e.length === 6) {
- this.elements = e.slice()
- } else {
- if (e !== undefined) {
- this.elements = [e, d, a, f, c, b]
- } else {
- this.elements = [1, 0, 0, 1, 0, 0]
- }
- }
- },
- prepend: function(a, l, h, g, m, k) {
- var b = this.elements,
- d = b[0],
- j = b[1],
- e = b[2],
- c = b[3],
- i = b[4],
- f = b[5];
- b[0] = a * d + h * j;
- b[1] = l * d + g * j;
- b[2] = a * e + h * c;
- b[3] = l * e + g * c;
- b[4] = a * i + h * f + m;
- b[5] = l * i + g * f + k;
- return this
- },
- prependMatrix: function(a) {
- return this.prepend.apply(this, a.elements)
- },
- append: function(a, l, h, g, m, k) {
- var b = this.elements,
- d = b[0],
- j = b[1],
- e = b[2],
- c = b[3],
- i = b[4],
- f = b[5];
- b[0] = a * d + l * e;
- b[1] = a * j + l * c;
- b[2] = h * d + g * e;
- b[3] = h * j + g * c;
- b[4] = m * d + k * e + i;
- b[5] = m * j + k * c + f;
- return this
- },
- appendMatrix: function(a) {
- return this.append.apply(this, a.elements)
- },
- set: function(f, e, a, g, c, b) {
- var d = this.elements;
- d[0] = f;
- d[1] = e;
- d[2] = a;
- d[3] = g;
- d[4] = c;
- d[5] = b;
- return this
- },
- inverse: function(i) {
- var g = this.elements,
- o = g[0],
- m = g[1],
- l = g[2],
- k = g[3],
- j = g[4],
- h = g[5],
- n = 1 / (o * k - m * l);
- o *= n;
- m *= n;
- l *= n;
- k *= n;
- if (i) {
- i.set(k, -m, -l, o, l * h - k * j, m * j - o * h);
- return i
- } else {
- return new Ext.draw.Matrix(k, -m, -l, o, l * h - k * j, m * j - o * h)
- }
- },
- translate: function(a, c, b) {
- if (b) {
- return this.prepend(1, 0, 0, 1, a, c)
- } else {
- return this.append(1, 0, 0, 1, a, c)
- }
- },
- scale: function(f, e, c, a, b) {
- var d = this;
- if (e == null) {
- e = f
- }
- if (c === undefined) {
- c = 0
- }
- if (a === undefined) {
- a = 0
- }
- if (b) {
- return d.prepend(f, 0, 0, e, c - c * f, a - a * e)
- } else {
- return d.append(f, 0, 0, e, c - c * f, a - a * e)
- }
- },
- rotate: function(g, e, c, b) {
- var d = this,
- f = Math.cos(g),
- a = Math.sin(g);
- e = e || 0;
- c = c || 0;
- if (b) {
- return d.prepend(f, a, -a, f, e - f * e + c * a, c - f * c - e * a)
- } else {
- return d.append(f, a, -a, f, e - f * e + c * a, c - f * c - e * a)
- }
- },
- rotateFromVector: function(a, h, c) {
- var e = this,
- g = Math.sqrt(a * a + h * h),
- f = a / g,
- b = h / g;
- if (c) {
- return e.prepend(f, b, -b, f, 0, 0)
- } else {
- return e.append(f, b, -b, f, 0, 0)
- }
- },
- clone: function() {
- return new Ext.draw.Matrix(this.elements)
- },
- flipX: function() {
- return this.append(-1, 0, 0, 1, 0, 0)
- },
- flipY: function() {
- return this.append(1, 0, 0, -1, 0, 0)
- },
- skewX: function(a) {
- return this.append(1, 0, Math.tan(a), 1, 0, 0)
- },
- skewY: function(a) {
- return this.append(1, Math.tan(a), 0, 1, 0, 0)
- },
- shearX: function(a) {
- return this.append(1, 0, a, 1, 0, 0)
- },
- shearY: function(a) {
- return this.append(1, a, 0, 1, 0, 0)
- },
- reset: function() {
- return this.set(1, 0, 0, 1, 0, 0)
- },
- precisionCompensate: function(j, g) {
- var c = this.elements,
- f = c[0],
- e = c[1],
- i = c[2],
- h = c[3],
- d = c[4],
- b = c[5],
- a = e * i - f * h;
- g.b = j * e / f;
- g.c = j * i / h;
- g.d = j;
- g.xx = f / j;
- g.yy = h / j;
- g.dx = (b * f * i - d * f * h) / a / j;
- g.dy = (d * e * h - b * f * h) / a / j
- },
- precisionCompensateRect: function(j, g) {
- var b = this.elements,
- f = b[0],
- e = b[1],
- i = b[2],
- h = b[3],
- c = b[4],
- a = b[5],
- d = i / f;
- g.b = j * e / f;
- g.c = j * d;
- g.d = j * h / f;
- g.xx = f / j;
- g.yy = f / j;
- g.dx = (a * i - c * h) / (e * d - h) / j;
- g.dy = -(a * f - c * e) / (e * d - h) / j
- },
- x: function(a, c) {
- var b = this.elements;
- return a * b[0] + c * b[2] + b[4]
- },
- y: function(a, c) {
- var b = this.elements;
- return a * b[1] + c * b[3] + b[5]
- },
- get: function(b, a) {
- return +this.elements[b + a * 2].toFixed(4)
- },
- transformPoint: function(b) {
- var c = this.elements,
- a, d;
- if (b.isPoint) {
- a = b.x;
- d = b.y
- } else {
- a = b[0];
- d = b[1]
- }
- return [a * c[0] + d * c[2] + c[4], a * c[1] + d * c[3] + c[5]]
- },
- transformBBox: function(q, i, j) {
- var b = this.elements,
- d = q.x,
- r = q.y,
- g = q.width * 0.5,
- o = q.height * 0.5,
- a = b[0],
- s = b[1],
- n = b[2],
- k = b[3],
- e = d + g,
- c = r + o,
- p, f, m;
- if (i) {
- g -= i;
- o -= i;
- m = [Math.sqrt(b[0] * b[0] + b[2] * b[2]), Math.sqrt(b[1] * b[1] + b[3] * b[3])];
- p = Math.abs(g * a) + Math.abs(o * n) + Math.abs(m[0] * i);
- f = Math.abs(g * s) + Math.abs(o * k) + Math.abs(m[1] * i)
- } else {
- p = Math.abs(g * a) + Math.abs(o * n);
- f = Math.abs(g * s) + Math.abs(o * k)
- }
- if (!j) {
- j = {}
- }
- j.x = e * a + c * n + b[4] - p;
- j.y = e * s + c * k + b[5] - f;
- j.width = p + p;
- j.height = f + f;
- return j
- },
- transformList: function(e) {
- var b = this.elements,
- a = b[0],
- h = b[2],
- l = b[4],
- k = b[1],
- g = b[3],
- j = b[5],
- f = e.length,
- c, d;
- for (d = 0; d < f; d++) {
- c = e[d];
- e[d] = [c[0] * a + c[1] * h + l, c[0] * k + c[1] * g + j]
- }
- return e
- },
- isIdentity: function() {
- var a = this.elements;
- return a[0] === 1 && a[1] === 0 && a[2] === 0 && a[3] === 1 && a[4] === 0 && a[5] === 0
- },
- isEqual: function(a) {
- var c = a && a.isMatrix ? a.elements : a,
- b = this.elements;
- return b[0] === c[0] && b[1] === c[1] && b[2] === c[2] && b[3] === c[3] && b[4] === c[4] && b[5] === c[5]
- },
- equals: function(a) {
- return this.isEqual(a)
- },
- toArray: function() {
- var a = this.elements;
- return [a[0], a[2], a[4], a[1], a[3], a[5]]
- },
- toVerticalArray: function() {
- return this.elements.slice()
- },
- toString: function() {
- var a = this;
- return [a.get(0, 0), a.get(0, 1), a.get(1, 0), a.get(1, 1), a.get(2, 0), a.get(2, 1)].join(",")
- },
- toContext: function(a) {
- a.transform.apply(a, this.elements);
- return this
- },
- toSvg: function() {
- var a = this.elements;
- return "matrix(" + a[0].toFixed(9) + "," + a[1].toFixed(9) + "," + a[2].toFixed(9) + "," + a[3].toFixed(9) + "," + a[4].toFixed(9) + "," + a[5].toFixed(9) + ")"
- },
- getScaleX: function() {
- var a = this.elements;
- return Math.sqrt(a[0] * a[0] + a[2] * a[2])
- },
- getScaleY: function() {
- var a = this.elements;
- return Math.sqrt(a[1] * a[1] + a[3] * a[3])
- },
- getXX: function() {
- return this.elements[0]
- },
- getXY: function() {
- return this.elements[1]
- },
- getYX: function() {
- return this.elements[2]
- },
- getYY: function() {
- return this.elements[3]
- },
- getDX: function() {
- return this.elements[4]
- },
- getDY: function() {
- return this.elements[5]
- },
- split: function() {
- var b = this.elements,
- d = b[0],
- c = b[1],
- e = b[3],
- a = {
- translateX: b[4],
- translateY: b[5]
- };
- a.rotate = a.rotation = Math.atan2(c, d);
- a.scaleX = d / Math.cos(a.rotate);
- a.scaleY = e / d * a.scaleX;
- return a
- }
-}, function() {
- function b(e, c, d) {
- e[c] = {
- get: function() {
- return this.elements[d]
- },
- set: function(f) {
- this.elements[d] = f
- }
- }
- }
- if (Object.defineProperties) {
- var a = {};
- b(a, "a", 0);
- b(a, "b", 1);
- b(a, "c", 2);
- b(a, "d", 3);
- b(a, "e", 4);
- b(a, "f", 5);
- Object.defineProperties(this.prototype, a)
- }
- this.prototype.multiply = this.prototype.appendMatrix
-});
-Ext.define("Ext.draw.modifier.Modifier", {
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- previous: null,
- next: null,
- sprite: null
- },
- constructor: function(a) {
- this.mixins.observable.constructor.call(this, a)
- },
- updateNext: function(a) {
- if (a) {
- a.setPrevious(this)
- }
- },
- updatePrevious: function(a) {
- if (a) {
- a.setNext(this)
- }
- },
- prepareAttributes: function(a) {
- if (this._previous) {
- this._previous.prepareAttributes(a)
- }
- },
- popUp: function(a, b) {
- if (this._next) {
- this._next.popUp(a, b)
- } else {
- Ext.apply(a, b)
- }
- },
- pushDown: function(a, c) {
- if (this._previous) {
- return this._previous.pushDown(a, c)
- } else {
- for (var b in c) {
- if (c[b] === a[b]) {
- delete c[b]
- }
- }
- return c
- }
- }
-});
-Ext.define("Ext.draw.modifier.Target", {
- requires: ["Ext.draw.Matrix"],
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.target",
- statics: {
- uniqueId: 0
- },
- prepareAttributes: function(a) {
- var b = this.getPrevious();
- if (b) {
- b.prepareAttributes(a)
- }
- a.attributeId = "attribute-" + Ext.draw.modifier.Target.uniqueId++;
- if (!a.hasOwnProperty("canvasAttributes")) {
- a.bbox = {
- plain: {
- dirty: true
- },
- transform: {
- dirty: true
- }
- };
- a.dirty = true;
- a.pendingUpdaters = {};
- a.canvasAttributes = {};
- a.matrix = new Ext.draw.Matrix();
- a.inverseMatrix = new Ext.draw.Matrix()
- }
- },
- applyChanges: function(f, k) {
- Ext.apply(f, k);
- var l = this.getSprite(),
- o = f.pendingUpdaters,
- h = l.self.def.getTriggers(),
- p, a, m, b, e, n, d, c, g;
- for (b in k) {
- e = true;
- if ((p = h[b])) {
- l.scheduleUpdaters(f, p, [b])
- }
- if (f.template && k.removeFromInstance && k.removeFromInstance[b]) {
- delete f[b]
- }
- }
- if (!e) {
- return
- }
- if (o.canvas) {
- n = o.canvas;
- delete o.canvas;
- for (d = 0, g = n.length; d < g; d++) {
- b = n[d];
- f.canvasAttributes[b] = f[b]
- }
- }
- if (f.hasOwnProperty("children")) {
- a = f.children;
- for (d = 0, g = a.length; d < g; d++) {
- m = a[d];
- Ext.apply(m.pendingUpdaters, o);
- if (n) {
- for (c = 0; c < n.length; c++) {
- b = n[c];
- m.canvasAttributes[b] = m[b]
- }
- }
- l.callUpdaters(m)
- }
- }
- l.setDirty(true);
- l.callUpdaters(f)
- },
- popUp: function(a, b) {
- this.applyChanges(a, b)
- },
- pushDown: function(a, b) {
- var c = this.getPrevious();
- if (c) {
- b = c.pushDown(a, b)
- }
- this.applyChanges(a, b);
- return b
- }
-});
-Ext.define("Ext.draw.TimingFunctions", function() {
- var g = Math.pow,
- j = Math.sin,
- m = Math.cos,
- l = Math.sqrt,
- e = Math.PI,
- b = ["quad", "cube", "quart", "quint"],
- c = {
- pow: function(o, i) {
- return g(o, i || 6)
- },
- expo: function(i) {
- return g(2, 8 * (i - 1))
- },
- circ: function(i) {
- return 1 - l(1 - i * i)
- },
- sine: function(i) {
- return 1 - j((1 - i) * e / 2)
- },
- back: function(i, o) {
- o = o || 1.616;
- return i * i * ((o + 1) * i - o)
- },
- bounce: function(q) {
- for (var o = 0, i = 1; 1; o += i, i /= 2) {
- if (q >= (7 - 4 * o) / 11) {
- return i * i - g((11 - 6 * o - 11 * q) / 4, 2)
- }
- }
- },
- elastic: function(o, i) {
- return g(2, 10 * --o) * m(20 * o * e * (i || 1) / 3)
- }
- },
- k = {},
- a, f, d;
-
- function h(i) {
- return function(o) {
- return g(o, i)
- }
- }
-
- function n(i, o) {
- k[i + "In"] = function(p) {
- return o(p)
- };
- k[i + "Out"] = function(p) {
- return 1 - o(1 - p)
- };
- k[i + "InOut"] = function(p) {
- return (p <= 0.5) ? o(2 * p) / 2 : (2 - o(2 * (1 - p))) / 2
- }
- }
- for (d = 0, f = b.length; d < f; ++d) {
- c[b[d]] = h(d + 2)
- }
- for (a in c) {
- n(a, c[a])
- }
- k.linear = Ext.identityFn;
- k.easeIn = k.quadIn;
- k.easeOut = k.quadOut;
- k.easeInOut = k.quadInOut;
- return {
- singleton: true,
- easingMap: k
- }
-}, function(a) {
- Ext.apply(a, a.easingMap)
-});
-Ext.define("Ext.draw.Animator", {
- uses: ["Ext.draw.Draw"],
- singleton: true,
- frameCallbacks: {},
- frameCallbackId: 0,
- scheduled: 0,
- frameStartTimeOffset: Ext.now(),
- animations: [],
- running: false,
- animationTime: function() {
- return Ext.AnimationQueue.frameStartTime - this.frameStartTimeOffset
- },
- add: function(b) {
- var a = this;
- if (!a.contains(b)) {
- a.animations.push(b);
- a.ignite();
- if ("fireEvent" in b) {
- b.fireEvent("animationstart", b)
- }
- }
- },
- remove: function(d) {
- var c = this,
- e = c.animations,
- b = 0,
- a = e.length;
- for (; b < a; ++b) {
- if (e[b] === d) {
- e.splice(b, 1);
- if ("fireEvent" in d) {
- d.fireEvent("animationend", d)
- }
- return
- }
- }
- },
- contains: function(a) {
- return Ext.Array.indexOf(this.animations, a) > -1
- },
- empty: function() {
- return this.animations.length === 0
- },
- step: function(d) {
- var c = this,
- f = c.animations,
- e, a = 0,
- b = f.length;
- for (; a < b; a++) {
- e = f[a];
- e.step(d);
- if (!e.animating) {
- f.splice(a, 1);
- a--;
- b--;
- if (e.fireEvent) {
- e.fireEvent("animationend", e)
- }
- }
- }
- },
- schedule: function(c, a) {
- a = a || this;
- var b = "frameCallback" + (this.frameCallbackId++);
- if (Ext.isString(c)) {
- c = a[c]
- }
- Ext.draw.Animator.frameCallbacks[b] = {
- fn: c,
- scope: a,
- once: true
- };
- this.scheduled++;
- Ext.draw.Animator.ignite();
- return b
- },
- scheduleIf: function(e, b) {
- b = b || this;
- var c = Ext.draw.Animator.frameCallbacks,
- a, d;
- if (Ext.isString(e)) {
- e = b[e]
- }
- for (d in c) {
- a = c[d];
- if (a.once && a.fn === e && a.scope === b) {
- return null
- }
- }
- return this.schedule(e, b)
- },
- cancel: function(a) {
- if (Ext.draw.Animator.frameCallbacks[a] && Ext.draw.Animator.frameCallbacks[a].once) {
- this.scheduled--;
- delete Ext.draw.Animator.frameCallbacks[a]
- }
- },
- addFrameCallback: function(c, a) {
- a = a || this;
- if (Ext.isString(c)) {
- c = a[c]
- }
- var b = "frameCallback" + (this.frameCallbackId++);
- Ext.draw.Animator.frameCallbacks[b] = {
- fn: c,
- scope: a
- };
- return b
- },
- removeFrameCallback: function(a) {
- delete Ext.draw.Animator.frameCallbacks[a]
- },
- fireFrameCallbacks: function() {
- var c = this.frameCallbacks,
- d, b, a;
- for (d in c) {
- a = c[d];
- b = a.fn;
- if (Ext.isString(b)) {
- b = a.scope[b]
- }
- b.call(a.scope);
- if (c[d] && a.once) {
- this.scheduled--;
- delete c[d]
- }
- }
- },
- handleFrame: function() {
- this.step(this.animationTime());
- this.fireFrameCallbacks();
- if (!this.scheduled && this.empty()) {
- Ext.AnimationQueue.stop(this.handleFrame, this);
- this.running = false;
- Ext.draw.Draw.endUpdateIOS()
- }
- },
- ignite: function() {
- if (!this.running) {
- this.running = true;
- Ext.AnimationQueue.start(this.handleFrame, this);
- Ext.draw.Draw.beginUpdateIOS()
- }
- }
-});
-Ext.define("Ext.draw.modifier.Animation", {
- requires: ["Ext.draw.TimingFunctions", "Ext.draw.Animator"],
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.animation",
- config: {
- easing: Ext.identityFn,
- duration: 0,
- customEasings: {},
- customDurations: {},
- customDuration: null
- },
- constructor: function(a) {
- var b = this;
- b.anyAnimation = b.anySpecialAnimations = false;
- b.animating = 0;
- b.animatingPool = [];
- b.callParent([a])
- },
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("timers")) {
- a.animating = false;
- a.timers = {};
- a.animationOriginal = Ext.Object.chain(a);
- a.animationOriginal.prototype = a
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.animationOriginal)
- }
- },
- updateSprite: function(a) {
- this.setConfig(a.config.fx)
- },
- updateDuration: function(a) {
- this.anyAnimation = a > 0
- },
- applyEasing: function(a) {
- if (typeof a === "string") {
- a = Ext.draw.TimingFunctions.easingMap[a]
- }
- return a
- },
- applyCustomEasings: function(a, e) {
- e = e || {};
- var g, d, b, h, c, f;
- for (d in a) {
- g = true;
- h = a[d];
- b = d.split(",");
- if (typeof h === "string") {
- h = Ext.draw.TimingFunctions.easingMap[h]
- }
- for (c = 0, f = b.length; c < f; c++) {
- e[b[c]] = h
- }
- }
- if (g) {
- this.anySpecialAnimations = g
- }
- return e
- },
- setEasingOn: function(a, e) {
- a = Ext.Array.from(a).slice();
- var c = {},
- d = a.length,
- b = 0;
- for (; b < d; b++) {
- c[a[b]] = e
- }
- this.setCustomEasings(c)
- },
- clearEasingOn: function(a) {
- a = Ext.Array.from(a, true);
- var b = 0,
- c = a.length;
- for (; b < c; b++) {
- delete this._customEasings[a[b]]
- }
- },
- applyCustomDurations: function(g, h) {
- h = h || {};
- var e, c, f, a, b, d;
- for (c in g) {
- e = true;
- f = g[c];
- a = c.split(",");
- for (b = 0, d = a.length; b < d; b++) {
- h[a[b]] = f
- }
- }
- if (e) {
- this.anySpecialAnimations = e
- }
- return h
- },
- applyCustomDuration: function(a, b) {
- if (a) {
- this.getCustomDurations();
- this.setCustomDurations(a)
- }
- },
- setDurationOn: function(b, e) {
- b = Ext.Array.from(b).slice();
- var a = {},
- c = 0,
- d = b.length;
- for (; c < d; c++) {
- a[b[c]] = e
- }
- this.setCustomDurations(a)
- },
- clearDurationOn: function(a) {
- a = Ext.Array.from(a, true);
- var b = 0,
- c = a.length;
- for (; b < c; b++) {
- delete this._customDurations[a[b]]
- }
- },
- setAnimating: function(a, b) {
- var e = this,
- d = e.animatingPool;
- if (a.animating !== b) {
- a.animating = b;
- if (b) {
- d.push(a);
- if (e.animating === 0) {
- Ext.draw.Animator.add(e)
- }
- e.animating++
- } else {
- for (var c = d.length; c--;) {
- if (d[c] === a) {
- d.splice(c, 1)
- }
- }
- e.animating = d.length
- }
- }
- },
- setAttrs: function(r, t) {
- var s = this,
- m = r.timers,
- h = s._sprite.self.def._animationProcessors,
- f = s._easing,
- e = s._duration,
- j = s._customDurations,
- i = s._customEasings,
- g = s.anySpecialAnimations,
- n = s.anyAnimation || g,
- o = r.animationOriginal,
- d = false,
- k, u, l, p, c, q, a;
- if (!n) {
- for (u in t) {
- if (r[u] === t[u]) {
- delete t[u]
- } else {
- r[u] = t[u]
- }
- delete o[u];
- delete m[u]
- }
- return t
- } else {
- for (u in t) {
- l = t[u];
- p = r[u];
- if (l !== p && p !== undefined && p !== null && (c = h[u])) {
- q = f;
- a = e;
- if (g) {
- if (u in i) {
- q = i[u]
- }
- if (u in j) {
- a = j[u]
- }
- }
- if (p && p.isGradient || l && l.isGradient) {
- a = 0
- }
- if (a) {
- if (!m[u]) {
- m[u] = {}
- }
- k = m[u];
- k.start = 0;
- k.easing = q;
- k.duration = a;
- k.compute = c.compute;
- k.serve = c.serve || Ext.identityFn;
- k.remove = t.removeFromInstance && t.removeFromInstance[u];
- if (c.parseInitial) {
- var b = c.parseInitial(p, l);
- k.source = b[0];
- k.target = b[1]
- } else {
- if (c.parse) {
- k.source = c.parse(p);
- k.target = c.parse(l)
- } else {
- k.source = p;
- k.target = l
- }
- }
- o[u] = l;
- delete t[u];
- d = true;
- continue
- } else {
- delete o[u]
- }
- } else {
- delete o[u]
- }
- delete m[u]
- }
- }
- if (d && !r.animating) {
- s.setAnimating(r, true)
- }
- return t
- },
- updateAttributes: function(g) {
- if (!g.animating) {
- return {}
- }
- var h = {},
- e = false,
- d = g.timers,
- f = g.animationOriginal,
- c = Ext.draw.Animator.animationTime(),
- a, b, i;
- if (g.lastUpdate === c) {
- return null
- }
- for (a in d) {
- b = d[a];
- if (!b.start) {
- b.start = c;
- i = 0
- } else {
- i = (c - b.start) / b.duration
- }
- if (i >= 1) {
- h[a] = f[a];
- delete f[a];
- if (d[a].remove) {
- h.removeFromInstance = h.removeFromInstance || {};
- h.removeFromInstance[a] = true
- }
- delete d[a]
- } else {
- h[a] = b.serve(b.compute(b.source, b.target, b.easing(i), g[a]));
- e = true
- }
- }
- g.lastUpdate = c;
- this.setAnimating(g, e);
- return h
- },
- pushDown: function(a, b) {
- b = this.callParent([a.animationOriginal, b]);
- return this.setAttrs(a, b)
- },
- popUp: function(a, b) {
- a = a.prototype;
- b = this.setAttrs(a, b);
- if (this._next) {
- return this._next.popUp(a, b)
- } else {
- return Ext.apply(a, b)
- }
- },
- step: function(g) {
- var f = this,
- c = f.animatingPool.slice(),
- e = c.length,
- b = 0,
- a, d;
- for (; b < e; b++) {
- a = c[b];
- d = f.updateAttributes(a);
- if (d && f._next) {
- f._next.popUp(a, d)
- }
- }
- },
- stop: function() {
- this.step();
- var d = this,
- b = d.animatingPool,
- a, c;
- for (a = 0, c = b.length; a < c; a++) {
- b[a].animating = false
- }
- d.animatingPool.length = 0;
- d.animating = 0;
- Ext.draw.Animator.remove(d)
- },
- destroy: function() {
- this.animatingPool.length = 0;
- this.animating = 0;
- this.callParent()
- }
-});
-Ext.define("Ext.draw.modifier.Highlight", {
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.highlight",
- config: {
- enabled: false,
- highlightStyle: null
- },
- preFx: true,
- applyHighlightStyle: function(b, a) {
- a = a || {};
- if (this.getSprite()) {
- Ext.apply(a, this.getSprite().self.def.normalize(b))
- } else {
- Ext.apply(a, b)
- }
- return a
- },
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("highlightOriginal")) {
- a.highlighted = false;
- a.highlightOriginal = Ext.Object.chain(a);
- a.highlightOriginal.prototype = a;
- a.highlightOriginal.removeFromInstance = {}
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.highlightOriginal)
- }
- },
- updateSprite: function(b, a) {
- if (b) {
- if (this.getHighlightStyle()) {
- this._highlightStyle = b.self.def.normalize(this.getHighlightStyle())
- }
- this.setHighlightStyle(b.config.highlight)
- }
- b.self.def.setConfig({
- defaults: {
- highlighted: false
- },
- processors: {
- highlighted: "bool"
- }
- });
- this.setSprite(b)
- },
- filterChanges: function(a, d) {
- var e = this,
- f = a.highlightOriginal,
- c = e.getHighlightStyle(),
- b;
- if (a.highlighted) {
- for (b in d) {
- if (c.hasOwnProperty(b)) {
- f[b] = d[b];
- delete d[b]
- }
- }
- }
- for (b in d) {
- if (b !== "highlighted" && f[b] === d[b]) {
- delete d[b]
- }
- }
- return d
- },
- pushDown: function(e, g) {
- var f = this.getHighlightStyle(),
- c = e.highlightOriginal,
- i = c.removeFromInstance,
- d, a, h, b;
- if (g.hasOwnProperty("highlighted")) {
- d = g.highlighted;
- delete g.highlighted;
- if (this._previous) {
- g = this._previous.pushDown(c, g)
- }
- g = this.filterChanges(e, g);
- if (d !== e.highlighted) {
- if (d) {
- for (a in f) {
- if (a in g) {
- c[a] = g[a]
- } else {
- h = e.template && e.template.ownAttr;
- if (h && !e.prototype.hasOwnProperty(a)) {
- i[a] = true;
- c[a] = h.animationOriginal[a]
- } else {
- b = c.timers[a];
- if (b && b.remove) {
- i[a] = true
- }
- c[a] = e[a]
- }
- }
- if (c[a] !== f[a]) {
- g[a] = f[a]
- }
- }
- } else {
- for (a in f) {
- if (!(a in g)) {
- g[a] = c[a]
- }
- delete c[a]
- }
- g.removeFromInstance = g.removeFromInstance || {};
- Ext.apply(g.removeFromInstance, i);
- c.removeFromInstance = {}
- }
- g.highlighted = d
- }
- } else {
- if (this._previous) {
- g = this._previous.pushDown(c, g)
- }
- g = this.filterChanges(e, g)
- }
- return g
- },
- popUp: function(a, b) {
- b = this.filterChanges(a, b);
- Ext.draw.modifier.Modifier.prototype.popUp.call(this, a, b)
- }
-});
-Ext.define("Ext.draw.sprite.Sprite", {
- alias: "sprite.sprite",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- requires: ["Ext.draw.Draw", "Ext.draw.gradient.Gradient", "Ext.draw.sprite.AttributeDefinition", "Ext.draw.modifier.Target", "Ext.draw.modifier.Animation", "Ext.draw.modifier.Highlight"],
- isSprite: true,
- statics: {
- defaultHitTestOptions: {
- fill: true,
- stroke: true
- }
- },
- inheritableStatics: {
- def: {
- processors: {
- strokeStyle: "color",
- fillStyle: "color",
- strokeOpacity: "limited01",
- fillOpacity: "limited01",
- lineWidth: "number",
- lineCap: "enums(butt,round,square)",
- lineJoin: "enums(round,bevel,miter)",
- lineDash: "data",
- lineDashOffset: "number",
- miterLimit: "number",
- shadowColor: "color",
- shadowOffsetX: "number",
- shadowOffsetY: "number",
- shadowBlur: "number",
- globalAlpha: "limited01",
- globalCompositeOperation: "enums(source-over,destination-over,source-in,destination-in,source-out,destination-out,source-atop,destination-atop,lighter,xor,copy)",
- hidden: "bool",
- transformFillStroke: "bool",
- zIndex: "number",
- translationX: "number",
- translationY: "number",
- rotationRads: "number",
- rotationCenterX: "number",
- rotationCenterY: "number",
- scalingX: "number",
- scalingY: "number",
- scalingCenterX: "number",
- scalingCenterY: "number",
- constrainGradients: "bool"
- },
- aliases: {
- stroke: "strokeStyle",
- fill: "fillStyle",
- color: "fillStyle",
- "stroke-width": "lineWidth",
- "stroke-linecap": "lineCap",
- "stroke-linejoin": "lineJoin",
- "stroke-miterlimit": "miterLimit",
- "text-anchor": "textAlign",
- opacity: "globalAlpha",
- translateX: "translationX",
- translateY: "translationY",
- rotateRads: "rotationRads",
- rotateCenterX: "rotationCenterX",
- rotateCenterY: "rotationCenterY",
- scaleX: "scalingX",
- scaleY: "scalingY",
- scaleCenterX: "scalingCenterX",
- scaleCenterY: "scalingCenterY"
- },
- defaults: {
- hidden: false,
- zIndex: 0,
- strokeStyle: "none",
- fillStyle: "none",
- lineWidth: 1,
- lineDash: [],
- lineDashOffset: 0,
- lineCap: "butt",
- lineJoin: "miter",
- miterLimit: 10,
- shadowColor: "none",
- shadowOffsetX: 0,
- shadowOffsetY: 0,
- shadowBlur: 0,
- globalAlpha: 1,
- strokeOpacity: 1,
- fillOpacity: 1,
- transformFillStroke: false,
- translationX: 0,
- translationY: 0,
- rotationRads: 0,
- rotationCenterX: null,
- rotationCenterY: null,
- scalingX: 1,
- scalingY: 1,
- scalingCenterX: null,
- scalingCenterY: null,
- constrainGradients: false
- },
- triggers: {
- zIndex: "zIndex",
- globalAlpha: "canvas",
- globalCompositeOperation: "canvas",
- transformFillStroke: "canvas",
- strokeStyle: "canvas",
- fillStyle: "canvas",
- strokeOpacity: "canvas",
- fillOpacity: "canvas",
- lineWidth: "canvas",
- lineCap: "canvas",
- lineJoin: "canvas",
- lineDash: "canvas",
- lineDashOffset: "canvas",
- miterLimit: "canvas",
- shadowColor: "canvas",
- shadowOffsetX: "canvas",
- shadowOffsetY: "canvas",
- shadowBlur: "canvas",
- translationX: "transform",
- translationY: "transform",
- rotationRads: "transform",
- rotationCenterX: "transform",
- rotationCenterY: "transform",
- scalingX: "transform",
- scalingY: "transform",
- scalingCenterX: "transform",
- scalingCenterY: "transform",
- constrainGradients: "canvas"
- },
- updaters: {
- bbox: "bboxUpdater",
- zIndex: function(a) {
- a.dirtyZIndex = true
- },
- transform: function(a) {
- a.dirtyTransform = true;
- a.bbox.transform.dirty = true
- }
- }
- }
- },
- config: {
- parent: null,
- surface: null
- },
- onClassExtended: function(d, c) {
- var b = d.superclass.self.def.initialConfig,
- e = c.inheritableStatics && c.inheritableStatics.def,
- a;
- if (e) {
- a = Ext.Object.merge({}, b, e);
- d.def = new Ext.draw.sprite.AttributeDefinition(a);
- delete c.inheritableStatics.def
- } else {
- d.def = new Ext.draw.sprite.AttributeDefinition(b)
- }
- d.def.spriteClass = d
- },
- constructor: function(b) {
- var d = this,
- c = d.self.def,
- e = c.getDefaults(),
- a;
- b = Ext.isObject(b) ? b : {};
- d.id = b.id || Ext.id(null, "ext-sprite-");
- d.attr = {};
- d.mixins.observable.constructor.apply(d, arguments);
- a = Ext.Array.from(b.modifiers, true);
- d.prepareModifiers(a);
- d.initializeAttributes();
- d.setAttributes(e, true);
- d.setAttributes(b)
- },
- getDirty: function() {
- return this.attr.dirty
- },
- setDirty: function(b) {
- this.attr.dirty = b;
- if (b) {
- var a = this.getParent();
- if (a) {
- a.setDirty(true)
- }
- }
- },
- addModifier: function(a, b) {
- var c = this;
- if (!(a instanceof Ext.draw.modifier.Modifier)) {
- a = Ext.factory(a, null, null, "modifier")
- }
- a.setSprite(c);
- if (a.preFx || a.config && a.config.preFx) {
- if (c.fx.getPrevious()) {
- c.fx.getPrevious().setNext(a)
- }
- a.setNext(c.fx)
- } else {
- c.topModifier.getPrevious().setNext(a);
- a.setNext(c.topModifier)
- }
- if (b) {
- c.initializeAttributes()
- }
- return a
- },
- prepareModifiers: function(d) {
- var c = this,
- a, b;
- c.topModifier = new Ext.draw.modifier.Target({
- sprite: c
- });
- c.fx = new Ext.draw.modifier.Animation({
- sprite: c
- });
- c.fx.setNext(c.topModifier);
- for (a = 0, b = d.length; a < b; a++) {
- c.addModifier(d[a], false)
- }
- },
- getAnimation: function() {
- return this.fx
- },
- setAnimation: function(a) {
- this.fx.setConfig(a)
- },
- initializeAttributes: function() {
- this.topModifier.prepareAttributes(this.attr)
- },
- callUpdaters: function(d) {
- var e = this,
- h = d.pendingUpdaters,
- i = e.self.def.getUpdaters(),
- c = false,
- a = false,
- b, g, f;
- e.callUpdaters = Ext.emptyFn;
- do {
- c = false;
- for (g in h) {
- c = true;
- b = h[g];
- delete h[g];
- f = i[g];
- if (typeof f === "string") {
- f = e[f]
- }
- if (f) {
- f.call(e, d, b)
- }
- }
- a = a || c
- } while (c);
- delete e.callUpdaters;
- if (a) {
- e.setDirty(true)
- }
- },
- scheduleUpdaters: function(a, e, c) {
- var f;
- if (c) {
- for (var b = 0, d = e.length; b < d; b++) {
- f = e[b];
- this.scheduleUpdater(a, f, c)
- }
- } else {
- for (f in e) {
- c = e[f];
- this.scheduleUpdater(a, f, c)
- }
- }
- },
- scheduleUpdater: function(a, c, b) {
- b = b || [];
- var d = a.pendingUpdaters;
- if (c in d) {
- if (b.length) {
- d[c] = Ext.Array.merge(d[c], b)
- }
- } else {
- d[c] = b
- }
- },
- setAttributes: function(d, g, c) {
- var a = this.attr,
- b, e, f;
- if (g) {
- if (c) {
- this.topModifier.pushDown(a, d)
- } else {
- f = {};
- for (b in d) {
- e = d[b];
- if (e !== a[b]) {
- f[b] = e
- }
- }
- this.topModifier.pushDown(a, f)
- }
- } else {
- this.topModifier.pushDown(a, this.self.def.normalize(d))
- }
- },
- setAttributesBypassingNormalization: function(b, a) {
- return this.setAttributes(b, true, a)
- },
- bboxUpdater: function(b) {
- var c = b.rotationRads !== 0,
- a = b.scalingX !== 1 || b.scalingY !== 1,
- d = b.rotationCenterX === null || b.rotationCenterY === null,
- e = b.scalingCenterX === null || b.scalingCenterY === null;
- b.bbox.plain.dirty = true;
- b.bbox.transform.dirty = true;
- if (c && d || a && e) {
- this.scheduleUpdater(b, "transform")
- }
- },
- getBBox: function(d) {
- var e = this,
- a = e.attr,
- f = a.bbox,
- c = f.plain,
- b = f.transform;
- if (c.dirty) {
- e.updatePlainBBox(c);
- c.dirty = false
- }
- if (!d) {
- e.applyTransformations();
- if (b.dirty) {
- e.updateTransformedBBox(b, c);
- b.dirty = false
- }
- return b
- }
- return c
- },
- updatePlainBBox: Ext.emptyFn,
- updateTransformedBBox: function(a, b) {
- this.attr.matrix.transformBBox(b, 0, a)
- },
- getBBoxCenter: function(a) {
- var b = this.getBBox(a);
- if (b) {
- return [b.x + b.width * 0.5, b.y + b.height * 0.5]
- } else {
- return [0, 0]
- }
- },
- hide: function() {
- this.attr.hidden = true;
- this.setDirty(true);
- return this
- },
- show: function() {
- this.attr.hidden = false;
- this.setDirty(true);
- return this
- },
- useAttributes: function(i, f) {
- this.applyTransformations();
- var d = this.attr,
- h = d.canvasAttributes,
- e = h.strokeStyle,
- g = h.fillStyle,
- b = h.lineDash,
- c = h.lineDashOffset,
- a;
- if (e) {
- if (e.isGradient) {
- i.strokeStyle = "black";
- i.strokeGradient = e
- } else {
- i.strokeGradient = false
- }
- }
- if (g) {
- if (g.isGradient) {
- i.fillStyle = "black";
- i.fillGradient = g
- } else {
- i.fillGradient = false
- }
- }
- if (b) {
- i.setLineDash(b)
- }
- if (Ext.isNumber(c + i.lineDashOffset)) {
- i.lineDashOffset = c
- }
- for (a in h) {
- if (h[a] !== undefined && h[a] !== i[a]) {
- i[a] = h[a]
- }
- }
- this.setGradientBBox(i, f)
- },
- setGradientBBox: function(b, c) {
- var a = this.attr;
- if (a.constrainGradients) {
- b.setGradientBBox({
- x: c[0],
- y: c[1],
- width: c[2],
- height: c[3]
- })
- } else {
- b.setGradientBBox(this.getBBox(a.transformFillStroke))
- }
- },
- applyTransformations: function(b) {
- if (!b && !this.attr.dirtyTransform) {
- return
- }
- var r = this,
- k = r.attr,
- p = r.getBBoxCenter(true),
- g = p[0],
- f = p[1],
- q = k.translationX,
- o = k.translationY,
- j = k.scalingX,
- i = k.scalingY === null ? k.scalingX : k.scalingY,
- m = k.scalingCenterX === null ? g : k.scalingCenterX,
- l = k.scalingCenterY === null ? f : k.scalingCenterY,
- s = k.rotationRads,
- e = k.rotationCenterX === null ? g : k.rotationCenterX,
- d = k.rotationCenterY === null ? f : k.rotationCenterY,
- c = Math.cos(s),
- a = Math.sin(s),
- n, h;
- if (j === 1 && i === 1) {
- m = 0;
- l = 0
- }
- if (s === 0) {
- e = 0;
- d = 0
- }
- n = m * (1 - j) - e;
- h = l * (1 - i) - d;
- k.matrix.elements = [c * j, a * j, -a * i, c * i, c * n - a * h + e + q, a * n + c * h + d + o];
- k.matrix.inverse(k.inverseMatrix);
- k.dirtyTransform = false;
- k.bbox.transform.dirty = true
- },
- transform: function(b, c) {
- var a = this.attr,
- e = a.matrix,
- d;
- if (b && b.isMatrix) {
- d = b.elements
- } else {
- d = b
- }
- e.prepend.apply(e, d.slice());
- e.inverse(a.inverseMatrix);
- if (c) {
- this.updateTransformAttributes()
- }
- a.dirtyTransform = false;
- a.bbox.transform.dirty = true;
- this.setDirty(true);
- return this
- },
- updateTransformAttributes: function() {
- var a = this.attr,
- b = a.matrix.split();
- a.rotationRads = b.rotate;
- a.rotationCenterX = 0;
- a.rotationCenterY = 0;
- a.scalingX = b.scaleX;
- a.scalingY = b.scaleY;
- a.scalingCenterX = 0;
- a.scalingCenterY = 0;
- a.translationX = b.translateX;
- a.translationY = b.translateY
- },
- resetTransform: function(b) {
- var a = this.attr;
- a.matrix.reset();
- a.inverseMatrix.reset();
- if (!b) {
- this.updateTransformAttributes()
- }
- a.dirtyTransform = false;
- a.bbox.transform.dirty = true;
- this.setDirty(true);
- return this
- },
- setTransform: function(a, b) {
- this.resetTransform(true);
- this.transform.call(this, a, b);
- return this
- },
- preRender: Ext.emptyFn,
- render: Ext.emptyFn,
- hitTest: function(b, c) {
- if (this.isVisible()) {
- var a = b[0],
- f = b[1],
- e = this.getBBox(),
- d = e && a >= e.x && a <= (e.x + e.width) && f >= e.y && f <= (e.y + e.height);
- if (d) {
- return {
- sprite: this
- }
- }
- }
- return null
- },
- isVisible: function() {
- var e = this.attr,
- f = this.getParent(),
- g = f && (f.isSurface || f.isVisible()),
- d = g && !e.hidden && e.globalAlpha,
- b = Ext.draw.Color.NONE,
- a = Ext.draw.Color.RGBA_NONE,
- c = e.fillOpacity && e.fillStyle !== b && e.fillStyle !== a,
- i = e.strokeOpacity && e.strokeStyle !== b && e.strokeStyle !== a,
- h = d && (c || i);
- return !!h
- },
- repaint: function() {
- var a = this.getSurface();
- if (a) {
- a.renderFrame()
- }
- },
- remove: function() {
- var a = this.getSurface();
- if (a && a.isSurface) {
- return a.remove(this)
- }
- return null
- },
- destroy: function() {
- var b = this,
- a = b.topModifier,
- c;
- while (a) {
- c = a;
- a = a.getPrevious();
- c.destroy()
- }
- delete b.attr;
- b.remove();
- if (b.fireEvent("beforedestroy", b) !== false) {
- b.fireEvent("destroy", b)
- }
- b.callParent()
- }
-}, function() {
- this.def = new Ext.draw.sprite.AttributeDefinition(this.def);
- this.def.spriteClass = this
-});
-Ext.define("Ext.draw.Path", {
- requires: ["Ext.draw.Draw"],
- statics: {
- pathRe: /,?([achlmqrstvxz]),?/gi,
- pathRe2: /-/gi,
- pathSplitRe: /\s|,/g
- },
- svgString: "",
- constructor: function(a) {
- var b = this;
- b.commands = [];
- b.params = [];
- b.cursor = null;
- b.startX = 0;
- b.startY = 0;
- if (a) {
- b.fromSvgString(a)
- }
- },
- clear: function() {
- var a = this;
- a.params.length = 0;
- a.commands.length = 0;
- a.cursor = null;
- a.startX = 0;
- a.startY = 0;
- a.dirt()
- },
- dirt: function() {
- this.svgString = ""
- },
- moveTo: function(a, c) {
- var b = this;
- if (!b.cursor) {
- b.cursor = [a, c]
- }
- b.params.push(a, c);
- b.commands.push("M");
- b.startX = a;
- b.startY = c;
- b.cursor[0] = a;
- b.cursor[1] = c;
- b.dirt()
- },
- lineTo: function(a, c) {
- var b = this;
- if (!b.cursor) {
- b.cursor = [a, c];
- b.params.push(a, c);
- b.commands.push("M")
- } else {
- b.params.push(a, c);
- b.commands.push("L")
- }
- b.cursor[0] = a;
- b.cursor[1] = c;
- b.dirt()
- },
- bezierCurveTo: function(c, e, b, d, a, g) {
- var f = this;
- if (!f.cursor) {
- f.moveTo(c, e)
- }
- f.params.push(c, e, b, d, a, g);
- f.commands.push("C");
- f.cursor[0] = a;
- f.cursor[1] = g;
- f.dirt()
- },
- quadraticCurveTo: function(b, e, a, d) {
- var c = this;
- if (!c.cursor) {
- c.moveTo(b, e)
- }
- c.bezierCurveTo((2 * b + c.cursor[0]) / 3, (2 * e + c.cursor[1]) / 3, (2 * b + a) / 3, (2 * e + d) / 3, a, d)
- },
- closePath: function() {
- var a = this;
- if (a.cursor) {
- a.cursor = null;
- a.commands.push("Z");
- a.dirt()
- }
- },
- arcTo: function(A, f, z, d, j, i, v) {
- var E = this;
- if (i === undefined) {
- i = j
- }
- if (v === undefined) {
- v = 0
- }
- if (!E.cursor) {
- E.moveTo(A, f);
- return
- }
- if (j === 0 || i === 0) {
- E.lineTo(A, f);
- return
- }
- z -= A;
- d -= f;
- var B = E.cursor[0] - A,
- g = E.cursor[1] - f,
- C = z * g - d * B,
- b, a, l, r, k, q, x = Math.sqrt(B * B + g * g),
- u = Math.sqrt(z * z + d * d),
- t, e, c;
- if (C === 0) {
- E.lineTo(A, f);
- return
- }
- if (i !== j) {
- b = Math.cos(v);
- a = Math.sin(v);
- l = b / j;
- r = a / i;
- k = -a / j;
- q = b / i;
- var D = l * B + r * g;
- g = k * B + q * g;
- B = D;
- D = l * z + r * d;
- d = k * z + q * d;
- z = D
- } else {
- B /= j;
- g /= i;
- z /= j;
- d /= i
- }
- e = B * u + z * x;
- c = g * u + d * x;
- t = 1 / (Math.sin(Math.asin(Math.abs(C) / (x * u)) * 0.5) * Math.sqrt(e * e + c * c));
- e *= t;
- c *= t;
- var o = (e * B + c * g) / (B * B + g * g),
- m = (e * z + c * d) / (z * z + d * d);
- var n = B * o - e,
- p = g * o - c,
- h = z * m - e,
- y = d * m - c,
- w = Math.atan2(p, n),
- s = Math.atan2(y, h);
- if (C > 0) {
- if (s < w) {
- s += Math.PI * 2
- }
- } else {
- if (w < s) {
- w += Math.PI * 2
- }
- }
- if (i !== j) {
- e = b * e * j - a * c * i + A;
- c = a * c * i + b * c * i + f;
- E.lineTo(b * j * n - a * i * p + e, a * j * n + b * i * p + c);
- E.ellipse(e, c, j, i, v, w, s, C < 0)
- } else {
- e = e * j + A;
- c = c * i + f;
- E.lineTo(j * n + e, i * p + c);
- E.ellipse(e, c, j, i, v, w, s, C < 0)
- }
- },
- ellipse: function(h, f, c, a, q, n, d, e) {
- var o = this,
- g = o.params,
- b = g.length,
- m, l, k;
- if (d - n >= Math.PI * 2) {
- o.ellipse(h, f, c, a, q, n, n + Math.PI, e);
- o.ellipse(h, f, c, a, q, n + Math.PI, d, e);
- return
- }
- if (!e) {
- if (d < n) {
- d += Math.PI * 2
- }
- m = o.approximateArc(g, h, f, c, a, q, n, d)
- } else {
- if (n < d) {
- n += Math.PI * 2
- }
- m = o.approximateArc(g, h, f, c, a, q, d, n);
- for (l = b, k = g.length - 2; l < k; l += 2, k -= 2) {
- var p = g[l];
- g[l] = g[k];
- g[k] = p;
- p = g[l + 1];
- g[l + 1] = g[k + 1];
- g[k + 1] = p
- }
- }
- if (!o.cursor) {
- o.cursor = [g[g.length - 2], g[g.length - 1]];
- o.commands.push("M")
- } else {
- o.cursor[0] = g[g.length - 2];
- o.cursor[1] = g[g.length - 1];
- o.commands.push("L")
- }
- for (l = 2; l < m; l += 6) {
- o.commands.push("C")
- }
- o.dirt()
- },
- arc: function(b, f, a, d, c, e) {
- this.ellipse(b, f, a, a, 0, d, c, e)
- },
- rect: function(b, e, c, a) {
- if (c == 0 || a == 0) {
- return
- }
- var d = this;
- d.moveTo(b, e);
- d.lineTo(b + c, e);
- d.lineTo(b + c, e + a);
- d.lineTo(b, e + a);
- d.closePath()
- },
- approximateArc: function(s, i, f, o, n, d, x, v) {
- var e = Math.cos(d),
- z = Math.sin(d),
- k = Math.cos(x),
- l = Math.sin(x),
- q = e * k * o - z * l * n,
- y = -e * l * o - z * k * n,
- p = z * k * o + e * l * n,
- w = -z * l * o + e * k * n,
- m = Math.PI / 2,
- r = 2,
- j = q,
- u = y,
- h = p,
- t = w,
- b = 0.547443256150549,
- C, g, A, a, B, c;
- v -= x;
- if (v < 0) {
- v += Math.PI * 2
- }
- s.push(q + i, p + f);
- while (v >= m) {
- s.push(j + u * b + i, h + t * b + f, j * b + u + i, h * b + t + f, u + i, t + f);
- r += 6;
- v -= m;
- C = j;
- j = u;
- u = -C;
- C = h;
- h = t;
- t = -C
- }
- if (v) {
- g = (0.3294738052815987 + 0.012120855841304373 * v) * v;
- A = Math.cos(v);
- a = Math.sin(v);
- B = A + g * a;
- c = a - g * A;
- s.push(j + u * g + i, h + t * g + f, j * B + u * c + i, h * B + t * c + f, j * A + u * a + i, h * A + t * a + f);
- r += 6
- }
- return r
- },
- arcSvg: function(j, h, r, m, w, t, c) {
- if (j < 0) {
- j = -j
- }
- if (h < 0) {
- h = -h
- }
- var x = this,
- u = x.cursor[0],
- f = x.cursor[1],
- a = (u - t) / 2,
- y = (f - c) / 2,
- d = Math.cos(r),
- s = Math.sin(r),
- o = a * d + y * s,
- v = -a * s + y * d,
- i = o / j,
- g = v / h,
- p = i * i + g * g,
- e = (u + t) * 0.5,
- b = (f + c) * 0.5,
- l = 0,
- k = 0;
- if (p >= 1) {
- p = Math.sqrt(p);
- j *= p;
- h *= p
- } else {
- p = Math.sqrt(1 / p - 1);
- if (m === w) {
- p = -p
- }
- l = p * j * g;
- k = -p * h * i;
- e += d * l - s * k;
- b += s * l + d * k
- }
- var q = Math.atan2((v - k) / h, (o - l) / j),
- n = Math.atan2((-v - k) / h, (-o - l) / j) - q;
- if (w) {
- if (n <= 0) {
- n += Math.PI * 2
- }
- } else {
- if (n >= 0) {
- n -= Math.PI * 2
- }
- }
- x.ellipse(e, b, j, h, r, q, q + n, 1 - w)
- },
- fromSvgString: function(e) {
- if (!e) {
- return
- }
- var m = this,
- h, l = {
- a: 7,
- c: 6,
- h: 1,
- l: 2,
- m: 2,
- q: 4,
- s: 4,
- t: 2,
- v: 1,
- z: 0,
- A: 7,
- C: 6,
- H: 1,
- L: 2,
- M: 2,
- Q: 4,
- S: 4,
- T: 2,
- V: 1,
- Z: 0
- },
- k = "",
- g, f, c = 0,
- b = 0,
- d = false,
- j, n, a;
- if (Ext.isString(e)) {
- h = e.replace(Ext.draw.Path.pathRe, " $1 ").replace(Ext.draw.Path.pathRe2, " -").split(Ext.draw.Path.pathSplitRe)
- } else {
- if (Ext.isArray(e)) {
- h = e.join(",").split(Ext.draw.Path.pathSplitRe)
- }
- }
- for (j = 0, n = 0; j < h.length; j++) {
- if (h[j] !== "") {
- h[n++] = h[j]
- }
- }
- h.length = n;
- m.clear();
- for (j = 0; j < h.length;) {
- k = d;
- d = h[j];
- a = (d.toUpperCase() !== d);
- j++;
- switch (d) {
- case "M":
- m.moveTo(c = +h[j], b = +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2
- }
- break;
- case "L":
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2
- }
- break;
- case "A":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.arcSvg(+h[j], +h[j + 1], +h[j + 2] * Math.PI / 180, +h[j + 3], +h[j + 4], c = +h[j + 5], b = +h[j + 6]);
- j += 7
- }
- break;
- case "C":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(+h[j], +h[j + 1], g = +h[j + 2], f = +h[j + 3], c = +h[j + 4], b = +h[j + 5]);
- j += 6
- }
- break;
- case "Z":
- m.closePath();
- break;
- case "m":
- m.moveTo(c += +h[j], b += +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2
- }
- break;
- case "l":
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2
- }
- break;
- case "a":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.arcSvg(+h[j], +h[j + 1], +h[j + 2] * Math.PI / 180, +h[j + 3], +h[j + 4], c += +h[j + 5], b += +h[j + 6]);
- j += 7
- }
- break;
- case "c":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + (+h[j]), b + (+h[j + 1]), g = c + (+h[j + 2]), f = b + (+h[j + 3]), c += +h[j + 4], b += +h[j + 5]);
- j += 6
- }
- break;
- case "z":
- m.closePath();
- break;
- case "s":
- if (!(k === "c" || k === "C" || k === "s" || k === "S")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + c - g, b + b - f, g = c + (+h[j]), f = b + (+h[j + 1]), c += +h[j + 2], b += +h[j + 3]);
- j += 4
- }
- break;
- case "S":
- if (!(k === "c" || k === "C" || k === "s" || k === "S")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + c - g, b + b - f, g = +h[j], f = +h[j + 1], c = (+h[j + 2]), b = (+h[j + 3]));
- j += 4
- }
- break;
- case "q":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + (+h[j]), f = b + (+h[j + 1]), c += +h[j + 2], b += +h[j + 3]);
- j += 4
- }
- break;
- case "Q":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = +h[j], f = +h[j + 1], c = +h[j + 2], b = +h[j + 3]);
- j += 4
- }
- break;
- case "t":
- if (!(k === "q" || k === "Q" || k === "t" || k === "T")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + c - g, f = b + b - f, c += +h[j + 1], b += +h[j + 2]);
- j += 2
- }
- break;
- case "T":
- if (!(k === "q" || k === "Q" || k === "t" || k === "T")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + c - g, f = b + b - f, c = (+h[j + 1]), b = (+h[j + 2]));
- j += 2
- }
- break;
- case "h":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b);
- j++
- }
- break;
- case "H":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b);
- j++
- }
- break;
- case "v":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c, b += +h[j]);
- j++
- }
- break;
- case "V":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c, b = +h[j]);
- j++
- }
- break
- }
- }
- },
- clone: function() {
- var a = this,
- b = new Ext.draw.Path();
- b.params = a.params.slice(0);
- b.commands = a.commands.slice(0);
- b.cursor = a.cursor ? a.cursor.slice(0) : null;
- b.startX = a.startX;
- b.startY = a.startY;
- b.svgString = a.svgString;
- return b
- },
- transform: function(j) {
- if (j.isIdentity()) {
- return
- }
- var a = j.getXX(),
- f = j.getYX(),
- m = j.getDX(),
- l = j.getXY(),
- e = j.getYY(),
- k = j.getDY(),
- b = this.params,
- c = 0,
- d = b.length,
- h, g;
- for (; c < d; c += 2) {
- h = b[c];
- g = b[c + 1];
- b[c] = h * a + g * f + m;
- b[c + 1] = h * l + g * e + k
- }
- this.dirt()
- },
- getDimension: function(f) {
- if (!f) {
- f = {}
- }
- if (!this.commands || !this.commands.length) {
- f.x = 0;
- f.y = 0;
- f.width = 0;
- f.height = 0;
- return f
- }
- f.left = Infinity;
- f.top = Infinity;
- f.right = -Infinity;
- f.bottom = -Infinity;
- var d = 0,
- c = 0,
- b = this.commands,
- g = this.params,
- e = b.length,
- a, h;
- for (; d < e; d++) {
- switch (b[d]) {
- case "M":
- case "L":
- a = g[c];
- h = g[c + 1];
- f.left = Math.min(a, f.left);
- f.top = Math.min(h, f.top);
- f.right = Math.max(a, f.right);
- f.bottom = Math.max(h, f.bottom);
- c += 2;
- break;
- case "C":
- this.expandDimension(f, a, h, g[c], g[c + 1], g[c + 2], g[c + 3], a = g[c + 4], h = g[c + 5]);
- c += 6;
- break
- }
- }
- f.x = f.left;
- f.y = f.top;
- f.width = f.right - f.left;
- f.height = f.bottom - f.top;
- return f
- },
- getDimensionWithTransform: function(n, f) {
- if (!this.commands || !this.commands.length) {
- if (!f) {
- f = {}
- }
- f.x = 0;
- f.y = 0;
- f.width = 0;
- f.height = 0;
- return f
- }
- f.left = Infinity;
- f.top = Infinity;
- f.right = -Infinity;
- f.bottom = -Infinity;
- var a = n.getXX(),
- k = n.getYX(),
- q = n.getDX(),
- p = n.getXY(),
- h = n.getYY(),
- o = n.getDY(),
- e = 0,
- d = 0,
- b = this.commands,
- c = this.params,
- g = b.length,
- m, l;
- for (; e < g; e++) {
- switch (b[e]) {
- case "M":
- case "L":
- m = c[d] * a + c[d + 1] * k + q;
- l = c[d] * p + c[d + 1] * h + o;
- f.left = Math.min(m, f.left);
- f.top = Math.min(l, f.top);
- f.right = Math.max(m, f.right);
- f.bottom = Math.max(l, f.bottom);
- d += 2;
- break;
- case "C":
- this.expandDimension(f, m, l, c[d] * a + c[d + 1] * k + q, c[d] * p + c[d + 1] * h + o, c[d + 2] * a + c[d + 3] * k + q, c[d + 2] * p + c[d + 3] * h + o, m = c[d + 4] * a + c[d + 5] * k + q, l = c[d + 4] * p + c[d + 5] * h + o);
- d += 6;
- break
- }
- }
- if (!f) {
- f = {}
- }
- f.x = f.left;
- f.y = f.top;
- f.width = f.right - f.left;
- f.height = f.bottom - f.top;
- return f
- },
- expandDimension: function(i, d, p, k, g, j, e, c, o) {
- var m = this,
- f = i.left,
- a = i.right,
- q = i.top,
- n = i.bottom,
- h = m.dim || (m.dim = []);
- m.curveDimension(d, k, j, c, h);
- f = Math.min(f, h[0]);
- a = Math.max(a, h[1]);
- m.curveDimension(p, g, e, o, h);
- q = Math.min(q, h[0]);
- n = Math.max(n, h[1]);
- i.left = f;
- i.right = a;
- i.top = q;
- i.bottom = n
- },
- curveDimension: function(p, n, k, j, h) {
- var i = 3 * (-p + 3 * (n - k) + j),
- g = 6 * (p - 2 * n + k),
- f = -3 * (p - n),
- o, m, e = Math.min(p, j),
- l = Math.max(p, j),
- q;
- if (i === 0) {
- if (g === 0) {
- h[0] = e;
- h[1] = l;
- return
- } else {
- o = -f / g;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- }
- } else {
- q = g * g - 4 * i * f;
- if (q >= 0) {
- q = Math.sqrt(q);
- o = (q - g) / 2 / i;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- if (q > 0) {
- o -= q / i;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- }
- }
- }
- h[0] = e;
- h[1] = l
- },
- interpolate: function(f, e, j, i, g) {
- if (g === 0) {
- return f
- }
- if (g === 1) {
- return i
- }
- var h = (1 - g) / g;
- return g * g * g * (i + h * (3 * j + h * (3 * e + h * f)))
- },
- fromStripes: function(g) {
- var e = this,
- c = 0,
- d = g.length,
- b, a, f;
- e.clear();
- for (; c < d; c++) {
- f = g[c];
- e.params.push.apply(e.params, f);
- e.commands.push("M");
- for (b = 2, a = f.length; b < a; b += 6) {
- e.commands.push("C")
- }
- }
- if (!e.cursor) {
- e.cursor = []
- }
- e.cursor[0] = e.params[e.params.length - 2];
- e.cursor[1] = e.params[e.params.length - 1];
- e.dirt()
- },
- toStripes: function(k) {
- var o = k || [],
- p, n, m, b, a, h, g, f, e, c = this.commands,
- d = this.params,
- l = c.length;
- for (f = 0, e = 0; f < l; f++) {
- switch (c[f]) {
- case "M":
- p = [h = b = d[e++], g = a = d[e++]];
- o.push(p);
- break;
- case "L":
- n = d[e++];
- m = d[e++];
- p.push((b + b + n) / 3, (a + a + m) / 3, (b + n + n) / 3, (a + m + m) / 3, b = n, a = m);
- break;
- case "C":
- p.push(d[e++], d[e++], d[e++], d[e++], b = d[e++], a = d[e++]);
- break;
- case "Z":
- n = h;
- m = g;
- p.push((b + b + n) / 3, (a + a + m) / 3, (b + n + n) / 3, (a + m + m) / 3, b = n, a = m);
- break
- }
- }
- return o
- },
- updateSvgString: function() {
- var b = [],
- a = this.commands,
- f = this.params,
- e = a.length,
- d = 0,
- c = 0;
- for (; d < e; d++) {
- switch (a[d]) {
- case "M":
- b.push("M" + f[c] + "," + f[c + 1]);
- c += 2;
- break;
- case "L":
- b.push("L" + f[c] + "," + f[c + 1]);
- c += 2;
- break;
- case "C":
- b.push("C" + f[c] + "," + f[c + 1] + " " + f[c + 2] + "," + f[c + 3] + " " + f[c + 4] + "," + f[c + 5]);
- c += 6;
- break;
- case "Z":
- b.push("Z");
- break
- }
- }
- this.svgString = b.join("")
- },
- toString: function() {
- if (!this.svgString) {
- this.updateSvgString()
- }
- return this.svgString
- }
-});
-Ext.define("Ext.draw.overrides.Path", {
- override: "Ext.draw.Path",
- rayOrigin: {
- x: -10000,
- y: -10000
- },
- isPointInPath: function(o, n) {
- var m = this,
- c = m.commands,
- q = Ext.draw.PathUtil,
- p = m.rayOrigin,
- f = m.params,
- l = c.length,
- e = null,
- d = null,
- b = 0,
- a = 0,
- k = 0,
- h, g;
- for (h = 0, g = 0; h < l; h++) {
- switch (c[h]) {
- case "M":
- if (e !== null) {
- if (q.linesIntersection(e, d, b, a, p.x, p.y, o, n)) {
- k += 1
- }
- }
- e = b = f[g];
- d = a = f[g + 1];
- g += 2;
- break;
- case "L":
- if (q.linesIntersection(b, a, f[g], f[g + 1], p.x, p.y, o, n)) {
- k += 1
- }
- b = f[g];
- a = f[g + 1];
- g += 2;
- break;
- case "C":
- k += q.cubicLineIntersections(b, f[g], f[g + 2], f[g + 4], a, f[g + 1], f[g + 3], f[g + 5], p.x, p.y, o, n).length;
- b = f[g + 4];
- a = f[g + 5];
- g += 6;
- break;
- case "Z":
- if (e !== null) {
- if (q.linesIntersection(e, d, b, a, p.x, p.y, o, n)) {
- k += 1
- }
- }
- break
- }
- }
- return k % 2 === 1
- },
- isPointOnPath: function(n, m) {
- var l = this,
- c = l.commands,
- o = Ext.draw.PathUtil,
- f = l.params,
- k = c.length,
- e = null,
- d = null,
- b = 0,
- a = 0,
- h, g;
- for (h = 0, g = 0; h < k; h++) {
- switch (c[h]) {
- case "M":
- if (e !== null) {
- if (o.pointOnLine(e, d, b, a, n, m)) {
- return true
- }
- }
- e = b = f[g];
- d = a = f[g + 1];
- g += 2;
- break;
- case "L":
- if (o.pointOnLine(b, a, f[g], f[g + 1], n, m)) {
- return true
- }
- b = f[g];
- a = f[g + 1];
- g += 2;
- break;
- case "C":
- if (o.pointOnCubic(b, f[g], f[g + 2], f[g + 4], a, f[g + 1], f[g + 3], f[g + 5], n, m)) {
- return true
- }
- b = f[g + 4];
- a = f[g + 5];
- g += 6;
- break;
- case "Z":
- if (e !== null) {
- if (o.pointOnLine(e, d, b, a, n, m)) {
- return true
- }
- }
- break
- }
- }
- return false
- },
- getSegmentIntersections: function(t, d, s, c, r, b, o, a) {
- var w = this,
- g = arguments.length,
- v = Ext.draw.PathUtil,
- f = w.commands,
- u = w.params,
- k = f.length,
- m = null,
- l = null,
- h = 0,
- e = 0,
- x = [],
- q, n, p;
- for (q = 0, n = 0; q < k; q++) {
- switch (f[q]) {
- case "M":
- if (m !== null) {
- switch (g) {
- case 4:
- p = v.linesIntersection(m, l, h, e, t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, m, l, h, e);
- x.push.apply(x, p);
- break
- }
- }
- m = h = u[n];
- l = e = u[n + 1];
- n += 2;
- break;
- case "L":
- switch (g) {
- case 4:
- p = v.linesIntersection(h, e, u[n], u[n + 1], t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, h, e, u[n], u[n + 1]);
- x.push.apply(x, p);
- break
- }
- h = u[n];
- e = u[n + 1];
- n += 2;
- break;
- case "C":
- switch (g) {
- case 4:
- p = v.cubicLineIntersections(h, u[n], u[n + 2], u[n + 4], e, u[n + 1], u[n + 3], u[n + 5], t, d, s, c);
- x.push.apply(x, p);
- break;
- case 8:
- p = v.cubicsIntersections(h, u[n], u[n + 2], u[n + 4], e, u[n + 1], u[n + 3], u[n + 5], t, s, r, o, d, c, b, a);
- x.push.apply(x, p);
- break
- }
- h = u[n + 4];
- e = u[n + 5];
- n += 6;
- break;
- case "Z":
- if (m !== null) {
- switch (g) {
- case 4:
- p = v.linesIntersection(m, l, h, e, t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, m, l, h, e);
- x.push.apply(x, p);
- break
- }
- }
- break
- }
- }
- return x
- },
- getIntersections: function(o) {
- var m = this,
- c = m.commands,
- g = m.params,
- l = c.length,
- f = null,
- e = null,
- b = 0,
- a = 0,
- d = [],
- k, h, n;
- for (k = 0, h = 0; k < l; k++) {
- switch (c[k]) {
- case "M":
- if (f !== null) {
- n = o.getSegmentIntersections.call(o, f, e, b, a);
- d.push.apply(d, n)
- }
- f = b = g[h];
- e = a = g[h + 1];
- h += 2;
- break;
- case "L":
- n = o.getSegmentIntersections.call(o, b, a, g[h], g[h + 1]);
- d.push.apply(d, n);
- b = g[h];
- a = g[h + 1];
- h += 2;
- break;
- case "C":
- n = o.getSegmentIntersections.call(o, b, a, g[h], g[h + 1], g[h + 2], g[h + 3], g[h + 4], g[h + 5]);
- d.push.apply(d, n);
- b = g[h + 4];
- a = g[h + 5];
- h += 6;
- break;
- case "Z":
- if (f !== null) {
- n = o.getSegmentIntersections.call(o, f, e, b, a);
- d.push.apply(d, n)
- }
- break
- }
- }
- return d
- }
-});
-Ext.define("Ext.draw.sprite.Path", {
- extend: "Ext.draw.sprite.Sprite",
- requires: ["Ext.draw.Draw", "Ext.draw.Path"],
- alias: ["sprite.path", "Ext.draw.Sprite"],
- type: "path",
- isPath: true,
- inheritableStatics: {
- def: {
- processors: {
- path: function(b, a) {
- if (!(b instanceof Ext.draw.Path)) {
- b = new Ext.draw.Path(b)
- }
- return b
- }
- },
- aliases: {
- d: "path"
- },
- triggers: {
- path: "bbox"
- },
- updaters: {
- path: function(a) {
- var b = a.path;
- if (!b || b.bindAttr !== a) {
- b = new Ext.draw.Path();
- b.bindAttr = a;
- a.path = b
- }
- b.clear();
- this.updatePath(b, a);
- this.scheduleUpdater(a, "bbox", ["path"])
- }
- }
- }
- },
- updatePlainBBox: function(a) {
- if (this.attr.path) {
- this.attr.path.getDimension(a)
- }
- },
- updateTransformedBBox: function(a) {
- if (this.attr.path) {
- this.attr.path.getDimensionWithTransform(this.attr.matrix, a)
- }
- },
- render: function(b, c) {
- var d = this.attr.matrix,
- a = this.attr;
- if (!a.path || a.path.params.length === 0) {
- return
- }
- d.toContext(c);
- c.appendPath(a.path);
- c.fillStroke(a)
- },
- updatePath: function(b, a) {}
-});
-Ext.define("Ext.draw.overrides.sprite.Path", {
- override: "Ext.draw.sprite.Path",
- requires: ["Ext.draw.Color"],
- isPointInPath: function(c, g) {
- var b = this.attr;
- if (b.fillStyle === Ext.draw.Color.RGBA_NONE) {
- return this.isPointOnPath(c, g)
- }
- var e = b.path,
- d = b.matrix,
- f, a;
- if (!d.isIdentity()) {
- f = e.params.slice(0);
- e.transform(b.matrix)
- }
- a = e.isPointInPath(c, g);
- if (f) {
- e.params = f
- }
- return a
- },
- isPointOnPath: function(c, g) {
- var b = this.attr,
- e = b.path,
- d = b.matrix,
- f, a;
- if (!d.isIdentity()) {
- f = e.params.slice(0);
- e.transform(b.matrix)
- }
- a = e.isPointOnPath(c, g);
- if (f) {
- e.params = f
- }
- return a
- },
- hitTest: function(i, l) {
- var e = this,
- c = e.attr,
- k = c.path,
- g = c.matrix,
- h = i[0],
- f = i[1],
- d = e.callParent([i, l]),
- j = null,
- a, b;
- if (!d) {
- return j
- }
- l = l || Ext.draw.sprite.Sprite.defaultHitTestOptions;
- if (!g.isIdentity()) {
- a = k.params.slice(0);
- k.transform(c.matrix)
- }
- if (l.fill && l.stroke) {
- b = c.fillStyle !== Ext.draw.Color.NONE && c.fillStyle !== Ext.draw.Color.RGBA_NONE;
- if (b) {
- if (k.isPointInPath(h, f)) {
- j = {
- sprite: e
- }
- }
- } else {
- if (k.isPointInPath(h, f) || k.isPointOnPath(h, f)) {
- j = {
- sprite: e
- }
- }
- }
- } else {
- if (l.stroke && !l.fill) {
- if (k.isPointOnPath(h, f)) {
- j = {
- sprite: e
- }
- }
- } else {
- if (l.fill && !l.stroke) {
- if (k.isPointInPath(h, f)) {
- j = {
- sprite: e
- }
- }
- }
- }
- }
- if (a) {
- k.params = a
- }
- return j
- },
- getIntersections: function(j) {
- if (!(j.isSprite && j.isPath)) {
- return []
- }
- var e = this.attr,
- d = j.attr,
- i = e.path,
- h = d.path,
- g = e.matrix,
- a = d.matrix,
- c, f, b;
- if (!g.isIdentity()) {
- c = i.params.slice(0);
- i.transform(e.matrix)
- }
- if (!a.isIdentity()) {
- f = h.params.slice(0);
- h.transform(d.matrix)
- }
- b = i.getIntersections(h);
- if (c) {
- i.params = c
- }
- if (f) {
- h.params = f
- }
- return b
- }
-});
-Ext.define("Ext.draw.sprite.Circle", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.circle",
- type: "circle",
- inheritableStatics: {
- def: {
- processors: {
- cx: "number",
- cy: "number",
- r: "number"
- },
- aliases: {
- radius: "r",
- x: "cx",
- y: "cy",
- centerX: "cx",
- centerY: "cy"
- },
- defaults: {
- cx: 0,
- cy: 0,
- r: 4
- },
- triggers: {
- cx: "path",
- cy: "path",
- r: "path"
- }
- }
- },
- updatePlainBBox: function(c) {
- var b = this.attr,
- a = b.cx,
- e = b.cy,
- d = b.r;
- c.x = a - d;
- c.y = e - d;
- c.width = d + d;
- c.height = d + d
- },
- updateTransformedBBox: function(d) {
- var g = this.attr,
- f = g.cx,
- e = g.cy,
- a = g.r,
- h = g.matrix,
- j = h.getScaleX(),
- i = h.getScaleY(),
- c, b;
- c = j * a;
- b = i * a;
- d.x = h.x(f, e) - c;
- d.y = h.y(f, e) - b;
- d.width = c + c;
- d.height = b + b
- },
- updatePath: function(b, a) {
- b.arc(a.cx, a.cy, a.r, 0, Math.PI * 2, false)
- }
-});
-Ext.define("Ext.draw.sprite.Arc", {
- extend: "Ext.draw.sprite.Circle",
- alias: "sprite.arc",
- type: "arc",
- inheritableStatics: {
- def: {
- processors: {
- startAngle: "number",
- endAngle: "number",
- anticlockwise: "bool"
- },
- aliases: {
- from: "startAngle",
- to: "endAngle",
- start: "startAngle",
- end: "endAngle"
- },
- defaults: {
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false
- },
- triggers: {
- startAngle: "path",
- endAngle: "path",
- anticlockwise: "path"
- }
- }
- },
- updatePath: function(b, a) {
- b.arc(a.cx, a.cy, a.r, a.startAngle, a.endAngle, a.anticlockwise)
- }
-});
-Ext.define("Ext.draw.sprite.Arrow", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.arrow",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 1.5,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c * 0.7, ",", e - c * 0.4, "l", [c * 0.6, 0, 0, -c * 0.4, c, c * 0.8, -c, c * 0.8, 0, -c * 0.4, -c * 0.6, 0], "z"))
- }
-});
-Ext.define("Ext.draw.sprite.Composite", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.composite",
- type: "composite",
- isComposite: true,
- config: {
- sprites: []
- },
- constructor: function() {
- this.sprites = [];
- this.sprites.map = {};
- this.callParent(arguments)
- },
- add: function(c) {
- if (!c) {
- return null
- }
- if (!c.isSprite) {
- c = Ext.create("sprite." + c.type, c);
- c.setParent(this);
- c.setSurface(this.getSurface())
- }
- var d = this,
- a = d.attr,
- b = c.applyTransformations;
- c.applyTransformations = function() {
- if (c.attr.dirtyTransform) {
- a.dirtyTransform = true;
- a.bbox.plain.dirty = true;
- a.bbox.transform.dirty = true
- }
- b.call(c)
- };
- d.sprites.push(c);
- d.sprites.map[c.id] = c.getId();
- a.bbox.plain.dirty = true;
- a.bbox.transform.dirty = true;
- return c
- },
- updateSurface: function(a) {
- for (var b = 0, c = this.sprites.length; b < c; b++) {
- this.sprites[b].setSurface(a)
- }
- },
- addAll: function(b) {
- if (b.isSprite || b.type) {
- this.add(b)
- } else {
- if (Ext.isArray(b)) {
- var a = 0;
- while (a < b.length) {
- this.add(b[a++])
- }
- }
- }
- },
- updatePlainBBox: function(g) {
- var e = this,
- b = Infinity,
- h = -Infinity,
- f = Infinity,
- a = -Infinity,
- j, k, c, d;
- for (c = 0, d = e.sprites.length; c < d; c++) {
- j = e.sprites[c];
- j.applyTransformations();
- k = j.getBBox();
- if (b > k.x) {
- b = k.x
- }
- if (h < k.x + k.width) {
- h = k.x + k.width
- }
- if (f > k.y) {
- f = k.y
- }
- if (a < k.y + k.height) {
- a = k.y + k.height
- }
- }
- g.x = b;
- g.y = f;
- g.width = h - b;
- g.height = a - f
- },
- render: function(a, b, f) {
- var d = this.attr.matrix,
- c, e;
- d.toContext(b);
- for (c = 0, e = this.sprites.length; c < e; c++) {
- a.renderSprite(this.sprites[c], f)
- }
- },
- destroy: function() {
- var c = this,
- d = c.sprites,
- b = d.length,
- a;
- c.callParent();
- for (a = 0; a < b; a++) {
- d[a].destroy()
- }
- d.length = 0
- }
-});
-Ext.define("Ext.draw.sprite.Cross", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.cross",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size / 1.7,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c, ",", e, "l", [-c, -c, c, -c, c, c, c, -c, c, c, -c, c, c, c, -c, c, -c, -c, -c, c, -c, -c, "z"]))
- }
-});
-Ext.define("Ext.draw.sprite.Diamond", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.diamond",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 1.25,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString(["M", a, e - c, "l", c, c, -c, c, -c, -c, c, -c, "z"])
- }
-});
-Ext.define("Ext.draw.sprite.Ellipse", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.ellipse",
- type: "ellipse",
- inheritableStatics: {
- def: {
- processors: {
- cx: "number",
- cy: "number",
- rx: "number",
- ry: "number",
- axisRotation: "number"
- },
- aliases: {
- radius: "r",
- x: "cx",
- y: "cy",
- centerX: "cx",
- centerY: "cy",
- radiusX: "rx",
- radiusY: "ry"
- },
- defaults: {
- cx: 0,
- cy: 0,
- rx: 1,
- ry: 1,
- axisRotation: 0
- },
- triggers: {
- cx: "path",
- cy: "path",
- rx: "path",
- ry: "path",
- axisRotation: "path"
- }
- }
- },
- updatePlainBBox: function(c) {
- var b = this.attr,
- a = b.cx,
- f = b.cy,
- e = b.rx,
- d = b.ry;
- c.x = a - e;
- c.y = f - d;
- c.width = e + e;
- c.height = d + d
- },
- updateTransformedBBox: function(d) {
- var i = this.attr,
- f = i.cx,
- e = i.cy,
- c = i.rx,
- b = i.ry,
- l = b / c,
- m = i.matrix.clone(),
- a, q, k, j, p, o, n, g;
- m.append(1, 0, 0, l, 0, e * (1 - l));
- a = m.getXX();
- k = m.getYX();
- p = m.getDX();
- q = m.getXY();
- j = m.getYY();
- o = m.getDY();
- n = Math.sqrt(a * a + k * k) * c;
- g = Math.sqrt(q * q + j * j) * c;
- d.x = f * a + e * k + p - n;
- d.y = f * q + e * j + o - g;
- d.width = n + n;
- d.height = g + g
- },
- updatePath: function(b, a) {
- b.ellipse(a.cx, a.cy, a.rx, a.ry, a.axisRotation, 0, Math.PI * 2, false)
- }
-});
-Ext.define("Ext.draw.sprite.EllipticalArc", {
- extend: "Ext.draw.sprite.Ellipse",
- alias: "sprite.ellipticalArc",
- type: "ellipticalArc",
- inheritableStatics: {
- def: {
- processors: {
- startAngle: "number",
- endAngle: "number",
- anticlockwise: "bool"
- },
- aliases: {
- from: "startAngle",
- to: "endAngle",
- start: "startAngle",
- end: "endAngle"
- },
- defaults: {
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false
- },
- triggers: {
- startAngle: "path",
- endAngle: "path",
- anticlockwise: "path"
- }
- }
- },
- updatePath: function(b, a) {
- b.ellipse(a.cx, a.cy, a.rx, a.ry, a.axisRotation, a.startAngle, a.endAngle, a.anticlockwise)
- }
-});
-Ext.define("Ext.draw.sprite.Rect", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.rect",
- type: "rect",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number",
- radius: "number"
- },
- aliases: {},
- triggers: {
- x: "path",
- y: "path",
- width: "path",
- height: "path",
- radius: "path"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 8,
- height: 8,
- radius: 0
- }
- }
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.x;
- b.y = a.y;
- b.width = a.width;
- b.height = a.height
- },
- updateTransformedBBox: function(a, b) {
- this.attr.matrix.transformBBox(b, this.attr.radius, a)
- },
- updatePath: function(f, d) {
- var c = d.x,
- g = d.y,
- e = d.width,
- b = d.height,
- a = Math.min(d.radius, Math.abs(d.height) * 0.5, Math.abs(d.width) * 0.5);
- if (a === 0) {
- f.rect(c, g, e, b)
- } else {
- f.moveTo(c + a, g);
- f.arcTo(c + e, g, c + e, g + b, a);
- f.arcTo(c + e, g + b, c, g + b, a);
- f.arcTo(c, g + b, c, g, a);
- f.arcTo(c, g, c + a, g, a)
- }
- }
-});
-Ext.define("Ext.draw.sprite.Image", {
- extend: "Ext.draw.sprite.Rect",
- alias: "sprite.image",
- type: "image",
- statics: {
- imageLoaders: {}
- },
- inheritableStatics: {
- def: {
- processors: {
- src: "string"
- },
- defaults: {
- src: "",
- width: null,
- height: null
- }
- }
- },
- render: function(c, o) {
- var j = this,
- h = j.attr,
- n = h.matrix,
- a = h.src,
- l = h.x,
- k = h.y,
- b = h.width,
- m = h.height,
- g = Ext.draw.sprite.Image.imageLoaders[a],
- f, d, e;
- if (g && g.done) {
- n.toContext(o);
- d = g.image;
- o.drawImage(d, l, k, b || (d.naturalWidth || d.width) / c.devicePixelRatio, m || (d.naturalHeight || d.height) / c.devicePixelRatio)
- } else {
- if (!g) {
- f = new Image();
- g = Ext.draw.sprite.Image.imageLoaders[a] = {
- image: f,
- done: false,
- pendingSprites: [j],
- pendingSurfaces: [c]
- };
- f.width = b;
- f.height = m;
- f.onload = function() {
- if (!g.done) {
- g.done = true;
- for (e = 0; e < g.pendingSprites.length; e++) {
- g.pendingSprites[e].setDirty(true)
- }
- for (e in g.pendingSurfaces) {
- g.pendingSurfaces[e].renderFrame()
- }
- }
- };
- f.src = a
- } else {
- Ext.Array.include(g.pendingSprites, j);
- Ext.Array.include(g.pendingSurfaces, c)
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Instancing", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.instancing",
- type: "instancing",
- isInstancing: true,
- config: {
- template: null
- },
- instances: null,
- applyTemplate: function(a) {
- if (!a.isSprite) {
- if (!a.xclass && !a.type) {
- a.type = "circle"
- }
- a = Ext.create(a.xclass || "sprite." + a.type, a)
- }
- a.setParent(this);
- return a
- },
- updateTemplate: function(a, b) {
- if (b) {
- delete b.ownAttr
- }
- a.setSurface(this.getSurface());
- a.ownAttr = a.attr;
- this.clearAll()
- },
- updateSurface: function(a) {
- var b = this.getTemplate();
- if (b) {
- b.setSurface(a)
- }
- },
- get: function(a) {
- return this.instances[a]
- },
- getCount: function() {
- return this.instances.length
- },
- clearAll: function() {
- var a = this.getTemplate();
- a.attr.children = this.instances = [];
- this.position = 0
- },
- createInstance: function(d, f, c) {
- var e = this.getTemplate(),
- b = e.attr,
- a = Ext.Object.chain(b);
- e.topModifier.prepareAttributes(a);
- e.attr = a;
- e.setAttributes(d, f, c);
- a.template = e;
- this.instances.push(a);
- e.attr = b;
- this.position++;
- return a
- },
- getBBox: function() {
- return null
- },
- getBBoxFor: function(b, d) {
- var c = this.getTemplate(),
- a = c.attr,
- e;
- c.attr = this.instances[b];
- e = c.getBBox(d);
- c.attr = a;
- return e
- },
- isVisible: function() {
- var b = this.attr,
- c = this.getParent(),
- a;
- a = c && c.isSurface && !b.hidden && b.globalAlpha;
- return !!a
- },
- isInstanceVisible: function(c) {
- var e = this,
- d = e.getTemplate(),
- b = d.attr,
- f = e.instances,
- a = false;
- if (!Ext.isNumber(c) || c < 0 || c >= f.length || !e.isVisible()) {
- return a
- }
- d.attr = f[c];
- a = d.isVisible(point, options);
- d.attr = b;
- return a
- },
- render: function(b, l, d, h) {
- var g = this,
- j = g.getTemplate(),
- k = g.attr.matrix,
- c = j.attr,
- a = g.instances,
- e, f = g.position;
- k.toContext(l);
- j.preRender(b, l, d, h);
- j.useAttributes(l, h);
- for (e = 0; e < f; e++) {
- if (a[e].dirtyZIndex) {
- break
- }
- }
- for (e = 0; e < f; e++) {
- if (a[e].hidden) {
- continue
- }
- l.save();
- j.attr = a[e];
- j.useAttributes(l, h);
- j.render(b, l, d, h);
- l.restore()
- }
- j.attr = c
- },
- setAttributesFor: function(c, e, f) {
- var d = this.getTemplate(),
- b = d.attr,
- a = this.instances[c];
- if (!a) {
- return
- }
- d.attr = a;
- if (f) {
- e = Ext.apply({}, e)
- } else {
- e = d.self.def.normalize(e)
- }
- d.topModifier.pushDown(a, e);
- d.attr = b
- },
- destroy: function() {
- var b = this,
- a = b.getTemplate();
- b.instances = null;
- if (a) {
- a.destroy()
- }
- b.callParent()
- }
-});
-Ext.define("Ext.draw.overrides.sprite.Instancing", {
- override: "Ext.draw.sprite.Instancing",
- hitTest: function(f, j) {
- var e = this,
- g = e.getTemplate(),
- b = g.attr,
- a = e.instances,
- d = a.length,
- c = 0,
- h = null;
- if (!e.isVisible()) {
- return h
- }
- for (; c < d; c++) {
- g.attr = a[c];
- h = g.hitTest(f, j);
- if (h) {
- h.isInstance = true;
- h.template = h.sprite;
- h.sprite = this;
- h.instance = a[c];
- h.index = c;
- return h
- }
- }
- g.attr = b;
- return h
- }
-});
-Ext.define("Ext.draw.sprite.Line", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.line",
- type: "line",
- inheritableStatics: {
- def: {
- processors: {
- fromX: "number",
- fromY: "number",
- toX: "number",
- toY: "number"
- },
- defaults: {
- fromX: 0,
- fromY: 0,
- toX: 1,
- toY: 1,
- strokeStyle: "black"
- },
- aliases: {
- x1: "fromX",
- y1: "fromY",
- x2: "toX",
- y2: "toY"
- }
- }
- },
- updateLineBBox: function(b, i, s, g, r, f) {
- var o = this.attr,
- q = o.matrix,
- h = o.lineWidth / 2,
- m, l, d, c, k, j, n;
- if (i) {
- n = q.transformPoint([s, g]);
- s = n[0];
- g = n[1];
- n = q.transformPoint([r, f]);
- r = n[0];
- f = n[1]
- }
- m = Math.min(s, r);
- d = Math.max(s, r);
- l = Math.min(g, f);
- c = Math.max(g, f);
- var t = Math.atan2(d - m, c - l),
- a = Math.sin(t),
- e = Math.cos(t),
- k = h * e,
- j = h * a;
- m -= k;
- l -= j;
- d += k;
- c += j;
- b.x = m;
- b.y = l;
- b.width = d - m;
- b.height = c - l
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- this.updateLineBBox(b, false, a.fromX, a.fromY, a.toX, a.toY)
- },
- updateTransformedBBox: function(b, c) {
- var a = this.attr;
- this.updateLineBBox(b, true, a.fromX, a.fromY, a.toX, a.toY)
- },
- render: function(b, c) {
- var a = this.attr,
- d = this.attr.matrix;
- d.toContext(c);
- c.beginPath();
- c.moveTo(a.fromX, a.fromY);
- c.lineTo(a.toX, a.toY);
- c.stroke()
- }
-});
-Ext.define("Ext.draw.sprite.Plus", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.plus",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size / 1.3,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c / 2, ",", e - c / 2, "l", [0, -c, c, 0, 0, c, c, 0, 0, c, -c, 0, 0, c, -c, 0, 0, -c, -c, 0, 0, -c, "z"]))
- }
-});
-Ext.define("Ext.draw.sprite.Sector", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.sector",
- type: "sector",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- margin: "number"
- },
- aliases: {
- rho: "endRho"
- },
- triggers: {
- centerX: "path,bbox",
- centerY: "path,bbox",
- startAngle: "path,bbox",
- endAngle: "path,bbox",
- startRho: "path,bbox",
- endRho: "path,bbox",
- margin: "path,bbox"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: 0,
- endAngle: 0,
- startRho: 0,
- endRho: 150,
- margin: 0,
- path: "M 0,0"
- }
- }
- },
- getMidAngle: function() {
- return this.midAngle || 0
- },
- updatePath: function(j, h) {
- var g = Math.min(h.startAngle, h.endAngle),
- c = Math.max(h.startAngle, h.endAngle),
- b = this.midAngle = (g + c) * 0.5,
- d = h.margin,
- f = h.centerX,
- e = h.centerY,
- i = Math.min(h.startRho, h.endRho),
- a = Math.max(h.startRho, h.endRho);
- if (d) {
- f += d * Math.cos(b);
- e += d * Math.sin(b)
- }
- j.moveTo(f + i * Math.cos(g), e + i * Math.sin(g));
- j.lineTo(f + a * Math.cos(g), e + a * Math.sin(g));
- j.arc(f, e, a, g, c, false);
- j.lineTo(f + i * Math.cos(c), e + i * Math.sin(c));
- j.arc(f, e, i, c, g, true)
- }
-});
-Ext.define("Ext.draw.sprite.Square", {
- extend: "Ext.draw.sprite.Rect",
- alias: "sprite.square",
- inheritableStatics: {
- def: {
- processors: {
- size: "number"
- },
- defaults: {
- size: 4
- },
- triggers: {
- size: "size"
- },
- updaters: {
- size: function(a) {
- var c = a.size,
- b = a.lineWidth / 2;
- this.setAttributes({
- x: a.x - c - b,
- y: a.y - c,
- height: 2 * c,
- width: 2 * c
- })
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.TextMeasurer", {
- singleton: true,
- requires: ["Ext.util.TextMetrics"],
- measureDiv: null,
- measureCache: {},
- precise: Ext.isIE8,
- measureDivTpl: {
- tag: "div",
- style: {
- overflow: "hidden",
- position: "relative",
- "float": "left",
- width: 0,
- height: 0
- },
- children: {
- tag: "div",
- style: {
- display: "block",
- position: "absolute",
- x: -100000,
- y: -100000,
- padding: 0,
- margin: 0,
- "z-index": -100000,
- "white-space": "nowrap"
- }
- }
- },
- actualMeasureText: function(g, b) {
- var e = Ext.draw.TextMeasurer,
- f = e.measureDiv,
- a = 100000,
- c;
- if (!f) {
- var d = Ext.Element.create({
- style: {
- overflow: "hidden",
- position: "relative",
- "float": "left",
- width: 0,
- height: 0
- }
- });
- e.measureDiv = f = Ext.Element.create({
- style: {
- position: "absolute",
- x: a,
- y: a,
- "z-index": -a,
- "white-space": "nowrap",
- display: "block",
- padding: 0,
- margin: 0
- }
- });
- Ext.getBody().appendChild(d);
- d.appendChild(f)
- }
- if (b) {
- f.setStyle({
- font: b,
- lineHeight: "normal"
- })
- }
- f.setText("(" + g + ")");
- c = f.getSize();
- f.setText("()");
- c.width -= f.getSize().width;
- return c
- },
- measureTextSingleLine: function(h, d) {
- if (this.precise) {
- return this.preciseMeasureTextSingleLine(h, d)
- }
- h = h.toString();
- var a = this.measureCache,
- g = h.split(""),
- c = 0,
- j = 0,
- l, b, e, f, k;
- if (!a[d]) {
- a[d] = {}
- }
- a = a[d];
- if (a[h]) {
- return a[h]
- }
- for (e = 0, f = g.length; e < f; e++) {
- b = g[e];
- if (!(l = a[b])) {
- k = this.actualMeasureText(b, d);
- l = a[b] = k
- }
- c += l.width;
- j = Math.max(j, l.height)
- }
- return a[h] = {
- width: c,
- height: j
- }
- },
- preciseMeasureTextSingleLine: function(c, a) {
- c = c.toString();
- var b = this.measureDiv || (this.measureDiv = Ext.getBody().createChild(this.measureDivTpl).down("div"));
- b.setStyle({
- font: a || ""
- });
- return Ext.util.TextMetrics.measure(b, c)
- },
- measureText: function(e, b) {
- var h = e.split("\n"),
- d = h.length,
- f = 0,
- a = 0,
- j, c, g;
- if (d === 1) {
- return this.measureTextSingleLine(e, b)
- }
- g = [];
- for (c = 0; c < d; c++) {
- j = this.measureTextSingleLine(h[c], b);
- g.push(j);
- f += j.height;
- a = Math.max(a, j.width)
- }
- return {
- width: a,
- height: f,
- sizes: g
- }
- }
-});
-Ext.define("Ext.draw.sprite.Text", function() {
- var d = {
- "xx-small": true,
- "x-small": true,
- small: true,
- medium: true,
- large: true,
- "x-large": true,
- "xx-large": true
- };
- var b = {
- normal: true,
- bold: true,
- bolder: true,
- lighter: true,
- 100: true,
- 200: true,
- 300: true,
- 400: true,
- 500: true,
- 600: true,
- 700: true,
- 800: true,
- 900: true
- };
- var a = {
- start: "start",
- left: "start",
- center: "center",
- middle: "center",
- end: "end",
- right: "end"
- };
- var c = {
- top: "top",
- hanging: "hanging",
- middle: "middle",
- center: "middle",
- alphabetic: "alphabetic",
- ideographic: "ideographic",
- bottom: "bottom"
- };
- return {
- extend: "Ext.draw.sprite.Sprite",
- requires: ["Ext.draw.TextMeasurer", "Ext.draw.Color"],
- alias: "sprite.text",
- type: "text",
- lineBreakRe: /\r?\n/g,
- inheritableStatics: {
- def: {
- animationProcessors: {
- text: "text"
- },
- processors: {
- x: "number",
- y: "number",
- text: "string",
- fontSize: function(e) {
- if (Ext.isNumber(+e)) {
- return e + "px"
- } else {
- if (e.match(Ext.dom.Element.unitRe)) {
- return e
- } else {
- if (e in d) {
- return e
- }
- }
- }
- },
- fontStyle: "enums(,italic,oblique)",
- fontVariant: "enums(,small-caps)",
- fontWeight: function(e) {
- if (e in b) {
- return String(e)
- } else {
- return ""
- }
- },
- fontFamily: "string",
- textAlign: function(e) {
- return a[e] || "center"
- },
- textBaseline: function(e) {
- return c[e] || "alphabetic"
- },
- font: "string"
- },
- aliases: {
- "font-size": "fontSize",
- "font-family": "fontFamily",
- "font-weight": "fontWeight",
- "font-variant": "fontVariant",
- "text-anchor": "textAlign"
- },
- defaults: {
- fontStyle: "",
- fontVariant: "",
- fontWeight: "",
- fontSize: "10px",
- fontFamily: "sans-serif",
- font: "10px sans-serif",
- textBaseline: "alphabetic",
- textAlign: "start",
- strokeStyle: "rgba(0, 0, 0, 0)",
- fillStyle: "#000",
- x: 0,
- y: 0,
- text: ""
- },
- triggers: {
- fontStyle: "fontX,bbox",
- fontVariant: "fontX,bbox",
- fontWeight: "fontX,bbox",
- fontSize: "fontX,bbox",
- fontFamily: "fontX,bbox",
- font: "font,bbox,canvas",
- textBaseline: "bbox",
- textAlign: "bbox",
- x: "bbox",
- y: "bbox",
- text: "bbox"
- },
- updaters: {
- fontX: "makeFontShorthand",
- font: "parseFontShorthand"
- }
- }
- },
- constructor: function(e) {
- if (e && e.font) {
- e = Ext.clone(e);
- for (var f in e) {
- if (f !== "font" && f.indexOf("font") === 0) {
- delete e[f]
- }
- }
- }
- Ext.draw.sprite.Sprite.prototype.constructor.call(this, e)
- },
- fontValuesMap: {
- italic: "fontStyle",
- oblique: "fontStyle",
- "small-caps": "fontVariant",
- bold: "fontWeight",
- bolder: "fontWeight",
- lighter: "fontWeight",
- "100": "fontWeight",
- "200": "fontWeight",
- "300": "fontWeight",
- "400": "fontWeight",
- "500": "fontWeight",
- "600": "fontWeight",
- "700": "fontWeight",
- "800": "fontWeight",
- "900": "fontWeight",
- "xx-small": "fontSize",
- "x-small": "fontSize",
- small: "fontSize",
- medium: "fontSize",
- large: "fontSize",
- "x-large": "fontSize",
- "xx-large": "fontSize"
- },
- makeFontShorthand: function(e) {
- var f = [];
- if (e.fontStyle) {
- f.push(e.fontStyle)
- }
- if (e.fontVariant) {
- f.push(e.fontVariant)
- }
- if (e.fontWeight) {
- f.push(e.fontWeight)
- }
- if (e.fontSize) {
- f.push(e.fontSize)
- }
- if (e.fontFamily) {
- f.push(e.fontFamily)
- }
- this.setAttributes({
- font: f.join(" ")
- }, true)
- },
- parseFontShorthand: function(j) {
- var m = j.font,
- k = m.length,
- l = {},
- n = this.fontValuesMap,
- e = 0,
- i, g, f, h;
- while (e < k && i !== -1) {
- i = m.indexOf(" ", e);
- if (i < 0) {
- f = m.substr(e)
- } else {
- if (i > e) {
- f = m.substr(e, i - e)
- } else {
- continue
- }
- }
- g = f.indexOf("/");
- if (g > 0) {
- f = f.substr(0, g)
- } else {
- if (g === 0) {
- continue
- }
- }
- if (f !== "normal" && f !== "inherit") {
- h = n[f];
- if (h) {
- l[h] = f
- } else {
- if (f.match(Ext.dom.Element.unitRe)) {
- l.fontSize = f
- } else {
- l.fontFamily = m.substr(e);
- break
- }
- }
- }
- e = i + 1
- }
- if (!l.fontStyle) {
- l.fontStyle = ""
- }
- if (!l.fontVariant) {
- l.fontVariant = ""
- }
- if (!l.fontWeight) {
- l.fontWeight = ""
- }
- this.setAttributes(l, true)
- },
- fontProperties: {
- fontStyle: true,
- fontVariant: true,
- fontWeight: true,
- fontSize: true,
- fontFamily: true
- },
- setAttributes: function(g, i, e) {
- var f, h;
- if (g && g.font) {
- h = {};
- for (f in g) {
- if (!(f in this.fontProperties)) {
- h[f] = g[f]
- }
- }
- g = h
- }
- this.callParent([g, i, e])
- },
- getBBox: function(g) {
- var h = this,
- f = h.attr.bbox.plain,
- e = h.getSurface();
- if (f.dirty) {
- h.updatePlainBBox(f);
- f.dirty = false
- }
- if (e.getInherited().rtl && e.getFlipRtlText()) {
- h.updatePlainBBox(f, true)
- }
- return h.callParent([g])
- },
- rtlAlignments: {
- start: "end",
- center: "center",
- end: "start"
- },
- updatePlainBBox: function(k, B) {
- var C = this,
- w = C.attr,
- o = w.x,
- n = w.y,
- q = [],
- t = w.font,
- r = w.text,
- s = w.textBaseline,
- l = w.textAlign,
- u = (B && C.oldSize) ? C.oldSize : (C.oldSize = Ext.draw.TextMeasurer.measureText(r, t)),
- z = C.getSurface(),
- p = z.getInherited().rtl,
- v = p && z.getFlipRtlText(),
- h = z.getRect(),
- f = u.sizes,
- g = u.height,
- j = u.width,
- m = f ? f.length : 0,
- e, A = 0;
- switch (s) {
- case "hanging":
- case "top":
- break;
- case "ideographic":
- case "bottom":
- n -= g;
- break;
- case "alphabetic":
- n -= g * 0.8;
- break;
- case "middle":
- n -= g * 0.5;
- break
- }
- if (v) {
- o = h[2] - h[0] - o;
- l = C.rtlAlignments[l]
- }
- switch (l) {
- case "start":
- if (p) {
- for (; A < m; A++) {
- e = f[A].width;
- q.push(-(j - e))
- }
- }
- break;
- case "end":
- o -= j;
- if (p) {
- break
- }
- for (; A < m; A++) {
- e = f[A].width;
- q.push(j - e)
- }
- break;
- case "center":
- o -= j * 0.5;
- for (; A < m; A++) {
- e = f[A].width;
- q.push((p ? -1 : 1) * (j - e) * 0.5)
- }
- break
- }
- w.textAlignOffsets = q;
- k.x = o;
- k.y = n;
- k.width = j;
- k.height = g
- },
- setText: function(e) {
- this.setAttributes({
- text: e
- }, true)
- },
- render: function(e, q, k) {
- var h = this,
- g = h.attr,
- p = Ext.draw.Matrix.fly(g.matrix.elements.slice(0)),
- o = h.getBBox(true),
- s = g.textAlignOffsets,
- m = Ext.draw.Color.RGBA_NONE,
- l, j, f, r, n;
- if (g.text.length === 0) {
- return
- }
- r = g.text.split(h.lineBreakRe);
- n = o.height / r.length;
- l = g.bbox.plain.x;
- j = g.bbox.plain.y + n * 0.78;
- p.toContext(q);
- if (e.getInherited().rtl) {
- l += g.bbox.plain.width
- }
- for (f = 0; f < r.length; f++) {
- if (q.fillStyle !== m) {
- q.fillText(r[f], l + (s[f] || 0), j + n * f)
- }
- if (q.strokeStyle !== m) {
- q.strokeText(r[f], l + (s[f] || 0), j + n * f)
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Tick", {
- extend: "Ext.draw.sprite.Line",
- alias: "sprite.tick",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "tick",
- y: "tick",
- size: "tick"
- },
- updaters: {
- tick: function(b) {
- var d = b.size * 1.5,
- c = b.lineWidth / 2,
- a = b.x,
- e = b.y;
- this.setAttributes({
- fromX: a - c,
- fromY: e - d,
- toX: a - c,
- toY: e + d
- })
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Triangle", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.triangle",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 2.2,
- a = b.x,
- e = b.y;
- d.fromSvgString("M".concat(a, ",", e, "m0-", c * 0.58, "l", c * 0.5, ",", c * 0.87, "-", c, ",0z"))
- }
-});
-Ext.define("Ext.draw.gradient.Linear", {
- extend: "Ext.draw.gradient.Gradient",
- requires: ["Ext.draw.Color"],
- type: "linear",
- config: {
- degrees: 0,
- radians: 0
- },
- applyRadians: function(b, a) {
- if (Ext.isNumber(b)) {
- return b
- }
- return a
- },
- applyDegrees: function(b, a) {
- if (Ext.isNumber(b)) {
- return b
- }
- return a
- },
- updateRadians: function(a) {
- this.setDegrees(Ext.draw.Draw.degrees(a))
- },
- updateDegrees: function(a) {
- this.setRadians(Ext.draw.Draw.rad(a))
- },
- generateGradient: function(q, o) {
- var c = this.getRadians(),
- p = Math.cos(c),
- j = Math.sin(c),
- m = o.width,
- f = o.height,
- d = o.x + m * 0.5,
- b = o.y + f * 0.5,
- n = this.getStops(),
- g = n.length,
- k, a, e;
- if (Ext.isNumber(d + b) && f > 0 && m > 0) {
- a = (Math.sqrt(f * f + m * m) * Math.abs(Math.cos(c - Math.atan(f / m)))) / 2;
- k = q.createLinearGradient(d + p * a, b + j * a, d - p * a, b - j * a);
- for (e = 0; e < g; e++) {
- k.addColorStop(n[e].offset, n[e].color)
- }
- return k
- }
- return Ext.draw.Color.NONE
- }
-});
-Ext.define("Ext.draw.gradient.Radial", {
- extend: "Ext.draw.gradient.Gradient",
- type: "radial",
- config: {
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- }
- },
- applyStart: function(a, b) {
- if (!b) {
- return a
- }
- var c = {
- x: b.x,
- y: b.y,
- r: b.r
- };
- if ("x" in a) {
- c.x = a.x
- } else {
- if ("centerX" in a) {
- c.x = a.centerX
- }
- }
- if ("y" in a) {
- c.y = a.y
- } else {
- if ("centerY" in a) {
- c.y = a.centerY
- }
- }
- if ("r" in a) {
- c.r = a.r
- } else {
- if ("radius" in a) {
- c.r = a.radius
- }
- }
- return c
- },
- applyEnd: function(b, a) {
- if (!a) {
- return b
- }
- var c = {
- x: a.x,
- y: a.y,
- r: a.r
- };
- if ("x" in b) {
- c.x = b.x
- } else {
- if ("centerX" in b) {
- c.x = b.centerX
- }
- }
- if ("y" in b) {
- c.y = b.y
- } else {
- if ("centerY" in b) {
- c.y = b.centerY
- }
- }
- if ("r" in b) {
- c.r = b.r
- } else {
- if ("radius" in b) {
- c.r = b.radius
- }
- }
- return c
- },
- generateGradient: function(n, m) {
- var a = this.getStart(),
- b = this.getEnd(),
- k = m.width * 0.5,
- d = m.height * 0.5,
- j = m.x + k,
- f = m.y + d,
- g = n.createRadialGradient(j + a.x * k, f + a.y * d, a.r * Math.max(k, d), j + b.x * k, f + b.y * d, b.r * Math.max(k, d)),
- l = this.getStops(),
- e = l.length,
- c;
- for (c = 0; c < e; c++) {
- g.addColorStop(l[c].offset, l[c].color)
- }
- return g
- }
-});
-Ext.define("Ext.draw.Surface", {
- extend: "Ext.draw.SurfaceBase",
- xtype: "surface",
- requires: ["Ext.draw.sprite.*", "Ext.draw.gradient.*", "Ext.draw.sprite.AttributeDefinition", "Ext.draw.Matrix", "Ext.draw.Draw"],
- uses: ["Ext.draw.engine.Canvas"],
- devicePixelRatio: window.devicePixelRatio || window.screen.deviceXDPI / window.screen.logicalXDPI,
- deprecated: {
- "5.1.0": {
- statics: {
- methods: {
- stableSort: function(a) {
- return Ext.Array.sort(a, function(d, c) {
- return d.attr.zIndex - c.attr.zIndex
- })
- }
- }
- }
- }
- },
- config: {
- cls: Ext.baseCSSPrefix + "surface",
- rect: null,
- background: null,
- items: [],
- dirty: false,
- flipRtlText: false
- },
- isSurface: true,
- isPendingRenderFrame: false,
- dirtyPredecessorCount: 0,
- constructor: function(a) {
- var b = this;
- b.predecessors = [];
- b.successors = [];
- b.map = {};
- b.callParent([a]);
- b.matrix = new Ext.draw.Matrix();
- b.inverseMatrix = b.matrix.inverse()
- },
- roundPixel: function(a) {
- return Math.round(this.devicePixelRatio * a) / this.devicePixelRatio
- },
- waitFor: function(a) {
- var b = this,
- c = b.predecessors;
- if (!Ext.Array.contains(c, a)) {
- c.push(a);
- a.successors.push(b);
- if (a.getDirty()) {
- b.dirtyPredecessorCount++
- }
- }
- },
- updateDirty: function(d) {
- var c = this.successors,
- e = c.length,
- b = 0,
- a;
- for (; b < e; b++) {
- a = c[b];
- if (d) {
- a.dirtyPredecessorCount++;
- a.setDirty(true)
- } else {
- a.dirtyPredecessorCount--;
- if (a.dirtyPredecessorCount === 0 && a.isPendingRenderFrame) {
- a.renderFrame()
- }
- }
- }
- },
- applyBackground: function(a, b) {
- this.setDirty(true);
- if (Ext.isString(a)) {
- a = {
- fillStyle: a
- }
- }
- return Ext.factory(a, Ext.draw.sprite.Rect, b)
- },
- applyRect: function(a, b) {
- if (b && a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]) {
- return
- }
- if (Ext.isArray(a)) {
- return [a[0], a[1], a[2], a[3]]
- } else {
- if (Ext.isObject(a)) {
- return [a.x || a.left, a.y || a.top, a.width || (a.right - a.left), a.height || (a.bottom - a.top)]
- }
- }
- },
- updateRect: function(i) {
- var h = this,
- c = i[0],
- f = i[1],
- g = c + i[2],
- a = f + i[3],
- e = h.getBackground(),
- d = h.element;
- d.setLocalXY(Math.floor(c), Math.floor(f));
- d.setSize(Math.ceil(g - Math.floor(c)), Math.ceil(a - Math.floor(f)));
- if (e) {
- e.setAttributes({
- x: 0,
- y: 0,
- width: Math.ceil(g - Math.floor(c)),
- height: Math.ceil(a - Math.floor(f))
- })
- }
- h.setDirty(true)
- },
- resetTransform: function() {
- this.matrix.set(1, 0, 0, 1, 0, 0);
- this.inverseMatrix.set(1, 0, 0, 1, 0, 0);
- this.setDirty(true)
- },
- get: function(a) {
- return this.map[a] || this.getItems()[a]
- },
- add: function() {
- var g = this,
- e = Array.prototype.slice.call(arguments),
- j = Ext.isArray(e[0]),
- a = g.map,
- c = [],
- f, k, h, b, d;
- f = Ext.Array.clean(j ? e[0] : e);
- if (!f.length) {
- return c
- }
- for (b = 0, d = f.length; b < d; b++) {
- k = f[b];
- h = null;
- if (k.isSprite && !a[k.getId()]) {
- h = k
- } else {
- if (!a[k.id]) {
- h = this.createItem(k)
- }
- }
- if (h) {
- a[h.getId()] = h;
- c.push(h);
- h.setParent(g);
- h.setSurface(g);
- g.onAdd(h)
- }
- }
- f = g.getItems();
- if (f) {
- f.push.apply(f, c)
- }
- g.dirtyZIndex = true;
- g.setDirty(true);
- if (!j && c.length === 1) {
- return c[0]
- } else {
- return c
- }
- },
- onAdd: Ext.emptyFn,
- remove: function(a, c) {
- var b = this,
- e, d;
- if (a) {
- if (a.charAt) {
- a = b.map[a]
- }
- if (!a || !a.isSprite) {
- return null
- }
- if (a.isDestroyed || a.isDestroying) {
- return a
- }
- e = a.getId();
- d = b.map[e];
- delete b.map[e];
- if (c) {
- a.destroy()
- }
- if (!d) {
- return a
- }
- a.setParent(null);
- a.setSurface(null);
- Ext.Array.remove(b.getItems(), a);
- b.dirtyZIndex = true;
- b.setDirty(true)
- }
- return a || null
- },
- removeAll: function(d) {
- var a = this.getItems(),
- b = a.length - 1,
- c;
- if (d) {
- for (; b >= 0; b--) {
- a[b].destroy()
- }
- } else {
- for (; b >= 0; b--) {
- c = a[b];
- c.setParent(null);
- c.setSurface(null)
- }
- }
- a.length = 0;
- this.map = {};
- this.dirtyZIndex = true
- },
- applyItems: function(a) {
- if (this.getItems()) {
- this.removeAll(true)
- }
- return Ext.Array.from(this.add(a))
- },
- createItem: function(a) {
- return Ext.create(a.xclass || "sprite." + a.type, a)
- },
- getBBox: function(f, b) {
- var f = Ext.Array.from(f),
- c = Infinity,
- h = -Infinity,
- g = Infinity,
- a = -Infinity,
- j, k, d, e;
- for (d = 0, e = f.length; d < e; d++) {
- j = f[d];
- k = j.getBBox(b);
- if (c > k.x) {
- c = k.x
- }
- if (h < k.x + k.width) {
- h = k.x + k.width
- }
- if (g > k.y) {
- g = k.y
- }
- if (a < k.y + k.height) {
- a = k.y + k.height
- }
- }
- return {
- x: c,
- y: g,
- width: h - c,
- height: a - g
- }
- },
- emptyRect: [0, 0, 0, 0],
- getEventXY: function(d) {
- var g = this,
- f = g.getInherited().rtl,
- c = d.getXY(),
- a = g.getOwnerBody(),
- i = a.getXY(),
- h = g.getRect() || g.emptyRect,
- j = [],
- b;
- if (f) {
- b = a.getWidth();
- j[0] = i[0] - c[0] - h[0] + b
- } else {
- j[0] = c[0] - i[0] - h[0]
- }
- j[1] = c[1] - i[1] - h[1];
- return j
- },
- clear: Ext.emptyFn,
- orderByZIndex: function() {
- var d = this,
- a = d.getItems(),
- e = false,
- b, c;
- if (d.getDirty()) {
- for (b = 0, c = a.length; b < c; b++) {
- if (a[b].attr.dirtyZIndex) {
- e = true;
- break
- }
- }
- if (e) {
- Ext.Array.sort(a, function(g, f) {
- return g.attr.zIndex - f.attr.zIndex
- });
- this.setDirty(true)
- }
- for (b = 0, c = a.length; b < c; b++) {
- a[b].attr.dirtyZIndex = false
- }
- }
- },
- repaint: function() {
- var a = this;
- a.repaint = Ext.emptyFn;
- Ext.defer(function() {
- delete a.repaint;
- a.element.repaint()
- }, 1)
- },
- renderFrame: function() {
- var g = this;
- if (!g.element) {
- return
- }
- if (g.dirtyPredecessorCount > 0) {
- g.isPendingRenderFrame = true;
- return
- }
- var f = g.getRect(),
- c = g.getBackground(),
- a = g.getItems(),
- e, b, d;
- if (!f) {
- return
- }
- g.orderByZIndex();
- if (g.getDirty()) {
- g.clear();
- g.clearTransform();
- if (c) {
- g.renderSprite(c)
- }
- for (b = 0, d = a.length; b < d; b++) {
- e = a[b];
- if (g.renderSprite(e) === false) {
- return
- }
- e.attr.textPositionCount = g.textPosition
- }
- g.setDirty(false)
- }
- },
- renderSprite: Ext.emptyFn,
- clearTransform: Ext.emptyFn,
- destroy: function() {
- var a = this;
- a.removeAll(true);
- a.predecessors = null;
- a.successors = null;
- a.callParent()
- }
-});
-Ext.define("Ext.draw.overrides.Surface", {
- override: "Ext.draw.Surface",
- hitTest: function(b, c) {
- var f = this,
- g = f.getItems(),
- e, d, a;
- c = c || Ext.draw.sprite.Sprite.defaultHitTestOptions;
- for (e = g.length - 1; e >= 0; e--) {
- d = g[e];
- if (d.hitTest) {
- a = d.hitTest(b, c);
- if (a) {
- return a
- }
- }
- }
- return null
- },
- hitTestEvent: function(b, a) {
- var c = this.getEventXY(b);
- return this.hitTest(c, a)
- }
-});
-Ext.define("Ext.draw.engine.SvgContext", {
- requires: ["Ext.draw.Color"],
- toSave: ["strokeOpacity", "strokeStyle", "fillOpacity", "fillStyle", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "lineDash", "lineDashOffset", "miterLimit", "shadowOffsetX", "shadowOffsetY", "shadowBlur", "shadowColor", "globalCompositeOperation", "position", "fillGradient", "strokeGradient"],
- strokeOpacity: 1,
- strokeStyle: "none",
- fillOpacity: 1,
- fillStyle: "none",
- lineDash: [],
- lineDashOffset: 0,
- globalAlpha: 1,
- lineWidth: 1,
- lineCap: "butt",
- lineJoin: "miter",
- miterLimit: 10,
- shadowOffsetX: 0,
- shadowOffsetY: 0,
- shadowBlur: 0,
- shadowColor: "none",
- globalCompositeOperation: "src",
- urlStringRe: /^url\(#([\w\-]+)\)$/,
- constructor: function(a) {
- this.surface = a;
- this.state = [];
- this.matrix = new Ext.draw.Matrix();
- this.path = null;
- this.clear()
- },
- clear: function() {
- this.group = this.surface.mainGroup;
- this.position = 0;
- this.path = null
- },
- getElement: function(a) {
- return this.surface.getSvgElement(this.group, a, this.position++)
- },
- removeElement: function(d) {
- var d = Ext.fly(d),
- h, g, b, f, a, e, c;
- if (!d) {
- return
- }
- if (d.dom.tagName === "g") {
- a = d.dom.gradients;
- for (c in a) {
- a[c].destroy()
- }
- } else {
- h = d.getAttribute("fill");
- g = d.getAttribute("stroke");
- b = h && h.match(this.urlStringRe);
- f = g && g.match(this.urlStringRe);
- if (b && b[1]) {
- e = Ext.fly(b[1]);
- if (e) {
- e.destroy()
- }
- }
- if (f && f[1]) {
- e = Ext.fly(f[1]);
- if (e) {
- e.destroy()
- }
- }
- }
- d.destroy()
- },
- save: function() {
- var c = this.toSave,
- e = {},
- d = this.getElement("g"),
- b, a;
- for (a = 0; a < c.length; a++) {
- b = c[a];
- if (b in this) {
- e[b] = this[b]
- }
- }
- this.position = 0;
- e.matrix = this.matrix.clone();
- this.state.push(e);
- this.group = d;
- return d
- },
- restore: function() {
- var d = this.toSave,
- e = this.state.pop(),
- c = this.group.dom.childNodes,
- b, a;
- while (c.length > this.position) {
- this.removeElement(c[c.length - 1])
- }
- for (a = 0; a < d.length; a++) {
- b = d[a];
- if (b in e) {
- this[b] = e[b]
- } else {
- delete this[b]
- }
- }
- this.setTransform.apply(this, e.matrix.elements);
- this.group = this.group.getParent()
- },
- transform: function(f, b, e, g, d, c) {
- if (this.path) {
- var a = Ext.draw.Matrix.fly([f, b, e, g, d, c]).inverse();
- this.path.transform(a)
- }
- this.matrix.append(f, b, e, g, d, c)
- },
- setTransform: function(e, a, d, f, c, b) {
- if (this.path) {
- this.path.transform(this.matrix)
- }
- this.matrix.reset();
- this.transform(e, a, d, f, c, b)
- },
- scale: function(a, b) {
- this.transform(a, 0, 0, b, 0, 0)
- },
- rotate: function(d) {
- var c = Math.cos(d),
- a = Math.sin(d),
- b = -Math.sin(d),
- e = Math.cos(d);
- this.transform(c, a, b, e, 0, 0)
- },
- translate: function(a, b) {
- this.transform(1, 0, 0, 1, a, b)
- },
- setGradientBBox: function(a) {
- this.bbox = a
- },
- beginPath: function() {
- this.path = new Ext.draw.Path()
- },
- moveTo: function(a, b) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.moveTo(a, b);
- this.path.element = null
- },
- lineTo: function(a, b) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.lineTo(a, b);
- this.path.element = null
- },
- rect: function(b, d, c, a) {
- this.moveTo(b, d);
- this.lineTo(b + c, d);
- this.lineTo(b + c, d + a);
- this.lineTo(b, d + a);
- this.closePath()
- },
- strokeRect: function(b, d, c, a) {
- this.beginPath();
- this.rect(b, d, c, a);
- this.stroke()
- },
- fillRect: function(b, d, c, a) {
- this.beginPath();
- this.rect(b, d, c, a);
- this.fill()
- },
- closePath: function() {
- if (!this.path) {
- this.beginPath()
- }
- this.path.closePath();
- this.path.element = null
- },
- arcSvg: function(d, a, f, g, c, b, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arcSvg(d, a, f, g, c, b, e);
- this.path.element = null
- },
- arc: function(b, f, a, d, c, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arc(b, f, a, d, c, e);
- this.path.element = null
- },
- ellipse: function(a, h, g, f, d, c, b, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.ellipse(a, h, g, f, d, c, b, e);
- this.path.element = null
- },
- arcTo: function(b, e, a, d, g, f, c) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arcTo(b, e, a, d, g, f, c);
- this.path.element = null
- },
- bezierCurveTo: function(d, f, b, e, a, c) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.bezierCurveTo(d, f, b, e, a, c);
- this.path.element = null
- },
- strokeText: function(d, a, e) {
- d = String(d);
- if (this.strokeStyle) {
- var b = this.getElement("text"),
- c = this.surface.getSvgElement(b, "tspan", 0);
- this.surface.setElementAttributes(b, {
- x: a,
- y: e,
- transform: this.matrix.toSvg(),
- stroke: this.strokeStyle,
- fill: "none",
- opacity: this.globalAlpha,
- "stroke-opacity": this.strokeOpacity,
- style: "font: " + this.font,
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- });
- if (this.lineDash.length) {
- this.surface.setElementAttributes(b, {
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- })
- }
- if (c.dom.firstChild) {
- c.dom.removeChild(c.dom.firstChild)
- }
- this.surface.setElementAttributes(c, {
- "alignment-baseline": "alphabetic"
- });
- c.dom.appendChild(document.createTextNode(Ext.String.htmlDecode(d)))
- }
- },
- fillText: function(d, a, e) {
- d = String(d);
- if (this.fillStyle) {
- var b = this.getElement("text"),
- c = this.surface.getSvgElement(b, "tspan", 0);
- this.surface.setElementAttributes(b, {
- x: a,
- y: e,
- transform: this.matrix.toSvg(),
- fill: this.fillStyle,
- opacity: this.globalAlpha,
- "fill-opacity": this.fillOpacity,
- style: "font: " + this.font
- });
- if (c.dom.firstChild) {
- c.dom.removeChild(c.dom.firstChild)
- }
- this.surface.setElementAttributes(c, {
- "alignment-baseline": "alphabetic"
- });
- c.dom.appendChild(document.createTextNode(Ext.String.htmlDecode(d)))
- }
- },
- drawImage: function(c, k, i, l, e, p, n, a, g) {
- var f = this,
- d = f.getElement("image"),
- j = k,
- h = i,
- b = typeof l === "undefined" ? c.width : l,
- m = typeof e === "undefined" ? c.height : e,
- o = null;
- if (typeof g !== "undefined") {
- o = k + " " + i + " " + l + " " + e;
- j = p;
- h = n;
- b = a;
- m = g
- }
- d.dom.setAttributeNS("http://www.w3.org/1999/xlink", "href", c.src);
- f.surface.setElementAttributes(d, {
- viewBox: o,
- x: j,
- y: h,
- width: b,
- height: m,
- opacity: f.globalAlpha,
- transform: f.matrix.toSvg()
- })
- },
- fill: function() {
- if (!this.path) {
- return
- }
- if (this.fillStyle) {
- var c, a = this.fillGradient,
- d = this.bbox,
- b = this.path.element;
- if (!b) {
- c = this.path.toString();
- b = this.path.element = this.getElement("path");
- this.surface.setElementAttributes(b, {
- d: c,
- transform: this.matrix.toSvg()
- })
- }
- this.surface.setElementAttributes(b, {
- fill: a && d ? a.generateGradient(this, d) : this.fillStyle,
- "fill-opacity": this.fillOpacity * this.globalAlpha
- })
- }
- },
- stroke: function() {
- if (!this.path) {
- return
- }
- if (this.strokeStyle) {
- var c, b = this.strokeGradient,
- d = this.bbox,
- a = this.path.element;
- if (!a || !this.path.svgString) {
- c = this.path.toString();
- if (!c) {
- return
- }
- a = this.path.element = this.getElement("path");
- this.surface.setElementAttributes(a, {
- fill: "none",
- d: c,
- transform: this.matrix.toSvg()
- })
- }
- this.surface.setElementAttributes(a, {
- stroke: b && d ? b.generateGradient(this, d) : this.strokeStyle,
- "stroke-linecap": this.lineCap,
- "stroke-linejoin": this.lineJoin,
- "stroke-width": this.lineWidth,
- "stroke-opacity": this.strokeOpacity * this.globalAlpha,
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- });
- if (this.lineDash.length) {
- this.surface.setElementAttributes(a, {
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- })
- }
- }
- },
- fillStroke: function(a, e) {
- var b = this,
- d = b.fillStyle,
- g = b.strokeStyle,
- c = b.fillOpacity,
- f = b.strokeOpacity;
- if (e === undefined) {
- e = a.transformFillStroke
- }
- if (!e) {
- a.inverseMatrix.toContext(b)
- }
- if (d && c !== 0) {
- b.fill()
- }
- if (g && f !== 0) {
- b.stroke()
- }
- },
- appendPath: function(a) {
- this.path = a.clone()
- },
- setLineDash: function(a) {
- this.lineDash = a
- },
- getLineDash: function() {
- return this.lineDash
- },
- createLinearGradient: function(d, g, b, e) {
- var f = this,
- c = f.surface.getNextDef("linearGradient"),
- a = f.group.dom.gradients || (f.group.dom.gradients = {}),
- h;
- f.surface.setElementAttributes(c, {
- x1: d,
- y1: g,
- x2: b,
- y2: e,
- gradientUnits: "userSpaceOnUse"
- });
- h = new Ext.draw.engine.SvgContext.Gradient(f, f.surface, c);
- a[c.dom.id] = h;
- return h
- },
- createRadialGradient: function(b, j, d, a, i, c) {
- var g = this,
- e = g.surface.getNextDef("radialGradient"),
- f = g.group.dom.gradients || (g.group.dom.gradients = {}),
- h;
- g.surface.setElementAttributes(e, {
- fx: b,
- fy: j,
- cx: a,
- cy: i,
- r: c,
- gradientUnits: "userSpaceOnUse"
- });
- h = new Ext.draw.engine.SvgContext.Gradient(g, g.surface, e, d / c);
- f[e.dom.id] = h;
- return h
- }
-});
-Ext.define("Ext.draw.engine.SvgContext.Gradient", {
- statics: {
- map: {}
- },
- constructor: function(c, a, d, b) {
- var f = this.statics().map,
- e;
- e = f[d.dom.id];
- if (e) {
- e.element = null
- }
- f[d.dom.id] = this;
- this.ctx = c;
- this.surface = a;
- this.element = d;
- this.position = 0;
- this.compression = b || 0
- },
- addColorStop: function(d, b) {
- var c = this.surface.getSvgElement(this.element, "stop", this.position++),
- a = this.compression;
- this.surface.setElementAttributes(c, {
- offset: (((1 - a) * d + a) * 100).toFixed(2) + "%",
- "stop-color": b,
- "stop-opacity": Ext.draw.Color.fly(b).a.toFixed(15)
- })
- },
- toString: function() {
- var a = this.element.dom.childNodes;
- while (a.length > this.position) {
- Ext.fly(a[a.length - 1]).destroy()
- }
- return "url(#" + this.element.getId() + ")"
- },
- destroy: function() {
- var b = this.statics().map,
- a = this.element;
- if (a && a.dom) {
- delete b[a.dom.id];
- a.destroy()
- }
- this.callParent()
- }
-});
-Ext.define("Ext.draw.engine.Svg", {
- extend: "Ext.draw.Surface",
- requires: ["Ext.draw.engine.SvgContext"],
- statics: {
- BBoxTextCache: {}
- },
- config: {
- highPrecision: false
- },
- getElementConfig: function() {
- return {
- reference: "element",
- style: {
- position: "absolute"
- },
- children: [{
- reference: "innerElement",
- style: {
- width: "100%",
- height: "100%",
- position: "relative"
- },
- children: [{
- tag: "svg",
- reference: "svgElement",
- namespace: "http://www.w3.org/2000/svg",
- width: "100%",
- height: "100%",
- version: 1.1
- }]
- }]
- }
- },
- constructor: function(a) {
- var b = this;
- b.callParent([a]);
- b.mainGroup = b.createSvgNode("g");
- b.defElement = b.createSvgNode("defs");
- b.svgElement.appendChild(b.mainGroup);
- b.svgElement.appendChild(b.defElement);
- b.ctx = new Ext.draw.engine.SvgContext(b)
- },
- createSvgNode: function(a) {
- var b = document.createElementNS("http://www.w3.org/2000/svg", a);
- return Ext.get(b)
- },
- getSvgElement: function(d, b, a) {
- var c;
- if (d.dom.childNodes.length > a) {
- c = d.dom.childNodes[a];
- if (c.tagName === b) {
- return Ext.get(c)
- } else {
- Ext.destroy(c)
- }
- }
- c = Ext.get(this.createSvgNode(b));
- if (a === 0) {
- d.insertFirst(c)
- } else {
- c.insertAfter(Ext.fly(d.dom.childNodes[a - 1]))
- }
- c.cache = {};
- return c
- },
- setElementAttributes: function(d, b) {
- var f = d.dom,
- a = d.cache,
- c, e;
- for (c in b) {
- e = b[c];
- if (a[c] !== e) {
- a[c] = e;
- f.setAttribute(c, e)
- }
- }
- },
- getNextDef: function(a) {
- return this.getSvgElement(this.defElement, a, this.defPosition++)
- },
- clearTransform: function() {
- var a = this;
- a.mainGroup.set({
- transform: a.matrix.toSvg()
- })
- },
- clear: function() {
- this.ctx.clear();
- this.defPosition = 0
- },
- renderSprite: function(b) {
- var d = this,
- c = d.getRect(),
- a = d.ctx;
- if (b.attr.hidden || b.attr.globalAlpha === 0) {
- a.save();
- a.restore();
- return
- }
- b.element = a.save();
- b.preRender(this);
- b.useAttributes(a, c);
- if (false === b.render(this, a, [0, 0, c[2], c[3]])) {
- return false
- }
- b.setDirty(false);
- a.restore()
- },
- flatten: function(e, b) {
- var c = '',
- f = Ext.getClassName(this),
- a, g, d;
- c += '';
- for (d = 0; d < b.length; d++) {
- a = b[d];
- if (Ext.getClassName(a) !== f) {
- continue
- }
- g = a.getRect();
- c += '';
- c += this.serializeNode(a.svgElement.dom);
- c += " "
- }
- c += " ";
- return {
- data: "data:image/svg+xml;utf8," + encodeURIComponent(c),
- type: "svg"
- }
- },
- serializeNode: function(d) {
- var b = "",
- c, f, a, e;
- if (d.nodeType === document.TEXT_NODE) {
- return d.nodeValue
- }
- b += "<" + d.nodeName;
- if (d.attributes.length) {
- for (c = 0, f = d.attributes.length; c < f; c++) {
- a = d.attributes[c];
- b += " " + a.name + '="' + a.value + '"'
- }
- }
- b += ">";
- if (d.childNodes && d.childNodes.length) {
- for (c = 0, f = d.childNodes.length; c < f; c++) {
- e = d.childNodes[c];
- b += this.serializeNode(e)
- }
- }
- b += "" + d.nodeName + ">";
- return b
- },
- destroy: function() {
- var a = this;
- a.ctx.destroy();
- a.mainGroup.destroy();
- delete a.mainGroup;
- delete a.ctx;
- a.callParent()
- },
- remove: function(a, b) {
- if (a && a.element) {
- if (this.ctx) {
- this.ctx.removeElement(a.element)
- } else {
- a.element.destroy()
- }
- a.element = null
- }
- this.callParent(arguments)
- }
-});
-Ext.draw || (Ext.draw = {});
-Ext.draw.engine || (Ext.draw.engine = {});
-Ext.draw.engine.excanvas = true;
-if (!document.createElement("canvas").getContext) {
- (function() {
- var ab = Math;
- var n = ab.round;
- var l = ab.sin;
- var A = ab.cos;
- var H = ab.abs;
- var N = ab.sqrt;
- var d = 10;
- var f = d / 2;
- var z = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];
-
- function y() {
- return this.context_ || (this.context_ = new D(this))
- }
- var t = Array.prototype.slice;
-
- function g(j, m, p) {
- var i = t.call(arguments, 2);
- return function() {
- return j.apply(m, i.concat(t.call(arguments)))
- }
- }
-
- function af(i) {
- return String(i).replace(/&/g, "&").replace(/"/g, """)
- }
-
- function Y(m, j, i) {
- Ext.onReady(function() {
- if (!m.namespaces[j]) {
- m.namespaces.add(j, i, "#default#VML")
- }
- })
- }
-
- function R(j) {
- Y(j, "g_vml_", "urn:schemas-microsoft-com:vml");
- Y(j, "g_o_", "urn:schemas-microsoft-com:office:office");
- if (!j.styleSheets.ex_canvas_) {
- var i = j.createStyleSheet();
- i.owningElement.id = "ex_canvas_";
- i.cssText = "canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"
- }
- }
- R(document);
- var e = {
- init: function(i) {
- var j = i || document;
- j.createElement("canvas");
- j.attachEvent("onreadystatechange", g(this.init_, this, j))
- },
- init_: function(p) {
- var m = p.getElementsByTagName("canvas");
- for (var j = 0; j < m.length; j++) {
- this.initElement(m[j])
- }
- },
- initElement: function(j) {
- if (!j.getContext) {
- j.getContext = y;
- R(j.ownerDocument);
- j.innerHTML = "";
- j.attachEvent("onpropertychange", x);
- j.attachEvent("onresize", W);
- var i = j.attributes;
- if (i.width && i.width.specified) {
- j.style.width = i.width.nodeValue + "px"
- } else {
- j.width = j.clientWidth
- }
- if (i.height && i.height.specified) {
- j.style.height = i.height.nodeValue + "px"
- } else {
- j.height = j.clientHeight
- }
- }
- return j
- }
- };
-
- function x(j) {
- var i = j.srcElement;
- switch (j.propertyName) {
- case "width":
- i.getContext().clearRect();
- i.style.width = i.attributes.width.nodeValue + "px";
- i.firstChild.style.width = i.clientWidth + "px";
- break;
- case "height":
- i.getContext().clearRect();
- i.style.height = i.attributes.height.nodeValue + "px";
- i.firstChild.style.height = i.clientHeight + "px";
- break
- }
- }
-
- function W(j) {
- var i = j.srcElement;
- if (i.firstChild) {
- i.firstChild.style.width = i.clientWidth + "px";
- i.firstChild.style.height = i.clientHeight + "px"
- }
- }
- e.init();
- var k = [];
- for (var ae = 0; ae < 16; ae++) {
- for (var ad = 0; ad < 16; ad++) {
- k[ae * 16 + ad] = ae.toString(16) + ad.toString(16)
- }
- }
-
- function B() {
- return [
- [1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]
- ]
- }
-
- function J(p, m) {
- var j = B();
- for (var i = 0; i < 3; i++) {
- for (var ah = 0; ah < 3; ah++) {
- var Z = 0;
- for (var ag = 0; ag < 3; ag++) {
- Z += p[i][ag] * m[ag][ah]
- }
- j[i][ah] = Z
- }
- }
- return j
- }
-
- function v(j, i) {
- i.fillStyle = j.fillStyle;
- i.lineCap = j.lineCap;
- i.lineJoin = j.lineJoin;
- i.lineDash = j.lineDash;
- i.lineWidth = j.lineWidth;
- i.miterLimit = j.miterLimit;
- i.shadowBlur = j.shadowBlur;
- i.shadowColor = j.shadowColor;
- i.shadowOffsetX = j.shadowOffsetX;
- i.shadowOffsetY = j.shadowOffsetY;
- i.strokeStyle = j.strokeStyle;
- i.globalAlpha = j.globalAlpha;
- i.font = j.font;
- i.textAlign = j.textAlign;
- i.textBaseline = j.textBaseline;
- i.arcScaleX_ = j.arcScaleX_;
- i.arcScaleY_ = j.arcScaleY_;
- i.lineScale_ = j.lineScale_
- }
- var b = {
- aliceblue: "#F0F8FF",
- antiquewhite: "#FAEBD7",
- aquamarine: "#7FFFD4",
- azure: "#F0FFFF",
- beige: "#F5F5DC",
- bisque: "#FFE4C4",
- black: "#000000",
- blanchedalmond: "#FFEBCD",
- blueviolet: "#8A2BE2",
- brown: "#A52A2A",
- burlywood: "#DEB887",
- cadetblue: "#5F9EA0",
- chartreuse: "#7FFF00",
- chocolate: "#D2691E",
- coral: "#FF7F50",
- cornflowerblue: "#6495ED",
- cornsilk: "#FFF8DC",
- crimson: "#DC143C",
- cyan: "#00FFFF",
- darkblue: "#00008B",
- darkcyan: "#008B8B",
- darkgoldenrod: "#B8860B",
- darkgray: "#A9A9A9",
- darkgreen: "#006400",
- darkgrey: "#A9A9A9",
- darkkhaki: "#BDB76B",
- darkmagenta: "#8B008B",
- darkolivegreen: "#556B2F",
- darkorange: "#FF8C00",
- darkorchid: "#9932CC",
- darkred: "#8B0000",
- darksalmon: "#E9967A",
- darkseagreen: "#8FBC8F",
- darkslateblue: "#483D8B",
- darkslategray: "#2F4F4F",
- darkslategrey: "#2F4F4F",
- darkturquoise: "#00CED1",
- darkviolet: "#9400D3",
- deeppink: "#FF1493",
- deepskyblue: "#00BFFF",
- dimgray: "#696969",
- dimgrey: "#696969",
- dodgerblue: "#1E90FF",
- firebrick: "#B22222",
- floralwhite: "#FFFAF0",
- forestgreen: "#228B22",
- gainsboro: "#DCDCDC",
- ghostwhite: "#F8F8FF",
- gold: "#FFD700",
- goldenrod: "#DAA520",
- grey: "#808080",
- greenyellow: "#ADFF2F",
- honeydew: "#F0FFF0",
- hotpink: "#FF69B4",
- indianred: "#CD5C5C",
- indigo: "#4B0082",
- ivory: "#FFFFF0",
- khaki: "#F0E68C",
- lavender: "#E6E6FA",
- lavenderblush: "#FFF0F5",
- lawngreen: "#7CFC00",
- lemonchiffon: "#FFFACD",
- lightblue: "#ADD8E6",
- lightcoral: "#F08080",
- lightcyan: "#E0FFFF",
- lightgoldenrodyellow: "#FAFAD2",
- lightgreen: "#90EE90",
- lightgrey: "#D3D3D3",
- lightpink: "#FFB6C1",
- lightsalmon: "#FFA07A",
- lightseagreen: "#20B2AA",
- lightskyblue: "#87CEFA",
- lightslategray: "#778899",
- lightslategrey: "#778899",
- lightsteelblue: "#B0C4DE",
- lightyellow: "#FFFFE0",
- limegreen: "#32CD32",
- linen: "#FAF0E6",
- magenta: "#FF00FF",
- mediumaquamarine: "#66CDAA",
- mediumblue: "#0000CD",
- mediumorchid: "#BA55D3",
- mediumpurple: "#9370DB",
- mediumseagreen: "#3CB371",
- mediumslateblue: "#7B68EE",
- mediumspringgreen: "#00FA9A",
- mediumturquoise: "#48D1CC",
- mediumvioletred: "#C71585",
- midnightblue: "#191970",
- mintcream: "#F5FFFA",
- mistyrose: "#FFE4E1",
- moccasin: "#FFE4B5",
- navajowhite: "#FFDEAD",
- oldlace: "#FDF5E6",
- olivedrab: "#6B8E23",
- orange: "#FFA500",
- orangered: "#FF4500",
- orchid: "#DA70D6",
- palegoldenrod: "#EEE8AA",
- palegreen: "#98FB98",
- paleturquoise: "#AFEEEE",
- palevioletred: "#DB7093",
- papayawhip: "#FFEFD5",
- peachpuff: "#FFDAB9",
- peru: "#CD853F",
- pink: "#FFC0CB",
- plum: "#DDA0DD",
- powderblue: "#B0E0E6",
- rosybrown: "#BC8F8F",
- royalblue: "#4169E1",
- saddlebrown: "#8B4513",
- salmon: "#FA8072",
- sandybrown: "#F4A460",
- seagreen: "#2E8B57",
- seashell: "#FFF5EE",
- sienna: "#A0522D",
- skyblue: "#87CEEB",
- slateblue: "#6A5ACD",
- slategray: "#708090",
- slategrey: "#708090",
- snow: "#FFFAFA",
- springgreen: "#00FF7F",
- steelblue: "#4682B4",
- tan: "#D2B48C",
- thistle: "#D8BFD8",
- tomato: "#FF6347",
- turquoise: "#40E0D0",
- violet: "#EE82EE",
- wheat: "#F5DEB3",
- whitesmoke: "#F5F5F5",
- yellowgreen: "#9ACD32"
- };
-
- function M(j) {
- var p = j.indexOf("(", 3);
- var i = j.indexOf(")", p + 1);
- var m = j.substring(p + 1, i).split(",");
- if (m.length != 4 || j.charAt(3) != "a") {
- m[3] = 1
- }
- return m
- }
-
- function c(i) {
- return parseFloat(i) / 100
- }
-
- function r(j, m, i) {
- return Math.min(i, Math.max(m, j))
- }
-
- function I(ag) {
- var i, ai, aj, ah, ak, Z;
- ah = parseFloat(ag[0]) / 360 % 360;
- if (ah < 0) {
- ah++
- }
- ak = r(c(ag[1]), 0, 1);
- Z = r(c(ag[2]), 0, 1);
- if (ak == 0) {
- i = ai = aj = Z
- } else {
- var j = Z < 0.5 ? Z * (1 + ak) : Z + ak - Z * ak;
- var m = 2 * Z - j;
- i = a(m, j, ah + 1 / 3);
- ai = a(m, j, ah);
- aj = a(m, j, ah - 1 / 3)
- }
- return "#" + k[Math.floor(i * 255)] + k[Math.floor(ai * 255)] + k[Math.floor(aj * 255)]
- }
-
- function a(j, i, m) {
- if (m < 0) {
- m++
- }
- if (m > 1) {
- m--
- }
- if (6 * m < 1) {
- return j + (i - j) * 6 * m
- } else {
- if (2 * m < 1) {
- return i
- } else {
- if (3 * m < 2) {
- return j + (i - j) * (2 / 3 - m) * 6
- } else {
- return j
- }
- }
- }
- }
- var C = {};
-
- function F(j) {
- if (j in C) {
- return C[j]
- }
- var ag, Z = 1;
- j = String(j);
- if (j.charAt(0) == "#") {
- ag = j
- } else {
- if (/^rgb/.test(j)) {
- var p = M(j);
- var ag = "#",
- ah;
- for (var m = 0; m < 3; m++) {
- if (p[m].indexOf("%") != -1) {
- ah = Math.floor(c(p[m]) * 255)
- } else {
- ah = +p[m]
- }
- ag += k[r(ah, 0, 255)]
- }
- Z = +p[3]
- } else {
- if (/^hsl/.test(j)) {
- var p = M(j);
- ag = I(p);
- Z = p[3]
- } else {
- ag = b[j] || j
- }
- }
- }
- return C[j] = {
- color: ag,
- alpha: Z
- }
- }
- var o = {
- style: "normal",
- variant: "normal",
- weight: "normal",
- size: 10,
- family: "sans-serif"
- };
- var L = {};
-
- function E(i) {
- if (L[i]) {
- return L[i]
- }
- var p = document.createElement("div");
- var m = p.style;
- try {
- m.font = i
- } catch (j) {}
- return L[i] = {
- style: m.fontStyle || o.style,
- variant: m.fontVariant || o.variant,
- weight: m.fontWeight || o.weight,
- size: m.fontSize || o.size,
- family: m.fontFamily || o.family
- }
- }
-
- function u(m, j) {
- var i = {};
- for (var ah in m) {
- i[ah] = m[ah]
- }
- var ag = parseFloat(j.currentStyle.fontSize),
- Z = parseFloat(m.size);
- if (typeof m.size == "number") {
- i.size = m.size
- } else {
- if (m.size.indexOf("px") != -1) {
- i.size = Z
- } else {
- if (m.size.indexOf("em") != -1) {
- i.size = ag * Z
- } else {
- if (m.size.indexOf("%") != -1) {
- i.size = (ag / 100) * Z
- } else {
- if (m.size.indexOf("pt") != -1) {
- i.size = Z / 0.75
- } else {
- i.size = ag
- }
- }
- }
- }
- }
- i.size *= 0.981;
- return i
- }
-
- function ac(i) {
- return i.style + " " + i.variant + " " + i.weight + " " + i.size + "px " + i.family
- }
- var s = {
- butt: "flat",
- round: "round"
- };
-
- function S(i) {
- return s[i] || "square"
- }
-
- function D(i) {
- this.m_ = B();
- this.mStack_ = [];
- this.aStack_ = [];
- this.currentPath_ = [];
- this.strokeStyle = "#000";
- this.fillStyle = "#000";
- this.lineWidth = 1;
- this.lineJoin = "miter";
- this.lineDash = [];
- this.lineCap = "butt";
- this.miterLimit = d * 1;
- this.globalAlpha = 1;
- this.font = "10px sans-serif";
- this.textAlign = "left";
- this.textBaseline = "alphabetic";
- this.canvas = i;
- var m = "width:" + i.clientWidth + "px;height:" + i.clientHeight + "px;overflow:hidden;position:absolute";
- var j = i.ownerDocument.createElement("div");
- j.style.cssText = m;
- i.appendChild(j);
- var p = j.cloneNode(false);
- p.style.backgroundColor = "red";
- p.style.filter = "alpha(opacity=0)";
- i.appendChild(p);
- this.element_ = j;
- this.arcScaleX_ = 1;
- this.arcScaleY_ = 1;
- this.lineScale_ = 1
- }
- var q = D.prototype;
- q.clearRect = function() {
- if (this.textMeasureEl_) {
- this.textMeasureEl_.removeNode(true);
- this.textMeasureEl_ = null
- }
- this.element_.innerHTML = ""
- };
- q.beginPath = function() {
- this.currentPath_ = []
- };
- q.moveTo = function(j, i) {
- var m = V(this, j, i);
- this.currentPath_.push({
- type: "moveTo",
- x: m.x,
- y: m.y
- });
- this.currentX_ = m.x;
- this.currentY_ = m.y
- };
- q.lineTo = function(j, i) {
- var m = V(this, j, i);
- this.currentPath_.push({
- type: "lineTo",
- x: m.x,
- y: m.y
- });
- this.currentX_ = m.x;
- this.currentY_ = m.y
- };
- q.bezierCurveTo = function(m, j, ak, aj, ai, ag) {
- var i = V(this, ai, ag);
- var ah = V(this, m, j);
- var Z = V(this, ak, aj);
- K(this, ah, Z, i)
- };
-
- function K(i, Z, m, j) {
- i.currentPath_.push({
- type: "bezierCurveTo",
- cp1x: Z.x,
- cp1y: Z.y,
- cp2x: m.x,
- cp2y: m.y,
- x: j.x,
- y: j.y
- });
- i.currentX_ = j.x;
- i.currentY_ = j.y
- }
- q.quadraticCurveTo = function(ai, m, j, i) {
- var ah = V(this, ai, m);
- var ag = V(this, j, i);
- var aj = {
- x: this.currentX_ + 2 / 3 * (ah.x - this.currentX_),
- y: this.currentY_ + 2 / 3 * (ah.y - this.currentY_)
- };
- var Z = {
- x: aj.x + (ag.x - this.currentX_) / 3,
- y: aj.y + (ag.y - this.currentY_) / 3
- };
- K(this, aj, Z, ag)
- };
- q.arc = function(al, aj, ak, ag, j, m) {
- ak *= d;
- var ap = m ? "at" : "wa";
- var am = al + A(ag) * ak - f;
- var ao = aj + l(ag) * ak - f;
- var i = al + A(j) * ak - f;
- var an = aj + l(j) * ak - f;
- if (am == i && !m) {
- am += 0.125
- }
- var Z = V(this, al, aj);
- var ai = V(this, am, ao);
- var ah = V(this, i, an);
- this.currentPath_.push({
- type: ap,
- x: Z.x,
- y: Z.y,
- radius: ak,
- xStart: ai.x,
- yStart: ai.y,
- xEnd: ah.x,
- yEnd: ah.y
- })
- };
- q.rect = function(m, j, i, p) {
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath()
- };
- q.strokeRect = function(m, j, i, p) {
- var Z = this.currentPath_;
- this.beginPath();
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath();
- this.stroke();
- this.currentPath_ = Z
- };
- q.fillRect = function(m, j, i, p) {
- var Z = this.currentPath_;
- this.beginPath();
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath();
- this.fill();
- this.currentPath_ = Z
- };
- q.createLinearGradient = function(j, p, i, m) {
- var Z = new U("gradient");
- Z.x0_ = j;
- Z.y0_ = p;
- Z.x1_ = i;
- Z.y1_ = m;
- return Z
- };
- q.createRadialGradient = function(p, ag, m, j, Z, i) {
- var ah = new U("gradientradial");
- ah.x0_ = p;
- ah.y0_ = ag;
- ah.r0_ = m;
- ah.x1_ = j;
- ah.y1_ = Z;
- ah.r1_ = i;
- return ah
- };
- q.drawImage = function(an, j) {
- var ah, Z, aj, ar, al, ak, ao, av;
- var ai = an.runtimeStyle.width;
- var am = an.runtimeStyle.height;
- an.runtimeStyle.width = "auto";
- an.runtimeStyle.height = "auto";
- var ag = an.width;
- var aq = an.height;
- an.runtimeStyle.width = ai;
- an.runtimeStyle.height = am;
- if (arguments.length == 3) {
- ah = arguments[1];
- Z = arguments[2];
- al = ak = 0;
- ao = aj = ag;
- av = ar = aq
- } else {
- if (arguments.length == 5) {
- ah = arguments[1];
- Z = arguments[2];
- aj = arguments[3];
- ar = arguments[4];
- al = ak = 0;
- ao = ag;
- av = aq
- } else {
- if (arguments.length == 9) {
- al = arguments[1];
- ak = arguments[2];
- ao = arguments[3];
- av = arguments[4];
- ah = arguments[5];
- Z = arguments[6];
- aj = arguments[7];
- ar = arguments[8]
- } else {
- throw Error("Invalid number of arguments")
- }
- }
- }
- var au = V(this, ah, Z);
- var at = [];
- var i = 10;
- var p = 10;
- var ap = this.m_;
- at.push(" ', ' ", " ");
- this.element_.insertAdjacentHTML("BeforeEnd", at.join(""))
- };
- q.setLineDash = function(i) {
- if (i.length === 1) {
- i = i.slice();
- i[1] = i[0]
- }
- this.lineDash = i
- };
- q.getLineDash = function() {
- return this.lineDash
- };
- q.stroke = function(ak) {
- var ai = [];
- var m = 10;
- var al = 10;
- ai.push(" aj.x) {
- aj.x = j.x
- }
- if (Z.y == null || j.y < Z.y) {
- Z.y = j.y
- }
- if (aj.y == null || j.y > aj.y) {
- aj.y = j.y
- }
- }
- }
- ai.push(' ">');
- if (!ak) {
- w(this, ai)
- } else {
- G(this, ai, Z, aj)
- }
- ai.push(" ");
- this.element_.insertAdjacentHTML("beforeEnd", ai.join(""))
- };
-
- function w(m, ag) {
- var j = F(m.strokeStyle);
- var p = j.color;
- var Z = j.alpha * m.globalAlpha;
- var i = m.lineScale_ * m.lineWidth;
- if (i < 1) {
- Z *= i
- }
- ag.push(" ')
- }
-
- function G(aq, ai, aK, ar) {
- var aj = aq.fillStyle;
- var aB = aq.arcScaleX_;
- var aA = aq.arcScaleY_;
- var j = ar.x - aK.x;
- var p = ar.y - aK.y;
- if (aj instanceof U) {
- var an = 0;
- var aF = {
- x: 0,
- y: 0
- };
- var ax = 0;
- var am = 1;
- if (aj.type_ == "gradient") {
- var al = aj.x0_ / aB;
- var m = aj.y0_ / aA;
- var ak = aj.x1_ / aB;
- var aM = aj.y1_ / aA;
- var aJ = V(aq, al, m);
- var aI = V(aq, ak, aM);
- var ag = aI.x - aJ.x;
- var Z = aI.y - aJ.y;
- an = Math.atan2(ag, Z) * 180 / Math.PI;
- if (an < 0) {
- an += 360
- }
- if (an < 0.000001) {
- an = 0
- }
- } else {
- var aJ = V(aq, aj.x0_, aj.y0_);
- aF = {
- x: (aJ.x - aK.x) / j,
- y: (aJ.y - aK.y) / p
- };
- j /= aB * d;
- p /= aA * d;
- var aD = ab.max(j, p);
- ax = 2 * aj.r0_ / aD;
- am = 2 * aj.r1_ / aD - ax
- }
- var av = aj.colors_;
- av.sort(function(aN, i) {
- return aN.offset - i.offset
- });
- var ap = av.length;
- var au = av[0].color;
- var at = av[ap - 1].color;
- var az = av[0].alpha * aq.globalAlpha;
- var ay = av[ap - 1].alpha * aq.globalAlpha;
- var aE = [];
- for (var aH = 0; aH < ap; aH++) {
- var ao = av[aH];
- aE.push(ao.offset * am + ax + " " + ao.color)
- }
- ai.push(' ')
- } else {
- if (aj instanceof T) {
- if (j && p) {
- var ah = -aK.x;
- var aC = -aK.y;
- ai.push(" ')
- }
- } else {
- var aL = F(aq.fillStyle);
- var aw = aL.color;
- var aG = aL.alpha * aq.globalAlpha;
- ai.push(' ')
- }
- }
- }
- q.fill = function() {
- this.$stroke(true)
- };
- q.closePath = function() {
- this.currentPath_.push({
- type: "close"
- })
- };
-
- function V(j, Z, p) {
- var i = j.m_;
- return {
- x: d * (Z * i[0][0] + p * i[1][0] + i[2][0]) - f,
- y: d * (Z * i[0][1] + p * i[1][1] + i[2][1]) - f
- }
- }
- q.save = function() {
- var i = {};
- v(this, i);
- this.aStack_.push(i);
- this.mStack_.push(this.m_);
- this.m_ = J(B(), this.m_)
- };
- q.restore = function() {
- if (this.aStack_.length) {
- v(this.aStack_.pop(), this);
- this.m_ = this.mStack_.pop()
- }
- };
-
- function h(i) {
- return isFinite(i[0][0]) && isFinite(i[0][1]) && isFinite(i[1][0]) && isFinite(i[1][1]) && isFinite(i[2][0]) && isFinite(i[2][1])
- }
-
- function aa(j, i, p) {
- if (!h(i)) {
- return
- }
- j.m_ = i;
- if (p) {
- var Z = i[0][0] * i[1][1] - i[0][1] * i[1][0];
- j.lineScale_ = N(H(Z))
- }
- }
- q.translate = function(m, j) {
- var i = [
- [1, 0, 0],
- [0, 1, 0],
- [m, j, 1]
- ];
- aa(this, J(i, this.m_), false)
- };
- q.rotate = function(j) {
- var p = A(j);
- var m = l(j);
- var i = [
- [p, m, 0],
- [-m, p, 0],
- [0, 0, 1]
- ];
- aa(this, J(i, this.m_), false)
- };
- q.scale = function(m, j) {
- this.arcScaleX_ *= m;
- this.arcScaleY_ *= j;
- var i = [
- [m, 0, 0],
- [0, j, 0],
- [0, 0, 1]
- ];
- aa(this, J(i, this.m_), true)
- };
- q.transform = function(Z, p, ah, ag, j, i) {
- var m = [
- [Z, p, 0],
- [ah, ag, 0],
- [j, i, 1]
- ];
- aa(this, J(m, this.m_), true)
- };
- q.setTransform = function(ag, Z, ai, ah, p, j) {
- var i = [
- [ag, Z, 0],
- [ai, ah, 0],
- [p, j, 1]
- ];
- aa(this, i, true)
- };
- q.drawText_ = function(am, ak, aj, ap, ai) {
- var ao = this.m_,
- at = 1000,
- j = 0,
- ar = at,
- ah = {
- x: 0,
- y: 0
- },
- ag = [];
- var i = u(E(this.font), this.element_);
- var p = ac(i);
- var au = this.element_.currentStyle;
- var Z = this.textAlign.toLowerCase();
- switch (Z) {
- case "left":
- case "center":
- case "right":
- break;
- case "end":
- Z = au.direction == "ltr" ? "right" : "left";
- break;
- case "start":
- Z = au.direction == "rtl" ? "right" : "left";
- break;
- default:
- Z = "left"
- }
- switch (this.textBaseline) {
- case "hanging":
- case "top":
- ah.y = i.size / 1.75;
- break;
- case "middle":
- break;
- default:
- case null:
- case "alphabetic":
- case "ideographic":
- case "bottom":
- ah.y = -i.size / 3;
- break
- }
- switch (Z) {
- case "right":
- j = at;
- ar = 0.05;
- break;
- case "center":
- j = ar = at / 2;
- break
- }
- var aq = V(this, ak + ah.x, aj + ah.y);
- ag.push('');
- if (ai) {
- w(this, ag)
- } else {
- G(this, ag, {
- x: -j,
- y: 0
- }, {
- x: ar,
- y: i.size
- })
- }
- var an = ao[0][0].toFixed(3) + "," + ao[1][0].toFixed(3) + "," + ao[0][1].toFixed(3) + "," + ao[1][1].toFixed(3) + ",0,0";
- var al = n(aq.x / d) + "," + n(aq.y / d);
- ag.push(' ', ' ', ' ');
- this.element_.insertAdjacentHTML("beforeEnd", ag.join(""))
- };
- q.fillText = function(m, i, p, j) {
- this.drawText_(m, i, p, j, false)
- };
- q.strokeText = function(m, i, p, j) {
- this.drawText_(m, i, p, j, true)
- };
- q.measureText = function(m) {
- if (!this.textMeasureEl_) {
- var i = ' ';
- this.element_.insertAdjacentHTML("beforeEnd", i);
- this.textMeasureEl_ = this.element_.lastChild
- }
- var j = this.element_.ownerDocument;
- this.textMeasureEl_.innerHTML = "";
- this.textMeasureEl_.style.font = this.font;
- this.textMeasureEl_.appendChild(j.createTextNode(m));
- return {
- width: this.textMeasureEl_.offsetWidth
- }
- };
- q.clip = function() {};
- q.arcTo = function() {};
- q.createPattern = function(j, i) {
- return new T(j, i)
- };
-
- function U(i) {
- this.type_ = i;
- this.x0_ = 0;
- this.y0_ = 0;
- this.r0_ = 0;
- this.x1_ = 0;
- this.y1_ = 0;
- this.r1_ = 0;
- this.colors_ = []
- }
- U.prototype.addColorStop = function(j, i) {
- i = F(i);
- this.colors_.push({
- offset: j,
- color: i.color,
- alpha: i.alpha
- })
- };
-
- function T(j, i) {
- Q(j);
- switch (i) {
- case "repeat":
- case null:
- case "":
- this.repetition_ = "repeat";
- break;
- case "repeat-x":
- case "repeat-y":
- case "no-repeat":
- this.repetition_ = i;
- break;
- default:
- O("SYNTAX_ERR")
- }
- this.src_ = j.src;
- this.width_ = j.width;
- this.height_ = j.height
- }
-
- function O(i) {
- throw new P(i)
- }
-
- function Q(i) {
- if (!i || i.nodeType != 1 || i.tagName != "IMG") {
- O("TYPE_MISMATCH_ERR")
- }
- if (i.readyState != "complete") {
- O("INVALID_STATE_ERR")
- }
- }
-
- function P(i) {
- this.code = this[i];
- this.message = i + ": DOM Exception " + this.code
- }
- var X = P.prototype = new Error();
- X.INDEX_SIZE_ERR = 1;
- X.DOMSTRING_SIZE_ERR = 2;
- X.HIERARCHY_REQUEST_ERR = 3;
- X.WRONG_DOCUMENT_ERR = 4;
- X.INVALID_CHARACTER_ERR = 5;
- X.NO_DATA_ALLOWED_ERR = 6;
- X.NO_MODIFICATION_ALLOWED_ERR = 7;
- X.NOT_FOUND_ERR = 8;
- X.NOT_SUPPORTED_ERR = 9;
- X.INUSE_ATTRIBUTE_ERR = 10;
- X.INVALID_STATE_ERR = 11;
- X.SYNTAX_ERR = 12;
- X.INVALID_MODIFICATION_ERR = 13;
- X.NAMESPACE_ERR = 14;
- X.INVALID_ACCESS_ERR = 15;
- X.VALIDATION_ERR = 16;
- X.TYPE_MISMATCH_ERR = 17;
- G_vmlCanvasManager = e;
- CanvasRenderingContext2D = D;
- CanvasGradient = U;
- CanvasPattern = T;
- DOMException = P
- })()
-}
-Ext.define("Ext.draw.engine.Canvas", {
- extend: "Ext.draw.Surface",
- requires: ["Ext.draw.engine.excanvas", "Ext.draw.Animator", "Ext.draw.Color"],
- config: {
- highPrecision: false
- },
- statics: {
- contextOverrides: {
- setGradientBBox: function(a) {
- this.bbox = a
- },
- fill: function() {
- var c = this.fillStyle,
- a = this.fillGradient,
- b = this.fillOpacity,
- d = this.globalAlpha,
- e = this.bbox;
- if (c !== Ext.draw.Color.RGBA_NONE && b !== 0) {
- if (a && e) {
- this.fillStyle = a.generateGradient(this, e)
- }
- if (b !== 1) {
- this.globalAlpha = d * b
- }
- this.$fill();
- if (b !== 1) {
- this.globalAlpha = d
- }
- if (a && e) {
- this.fillStyle = c
- }
- }
- },
- stroke: function() {
- var e = this.strokeStyle,
- c = this.strokeGradient,
- a = this.strokeOpacity,
- b = this.globalAlpha,
- d = this.bbox;
- if (e !== Ext.draw.Color.RGBA_NONE && a !== 0) {
- if (c && d) {
- this.strokeStyle = c.generateGradient(this, d)
- }
- if (a !== 1) {
- this.globalAlpha = b * a
- }
- this.$stroke();
- if (a !== 1) {
- this.globalAlpha = b
- }
- if (c && d) {
- this.strokeStyle = e
- }
- }
- },
- fillStroke: function(d, e) {
- var j = this,
- i = this.fillStyle,
- h = this.fillOpacity,
- f = this.strokeStyle,
- c = this.strokeOpacity,
- b = j.shadowColor,
- a = j.shadowBlur,
- g = Ext.draw.Color.RGBA_NONE;
- if (e === undefined) {
- e = d.transformFillStroke
- }
- if (!e) {
- d.inverseMatrix.toContext(j)
- }
- if (i !== g && h !== 0) {
- j.fill();
- j.shadowColor = g;
- j.shadowBlur = 0
- }
- if (f !== g && c !== 0) {
- j.stroke()
- }
- j.shadowColor = b;
- j.shadowBlur = a
- },
- setLineDash: function(a) {
- if (this.$setLineDash) {
- this.$setLineDash(a)
- }
- },
- getLineDash: function() {
- if (this.$getLineDash) {
- return this.$getLineDash()
- }
- },
- ellipse: function(g, e, c, a, j, b, f, d) {
- var i = Math.cos(j),
- h = Math.sin(j);
- this.transform(i * c, h * c, -h * a, i * a, g, e);
- this.arc(0, 0, 1, b, f, d);
- this.transform(i / c, -h / a, h / c, i / a, -(i * g + h * e) / c, (h * g - i * e) / a)
- },
- appendPath: function(f) {
- var e = this,
- c = 0,
- b = 0,
- a = f.commands,
- g = f.params,
- d = a.length;
- e.beginPath();
- for (; c < d; c++) {
- switch (a[c]) {
- case "M":
- e.moveTo(g[b], g[b + 1]);
- b += 2;
- break;
- case "L":
- e.lineTo(g[b], g[b + 1]);
- b += 2;
- break;
- case "C":
- e.bezierCurveTo(g[b], g[b + 1], g[b + 2], g[b + 3], g[b + 4], g[b + 5]);
- b += 6;
- break;
- case "Z":
- e.closePath();
- break
- }
- }
- },
- save: function() {
- var c = this.toSave,
- d = c.length,
- e = d && {},
- b = 0,
- a;
- for (; b < d; b++) {
- a = c[b];
- if (a in this) {
- e[a] = this[a]
- }
- }
- this.state.push(e);
- this.$save()
- },
- restore: function() {
- var b = this.state.pop(),
- a;
- if (b) {
- for (a in b) {
- this[a] = b[a]
- }
- }
- this.$restore()
- }
- }
- },
- splitThreshold: 3000,
- toSave: ["fillGradient", "strokeGradient"],
- element: {
- reference: "element",
- style: {
- position: "absolute"
- },
- children: [{
- reference: "innerElement",
- style: {
- width: "100%",
- height: "100%",
- position: "relative"
- }
- }]
- },
- createCanvas: function() {
- var c = Ext.Element.create({
- tag: "canvas",
- cls: Ext.baseCSSPrefix + "surface-canvas"
- });
- window.G_vmlCanvasManager && G_vmlCanvasManager.initElement(c.dom);
- var d = Ext.draw.engine.Canvas.contextOverrides,
- a = c.dom.getContext("2d"),
- b;
- if (a.ellipse) {
- delete d.ellipse
- }
- a.state = [];
- a.toSave = this.toSave;
- for (b in d) {
- a["$" + b] = a[b]
- }
- Ext.apply(a, d);
- if (this.getHighPrecision()) {
- this.enablePrecisionCompensation(a)
- } else {
- this.disablePrecisionCompensation(a)
- }
- this.innerElement.appendChild(c);
- this.canvases.push(c);
- this.contexts.push(a)
- },
- updateHighPrecision: function(d) {
- var e = this.contexts,
- c = e.length,
- b, a;
- for (b = 0; b < c; b++) {
- a = e[b];
- if (d) {
- this.enablePrecisionCompensation(a)
- } else {
- this.disablePrecisionCompensation(a)
- }
- }
- },
- precisionNames: ["rect", "fillRect", "strokeRect", "clearRect", "moveTo", "lineTo", "arc", "arcTo", "save", "restore", "updatePrecisionCompensate", "setTransform", "transform", "scale", "translate", "rotate", "quadraticCurveTo", "bezierCurveTo", "createLinearGradient", "createRadialGradient", "fillText", "strokeText", "drawImage"],
- disablePrecisionCompensation: function(b) {
- var a = Ext.draw.engine.Canvas.contextOverrides,
- f = this.precisionNames,
- e = f.length,
- d, c;
- for (d = 0; d < e; d++) {
- c = f[d];
- if (!(c in a)) {
- delete b[c]
- }
- }
- this.setDirty(true)
- },
- enablePrecisionCompensation: function(j) {
- var c = this,
- a = 1,
- g = 1,
- l = 0,
- k = 0,
- i = new Ext.draw.Matrix(),
- b = [],
- e = {},
- d = Ext.draw.engine.Canvas.contextOverrides,
- h = j.constructor.prototype;
- var f = {
- toSave: c.toSave,
- rect: function(m, p, n, o) {
- return h.rect.call(this, m * a + l, p * g + k, n * a, o * g)
- },
- fillRect: function(m, p, n, o) {
- this.updatePrecisionCompensateRect();
- h.fillRect.call(this, m * a + l, p * g + k, n * a, o * g);
- this.updatePrecisionCompensate()
- },
- strokeRect: function(m, p, n, o) {
- this.updatePrecisionCompensateRect();
- h.strokeRect.call(this, m * a + l, p * g + k, n * a, o * g);
- this.updatePrecisionCompensate()
- },
- clearRect: function(m, p, n, o) {
- return h.clearRect.call(this, m * a + l, p * g + k, n * a, o * g)
- },
- moveTo: function(m, n) {
- return h.moveTo.call(this, m * a + l, n * g + k)
- },
- lineTo: function(m, n) {
- return h.lineTo.call(this, m * a + l, n * g + k)
- },
- arc: function(n, r, m, p, o, q) {
- this.updatePrecisionCompensateRect();
- h.arc.call(this, n * a + l, r * a + k, m * a, p, o, q);
- this.updatePrecisionCompensate()
- },
- arcTo: function(o, q, n, p, m) {
- this.updatePrecisionCompensateRect();
- h.arcTo.call(this, o * a + l, q * g + k, n * a + l, p * g + k, m * a);
- this.updatePrecisionCompensate()
- },
- save: function() {
- b.push(i);
- i = i.clone();
- d.save.call(this);
- h.save.call(this)
- },
- restore: function() {
- i = b.pop();
- d.restore.call(this);
- h.restore.call(this);
- this.updatePrecisionCompensate()
- },
- updatePrecisionCompensate: function() {
- i.precisionCompensate(c.devicePixelRatio, e);
- a = e.xx;
- g = e.yy;
- l = e.dx;
- k = e.dy;
- h.setTransform.call(this, c.devicePixelRatio, e.b, e.c, e.d, 0, 0)
- },
- updatePrecisionCompensateRect: function() {
- i.precisionCompensateRect(c.devicePixelRatio, e);
- a = e.xx;
- g = e.yy;
- l = e.dx;
- k = e.dy;
- h.setTransform.call(this, c.devicePixelRatio, e.b, e.c, e.d, 0, 0)
- },
- setTransform: function(q, o, n, m, r, p) {
- i.set(q, o, n, m, r, p);
- this.updatePrecisionCompensate()
- },
- transform: function(q, o, n, m, r, p) {
- i.append(q, o, n, m, r, p);
- this.updatePrecisionCompensate()
- },
- scale: function(n, m) {
- this.transform(n, 0, 0, m, 0, 0)
- },
- translate: function(n, m) {
- this.transform(1, 0, 0, 1, n, m)
- },
- rotate: function(o) {
- var n = Math.cos(o),
- m = Math.sin(o);
- this.transform(n, m, -m, n, 0, 0)
- },
- quadraticCurveTo: function(n, p, m, o) {
- h.quadraticCurveTo.call(this, n * a + l, p * g + k, m * a + l, o * g + k)
- },
- bezierCurveTo: function(r, p, o, n, m, q) {
- h.bezierCurveTo.call(this, r * a + l, p * g + k, o * a + l, n * g + k, m * a + l, q * g + k)
- },
- createLinearGradient: function(n, p, m, o) {
- this.updatePrecisionCompensateRect();
- var q = h.createLinearGradient.call(this, n * a + l, p * g + k, m * a + l, o * g + k);
- this.updatePrecisionCompensate();
- return q
- },
- createRadialGradient: function(p, r, o, n, q, m) {
- this.updatePrecisionCompensateRect();
- var s = h.createLinearGradient.call(this, p * a + l, r * a + k, o * a, n * a + l, q * a + k, m * a);
- this.updatePrecisionCompensate();
- return s
- },
- fillText: function(o, m, p, n) {
- h.setTransform.apply(this, i.elements);
- if (typeof n === "undefined") {
- h.fillText.call(this, o, m, p)
- } else {
- h.fillText.call(this, o, m, p, n)
- }
- this.updatePrecisionCompensate()
- },
- strokeText: function(o, m, p, n) {
- h.setTransform.apply(this, i.elements);
- if (typeof n === "undefined") {
- h.strokeText.call(this, o, m, p)
- } else {
- h.strokeText.call(this, o, m, p, n)
- }
- this.updatePrecisionCompensate()
- },
- fill: function() {
- var m = this.fillGradient,
- n = this.bbox;
- this.updatePrecisionCompensateRect();
- if (m && n) {
- this.fillStyle = m.generateGradient(this, n)
- }
- h.fill.call(this);
- this.updatePrecisionCompensate()
- },
- stroke: function() {
- var m = this.strokeGradient,
- n = this.bbox;
- this.updatePrecisionCompensateRect();
- if (m && n) {
- this.strokeStyle = m.generateGradient(this, n)
- }
- h.stroke.call(this);
- this.updatePrecisionCompensate()
- },
- drawImage: function(u, s, r, q, p, o, n, m, t) {
- switch (arguments.length) {
- case 3:
- return h.drawImage.call(this, u, s * a + l, r * g + k);
- case 5:
- return h.drawImage.call(this, u, s * a + l, r * g + k, q * a, p * g);
- case 9:
- return h.drawImage.call(this, u, s, r, q, p, o * a + l, n * g * k, m * a, t * g)
- }
- }
- };
- Ext.apply(j, f);
- this.setDirty(true)
- },
- updateRect: function(a) {
- this.callParent([a]);
- var C = this,
- p = Math.floor(a[0]),
- e = Math.floor(a[1]),
- g = Math.ceil(a[0] + a[2]),
- B = Math.ceil(a[1] + a[3]),
- u = C.devicePixelRatio,
- D = C.canvases,
- d = g - p,
- y = B - e,
- n = Math.round(C.splitThreshold / u),
- c = C.xSplits = Math.ceil(d / n),
- f = C.ySplits = Math.ceil(y / n),
- v, s, q, A, z, x, o, m;
- for (s = 0, z = 0; s < f; s++, z += n) {
- for (v = 0, A = 0; v < c; v++, A += n) {
- q = s * c + v;
- if (q >= D.length) {
- C.createCanvas()
- }
- x = D[q].dom;
- x.style.left = A + "px";
- x.style.top = z + "px";
- m = Math.min(n, y - z);
- if (m * u !== x.height) {
- x.height = m * u;
- x.style.height = m + "px"
- }
- o = Math.min(n, d - A);
- if (o * u !== x.width) {
- x.width = o * u;
- x.style.width = o + "px"
- }
- C.applyDefaults(C.contexts[q])
- }
- }
- for (q += 1; q < D.length; q++) {
- D[q].destroy()
- }
- C.activeCanvases = c * f;
- D.length = C.activeCanvases;
- C.clear()
- },
- clearTransform: function() {
- var f = this,
- a = f.xSplits,
- g = f.ySplits,
- d = f.contexts,
- h = f.splitThreshold,
- l = f.devicePixelRatio,
- e, c, b, m;
- for (e = 0; e < a; e++) {
- for (c = 0; c < g; c++) {
- b = c * a + e;
- m = d[b];
- m.translate(-h * e, -h * c);
- m.scale(l, l);
- f.matrix.toContext(m)
- }
- }
- },
- renderSprite: function(q) {
- var C = this,
- b = C.getRect(),
- e = C.matrix,
- g = q.getParent(),
- v = Ext.draw.Matrix.fly([1, 0, 0, 1, 0, 0]),
- p = C.splitThreshold / C.devicePixelRatio,
- c = C.xSplits,
- m = C.ySplits,
- A, z, s, a, r, o, d = 0,
- B, n = 0,
- f, l = b[2],
- y = b[3],
- x, u, t;
- while (g && (g !== C)) {
- v.prependMatrix(g.matrix || g.attr && g.attr.matrix);
- g = g.getParent()
- }
- v.prependMatrix(e);
- a = q.getBBox();
- if (a) {
- a = v.transformBBox(a)
- }
- q.preRender(C);
- if (q.attr.hidden || q.attr.globalAlpha === 0) {
- q.setDirty(false);
- return
- }
- for (u = 0, z = 0; u < m; u++, z += p) {
- for (x = 0, A = 0; x < c; x++, A += p) {
- t = u * c + x;
- s = C.contexts[t];
- r = Math.min(p, l - A);
- o = Math.min(p, y - z);
- d = A;
- B = d + r;
- n = z;
- f = n + o;
- if (a) {
- if (a.x > B || a.x + a.width < d || a.y > f || a.y + a.height < n) {
- continue
- }
- }
- s.save();
- q.useAttributes(s, b);
- if (false === q.render(C, s, [d, n, r, o], b)) {
- return false
- }
- s.restore()
- }
- }
- q.setDirty(false)
- },
- flatten: function(n, a) {
- var k = document.createElement("canvas"),
- f = Ext.getClassName(this),
- g = this.devicePixelRatio,
- l = k.getContext("2d"),
- b, c, h, e, d, m;
- k.width = Math.ceil(n.width * g);
- k.height = Math.ceil(n.height * g);
- for (e = 0; e < a.length; e++) {
- b = a[e];
- if (Ext.getClassName(b) !== f) {
- continue
- }
- h = b.getRect();
- for (d = 0; d < b.canvases.length; d++) {
- c = b.canvases[d];
- m = c.getOffsetsTo(c.getParent());
- l.drawImage(c.dom, (h[0] + m[0]) * g, (h[1] + m[1]) * g)
- }
- }
- return {
- data: k.toDataURL(),
- type: "png"
- }
- },
- applyDefaults: function(a) {
- var b = Ext.draw.Color.RGBA_NONE;
- a.strokeStyle = b;
- a.fillStyle = b;
- a.textAlign = "start";
- a.textBaseline = "alphabetic";
- a.miterLimit = 1
- },
- clear: function() {
- var d = this,
- e = d.activeCanvases,
- c, b, a;
- for (c = 0; c < e; c++) {
- b = d.canvases[c].dom;
- a = d.contexts[c];
- a.setTransform(1, 0, 0, 1, 0, 0);
- a.clearRect(0, 0, b.width, b.height)
- }
- d.setDirty(true)
- },
- destroy: function() {
- var c = this,
- a, b = c.canvases.length;
- for (a = 0; a < b; a++) {
- c.contexts[a] = null;
- c.canvases[a].destroy();
- c.canvases[a] = null
- }
- delete c.contexts;
- delete c.canvases;
- c.callParent()
- },
- privates: {
- initElement: function() {
- var a = this;
- a.callParent();
- a.canvases = [];
- a.contexts = [];
- a.activeCanvases = (a.xSplits = 0) * (a.ySplits = 0)
- }
- }
-}, function() {
- var c = this,
- b = c.prototype,
- a = 10000000000;
- if (Ext.os.is.Android4 && Ext.browser.is.Chrome) {
- a = 3000
- } else {
- if (Ext.is.iOS) {
- a = 2200
- }
- }
- b.splitThreshold = a
-});
-Ext.define("Ext.draw.Container", {
- extend: "Ext.draw.ContainerBase",
- alternateClassName: "Ext.draw.Component",
- xtype: "draw",
- defaultType: "surface",
- isDrawContainer: true,
- requires: ["Ext.draw.Surface", "Ext.draw.engine.Svg", "Ext.draw.engine.Canvas", "Ext.draw.gradient.GradientDefinition"],
- engine: "Ext.draw.engine.Canvas",
- config: {
- cls: Ext.baseCSSPrefix + "draw-container",
- resizeHandler: null,
- sprites: null,
- gradients: []
- },
- defaultDownloadServerUrl: "http://svg.sencha.io",
- supportedFormats: ["png", "pdf", "jpeg", "gif"],
- supportedOptions: {
- version: Ext.isNumber,
- data: Ext.isString,
- format: function(a) {
- return Ext.Array.indexOf(this.supportedFormats, a) >= 0
- },
- filename: Ext.isString,
- width: Ext.isNumber,
- height: Ext.isNumber,
- scale: Ext.isNumber,
- pdf: Ext.isObject,
- jpeg: Ext.isObject
- },
- initAnimator: function() {
- this.frameCallbackId = Ext.draw.Animator.addFrameCallback("renderFrame", this)
- },
- applyGradients: function(b) {
- var a = [],
- c, f, d, e;
- if (!Ext.isArray(b)) {
- return a
- }
- for (c = 0, f = b.length; c < f; c++) {
- d = b[c];
- if (!Ext.isObject(d)) {
- continue
- }
- if (typeof d.type !== "string") {
- d.type = "linear"
- }
- if (d.angle) {
- d.degrees = d.angle;
- delete d.angle
- }
- if (Ext.isObject(d.stops)) {
- d.stops = (function(i) {
- var g = [],
- h;
- for (e in i) {
- h = i[e];
- h.offset = e / 100;
- g.push(h)
- }
- return g
- })(d.stops)
- }
- a.push(d)
- }
- Ext.draw.gradient.GradientDefinition.add(a);
- return a
- },
- applySprites: function(f) {
- if (!f) {
- return
- }
- f = Ext.Array.from(f);
- var e = f.length,
- b = [],
- d, a, c;
- for (d = 0; d < e; d++) {
- c = f[d];
- a = c.surface;
- if (!(a && a.isSurface)) {
- if (Ext.isString(a)) {
- a = this.getSurface(a)
- } else {
- a = this.getSurface("main")
- }
- }
- c = a.add(c);
- b.push(c)
- }
- return b
- },
- onBodyResize: function() {
- var b = this.element,
- a;
- if (!b) {
- return
- }
- a = b.getSize();
- if (a.width && a.height) {
- this.setBodySize(a)
- }
- },
- setBodySize: function(c) {
- var d = this,
- b = d.getResizeHandler() || d.defaultResizeHandler,
- a;
- d.fireEvent("bodyresize", d, c);
- a = b.call(d, c);
- if (a !== false) {
- d.renderFrame()
- }
- },
- defaultResizeHandler: function(a) {
- this.getItems().each(function(b) {
- b.setRect([0, 0, a.width, a.height])
- })
- },
- getSurface: function(d) {
- d = this.getId() + "-" + (d || "main");
- var c = this,
- b = c.getItems(),
- a = b.get(d);
- if (!a) {
- a = c.add({
- xclass: c.engine,
- id: d
- });
- c.onBodyResize()
- }
- return a
- },
- renderFrame: function() {
- var e = this,
- a = e.getItems(),
- b, d, c;
- for (b = 0, d = a.length; b < d; b++) {
- c = a.items[b];
- if (c.isSurface) {
- c.renderFrame()
- }
- }
- },
- getImage: function(k) {
- var l = this.innerElement.getSize(),
- a = Array.prototype.slice.call(this.items.items),
- d, g, c = this.surfaceZIndexes,
- f, e, b, h;
- for (e = 1; e < a.length; e++) {
- b = a[e];
- h = c[b.type];
- f = e - 1;
- while (f >= 0 && c[a[f].type] > h) {
- a[f + 1] = a[f];
- f--
- }
- a[f + 1] = b
- }
- d = a[0].flatten(l, a);
- if (k === "image") {
- g = new Image();
- g.src = d.data;
- d.data = g;
- return d
- }
- if (k === "stream") {
- d.data = d.data.replace(/^data:image\/[^;]+/, "data:application/octet-stream");
- return d
- }
- return d
- },
- download: function(d) {
- var e = this,
- a = [],
- b, c, f;
- d = Ext.apply({
- version: 2,
- data: e.getImage().data
- }, d);
- for (c in d) {
- if (d.hasOwnProperty(c)) {
- f = d[c];
- if (c in e.supportedOptions) {
- if (e.supportedOptions[c].call(e, f)) {
- a.push({
- tag: "input",
- type: "hidden",
- name: c,
- value: Ext.String.htmlEncode(Ext.isObject(f) ? Ext.JSON.encode(f) : f)
- })
- }
- }
- }
- }
- b = Ext.dom.Helper.markup({
- tag: "html",
- children: [{
- tag: "head"
- }, {
- tag: "body",
- children: [{
- tag: "form",
- method: "POST",
- action: d.url || e.defaultDownloadServerUrl,
- children: a
- }, {
- tag: "script",
- type: "text/javascript",
- children: 'document.getElementsByTagName("form")[0].submit();'
- }]
- }]
- });
- window.open("", "ImageDownload_" + Date.now()).document.write(b)
- },
- destroy: function() {
- var a = this.frameCallbackId;
- if (a) {
- Ext.draw.Animator.removeFrameCallback(a)
- }
- this.callParent()
- }
-}, function() {
- if (location.search.match("svg")) {
- Ext.draw.Container.prototype.engine = "Ext.draw.engine.Svg"
- } else {
- if ((Ext.os.is.BlackBerry && Ext.os.version.getMajor() === 10) || (Ext.browser.is.AndroidStock4 && (Ext.os.version.getMinor() === 1 || Ext.os.version.getMinor() === 2 || Ext.os.version.getMinor() === 3))) {
- Ext.draw.Container.prototype.engine = "Ext.draw.engine.Svg"
- }
- }
-});
-Ext.define("Ext.chart.theme.Base", {
- mixins: {
- factoryable: "Ext.mixin.Factoryable"
- },
- requires: ["Ext.draw.Color"],
- factoryConfig: {
- type: "chart.theme"
- },
- isTheme: true,
- config: {
- baseColor: null,
- colors: undefined,
- gradients: null,
- chart: {
- defaults: {
- background: "#23272a"
- }
- },
- axis: {
- defaults: {
- label: {
- x: 0,
- y: 0,
- textBaseline: "middle",
- textAlign: "center",
- fontSize: "default",
- fontFamily: "default",
- fontWeight: "default",
- fillStyle: "white",
- color: "white"
- },
- title: {
- fillStyle: "black",
- fontSize: "default*1.23",
- fontFamily: "default",
- fontWeight: "default",
- color: "white"
- },
- style: {
- strokeStyle: "black"
- },
- grid: {
- strokeStyle: "rgba(44, 47, 51, 1)"
- }
- },
- top: {
- style: {
- textPadding: 5
- }
- },
- bottom: {
- style: {
- textPadding: 5
- }
- }
- },
- series: {
- defaults: {
- label: {
- fillStyle: "black",
- strokeStyle: "none",
- fontFamily: "default",
- fontWeight: "default",
- fontSize: "default*1.077",
- textBaseline: "middle",
- textAlign: "center"
- },
- labelOverflowPadding: 5
- }
- },
- sprites: {
- text: {
- fontSize: "default",
- fontWeight: "default",
- fontFamily: "default",
- fillStyle: "black",
- color: "white"
- }
- },
- seriesThemes: undefined,
- markerThemes: {
- type: ["circle", "cross", "plus", "square", "triangle", "diamond"]
- },
- useGradients: false,
- background: null
- },
- colorDefaults: ["#94ae0a", "#115fa6", "#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
- constructor: function(a) {
- this.initConfig(a);
- this.resolveDefaults()
- },
- defaultRegEx: /^default([+\-/\*]\d+(?:\.\d+)?)?$/,
- defaultOperators: {
- "*": function(b, a) {
- return b * a
- },
- "+": function(b, a) {
- return b + a
- },
- "-": function(b, a) {
- return b - a
- }
- },
- resolveDefaults: function() {
- var a = this;
- Ext.onReady(function() {
- var f = Ext.clone(a.getSprites()),
- e = Ext.clone(a.getAxis()),
- d = Ext.clone(a.getSeries()),
- g, c, b;
- if (!a.superclass.defaults) {
- g = Ext.getBody().createChild({
- tag: "div",
- cls: "x-component"
- });
- a.superclass.defaults = {
- fontFamily: g.getStyle("fontFamily"),
- fontWeight: g.getStyle("fontWeight"),
- fontSize: parseFloat(g.getStyle("fontSize")),
- fontVariant: g.getStyle("fontVariant"),
- fontStyle: g.getStyle("fontStyle")
- };
- g.destroy()
- }
- a.replaceDefaults(f.text);
- a.setSprites(f);
- for (c in e) {
- b = e[c];
- a.replaceDefaults(b.label);
- a.replaceDefaults(b.title)
- }
- a.setAxis(e);
- for (c in d) {
- b = d[c];
- a.replaceDefaults(b.label)
- }
- a.setSeries(d)
- })
- },
- replaceDefaults: function(h) {
- var e = this,
- g = e.superclass.defaults,
- a = e.defaultRegEx,
- d, f, c, b;
- if (Ext.isObject(h)) {
- for (d in g) {
- c = a.exec(h[d]);
- if (c) {
- f = g[d];
- c = c[1];
- if (c) {
- b = e.defaultOperators[c.charAt(0)];
- f = Math.round(b(f, parseFloat(c.substr(1))))
- }
- h[d] = f
- }
- }
- }
- },
- applyBaseColor: function(c) {
- var a, b;
- if (c) {
- a = c.isColor ? c : Ext.draw.Color.fromString(c);
- b = a.getHSL()[2];
- if (b < 0.15) {
- a = a.createLighter(0.3)
- } else {
- if (b < 0.3) {
- a = a.createLighter(0.15)
- } else {
- if (b > 0.85) {
- a = a.createDarker(0.3)
- } else {
- if (b > 0.7) {
- a = a.createDarker(0.15)
- }
- }
- }
- }
- this.setColors([a.createDarker(0.3).toString(), a.createDarker(0.15).toString(), a.toString(), a.createLighter(0.12).toString(), a.createLighter(0.24).toString(), a.createLighter(0.31).toString()])
- }
- return c
- },
- applyColors: function(a) {
- return a || this.colorDefaults
- },
- updateUseGradients: function(a) {
- if (a) {
- this.updateGradients({
- type: "linear",
- degrees: 90
- })
- }
- },
- updateBackground: function(a) {
- if (a) {
- var b = this.getChart();
- b.defaults.background = a;
- this.setChart(b)
- }
- },
- updateGradients: function(a) {
- var c = this.getColors(),
- e = [],
- h, b, d, f, g;
- if (Ext.isObject(a)) {
- for (f = 0, g = c && c.length || 0; f < g; f++) {
- b = Ext.draw.Color.fromString(c[f]);
- if (b) {
- d = b.createLighter(0.15).toString();
- h = Ext.apply(Ext.Object.chain(a), {
- stops: [{
- offset: 1,
- color: b.toString()
- }, {
- offset: 0,
- color: d.toString()
- }]
- });
- e.push(h)
- }
- }
- this.setColors(e)
- }
- },
- applySeriesThemes: function(a) {
- this.getBaseColor();
- this.getUseGradients();
- this.getGradients();
- var b = this.getColors();
- if (!a) {
- a = {
- fillStyle: Ext.Array.clone(b),
- strokeStyle: Ext.Array.map(b, function(d) {
- var c = Ext.draw.Color.fromString(d.stops ? d.stops[0].color : d);
- return c.createDarker(0.15).toString()
- })
- }
- }
- return a
- }
-});
-Ext.define("Ext.chart.theme.Default", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.default", "chart.theme.Base"]
-});
-Ext.define("Ext.chart.Markers", {
- extend: "Ext.draw.sprite.Instancing",
- isMarkers: true,
- defaultCategory: "default",
- constructor: function() {
- this.callParent(arguments);
- this.categories = {};
- this.revisions = {}
- },
- destroy: function() {
- this.categories = null;
- this.revisions = null;
- this.callParent()
- },
- getMarkerFor: function(b, a) {
- if (b in this.categories) {
- var c = this.categories[b];
- if (a in c) {
- return this.get(c[a])
- }
- }
- },
- clear: function(a) {
- a = a || this.defaultCategory;
- if (!(a in this.revisions)) {
- this.revisions[a] = 1
- } else {
- this.revisions[a]++
- }
- },
- putMarkerFor: function(e, b, c, h, f) {
- e = e || this.defaultCategory;
- var d = this,
- g = d.categories[e] || (d.categories[e] = {}),
- a;
- if (c in g) {
- d.setAttributesFor(g[c], b, h)
- } else {
- g[c] = d.getCount();
- d.createInstance(b, h)
- }
- a = d.get(g[c]);
- if (a) {
- a.category = e;
- if (!f) {
- a.revision = d.revisions[e] || (d.revisions[e] = 1)
- }
- }
- },
- getMarkerBBoxFor: function(c, a, b) {
- if (c in this.categories) {
- var d = this.categories[c];
- if (a in d) {
- return this.getBBoxFor(d[a], b)
- }
- }
- },
- getBBox: function() {
- return null
- },
- render: function(a, l, b) {
- var f = this,
- k = f.revisions,
- j = f.attr.matrix,
- h = f.getTemplate(),
- d = h.attr,
- g, c, e;
- j.toContext(l);
- h.preRender(a, l, b);
- h.useAttributes(l, b);
- for (c = 0, e = f.instances.length; c < e; c++) {
- g = f.get(c);
- if (g.hidden || g.revision !== k[g.category]) {
- continue
- }
- l.save();
- h.attr = g;
- h.useAttributes(l, b);
- h.render(a, l, b);
- l.restore()
- }
- h.attr = d
- }
-});
-Ext.define("Ext.chart.label.Callout", {
- extend: "Ext.draw.modifier.Modifier",
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("calloutOriginal")) {
- a.calloutOriginal = Ext.Object.chain(a);
- a.calloutOriginal.prototype = a
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.calloutOriginal)
- }
- },
- setAttrs: function(e, h) {
- var d = e.callout,
- i = e.calloutOriginal,
- l = e.bbox.plain,
- c = (l.width || 0) + e.labelOverflowPadding,
- m = (l.height || 0) + e.labelOverflowPadding,
- p, o;
- if ("callout" in h) {
- d = h.callout
- }
- if ("callout" in h || "calloutPlaceX" in h || "calloutPlaceY" in h || "x" in h || "y" in h) {
- var n = "rotationRads" in h ? i.rotationRads = h.rotationRads : i.rotationRads,
- g = "x" in h ? (i.x = h.x) : i.x,
- f = "y" in h ? (i.y = h.y) : i.y,
- b = "calloutPlaceX" in h ? h.calloutPlaceX : e.calloutPlaceX,
- a = "calloutPlaceY" in h ? h.calloutPlaceY : e.calloutPlaceY,
- k = "calloutVertical" in h ? h.calloutVertical : e.calloutVertical,
- j;
- n %= Math.PI * 2;
- if (Math.cos(n) < 0) {
- n = (n + Math.PI) % (Math.PI * 2)
- }
- if (n > Math.PI) {
- n -= Math.PI * 2
- }
- if (k) {
- n = n * (1 - d) - Math.PI / 2 * d;
- j = c;
- c = m;
- m = j
- } else {
- n = n * (1 - d)
- }
- h.rotationRads = n;
- h.x = g * (1 - d) + b * d;
- h.y = f * (1 - d) + a * d;
- p = b - g;
- o = a - f;
- if (Math.abs(o * c) > Math.abs(p * m)) {
- if (o > 0) {
- h.calloutEndX = h.x - (m / 2) * (p / o) * d;
- h.calloutEndY = h.y - (m / 2) * d
- } else {
- h.calloutEndX = h.x + (m / 2) * (p / o) * d;
- h.calloutEndY = h.y + (m / 2) * d
- }
- } else {
- if (p > 0) {
- h.calloutEndX = h.x - c / 2;
- h.calloutEndY = h.y - (c / 2) * (o / p) * d
- } else {
- h.calloutEndX = h.x + c / 2;
- h.calloutEndY = h.y + (c / 2) * (o / p) * d
- }
- }
- if (h.calloutStartX && h.calloutStartY) {
- h.calloutHasLine = (p > 0 && h.calloutStartX < h.calloutEndX) || (p <= 0 && h.calloutStartX > h.calloutEndX) || (o > 0 && h.calloutStartY < h.calloutEndY) || (o <= 0 && h.calloutStartY > h.calloutEndY)
- } else {
- h.calloutHasLine = true
- }
- }
- return h
- },
- pushDown: function(a, b) {
- b = this.callParent([a.calloutOriginal, b]);
- return this.setAttrs(a, b)
- },
- popUp: function(a, b) {
- a = a.prototype;
- b = this.setAttrs(a, b);
- if (this._next) {
- return this._next.popUp(a, b)
- } else {
- return Ext.apply(a, b)
- }
- }
-});
-Ext.define("Ext.chart.label.Label", {
- extend: "Ext.draw.sprite.Text",
- requires: ["Ext.chart.label.Callout"],
- inheritableStatics: {
- def: {
- processors: {
- callout: "limited01",
- calloutHasLine: "bool",
- calloutPlaceX: "number",
- calloutPlaceY: "number",
- calloutStartX: "number",
- calloutStartY: "number",
- calloutEndX: "number",
- calloutEndY: "number",
- calloutColor: "color",
- calloutWidth: "number",
- calloutVertical: "bool",
- labelOverflowPadding: "number",
- display: "enums(none,under,over,rotate,insideStart,insideEnd,inside,outside)",
- orientation: "enums(horizontal,vertical)",
- renderer: "default"
- },
- defaults: {
- callout: 0,
- calloutHasLine: true,
- calloutPlaceX: 0,
- calloutPlaceY: 0,
- calloutStartX: 0,
- calloutStartY: 0,
- calloutEndX: 0,
- calloutEndY: 0,
- calloutWidth: 1,
- calloutVertical: false,
- calloutColor: "black",
- labelOverflowPadding: 5,
- display: "none",
- orientation: "",
- renderer: null
- },
- triggers: {
- callout: "transform",
- calloutPlaceX: "transform",
- calloutPlaceY: "transform",
- labelOverflowPadding: "transform",
- calloutRotation: "transform",
- display: "hidden"
- },
- updaters: {
- hidden: function(a) {
- a.hidden = a.display === "none"
- }
- }
- }
- },
- config: {
- fx: {
- customDurations: {
- callout: 200
- }
- },
- field: null,
- calloutLine: true
- },
- applyCalloutLine: function(a) {
- if (a) {
- return Ext.apply({}, a)
- }
- },
- prepareModifiers: function() {
- this.callParent(arguments);
- this.calloutModifier = new Ext.chart.label.Callout({
- sprite: this
- });
- this.fx.setNext(this.calloutModifier);
- this.calloutModifier.setNext(this.topModifier)
- },
- render: function(b, c) {
- var e = this,
- a = e.attr,
- d = a.calloutColor;
- c.save();
- c.globalAlpha *= a.callout;
- if (c.globalAlpha > 0 && a.calloutHasLine) {
- if (d && d.isGradient) {
- d = d.getStops()[0].color
- }
- c.strokeStyle = d;
- c.fillStyle = d;
- c.lineWidth = a.calloutWidth;
- c.beginPath();
- c.moveTo(e.attr.calloutStartX, e.attr.calloutStartY);
- c.lineTo(e.attr.calloutEndX, e.attr.calloutEndY);
- c.stroke();
- c.beginPath();
- c.arc(e.attr.calloutStartX, e.attr.calloutStartY, 1 * a.calloutWidth, 0, 2 * Math.PI, true);
- c.fill();
- c.beginPath();
- c.arc(e.attr.calloutEndX, e.attr.calloutEndY, 1 * a.calloutWidth, 0, 2 * Math.PI, true);
- c.fill()
- }
- c.restore();
- Ext.draw.sprite.Text.prototype.render.apply(e, arguments)
- }
-});
-Ext.define("Ext.chart.series.Series", {
- requires: ["Ext.chart.Markers", "Ext.chart.label.Label", "Ext.tip.ToolTip"],
- mixins: ["Ext.mixin.Observable", "Ext.mixin.Bindable"],
- isSeries: true,
- defaultBindProperty: "store",
- type: null,
- seriesType: "sprite",
- identifiablePrefix: "ext-line-",
- observableType: "series",
- darkerStrokeRatio: 0.15,
- config: {
- chart: null,
- title: null,
- renderer: null,
- showInLegend: true,
- triggerAfterDraw: false,
- style: {},
- subStyle: {},
- themeStyle: {},
- colors: null,
- useDarkerStrokeColor: true,
- store: null,
- label: {},
- labelOverflowPadding: null,
- showMarkers: true,
- marker: null,
- markerSubStyle: null,
- itemInstancing: null,
- background: null,
- highlightItem: null,
- surface: null,
- overlaySurface: null,
- hidden: false,
- highlight: false,
- highlightCfg: {
- merge: function(a) {
- return a
- },
- $value: {
- fillStyle: "yellow",
- strokeStyle: "red"
- }
- },
- animation: null,
- tooltip: null
- },
- directions: [],
- sprites: null,
- themeColorCount: function() {
- return 1
- },
- isStoreDependantColorCount: false,
- themeMarkerCount: function() {
- return 0
- },
- getFields: function(f) {
- var e = this,
- a = [],
- c, b, d;
- for (b = 0, d = f.length; b < d; b++) {
- c = e["get" + f[b] + "Field"]();
- if (Ext.isArray(c)) {
- a.push.apply(a, c)
- } else {
- a.push(c)
- }
- }
- return a
- },
- applyAnimation: function(a, b) {
- if (!a) {
- a = {
- duration: 0
- }
- } else {
- if (a === true) {
- a = {
- easing: "easeInOut",
- duration: 500
- }
- }
- }
- return b ? Ext.apply({}, a, b) : a
- },
- getAnimation: function() {
- var a = this.getChart();
- if (a && a.animationSuspendCount) {
- return {
- duration: 0
- }
- } else {
- return this.callParent()
- }
- },
- updateTitle: function(a) {
- var j = this,
- g = j.getChart();
- if (!g || g.isInitializing) {
- return
- }
- a = Ext.Array.from(a);
- var c = g.getSeries(),
- b = Ext.Array.indexOf(c, j),
- e = g.getLegendStore(),
- h = j.getYField(),
- d, l, k, f;
- if (e.getCount() && b !== -1) {
- f = h ? Math.min(a.length, h.length) : a.length;
- for (d = 0; d < f; d++) {
- k = a[d];
- l = e.getAt(b + d);
- if (k && l) {
- l.set("name", k)
- }
- }
- }
- },
- applyHighlight: function(a, b) {
- if (Ext.isObject(a)) {
- a = Ext.merge({}, this.config.highlightCfg, a)
- } else {
- if (a === true) {
- a = this.config.highlightCfg
- }
- }
- return Ext.apply(b || {}, a)
- },
- updateHighlight: function(a) {
- this.getStyle();
- if (!Ext.Object.isEmpty(a)) {
- this.addItemHighlight()
- }
- },
- updateHighlightCfg: function(a) {
- if (!Ext.Object.equals(a, this.defaultConfig.highlightCfg)) {
- this.addItemHighlight()
- }
- },
- applyItemInstancing: function(a, b) {
- return Ext.merge(b || {}, a)
- },
- setAttributesForItem: function(c, d) {
- var b = c && c.sprite,
- a;
- if (b) {
- if (b.itemsMarker && c.category === "items") {
- b.putMarker(c.category, d, c.index, false, true)
- }
- if (b.isMarkerHolder && c.category === "markers") {
- b.putMarker(c.category, d, c.index, false, true)
- } else {
- if (b.isInstancing) {
- b.setAttributesFor(c.index, d)
- } else {
- if (Ext.isArray(b)) {
- for (a = 0; a < b.length; a++) {
- b[a].setAttributes(d)
- }
- } else {
- b.setAttributes(d)
- }
- }
- }
- }
- },
- getBBoxForItem: function(a) {
- if (a && a.sprite) {
- if (a.sprite.itemsMarker && a.category === "items") {
- return a.sprite.getMarkerBBox(a.category, a.index)
- } else {
- if (a.sprite instanceof Ext.draw.sprite.Instancing) {
- return a.sprite.getBBoxFor(a.index)
- } else {
- return a.sprite.getBBox()
- }
- }
- }
- return null
- },
- applyHighlightItem: function(d, a) {
- if (d === a) {
- return
- }
- if (Ext.isObject(d) && Ext.isObject(a)) {
- var c = d.sprite === a.sprite,
- b = d.index === a.index;
- if (c && b) {
- return
- }
- }
- return d
- },
- updateHighlightItem: function(b, a) {
- this.setAttributesForItem(a, {
- highlighted: false
- });
- this.setAttributesForItem(b, {
- highlighted: true
- })
- },
- constructor: function(a) {
- var b = this,
- c;
- a = a || {};
- if (a.tips) {
- a = Ext.apply({
- tooltip: a.tips
- }, a)
- }
- if (a.highlightCfg) {
- a = Ext.apply({
- highlight: a.highlightCfg
- }, a)
- }
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.sprites = [];
- b.dataRange = [];
- b.mixins.observable.constructor.call(b, a);
- b.initBindable()
- },
- lookupViewModel: function(a) {
- var b = this.getChart();
- return b ? b.lookupViewModel(a) : null
- },
- applyTooltip: function(c, b) {
- var a = Ext.apply({
- xtype: "tooltip",
- renderer: Ext.emptyFn,
- constrainPosition: true,
- shrinkWrapDock: true,
- autoHide: true,
- offsetX: 10,
- offsetY: 10
- }, c);
- return Ext.create(a)
- },
- updateTooltip: function() {
- this.addItemHighlight()
- },
- addItemHighlight: function() {
- var d = this.getChart();
- if (!d) {
- return
- }
- var e = d.getInteractions(),
- c, a, b;
- for (c = 0; c < e.length; c++) {
- a = e[c];
- if (a.isItemHighlight || a.isItemEdit) {
- b = true;
- break
- }
- }
- if (!b) {
- e.push("itemhighlight");
- d.setInteractions(e)
- }
- },
- showTooltip: function(l, m) {
- var d = this,
- n = d.getTooltip(),
- j, a, i, f, h, k, g, e, b, c;
- if (!n) {
- return
- }
- clearTimeout(d.tooltipTimeout);
- b = n.config;
- if (n.trackMouse) {
- m[0] += b.offsetX;
- m[1] += b.offsetY
- } else {
- j = l.sprite;
- a = j.getSurface();
- i = Ext.get(a.getId());
- if (i) {
- k = l.series.getBBoxForItem(l);
- g = k.x + k.width / 2;
- e = k.y + k.height / 2;
- h = a.matrix.transformPoint([g, e]);
- f = i.getXY();
- c = a.getInherited().rtl;
- g = c ? f[0] + i.getWidth() - h[0] : f[0] + h[0];
- e = f[1] + h[1];
- m = [g, e]
- }
- }
- Ext.callback(n.renderer, n.scope, [n, l.record, l], 0, d);
- n.show(m)
- },
- hideTooltip: function(b) {
- var a = this,
- c = a.getTooltip();
- if (!c) {
- return
- }
- clearTimeout(a.tooltipTimeout);
- a.tooltipTimeout = Ext.defer(function() {
- c.hide()
- }, 1)
- },
- applyStore: function(a) {
- return a && Ext.StoreManager.lookup(a)
- },
- getStore: function() {
- return this._store || this.getChart() && this.getChart().getStore()
- },
- updateStore: function(b, a) {
- var h = this,
- g = h.getChart(),
- c = g && g.getStore(),
- f, j, e, d;
- a = a || c;
- if (a && a !== b) {
- a.un({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: h
- })
- }
- if (b) {
- b.on({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: h
- });
- f = h.getSprites();
- for (d = 0, e = f.length; d < e; d++) {
- j = f[d];
- if (j.setStore) {
- j.setStore(b)
- }
- }
- h.onDataChanged()
- }
- h.fireEvent("storechange", h, b, a)
- },
- onStoreChange: function(b, a, c) {
- if (!this._store) {
- this.updateStore(a, c)
- }
- },
- coordinate: function(o, m, e) {
- var l = this,
- p = l.getStore(),
- h = l.getHidden(),
- k = p.getData().items,
- b = l["get" + o + "Axis"](),
- f = {
- min: Infinity,
- max: -Infinity
- },
- q = l["fieldCategory" + o] || [o],
- g = l.getFields(q),
- d, n, c, a = {},
- j = l.getSprites();
- if (j.length > 0) {
- if (!Ext.isBoolean(h) || !h) {
- for (d = 0; d < q.length; d++) {
- n = g[d];
- c = l.coordinateData(k, n, b);
- l.getRangeOfData(c, f);
- a["data" + q[d]] = c
- }
- }
- l.dataRange[m] = f.min;
- l.dataRange[m + e] = f.max;
- a["dataMin" + o] = f.min;
- a["dataMax" + o] = f.max;
- if (b) {
- b.range = null;
- a["range" + o] = b.getRange()
- }
- for (d = 0; d < j.length; d++) {
- j[d].setAttributes(a)
- }
- }
- },
- coordinateData: function(b, h, d) {
- var g = [],
- f = b.length,
- e = d && d.getLayout(),
- c, a;
- for (c = 0; c < f; c++) {
- a = b[c].data[h];
- if (!Ext.isEmpty(a, true)) {
- if (e) {
- g[c] = e.getCoordFor(a, h, c, b)
- } else {
- g[c] = +a
- }
- } else {
- g[c] = a
- }
- }
- return g
- },
- getRangeOfData: function(g, b) {
- var e = g.length,
- d = b.min,
- a = b.max,
- c, f;
- for (c = 0; c < e; c++) {
- f = g[c];
- if (f < d) {
- d = f
- }
- if (f > a) {
- a = f
- }
- }
- b.min = d;
- b.max = a
- },
- updateLabelData: function() {
- var h = this,
- l = h.getStore(),
- g = l.getData().items,
- f = h.getSprites(),
- a = h.getLabel().getTemplate(),
- n = Ext.Array.from(a.getField()),
- c, b, e, d, m, k;
- if (!f.length || !n.length) {
- return
- }
- for (c = 0; c < f.length; c++) {
- d = [];
- m = f[c];
- k = m.getField();
- if (Ext.Array.indexOf(n, k) < 0) {
- k = n[c]
- }
- for (b = 0, e = g.length; b < e; b++) {
- d.push(g[b].get(k))
- }
- m.setAttributes({
- labels: d
- })
- }
- },
- processData: function() {
- if (!this.getStore()) {
- return
- }
- var d = this,
- f = this.directions,
- a, c = f.length,
- e, b;
- for (a = 0; a < c; a++) {
- e = f[a];
- b = d["get" + e + "Axis"]();
- if (b) {
- b.processData(d);
- continue
- }
- if (d["coordinate" + e]) {
- d["coordinate" + e]()
- }
- }
- d.updateLabelData()
- },
- applyBackground: function(a) {
- if (this.getChart()) {
- this.getSurface().setBackground(a);
- return this.getSurface().getBackground()
- } else {
- return a
- }
- },
- updateChart: function(d, a) {
- var c = this,
- b = c._store;
- if (a) {
- a.un("axeschange", "onAxesChange", c);
- c.clearSprites();
- c.setSurface(null);
- c.setOverlaySurface(null);
- a.unregister(c);
- c.onChartDetached(a);
- if (!b) {
- c.updateStore(null)
- }
- }
- if (d) {
- c.setSurface(d.getSurface("series"));
- c.setOverlaySurface(d.getSurface("overlay"));
- d.on("axeschange", "onAxesChange", c);
- if (d.getAxes()) {
- c.onAxesChange(d)
- }
- c.onChartAttached(d);
- d.register(c);
- if (!b) {
- c.updateStore(d.getStore())
- }
- }
- },
- onAxesChange: function(h) {
- var k = this,
- g = h.getAxes(),
- c, a = {},
- b = {},
- e = false,
- j = this.directions,
- l, d, f;
- for (d = 0, f = j.length; d < f; d++) {
- l = j[d];
- b[l] = k.getFields(k["fieldCategory" + l])
- }
- for (d = 0, f = g.length; d < f; d++) {
- c = g[d];
- if (!a[c.getDirection()]) {
- a[c.getDirection()] = [c]
- } else {
- a[c.getDirection()].push(c)
- }
- }
- for (d = 0, f = j.length; d < f; d++) {
- l = j[d];
- if (k["get" + l + "Axis"]()) {
- continue
- }
- if (a[l]) {
- c = k.findMatchingAxis(a[l], b[l]);
- if (c) {
- k["set" + l + "Axis"](c);
- if (c.getNeedHighPrecision()) {
- e = true
- }
- }
- }
- }
- this.getSurface().setHighPrecision(e)
- },
- findMatchingAxis: function(f, e) {
- var d, c, b, a;
- for (b = 0; b < f.length; b++) {
- d = f[b];
- c = d.getFields();
- if (!c.length) {
- return d
- } else {
- if (e) {
- for (a = 0; a < e.length; a++) {
- if (Ext.Array.indexOf(c, e[a]) >= 0) {
- return d
- }
- }
- }
- }
- }
- },
- onChartDetached: function(a) {
- var b = this;
- b.fireEvent("chartdetached", a, b);
- a.un("storechange", "onStoreChange", b)
- },
- onChartAttached: function(a) {
- var b = this;
- b.setBackground(b.getBackground());
- b.fireEvent("chartattached", a, b);
- a.on("storechange", "onStoreChange", b);
- b.processData()
- },
- updateOverlaySurface: function(a) {
- var b = this;
- if (a) {
- if (b.getLabel()) {
- b.getOverlaySurface().add(b.getLabel())
- }
- }
- },
- applyLabel: function(a, b) {
- if (!b) {
- b = new Ext.chart.Markers({
- zIndex: 10
- });
- b.setTemplate(new Ext.chart.label.Label(a))
- } else {
- b.getTemplate().setAttributes(a)
- }
- return b
- },
- createItemInstancingSprite: function(c, b) {
- var e = this,
- f = new Ext.chart.Markers(),
- a, d;
- f.setAttributes({
- zIndex: Number.MAX_VALUE
- });
- a = Ext.apply({}, b);
- if (e.getHighlight()) {
- a.highlight = e.getHighlight();
- a.modifiers = ["highlight"]
- }
- f.setTemplate(a);
- d = f.getTemplate();
- d.setAttributes(e.getStyle());
- d.fx.on("animationstart", "onSpriteAnimationStart", this);
- d.fx.on("animationend", "onSpriteAnimationEnd", this);
- c.bindMarker("items", f);
- e.getSurface().add(f);
- return f
- },
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer()
- }
- },
- updateRenderer: function(c) {
- var b = this,
- a = b.getChart(),
- d;
- if (a && a.isInitializing) {
- return
- }
- d = b.getSprites();
- if (d.length) {
- d[0].setAttributes({
- renderer: c || null
- });
- if (a && !a.isInitializing) {
- a.redraw()
- }
- }
- },
- updateShowMarkers: function(a) {
- var d = this.getSprites(),
- b = d && d[0],
- c = b && b.getMarker("markers");
- if (c) {
- c.getTemplate().setAttributes({
- hidden: !a
- })
- }
- },
- createSprite: function() {
- var f = this,
- a = f.getSurface(),
- e = f.getItemInstancing(),
- d = a.add(f.getDefaultSpriteConfig()),
- b = f.getMarker(),
- g, c;
- d.setAttributes(f.getStyle());
- d.setSeries(f);
- if (e) {
- d.itemsMarker = f.createItemInstancingSprite(d, e)
- }
- if (d.bindMarker) {
- if (b) {
- g = new Ext.chart.Markers();
- c = Ext.Object.merge({}, b);
- if (f.getHighlight()) {
- c.highlight = f.getHighlight();
- c.modifiers = ["highlight"]
- }
- g.setTemplate(c);
- g.getTemplate().fx.setCustomDurations({
- translationX: 0,
- translationY: 0
- });
- d.dataMarker = g;
- d.bindMarker("markers", g);
- f.getOverlaySurface().add(g)
- }
- if (f.getLabel().getTemplate().getField()) {
- d.bindMarker("labels", f.getLabel())
- }
- }
- if (d.setStore) {
- d.setStore(f.getStore())
- }
- d.fx.on("animationstart", "onSpriteAnimationStart", f);
- d.fx.on("animationend", "onSpriteAnimationEnd", f);
- f.sprites.push(d);
- return d
- },
- getSprites: Ext.emptyFn,
- onDataChanged: function() {
- var d = this,
- c = d.getChart(),
- b = c && c.getStore(),
- a = d.getStore();
- if (a !== b) {
- d.processData()
- }
- },
- isXType: function(a) {
- return a === "series"
- },
- getItemId: function() {
- return this.getId()
- },
- applyThemeStyle: function(e, a) {
- var b = this,
- d, c;
- d = e && e.subStyle && e.subStyle.fillStyle;
- c = d && e.subStyle.strokeStyle;
- if (d && !c) {
- e.subStyle.strokeStyle = b.getStrokeColorsFromFillColors(d)
- }
- d = e && e.markerSubStyle && e.markerSubStyle.fillStyle;
- c = d && e.markerSubStyle.strokeStyle;
- if (d && !c) {
- e.markerSubStyle.strokeStyle = b.getStrokeColorsFromFillColors(d)
- }
- return Ext.apply(a || {}, e)
- },
- applyStyle: function(c, b) {
- var a = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + this.seriesType));
- if (a && a.def) {
- c = a.def.normalize(c)
- }
- return Ext.apply({}, c, b)
- },
- applySubStyle: function(b, c) {
- var a = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + this.seriesType));
- if (a && a.def) {
- b = a.def.batchedNormalize(b, true)
- }
- return Ext.merge({}, c, b)
- },
- applyMarker: function(c, a) {
- var d = (c && c.type) || (a && a.type) || "circle",
- b = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + d));
- if (b && b.def) {
- c = b.def.normalize(Ext.isObject(c) ? c : {}, true);
- c.type = d
- }
- return Ext.merge(a || {}, c)
- },
- applyMarkerSubStyle: function(c, a) {
- var d = (c && c.type) || (a && a.type) || "circle",
- b = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + d));
- if (b && b.def) {
- c = b.def.batchedNormalize(c, true)
- }
- return Ext.merge(a || {}, c)
- },
- updateHidden: function(b) {
- var a = this;
- a.getColors();
- a.getSubStyle();
- a.setSubStyle({
- hidden: b
- });
- a.processData();
- a.doUpdateStyles();
- if (!Ext.isArray(b)) {
- a.updateLegendStore(b)
- }
- },
- updateLegendStore: function(f, b) {
- var e = this,
- d = e.getChart(),
- c = d.getLegendStore(),
- g = e.getId(),
- a;
- if (c) {
- if (arguments.length > 1) {
- a = c.findBy(function(h) {
- return h.get("series") === g && h.get("index") === b
- });
- if (a !== -1) {
- a = c.getAt(a)
- }
- } else {
- a = c.findRecord("series", g)
- }
- if (a && a.get("disabled") !== f) {
- a.set("disabled", f)
- }
- }
- },
- setHiddenByIndex: function(a, c) {
- var b = this;
- if (Ext.isArray(b.getHidden())) {
- b.getHidden()[a] = c;
- b.updateHidden(b.getHidden());
- b.updateLegendStore(c, a)
- } else {
- b.setHidden(c)
- }
- },
- getStrokeColorsFromFillColors: function(a) {
- var c = this,
- e = c.getUseDarkerStrokeColor(),
- b = (Ext.isNumber(e) ? e : c.darkerStrokeRatio),
- d;
- if (e) {
- d = Ext.Array.map(a, function(f) {
- f = Ext.isString(f) ? f : f.stops[0].color;
- f = Ext.draw.Color.fromString(f);
- return f.createDarker(b).toString()
- })
- } else {
- d = Ext.Array.clone(a)
- }
- return d
- },
- updateThemeColors: function(b) {
- var c = this,
- d = c.getThemeStyle(),
- a = Ext.Array.clone(b),
- f = c.getStrokeColorsFromFillColors(b),
- e = {
- fillStyle: a,
- strokeStyle: f
- };
- d.subStyle = Ext.apply(d.subStyle || {}, e);
- d.markerSubStyle = Ext.apply(d.markerSubStyle || {}, e);
- c.doUpdateStyles()
- },
- themeOnlyIfConfigured: {},
- updateTheme: function(d) {
- var h = this,
- a = d.getSeries(),
- n = h.getInitialConfig(),
- c = h.defaultConfig,
- f = h.getConfigurator().configs,
- j = a.defaults,
- k = a[h.type],
- g = h.themeOnlyIfConfigured,
- l, i, o, b, m, e;
- a = Ext.merge({}, j, k);
- for (l in a) {
- i = a[l];
- e = f[l];
- if (i !== null && i !== undefined && e) {
- m = n[l];
- o = Ext.isObject(i);
- b = m === c[l];
- if (o) {
- if (b && g[l]) {
- continue
- }
- i = Ext.merge({}, i, m)
- }
- if (b || o) {
- h[e.names.set](i)
- }
- }
- }
- },
- updateChartColors: function(a) {
- var b = this;
- if (!b.getColors()) {
- b.updateThemeColors(a)
- }
- },
- updateColors: function(a) {
- this.updateThemeColors(a)
- },
- updateStyle: function() {
- this.doUpdateStyles()
- },
- updateSubStyle: function() {
- this.doUpdateStyles()
- },
- updateThemeStyle: function() {
- this.doUpdateStyles()
- },
- doUpdateStyles: function() {
- var g = this,
- h = g.sprites,
- d = g.getItemInstancing(),
- c = 0,
- f = h && h.length,
- a = g.getConfig("showMarkers", true),
- b = g.getMarker(),
- e;
- for (; c < f; c++) {
- e = g.getStyleByIndex(c);
- if (d) {
- h[c].itemsMarker.getTemplate().setAttributes(e)
- }
- h[c].setAttributes(e);
- if (b && h[c].dataMarker) {
- h[c].dataMarker.getTemplate().setAttributes(g.getMarkerStyleByIndex(c))
- }
- }
- },
- getStyleWithTheme: function() {
- var b = this,
- c = b.getThemeStyle(),
- d = (c && c.style) || {},
- a = Ext.applyIf(Ext.apply({}, b.getStyle()), d);
- return a
- },
- getSubStyleWithTheme: function() {
- var c = this,
- d = c.getThemeStyle(),
- a = (d && d.subStyle) || {},
- b = Ext.applyIf(Ext.apply({}, c.getSubStyle()), a);
- return b
- },
- getStyleByIndex: function(b) {
- var e = this,
- h = e.getThemeStyle(),
- d, g, c, f, a = {};
- d = e.getStyle();
- g = (h && h.style) || {};
- c = e.styleDataForIndex(e.getSubStyle(), b);
- f = e.styleDataForIndex((h && h.subStyle), b);
- Ext.apply(a, g);
- Ext.apply(a, f);
- Ext.apply(a, d);
- Ext.apply(a, c);
- return a
- },
- getMarkerStyleByIndex: function(d) {
- var g = this,
- c = g.getThemeStyle(),
- a, e, k, j, b, l, h, f, m = {};
- a = g.getStyle();
- e = (c && c.style) || {};
- k = g.styleDataForIndex(g.getSubStyle(), d);
- if (k.hasOwnProperty("hidden")) {
- k.hidden = k.hidden || !this.getConfig("showMarkers", true)
- }
- j = g.styleDataForIndex((c && c.subStyle), d);
- b = g.getMarker();
- l = (c && c.marker) || {};
- h = g.getMarkerSubStyle();
- f = g.styleDataForIndex((c && c.markerSubStyle), d);
- Ext.apply(m, e);
- Ext.apply(m, j);
- Ext.apply(m, l);
- Ext.apply(m, f);
- Ext.apply(m, a);
- Ext.apply(m, k);
- Ext.apply(m, b);
- Ext.apply(m, h);
- return m
- },
- styleDataForIndex: function(d, c) {
- var e, b, a = {};
- if (d) {
- for (b in d) {
- e = d[b];
- if (Ext.isArray(e)) {
- a[b] = e[c % e.length]
- } else {
- a[b] = e
- }
- }
- }
- return a
- },
- getItemForPoint: Ext.emptyFn,
- getItemByIndex: function(a, e) {
- var d = this,
- f = d.getSprites(),
- b = f && f[0],
- c;
- if (!b) {
- return
- }
- if (e === undefined && b.isMarkerHolder) {
- e = d.getItemInstancing() ? "items" : "markers"
- } else {
- if (!e || e === "" || e === "sprites") {
- b = f[a]
- }
- }
- if (b) {
- c = {
- series: d,
- category: e,
- index: a,
- record: d.getStore().getData().items[a],
- field: d.getYField(),
- sprite: b
- };
- return c
- }
- },
- onSpriteAnimationStart: function(a) {
- this.fireEvent("animationstart", this, a)
- },
- onSpriteAnimationEnd: function(a) {
- this.fireEvent("animationend", this, a)
- },
- resolveListenerScope: function(e) {
- var d = this,
- a = Ext._namedScopes[e],
- c = d.getChart(),
- b;
- if (!a) {
- b = c ? c.resolveListenerScope(e, false) : (e || d)
- } else {
- if (a.isThis) {
- b = d
- } else {
- if (a.isController) {
- b = c ? c.resolveListenerScope(e, false) : d
- } else {
- if (a.isSelf) {
- b = c ? c.resolveListenerScope(e, false) : d;
- if (b === c && !c.getInheritedConfig("defaultListenerScope")) {
- b = d
- }
- }
- }
- }
- }
- return b
- },
- provideLegendInfo: function(a) {
- a.push({
- name: this.getTitle() || this.getId(),
- mark: "black",
- disabled: this.getHidden(),
- series: this.getId(),
- index: 0
- })
- },
- clearSprites: function() {
- var d = this.sprites,
- b, a, c;
- for (a = 0, c = d.length; a < c; a++) {
- b = d[a];
- if (b && b.isSprite) {
- b.destroy()
- }
- }
- this.sprites = []
- },
- destroy: function() {
- var b = this,
- a = b._store,
- c = b.getConfig("tooltip", true);
- if (a && a.getAutoDestroy()) {
- Ext.destroy(a)
- }
- b.setChart(null);
- b.clearListeners();
- if (c) {
- Ext.destroy(c);
- clearTimeout(b.tooltipTimeout)
- }
- b.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.Abstract", {
- xtype: "interaction",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- gestures: {
- tap: "onGesture"
- },
- chart: null,
- enabled: true
- },
- throttleGap: 0,
- stopAnimationBeforeSync: false,
- constructor: function(a) {
- var b = this,
- c;
- a = a || {};
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.mixins.observable.constructor.call(b, a)
- },
- initialize: Ext.emptyFn,
- updateChart: function(c, a) {
- var b = this;
- if (a === c) {
- return
- }
- if (a) {
- a.unregister(b);
- b.removeChartListener(a)
- }
- if (c) {
- c.register(b);
- b.addChartListener()
- }
- },
- updateEnabled: function(a) {
- var c = this,
- b = c.getChart();
- if (b) {
- if (a) {
- c.addChartListener()
- } else {
- c.removeChartListener(b)
- }
- }
- },
- onGesture: Ext.emptyFn,
- getItemForEvent: function(d) {
- var b = this,
- a = b.getChart(),
- c = a.getEventXY(d);
- return a.getItemForPoint(c[0], c[1])
- },
- getItemsForEvent: function(d) {
- var b = this,
- a = b.getChart(),
- c = a.getEventXY(d);
- return a.getItemsForPoint(c[0], c[1])
- },
- addChartListener: function() {
- var c = this,
- b = c.getChart(),
- e = c.getGestures(),
- a;
- if (!c.getEnabled()) {
- return
- }
-
- function d(f, g) {
- b.addElementListener(f, c.listeners[f] = function(j) {
- var i = c.getLocks(),
- h;
- if (c.getEnabled() && (!(f in i) || i[f] === c)) {
- h = (Ext.isFunction(g) ? g : c[g]).apply(this, arguments);
- if (h === false && j && j.stopPropagation) {
- j.stopPropagation()
- }
- return h
- }
- }, c)
- }
- c.listeners = c.listeners || {};
- for (a in e) {
- d(a, e[a])
- }
- },
- removeChartListener: function(c) {
- var d = this,
- e = d.getGestures(),
- b;
-
- function a(f) {
- var g = d.listeners[f];
- if (g) {
- c.removeElementListener(f, g);
- delete d.listeners[f]
- }
- }
- if (d.listeners) {
- for (b in e) {
- a(b)
- }
- }
- },
- lockEvents: function() {
- var d = this,
- c = d.getLocks(),
- a = Array.prototype.slice.call(arguments),
- b = a.length;
- while (b--) {
- c[a[b]] = d
- }
- },
- unlockEvents: function() {
- var c = this.getLocks(),
- a = Array.prototype.slice.call(arguments),
- b = a.length;
- while (b--) {
- delete c[a[b]]
- }
- },
- getLocks: function() {
- var a = this.getChart();
- return a.lockedEvents || (a.lockedEvents = {})
- },
- isMultiTouch: function() {
- if (Ext.browser.is.IE10) {
- return true
- }
- return !Ext.os.is.Desktop
- },
- initializeDefaults: Ext.emptyFn,
- doSync: function() {
- var b = this,
- a = b.getChart();
- if (b.syncTimer) {
- clearTimeout(b.syncTimer);
- b.syncTimer = null
- }
- if (b.stopAnimationBeforeSync) {
- a.animationSuspendCount++
- }
- a.redraw();
- if (b.stopAnimationBeforeSync) {
- a.animationSuspendCount--
- }
- b.syncThrottle = Date.now() + b.throttleGap
- },
- sync: function() {
- var a = this;
- if (a.throttleGap && Ext.frameStartTime < a.syncThrottle) {
- if (a.syncTimer) {
- return
- }
- a.syncTimer = Ext.defer(function() {
- a.doSync()
- }, a.throttleGap)
- } else {
- a.doSync()
- }
- },
- getItemId: function() {
- return this.getId()
- },
- isXType: function(a) {
- return a === "interaction"
- },
- destroy: function() {
- var a = this;
- a.setChart(null);
- delete a.listeners;
- a.callParent()
- }
-}, function() {
- if (Ext.os.is.Android4) {
- this.prototype.throttleGap = 40
- }
-});
-Ext.define("Ext.chart.MarkerHolder", {
- extend: "Ext.Mixin",
- mixinConfig: {
- id: "markerHolder",
- after: {
- constructor: "constructor",
- preRender: "preRender"
- },
- before: {
- destroy: "destroy"
- }
- },
- isMarkerHolder: true,
- surfaceMatrix: null,
- inverseSurfaceMatrix: null,
- deprecated: {
- 6: {
- methods: {
- getBoundMarker: {
- message: "Please use the 'getMarker' method instead.",
- fn: function(b) {
- var a = this.boundMarkers[b];
- return a ? [a] : a
- }
- }
- }
- }
- },
- constructor: function() {
- this.boundMarkers = {};
- this.cleanRedraw = false
- },
- bindMarker: function(b, a) {
- var c = this,
- d = c.boundMarkers;
- if (a && a.isMarkers) {
- c.releaseMarker(b);
- d[b] = a;
- a.on("destroy", c.onMarkerDestroy, c)
- }
- },
- onMarkerDestroy: function(a) {
- this.releaseMarker(a)
- },
- releaseMarker: function(a) {
- var c = this.boundMarkers,
- b;
- if (a && a.isMarkers) {
- for (b in c) {
- if (c[b] === a) {
- delete c[b];
- break
- }
- }
- } else {
- b = a;
- a = c[b];
- delete c[b]
- }
- return a || null
- },
- getMarker: function(a) {
- return this.boundMarkers[a] || null
- },
- preRender: function() {
- var f = this,
- g = f.getId(),
- d = f.boundMarkers,
- e = f.getParent(),
- c, a, b;
- if (f.surfaceMatrix) {
- b = f.surfaceMatrix.set(1, 0, 0, 1, 0, 0)
- } else {
- b = f.surfaceMatrix = new Ext.draw.Matrix()
- }
- f.cleanRedraw = !f.attr.dirty;
- if (!f.cleanRedraw) {
- for (c in d) {
- a = d[c];
- if (a) {
- a.clear(g)
- }
- }
- }
- while (e && e.attr && e.attr.matrix) {
- b.prependMatrix(e.attr.matrix);
- e = e.getParent()
- }
- b.prependMatrix(e.matrix);
- f.surfaceMatrix = b;
- f.inverseSurfaceMatrix = b.inverse(f.inverseSurfaceMatrix)
- },
- putMarker: function(d, a, c, g, e) {
- var b = this.boundMarkers[d],
- f = this.getId();
- if (b) {
- b.putMarkerFor(f, a, c, g, e)
- }
- },
- getMarkerBBox: function(c, b, d) {
- var a = this.boundMarkers[c],
- e = this.getId();
- if (a) {
- return a.getMarkerBBoxFor(e, b, d)
- }
- },
- destroy: function() {
- var c = this.boundMarkers,
- b, a;
- for (b in c) {
- a = c[b];
- a.destroy()
- }
- }
-});
-Ext.define("Ext.chart.axis.sprite.Axis", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.axis",
- type: "axis",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- requires: ["Ext.draw.sprite.Text"],
- inheritableStatics: {
- def: {
- processors: {
- grid: "bool",
- axisLine: "bool",
- minorTicks: "bool",
- minorTickSize: "number",
- majorTicks: "bool",
- majorTickSize: "number",
- length: "number",
- startGap: "number",
- endGap: "number",
- dataMin: "number",
- dataMax: "number",
- visibleMin: "number",
- visibleMax: "number",
- position: "enums(left,right,top,bottom,angular,radial,gauge)",
- minStepSize: "number",
- estStepSize: "number",
- titleOffset: "number",
- textPadding: "number",
- min: "number",
- max: "number",
- centerX: "number",
- centerY: "number",
- radius: "number",
- totalAngle: "number",
- baseRotation: "number",
- data: "default",
- enlargeEstStepSizeByText: "bool"
- },
- defaults: {
- grid: false,
- axisLine: true,
- minorTicks: false,
- minorTickSize: 3,
- majorTicks: true,
- majorTickSize: 5,
- length: 0,
- startGap: 0,
- endGap: 0,
- visibleMin: 0,
- visibleMax: 1,
- dataMin: 0,
- dataMax: 1,
- position: "",
- minStepSize: 0,
- estStepSize: 20,
- min: 0,
- max: 1,
- centerX: 0,
- centerY: 0,
- radius: 1,
- baseRotation: 0,
- data: null,
- titleOffset: 0,
- textPadding: 0,
- scalingCenterY: 0,
- scalingCenterX: 0,
- strokeStyle: "black",
- enlargeEstStepSizeByText: false
- },
- triggers: {
- minorTickSize: "bbox",
- majorTickSize: "bbox",
- position: "bbox,layout",
- axisLine: "bbox,layout",
- min: "layout",
- max: "layout",
- length: "layout",
- minStepSize: "layout",
- estStepSize: "layout",
- data: "layout",
- dataMin: "layout",
- dataMax: "layout",
- visibleMin: "layout",
- visibleMax: "layout",
- enlargeEstStepSizeByText: "layout"
- },
- updaters: {
- layout: "layoutUpdater"
- }
- }
- },
- config: {
- label: null,
- layout: null,
- segmenter: null,
- renderer: null,
- layoutContext: null,
- axis: null
- },
- thickness: 0,
- stepSize: 0,
- getBBox: function() {
- return null
- },
- defaultRenderer: function(a) {
- return this.segmenter.renderer(a, this)
- },
- layoutUpdater: function() {
- var h = this,
- f = h.getAxis().getChart();
- if (f.isInitializing) {
- return
- }
- var e = h.attr,
- d = h.getLayout(),
- g = f.getInherited().rtl,
- b = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMin,
- i = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMax,
- c = e.position,
- a = {
- attr: e,
- segmenter: h.getSegmenter(),
- renderer: h.defaultRenderer
- };
- if (c === "left" || c === "right") {
- e.translationX = 0;
- e.translationY = i * e.length / (i - b);
- e.scalingX = 1;
- e.scalingY = -e.length / (i - b);
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- } else {
- if (c === "top" || c === "bottom") {
- if (g) {
- e.translationX = e.length + b * e.length / (i - b) + 1
- } else {
- e.translationX = -b * e.length / (i - b)
- }
- e.translationY = 0;
- e.scalingX = (g ? -1 : 1) * e.length / (i - b);
- e.scalingY = 1;
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- }
- }
- if (d) {
- d.calculateLayout(a);
- h.setLayoutContext(a)
- }
- },
- iterate: function(e, j) {
- var c, g, a, b, h, d, k = Ext.Array.some,
- m = Math.abs,
- f;
- if (e.getLabel) {
- if (e.min < e.from) {
- j.call(this, e.min, e.getLabel(e.min), -1, e)
- }
- for (c = 0; c <= e.steps; c++) {
- j.call(this, e.get(c), e.getLabel(c), c, e)
- }
- if (e.max > e.to) {
- j.call(this, e.max, e.getLabel(e.max), e.steps + 1, e)
- }
- } else {
- b = this.getAxis();
- h = b.floatingAxes;
- d = [];
- f = (e.to - e.from) / (e.steps + 1);
- if (b.getFloating()) {
- for (a in h) {
- d.push(h[a])
- }
- }
-
- function l(i) {
- return !d.length || k(d, function(n) {
- return m(n - i) > f
- })
- }
- if (e.min < e.from && l(e.min)) {
- j.call(this, e.min, e.min, -1, e)
- }
- for (c = 0; c <= e.steps; c++) {
- g = e.get(c);
- if (l(g)) {
- j.call(this, g, g, c, e)
- }
- }
- if (e.max > e.to && l(e.max)) {
- j.call(this, e.max, e.max, e.steps + 1, e)
- }
- }
- },
- renderTicks: function(l, m, s, p) {
- var v = this,
- k = v.attr,
- u = k.position,
- n = k.matrix,
- e = 0.5 * k.lineWidth,
- f = n.getXX(),
- i = n.getDX(),
- j = n.getYY(),
- h = n.getDY(),
- o = s.majorTicks,
- d = k.majorTickSize,
- a = s.minorTicks,
- r = k.minorTickSize;
- if (o) {
- switch (u) {
- case "right":
- function q(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * j + h) + e;
- m.moveTo(0, x);
- m.lineTo(w, x)
- }
- }
- v.iterate(o, q(d));
- a && v.iterate(a, q(r));
- break;
- case "left":
- function t(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * j + h) + e;
- m.moveTo(p[2] - w, x);
- m.lineTo(p[2], x)
- }
- }
- v.iterate(o, t(d));
- a && v.iterate(a, t(r));
- break;
- case "bottom":
- function c(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * f + i) - e;
- m.moveTo(x, 0);
- m.lineTo(x, w)
- }
- }
- v.iterate(o, c(d));
- a && v.iterate(a, c(r));
- break;
- case "top":
- function b(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * f + i) - e;
- m.moveTo(x, p[3]);
- m.lineTo(x, p[3] - w)
- }
- }
- v.iterate(o, b(d));
- a && v.iterate(a, b(r));
- break;
- case "angular":
- v.iterate(o, function(w, y, x) {
- w = w / (k.max + 1) * Math.PI * 2 + k.baseRotation;
- m.moveTo(k.centerX + (k.length) * Math.cos(w), k.centerY + (k.length) * Math.sin(w));
- m.lineTo(k.centerX + (k.length + d) * Math.cos(w), k.centerY + (k.length + d) * Math.sin(w))
- });
- break;
- case "gauge":
- var g = v.getGaugeAngles();
- v.iterate(o, function(w, y, x) {
- w = (w - k.min) / (k.max - k.min + 1) * k.totalAngle - k.totalAngle + g.start;
- m.moveTo(k.centerX + (k.length) * Math.cos(w), k.centerY + (k.length) * Math.sin(w));
- m.lineTo(k.centerX + (k.length + d) * Math.cos(w), k.centerY + (k.length + d) * Math.sin(w))
- });
- break
- }
- }
- },
- renderLabels: function(E, q, D, K) {
- var o = this,
- k = o.attr,
- i = 0.5 * k.lineWidth,
- u = k.position,
- y = k.matrix,
- A = k.textPadding,
- x = y.getXX(),
- d = y.getDX(),
- g = y.getYY(),
- c = y.getDY(),
- n = 0,
- I = D.majorTicks,
- G = Math.max(k.majorTickSize, k.minorTickSize) + k.lineWidth,
- f = Ext.draw.Draw.isBBoxIntersect,
- F = o.getLabel(),
- J, s, r = null,
- w = 0,
- b = 0,
- m = D.segmenter,
- B = o.getRenderer(),
- t = o.getAxis(),
- z = t.getTitle(),
- a = z && z.attr.text !== "" && z.getBBox(),
- l, h = null,
- p, C, v, e, H;
- if (I && F && !F.attr.hidden) {
- J = F.attr.font;
- if (q.font !== J) {
- q.font = J
- }
- F.setAttributes({
- translationX: 0,
- translationY: 0
- }, true);
- F.applyTransformations();
- l = F.attr.inverseMatrix.elements.slice(0);
- switch (u) {
- case "left":
- e = a ? a.x + a.width : 0;
- switch (F.attr.textAlign) {
- case "start":
- H = E.roundPixel(e + d) - i;
- break;
- case "end":
- H = E.roundPixel(K[2] - G + d) - i;
- break;
- default:
- H = E.roundPixel(e + (K[2] - e - G) / 2 + d) - i
- }
- F.setAttributes({
- translationX: H
- }, true);
- break;
- case "right":
- e = a ? K[2] - a.x : 0;
- switch (F.attr.textAlign) {
- case "start":
- H = E.roundPixel(G + d) + i;
- break;
- case "end":
- H = E.roundPixel(K[2] - e + d) + i;
- break;
- default:
- H = E.roundPixel(G + (K[2] - G - e) / 2 + d) + i
- }
- F.setAttributes({
- translationX: H
- }, true);
- break;
- case "top":
- e = a ? a.y + a.height : 0;
- F.setAttributes({
- translationY: E.roundPixel(e + (K[3] - e - G) / 2) - i
- }, true);
- break;
- case "bottom":
- e = a ? K[3] - a.y : 0;
- F.setAttributes({
- translationY: E.roundPixel(G + (K[3] - G - e) / 2) + i
- }, true);
- break;
- case "radial":
- F.setAttributes({
- translationX: k.centerX
- }, true);
- break;
- case "angular":
- F.setAttributes({
- translationY: k.centerY
- }, true);
- break;
- case "gauge":
- F.setAttributes({
- translationY: k.centerY
- }, true);
- break
- }
- if (u === "left" || u === "right") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- F.setAttributes({
- text: String(v),
- translationY: E.roundPixel(L * g + c)
- }, true);
- F.applyTransformations();
- n = Math.max(n, F.getBBox().width + G);
- if (n <= o.thickness) {
- C = Ext.draw.Matrix.fly(F.attr.matrix.elements.slice(0));
- p = C.prepend.apply(C, l).transformBBox(F.getBBox(true));
- if (h && !f(p, h, A)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.height;
- b++
- }
- })
- } else {
- if (u === "top" || u === "bottom") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- F.setAttributes({
- text: String(v),
- translationX: E.roundPixel(L * x + d)
- }, true);
- F.applyTransformations();
- n = Math.max(n, F.getBBox().height + G);
- if (n <= o.thickness) {
- C = Ext.draw.Matrix.fly(F.attr.matrix.elements.slice(0));
- p = C.prepend.apply(C, l).transformBBox(F.getBBox(true));
- if (h && !f(p, h, A)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "radial") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- if (typeof v !== "undefined") {
- F.setAttributes({
- text: String(v),
- translationX: k.centerX - E.roundPixel(L) / k.max * k.length * Math.cos(k.baseRotation + Math.PI / 2),
- translationY: k.centerY - E.roundPixel(L) / k.max * k.length * Math.sin(k.baseRotation + Math.PI / 2)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "angular") {
- s = k.majorTickSize + k.lineWidth * 0.5 + (parseInt(F.attr.fontSize, 10) || 10) / 2;
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- n = Math.max(n, Math.max(k.majorTickSize, k.minorTickSize) + (k.lineCap !== "butt" ? k.lineWidth * 0.5 : 0));
- if (typeof v !== "undefined") {
- var O = L / (k.max + 1) * Math.PI * 2 + k.baseRotation;
- F.setAttributes({
- text: String(v),
- translationX: k.centerX + (k.length + s) * Math.cos(O),
- translationY: k.centerY + (k.length + s) * Math.sin(O)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "gauge") {
- var j = o.getGaugeAngles();
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- if (typeof v !== "undefined") {
- var O = (L - k.min) / (k.max - k.min + 1) * k.totalAngle - k.totalAngle + j.start;
- F.setAttributes({
- text: String(v),
- translationX: k.centerX + (k.length + 10) * Math.cos(O),
- translationY: k.centerY + (k.length + 10) * Math.sin(O)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- }
- }
- }
- }
- }
- if (k.enlargeEstStepSizeByText && b) {
- w /= b;
- w += G;
- w *= 2;
- if (k.estStepSize < w) {
- k.estStepSize = w
- }
- }
- if (Math.abs(o.thickness - (n)) > 1) {
- o.thickness = n;
- k.bbox.plain.dirty = true;
- k.bbox.transform.dirty = true;
- o.doThicknessChanged();
- return false
- }
- }
- },
- renderAxisLine: function(a, i, e, c) {
- var h = this,
- g = h.attr,
- b = g.lineWidth * 0.5,
- j = g.position,
- d, f;
- if (g.axisLine && g.length) {
- switch (j) {
- case "left":
- d = a.roundPixel(c[2]) - b;
- i.moveTo(d, -g.endGap);
- i.lineTo(d, g.length + g.startGap + 1);
- break;
- case "right":
- i.moveTo(b, -g.endGap);
- i.lineTo(b, g.length + g.startGap + 1);
- break;
- case "bottom":
- i.moveTo(-g.startGap, b);
- i.lineTo(g.length + g.endGap, b);
- break;
- case "top":
- d = a.roundPixel(c[3]) - b;
- i.moveTo(-g.startGap, d);
- i.lineTo(g.length + g.endGap, d);
- break;
- case "angular":
- i.moveTo(g.centerX + g.length, g.centerY);
- i.arc(g.centerX, g.centerY, g.length, 0, Math.PI * 2, true);
- break;
- case "gauge":
- f = h.getGaugeAngles();
- i.moveTo(g.centerX + Math.cos(f.start) * g.length, g.centerY + Math.sin(f.start) * g.length);
- i.arc(g.centerX, g.centerY, g.length, f.start, f.end, true);
- break
- }
- }
- },
- getGaugeAngles: function() {
- var a = this,
- c = a.attr.totalAngle,
- b;
- if (c <= Math.PI) {
- b = (Math.PI - c) * 0.5
- } else {
- b = -(Math.PI * 2 - c) * 0.5
- }
- b = Math.PI * 2 - b;
- return {
- start: b,
- end: b - c
- }
- },
- renderGridLines: function(m, n, s, r) {
- var t = this,
- b = t.getAxis(),
- l = t.attr,
- p = l.matrix,
- d = l.startGap,
- a = l.endGap,
- c = p.getXX(),
- k = p.getYY(),
- h = p.getDX(),
- g = p.getDY(),
- u = l.position,
- f = b.getGridAlignment(),
- q = s.majorTicks,
- e, o, i;
- if (l.grid) {
- if (q) {
- if (u === "left" || u === "right") {
- i = l.min * k + g + a + d;
- t.iterate(q, function(j, w, v) {
- e = j * k + g + a;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- y: e,
- height: i - e
- }, o = v, true);
- i = e
- });
- o++;
- e = 0;
- t.putMarker(f + "-" + (o % 2 ? "odd" : "even"), {
- y: e,
- height: i - e
- }, o, true)
- } else {
- if (u === "top" || u === "bottom") {
- i = l.min * c + h + d;
- if (d) {
- t.putMarker(f + "-even", {
- x: 0,
- width: i
- }, -1, true)
- }
- t.iterate(q, function(j, w, v) {
- e = j * c + h + d;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- x: e,
- width: i - e
- }, o = v, true);
- i = e
- });
- o++;
- e = l.length + l.startGap + l.endGap;
- t.putMarker(f + "-" + (o % 2 ? "odd" : "even"), {
- x: e,
- width: i - e
- }, o, true)
- } else {
- if (u === "radial") {
- t.iterate(q, function(j, w, v) {
- if (!j) {
- return
- }
- e = j / l.max * l.length;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- scalingX: e,
- scalingY: e
- }, v, true);
- i = e
- })
- } else {
- if (u === "angular") {
- t.iterate(q, function(j, w, v) {
- if (!l.length) {
- return
- }
- e = j / (l.max + 1) * Math.PI * 2 + l.baseRotation;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- rotationRads: e,
- rotationCenterX: 0,
- rotationCenterY: 0,
- scalingX: l.length,
- scalingY: l.length
- }, v, true);
- i = e
- })
- }
- }
- }
- }
- }
- }
- },
- renderLimits: function(o) {
- var t = this,
- a = t.getAxis(),
- h = a.getChart(),
- p = h.getInnerPadding(),
- d = Ext.Array.from(a.getLimits());
- if (!d.length) {
- return
- }
- var r = a.limits.surface.getRect(),
- m = t.attr,
- n = m.matrix,
- u = m.position,
- k = Ext.Object.chain,
- v = a.limits.titles,
- c, j, b, s, l, q, f, g, e;
- v.instances = [];
- v.position = 0;
- if (u === "left" || u === "right") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l * n.getYY() + n.getDY();
- s.line.y = l + p.top;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("horizontal-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- j = s.line.title.position || (u === "left" ? "start" : "end");
- switch (j) {
- case "start":
- g = 10;
- break;
- case "end":
- g = r[2] - 10;
- break;
- case "middle":
- g = r[2] / 2;
- break
- }
- v.setAttributesFor(v.position - 1, {
- x: g,
- y: s.line.y - c.height / 2,
- textAlign: j,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "top" || u === "bottom") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l * n.getXX() + n.getDX();
- s.line.x = l + p.left;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("vertical-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- j = s.line.title.position || (u === "top" ? "end" : "start");
- switch (j) {
- case "start":
- e = r[3] - c.width / 2 - 10;
- break;
- case "end":
- e = c.width / 2 + 10;
- break;
- case "middle":
- e = r[3] / 2;
- break
- }
- v.setAttributesFor(v.position - 1, {
- x: s.line.x + c.height / 2,
- y: e,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle,
- rotationRads: Math.PI / 2
- })
- }
- }
- } else {
- if (u === "radial") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- if (l > m.max) {
- continue
- }
- l = l / m.max * m.length;
- s.line.cx = m.centerX;
- s.line.cy = m.centerY;
- s.line.scalingX = l;
- s.line.scalingY = l;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("circular-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- v.setAttributesFor(v.position - 1, {
- x: m.centerX,
- y: m.centerY - l - c.height / 2,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "angular") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l / (m.max + 1) * Math.PI * 2 + m.baseRotation;
- s.line.translationX = m.centerX;
- s.line.translationY = m.centerY;
- s.line.rotationRads = l;
- s.line.rotationCenterX = 0;
- s.line.rotationCenterY = 0;
- s.line.scalingX = m.length;
- s.line.scalingY = m.length;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("radial-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- b = ((l > -0.5 * Math.PI && l < 0.5 * Math.PI) || (l > 1.5 * Math.PI && l < 2 * Math.PI)) ? 1 : -1;
- v.setAttributesFor(v.position - 1, {
- x: m.centerX + 0.5 * m.length * Math.cos(l) + b * c.height / 2 * Math.sin(l),
- y: m.centerY + 0.5 * m.length * Math.sin(l) - b * c.height / 2 * Math.cos(l),
- rotationRads: b === 1 ? l : l - Math.PI,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "gauge") {}
- }
- }
- }
- }
- },
- doThicknessChanged: function() {
- var a = this.getAxis();
- if (a) {
- a.onThicknessChanged()
- }
- },
- render: function(a, c, d) {
- var e = this,
- b = e.getLayoutContext();
- if (b) {
- if (false === e.renderLabels(a, c, b, d)) {
- return false
- }
- c.beginPath();
- e.renderTicks(a, c, b, d);
- e.renderAxisLine(a, c, b, d);
- e.renderGridLines(a, c, b, d);
- e.renderLimits(d);
- c.stroke()
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Segmenter", {
- config: {
- axis: null
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- renderer: function(b, a) {
- return String(b)
- },
- from: function(a) {
- return a
- },
- diff: Ext.emptyFn,
- align: Ext.emptyFn,
- add: Ext.emptyFn,
- preferredStep: Ext.emptyFn
-});
-Ext.define("Ext.chart.axis.segmenter.Names", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.names",
- renderer: function(b, a) {
- return b
- },
- diff: function(b, a, c) {
- return Math.floor(a - b)
- },
- align: function(c, b, a) {
- return Math.floor(c)
- },
- add: function(c, b, a) {
- return c + b
- },
- preferredStep: function(c, a, b, d) {
- return {
- unit: 1,
- step: 1
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Numeric", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.numeric",
- isNumeric: true,
- renderer: function(b, a) {
- return b.toFixed(Math.max(0, a.majorTicks.unit.fixes))
- },
- diff: function(b, a, c) {
- return Math.floor((a - b) / c.scale)
- },
- align: function(c, b, a) {
- return Math.floor(c / (a.scale * b)) * a.scale * b
- },
- add: function(c, b, a) {
- return c + b * a.scale
- },
- preferredStep: function(c, b) {
- var a = Math.floor(Math.log(b) * Math.LOG10E),
- d = Math.pow(10, a);
- b /= d;
- if (b < 2) {
- b = 2
- } else {
- if (b < 5) {
- b = 5
- } else {
- if (b < 10) {
- b = 10;
- a++
- }
- }
- }
- return {
- unit: {
- fixes: -a,
- scale: d
- },
- step: b
- }
- },
- exactStep: function(c, b) {
- var a = Math.floor(Math.log(b) * Math.LOG10E),
- d = Math.pow(10, a);
- return {
- unit: {
- fixes: -a + (b % d === 0 ? 0 : 1),
- scale: 1
- },
- step: b
- }
- },
- adjustByMajorUnit: function(e, g, c) {
- var d = c[0],
- b = c[1],
- a = e * g,
- f = d % a;
- if (f !== 0) {
- c[0] = d - f + (d < 0 ? -a : 0)
- }
- f = b % a;
- if (f !== 0) {
- c[1] = b - f + (b > 0 ? a : 0)
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Time", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.time",
- config: {
- step: null
- },
- renderer: function(c, b) {
- var a = Ext.Date;
- switch (b.majorTicks.unit) {
- case "y":
- return a.format(c, "Y");
- case "mo":
- return a.format(c, "Y-m");
- case "d":
- return a.format(c, "Y-m-d")
- }
- return a.format(c, "Y-m-d\nH:i:s")
- },
- from: function(a) {
- return new Date(a)
- },
- diff: function(b, a, c) {
- if (isFinite(b)) {
- b = new Date(b)
- }
- if (isFinite(a)) {
- a = new Date(a)
- }
- return Ext.Date.diff(b, a, c)
- },
- align: function(a, c, b) {
- if (b === "d" && c >= 7) {
- a = Ext.Date.align(a, "d", c);
- a.setDate(a.getDate() - a.getDay() + 1);
- return a
- } else {
- return Ext.Date.align(a, b, c)
- }
- },
- add: function(c, b, a) {
- return Ext.Date.add(new Date(c), a, b)
- },
- stepUnits: [
- [Ext.Date.YEAR, 1, 2, 5, 10, 20, 50, 100, 200, 500],
- [Ext.Date.MONTH, 1, 3, 6],
- [Ext.Date.DAY, 1, 7, 14],
- [Ext.Date.HOUR, 1, 6, 12],
- [Ext.Date.MINUTE, 1, 5, 15, 30],
- [Ext.Date.SECOND, 1, 5, 15, 30],
- [Ext.Date.MILLI, 1, 2, 5, 10, 20, 50, 100, 200, 500]
- ],
- preferredStep: function(b, e) {
- if (this.getStep()) {
- return this.getStep()
- }
- var f = new Date(+b),
- g = new Date(+b + Math.ceil(e)),
- d = this.stepUnits,
- l, k, h, c, a;
- for (c = 0; c < d.length; c++) {
- k = d[c][0];
- h = this.diff(f, g, k);
- if (h > 0) {
- for (a = 1; a < d[c].length; a++) {
- if (h <= d[c][a]) {
- l = {
- unit: k,
- step: d[c][a]
- };
- break
- }
- }
- if (!l) {
- c--;
- l = {
- unit: d[c][0],
- step: 1
- }
- }
- break
- }
- }
- if (!l) {
- l = {
- unit: Ext.Date.DAY,
- step: 1
- }
- }
- return l
- }
-});
-Ext.define("Ext.chart.axis.layout.Layout", {
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- axis: null
- },
- constructor: function(a) {
- this.mixins.observable.constructor.call(this, a)
- },
- processData: function(b) {
- var e = this,
- c = e.getAxis(),
- f = c.getDirection(),
- g = c.boundSeries,
- a, d;
- if (b) {
- b["coordinate" + f]()
- } else {
- for (a = 0, d = g.length; a < d; a++) {
- g[a]["coordinate" + f]()
- }
- }
- },
- calculateMajorTicks: function(a) {
- var f = this,
- e = a.attr,
- d = e.max - e.min,
- i = d / Math.max(1, e.length) * (e.visibleMax - e.visibleMin),
- h = e.min + d * e.visibleMin,
- b = e.min + d * e.visibleMax,
- g = e.estStepSize * i,
- c = f.snapEnds(a, e.min, e.max, g);
- if (c) {
- f.trimByRange(a, c, h, b);
- a.majorTicks = c
- }
- },
- calculateMinorTicks: function(a) {
- if (this.snapMinorEnds) {
- a.minorTicks = this.snapMinorEnds(a)
- }
- },
- calculateLayout: function(b) {
- var c = this,
- a = b.attr;
- if (a.length === 0) {
- return null
- }
- if (a.majorTicks) {
- c.calculateMajorTicks(b);
- if (a.minorTicks) {
- c.calculateMinorTicks(b)
- }
- }
- },
- snapEnds: Ext.emptyFn,
- trimByRange: function(b, f, i, a) {
- var g = b.segmenter,
- j = f.unit,
- h = g.diff(f.from, i, j),
- d = g.diff(f.from, a, j),
- c = Math.max(0, Math.ceil(h / f.step)),
- e = Math.min(f.steps, Math.floor(d / f.step));
- if (e < f.steps) {
- f.to = g.add(f.from, e * f.step, j)
- }
- if (f.max > a) {
- f.max = f.to
- }
- if (f.from < i) {
- f.from = g.add(f.from, c * f.step, j);
- while (f.from < i) {
- c++;
- f.from = g.add(f.from, f.step, j)
- }
- }
- if (f.min < i) {
- f.min = f.from
- }
- f.steps = e - c
- }
-});
-Ext.define("Ext.chart.axis.layout.Discrete", {
- extend: "Ext.chart.axis.layout.Layout",
- alias: "axisLayout.discrete",
- isDiscrete: true,
- processData: function() {
- var f = this,
- d = f.getAxis(),
- c = d.boundSeries,
- g = d.getDirection(),
- b, e, a;
- f.labels = [];
- f.labelMap = {};
- for (b = 0, e = c.length; b < e; b++) {
- a = c[b];
- if (a["get" + g + "Axis"]() === d) {
- a["coordinate" + g]()
- }
- }
- d.getSprites()[0].setAttributes({
- data: f.labels
- });
- f.fireEvent("datachange", f.labels)
- },
- calculateLayout: function(a) {
- a.data = this.labels;
- this.callParent([a])
- },
- calculateMajorTicks: function(a) {
- var g = this,
- f = a.attr,
- d = a.data,
- e = f.max - f.min,
- j = e / Math.max(1, f.length) * (f.visibleMax - f.visibleMin),
- i = f.min + e * f.visibleMin,
- b = f.min + e * f.visibleMax,
- h = f.estStepSize * j;
- var c = g.snapEnds(a, Math.max(0, f.min), Math.min(f.max, d.length - 1), h);
- if (c) {
- g.trimByRange(a, c, i, b);
- a.majorTicks = c
- }
- },
- snapEnds: function(e, d, a, b) {
- b = Math.ceil(b);
- var c = Math.floor((a - d) / b),
- f = e.data;
- return {
- min: d,
- max: a,
- from: d,
- to: c * b + d,
- step: b,
- steps: c,
- unit: 1,
- getLabel: function(g) {
- return f[this.from + this.step * g]
- },
- get: function(g) {
- return this.from + this.step * g
- }
- }
- },
- trimByRange: function(b, f, h, a) {
- var i = f.unit,
- g = Math.ceil((h - f.from) / i) * i,
- d = Math.floor((a - f.from) / i) * i,
- c = Math.max(0, Math.ceil(g / f.step)),
- e = Math.min(f.steps, Math.floor(d / f.step));
- if (e < f.steps) {
- f.to = e
- }
- if (f.max > a) {
- f.max = f.to
- }
- if (f.from < h && f.step > 0) {
- f.from = f.from + c * f.step * i;
- while (f.from < h) {
- c++;
- f.from += f.step * i
- }
- }
- if (f.min < h) {
- f.min = f.from
- }
- f.steps = e - c
- },
- getCoordFor: function(c, d, a, b) {
- this.labels.push(c);
- return this.labels.length - 1
- }
-});
-Ext.define("Ext.chart.axis.layout.CombineDuplicate", {
- extend: "Ext.chart.axis.layout.Discrete",
- alias: "axisLayout.combineDuplicate",
- getCoordFor: function(d, e, b, c) {
- if (!(d in this.labelMap)) {
- var a = this.labelMap[d] = this.labels.length;
- this.labels.push(d);
- return a
- }
- return this.labelMap[d]
- }
-});
-Ext.define("Ext.chart.axis.layout.Continuous", {
- extend: "Ext.chart.axis.layout.Layout",
- alias: "axisLayout.continuous",
- isContinuous: true,
- config: {
- adjustMinimumByMajorUnit: false,
- adjustMaximumByMajorUnit: false
- },
- getCoordFor: function(c, d, a, b) {
- return +c
- },
- snapEnds: function(a, d, i, h) {
- var f = a.segmenter,
- c = this.getAxis(),
- l = c.getMajorTickSteps(),
- e = l && f.exactStep ? f.exactStep(d, (i - d) / l) : f.preferredStep(d, h),
- k = e.unit,
- b = e.step,
- j = f.align(d, b, k),
- g = (l || f.diff(d, i, k)) + 1;
- return {
- min: f.from(d),
- max: f.from(i),
- from: j,
- to: f.add(j, g * b, k),
- step: b,
- steps: g,
- unit: k,
- get: function(m) {
- return f.add(this.from, this.step * m, k)
- }
- }
- },
- snapMinorEnds: function(a) {
- var e = a.majorTicks,
- m = this.getAxis().getMinorTickSteps(),
- f = a.segmenter,
- d = e.min,
- i = e.max,
- k = e.from,
- l = e.unit,
- b = e.step / m,
- n = b * l.scale,
- j = k - d,
- c = Math.floor(j / n),
- h = c + Math.floor((i - e.to) / n) + 1,
- g = e.steps * m + h;
- return {
- min: d,
- max: i,
- from: d + j % n,
- to: f.add(k, g * b, l),
- step: b,
- steps: g,
- unit: l,
- get: function(o) {
- return (o % m + c + 1 !== 0) ? f.add(this.from, this.step * o, l) : null
- }
- }
- }
-});
-Ext.define("Ext.chart.axis.Axis", {
- xtype: "axis",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- requires: ["Ext.chart.axis.sprite.Axis", "Ext.chart.axis.segmenter.*", "Ext.chart.axis.layout.*"],
- isAxis: true,
- config: {
- position: "bottom",
- fields: [],
- label: undefined,
- grid: false,
- limits: null,
- renderer: null,
- chart: null,
- style: null,
- margin: 0,
- titleMargin: 4,
- background: null,
- minimum: NaN,
- maximum: NaN,
- reconcileRange: false,
- minZoom: 1,
- maxZoom: 10000,
- layout: "continuous",
- segmenter: "numeric",
- hidden: false,
- majorTickSteps: 0,
- minorTickSteps: 0,
- adjustByMajorUnit: true,
- title: null,
- increment: 0.5,
- length: 0,
- center: null,
- radius: null,
- totalAngle: Math.PI,
- rotation: null,
- labelInSpan: null,
- visibleRange: [0, 1],
- needHighPrecision: false,
- linkedTo: null,
- floating: null
- },
- titleOffset: 0,
- spriteAnimationCount: 0,
- prevMin: 0,
- prevMax: 1,
- boundSeries: [],
- sprites: null,
- surface: null,
- range: null,
- xValues: [],
- yValues: [],
- masterAxis: null,
- applyRotation: function(b) {
- var a = Math.PI * 2;
- return (b % a + Math.PI) % a - Math.PI
- },
- updateRotation: function(b) {
- var c = this.getSprites(),
- a = this.getPosition();
- if (!this.getHidden() && a === "angular" && c[0]) {
- c[0].setAttributes({
- baseRotation: b
- })
- }
- },
- applyTitle: function(c, b) {
- var a;
- if (Ext.isString(c)) {
- c = {
- text: c
- }
- }
- if (!b) {
- b = Ext.create("sprite.text", c);
- if ((a = this.getSurface())) {
- a.add(b)
- }
- } else {
- b.setAttributes(c)
- }
- return b
- },
- applyFloating: function(b, a) {
- if (b === null) {
- b = {
- value: null,
- alongAxis: null
- }
- } else {
- if (Ext.isNumber(b)) {
- b = {
- value: b,
- alongAxis: null
- }
- }
- }
- if (Ext.isObject(b)) {
- if (a && a.alongAxis) {
- delete this.getChart().getAxis(a.alongAxis).floatingAxes[this.getId()]
- }
- return b
- }
- return a
- },
- constructor: function(a) {
- var b = this,
- c;
- b.sprites = [];
- b.labels = [];
- b.floatingAxes = {};
- a = a || {};
- if (a.position === "angular") {
- a.style = a.style || {};
- a.style.estStepSize = 1
- }
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.mixins.observable.constructor.apply(b, arguments)
- },
- getAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "vertical";
- case "top":
- case "bottom":
- return "horizontal";
- case "radial":
- return "radial";
- case "angular":
- return "angular"
- }
- },
- getGridAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "horizontal";
- case "top":
- case "bottom":
- return "vertical";
- case "radial":
- return "circular";
- case "angular":
- return "radial"
- }
- },
- getSurface: function() {
- var e = this,
- d = e.getChart();
- if (d && !e.surface) {
- var b = e.surface = d.getSurface(e.getId(), "axis"),
- c = e.gridSurface = d.getSurface("main"),
- a = e.getSprites()[0],
- f = e.getGridAlignment();
- c.waitFor(b);
- e.getGrid();
- if (e.getLimits() && f) {
- f = f.replace("3d", "");
- e.limits = {
- surface: d.getSurface("overlay"),
- lines: new Ext.chart.Markers(),
- titles: new Ext.draw.sprite.Instancing()
- };
- e.limits.lines.setTemplate({
- xclass: "grid." + f
- });
- e.limits.lines.getTemplate().setAttributes({
- strokeStyle: "black"
- }, true);
- e.limits.surface.add(e.limits.lines);
- a.bindMarker(f + "-limit-lines", e.limits.lines);
- e.limitTitleTpl = new Ext.draw.sprite.Text();
- e.limits.titles.setTemplate(e.limitTitleTpl);
- e.limits.surface.add(e.limits.titles);
- d.on("redraw", e.renderLimits, e)
- }
- }
- return e.surface
- },
- applyGrid: function(a) {
- if (a === true) {
- return {}
- }
- return a
- },
- updateGrid: function(b) {
- var e = this,
- d = e.getChart();
- if (!d) {
- e.on({
- chartattached: Ext.bind(e.updateGrid, e, [b]),
- single: true
- });
- return
- }
- var c = e.gridSurface,
- a = e.getSprites()[0],
- f = e.getGridAlignment(),
- g;
- if (b) {
- g = e.gridSpriteEven;
- if (!g) {
- g = e.gridSpriteEven = new Ext.chart.Markers();
- g.setTemplate({
- xclass: "grid." + f
- });
- c.add(g);
- a.bindMarker(f + "-even", g)
- }
- if (Ext.isObject(b)) {
- g.getTemplate().setAttributes(b);
- if (Ext.isObject(b.even)) {
- g.getTemplate().setAttributes(b.even)
- }
- }
- g = e.gridSpriteOdd;
- if (!g) {
- g = e.gridSpriteOdd = new Ext.chart.Markers();
- g.setTemplate({
- xclass: "grid." + f
- });
- c.add(g);
- a.bindMarker(f + "-odd", g)
- }
- if (Ext.isObject(b)) {
- g.getTemplate().setAttributes(b);
- if (Ext.isObject(b.odd)) {
- g.getTemplate().setAttributes(b.odd)
- }
- }
- }
- },
- renderLimits: function() {
- this.getSprites()[0].renderLimits()
- },
- getCoordFor: function(c, d, a, b) {
- return this.getLayout().getCoordFor(c, d, a, b)
- },
- applyPosition: function(a) {
- return a.toLowerCase()
- },
- applyLength: function(b, a) {
- return b > 0 ? b : a
- },
- applyLabel: function(b, a) {
- if (!a) {
- a = new Ext.draw.sprite.Text({})
- }
- if (this.limitTitleTpl) {
- this.limitTitleTpl.setAttributes(b)
- }
- a.setAttributes(b);
- return a
- },
- applyLayout: function(b, a) {
- b = Ext.factory(b, null, a, "axisLayout");
- b.setAxis(this);
- return b
- },
- applySegmenter: function(a, b) {
- a = Ext.factory(a, null, b, "segmenter");
- a.setAxis(this);
- return a
- },
- updateMinimum: function() {
- this.range = null
- },
- updateMaximum: function() {
- this.range = null
- },
- hideLabels: function() {
- this.getSprites()[0].setDirty(true);
- this.setLabel({
- hidden: true
- })
- },
- showLabels: function() {
- this.getSprites()[0].setDirty(true);
- this.setLabel({
- hidden: false
- })
- },
- renderFrame: function() {
- this.getSurface().renderFrame()
- },
- updateChart: function(d, b) {
- var c = this,
- a;
- if (b) {
- b.unregister(c);
- b.un("serieschange", c.onSeriesChange, c);
- b.un("redraw", c.renderLimits, c);
- c.linkAxis();
- c.fireEvent("chartdetached", b, c)
- }
- if (d) {
- d.on("serieschange", c.onSeriesChange, c);
- c.surface = null;
- a = c.getSurface();
- c.getLabel().setSurface(a);
- a.add(c.getSprites());
- a.add(c.getTitle());
- d.register(c);
- c.fireEvent("chartattached", d, c)
- }
- },
- applyBackground: function(a) {
- var b = Ext.ClassManager.getByAlias("sprite.rect");
- return b.def.normalize(a)
- },
- processData: function() {
- this.getLayout().processData();
- this.range = null
- },
- getDirection: function() {
- return this.getChart().getDirectionForAxis(this.getPosition())
- },
- isSide: function() {
- var a = this.getPosition();
- return a === "left" || a === "right"
- },
- applyFields: function(a) {
- return Ext.Array.from(a)
- },
- applyVisibleRange: function(a, c) {
- this.getChart();
- if (a[0] > a[1]) {
- var b = a[0];
- a[0] = a[1];
- a[0] = b
- }
- if (a[1] === a[0]) {
- a[1] += 1 / this.getMaxZoom()
- }
- if (a[1] > a[0] + 1) {
- a[0] = 0;
- a[1] = 1
- } else {
- if (a[0] < 0) {
- a[1] -= a[0];
- a[0] = 0
- } else {
- if (a[1] > 1) {
- a[0] -= a[1] - 1;
- a[1] = 1
- }
- }
- }
- if (c && a[0] === c[0] && a[1] === c[1]) {
- return undefined
- }
- return a
- },
- updateVisibleRange: function(a) {
- this.fireEvent("visiblerangechange", this, a)
- },
- onSeriesChange: function(e) {
- var f = this,
- b = e.getSeries(),
- j = "get" + f.getDirection() + "Axis",
- g = [],
- c, d = b.length,
- a, h;
- for (c = 0; c < d; c++) {
- if (this === b[c][j]()) {
- g.push(b[c])
- }
- }
- f.boundSeries = g;
- a = f.getLinkedTo();
- h = !Ext.isEmpty(a) && e.getAxis(a);
- if (h) {
- f.linkAxis(h)
- } else {
- f.getLayout().processData()
- }
- },
- linkAxis: function(a) {
- var c = this;
-
- function b(f, d, e) {
- e.getLayout()[f]("datachange", "onDataChange", d);
- e[f]("rangechange", "onMasterAxisRangeChange", d)
- }
- if (c.masterAxis) {
- b("un", c, c.masterAxis);
- c.masterAxis = null
- }
- if (a) {
- if (a.type !== this.type) {
- Ext.Error.raise("Linked axes must be of the same type.")
- }
- b("on", c, a);
- c.onDataChange(a.getLayout().labels);
- c.onMasterAxisRangeChange(a, a.range);
- c.setStyle(Ext.apply({}, c.config.style, a.config.style));
- c.setTitle(Ext.apply({}, c.config.title, a.config.title));
- c.setLabel(Ext.apply({}, c.config.label, a.config.label));
- c.masterAxis = a
- }
- },
- onDataChange: function(a) {
- this.getLayout().labels = a
- },
- onMasterAxisRangeChange: function(b, a) {
- this.range = a
- },
- applyRange: function(a) {
- if (!a) {
- return this.dataRange.slice(0)
- } else {
- return [a[0] === null ? this.dataRange[0] : a[0], a[1] === null ? this.dataRange[1] : a[1]]
- }
- },
- getRange: function() {
- var m = this;
- if (m.range) {
- return m.range
- } else {
- if (m.masterAxis) {
- return m.masterAxis.range
- }
- }
- if (Ext.isNumber(m.getMinimum() + m.getMaximum())) {
- return m.range = [m.getMinimum(), m.getMaximum()]
- }
- var d = Infinity,
- n = -Infinity,
- o = m.boundSeries,
- h = m.getLayout(),
- l = m.getSegmenter(),
- p = m.getVisibleRange(),
- b = "get" + m.getDirection() + "Range",
- a, j, g, f, e, k;
- for (e = 0, k = o.length; e < k; e++) {
- f = o[e];
- var c = f[b]();
- if (c) {
- if (c[0] < d) {
- d = c[0]
- }
- if (c[1] > n) {
- n = c[1]
- }
- }
- }
- if (!isFinite(n)) {
- n = m.prevMax
- }
- if (!isFinite(d)) {
- d = m.prevMin
- }
- if (m.getLabelInSpan() || d === n) {
- n += m.getIncrement();
- d -= m.getIncrement()
- }
- if (Ext.isNumber(m.getMinimum())) {
- d = m.getMinimum()
- } else {
- m.prevMin = d
- }
- if (Ext.isNumber(m.getMaximum())) {
- n = m.getMaximum()
- } else {
- m.prevMax = n
- }
- m.range = [Ext.Number.correctFloat(d), Ext.Number.correctFloat(n)];
- if (m.getReconcileRange()) {
- m.reconcileRange()
- }
- if (m.getAdjustByMajorUnit() && l.adjustByMajorUnit && !m.getMajorTickSteps()) {
- j = Ext.Object.chain(m.getSprites()[0].attr);
- j.min = m.range[0];
- j.max = m.range[1];
- j.visibleMin = p[0];
- j.visibleMax = p[1];
- a = {
- attr: j,
- segmenter: l
- };
- h.calculateLayout(a);
- g = a.majorTicks;
- if (g) {
- l.adjustByMajorUnit(g.step, g.unit.scale, m.range);
- j.min = m.range[0];
- j.max = m.range[1];
- delete a.majorTicks;
- h.calculateLayout(a);
- g = a.majorTicks;
- l.adjustByMajorUnit(g.step, g.unit.scale, m.range)
- } else {
- if (!m.hasClearRangePending) {
- m.hasClearRangePending = true;
- m.getChart().on("layout", "clearRange", m)
- }
- }
- }
- if (!Ext.Array.equals(m.range, m.oldRange || [])) {
- m.fireEvent("rangechange", m, m.range);
- m.oldRange = m.range
- }
- return m.range
- },
- clearRange: function() {
- delete this.hasClearRangePending;
- this.range = null
- },
- reconcileRange: function() {
- var e = this,
- g = e.getChart().getAxes(),
- f = e.getDirection(),
- b, d, c, a;
- if (!g) {
- return
- }
- for (b = 0, d = g.length; b < d; b++) {
- c = g[b];
- a = c.getRange();
- if (c === e || c.getDirection() !== f || !a || !c.getReconcileRange()) {
- continue
- }
- if (a[0] < e.range[0]) {
- e.range[0] = a[0]
- }
- if (a[1] > e.range[1]) {
- e.range[1] = a[1]
- }
- }
- },
- applyStyle: function(c, b) {
- var a = Ext.ClassManager.getByAlias("sprite." + this.seriesType);
- if (a && a.def) {
- c = a.def.normalize(c)
- }
- b = Ext.apply(b || {}, c);
- return b
- },
- themeOnlyIfConfigured: {
- grid: true
- },
- updateTheme: function(d) {
- var i = this,
- k = d.getAxis(),
- e = i.getPosition(),
- o = i.getInitialConfig(),
- c = i.defaultConfig,
- g = i.getConfigurator().configs,
- a = k.defaults,
- n = k[e],
- h = i.themeOnlyIfConfigured,
- l, j, p, b, m, f;
- k = Ext.merge({}, a, n);
- for (l in k) {
- j = k[l];
- f = g[l];
- if (j !== null && j !== undefined && f) {
- m = o[l];
- p = Ext.isObject(j);
- b = m === c[l];
- if (p) {
- if (b && h[l]) {
- continue
- }
- j = Ext.merge({}, j, m)
- }
- if (b || p) {
- i[f.names.set](j)
- }
- }
- }
- },
- updateCenter: function(b) {
- var e = this.getSprites(),
- a = e[0],
- d = b[0],
- c = b[1];
- if (a) {
- a.setAttributes({
- centerX: d,
- centerY: c
- })
- }
- if (this.gridSpriteEven) {
- this.gridSpriteEven.getTemplate().setAttributes({
- translationX: d,
- translationY: c,
- rotationCenterX: d,
- rotationCenterY: c
- })
- }
- if (this.gridSpriteOdd) {
- this.gridSpriteOdd.getTemplate().setAttributes({
- translationX: d,
- translationY: c,
- rotationCenterX: d,
- rotationCenterY: c
- })
- }
- },
- getSprites: function() {
- if (!this.getChart()) {
- return
- }
- var i = this,
- e = i.getRange(),
- f = i.getPosition(),
- g = i.getChart(),
- c = g.getAnimation(),
- d, a, b = i.getLength(),
- h = i.superclass;
- if (c === false) {
- c = {
- duration: 0
- }
- }
- if (e) {
- a = Ext.applyIf({
- position: f,
- axis: i,
- min: e[0],
- max: e[1],
- length: b,
- grid: i.getGrid(),
- hidden: i.getHidden(),
- titleOffset: i.titleOffset,
- layout: i.getLayout(),
- segmenter: i.getSegmenter(),
- totalAngle: i.getTotalAngle(),
- label: i.getLabel()
- }, i.getStyle());
- if (!i.sprites.length) {
- while (!h.xtype) {
- h = h.superclass
- }
- d = Ext.create("sprite." + h.xtype, a);
- d.fx.setCustomDurations({
- baseRotation: 0
- });
- d.fx.on("animationstart", "onAnimationStart", i);
- d.fx.on("animationend", "onAnimationEnd", i);
- d.setLayout(i.getLayout());
- d.setSegmenter(i.getSegmenter());
- d.setLabel(i.getLabel());
- i.sprites.push(d);
- i.updateTitleSprite()
- } else {
- d = i.sprites[0];
- d.setAnimation(c);
- d.setAttributes(a)
- }
- if (i.getRenderer()) {
- d.setRenderer(i.getRenderer())
- }
- }
- return i.sprites
- },
- updateTitleSprite: function() {
- var f = this,
- b = f.getLength();
- if (!f.sprites[0] || !Ext.isNumber(b)) {
- return
- }
- var h = this.sprites[0].thickness,
- a = f.getSurface(),
- g = f.getTitle(),
- e = f.getPosition(),
- c = f.getMargin(),
- i = f.getTitleMargin(),
- d = a.roundPixel(b / 2);
- if (g) {
- switch (e) {
- case "top":
- g.setAttributes({
- x: d,
- y: c + i / 2,
- textBaseline: "top",
- textAlign: "center"
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().height + i;
- break;
- case "bottom":
- g.setAttributes({
- x: d,
- y: h + i / 2,
- textBaseline: "top",
- textAlign: "center"
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().height + i;
- break;
- case "left":
- g.setAttributes({
- x: c + i / 2,
- y: d,
- textBaseline: "top",
- textAlign: "center",
- rotationCenterX: c + i / 2,
- rotationCenterY: d,
- rotationRads: -Math.PI / 2
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().width + i;
- break;
- case "right":
- g.setAttributes({
- x: h - c + i / 2,
- y: d,
- textBaseline: "bottom",
- textAlign: "center",
- rotationCenterX: h + i / 2,
- rotationCenterY: d,
- rotationRads: Math.PI / 2
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().width + i;
- break
- }
- }
- },
- onThicknessChanged: function() {
- this.getChart().onThicknessChanged()
- },
- getThickness: function() {
- if (this.getHidden()) {
- return 0
- }
- return (this.sprites[0] && this.sprites[0].thickness || 1) + this.titleOffset + this.getMargin()
- },
- onAnimationStart: function() {
- this.spriteAnimationCount++;
- if (this.spriteAnimationCount === 1) {
- this.fireEvent("animationstart", this)
- }
- },
- onAnimationEnd: function() {
- this.spriteAnimationCount--;
- if (this.spriteAnimationCount === 0) {
- this.fireEvent("animationend", this)
- }
- },
- getItemId: function() {
- return this.getId()
- },
- getAncestorIds: function() {
- return [this.getChart().getId()]
- },
- isXType: function(a) {
- return a === "axis"
- },
- resolveListenerScope: function(e) {
- var d = this,
- a = Ext._namedScopes[e],
- c = d.getChart(),
- b;
- if (!a) {
- b = c ? c.resolveListenerScope(e, false) : (e || d)
- } else {
- if (a.isThis) {
- b = d
- } else {
- if (a.isController) {
- b = c ? c.resolveListenerScope(e, false) : d
- } else {
- if (a.isSelf) {
- b = c ? c.resolveListenerScope(e, false) : d;
- if (b === c && !c.getInheritedConfig("defaultListenerScope")) {
- b = d
- }
- }
- }
- }
- }
- return b
- },
- destroy: function() {
- var a = this;
- a.setChart(null);
- a.surface.destroy();
- a.surface = null;
- a.callParent()
- }
-});
-Ext.define("Ext.chart.LegendBase", {
- extend: "Ext.view.View",
- config: {
- tpl: ['
', '
', '', "', " {name}", "
", " ", "
"],
- nodeContainerSelector: "div." + Ext.baseCSSPrefix + "legend-container",
- itemSelector: "div." + Ext.baseCSSPrefix + "legend-item",
- docked: "bottom"
- },
- setDocked: function(d) {
- var c = this,
- a = c.ownerCt,
- b;
- c.docked = d;
- switch (d) {
- case "top":
- case "bottom":
- c.addCls(Ext.baseCSSPrefix + "horizontal");
- b = "hbox";
- break;
- case "left":
- case "right":
- c.removeCls(Ext.baseCSSPrefix + "horizontal");
- b = "vbox";
- break
- }
- if (a) {
- a.setDocked(d)
- }
- },
- setStore: function(a) {
- this.bindStore(a)
- },
- clearViewEl: function() {
- this.callParent(arguments);
- Ext.removeNode(this.getNodeContainer())
- },
- onItemClick: function(a, c, b, d) {
- this.callParent(arguments);
- this.toggleItem(b)
- }
-});
-Ext.define("Ext.chart.Legend", {
- xtype: "legend",
- extend: "Ext.chart.LegendBase",
- config: {
- baseCls: Ext.baseCSSPrefix + "legend",
- padding: 5,
- rect: null,
- disableSelection: true,
- toggleable: true
- },
- toggleItem: function(c) {
- if (!this.getToggleable()) {
- return
- }
- var b = this.getStore(),
- h = 0,
- e, g = true,
- d, f, a;
- if (b) {
- f = b.getCount();
- for (d = 0; d < f; d++) {
- a = b.getAt(d);
- if (a.get("disabled")) {
- h++
- }
- }
- g = f - h > 1;
- a = b.getAt(c);
- if (a) {
- e = a.get("disabled");
- if (e || g) {
- a.set("disabled", !e)
- }
- }
- }
- }
-});
-Ext.define("Ext.chart.AbstractChart", {
- extend: "Ext.draw.Container",
- requires: ["Ext.chart.theme.Default", "Ext.chart.series.Series", "Ext.chart.interactions.Abstract", "Ext.chart.axis.Axis", "Ext.data.StoreManager", "Ext.chart.Legend", "Ext.data.Store"],
- isChart: true,
- defaultBindProperty: "store",
- config: {
- store: "ext-empty-store",
- theme: "default",
- style: null,
- animation: !Ext.isIE8,
- series: [],
- axes: [],
- legend: null,
- colors: null,
- insetPadding: {
- top: 10,
- left: 10,
- right: 10,
- bottom: 10
- },
- background: null,
- interactions: [],
- mainRect: null,
- resizeHandler: null,
- highlightItem: null
- },
- animationSuspendCount: 0,
- chartLayoutSuspendCount: 0,
- axisThicknessSuspendCount: 0,
- isThicknessChanged: false,
- surfaceZIndexes: {
- background: 0,
- main: 1,
- grid: 2,
- series: 3,
- axis: 4,
- chart: 5,
- overlay: 6,
- events: 7
- },
- constructor: function(a) {
- var b = this;
- b.itemListeners = {};
- b.surfaceMap = {};
- b.chartComponents = {};
- b.isInitializing = true;
- b.suspendChartLayout();
- b.animationSuspendCount++;
- b.callParent(arguments);
- delete b.isInitializing;
- b.getSurface("main");
- b.getSurface("chart").setFlipRtlText(b.getInherited().rtl);
- b.getSurface("overlay").waitFor(b.getSurface("series"));
- b.animationSuspendCount--;
- b.resumeChartLayout()
- },
- applyAnimation: function(a, b) {
- if (!a) {
- a = {
- duration: 0
- }
- } else {
- if (a === true) {
- a = {
- easing: "easeInOut",
- duration: 500
- }
- }
- }
- return b ? Ext.apply({}, a, b) : a
- },
- getAnimation: function() {
- if (this.animationSuspendCount) {
- return {
- duration: 0
- }
- } else {
- return this.callParent()
- }
- },
- applyInsetPadding: function(b, a) {
- if (!Ext.isObject(b)) {
- return Ext.util.Format.parseBox(b)
- } else {
- if (!a) {
- return b
- } else {
- return Ext.apply(a, b)
- }
- }
- },
- suspendAnimation: function() {
- var d = this,
- c = d.getSeries(),
- e = c.length,
- b = -1,
- a;
- d.animationSuspendCount++;
- if (d.animationSuspendCount === 1) {
- while (++b < e) {
- a = c[b];
- a.setAnimation(a.getAnimation())
- }
- }
- },
- resumeAnimation: function() {
- var d = this,
- c = d.getSeries(),
- f = c.length,
- b = -1,
- a, e;
- d.animationSuspendCount--;
- if (d.animationSuspendCount === 0) {
- while (++b < f) {
- a = c[b];
- e = a.getAnimation();
- a.setAnimation(e.duration && e || d.getAnimation())
- }
- }
- },
- suspendChartLayout: function() {
- this.chartLayoutSuspendCount++;
- if (this.chartLayoutSuspendCount === 1) {
- if (this.scheduledLayoutId) {
- this.layoutInSuspension = true;
- this.cancelChartLayout()
- } else {
- this.layoutInSuspension = false
- }
- }
- },
- resumeChartLayout: function() {
- this.chartLayoutSuspendCount--;
- if (this.chartLayoutSuspendCount === 0) {
- if (this.layoutInSuspension) {
- this.scheduleLayout()
- }
- }
- },
- cancelChartLayout: function() {
- if (this.scheduledLayoutId) {
- Ext.draw.Animator.cancel(this.scheduledLayoutId);
- this.scheduledLayoutId = null
- }
- },
- scheduleLayout: function() {
- var a = this;
- if (a.allowSchedule() && !a.scheduledLayoutId) {
- a.scheduledLayoutId = Ext.draw.Animator.schedule("doScheduleLayout", a)
- }
- },
- allowSchedule: function() {
- return true
- },
- doScheduleLayout: function() {
- if (this.chartLayoutSuspendCount) {
- this.layoutInSuspension = true
- } else {
- this.performLayout()
- }
- },
- suspendThicknessChanged: function() {
- this.axisThicknessSuspendCount++
- },
- resumeThicknessChanged: function() {
- if (this.axisThicknessSuspendCount > 0) {
- this.axisThicknessSuspendCount--;
- if (this.axisThicknessSuspendCount === 0 && this.isThicknessChanged) {
- this.onThicknessChanged()
- }
- }
- },
- onThicknessChanged: function() {
- if (this.axisThicknessSuspendCount === 0) {
- this.isThicknessChanged = false;
- this.performLayout()
- } else {
- this.isThicknessChanged = true
- }
- },
- applySprites: function(b) {
- var a = this.getSurface("chart");
- b = Ext.Array.from(b);
- a.removeAll(true);
- a.add(b);
- return b
- },
- initItems: function() {
- var a = this.items,
- b, d, c;
- if (a && !a.isMixedCollection) {
- this.items = [];
- a = Ext.Array.from(a);
- for (b = 0, d = a.length; b < d; b++) {
- c = a[b];
- if (c.type) {
- Ext.raise("To add custom sprites to the chart use the 'sprites' config.")
- } else {
- this.items.push(c)
- }
- }
- }
- this.callParent()
- },
- applyBackground: function(c, e) {
- var b = this.getSurface("background"),
- d, a, f;
- if (c) {
- if (e) {
- d = e.attr.width;
- a = e.attr.height;
- f = e.type === (c.type || "rect")
- }
- if (c.isSprite) {
- e = c
- } else {
- if (c.type === "image" && Ext.isString(c.src)) {
- if (f) {
- e.setAttributes({
- src: c.src
- })
- } else {
- b.remove(e, true);
- e = b.add(c)
- }
- } else {
- if (f) {
- e.setAttributes({
- fillStyle: c
- })
- } else {
- b.remove(e, true);
- e = b.add({
- type: "rect",
- fillStyle: c,
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0
- }
- }
- })
- }
- }
- }
- }
- if (d && a) {
- e.setAttributes({
- width: d,
- height: a
- })
- }
- e.setAnimation(this.getAnimation());
- return e
- },
- getLegendStore: function() {
- return this.legendStore
- },
- refreshLegendStore: function() {
- if (this.getLegendStore()) {
- var d, e, c = this.getSeries(),
- b, a = [];
- if (c) {
- for (d = 0, e = c.length; d < e; d++) {
- b = c[d];
- if (b.getShowInLegend()) {
- b.provideLegendInfo(a)
- }
- }
- }
- this.getLegendStore().setData(a)
- }
- },
- resetLegendStore: function() {
- var c = this.getLegendStore(),
- e, d, a, b;
- if (c) {
- e = this.getLegendStore().getData().items;
- for (d = 0, a = e.length; d < a; d++) {
- b = e[d];
- b.beginEdit();
- b.set("disabled", false);
- b.commit()
- }
- }
- },
- onUpdateLegendStore: function(b, a) {
- var d = this.getSeries(),
- c;
- if (a && d) {
- c = d.map[a.get("series")];
- if (c) {
- c.setHiddenByIndex(a.get("index"), a.get("disabled"));
- this.redraw()
- }
- }
- },
- defaultResizeHandler: function(a) {
- this.scheduleLayout();
- return false
- },
- applyMainRect: function(a, b) {
- if (!b) {
- return a
- }
- this.getSeries();
- this.getAxes();
- if (a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]) {
- return b
- } else {
- return a
- }
- },
- register: function(a) {
- var b = this.chartComponents,
- c = a.getId();
- b[c] = a
- },
- unregister: function(a) {
- var b = this.chartComponents,
- c = a.getId();
- delete b[c]
- },
- get: function(a) {
- return this.chartComponents[a]
- },
- getAxis: function(a) {
- if (a instanceof Ext.chart.axis.Axis) {
- return a
- } else {
- if (Ext.isNumber(a)) {
- return this.getAxes()[a]
- } else {
- if (Ext.isString(a)) {
- return this.get(a)
- }
- }
- }
- },
- getSurface: function(b, c) {
- b = b || "main";
- c = c || b;
- var d = this,
- a = this.callParent([b]),
- f = d.surfaceZIndexes,
- e = d.surfaceMap;
- if (c in f) {
- a.element.setStyle("zIndex", f[c])
- }
- if (!e[c]) {
- e[c] = []
- }
- if (Ext.Array.indexOf(e[c], a) < 0) {
- a.type = c;
- e[c].push(a);
- a.on("destroy", d.forgetSurface, d)
- }
- return a
- },
- forgetSurface: function(a) {
- var d = this.surfaceMap;
- if (!d || this.isDestroying) {
- return
- }
- var c = d[a.type],
- b = c ? Ext.Array.indexOf(c, a) : -1;
- if (b >= 0) {
- c.splice(b, 1)
- }
- },
- applyAxes: function(b, k) {
- var l = this,
- g = {
- left: "right",
- right: "left"
- },
- m = [],
- c, d, e, a, f, h, j;
- l.animationSuspendCount++;
- l.getStore();
- if (!k) {
- k = [];
- k.map = {}
- }
- j = k.map;
- m.map = {};
- b = Ext.Array.from(b, true);
- for (f = 0, h = b.length; f < h; f++) {
- c = b[f];
- if (!c) {
- continue
- }
- if (c instanceof Ext.chart.axis.Axis) {
- d = j[c.getId()];
- c.setChart(l)
- } else {
- c = Ext.Object.chain(c);
- e = c.linkedTo;
- a = c.id;
- if (Ext.isNumber(e)) {
- c = Ext.merge({}, b[e], c)
- } else {
- if (Ext.isString(e)) {
- Ext.Array.each(b, function(i) {
- if (i.id === c.linkedTo) {
- c = Ext.merge({}, i, c);
- return false
- }
- })
- }
- }
- c.id = a;
- c.chart = l;
- if (l.getInherited().rtl) {
- c.position = g[c.position] || c.position
- }
- a = c.getId && c.getId() || c.id;
- c = Ext.factory(c, null, d = j[a], "axis")
- }
- if (c) {
- m.push(c);
- m.map[c.getId()] = c;
- if (!d) {
- c.on("animationstart", "onAnimationStart", l);
- c.on("animationend", "onAnimationEnd", l)
- }
- }
- }
- for (f in j) {
- if (!m.map[f]) {
- j[f].destroy()
- }
- }
- l.animationSuspendCount--;
- return m
- },
- updateAxes: function() {
- if (!this.isDestroying) {
- this.scheduleLayout()
- }
- },
- circularCopyArray: function(e, f, d) {
- var c = [],
- b, a = e && e.length;
- if (a) {
- for (b = 0; b < d; b++) {
- c.push(e[(f + b) % a])
- }
- }
- return c
- },
- circularCopyObject: function(f, g, d) {
- var c = this,
- b, e, a = {};
- if (d) {
- for (b in f) {
- if (f.hasOwnProperty(b)) {
- e = f[b];
- if (Ext.isArray(e)) {
- a[b] = c.circularCopyArray(e, g, d)
- } else {
- a[b] = e
- }
- }
- }
- }
- return a
- },
- getColors: function() {
- var b = this,
- a = b.config.colors,
- c = b.getTheme();
- if (Ext.isArray(a) && a.length > 0) {
- a = b.applyColors(a)
- }
- return a || (c && c.getColors())
- },
- applyColors: function(a) {
- a = Ext.Array.map(a, function(b) {
- if (Ext.isString(b)) {
- return b
- } else {
- return b.toString()
- }
- });
- return a
- },
- updateColors: function(c) {
- var k = this,
- e = k.getTheme(),
- a = c || (e && e.getColors()),
- l = 0,
- f = k.getSeries(),
- d = f && f.length,
- g, j, b, h;
- if (a.length) {
- for (g = 0; g < d; g++) {
- j = f[g];
- h = j.themeColorCount();
- b = k.circularCopyArray(a, l, h);
- l += h;
- j.updateChartColors(b)
- }
- }
- k.refreshLegendStore()
- },
- applyTheme: function(a) {
- if (a && a.isTheme) {
- return a
- }
- return Ext.Factory.chartTheme(a)
- },
- updateTheme: function(g) {
- var e = this,
- f = e.getAxes(),
- d = e.getSeries(),
- a = e.getColors(),
- c, b;
- e.updateChartTheme(g);
- for (b = 0; b < f.length; b++) {
- f[b].updateTheme(g)
- }
- for (b = 0; b < d.length; b++) {
- c = d[b];
- c.updateTheme(g)
- }
- e.updateSpriteTheme(g);
- e.updateColors(a);
- e.redraw()
- },
- themeOnlyIfConfigured: {},
- updateChartTheme: function(c) {
- var i = this,
- k = c.getChart(),
- n = i.getInitialConfig(),
- b = i.defaultConfig,
- e = i.getConfigurator().configs,
- f = k.defaults,
- g = k[i.xtype],
- h = i.themeOnlyIfConfigured,
- l, j, o, a, m, d;
- k = Ext.merge({}, f, g);
- for (l in k) {
- j = k[l];
- d = e[l];
- if (j !== null && j !== undefined && d) {
- m = n[l];
- o = Ext.isObject(j);
- a = m === b[l];
- if (o) {
- if (a && h[l]) {
- continue
- }
- j = Ext.merge({}, j, m)
- }
- if (a || o) {
- i[d.names.set](j)
- }
- }
- }
- },
- updateSpriteTheme: function(c) {
- this.getSprites();
- var j = this,
- e = j.getSurface("chart"),
- h = e.getItems(),
- m = c.getSprites(),
- k, a, l, f, d, b, g;
- for (b = 0, g = h.length; b < g; b++) {
- k = h[b];
- a = m[k.type];
- if (a) {
- f = {};
- d = k.type === "text";
- for (l in a) {
- if (!(l in k.config)) {
- if (!(d && l.indexOf("font") === 0 && k.config.font)) {
- f[l] = a[l]
- }
- }
- }
- k.setAttributes(f)
- }
- }
- },
- addSeries: function(b) {
- var a = this.getSeries();
- Ext.Array.push(a, b);
- this.setSeries(a)
- },
- removeSeries: function(d) {
- d = Ext.Array.from(d);
- var b = this.getSeries(),
- f = [],
- a = d.length,
- g = {},
- c, e;
- for (c = 0; c < a; c++) {
- e = d[c];
- if (typeof e !== "string") {
- e = e.getId()
- }
- g[e] = true
- }
- for (c = 0, a = b.length; c < a; c++) {
- if (!g[b[c].getId()]) {
- f.push(b[c])
- }
- }
- this.setSeries(f)
- },
- applySeries: function(e, d) {
- var g = this,
- j = [],
- h, a, c, f, b;
- g.animationSuspendCount++;
- g.getAxes();
- if (d) {
- h = d.map
- } else {
- d = [];
- h = d.map = {}
- }
- j.map = {};
- e = Ext.Array.from(e, true);
- for (c = 0, f = e.length; c < f; c++) {
- b = e[c];
- if (!b) {
- continue
- }
- a = h[b.getId && b.getId() || b.id];
- if (b instanceof Ext.chart.series.Series) {
- if (a && a !== b) {
- a.destroy()
- }
- b.setChart(g)
- } else {
- if (Ext.isObject(b)) {
- if (a) {
- a.setConfig(b);
- b = a
- } else {
- if (Ext.isString(b)) {
- b = {
- type: b
- }
- }
- b.chart = g;
- b = Ext.create(b.xclass || ("series." + b.type), b);
- b.on("animationstart", "onAnimationStart", g);
- b.on("animationend", "onAnimationEnd", g)
- }
- }
- }
- j.push(b);
- j.map[b.getId()] = b
- }
- for (c in h) {
- if (!j.map[h[c].getId()]) {
- h[c].destroy()
- }
- }
- g.animationSuspendCount--;
- return j
- },
- applyLegend: function(b, a) {
- return Ext.factory(b, Ext.chart.Legend, a)
- },
- updateLegend: function(b, a) {
- if (a) {
- a.destroy()
- }
- if (b) {
- this.getItems();
- this.legendStore = new Ext.data.Store({
- autoDestroy: true,
- fields: ["id", "name", "mark", "disabled", "series", "index"]
- });
- b.setStore(this.legendStore);
- this.refreshLegendStore();
- this.legendStore.on("update", "onUpdateLegendStore", this)
- }
- },
- updateSeries: function(b, a) {
- var c = this;
- if (c.isDestroying) {
- return
- }
- c.animationSuspendCount++;
- c.fireEvent("serieschange", c, b, a);
- c.refreshLegendStore();
- if (!Ext.isEmpty(b)) {
- c.updateTheme(c.getTheme())
- }
- c.scheduleLayout();
- c.animationSuspendCount--
- },
- applyInteractions: function(h, d) {
- if (!d) {
- d = [];
- d.map = {}
- }
- var g = this,
- a = [],
- c = d.map,
- e, f, b;
- a.map = {};
- h = Ext.Array.from(h, true);
- for (e = 0, f = h.length; e < f; e++) {
- b = h[e];
- if (!b) {
- continue
- }
- b = Ext.factory(b, null, c[b.getId && b.getId() || b.id], "interaction");
- if (b) {
- b.setChart(g);
- a.push(b);
- a.map[b.getId()] = b
- }
- }
- for (e in c) {
- if (!a.map[e]) {
- c[e].destroy()
- }
- }
- return a
- },
- getInteraction: function(e) {
- var f = this.getInteractions(),
- a = f && f.length,
- c = null,
- b, d;
- if (a) {
- for (d = 0; d < a; ++d) {
- b = f[d];
- if (b.type === e) {
- c = b;
- break
- }
- }
- }
- return c
- },
- applyStore: function(a) {
- return a && Ext.StoreManager.lookup(a)
- },
- updateStore: function(a, c) {
- var b = this;
- if (c) {
- c.un({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: b,
- order: "after"
- });
- if (c.autoDestroy) {
- c.destroy()
- }
- }
- if (a) {
- a.on({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: b,
- order: "after"
- })
- }
- b.fireEvent("storechange", b, a, c);
- b.onDataChanged()
- },
- redraw: function() {
- this.fireEvent("redraw", this)
- },
- performLayout: function() {
- var d = this,
- b = d.getChartSize(true),
- c = [0, 0, b.width, b.height],
- a = d.getBackground();
- d.hasFirstLayout = true;
- d.fireEvent("layout", d);
- d.cancelChartLayout();
- d.getSurface("background").setRect(c);
- d.getSurface("chart").setRect(c);
- a.setAttributes({
- width: b.width,
- height: b.height
- })
- },
- getChartSize: function(b) {
- var a = this;
- if (b) {
- a.chartSize = null
- }
- return a.chartSize || (a.chartSize = a.innerElement.getSize())
- },
- getEventXY: function(a) {
- return this.getSurface().getEventXY(a)
- },
- getItemForPoint: function(h, g) {
- var f = this,
- a = f.getSeries(),
- e = f.getMainRect(),
- d = a.length,
- b = f.hasFirstLayout ? d - 1 : -1,
- c, j;
- if (!(e && h >= 0 && h <= e[2] && g >= 0 && g <= e[3])) {
- return null
- }
- for (; b >= 0; b--) {
- c = a[b];
- j = c.getItemForPoint(h, g);
- if (j) {
- return j
- }
- }
- return null
- },
- getItemsForPoint: function(h, g) {
- var f = this,
- a = f.getSeries(),
- d = a.length,
- b = f.hasFirstLayout ? d - 1 : -1,
- e = [],
- c, j;
- for (; b >= 0; b--) {
- c = a[b];
- j = c.getItemForPoint(h, g);
- if (j) {
- e.push(j)
- }
- }
- return e
- },
- onAnimationStart: function() {
- this.fireEvent("animationstart", this)
- },
- onAnimationEnd: function() {
- this.fireEvent("animationend", this)
- },
- onDataChanged: function() {
- var d = this;
- if (d.isInitializing) {
- return
- }
- var c = d.getMainRect(),
- a = d.getStore(),
- b = d.getSeries(),
- e = d.getAxes();
- if (!a || !e || !b) {
- return
- }
- if (!c) {
- d.on({
- redraw: d.onDataChanged,
- scope: d,
- single: true
- });
- return
- }
- d.processData();
- d.redraw()
- },
- recordCount: 0,
- processData: function() {
- var g = this,
- e = g.getStore().getCount(),
- c = g.getSeries(),
- f = c.length,
- d = false,
- b = 0,
- a;
- for (; b < f; b++) {
- a = c[b];
- a.processData();
- if (!d && a.isStoreDependantColorCount) {
- d = true
- }
- }
- if (d && e > g.recordCount) {
- g.updateColors(g.getColors());
- g.recordCount = e
- }
- },
- bindStore: function(a) {
- this.setStore(a)
- },
- applyHighlightItem: function(f, a) {
- if (f === a) {
- return
- }
- if (Ext.isObject(f) && Ext.isObject(a)) {
- var e = f,
- d = a,
- c = e.sprite && (e.sprite[0] || e.sprite),
- b = d.sprite && (d.sprite[0] || d.sprite);
- if (c === b && e.index === d.index) {
- return
- }
- }
- return f
- },
- updateHighlightItem: function(b, a) {
- if (a) {
- a.series.setAttributesForItem(a, {
- highlighted: false
- })
- }
- if (b) {
- b.series.setAttributesForItem(b, {
- highlighted: true
- });
- this.fireEvent("itemhighlight", this, b, a)
- }
- this.fireEvent("itemhighlightchange", this, b, a)
- },
- destroyChart: function() {
- var f = this,
- d = f.getLegend(),
- g = f.getAxes(),
- c = f.getSeries(),
- h = f.getInteractions(),
- b = [],
- a, e;
- f.surfaceMap = null;
- for (a = 0, e = h.length; a < e; a++) {
- h[a].destroy()
- }
- for (a = 0, e = g.length; a < e; a++) {
- g[a].destroy()
- }
- for (a = 0, e = c.length; a < e; a++) {
- c[a].destroy()
- }
- f.setInteractions(b);
- f.setAxes(b);
- f.setSeries(b);
- if (d) {
- d.destroy();
- f.setLegend(null)
- }
- f.legendStore = null;
- f.setStore(null);
- f.cancelChartLayout()
- },
- getRefItems: function(b) {
- var g = this,
- e = g.getSeries(),
- h = g.getAxes(),
- a = g.getInteractions(),
- c = [],
- d, f;
- for (d = 0, f = e.length; d < f; d++) {
- c.push(e[d]);
- if (e[d].getRefItems) {
- c.push.apply(c, e[d].getRefItems(b))
- }
- }
- for (d = 0, f = h.length; d < f; d++) {
- c.push(h[d]);
- if (h[d].getRefItems) {
- c.push.apply(c, h[d].getRefItems(b))
- }
- }
- for (d = 0, f = a.length; d < f; d++) {
- c.push(a[d]);
- if (a[d].getRefItems) {
- c.push.apply(c, a[d].getRefItems(b))
- }
- }
- return c
- }
-});
-Ext.define("Ext.chart.overrides.AbstractChart", {
- override: "Ext.chart.AbstractChart",
- updateLegend: function(b, a) {
- var c;
- this.callParent([b, a]);
- if (b) {
- c = b.docked;
- this.addDocked({
- dock: c,
- xtype: "panel",
- shrinkWrap: true,
- scrollable: true,
- layout: {
- type: c === "top" || c === "bottom" ? "hbox" : "vbox",
- pack: "center"
- },
- items: b,
- cls: Ext.baseCSSPrefix + "legend-panel"
- })
- }
- },
- performLayout: function() {
- if (this.isVisible(true)) {
- return this.callParent()
- }
- this.cancelChartLayout();
- return false
- },
- afterComponentLayout: function(c, a, b, d) {
- this.callParent([c, a, b, d]);
- this.scheduleLayout()
- },
- allowSchedule: function() {
- return this.rendered
- },
- onDestroy: function() {
- this.destroyChart();
- this.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.grid.HorizontalGrid", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "grid.horizontal",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 1,
- height: 1,
- strokeStyle: "#DDD"
- }
- }
- },
- render: function(b, c, e) {
- var a = this.attr,
- f = b.roundPixel(a.y),
- d = c.lineWidth * 0.5;
- c.beginPath();
- c.rect(e[0] - b.matrix.getDX(), f + d, +e[2], a.height);
- c.fill();
- c.beginPath();
- c.moveTo(e[0] - b.matrix.getDX(), f + d);
- c.lineTo(e[0] + e[2] - b.matrix.getDX(), f + d);
- c.stroke()
- }
-});
-Ext.define("Ext.chart.grid.VerticalGrid", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "grid.vertical",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 1,
- height: 1,
- strokeStyle: "#DDD"
- }
- }
- },
- render: function(c, d, f) {
- var b = this.attr,
- a = c.roundPixel(b.x),
- e = d.lineWidth * 0.5;
- d.beginPath();
- d.rect(a - e, f[1] - c.matrix.getDY(), b.width, f[3]);
- d.fill();
- d.beginPath();
- d.moveTo(a - e, f[1] - c.matrix.getDY());
- d.lineTo(a - e, f[1] + f[3] - c.matrix.getDY());
- d.stroke()
- }
-});
-Ext.define("Ext.chart.CartesianChart", {
- extend: "Ext.chart.AbstractChart",
- alternateClassName: "Ext.chart.Chart",
- requires: ["Ext.chart.grid.HorizontalGrid", "Ext.chart.grid.VerticalGrid"],
- xtype: ["cartesian", "chart"],
- isCartesian: true,
- config: {
- flipXY: false,
- innerRect: [0, 0, 1, 1],
- innerPadding: {
- top: 0,
- left: 0,
- right: 0,
- bottom: 0
- }
- },
- applyInnerPadding: function(b, a) {
- if (!Ext.isObject(b)) {
- return Ext.util.Format.parseBox(b)
- } else {
- if (!a) {
- return b
- } else {
- return Ext.apply(a, b)
- }
- }
- },
- getDirectionForAxis: function(a) {
- var b = this.getFlipXY();
- if (a === "left" || a === "right") {
- if (b) {
- return "X"
- } else {
- return "Y"
- }
- } else {
- if (b) {
- return "Y"
- } else {
- return "X"
- }
- }
- },
- performLayout: function() {
- var A = this;
- A.animationSuspendCount++;
- if (A.callParent() === false) {
- --A.animationSuspendCount;
- return
- }
- A.suspendThicknessChanged();
- var d = A.getSurface("chart").getRect(),
- o = d[2],
- n = d[3],
- z = A.getAxes(),
- b, q = A.getSeries(),
- h, l, a, f = A.getInsetPadding(),
- v = A.getInnerPadding(),
- r, c, e = Ext.apply({}, f),
- u, p, s, k, m, y, t, x, g, j = A.getInherited().rtl,
- w = A.getFlipXY();
- if (o <= 0 || n <= 0) {
- return
- }
- for (x = 0; x < z.length; x++) {
- b = z[x];
- l = b.getSurface();
- m = b.getFloating();
- y = m ? m.value : null;
- a = b.getThickness();
- switch (b.getPosition()) {
- case "top":
- l.setRect([0, e.top + 1, o, a]);
- break;
- case "bottom":
- l.setRect([0, n - (e.bottom + a), o, a]);
- break;
- case "left":
- l.setRect([e.left, 0, a, n]);
- break;
- case "right":
- l.setRect([o - (e.right + a), 0, a, n]);
- break
- }
- if (y === null) {
- e[b.getPosition()] += a
- }
- }
- o -= e.left + e.right;
- n -= e.top + e.bottom;
- u = [e.left, e.top, o, n];
- e.left += v.left;
- e.top += v.top;
- e.right += v.right;
- e.bottom += v.bottom;
- p = o - v.left - v.right;
- s = n - v.top - v.bottom;
- A.setInnerRect([e.left, e.top, p, s]);
- if (p <= 0 || s <= 0) {
- return
- }
- A.setMainRect(u);
- A.getSurface().setRect(u);
- for (x = 0, g = A.surfaceMap.grid && A.surfaceMap.grid.length; x < g; x++) {
- c = A.surfaceMap.grid[x];
- c.setRect(u);
- c.matrix.set(1, 0, 0, 1, v.left, v.top);
- c.matrix.inverse(c.inverseMatrix)
- }
- for (x = 0; x < z.length; x++) {
- b = z[x];
- l = b.getSurface();
- t = l.matrix;
- k = t.elements;
- switch (b.getPosition()) {
- case "top":
- case "bottom":
- k[4] = e.left;
- b.setLength(p);
- break;
- case "left":
- case "right":
- k[5] = e.top;
- b.setLength(s);
- break
- }
- b.updateTitleSprite();
- t.inverse(l.inverseMatrix)
- }
- for (x = 0, g = q.length; x < g; x++) {
- h = q[x];
- r = h.getSurface();
- r.setRect(u);
- if (w) {
- if (j) {
- r.matrix.set(0, -1, -1, 0, v.left + p, v.top + s)
- } else {
- r.matrix.set(0, -1, 1, 0, v.left, v.top + s)
- }
- } else {
- r.matrix.set(1, 0, 0, -1, v.left, v.top + s)
- }
- r.matrix.inverse(r.inverseMatrix);
- h.getOverlaySurface().setRect(u)
- }
- A.redraw();
- A.animationSuspendCount--;
- A.resumeThicknessChanged()
- },
- refloatAxes: function() {
- var h = this,
- g = h.getAxes(),
- o = (g && g.length) || 0,
- c, d, n, f, l, b, k, r = h.getChartSize(),
- q = h.getInsetPadding(),
- p = h.getInnerPadding(),
- a = r.width - q.left - q.right,
- m = r.height - q.top - q.bottom,
- j, e;
- for (e = 0; e < o; e++) {
- c = g[e];
- f = c.getFloating();
- l = f ? f.value : null;
- if (l === null) {
- delete c.floatingAtCoord;
- continue
- }
- d = c.getSurface();
- n = d.getRect();
- if (!n) {
- continue
- }
- n = n.slice();
- b = h.getAxis(f.alongAxis);
- if (b) {
- j = b.getAlignment() === "horizontal";
- if (Ext.isString(l)) {
- l = b.getCoordFor(l)
- }
- b.floatingAxes[c.getId()] = l;
- k = b.getSprites()[0].attr.matrix;
- if (j) {
- l = l * k.getXX() + k.getDX();
- c.floatingAtCoord = l + p.left + p.right
- } else {
- l = l * k.getYY() + k.getDY();
- c.floatingAtCoord = l + p.top + p.bottom
- }
- } else {
- j = c.getAlignment() === "horizontal";
- if (j) {
- c.floatingAtCoord = l + p.top + p.bottom
- } else {
- c.floatingAtCoord = l + p.left + p.right
- }
- l = d.roundPixel(0.01 * l * (j ? m : a))
- }
- switch (c.getPosition()) {
- case "top":
- n[1] = q.top + p.top + l - n[3] + 1;
- break;
- case "bottom":
- n[1] = q.top + p.top + (b ? l : m - l);
- break;
- case "left":
- n[0] = q.left + p.left + l - n[2];
- break;
- case "right":
- n[0] = q.left + p.left + (b ? l : a - l) - 1;
- break
- }
- d.setRect(n)
- }
- },
- redraw: function() {
- var C = this,
- r = C.getSeries(),
- z = C.getAxes(),
- b = C.getMainRect(),
- p, t, w = C.getInnerPadding(),
- f, l, s, e, q, A, v, g, d, c, a, k, n, y = C.getFlipXY(),
- x = 1000,
- m, u, h, o, B;
- if (!b) {
- return
- }
- p = b[2] - w.left - w.right;
- t = b[3] - w.top - w.bottom;
- for (A = 0; A < r.length; A++) {
- h = r[A];
- if ((c = h.getXAxis())) {
- n = c.getVisibleRange();
- l = c.getRange();
- l = [l[0] + (l[1] - l[0]) * n[0], l[0] + (l[1] - l[0]) * n[1]]
- } else {
- l = h.getXRange()
- }
- if ((a = h.getYAxis())) {
- n = a.getVisibleRange();
- s = a.getRange();
- s = [s[0] + (s[1] - s[0]) * n[0], s[0] + (s[1] - s[0]) * n[1]]
- } else {
- s = h.getYRange()
- }
- q = {
- visibleMinX: l[0],
- visibleMaxX: l[1],
- visibleMinY: s[0],
- visibleMaxY: s[1],
- innerWidth: p,
- innerHeight: t,
- flipXY: y
- };
- f = h.getSprites();
- for (v = 0, g = f.length; v < g; v++) {
- o = f[v];
- m = o.attr.zIndex;
- if (m < x) {
- m += (A + 1) * 100 + x;
- o.attr.zIndex = m;
- B = o.getMarker("items");
- if (B) {
- u = B.attr.zIndex;
- if (u === Number.MAX_VALUE) {
- B.attr.zIndex = m
- } else {
- if (u < x) {
- B.attr.zIndex = m + u
- }
- }
- }
- }
- o.setAttributes(q, true)
- }
- }
- for (A = 0; A < z.length; A++) {
- d = z[A];
- e = d.isSide();
- f = d.getSprites();
- k = d.getRange();
- n = d.getVisibleRange();
- q = {
- dataMin: k[0],
- dataMax: k[1],
- visibleMin: n[0],
- visibleMax: n[1]
- };
- if (e) {
- q.length = t;
- q.startGap = w.bottom;
- q.endGap = w.top
- } else {
- q.length = p;
- q.startGap = w.left;
- q.endGap = w.right
- }
- for (v = 0, g = f.length; v < g; v++) {
- f[v].setAttributes(q, true)
- }
- }
- C.renderFrame();
- C.callParent(arguments)
- },
- renderFrame: function() {
- this.refloatAxes();
- this.callParent()
- }
-});
-Ext.define("Ext.chart.grid.CircularGrid", {
- extend: "Ext.draw.sprite.Circle",
- alias: "grid.circular",
- inheritableStatics: {
- def: {
- defaults: {
- r: 1,
- strokeStyle: "#DDD"
- }
- }
- }
-});
-Ext.define("Ext.chart.grid.RadialGrid", {
- extend: "Ext.draw.sprite.Path",
- alias: "grid.radial",
- inheritableStatics: {
- def: {
- processors: {
- startRadius: "number",
- endRadius: "number"
- },
- defaults: {
- startRadius: 0,
- endRadius: 1,
- scalingCenterX: 0,
- scalingCenterY: 0,
- strokeStyle: "#DDD"
- },
- triggers: {
- startRadius: "path,bbox",
- endRadius: "path,bbox"
- }
- }
- },
- render: function() {
- this.callParent(arguments)
- },
- updatePath: function(d, a) {
- var b = a.startRadius,
- c = a.endRadius;
- d.moveTo(b, 0);
- d.lineTo(c, 0)
- }
-});
-Ext.define("Ext.chart.PolarChart", {
- extend: "Ext.chart.AbstractChart",
- requires: ["Ext.chart.grid.CircularGrid", "Ext.chart.grid.RadialGrid"],
- xtype: "polar",
- isPolar: true,
- config: {
- center: [0, 0],
- radius: 0,
- innerPadding: 0
- },
- getDirectionForAxis: function(a) {
- return a === "radial" ? "Y" : "X"
- },
- applyCenter: function(a, b) {
- if (b && a[0] === b[0] && a[1] === b[1]) {
- return
- }
- return [+a[0], +a[1]]
- },
- updateCenter: function(a) {
- var g = this,
- h = g.getAxes(),
- d = g.getSeries(),
- c, f, e, b;
- for (c = 0, f = h.length; c < f; c++) {
- e = h[c];
- e.setCenter(a)
- }
- for (c = 0, f = d.length; c < f; c++) {
- b = d[c];
- b.setCenter(a)
- }
- },
- applyInnerPadding: function(b, a) {
- return Ext.isNumber(b) ? b : a
- },
- doSetSurfaceRect: function(b, c) {
- var a = this.getMainRect();
- b.setRect(c);
- b.matrix.set(1, 0, 0, 1, a[0] - c[0], a[1] - c[1]);
- b.inverseMatrix.set(1, 0, 0, 1, c[0] - a[0], c[1] - a[1])
- },
- applyAxes: function(f, h) {
- var e = this,
- g = Ext.Array.from(e.config.series)[0],
- b, d, c, a;
- if (g.type === "radar" && f && f.length) {
- for (b = 0, d = f.length; b < d; b++) {
- c = f[b];
- if (c.position === "angular") {
- a = true;
- break
- }
- }
- if (!a) {
- f.push({
- type: "category",
- position: "angular",
- fields: g.xField || g.angleField,
- style: {
- estStepSize: 1
- },
- grid: true
- })
- }
- }
- return this.callParent(arguments)
- },
- performLayout: function() {
- var F = this,
- g = true;
- try {
- F.animationSuspendCount++;
- if (this.callParent() === false) {
- g = false;
- return
- }
- F.suspendThicknessChanged();
- var h = F.getSurface("chart").getRect(),
- v = F.getInsetPadding(),
- G = F.getInnerPadding(),
- l = Ext.apply({}, v),
- d, s = h[2] - v.left - v.right,
- r = h[3] - v.top - v.bottom,
- x = [v.left, v.top, s, r],
- u = F.getSeries(),
- p, t = s - G * 2,
- w = r - G * 2,
- D = [t * 0.5 + G, w * 0.5 + G],
- j = Math.min(t, w) * 0.5,
- A = F.getAxes(),
- f, a, k, m = [],
- o = [],
- E = j - G,
- z, n, b, q, y, c, C;
- F.setMainRect(x);
- F.doSetSurfaceRect(F.getSurface(), x);
- for (z = 0, n = F.surfaceMap.grid && F.surfaceMap.grid.length; z < n; z++) {
- F.doSetSurfaceRect(F.surfaceMap.grid[z], h)
- }
- for (z = 0, n = A.length; z < n; z++) {
- f = A[z];
- switch (f.getPosition()) {
- case "angular":
- m.push(f);
- break;
- case "radial":
- o.push(f);
- break
- }
- }
- for (z = 0, n = m.length; z < n; z++) {
- f = m[z];
- q = f.getFloating();
- y = q ? q.value : null;
- F.doSetSurfaceRect(f.getSurface(), h);
- a = f.getThickness();
- for (d in l) {
- l[d] += a
- }
- s = h[2] - l.left - l.right;
- r = h[3] - l.top - l.bottom;
- b = Math.min(s, r) * 0.5;
- if (z === 0) {
- E = b - G
- }
- f.setMinimum(0);
- f.setLength(b);
- f.getSprites();
- k = f.sprites[0].attr.lineWidth * 0.5;
- for (d in l) {
- l[d] += k
- }
- }
- for (z = 0, n = o.length; z < n; z++) {
- f = o[z];
- F.doSetSurfaceRect(f.getSurface(), h);
- f.setMinimum(0);
- f.setLength(E);
- f.getSprites()
- }
- for (z = 0, n = u.length; z < n; z++) {
- p = u[z];
- if (p.type === "gauge" && !c) {
- c = p
- } else {
- p.setRadius(E)
- }
- F.doSetSurfaceRect(p.getSurface(), x)
- }
- F.doSetSurfaceRect(F.getSurface("overlay"), h);
- if (c) {
- c.setRect(x);
- C = c.getRadius() - G;
- F.setRadius(C);
- F.setCenter(c.getCenter());
- c.setRadius(C);
- if (A.length && A[0].getPosition() === "gauge") {
- f = A[0];
- F.doSetSurfaceRect(f.getSurface(), h);
- f.setTotalAngle(c.getTotalAngle());
- f.setLength(C)
- }
- } else {
- F.setRadius(j);
- F.setCenter(D)
- }
- F.redraw()
- } catch (B) {
- throw B
- } finally {
- F.animationSuspendCount--;
- if (g) {
- F.resumeThicknessChanged()
- }
- }
- },
- refloatAxes: function() {
- var j = this,
- g = j.getAxes(),
- h = j.getMainRect(),
- f, k, b, d, a, c, e;
- if (!h) {
- return
- }
- e = 0.5 * Math.min(h[2], h[3]);
- for (d = 0, a = g.length; d < a; d++) {
- c = g[d];
- f = c.getFloating();
- k = f ? f.value : null;
- if (k !== null) {
- b = j.getAxis(f.alongAxis);
- if (c.getPosition() === "angular") {
- if (b) {
- k = b.getLength() * k / b.getRange()[1]
- } else {
- k = 0.01 * k * e
- }
- c.sprites[0].setAttributes({
- length: k
- }, true)
- } else {
- if (b) {
- if (Ext.isString(k)) {
- k = b.getCoordFor(k)
- }
- k = k / (b.getRange()[1] + 1) * Math.PI * 2 - Math.PI * 1.5 + c.getRotation()
- } else {
- k = Ext.draw.Draw.rad(k)
- }
- c.sprites[0].setAttributes({
- baseRotation: k
- }, true)
- }
- }
- }
- },
- redraw: function() {
- var f = this,
- g = f.getAxes(),
- d, c = f.getSeries(),
- b, a, e;
- for (a = 0, e = g.length; a < e; a++) {
- d = g[a];
- d.getSprites()
- }
- for (a = 0, e = c.length; a < e; a++) {
- b = c[a];
- b.getSprites()
- }
- f.renderFrame();
- f.callParent(arguments)
- },
- renderFrame: function() {
- this.refloatAxes();
- this.callParent()
- }
-});
-Ext.define("Ext.chart.SpaceFillingChart", {
- extend: "Ext.chart.AbstractChart",
- xtype: "spacefilling",
- config: {},
- performLayout: function() {
- var j = this;
- try {
- j.animationSuspendCount++;
- if (j.callParent() === false) {
- return
- }
- var k = j.getSurface("chart").getRect(),
- l = j.getInsetPadding(),
- a = k[2] - l.left - l.right,
- m = k[3] - l.top - l.bottom,
- h = [l.left, l.top, a, m],
- b = j.getSeries(),
- d, c, g;
- j.getSurface().setRect(h);
- j.setMainRect(h);
- for (c = 0, g = b.length; c < g; c++) {
- d = b[c];
- d.getSurface().setRect(h);
- if (d.setRect) {
- d.setRect(h)
- }
- d.getOverlaySurface().setRect(k)
- }
- j.redraw()
- } catch (f) {
- throw f
- } finally {
- j.animationSuspendCount--
- }
- },
- redraw: function() {
- var e = this,
- c = e.getSeries(),
- b, a, d;
- for (a = 0, d = c.length; a < d; a++) {
- b = c[a];
- b.getSprites()
- }
- e.renderFrame();
- e.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.axis.sprite.Axis3D", {
- extend: "Ext.chart.axis.sprite.Axis",
- alias: "sprite.axis3d",
- type: "axis3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- },
- triggers: {
- depth: "layout"
- }
- }
- },
- config: {
- fx: {
- customDurations: {
- depth: 0
- }
- }
- },
- layoutUpdater: function() {
- var h = this,
- f = h.getAxis().getChart();
- if (f.isInitializing) {
- return
- }
- var e = h.attr,
- d = h.getLayout(),
- c = d.isDiscrete ? 0 : e.depth,
- g = f.getInherited().rtl,
- b = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMin,
- i = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMax,
- a = {
- attr: e,
- segmenter: h.getSegmenter(),
- renderer: h.defaultRenderer
- };
- if (e.position === "left" || e.position === "right") {
- e.translationX = 0;
- e.translationY = i * (e.length - c) / (i - b) + c;
- e.scalingX = 1;
- e.scalingY = (-e.length + c) / (i - b);
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- } else {
- if (e.position === "top" || e.position === "bottom") {
- if (g) {
- e.translationX = e.length + b * e.length / (i - b) + 1
- } else {
- e.translationX = -b * e.length / (i - b)
- }
- e.translationY = 0;
- e.scalingX = (g ? -1 : 1) * (e.length - c) / (i - b);
- e.scalingY = 1;
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- }
- }
- if (d) {
- d.calculateLayout(a);
- h.setLayoutContext(a)
- }
- },
- renderAxisLine: function(a, j, f, c) {
- var i = this,
- h = i.attr,
- b = h.lineWidth * 0.5,
- f = i.getLayout(),
- d = f.isDiscrete ? 0 : h.depth,
- k = h.position,
- e, g;
- if (h.axisLine && h.length) {
- switch (k) {
- case "left":
- e = a.roundPixel(c[2]) - b;
- j.moveTo(e, -h.endGap + d);
- j.lineTo(e, h.length + h.startGap);
- break;
- case "right":
- j.moveTo(b, -h.endGap);
- j.lineTo(b, h.length + h.startGap);
- break;
- case "bottom":
- j.moveTo(-h.startGap, b);
- j.lineTo(h.length - d + h.endGap, b);
- break;
- case "top":
- e = a.roundPixel(c[3]) - b;
- j.moveTo(-h.startGap, e);
- j.lineTo(h.length + h.endGap, e);
- break;
- case "angular":
- j.moveTo(h.centerX + h.length, h.centerY);
- j.arc(h.centerX, h.centerY, h.length, 0, Math.PI * 2, true);
- break;
- case "gauge":
- g = i.getGaugeAngles();
- j.moveTo(h.centerX + Math.cos(g.start) * h.length, h.centerY + Math.sin(g.start) * h.length);
- j.arc(h.centerX, h.centerY, h.length, g.start, g.end, true);
- break
- }
- }
- }
-});
-Ext.define("Ext.chart.axis.Axis3D", {
- extend: "Ext.chart.axis.Axis",
- xtype: "axis3d",
- requires: ["Ext.chart.axis.sprite.Axis3D"],
- config: {
- depth: 0
- },
- onSeriesChange: function(e) {
- var g = this,
- b = "depthchange",
- f = "onSeriesDepthChange",
- d, c;
-
- function a(h) {
- var i = g.boundSeries;
- for (d = 0; d < i.length; d++) {
- c = i[d];
- c[h](b, f, g)
- }
- }
- a("un");
- g.callParent(arguments);
- a("on")
- },
- onSeriesDepthChange: function(b, f) {
- var d = this,
- g = f,
- e = d.boundSeries,
- a, c;
- if (f > d.getDepth()) {
- g = f
- } else {
- for (a = 0; a < e.length; a++) {
- c = e[a];
- if (c !== b && c.getDepth) {
- f = c.getDepth();
- if (f > g) {
- g = f
- }
- }
- }
- }
- d.setDepth(g)
- },
- updateDepth: function(d) {
- var b = this,
- c = b.getSprites(),
- a = {
- depth: d
- };
- if (c && c.length) {
- c[0].setAttributes(a)
- }
- if (b.gridSpriteEven && b.gridSpriteOdd) {
- b.gridSpriteEven.getTemplate().setAttributes(a);
- b.gridSpriteOdd.getTemplate().setAttributes(a)
- }
- },
- getGridAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "horizontal3d";
- case "top":
- case "bottom":
- return "vertical3d"
- }
- }
-});
-Ext.define("Ext.chart.axis.Category", {
- requires: ["Ext.chart.axis.layout.CombineDuplicate", "Ext.chart.axis.segmenter.Names"],
- extend: "Ext.chart.axis.Axis",
- alias: "axis.category",
- type: "category",
- config: {
- layout: "combineDuplicate",
- segmenter: "names"
- }
-});
-Ext.define("Ext.chart.axis.Category3D", {
- requires: ["Ext.chart.axis.layout.CombineDuplicate", "Ext.chart.axis.segmenter.Names"],
- extend: "Ext.chart.axis.Axis3D",
- alias: "axis.category3d",
- type: "category3d",
- config: {
- layout: "combineDuplicate",
- segmenter: "names"
- }
-});
-Ext.define("Ext.chart.axis.Numeric", {
- extend: "Ext.chart.axis.Axis",
- type: "numeric",
- alias: ["axis.numeric", "axis.radial"],
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Numeric"],
- config: {
- layout: "continuous",
- segmenter: "numeric",
- aggregator: "double"
- }
-});
-Ext.define("Ext.chart.axis.Numeric3D", {
- extend: "Ext.chart.axis.Axis3D",
- alias: ["axis.numeric3d"],
- type: "numeric3d",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Numeric"],
- config: {
- layout: "continuous",
- segmenter: "numeric",
- aggregator: "double"
- }
-});
-Ext.define("Ext.chart.axis.Time", {
- extend: "Ext.chart.axis.Numeric",
- alias: "axis.time",
- type: "time",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Time"],
- config: {
- calculateByLabelSize: true,
- dateFormat: null,
- fromDate: null,
- toDate: null,
- step: [Ext.Date.DAY, 1],
- layout: "continuous",
- segmenter: "time",
- aggregator: "time"
- },
- updateDateFormat: function(a) {
- this.setRenderer(function(c, b) {
- return Ext.Date.format(new Date(b), a)
- })
- },
- updateFromDate: function(a) {
- this.setMinimum(+a)
- },
- updateToDate: function(a) {
- this.setMaximum(+a)
- },
- getCoordFor: function(a) {
- if (Ext.isString(a)) {
- a = new Date(a)
- }
- return +a
- }
-});
-Ext.define("Ext.chart.axis.Time3D", {
- extend: "Ext.chart.axis.Numeric3D",
- alias: "axis.time3d",
- type: "time3d",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Time"],
- config: {
- calculateByLabelSize: true,
- dateFormat: null,
- fromDate: null,
- toDate: null,
- step: [Ext.Date.DAY, 1],
- layout: "continuous",
- segmenter: "time",
- aggregator: "time"
- },
- updateDateFormat: function(a) {
- this.setRenderer(function(c, b) {
- return Ext.Date.format(new Date(b), a)
- })
- },
- updateFromDate: function(a) {
- this.setMinimum(+a)
- },
- updateToDate: function(a) {
- this.setMaximum(+a)
- },
- getCoordFor: function(a) {
- if (Ext.isString(a)) {
- a = new Date(a)
- }
- return +a
- }
-});
-Ext.define("Ext.chart.grid.HorizontalGrid3D", {
- extend: "Ext.chart.grid.HorizontalGrid",
- alias: "grid.horizontal3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- }
- }
- },
- render: function(a, k, d) {
- var f = this.attr,
- i = a.roundPixel(f.x),
- h = a.roundPixel(f.y),
- l = a.matrix.getDX(),
- c = k.lineWidth * 0.5,
- j = f.height,
- e = f.depth,
- b, g;
- if (h <= d[1]) {
- return
- }
- b = d[0] + e - l;
- g = h + c - e;
- k.beginPath();
- k.rect(b, g, d[2], j);
- k.fill();
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + d[2], g);
- k.stroke();
- b = d[0] + i - l;
- g = h + c;
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + e, g - e);
- k.lineTo(b + e, g - e + j);
- k.lineTo(b, g + j);
- k.closePath();
- k.fill();
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + e, g - e);
- k.stroke()
- }
-});
-Ext.define("Ext.chart.grid.VerticalGrid3D", {
- extend: "Ext.chart.grid.VerticalGrid",
- alias: "grid.vertical3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- }
- }
- },
- render_: function(c, d, f) {
- var b = this.attr,
- a = c.roundPixel(b.x),
- e = d.lineWidth * 0.5;
- d.beginPath();
- d.rect(a - e, f[1] - c.matrix.getDY(), b.width, f[3]);
- d.fill();
- d.beginPath();
- d.moveTo(a - e, f[1] - c.matrix.getDY());
- d.lineTo(a - e, f[1] + f[3] - c.matrix.getDY());
- d.stroke()
- },
- render: function(b, j, e) {
- var g = this.attr,
- i = b.roundPixel(g.x),
- k = b.matrix.getDY(),
- d = j.lineWidth * 0.5,
- a = g.width,
- f = g.depth,
- c, h;
- if (i >= e[2]) {
- return
- }
- c = i - d + f;
- h = e[1] - f - k;
- j.beginPath();
- j.rect(c, h, a, e[3]);
- j.fill();
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c, h + e[3]);
- j.stroke();
- c = i - d;
- h = e[3];
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c + f, h - f);
- j.lineTo(c + f + a, h - f);
- j.lineTo(c + a, h);
- j.closePath();
- j.fill();
- c = i - d;
- h = e[3];
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c + f, h - f);
- j.stroke()
- }
-});
-Ext.define("Ext.chart.interactions.CrossZoom", {
- extend: "Ext.chart.interactions.Abstract",
- type: "crosszoom",
- alias: "interaction.crosszoom",
- isCrossZoom: true,
- config: {
- axes: true,
- gestures: {
- dragstart: "onGestureStart",
- drag: "onGesture",
- dragend: "onGestureEnd",
- dblclick: "onDoubleTap"
- },
- undoButton: {}
- },
- stopAnimationBeforeSync: false,
- zoomAnimationInProgress: false,
- constructor: function() {
- this.callParent(arguments);
- this.zoomHistory = []
- },
- applyAxes: function(b) {
- var a = {};
- if (b === true) {
- return {
- top: {},
- right: {},
- bottom: {},
- left: {}
- }
- } else {
- if (Ext.isArray(b)) {
- a = {};
- Ext.each(b, function(c) {
- a[c] = {}
- })
- } else {
- if (Ext.isObject(b)) {
- Ext.iterate(b, function(c, d) {
- if (d === true) {
- a[c] = {}
- } else {
- if (d !== false) {
- a[c] = d
- }
- }
- })
- }
- }
- }
- return a
- },
- applyUndoButton: function(b, a) {
- var c = this;
- if (a) {
- a.destroy()
- }
- if (b) {
- return Ext.create("Ext.Button", Ext.apply({
- cls: [],
- text: "Undo Zoom",
- disabled: true,
- handler: function() {
- c.undoZoom()
- }
- }, b))
- }
- },
- getSurface: function() {
- return this.getChart() && this.getChart().getSurface("main")
- },
- setSeriesOpacity: function(b) {
- var a = this.getChart() && this.getChart().getSurface("series");
- if (a) {
- a.element.setStyle("opacity", b)
- }
- },
- onGestureStart: function(h) {
- var j = this,
- i = j.getChart(),
- d = j.getSurface(),
- l = i.getInnerRect(),
- c = i.getInnerPadding(),
- g = c.left,
- b = g + l[2],
- f = c.top,
- a = f + l[3],
- n = i.getEventXY(h),
- m = n[0],
- k = n[1];
- if (j.zoomAnimationInProgress) {
- return
- }
- if (m > g && m < b && k > f && k < a) {
- j.gestureEvent = "drag";
- j.lockEvents(j.gestureEvent);
- j.startX = m;
- j.startY = k;
- j.selectionRect = d.add({
- type: "rect",
- globalAlpha: 0.5,
- fillStyle: "rgba(80,80,140,0.5)",
- strokeStyle: "rgba(80,80,140,1)",
- lineWidth: 2,
- x: m,
- y: k,
- width: 0,
- height: 0,
- zIndex: 10000
- });
- j.setSeriesOpacity(0.8);
- return false
- }
- },
- onGesture: function(h) {
- var j = this;
- if (j.zoomAnimationInProgress) {
- return
- }
- if (j.getLocks()[j.gestureEvent] === j) {
- var i = j.getChart(),
- d = j.getSurface(),
- l = i.getInnerRect(),
- c = i.getInnerPadding(),
- g = c.left,
- b = g + l[2],
- f = c.top,
- a = f + l[3],
- n = i.getEventXY(h),
- m = n[0],
- k = n[1];
- if (m < g) {
- m = g
- } else {
- if (m > b) {
- m = b
- }
- }
- if (k < f) {
- k = f
- } else {
- if (k > a) {
- k = a
- }
- }
- j.selectionRect.setAttributes({
- width: m - j.startX,
- height: k - j.startY
- });
- if (Math.abs(j.startX - m) < 11 || Math.abs(j.startY - k) < 11) {
- j.selectionRect.setAttributes({
- globalAlpha: 0.5
- })
- } else {
- j.selectionRect.setAttributes({
- globalAlpha: 1
- })
- }
- d.renderFrame();
- return false
- }
- },
- onGestureEnd: function(i) {
- var l = this;
- if (l.zoomAnimationInProgress) {
- return
- }
- if (l.getLocks()[l.gestureEvent] === l) {
- var k = l.getChart(),
- d = l.getSurface(),
- n = k.getInnerRect(),
- c = k.getInnerPadding(),
- g = c.left,
- b = g + n[2],
- f = c.top,
- a = f + n[3],
- h = n[2],
- j = n[3],
- p = k.getEventXY(i),
- o = p[0],
- m = p[1];
- if (o < g) {
- o = g
- } else {
- if (o > b) {
- o = b
- }
- }
- if (m < f) {
- m = f
- } else {
- if (m > a) {
- m = a
- }
- }
- if (Math.abs(l.startX - o) < 11 || Math.abs(l.startY - m) < 11) {
- d.remove(l.selectionRect)
- } else {
- l.zoomBy([Math.min(l.startX, o) / h, 1 - Math.max(l.startY, m) / j, Math.max(l.startX, o) / h, 1 - Math.min(l.startY, m) / j]);
- l.selectionRect.setAttributes({
- x: Math.min(l.startX, o),
- y: Math.min(l.startY, m),
- width: Math.abs(l.startX - o),
- height: Math.abs(l.startY - m)
- });
- l.selectionRect.setAnimation(k.getAnimation() || {
- duration: 0
- });
- l.selectionRect.setAttributes({
- globalAlpha: 0,
- x: 0,
- y: 0,
- width: h,
- height: j
- });
- l.zoomAnimationInProgress = true;
- k.suspendThicknessChanged();
- l.selectionRect.fx.on("animationend", function() {
- k.resumeThicknessChanged();
- d.remove(l.selectionRect);
- l.selectionRect = null;
- l.zoomAnimationInProgress = false
- })
- }
- d.renderFrame();
- l.sync();
- l.unlockEvents(l.gestureEvent);
- l.setSeriesOpacity(1);
- if (!l.zoomAnimationInProgress) {
- d.remove(l.selectionRect);
- l.selectionRect = null
- }
- }
- },
- zoomBy: function(o) {
- var n = this,
- a = n.getAxes(),
- k = n.getChart(),
- j = k.getAxes(),
- l = k.getInherited().rtl,
- f, d = {},
- c, b;
- if (l) {
- o = o.slice();
- c = 1 - o[0];
- b = 1 - o[2];
- o[0] = Math.min(c, b);
- o[2] = Math.max(c, b)
- }
- for (var h = 0; h < j.length; h++) {
- var g = j[h];
- f = a[g.getPosition()];
- if (f && f.allowZoom !== false) {
- var e = g.isSide(),
- m = g.getVisibleRange();
- d[g.getId()] = m.slice(0);
- if (!e) {
- g.setVisibleRange([(m[1] - m[0]) * o[0] + m[0], (m[1] - m[0]) * o[2] + m[0]])
- } else {
- g.setVisibleRange([(m[1] - m[0]) * o[1] + m[0], (m[1] - m[0]) * o[3] + m[0]])
- }
- }
- }
- n.zoomHistory.push(d);
- n.getUndoButton().setDisabled(false)
- },
- undoZoom: function() {
- var c = this.zoomHistory.pop(),
- d = this.getChart().getAxes();
- if (c) {
- for (var a = 0; a < d.length; a++) {
- var b = d[a];
- if (c[b.getId()]) {
- b.setVisibleRange(c[b.getId()])
- }
- }
- }
- this.getUndoButton().setDisabled(this.zoomHistory.length === 0);
- this.sync()
- },
- onDoubleTap: function(a) {
- this.undoZoom()
- },
- destroy: function() {
- this.setUndoButton(null);
- this.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.interactions.Crosshair", {
- extend: "Ext.chart.interactions.Abstract",
- requires: ["Ext.chart.grid.HorizontalGrid", "Ext.chart.grid.VerticalGrid", "Ext.chart.CartesianChart", "Ext.chart.axis.layout.Discrete"],
- type: "crosshair",
- alias: "interaction.crosshair",
- config: {
- axes: {
- top: {
- label: {},
- rect: {}
- },
- right: {
- label: {},
- rect: {}
- },
- bottom: {
- label: {},
- rect: {}
- },
- left: {
- label: {},
- rect: {}
- }
- },
- lines: {
- horizontal: {
- strokeStyle: "black",
- lineDash: [5, 5]
- },
- vertical: {
- strokeStyle: "black",
- lineDash: [5, 5]
- }
- },
- gesture: "drag"
- },
- applyAxes: function(b, a) {
- return Ext.merge(a || {}, b)
- },
- applyLines: function(a, b) {
- return Ext.merge(b || {}, a)
- },
- updateChart: function(a) {
- if (a && !a.isCartesian) {
- Ext.raise("Crosshair interaction can only be used on cartesian charts.")
- }
- this.callParent(arguments)
- },
- getGestures: function() {
- var a = this,
- b = {};
- b[a.getGesture()] = "onGesture";
- b[a.getGesture() + "start"] = "onGestureStart";
- b[a.getGesture() + "end"] = "onGestureEnd";
- return b
- },
- onGestureStart: function(N) {
- var m = this,
- O = m.getChart(),
- B = O.getTheme().getAxis(),
- A, F = O.getSurface("overlay"),
- s = O.getInnerRect(),
- n = s[2],
- M = s[3],
- r = O.getEventXY(N),
- D = r[0],
- C = r[1],
- E = O.getAxes(),
- u = m.getAxes(),
- h = m.getLines(),
- q, v, b, d, k, z, G, L, J, o, I, w, l, f, p, j, t, a, g, H, c, K;
- if (D > 0 && D < n && C > 0 && C < M) {
- m.lockEvents(m.getGesture());
- H = Ext.apply({
- xclass: "Ext.chart.grid.HorizontalGrid",
- x: 0,
- y: C,
- width: n
- }, h.horizontal);
- c = Ext.apply({
- xclass: "Ext.chart.grid.VerticalGrid",
- x: D,
- y: 0,
- height: M
- }, h.vertical);
- m.axesLabels = m.axesLabels || {};
- for (K = 0; K < E.length; K++) {
- q = E[K];
- v = q.getSurface();
- b = v.getRect();
- w = q.getSprites()[0];
- d = b[2];
- k = b[3];
- z = q.getPosition();
- G = q.getAlignment();
- t = q.getTitle();
- a = t && t.attr.text !== "" && t.getBBox();
- l = w.attr;
- f = w.thickness;
- p = l.axisLine ? l.lineWidth : 0;
- j = p / 2;
- I = Math.max(l.majorTickSize, l.minorTickSize) + p;
- L = m.axesLabels[z] = v.add({
- type: "composite"
- });
- L.labelRect = L.add(Ext.apply({
- type: "rect",
- fillStyle: "white",
- x: z === "right" ? p : 0,
- y: z === "bottom" ? p : 0,
- width: d - p - (G === "vertical" && a ? a.width : 0),
- height: k - p - (G === "horizontal" && a ? a.height : 0),
- translationX: z === "left" && a ? a.width : 0,
- translationY: z === "top" && a ? a.height : 0
- }, u.rect || u[z].rect));
- if (G === "vertical" && !c.strokeStyle) {
- c.strokeStyle = l.strokeStyle
- }
- if (G === "horizontal" && !H.strokeStyle) {
- H.strokeStyle = l.strokeStyle
- }
- A = Ext.merge({}, B.defaults, B[z]);
- J = Ext.apply({}, q.config.label, A.label);
- o = u.label || u[z].label;
- L.labelText = L.add(Ext.apply(J, o, {
- type: "text",
- x: (function() {
- switch (z) {
- case "left":
- g = a ? a.x + a.width : 0;
- return g + (d - g - I) / 2 - j;
- case "right":
- g = a ? d - a.x : 0;
- return I + (d - I - g) / 2 + j;
- default:
- return 0
- }
- })(),
- y: (function() {
- switch (z) {
- case "top":
- g = a ? a.y + a.height : 0;
- return g + (k - g - I) / 2 - j;
- case "bottom":
- g = a ? k - a.y : 0;
- return I + (k - I - g) / 2 + j;
- default:
- return 0
- }
- })()
- }))
- }
- m.horizontalLine = F.add(H);
- m.verticalLine = F.add(c);
- return false
- }
- },
- onGesture: function(G) {
- var K = this;
- if (K.getLocks()[K.getGesture()] !== K) {
- return
- }
- var u = K.getChart(),
- z = u.getSurface("overlay"),
- a = Ext.Array.slice(u.getInnerRect()),
- r = u.getInnerPadding(),
- t = r.left,
- q = r.top,
- E = a[2],
- f = a[3],
- d = u.getEventXY(G),
- k = d[0],
- j = d[1],
- D = u.getAxes(),
- c, h, m, p, J, w, I, H, s, b, C, g, v, n, l, A, F, o, B;
- if (k < 0) {
- k = 0
- } else {
- if (k > E) {
- k = E
- }
- }
- if (j < 0) {
- j = 0
- } else {
- if (j > f) {
- j = f
- }
- }
- k += t;
- j += q;
- for (B = 0; B < D.length; B++) {
- c = D[B];
- h = c.getPosition();
- m = c.getAlignment();
- p = c.getSurface();
- J = c.getSprites()[0];
- w = J.attr.matrix;
- C = J.attr.textPadding * 2;
- s = K.axesLabels[h];
- I = J.getLayoutContext();
- H = c.getSegmenter();
- if (s) {
- if (m === "vertical") {
- v = w.getYY();
- l = w.getDY();
- F = (j - l - q) / v;
- if (c.getLayout() instanceof Ext.chart.axis.layout.Discrete) {
- j = Math.round(F) * v + l + q;
- F = H.from(Math.round(F));
- F = J.attr.data[F]
- } else {
- F = H.from(F)
- }
- o = H.renderer(F, I);
- s.setAttributes({
- translationY: j - q
- });
- s.labelText.setAttributes({
- text: o
- });
- b = s.labelText.getBBox();
- s.labelRect.setAttributes({
- height: b.height + C,
- y: -(b.height + C) / 2
- });
- p.renderFrame()
- } else {
- g = w.getXX();
- n = w.getDX();
- A = (k - n - t) / g;
- if (c.getLayout() instanceof Ext.chart.axis.layout.Discrete) {
- k = Math.round(A) * g + n + t;
- A = H.from(Math.round(A));
- A = J.attr.data[A]
- } else {
- A = H.from(A)
- }
- o = H.renderer(A, I);
- s.setAttributes({
- translationX: k - t
- });
- s.labelText.setAttributes({
- text: o
- });
- b = s.labelText.getBBox();
- s.labelRect.setAttributes({
- width: b.width + C,
- x: -(b.width + C) / 2
- });
- p.renderFrame()
- }
- }
- }
- K.horizontalLine.setAttributes({
- y: j,
- strokeStyle: J.attr.strokeStyle
- });
- K.verticalLine.setAttributes({
- x: k,
- strokeStyle: J.attr.strokeStyle
- });
- z.renderFrame();
- return false
- },
- onGestureEnd: function(h) {
- var l = this,
- k = l.getChart(),
- a = k.getSurface("overlay"),
- j = k.getAxes(),
- c, g, d, b, f;
- a.remove(l.verticalLine);
- a.remove(l.horizontalLine);
- for (f = 0; f < j.length; f++) {
- c = j[f];
- g = c.getPosition();
- d = c.getSurface();
- b = l.axesLabels[g];
- if (b) {
- delete l.axesLabels[g];
- d.remove(b)
- }
- d.renderFrame()
- }
- a.renderFrame();
- l.unlockEvents(l.getGesture())
- }
-});
-Ext.define("Ext.chart.interactions.ItemHighlight", {
- extend: "Ext.chart.interactions.Abstract",
- type: "itemhighlight",
- alias: "interaction.itemhighlight",
- isItemHighlight: true,
- config: {
- gestures: {
- tap: "onTapGesture",
- mousemove: "onMouseMoveGesture",
- mousedown: "onMouseDownGesture",
- mouseup: "onMouseUpGesture",
- mouseleave: "onMouseUpGesture"
- },
- sticky: false
- },
- stickyHighlightItem: null,
- onMouseMoveGesture: function(g) {
- var d = this,
- h = d.tipItem,
- a = g.pointerType === "mouse",
- c, f, b;
- if (d.getSticky()) {
- return true
- }
- if (d.isDragging) {
- if (h && a) {
- h.series.hideTooltip(h);
- d.tipItem = null
- }
- } else {
- if (!d.stickyHighlightItem) {
- c = d.getItemForEvent(g);
- b = d.getChart();
- if (c !== b.getHighlightItem()) {
- d.highlight(c);
- d.sync()
- }
- if (a) {
- if (h && (!c || h.field !== c.field || h.record !== c.record)) {
- h.series.hideTooltip(h);
- d.tipItem = h = null
- }
- if (c && (f = c.series.getTooltip())) {
- if (f.trackMouse || !h) {
- c.series.showTooltip(c, g.getXY())
- }
- d.tipItem = c
- }
- }
- return false
- }
- }
- },
- highlight: function(a) {
- this.getChart().setHighlightItem(a)
- },
- showTooltip: function(b, a) {
- a.series.showTooltip(a, b.getXY());
- this.tipItem = a
- },
- onMouseDownGesture: function() {
- this.isDragging = true
- },
- onMouseUpGesture: function() {
- this.isDragging = false
- },
- onTapGesture: function(c) {
- var b = this;
- if (c.pointerType === "mouse" && !b.getSticky()) {
- return
- }
- var a = b.getItemForEvent(c);
- if (b.stickyHighlightItem && a && (b.stickyHighlightItem.index === a.index)) {
- a = null
- }
- b.stickyHighlightItem = a;
- b.highlight(a)
- }
-});
-Ext.define("Ext.chart.interactions.ItemEdit", {
- extend: "Ext.chart.interactions.ItemHighlight",
- requires: ["Ext.tip.ToolTip"],
- type: "itemedit",
- alias: "interaction.itemedit",
- isItemEdit: true,
- config: {
- style: null,
- renderer: null,
- tooltip: true,
- gestures: {
- dragstart: "onDragStart",
- drag: "onDrag",
- dragend: "onDragEnd"
- },
- cursors: {
- ewResize: "ew-resize",
- nsResize: "ns-resize",
- move: "move"
- }
- },
- item: null,
- applyTooltip: function(b) {
- if (b) {
- var a = Ext.apply({}, b, {
- renderer: this.defaultTooltipRenderer,
- constrainPosition: true,
- shrinkWrapDock: true,
- autoHide: true,
- offsetX: 10,
- offsetY: 10
- });
- b = new Ext.tip.ToolTip(a)
- }
- return b
- },
- defaultTooltipRenderer: function(b, a, f, d) {
- var c = [];
- if (f.xField) {
- c.push(f.xField + ": " + f.xValue)
- }
- if (f.yField) {
- c.push(f.yField + ": " + f.yValue)
- }
- b.setHtml(c.join(" "))
- },
- onDragStart: function(d) {
- var c = this,
- a = c.getChart(),
- b = a.getHighlightItem();
- if (b) {
- a.fireEvent("beginitemedit", a, c, c.item = b);
- return false
- }
- },
- onDrag: function(f) {
- var d = this,
- b = d.getChart(),
- c = b.getHighlightItem(),
- a = c && c.sprite.type;
- if (c) {
- switch (a) {
- case "barSeries":
- return d.onDragBar(f);
- break;
- case "scatterSeries":
- return d.onDragScatter(f);
- break
- }
- }
- },
- highlight: function(f) {
- var e = this,
- d = e.getChart(),
- a = d.getFlipXY(),
- g = e.getCursors(),
- c = f && f.sprite.type,
- b = d.el.dom.style;
- e.callParent([f]);
- if (f) {
- switch (c) {
- case "barSeries":
- if (a) {
- b.cursor = g.ewResize
- } else {
- b.cursor = g.nsResize
- }
- break;
- case "scatterSeries":
- b.cursor = g.move;
- break
- }
- } else {
- d.el.dom.style.cursor = "default"
- }
- },
- onDragBar: function(i) {
- var m = this,
- k = m.getChart(),
- l = k.getInherited().rtl,
- f = k.isCartesian && k.getFlipXY(),
- q = k.getHighlightItem(),
- g = q.sprite.getMarker("items"),
- p = g.getMarkerFor(q.sprite.getId(), q.index),
- b = q.sprite.getSurface(),
- c = b.getRect(),
- r = b.getEventXY(i),
- o = q.sprite.attr.matrix,
- j = m.getRenderer(),
- a, n, d, h;
- if (f) {
- h = l ? c[2] - r[0] : r[0]
- } else {
- h = c[3] - r[1]
- }
- a = {
- x: p.x,
- y: h,
- width: p.width,
- height: p.height + (p.y - h),
- radius: p.radius,
- fillStyle: "none",
- lineDash: [4, 4],
- zIndex: 100
- };
- Ext.apply(a, m.getStyle());
- if (Ext.isArray(q.series.getYField())) {
- h = h - p.y - p.height
- }
- m.target = {
- index: q.index,
- yField: q.field,
- yValue: (h - o.getDY()) / o.getYY()
- };
- d = [k, {
- target: m.target,
- style: a,
- item: q
- }];
- n = Ext.callback(j, null, d, 0, k);
- if (n) {
- Ext.apply(a, n)
- }
- q.sprite.putMarker("items", a, "itemedit");
- m.showTooltip(i, m.target, q);
- b.renderFrame()
- },
- onDragScatter: function(n) {
- var t = this,
- g = t.getChart(),
- d = g.getInherited().rtl,
- l = g.isCartesian && g.getFlipXY(),
- o = g.getHighlightItem(),
- b = o.sprite.getMarker("items"),
- p = b.getMarkerFor(o.sprite.getId(), o.index),
- j = o.sprite.getSurface(),
- h = j.getRect(),
- a = j.getEventXY(n),
- k = o.sprite.attr.matrix,
- c = o.series.getXAxis(),
- f = c && c.getLayout().isContinuous,
- i = t.getRenderer(),
- m, u, q, s, r;
- if (l) {
- r = d ? h[2] - a[0] : a[0]
- } else {
- r = h[3] - a[1]
- }
- if (f) {
- if (l) {
- s = h[3] - a[1]
- } else {
- s = a[0]
- }
- } else {
- s = p.translationX
- }
- m = {
- translationX: s,
- translationY: r,
- scalingX: p.scalingX,
- scalingY: p.scalingY,
- r: p.r,
- fillStyle: "none",
- lineDash: [4, 4],
- zIndex: 100
- };
- Ext.apply(m, t.getStyle());
- t.target = {
- index: o.index,
- yField: o.field,
- yValue: (r - k.getDY()) / k.getYY()
- };
- if (f) {
- Ext.apply(t.target, {
- xField: o.series.getXField(),
- xValue: (s - k.getDX()) / k.getXX()
- })
- }
- q = [g, {
- target: t.target,
- style: m,
- item: o
- }];
- u = Ext.callback(i, null, q, 0, g);
- if (u) {
- Ext.apply(m, u)
- }
- o.sprite.putMarker("items", m, "itemedit");
- t.showTooltip(n, t.target, o);
- j.renderFrame()
- },
- showTooltip: function(g, f, c) {
- var d = this.getTooltip(),
- a, b;
- if (d && Ext.toolkit !== "modern") {
- a = d.config;
- b = this.getChart();
- Ext.callback(a.renderer, null, [d, c, f, g], 0, b);
- d.show([g.x + a.offsetX, g.y + a.offsetY])
- }
- },
- hideTooltip: function() {
- var a = this.getTooltip();
- if (a && Ext.toolkit !== "modern") {
- a.hide()
- }
- },
- onDragEnd: function(g) {
- var d = this,
- f = d.target,
- c = d.getChart(),
- b = c.getStore(),
- a;
- if (f) {
- a = b.getAt(f.index);
- if (f.yField) {
- a.set(f.yField, f.yValue, {
- convert: false
- })
- }
- if (f.xField) {
- a.set(f.xField, f.xValue, {
- convert: false
- })
- }
- if (f.yField || f.xField) {
- d.getChart().onDataChanged()
- }
- d.target = null
- }
- d.hideTooltip();
- if (d.item) {
- c.fireEvent("enditemedit", c, d, d.item, f)
- }
- d.highlight(d.item = null)
- },
- destroy: function() {
- var a = this.getConfig("tooltip", true);
- Ext.destroy(a);
- this.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.PanZoom", {
- extend: "Ext.chart.interactions.Abstract",
- type: "panzoom",
- alias: "interaction.panzoom",
- requires: ["Ext.draw.Animator"],
- config: {
- axes: {
- top: {},
- right: {},
- bottom: {},
- left: {}
- },
- minZoom: null,
- maxZoom: null,
- showOverflowArrows: true,
- panGesture: "drag",
- zoomGesture: "pinch",
- zoomOnPanGesture: false,
- modeToggleButton: {
- xtype: "segmentedbutton",
- width: 200,
- defaults: {
- ui: "default-toolbar"
- },
- cls: Ext.baseCSSPrefix + "panzoom-toggle",
- items: [{
- text: "Pan"
- }, {
- text: "Zoom"
- }]
- },
- hideLabelInGesture: false
- },
- stopAnimationBeforeSync: true,
- applyAxes: function(b, a) {
- return Ext.merge(a || {}, b)
- },
- applyZoomOnPanGesture: function(a) {
- this.getChart();
- if (this.isMultiTouch()) {
- return false
- }
- return a
- },
- updateZoomOnPanGesture: function(b) {
- var a = this.getModeToggleButton();
- if (!this.isMultiTouch()) {
- a.show();
- a.setValue(b ? 1 : 0)
- } else {
- a.hide()
- }
- },
- toggleMode: function() {
- var a = this;
- if (!a.isMultiTouch()) {
- a.setZoomOnPanGesture(!a.getZoomOnPanGesture())
- }
- },
- applyModeToggleButton: function(c, b) {
- var d = this,
- a = Ext.factory(c, "Ext.button.Segmented", b);
- if (!a && b) {
- b.destroy()
- }
- if (a && !b) {
- a.addListener("toggle", function(e) {
- d.setZoomOnPanGesture(e.getValue() === 1)
- })
- }
- return a
- },
- getGestures: function() {
- var c = this,
- e = {},
- d = c.getPanGesture(),
- b = c.getZoomGesture(),
- a = Ext.supports.Touch;
- e[b] = "onZoomGestureMove";
- e[b + "start"] = "onZoomGestureStart";
- e[b + "end"] = "onZoomGestureEnd";
- e[d] = "onPanGestureMove";
- e[d + "start"] = "onPanGestureStart";
- e[d + "end"] = "onPanGestureEnd";
- e.doubletap = "onDoubleTap";
- return e
- },
- onDoubleTap: function(h) {
- var f = this,
- c = f.getChart(),
- g = c.getAxes(),
- b, a, d;
- for (a = 0, d = g.length; a < d; a++) {
- b = g[a];
- b.setVisibleRange([0, 1])
- }
- c.redraw()
- },
- onPanGestureStart: function(d) {
- if (!d || !d.touches || d.touches.length < 2) {
- var b = this,
- a = b.getChart().getInnerRect(),
- c = b.getChart().element.getXY();
- b.startX = d.getX() - c[0] - a[0];
- b.startY = d.getY() - c[1] - a[1];
- b.oldVisibleRanges = null;
- b.hideLabels();
- b.getChart().suspendThicknessChanged();
- b.lockEvents(b.getPanGesture());
- return false
- }
- },
- onPanGestureMove: function(d) {
- var b = this;
- if (b.getLocks()[b.getPanGesture()] === b) {
- var a = b.getChart().getInnerRect(),
- c = b.getChart().element.getXY();
- if (b.getZoomOnPanGesture()) {
- b.transformAxesBy(b.getZoomableAxes(d), 0, 0, (d.getX() - c[0] - a[0]) / b.startX, b.startY / (d.getY() - c[1] - a[1]))
- } else {
- b.transformAxesBy(b.getPannableAxes(d), d.getX() - c[0] - a[0] - b.startX, d.getY() - c[1] - a[1] - b.startY, 1, 1)
- }
- b.sync();
- return false
- }
- },
- onPanGestureEnd: function(b) {
- var a = this,
- c = a.getPanGesture();
- if (a.getLocks()[c] === a) {
- a.getChart().resumeThicknessChanged();
- a.showLabels();
- a.sync();
- a.unlockEvents(c);
- return false
- }
- },
- onZoomGestureStart: function(b) {
- if (b.touches && b.touches.length === 2) {
- var c = this,
- i = c.getChart().element.getXY(),
- f = c.getChart().getInnerRect(),
- h = i[0] + f[0],
- d = i[1] + f[1],
- j = [b.touches[0].point.x - h, b.touches[0].point.y - d, b.touches[1].point.x - h, b.touches[1].point.y - d],
- g = Math.max(44, Math.abs(j[2] - j[0])),
- a = Math.max(44, Math.abs(j[3] - j[1]));
- c.getChart().suspendThicknessChanged();
- c.lastZoomDistances = [g, a];
- c.lastPoints = j;
- c.oldVisibleRanges = null;
- c.hideLabels();
- c.lockEvents(c.getZoomGesture());
- return false
- }
- },
- onZoomGestureMove: function(d) {
- var f = this;
- if (f.getLocks()[f.getZoomGesture()] === f) {
- var i = f.getChart().getInnerRect(),
- n = f.getChart().element.getXY(),
- k = n[0] + i[0],
- h = n[1] + i[1],
- o = Math.abs,
- c = f.lastPoints,
- m = [d.touches[0].point.x - k, d.touches[0].point.y - h, d.touches[1].point.x - k, d.touches[1].point.y - h],
- g = Math.max(44, o(m[2] - m[0])),
- b = Math.max(44, o(m[3] - m[1])),
- a = this.lastZoomDistances || [g, b],
- l = g / a[0],
- j = b / a[1];
- f.transformAxesBy(f.getZoomableAxes(d), i[2] * (l - 1) / 2 + m[2] - c[2] * l, i[3] * (j - 1) / 2 + m[3] - c[3] * j, l, j);
- f.sync();
- return false
- }
- },
- onZoomGestureEnd: function(c) {
- var b = this,
- a = b.getZoomGesture();
- if (b.getLocks()[a] === b) {
- b.getChart().resumeThicknessChanged();
- b.showLabels();
- b.sync();
- b.unlockEvents(a);
- return false
- }
- },
- hideLabels: function() {
- if (this.getHideLabelInGesture()) {
- this.eachInteractiveAxes(function(a) {
- a.hideLabels()
- })
- }
- },
- showLabels: function() {
- if (this.getHideLabelInGesture()) {
- this.eachInteractiveAxes(function(a) {
- a.showLabels()
- })
- }
- },
- isEventOnAxis: function(c, a) {
- var b = a.getSurface().getRect();
- return b[0] <= c.getX() && c.getX() <= b[0] + b[2] && b[1] <= c.getY() && c.getY() <= b[1] + b[3]
- },
- getPannableAxes: function(d) {
- var h = this,
- a = h.getAxes(),
- f = h.getChart().getAxes(),
- c, g = f.length,
- k = [],
- j = false,
- b;
- if (d) {
- for (c = 0; c < g; c++) {
- if (this.isEventOnAxis(d, f[c])) {
- j = true;
- break
- }
- }
- }
- for (c = 0; c < g; c++) {
- b = a[f[c].getPosition()];
- if (b && b.allowPan !== false && (!j || this.isEventOnAxis(d, f[c]))) {
- k.push(f[c])
- }
- }
- return k
- },
- getZoomableAxes: function(f) {
- var j = this,
- a = j.getAxes(),
- g = j.getChart().getAxes(),
- l = [],
- d, h = g.length,
- c, k = false,
- b;
- if (f) {
- for (d = 0; d < h; d++) {
- if (this.isEventOnAxis(f, g[d])) {
- k = true;
- break
- }
- }
- }
- for (d = 0; d < h; d++) {
- c = g[d];
- b = a[c.getPosition()];
- if (b && b.allowZoom !== false && (!k || this.isEventOnAxis(f, c))) {
- l.push(c)
- }
- }
- return l
- },
- eachInteractiveAxes: function(c) {
- var d = this,
- b = d.getAxes(),
- e = d.getChart().getAxes();
- for (var a = 0; a < e.length; a++) {
- if (b[e[a].getPosition()]) {
- if (false === c.call(this, e[a])) {
- return
- }
- }
- }
- },
- transformAxesBy: function(d, j, g, h, e) {
- var f = this.getChart().getInnerRect(),
- a = this.getAxes(),
- k, b = this.oldVisibleRanges,
- l = false;
- if (!b) {
- this.oldVisibleRanges = b = {};
- this.eachInteractiveAxes(function(i) {
- b[i.getId()] = i.getVisibleRange()
- })
- }
- if (!f) {
- return
- }
- for (var c = 0; c < d.length; c++) {
- k = a[d[c].getPosition()];
- l = this.transformAxisBy(d[c], b[d[c].getId()], j, g, h, e, this.minZoom || k.minZoom, this.maxZoom || k.maxZoom) || l
- }
- return l
- },
- transformAxisBy: function(c, o, r, q, k, i, h, m) {
- var s = this,
- b = o[1] - o[0],
- l = c.getVisibleRange(),
- g = h || s.getMinZoom() || c.config.minZoom,
- j = m || s.getMaxZoom() || c.config.maxZoom,
- a = s.getChart().getInnerRect(),
- f, p;
- if (!a) {
- return
- }
- var d = c.isSide(),
- e = d ? a[3] : a[2],
- n = d ? -q : r;
- b /= d ? i : k;
- if (b < 0) {
- b = -b
- }
- if (b * g > 1) {
- b = 1
- }
- if (b * j < 1) {
- b = 1 / j
- }
- f = o[0];
- p = o[1];
- l = l[1] - l[0];
- if (b === l && l === 1) {
- return
- }
- c.setVisibleRange([(o[0] + o[1] - b) * 0.5 - n / e * b, (o[0] + o[1] + b) * 0.5 - n / e * b]);
- return (Math.abs(f - c.getVisibleRange()[0]) > 1e-10 || Math.abs(p - c.getVisibleRange()[1]) > 1e-10)
- },
- destroy: function() {
- this.setModeToggleButton(null);
- this.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.Rotate", {
- extend: "Ext.chart.interactions.Abstract",
- type: "rotate",
- alias: "interaction.rotate",
- config: {
- gesture: "rotate",
- gestures: {
- rotate: "onRotate",
- rotateend: "onRotate",
- dragstart: "onGestureStart",
- drag: "onGesture",
- dragend: "onGestureEnd"
- },
- rotation: 0
- },
- oldRotations: null,
- getAngle: function(f) {
- var c = this,
- b = c.getChart(),
- d = b.getEventXY(f),
- a = b.getCenter();
- return Math.atan2(d[1] - a[1], d[0] - a[0])
- },
- getRadius: function(a) {
- return this.getChart().getRadius()
- },
- getEventRadius: function(h) {
- var f = this,
- d = f.getChart(),
- g = d.getEventXY(h),
- a = d.getCenter(),
- c = g[0] - a[0],
- b = g[1] - a[1];
- return Math.sqrt(c * c + b * b)
- },
- onGestureStart: function(d) {
- var c = this,
- b = c.getRadius(d),
- a = c.getEventRadius(d);
- if (b >= a) {
- c.lockEvents("drag");
- c.angle = c.getAngle(d);
- c.oldRotations = {};
- return false
- }
- },
- onGesture: function(b) {
- var a = this,
- c = a.getAngle(b) - a.angle;
- if (a.getLocks().drag === a) {
- a.doRotateTo(c, true);
- return false
- }
- },
- doRotateTo: function(d, a, b) {
- var n = this,
- l = n.getChart(),
- k = l.getAxes(),
- f = l.getSeries(),
- m = n.oldRotations,
- c, j, g, e, h;
- if (!b) {
- l.suspendAnimation()
- }
- for (e = 0, h = k.length; e < h; e++) {
- c = k[e];
- g = m[c.getId()] || (m[c.getId()] = c.getRotation());
- c.setRotation(d + (a ? g : 0))
- }
- for (e = 0, h = f.length; e < h; e++) {
- j = f[e];
- g = m[j.getId()] || (m[j.getId()] = j.getRotation());
- j.setRotation(d + (a ? g : 0))
- }
- n.setRotation(d + (a ? g : 0));
- n.fireEvent("rotate", n, n.getRotation());
- n.sync();
- if (!b) {
- l.resumeAnimation()
- }
- },
- rotateTo: function(c, b, a) {
- this.doRotateTo(c, b, a);
- this.oldRotations = {}
- },
- onGestureEnd: function(b) {
- var a = this;
- if (a.getLocks().drag === a) {
- a.onGesture(b);
- a.unlockEvents("drag");
- a.fireEvent("rotationEnd", a, a.getRotation());
- return false
- }
- },
- onRotate: function(a) {}
-});
-Ext.define("Ext.chart.interactions.RotatePie3D", {
- extend: "Ext.chart.interactions.Rotate",
- type: "rotatePie3d",
- alias: "interaction.rotatePie3d",
- getAngle: function(g) {
- var a = this.getChart(),
- f = a.getInherited().rtl,
- d = f ? -1 : 1,
- h = g.getXY(),
- c = a.element.getXY(),
- b = a.getMainRect();
- return d * Math.atan2(h[1] - c[1] - b[3] * 0.5, h[0] - c[0] - b[2] * 0.5)
- },
- getRadius: function(j) {
- var f = this.getChart(),
- a = f.getRadius(),
- d = f.getSeries(),
- h = d.length,
- c = 0,
- b, g;
- for (; c < h; c++) {
- b = d[c];
- if (b.isPie3D) {
- g = b.getRadius();
- if (g > a) {
- a = g
- }
- }
- }
- return a
- }
-});
-Ext.define("Ext.chart.plugin.ItemEvents", {
- extend: "Ext.plugin.Abstract",
- alias: "plugin.chartitemevents",
- moveEvents: false,
- mouseMoveEvents: {
- mousemove: true,
- mouseover: true,
- mouseout: true
- },
- itemMouseMoveEvents: {
- itemmousemove: true,
- itemmouseover: true,
- itemmouseout: true
- },
- init: function(b) {
- var a = "handleEvent";
- this.chart = b;
- b.addElementListener({
- click: a,
- dblclick: a,
- mousedown: a,
- mousemove: a,
- mouseup: a,
- mouseover: a,
- mouseout: a,
- priority: 1001,
- scope: this
- })
- },
- hasItemMouseMoveListeners: function() {
- var b = this.chart.hasListeners,
- a;
- for (a in this.itemMouseMoveEvents) {
- if (a in b) {
- return true
- }
- }
- return false
- },
- handleEvent: function(g) {
- var d = this,
- a = d.chart,
- h = g.type in d.mouseMoveEvents,
- c = d.lastItem,
- f, b;
- if (h && !d.hasItemMouseMoveListeners() && !d.moveEvents) {
- return
- }
- f = a.getEventXY(g);
- b = a.getItemForPoint(f[0], f[1]);
- if (h && !Ext.Object.equals(b, c)) {
- if (c) {
- a.fireEvent("itemmouseout", a, c, g);
- c.series.fireEvent("itemmouseout", c.series, c, g)
- }
- if (b) {
- a.fireEvent("itemmouseover", a, b, g);
- b.series.fireEvent("itemmouseover", b.series, b, g)
- }
- }
- if (b) {
- a.fireEvent("item" + g.type, a, b, g);
- b.series.fireEvent("item" + g.type, b.series, b, g)
- }
- d.lastItem = b
- }
-});
-Ext.define("Ext.chart.series.Cartesian", {
- extend: "Ext.chart.series.Series",
- config: {
- xField: null,
- yField: null,
- xAxis: null,
- yAxis: null
- },
- directions: ["X", "Y"],
- fieldCategoryX: ["X"],
- fieldCategoryY: ["Y"],
- applyXAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- applyYAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- updateXAxis: function(a) {
- a.processData(this)
- },
- updateYAxis: function(a) {
- a.processData(this)
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- getItemForPoint: function(a, g) {
- if (this.getSprites()) {
- var f = this,
- d = f.getSprites()[0],
- b = f.getStore(),
- e, c;
- if (f.getHidden()) {
- return null
- }
- if (d) {
- c = d.getIndexNearPoint(a, g);
- if (c !== -1) {
- e = {
- series: f,
- category: f.getItemInstancing() ? "items" : "markers",
- index: c,
- record: b.getData().items[c],
- field: f.getYField(),
- sprite: d
- };
- return e
- }
- }
- }
- },
- createSprite: function() {
- var c = this,
- a = c.callParent(),
- b = c.getChart(),
- d = c.getXAxis();
- a.setAttributes({
- flipXY: b.getFlipXY(),
- xAxis: d
- });
- if (a.setAggregator && d && d.getAggregator) {
- if (d.getAggregator) {
- a.setAggregator({
- strategy: d.getAggregator()
- })
- } else {
- a.setAggregator({})
- }
- }
- return a
- },
- getSprites: function() {
- var d = this,
- c = this.getChart(),
- e = d.getAnimation() || c && c.getAnimation(),
- b = d.getItemInstancing(),
- f = d.sprites,
- a;
- if (!c) {
- return []
- }
- if (!f.length) {
- a = d.createSprite()
- } else {
- a = f[0]
- }
- if (e) {
- if (b) {
- a.itemsMarker.getTemplate().setAnimation(e)
- }
- a.setAnimation(e)
- }
- return f
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getSubStyleWithTheme(),
- c = a.fillStyle;
- if (Ext.isArray(c)) {
- c = c[0]
- }
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- },
- getXRange: function() {
- return [this.dataRange[0], this.dataRange[2]]
- },
- getYRange: function() {
- return [this.dataRange[1], this.dataRange[3]]
- }
-});
-Ext.define("Ext.chart.series.StackedCartesian", {
- extend: "Ext.chart.series.Cartesian",
- config: {
- stacked: true,
- splitStacks: true,
- fullStack: false,
- fullStackTotal: 100,
- hidden: []
- },
- spriteAnimationCount: 0,
- themeColorCount: function() {
- var b = this,
- a = b.getYField();
- return Ext.isArray(a) ? a.length : 1
- },
- updateStacked: function() {
- this.processData()
- },
- updateSplitStacks: function() {
- this.processData()
- },
- coordinateY: function() {
- return this.coordinateStacked("Y", 1, 2)
- },
- coordinateStacked: function(D, e, m) {
- var F = this,
- f = F.getStore(),
- r = f.getData().items,
- B = r.length,
- c = F["get" + D + "Axis"](),
- x = F.getHidden(),
- a = F.getSplitStacks(),
- z = F.getFullStack(),
- l = F.getFullStackTotal(),
- p = {
- min: 0,
- max: 0
- },
- n = F["fieldCategory" + D],
- C = [],
- o = [],
- E = [],
- h, A = F.getStacked(),
- g = F.getSprites(),
- q = [],
- w, v, u, s, H, y, b, d, G, t;
- if (!g.length) {
- return
- }
- for (w = 0; w < n.length; w++) {
- d = n[w];
- s = F.getFields([d]);
- H = s.length;
- for (v = 0; v < B; v++) {
- C[v] = 0;
- o[v] = 0;
- E[v] = 0
- }
- for (v = 0; v < H; v++) {
- if (!x[v]) {
- q[v] = F.coordinateData(r, s[v], c)
- }
- }
- if (A && z) {
- y = [];
- if (a) {
- b = []
- }
- for (v = 0; v < B; v++) {
- y[v] = 0;
- if (a) {
- b[v] = 0
- }
- for (u = 0; u < H; u++) {
- G = q[u];
- if (!G) {
- continue
- }
- G = G[v];
- if (G >= 0 || !a) {
- y[v] += G
- } else {
- if (G < 0) {
- b[v] += G
- }
- }
- }
- }
- }
- for (v = 0; v < H; v++) {
- t = {};
- if (x[v]) {
- t["dataStart" + d] = C;
- t["data" + d] = C;
- g[v].setAttributes(t);
- continue
- }
- G = q[v];
- if (A) {
- h = [];
- for (u = 0; u < B; u++) {
- if (!G[u]) {
- G[u] = 0
- }
- if (G[u] >= 0 || !a) {
- if (z && y[u]) {
- G[u] *= l / y[u]
- }
- C[u] = o[u];
- o[u] += G[u];
- h[u] = o[u]
- } else {
- if (z && b[u]) {
- G[u] *= l / b[u]
- }
- C[u] = E[u];
- E[u] += G[u];
- h[u] = E[u]
- }
- }
- t["dataStart" + d] = C;
- t["data" + d] = h;
- F.getRangeOfData(C, p);
- F.getRangeOfData(h, p)
- } else {
- t["dataStart" + d] = C;
- t["data" + d] = G;
- F.getRangeOfData(G, p)
- }
- g[v].setAttributes(t)
- }
- }
- F.dataRange[e] = p.min;
- F.dataRange[e + m] = p.max;
- t = {};
- t["dataMin" + D] = p.min;
- t["dataMax" + D] = p.max;
- for (w = 0; w < g.length; w++) {
- g[w].setAttributes(t)
- }
- },
- getFields: function(f) {
- var e = this,
- a = [],
- c, b, d;
- for (b = 0, d = f.length; b < d; b++) {
- c = e["get" + f[b] + "Field"]();
- if (Ext.isArray(c)) {
- a.push.apply(a, c)
- } else {
- a.push(c)
- }
- }
- return a
- },
- updateLabelOverflowPadding: function(a) {
- this.getLabel().setAttributes({
- labelOverflowPadding: a
- })
- },
- getSprites: function() {
- var k = this,
- j = k.getChart(),
- c = k.getAnimation() || j && j.getAnimation(),
- f = k.getFields(k.fieldCategoryY),
- b = k.getItemInstancing(),
- h = k.sprites,
- l, e = k.getHidden(),
- g = false,
- d, a = f.length;
- if (!j) {
- return []
- }
- for (d = 0; d < a; d++) {
- l = h[d];
- if (!l) {
- l = k.createSprite();
- l.setAttributes({
- zIndex: -d
- });
- l.setField(f[d]);
- g = true;
- e.push(false);
- if (b) {
- l.itemsMarker.getTemplate().setAttributes(k.getStyleByIndex(d))
- } else {
- l.setAttributes(k.getStyleByIndex(d))
- }
- }
- if (c) {
- if (b) {
- l.itemsMarker.getTemplate().setAnimation(c)
- }
- l.setAnimation(c)
- }
- }
- if (g) {
- k.updateHidden(e)
- }
- return h
- },
- getItemForPoint: function(k, j) {
- if (this.getSprites()) {
- var h = this,
- b, g, m, a = h.getItemInstancing(),
- f = h.getSprites(),
- l = h.getStore(),
- c = h.getHidden(),
- n, d, e;
- for (b = 0, g = f.length; b < g; b++) {
- if (!c[b]) {
- m = f[b];
- d = m.getIndexNearPoint(k, j);
- if (d !== -1) {
- e = h.getYField();
- n = {
- series: h,
- index: d,
- category: a ? "items" : "markers",
- record: l.getData().items[d],
- field: typeof e === "string" ? e : e[b],
- sprite: m
- };
- return n
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(e) {
- var g = this,
- f = g.getSprites(),
- h = g.getTitle(),
- j = g.getYField(),
- d = g.getHidden(),
- k = f.length === 1,
- b, l, c, a;
- for (c = 0; c < f.length; c++) {
- b = g.getStyleByIndex(c);
- l = b.fillStyle;
- if (h) {
- if (Ext.isArray(h)) {
- a = h[c]
- } else {
- if (k) {
- a = h
- }
- }
- } else {
- if (Ext.isArray(j)) {
- a = j[c]
- } else {
- a = g.getId()
- }
- }
- e.push({
- name: a,
- mark: (Ext.isObject(l) ? l.stops && l.stops[0].color : l) || b.strokeStyle || "black",
- disabled: d[c],
- series: g.getId(),
- index: c
- })
- }
- },
- onSpriteAnimationStart: function(a) {
- this.spriteAnimationCount++;
- if (this.spriteAnimationCount === 1) {
- this.fireEvent("animationstart")
- }
- },
- onSpriteAnimationEnd: function(a) {
- this.spriteAnimationCount--;
- if (this.spriteAnimationCount === 0) {
- this.fireEvent("animationend")
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Series", {
- extend: "Ext.draw.sprite.Sprite",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- inheritableStatics: {
- def: {
- processors: {
- dataMinX: "number",
- dataMaxX: "number",
- dataMinY: "number",
- dataMaxY: "number",
- rangeX: "data",
- rangeY: "data",
- dataX: "data",
- dataY: "data"
- },
- defaults: {
- dataMinX: 0,
- dataMaxX: 1,
- dataMinY: 0,
- dataMaxY: 1,
- rangeX: null,
- rangeY: null,
- dataX: null,
- dataY: null
- },
- triggers: {
- dataX: "bbox",
- dataY: "bbox",
- dataMinX: "bbox",
- dataMaxX: "bbox",
- dataMinY: "bbox",
- dataMaxY: "bbox"
- }
- }
- },
- config: {
- store: null,
- series: null,
- field: null
- }
-});
-Ext.define("Ext.chart.series.sprite.Cartesian", {
- extend: "Ext.chart.series.sprite.Series",
- inheritableStatics: {
- def: {
- processors: {
- labels: "default",
- labelOverflowPadding: "number",
- selectionTolerance: "number",
- flipXY: "bool",
- renderer: "default",
- visibleMinX: "number",
- visibleMinY: "number",
- visibleMaxX: "number",
- visibleMaxY: "number",
- innerWidth: "number",
- innerHeight: "number"
- },
- defaults: {
- labels: null,
- labelOverflowPadding: 10,
- selectionTolerance: 20,
- flipXY: false,
- renderer: null,
- transformFillStroke: false,
- visibleMinX: 0,
- visibleMinY: 0,
- visibleMaxX: 1,
- visibleMaxY: 1,
- innerWidth: 1,
- innerHeight: 1
- },
- triggers: {
- dataX: "dataX,bbox",
- dataY: "dataY,bbox",
- visibleMinX: "panzoom",
- visibleMinY: "panzoom",
- visibleMaxX: "panzoom",
- visibleMaxY: "panzoom",
- innerWidth: "panzoom",
- innerHeight: "panzoom"
- },
- updaters: {
- dataX: function(a) {
- this.processDataX();
- this.scheduleUpdater(a, "dataY", ["dataY"])
- },
- dataY: function() {
- this.processDataY()
- },
- panzoom: function(c) {
- var e = c.visibleMaxX - c.visibleMinX,
- d = c.visibleMaxY - c.visibleMinY,
- b = c.flipXY ? c.innerHeight : c.innerWidth,
- g = !c.flipXY ? c.innerHeight : c.innerWidth,
- a = this.getSurface(),
- f = a ? a.getInherited().rtl : false;
- if (f && !c.flipXY) {
- c.translationX = b + c.visibleMinX * b / e
- } else {
- c.translationX = -c.visibleMinX * b / e
- }
- c.translationY = -c.visibleMinY * g / d;
- c.scalingX = (f && !c.flipXY ? -1 : 1) * b / e;
- c.scalingY = g / d;
- c.scalingCenterX = 0;
- c.scalingCenterY = 0;
- this.applyTransformations(true)
- }
- }
- }
- },
- processDataY: Ext.emptyFn,
- processDataX: Ext.emptyFn,
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.dataMinX;
- b.y = a.dataMinY;
- b.width = a.dataMaxX - a.dataMinX;
- b.height = a.dataMaxY - a.dataMinY
- },
- binarySearch: function(d) {
- var b = this.attr.dataX,
- f = 0,
- a = b.length;
- if (d <= b[0]) {
- return f
- }
- if (d >= b[a - 1]) {
- return a - 1
- }
- while (f + 1 < a) {
- var c = (f + a) >> 1,
- e = b[c];
- if (e === d) {
- return c
- } else {
- if (e < d) {
- f = c
- } else {
- a = c
- }
- }
- }
- return f
- },
- render: function(b, c, g) {
- var f = this,
- a = f.attr,
- e = a.inverseMatrix.clone();
- e.appendMatrix(b.inverseMatrix);
- if (a.dataX === null || a.dataX === undefined) {
- return
- }
- if (a.dataY === null || a.dataY === undefined) {
- return
- }
- if (e.getXX() * e.getYX() || e.getXY() * e.getYY()) {
- console.log("Cartesian Series sprite does not support rotation/sheering");
- return
- }
- var d = e.transformList([
- [g[0] - 1, g[3] + 1],
- [g[0] + g[2] + 1, -1]
- ]);
- d = d[0].concat(d[1]);
- f.renderClipped(b, c, d, g)
- },
- renderClipped: Ext.emptyFn,
- getIndexNearPoint: function(f, e) {
- var w = this,
- q = w.attr.matrix,
- h = w.attr.dataX,
- g = w.attr.dataY,
- k = w.attr.selectionTolerance,
- t, r, c = -1,
- j = q.clone().prependMatrix(w.surfaceMatrix).inverse(),
- u = j.transformPoint([f, e]),
- b = j.transformPoint([f - k, e - k]),
- n = j.transformPoint([f + k, e + k]),
- a = Math.min(b[0], n[0]),
- s = Math.max(b[0], n[0]),
- l = Math.min(b[1], n[1]),
- d = Math.max(b[1], n[1]),
- m, v, o, p;
- for (o = 0, p = h.length; o < p; o++) {
- m = h[o];
- v = g[o];
- if (m > a && m < s && v > l && v < d) {
- if (c === -1 || (Math.abs(m - u[0]) < t) && (Math.abs(v - u[1]) < r)) {
- t = Math.abs(m - u[0]);
- r = Math.abs(v - u[1]);
- c = o
- }
- }
- }
- return c
- }
-});
-Ext.define("Ext.chart.series.sprite.StackedCartesian", {
- extend: "Ext.chart.series.sprite.Cartesian",
- inheritableStatics: {
- def: {
- processors: {
- groupCount: "number",
- groupOffset: "number",
- dataStartY: "data"
- },
- defaults: {
- selectionTolerance: 20,
- groupCount: 1,
- groupOffset: 0,
- dataStartY: null
- },
- triggers: {
- dataStartY: "dataY,bbox"
- }
- }
- },
- getIndexNearPoint: function(e, d) {
- var o = this,
- q = o.attr.matrix,
- h = o.attr.dataX,
- f = o.attr.dataY,
- u = o.attr.dataStartY,
- l = o.attr.selectionTolerance,
- s = 0.5,
- r = Infinity,
- b = -1,
- k = q.clone().prependMatrix(this.surfaceMatrix).inverse(),
- t = k.transformPoint([e, d]),
- a = k.transformPoint([e - l, d - l]),
- n = k.transformPoint([e + l, d + l]),
- m = Math.min(a[1], n[1]),
- c = Math.max(a[1], n[1]),
- j, g;
- for (var p = 0; p < h.length; p++) {
- if (Math.min(u[p], f[p]) <= c && m <= Math.max(u[p], f[p])) {
- j = Math.abs(h[p] - t[0]);
- g = Math.max(-Math.min(f[p] - t[1], t[1] - u[p]), 0);
- if (j < s && g <= r) {
- s = j;
- r = g;
- b = p
- }
- }
- }
- return b
- }
-});
-Ext.define("Ext.chart.series.sprite.Area", {
- alias: "sprite.areaSeries",
- extend: "Ext.chart.series.sprite.StackedCartesian",
- inheritableStatics: {
- def: {
- processors: {
- step: "bool"
- },
- defaults: {
- step: false
- }
- }
- },
- renderClipped: function(q, s, A) {
- var B = this,
- p = B.attr,
- l = p.dataX,
- j = p.dataY,
- C = p.dataStartY,
- t = p.matrix,
- h, g, v, f, d, z, w, e = t.elements[0],
- m = t.elements[4],
- o = t.elements[3],
- k = t.elements[5],
- c = B.surfaceMatrix,
- n = {},
- r = Math.min(A[0], A[2]),
- u = Math.max(A[0], A[2]),
- b = Math.max(0, this.binarySearch(r)),
- a = Math.min(l.length - 1, this.binarySearch(u) + 1);
- s.beginPath();
- z = l[b] * e + m;
- w = j[b] * o + k;
- s.moveTo(z, w);
- if (p.step) {
- d = w;
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, d);
- s.lineTo(h, d = g)
- }
- } else {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, g)
- }
- }
- if (C) {
- if (p.step) {
- f = l[a] * e + m;
- for (v = a; v >= b; v--) {
- h = l[v] * e + m;
- g = C[v] * o + k;
- s.lineTo(f, g);
- s.lineTo(f = h, g)
- }
- } else {
- for (v = a; v >= b; v--) {
- h = l[v] * e + m;
- g = C[v] * o + k;
- s.lineTo(h, g)
- }
- }
- } else {
- s.lineTo(l[a] * e + m, g);
- s.lineTo(l[a] * e + m, k);
- s.lineTo(z, k);
- s.lineTo(z, j[v] * o + k)
- }
- if (p.transformFillStroke) {
- p.matrix.toContext(s)
- }
- s.fill();
- if (p.transformFillStroke) {
- p.inverseMatrix.toContext(s)
- }
- s.beginPath();
- s.moveTo(z, w);
- if (p.step) {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, d);
- s.lineTo(h, d = g);
- n.translationX = c.x(h, g);
- n.translationY = c.y(h, g);
- B.putMarker("markers", n, v, !p.renderer)
- }
- } else {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, g);
- n.translationX = c.x(h, g);
- n.translationY = c.y(h, g);
- B.putMarker("markers", n, v, !p.renderer)
- }
- }
- if (p.transformFillStroke) {
- p.matrix.toContext(s)
- }
- s.stroke()
- }
-});
-Ext.define("Ext.chart.series.Area", {
- extend: "Ext.chart.series.StackedCartesian",
- alias: "series.area",
- type: "area",
- seriesType: "areaSeries",
- requires: ["Ext.chart.series.sprite.Area"],
- config: {
- splitStacks: false
- }
-});
-Ext.define("Ext.chart.series.sprite.Bar", {
- alias: "sprite.barSeries",
- extend: "Ext.chart.series.sprite.StackedCartesian",
- inheritableStatics: {
- def: {
- processors: {
- minBarWidth: "number",
- maxBarWidth: "number",
- minGapWidth: "number",
- radius: "number",
- inGroupGapWidth: "number"
- },
- defaults: {
- minBarWidth: 2,
- maxBarWidth: 100,
- minGapWidth: 5,
- inGroupGapWidth: 3,
- radius: 0
- }
- }
- },
- drawLabel: function(k, i, s, h, o) {
- var q = this,
- n = q.attr,
- f = q.getMarker("labels"),
- d = f.getTemplate(),
- l = q.labelCfg || (q.labelCfg = {}),
- c = q.surfaceMatrix,
- j = n.labelOverflowPadding,
- b = d.attr.display,
- m = d.attr.orientation,
- g, e, a, r, t, p;
- l.x = c.x(i, h);
- l.y = c.y(i, h);
- if (!n.flipXY) {
- l.rotationRads = -Math.PI * 0.5
- } else {
- l.rotationRads = 0
- }
- l.calloutVertical = !n.flipXY;
- switch (m) {
- case "horizontal":
- l.rotationRads = 0;
- l.calloutVertical = false;
- break;
- case "vertical":
- l.rotationRads = -Math.PI * 0.5;
- l.calloutVertical = true;
- break
- }
- l.text = k;
- if (d.attr.renderer) {
- p = [k, f, l, {
- store: q.getStore()
- }, o];
- r = Ext.callback(d.attr.renderer, null, p, 0, q.getSeries());
- if (typeof r === "string") {
- l.text = r
- } else {
- if (typeof r === "object") {
- if ("text" in r) {
- l.text = r.text
- }
- t = true
- }
- }
- }
- a = q.getMarkerBBox("labels", o, true);
- if (!a) {
- q.putMarker("labels", l, o);
- a = q.getMarkerBBox("labels", o, true)
- }
- e = (a.width / 2 + j);
- if (s > h) {
- e = -e
- }
- if ((m === "horizontal" && n.flipXY) || (m === "vertical" && !n.flipXY) || !m) {
- g = (b === "insideStart") ? s + e : h - e
- } else {
- g = (b === "insideStart") ? s + j * 2 : h - j * 2
- }
- l.x = c.x(i, g);
- l.y = c.y(i, g);
- g = (b === "insideStart") ? s - e : h + e;
- l.calloutPlaceX = c.x(i, g);
- l.calloutPlaceY = c.y(i, g);
- g = (b === "insideStart") ? s : h;
- l.calloutStartX = c.x(i, g);
- l.calloutStartY = c.y(i, g);
- if (s > h) {
- e = -e
- }
- if (Math.abs(h - s) <= e * 2 || b === "outside") {
- l.callout = 1
- } else {
- l.callout = 0
- }
- if (t) {
- Ext.apply(l, r)
- }
- q.putMarker("labels", l, o)
- },
- drawBar: function(l, b, d, c, h, k, a, e) {
- var g = this,
- j = {},
- f = g.attr.renderer,
- i;
- j.x = c;
- j.y = h;
- j.width = k - c;
- j.height = a - h;
- j.radius = g.attr.radius;
- if (f) {
- i = Ext.callback(f, null, [g, j, {
- store: g.getStore()
- }, e], 0, g.getSeries());
- Ext.apply(j, i)
- }
- g.putMarker("items", j, e, !f)
- },
- renderClipped: function(G, u, F, C) {
- if (this.cleanRedraw) {
- return
- }
- var q = this,
- o = q.attr,
- w = o.dataX,
- v = o.dataY,
- H = o.labels,
- n = o.dataStartY,
- m = o.groupCount,
- E = o.groupOffset - (m - 1) * 0.5,
- z = o.inGroupGapWidth,
- t = u.lineWidth,
- D = o.matrix,
- B = D.elements[0],
- j = D.elements[3],
- e = D.elements[4],
- d = G.roundPixel(D.elements[5]) - 1,
- J = (B < 0 ? -1 : 1) * B - o.minGapWidth,
- k = (Math.min(J, o.maxBarWidth) - z * (m - 1)) / m,
- A = G.roundPixel(Math.max(o.minBarWidth, k)),
- c = q.surfaceMatrix,
- g, I, b, h, K, a, l = 0.5 * o.lineWidth,
- L = Math.min(F[0], F[2]),
- x = Math.max(F[0], F[2]),
- y = Math.max(0, Math.floor(L)),
- p = Math.min(w.length - 1, Math.ceil(x)),
- f = H && q.getMarker("labels"),
- s, r;
- for (K = y; K <= p; K++) {
- s = n ? n[K] : 0;
- r = v[K];
- a = w[K] * B + e + E * (A + z);
- g = G.roundPixel(a - A / 2) + l;
- h = G.roundPixel(r * j + d + t);
- I = G.roundPixel(a + A / 2) - l;
- b = G.roundPixel(s * j + d + t);
- q.drawBar(u, G, F, g, h - l, I, b - l, K);
- if (f && H[K] != null) {
- q.drawLabel(H[K], a, b, h, K)
- }
- q.putMarker("markers", {
- translationX: c.x(a, h),
- translationY: c.y(a, h)
- }, K, true)
- }
- },
- getIndexNearPoint: function(l, k) {
- var m = this,
- g = m.attr,
- h = g.dataX,
- a = m.getSurface(),
- b = a.getRect() || [0, 0, 0, 0],
- j = b[3],
- e, d, c, n, f = -1;
- if (g.flipXY) {
- e = j - k;
- if (a.getInherited().rtl) {
- d = b[2] - l
- } else {
- d = l
- }
- } else {
- e = l;
- d = j - k
- }
- for (c = 0; c < h.length; c++) {
- n = m.getMarkerBBox("items", c);
- if (Ext.draw.Draw.isPointInBBox(e, d, n)) {
- f = c;
- break
- }
- }
- return f
- }
-});
-Ext.define("Ext.chart.series.Bar", {
- extend: "Ext.chart.series.StackedCartesian",
- alias: "series.bar",
- type: "bar",
- seriesType: "barSeries",
- requires: ["Ext.chart.series.sprite.Bar", "Ext.draw.sprite.Rect"],
- config: {
- itemInstancing: {
- type: "rect",
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- radius: 0
- }
- }
- }
- },
- getItemForPoint: function(a, f) {
- if (this.getSprites()) {
- var d = this,
- c = d.getChart(),
- e = c.getInnerPadding(),
- b = c.getInherited().rtl;
- arguments[0] = a + (b ? e.right : -e.left);
- arguments[1] = f + e.bottom;
- return d.callParent(arguments)
- }
- },
- updateXAxis: function(a) {
- a.setLabelInSpan(true);
- this.callParent(arguments)
- },
- updateHidden: function(a) {
- this.callParent(arguments);
- this.updateStacked()
- },
- updateStacked: function(c) {
- var e = this,
- g = e.getSprites(),
- d = g.length,
- f = [],
- a = {},
- b;
- for (b = 0; b < d; b++) {
- if (!g[b].attr.hidden) {
- f.push(g[b])
- }
- }
- d = f.length;
- if (e.getStacked()) {
- a.groupCount = 1;
- a.groupOffset = 0;
- for (b = 0; b < d; b++) {
- f[b].setAttributes(a)
- }
- } else {
- a.groupCount = f.length;
- for (b = 0; b < d; b++) {
- a.groupOffset = b;
- f[b].setAttributes(a)
- }
- }
- e.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.series.sprite.Bar3D", {
- extend: "Ext.chart.series.sprite.Bar",
- alias: "sprite.bar3dSeries",
- requires: ["Ext.draw.gradient.Linear"],
- inheritableStatics: {
- def: {
- processors: {
- depthWidthRatio: "number",
- saturationFactor: "number",
- brightnessFactor: "number",
- colorSpread: "number"
- },
- defaults: {
- depthWidthRatio: 1 / 3,
- saturationFactor: 1,
- brightnessFactor: 1,
- colorSpread: 1,
- transformFillStroke: true
- },
- triggers: {
- groupCount: "panzoom"
- },
- updaters: {
- panzoom: function(c) {
- var g = this,
- e = c.visibleMaxX - c.visibleMinX,
- d = c.visibleMaxY - c.visibleMinY,
- b = c.flipXY ? c.innerHeight : c.innerWidth,
- h = !c.flipXY ? c.innerHeight : c.innerWidth,
- a = g.getSurface(),
- f = a ? a.getInherited().rtl : false;
- if (f && !c.flipXY) {
- c.translationX = b + c.visibleMinX * b / e
- } else {
- c.translationX = -c.visibleMinX * b / e
- }
- c.translationY = -c.visibleMinY * (h - g.depth) / d;
- c.scalingX = (f && !c.flipXY ? -1 : 1) * b / e;
- c.scalingY = (h - g.depth) / d;
- c.scalingCenterX = 0;
- c.scalingCenterY = 0;
- g.applyTransformations(true)
- }
- }
- }
- },
- config: {
- showStroke: false
- },
- depth: 0,
- drawBar: function(p, b, d, c, l, o, a, h) {
- var k = this,
- i = k.attr,
- n = {},
- j = i.renderer,
- m, g, f, e;
- n.x = (c + o) * 0.5;
- n.y = l;
- n.width = (o - c) * 0.75;
- n.height = a - l;
- n.depth = g = n.width * i.depthWidthRatio;
- n.orientation = i.flipXY ? "horizontal" : "vertical";
- n.saturationFactor = i.saturationFactor;
- n.brightnessFactor = i.brightnessFactor;
- n.colorSpread = i.colorSpread;
- if (g !== k.depth) {
- k.depth = g;
- f = k.getSeries();
- f.fireEvent("depthchange", f, g)
- }
- if (j) {
- e = [k, n, {
- store: k.getStore()
- }, h];
- m = Ext.callback(j, null, e, 0, k.getSeries());
- Ext.apply(n, m)
- }
- k.putMarker("items", n, h, !j)
- }
-});
-Ext.define("Ext.chart.series.sprite.Box", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.box",
- type: "box",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number",
- depth: "number",
- orientation: "enums(vertical,horizontal)",
- showStroke: "bool",
- saturationFactor: "number",
- brightnessFactor: "number",
- colorSpread: "number"
- },
- triggers: {
- x: "bbox",
- y: "bbox",
- width: "bbox",
- height: "bbox",
- depth: "bbox",
- orientation: "bbox"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 8,
- height: 8,
- depth: 8,
- orientation: "vertical",
- showStroke: false,
- saturationFactor: 1,
- brightnessFactor: 1,
- colorSpread: 1,
- lineJoin: "bevel"
- }
- }
- },
- constructor: function(a) {
- this.callParent([a]);
- this.topGradient = new Ext.draw.gradient.Linear({});
- this.rightGradient = new Ext.draw.gradient.Linear({});
- this.frontGradient = new Ext.draw.gradient.Linear({})
- },
- updatePlainBBox: function(d) {
- var c = this.attr,
- b = c.x,
- g = c.y,
- e = c.width,
- a = c.height,
- f = c.depth;
- d.x = b - e * 0.5;
- d.width = e + f;
- if (a > 0) {
- d.y = g;
- d.height = a + f
- } else {
- d.y = g + f;
- d.height = a - f
- }
- },
- render: function(l, m) {
- var u = this,
- k = u.attr,
- r = k.x,
- j = k.y,
- f = j + k.height,
- i = j < f,
- e = k.width * 0.5,
- v = k.depth,
- d = k.orientation === "horizontal",
- g = k.globalAlpha < 1,
- c = k.fillStyle,
- n = Ext.draw.Color.create(c.isGradient ? c.getStops()[0].color : c),
- h = k.saturationFactor,
- o = k.brightnessFactor,
- t = k.colorSpread,
- b = n.getHSV(),
- a = {},
- s, q, p;
- if (!k.showStroke) {
- m.strokeStyle = Ext.draw.Color.RGBA_NONE
- }
- if (i) {
- p = j;
- j = f;
- f = p
- }
- u.topGradient.setDegrees(d ? 0 : 80);
- u.topGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 + t * 0.1) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.11) * o, 0, 1))
- }]);
- u.rightGradient.setDegrees(d ? 45 : 90);
- u.rightGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.14) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 + t * 0.4) * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.32) * o, 0, 1))
- }]);
- if (d) {
- u.frontGradient.setDegrees(0)
- } else {
- u.frontGradient.setRadians(Math.atan2(j - f, e * 2))
- }
- u.frontGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 - t * 0.1) * h, 0, 1), Ext.Number.constrain((0.5 + t * 0.1) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 + t * 0.1) * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.23) * o, 0, 1))
- }]);
- if (g || i) {
- m.beginPath();
- m.moveTo(r - e, f);
- m.lineTo(r - e + v, f + v);
- m.lineTo(r + e + v, f + v);
- m.lineTo(r + e, f);
- m.closePath();
- a.x = r - e;
- a.y = j;
- a.width = e + v;
- a.height = v;
- m.fillStyle = (d ? u.rightGradient : u.topGradient).generateGradient(m, a);
- m.fillStroke(k)
- }
- if (g) {
- m.beginPath();
- m.moveTo(r - e, j);
- m.lineTo(r - e + v, j + v);
- m.lineTo(r - e + v, f + v);
- m.lineTo(r - e, f);
- m.closePath();
- a.x = r + e;
- a.y = f;
- a.width = v;
- a.height = j + v - f;
- m.fillStyle = (d ? u.topGradient : u.rightGradient).generateGradient(m, a);
- m.fillStroke(k)
- }
- q = l.roundPixel(j);
- m.beginPath();
- m.moveTo(r - e, q);
- m.lineTo(r - e + v, j + v);
- m.lineTo(r + e + v, j + v);
- m.lineTo(r + e, q);
- m.closePath();
- a.x = r - e;
- a.y = j;
- a.width = e + v;
- a.height = v;
- m.fillStyle = (d ? u.rightGradient : u.topGradient).generateGradient(m, a);
- m.fillStroke(k);
- s = l.roundPixel(r + e);
- m.beginPath();
- m.moveTo(s, l.roundPixel(j));
- m.lineTo(r + e + v, j + v);
- m.lineTo(r + e + v, f + v);
- m.lineTo(s, f);
- m.closePath();
- a.x = r + e;
- a.y = f;
- a.width = v;
- a.height = j + v - f;
- m.fillStyle = (d ? u.topGradient : u.rightGradient).generateGradient(m, a);
- m.fillStroke(k);
- s = l.roundPixel(r + e);
- q = l.roundPixel(j);
- m.beginPath();
- m.moveTo(r - e, f);
- m.lineTo(r - e, q);
- m.lineTo(s, q);
- m.lineTo(s, f);
- m.closePath();
- a.x = r - e;
- a.y = f;
- a.width = e * 2;
- a.height = j - f;
- m.fillStyle = u.frontGradient.generateGradient(m, a);
- m.fillStroke(k)
- }
-});
-Ext.define("Ext.chart.series.Bar3D", {
- extend: "Ext.chart.series.Bar",
- requires: ["Ext.chart.series.sprite.Bar3D", "Ext.chart.series.sprite.Box"],
- alias: "series.bar3d",
- type: "bar3d",
- seriesType: "bar3dSeries",
- config: {
- itemInstancing: {
- type: "box",
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- depth: 0
- }
- }
- },
- highlightCfg: {
- opacity: 0.8
- }
- },
- getSprites: function() {
- var c = this.callParent(arguments),
- b, d, a;
- for (a = 0; a < c.length; a++) {
- b = c[a];
- d = b.attr.zIndex;
- if (d < 0) {
- b.setAttributes({
- zIndex: -d
- })
- }
- if (b.setSeries) {
- b.setSeries(this)
- }
- }
- return c
- },
- getDepth: function() {
- var a = this.getSprites()[0];
- return a ? (a.depth || 0) : 0
- },
- getItemForPoint: function(m, k) {
- if (this.getSprites()) {
- var j = this,
- b, o, a = j.getItemInstancing(),
- h = j.getSprites(),
- n = j.getStore(),
- c = j.getHidden(),
- g = j.getChart(),
- l = g.getInnerPadding(),
- f = g.getInherited().rtl,
- p, d, e;
- m = m + (f ? l.right : -l.left);
- k = k + l.bottom;
- for (b = h.length - 1; b >= 0; b--) {
- if (!c[b]) {
- o = h[b];
- d = o.getIndexNearPoint(m, k);
- if (d !== -1) {
- e = j.getYField();
- p = {
- series: j,
- index: d,
- category: a ? "items" : "markers",
- record: n.getData().items[d],
- field: typeof e === "string" ? e : e[b],
- sprite: o
- };
- return p
- }
- }
- }
- return null
- }
- }
-});
-Ext.define("Ext.draw.LimitedCache", {
- config: {
- limit: 40,
- feeder: function() {
- return 0
- },
- scope: null
- },
- cache: null,
- constructor: function(a) {
- this.cache = {};
- this.cache.list = [];
- this.cache.tail = 0;
- this.initConfig(a)
- },
- get: function(e) {
- var c = this.cache,
- b = this.getLimit(),
- a = this.getFeeder(),
- d = this.getScope() || this;
- if (c[e]) {
- return c[e].value
- }
- if (c.list[c.tail]) {
- delete c[c.list[c.tail].cacheId]
- }
- c[e] = c.list[c.tail] = {
- value: a.apply(d, Array.prototype.slice.call(arguments, 1)),
- cacheId: e
- };
- c.tail++;
- if (c.tail === b) {
- c.tail = 0
- }
- return c[e].value
- },
- clear: function() {
- this.cache = {};
- this.cache.list = [];
- this.cache.tail = 0
- }
-});
-Ext.define("Ext.draw.SegmentTree", {
- config: {
- strategy: "double"
- },
- time: function(m, l, n, c, E, d, e) {
- var f = 0,
- o, A, s = new Date(n[m.startIdx[0]]),
- x = new Date(n[m.endIdx[l - 1]]),
- D = Ext.Date,
- u = [
- [D.MILLI, 1, "ms1", null],
- [D.MILLI, 2, "ms2", "ms1"],
- [D.MILLI, 5, "ms5", "ms1"],
- [D.MILLI, 10, "ms10", "ms5"],
- [D.MILLI, 50, "ms50", "ms10"],
- [D.MILLI, 100, "ms100", "ms50"],
- [D.MILLI, 500, "ms500", "ms100"],
- [D.SECOND, 1, "s1", "ms500"],
- [D.SECOND, 10, "s10", "s1"],
- [D.SECOND, 30, "s30", "s10"],
- [D.MINUTE, 1, "mi1", "s10"],
- [D.MINUTE, 5, "mi5", "mi1"],
- [D.MINUTE, 10, "mi10", "mi5"],
- [D.MINUTE, 30, "mi30", "mi10"],
- [D.HOUR, 1, "h1", "mi30"],
- [D.HOUR, 6, "h6", "h1"],
- [D.HOUR, 12, "h12", "h6"],
- [D.DAY, 1, "d1", "h12"],
- [D.DAY, 7, "d7", "d1"],
- [D.MONTH, 1, "mo1", "d1"],
- [D.MONTH, 3, "mo3", "mo1"],
- [D.MONTH, 6, "mo6", "mo3"],
- [D.YEAR, 1, "y1", "mo3"],
- [D.YEAR, 5, "y5", "y1"],
- [D.YEAR, 10, "y10", "y5"],
- [D.YEAR, 100, "y100", "y10"]
- ],
- z, b, k = f,
- F = l,
- j = false,
- r = m.startIdx,
- h = m.endIdx,
- w = m.minIdx,
- C = m.maxIdx,
- a = m.open,
- y = m.close,
- g = m.minX,
- q = m.minY,
- p = m.maxX,
- B = m.maxY,
- v, t;
- for (z = 0; l > f + 1 && z < u.length; z++) {
- s = new Date(n[r[0]]);
- b = u[z];
- s = D.align(s, b[0], b[1]);
- if (D.diff(s, x, b[0]) > n.length * 2 * b[1]) {
- continue
- }
- if (b[3] && m.map["time_" + b[3]]) {
- o = m.map["time_" + b[3]][0];
- A = m.map["time_" + b[3]][1]
- } else {
- o = k;
- A = F
- }
- f = l;
- t = s;
- j = true;
- r[l] = r[o];
- h[l] = h[o];
- w[l] = w[o];
- C[l] = C[o];
- a[l] = a[o];
- y[l] = y[o];
- g[l] = g[o];
- q[l] = q[o];
- p[l] = p[o];
- B[l] = B[o];
- t = Ext.Date.add(t, b[0], b[1]);
- for (v = o + 1; v < A; v++) {
- if (n[h[v]] < +t) {
- h[l] = h[v];
- y[l] = y[v];
- if (B[v] > B[l]) {
- B[l] = B[v];
- p[l] = p[v];
- C[l] = C[v]
- }
- if (q[v] < q[l]) {
- q[l] = q[v];
- g[l] = g[v];
- w[l] = w[v]
- }
- } else {
- l++;
- r[l] = r[v];
- h[l] = h[v];
- w[l] = w[v];
- C[l] = C[v];
- a[l] = a[v];
- y[l] = y[v];
- g[l] = g[v];
- q[l] = q[v];
- p[l] = p[v];
- B[l] = B[v];
- t = Ext.Date.add(t, b[0], b[1])
- }
- }
- if (l > f) {
- m.map["time_" + b[2]] = [f, l]
- }
- }
- },
- "double": function(h, u, j, a, t, b, c) {
- var e = 0,
- k, f = 1,
- n, d, v, g, s, l, m, r, q, p, o;
- while (u > e + 1) {
- k = e;
- e = u;
- f += f;
- for (n = k; n < e; n += 2) {
- if (n === e - 1) {
- d = h.startIdx[n];
- v = h.endIdx[n];
- g = h.minIdx[n];
- s = h.maxIdx[n];
- l = h.open[n];
- m = h.close[n];
- r = h.minX[n];
- q = h.minY[n];
- p = h.maxX[n];
- o = h.maxY[n]
- } else {
- d = h.startIdx[n];
- v = h.endIdx[n + 1];
- l = h.open[n];
- m = h.close[n];
- if (h.minY[n] <= h.minY[n + 1]) {
- g = h.minIdx[n];
- r = h.minX[n];
- q = h.minY[n]
- } else {
- g = h.minIdx[n + 1];
- r = h.minX[n + 1];
- q = h.minY[n + 1]
- }
- if (h.maxY[n] >= h.maxY[n + 1]) {
- s = h.maxIdx[n];
- p = h.maxX[n];
- o = h.maxY[n]
- } else {
- s = h.maxIdx[n + 1];
- p = h.maxX[n + 1];
- o = h.maxY[n + 1]
- }
- }
- h.startIdx[u] = d;
- h.endIdx[u] = v;
- h.minIdx[u] = g;
- h.maxIdx[u] = s;
- h.open[u] = l;
- h.close[u] = m;
- h.minX[u] = r;
- h.minY[u] = q;
- h.maxX[u] = p;
- h.maxY[u] = o;
- u++
- }
- h.map["double_" + f] = [e, u]
- }
- },
- none: Ext.emptyFn,
- aggregateData: function(h, a, r, c, d) {
- var b = h.length,
- e = [],
- s = [],
- f = [],
- q = [],
- j = [],
- p = [],
- n = [],
- o = [],
- m = [],
- k = [],
- g = {
- startIdx: e,
- endIdx: s,
- minIdx: f,
- maxIdx: q,
- open: j,
- minX: p,
- minY: n,
- maxX: o,
- maxY: m,
- close: k
- },
- l;
- for (l = 0; l < b; l++) {
- e[l] = l;
- s[l] = l;
- f[l] = l;
- q[l] = l;
- j[l] = a[l];
- p[l] = h[l];
- n[l] = c[l];
- o[l] = h[l];
- m[l] = r[l];
- k[l] = d[l]
- }
- g.map = {
- original: [0, b]
- };
- if (b) {
- this[this.getStrategy()](g, b, h, a, r, c, d)
- }
- return g
- },
- binarySearchMin: function(c, g, a, e) {
- var b = this.dataX;
- if (e <= b[c.startIdx[0]]) {
- return g
- }
- if (e >= b[c.startIdx[a - 1]]) {
- return a - 1
- }
- while (g + 1 < a) {
- var d = (g + a) >> 1,
- f = b[c.startIdx[d]];
- if (f === e) {
- return d
- } else {
- if (f < e) {
- g = d
- } else {
- a = d
- }
- }
- }
- return g
- },
- binarySearchMax: function(c, g, a, e) {
- var b = this.dataX;
- if (e <= b[c.endIdx[0]]) {
- return g
- }
- if (e >= b[c.endIdx[a - 1]]) {
- return a - 1
- }
- while (g + 1 < a) {
- var d = (g + a) >> 1,
- f = b[c.endIdx[d]];
- if (f === e) {
- return d
- } else {
- if (f < e) {
- g = d
- } else {
- a = d
- }
- }
- }
- return a
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- setData: function(d, a, b, c, e) {
- if (!b) {
- e = c = b = a
- }
- this.dataX = d;
- this.dataOpen = a;
- this.dataHigh = b;
- this.dataLow = c;
- this.dataClose = e;
- if (d.length === b.length && d.length === c.length) {
- this.cache = this.aggregateData(d, a, b, c, e)
- }
- },
- getAggregation: function(d, k, i) {
- if (!this.cache) {
- return null
- }
- var c = Infinity,
- g = this.dataX[this.dataX.length - 1] - this.dataX[0],
- l = this.cache.map,
- m = l.original,
- a, e, j, b, f, h;
- for (a in l) {
- e = l[a];
- j = e[1] - e[0] - 1;
- b = g / j;
- if (i <= b && b < c) {
- m = e;
- c = b
- }
- }
- f = Math.max(this.binarySearchMin(this.cache, m[0], m[1], d), m[0]);
- h = Math.min(this.binarySearchMax(this.cache, m[0], m[1], k) + 1, m[1]);
- return {
- data: this.cache,
- start: f,
- end: h
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Aggregative", {
- extend: "Ext.chart.series.sprite.Cartesian",
- requires: ["Ext.draw.LimitedCache", "Ext.draw.SegmentTree"],
- inheritableStatics: {
- def: {
- processors: {
- dataHigh: "data",
- dataLow: "data",
- dataClose: "data"
- },
- aliases: {
- dataOpen: "dataY"
- },
- defaults: {
- dataHigh: null,
- dataLow: null,
- dataClose: null
- }
- }
- },
- config: {
- aggregator: {}
- },
- applyAggregator: function(b, a) {
- return Ext.factory(b, Ext.draw.SegmentTree, a)
- },
- constructor: function() {
- this.callParent(arguments)
- },
- processDataY: function() {
- var d = this,
- b = d.attr,
- e = b.dataHigh,
- a = b.dataLow,
- f = b.dataClose,
- c = b.dataY;
- d.callParent(arguments);
- if (b.dataX && c && c.length > 0) {
- if (e) {
- d.getAggregator().setData(b.dataX, b.dataY, e, a, f)
- } else {
- d.getAggregator().setData(b.dataX, b.dataY)
- }
- }
- },
- getGapWidth: function() {
- return 1
- },
- renderClipped: function(b, c, g, f) {
- var e = this,
- d = Math.min(g[0], g[2]),
- a = Math.max(g[0], g[2]),
- h = e.getAggregator() && e.getAggregator().getAggregation(d, a, (a - d) / f[2] * e.getGapWidth());
- if (h) {
- e.dataStart = h.data.startIdx[h.start];
- e.dataEnd = h.data.endIdx[h.end - 1];
- e.renderAggregates(h.data, h.start, h.end, b, c, g, f)
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.CandleStick", {
- alias: "sprite.candlestickSeries",
- extend: "Ext.chart.series.sprite.Aggregative",
- inheritableStatics: {
- def: {
- processors: {
- raiseStyle: function(b, a) {
- return Ext.merge({}, a || {}, b)
- },
- dropStyle: function(b, a) {
- return Ext.merge({}, a || {}, b)
- },
- barWidth: "number",
- padding: "number",
- ohlcType: "enums(candlestick,ohlc)"
- },
- defaults: {
- raiseStyle: {
- strokeStyle: "green",
- fillStyle: "green"
- },
- dropStyle: {
- strokeStyle: "red",
- fillStyle: "red"
- },
- planar: false,
- barWidth: 15,
- padding: 3,
- lineJoin: "miter",
- miterLimit: 5,
- ohlcType: "candlestick"
- },
- triggers: {
- raiseStyle: "raiseStyle",
- dropStyle: "dropStyle"
- },
- updaters: {
- raiseStyle: function() {
- this.raiseTemplate && this.raiseTemplate.setAttributes(this.attr.raiseStyle)
- },
- dropStyle: function() {
- this.dropTemplate && this.dropTemplate.setAttributes(this.attr.dropStyle)
- }
- }
- }
- },
- candlestick: function(i, c, a, e, h, f, b) {
- var d = Math.min(c, h),
- g = Math.max(c, h);
- i.moveTo(f, e);
- i.lineTo(f, g);
- i.moveTo(f + b, g);
- i.lineTo(f + b, d);
- i.lineTo(f - b, d);
- i.lineTo(f - b, g);
- i.closePath();
- i.moveTo(f, a);
- i.lineTo(f, d)
- },
- ohlc: function(b, d, e, a, f, c, g) {
- b.moveTo(c, e);
- b.lineTo(c, a);
- b.moveTo(c, d);
- b.lineTo(c - g, d);
- b.moveTo(c, f);
- b.lineTo(c + g, f)
- },
- constructor: function() {
- this.callParent(arguments);
- this.raiseTemplate = new Ext.draw.sprite.Rect({
- parent: this
- });
- this.dropTemplate = new Ext.draw.sprite.Rect({
- parent: this
- })
- },
- getGapWidth: function() {
- var a = this.attr,
- b = a.barWidth,
- c = a.padding;
- return b + c
- },
- renderAggregates: function(d, c, b, t, u, z) {
- var D = this,
- s = this.attr,
- j = s.dataX,
- v = s.matrix,
- e = v.getXX(),
- r = v.getYY(),
- l = v.getDX(),
- h = v.getDY(),
- o = s.barWidth / e,
- C, k = s.ohlcType,
- f = Math.round(o * 0.5 * e),
- a = d.open,
- y = d.close,
- B = d.maxY,
- p = d.minY,
- q = d.startIdx,
- m, g, E, n, A, x, w = s.lineWidth * t.devicePixelRatio / 2;
- w -= Math.floor(w);
- u.save();
- C = this.raiseTemplate;
- C.useAttributes(u, z);
- u.beginPath();
- for (x = c; x < b; x++) {
- if (a[x] <= y[x]) {
- m = Math.round(a[x] * r + h) + w;
- g = Math.round(B[x] * r + h) + w;
- E = Math.round(p[x] * r + h) + w;
- n = Math.round(y[x] * r + h) + w;
- A = Math.round(j[q[x]] * e + l) + w;
- D[k](u, m, g, E, n, A, f)
- }
- }
- u.fillStroke(C.attr);
- u.restore();
- u.save();
- C = this.dropTemplate;
- C.useAttributes(u, z);
- u.beginPath();
- for (x = c; x < b; x++) {
- if (a[x] > y[x]) {
- m = Math.round(a[x] * r + h) + w;
- g = Math.round(B[x] * r + h) + w;
- E = Math.round(p[x] * r + h) + w;
- n = Math.round(y[x] * r + h) + w;
- A = Math.round(j[q[x]] * e + l) + w;
- D[k](u, m, g, E, n, A, f)
- }
- }
- u.fillStroke(C.attr);
- u.restore()
- }
-});
-Ext.define("Ext.chart.series.CandleStick", {
- extend: "Ext.chart.series.Cartesian",
- requires: ["Ext.chart.series.sprite.CandleStick"],
- alias: "series.candlestick",
- type: "candlestick",
- seriesType: "candlestickSeries",
- config: {
- openField: null,
- highField: null,
- lowField: null,
- closeField: null
- },
- fieldCategoryY: ["Open", "High", "Low", "Close"],
- themeColorCount: function() {
- return 2
- }
-});
-Ext.define("Ext.chart.series.Polar", {
- extend: "Ext.chart.series.Series",
- config: {
- rotation: 0,
- radius: null,
- center: [0, 0],
- offsetX: 0,
- offsetY: 0,
- showInLegend: true,
- xField: null,
- yField: null,
- angleField: null,
- radiusField: null,
- xAxis: null,
- yAxis: null
- },
- directions: ["X", "Y"],
- fieldCategoryX: ["X"],
- fieldCategoryY: ["Y"],
- deprecatedConfigs: {
- field: "angleField",
- lengthField: "radiusField"
- },
- constructor: function(b) {
- var c = this,
- a = c.getConfigurator(),
- e = a.configs,
- d;
- if (b) {
- for (d in c.deprecatedConfigs) {
- if (d in b && !(b in e)) {
- Ext.raise("'" + d + "' config has been deprecated. Please use the '" + c.deprecatedConfigs[d] + "' config instead.")
- }
- }
- }
- c.callParent([b])
- },
- getXField: function() {
- return this.getAngleField()
- },
- updateXField: function(a) {
- this.setAngleField(a)
- },
- getYField: function() {
- return this.getRadiusField()
- },
- updateYField: function(a) {
- this.setRadiusField(a)
- },
- applyXAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- applyYAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- getXRange: function() {
- return [this.dataRange[0], this.dataRange[2]]
- },
- getYRange: function() {
- return [this.dataRange[1], this.dataRange[3]]
- },
- themeColorCount: function() {
- var c = this,
- a = c.getStore(),
- b = a && a.getCount() || 0;
- return b
- },
- isStoreDependantColorCount: true,
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer(),
- centerX: 0,
- centerY: 0,
- rotationCenterX: 0,
- rotationCenterY: 0
- }
- },
- applyRotation: function(a) {
- return Ext.draw.sprite.AttributeParser.angle(a)
- },
- updateRotation: function(a) {
- var b = this.getSprites();
- if (b && b[0]) {
- b[0].setAttributes({
- baseRotation: a
- })
- }
- }
-});
-Ext.define("Ext.chart.series.Gauge", {
- alias: "series.gauge",
- extend: "Ext.chart.series.Polar",
- type: "gauge",
- seriesType: "pieslice",
- requires: ["Ext.draw.sprite.Sector"],
- config: {
- needle: false,
- needleLength: 90,
- needleWidth: 4,
- donut: 30,
- showInLegend: false,
- value: null,
- colors: null,
- sectors: null,
- minimum: 0,
- maximum: 100,
- rotation: 0,
- totalAngle: Math.PI / 2,
- rect: [0, 0, 1, 1],
- center: [0.5, 0.75],
- radius: 0.5,
- wholeDisk: false
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- updateNeedle: function(b) {
- var a = this,
- d = a.getSprites(),
- c = a.valueToAngle(a.getValue());
- if (d && d.length) {
- d[0].setAttributes({
- startAngle: (b ? c : 0),
- endAngle: c,
- strokeOpacity: (b ? 1 : 0),
- lineWidth: (b ? a.getNeedleWidth() : 0)
- });
- a.doUpdateStyles()
- }
- },
- themeColorCount: function() {
- var c = this,
- a = c.getStore(),
- b = a && a.getCount() || 0;
- return b + (c.getNeedle() ? 0 : 1)
- },
- updateColors: function(a, b) {
- var f = this,
- h = f.getSectors(),
- j = h && h.length,
- e = f.getSprites(),
- c = Ext.Array.clone(a),
- g = a && a.length,
- d;
- if (!g || !a[0]) {
- return
- }
- for (d = 0; d < j; d++) {
- c[d + 1] = h[d].color || c[d + 1] || a[d % g]
- }
- if (e.length) {
- e[0].setAttributes({
- strokeStyle: c[0]
- })
- }
- this.setSubStyle({
- fillStyle: c,
- strokeStyle: c
- });
- this.doUpdateStyles()
- },
- updateRect: function(f) {
- var d = this.getWholeDisk(),
- c = d ? Math.PI : this.getTotalAngle() / 2,
- g = this.getDonut() / 100,
- e, b, a;
- if (c <= Math.PI / 2) {
- e = 2 * Math.sin(c);
- b = 1 - g * Math.cos(c)
- } else {
- e = 2;
- b = 1 - Math.cos(c)
- }
- a = Math.min(f[2] / e, f[3] / b);
- this.setRadius(a);
- this.setCenter([f[2] / 2, a + (f[3] - b * a) / 2])
- },
- updateCenter: function(a) {
- this.setStyle({
- centerX: a[0],
- centerY: a[1],
- rotationCenterX: a[0],
- rotationCenterY: a[1]
- });
- this.doUpdateStyles()
- },
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a - (this.getTotalAngle() + Math.PI) / 2
- });
- this.doUpdateStyles()
- },
- doUpdateShape: function(b, f) {
- var a, d = this.getSectors(),
- c = (d && d.length) || 0,
- e = this.getNeedleLength() / 100;
- a = [b * e, b];
- while (c--) {
- a.push(b)
- }
- this.setSubStyle({
- endRho: a,
- startRho: b / 100 * f
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- var b = this.getDonut();
- this.doUpdateShape(a, b)
- },
- updateDonut: function(b) {
- var a = this.getRadius();
- this.doUpdateShape(a, b)
- },
- valueToAngle: function(a) {
- a = this.applyValue(a);
- return this.getTotalAngle() * (a - this.getMinimum()) / (this.getMaximum() - this.getMinimum())
- },
- applyValue: function(a) {
- return Math.min(this.getMaximum(), Math.max(a, this.getMinimum()))
- },
- updateValue: function(b) {
- var a = this,
- c = a.getNeedle(),
- e = a.valueToAngle(b),
- d = a.getSprites();
- d[0].rendererData.value = b;
- d[0].setAttributes({
- startAngle: (c ? e : 0),
- endAngle: e
- });
- a.doUpdateStyles()
- },
- processData: function() {
- var f = this,
- j = f.getStore(),
- a, d, h, b, g, e = j && j.first(),
- c, i;
- if (e) {
- c = f.getXField();
- if (c) {
- i = e.get(c)
- }
- }
- if (a = f.getXAxis()) {
- d = a.getMinimum();
- h = a.getMaximum();
- b = a.getSprites()[0].fx;
- g = b.getDuration();
- b.setDuration(0);
- if (Ext.isNumber(d)) {
- f.setMinimum(d)
- } else {
- a.setMinimum(f.getMinimum())
- }
- if (Ext.isNumber(h)) {
- f.setMaximum(h)
- } else {
- a.setMaximum(f.getMaximum())
- }
- b.setDuration(g)
- }
- if (!Ext.isNumber(i)) {
- i = f.getMinimum()
- }
- f.setValue(i)
- },
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer(),
- fx: {
- customDurations: {
- translationX: 0,
- translationY: 0,
- rotationCenterX: 0,
- rotationCenterY: 0,
- centerX: 0,
- centerY: 0,
- startRho: 0,
- endRho: 0,
- baseRotation: 0
- }
- }
- }
- },
- normalizeSectors: function(f) {
- var d = this,
- c = (f && f.length) || 0,
- b, e, g, a;
- if (c) {
- for (b = 0; b < c; b++) {
- e = f[b];
- if (typeof e === "number") {
- f[b] = {
- start: (b > 0 ? f[b - 1].end : d.getMinimum()),
- end: Math.min(e, d.getMaximum())
- };
- if (b == (c - 1) && f[b].end < d.getMaximum()) {
- f[b + 1] = {
- start: f[b].end,
- end: d.getMaximum()
- }
- }
- } else {
- if (typeof e.start === "number") {
- g = Math.max(e.start, d.getMinimum())
- } else {
- g = (b > 0 ? f[b - 1].end : d.getMinimum())
- }
- if (typeof e.end === "number") {
- a = Math.min(e.end, d.getMaximum())
- } else {
- a = d.getMaximum()
- }
- f[b].start = g;
- f[b].end = a
- }
- }
- } else {
- f = [{
- start: d.getMinimum(),
- end: d.getMaximum()
- }]
- }
- return f
- },
- getSprites: function() {
- var j = this,
- m = j.getStore(),
- l = j.getValue(),
- c, g;
- if (!m && !Ext.isNumber(l)) {
- return []
- }
- var h = j.getChart(),
- b = j.getAnimation() || h && h.getAnimation(),
- f = j.sprites,
- k = 0,
- o, n, e, d, a = [];
- if (f && f.length) {
- f[0].setAnimation(b);
- return f
- }
- d = {
- store: m,
- field: j.getXField(),
- angleField: j.getXField(),
- value: l,
- series: j
- };
- o = j.createSprite();
- o.setAttributes({
- zIndex: 10
- }, true);
- o.rendererData = d;
- o.rendererIndex = k++;
- a.push(j.getNeedleWidth());
- j.getLabel().getTemplate().setField(true);
- n = j.normalizeSectors(j.getSectors());
- for (c = 0, g = n.length; c < g; c++) {
- e = {
- startAngle: j.valueToAngle(n[c].start),
- endAngle: j.valueToAngle(n[c].end),
- label: n[c].label,
- fillStyle: n[c].color,
- strokeOpacity: 0,
- doCallout: false,
- labelOverflowPadding: -1
- };
- Ext.apply(e, n[c].style);
- o = j.createSprite();
- o.rendererData = d;
- o.rendererIndex = k++;
- o.setAttributes(e, true);
- a.push(e.lineWidth)
- }
- j.setSubStyle({
- lineWidth: a
- });
- j.doUpdateStyles();
- return f
- }
-});
-Ext.define("Ext.chart.series.sprite.Line", {
- alias: "sprite.lineSeries",
- extend: "Ext.chart.series.sprite.Aggregative",
- inheritableStatics: {
- def: {
- processors: {
- smooth: "bool",
- fillArea: "bool",
- step: "bool",
- preciseStroke: "bool",
- xAxis: "default",
- yCap: "default"
- },
- defaults: {
- smooth: false,
- fillArea: false,
- step: false,
- preciseStroke: true,
- xAxis: null,
- yCap: Math.pow(2, 20),
- yJump: 50
- },
- triggers: {
- dataX: "dataX,bbox,smooth",
- dataY: "dataY,bbox,smooth",
- smooth: "smooth"
- },
- updaters: {
- smooth: function(a) {
- var c = a.dataX,
- b = a.dataY;
- if (a.smooth && c && b && c.length > 2 && b.length > 2) {
- this.smoothX = Ext.draw.Draw.spline(c);
- this.smoothY = Ext.draw.Draw.spline(b)
- } else {
- delete this.smoothX;
- delete this.smoothY
- }
- }
- }
- }
- },
- list: null,
- updatePlainBBox: function(d) {
- var b = this.attr,
- c = Math.min(0, b.dataMinY),
- a = Math.max(0, b.dataMaxY);
- d.x = b.dataMinX;
- d.y = c;
- d.width = b.dataMaxX - b.dataMinX;
- d.height = a - c
- },
- drawStrip: function(a, c) {
- a.moveTo(c[0], c[1]);
- for (var b = 2, d = c.length; b < d; b += 2) {
- a.lineTo(c[b], c[b + 1])
- }
- },
- drawStraightStroke: function(p, q, e, d, u, h) {
- var w = this,
- o = w.attr,
- n = o.renderer,
- g = o.step,
- a = true,
- l = {
- type: "line",
- smooth: false,
- step: g
- },
- m = [],
- l, z, v, f, k, j, t, c, s, b, r;
- for (r = 3; r < u.length; r += 3) {
- t = u[r - 3];
- c = u[r - 2];
- k = u[r];
- j = u[r + 1];
- s = u[r + 3];
- b = u[r + 4];
- if (n) {
- l.x = k;
- l.y = j;
- l.x0 = t;
- l.y0 = c;
- v = [w, l, w.rendererData, e + r / 3];
- z = Ext.callback(n, null, v, 0, w.getSeries())
- }
- if (Ext.isNumber(k + j + t + c)) {
- if (a) {
- q.beginPath();
- q.moveTo(t, c);
- m.push(t, c);
- f = t;
- a = false
- }
- } else {
- continue
- }
- if (g) {
- q.lineTo(k, c);
- m.push(k, c)
- }
- q.lineTo(k, j);
- m.push(k, j);
- if (z || !(Ext.isNumber(s + b))) {
- q.save();
- Ext.apply(q, z);
- if (o.fillArea) {
- q.lineTo(k, h);
- q.lineTo(f, h);
- q.closePath();
- q.fill()
- }
- q.beginPath();
- w.drawStrip(q, m);
- m = [];
- q.stroke();
- q.restore();
- q.beginPath();
- a = true
- }
- }
- },
- calculateScale: function(c, a) {
- var b = 0,
- d = c;
- while (d < a && c > 0) {
- b++;
- d += c >> b
- }
- return Math.pow(2, b > 0 ? b - 1 : b)
- },
- drawSmoothStroke: function(u, v, c, b, C, f) {
- var G = this,
- t = G.attr,
- d = t.step,
- z = t.matrix,
- s = t.renderer,
- e = z.getXX(),
- p = z.getYY(),
- m = z.getDX(),
- k = z.getDY(),
- r = G.smoothX,
- q = G.smoothY,
- I = G.calculateScale(t.dataX.length, b),
- o, F, n, E, h, g, B, a, A, w, H, D, l = {
- type: "line",
- smooth: true,
- step: d
- };
- v.beginPath();
- v.moveTo(r[c * 3] * e + m, q[c * 3] * p + k);
- for (A = 0, w = c * 3 + 1; A < C.length - 3; A += 3, w += 3 * I) {
- o = r[w] * e + m;
- F = q[w] * p + k;
- n = r[w + 1] * e + m;
- E = q[w + 1] * p + k;
- h = u.roundPixel(C[A + 3]);
- g = C[A + 4];
- B = u.roundPixel(C[A]);
- a = C[A + 1];
- if (s) {
- l.x0 = B;
- l.y0 = a;
- l.cx1 = o;
- l.cy1 = F;
- l.cx2 = n;
- l.cy2 = E;
- l.x = h;
- l.y = g;
- D = [G, l, G.rendererData, c + A / 3 + 1];
- H = Ext.callback(s, null, D, 0, G.getSeries());
- v.save();
- Ext.apply(v, H)
- }
- if (t.fillArea) {
- v.moveTo(B, a);
- v.bezierCurveTo(o, F, n, E, h, g);
- v.lineTo(h, f);
- v.lineTo(B, f);
- v.lineTo(B, a);
- v.closePath();
- v.fill();
- v.beginPath()
- }
- v.moveTo(B, a);
- v.bezierCurveTo(o, F, n, E, h, g);
- v.stroke();
- v.moveTo(B, a);
- v.closePath();
- if (s) {
- v.restore()
- }
- v.beginPath();
- v.moveTo(h, g)
- }
- v.beginPath()
- },
- drawLabel: function(k, i, h, o, a) {
- var q = this,
- n = q.attr,
- e = q.getMarker("labels"),
- d = e.getTemplate(),
- m = q.labelCfg || (q.labelCfg = {}),
- c = q.surfaceMatrix,
- g, f, j = n.labelOverflowPadding,
- l, b, r, p, s;
- m.x = c.x(i, h);
- m.y = c.y(i, h);
- if (n.flipXY) {
- m.rotationRads = Math.PI * 0.5
- } else {
- m.rotationRads = 0
- }
- m.text = k;
- if (d.attr.renderer) {
- p = [k, e, m, q.rendererData, o];
- r = Ext.callback(d.attr.renderer, null, p, 0, q.getSeries());
- if (typeof r === "string") {
- m.text = r
- } else {
- if (typeof r === "object") {
- if ("text" in r) {
- m.text = r.text
- }
- s = true
- }
- }
- }
- b = q.getMarkerBBox("labels", o, true);
- if (!b) {
- q.putMarker("labels", m, o);
- b = q.getMarkerBBox("labels", o, true)
- }
- l = b.height / 2;
- g = i;
- switch (d.attr.display) {
- case "under":
- f = h - l - j;
- break;
- case "rotate":
- g += j;
- f = h - j;
- m.rotationRads = -Math.PI / 4;
- break;
- default:
- f = h + l + j
- }
- m.x = c.x(g, f);
- m.y = c.y(g, f);
- if (s) {
- Ext.apply(m, r)
- }
- q.putMarker("labels", m, o)
- },
- drawMarker: function(j, h, d) {
- var g = this,
- e = g.attr,
- f = e.renderer,
- c = g.surfaceMatrix,
- b = {},
- i, a;
- if (f && g.getMarker("markers")) {
- b.type = "marker";
- b.x = j;
- b.y = h;
- a = [g, b, g.rendererData, d];
- i = Ext.callback(f, null, a, 0, g.getSeries());
- if (i) {
- Ext.apply(b, i)
- }
- }
- b.translationX = c.x(j, h);
- b.translationY = c.y(j, h);
- delete b.x;
- delete b.y;
- g.putMarker("markers", b, d, !f)
- },
- drawStroke: function(a, c, h, b, f, e) {
- var d = this,
- g = d.attr.smooth && d.smoothX && d.smoothY;
- if (g) {
- d.drawSmoothStroke(a, c, h, b, f, e)
- } else {
- d.drawStraightStroke(a, c, h, b, f, e)
- }
- },
- renderAggregates: function(B, w, l, N, o, I, D) {
- var m = this,
- k = m.attr,
- s = k.dataX,
- r = k.dataY,
- h = k.labels,
- v = k.xAxis,
- a = k.yCap,
- g = k.smooth && m.smoothX && m.smoothY,
- d = h && m.getMarker("labels"),
- t = m.getMarker("markers"),
- E = k.matrix,
- u = N.devicePixelRatio,
- C = E.getXX(),
- f = E.getYY(),
- c = E.getDX(),
- b = E.getDY(),
- q = m.list || (m.list = []),
- F = B.minX,
- e = B.maxX,
- j = B.minY,
- P = B.maxY,
- U = B.startIdx,
- S = true,
- Q, T, L, K, R, G;
- m.rendererData = {
- store: m.getStore()
- };
- q.length = 0;
- for (R = w; R < l; R++) {
- var O = F[R],
- p = e[R],
- M = j[R],
- n = P[R];
- if (O < p) {
- q.push(O * C + c, M * f + b, U[R]);
- q.push(p * C + c, n * f + b, U[R])
- } else {
- if (O > p) {
- q.push(p * C + c, n * f + b, U[R]);
- q.push(O * C + c, M * f + b, U[R])
- } else {
- q.push(p * C + c, n * f + b, U[R])
- }
- }
- }
- if (q.length) {
- for (R = 0; R < q.length; R += 3) {
- L = q[R];
- K = q[R + 1];
- if (Ext.isNumber(L + K)) {
- if (K > a) {
- K = a
- } else {
- if (K < -a) {
- K = -a
- }
- }
- q[R + 1] = K
- } else {
- S = false;
- continue
- }
- G = q[R + 2];
- if (t) {
- m.drawMarker(L, K, G)
- }
- if (d && h[G]) {
- m.drawLabel(h[G], L, K, G, D)
- }
- }
- m.isContinuousLine = S;
- if (g && !S) {
- Ext.raise("Line smoothing in only supported for gapless data, where all data points are finite numbers.")
- }
- if (v) {
- T = v.getAlignment() === "vertical";
- if (Ext.isNumber(v.floatingAtCoord)) {
- Q = (T ? D[2] : D[3]) - v.floatingAtCoord
- } else {
- Q = T ? D[0] : D[1]
- }
- } else {
- Q = k.flipXY ? D[0] : D[1]
- }
- if (k.preciseStroke) {
- if (k.fillArea) {
- o.fill()
- }
- if (k.transformFillStroke) {
- k.inverseMatrix.toContext(o)
- }
- m.drawStroke(N, o, w, l, q, Q);
- if (k.transformFillStroke) {
- k.matrix.toContext(o)
- }
- o.stroke()
- } else {
- m.drawStroke(N, o, w, l, q, Q);
- if (S && g && k.fillArea && !k.renderer) {
- var A = s[s.length - 1] * C + c + u,
- z = r[r.length - 1] * f + b,
- J = s[0] * C + c - u,
- H = r[0] * f + b;
- o.lineTo(A, z);
- o.lineTo(A, Q - k.lineWidth);
- o.lineTo(J, Q - k.lineWidth);
- o.lineTo(J, H)
- }
- if (k.transformFillStroke) {
- k.matrix.toContext(o)
- }
- if (k.fillArea) {
- o.fillStroke(k, true)
- } else {
- o.stroke(true)
- }
- }
- }
- }
-});
-Ext.define("Ext.chart.series.Line", {
- extend: "Ext.chart.series.Cartesian",
- alias: "series.line",
- type: "line",
- seriesType: "lineSeries",
- requires: ["Ext.chart.series.sprite.Line"],
- config: {
- selectionTolerance: 20,
- smooth: false,
- step: false,
- fill: undefined,
- aggregator: {
- strategy: "double"
- }
- },
- defaultSmoothness: 3,
- overflowBuffer: 1,
- themeMarkerCount: function() {
- return 1
- },
- getDefaultSpriteConfig: function() {
- var d = this,
- e = d.callParent(arguments),
- c = Ext.apply({}, d.getStyle()),
- b, a = false;
- if (typeof d.config.fill != "undefined") {
- if (d.config.fill) {
- a = true;
- if (typeof c.fillStyle == "undefined") {
- if (typeof c.strokeStyle == "undefined") {
- b = d.getStyleWithTheme();
- c.fillStyle = b.fillStyle;
- c.strokeStyle = b.strokeStyle
- } else {
- c.fillStyle = c.strokeStyle
- }
- }
- }
- } else {
- if (c.fillStyle) {
- a = true
- }
- }
- if (!a) {
- delete c.fillStyle
- }
- c = Ext.apply(e || {}, c);
- return Ext.apply(c, {
- fillArea: a,
- step: d.config.step,
- smooth: d.config.smooth,
- selectionTolerance: d.config.selectionTolerance
- })
- },
- updateStep: function(b) {
- var a = this.getSprites()[0];
- if (a && a.attr.step !== b) {
- a.setAttributes({
- step: b
- })
- }
- },
- updateFill: function(b) {
- var a = this.getSprites()[0];
- if (a && a.attr.fillArea !== b) {
- a.setAttributes({
- fillArea: b
- })
- }
- },
- updateSmooth: function(a) {
- var b = this.getSprites()[0];
- if (b && b.attr.smooth !== a) {
- b.setAttributes({
- smooth: a
- })
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.PieSlice", {
- extend: "Ext.draw.sprite.Sector",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- alias: "sprite.pieslice",
- inheritableStatics: {
- def: {
- processors: {
- doCallout: "bool",
- label: "string",
- rotateLabels: "bool",
- labelOverflowPadding: "number",
- renderer: "default"
- },
- defaults: {
- doCallout: true,
- rotateLabels: true,
- label: "",
- labelOverflowPadding: 10,
- renderer: null
- }
- }
- },
- config: {
- rendererData: null,
- rendererIndex: 0,
- series: null
- },
- setGradientBBox: function(q, k) {
- var j = this,
- i = j.attr,
- g = (i.fillStyle && i.fillStyle.isGradient) || (i.strokeStyle && i.strokeStyle.isGradient);
- if (g && !i.constrainGradients) {
- var b = j.getMidAngle(),
- d = i.margin,
- e = i.centerX,
- c = i.centerY,
- a = i.endRho,
- l = i.matrix,
- o = l.getScaleX(),
- n = l.getScaleY(),
- m = o * a,
- f = n * a,
- p = {
- width: m + m,
- height: f + f
- };
- if (d) {
- e += d * Math.cos(b);
- c += d * Math.sin(b)
- }
- p.x = l.x(e, c) - m;
- p.y = l.y(e, c) - f;
- q.setGradientBBox(p)
- } else {
- j.callParent([q, k])
- }
- },
- render: function(b, c, g, f) {
- var e = this,
- a = e.attr,
- h = {},
- d;
- if (a.renderer) {
- h = {
- type: "sector",
- text: a.text,
- centerX: a.centerX,
- centerY: a.centerY,
- margin: a.margin,
- startAngle: Math.min(a.startAngle, a.endAngle),
- endAngle: Math.max(a.startAngle, a.endAngle),
- startRho: Math.min(a.startRho, a.endRho),
- endRho: Math.max(a.startRho, a.endRho)
- };
- d = Ext.callback(a.renderer, null, [e, h, e.rendererData, e.rendererIndex], 0, e.getSeries());
- e.setAttributes(d);
- e.useAttributes(c, g)
- }
- e.callParent([b, c, g, f]);
- if (a.label && e.getMarker("labels")) {
- e.placeLabel()
- }
- },
- placeLabel: function() {
- var z = this,
- s = z.attr,
- r = s.attributeId,
- t = Math.min(s.startAngle, s.endAngle),
- p = Math.max(s.startAngle, s.endAngle),
- k = (t + p) * 0.5,
- n = s.margin,
- h = s.centerX,
- g = s.centerY,
- f = Math.sin(k),
- c = Math.cos(k),
- v = Math.min(s.startRho, s.endRho) + n,
- m = Math.max(s.startRho, s.endRho) + n,
- l = (v + m) * 0.5,
- b = z.surfaceMatrix,
- o = z.labelCfg || (z.labelCfg = {}),
- e = z.getMarker("labels"),
- d = e.getTemplate(),
- a = d.getCalloutLine(),
- q = a && a.length || 40,
- u, j, i, A, w;
- b.appendMatrix(s.matrix);
- o.text = s.label;
- j = h + c * l;
- i = g + f * l;
- o.x = b.x(j, i);
- o.y = b.y(j, i);
- j = h + c * m;
- i = g + f * m;
- o.calloutStartX = b.x(j, i);
- o.calloutStartY = b.y(j, i);
- j = h + c * (m + q);
- i = g + f * (m + q);
- o.calloutPlaceX = b.x(j, i);
- o.calloutPlaceY = b.y(j, i);
- if (!s.rotateLabels) {
- o.rotationRads = 0
- } else {
- switch (d.attr.orientation) {
- case "horizontal":
- o.rotationRads = k + Math.atan2(b.y(1, 0) - b.y(0, 0), b.x(1, 0) - b.x(0, 0)) + Math.PI / 2;
- break;
- case "vertical":
- o.rotationRads = k + Math.atan2(b.y(1, 0) - b.y(0, 0), b.x(1, 0) - b.x(0, 0));
- break
- }
- }
- o.calloutColor = (a && a.color) || z.attr.fillStyle;
- if (a) {
- if (a.width) {
- o.calloutWidth = a.width
- }
- } else {
- o.calloutHasLine = false
- }
- o.globalAlpha = s.globalAlpha * s.fillOpacity;
- o.hidden = (s.startAngle == s.endAngle);
- if (d.attr.renderer) {
- w = [z.attr.label, e, o, z.rendererData, z.rendererIndex];
- A = Ext.callback(d.attr.renderer, null, w, 0, z.getSeries());
- if (typeof A === "string") {
- o.text = A
- } else {
- Ext.apply(o, A)
- }
- }
- z.putMarker("labels", o, r);
- u = z.getMarkerBBox("labels", r, true);
- if (u) {
- if (s.doCallout) {
- if (d.attr.display === "outside") {
- z.putMarker("labels", {
- callout: 1
- }, r)
- } else {
- if (d.attr.display === "inside") {
- z.putMarker("labels", {
- callout: 0
- }, r)
- } else {
- z.putMarker("labels", {
- callout: 1 - z.sliceContainsLabel(s, u)
- }, r)
- }
- }
- } else {
- z.putMarker("labels", {
- globalAlpha: z.sliceContainsLabel(s, u)
- }, r)
- }
- }
- },
- sliceContainsLabel: function(d, f) {
- var e = d.labelOverflowPadding,
- h = (d.endRho + d.startRho) / 2,
- g = h + (f.width + e) / 2,
- i = h - (f.width + e) / 2,
- j, c, b, a;
- if (e < 0) {
- return 1
- }
- if (f.width + e * 2 > (d.endRho - d.startRho)) {
- return 0
- }
- c = Math.sqrt(d.endRho * d.endRho - g * g);
- b = Math.sqrt(d.endRho * d.endRho - i * i);
- j = Math.abs(d.endAngle - d.startAngle);
- a = (j > Math.PI / 2 ? i : Math.abs(Math.tan(j / 2)) * i);
- if (f.height + e * 2 > Math.min(c, b, a) * 2) {
- return 0
- }
- return 1
- }
-});
-Ext.define("Ext.chart.series.Pie", {
- extend: "Ext.chart.series.Polar",
- requires: ["Ext.chart.series.sprite.PieSlice"],
- type: "pie",
- alias: "series.pie",
- seriesType: "pieslice",
- config: {
- donut: 0,
- rotation: 0,
- clockwise: true,
- totalAngle: 2 * Math.PI,
- hidden: [],
- radiusFactor: 100,
- highlightCfg: {
- margin: 20
- },
- style: {}
- },
- directions: ["X"],
- applyLabel: function(a, b) {
- if (Ext.isObject(a) && !Ext.isString(a.orientation)) {
- Ext.apply(a = Ext.Object.chain(a), {
- orientation: "vertical"
- })
- }
- return this.callParent([a, b])
- },
- updateLabelData: function() {
- var h = this,
- j = h.getStore(),
- g = j.getData().items,
- e = h.getSprites(),
- a = h.getLabel().getTemplate().getField(),
- d = h.getHidden(),
- b, f, c, k;
- if (e.length && a) {
- c = [];
- for (b = 0, f = g.length; b < f; b++) {
- c.push(g[b].get(a))
- }
- for (b = 0, f = e.length; b < f; b++) {
- k = e[b];
- k.setAttributes({
- label: c[b]
- });
- k.putMarker("labels", {
- hidden: d[b]
- }, k.attr.attributeId)
- }
- }
- },
- coordinateX: function() {
- var t = this,
- f = t.getStore(),
- q = f.getData().items,
- c = q.length,
- b = t.getXField(),
- e = t.getYField(),
- l, a = 0,
- m, k, s = 0,
- o = t.getHidden(),
- d = [],
- p, g = 0,
- h = t.getTotalAngle(),
- r = t.getClockwise() ? 1 : -1,
- j = t.getSprites(),
- n;
- if (!j) {
- return
- }
- for (p = 0; p < c; p++) {
- l = Math.abs(Number(q[p].get(b))) || 0;
- k = e && Math.abs(Number(q[p].get(e))) || 0;
- if (!o[p]) {
- a += l;
- if (k > s) {
- s = k
- }
- }
- d[p] = a;
- if (p >= o.length) {
- o[p] = false
- }
- }
- o.length = c;
- t.maxY = s;
- if (a !== 0) {
- m = h / a
- }
- for (p = 0; p < c; p++) {
- j[p].setAttributes({
- startAngle: g,
- endAngle: g = (m ? r * d[p] * m : 0),
- globalAlpha: 1
- })
- }
- if (c < t.sprites.length) {
- for (p = c; p < t.sprites.length; p++) {
- n = t.sprites[p];
- n.getMarker("labels").clear(n.getId());
- n.releaseMarker("labels");
- n.destroy()
- }
- t.sprites.length = c
- }
- for (p = c; p < t.sprites.length; p++) {
- j[p].setAttributes({
- startAngle: h,
- endAngle: h,
- globalAlpha: 0
- })
- }
- t.getChart().refreshLegendStore()
- },
- updateCenter: function(a) {
- this.setStyle({
- translationX: a[0] + this.getOffsetX(),
- translationY: a[1] + this.getOffsetY()
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- this.setStyle({
- startRho: a * this.getDonut() * 0.01,
- endRho: a * this.getRadiusFactor() * 0.01
- });
- this.doUpdateStyles()
- },
- getStyleByIndex: function(c) {
- var g = this,
- j = g.getStore(),
- k = j.getAt(c),
- f = g.getYField(),
- d = g.getRadius(),
- a = {},
- e, b, h;
- if (k) {
- h = f && Math.abs(Number(k.get(f))) || 0;
- e = d * g.getDonut() * 0.01;
- b = d * g.getRadiusFactor() * 0.01;
- a = g.callParent([c]);
- a.startRho = e;
- a.endRho = g.maxY ? (e + (b - e) * h / g.maxY) : b
- }
- return a
- },
- updateDonut: function(b) {
- var a = this.getRadius();
- this.setStyle({
- startRho: a * b * 0.01,
- endRho: a * this.getRadiusFactor() * 0.01
- });
- this.doUpdateStyles()
- },
- rotationOffset: -Math.PI / 2,
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a + this.rotationOffset
- });
- this.doUpdateStyles()
- },
- updateTotalAngle: function(a) {
- this.processData()
- },
- getSprites: function() {
- var k = this,
- h = k.getChart(),
- n = k.getStore();
- if (!h || !n) {
- return []
- }
- k.getColors();
- k.getSubStyle();
- var j = n.getData().items,
- b = j.length,
- d = k.getAnimation() || h && h.getAnimation(),
- g = k.sprites,
- o, l = 0,
- f, e, c = false,
- m = k.getLabel(),
- a = m.getTemplate();
- f = {
- store: n,
- field: k.getXField(),
- angleField: k.getXField(),
- radiusField: k.getYField(),
- series: k
- };
- for (e = 0; e < b; e++) {
- o = g[e];
- if (!o) {
- o = k.createSprite();
- if (k.getHighlight()) {
- o.config.highlight = k.getHighlight();
- o.addModifier("highlight", true)
- }
- if (a.getField()) {
- a.setAttributes({
- labelOverflowPadding: k.getLabelOverflowPadding()
- });
- a.fx.setCustomDurations({
- callout: 200
- })
- }
- o.setAttributes(k.getStyleByIndex(e));
- o.rendererData = f;
- o.rendererIndex = l++;
- c = true
- }
- o.setAnimation(d)
- }
- if (c) {
- k.doUpdateStyles()
- }
- return k.sprites
- },
- betweenAngle: function(d, f, c) {
- var e = Math.PI * 2,
- g = this.rotationOffset;
- if (!this.getClockwise()) {
- d *= -1;
- f *= -1;
- c *= -1;
- f -= g;
- c -= g
- } else {
- f += g;
- c += g
- }
- d -= f;
- c -= f;
- d %= e;
- c %= e;
- d += e;
- c += e;
- d %= e;
- c %= e;
- return d < c || c === 0
- },
- getItemForAngle: function(a) {
- var h = this,
- f = h.getSprites(),
- d;
- a %= Math.PI * 2;
- while (a < 0) {
- a += Math.PI * 2
- }
- if (f) {
- var j = h.getStore(),
- g = j.getData().items,
- c = h.getHidden(),
- b = 0,
- e = j.getCount();
- for (; b < e; b++) {
- if (!c[b]) {
- d = f[b].attr;
- if (d.startAngle <= a && d.endAngle >= a) {
- return {
- series: h,
- sprite: f[b],
- index: b,
- record: g[b],
- field: h.getXField()
- }
- }
- }
- }
- }
- return null
- },
- getItemForPoint: function(f, e) {
- var t = this,
- c = t.getSprites();
- if (c) {
- var s = t.getCenter(),
- q = t.getOffsetX(),
- p = t.getOffsetY(),
- j = f - s[0] + q,
- h = e - s[1] + p,
- b = t.getStore(),
- g = t.getDonut(),
- o = b.getData().items,
- r = Math.atan2(h, j) - t.getRotation(),
- a = Math.sqrt(j * j + h * h),
- l = t.getRadius() * g * 0.01,
- m = t.getHidden(),
- n, d, k;
- for (n = 0, d = o.length; n < d; n++) {
- if (!m[n]) {
- k = c[n].attr;
- if (a >= l + k.margin && a <= k.endRho + k.margin) {
- if (t.betweenAngle(r, k.startAngle, k.endAngle)) {
- return {
- series: t,
- sprite: c[n],
- index: n,
- record: o[n],
- field: t.getXField()
- }
- }
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(f) {
- var h = this,
- j = h.getStore();
- if (j) {
- var g = j.getData().items,
- b = h.getLabel().getTemplate().getField(),
- c = h.getXField(),
- e = h.getHidden(),
- d, a, k;
- for (d = 0; d < g.length; d++) {
- a = h.getStyleByIndex(d);
- k = a.fillStyle;
- if (Ext.isObject(k)) {
- k = k.stops && k.stops[0].color
- }
- f.push({
- name: b ? String(g[d].get(b)) : c + " " + d,
- mark: k || a.strokeStyle || "black",
- disabled: e[d],
- series: h.getId(),
- index: d
- })
- }
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Pie3DPart", {
- extend: "Ext.draw.sprite.Path",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- alias: "sprite.pie3dPart",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- margin: "number",
- thickness: "number",
- bevelWidth: "number",
- distortion: "number",
- baseColor: "color",
- colorSpread: "number",
- baseRotation: "number",
- part: "enums(top,bottom,start,end,innerFront,innerBack,outerFront,outerBack)",
- label: "string"
- },
- aliases: {
- rho: "endRho"
- },
- triggers: {
- centerX: "path,bbox",
- centerY: "path,bbox",
- startAngle: "path,partZIndex",
- endAngle: "path,partZIndex",
- startRho: "path",
- endRho: "path,bbox",
- margin: "path,bbox",
- thickness: "path",
- distortion: "path",
- baseRotation: "path,partZIndex",
- baseColor: "partZIndex,partColor",
- colorSpread: "partColor",
- part: "path,partZIndex",
- globalAlpha: "canvas,alpha"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: Math.PI * 2,
- endAngle: Math.PI * 2,
- startRho: 0,
- endRho: 150,
- margin: 0,
- thickness: 35,
- distortion: 0.5,
- baseRotation: 0,
- baseColor: "white",
- colorSpread: 1,
- miterLimit: 1,
- bevelWidth: 5,
- strokeOpacity: 0,
- part: "top",
- label: ""
- },
- updaters: {
- alpha: "alphaUpdater",
- partColor: "partColorUpdater",
- partZIndex: "partZIndexUpdater"
- }
- }
- },
- bevelParams: [],
- constructor: function(a) {
- this.callParent([a]);
- this.bevelGradient = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: "rgba(255,255,255,0)"
- }, {
- offset: 0.7,
- color: "rgba(255,255,255,0.6)"
- }, {
- offset: 1,
- color: "rgba(255,255,255,0)"
- }]
- })
- },
- alphaUpdater: function(a) {
- var d = this,
- c = a.globalAlpha,
- b = d.oldOpacity;
- if (c !== b && (c === 1 || b === 1)) {
- d.scheduleUpdater(a, "path", ["globalAlpha"]);
- d.oldOpacity = c
- }
- },
- partColorUpdater: function(a) {
- var d = Ext.draw.Color.fly(a.baseColor),
- b = d.toString(),
- e = a.colorSpread,
- c;
- switch (a.part) {
- case "top":
- c = new Ext.draw.gradient.Radial({
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- },
- stops: [{
- offset: 0,
- color: d.createLighter(0.1 * e)
- }, {
- offset: 1,
- color: d.createDarker(0.1 * e)
- }]
- });
- break;
- case "bottom":
- c = new Ext.draw.gradient.Radial({
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- },
- stops: [{
- offset: 0,
- color: d.createDarker(0.2 * e)
- }, {
- offset: 1,
- color: d.toString()
- }]
- });
- break;
- case "outerFront":
- case "outerBack":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.15 * e).toString()
- }, {
- offset: 0.3,
- color: b
- }, {
- offset: 0.8,
- color: d.createLighter(0.2 * e).toString()
- }, {
- offset: 1,
- color: d.createDarker(0.25 * e).toString()
- }]
- });
- break;
- case "start":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 1,
- color: d.createLighter(0.2 * e).toString()
- }]
- });
- break;
- case "end":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 1,
- color: d.createLighter(0.2 * e).toString()
- }]
- });
- break;
- case "innerFront":
- case "innerBack":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 0.2,
- color: d.createLighter(0.2 * e).toString()
- }, {
- offset: 0.7,
- color: b
- }, {
- offset: 1,
- color: d.createDarker(0.1 * e).toString()
- }]
- });
- break
- }
- a.fillStyle = c;
- a.canvasAttributes.fillStyle = c
- },
- partZIndexUpdater: function(a) {
- var c = Ext.draw.sprite.AttributeParser.angle,
- e = a.baseRotation,
- d = a.startAngle,
- b = a.endAngle,
- f;
- switch (a.part) {
- case "top":
- a.zIndex = 5;
- break;
- case "outerFront":
- d = c(d + e);
- b = c(b + e);
- if (d >= 0 && b < 0) {
- f = Math.sin(d)
- } else {
- if (d <= 0 && b > 0) {
- f = Math.sin(b)
- } else {
- if (d >= 0 && b > 0) {
- if (d > b) {
- f = 0
- } else {
- f = Math.max(Math.sin(d), Math.sin(b))
- }
- } else {
- f = 1
- }
- }
- }
- a.zIndex = 4 + f;
- break;
- case "outerBack":
- a.zIndex = 1;
- break;
- case "start":
- a.zIndex = 4 + Math.sin(c(d + e));
- break;
- case "end":
- a.zIndex = 4 + Math.sin(c(b + e));
- break;
- case "innerFront":
- a.zIndex = 2;
- break;
- case "innerBack":
- a.zIndex = 4 + Math.sin(c((d + b) / 2 + e));
- break;
- case "bottom":
- a.zIndex = 0;
- break
- }
- a.dirtyZIndex = true
- },
- updatePlainBBox: function(k) {
- var f = this.attr,
- a = f.part,
- b = f.baseRotation,
- e = f.centerX,
- d = f.centerY,
- j, c, i, h, g, l;
- if (a === "start") {
- c = f.startAngle + b
- } else {
- if (a === "end") {
- c = f.endAngle + b
- }
- }
- if (Ext.isNumber(c)) {
- g = Math.sin(c);
- l = Math.cos(c);
- i = Math.min(e + l * f.startRho, e + l * f.endRho);
- h = d + g * f.startRho * f.distortion;
- k.x = i;
- k.y = h;
- k.width = l * (f.endRho - f.startRho);
- k.height = f.thickness + g * (f.endRho - f.startRho) * 2;
- return
- }
- if (a === "innerFront" || a === "innerBack") {
- j = f.startRho
- } else {
- j = f.endRho
- }
- k.width = j * 2;
- k.height = j * f.distortion * 2 + f.thickness;
- k.x = f.centerX - j;
- k.y = f.centerY - j * f.distortion
- },
- updateTransformedBBox: function(a) {
- if (this.attr.part === "start" || this.attr.part === "end") {
- return this.callParent(arguments)
- }
- return this.updatePlainBBox(a)
- },
- updatePath: function(a) {
- if (!this.attr.globalAlpha) {
- return
- }
- if (this.attr.endAngle < this.attr.startAngle) {
- return
- }
- this[this.attr.part + "Renderer"](a)
- },
- render: function(b, c) {
- var d = this,
- a = d.attr;
- if (!a.globalAlpha) {
- return
- }
- d.callParent([b, c]);
- d.bevelRenderer(b, c);
- if (a.label && d.getMarker("labels")) {
- d.placeLabel()
- }
- },
- placeLabel: function() {
- var z = this,
- u = z.attr,
- t = u.attributeId,
- p = u.margin,
- c = u.distortion,
- i = u.centerX,
- h = u.centerY,
- j = u.baseRotation,
- v = u.startAngle + j,
- r = u.endAngle + j,
- m = (v + r) / 2,
- w = u.startRho + p,
- o = u.endRho + p,
- n = (w + o) / 2,
- a = Math.sin(m),
- b = Math.cos(m),
- e = z.surfaceMatrix,
- g = z.getMarker("labels"),
- f = g.getTemplate(),
- d = f.getCalloutLine(),
- s = d && d.length || 40,
- q = {},
- l, k;
- e.appendMatrix(u.matrix);
- q.text = u.label;
- l = i + b * n;
- k = h + a * n * c;
- q.x = e.x(l, k);
- q.y = e.y(l, k);
- l = i + b * o;
- k = h + a * o * c;
- q.calloutStartX = e.x(l, k);
- q.calloutStartY = e.y(l, k);
- l = i + b * (o + s);
- k = h + a * (o + s) * c;
- q.calloutPlaceX = e.x(l, k);
- q.calloutPlaceY = e.y(l, k);
- q.calloutWidth = 2;
- z.putMarker("labels", q, t);
- z.putMarker("labels", {
- callout: 1
- }, t)
- },
- bevelRenderer: function(b, c) {
- var f = this,
- a = f.attr,
- e = a.bevelWidth,
- g = f.bevelParams,
- d;
- for (d = 0; d < g.length; d++) {
- c.beginPath();
- c.ellipse.apply(c, g[d]);
- c.save();
- c.lineWidth = e;
- c.strokeOpacity = e ? 1 : 0;
- c.strokeGradient = f.bevelGradient;
- c.stroke(a);
- c.restore()
- }
- },
- lidRenderer: function(o, m) {
- var k = this.attr,
- g = k.margin,
- c = k.distortion,
- i = k.centerX,
- h = k.centerY,
- f = k.baseRotation,
- j = k.startAngle + f,
- e = k.endAngle + f,
- d = (j + e) / 2,
- l = k.startRho,
- b = k.endRho,
- n = Math.sin(e),
- a = Math.cos(e);
- i += Math.cos(d) * g;
- h += Math.sin(d) * g * c;
- o.ellipse(i, h + m, l, l * c, 0, j, e, false);
- o.lineTo(i + a * b, h + m + n * b * c);
- o.ellipse(i, h + m, b, b * c, 0, e, j, true);
- o.closePath()
- },
- topRenderer: function(a) {
- this.lidRenderer(a, 0)
- },
- bottomRenderer: function(b) {
- var a = this.attr;
- if (a.globalAlpha < 1 || a.shadowColor !== Ext.draw.Color.RGBA_NONE) {
- this.lidRenderer(b, a.thickness)
- }
- },
- sideRenderer: function(l, s) {
- var o = this.attr,
- k = o.margin,
- g = o.centerX,
- f = o.centerY,
- e = o.distortion,
- h = o.baseRotation,
- p = o.startAngle + h,
- m = o.endAngle + h,
- a = o.thickness,
- q = o.startRho,
- j = o.endRho,
- r = (s === "start" && p) || (s === "end" && m),
- b = Math.sin(r),
- d = Math.cos(r),
- c = o.globalAlpha < 1,
- n = s === "start" && d < 0 || s === "end" && d > 0 || c,
- i;
- if (n) {
- i = (p + m) / 2;
- g += Math.cos(i) * k;
- f += Math.sin(i) * k * e;
- l.moveTo(g + d * q, f + b * q * e);
- l.lineTo(g + d * j, f + b * j * e);
- l.lineTo(g + d * j, f + b * j * e + a);
- l.lineTo(g + d * q, f + b * q * e + a);
- l.closePath()
- }
- },
- startRenderer: function(a) {
- this.sideRenderer(a, "start")
- },
- endRenderer: function(a) {
- this.sideRenderer(a, "end")
- },
- rimRenderer: function(q, e, o, j) {
- var w = this,
- s = w.attr,
- p = s.margin,
- h = s.centerX,
- g = s.centerY,
- d = s.distortion,
- i = s.baseRotation,
- t = Ext.draw.sprite.AttributeParser.angle,
- u = s.startAngle + i,
- r = s.endAngle + i,
- k = t((u + r) / 2),
- a = s.thickness,
- b = s.globalAlpha < 1,
- c, n, v;
- w.bevelParams = [];
- u = t(u);
- r = t(r);
- h += Math.cos(k) * p;
- g += Math.sin(k) * p * d;
- c = u >= 0 && r >= 0;
- n = u <= 0 && r <= 0;
-
- function l() {
- q.ellipse(h, g + a, e, e * d, 0, Math.PI, u, true);
- q.lineTo(h + Math.cos(u) * e, g + Math.sin(u) * e * d);
- v = [h, g, e, e * d, 0, u, Math.PI, false];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function f() {
- q.ellipse(h, g + a, e, e * d, 0, 0, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, 0, true];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function x() {
- q.ellipse(h, g + a, e, e * d, 0, Math.PI, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, Math.PI, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function m() {
- q.ellipse(h, g + a, e, e * d, 0, u, 0, false);
- q.lineTo(h + e, g);
- v = [h, g, e, e * d, 0, 0, u, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- if (j) {
- if (!o || b) {
- if (u >= 0 && r < 0) {
- l()
- } else {
- if (u <= 0 && r > 0) {
- f()
- } else {
- if (u <= 0 && r < 0) {
- if (u > r) {
- q.ellipse(h, g + a, e, e * d, 0, 0, Math.PI, false);
- q.lineTo(h - e, g);
- v = [h, g, e, e * d, 0, Math.PI, 0, true];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- } else {
- if (u > r) {
- l();
- f()
- } else {
- v = [h, g, e, e * d, 0, u, r, false];
- if (c && !o || n && o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d + a);
- q.ellipse(h, g + a, e, e * d, 0, r, u, true);
- q.closePath()
- }
- }
- }
- }
- }
- } else {
- if (o || b) {
- if (u >= 0 && r < 0) {
- x()
- } else {
- if (u <= 0 && r > 0) {
- m()
- } else {
- if (u <= 0 && r < 0) {
- if (u > r) {
- x();
- m()
- } else {
- q.ellipse(h, g + a, e, e * d, 0, u, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, u, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- } else {
- if (u > r) {
- q.ellipse(h, g + a, e, e * d, 0, -Math.PI, 0, false);
- q.lineTo(h + e, g);
- v = [h, g, e, e * d, 0, 0, -Math.PI, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- }
- }
- }
- }
- }
- },
- innerFrontRenderer: function(a) {
- this.rimRenderer(a, this.attr.startRho, true, true)
- },
- innerBackRenderer: function(a) {
- this.rimRenderer(a, this.attr.startRho, true, false)
- },
- outerFrontRenderer: function(a) {
- this.rimRenderer(a, this.attr.endRho, false, true)
- },
- outerBackRenderer: function(a) {
- this.rimRenderer(a, this.attr.endRho, false, false)
- }
-});
-Ext.define("Ext.draw.PathUtil", function() {
- var a = Math.abs,
- c = Math.pow,
- e = Math.cos,
- b = Math.acos,
- d = Math.sqrt,
- f = Math.PI;
- return {
- singleton: true,
- requires: ["Ext.draw.overrides.Path", "Ext.draw.overrides.sprite.Path", "Ext.draw.overrides.sprite.Instancing", "Ext.draw.overrides.Surface"],
- cubicRoots: function(m) {
- var z = m[0],
- x = m[1],
- w = m[2],
- v = m[3];
- if (z === 0) {
- return this.quadraticRoots(x, w, v)
- }
- var s = x / z,
- r = w / z,
- q = v / z,
- k = (3 * r - c(s, 2)) / 9,
- j = (9 * s * r - 27 * q - 2 * c(s, 3)) / 54,
- p = c(k, 3) + c(j, 2),
- n = [],
- h, g, o, l, u, y = Ext.Number.sign;
- if (p >= 0) {
- h = y(j + d(p)) * c(a(j + d(p)), 1 / 3);
- g = y(j - d(p)) * c(a(j - d(p)), 1 / 3);
- n[0] = -s / 3 + (h + g);
- n[1] = -s / 3 - (h + g) / 2;
- n[2] = n[1];
- o = a(d(3) * (h - g) / 2);
- if (o !== 0) {
- n[1] = -1;
- n[2] = -1
- }
- } else {
- l = b(j / d(-c(k, 3)));
- n[0] = 2 * d(-k) * e(l / 3) - s / 3;
- n[1] = 2 * d(-k) * e((l + 2 * f) / 3) - s / 3;
- n[2] = 2 * d(-k) * e((l + 4 * f) / 3) - s / 3
- }
- for (u = 0; u < 3; u++) {
- if (n[u] < 0 || n[u] > 1) {
- n[u] = -1
- }
- }
- return n
- },
- quadraticRoots: function(h, g, n) {
- var m, l, k, j;
- if (h === 0) {
- return this.linearRoot(g, n)
- }
- m = g * g - 4 * h * n;
- if (m === 0) {
- k = [-g / (2 * h)]
- } else {
- if (m > 0) {
- l = d(m);
- k = [(-g - l) / (2 * h), (-g + l) / (2 * h)]
- } else {
- return []
- }
- }
- for (j = 0; j < k.length; j++) {
- if (k[j] < 0 || k[j] > 1) {
- k[j] = -1
- }
- }
- return k
- },
- linearRoot: function(h, g) {
- var i = -g / h;
- if (h === 0 || i < 0 || i > 1) {
- return []
- }
- return [i]
- },
- bezierCoeffs: function(h, g, k, j) {
- var i = [];
- i[0] = -h + 3 * g - 3 * k + j;
- i[1] = 3 * h - 6 * g + 3 * k;
- i[2] = -3 * h + 3 * g;
- i[3] = h;
- return i
- },
- cubicLineIntersections: function(I, G, F, E, l, k, j, h, M, p, K, n) {
- var u = [],
- N = [],
- D = p - n,
- z = K - M,
- y = M * (n - p) - p * (K - M),
- L = this.bezierCoeffs(I, G, F, E),
- J = this.bezierCoeffs(l, k, j, h),
- H, x, w, v, g, q, o, m;
- u[0] = D * L[0] + z * J[0];
- u[1] = D * L[1] + z * J[1];
- u[2] = D * L[2] + z * J[2];
- u[3] = D * L[3] + z * J[3] + y;
- x = this.cubicRoots(u);
- for (H = 0; H < x.length; H++) {
- v = x[H];
- if (v < 0 || v > 1) {
- continue
- }
- g = v * v;
- q = g * v;
- o = L[0] * q + L[1] * g + L[2] * v + L[3];
- m = J[0] * q + J[1] * g + J[2] * v + J[3];
- if ((K - M) !== 0) {
- w = (o - M) / (K - M)
- } else {
- w = (m - p) / (n - p)
- }
- if (!(w < 0 || w > 1)) {
- N.push([o, m])
- }
- }
- return N
- },
- splitCubic: function(g, q, p, o, m) {
- var j = m * m,
- n = m * j,
- i = m - 1,
- h = i * i,
- k = i * h,
- l = n * o - 3 * j * i * p + 3 * m * h * q - k * g;
- return [
- [g, m * q - i * g, j * p - 2 * m * i * q + h * g, l],
- [l, j * o - 2 * m * i * p + h * q, m * o - i * p, o]
- ]
- },
- cubicDimension: function(p, o, l, k) {
- var j = 3 * (-p + 3 * (o - l) + k),
- i = 6 * (p - 2 * o + l),
- h = -3 * (p - o),
- q, n, g = Math.min(p, k),
- m = Math.max(p, k),
- r;
- if (j === 0) {
- if (i === 0) {
- return [g, m]
- } else {
- q = -h / i;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- }
- } else {
- r = i * i - 4 * j * h;
- if (r >= 0) {
- r = d(r);
- q = (r - i) / 2 / j;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- if (r > 0) {
- q -= r / j;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- }
- }
- }
- return [g, m]
- },
- interpolateCubic: function(h, g, l, k, i) {
- if (i === 0) {
- return h
- }
- if (i === 1) {
- return k
- }
- var j = (1 - i) / i;
- return i * i * i * (k + j * (3 * l + j * (3 * g + j * h)))
- },
- cubicsIntersections: function(r, q, p, o, A, z, y, v, g, F, E, D, m, l, k, i) {
- var C = this,
- x = C.cubicDimension(r, q, p, o),
- B = C.cubicDimension(A, z, y, v),
- n = C.cubicDimension(g, F, E, D),
- s = C.cubicDimension(m, l, k, i),
- j, h, u, t, w = [];
- if (x[0] > n[1] || x[1] < n[0] || B[0] > s[1] || B[1] < s[0]) {
- return []
- }
- if (a(A - z) < 1 && a(y - v) < 1 && a(r - o) < 1 && a(q - p) < 1 && a(m - l) < 1 && a(k - i) < 1 && a(g - D) < 1 && a(F - E) < 1) {
- return [
- [(r + o) * 0.5, (A + z) * 0.5]
- ]
- }
- j = C.splitCubic(r, q, p, o, 0.5);
- h = C.splitCubic(A, z, y, v, 0.5);
- u = C.splitCubic(g, F, E, D, 0.5);
- t = C.splitCubic(m, l, k, i, 0.5);
- w.push.apply(w, C.cubicsIntersections.apply(C, j[0].concat(h[0], u[0], t[0])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[0].concat(h[0], u[1], t[1])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[1].concat(h[1], u[0], t[0])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[1].concat(h[1], u[1], t[1])));
- return w
- },
- linesIntersection: function(k, p, j, o, h, n, q, m) {
- var l = (j - k) * (m - n) - (o - p) * (q - h),
- i, g;
- if (l === 0) {
- return null
- }
- i = ((q - h) * (p - n) - (k - h) * (m - n)) / l;
- g = ((j - k) * (p - n) - (o - p) * (k - h)) / l;
- if (i >= 0 && i <= 1 && g >= 0 && g <= 1) {
- return [k + i * (j - k), p + i * (o - p)]
- }
- return null
- },
- pointOnLine: function(j, m, h, l, g, n) {
- var k, i;
- if (a(h - j) < a(l - m)) {
- i = j;
- j = m;
- m = i;
- i = h;
- h = l;
- l = i;
- i = g;
- g = n;
- n = i
- }
- k = (g - j) / (h - j);
- if (k < 0 || k > 1) {
- return false
- }
- return a(m + k * (l - m) - n) < 4
- },
- pointOnCubic: function(w, u, s, r, l, k, h, g, p, o) {
- var C = this,
- B = C.bezierCoeffs(w, u, s, r),
- A = C.bezierCoeffs(l, k, h, g),
- z, v, n, m, q;
- B[3] -= p;
- A[3] -= o;
- n = C.cubicRoots(B);
- m = C.cubicRoots(A);
- for (z = 0; z < n.length; z++) {
- q = n[z];
- for (v = 0; v < m.length; v++) {
- if (q >= 0 && q <= 1 && a(q - m[v]) < 0.05) {
- return true
- }
- }
- }
- return false
- }
- }
-});
-Ext.define("Ext.chart.series.Pie3D", {
- extend: "Ext.chart.series.Polar",
- requires: ["Ext.chart.series.sprite.Pie3DPart", "Ext.draw.PathUtil"],
- type: "pie3d",
- seriesType: "pie3d",
- alias: "series.pie3d",
- isPie3D: true,
- config: {
- rect: [0, 0, 0, 0],
- thickness: 35,
- distortion: 0.5,
- donut: false,
- hidden: [],
- highlightCfg: {
- margin: 20
- },
- shadow: false
- },
- rotationOffset: -Math.PI / 2,
- setField: function(a) {
- return this.setXField(a)
- },
- getField: function() {
- return this.getXField()
- },
- updateRotation: function(a) {
- this.setStyle({
- baseRotation: a + this.rotationOffset
- });
- this.doUpdateStyles()
- },
- updateDistortion: function() {
- this.setRadius()
- },
- updateThickness: function() {
- this.setRadius()
- },
- updateColors: function(a) {
- this.setSubStyle({
- baseColor: a
- })
- },
- applyShadow: function(a) {
- if (a === true) {
- a = {
- shadowColor: "rgba(0,0,0,0.8)",
- shadowBlur: 30
- }
- } else {
- if (!Ext.isObject(a)) {
- a = {
- shadowColor: Ext.draw.Color.RGBA_NONE
- }
- }
- }
- return a
- },
- updateShadow: function(g) {
- var e = this,
- f = e.getSprites(),
- d = e.spritesPerSlice,
- c = f && f.length,
- b, a;
- for (b = 1; b < c; b += d) {
- a = f[b];
- if (a.attr.part = "bottom") {
- a.setAttributes(g)
- }
- }
- },
- getStyleByIndex: function(b) {
- var d = this.callParent([b]),
- c = this.getStyle(),
- a = d.fillStyle || d.fill || d.color,
- e = c.strokeStyle || c.stroke;
- if (a) {
- d.baseColor = a;
- delete d.fillStyle;
- delete d.fill;
- delete d.color
- }
- if (e) {
- d.strokeStyle = e
- }
- return d
- },
- doUpdateStyles: function() {
- var g = this,
- h = g.getSprites(),
- f = g.spritesPerSlice,
- e = h && h.length,
- c = 0,
- b = 0,
- a, d;
- for (; c < e; c += f, b++) {
- d = g.getStyleByIndex(b);
- for (a = 0; a < f; a++) {
- h[c + a].setAttributes(d)
- }
- }
- },
- coordinateX: function() {
- var w = this,
- m = w.getChart(),
- u = m && m.getAnimation(),
- f = w.getStore(),
- t = f.getData().items,
- d = t.length,
- b = w.getXField(),
- p = w.getRotation(),
- s = w.getHidden(),
- n, c = 0,
- h, e = [],
- k = w.getSprites(),
- a = k.length,
- l = w.spritesPerSlice,
- g = 0,
- o = Math.PI * 2,
- v = 1e-10,
- r, q;
- for (r = 0; r < d; r++) {
- n = Math.abs(Number(t[r].get(b))) || 0;
- if (!s[r]) {
- c += n
- }
- e[r] = c;
- if (r >= s.length) {
- s[r] = false
- }
- }
- s.length = d;
- if (c === 0) {
- return
- }
- h = 2 * Math.PI / c;
- for (r = 0; r < d; r++) {
- e[r] *= h
- }
- for (r = 0; r < a; r++) {
- k[r].setAnimation(u)
- }
- for (r = 0; r < d; r++) {
- for (q = 0; q < l; q++) {
- k[r * l + q].setAttributes({
- startAngle: g,
- endAngle: e[r] - v,
- globalAlpha: 1,
- baseRotation: p
- })
- }
- g = e[r]
- }
- for (r *= l; r < a; r++) {
- k[r].setAnimation(u);
- k[r].setAttributes({
- startAngle: o,
- endAngle: o,
- globalAlpha: 0,
- baseRotation: p
- })
- }
- },
- updateLabelData: function() {
- var l = this,
- m = l.getStore(),
- k = m.getData().items,
- h = l.getSprites(),
- b = l.getLabel().getTemplate().getField(),
- f = l.getHidden(),
- a = l.spritesPerSlice,
- d, c, g, e, n;
- if (h.length && b) {
- e = [];
- for (d = 0, g = k.length; d < g; d++) {
- e.push(k[d].get(b))
- }
- for (d = 0, c = 0, g = h.length; d < g; d += a, c++) {
- n = h[d];
- n.setAttributes({
- label: e[c]
- });
- n.putMarker("labels", {
- hidden: f[c]
- }, n.attr.attributeId)
- }
- }
- },
- applyRadius: function() {
- var f = this,
- d = f.getChart(),
- h = d.getInnerPadding(),
- e = d.getMainRect() || [0, 0, 1, 1],
- c = e[2] - h * 2,
- a = e[3] - h * 2 - f.getThickness(),
- g = c / 2,
- b = g * f.getDistortion();
- if (b > a / 2) {
- return a / (f.getDistortion() * 2)
- } else {
- return g
- }
- },
- getSprites: function() {
- var y = this,
- e = y.getStore();
- if (!e) {
- return []
- }
- var n = y.getChart(),
- p = y.getSurface(),
- t = e.getData().items,
- l = y.spritesPerSlice,
- a = t.length,
- v = y.getAnimation() || n && n.getAnimation(),
- x = y.getCenter(),
- w = y.getOffsetX(),
- u = y.getOffsetY(),
- b = y.getRadius(),
- q = y.getRotation(),
- d = y.getHighlight(),
- c = {
- centerX: x[0] + w,
- centerY: x[1] + u - y.getThickness() / 2,
- endRho: b,
- startRho: b * y.getDonut() / 100,
- thickness: y.getThickness(),
- distortion: y.getDistortion()
- },
- k = y.sprites,
- h = y.getLabel(),
- f = h.getTemplate(),
- m, g, o, s, r;
- for (s = 0; s < a; s++) {
- g = Ext.apply({}, this.getStyleByIndex(s), c);
- if (!k[s * l]) {
- for (r = 0; r < y.partNames.length; r++) {
- o = p.add({
- type: "pie3dPart",
- part: y.partNames[r]
- });
- if (r === 0 && f.getField()) {
- o.bindMarker("labels", h)
- }
- o.fx.setDurationOn("baseRotation", q);
- if (d) {
- o.config.highlight = d;
- o.addModifier("highlight", true)
- }
- o.setAttributes(g);
- k.push(o)
- }
- } else {
- m = k.slice(s * l, (s + 1) * l);
- for (r = 0; r < m.length; r++) {
- o = m[r];
- if (v) {
- o.setAnimation(v)
- }
- o.setAttributes(g)
- }
- }
- }
- return k
- },
- betweenAngle: function(d, f, c) {
- var e = Math.PI * 2,
- g = this.rotationOffset;
- f += g;
- c += g;
- d -= f;
- c -= f;
- d %= e;
- c %= e;
- d += e;
- c += e;
- d %= e;
- c %= e;
- return d < c || c === 0
- },
- getItemForPoint: function(k, j) {
- var h = this,
- g = h.getSprites();
- if (g) {
- var l = h.getStore(),
- b = l.getData().items,
- a = h.spritesPerSlice,
- e = h.getHidden(),
- c, f, m, d;
- for (c = 0, f = b.length; c < f; c++) {
- if (!e[c]) {
- d = c * a;
- m = g[d];
- if (m.hitTest([k, j])) {
- return {
- series: h,
- sprite: g.slice(d, d + a),
- index: c,
- record: b[c],
- category: "sprites",
- field: h.getXField()
- }
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(f) {
- var h = this,
- k = h.getStore();
- if (k) {
- var g = k.getData().items,
- b = h.getLabel().getTemplate().getField(),
- j = h.getField(),
- e = h.getHidden(),
- d, a, c;
- for (d = 0; d < g.length; d++) {
- a = h.getStyleByIndex(d);
- c = a.baseColor;
- f.push({
- name: b ? String(g[d].get(b)) : j + " " + d,
- mark: c || "black",
- disabled: e[d],
- series: h.getId(),
- index: d
- })
- }
- }
- }
-}, function() {
- var b = this.prototype,
- a = Ext.chart.series.sprite.Pie3DPart.def.getInitialConfig().processors.part;
- b.partNames = a.replace(/^enums\(|\)/g, "").split(",");
- b.spritesPerSlice = b.partNames.length
-});
-Ext.define("Ext.chart.series.sprite.Polar", {
- extend: "Ext.chart.series.sprite.Series",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- baseRotation: "number",
- labels: "default",
- labelOverflowPadding: "number"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: 0,
- endAngle: Math.PI,
- startRho: 0,
- endRho: 150,
- baseRotation: 0,
- labels: null,
- labelOverflowPadding: 10
- },
- triggers: {
- centerX: "bbox",
- centerY: "bbox",
- startAngle: "bbox",
- endAngle: "bbox",
- startRho: "bbox",
- endRho: "bbox",
- baseRotation: "bbox"
- }
- }
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.centerX - a.endRho;
- b.y = a.centerY + a.endRho;
- b.width = a.endRho * 2;
- b.height = a.endRho * 2
- }
-});
-Ext.define("Ext.chart.series.sprite.Radar", {
- alias: "sprite.radar",
- extend: "Ext.chart.series.sprite.Polar",
- getDataPointXY: function(d) {
- var u = this,
- n = u.attr,
- f = n.centerX,
- e = n.centerY,
- o = n.matrix,
- t = n.dataMinX,
- s = n.dataMaxX,
- k = n.dataX,
- j = n.dataY,
- l = n.endRho,
- p = n.startRho,
- g = n.baseRotation,
- i, h, m, c, b, a, q;
- if (n.rangeY) {
- q = n.rangeY[1]
- } else {
- q = n.dataMaxY
- }
- c = (k[d] - t) / (s - t + 1) * 2 * Math.PI + g;
- m = j[d] / q * (l - p) + p;
- b = f + Math.cos(c) * m;
- a = e + Math.sin(c) * m;
- i = o.x(b, a);
- h = o.y(b, a);
- return [i, h]
- },
- render: function(a, l) {
- var h = this,
- f = h.attr,
- g = f.dataX,
- b = g.length,
- e = h.surfaceMatrix,
- d = {},
- c, k, j, m;
- l.beginPath();
- for (c = 0; c < b; c++) {
- m = h.getDataPointXY(c);
- k = m[0];
- j = m[1];
- if (c === 0) {
- l.moveTo(k, j)
- }
- l.lineTo(k, j);
- d.translationX = e.x(k, j);
- d.translationY = e.y(k, j);
- h.putMarker("markers", d, c, true)
- }
- l.closePath();
- l.fillStroke(f)
- }
-});
-Ext.define("Ext.chart.series.Radar", {
- extend: "Ext.chart.series.Polar",
- type: "radar",
- seriesType: "radar",
- alias: "series.radar",
- requires: ["Ext.chart.series.sprite.Radar"],
- themeColorCount: function() {
- return 1
- },
- isStoreDependantColorCount: false,
- themeMarkerCount: function() {
- return 1
- },
- updateAngularAxis: function(a) {
- a.processData(this)
- },
- updateRadialAxis: function(a) {
- a.processData(this)
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- updateCenter: function(a) {
- this.setStyle({
- translationX: a[0] + this.getOffsetX(),
- translationY: a[1] + this.getOffsetY()
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- this.setStyle({
- endRho: a
- });
- this.doUpdateStyles()
- },
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a
- });
- this.doUpdateStyles()
- },
- updateTotalAngle: function(a) {
- this.processData()
- },
- getItemForPoint: function(k, j) {
- var h = this,
- m = h.sprites && h.sprites[0],
- f = m.attr,
- g = f.dataX,
- a = g.length,
- l = h.getStore(),
- e = h.getMarker(),
- b, o, p, d, n, c;
- if (h.getHidden()) {
- return null
- }
- if (m && e) {
- c = m.getMarker("markers");
- for (d = 0; d < a; d++) {
- n = c.getBBoxFor(d);
- b = (n.width + n.height) * 0.25;
- p = m.getDataPointXY(d);
- if (Math.abs(p[0] - k) < b && Math.abs(p[1] - j) < b) {
- o = {
- series: h,
- sprite: m,
- index: d,
- category: "markers",
- record: l.getData().items[d],
- field: h.getYField()
- };
- return o
- }
- }
- }
- return h.callParent(arguments)
- },
- getDefaultSpriteConfig: function() {
- var a = this.callParent(),
- b = {
- customDurations: {
- translationX: 0,
- translationY: 0,
- rotationRads: 0,
- dataMinX: 0,
- dataMaxX: 0
- }
- };
- if (a.fx) {
- Ext.apply(a.fx, b)
- } else {
- a.fx = b
- }
- return a
- },
- getSprites: function() {
- var d = this,
- c = d.getChart(),
- e = d.getAnimation() || c && c.getAnimation(),
- b = d.sprites[0],
- a;
- if (!c) {
- return []
- }
- if (!b) {
- b = d.createSprite()
- }
- if (e) {
- a = b.getMarker("markers");
- if (a) {
- a.getTemplate().setAnimation(e)
- }
- b.setAnimation(e)
- }
- return d.sprites
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getSubStyleWithTheme(),
- c = a.fillStyle;
- if (Ext.isArray(c)) {
- c = c[0]
- }
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- }
-});
-Ext.define("Ext.chart.series.sprite.Scatter", {
- alias: "sprite.scatterSeries",
- extend: "Ext.chart.series.sprite.Cartesian",
- renderClipped: function(r, s, w, u) {
- if (this.cleanRedraw) {
- return
- }
- var C = this,
- q = C.attr,
- l = q.dataX,
- h = q.dataY,
- z = q.labels,
- j = C.getSeries(),
- b = z && C.getMarker("labels"),
- t = C.attr.matrix,
- c = t.getXX(),
- p = t.getYY(),
- m = t.getDX(),
- k = t.getDY(),
- n = {},
- D, B, d = r.getInherited().rtl && !q.flipXY ? -1 : 1,
- a, A, o, e, g, f, v;
- if (q.flipXY) {
- a = u[1] - c * d;
- A = u[1] + u[3] + c * d;
- o = u[0] - p;
- e = u[0] + u[2] + p
- } else {
- a = u[0] - c * d;
- A = u[0] + u[2] + c * d;
- o = u[1] - p;
- e = u[1] + u[3] + p
- }
- for (v = 0; v < l.length; v++) {
- g = l[v];
- f = h[v];
- g = g * c + m;
- f = f * p + k;
- if (a <= g && g <= A && o <= f && f <= e) {
- if (q.renderer) {
- n = {
- type: "items",
- translationX: g,
- translationY: f
- };
- B = [C, n, {
- store: C.getStore()
- }, v];
- D = Ext.callback(q.renderer, null, B, 0, j);
- n = Ext.apply(n, D)
- } else {
- n.translationX = g;
- n.translationY = f
- }
- C.putMarker("items", n, v, !q.renderer);
- if (b && z[v]) {
- C.drawLabel(z[v], g, f, v, u)
- }
- }
- }
- },
- drawLabel: function(j, h, g, p, a) {
- var r = this,
- m = r.attr,
- d = r.getMarker("labels"),
- c = d.getTemplate(),
- l = r.labelCfg || (r.labelCfg = {}),
- b = r.surfaceMatrix,
- f, e, i = m.labelOverflowPadding,
- o = m.flipXY,
- k, n, s, q;
- l.text = j;
- n = r.getMarkerBBox("labels", p, true);
- if (!n) {
- r.putMarker("labels", l, p);
- n = r.getMarkerBBox("labels", p, true)
- }
- if (o) {
- l.rotationRads = Math.PI * 0.5
- } else {
- l.rotationRads = 0
- }
- k = n.height / 2;
- f = h;
- switch (c.attr.display) {
- case "under":
- e = g - k - i;
- break;
- case "rotate":
- f += i;
- e = g - i;
- l.rotationRads = -Math.PI / 4;
- break;
- default:
- e = g + k + i
- }
- l.x = b.x(f, e);
- l.y = b.y(f, e);
- if (c.attr.renderer) {
- q = [j, d, l, {
- store: r.getStore()
- }, p];
- s = Ext.callback(c.attr.renderer, null, q, 0, r.getSeries());
- if (typeof s === "string") {
- l.text = s
- } else {
- Ext.apply(l, s)
- }
- }
- r.putMarker("labels", l, p)
- }
-});
-Ext.define("Ext.chart.series.Scatter", {
- extend: "Ext.chart.series.Cartesian",
- alias: "series.scatter",
- type: "scatter",
- seriesType: "scatterSeries",
- requires: ["Ext.chart.series.sprite.Scatter"],
- config: {
- itemInstancing: {
- fx: {
- customDurations: {
- translationX: 0,
- translationY: 0
- }
- }
- }
- },
- themeMarkerCount: function() {
- return 1
- },
- applyMarker: function(b, a) {
- this.getItemInstancing();
- this.setItemInstancing(b);
- return this.callParent(arguments)
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getMarkerStyleByIndex(0),
- c = a.fillStyle;
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- }
-});
-Ext.define("Ext.chart.theme.Blue", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.blue", "chart.theme.Blue"],
- config: {
- baseColor: "#4d7fe6"
- }
-});
-Ext.define("Ext.chart.theme.BlueGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.blue-gradients", "chart.theme.Blue:gradients"],
- config: {
- baseColor: "#4d7fe6",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category1", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category1", "chart.theme.Category1"],
- config: {
- colors: ["#f0a50a", "#c20024", "#2044ba", "#810065", "#7eae29"]
- }
-});
-Ext.define("Ext.chart.theme.Category1Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category1-gradients", "chart.theme.Category1:gradients"],
- config: {
- colors: ["#f0a50a", "#c20024", "#2044ba", "#810065", "#7eae29"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category2", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category2", "chart.theme.Category2"],
- config: {
- colors: ["#6d9824", "#87146e", "#2a9196", "#d39006", "#1e40ac"]
- }
-});
-Ext.define("Ext.chart.theme.Category2Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category2-gradients", "chart.theme.Category2:gradients"],
- config: {
- colors: ["#6d9824", "#87146e", "#2a9196", "#d39006", "#1e40ac"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category3", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category3", "chart.theme.Category3"],
- config: {
- colors: ["#fbbc29", "#ce2e4e", "#7e0062", "#158b90", "#57880e"]
- }
-});
-Ext.define("Ext.chart.theme.Category3Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category3-gradients", "chart.theme.Category3:gradients"],
- config: {
- colors: ["#fbbc29", "#ce2e4e", "#7e0062", "#158b90", "#57880e"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category4", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category4", "chart.theme.Category4"],
- config: {
- colors: ["#ef5773", "#fcbd2a", "#4f770d", "#1d3eaa", "#9b001f"]
- }
-});
-Ext.define("Ext.chart.theme.Category4Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category4-gradients", "chart.theme.Category4:gradients"],
- config: {
- colors: ["#ef5773", "#fcbd2a", "#4f770d", "#1d3eaa", "#9b001f"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category5", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category5", "chart.theme.Category5"],
- config: {
- colors: ["#7eae29", "#fdbe2a", "#910019", "#27b4bc", "#d74dbc"]
- }
-});
-Ext.define("Ext.chart.theme.Category5Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category5-gradients", "chart.theme.Category5:gradients"],
- config: {
- colors: ["#7eae29", "#fdbe2a", "#910019", "#27b4bc", "#d74dbc"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category6", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category6", "chart.theme.Category6"],
- config: {
- colors: ["#44dce1", "#0b2592", "#996e05", "#7fb325", "#b821a1"]
- }
-});
-Ext.define("Ext.chart.theme.Category6Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category6-gradients", "chart.theme.Category6:gradients"],
- config: {
- colors: ["#44dce1", "#0b2592", "#996e05", "#7fb325", "#b821a1"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.DefaultGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.default-gradients", "chart.theme.Base:gradients"],
- config: {
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Green", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.green", "chart.theme.Green"],
- config: {
- baseColor: "#b1da5a"
- }
-});
-Ext.define("Ext.chart.theme.GreenGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.green-gradients", "chart.theme.Green:gradients"],
- config: {
- baseColor: "#b1da5a",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Midnight", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.midnight", "chart.theme.Midnight"],
- config: {
- colors: ["#A837FF", "#4AC0F2", "#FF4D35", "#FF8809", "#61C102", "#FF37EA"],
- chart: {
- defaults: {
- background: "rgb(52, 52, 53)"
- }
- },
- axis: {
- defaults: {
- style: {
- strokeStyle: "rgb(224, 224, 227)"
- },
- label: {
- fillStyle: "rgb(224, 224, 227)"
- },
- title: {
- fillStyle: "rgb(224, 224, 227)"
- },
- grid: {
- strokeStyle: "rgb(112, 112, 115)"
- }
- }
- },
- series: {
- defaults: {
- label: {
- fillStyle: "rgb(224, 224, 227)"
- }
- }
- },
- sprites: {
- text: {
- fillStyle: "rgb(224, 224, 227)"
- }
- }
- }
-});
-Ext.define("Ext.chart.theme.Muted", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.muted", "chart.theme.Muted"],
- config: {
- colors: ["#8ca640", "#974144", "#4091ba", "#8e658e", "#3b8d8b", "#b86465", "#d2af69", "#6e8852", "#3dcc7e", "#a6bed1", "#cbaa4b", "#998baa"]
- }
-});
-Ext.define("Ext.chart.theme.Purple", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.purple", "chart.theme.Purple"],
- config: {
- baseColor: "#da5abd"
- }
-});
-Ext.define("Ext.chart.theme.PurpleGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.purple-gradients", "chart.theme.Purple:gradients"],
- config: {
- baseColor: "#da5abd",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Red", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.red", "chart.theme.Red"],
- config: {
- baseColor: "#e84b67"
- }
-});
-Ext.define("Ext.chart.theme.RedGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.red-gradients", "chart.theme.Red:gradients"],
- config: {
- baseColor: "#e84b67",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Sky", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.sky", "chart.theme.Sky"],
- config: {
- baseColor: "#4ce0e7"
- }
-});
-Ext.define("Ext.chart.theme.SkyGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.sky-gradients", "chart.theme.Sky:gradients"],
- config: {
- baseColor: "#4ce0e7",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Yellow", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.yellow", "chart.theme.Yellow"],
- config: {
- baseColor: "#fec935"
- }
-});
-Ext.define("Ext.chart.theme.YellowGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.yellow-gradients", "chart.theme.Yellow:gradients"],
- config: {
- baseColor: "#fec935",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.draw.Point", {
- requires: ["Ext.draw.Draw", "Ext.draw.Matrix"],
- isPoint: true,
- x: 0,
- y: 0,
- length: 0,
- angle: 0,
- angleUnits: "degrees",
- statics: {
- fly: (function() {
- var a = null;
- return function(b, c) {
- if (!a) {
- a = new Ext.draw.Point()
- }
- a.constructor(b, c);
- return a
- }
- })()
- },
- constructor: function(a, c) {
- var b = this;
- if (typeof a === "number") {
- b.x = a;
- if (typeof c === "number") {
- b.y = c
- } else {
- b.y = a
- }
- } else {
- if (Ext.isArray(a)) {
- b.x = a[0];
- b.y = a[1]
- } else {
- if (a) {
- b.x = a.x;
- b.y = a.y
- }
- }
- }
- b.calculatePolar()
- },
- calculateCartesian: function() {
- var b = this,
- a = b.length,
- c = b.angle;
- if (b.angleUnits === "degrees") {
- c = Ext.draw.Draw.rad(c)
- }
- b.x = Math.cos(c) * a;
- b.y = Math.sin(c) * a
- },
- calculatePolar: function() {
- var b = this,
- a = b.x,
- c = b.y;
- b.length = Math.sqrt(a * a + c * c);
- b.angle = Math.atan2(c, a);
- if (b.angleUnits === "degrees") {
- b.angle = Ext.draw.Draw.degrees(b.angle)
- }
- },
- setX: function(a) {
- this.x = a;
- this.calculatePolar()
- },
- setY: function(a) {
- this.y = a;
- this.calculatePolar()
- },
- set: function(a, b) {
- this.constructor(a, b)
- },
- setAngle: function(a) {
- this.angle = a;
- this.calculateCartesian()
- },
- setLength: function(a) {
- this.length = a;
- this.calculateCartesian()
- },
- setPolar: function(b, a) {
- this.angle = b;
- this.length = a;
- this.calculateCartesian()
- },
- clone: function() {
- return new Ext.draw.Point(this.x, this.y)
- },
- add: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return new Ext.draw.Point(this.x + b.x, this.y + b.y)
- },
- sub: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return new Ext.draw.Point(this.x - b.x, this.y - b.y)
- },
- mul: function(a) {
- return new Ext.draw.Point(this.x * a, this.y * a)
- },
- div: function(a) {
- return new Ext.draw.Point(this.x / a, this.y / a)
- },
- dot: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return this.x * b.x + this.y * b.y
- },
- equals: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return this.x === b.x && this.y === b.y
- },
- rotate: function(f, c) {
- var d, e, b, g, a;
- if (this.angleUnits === "degrees") {
- f = Ext.draw.Draw.rad(f);
- d = Math.sin(f);
- e = Math.cos(f)
- }
- if (c) {
- b = c.x;
- g = c.y
- } else {
- b = 0;
- g = 0
- }
- a = Ext.draw.Matrix.fly([e, d, -d, e, b - e * b + g * d, g - e * g + b * -d]).transformPoint(this);
- return new Ext.draw.Point(a)
- },
- transform: function(a) {
- if (a && a.isMatrix) {
- return new Ext.draw.Point(a.transformPoint(this))
- } else {
- if (arguments.length === 6) {
- return new Ext.draw.Point(Ext.draw.Matrix.fly(arguments).transformPoint(this))
- } else {
- Ext.raise("Invalid parameters.")
- }
- }
- },
- round: function() {
- return new Ext.draw.Point(Math.round(this.x), Math.round(this.y))
- },
- ceil: function() {
- return new Ext.draw.Point(Math.ceil(this.x), Math.ceil(this.y))
- },
- floor: function() {
- return new Ext.draw.Point(Math.floor(this.x), Math.floor(this.y))
- },
- abs: function(a, b) {
- return new Ext.draw.Point(Math.abs(this.x), Math.abs(this.y))
- },
- normalize: function(c) {
- var b = this.x,
- f = this.y,
- a, e, d;
- c = c || 1;
- if (b === 0) {
- a = 0;
- e = c * Ext.Number.sign(f)
- } else {
- d = f / b;
- a = c / Math.sqrt(1 + d * d);
- e = a * d
- }
- return new Ext.draw.Point(a, e)
- },
- getDistanceToLine: function(c, b) {
- if (arguments.length === 4) {
- c = new Ext.draw.Point(arguments[0], arguments[1]);
- b = new Ext.draw.Point(arguments[2], arguments[3])
- }
- var d = b.sub(c).normalize(),
- a = c.sub(this);
- return a.sub(d.mul(a.dot(d)))
- },
- isZero: function() {
- return this.x === 0 && this.y === 0
- },
- isNumber: function() {
- return Ext.isNumber(this.x + this.y)
- }
-});
-Ext.define("Ext.draw.plugin.SpriteEvents", {
- extend: "Ext.plugin.Abstract",
- alias: "plugin.spriteevents",
- requires: ["Ext.draw.PathUtil"],
- mouseMoveEvents: {
- mousemove: true,
- mouseover: true,
- mouseout: true
- },
- spriteMouseMoveEvents: {
- spritemousemove: true,
- spritemouseover: true,
- spritemouseout: true
- },
- init: function(a) {
- var b = "handleEvent";
- this.drawContainer = a;
- a.addElementListener({
- click: b,
- dblclick: b,
- mousedown: b,
- mousemove: b,
- mouseup: b,
- mouseover: b,
- mouseout: b,
- priority: 1001,
- scope: this
- })
- },
- hasSpriteMouseMoveListeners: function() {
- var b = this.drawContainer.hasListeners,
- a;
- for (a in this.spriteMouseMoveEvents) {
- if (a in b) {
- return true
- }
- }
- return false
- },
- hitTestEvent: function(f) {
- var b = this.drawContainer.getItems(),
- a, d, c;
- for (c = b.length - 1; c >= 0; c--) {
- a = b.get(c);
- d = a.hitTestEvent(f);
- if (d) {
- return d
- }
- }
- return null
- },
- handleEvent: function(f) {
- var d = this,
- b = d.drawContainer,
- g = f.type in d.mouseMoveEvents,
- a = d.lastSprite,
- c;
- if (g && !d.hasSpriteMouseMoveListeners()) {
- return
- }
- c = d.hitTestEvent(f);
- if (g && !Ext.Object.equals(c, a)) {
- if (a) {
- b.fireEvent("spritemouseout", a, f)
- }
- if (c) {
- b.fireEvent("spritemouseover", c, f)
- }
- }
- if (c) {
- b.fireEvent("sprite" + f.type, c, f)
- }
- d.lastSprite = c
- }
-});
-Ext.define("Ext.chart.TipSurface", {
- extend: "Ext.draw.Container",
- spriteArray: false,
- renderFirst: true,
- constructor: function(a) {
- this.callParent([a]);
- if (a.sprites) {
- this.spriteArray = [].concat(a.sprites);
- delete a.sprites
- }
- },
- onRender: function() {
- var c = this,
- b = 0,
- a = 0,
- d, e;
- this.callParent(arguments);
- e = c.spriteArray;
- if (c.renderFirst && e) {
- c.renderFirst = false;
- for (a = e.length; b < a; b++) {
- d = c.surface.add(e[b]);
- d.setAttributes({
- hidden: false
- }, true)
- }
- }
- }
-});
-Ext.define("Ext.chart.interactions.ItemInfo", {
- extend: "Ext.chart.interactions.Abstract",
- type: "iteminfo",
- alias: "interaction.iteminfo",
- config: {
- extjsGestures: {
- start: {
- event: "click",
- handler: "onInfoGesture"
- },
- move: {
- event: "mousemove",
- handler: "onInfoGesture"
- },
- end: {
- event: "mouseleave",
- handler: "onInfoGesture"
- }
- }
- },
- item: null,
- onInfoGesture: function(f, a) {
- var c = this,
- b = c.getItemForEvent(f),
- d = b && b.series.tooltip;
- if (d) {
- d.onMouseMove.call(d, f)
- }
- if (b !== c.item) {
- if (b) {
- b.series.showTip(b)
- } else {
- c.item.series.hideTip(c.item)
- }
- c.item = b
- }
- return false
- }
-});
diff --git a/serverside/jsmod/5.4-3/proxmoxlib.js b/serverside/jsmod/5.4-3/proxmoxlib.js
deleted file mode 100644
index 6e316d7..0000000
--- a/serverside/jsmod/5.4-3/proxmoxlib.js
+++ /dev/null
@@ -1,6757 +0,0 @@
-// 1.0-25
-Ext.ns('Proxmox');
-Ext.ns('Proxmox.Setup');
-
-if (!Ext.isDefined(Proxmox.Setup.auth_cookie_name)) {
- throw "Proxmox library not initialized";
-}
-
-// 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
-
- yesText: gettext('Yes'),
- noText: gettext('No'),
- enabledText: gettext('Enabled'),
- disabledText: gettext('Disabled'),
- noneText: gettext('none'),
- errorText: gettext('Error'),
- unknownText: gettext('Unknown'),
- defaultText: gettext('Default'),
- daysText: gettext('days'),
- dayText: gettext('day'),
- runningText: gettext('running'),
- stoppedText: gettext('stopped'),
- neverText: gettext('never'),
- totalText: gettext('Total'),
- usedText: gettext('Used'),
- directoryText: gettext('Directory'),
- stateText: gettext('State'),
- groupText: gettext('Group'),
-
- language_map: {
- zh_CN: 'Chinese (Simplified)',
- zh_TW: 'Chinese (Traditional)',
- ca: 'Catalan',
- da: 'Danish',
- en: 'English',
- eu: 'Euskera (Basque)',
- fr: 'French',
- de: 'German',
- it: 'Italian',
- es: 'Spanish',
- ja: 'Japanese',
- nb: 'Norwegian (Bokmal)',
- nn: 'Norwegian (Nynorsk)',
- fa: 'Persian (Farsi)',
- pl: 'Polish',
- pt_BR: 'Portuguese (Brazil)',
- ru: 'Russian',
- sl: 'Slovenian',
- sv: 'Swedish',
- tr: 'Turkish'
- },
-
- render_language: function (value) {
- if (!value) {
- return Proxmox.Utils.defaultText + ' (English)';
- }
- var text = Proxmox.Utils.language_map[value];
- if (text) {
- return text + ' (' + value + ')';
- }
- return value;
- },
-
- language_array: function() {
- var data = [['__default__', Proxmox.Utils.render_language('')]];
- Ext.Object.each(Proxmox.Utils.language_map, function(key, value) {
- data.push([key, Proxmox.Utils.render_language(value)]);
- });
-
- return data;
- },
-
- getNoSubKeyHtml: function(url) {
- // url http://www.proxmox.com/products/proxmox-ve/subscription-service-plans
- return Ext.String.format('You do not have a valid subscription for this server. Please visit www.proxmox.com to get a list of available options.', url || 'http://www.proxmox.com');
- },
-
- format_boolean_with_default: function(value) {
- if (Ext.isDefined(value) && value !== '__default__') {
- return value ? Proxmox.Utils.yesText : Proxmox.Utils.noText;
- }
- return Proxmox.Utils.defaultText;
- },
-
- format_boolean: function(value) {
- return value ? Proxmox.Utils.yesText : Proxmox.Utils.noText;
- },
-
- format_neg_boolean: function(value) {
- return !value ? Proxmox.Utils.yesText : Proxmox.Utils.noText;
- },
-
- format_enabled_toggle: function(value) {
- return value ? Proxmox.Utils.enabledText : Proxmox.Utils.disabledText;
- },
-
- format_expire: function(date) {
- if (!date) {
- return Proxmox.Utils.neverText;
- }
- return Ext.Date.format(date, "Y-m-d");
- },
-
- format_duration_long: function(ut) {
-
- var days = Math.floor(ut / 86400);
- ut -= days*86400;
- var hours = Math.floor(ut / 3600);
- ut -= hours*3600;
- var mins = Math.floor(ut / 60);
- ut -= mins*60;
-
- var hours_str = '00' + hours.toString();
- hours_str = hours_str.substr(hours_str.length - 2);
- var mins_str = "00" + mins.toString();
- mins_str = mins_str.substr(mins_str.length - 2);
- var ut_str = "00" + ut.toString();
- ut_str = ut_str.substr(ut_str.length - 2);
-
- if (days) {
- var ds = days > 1 ? Proxmox.Utils.daysText : Proxmox.Utils.dayText;
- return days.toString() + ' ' + ds + ' ' +
- hours_str + ':' + mins_str + ':' + ut_str;
- } else {
- return hours_str + ':' + mins_str + ':' + ut_str;
- }
- },
-
- format_subscription_level: function(level) {
- if (level === 'c') {
- return 'Community';
- } else if (level === 'b') {
- return 'Basic';
- } else if (level === 's') {
- return 'Standard';
- } else if (level === 'p') {
- return 'Premium';
- } else {
- return Proxmox.Utils.noneText;
- }
- },
-
- compute_min_label_width: function(text, width) {
-
- if (width === undefined) { width = 100; }
-
- var tm = new Ext.util.TextMetrics();
- var min = tm.getWidth(text + ':');
-
- return min < width ? width : min;
- },
-
- setAuthData: function(data) {
- Proxmox.CSRFPreventionToken = data.CSRFPreventionToken;
- Proxmox.UserName = data.username;
- Proxmox.LoggedOut = data.LoggedOut;
- // creates a session cookie (expire = null)
- // that way the cookie gets deleted after the browser window is closed
- Ext.util.Cookies.set(Proxmox.Setup.auth_cookie_name, data.ticket, null, '/', null, true);
- },
-
- authOK: function() {
- if (Proxmox.LoggedOut) {
- return undefined;
- }
- return (Proxmox.UserName !== '') && Ext.util.Cookies.get(Proxmox.Setup.auth_cookie_name);
- },
-
- authClear: function() {
- if (Proxmox.LoggedOut) {
- return undefined;
- }
- 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, clearMaskBeforeLoad) {
- if (clearMaskBeforeLoad) {
- me.mon(store, 'beforeload', function(s, operation, eOpts) {
- Proxmox.Utils.setErrorMask(me, false);
- });
- } else {
- 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 += " ";
- Ext.Object.each(result.errors, function(prop, desc) {
- msg += "" + Ext.htmlEncode(prop) + " : " +
- 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) {
- if (Proxmox.Utils.toolkit === 'touch') {
- options.waitMsgTarget.setMasked(false);
- } else {
- 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) {
- if (Proxmox.Utils.toolkit === 'touch') {
- options.waitMsgTarget.setMasked(false);
- } else {
- 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) {
- if (Proxmox.Utils.toolkit === 'touch') {
- target.setMasked({ xtype: 'loadmask', message: newopts.waitMsg} );
- } else {
- // Note: ExtJS bug - this does not work when component is not rendered
- target.setLoading(newopts.waitMsg);
- }
- }
- Ext.Ajax.request(newopts);
- },
-
- checked_command: function(orig_cmd) {
- Proxmox.Utils.API2Request({
- url: '/nodes/localhost/subscription',
- method: 'GET',
- //waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- var data = response.result.data;
-
- if (data.status !== 'Active') {
- Ext.Msg.show({
- title: gettext('No valid subscription'),
- icon: Ext.Msg.WARNING,
- msg: Proxmox.Utils.getNoSubKeyHtml(data.url),
- buttons: Ext.Msg.OK,
- callback: function(btn) {
- if (btn !== 'ok') {
- return;
- }
- orig_cmd();
- }
- });
- } else {
- orig_cmd();
- }
- }
- });
- },
-
- assemble_field_data: function(values, data) {
- if (Ext.isObject(data)) {
- Ext.Object.each(data, function(name, val) {
- if (values.hasOwnProperty(name)) {
- var bucket = values[name];
- if (!Ext.isArray(bucket)) {
- bucket = values[name] = [bucket];
- }
- if (Ext.isArray(val)) {
- values[name] = bucket.concat(val);
- } else {
- bucket.push(val);
- }
- } else {
- values[name] = val;
- }
- });
- }
- },
-
- dialog_title: function(subject, create, isAdd) {
- if (create) {
- if (isAdd) {
- return gettext('Add') + ': ' + subject;
- } else {
- return gettext('Create') + ': ' + subject;
- }
- } else {
- return gettext('Edit') + ': ' + subject;
- }
- },
-
- network_iface_types: {
- eth: gettext("Network Device"),
- bridge: 'Linux Bridge',
- bond: 'Linux Bond',
- vlan: 'Linux VLAN',
- OVSBridge: 'OVS Bridge',
- OVSBond: 'OVS Bond',
- OVSPort: 'OVS Port',
- OVSIntPort: 'OVS IntPort'
- },
-
- render_network_iface_type: function(value) {
- return Proxmox.Utils.network_iface_types[value] ||
- Proxmox.Utils.unknownText;
- },
-
- task_desc_table: {
- acmenewcert: [ 'SRV', gettext('Order Certificate') ],
- acmeregister: [ 'ACME Account', gettext('Register') ],
- acmedeactivate: [ 'ACME Account', gettext('Deactivate') ],
- acmeupdate: [ 'ACME Account', gettext('Update') ],
- acmerefresh: [ 'ACME Account', gettext('Refresh') ],
- acmerenew: [ 'SRV', gettext('Renew Certificate') ],
- acmerevoke: [ 'SRV', gettext('Revoke Certificate') ],
- 'move_volume': [ 'CT', gettext('Move Volume') ],
- clustercreate: [ '', gettext('Create Cluster') ],
- clusterjoin: [ '', gettext('Join Cluster') ],
- diskinit: [ 'Disk', gettext('Initialize Disk with GPT') ],
- vncproxy: [ 'VM/CT', gettext('Console') ],
- spiceproxy: [ 'VM/CT', gettext('Console') + ' (Spice)' ],
- vncshell: [ '', gettext('Shell') ],
- spiceshell: [ '', gettext('Shell') + ' (Spice)' ],
- qmsnapshot: [ 'VM', gettext('Snapshot') ],
- qmrollback: [ 'VM', gettext('Rollback') ],
- qmdelsnapshot: [ 'VM', gettext('Delete Snapshot') ],
- qmcreate: [ 'VM', gettext('Create') ],
- qmrestore: [ 'VM', gettext('Restore') ],
- qmdestroy: [ 'VM', gettext('Destroy') ],
- qmigrate: [ 'VM', gettext('Migrate') ],
- qmclone: [ 'VM', gettext('Clone') ],
- qmmove: [ 'VM', gettext('Move disk') ],
- qmtemplate: [ 'VM', gettext('Convert to template') ],
- qmstart: [ 'VM', gettext('Start') ],
- qmstop: [ 'VM', gettext('Stop') ],
- qmreset: [ 'VM', gettext('Reset') ],
- qmshutdown: [ 'VM', gettext('Shutdown') ],
- qmsuspend: [ 'VM', gettext('Hibernate') ],
- qmpause: [ 'VM', gettext('Pause') ],
- qmresume: [ 'VM', gettext('Resume') ],
- qmconfig: [ 'VM', gettext('Configure') ],
- vzsnapshot: [ 'CT', gettext('Snapshot') ],
- vzrollback: [ 'CT', gettext('Rollback') ],
- vzdelsnapshot: [ 'CT', gettext('Delete Snapshot') ],
- vzcreate: ['CT', gettext('Create') ],
- vzrestore: ['CT', gettext('Restore') ],
- vzdestroy: ['CT', gettext('Destroy') ],
- vzmigrate: [ 'CT', gettext('Migrate') ],
- vzclone: [ 'CT', gettext('Clone') ],
- vztemplate: [ 'CT', gettext('Convert to template') ],
- vzstart: ['CT', gettext('Start') ],
- vzstop: ['CT', gettext('Stop') ],
- vzmount: ['CT', gettext('Mount') ],
- vzumount: ['CT', gettext('Unmount') ],
- vzshutdown: ['CT', gettext('Shutdown') ],
- vzsuspend: [ 'CT', gettext('Suspend') ],
- vzresume: [ 'CT', gettext('Resume') ],
- hamigrate: [ 'HA', gettext('Migrate') ],
- hastart: [ 'HA', gettext('Start') ],
- hastop: [ 'HA', gettext('Stop') ],
- srvstart: ['SRV', gettext('Start') ],
- srvstop: ['SRV', gettext('Stop') ],
- srvrestart: ['SRV', gettext('Restart') ],
- srvreload: ['SRV', gettext('Reload') ],
- cephcreatemgr: ['Ceph Manager', gettext('Create') ],
- cephdestroymgr: ['Ceph Manager', gettext('Destroy') ],
- cephcreatemon: ['Ceph Monitor', gettext('Create') ],
- cephdestroymon: ['Ceph Monitor', gettext('Destroy') ],
- cephcreateosd: ['Ceph OSD', gettext('Create') ],
- cephdestroyosd: ['Ceph OSD', gettext('Destroy') ],
- cephcreatepool: ['Ceph Pool', gettext('Create') ],
- cephdestroypool: ['Ceph Pool', gettext('Destroy') ],
- cephfscreate: ['CephFS', gettext('Create') ],
- cephcreatemds: ['Ceph Metadata Server', gettext('Create') ],
- cephdestroymds: ['Ceph Metadata Server', gettext('Destroy') ],
- imgcopy: ['', gettext('Copy data') ],
- imgdel: ['', gettext('Erase data') ],
- unknownimgdel: ['', gettext('Destroy image from unknown guest') ],
- download: ['', gettext('Download') ],
- vzdump: ['VM/CT', gettext('Backup') ],
- aptupdate: ['', gettext('Update package database') ],
- startall: [ '', gettext('Start all VMs and Containers') ],
- stopall: [ '', gettext('Stop all VMs and Containers') ],
- migrateall: [ '', gettext('Migrate all VMs and Containers') ],
- dircreate: [ gettext('Directory Storage'), gettext('Create') ],
- lvmcreate: [ gettext('LVM Storage'), gettext('Create') ],
- lvmthincreate: [ gettext('LVM-Thin Storage'), gettext('Create') ],
- zfscreate: [ gettext('ZFS Storage'), gettext('Create') ]
- },
-
- format_task_description: function(type, id) {
- var farray = Proxmox.Utils.task_desc_table[type];
- var text;
- if (!farray) {
- text = type;
- if (id) {
- type += ' ' + id;
- }
- return text;
- }
- var prefix = farray[0];
- text = farray[1];
- if (prefix) {
- return prefix + ' ' + id + ' - ' + text;
- }
- return text;
- },
-
- format_size: function(size) {
- /*jslint confusion: true */
-
- var units = ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'];
- var num = 0;
-
- while (size >= 1024 && ((num++)+1) < units.length) {
- size = size / 1024;
- }
-
- return size.toFixed((num > 0)?2:0) + " " + units[num] + "B";
- },
-
- render_upid: function(value, metaData, record) {
- var type = record.data.type;
- var id = record.data.id;
-
- return Proxmox.Utils.format_task_description(type, id);
- },
-
- render_uptime: function(value) {
-
- var uptime = value;
-
- if (uptime === undefined) {
- return '';
- }
-
- if (uptime <= 0) {
- return '-';
- }
-
- return Proxmox.Utils.format_duration_long(uptime);
- },
-
- parse_task_upid: function(upid) {
- var task = {};
-
- 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]+):$/);
- if (!res) {
- throw "unable to parse upid '" + upid + "'";
- }
- task.node = res[1];
- task.pid = parseInt(res[2], 16);
- task.pstart = parseInt(res[3], 16);
- task.starttime = parseInt(res[4], 16);
- task.type = res[5];
- task.id = res[6];
- task.user = res[7];
-
- task.desc = Proxmox.Utils.format_task_description(task.type, task.id);
-
- return task;
- },
-
- render_timestamp: function(value, metaData, record, rowIndex, colIndex, store) {
- var servertime = new Date(value * 1000);
- return Ext.Date.format(servertime, 'Y-m-d H:i:s');
- },
-
- openXtermJsViewer: function(vmtype, vmid, nodename, vmname, cmd) {
- var url = Ext.Object.toQueryString({
- console: vmtype, // kvm, lxc, upgrade or shell
- xtermjs: 1,
- vmid: vmid,
- vmname: vmname,
- node: nodename,
- cmd: cmd,
-
- });
- var nw = window.open("?" + url, '_blank', 'toolbar=no,location=no,status=no,menubar=no,resizable=yes,width=800,height=420');
- if (nw) {
- nw.focus();
- }
- }
-
-},
-
- 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+)?$");
- }
-});
-// ExtJS related things
-
- // do not send '_dc' parameter
-Ext.Ajax.disableCaching = false;
-
-// custom Vtypes
-Ext.apply(Ext.form.field.VTypes, {
- IPAddress: function(v) {
- return Proxmox.Utils.IP4_match.test(v);
- },
- IPAddressText: gettext('Example') + ': 192.168.1.1',
- IPAddressMask: /[\d\.]/i,
-
- IPCIDRAddress: function(v) {
- var result = Proxmox.Utils.IP4_cidr_match.exec(v);
- // limits according to JSON Schema see
- // pve-common/src/PVE/JSONSchema.pm
- return (result !== null && result[1] >= 8 && result[1] <= 32);
- },
- IPCIDRAddressText: gettext('Example') + ': 192.168.1.1/24' + " " + gettext('Valid CIDR Range') + ': 8-32',
- IPCIDRAddressMask: /[\d\.\/]/i,
-
- IP6Address: function(v) {
- return Proxmox.Utils.IP6_match.test(v);
- },
- IP6AddressText: gettext('Example') + ': 2001:DB8::42',
- IP6AddressMask: /[A-Fa-f0-9:]/,
-
- IP6CIDRAddress: function(v) {
- var result = Proxmox.Utils.IP6_cidr_match.exec(v);
- // limits according to JSON Schema see
- // pve-common/src/PVE/JSONSchema.pm
- return (result !== null && result[1] >= 8 && result[1] <= 128);
- },
- IP6CIDRAddressText: gettext('Example') + ': 2001:DB8::42/64' + " " + gettext('Valid CIDR Range') + ': 8-128',
- IP6CIDRAddressMask: /[A-Fa-f0-9:\/]/,
-
- IP6PrefixLength: function(v) {
- return v >= 0 && v <= 128;
- },
- IP6PrefixLengthText: gettext('Example') + ': X, where 0 <= X <= 128',
- IP6PrefixLengthMask: /[0-9]/,
-
- IP64Address: function(v) {
- return Proxmox.Utils.IP64_match.test(v);
- },
- IP64AddressText: gettext('Example') + ': 192.168.1.1 2001:DB8::42',
- IP64AddressMask: /[A-Fa-f0-9\.:]/,
-
- MacAddress: function(v) {
- return (/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/).test(v);
- },
- MacAddressMask: /[a-fA-F0-9:]/,
- MacAddressText: gettext('Example') + ': 01:23:45:67:89:ab',
-
- MacPrefix: function(v) {
- return (/^[a-f0-9][02468ace](?::[a-f0-9]{2}){0,2}:?$/i).test(v);
- },
- MacPrefixMask: /[a-fA-F0-9:]/,
- MacPrefixText: gettext('Example') + ': 02:8f - ' + gettext('only unicast addresses are allowed'),
-
- BridgeName: function(v) {
- return (/^vmbr\d{1,4}$/).test(v);
- },
- BridgeNameText: gettext('Format') + ': vmbrN , where 0 <= N <= 9999',
-
- BondName: function(v) {
- return (/^bond\d{1,4}$/).test(v);
- },
- BondNameText: gettext('Format') + ': bondN , where 0 <= N <= 9999',
-
- InterfaceName: function(v) {
- return (/^[a-z][a-z0-9_]{1,20}$/).test(v);
- },
- InterfaceNameText: gettext("Allowed characters") + ": 'a-z', '0-9', '_'" + " " +
- gettext("Minimum characters") + ": 2" + " " +
- gettext("Maximum characters") + ": 21" + " " +
- gettext("Must start with") + ": 'a-z'",
-
- StorageId: function(v) {
- return (/^[a-z][a-z0-9\-\_\.]*[a-z0-9]$/i).test(v);
- },
- StorageIdText: gettext("Allowed characters") + ": 'A-Z', 'a-z', '0-9', '-', '_', '.'" + " " +
- gettext("Minimum characters") + ": 2" + " " +
- gettext("Must start with") + ": 'A-Z', 'a-z' " +
- gettext("Must end with") + ": 'A-Z', 'a-z', '0-9' ",
-
- ConfigId: function(v) {
- return (/^[a-z][a-z0-9\_]+$/i).test(v);
- },
- ConfigIdText: gettext("Allowed characters") + ": 'A-Z', 'a-z', '0-9', '_'" + " " +
- gettext("Minimum characters") + ": 2" + " " +
- gettext("Must start with") + ": " + gettext("letter"),
-
- HttpProxy: function(v) {
- return (/^http:\/\/.*$/).test(v);
- },
- HttpProxyText: gettext('Example') + ": http://username:password@host:port/",
-
- DnsName: function(v) {
- return Proxmox.Utils.DnsName_match.test(v);
- },
- DnsNameText: gettext('This is not a valid DNS name'),
-
- // workaround for https://www.sencha.com/forum/showthread.php?302150
- proxmoxMail: function(v) {
- return (/^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,63}$/).test(v);
- },
- proxmoxMailText: gettext('Example') + ": user@example.com",
-
- DnsOrIp: function(v) {
- if (!Proxmox.Utils.DnsName_match.test(v) &&
- !Proxmox.Utils.IP64_match.test(v)) {
- return false;
- }
-
- return true;
- },
- DnsOrIpText: gettext('Not a valid DNS name or IP address.'),
-
- HostList: function(v) {
- var list = v.split(/[\ \,\;]+/);
- var i;
- for (i = 0; i < list.length; i++) {
- if (list[i] == "") {
- continue;
- }
-
- if (!Proxmox.Utils.HostPort_match.test(list[i]) &&
- !Proxmox.Utils.HostPortBrackets_match.test(list[i]) &&
- !Proxmox.Utils.IP6_dotnotation_match.test(list[i])) {
- return false;
- }
- }
-
- return true;
- },
- HostListText: gettext('Not a valid list of hosts'),
-
- password: function(val, field) {
- if (field.initialPassField) {
- var pwd = field.up('form').down(
- '[name=' + field.initialPassField + ']');
- return (val == pwd.getValue());
- }
- return true;
- },
-
- passwordText: gettext('Passwords do not match')
-});
-
-// Firefox 52+ Touchscreen bug
-// see https://www.sencha.com/forum/showthread.php?336762-Examples-don-t-work-in-Firefox-52-touchscreen/page2
-// and https://bugzilla.proxmox.com/show_bug.cgi?id=1223
-Ext.define('EXTJS_23846.Element', {
- override: 'Ext.dom.Element'
-}, function(Element) {
- var supports = Ext.supports,
- proto = Element.prototype,
- eventMap = proto.eventMap,
- additiveEvents = proto.additiveEvents;
-
- if (Ext.os.is.Desktop && supports.TouchEvents && !supports.PointerEvents) {
- eventMap.touchstart = 'mousedown';
- eventMap.touchmove = 'mousemove';
- eventMap.touchend = 'mouseup';
- eventMap.touchcancel = 'mouseup';
-
- additiveEvents.mousedown = 'mousedown';
- additiveEvents.mousemove = 'mousemove';
- additiveEvents.mouseup = 'mouseup';
- additiveEvents.touchstart = 'touchstart';
- additiveEvents.touchmove = 'touchmove';
- additiveEvents.touchend = 'touchend';
- additiveEvents.touchcancel = 'touchcancel';
-
- additiveEvents.pointerdown = 'mousedown';
- additiveEvents.pointermove = 'mousemove';
- additiveEvents.pointerup = 'mouseup';
- additiveEvents.pointercancel = 'mouseup';
- }
-});
-
-Ext.define('EXTJS_23846.Gesture', {
- override: 'Ext.event.publisher.Gesture'
-}, function(Gesture) {
- var me = Gesture.instance;
-
- if (Ext.supports.TouchEvents && !Ext.isWebKit && Ext.os.is.Desktop) {
- me.handledDomEvents.push('mousedown', 'mousemove', 'mouseup');
- me.registerEvents();
- }
-});
-
-// we always want the number in x.y format and never in, e.g., x,y
-Ext.define('PVE.form.field.Number', {
- override: 'Ext.form.field.Number',
- submitLocaleSeparator: false
-});
-
-// ExtJs 5-6 has an issue with caching
-// see https://www.sencha.com/forum/showthread.php?308989
-Ext.define('Proxmox.UnderlayPool', {
- override: 'Ext.dom.UnderlayPool',
-
- checkOut: function () {
- var cache = this.cache,
- len = cache.length,
- el;
-
- // do cleanup because some of the objects might have been destroyed
- while (len--) {
- if (cache[len].destroyed) {
- cache.splice(len, 1);
- }
- }
- // end do cleanup
-
- el = cache.shift();
-
- if (!el) {
- el = Ext.Element.create(this.elementConfig);
- el.setVisibilityMode(2);
- //
- // tell the spec runner to ignore this element when checking if the dom is clean
- el.dom.setAttribute('data-sticky', true);
- //
- }
-
- return el;
- }
-});
-
-// 'Enter' in Textareas and aria multiline fields should not activate the
-// defaultbutton, fixed in extjs 6.0.2
-Ext.define('PVE.panel.Panel', {
- override: 'Ext.panel.Panel',
-
- fireDefaultButton: function(e) {
- if (e.target.getAttribute('aria-multiline') === 'true' ||
- e.target.tagName === "TEXTAREA") {
- return true;
- }
- return this.callParent(arguments);
- }
-});
-
-// if the order of the values are not the same in originalValue and value
-// extjs will not overwrite value, but marks the field dirty and thus
-// the reset button will be enabled (but clicking it changes nothing)
-// so if the arrays are not the same after resetting, we
-// clear and set it
-Ext.define('Proxmox.form.ComboBox', {
- override: 'Ext.form.field.ComboBox',
-
- reset: function() {
- // copied from combobox
- var me = this;
- me.callParent();
-
- // clear and set when not the same
- var value = me.getValue();
- if (Ext.isArray(me.originalValue) && Ext.isArray(value) && !Ext.Array.equals(value, me.originalValue)) {
- me.clearValue();
- me.setValue(me.originalValue);
- }
- }
-});
-
-// when refreshing a grid/tree view, restoring the focus moves the view back to
-// the previously focused item. Save scroll position before refocusing.
-Ext.define(null, {
- override: 'Ext.view.Table',
-
- jumpToFocus: false,
-
- saveFocusState: function() {
- var me = this,
- store = me.dataSource,
- actionableMode = me.actionableMode,
- navModel = me.getNavigationModel(),
- focusPosition = actionableMode ? me.actionPosition : navModel.getPosition(true),
- refocusRow, refocusCol;
-
- if (focusPosition) {
- // Separate this from the instance that the nav model is using.
- focusPosition = focusPosition.clone();
-
- // Exit actionable mode.
- // We must inform any Actionables that they must relinquish control.
- // Tabbability must be reset.
- if (actionableMode) {
- me.ownerGrid.setActionableMode(false);
- }
-
- // Blur the focused descendant, but do not trigger focusLeave.
- me.el.dom.focus();
-
- // Exiting actionable mode navigates to the owning cell, so in either focus mode we must
- // clear the navigation position
- navModel.setPosition();
-
- // The following function will attempt to refocus back in the same mode to the same cell
- // as it was at before based upon the previous record (if it's still inthe store), or the row index.
- return function() {
- // If we still have data, attempt to refocus in the same mode.
- if (store.getCount()) {
-
- // Adjust expectations of where we are able to refocus according to what kind of destruction
- // might have been wrought on this view's DOM during focus save.
- refocusRow = Math.min(focusPosition.rowIdx, me.all.getCount() - 1);
- refocusCol = Math.min(focusPosition.colIdx, me.getVisibleColumnManager().getColumns().length - 1);
- focusPosition = new Ext.grid.CellContext(me).setPosition(
- store.contains(focusPosition.record) ? focusPosition.record : refocusRow, refocusCol);
-
- if (actionableMode) {
- me.ownerGrid.setActionableMode(true, focusPosition);
- } else {
- me.cellFocused = true;
-
- // we sometimes want to scroll back to where we were
- var x = me.getScrollX();
- var y = me.getScrollY();
-
- // Pass "preventNavigation" as true so that that does not cause selection.
- navModel.setPosition(focusPosition, null, null, null, true);
-
- if (!me.jumpToFocus) {
- me.scrollTo(x,y);
- }
- }
- }
- // No rows - focus associated column header
- else {
- focusPosition.column.focus();
- }
- };
- }
- return Ext.emptyFn;
- }
-});
-
-// should be fixed with ExtJS 6.0.2, see:
-// https://www.sencha.com/forum/showthread.php?307244-Bug-with-datefield-in-window-with-scroll
-Ext.define('Proxmox.Datepicker', {
- override: 'Ext.picker.Date',
- hideMode: 'visibility'
-});
-
-// ExtJS 6.0.1 has no setSubmitValue() (although you find it in the docs).
-// Note: this.submitValue is a boolean flag, whereas getSubmitValue() returns
-// data to be submitted.
-Ext.define('Proxmox.form.field.Text', {
- override: 'Ext.form.field.Text',
-
- setSubmitValue: function(v) {
- this.submitValue = v;
- },
-});
-
-// this should be fixed with ExtJS 6.0.2
-// make mousescrolling work in firefox in the containers overflowhandler
-Ext.define(null, {
- override: 'Ext.layout.container.boxOverflow.Scroller',
-
- createWheelListener: function() {
- var me = this;
- if (Ext.isFirefox) {
- me.wheelListener = me.layout.innerCt.on('wheel', me.onMouseWheelFirefox, me, {destroyable: true});
- } else {
- me.wheelListener = me.layout.innerCt.on('mousewheel', me.onMouseWheel, me, {destroyable: true});
- }
- },
-
- // special wheel handler for firefox. differs from the default onMouseWheel
- // handler by using deltaY instead of wheelDeltaY and no normalizing,
- // because it is already
- onMouseWheelFirefox: function(e) {
- e.stopEvent();
- var delta = e.browserEvent.deltaY || 0;
- this.scrollBy(delta * this.wheelIncrement, false);
- }
-
-});
-
-// force alert boxes to be rendered with an Error Icon
-// since Ext.Msg is an object and not a prototype, we need to override it
-// after the framework has been initiated
-Ext.onReady(function() {
-/*jslint confusion: true */
- Ext.override(Ext.Msg, {
- alert: function(title, message, fn, scope) {
- if (Ext.isString(title)) {
- var config = {
- title: title,
- message: message,
- icon: this.ERROR,
- buttons: this.OK,
- fn: fn,
- scope : scope,
- minWidth: this.minWidth
- };
- return this.show(config);
- }
- }
- });
-/*jslint confusion: false */
-});
-Ext.define('Ext.ux.IFrame', {
- extend: 'Ext.Component',
-
- alias: 'widget.uxiframe',
-
- loadMask: 'Loading...',
-
- src: 'about:blank',
-
- renderTpl: [
- ''
- ],
- childEls: ['iframeEl'],
-
- initComponent: function () {
- this.callParent();
-
- this.frameName = this.frameName || this.id + '-frame';
- },
-
- initEvents : function() {
- var me = this;
- me.callParent();
- me.iframeEl.on('load', me.onLoad, me);
- },
-
- initRenderData: function() {
- return Ext.apply(this.callParent(), {
- src: this.src,
- frameName: this.frameName
- });
- },
-
- getBody: function() {
- var doc = this.getDoc();
- return doc.body || doc.documentElement;
- },
-
- getDoc: function() {
- try {
- return this.getWin().document;
- } catch (ex) {
- return null;
- }
- },
-
- getWin: function() {
- var me = this,
- name = me.frameName,
- win = Ext.isIE
- ? me.iframeEl.dom.contentWindow
- : window.frames[name];
- return win;
- },
-
- getFrame: function() {
- var me = this;
- return me.iframeEl.dom;
- },
-
- beforeDestroy: function () {
- this.cleanupListeners(true);
- this.callParent();
- },
-
- cleanupListeners: function(destroying){
- var doc, prop;
-
- if (this.rendered) {
- try {
- doc = this.getDoc();
- if (doc) {
- /*jslint nomen: true*/
- Ext.get(doc).un(this._docListeners);
- /*jslint nomen: false*/
- if (destroying && doc.hasOwnProperty) {
- for (prop in doc) {
- if (doc.hasOwnProperty(prop)) {
- delete doc[prop];
- }
- }
- }
- }
- } catch(e) { }
- }
- },
-
- onLoad: function() {
- var me = this,
- doc = me.getDoc(),
- fn = me.onRelayedEvent;
-
- if (doc) {
- try {
- // These events need to be relayed from the inner document (where they stop
- // bubbling) up to the outer document. This has to be done at the DOM level so
- // the event reaches listeners on elements like the document body. The effected
- // mechanisms that depend on this bubbling behavior are listed to the right
- // of the event.
- /*jslint nomen: true*/
- Ext.get(doc).on(
- me._docListeners = {
- mousedown: fn, // menu dismisal (MenuManager) and Window onMouseDown (toFront)
- mousemove: fn, // window resize drag detection
- mouseup: fn, // window resize termination
- click: fn, // not sure, but just to be safe
- dblclick: fn, // not sure again
- scope: me
- }
- );
- /*jslint nomen: false*/
- } catch(e) {
- // cannot do this xss
- }
-
- // We need to be sure we remove all our events from the iframe on unload or we're going to LEAK!
- Ext.get(this.getWin()).on('beforeunload', me.cleanupListeners, me);
-
- this.el.unmask();
- this.fireEvent('load', this);
-
- } else if (me.src) {
-
- this.el.unmask();
- this.fireEvent('error', this);
- }
-
-
- },
-
- onRelayedEvent: function (event) {
- // relay event from the iframe's document to the document that owns the iframe...
-
- var iframeEl = this.iframeEl,
-
- // Get the left-based iframe position
- iframeXY = iframeEl.getTrueXY(),
- originalEventXY = event.getXY(),
-
- // Get the left-based XY position.
- // This is because the consumer of the injected event will
- // perform its own RTL normalization.
- eventXY = event.getTrueXY();
-
- // the event from the inner document has XY relative to that document's origin,
- // so adjust it to use the origin of the iframe in the outer document:
- event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
-
- event.injectEvent(iframeEl); // blame the iframe for the event...
-
- event.xy = originalEventXY; // restore the original XY (just for safety)
- },
-
- load: function (src) {
- var me = this,
- text = me.loadMask,
- frame = me.getFrame();
-
- if (me.fireEvent('beforeload', me, src) !== false) {
- if (text && me.el) {
- me.el.mask(text);
- }
-
- frame.src = me.src = (src || me.src);
- }
- }
-});
-Ext.define('Proxmox.Mixin.CBind', {
- extend: 'Ext.Mixin',
-
- mixinConfig: {
- before: {
- initComponent: 'cloneTemplates'
- }
- },
-
- cloneTemplates: function() {
- var me = this;
-
- if (typeof(me.cbindData) == "function") {
- me.cbindData = me.cbindData(me.initialConfig) || {};
- }
-
- var getConfigValue = function(cname) {
-
- if (cname in me.initialConfig) {
- return me.initialConfig[cname];
- }
- if (cname in me.cbindData) {
- return me.cbindData[cname];
- }
- if (cname in me) {
- return me[cname];
- }
- throw "unable to get cbind data for '" + cname + "'";
- };
-
- var applyCBind = function(obj) {
- var cbind = obj.cbind, prop, cdata, cvalue, match, found;
- if (!cbind) return;
-
- for (prop in cbind) {
- cdata = cbind[prop];
-
- found = false;
- if (match = /^\{(!)?([a-z_][a-z0-9_]*)\}$/i.exec(cdata)) {
- var cvalue = getConfigValue(match[2]);
- if (match[1]) cvalue = !cvalue;
- obj[prop] = cvalue;
- found = true;
- } else if (match = /^\{(!)?([a-z_][a-z0-9_]*(\.[a-z_][a-z0-9_]*)+)\}$/i.exec(cdata)) {
- var keys = match[2].split('.');
- var cvalue = getConfigValue(keys.shift());
- keys.forEach(function(k) {
- if (k in cvalue) {
- cvalue = cvalue[k];
- } else {
- throw "unable to get cbind data for '" + match[2] + "'";
- }
- });
- if (match[1]) cvalue = !cvalue;
- obj[prop] = cvalue;
- found = true;
- } else {
- obj[prop] = cdata.replace(/{([a-z_][a-z0-9_]*)\}/ig, function(match, cname) {
- var cvalue = getConfigValue(cname);
- found = true;
- return cvalue;
- });
- }
- if (!found) {
- throw "unable to parse cbind template '" + cdata + "'";
- }
-
- }
- };
-
- if (me.cbind) {
- applyCBind(me);
- }
-
- var cloneTemplateArray = function(org) {
- var copy, i, found, el, elcopy, arrayLength;
-
- arrayLength = org.length;
- found = false;
- for (i = 0; i < arrayLength; i++) {
- el = org[i];
- if (el.constructor == Object && el.xtype) {
- found = true;
- break;
- }
- }
-
- if (!found) return org; // no need to copy
-
- copy = [];
- for (i = 0; i < arrayLength; i++) {
- el = org[i];
- if (el.constructor == Object && el.xtype) {
- elcopy = cloneTemplateObject(el);
- if (elcopy.cbind) {
- applyCBind(elcopy);
- }
- copy.push(elcopy);
- } else if (el.constructor == Array) {
- elcopy = cloneTemplateArray(el);
- copy.push(elcopy);
- } else {
- copy.push(el);
- }
- }
- return copy;
- };
-
- var cloneTemplateObject = function(org) {
- var res = {}, prop, el, copy;
- for (prop in org) {
- el = org[prop];
- if (el.constructor == Object && el.xtype) {
- copy = cloneTemplateObject(el);
- if (copy.cbind) {
- applyCBind(copy);
- }
- res[prop] = copy;
- } else if (el.constructor == Array) {
- copy = cloneTemplateArray(el);
- res[prop] = copy;
- } else {
- res[prop] = el;
- }
- }
- return res;
- };
-
- var condCloneProperties = function() {
- var prop, el, i, tmp;
-
- for (prop in me) {
- el = me[prop];
- if (el === undefined || el === null) continue;
- if (typeof(el) === 'object' && el.constructor == Object) {
- if (el.xtype && prop != 'config') {
- me[prop] = cloneTemplateObject(el);
- }
- } else if (el.constructor == Array) {
- tmp = cloneTemplateArray(el);
- me[prop] = tmp;
- }
- }
- };
-
- condCloneProperties();
- }
-});
-/* 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;
- }
-});
-
-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]);
- }
-}, function() {
-
- Ext.define('KeyValue', {
- extend: "Ext.data.Model",
- fields: [ 'key', 'value' ],
- idProperty: 'key'
- });
-
- Ext.define('KeyValuePendingDelete', {
- extend: "Ext.data.Model",
- fields: [ 'key', 'value', 'pending', 'delete' ],
- idProperty: 'key'
- });
-
- Ext.define('proxmox-tasks', {
- extend: 'Ext.data.Model',
- fields: [
- { name: 'starttime', type : 'date', dateFormat: 'timestamp' },
- { name: 'endtime', type : 'date', dateFormat: 'timestamp' },
- { name: 'pid', type: 'int' },
- 'node', 'upid', 'user', 'status', 'type', 'id'
- ],
- idProperty: 'upid'
- });
-
- Ext.define('proxmox-cluster-log', {
- extend: 'Ext.data.Model',
- fields: [
- { name: 'uid' , type: 'int' },
- { name: 'time', type : 'date', dateFormat: 'timestamp' },
- { name: 'pri', type: 'int' },
- { name: 'pid', type: 'int' },
- 'node', 'user', 'tag', 'msg',
- {
- name: 'id',
- convert: function(value, record) {
- var info = record.data;
- var text;
-
- if (value) {
- return value;
- }
- // compute unique ID
- return info.uid + ':' + info.node;
- }
- }
- ],
- idProperty: 'id'
- });
-
-});
-/* 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',
- alias: 'store.update',
-
- isStopped: true,
-
- autoStart: false,
-
- destroy: function() {
- var me = this;
- me.stopUpdate();
- me.callParent();
- },
-
- 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()) {
- var start = new Date();
- me.load(function() {
- var runtime = (new Date()) - start;
- 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(); this makes problems with chrome
- load_task.delay(1, run_load_task);
- },
- stopUpdate: function() {
- me.isStopped = true;
- load_task.cancel();
- }
- });
-
- me.callParent([config]);
-
- me.load_task = load_task;
-
- if (me.autoStart) {
- me.startUpdate();
- }
- }
-});
-/*
- * 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);
- }
-});
-/* 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',
-
- getRecord: function() {
- var me = this;
- var record = Ext.create('Ext.data.Model');
- me.getData().each(function(item) {
- record.set(item.data.key, item.data.value);
- });
- record.commit(true);
- return record;
- },
-
- 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]);
- }
-});
-/* Extends the Proxmox.data.UpdateStore type
- *
- *
- */
-Ext.define('Proxmox.data.RRDStore', {
- extend: 'Proxmox.data.UpdateStore',
- alias: 'store.proxmoxRRDStore',
-
- setRRDUrl: function(timeframe, cf) {
- var me = this;
- if (!timeframe) {
- timeframe = me.timeframe;
- }
-
- if (!cf) {
- cf = me.cf;
- }
-
- me.proxy.url = me.rrdurl + "?timeframe=" + timeframe + "&cf=" + cf;
- },
-
- proxy: {
- type: 'proxmox'
- },
-
- timeframe: 'hour',
-
- cf: 'AVERAGE',
-
- constructor: function(config) {
- var me = this;
-
- config = config || {};
-
- // set default interval to 30seconds
- if (!config.interval) {
- config.interval = 30000;
- }
-
- // set a new storeid
- if (!config.storeid) {
- config.storeid = 'rrdstore-' + (++Ext.idSeed);
- }
-
- // rrdurl is required
- if (!config.rrdurl) {
- throw "no rrdurl specified";
- }
-
- var stateid = 'proxmoxRRDTypeSelection';
- var sp = Ext.state.Manager.getProvider();
- var stateinit = sp.get(stateid);
-
- if (stateinit) {
- if(stateinit.timeframe !== me.timeframe || stateinit.cf !== me.rrdcffn){
- me.timeframe = stateinit.timeframe;
- me.rrdcffn = stateinit.cf;
- }
- }
-
- me.callParent([config]);
-
- me.setRRDUrl();
- me.mon(sp, 'statechange', function(prov, key, state){
- if (key === stateid) {
- if (state && state.id) {
- if (state.timeframe !== me.timeframe || state.cf !== me.cf) {
- me.timeframe = state.timeframe;
- me.cf = state.cf;
- me.setRRDUrl();
- me.reload();
- }
- }
- }
- });
- }
-});
-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']
- ]
-});
-Ext.define('Proxmox.form.field.Integer',{
- extend: 'Ext.form.field.Number',
- alias: 'widget.proxmoxintegerfield',
-
- config: {
- deleteEmpty: false
- },
-
- allowDecimals: false,
- allowExponential: false,
- step: 1,
-
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue && !me.isFileUpload()) {
- val = me.getSubmitValue();
- if (val !== undefined && val !== null && val !== '') {
- data = {};
- data[me.getName()] = val;
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- }
-
-});
-Ext.define('Proxmox.form.field.Textfield', {
- extend: 'Ext.form.field.Text',
- alias: ['widget.proxmoxtextfield'],
-
- config: {
- skipEmptyText: true,
-
- deleteEmpty: false,
- },
-
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue && !me.isFileUpload()) {
- val = me.getSubmitValue();
- if (val !== null) {
- data = {};
- data[me.getName()] = val;
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- getSubmitValue: function() {
- var me = this;
-
- var value = this.processRawValue(this.getRawValue());
- if (value !== '') {
- return value;
- }
-
- return me.getSkipEmptyText() ? null: value;
- },
-
- setAllowBlank: function(allowBlank) {
- this.allowBlank = allowBlank;
- }
-});
-Ext.define('Proxmox.DateTimeField', {
- extend: 'Ext.form.FieldContainer',
- xtype: 'promxoxDateTimeField',
-
- layout: 'hbox',
-
- referenceHolder: true,
-
- submitFormat: 'U',
-
- getValue: function() {
- var me = this;
- var d = me.lookupReference('dateentry').getValue();
-
- if (d === undefined || d === null) { return null; }
-
- var t = me.lookupReference('timeentry').getValue();
-
- if (t === undefined || t === null) { return null; }
-
- var offset = (t.getHours()*3600+t.getMinutes()*60)*1000;
-
- return new Date(d.getTime() + offset);
- },
-
- getSubmitValue: function() {
- var me = this;
- var format = me.submitFormat;
- var value = me.getValue();
-
- return value ? Ext.Date.format(value, format) : null;
- },
-
- items: [
- {
- xtype: 'datefield',
- editable: false,
- reference: 'dateentry',
- flex: 1,
- format: 'Y-m-d'
- },
- {
- xtype: 'timefield',
- reference: 'timeentry',
- format: 'H:i',
- width: 80,
- value: '00:00',
- increment: 60
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- me.callParent();
-
- var value = me.value || new Date();
-
- me.lookupReference('dateentry').setValue(value);
- me.lookupReference('timeentry').setValue(value);
-
- me.relayEvents(me.lookupReference('dateentry'), ['change']);
- me.relayEvents(me.lookupReference('timeentry'), ['change']);
- }
-});
-Ext.define('Proxmox.form.Checkbox', {
- extend: 'Ext.form.field.Checkbox',
- alias: ['widget.proxmoxcheckbox'],
-
- config: {
- defaultValue: undefined,
- deleteDefaultValue: false,
- deleteEmpty: false
- },
-
- inputValue: '1',
-
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue) {
- val = me.getSubmitValue();
- if (val !== null) {
- data = {};
- if ((val == me.getDefaultValue()) && me.getDeleteDefaultValue()) {
- data['delete'] = me.getName();
- } else {
- data[me.getName()] = val;
- }
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- // also accept integer 1 as true
- setRawValue: function(value) {
- var me = this;
-
- if (value === 1) {
- me.callParent([true]);
- } else {
- me.callParent([value]);
- }
- }
-
-});
-/* Key-Value ComboBox
- *
- * config properties:
- * comboItems: an array of Key - Value pairs
- * deleteEmpty: if set to true (default), an empty value received from the
- * comboBox will reset the property to its default value
- */
-Ext.define('Proxmox.form.KVComboBox', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.proxmoxKVComboBox',
-
- config: {
- deleteEmpty: true
- },
-
- comboItems: undefined,
- displayField: 'value',
- valueField: 'key',
- queryMode: 'local',
-
- // overide framework function to implement deleteEmpty behaviour
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue) {
- val = me.getSubmitValue();
- if (val !== null && val !== '' && val !== '__default__') {
- data = {};
- data[me.getName()] = val;
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- validator: function(val) {
- var me = this;
-
- if (me.editable || val === null || val === '') {
- return true;
- }
-
- if (me.store.getCount() > 0) {
- var values = me.multiSelect ? val.split(me.delimiter) : [val];
- var items = me.store.getData().collect('value', 'data');
- if (Ext.Array.every(values, function(value) {
- return Ext.Array.contains(items, value);
- })) {
- return true;
- }
- }
-
- // returns a boolean or string
- /*jslint confusion: true */
- return "value '" + val + "' not allowed!";
- },
-
- initComponent: function() {
- var me = this;
-
- me.store = Ext.create('Ext.data.ArrayStore', {
- model: 'KeyValue',
- data : me.comboItems
- });
-
- if (me.initialConfig.editable === undefined) {
- me.editable = false;
- }
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.form.LanguageSelector', {
- extend: 'Proxmox.form.KVComboBox',
- xtype: 'proxmoxLanguageSelector',
-
- comboItems: Proxmox.Utils.language_array()
-});
-/*
- * ComboGrid component: a ComboBox where the dropdown menu (the
- * "Picker") is a Grid with Rows and Columns expects a listConfig
- * object with a columns property roughly based on the GridPicker from
- * https://www.sencha.com/forum/showthread.php?299909
- *
-*/
-
-Ext.define('Proxmox.form.ComboGrid', {
- extend: 'Ext.form.field.ComboBox',
- alias: ['widget.proxmoxComboGrid'],
-
- // this value is used as default value after load()
- preferredValue: undefined,
-
- // hack: allow to select empty value
- // seems extjs does not allow that when 'editable == false'
- onKeyUp: function(e, t) {
- var me = this;
- var key = e.getKey();
-
- if (!me.editable && me.allowBlank && !me.multiSelect &&
- (key == e.BACKSPACE || key == e.DELETE)) {
- me.setValue('');
- }
-
- me.callParent(arguments);
- },
-
- // needed to trigger onKeyUp etc.
- enableKeyEvents: true,
-
- editable: false,
-
- // override ExtJS method
- // if the field has multiSelect enabled, the store is not loaded, and
- // the displayfield == valuefield, it saves the rawvalue as an array
- // but the getRawValue method is only defined in the textfield class
- // (which has not to deal with arrays) an returns the string in the
- // field (not an array)
- //
- // so if we have multiselect enabled, return the rawValue (which
- // should be an array) and else we do callParent so
- // it should not impact any other use of the class
- getRawValue: function() {
- var me = this;
- if (me.multiSelect) {
- return me.rawValue;
- } else {
- return me.callParent();
- }
- },
-
-// override ExtJS protected method
- onBindStore: function(store, initial) {
- var me = this,
- picker = me.picker,
- extraKeySpec,
- valueCollectionConfig;
-
- // We're being bound, not unbound...
- if (store) {
- // If store was created from a 2 dimensional array with generated field names 'field1' and 'field2'
- if (store.autoCreated) {
- me.queryMode = 'local';
- me.valueField = me.displayField = 'field1';
- if (!store.expanded) {
- me.displayField = 'field2';
- }
-
- // displayTpl config will need regenerating with the autogenerated displayField name 'field1'
- me.setDisplayTpl(null);
- }
- if (!Ext.isDefined(me.valueField)) {
- me.valueField = me.displayField;
- }
-
- // Add a byValue index to the store so that we can efficiently look up records by the value field
- // when setValue passes string value(s).
- // The two indices (Ext.util.CollectionKeys) are configured unique: false, so that if duplicate keys
- // are found, they are all returned by the get call.
- // This is so that findByText and findByValue are able to return the *FIRST* matching value. By default,
- // if unique is true, CollectionKey keeps the *last* matching value.
- extraKeySpec = {
- byValue: {
- rootProperty: 'data',
- unique: false
- }
- };
- extraKeySpec.byValue.property = me.valueField;
- store.setExtraKeys(extraKeySpec);
-
- if (me.displayField === me.valueField) {
- store.byText = store.byValue;
- } else {
- extraKeySpec.byText = {
- rootProperty: 'data',
- unique: false
- };
- extraKeySpec.byText.property = me.displayField;
- store.setExtraKeys(extraKeySpec);
- }
-
- // We hold a collection of the values which have been selected, keyed by this field's valueField.
- // This collection also functions as the selected items collection for the BoundList's selection model
- valueCollectionConfig = {
- rootProperty: 'data',
- extraKeys: {
- byInternalId: {
- property: 'internalId'
- },
- byValue: {
- property: me.valueField,
- rootProperty: 'data'
- }
- },
- // Whenever this collection is changed by anyone, whether by this field adding to it,
- // or the BoundList operating, we must refresh our value.
- listeners: {
- beginupdate: me.onValueCollectionBeginUpdate,
- endupdate: me.onValueCollectionEndUpdate,
- scope: me
- }
- };
-
- // This becomes our collection of selected records for the Field.
- me.valueCollection = new Ext.util.Collection(valueCollectionConfig);
-
- // We use the selected Collection as our value collection and the basis
- // for rendering the tag list.
-
- //proxmox override: since the picker is represented by a grid panel,
- // we changed here the selection to RowModel
- me.pickerSelectionModel = new Ext.selection.RowModel({
- mode: me.multiSelect ? 'SIMPLE' : 'SINGLE',
- // There are situations when a row is selected on mousedown but then the mouse is dragged to another row
- // and released. In these situations, the event target for the click event won't be the row where the mouse
- // was released but the boundview. The view will then determine that it should fire a container click, and
- // the DataViewModel will then deselect all prior selections. Setting `deselectOnContainerClick` here will
- // prevent the model from deselecting.
- deselectOnContainerClick: false,
- enableInitialSelection: false,
- pruneRemoved: false,
- selected: me.valueCollection,
- store: store,
- listeners: {
- scope: me,
- lastselectedchanged: me.updateBindSelection
- }
- });
-
- if (!initial) {
- me.resetToDefault();
- }
-
- if (picker) {
- picker.setSelectionModel(me.pickerSelectionModel);
- if (picker.getStore() !== store) {
- picker.bindStore(store);
- }
- }
- }
- },
-
- // copied from ComboBox
- createPicker: function() {
- var me = this;
- var picker;
-
- var pickerCfg = Ext.apply({
- // proxmox overrides: display a grid for selection
- xtype: 'gridpanel',
- id: me.pickerId,
- pickerField: me,
- floating: true,
- hidden: true,
- store: me.store,
- displayField: me.displayField,
- preserveScrollOnRefresh: true,
- pageSize: me.pageSize,
- tpl: me.tpl,
- selModel: me.pickerSelectionModel,
- focusOnToFront: false
- }, me.listConfig, me.defaultListConfig);
-
- picker = me.picker || Ext.widget(pickerCfg);
-
- if (picker.getStore() !== me.store) {
- picker.bindStore(me.store);
- }
-
- if (me.pageSize) {
- picker.pagingToolbar.on('beforechange', me.onPageChange, me);
- }
-
- // proxmox overrides: pass missing method in gridPanel to its view
- picker.refresh = function() {
- picker.getSelectionModel().select(me.valueCollection.getRange());
- picker.getView().refresh();
- };
- picker.getNodeByRecord = function() {
- picker.getView().getNodeByRecord(arguments);
- };
-
- // We limit the height of the picker to fit in the space above
- // or below this field unless the picker has its own ideas about that.
- if (!picker.initialConfig.maxHeight) {
- picker.on({
- beforeshow: me.onBeforePickerShow,
- scope: me
- });
- }
- picker.getSelectionModel().on({
- beforeselect: me.onBeforeSelect,
- beforedeselect: me.onBeforeDeselect,
- focuschange: me.onFocusChange,
- selectionChange: function (sm, selectedRecords) {
- var me = this;
- if (selectedRecords.length) {
- me.setValue(selectedRecords);
- me.fireEvent('select', me, selectedRecords);
- }
- },
- scope: me
- });
-
- // hack for extjs6
- // when the clicked item is the same as the previously selected,
- // it does not select the item
- // instead we hide the picker
- if (!me.multiSelect) {
- picker.on('itemclick', function (sm,record) {
- if (picker.getSelection()[0] === record) {
- picker.hide();
- }
- });
- }
-
- // when our store is not yet loaded, we increase
- // the height of the gridpanel, so that we can see
- // the loading mask
- //
- // we save the minheight to reset it after the load
- picker.on('show', function() {
- if (me.enableLoadMask) {
- me.savedMinHeight = picker.getMinHeight();
- picker.setMinHeight(100);
- }
- });
-
- picker.getNavigationModel().navigateOnSpace = false;
-
- return picker;
- },
-
- initComponent: function() {
- var me = this;
-
- Ext.apply(me, {
- queryMode: 'local',
- matchFieldWidth: false
- });
-
- Ext.applyIf(me, { value: ''}); // hack: avoid ExtJS validate() bug
-
- Ext.applyIf(me.listConfig, { width: 400 });
-
- me.callParent();
-
- // Create the picker at an early stage, so it is available to store the previous selection
- if (!me.picker) {
- me.createPicker();
- }
-
- if (me.editable) {
- // The trigger.picker causes first a focus event on the field then
- // toggles the selection picker. Thus skip expanding in this case,
- // else our focus listner expands and the picker.trigger then
- // collapses it directly afterwards.
- Ext.override(me.triggers.picker, {
- onMouseDown : function (e) {
- // copied "should we focus" check from Ext.form.trigger.Trigger
- if (e.pointerType !== 'touch' && !this.field.owns(Ext.Element.getActiveElement())) {
- me.skip_expand_on_focus = true;
- }
- this.callParent(arguments);
- }
- });
-
- me.on("focus", function(me) {
- if (!me.isExpanded && !me.skip_expand_on_focus) {
- me.expand();
- }
- me.skip_expand_on_focus = false;
- });
- }
-
- me.mon(me.store, 'beforeload', function() {
- if (!me.isDisabled()) {
- me.enableLoadMask = true;
- }
- });
-
- // hack: autoSelect does not work
- me.mon(me.store, 'load', function(store, r, success, o) {
- if (success) {
- me.clearInvalid();
-
- if (me.enableLoadMask) {
- delete me.enableLoadMask;
-
- // if the picker exists,
- // we reset its minheight to the saved var/0
- // we have to update the layout, otherwise the height
- // gets not recalculated
- if (me.picker) {
- me.picker.setMinHeight(me.savedMinHeight || 0);
- delete me.savedMinHeight;
- me.picker.updateLayout();
- }
- }
-
- var def = me.getValue() || me.preferredValue;
- if (def) {
- me.setValue(def, true); // sync with grid
- }
- var found = false;
- if (def) {
- if (Ext.isArray(def)) {
- Ext.Array.each(def, function(v) {
- if (store.findRecord(me.valueField, v)) {
- found = true;
- return false; // break
- }
- });
- } else {
- found = store.findRecord(me.valueField, def);
- }
- }
-
- if (!found) {
- var rec = me.store.first();
- if (me.autoSelect && rec && rec.data) {
- def = rec.data[me.valueField];
- me.setValue(def, true);
- } else {
- me.setValue(me.editable ? def : '', true);
- }
- }
- }
- });
- }
-});
-Ext.define('Proxmox.form.RRDTypeSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: ['widget.proxmoxRRDTypeSelector'],
-
- displayField: 'text',
- valueField: 'id',
- editable: false,
- queryMode: 'local',
- value: 'hour',
- stateEvents: [ 'select' ],
- stateful: true,
- stateId: 'proxmoxRRDTypeSelection',
- store: {
- type: 'array',
- fields: [ 'id', 'timeframe', 'cf', 'text' ],
- data : [
- [ 'hour', 'hour', 'AVERAGE',
- gettext('Hour') + ' (' + gettext('average') +')' ],
- [ 'hourmax', 'hour', 'MAX',
- gettext('Hour') + ' (' + gettext('maximum') + ')' ],
- [ 'day', 'day', 'AVERAGE',
- gettext('Day') + ' (' + gettext('average') + ')' ],
- [ 'daymax', 'day', 'MAX',
- gettext('Day') + ' (' + gettext('maximum') + ')' ],
- [ 'week', 'week', 'AVERAGE',
- gettext('Week') + ' (' + gettext('average') + ')' ],
- [ 'weekmax', 'week', 'MAX',
- gettext('Week') + ' (' + gettext('maximum') + ')' ],
- [ 'month', 'month', 'AVERAGE',
- gettext('Month') + ' (' + gettext('average') + ')' ],
- [ 'monthmax', 'month', 'MAX',
- gettext('Month') + ' (' + gettext('maximum') + ')' ],
- [ 'year', 'year', 'AVERAGE',
- gettext('Year') + ' (' + gettext('average') + ')' ],
- [ 'yearmax', 'year', 'MAX',
- gettext('Year') + ' (' + gettext('maximum') + ')' ]
- ]
- },
- // save current selection in the state Provider so RRDView can read it
- getState: function() {
- var ind = this.getStore().findExact('id', this.getValue());
- var rec = this.getStore().getAt(ind);
- if (!rec) {
- return;
- }
- return {
- id: rec.data.id,
- timeframe: rec.data.timeframe,
- cf: rec.data.cf
- };
- },
- // set selection based on last saved state
- applyState : function(state) {
- if (state && state.id) {
- this.setValue(state.id);
- }
- }
-});
-Ext.define('Proxmox.form.BondModeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.bondModeSelector'],
-
- openvswitch: false,
-
- initComponent: function() {
- var me = this;
-
- if (me.openvswitch) {
- me.comboItems = [
- ['active-backup', 'active-backup'],
- ['balance-slb', 'balance-slb'],
- ['lacp-balance-slb', 'LACP (balance-slb)'],
- ['lacp-balance-tcp', 'LACP (balance-tcp)']
- ];
- } else {
- me.comboItems = [
- ['balance-rr', 'balance-rr'],
- ['active-backup', 'active-backup'],
- ['balance-xor', 'balance-xor'],
- ['broadcast', 'broadcast'],
- ['802.3ad', 'LACP (802.3ad)'],
- ['balance-tlb', 'balance-tlb'],
- ['balance-alb', 'balance-alb']
- ];
- }
-
- me.callParent();
- }
-});
-
-Ext.define('Proxmox.form.BondPolicySelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.bondPolicySelector'],
- comboItems: [
- ['layer2', 'layer2'],
- ['layer2+3', 'layer2+3'],
- ['layer3+4', 'layer3+4']
- ]
-});
-
-/* Button features:
- * - observe selection changes to enable/disable the button using enableFn()
- * - pop up confirmation dialog using confirmMsg()
- */
-Ext.define('Proxmox.button.Button', {
- extend: 'Ext.button.Button',
- alias: 'widget.proxmoxButton',
-
- // the selection model to observe
- selModel: undefined,
-
- // if 'false' handler will not be called (button disabled)
- enableFn: function(record) { },
-
- // function(record) or text
- confirmMsg: false,
-
- // take special care in confirm box (select no as default).
- dangerous: false,
-
- initComponent: function() {
- /*jslint confusion: true */
-
- var me = this;
-
- if (me.handler) {
-
- // Note: me.realHandler may be a string (see named scopes)
- var realHandler = me.handler;
-
- me.handler = function(button, event) {
- var rec, msg;
- if (me.selModel) {
- rec = me.selModel.getSelection()[0];
- if (!rec || (me.enableFn(rec) === false)) {
- return;
- }
- }
-
- if (me.confirmMsg) {
- msg = me.confirmMsg;
- if (Ext.isFunction(me.confirmMsg)) {
- msg = me.confirmMsg(rec);
- }
- Ext.MessageBox.defaultButton = me.dangerous ? 2 : 1;
- Ext.Msg.show({
- title: gettext('Confirm'),
- icon: me.dangerous ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
- msg: msg,
- buttons: Ext.Msg.YESNO,
- defaultFocus: me.dangerous ? 'no' : 'yes',
- callback: function(btn) {
- if (btn !== 'yes') {
- return;
- }
- Ext.callback(realHandler, me.scope, [button, event, rec], 0, me);
- }
- });
- } else {
- Ext.callback(realHandler, me.scope, [button, event, rec], 0, me);
- }
- };
- }
-
- me.callParent();
-
- var grid;
- if (!me.selModel && me.selModel !== null) {
- grid = me.up('grid');
- if (grid && grid.selModel) {
- me.selModel = grid.selModel;
- }
- }
-
- if (me.waitMsgTarget === true) {
- grid = me.up('grid');
- if (grid) {
- me.waitMsgTarget = grid;
- } else {
- throw "unable to find waitMsgTarget";
- }
- }
-
- if (me.selModel) {
-
- me.mon(me.selModel, "selectionchange", function() {
- var rec = me.selModel.getSelection()[0];
- if (!rec || (me.enableFn(rec) === false)) {
- me.setDisabled(true);
- } else {
- me.setDisabled(false);
- }
- });
- }
- }
-});
-
-
-Ext.define('Proxmox.button.StdRemoveButton', {
- extend: 'Proxmox.button.Button',
- alias: 'widget.proxmoxStdRemoveButton',
-
- text: gettext('Remove'),
-
- disabled: true,
-
- config: {
- baseurl: undefined
- },
-
- getUrl: function(rec) {
- var me = this;
-
- return me.baseurl + '/' + rec.getId();
- },
-
- // also works with names scopes
- callback: function(options, success, response) {},
-
- getRecordName: function(rec) { return rec.getId() },
-
- confirmMsg: function (rec) {
- var me = this;
-
- var name = me.getRecordName(rec);
- return Ext.String.format(
- gettext('Are you sure you want to remove entry {0}'),
- "'" + name + "'");
- },
-
- handler: function(btn, event, rec) {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: me.getUrl(rec),
- method: 'DELETE',
- waitMsgTarget: me.waitMsgTarget,
- callback: function(options, success, response) {
- Ext.callback(me.callback, me.scope, [options, success, response], 0, me);
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
-});
-/* help button pointing to an online documentation
- for components contained in a modal window
-*/
-/*global
- proxmoxOnlineHelpInfo
-*/
-Ext.define('Proxmox.button.Help', {
- extend: 'Ext.button.Button',
- xtype: 'proxmoxHelpButton',
-
- text: gettext('Help'),
-
- // make help button less flashy by styling it like toolbar buttons
- iconCls: ' x-btn-icon-el-default-toolbar-small fa fa-question-circle',
- cls: 'x-btn-default-toolbar-small proxmox-inline-button',
-
- hidden: true,
-
- listenToGlobalEvent: true,
-
- controller: {
- xclass: 'Ext.app.ViewController',
- listen: {
- global: {
- proxmoxShowHelp: 'onProxmoxShowHelp',
- proxmoxHideHelp: 'onProxmoxHideHelp'
- }
- },
- onProxmoxShowHelp: function(helpLink) {
- var me = this.getView();
- if (me.listenToGlobalEvent === true) {
- me.setOnlineHelp(helpLink);
- me.show();
- }
- },
- onProxmoxHideHelp: function() {
- var me = this.getView();
- if (me.listenToGlobalEvent === true) {
- me.hide();
- }
- }
- },
-
- getOnlineHelpInfo: function (ref) {
- var helpMap;
- if (typeof proxmoxOnlineHelpInfo !== 'undefined') {
- helpMap = proxmoxOnlineHelpInfo;
- } else if (typeof pveOnlineHelpInfo !== 'undefined') {
- // be backward compatible with older pve-doc-generators
- helpMap = pveOnlineHelpInfo;
- } else {
- throw "no global OnlineHelpInfo map declared";
- }
-
- return helpMap[ref];
- },
-
- // this sets the link and the tooltip text
- setOnlineHelp:function(blockid) {
- var me = this;
-
- var info = me.getOnlineHelpInfo(blockid);
- if (info) {
- me.onlineHelp = blockid;
- var title = info.title;
- if (info.subtitle) {
- title += ' - ' + info.subtitle;
- }
- me.setTooltip(title);
- }
- },
-
- // helper to set the onlineHelp via a config object
- setHelpConfig: function(config) {
- var me = this;
- me.setOnlineHelp(config.onlineHelp);
- },
-
- handler: function() {
- var me = this;
- var docsURI;
-
- if (me.onlineHelp) {
- var info = me.getOnlineHelpInfo(me.onlineHelp);
- if (info) {
- docsURI = window.location.origin + info.link;
- }
- }
-
- if (docsURI) {
- window.open(docsURI);
- } else {
- Ext.Msg.alert(gettext('Help'), gettext('No Help available'));
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.callParent();
-
- if (me.onlineHelp) {
- me.setOnlineHelp(me.onlineHelp); // set tooltip
- }
- }
-});
-/* Renders a list of key values objets
-
-mandatory config parameters:
-rows: an object container where each propery is a key-value object we want to render
- var rows = {
- keyboard: {
- header: gettext('Keyboard Layout'),
- editor: 'Your.KeyboardEdit',
- required: true
- },
-
-optional:
-disabled: setting this parameter to true will disable selection and focus on the
-proxmoxObjectGrid as well as greying out input elements.
-Useful for a readonly tabular display
-
-*/
-
-Ext.define('Proxmox.grid.ObjectGrid', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.proxmoxObjectGrid'],
- disabled: false,
- hideHeaders: true,
-
- monStoreErrors: false,
-
- add_combobox_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {};
- me.rows = me.rows || {};
-
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue,
- header: text,
- renderer: opts.renderer,
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- items: {
- xtype: 'proxmoxKVComboBox',
- name: name,
- comboItems: opts.comboItems,
- value: opts.defaultValue,
- deleteEmpty: opts.deleteEmpty ? true : false,
- emptyText: opts.defaultValue,
- labelWidth: Proxmox.Utils.compute_min_label_width(
- text, opts.labelWidth),
- fieldLabel: text
- }
- }
- };
- },
-
- add_text_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {};
- me.rows = me.rows || {};
-
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue,
- header: text,
- renderer: opts.renderer,
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- items: {
- xtype: 'proxmoxtextfield',
- name: name,
- deleteEmpty: opts.deleteEmpty ? true : false,
- emptyText: opts.defaultValue,
- labelWidth: Proxmox.Utils.compute_min_label_width(
- text, opts.labelWidth),
- vtype: opts.vtype,
- fieldLabel: text
- }
- }
- };
- },
-
- add_boolean_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {};
- me.rows = me.rows || {};
-
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue || 0,
- header: text,
- renderer: opts.renderer || Proxmox.Utils.format_boolean,
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- items: {
- xtype: 'proxmoxcheckbox',
- name: name,
- uncheckedValue: 0,
- defaultValue: opts.defaultValue || 0,
- checked: opts.defaultValue ? true : false,
- deleteDefaultValue: opts.deleteDefaultValue ? true : false,
- labelWidth: Proxmox.Utils.compute_min_label_width(
- text, opts.labelWidth),
- fieldLabel: text
- }
- }
- };
- },
-
- add_integer_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {}
- me.rows = me.rows || {};
-
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue,
- header: text,
- renderer: opts.renderer,
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- items: {
- xtype: 'proxmoxintegerfield',
- name: name,
- minValue: opts.minValue,
- maxValue: opts.maxValue,
- emptyText: gettext('Default'),
- deleteEmpty: opts.deleteEmpty ? true : false,
- value: opts.defaultValue,
- labelWidth: Proxmox.Utils.compute_min_label_width(
- text, opts.labelWidth),
- fieldLabel: text
- }
- }
- };
- },
-
- editorConfig: {}, // default config passed to editor
-
- run_editor: function() {
- var me = this;
-
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var rows = me.rows;
- var rowdef = rows[rec.data.key];
- if (!rowdef.editor) {
- return;
- }
-
- var win;
- var config;
- if (Ext.isString(rowdef.editor)) {
- config = Ext.apply({
- confid: rec.data.key,
- }, me.editorConfig);
- win = Ext.create(rowdef.editor, config);
- } else {
- config = Ext.apply({
- confid: rec.data.key,
- }, me.editorConfig);
- Ext.apply(config, rowdef.editor);
- win = Ext.createWidget(rowdef.editor.xtype, config);
- win.load();
- }
-
- win.show();
- win.on('destroy', me.reload, me);
- },
-
- reload: function() {
- var me = this;
- me.rstore.load();
- },
-
- getObjectValue: function(key, defaultValue) {
- var me = this;
- var rec = me.store.getById(key);
- if (rec) {
- return rec.data.value;
- }
- return defaultValue;
- },
-
- renderKey: function(key, metaData, record, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var rowdef = (rows && rows[key]) ? rows[key] : {};
- return rowdef.header || key;
- },
-
- renderValue: function(value, metaData, record, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var key = record.data.key;
- var rowdef = (rows && rows[key]) ? rows[key] : {};
-
- var renderer = rowdef.renderer;
- if (renderer) {
- return renderer(value, metaData, record, rowIndex, colIndex, store);
- }
-
- return value;
- },
-
- listeners: {
- itemkeydown: function(view, record, item, index, e) {
- if (e.getKey() === e.ENTER) {
- this.pressedIndex = index;
- }
- },
- itemkeyup: function(view, record, item, index, e) {
- if (e.getKey() === e.ENTER && index == this.pressedIndex) {
- this.run_editor();
- }
-
- this.pressedIndex = undefined;
- }
- },
-
- initComponent : function() {
- var me = this;
-
- var rows = me.rows;
-
- if (!me.rstore) {
- if (!me.url) {
- throw "no url specified";
- }
-
- me.rstore = Ext.create('Proxmox.data.ObjectStore', {
- url: me.url,
- interval: me.interval,
- extraParams: me.extraParams,
- rows: me.rows
- });
- }
-
- var rstore = me.rstore;
-
- var store = Ext.create('Proxmox.data.DiffStore', { rstore: rstore,
- sorters: [],
- filters: []
- });
-
- if (rows) {
- Ext.Object.each(rows, function(key, rowdef) {
- if (Ext.isDefined(rowdef.defaultValue)) {
- store.add({ key: key, value: rowdef.defaultValue });
- } else if (rowdef.required) {
- store.add({ key: key, value: undefined });
- }
- });
- }
-
- if (me.sorterFn) {
- store.sorters.add(Ext.create('Ext.util.Sorter', {
- sorterFn: me.sorterFn
- }));
- }
-
- store.filters.add(Ext.create('Ext.util.Filter', {
- filterFn: function(item) {
- if (rows) {
- var rowdef = rows[item.data.key];
- if (!rowdef || (rowdef.visible === false)) {
- return false;
- }
- }
- return true;
- }
- }));
-
- Proxmox.Utils.monStoreErrors(me, rstore);
-
- Ext.applyIf(me, {
- store: store,
- stateful: false,
- columns: [
- {
- header: gettext('Name'),
- width: me.cwidth1 || 200,
- dataIndex: 'key',
- renderer: me.renderKey
- },
- {
- flex: 1,
- header: gettext('Value'),
- dataIndex: 'value',
- renderer: me.renderValue
- }
- ]
- });
-
- me.callParent();
-
- if (me.monStoreErrors) {
- Proxmox.Utils.monStoreErrors(me, me.store);
- }
- }
-});
-Ext.define('Proxmox.grid.PendingObjectGrid', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.proxmoxPendingObjectGrid'],
-
- getObjectValue: function(key, defaultValue, pending) {
- var me = this;
- var rec = me.store.getById(key);
- if (rec) {
- var value = rec.data.value;
- if (pending) {
- if (Ext.isDefined(rec.data.pending) && rec.data.pending !== '') {
- value = rec.data.pending;
- } else if (rec.data['delete'] === 1) {
- value = defaultValue;
- }
- }
-
- if (Ext.isDefined(value) && (value !== '')) {
- return value;
- } else {
- return defaultValue;
- }
- }
- return defaultValue;
- },
-
- hasPendingChanges: function(key) {
- var me = this;
- var rows = me.rows;
- var rowdef = (rows && rows[key]) ? rows[key] : {};
- var keys = rowdef.multiKey || [ key ];
- var pending = false;
-
- Ext.Array.each(keys, function(k) {
- var rec = me.store.getById(k);
- if (rec && rec.data && (
- (Ext.isDefined(rec.data.pending) && rec.data.pending !== '') ||
- rec.data['delete'] === 1
- )) {
- pending = true;
- return false; // break
- }
- });
-
- return pending;
- },
-
- renderValue: function(value, metaData, record, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var key = record.data.key;
- var rowdef = (rows && rows[key]) ? rows[key] : {};
- var renderer = rowdef.renderer;
- var current = '';
- var pendingdelete = '';
- var pending = '';
-
- if (renderer) {
- current = renderer(value, metaData, record, rowIndex, colIndex, store, false);
- if (me.hasPendingChanges(key)) {
- pending = renderer(record.data.pending, metaData, record, rowIndex, colIndex, store, true);
- }
- if (pending == current) {
- pending = undefined;
- }
- } else {
- current = value || '';
- pending = record.data.pending;
- }
-
- if (record.data['delete']) {
- var delete_all = true;
- if (rowdef.multiKey) {
- Ext.Array.each(rowdef.multiKey, function(k) {
- var rec = me.store.getById(k);
- if (rec && rec.data && rec.data['delete'] !== 1) {
- delete_all = false;
- return false; // break
- }
- });
- }
- if (delete_all) {
- pending = ''+ current +'
';
- }
- }
-
- if (pending) {
- return current + '' + pending + '
';
- } else {
- return current;
- }
- },
-
- initComponent : function() {
- var me = this;
-
- var rows = me.rows;
-
- if (!me.rstore) {
- if (!me.url) {
- throw "no url specified";
- }
-
- me.rstore = Ext.create('Proxmox.data.ObjectStore', {
- model: 'KeyValuePendingDelete',
- readArray: true,
- url: me.url,
- interval: me.interval,
- extraParams: me.extraParams,
- rows: me.rows
- });
- }
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.panel.InputPanel', {
- extend: 'Ext.panel.Panel',
- alias: ['widget.inputpanel'],
- listeners: {
- activate: function() {
- // notify owning container that it should display a help button
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
- }
- },
- deactivate: function() {
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
- }
- }
- },
- border: false,
-
- // override this with an URL to a relevant chapter of the pve manual
- // setting this will display a help button in our parent panel
- onlineHelp: undefined,
-
- // will be set if the inputpanel has advanced items
- hasAdvanced: false,
-
- // if the panel has advanced items,
- // this will determine if they are shown by default
- showAdvanced: false,
-
- // overwrite this to modify submit data
- onGetValues: function(values) {
- return values;
- },
-
- getValues: function(dirtyOnly) {
- var me = this;
-
- if (Ext.isFunction(me.onGetValues)) {
- dirtyOnly = false;
- }
-
- var values = {};
-
- Ext.Array.each(me.query('[isFormField]'), function(field) {
- if (!dirtyOnly || field.isDirty()) {
- Proxmox.Utils.assemble_field_data(values, field.getSubmitData());
- }
- });
-
- return me.onGetValues(values);
- },
-
- setAdvancedVisible: function(visible) {
- var me = this;
- var advItems = me.getComponent('advancedContainer');
- if (advItems) {
- advItems.setVisible(visible);
- }
- },
-
- setValues: function(values) {
- var me = this;
-
- var form = me.up('form');
-
- Ext.iterate(values, function(fieldId, val) {
- var field = me.query('[isFormField][name=' + fieldId + ']')[0];
- if (field) {
- field.setValue(val);
- if (form.trackResetOnLoad) {
- field.resetOriginalValue();
- }
- }
- });
- },
-
- initComponent: function() {
- var me = this;
-
- var items;
-
- if (me.items) {
- me.columns = 1;
- items = [
- {
- columnWidth: 1,
- layout: 'anchor',
- items: me.items
- }
- ];
- me.items = undefined;
- } else if (me.column4) {
- me.columns = 4;
- items = [
- {
- columnWidth: 0.25,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.column1
- },
- {
- columnWidth: 0.25,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.column2
- },
- {
- columnWidth: 0.25,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.column3
- },
- {
- columnWidth: 0.25,
- padding: '0 0 0 10',
- layout: 'anchor',
- items: me.column4
- }
- ];
- if (me.columnB) {
- items.push({
- columnWidth: 1,
- padding: '10 0 0 0',
- layout: 'anchor',
- items: me.columnB
- });
- }
- } else if (me.column1) {
- me.columns = 2;
- items = [
- {
- columnWidth: 0.5,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.column1
- },
- {
- columnWidth: 0.5,
- padding: '0 0 0 10',
- layout: 'anchor',
- items: me.column2 || [] // allow empty column
- }
- ];
- if (me.columnB) {
- items.push({
- columnWidth: 1,
- padding: '10 0 0 0',
- layout: 'anchor',
- items: me.columnB
- });
- }
- } else {
- throw "unsupported config";
- }
-
- var advItems;
- if (me.advancedItems) {
- advItems = [
- {
- columnWidth: 1,
- layout: 'anchor',
- items: me.advancedItems
- }
- ];
- me.advancedItems = undefined;
- } else if (me.advancedColumn1) {
- advItems = [
- {
- columnWidth: 0.5,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.advancedColumn1
- },
- {
- columnWidth: 0.5,
- padding: '0 0 0 10',
- layout: 'anchor',
- items: me.advancedColumn2 || [] // allow empty column
- }
- ];
-
- me.advancedColumn1 = undefined;
- me.advancedColumn2 = undefined;
-
- if (me.advancedColumnB) {
- advItems.push({
- columnWidth: 1,
- padding: '10 0 0 0',
- layout: 'anchor',
- items: me.advancedColumnB
- });
- me.advancedColumnB = undefined;
- }
- }
-
- if (advItems) {
- me.hasAdvanced = true;
- advItems.unshift({
- columnWidth: 1,
- xtype: 'box',
- hidden: false,
- border: true,
- autoEl: {
- tag: 'hr'
- }
- });
- items.push({
- columnWidth: 1,
- xtype: 'container',
- itemId: 'advancedContainer',
- hidden: !me.showAdvanced,
- layout: 'column',
- defaults: {
- border: false
- },
- items: advItems
- });
- }
-
- if (me.useFieldContainer) {
- Ext.apply(me, {
- layout: 'fit',
- items: Ext.apply(me.useFieldContainer, {
- layout: 'column',
- defaultType: 'container',
- items: items
- })
- });
- } else {
- Ext.apply(me, {
- layout: 'column',
- defaultType: 'container',
- items: items
- });
- }
-
- me.callParent();
- }
-});
-/*
- * Display log entries in a panel with scrollbar
- * The log entries are automatically refreshed via a background task,
- * with newest entries comming at the bottom
- */
-Ext.define('Proxmox.panel.LogView', {
- extend: 'Ext.panel.Panel',
- xtype: 'proxmoxLogView',
-
- pageSize: 500,
- viewBuffer: 50,
- lineHeight: 16,
-
- scrollToEnd: true,
-
- // callback for load failure, used for ceph
- failCallback: undefined,
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- updateParams: function() {
- var me = this;
- var viewModel = me.getViewModel();
- var since = viewModel.get('since');
- var until = viewModel.get('until');
- if (viewModel.get('hide_timespan')) {
- return;
- }
-
- if (since > until) {
- Ext.Msg.alert('Error', 'Since date must be less equal than Until date.');
- return;
- }
-
- viewModel.set('params.since', Ext.Date.format(since, 'Y-m-d'));
- viewModel.set('params.until', Ext.Date.format(until, 'Y-m-d') + ' 23:59:59');
- me.getView().loadTask.delay(200);
- },
-
- scrollPosBottom: function() {
- var view = this.getView();
- var pos = view.getScrollY();
- var maxPos = view.getScrollable().getMaxPosition().y;
- return maxPos - pos;
- },
-
- updateView: function(text, first, total) {
- var me = this;
- var view = me.getView();
- var viewModel = me.getViewModel();
- var content = me.lookup('content');
- var data = viewModel.get('data');
-
- if (first === data.first && total === data.total && text.length === data.textlen) {
- return; // same content, skip setting and scrolling
- }
- viewModel.set('data', {
- first: first,
- total: total,
- textlen: text.length
- });
-
- var scrollPos = me.scrollPosBottom();
-
- content.update(text);
-
- if (view.scrollToEnd && scrollPos <= 0) {
- // we use setTimeout to work around scroll handling on touchscreens
- setTimeout(function() { view.scrollTo(0, Infinity); }, 10);
- }
- },
-
- doLoad: function() {
- var me = this;
- var view = me.getView();
- var viewModel = me.getViewModel();
- Proxmox.Utils.API2Request({
- url: me.getView().url,
- params: viewModel.get('params'),
- method: 'GET',
- success: function(response) {
- Proxmox.Utils.setErrorMask(me, false);
- var total = response.result.total;
- var lines = new Array();
- var first = Infinity;
-
- Ext.Array.each(response.result.data, function(line) {
- if (first > line.n) {
- first = line.n;
- }
- lines[line.n - 1] = Ext.htmlEncode(line.t);
- });
-
- lines.length = total;
- me.updateView(lines.join(' '), first - 1, total);
- },
- failure: function(response) {
- if (view.failCallback) {
- view.failCallback(response);
- } else {
- var msg = response.htmlStatus;
- Proxmox.Utils.setErrorMask(me, msg);
- }
- }
- });
- },
-
- onScroll: function(x, y) {
- var me = this;
- var view = me.getView();
- var viewModel = me.getViewModel();
-
- var lineHeight = view.lineHeight;
- var line = view.getScrollY()/lineHeight;
- var start = viewModel.get('params.start');
- var limit = viewModel.get('params.limit');
- var viewLines = view.getHeight()/lineHeight;
-
- var viewStart = Math.max(parseInt(line - 1 - view.viewBuffer, 10), 0);
- var viewEnd = parseInt(line + viewLines + 1 + view.viewBuffer, 10);
-
- if (viewStart < start || viewEnd > (start+limit)) {
- viewModel.set('params.start',
- Math.max(parseInt(line - limit/2 + 10, 10), 0));
- view.loadTask.delay(200);
- }
- },
-
- init: function(view) {
- var me = this;
-
- if (!view.url) {
- throw "no url specified";
- }
-
- var viewModel = this.getViewModel();
- var since = new Date();
- since.setDate(since.getDate() - 3);
- viewModel.set('until', new Date());
- viewModel.set('since', since);
- viewModel.set('params.limit', view.pageSize);
- viewModel.set('hide_timespan', !view.log_select_timespan);
- me.lookup('content').setStyle('line-height', view.lineHeight + 'px');
-
- view.loadTask = new Ext.util.DelayedTask(me.doLoad, me);
-
- me.updateParams();
- view.task = Ext.TaskManager.start({
- run: function() {
- if (!view.isVisible() || !view.scrollToEnd) {
- return;
- }
-
- if (me.scrollPosBottom() <= 1) {
- view.loadTask.delay(200);
- }
- },
- interval: 1000
- });
- }
- },
-
- onDestroy: function() {
- var me = this;
- me.loadTask.cancel();
- Ext.TaskManager.stop(me.task);
- },
-
- // for user to initiate a load from outside
- requestUpdate: function() {
- var me = this;
- me.loadTask.delay(200);
- },
-
- viewModel: {
- data: {
- until: null,
- since: null,
- hide_timespan: false,
- data: {
- start: 0,
- total: 0,
- textlen: 0
- },
- params: {
- start: 0,
- limit: 500,
- }
- }
- },
-
- layout: 'auto',
- bodyPadding: 5,
- scrollable: {
- x: 'auto',
- y: 'auto',
- listeners: {
- // we have to have this here, since we cannot listen to events
- // of the scroller in the viewcontroller (extjs bug?), nor does
- // the panel have a 'scroll' event'
- scroll: {
- fn: function(scroller, x, y) {
- var controller = this.component.getController();
- if (controller) { // on destroy, controller can be gone
- controller.onScroll(x,y);
- }
- },
- buffer: 200
- },
- }
- },
-
- tbar: {
- bind: {
- hidden: '{hide_timespan}'
- },
- items: [
- '->',
- 'Since: ',
- {
- xtype: 'datefield',
- name: 'since_date',
- reference: 'since',
- format: 'Y-m-d',
- bind: {
- value: '{since}',
- maxValue: '{until}'
- }
- },
- 'Until: ',
- {
- xtype: 'datefield',
- name: 'until_date',
- reference: 'until',
- format: 'Y-m-d',
- bind: {
- value: '{until}',
- minValue: '{since}'
- }
- },
- {
- xtype: 'button',
- text: 'Update',
- handler: 'updateParams'
- }
- ],
- },
-
- items: [
- {
- xtype: 'box',
- reference: 'content',
- style: {
- font: 'normal 11px tahoma, arial, verdana, sans-serif',
- 'white-space': 'pre'
- },
- }
- ]
-});
-Ext.define('Proxmox.widget.RRDChart', {
- extend: 'Ext.chart.CartesianChart',
- alias: 'widget.proxmoxRRDChart',
-
- unit: undefined, // bytes, bytespersecond, percent
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- convertToUnits: function(value) {
- var units = ['', 'k','M','G','T', 'P'];
- var si = 0;
- while(value >= 1000 && si < (units.length -1)){
- value = value / 1000;
- si++;
- }
-
- // javascript floating point weirdness
- value = Ext.Number.correctFloat(value);
-
- // limit to 2 decimal points
- value = Ext.util.Format.number(value, "0.##");
-
- return value.toString() + " " + units[si];
- },
-
- leftAxisRenderer: function(axis, label, layoutContext) {
- var me = this;
-
- return me.convertToUnits(label);
- },
-
- onSeriesTooltipRender: function(tooltip, record, item) {
- var me = this.getView();
-
- var suffix = '';
-
- if (me.unit === 'percent') {
- suffix = '%';
- } else if (me.unit === 'bytes') {
- suffix = 'B';
- } else if (me.unit === 'bytespersecond') {
- suffix = 'B/s';
- }
-
- var prefix = item.field;
- if (me.fieldTitles && me.fieldTitles[me.fields.indexOf(item.field)]) {
- prefix = me.fieldTitles[me.fields.indexOf(item.field)];
- }
- tooltip.setHtml(prefix + ': ' + this.convertToUnits(record.get(item.field)) + suffix +
- ' ' + new Date(record.get('time')));
- },
-
- onAfterAnimation: function(chart, eopts) {
- // if the undobuton is disabled,
- // disable our tool
-
- var ourUndoZoomButton = chart.tools[0];
- var undoButton = chart.interactions[0].getUndoButton();
- ourUndoZoomButton.setDisabled(undoButton.isDisabled());
- }
- },
-
- width: 770,
- height: 300,
- animation: false,
- interactions: [{
- type: 'crosszoom'
- }],
- axes: [{
- type: 'numeric',
- position: 'left',
- grid: true,
- renderer: 'leftAxisRenderer',
- //renderer: function(axis, label) { return label; },
- minimum: 0
- }, {
- type: 'time',
- position: 'bottom',
- grid: true,
- fields: ['time']
- }],
- legend: {
- docked: 'bottom'
- },
- listeners: {
- animationend: 'onAfterAnimation'
- },
-
-
- initComponent: function() {
- var me = this;
- var series = {};
-
- if (!me.store) {
- throw "cannot work without store";
- }
-
- if (!me.fields) {
- throw "cannot work without fields";
- }
-
- me.callParent();
-
- // add correct label for left axis
- var axisTitle = "";
- if (me.unit === 'percent') {
- axisTitle = "%";
- } else if (me.unit === 'bytes') {
- axisTitle = "Bytes";
- } else if (me.unit === 'bytespersecond') {
- axisTitle = "Bytes/s";
- } else if (me.fieldTitles && me.fieldTitles.length === 1) {
- axisTitle = me.fieldTitles[0];
- } else if (me.fields.length === 1) {
- axisTitle = me.fields[0];
- }
-
- me.axes[0].setTitle(axisTitle);
-
- if (!me.noTool) {
- me.addTool([{
- type: 'minus',
- disabled: true,
- tooltip: gettext('Undo Zoom'),
- handler: function(){
- var undoButton = me.interactions[0].getUndoButton();
- if (undoButton.handler) {
- undoButton.handler();
- }
- }
- },{
- type: 'restore',
- tooltip: gettext('Toggle Legend'),
- handler: function(){
- if (me.legend) {
- me.legend.setVisible(!me.legend.isVisible());
- }
- }
- }]);
- }
-
- // add a series for each field we get
- me.fields.forEach(function(item, index){
- var title = item;
- if (me.fieldTitles && me.fieldTitles[index]) {
- title = me.fieldTitles[index];
- }
- me.addSeries(Ext.apply(
- {
- type: 'line',
- xField: 'time',
- yField: item,
- title: title,
- fill: true,
- style: {
- lineWidth: 1.5,
- opacity: 0.60
- },
- marker: {
- opacity: 0,
- scaling: 0.01,
- fx: {
- duration: 200,
- easing: 'easeOut'
- }
- },
- highlightCfg: {
- opacity: 1,
- scaling: 1.5
- },
- tooltip: {
- trackMouse: true,
- renderer: 'onSeriesTooltipRender'
- }
- },
- me.seriesConfig
- ));
- });
-
- // enable animation after the store is loaded
- me.store.onAfter('load', function() {
- me.setAnimation(true);
- }, this, {single: true});
- }
-});
-Ext.define('Proxmox.panel.GaugeWidget', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.proxmoxGauge',
-
- defaults: {
- style: {
- 'text-align':'center'
- }
- },
- items: [
- {
- xtype: 'box',
- itemId: 'title',
- data: {
- title: ''
- },
- tpl: '{title} '
- },
- {
- xtype: 'polar',
- height: 120,
- border: false,
- itemId: 'chart',
- series: [{
- type: 'gauge',
- value: 0,
- colors: ['#f5f5f5'],
- sectors: [0],
- donut: 90,
- needleLength: 100,
- totalAngle: Math.PI
- }],
- sprites: [{
- id: 'valueSprite',
- type: 'text',
- text: '',
- textAlign: 'center',
- textBaseline: 'bottom',
- x: 125,
- y: 110,
- fontSize: 30
- }]
- },
- {
- xtype: 'box',
- itemId: 'text'
- }
- ],
-
- header: false,
- border: false,
-
- warningThreshold: 0.6,
- criticalThreshold: 0.9,
- warningColor: '#fc0',
- criticalColor: '#FF6C59',
- defaultColor: '#7289DA',
- backgroundColor: '#2C2F33',
-
- initialValue: 0,
-
-
- updateValue: function(value, text) {
- var me = this;
- var color = me.defaultColor;
- var attr = {};
-
- if (value >= me.criticalThreshold) {
- color = me.criticalColor;
- } else if (value >= me.warningThreshold) {
- color = me.warningColor;
- }
-
- me.chart.series[0].setColors([color, me.backgroundColor]);
- me.chart.series[0].setValue(value*100);
-
- me.valueSprite.setText(' '+(value*100).toFixed(0) + '%');
- attr.x = me.chart.getWidth()/2;
- attr.y = me.chart.getHeight()-20;
- if (me.spriteFontSize) {
- attr.fontSize = me.spriteFontSize;
- }
- me.valueSprite.setAttributes(attr, true);
-
- if (text !== undefined) {
- me.text.setHtml(text);
- }
- },
-
- initComponent: function() {
- var me = this;
-
- me.callParent();
-
- if (me.title) {
- me.getComponent('title').update({title: me.title});
- }
- me.text = me.getComponent('text');
- me.chart = me.getComponent('chart');
- me.valueSprite = me.chart.getSurface('chart').get('valueSprite');
- }
-});
-// fixme: how can we avoid those lint errors?
-/*jslint confusion: true */
-Ext.define('Proxmox.window.Edit', {
- extend: 'Ext.window.Window',
- alias: 'widget.proxmoxWindowEdit',
-
- // autoLoad trigger a load() after component creation
- autoLoad: false,
-
- resizable: false,
-
- // use this tio atimatically generate a title like
- // Create:
- subject: undefined,
-
- // set isCreate to true if you want a Create button (instead
- // OK and RESET)
- isCreate: false,
-
- // set to true if you want an Add button (instead of Create)
- isAdd: false,
-
- // set to true if you want an Remove button (instead of Create)
- isRemove: false,
-
- // custom submitText
- submitText: undefined,
-
- backgroundDelay: 0,
-
- // needed for finding the reference to submitbutton
- // because we do not have a controller
- referenceHolder: true,
- defaultButton: 'submitbutton',
-
- // finds the first form field
- defaultFocus: 'field[disabled=false][hidden=false]',
-
- showProgress: false,
-
- showTaskViewer: false,
-
- // gets called if we have a progress bar or taskview and it detected that
- // the task finished. function(success)
- taskDone: Ext.emptyFn,
-
- // gets called when the api call is finished, right at the beginning
- // function(success, response, options)
- apiCallDone: Ext.emptyFn,
-
- // assign a reference from docs, to add a help button docked to the
- // bottom of the window. If undefined we magically fall back to the
- // onlineHelp of our first item, if set.
- onlineHelp: undefined,
-
- isValid: function() {
- var me = this;
-
- var form = me.formPanel.getForm();
- return form.isValid();
- },
-
- getValues: function(dirtyOnly) {
- var me = this;
-
- var values = {};
-
- var form = me.formPanel.getForm();
-
- form.getFields().each(function(field) {
- if (!field.up('inputpanel') && (!dirtyOnly || field.isDirty())) {
- Proxmox.Utils.assemble_field_data(values, field.getSubmitData());
- }
- });
-
- Ext.Array.each(me.query('inputpanel'), function(panel) {
- Proxmox.Utils.assemble_field_data(values, panel.getValues(dirtyOnly));
- });
-
- return values;
- },
-
- setValues: function(values) {
- var me = this;
-
- var form = me.formPanel.getForm();
-
- Ext.iterate(values, function(fieldId, val) {
- var field = form.findField(fieldId);
- if (field && !field.up('inputpanel')) {
- field.setValue(val);
- if (form.trackResetOnLoad) {
- field.resetOriginalValue();
- }
- }
- });
-
- Ext.Array.each(me.query('inputpanel'), function(panel) {
- panel.setValues(values);
- });
- },
-
- submit: function() {
- var me = this;
-
- var form = me.formPanel.getForm();
-
- var values = me.getValues();
- Ext.Object.each(values, function(name, val) {
- if (values.hasOwnProperty(name)) {
- if (Ext.isArray(val) && !val.length) {
- values[name] = '';
- }
- }
- });
-
- if (me.digest) {
- values.digest = me.digest;
- }
-
- if (me.backgroundDelay) {
- values.background_delay = me.backgroundDelay;
- }
-
- var url = me.url;
- if (me.method === 'DELETE') {
- url = url + "?" + Ext.Object.toQueryString(values);
- values = undefined;
- }
-
- Proxmox.Utils.API2Request({
- url: url,
- waitMsgTarget: me,
- method: me.method || (me.backgroundDelay ? 'POST' : 'PUT'),
- params: values,
- failure: function(response, options) {
- me.apiCallDone(false, response, options);
-
- if (response.result && response.result.errors) {
- form.markInvalid(response.result.errors);
- }
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var hasProgressBar = (me.backgroundDelay || me.showProgress || me.showTaskViewer) &&
- response.result.data ? true : false;
-
- me.apiCallDone(true, response, options);
-
- if (hasProgressBar) {
- // stay around so we can trigger our close events
- // when background action is completed
- me.hide();
-
- var upid = response.result.data;
- var viewerClass = me.showTaskViewer ? 'Viewer' : 'Progress';
- var win = Ext.create('Proxmox.window.Task' + viewerClass, {
- upid: upid,
- taskDone: me.taskDone,
- listeners: {
- destroy: function () {
- me.close();
- }
- }
- });
- win.show();
- } else {
- me.close();
- }
- }
- });
- },
-
- load: function(options) {
- var me = this;
-
- var form = me.formPanel.getForm();
-
- options = options || {};
-
- var newopts = Ext.apply({
- waitMsgTarget: me
- }, options);
-
- var createWrapper = function(successFn) {
- Ext.apply(newopts, {
- url: me.url,
- method: 'GET',
- success: function(response, opts) {
- form.clearInvalid();
- me.digest = response.result.data.digest;
- if (successFn) {
- successFn(response, opts);
- } else {
- me.setValues(response.result.data);
- }
- // hack: fix ExtJS bug
- Ext.Array.each(me.query('radiofield'), function(f) {
- f.resetOriginalValue();
- });
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus, function() {
- me.close();
- });
- }
- });
- };
-
- createWrapper(options.success);
-
- Proxmox.Utils.API2Request(newopts);
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.url) {
- throw "no url specified";
- }
-
- if (me.create) {throw "deprecated parameter, use isCreate";}
-
- var items = Ext.isArray(me.items) ? me.items : [ me.items ];
-
- me.items = undefined;
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- url: me.url,
- method: me.method || 'PUT',
- trackResetOnLoad: true,
- bodyPadding: 10,
- border: false,
- defaults: Ext.apply({}, me.defaults, {
- border: false
- }),
- fieldDefaults: Ext.apply({}, me.fieldDefaults, {
- labelWidth: 100,
- anchor: '100%'
- }),
- items: items
- });
-
- var inputPanel = me.formPanel.down('inputpanel');
-
- var form = me.formPanel.getForm();
-
- var submitText;
- if (me.isCreate) {
- if (me.submitText) {
- submitText = me.submitText;
- } else if (me.isAdd) {
- submitText = gettext('Add');
- } else if (me.isRemove) {
- submitText = gettext('Remove');
- } else {
- submitText = gettext('Create');
- }
- } else {
- submitText = me.submitText || gettext('OK');
- }
-
- var submitBtn = Ext.create('Ext.Button', {
- reference: 'submitbutton',
- text: submitText,
- disabled: !me.isCreate,
- handler: function() {
- me.submit();
- }
- });
-
- var resetBtn = Ext.create('Ext.Button', {
- text: 'Reset',
- disabled: true,
- handler: function(){
- form.reset();
- }
- });
-
- var set_button_status = function() {
- var valid = form.isValid();
- var dirty = form.isDirty();
- submitBtn.setDisabled(!valid || !(dirty || me.isCreate));
- resetBtn.setDisabled(!dirty);
-
- if (inputPanel && inputPanel.hasAdvanced) {
- // we want to show the advanced options
- // as soon as some of it is not valid
- var advancedItems = me.down('#advancedContainer').query('field');
- var valid = true;
- advancedItems.forEach(function(field) {
- if (!field.isValid()) {
- valid = false;
- }
- });
-
- if (!valid) {
- inputPanel.setAdvancedVisible(true);
- me.down('#advancedcb').setValue(true);
- }
- }
- };
-
- form.on('dirtychange', set_button_status);
- form.on('validitychange', set_button_status);
-
- var colwidth = 300;
- if (me.fieldDefaults && me.fieldDefaults.labelWidth) {
- colwidth += me.fieldDefaults.labelWidth - 100;
- }
-
- var twoColumn = inputPanel &&
- (inputPanel.column1 || inputPanel.column2);
-
- if (me.subject && !me.title) {
- me.title = Proxmox.Utils.dialog_title(me.subject, me.isCreate, me.isAdd);
- }
-
- if (me.isCreate) {
- me.buttons = [ submitBtn ] ;
- } else {
- me.buttons = [ submitBtn, resetBtn ];
- }
-
- if (inputPanel && inputPanel.hasAdvanced) {
- var sp = Ext.state.Manager.getProvider();
- var advchecked = sp.get('proxmox-advanced-cb');
- inputPanel.setAdvancedVisible(advchecked);
- me.buttons.unshift(
- {
- xtype: 'proxmoxcheckbox',
- itemId: 'advancedcb',
- boxLabelAlign: 'before',
- boxLabel: gettext('Advanced'),
- stateId: 'proxmox-advanced-cb',
- value: advchecked,
- listeners: {
- change: function(cb, val) {
- inputPanel.setAdvancedVisible(val);
- sp.set('proxmox-advanced-cb', val);
- }
- }
- }
- );
- }
-
- var onlineHelp = me.onlineHelp;
- if (!onlineHelp && inputPanel && inputPanel.onlineHelp) {
- onlineHelp = inputPanel.onlineHelp;
- }
-
- if (onlineHelp) {
- var helpButton = Ext.create('Proxmox.button.Help');
- me.buttons.unshift(helpButton, '->');
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', onlineHelp);
- }
-
- Ext.applyIf(me, {
- modal: true,
- width: twoColumn ? colwidth*2 : colwidth,
- border: false,
- items: [ me.formPanel ]
- });
-
- me.callParent();
-
- // always mark invalid fields
- me.on('afterlayout', function() {
- // on touch devices, the isValid function
- // triggers a layout, which triggers an isValid
- // and so on
- // to prevent this we disable the layouting here
- // and enable it afterwards
- me.suspendLayout = true;
- me.isValid();
- me.suspendLayout = false;
- });
-
- if (me.autoLoad) {
- me.load();
- }
- }
-});
-Ext.define('Proxmox.window.PasswordEdit', {
- extend: 'Proxmox.window.Edit',
- alias: 'proxmoxWindowPasswordEdit',
-
- subject: gettext('Password'),
-
- url: '/api2/extjs/access/password',
-
- fieldDefaults: {
- labelWidth: 120
- },
-
- items: [
- {
- xtype: 'textfield',
- inputType: 'password',
- fieldLabel: gettext('Password'),
- minLength: 5,
- allowBlank: false,
- name: 'password',
- listeners: {
- change: function(field){
- field.next().validate();
- },
- blur: function(field){
- field.next().validate();
- }
- }
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- fieldLabel: gettext('Confirm password'),
- name: 'verifypassword',
- allowBlank: false,
- vtype: 'password',
- initialPassField: 'password',
- submitValue: false
- },
- {
- xtype: 'hiddenfield',
- name: 'userid'
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.userid) {
- throw "no userid specified";
- }
-
- me.callParent();
- me.down('[name=userid]').setValue(me.userid);
- }
-});
-Ext.define('Proxmox.window.TaskProgress', {
- extend: 'Ext.window.Window',
- alias: 'widget.proxmoxTaskProgress',
-
- taskDone: Ext.emptyFn,
-
- initComponent: function() {
- var me = this;
-
- if (!me.upid) {
- throw "no task specified";
- }
-
- var task = Proxmox.Utils.parse_task_upid(me.upid);
-
- var statstore = Ext.create('Proxmox.data.ObjectStore', {
- url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + "/status",
- interval: 1000,
- rows: {
- status: { defaultValue: 'unknown' },
- exitstatus: { defaultValue: 'unknown' }
- }
- });
-
- me.on('destroy', statstore.stopUpdate);
-
- var getObjectValue = function(key, defaultValue) {
- var rec = statstore.getById(key);
- if (rec) {
- return rec.data.value;
- }
- return defaultValue;
- };
-
- var pbar = Ext.create('Ext.ProgressBar', { text: 'running...' });
-
- me.mon(statstore, 'load', function() {
- var status = getObjectValue('status');
- if (status === 'stopped') {
- var exitstatus = getObjectValue('exitstatus');
- if (exitstatus == 'OK') {
- pbar.reset();
- pbar.updateText("Done!");
- Ext.Function.defer(me.close, 1000, me);
- } else {
- me.close();
- Ext.Msg.alert('Task failed', exitstatus);
- }
- me.taskDone(exitstatus == 'OK');
- }
- });
-
- var descr = Proxmox.Utils.format_task_description(task.type, task.id);
-
- Ext.apply(me, {
- title: gettext('Task') + ': ' + descr,
- width: 300,
- layout: 'auto',
- modal: true,
- bodyPadding: 5,
- items: pbar,
- buttons: [
- {
- text: gettext('Details'),
- handler: function() {
- var win = Ext.create('Proxmox.window.TaskViewer', {
- taskDone: me.taskDone,
- upid: me.upid
- });
- win.show();
- me.close();
- }
- }
- ]
- });
-
- me.callParent();
-
- statstore.startUpdate();
-
- pbar.wait();
- }
-});
-
-// fixme: how can we avoid those lint errors?
-/*jslint confusion: true */
-
-Ext.define('Proxmox.window.TaskViewer', {
- extend: 'Ext.window.Window',
- alias: 'widget.proxmoxTaskViewer',
-
- extraTitle: '', // string to prepend after the generic task title
-
- taskDone: Ext.emptyFn,
-
- initComponent: function() {
- var me = this;
-
- if (!me.upid) {
- throw "no task specified";
- }
-
- var task = Proxmox.Utils.parse_task_upid(me.upid);
-
- var statgrid;
-
- var rows = {
- status: {
- header: gettext('Status'),
- defaultValue: 'unknown',
- renderer: function(value) {
- if (value != 'stopped') {
- return value;
- }
- var es = statgrid.getObjectValue('exitstatus');
- if (es) {
- return value + ': ' + es;
- }
- }
- },
- exitstatus: {
- visible: false
- },
- type: {
- header: gettext('Task type'),
- required: true
- },
- user: {
- header: gettext('User name'),
- required: true
- },
- node: {
- header: gettext('Node'),
- required: true
- },
- pid: {
- header: gettext('Process ID'),
- required: true
- },
- starttime: {
- header: gettext('Start Time'),
- required: true,
- renderer: Proxmox.Utils.render_timestamp
- },
- upid: {
- header: gettext('Unique task ID')
- }
- };
-
- var statstore = Ext.create('Proxmox.data.ObjectStore', {
- url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + "/status",
- interval: 1000,
- rows: rows
- });
-
- me.on('destroy', statstore.stopUpdate);
-
- var stop_task = function() {
- Proxmox.Utils.API2Request({
- url: "/nodes/" + task.node + "/tasks/" + me.upid,
- waitMsgTarget: me,
- method: 'DELETE',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var stop_btn1 = new Ext.Button({
- text: gettext('Stop'),
- disabled: true,
- handler: stop_task
- });
-
- var stop_btn2 = new Ext.Button({
- text: gettext('Stop'),
- disabled: true,
- handler: stop_task
- });
-
- statgrid = Ext.create('Proxmox.grid.ObjectGrid', {
- title: gettext('Status'),
- layout: 'fit',
- tbar: [ stop_btn1 ],
- rstore: statstore,
- rows: rows,
- border: false
- });
-
- var logView = Ext.create('Proxmox.panel.LogView', {
- title: gettext('Output'),
- tbar: [ stop_btn2 ],
- border: false,
- url: "/api2/extjs/nodes/" + task.node + "/tasks/" + me.upid + "/log"
- });
-
- me.mon(statstore, 'load', function() {
- var status = statgrid.getObjectValue('status');
-
- if (status === 'stopped') {
- logView.scrollToEnd = false;
- logView.requestUpdate();
- statstore.stopUpdate();
- me.taskDone(statgrid.getObjectValue('exitstatus') == 'OK');
- }
-
- stop_btn1.setDisabled(status !== 'running');
- stop_btn2.setDisabled(status !== 'running');
- });
-
- statstore.startUpdate();
-
- Ext.apply(me, {
- title: "Task viewer: " + task.desc + me.extraTitle,
- width: 800,
- height: 400,
- layout: 'fit',
- modal: true,
- items: [{
- xtype: 'tabpanel',
- region: 'center',
- items: [ logView, statgrid ]
- }]
- });
-
- me.callParent();
-
- logView.fireEvent('show', logView);
- }
-});
-
-Ext.define('apt-pkglist', {
- extend: 'Ext.data.Model',
- fields: [ 'Package', 'Title', 'Description', 'Section', 'Arch',
- 'Priority', 'Version', 'OldVersion', 'ChangeLogUrl', 'Origin' ],
- idProperty: 'Package'
-});
-
-Ext.define('Proxmox.node.APT', {
- extend: 'Ext.grid.GridPanel',
-
- xtype: 'proxmoxNodeAPT',
-
- upgradeBtn: undefined,
-
- columns: [
- {
- header: gettext('Package'),
- width: 200,
- sortable: true,
- dataIndex: 'Package'
- },
- {
- text: gettext('Version'),
- columns: [
- {
- header: gettext('current'),
- width: 100,
- sortable: false,
- dataIndex: 'OldVersion'
- },
- {
- header: gettext('new'),
- width: 100,
- sortable: false,
- dataIndex: 'Version'
- }
- ]
- },
- {
- header: gettext('Description'),
- sortable: false,
- dataIndex: 'Title',
- flex: 1
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var store = Ext.create('Ext.data.Store', {
- model: 'apt-pkglist',
- groupField: 'Origin',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + "/apt/update"
- },
- sorters: [
- {
- property : 'Package',
- direction: 'ASC'
- }
- ]
- });
-
- var groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
- groupHeaderTpl: '{[ "Origin: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})',
- enableGroupingMenu: false
- });
-
- var rowBodyFeature = Ext.create('Ext.grid.feature.RowBody', {
- getAdditionalData: function (data, rowIndex, record, orig) {
- var headerCt = this.view.headerCt;
- var colspan = headerCt.getColumnCount();
- // Usually you would style the my-body-class in CSS file
- return {
- rowBody: '' +
- Ext.String.htmlEncode(data.Description) +
- '
',
- rowBodyColspan: colspan
- };
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- Proxmox.Utils.monStoreErrors(me, store, true);
-
- var apt_command = function(cmd){
- Proxmox.Utils.API2Request({
- url: "/nodes/" + me.nodename + "/apt/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- me.mon(win, 'close', reload);
- }
- });
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var update_btn = new Ext.Button({
- text: gettext('Refresh'),
- handler: function(){
- Proxmox.Utils.checked_command(function() { apt_command('update'); });
- }
- });
-
- var show_changelog = function(rec) {
- if (!rec || !rec.data || !(rec.data.ChangeLogUrl && rec.data.Package)) {
- return;
- }
-
- var view = Ext.createWidget('component', {
- autoScroll: true,
- style: {
- 'background-color': 'white',
- 'white-space': 'pre',
- 'font-family': 'monospace',
- padding: '5px'
- }
- });
-
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Changelog') + ": " + rec.data.Package,
- width: 800,
- height: 400,
- layout: 'fit',
- modal: true,
- items: [ view ]
- });
-
- Proxmox.Utils.API2Request({
- waitMsgTarget: me,
- url: "/nodes/" + me.nodename + "/apt/changelog",
- params: {
- name: rec.data.Package,
- version: rec.data.Version
- },
- method: 'GET',
- failure: function(response, opts) {
- win.close();
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- win.show();
- view.update(Ext.htmlEncode(response.result.data));
- }
- });
-
- };
-
- var changelog_btn = new Proxmox.button.Button({
- text: gettext('Changelog'),
- selModel: sm,
- disabled: true,
- enableFn: function(rec) {
- if (!rec || !rec.data || !(rec.data.ChangeLogUrl && rec.data.Package)) {
- return false;
- }
- return true;
- },
- handler: function(b, e, rec) {
- show_changelog(rec);
- }
- });
-
- if (me.upgradeBtn) {
- me.tbar = [ update_btn, me.upgradeBtn, changelog_btn ];
- } else {
- me.tbar = [ update_btn, changelog_btn ];
- }
-
- Ext.apply(me, {
- store: store,
- stateful: true,
- stateId: 'grid-update',
- selModel: sm,
- viewConfig: {
- stripeRows: false,
- emptyText: '' + gettext('No updates available.') + '
'
- },
- features: [ groupingFeature, rowBodyFeature ],
- listeners: {
- activate: reload,
- itemdblclick: function(v, rec) {
- show_changelog(rec);
- }
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.node.NetworkEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.proxmoxNodeNetworkEdit'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.iftype) {
- throw "no network device type specified";
- }
-
- me.isCreate = !me.iface;
-
- var iface_vtype;
-
- if (me.iftype === 'bridge') {
- iface_vtype = 'BridgeName';
- } else if (me.iftype === 'bond') {
- iface_vtype = 'BondName';
- } else if (me.iftype === 'eth' && !me.isCreate) {
- iface_vtype = 'InterfaceName';
- } else if (me.iftype === 'vlan' && !me.isCreate) {
- iface_vtype = 'InterfaceName';
- } else if (me.iftype === 'OVSBridge') {
- iface_vtype = 'BridgeName';
- } else if (me.iftype === 'OVSBond') {
- iface_vtype = 'BondName';
- } else if (me.iftype === 'OVSIntPort') {
- iface_vtype = 'InterfaceName';
- } else if (me.iftype === 'OVSPort') {
- iface_vtype = 'InterfaceName';
- } else {
- console.log(me.iftype);
- throw "unknown network device type specified";
- }
-
- me.subject = Proxmox.Utils.render_network_iface_type(me.iftype);
-
- var column2 = [];
-
- if (!(me.iftype === 'OVSIntPort' || me.iftype === 'OVSPort' ||
- me.iftype === 'OVSBond')) {
- column2.push({
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Autostart'),
- name: 'autostart',
- uncheckedValue: 0,
- checked: me.isCreate ? true : undefined
- });
- }
-
- if (me.iftype === 'bridge') {
- column2.push({
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('VLAN aware'),
- name: 'bridge_vlan_aware',
- deleteEmpty: !me.isCreate
- });
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('Bridge ports'),
- name: 'bridge_ports'
- });
- } else if (me.iftype === 'OVSBridge') {
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('Bridge ports'),
- name: 'ovs_ports'
- });
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('OVS options'),
- name: 'ovs_options'
- });
- } else if (me.iftype === 'OVSPort' || me.iftype === 'OVSIntPort') {
- column2.push({
- xtype: me.isCreate ? 'PVE.form.BridgeSelector' : 'displayfield',
- fieldLabel: Proxmox.Utils.render_network_iface_type('OVSBridge'),
- allowBlank: false,
- nodename: me.nodename,
- bridgeType: 'OVSBridge',
- name: 'ovs_bridge'
- });
- column2.push({
- xtype: 'pveVlanField',
- deleteEmpty: !me.isCreate,
- name: 'ovs_tag',
- value: ''
- });
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('OVS options'),
- name: 'ovs_options'
- });
- } else if (me.iftype === 'bond') {
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('Slaves'),
- name: 'slaves'
- });
-
- var policySelector = Ext.createWidget('bondPolicySelector', {
- fieldLabel: gettext('Hash policy'),
- name: 'bond_xmit_hash_policy',
- deleteEmpty: !me.isCreate,
- disabled: true
- });
-
- column2.push({
- xtype: 'bondModeSelector',
- fieldLabel: gettext('Mode'),
- name: 'bond_mode',
- value: me.isCreate ? 'balance-rr' : undefined,
- listeners: {
- change: function(f, value) {
- if (value === 'balance-xor' ||
- value === '802.3ad') {
- policySelector.setDisabled(false);
- } else {
- policySelector.setDisabled(true);
- policySelector.setValue('');
- }
- }
- },
- allowBlank: false
- });
-
- column2.push(policySelector);
-
- } else if (me.iftype === 'OVSBond') {
- column2.push({
- xtype: me.isCreate ? 'PVE.form.BridgeSelector' : 'displayfield',
- fieldLabel: Proxmox.Utils.render_network_iface_type('OVSBridge'),
- allowBlank: false,
- nodename: me.nodename,
- bridgeType: 'OVSBridge',
- name: 'ovs_bridge'
- });
- column2.push({
- xtype: 'pveVlanField',
- deleteEmpty: !me.isCreate,
- name: 'ovs_tag',
- value: ''
- });
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('OVS options'),
- name: 'ovs_options'
- });
- }
-
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('Comment'),
- allowBlank: true,
- nodename: me.nodename,
- name: 'comments'
- });
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = "/api2/extjs/nodes/" + me.nodename + "/network";
- method = 'POST';
- } else {
- url = "/api2/extjs/nodes/" + me.nodename + "/network/" + me.iface;
- method = 'PUT';
- }
-
- var column1 = [
- {
- xtype: 'hiddenfield',
- name: 'type',
- value: me.iftype
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- fieldLabel: gettext('Name'),
- name: 'iface',
- value: me.iface,
- vtype: iface_vtype,
- allowBlank: false
- }
- ];
-
- if (me.iftype === 'OVSBond') {
- column1.push(
- {
- xtype: 'bondModeSelector',
- fieldLabel: gettext('Mode'),
- name: 'bond_mode',
- openvswitch: true,
- value: me.isCreate ? 'active-backup' : undefined,
- allowBlank: false
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Slaves'),
- name: 'ovs_bonds'
- }
- );
- } else {
-
- column1.push(
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: gettext('IP address'),
- vtype: 'IPAddress',
- name: 'address'
- },
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: gettext('Subnet mask'),
- vtype: 'IPAddress',
- name: 'netmask',
- validator: function(value) {
- /*jslint confusion: true */
- if (!me.items) {
- return true;
- }
- var address = me.down('field[name=address]').getValue();
- if (value !== '') {
- if (address === '') {
- return "Subnet mask requires option 'IP address'";
- }
- } else {
- if (address !== '') {
- return "Option 'IP address' requires a subnet mask";
- }
- }
-
- return true;
- }
- },
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: gettext('Gateway'),
- vtype: 'IPAddress',
- name: 'gateway'
- },
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: gettext('IPv6 address'),
- vtype: 'IP6Address',
- name: 'address6'
- },
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: gettext('Prefix length'),
- vtype: 'IP6PrefixLength',
- name: 'netmask6',
- value: '',
- allowBlank: true,
- validator: function(value) {
- /*jslint confusion: true */
- if (!me.items) {
- return true;
- }
- var address = me.down('field[name=address6]').getValue();
- if (value !== '') {
- if (address === '') {
- return "IPv6 prefix length requires option 'IPv6 address'";
- }
- } else {
- if (address !== '') {
- return "Option 'IPv6 address' requires an IPv6 prefix length";
- }
- }
-
- return true;
- }
- },
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: gettext('Gateway'),
- vtype: 'IP6Address',
- name: 'gateway6'
- }
- );
- }
-
- Ext.applyIf(me, {
- url: url,
- method: method,
- items: {
- xtype: 'inputpanel',
- column1: column1,
- column2: column2
- }
- });
-
- me.callParent();
-
- if (me.isCreate) {
- me.down('field[name=iface]').setValue(me.iface_default);
- } else {
- me.load({
- success: function(response, options) {
- var data = response.result.data;
- if (data.type !== me.iftype) {
- var msg = "Got unexpected device type";
- Ext.Msg.alert(gettext('Error'), msg, function() {
- me.close();
- });
- return;
- }
- me.setValues(data);
- me.isValid(); // trigger validation
- }
- });
- }
- }
-});
-Ext.define('proxmox-networks', {
- extend: 'Ext.data.Model',
- fields: [
- 'iface', 'type', 'active', 'autostart',
- 'bridge_ports', 'slaves',
- 'address', 'netmask', 'gateway',
- 'address6', 'netmask6', 'gateway6',
- 'comments'
- ],
- idProperty: 'iface'
-});
-
-Ext.define('Proxmox.node.NetworkView', {
- extend: 'Ext.panel.Panel',
-
- alias: ['widget.proxmoxNodeNetworkView'],
-
- // defines what types of network devices we want to create
- // order is always the same
- types: ['bridge', 'bond', 'ovs'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var baseUrl = '/nodes/' + me.nodename + '/network';
-
- var store = Ext.create('Ext.data.Store', {
- model: 'proxmox-networks',
- proxy: {
- type: 'proxmox',
- url: '/api2/json' + baseUrl
- },
- sorters: [
- {
- property : 'iface',
- direction: 'ASC'
- }
- ]
- });
-
- var reload = function() {
- var changeitem = me.down('#changes');
- Proxmox.Utils.API2Request({
- url: baseUrl,
- failure: function(response, opts) {
- store.loadData({});
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- changeitem.update('');
- changeitem.setHidden(true);
- },
- success: function(response, opts) {
- var result = Ext.decode(response.responseText);
- store.loadData(result.data);
- var changes = result.changes;
- if (changes === undefined || changes === '') {
- changes = gettext("No changes");
- changeitem.setHidden(true);
- } else {
- changeitem.update("" + Ext.htmlEncode(changes) + " ");
- changeitem.setHidden(false);
- }
- }
- });
- };
-
- var run_editor = function() {
- var grid = me.down('gridpanel');
- var sm = grid.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iface: rec.data.iface,
- iftype: rec.data.type
- });
- win.show();
- win.on('destroy', reload);
- };
-
- var edit_btn = new Ext.Button({
- text: gettext('Edit'),
- disabled: true,
- handler: run_editor
- });
-
- var del_btn = new Ext.Button({
- text: gettext('Remove'),
- disabled: true,
- handler: function(){
- var grid = me.down('gridpanel');
- var sm = grid.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var iface = rec.data.iface;
-
- Proxmox.Utils.API2Request({
- url: baseUrl + '/' + iface,
- method: 'DELETE',
- waitMsgTarget: me,
- callback: function() {
- reload();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- var set_button_status = function() {
- var grid = me.down('gridpanel');
- var sm = grid.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- edit_btn.setDisabled(!rec);
- del_btn.setDisabled(!rec);
- };
-
- var render_ports = function(value, metaData, record) {
- if (value === 'bridge') {
- return record.data.bridge_ports;
- } else if (value === 'bond') {
- return record.data.slaves;
- } else if (value === 'OVSBridge') {
- return record.data.ovs_ports;
- } else if (value === 'OVSBond') {
- return record.data.ovs_bonds;
- }
- };
-
- var find_next_iface_id = function(prefix) {
- var next;
- for (next = 0; next <= 9999; next++) {
- if (!store.getById(prefix + next.toString())) {
- break;
- }
- }
- return prefix + next.toString();
- };
-
- var menu_items = [];
-
- if (me.types.indexOf('bridge') !== -1) {
- menu_items.push({
- text: Proxmox.Utils.render_network_iface_type('bridge'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'bridge',
- iface_default: find_next_iface_id('vmbr')
- });
- win.on('destroy', reload);
- win.show();
- }
- });
- }
-
- if (me.types.indexOf('bond') !== -1) {
- menu_items.push({
- text: Proxmox.Utils.render_network_iface_type('bond'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'bond',
- iface_default: find_next_iface_id('bond')
- });
- win.on('destroy', reload);
- win.show();
- }
- });
- }
-
- if (me.types.indexOf('ovs') !== -1) {
- if (menu_items.length > 0) {
- menu_items.push({ xtype: 'menuseparator' });
- }
-
- menu_items.push(
- {
- text: Proxmox.Utils.render_network_iface_type('OVSBridge'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'OVSBridge',
- iface_default: find_next_iface_id('vmbr')
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: Proxmox.Utils.render_network_iface_type('OVSBond'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'OVSBond',
- iface_default: find_next_iface_id('bond')
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: Proxmox.Utils.render_network_iface_type('OVSIntPort'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'OVSIntPort'
- });
- win.on('destroy', reload);
- win.show();
- }
- }
- );
- }
-
- Ext.apply(me, {
- layout: 'border',
- tbar: [
- {
- text: gettext('Create'),
- menu: {
- plain: true,
- items: menu_items
- }
- }, ' ',
- {
- text: gettext('Revert'),
- handler: function() {
- Proxmox.Utils.API2Request({
- url: baseUrl,
- method: 'DELETE',
- waitMsgTarget: me,
- callback: function() {
- reload();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- },
- edit_btn,
- del_btn
- ],
- items: [
- {
- xtype: 'gridpanel',
- stateful: true,
- stateId: 'grid-node-network',
- store: store,
- region: 'center',
- border: false,
- columns: [
- {
- header: gettext('Name'),
- sortable: true,
- dataIndex: 'iface'
- },
- {
- header: gettext('Type'),
- sortable: true,
- width: 120,
- renderer: Proxmox.Utils.render_network_iface_type,
- dataIndex: 'type'
- },
- {
- xtype: 'booleancolumn',
- header: gettext('Active'),
- width: 80,
- sortable: true,
- dataIndex: 'active',
- trueText: Proxmox.Utils.yesText,
- falseText: Proxmox.Utils.noText,
- undefinedText: Proxmox.Utils.noText,
- },
- {
- xtype: 'booleancolumn',
- header: gettext('Autostart'),
- width: 80,
- sortable: true,
- dataIndex: 'autostart',
- trueText: Proxmox.Utils.yesText,
- falseText: Proxmox.Utils.noText,
- undefinedText: Proxmox.Utils.noText
- },
- {
- xtype: 'booleancolumn',
- header: gettext('VLAN aware'),
- width: 80,
- sortable: true,
- dataIndex: 'bridge_vlan_aware',
- trueText: Proxmox.Utils.yesText,
- falseText: Proxmox.Utils.noText,
- undefinedText: Proxmox.Utils.noText
- },
- {
- header: gettext('Ports/Slaves'),
- dataIndex: 'type',
- renderer: render_ports
- },
- {
- header: gettext('IP address'),
- sortable: true,
- width: 120,
- dataIndex: 'address',
- renderer: function(value, metaData, rec) {
- if (rec.data.address && rec.data.address6) {
- return rec.data.address + " "
- + rec.data.address6 + '/' + rec.data.netmask6;
- } else if (rec.data.address6) {
- return rec.data.address6 + '/' + rec.data.netmask6;
- } else {
- return rec.data.address;
- }
- }
- },
- {
- header: gettext('Subnet mask'),
- width: 120,
- sortable: true,
- dataIndex: 'netmask'
- },
- {
- header: gettext('Gateway'),
- width: 120,
- sortable: true,
- dataIndex: 'gateway',
- renderer: function(value, metaData, rec) {
- if (rec.data.gateway && rec.data.gateway6) {
- return rec.data.gateway + " " + rec.data.gateway6;
- } else if (rec.data.gateway6) {
- return rec.data.gateway6;
- } else {
- return rec.data.gateway;
- }
- }
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comments',
- flex: 1,
- renderer: Ext.String.htmlEncode
- }
- ],
- listeners: {
- selectionchange: set_button_status,
- itemdblclick: run_editor
- }
- },
- {
- border: false,
- region: 'south',
- autoScroll: true,
- hidden: true,
- itemId: 'changes',
- tbar: [
- gettext('Pending changes') + ' (' +
- gettext('Please reboot to activate changes') + ')'
- ],
- split: true,
- bodyPadding: 5,
- flex: 0.6,
- html: gettext("No changes")
- }
- ],
- });
-
- me.callParent();
- reload();
- }
-});
-Ext.define('Proxmox.node.DNSEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.proxmoxNodeDNSEdit'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.items = [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Search domain'),
- name: 'search',
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('DNS server') + " 1",
- vtype: 'IP64Address',
- skipEmptyText: true,
- name: 'dns1'
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('DNS server') + " 2",
- vtype: 'IP64Address',
- skipEmptyText: true,
- name: 'dns2'
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('DNS server') + " 3",
- vtype: 'IP64Address',
- skipEmptyText: true,
- name: 'dns3'
- }
- ];
-
- Ext.applyIf(me, {
- subject: gettext('DNS'),
- url: "/api2/extjs/nodes/" + me.nodename + "/dns",
- fieldDefaults: {
- labelWidth: 120
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('Proxmox.node.HostsView', {
- extend: 'Ext.panel.Panel',
- xtype: 'proxmoxNodeHostsView',
-
- reload: function() {
- var me = this;
- me.store.load();
- },
-
- tbar: [
- {
- text: gettext('Save'),
- disabled: true,
- itemId: 'savebtn',
- handler: function() {
- var me = this.up('panel');
- Proxmox.Utils.API2Request({
- params: {
- digest: me.digest,
- data: me.down('#hostsfield').getValue()
- },
- method: 'POST',
- url: '/nodes/' + me.nodename + '/hosts',
- waitMsgTarget: me,
- success: function(response, opts) {
- me.reload();
- },
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- }
- },
- {
- text: gettext('Revert'),
- disabled: true,
- itemId: 'resetbtn',
- handler: function() {
- var me = this.up('panel');
- me.down('#hostsfield').reset();
- }
- }
- ],
-
- layout: 'fit',
-
- items: [
- {
- xtype: 'textarea',
- itemId: 'hostsfield',
- fieldStyle: {
- 'font-family': 'monospace',
- 'white-space': 'pre'
- },
- listeners: {
- dirtychange: function(ta, dirty) {
- var me = this.up('panel');
- me.down('#savebtn').setDisabled(!dirty);
- me.down('#resetbtn').setDisabled(!dirty);
- }
- }
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.store = Ext.create('Ext.data.Store', {
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + "/hosts",
- }
- });
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.store);
-
- me.mon(me.store, 'load', function(store, records, success) {
- if (!success || records.length < 1) {
- return;
- }
- me.digest = records[0].data.digest;
- var data = records[0].data.data;
- me.down('#hostsfield').setValue(data);
- me.down('#hostsfield').resetOriginalValue();
- });
-
- me.reload();
- }
-});
-Ext.define('Proxmox.node.DNSView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.proxmoxNodeDNSView'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var run_editor = function() {
- var win = Ext.create('Proxmox.node.DNSEdit', {
- nodename: me.nodename
- });
- win.show();
- };
-
- Ext.apply(me, {
- url: "/api2/json/nodes/" + me.nodename + "/dns",
- cwidth1: 130,
- interval: 1000,
- run_editor: run_editor,
- rows: {
- search: {
- header: 'Search domain',
- required: true,
- renderer: Ext.htmlEncode
- },
- dns1: {
- header: gettext('DNS server') + " 1",
- required: true,
- renderer: Ext.htmlEncode
- },
- dns2: {
- header: gettext('DNS server') + " 2",
- renderer: Ext.htmlEncode
- },
- dns3: {
- header: gettext('DNS server') + " 3",
- renderer: Ext.htmlEncode
- }
- },
- tbar: [
- {
- text: gettext("Edit"),
- handler: run_editor
- }
- ],
- listeners: {
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- }
-});
-Ext.define('Proxmox.node.Tasks', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.proxmoxNodeTasks'],
- stateful: true,
- stateId: 'grid-node-tasks',
- loadMask: true,
- sortableColumns: false,
- vmidFilter: 0,
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var store = Ext.create('Ext.data.BufferedStore', {
- pageSize: 500,
- autoLoad: true,
- remoteFilter: true,
- model: 'proxmox-tasks',
- proxy: {
- type: 'proxmox',
- startParam: 'start',
- limitParam: 'limit',
- url: "/api2/json/nodes/" + me.nodename + "/tasks"
- }
- });
-
- var userfilter = '';
- var filter_errors = 0;
-
- var updateProxyParams = function() {
- var params = {
- errors: filter_errors
- };
- if (userfilter) {
- params.userfilter = userfilter;
- }
- if (me.vmidFilter) {
- params.vmid = me.vmidFilter;
- }
- store.proxy.extraParams = params;
- };
-
- updateProxyParams();
-
- var reload_task = Ext.create('Ext.util.DelayedTask',function() {
- updateProxyParams();
- store.reload();
- });
-
- var run_task_viewer = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: rec.data.upid
- });
- win.show();
- };
-
- var view_btn = new Ext.Button({
- text: gettext('View'),
- disabled: true,
- handler: run_task_viewer
- });
-
- Proxmox.Utils.monStoreErrors(me, store, true);
-
- Ext.apply(me, {
- store: store,
- viewConfig: {
- trackOver: false,
- stripeRows: false, // does not work with getRowClass()
-
- getRowClass: function(record, index) {
- var status = record.get('status');
-
- if (status && status != 'OK') {
- return "proxmox-invalid-row";
- }
- }
- },
- tbar: [
- view_btn, '->', gettext('User name') +':', ' ',
- {
- xtype: 'textfield',
- width: 200,
- value: userfilter,
- enableKeyEvents: true,
- listeners: {
- keyup: function(field, e) {
- userfilter = field.getValue();
- reload_task.delay(500);
- }
- }
- }, ' ', gettext('Only Errors') + ':', ' ',
- {
- xtype: 'checkbox',
- hideLabel: true,
- checked: filter_errors,
- listeners: {
- change: function(field, checked) {
- filter_errors = checked ? 1 : 0;
- reload_task.delay(10);
- }
- }
- }, ' '
- ],
- columns: [
- {
- header: gettext("Start Time"),
- dataIndex: 'starttime',
- width: 100,
- renderer: function(value) {
- return Ext.Date.format(value, "M d H:i:s");
- }
- },
- {
- header: gettext("End Time"),
- dataIndex: 'endtime',
- width: 100,
- renderer: function(value, metaData, record) {
- return Ext.Date.format(value,"M d H:i:s");
- }
- },
- {
- header: gettext("Node"),
- dataIndex: 'node',
- width: 100
- },
- {
- header: gettext("User name"),
- dataIndex: 'user',
- width: 150
- },
- {
- header: gettext("Description"),
- dataIndex: 'upid',
- flex: 1,
- renderer: Proxmox.Utils.render_upid
- },
- {
- header: gettext("Status"),
- dataIndex: 'status',
- width: 200,
- renderer: function(value, metaData, record) {
- if (value == 'OK') {
- return 'OK';
- }
- // metaData.attr = 'style="color:red;"';
- return "ERROR: " + value;
- }
- }
- ],
- listeners: {
- itemdblclick: run_task_viewer,
- selectionchange: function(v, selections) {
- view_btn.setDisabled(!(selections && selections[0]));
- },
- show: function() { reload_task.delay(10); },
- destroy: function() { reload_task.cancel(); }
- }
- });
-
- me.callParent();
-
- }
-});
-Ext.define('proxmox-services', {
- extend: 'Ext.data.Model',
- fields: [ 'service', 'name', 'desc', 'state' ],
- idProperty: 'service'
-});
-
-Ext.define('Proxmox.node.ServiceView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.proxmoxNodeServiceView'],
-
- startOnlyServices: {},
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var rstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 1000,
- storeid: 'proxmox-services' + me.nodename,
- model: 'proxmox-services',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + "/services"
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: rstore,
- sortAfterUpdate: true,
- sorters: [
- {
- property : 'name',
- direction: 'ASC'
- }
- ]
- });
-
- var view_service_log = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Syslog') + ': ' + rec.data.service,
- modal: true,
- items: {
- xtype: 'proxmoxLogView',
- width: 800,
- height: 400,
- url: "/api2/extjs/nodes/" + me.nodename + "/syslog?service=" +
- rec.data.service,
- log_select_timespan: 1
- }
- });
- win.show();
- };
-
- var service_cmd = function(cmd) {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- Proxmox.Utils.API2Request({
- url: "/nodes/" + me.nodename + "/services/" + rec.data.service + "/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- me.loading = true;
- },
- success: function(response, opts) {
- rstore.startUpdate();
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid
- });
- win.show();
- }
- });
- };
-
- var start_btn = new Ext.Button({
- text: gettext('Start'),
- disabled: true,
- handler: function(){
- service_cmd("start");
- }
- });
-
- var stop_btn = new Ext.Button({
- text: gettext('Stop'),
- disabled: true,
- handler: function(){
- service_cmd("stop");
- }
- });
-
- var restart_btn = new Ext.Button({
- text: gettext('Restart'),
- disabled: true,
- handler: function(){
- service_cmd("restart");
- }
- });
-
- var syslog_btn = new Ext.Button({
- text: gettext('Syslog'),
- disabled: true,
- handler: view_service_log
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- start_btn.disable();
- stop_btn.disable();
- restart_btn.disable();
- syslog_btn.disable();
- return;
- }
- var service = rec.data.service;
- var state = rec.data.state;
-
- syslog_btn.enable();
-
- if (me.startOnlyServices[service]) {
- if (state == 'running') {
- start_btn.disable();
- restart_btn.enable();
- } else {
- start_btn.enable();
- restart_btn.disable();
- }
- stop_btn.disable();
- } else {
- if (state == 'running') {
- start_btn.disable();
- restart_btn.enable();
- stop_btn.enable();
- } else {
- start_btn.enable();
- restart_btn.disable();
- stop_btn.disable();
- }
- }
- };
-
- me.mon(store, 'refresh', set_button_status);
-
- Proxmox.Utils.monStoreErrors(me, rstore);
-
- Ext.apply(me, {
- store: store,
- stateful: false,
- tbar: [ start_btn, stop_btn, restart_btn, syslog_btn ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- dataIndex: 'name'
- },
- {
- header: gettext('Status'),
- width: 100,
- sortable: true,
- dataIndex: 'state'
- },
- {
- header: gettext('Description'),
- renderer: Ext.String.htmlEncode,
- dataIndex: 'desc',
- flex: 2
- }
- ],
- listeners: {
- selectionchange: set_button_status,
- itemdblclick: view_service_log,
- activate: rstore.startUpdate,
- destroy: rstore.stopUpdate
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.node.TimeEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.proxmoxNodeTimeEdit'],
-
- subject: gettext('Time zone'),
-
- width: 400,
-
- autoLoad: true,
-
- fieldDefaults: {
- labelWidth: 70
- },
-
- items: {
- xtype: 'combo',
- fieldLabel: gettext('Time zone'),
- name: 'timezone',
- queryMode: 'local',
- store: Ext.create('Proxmox.data.TimezoneStore'),
- displayField: 'zone',
- forceSelection: true,
- editable: false,
- allowBlank: false
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
- me.url = "/api2/extjs/nodes/" + me.nodename + "/time";
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.node.TimeView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.proxmoxNodeTimeView'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var tzoffset = (new Date()).getTimezoneOffset()*60000;
- var renderlocaltime = function(value) {
- var servertime = new Date((value * 1000) + tzoffset);
- return Ext.Date.format(servertime, 'Y-m-d H:i:s');
- };
-
- var run_editor = function() {
- var win = Ext.create('Proxmox.node.TimeEdit', {
- nodename: me.nodename
- });
- win.show();
- };
-
- Ext.apply(me, {
- url: "/api2/json/nodes/" + me.nodename + "/time",
- cwidth1: 150,
- interval: 1000,
- run_editor: run_editor,
- rows: {
- timezone: {
- header: gettext('Time zone'),
- required: true
- },
- localtime: {
- header: gettext('Server time'),
- required: true,
- renderer: renderlocaltime
- }
- },
- tbar: [
- {
- text: gettext("Edit"),
- handler: run_editor
- }
- ],
- listeners: {
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- }
-});
diff --git a/serverside/jsmod/5.4-3/pvemanagerlib.js b/serverside/jsmod/5.4-3/pvemanagerlib.js
deleted file mode 100644
index e62acde..0000000
--- a/serverside/jsmod/5.4-3/pvemanagerlib.js
+++ /dev/null
@@ -1,38347 +0,0 @@
-var pveOnlineHelpInfo = {
- "ceph_rados_block_devices" : {
- "link" : "/pve-docs/chapter-pvesm.html#ceph_rados_block_devices",
- "title" : "Ceph RADOS Block Devices (RBD)"
- },
- "chapter_ha_manager" : {
- "link" : "/pve-docs/chapter-ha-manager.html#chapter_ha_manager",
- "title" : "High Availability"
- },
- "chapter_lvm" : {
- "link" : "/pve-docs/chapter-sysadmin.html#chapter_lvm",
- "title" : "Logical Volume Manager (LVM)"
- },
- "chapter_pct" : {
- "link" : "/pve-docs/chapter-pct.html#chapter_pct",
- "title" : "Proxmox Container Toolkit"
- },
- "chapter_pve_firewall" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#chapter_pve_firewall",
- "title" : "Proxmox VE Firewall"
- },
- "chapter_pveceph" : {
- "link" : "/pve-docs/chapter-pveceph.html#chapter_pveceph",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "chapter_pvecm" : {
- "link" : "/pve-docs/chapter-pvecm.html#chapter_pvecm",
- "title" : "Cluster Manager"
- },
- "chapter_pvesr" : {
- "link" : "/pve-docs/chapter-pvesr.html#chapter_pvesr",
- "title" : "Storage Replication"
- },
- "chapter_storage" : {
- "link" : "/pve-docs/chapter-pvesm.html#chapter_storage",
- "title" : "Proxmox VE Storage"
- },
- "chapter_system_administration" : {
- "link" : "/pve-docs/chapter-sysadmin.html#chapter_system_administration",
- "title" : "Host System Administration"
- },
- "chapter_user_management" : {
- "link" : "/pve-docs/chapter-pveum.html#chapter_user_management",
- "title" : "User Management"
- },
- "chapter_virtual_machines" : {
- "link" : "/pve-docs/chapter-qm.html#chapter_virtual_machines",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "chapter_vzdump" : {
- "link" : "/pve-docs/chapter-vzdump.html#chapter_vzdump",
- "title" : "Backup and Restore"
- },
- "chapter_zfs" : {
- "link" : "/pve-docs/chapter-sysadmin.html#chapter_zfs",
- "title" : "ZFS on Linux"
- },
- "datacenter_configuration_file" : {
- "link" : "/pve-docs/pve-admin-guide.html#datacenter_configuration_file",
- "title" : "Datacenter Configuration"
- },
- "getting_help" : {
- "link" : "/pve-docs/pve-admin-guide.html#getting_help",
- "title" : "Getting Help"
- },
- "gui_my_settings" : {
- "link" : "/pve-docs/chapter-pve-gui.html#gui_my_settings",
- "subtitle" : "My Settings",
- "title" : "Graphical User Interface"
- },
- "ha_manager_fencing" : {
- "link" : "/pve-docs/chapter-ha-manager.html#ha_manager_fencing",
- "subtitle" : "Fencing",
- "title" : "High Availability"
- },
- "ha_manager_groups" : {
- "link" : "/pve-docs/chapter-ha-manager.html#ha_manager_groups",
- "subtitle" : "Groups",
- "title" : "High Availability"
- },
- "ha_manager_resource_config" : {
- "link" : "/pve-docs/chapter-ha-manager.html#ha_manager_resource_config",
- "subtitle" : "Resources",
- "title" : "High Availability"
- },
- "ha_manager_resources" : {
- "link" : "/pve-docs/chapter-ha-manager.html#ha_manager_resources",
- "subtitle" : "Resources",
- "title" : "High Availability"
- },
- "pct_configuration" : {
- "link" : "/pve-docs/chapter-pct.html#pct_configuration",
- "subtitle" : "Configuration",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_container_images" : {
- "link" : "/pve-docs/chapter-pct.html#pct_container_images",
- "subtitle" : "Container Images",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_container_network" : {
- "link" : "/pve-docs/chapter-pct.html#pct_container_network",
- "subtitle" : "Network",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_container_storage" : {
- "link" : "/pve-docs/chapter-pct.html#pct_container_storage",
- "subtitle" : "Container Storage",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_cpu" : {
- "link" : "/pve-docs/chapter-pct.html#pct_cpu",
- "subtitle" : "CPU",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_general" : {
- "link" : "/pve-docs/chapter-pct.html#pct_general",
- "subtitle" : "General Settings",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_memory" : {
- "link" : "/pve-docs/chapter-pct.html#pct_memory",
- "subtitle" : "Memory",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_migration" : {
- "link" : "/pve-docs/chapter-pct.html#pct_migration",
- "subtitle" : "Migration",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_options" : {
- "link" : "/pve-docs/chapter-pct.html#pct_options",
- "subtitle" : "Options",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_snapshots" : {
- "link" : "/pve-docs/chapter-pct.html#pct_snapshots",
- "subtitle" : "Snapshots",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_startup_and_shutdown" : {
- "link" : "/pve-docs/chapter-pct.html#pct_startup_and_shutdown",
- "subtitle" : "Automatic Start and Shutdown of Containers",
- "title" : "Proxmox Container Toolkit"
- },
- "pve_admin_guide" : {
- "link" : "/pve-docs/pve-admin-guide.html",
- "title" : "Proxmox VE Administration Guide"
- },
- "pve_ceph_install" : {
- "link" : "/pve-docs/chapter-pveceph.html#pve_ceph_install",
- "subtitle" : "Installation of Ceph Packages",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pve_ceph_monitors" : {
- "link" : "/pve-docs/chapter-pveceph.html#pve_ceph_monitors",
- "subtitle" : "Creating Ceph Monitors",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pve_ceph_osds" : {
- "link" : "/pve-docs/chapter-pveceph.html#pve_ceph_osds",
- "subtitle" : "Creating Ceph OSDs",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pve_ceph_pools" : {
- "link" : "/pve-docs/chapter-pveceph.html#pve_ceph_pools",
- "subtitle" : "Creating Ceph Pools",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pve_documentation_index" : {
- "link" : "/pve-docs/index.html",
- "title" : "Proxmox VE Documentation Index"
- },
- "pve_firewall_cluster_wide_setup" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_cluster_wide_setup",
- "subtitle" : "Cluster Wide Setup",
- "title" : "Proxmox VE Firewall"
- },
- "pve_firewall_host_specific_configuration" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_host_specific_configuration",
- "subtitle" : "Host Specific Configuration",
- "title" : "Proxmox VE Firewall"
- },
- "pve_firewall_ip_aliases" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_ip_aliases",
- "subtitle" : "IP Aliases",
- "title" : "Proxmox VE Firewall"
- },
- "pve_firewall_ip_sets" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_ip_sets",
- "subtitle" : "IP Sets",
- "title" : "Proxmox VE Firewall"
- },
- "pve_firewall_vm_container_configuration" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_vm_container_configuration",
- "subtitle" : "VM/Container Configuration",
- "title" : "Proxmox VE Firewall"
- },
- "pve_service_daemons" : {
- "link" : "/pve-docs/index.html#_service_daemons",
- "title" : "Service Daemons"
- },
- "pveceph_fs" : {
- "link" : "/pve-docs/chapter-pveceph.html#pveceph_fs",
- "subtitle" : "CephFS",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pveceph_fs_create" : {
- "link" : "/pve-docs/chapter-pveceph.html#pveceph_fs_create",
- "subtitle" : "Create a CephFS",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pveceph_fs_mds" : {
- "link" : "/pve-docs/chapter-pveceph.html#pveceph_fs_mds",
- "subtitle" : "Metadata Server (MDS)",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pvesr_schedule_time_format" : {
- "link" : "/pve-docs/chapter-pvesr.html#pvesr_schedule_time_format",
- "subtitle" : "Schedule Format",
- "title" : "Storage Replication"
- },
- "pveum_authentication_realms" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_authentication_realms",
- "subtitle" : "Authentication Realms",
- "title" : "User Management"
- },
- "pveum_groups" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_groups",
- "subtitle" : "Groups",
- "title" : "User Management"
- },
- "pveum_permission_management" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_permission_management",
- "subtitle" : "Permission Management",
- "title" : "User Management"
- },
- "pveum_pools" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_pools",
- "subtitle" : "Pools",
- "title" : "User Management"
- },
- "pveum_roles" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_roles",
- "subtitle" : "Roles",
- "title" : "User Management"
- },
- "pveum_tfa_auth" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_tfa_auth",
- "subtitle" : "Two factor authentication",
- "title" : "User Management"
- },
- "pveum_users" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_users",
- "subtitle" : "Users",
- "title" : "User Management"
- },
- "qm_bios_and_uefi" : {
- "link" : "/pve-docs/chapter-qm.html#qm_bios_and_uefi",
- "subtitle" : "BIOS and UEFI",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_cloud_init" : {
- "link" : "/pve-docs/chapter-qm.html#qm_cloud_init",
- "title" : "Cloud-Init Support"
- },
- "qm_copy_and_clone" : {
- "link" : "/pve-docs/chapter-qm.html#qm_copy_and_clone",
- "subtitle" : "Copies and Clones",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_cpu" : {
- "link" : "/pve-docs/chapter-qm.html#qm_cpu",
- "subtitle" : "CPU",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_general_settings" : {
- "link" : "/pve-docs/chapter-qm.html#qm_general_settings",
- "subtitle" : "General Settings",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_hard_disk" : {
- "link" : "/pve-docs/chapter-qm.html#qm_hard_disk",
- "subtitle" : "Hard Disk",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_memory" : {
- "link" : "/pve-docs/chapter-qm.html#qm_memory",
- "subtitle" : "Memory",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_migration" : {
- "link" : "/pve-docs/chapter-qm.html#qm_migration",
- "subtitle" : "Migration",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_network_device" : {
- "link" : "/pve-docs/chapter-qm.html#qm_network_device",
- "subtitle" : "Network Device",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_options" : {
- "link" : "/pve-docs/chapter-qm.html#qm_options",
- "subtitle" : "Options",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_os_settings" : {
- "link" : "/pve-docs/chapter-qm.html#qm_os_settings",
- "subtitle" : "OS Settings",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_pci_passthrough" : {
- "link" : "/pve-docs/chapter-qm.html#qm_pci_passthrough",
- "title" : "PCI(e) Passthrough"
- },
- "qm_startup_and_shutdown" : {
- "link" : "/pve-docs/chapter-qm.html#qm_startup_and_shutdown",
- "subtitle" : "Automatic Start and Shutdown of Virtual Machines",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_system_settings" : {
- "link" : "/pve-docs/chapter-qm.html#qm_system_settings",
- "subtitle" : "System Settings",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_usb_passthrough" : {
- "link" : "/pve-docs/chapter-qm.html#qm_usb_passthrough",
- "subtitle" : "USB Passthrough",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_virtual_machines_settings" : {
- "link" : "/pve-docs/chapter-qm.html#qm_virtual_machines_settings",
- "subtitle" : "Virtual Machines Settings",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "storage_cephfs" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_cephfs",
- "title" : "Ceph Filesystem (CephFS)"
- },
- "storage_cifs" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_cifs",
- "title" : "CIFS Backend"
- },
- "storage_directory" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_directory",
- "title" : "Directory Backend"
- },
- "storage_glusterfs" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_glusterfs",
- "title" : "GlusterFS Backend"
- },
- "storage_lvm" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_lvm",
- "title" : "LVM Backend"
- },
- "storage_lvmthin" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_lvmthin",
- "title" : "LVM thin Backend"
- },
- "storage_nfs" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_nfs",
- "title" : "NFS Backend"
- },
- "storage_open_iscsi" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_open_iscsi",
- "title" : "Open-iSCSI initiator"
- },
- "storage_zfspool" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_zfspool",
- "title" : "Local ZFS Pool Backend"
- },
- "sysadmin_certificate_management" : {
- "link" : "/pve-docs/chapter-sysadmin.html#sysadmin_certificate_management",
- "title" : "Certificate Management"
- },
- "sysadmin_network_configuration" : {
- "link" : "/pve-docs/chapter-sysadmin.html#sysadmin_network_configuration",
- "title" : "Network Configuration"
- }
-};
-Ext.ns('PVE');
-
-// 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 = {
- log: function() {}
- };
-}
-console.log("Starting PVE Manager");
-
-Ext.Ajax.defaultHeaders = {
- 'Accept': 'application/json'
-};
-
-/*jslint confusion: true */
-Ext.define('PVE.Utils', { utilities: {
-
- // this singleton contains miscellaneous utilities
-
- toolkit: undefined, // (extjs|touch), set inside Toolkit.js
-
- bus_match: /^(ide|sata|virtio|scsi)\d+$/,
-
- log_severity_hash: {
- 0: "panic",
- 1: "alert",
- 2: "critical",
- 3: "error",
- 4: "warning",
- 5: "notice",
- 6: "info",
- 7: "debug"
- },
-
- support_level_hash: {
- 'c': gettext('Community'),
- 'b': gettext('Basic'),
- 's': gettext('Standard'),
- 'p': gettext('Premium')
- },
-
- noSubKeyHtml: 'You do not have a valid subscription for this server. Please visit www.proxmox.com to get a list of available options.',
-
- kvm_ostypes: {
- 'Linux': [
- { desc: '4.X/3.X/2.6 Kernel', val: 'l26' },
- { desc: '2.4 Kernel', val: 'l24' }
- ],
- 'Microsoft Windows': [
- { desc: '10/2016', val: 'win10' },
- { desc: '8.x/2012/2012r2', val: 'win8' },
- { desc: '7/2008r2', val: 'win7' },
- { desc: 'Vista/2008', val: 'w2k8' },
- { desc: 'XP/2003', val: 'wxp' },
- { desc: '2000', val: 'w2k' }
- ],
- 'Solaris Kernel': [
- { desc: '-', val: 'solaris'}
- ],
- 'Other': [
- { desc: '-', val: 'other'}
- ]
- },
-
- get_health_icon: function(state, circle) {
- if (circle === undefined) {
- circle = false;
- }
-
- if (state === undefined) {
- state = 'uknown';
- }
-
- var icon = 'faded fa-question';
- switch(state) {
- case 'good':
- icon = 'good fa-check';
- break;
- case 'warning':
- icon = 'warning fa-exclamation';
- break;
- case 'critical':
- icon = 'critical fa-times';
- break;
- default: break;
- }
-
- if (circle) {
- icon += '-circle';
- }
-
- return icon;
- },
-
- map_ceph_health: {
- 'HEALTH_OK':'good',
- 'HEALTH_WARN':'warning',
- 'HEALTH_ERR':'critical'
- },
-
- render_ceph_health: function(healthObj) {
- var state = {
- iconCls: PVE.Utils.get_health_icon(),
- text: ''
- };
-
- if (!healthObj || !healthObj.status) {
- return state;
- }
-
- var health = PVE.Utils.map_ceph_health[healthObj.status];
-
- state.iconCls = PVE.Utils.get_health_icon(health, true);
- state.text = healthObj.status;
-
- return state;
- },
-
- render_zfs_health: function(value) {
- if (typeof value == 'undefined'){
- return "";
- }
- var iconCls = 'question-circle';
- switch (value) {
- case 'AVAIL':
- case 'ONLINE':
- iconCls = 'check-circle good';
- break;
- case 'REMOVED':
- case 'DEGRADED':
- iconCls = 'exclamation-circle warning';
- break;
- case 'UNAVAIL':
- case 'FAULTED':
- case 'OFFLINE':
- iconCls = 'times-circle critical';
- break;
- default: //unknown
- }
-
- return ' ' + value;
-
- },
-
- get_kvm_osinfo: function(value) {
- var info = { base: 'Other' }; // default
- if (value) {
- Ext.each(Object.keys(PVE.Utils.kvm_ostypes), function(k) {
- Ext.each(PVE.Utils.kvm_ostypes[k], function(e) {
- if (e.val === value) {
- info = { desc: e.desc, base: k };
- }
- });
- });
- }
- return info;
- },
-
- render_kvm_ostype: function (value) {
- var osinfo = PVE.Utils.get_kvm_osinfo(value);
- if (osinfo.desc && osinfo.desc !== '-') {
- return osinfo.base + ' ' + osinfo.desc;
- } else {
- return osinfo.base;
- }
- },
-
- render_hotplug_features: function (value) {
- var fa = [];
-
- if (!value || (value === '0')) {
- return gettext('Disabled');
- }
-
- if (value === '1') {
- value = 'disk,network,usb';
- }
-
- Ext.each(value.split(','), function(el) {
- if (el === 'disk') {
- fa.push(gettext('Disk'));
- } else if (el === 'network') {
- fa.push(gettext('Network'));
- } else if (el === 'usb') {
- fa.push('USB');
- } else if (el === 'memory') {
- fa.push(gettext('Memory'));
- } else if (el === 'cpu') {
- fa.push(gettext('CPU'));
- } else {
- fa.push(el);
- }
- });
-
- return fa.join(', ');
- },
-
- render_qga_features: function(value) {
- if (!value) {
- return Proxmox.Utils.defaultText + ' (' + Proxmox.Utils.disabledText + ')';
- }
- var props = PVE.Parser.parsePropertyString(value, 'enabled');
- if (!PVE.Parser.parseBoolean(props.enabled)) {
- return Proxmox.Utils.disabledText;
- }
-
- delete props.enabled;
- var agentstring = Proxmox.Utils.enabledText;
-
- Ext.Object.each(props, function(key, value) {
- var keystring = '' ;
- agentstring += ', ' + key + ': ';
-
- if (PVE.Parser.parseBoolean(value)) {
- agentstring += Proxmox.Utils.enabledText;
- } else {
- agentstring += Proxmox.Utils.disabledText;
- }
- });
-
- return agentstring;
- },
-
- render_qemu_machine: function(value) {
- return value || (Proxmox.Utils.defaultText + ' (i440fx)');
- },
-
- render_qemu_bios: function(value) {
- if (!value) {
- return Proxmox.Utils.defaultText + ' (SeaBIOS)';
- } else if (value === 'seabios') {
- return "SeaBIOS";
- } else if (value === 'ovmf') {
- return "OVMF (UEFI)";
- } else {
- return value;
- }
- },
-
- render_dc_ha_opts: function(value) {
- if (!value) {
- return Proxmox.Utils.defaultText;
- } else {
- return PVE.Parser.printPropertyString(value);
- }
- },
- render_as_property_string: function(value) {
- return (!value) ? Proxmox.Utils.defaultText
- : PVE.Parser.printPropertyString(value);
- },
-
- render_scsihw: function(value) {
- if (!value) {
- return Proxmox.Utils.defaultText + ' (LSI 53C895A)';
- } else if (value === 'lsi') {
- return 'LSI 53C895A';
- } else if (value === 'lsi53c810') {
- return 'LSI 53C810';
- } else if (value === 'megasas') {
- return 'MegaRAID SAS 8708EM2';
- } else if (value === 'virtio-scsi-pci') {
- return 'VirtIO SCSI';
- } else if (value === 'virtio-scsi-single') {
- return 'VirtIO SCSI single';
- } else if (value === 'pvscsi') {
- return 'VMware PVSCSI';
- } else {
- return value;
- }
- },
-
- // fixme: auto-generate this
- // for now, please keep in sync with PVE::Tools::kvmkeymaps
- kvm_keymaps: {
- //ar: 'Arabic',
- da: 'Danish',
- de: 'German',
- 'de-ch': 'German (Swiss)',
- 'en-gb': 'English (UK)',
- 'en-us': 'English (USA)',
- es: 'Spanish',
- //et: 'Estonia',
- fi: 'Finnish',
- //fo: 'Faroe Islands',
- fr: 'French',
- 'fr-be': 'French (Belgium)',
- 'fr-ca': 'French (Canada)',
- 'fr-ch': 'French (Swiss)',
- //hr: 'Croatia',
- hu: 'Hungarian',
- is: 'Icelandic',
- it: 'Italian',
- ja: 'Japanese',
- lt: 'Lithuanian',
- //lv: 'Latvian',
- mk: 'Macedonian',
- nl: 'Dutch',
- //'nl-be': 'Dutch (Belgium)',
- no: 'Norwegian',
- pl: 'Polish',
- pt: 'Portuguese',
- 'pt-br': 'Portuguese (Brazil)',
- //ru: 'Russian',
- sl: 'Slovenian',
- sv: 'Swedish',
- //th: 'Thai',
- tr: 'Turkish'
- },
-
- kvm_vga_drivers: {
- std: gettext('Standard VGA'),
- vmware: gettext('VMware compatible'),
- qxl: 'SPICE',
- qxl2: 'SPICE dual monitor',
- qxl3: 'SPICE three monitors',
- qxl4: 'SPICE four monitors',
- serial0: gettext('Serial terminal') + ' 0',
- serial1: gettext('Serial terminal') + ' 1',
- serial2: gettext('Serial terminal') + ' 2',
- serial3: gettext('Serial terminal') + ' 3',
- virtio: 'VirtIO-GPU',
- none: Proxmox.Utils.noneText
- },
-
- render_kvm_language: function (value) {
- if (!value || value === '__default__') {
- return Proxmox.Utils.defaultText;
- }
- var text = PVE.Utils.kvm_keymaps[value];
- if (text) {
- return text + ' (' + value + ')';
- }
- return value;
- },
-
- kvm_keymap_array: function() {
- var data = [['__default__', PVE.Utils.render_kvm_language('')]];
- Ext.Object.each(PVE.Utils.kvm_keymaps, function(key, value) {
- data.push([key, PVE.Utils.render_kvm_language(value)]);
- });
-
- return data;
- },
-
- console_map: {
- '__default__': Proxmox.Utils.defaultText + ' (HTML5)',
- 'vv': 'SPICE (remote-viewer)',
- 'html5': 'HTML5 (noVNC)',
- 'xtermjs': 'xterm.js'
- },
-
- render_console_viewer: function(value) {
- value = value || '__default__';
- if (PVE.Utils.console_map[value]) {
- return PVE.Utils.console_map[value];
- }
- return value;
- },
-
- console_viewer_array: function() {
- return Ext.Array.map(Object.keys(PVE.Utils.console_map), function(v) {
- return [v, PVE.Utils.render_console_viewer(v)];
- });
- },
-
- render_kvm_vga_driver: function (value) {
- if (!value) {
- return Proxmox.Utils.defaultText;
- }
- var vga = PVE.Parser.parsePropertyString(value, 'type');
- var text = PVE.Utils.kvm_vga_drivers[vga.type];
- if (!vga.type) {
- text = Proxmox.Utils.defaultText;
- }
- if (text) {
- return text + ' (' + value + ')';
- }
- return value;
- },
-
- kvm_vga_driver_array: function() {
- var data = [['__default__', PVE.Utils.render_kvm_vga_driver('')]];
- Ext.Object.each(PVE.Utils.kvm_vga_drivers, function(key, value) {
- data.push([key, PVE.Utils.render_kvm_vga_driver(value)]);
- });
-
- return data;
- },
-
- render_kvm_startup: function(value) {
- var startup = PVE.Parser.parseStartup(value);
-
- var res = 'order=';
- if (startup.order === undefined) {
- res += 'any';
- } else {
- res += startup.order;
- }
- if (startup.up !== undefined) {
- res += ',up=' + startup.up;
- }
- if (startup.down !== undefined) {
- res += ',down=' + startup.down;
- }
-
- return res;
- },
-
- extractFormActionError: function(action) {
- var msg;
- switch (action.failureType) {
- case Ext.form.action.Action.CLIENT_INVALID:
- msg = gettext('Form fields may not be submitted with invalid values');
- break;
- case Ext.form.action.Action.CONNECT_FAILURE:
- msg = gettext('Connection error');
- var resp = action.response;
- if (resp.status && resp.statusText) {
- msg += " " + resp.status + ": " + resp.statusText;
- }
- break;
- case Ext.form.action.Action.LOAD_FAILURE:
- case Ext.form.action.Action.SERVER_INVALID:
- msg = Proxmox.Utils.extractRequestError(action.result, true);
- break;
- }
- return msg;
- },
-
- format_duration_short: function(ut) {
-
- if (ut < 60) {
- return ut.toFixed(1) + 's';
- }
-
- if (ut < 3600) {
- var mins = ut / 60;
- return mins.toFixed(1) + 'm';
- }
-
- if (ut < 86400) {
- var hours = ut / 3600;
- return hours.toFixed(1) + 'h';
- }
-
- var days = ut / 86400;
- return days.toFixed(1) + 'd';
- },
-
- contentTypes: {
- 'images': gettext('Disk image'),
- 'backup': gettext('VZDump backup file'),
- 'vztmpl': gettext('Container template'),
- 'iso': gettext('ISO image'),
- 'rootdir': gettext('Container'),
- 'snippets': gettext('Snippets')
- },
-
- storageSchema: {
- dir: {
- name: Proxmox.Utils.directoryText,
- ipanel: 'DirInputPanel',
- faIcon: 'folder'
- },
- lvm: {
- name: 'LVM',
- ipanel: 'LVMInputPanel',
- faIcon: 'folder'
- },
- lvmthin: {
- name: 'LVM-Thin',
- ipanel: 'LvmThinInputPanel',
- faIcon: 'folder'
- },
- nfs: {
- name: 'NFS',
- ipanel: 'NFSInputPanel',
- faIcon: 'building'
- },
- cifs: {
- name: 'CIFS',
- ipanel: 'CIFSInputPanel',
- faIcon: 'building'
- },
- glusterfs: {
- name: 'GlusterFS',
- ipanel: 'GlusterFsInputPanel',
- faIcon: 'building'
- },
- iscsi: {
- name: 'iSCSI',
- ipanel: 'IScsiInputPanel',
- faIcon: 'building'
- },
- sheepdog: {
- name: 'Sheepdog',
- ipanel: 'SheepdogInputPanel',
- hideAdd: true,
- faIcon: 'building'
- },
- cephfs: {
- name: 'CephFS',
- ipanel: 'CephFSInputPanel',
- faIcon: 'building'
- },
- pvecephfs: {
- name: 'CephFS (PVE)',
- ipanel: 'CephFSInputPanel',
- hideAdd: true,
- faIcon: 'building'
- },
- rbd: {
- name: 'RBD',
- ipanel: 'RBDInputPanel',
- faIcon: 'building'
- },
- pveceph: {
- name: 'RBD (PVE)',
- ipanel: 'RBDInputPanel',
- hideAdd: true,
- faIcon: 'building'
- },
- zfs: {
- name: 'ZFS over iSCSI',
- ipanel: 'ZFSInputPanel',
- faIcon: 'building'
- },
- zfspool: {
- name: 'ZFS',
- ipanel: 'ZFSPoolInputPanel',
- faIcon: 'folder'
- },
- drbd: {
- name: 'DRBD',
- hideAdd: true
- }
- },
-
- format_storage_type: function(value, md, record) {
- if (value === 'rbd') {
- value = (!record || record.get('monhost') ? 'rbd' : 'pveceph');
- } else if (value === 'cephfs') {
- value = (!record || record.get('monhost') ? 'cephfs' : 'pvecephfs');
- }
-
- var schema = PVE.Utils.storageSchema[value];
- if (schema) {
- return schema.name;
- }
- return Proxmox.Utils.unknownText;
- },
-
- format_ha: function(value) {
- var text = Proxmox.Utils.noneText;
-
- if (value.managed) {
- text = value.state || Proxmox.Utils.noneText;
-
- text += ', ' + Proxmox.Utils.groupText + ': ';
- text += value.group || Proxmox.Utils.noneText;
- }
-
- return text;
- },
-
- format_content_types: function(value) {
- return value.split(',').sort().map(function(ct) {
- return PVE.Utils.contentTypes[ct] || ct;
- }).join(', ');
- },
-
- render_storage_content: function(value, metaData, record) {
- var data = record.data;
- if (Ext.isNumber(data.channel) &&
- Ext.isNumber(data.id) &&
- Ext.isNumber(data.lun)) {
- return "CH " +
- Ext.String.leftPad(data.channel,2, '0') +
- " ID " + data.id + " LUN " + data.lun;
- }
- return data.volid.replace(/^.*:(.*\/)?/,'');
- },
-
- render_serverity: function (value) {
- return PVE.Utils.log_severity_hash[value] || value;
- },
-
- render_cpu: function(value, metaData, record, rowIndex, colIndex, store) {
-
- if (!(record.data.uptime && Ext.isNumeric(value))) {
- return '';
- }
-
- var maxcpu = record.data.maxcpu || 1;
-
- if (!Ext.isNumeric(maxcpu) && (maxcpu >= 1)) {
- return '';
- }
-
- var per = value * 100;
-
- return per.toFixed(1) + '% of ' + maxcpu.toString() + (maxcpu > 1 ? 'CPUs' : 'CPU');
- },
-
- render_size: function(value, metaData, record, rowIndex, colIndex, store) {
- /*jslint confusion: true */
-
- if (!Ext.isNumeric(value)) {
- return '';
- }
-
- return Proxmox.Utils.format_size(value);
- },
-
- render_bandwidth: function(value) {
- if (!Ext.isNumeric(value)) {
- return '';
- }
-
- return Proxmox.Utils.format_size(value) + '/s';
- },
-
- render_timestamp_human_readable: function(value) {
- return Ext.Date.format(new Date(value * 1000), 'l d F Y H:i:s');
- },
-
- render_duration: function(value) {
- if (value === undefined) {
- return '-';
- }
- return PVE.Utils.format_duration_short(value);
- },
-
- calculate_mem_usage: function(data) {
- if (!Ext.isNumeric(data.mem) ||
- data.maxmem === 0 ||
- data.uptime < 1) {
- return -1;
- }
-
- return (data.mem / data.maxmem);
- },
-
- render_mem_usage_percent: function(value, metaData, record, rowIndex, colIndex, store) {
- if (!Ext.isNumeric(value) || value === -1) {
- return '';
- }
- if (value > 1 ) {
- // we got no percentage but bytes
- var mem = value;
- var maxmem = record.data.maxmem;
- if (!record.data.uptime ||
- maxmem === 0 ||
- !Ext.isNumeric(mem)) {
- return '';
- }
-
- return ((mem*100)/maxmem).toFixed(1) + " %";
- }
- return (value*100).toFixed(1) + " %";
- },
-
- render_mem_usage: function(value, metaData, record, rowIndex, colIndex, store) {
-
- var mem = value;
- var maxmem = record.data.maxmem;
-
- if (!record.data.uptime) {
- return '';
- }
-
- if (!(Ext.isNumeric(mem) && maxmem)) {
- return '';
- }
-
- return PVE.Utils.render_size(value);
- },
-
- calculate_disk_usage: function(data) {
-
- if (!Ext.isNumeric(data.disk) ||
- data.type === 'qemu' ||
- (data.type === 'lxc' && data.uptime === 0) ||
- data.maxdisk === 0) {
- return -1;
- }
-
- return (data.disk / data.maxdisk);
- },
-
- render_disk_usage_percent: function(value, metaData, record, rowIndex, colIndex, store) {
- if (!Ext.isNumeric(value) || value === -1) {
- return '';
- }
-
- return (value * 100).toFixed(1) + " %";
- },
-
- render_disk_usage: function(value, metaData, record, rowIndex, colIndex, store) {
-
- var disk = value;
- var maxdisk = record.data.maxdisk;
- var type = record.data.type;
-
- if (!Ext.isNumeric(disk) ||
- type === 'qemu' ||
- maxdisk === 0 ||
- (type === 'lxc' && record.data.uptime === 0)) {
- return '';
- }
-
- return PVE.Utils.render_size(value);
- },
-
- get_object_icon_class: function(type, record) {
- var status = '';
- var objType = type;
-
- if (type === 'type') {
- // for folder view
- objType = record.groupbyid;
- } else if (record.template) {
- // templates
- objType = 'template';
- status = type;
- } else {
- // everything else
- status = record.status + ' ha-' + record.hastate;
- }
-
- var defaults = PVE.tree.ResourceTree.typeDefaults[objType];
- if (defaults && defaults.iconCls) {
- var retVal = defaults.iconCls + ' ' + status;
- return retVal;
- }
-
- return '';
- },
-
- render_resource_type: function(value, metaData, record, rowIndex, colIndex, store) {
-
- var cls = PVE.Utils.get_object_icon_class(value,record.data);
-
- var fa = ' ';
- return fa + value;
- },
-
- render_support_level: function(value, metaData, record) {
- return PVE.Utils.support_level_hash[value] || '-';
- },
-
- render_upid: function(value, metaData, record) {
- var type = record.data.type;
- var id = record.data.id;
-
- return Proxmox.Utils.format_task_description(type, id);
- },
-
- /* render functions for new status panel */
-
- render_usage: function(val) {
- return (val*100).toFixed(2) + '%';
- },
-
- render_cpu_usage: function(val, max) {
- return Ext.String.format(gettext('{0}% of {1}') +
- ' ' + gettext('CPU(s)'), (val*100).toFixed(2), max);
- },
-
- render_size_usage: function(val, max) {
- if (max === 0) {
- return gettext('N/A');
- }
- return (val*100/max).toFixed(2) + '% '+ '(' +
- Ext.String.format(gettext('{0} of {1}'),
- PVE.Utils.render_size(val), PVE.Utils.render_size(max)) + ')';
- },
-
- /* this is different for nodes */
- render_node_cpu_usage: function(value, record) {
- return PVE.Utils.render_cpu_usage(value, record.cpus);
- },
-
- /* this is different for nodes */
- render_node_size_usage: function(record) {
- return PVE.Utils.render_size_usage(record.used, record.total);
- },
-
- render_optional_url: function(value) {
- var match;
- if (value && (match = value.match(/^https?:\/\//)) !== null) {
- return '' + value + ' ';
- }
- return value;
- },
-
- render_san: function(value) {
- var names = [];
- if (Ext.isArray(value)) {
- value.forEach(function(val) {
- if (!Ext.isNumber(val)) {
- names.push(val);
- }
- });
- return names.join(' ');
- }
- return value;
- },
-
- render_full_name: function(firstname, metaData, record) {
- var first = firstname || '';
- var last = record.data.lastname || '';
- return Ext.htmlEncode(first + " " + last);
- },
-
- render_u2f_error: function(error) {
- var ErrorNames = {
- '1': gettext('Other Error'),
- '2': gettext('Bad Request'),
- '3': gettext('Configuration Unsupported'),
- '4': gettext('Device Ineligible'),
- '5': gettext('Timeout')
- };
- return "U2F Error: " + ErrorNames[error] || Proxmox.Utils.unknownText;
- },
-
- windowHostname: function() {
- return window.location.hostname.replace(Proxmox.Utils.IP6_bracket_match,
- function(m, addr, offset, original) { return addr; });
- },
-
- openDefaultConsoleWindow: function(consoles, vmtype, vmid, nodename, vmname, cmd) {
- var dv = PVE.Utils.defaultViewer(consoles);
- PVE.Utils.openConsoleWindow(dv, vmtype, vmid, nodename, vmname, cmd);
- },
-
- openConsoleWindow: function(viewer, vmtype, vmid, nodename, vmname, cmd) {
- // kvm, lxc, shell, upgrade
-
- if (vmid == undefined && (vmtype === 'kvm' || vmtype === 'lxc')) {
- throw "missing vmid";
- }
-
- if (!nodename) {
- throw "no nodename specified";
- }
-
- if (viewer === 'html5') {
- PVE.Utils.openVNCViewer(vmtype, vmid, nodename, vmname, cmd);
- } else if (viewer === 'xtermjs') {
- Proxmox.Utils.openXtermJsViewer(vmtype, vmid, nodename, vmname, cmd);
- } else if (viewer === 'vv') {
- var url;
- var params = { proxy: PVE.Utils.windowHostname() };
- if (vmtype === 'kvm') {
- url = '/nodes/' + nodename + '/qemu/' + vmid.toString() + '/spiceproxy';
- PVE.Utils.openSpiceViewer(url, params);
- } else if (vmtype === 'lxc') {
- url = '/nodes/' + nodename + '/lxc/' + vmid.toString() + '/spiceproxy';
- PVE.Utils.openSpiceViewer(url, params);
- } else if (vmtype === 'shell') {
- url = '/nodes/' + nodename + '/spiceshell';
- PVE.Utils.openSpiceViewer(url, params);
- } else if (vmtype === 'upgrade') {
- url = '/nodes/' + nodename + '/spiceshell';
- params.upgrade = 1;
- PVE.Utils.openSpiceViewer(url, params);
- } else if (vmtype === 'cmd') {
- url = '/nodes/' + nodename + '/spiceshell';
- params.cmd = cmd;
- PVE.Utils.openSpiceViewer(url, params);
- }
- } else {
- throw "unknown viewer type";
- }
- },
-
- defaultViewer: function(consoles) {
-
- var allowSpice, allowXtermjs;
-
- if (consoles === true) {
- allowSpice = true;
- allowXtermjs = true;
- } else if (typeof consoles === 'object') {
- allowSpice = consoles.spice;
- allowXtermjs = !!consoles.xtermjs;
- }
- var vncdefault = 'html5';
- var dv = PVE.VersionInfo.console || vncdefault;
- if ((dv === 'vv' && !allowSpice) || (dv === 'xtermjs' && !allowXtermjs)) {
- dv = vncdefault;
- }
-
- return dv;
- },
-
- openVNCViewer: function(vmtype, vmid, nodename, vmname, cmd) {
- var url = Ext.Object.toQueryString({
- console: vmtype, // kvm, lxc, upgrade or shell
- novnc: 1,
- vmid: vmid,
- vmname: vmname,
- node: nodename,
- resize: 'off',
- cmd: cmd
- });
- var nw = window.open("?" + url, '_blank', "innerWidth=745,innerheight=427");
- if (nw) {
- nw.focus();
- }
- },
-
- openSpiceViewer: function(url, params){
-
- var downloadWithName = function(uri, name) {
- var link = Ext.DomHelper.append(document.body, {
- tag: 'a',
- href: uri,
- css : 'display:none;visibility:hidden;height:0px;'
- });
-
- // Note: we need to tell android the correct file name extension
- // but we do not set 'download' tag for other environments, because
- // It can have strange side effects (additional user prompt on firefox)
- var andriod = navigator.userAgent.match(/Android/i) ? true : false;
- if (andriod) {
- link.download = name;
- }
-
- if (link.fireEvent) {
- link.fireEvent('onclick');
- } else {
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
- link.dispatchEvent(evt);
- }
- };
-
- Proxmox.Utils.API2Request({
- url: url,
- params: params,
- method: 'POST',
- failure: function(response, opts){
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, opts){
- var raw = "[virt-viewer]\n";
- Ext.Object.each(response.result.data, function(k, v) {
- raw += k + "=" + v + "\n";
- });
- var url = 'data:application/x-virt-viewer;charset=UTF-8,' +
- encodeURIComponent(raw);
-
- downloadWithName(url, "pve-spice.vv");
- }
- });
- },
-
- openTreeConsole: function(tree, record, item, index, e) {
- e.stopEvent();
- var nodename = record.data.node;
- var vmid = record.data.vmid;
- var vmname = record.data.name;
- if (record.data.type === 'qemu' && !record.data.template) {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/qemu/' + vmid + '/status/current',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, opts) {
- var allowSpice = !!response.result.data.spice;
- PVE.Utils.openDefaultConsoleWindow(allowSpice, 'kvm', vmid, nodename, vmname);
- }
- });
- } else if (record.data.type === 'lxc' && !record.data.template) {
- PVE.Utils.openDefaultConsoleWindow(true, 'lxc', vmid, nodename, vmname);
- }
- },
-
- // test automation helper
- call_menu_handler: function(menu, text) {
-
- var list = menu.query('menuitem');
-
- Ext.Array.each(list, function(item) {
- if (item.text === text) {
- if (item.handler) {
- item.handler();
- return 1;
- } else {
- return undefined;
- }
- }
- });
- },
-
- createCmdMenu: function(v, record, item, index, event) {
- event.stopEvent();
- if (!(v instanceof Ext.tree.View)) {
- v.select(record);
- }
- var menu;
- var template = !!record.data.template;
- var type = record.data.type;
-
- if (template) {
- if (type === 'qemu' || type == 'lxc') {
- menu = Ext.create('PVE.menu.TemplateMenu', {
- pveSelNode: record
- });
- }
- } else if (type === 'qemu' ||
- type === 'lxc' ||
- type === 'node') {
- menu = Ext.create('PVE.' + type + '.CmdMenu', {
- pveSelNode: record,
- nodename: record.data.node
- });
- } else {
- return;
- }
-
- menu.showAt(event.getXY());
- return menu;
- },
-
- // helper for deleting field which are set to there default values
- delete_if_default: function(values, fieldname, default_val, create) {
- if (values[fieldname] === '' || values[fieldname] === default_val) {
- if (!create) {
- if (values['delete']) {
- values['delete'] += ',' + fieldname;
- } else {
- values['delete'] = fieldname;
- }
- }
-
- delete values[fieldname];
- }
- },
-
- loadSSHKeyFromFile: function(file, callback) {
- // ssh-keygen produces 740 bytes for an average 4096 bit rsa key, with
- // a user@host comment, 1420 for 8192 bits; current max is 16kbit
- // assume: 740*8 for max. 32kbit (5920 byte file)
- // round upwards to nearest nice number => 8192 bytes, leaves lots of comment space
- if (file.size > 8192) {
- Ext.Msg.alert(gettext('Error'), gettext("Invalid file size: ") + file.size);
- return;
- }
- /*global
- FileReader
- */
- var reader = new FileReader();
- reader.onload = function(evt) {
- callback(evt.target.result);
- };
- reader.readAsText(file);
- },
-
- bus_counts: { ide: 4, sata: 6, scsi: 16, virtio: 16 },
-
- // types is either undefined (all busses), an array of busses, or a single bus
- forEachBus: function(types, func) {
- var busses = Object.keys(PVE.Utils.bus_counts);
- var i, j, count, cont;
-
- if (Ext.isArray(types)) {
- busses = types;
- } else if (Ext.isDefined(types)) {
- busses = [ types ];
- }
-
- // check if we only have valid busses
- for (i = 0; i < busses.length; i++) {
- if (!PVE.Utils.bus_counts[busses[i]]) {
- throw "invalid bus: '" + busses[i] + "'";
- }
- }
-
- for (i = 0; i < busses.length; i++) {
- count = PVE.Utils.bus_counts[busses[i]];
- for (j = 0; j < count; j++) {
- cont = func(busses[i], j);
- if (!cont && cont !== undefined) {
- return;
- }
- }
- }
- },
-
- mp_counts: { mps: 256, unused: 256 },
-
- forEachMP: function(func, includeUnused) {
- var i, cont;
- for (i = 0; i < PVE.Utils.mp_counts.mps; i++) {
- cont = func('mp', i);
- if (!cont && cont !== undefined) {
- return;
- }
- }
-
- if (!includeUnused) {
- return;
- }
-
- for (i = 0; i < PVE.Utils.mp_counts.unused; i++) {
- cont = func('unused', i);
- if (!cont && cont !== undefined) {
- return;
- }
- }
- },
-
- cleanEmptyObjectKeys: function (obj) {
- var propName;
- for (propName in obj) {
- if (obj.hasOwnProperty(propName)) {
- if (obj[propName] === null || obj[propName] === undefined) {
- delete obj[propName];
- }
- }
- }
- },
-
- handleStoreErrorOrMask: function(me, store, regex, callback) {
-
- me.mon(store, 'load', function (proxy, response, success, operation) {
-
- if (success) {
- Proxmox.Utils.setErrorMask(me, false);
- return;
- }
- var msg;
-
- if (operation.error.statusText) {
- if (operation.error.statusText.match(regex)) {
- callback(me, operation.error);
- return;
- } else {
- msg = operation.error.statusText + ' (' + operation.error.status + ')';
- }
- } else {
- msg = gettext('Connection error');
- }
- Proxmox.Utils.setErrorMask(me, msg);
- });
- },
-
- showCephInstallOrMask: function(container, msg, nodename, callback){
- var regex = new RegExp("not (installed|initialized)", "i");
- if (msg.match(regex)) {
- if (Proxmox.UserName === 'root@pam') {
- container.el.mask();
- if (!container.down('pveCephInstallWindow')){
- var isInstalled = msg.match(/not initialized/i) ? true : false;
- var win = Ext.create('PVE.ceph.Install', {
- nodename: nodename
- });
- win.getViewModel().set('isInstalled', isInstalled);
- container.add(win);
- win.show();
- callback(win);
- }
- } else {
- container.mask(Ext.String.format(gettext('{0} not installed.') +
- ' ' + gettext('Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
- }
- return true;
- } else {
- return false;
- }
- }
-},
-
- singleton: true,
- constructor: function() {
- var me = this;
- Ext.apply(me, me.utilities);
- }
-
-});
-
-// ExtJS related things
-
-Proxmox.Utils.toolkit = 'extjs';
-
-// custom PVE specific VTypes
-Ext.apply(Ext.form.field.VTypes, {
-
- QemuStartDate: function(v) {
- return (/^(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)$/).test(v);
- },
- QemuStartDateText: gettext('Format') + ': "now" or "2006-06-17T16:01:21" or "2006-06-17"',
- IP64AddressList: function(v) {
- var list = v.split(/[\ \,\;]+/);
- var i;
- for (i = 0; i < list.length; i++) {
- if (list[i] == '') {
- continue;
- }
-
- if (!Proxmox.Utils.IP64_match.test(list[i])) {
- return false;
- }
- }
-
- return true;
- },
- IP64AddressListText: gettext('Example') + ': 192.168.1.1,192.168.1.2',
- IP64AddressListMask: /[A-Fa-f0-9\,\:\.\;\ ]/
-});
-
-Ext.define('PVE.form.field.Display', {
- override: 'Ext.form.field.Display',
-
- setSubmitValue: function(value) {
- // do nothing, this is only to allow generalized bindings for the:
- // `me.isCreate ? 'textfield' : 'displayfield'` cases we have.
- }
-});
-// Some configuration values are complex strings -
-// so we need parsers/generators for them.
-
-Ext.define('PVE.Parser', { statics: {
-
- // this class only contains static functions
-
- parseACME: function(value) {
- if (!value) {
- return;
- }
-
- var res = {};
- var errors = false;
-
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; //continue
- }
-
- var match_res;
- if ((match_res = p.match(/^(?:domains=)?((?:[a-zA-Z0-9\-\.]+[;, ]?)+)$/)) !== null) {
- res.domains = match_res[1].split(/[;, ]/);
- } else {
- errors = true;
- return false;
- }
- });
-
- if (errors || !res) {
- return;
- }
-
- return res;
- },
-
- parseBoolean: function(value, default_value) {
- if (!Ext.isDefined(value)) {
- return default_value;
- }
- value = value.toLowerCase();
- return value === '1' ||
- value === 'on' ||
- value === 'yes' ||
- value === 'true';
- },
-
- parsePropertyString: function(value, defaultKey) {
- var res = {},
- error;
-
- Ext.Array.each(value.split(','), function(p) {
- var kv = p.split('=', 2);
- if (Ext.isDefined(kv[1])) {
- res[kv[0]] = kv[1];
- } else if (Ext.isDefined(defaultKey)) {
- if (Ext.isDefined(res[defaultKey])) {
- error = 'defaultKey may be only defined once in propertyString';
- return false; // break
- }
- res[defaultKey] = kv[0];
- } else {
- error = 'invalid propertyString, not a key=value pair and no defaultKey defined';
- return false; // break
- }
- });
-
- if (error !== undefined) {
- console.error(error);
- return;
- }
-
- return res;
- },
-
- printPropertyString: function(data, defaultKey) {
- var stringparts = [];
-
- Ext.Object.each(data, function(key, value) {
- if (defaultKey !== undefined && key === defaultKey) {
- stringparts.unshift(value);
- } else {
- stringparts.push(key + '=' + value);
- }
- });
-
- return stringparts.join(',');
- },
-
- parseQemuNetwork: function(key, value) {
- if (!(key && value)) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
-
- var match_res;
-
- if ((match_res = p.match(/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|vmxnet3|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i)) !== null) {
- res.model = match_res[1].toLowerCase();
- if (match_res[3]) {
- res.macaddr = match_res[3];
- }
- } else if ((match_res = p.match(/^bridge=(\S+)$/)) !== null) {
- res.bridge = match_res[1];
- } else if ((match_res = p.match(/^rate=(\d+(\.\d+)?)$/)) !== null) {
- res.rate = match_res[1];
- } else if ((match_res = p.match(/^tag=(\d+(\.\d+)?)$/)) !== null) {
- res.tag = match_res[1];
- } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
- res.firewall = match_res[1];
- } else if ((match_res = p.match(/^link_down=(\d+)$/)) !== null) {
- res.disconnect = match_res[1];
- } else if ((match_res = p.match(/^queues=(\d+)$/)) !== null) {
- res.queues = match_res[1];
- } else if ((match_res = p.match(/^trunks=(\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*)$/)) !== null) {
- res.trunks = match_res[1];
- } else {
- errors = true;
- return false; // break
- }
- });
-
- if (errors || !res.model) {
- return;
- }
-
- return res;
- },
-
- printQemuNetwork: function(net) {
-
- var netstr = net.model;
- if (net.macaddr) {
- netstr += "=" + net.macaddr;
- }
- if (net.bridge) {
- netstr += ",bridge=" + net.bridge;
- if (net.tag) {
- netstr += ",tag=" + net.tag;
- }
- if (net.firewall) {
- netstr += ",firewall=" + net.firewall;
- }
- }
- if (net.rate) {
- netstr += ",rate=" + net.rate;
- }
- if (net.queues) {
- netstr += ",queues=" + net.queues;
- }
- if (net.disconnect) {
- netstr += ",link_down=" + net.disconnect;
- }
- if (net.trunks) {
- netstr += ",trunks=" + net.trunks;
- }
- return netstr;
- },
-
- parseQemuDrive: function(key, value) {
- if (!(key && value)) {
- return;
- }
-
- var res = {};
-
- var match_res = key.match(/^([a-z]+)(\d+)$/);
- if (!match_res) {
- return;
- }
- res['interface'] = match_res[1];
- res.index = match_res[2];
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
- var match_res = p.match(/^([a-z_]+)=(\S+)$/);
- if (!match_res) {
- if (!p.match(/\=/)) {
- res.file = p;
- return; // continue
- }
- errors = true;
- return false; // break
- }
- var k = match_res[1];
- if (k === 'volume') {
- k = 'file';
- }
-
- if (Ext.isDefined(res[k])) {
- errors = true;
- return false; // break
- }
-
- var v = match_res[2];
-
- if (k === 'cache' && v === 'off') {
- v = 'none';
- }
-
- res[k] = v;
- });
-
- if (errors || !res.file) {
- return;
- }
-
- return res;
- },
-
- printQemuDrive: function(drive) {
-
- var drivestr = drive.file;
-
- Ext.Object.each(drive, function(key, value) {
- if (!Ext.isDefined(value) || key === 'file' ||
- key === 'index' || key === 'interface') {
- return; // continue
- }
- drivestr += ',' + key + '=' + value;
- });
-
- return drivestr;
- },
-
- parseIPConfig: function(key, value) {
- if (!(key && value)) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
-
- var match_res;
- if ((match_res = p.match(/^ip=(\S+)$/)) !== null) {
- res.ip = match_res[1];
- } else if ((match_res = p.match(/^gw=(\S+)$/)) !== null) {
- res.gw = match_res[1];
- } else if ((match_res = p.match(/^ip6=(\S+)$/)) !== null) {
- res.ip6 = match_res[1];
- } else if ((match_res = p.match(/^gw6=(\S+)$/)) !== null) {
- res.gw6 = match_res[1];
- } else {
- errors = true;
- return false; // break
- }
- });
-
- if (errors) {
- return;
- }
-
- return res;
- },
-
- printIPConfig: function(cfg) {
- var c = "";
- var str = "";
- if (cfg.ip) {
- str += "ip=" + cfg.ip;
- c = ",";
- }
- if (cfg.gw) {
- str += c + "gw=" + cfg.gw;
- c = ",";
- }
- if (cfg.ip6) {
- str += c + "ip6=" + cfg.ip6;
- c = ",";
- }
- if (cfg.gw6) {
- str += c + "gw6=" + cfg.gw6;
- c = ",";
- }
- return str;
- },
-
- parseOpenVZNetIf: function(value) {
- if (!value) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(';'), function(item) {
- if (!item || item.match(/^\s*$/)) {
- return; // continue
- }
-
- var data = {};
- Ext.Array.each(item.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
- var match_res = p.match(/^(ifname|mac|bridge|host_ifname|host_mac|mac_filter)=(\S+)$/);
- if (!match_res) {
- errors = true;
- return false; // break
- }
- if (match_res[1] === 'bridge'){
- var bridgevlanf = match_res[2];
- var bridge_res = bridgevlanf.match(/^(vmbr(\d+))(v(\d+))?(f)?$/);
- if (!bridge_res) {
- errors = true;
- return false; // break
- }
- data.bridge = bridge_res[1];
- data.tag = bridge_res[4];
- /*jslint confusion: true*/
- data.firewall = bridge_res[5] ? 1 : 0;
- /*jslint confusion: false*/
- } else {
- data[match_res[1]] = match_res[2];
- }
- });
-
- if (errors || !data.ifname) {
- errors = true;
- return false; // break
- }
-
- data.raw = item;
-
- res[data.ifname] = data;
- });
-
- return errors ? undefined: res;
- },
-
- printOpenVZNetIf: function(netif) {
- var netarray = [];
-
- Ext.Object.each(netif, function(iface, data) {
- var tmparray = [];
- Ext.Array.each(['ifname', 'mac', 'bridge', 'host_ifname' , 'host_mac', 'mac_filter', 'tag', 'firewall'], function(key) {
- var value = data[key];
- if (key === 'bridge'){
- if(data.tag){
- value = value + 'v' + data.tag;
- }
- if (data.firewall){
- value = value + 'f';
- }
- }
- if (value) {
- tmparray.push(key + '=' + value);
- }
-
- });
- netarray.push(tmparray.join(','));
- });
-
- return netarray.join(';');
- },
-
- parseLxcNetwork: function(value) {
- if (!value) {
- return;
- }
-
- var data = {};
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
- var match_res = p.match(/^(bridge|hwaddr|mtu|name|ip|ip6|gw|gw6|tag|rate)=(\S+)$/);
- if (match_res) {
- data[match_res[1]] = match_res[2];
- } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
- data.firewall = PVE.Parser.parseBoolean(match_res[1]);
- } else {
- // todo: simply ignore errors ?
- return; // continue
- }
- });
-
- return data;
- },
-
- printLxcNetwork: function(data) {
- var tmparray = [];
- Ext.Array.each(['bridge', 'hwaddr', 'mtu', 'name', 'ip',
- 'gw', 'ip6', 'gw6', 'firewall', 'tag'], function(key) {
- var value = data[key];
- if (value) {
- tmparray.push(key + '=' + value);
- }
- });
-
- /*jslint confusion: true*/
- if (data.rate > 0) {
- tmparray.push('rate=' + data.rate);
- }
- /*jslint confusion: false*/
- return tmparray.join(',');
- },
-
- parseLxcMountPoint: function(value) {
- if (!value) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
- var match_res = p.match(/^([a-z_]+)=(.+)$/);
- if (!match_res) {
- if (!p.match(/\=/)) {
- res.file = p;
- return; // continue
- }
- errors = true;
- return false; // break
- }
- var k = match_res[1];
- if (k === 'volume') {
- k = 'file';
- }
-
- if (Ext.isDefined(res[k])) {
- errors = true;
- return false; // break
- }
-
- var v = match_res[2];
-
- res[k] = v;
- });
-
- if (errors || !res.file) {
- return;
- }
-
- var m = res.file.match(/^([a-z][a-z0-9\-\_\.]*[a-z0-9]):/i);
- if (m) {
- res.storage = m[1];
- res.type = 'volume';
- } else if (res.file.match(/^\/dev\//)) {
- res.type = 'device';
- } else {
- res.type = 'bind';
- }
-
- return res;
- },
-
- printLxcMountPoint: function(mp) {
- var drivestr = mp.file;
-
- Ext.Object.each(mp, function(key, value) {
- if (!Ext.isDefined(value) || key === 'file' ||
- key === 'type' || key === 'storage') {
- return; // continue
- }
- drivestr += ',' + key + '=' + value;
- });
-
- return drivestr;
- },
-
- parseStartup: function(value) {
- if (value === undefined) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
-
- var match_res;
-
- if ((match_res = p.match(/^(order)?=(\d+)$/)) !== null) {
- res.order = match_res[2];
- } else if ((match_res = p.match(/^up=(\d+)$/)) !== null) {
- res.up = match_res[1];
- } else if ((match_res = p.match(/^down=(\d+)$/)) !== null) {
- res.down = match_res[1];
- } else {
- errors = true;
- return false; // break
- }
- });
-
- if (errors) {
- return;
- }
-
- return res;
- },
-
- printStartup: function(startup) {
- var arr = [];
- if (startup.order !== undefined && startup.order !== '') {
- arr.push('order=' + startup.order);
- }
- if (startup.up !== undefined && startup.up !== '') {
- arr.push('up=' + startup.up);
- }
- if (startup.down !== undefined && startup.down !== '') {
- arr.push('down=' + startup.down);
- }
-
- return arr.join(',');
- },
-
- parseQemuSmbios1: function(value) {
- var res = {};
-
- Ext.Array.each(value.split(','), function(p) {
- var kva = p.split('=', 2);
- res[kva[0]] = kva[1];
- });
-
- return res;
- },
-
- printQemuSmbios1: function(data) {
-
- var datastr = '';
-
- Ext.Object.each(data, function(key, value) {
- if (value === '') { return; }
- datastr += (datastr !== '' ? ',' : '') + key + '=' + value;
- });
-
- return datastr;
- },
-
- parseTfaConfig: function(value) {
- var res = {};
-
- Ext.Array.each(value.split(','), function(p) {
- var kva = p.split('=', 2);
- res[kva[0]] = kva[1];
- });
-
- return res;
- },
-
- parseQemuCpu: function(value) {
- if (!value) {
- return {};
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
-
- if (!p.match(/\=/)) {
- if (Ext.isDefined(res.cpu)) {
- errors = true;
- return false; // break
- }
- res.cputype = p;
- return; // continue
- }
-
- var match_res = p.match(/^([a-z_]+)=(\S+)$/);
- if (!match_res) {
- errors = true;
- return false; // break
- }
-
- var k = match_res[1];
- if (Ext.isDefined(res[k])) {
- errors = true;
- return false; // break
- }
-
- res[k] = match_res[2];
- });
-
- if (errors || !res.cputype) {
- return;
- }
-
- return res;
- },
-
- printQemuCpu: function(cpu) {
- var cpustr = cpu.cputype;
- var optstr = '';
-
- Ext.Object.each(cpu, function(key, value) {
- if (!Ext.isDefined(value) || key === 'cputype') {
- return; // continue
- }
- optstr += ',' + key + '=' + value;
- });
-
- if (!cpustr) {
- if (optstr) {
- return 'kvm64' + optstr;
- }
- return;
- }
-
- return cpustr + optstr;
- },
-
- parseSSHKey: function(key) {
- // |--- options can have quotes--| type key comment
- var keyre = /^(?:((?:[^\s"]|\"(?:\\.|[^"\\])*")+)\s+)?(\S+)\s+(\S+)(?:\s+(.*))?$/;
- var typere = /^(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)$/;
-
- var m = key.match(keyre);
- if (!m) {
- return null;
- }
- if (m.length < 3 || !m[2]) { // [2] is always either type or key
- return null;
- }
- if (m[1] && m[1].match(typere)) {
- return {
- type: m[1],
- key: m[2],
- comment: m[3]
- };
- }
- if (m[2].match(typere)) {
- return {
- options: m[1],
- type: m[2],
- key: m[3],
- comment: m[4]
- };
- }
- return null;
- }
-}});
-/* This state provider keeps part of the state inside
- * the browser history.
- *
- * We compress (shorten) url using dictionary based compression
- * i.e. use column separated list instead of url encoded hash:
- * #v\d* version/format
- * := indicates string values
- * :\d+ lookup value in dictionary hash
- * #v1:=value1:5:=value2:=value3:...
-*/
-
-Ext.define('PVE.StateProvider', {
- extend: 'Ext.state.LocalStorageProvider',
-
- // private
- setHV: function(name, newvalue, fireEvents) {
- var me = this;
-
- var changes = false;
- var oldtext = Ext.encode(me.UIState[name]);
- var newtext = Ext.encode(newvalue);
- if (newtext != oldtext) {
- changes = true;
- me.UIState[name] = newvalue;
- //console.log("changed old " + name + " " + oldtext);
- //console.log("changed new " + name + " " + newtext);
- if (fireEvents) {
- me.fireEvent("statechange", me, name, { value: newvalue });
- }
- }
- return changes;
- },
-
- // private
- hslist: [
- // order is important for notifications
- // [ name, default ]
- ['view', 'server'],
- ['rid', 'root'],
- ['ltab', 'tasks'],
- ['nodetab', ''],
- ['storagetab', ''],
- ['pooltab', ''],
- ['kvmtab', ''],
- ['lxctab', ''],
- ['dctab', '']
- ],
-
- hprefix: 'v1',
-
- compDict: {
- cloudinit: 52,
- replication: 51,
- system: 50,
- monitor: 49,
- 'ha-fencing': 48,
- 'ha-groups': 47,
- 'ha-resources': 46,
- 'ceph-log': 45,
- 'ceph-crushmap':44,
- 'ceph-pools': 43,
- 'ceph-osdtree': 42,
- 'ceph-disklist': 41,
- 'ceph-monlist': 40,
- 'ceph-config': 39,
- ceph: 38,
- 'firewall-fwlog': 37,
- 'firewall-options': 36,
- 'firewall-ipset': 35,
- 'firewall-aliases': 34,
- 'firewall-sg': 33,
- firewall: 32,
- apt: 31,
- members: 30,
- snapshot: 29,
- ha: 28,
- support: 27,
- pools: 26,
- syslog: 25,
- ubc: 24,
- initlog: 23,
- openvz: 22,
- backup: 21,
- resources: 20,
- content: 19,
- root: 18,
- domains: 17,
- roles: 16,
- groups: 15,
- users: 14,
- time: 13,
- dns: 12,
- network: 11,
- services: 10,
- options: 9,
- console: 8,
- hardware: 7,
- permissions: 6,
- summary: 5,
- tasks: 4,
- clog: 3,
- storage: 2,
- folder: 1,
- server: 0
- },
-
- decodeHToken: function(token) {
- var me = this;
-
- var state = {};
- if (!token) {
- Ext.Array.each(me.hslist, function(rec) {
- state[rec[0]] = rec[1];
- });
- return state;
- }
-
- // return Ext.urlDecode(token);
-
- var items = token.split(':');
- var prefix = items.shift();
-
- if (prefix != me.hprefix) {
- return me.decodeHToken();
- }
-
- Ext.Array.each(me.hslist, function(rec) {
- var value = items.shift();
- if (value) {
- if (value[0] === '=') {
- value = decodeURIComponent(value.slice(1));
- } else {
- Ext.Object.each(me.compDict, function(key, cv) {
- if (value == cv) {
- value = key;
- return false;
- }
- });
- }
- }
- state[rec[0]] = value;
- });
-
- return state;
- },
-
- encodeHToken: function(state) {
- var me = this;
-
- // return Ext.urlEncode(state);
-
- var ctoken = me.hprefix;
- Ext.Array.each(me.hslist, function(rec) {
- var value = state[rec[0]];
- if (!Ext.isDefined(value)) {
- value = rec[1];
- }
- value = encodeURIComponent(value);
- if (!value) {
- ctoken += ':';
- } else {
- var comp = me.compDict[value];
- if (Ext.isDefined(comp)) {
- ctoken += ":" + comp;
- } else {
- ctoken += ":=" + value;
- }
- }
- });
-
- return ctoken;
- },
-
- constructor: function(config){
- var me = this;
-
- me.callParent([config]);
-
- me.UIState = me.decodeHToken(); // set default
-
- var history_change_cb = function(token) {
- //console.log("HC " + token);
- if (!token) {
- var res = window.confirm(gettext('Are you sure you want to navigate away from this page?'));
- if (res){
- // process text value and close...
- Ext.History.back();
- } else {
- Ext.History.forward();
- }
- return;
- }
-
- var newstate = me.decodeHToken(token);
- Ext.Array.each(me.hslist, function(rec) {
- if (typeof newstate[rec[0]] == "undefined") {
- return;
- }
- me.setHV(rec[0], newstate[rec[0]], true);
- });
- };
-
- var start_token = Ext.History.getToken();
- if (start_token) {
- history_change_cb(start_token);
- } else {
- var htext = me.encodeHToken(me.UIState);
- Ext.History.add(htext);
- }
-
- Ext.History.on('change', history_change_cb);
- },
-
- get: function(name, defaultValue){
- /*jslint confusion: true */
- var me = this;
- var data;
-
- if (typeof me.UIState[name] != "undefined") {
- data = { value: me.UIState[name] };
- } else {
- data = me.callParent(arguments);
- if (!data && name === 'GuiCap') {
- data = { vms: {}, storage: {}, access: {}, nodes: {}, dc: {} };
- }
- }
-
- //console.log("GET " + name + " " + Ext.encode(data));
- return data;
- },
-
- clear: function(name){
- var me = this;
-
- if (typeof me.UIState[name] != "undefined") {
- me.UIState[name] = null;
- }
-
- me.callParent(arguments);
- },
-
- set: function(name, value){
- var me = this;
-
- //console.log("SET " + name + " " + Ext.encode(value));
- if (typeof me.UIState[name] != "undefined") {
- var newvalue = value ? value.value : null;
- if (me.setHV(name, newvalue, false)) {
- var htext = me.encodeHToken(me.UIState);
- Ext.History.add(htext);
- }
- } else {
- me.callParent(arguments);
- }
- }
-});
-Ext.define('PVE.menu.Item', {
- extend: 'Ext.menu.Item',
- alias: 'widget.pveMenuItem',
-
- // set to wrap the handler callback in a confirm dialog showing this text
- confirmMsg: false,
-
- // set to focus 'No' instead of 'Yes' button and show a warning symbol
- dangerous: false,
-
- initComponent: function() {
- var me = this;
-
- if (me.handler) {
- me.setHandler(me.handler, me.scope);
- }
-
- me.callParent();
- },
-
- setHandler: function(fn, scope) {
- var me = this;
- me.scope = scope;
- me.handler = function(button, e) {
- var rec, msg;
- if (me.confirmMsg) {
- msg = me.confirmMsg;
- Ext.MessageBox.defaultButton = me.dangerous ? 2 : 1;
- Ext.Msg.show({
- title: gettext('Confirm'),
- icon: me.dangerous ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
- msg: msg,
- buttons: Ext.Msg.YESNO,
- defaultFocus: me.dangerous ? 'no' : 'yes',
- callback: function(btn) {
- if (btn === 'yes') {
- Ext.callback(fn, me.scope, [me, e], 0, me);
- }
- }
- });
- } else {
- Ext.callback(fn, me.scope, [me, e], 0, me);
- }
- };
- }
-});
-Ext.define('PVE.menu.TemplateMenu', {
- extend: 'Ext.menu.Menu',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var guestType = me.pveSelNode.data.type;
- if (guestType !== 'qemu' && guestType != 'lxc') {
- throw "invalid guest type";
- }
-
- var vmname = me.pveSelNode.data.name;
-
- var template = me.pveSelNode.data.template;
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + nodename + '/' + guestType + '/' + vmid + "/status/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- me.title = (guestType === 'qemu' ? 'VM ' : 'CT ') + vmid;
-
- me.items = [
- {
- text: gettext('Migrate'),
- iconCls: 'fa fa-fw fa-send-o',
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: guestType,
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- }
- },
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- handler: function() {
- var win = Ext.create('PVE.window.Clone', {
- nodename: nodename,
- guestType: guestType,
- vmid: vmid,
- isTemplate: template
- });
- win.show();
- }
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.button.ConsoleButton', {
- extend: 'Ext.button.Split',
- alias: 'widget.pveConsoleButton',
-
- consoleType: 'shell', // one of 'shell', 'kvm', 'lxc', 'upgrade', 'cmd'
-
- cmd: undefined,
-
- consoleName: undefined,
-
- iconCls: 'fa fa-terminal',
-
- enableSpice: true,
- enableXtermjs: true,
-
- nodename: undefined,
-
- vmid: 0,
-
- text: gettext('Console'),
-
- setEnableSpice: function(enable){
- var me = this;
-
- me.enableSpice = enable;
- me.down('#spicemenu').setDisabled(!enable);
- },
-
- setEnableXtermJS: function(enable){
- var me = this;
-
- me.enableXtermjs = enable;
- me.down('#xtermjs').setDisabled(!enable);
- },
-
- handler: function() {
- var me = this;
- var consoles = {
- spice: me.enableSpice,
- xtermjs: me.enableXtermjs
- };
- PVE.Utils.openDefaultConsoleWindow(consoles, me.consoleType, me.vmid,
- me.nodename, me.consoleName, me.cmd);
- },
-
- menu: [
- {
- xtype:'menuitem',
- text: 'noVNC',
- iconCls: 'pve-itype-icon-novnc',
- type: 'html5',
- handler: function(button) {
- var me = this.up('button');
- PVE.Utils.openConsoleWindow(button.type, me.consoleType, me.vmid, me.nodename, me.consoleName, me.cmd);
- }
- },
- {
- xterm: 'menuitem',
- itemId: 'spicemenu',
- text: 'SPICE',
- type: 'vv',
- iconCls: 'pve-itype-icon-virt-viewer',
- handler: function(button) {
- var me = this.up('button');
- PVE.Utils.openConsoleWindow(button.type, me.consoleType, me.vmid, me.nodename, me.consoleName, me.cmd);
- }
- },
- {
- text: 'xterm.js',
- itemId: 'xtermjs',
- iconCls: 'pve-itype-icon-xtermjs',
- type: 'xtermjs',
- handler: function(button) {
- var me = this.up('button');
- PVE.Utils.openConsoleWindow(button.type, me.consoleType, me.vmid, me.nodename, me.consoleName, me.cmd);
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.callParent();
- }
-});
-/* Button features:
- * - observe selection changes to enable/disable the button using enableFn()
- * - pop up confirmation dialog using confirmMsg()
- *
- * does this for the button and every menu item
- */
-Ext.define('PVE.button.Split', {
- extend: 'Ext.button.Split',
- alias: 'widget.pveSplitButton',
-
- // the selection model to observe
- selModel: undefined,
-
- // if 'false' handler will not be called (button disabled)
- enableFn: function(record) { },
-
- // function(record) or text
- confirmMsg: false,
-
- // take special care in confirm box (select no as default).
- dangerous: false,
-
- handlerWrapper: function(button, event) {
- var me = this;
- var rec, msg;
- if (me.selModel) {
- rec = me.selModel.getSelection()[0];
- if (!rec || (me.enableFn(rec) === false)) {
- return;
- }
- }
-
- if (me.confirmMsg) {
- msg = me.confirmMsg;
- // confirMsg can be boolean or function
- /*jslint confusion: true*/
- if (Ext.isFunction(me.confirmMsg)) {
- msg = me.confirmMsg(rec);
- }
- /*jslint confusion: false*/
- Ext.MessageBox.defaultButton = me.dangerous ? 2 : 1;
- Ext.Msg.show({
- title: gettext('Confirm'),
- icon: me.dangerous ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
- msg: msg,
- buttons: Ext.Msg.YESNO,
- callback: function(btn) {
- if (btn !== 'yes') {
- return;
- }
- me.realHandler(button, event, rec);
- }
- });
- } else {
- me.realHandler(button, event, rec);
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
-
- var me = this;
-
- if (me.handler) {
- me.realHandler = me.handler;
- me.handler = me.handlerWrapper;
- }
-
- if (me.menu && me.menu.items) {
- me.menu.items.forEach(function(item) {
- if (item.handler) {
- item.realHandler = item.handler;
- item.handler = me.handlerWrapper;
- }
-
- if (item.selModel) {
- me.mon(item.selModel, "selectionchange", function() {
- var rec = item.selModel.getSelection()[0];
- if (!rec || (item.enableFn(rec) === false )) {
- item.setDisabled(true);
- } else {
- item.setDisabled(false);
- }
- });
- }
- });
- }
-
- me.callParent();
-
- if (me.selModel) {
-
- me.mon(me.selModel, "selectionchange", function() {
- var rec = me.selModel.getSelection()[0];
- if (!rec || (me.enableFn(rec) === false)) {
- me.setDisabled(true);
- } else {
- me.setDisabled(false);
- }
- });
- }
- }
-});
-Ext.define('PVE.controller.StorageEdit', {
- extend: 'Ext.app.ViewController',
- alias: 'controller.storageEdit',
- control: {
- 'field[name=content]': {
- change: function(field, value) {
- var hasBackups = Ext.Array.contains(value, 'backup');
- var maxfiles = this.lookupReference('maxfiles');
- if (!maxfiles) {
- return;
- }
-
- if (!hasBackups) {
- // clear values which will never be submitted
- maxfiles.reset();
- }
- maxfiles.setDisabled(!hasBackups);
- }
- }
- }
-});
-Ext.define('PVE.qemu.CmdMenu', {
- extend: 'Ext.menu.Menu',
-
- showSeparator: false,
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var vmname = me.pveSelNode.data.name;
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + nodename + '/qemu/' + vmid + "/status/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var running = false;
- var stopped = true;
- var suspended = false;
- var standalone = PVE.data.ResourceStore.getNodes().length < 2;
-
- switch (me.pveSelNode.data.status) {
- case 'running':
- running = true;
- stopped = false;
- break;
- case 'suspended':
- stopped = false;
- suspended = true;
- break;
- case 'paused':
- stopped = false;
- suspended = true;
- break;
- default: break;
- }
-
- me.title = "VM " + vmid;
-
- me.items = [
- {
- text: gettext('Start'),
- iconCls: 'fa fa-fw fa-play',
- hidden: running || suspended,
- disabled: running || suspended,
- handler: function() {
- vm_command('start');
- }
- },
- {
- text: gettext('Pause'),
- iconCls: 'fa fa-fw fa-pause',
- hidden: stopped || suspended,
- disabled: stopped || suspended,
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmpause', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
- vm_command('suspend');
- });
- }
- },
- {
- text: gettext('Hibernate'),
- iconCls: 'fa fa-fw fa-download',
- hidden: stopped || suspended,
- disabled: stopped || suspended,
- tooltip: gettext('Suspend to disk'),
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmsuspend', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
- vm_command('suspend', { todisk: 1 });
- });
- }
- },
- {
- text: gettext('Resume'),
- iconCls: 'fa fa-fw fa-play',
- hidden: !suspended,
- handler: function() {
- vm_command('resume');
- }
- },
- {
- text: gettext('Shutdown'),
- iconCls: 'fa fa-fw fa-power-off',
- disabled: stopped || suspended,
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmshutdown', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- vm_command('shutdown');
- });
- }
- },
- {
- text: gettext('Stop'),
- iconCls: 'fa fa-fw fa-stop',
- disabled: stopped,
- tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'VM'),
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmstop', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- vm_command("stop");
- });
- }
- },
- {
- xtype: 'menuseparator',
- hidden: (standalone || !caps.vms['VM.Migrate']) && !caps.vms['VM.Allocate'] && !caps.vms['VM.Clone']
- },
- {
- text: gettext('Migrate'),
- iconCls: 'fa fa-fw fa-send-o',
- hidden: standalone || !caps.vms['VM.Migrate'],
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: 'qemu',
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- }
- },
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- hidden: !caps.vms['VM.Clone'],
- handler: function() {
- PVE.window.Clone.wrap(nodename, vmid, me.isTemplate, 'qemu');
- }
- },
- {
- text: gettext('Convert to template'),
- iconCls: 'fa fa-fw fa-file-o',
- hidden: !caps.vms['VM.Allocate'],
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmtemplate', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/qemu/' + vmid + '/template',
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- });
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Console'),
- iconCls: 'fa fa-fw fa-terminal',
- handler: function() {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/qemu/' + vmid + '/status/current',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, opts) {
- var allowSpice = response.result.data.spice;
- var allowXtermjs = response.result.data.serial;
- var consoles = {
- spice: allowSpice,
- xtermjs: allowXtermjs
- };
- PVE.Utils.openDefaultConsoleWindow(consoles, 'kvm', vmid, nodename, vmname);
- }
- });
- }
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.lxc.CmdMenu', {
- extend: 'Ext.menu.Menu',
-
- showSeparator: false,
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no CT ID specified";
- }
- var vmname = me.pveSelNode.data.name;
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + nodename + '/lxc/' + vmid + "/status/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var running = false;
- var stopped = true;
- var suspended = false;
- var standalone = PVE.data.ResourceStore.getNodes().length < 2;
-
- switch (me.pveSelNode.data.status) {
- case 'running':
- running = true;
- stopped = false;
- break;
- case 'paused':
- stopped = false;
- suspended = true;
- break;
- default: break;
- }
-
- me.title = 'CT ' + vmid;
-
- me.items = [
- {
- text: gettext('Start'),
- iconCls: 'fa fa-fw fa-play',
- disabled: running,
- handler: function() {
- vm_command('start');
- }
- },
-// {
-// text: gettext('Suspend'),
-// iconCls: 'fa fa-fw fa-pause',
-// hidde: suspended,
-// disabled: stopped || suspended,
-// handler: function() {
-// var msg = Proxmox.Utils.format_task_description('vzsuspend', vmid);
-// Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
-// if (btn !== 'yes') {
-// return;
-// }
-//
-// vm_command('suspend');
-// });
-// }
-// },
-// {
-// text: gettext('Resume'),
-// iconCls: 'fa fa-fw fa-play',
-// hidden: !suspended,
-// handler: function() {
-// vm_command('resume');
-// }
-// },
- {
- text: gettext('Shutdown'),
- iconCls: 'fa fa-fw fa-power-off',
- disabled: stopped || suspended,
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('vzshutdown', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- vm_command('shutdown');
- });
- }
- },
- {
- text: gettext('Stop'),
- iconCls: 'fa fa-fw fa-stop',
- disabled: stopped,
- tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'CT'),
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('vzstop', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- vm_command("stop");
- });
- }
- },
- {
- xtype: 'menuseparator',
- hidden: standalone || !caps.vms['VM.Migrate']
- },
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- hidden: !caps.vms['VM.Clone'],
- handler: function() {
- PVE.window.Clone.wrap(nodename, vmid, me.isTemplate, 'lxc');
- }
- },
- {
- text: gettext('Migrate'),
- iconCls: 'fa fa-fw fa-send-o',
- hidden: standalone || !caps.vms['VM.Migrate'],
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: 'lxc',
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- }
- },
- {
- text: gettext('Convert to template'),
- iconCls: 'fa fa-fw fa-file-o',
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('vztemplate', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/lxc/' + vmid + '/template',
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- });
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Console'),
- iconCls: 'fa fa-fw fa-terminal',
- handler: function() {
- PVE.Utils.openDefaultConsoleWindow(true, 'lxc', vmid, nodename, vmname);
- }
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.node.CmdMenu', {
- extend: 'Ext.menu.Menu',
- xtype: 'nodeCmdMenu',
-
- showSeparator: false,
-
- items: [
- {
- text: gettext('Create VM'),
- itemId: 'createvm',
- iconCls: 'fa fa-desktop',
- handler: function() {
- var me = this.up('menu');
- var wiz = Ext.create('PVE.qemu.CreateWizard', {
- nodename: me.nodename
- });
- wiz.show();
- }
- },
- {
- text: gettext('Create CT'),
- itemId: 'createct',
- iconCls: 'fa fa-cube',
- handler: function() {
- var me = this.up('menu');
- var wiz = Ext.create('PVE.lxc.CreateWizard', {
- nodename: me.nodename
- });
- wiz.show();
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Bulk Start'),
- itemId: 'bulkstart',
- iconCls: 'fa fa-fw fa-play',
- handler: function() {
- var me = this.up('menu');
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: me.nodename,
- title: gettext('Bulk Start'),
- btnText: gettext('Start'),
- action: 'startall'
- });
- win.show();
- }
- },
- {
- text: gettext('Bulk Stop'),
- itemId: 'bulkstop',
- iconCls: 'fa fa-fw fa-stop',
- handler: function() {
- var me = this.up('menu');
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: me.nodename,
- title: gettext('Bulk Stop'),
- btnText: gettext('Stop'),
- action: 'stopall'
- });
- win.show();
- }
- },
- {
- text: gettext('Bulk Migrate'),
- itemId: 'bulkmigrate',
- iconCls: 'fa fa-fw fa-send-o',
- handler: function() {
- var me = this.up('menu');
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: me.nodename,
- title: gettext('Bulk Migrate'),
- btnText: gettext('Migrate'),
- action: 'migrateall'
- });
- win.show();
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Shell'),
- itemId: 'shell',
- iconCls: 'fa fa-fw fa-terminal',
- handler: function() {
- var me = this.up('menu');
- PVE.Utils.openDefaultConsoleWindow(true, 'shell', undefined, me.nodename, undefined);
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Wake-on-LAN'),
- itemId: 'wakeonlan',
- iconCls: 'fa fa-fw fa-power-off',
- handler: function() {
- var me = this.up('menu');
- Proxmox.Utils.API2Request({
- param: {},
- url: '/nodes/' + me.nodename + '/wakeonlan',
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- Ext.Msg.show({
- title: 'Success',
- icon: Ext.Msg.INFO,
- msg: Ext.String.format(gettext("Wake on LAN packet send for '{0}': '{1}'"), me.nodename, response.result.data)
- });
- }
- });
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw 'no nodename specified';
- }
-
- me.title = gettext('Node') + " '" + me.nodename + "'";
- me.callParent();
-
- var caps = Ext.state.Manager.get('GuiCap');
- // disable not allowed options
- if (!caps.vms['VM.Allocate']) {
- me.getComponent('createct').setDisabled(true);
- me.getComponent('createvm').setDisabled(true);
- }
-
- if (!caps.nodes['Sys.PowerMgmt']) {
- me.getComponent('bulkstart').setDisabled(true);
- me.getComponent('bulkstop').setDisabled(true);
- me.getComponent('bulkmigrate').setDisabled(true);
- me.getComponent('wakeonlan').setDisabled(true);
- }
-
- if (!caps.nodes['Sys.Console']) {
- me.getComponent('shell').setDisabled(true);
- }
-
- if (me.pveSelNode.data.running) {
- me.getComponent('wakeonlan').setDisabled(true);
- }
- }
-});
-Ext.define('PVE.noVncConsole', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNoVncConsole',
-
- nodename: undefined,
-
- vmid: undefined,
-
- cmd: undefined,
-
- consoleType: undefined, // lxc, kvm, shell, cmd
-
- layout: 'fit',
-
- xtermjs: false,
-
- border: false,
-
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.consoleType) {
- throw "no console type specified";
- }
-
- if (!me.vmid && me.consoleType !== 'shell' && me.consoleType !== 'cmd') {
- throw "no VM ID specified";
- }
-
- // always use same iframe, to avoid running several noVnc clients
- // at same time (to avoid performance problems)
- var box = Ext.create('Ext.ux.IFrame', { itemid : "vncconsole" });
-
- var type = me.xtermjs ? 'xtermjs' : 'novnc';
- Ext.apply(me, {
- items: box,
- listeners: {
- activate: function() {
- var queryDict = {
- console: me.consoleType, // kvm, lxc, upgrade or shell
- vmid: me.vmid,
- node: me.nodename,
- cmd: me.cmd,
- resize: 'scale'
- };
- queryDict[type] = 1;
- PVE.Utils.cleanEmptyObjectKeys(queryDict);
- var url = '/?' + Ext.Object.toQueryString(queryDict);
- box.load(url);
- }
- }
- });
-
- me.callParent();
-
- me.on('afterrender', function() {
- me.focus();
- });
- }
-});
-
-Ext.define('PVE.data.PermPathStore', {
- extend: 'Ext.data.Store',
- alias: 'store.pvePermPath',
- fields: [ 'value' ],
- autoLoad: false,
- data: [
- {'value': '/'},
- {'value': '/access'},
- {'value': '/nodes'},
- {'value': '/pool'},
- {'value': '/storage'},
- {'value': '/vms'}
- ],
-
- constructor: function(config) {
- var me = this;
-
- config = config || {};
-
- me.callParent([config]);
-
- me.suspendEvents();
- PVE.data.ResourceStore.each(function(record) {
- switch (record.get('type')) {
- case 'node':
- me.add({value: '/nodes/' + record.get('text')});
- break;
-
- case 'qemu':
- me.add({value: '/vms/' + record.get('vmid')});
- break;
-
- case 'lxc':
- me.add({value: '/vms/' + record.get('vmid')});
- break;
-
- case 'storage':
- me.add({value: '/storage/' + record.get('storage')});
- break;
- case 'pool':
- me.add({value: '/pool/' + record.get('pool')});
- break;
- }
- });
- me.resumeEvents();
-
- me.fireEvent('refresh', me);
- me.fireEvent('datachanged', me);
-
- me.sort({
- property: 'value',
- direction: 'ASC'
- });
- }
-});
-Ext.define('PVE.data.ResourceStore', {
- extend: 'Proxmox.data.UpdateStore',
- singleton: true,
-
- findVMID: function(vmid) {
- var me = this, i;
-
- return (me.findExact('vmid', parseInt(vmid, 10)) >= 0);
- },
-
- // returns the cached data from all nodes
- getNodes: function() {
- var me = this;
-
- var nodes = [];
- me.each(function(record) {
- if (record.get('type') == "node") {
- nodes.push( record.getData() );
- }
- });
-
- return nodes;
- },
-
- storageIsShared: function(storage_path) {
- var me = this;
-
- var index = me.findExact('id', storage_path);
-
- return me.getAt(index).data.shared;
- },
-
- guestNode: function(vmid) {
- var me = this;
-
- var index = me.findExact('vmid', parseInt(vmid, 10));
-
- return me.getAt(index).data.node;
- },
-
- constructor: function(config) {
- // fixme: how to avoid those warnings
- /*jslint confusion: true */
-
- var me = this;
-
- config = config || {};
-
- var field_defaults = {
- type: {
- header: gettext('Type'),
- type: 'string',
- renderer: PVE.Utils.render_resource_type,
- sortable: true,
- hideable: false,
- width: 100
- },
- id: {
- header: 'ID',
- type: 'string',
- hidden: true,
- sortable: true,
- width: 80
- },
- running: {
- header: gettext('Online'),
- type: 'boolean',
- renderer: Proxmox.Utils.format_boolean,
- hidden: true,
- convert: function(value, record) {
- var info = record.data;
- return (Ext.isNumeric(info.uptime) && (info.uptime > 0));
- }
- },
- text: {
- header: gettext('Description'),
- type: 'string',
- sortable: true,
- width: 200,
- convert: function(value, record) {
- var info = record.data;
- var text;
-
- if (value) {
- return value;
- }
-
- if (Ext.isNumeric(info.vmid) && info.vmid > 0) {
- text = String(info.vmid);
- if (info.name) {
- text += " (" + info.name + ')';
- }
- } else { // node, pool, storage
- text = info[info.type] || info.id;
- if (info.node && info.type !== 'node') {
- text += " (" + info.node + ")";
- }
- }
-
- return text;
- }
- },
- vmid: {
- header: 'VMID',
- type: 'integer',
- hidden: true,
- sortable: true,
- width: 80
- },
- name: {
- header: gettext('Name'),
- hidden: true,
- sortable: true,
- type: 'string'
- },
- disk: {
- header: gettext('Disk usage'),
- type: 'integer',
- renderer: PVE.Utils.render_disk_usage,
- sortable: true,
- width: 100,
- hidden: true
- },
- diskuse: {
- header: gettext('Disk usage') + " %",
- type: 'number',
- sortable: true,
- renderer: PVE.Utils.render_disk_usage_percent,
- width: 100,
- calculate: PVE.Utils.calculate_disk_usage,
- sortType: 'asFloat'
- },
- maxdisk: {
- header: gettext('Disk size'),
- type: 'integer',
- renderer: PVE.Utils.render_size,
- sortable: true,
- hidden: true,
- width: 100
- },
- mem: {
- header: gettext('Memory usage'),
- type: 'integer',
- renderer: PVE.Utils.render_mem_usage,
- sortable: true,
- hidden: true,
- width: 100
- },
- memuse: {
- header: gettext('Memory usage') + " %",
- type: 'number',
- renderer: PVE.Utils.render_mem_usage_percent,
- calculate: PVE.Utils.calculate_mem_usage,
- sortType: 'asFloat',
- sortable: true,
- width: 100
- },
- maxmem: {
- header: gettext('Memory size'),
- type: 'integer',
- renderer: PVE.Utils.render_size,
- hidden: true,
- sortable: true,
- width: 100
- },
- cpu: {
- header: gettext('CPU usage'),
- type: 'float',
- renderer: PVE.Utils.render_cpu,
- sortable: true,
- width: 100
- },
- maxcpu: {
- header: gettext('maxcpu'),
- type: 'integer',
- hidden: true,
- sortable: true,
- width: 60
- },
- diskread: {
- header: gettext('Total Disk Read'),
- type: 'integer',
- hidden: true,
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- width: 100
- },
- diskwrite: {
- header: gettext('Total Disk Write'),
- type: 'integer',
- hidden: true,
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- width: 100
- },
- netin: {
- header: gettext('Total NetIn'),
- type: 'integer',
- hidden: true,
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- width: 100
- },
- netout: {
- header: gettext('Total NetOut'),
- type: 'integer',
- hidden: true,
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- width: 100
- },
- template: {
- header: gettext('Template'),
- type: 'integer',
- hidden: true,
- sortable: true,
- width: 60
- },
- uptime: {
- header: gettext('Uptime'),
- type: 'integer',
- renderer: Proxmox.Utils.render_uptime,
- sortable: true,
- width: 110
- },
- node: {
- header: gettext('Node'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- },
- storage: {
- header: gettext('Storage'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- },
- pool: {
- header: gettext('Pool'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- },
- hastate: {
- header: gettext('HA State'),
- type: 'string',
- defaultValue: 'unmanaged',
- hidden: true,
- sortable: true
- },
- status: {
- header: gettext('Status'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- }
- };
-
- var fields = [];
- var fieldNames = [];
- Ext.Object.each(field_defaults, function(key, value) {
- var field = {name: key, type: value.type};
- if (Ext.isDefined(value.convert)) {
- field.convert = value.convert;
- }
-
- if (Ext.isDefined(value.calculate)) {
- field.calculate = value.calculate;
- }
-
- if (Ext.isDefined(value.defaultValue)) {
- field.defaultValue = value.defaultValue;
- }
-
- fields.push(field);
- fieldNames.push(key);
- });
-
- Ext.define('PVEResources', {
- extend: "Ext.data.Model",
- fields: fields,
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/resources'
- }
- });
-
- Ext.define('PVETree', {
- extend: "Ext.data.Model",
- fields: fields,
- proxy: { type: 'memory' }
- });
-
- Ext.apply(config, {
- storeid: 'PVEResources',
- model: 'PVEResources',
- defaultColumns: function() {
- var res = [];
- Ext.Object.each(field_defaults, function(field, info) {
- var fi = Ext.apply({ dataIndex: field }, info);
- res.push(fi);
- });
- return res;
- },
- fieldNames: fieldNames
- });
-
- me.callParent([config]);
- }
-});
-Ext.define('pve-domains', {
- extend: "Ext.data.Model",
- fields: [
- 'realm', 'type', 'comment', 'default', 'tfa',
- {
- name: 'descr',
- // Note: We use this in the RealmComboBox.js (see Bug #125)
- convert: function(value, record) {
- if (value) {
- return value;
- }
-
- var info = record.data;
- // return realm if there is no comment
- var text = info.comment || info.realm;
-
- if (info.tfa) {
- text += " (+ " + info.tfa + ")";
- }
-
- return Ext.String.htmlEncode(text);
- }
- }
- ],
- idProperty: 'realm',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/domains"
- }
-});
-Ext.define('pve-rrd-node', {
- extend: 'Ext.data.Model',
- fields: [
- {
- name:'cpu',
- // percentage
- convert: function(value) {
- return value*100;
- }
- },
- {
- name:'iowait',
- // percentage
- convert: function(value) {
- return value*100;
- }
- },
- 'loadavg',
- 'maxcpu',
- 'memtotal',
- 'memused',
- 'netin',
- 'netout',
- 'roottotal',
- 'rootused',
- 'swaptotal',
- 'swapused',
- { type: 'date', dateFormat: 'timestamp', name: 'time' }
- ]
-});
-
-Ext.define('pve-rrd-guest', {
- extend: 'Ext.data.Model',
- fields: [
- {
- name:'cpu',
- // percentage
- convert: function(value) {
- return value*100;
- }
- },
- 'maxcpu',
- 'netin',
- 'netout',
- 'mem',
- 'maxmem',
- 'disk',
- 'maxdisk',
- 'diskread',
- 'diskwrite',
- { type: 'date', dateFormat: 'timestamp', name: 'time' }
- ]
-});
-
-Ext.define('pve-rrd-storage', {
- extend: 'Ext.data.Model',
- fields: [
- 'used',
- 'total',
- { type: 'date', dateFormat: 'timestamp', name: 'time' }
- ]
-});
-Ext.define('PVE.form.VlanField', {
- extend: 'Ext.form.field.Number',
- alias: ['widget.pveVlanField'],
-
- deleteEmpty: false,
-
- emptyText: 'no VLAN',
-
- fieldLabel: gettext('VLAN Tag'),
-
- allowBlank: true,
-
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue) {
- val = me.getSubmitValue();
- if (val) {
- data = {};
- data[me.getName()] = val;
- } else if (me.deleteEmpty) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- initComponent: function() {
- var me = this;
-
- Ext.apply(me, {
- minValue: 1,
- maxValue: 4094
- });
-
- me.callParent();
- }
-});
-// boolean type including 'Default' (delete property from file)
-Ext.define('PVE.form.Boolean', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.booleanfield'],
- comboItems: [
- ['__default__', gettext('Default')],
- [1, gettext('Yes')],
- [0, gettext('No')]
- ]
-});
-Ext.define('PVE.form.CompressionSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveCompressionSelector'],
- comboItems: [
- ['0', Proxmox.Utils.noneText],
- ['lzo', 'LZO (' + gettext('fast') + ')'],
- ['gzip', 'GZIP (' + gettext('good') + ')']
- ]
-});
-Ext.define('PVE.form.PoolSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pvePoolSelector'],
-
- allowBlank: false,
- valueField: 'poolid',
- displayField: 'poolid',
-
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-pools',
- sorters: 'poolid'
- });
-
- Ext.apply(me, {
- store: store,
- autoSelect: false,
- listConfig: {
- columns: [
- {
- header: gettext('Pool'),
- sortable: true,
- dataIndex: 'poolid',
- flex: 1
- },
- {
- header: gettext('Comment'),
- sortable: false,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
-
- store.load();
- }
-
-}, function() {
-
- Ext.define('pve-pools', {
- extend: 'Ext.data.Model',
- fields: [ 'poolid', 'comment' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/pools"
- },
- idProperty: 'poolid'
- });
-
-});
-Ext.define('PVE.form.PrivilegesSelector', {
- extend: 'Proxmox.form.KVComboBox',
- xtype: 'pvePrivilegesSelector',
-
- multiSelect: true,
-
- initComponent: function() {
- var me = this;
-
- // So me.store is available.
- me.callParent();
-
- Proxmox.Utils.API2Request({
- url: '/access/roles/Administrator',
- method: 'GET',
- success: function(response, options) {
- var data = [], key;
- /*jslint forin: true */
- for (key in response.result.data) {
- data.push([key, key]);
- }
- /*jslint forin: false */
-
- me.store.setData(data);
-
- me.store.sort({
- property: 'key',
- direction: 'ASC'
- });
- },
-
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
-});
-Ext.define('pve-groups', {
- extend: 'Ext.data.Model',
- fields: [ 'groupid', 'comment' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/groups"
- },
- idProperty: 'groupid'
-});
-
-Ext.define('PVE.form.GroupSelector', {
- extend: 'Proxmox.form.ComboGrid',
- xtype: 'pveGroupSelector',
-
- allowBlank: false,
- autoSelect: false,
- valueField: 'groupid',
- displayField: 'groupid',
- listConfig: {
- columns: [
- {
- header: gettext('Group'),
- sortable: true,
- dataIndex: 'groupid',
- flex: 1
- },
- {
- header: gettext('Comment'),
- sortable: false,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- },
-
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-groups',
- sorters: [{
- property: 'groupid'
- }]
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- store.load();
- }
-});
-Ext.define('PVE.form.UserSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveUserSelector'],
-
- allowBlank: false,
- autoSelect: false,
- valueField: 'userid',
- displayField: 'userid',
-
- editable: true,
- anyMatch: true,
- forceSelection: true,
-
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-users',
- sorters: [{
- property: 'userid'
- }]
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: gettext('User'),
- sortable: true,
- dataIndex: 'userid',
- flex: 1
- },
- {
- header: gettext('Name'),
- sortable: true,
- renderer: PVE.Utils.render_full_name,
- dataIndex: 'firstname',
- flex: 1
- },
- {
- header: gettext('Comment'),
- sortable: false,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
-
- store.load({ params: { enabled: 1 }});
- }
-
-}, function() {
-
- Ext.define('pve-users', {
- extend: 'Ext.data.Model',
- fields: [
- 'userid', 'firstname', 'lastname' , 'email', 'comment',
- { type: 'boolean', name: 'enable' },
- { type: 'date', dateFormat: 'timestamp', name: 'expire' }
- ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/users"
- },
- idProperty: 'userid'
- });
-
-});
-
-
-Ext.define('PVE.form.RoleSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveRoleSelector'],
-
- allowBlank: false,
- autoSelect: false,
- valueField: 'roleid',
- displayField: 'roleid',
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-roles',
- sorters: [{
- property: 'roleid'
- }]
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: gettext('Role'),
- sortable: true,
- dataIndex: 'roleid',
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
-
- store.load();
- }
-
-}, function() {
-
- Ext.define('pve-roles', {
- extend: 'Ext.data.Model',
- fields: [ 'roleid', 'privs' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/roles"
- },
- idProperty: 'roleid'
- });
-
-});
-Ext.define('PVE.form.GuestIDSelector', {
- extend: 'Ext.form.field.Number',
- alias: 'widget.pveGuestIDSelector',
-
- allowBlank: false,
-
- minValue: 100,
-
- maxValue: 999999999,
-
- validateExists: undefined,
-
- loadNextFreeID: false,
-
- guestType: undefined,
-
- validator: function(value) {
- var me = this;
-
- if (!Ext.isNumeric(value) ||
- value < me.minValue ||
- value > me.maxValue) {
- // check is done by ExtJS
- return true;
- }
-
- if (me.validateExists === true && !me.exists) {
- return me.unknownID;
- }
-
- if (me.validateExists === false && me.exists) {
- return me.inUseID;
- }
-
- return true;
- },
-
- initComponent: function() {
- var me = this;
- var label = '{0} ID';
- var unknownID = gettext('This {0} ID does not exists');
- var inUseID = gettext('This {0} ID is already in use');
- var type = 'CT/VM';
-
- if (me.guestType === 'lxc') {
- type = 'CT';
- } else if (me.guestType === 'qemu') {
- type = 'VM';
- }
-
- me.label = Ext.String.format(label, type);
- me.unknownID = Ext.String.format(unknownID, type);
- me.inUseID = Ext.String.format(inUseID, type);
-
- Ext.apply(me, {
- fieldLabel: me.label,
- listeners: {
- 'change': function(field, newValue, oldValue) {
- if (!Ext.isDefined(me.validateExists)) {
- return;
- }
- Proxmox.Utils.API2Request({
- params: { vmid: newValue },
- url: '/cluster/nextid',
- method: 'GET',
- success: function(response, opts) {
- me.exists = false;
- me.validate();
- },
- failure: function(response, opts) {
- me.exists = true;
- me.validate();
- }
- });
- }
- }
- });
-
- me.callParent();
-
- if (me.loadNextFreeID) {
- Proxmox.Utils.API2Request({
- url: '/cluster/nextid',
- method: 'GET',
- success: function(response, opts) {
- me.setRawValue(response.result.data);
- }
- });
- }
- }
-});
-Ext.define('PVE.form.MemoryField', {
- extend: 'Ext.form.field.Number',
- alias: 'widget.pveMemoryField',
-
- allowBlank: false,
-
- hotplug: false,
-
- minValue: 32,
-
- maxValue: 4178944,
-
- step: 32,
-
- value: '512', // qm default
-
- allowDecimals: false,
-
- allowExponential: false,
-
- computeUpDown: function(value) {
- var me = this;
-
- if (!me.hotplug) {
- return { up: value + me.step, down: value - me.step };
- }
-
- var dimm_size = 512;
- var prev_dimm_size = 0;
- var min_size = 1024;
- var current_size = min_size;
- var value_up = min_size;
- var value_down = min_size;
- var value_start = min_size;
-
- var i, j;
- for (j = 0; j < 9; j++) {
- for (i = 0; i < 32; i++) {
- if ((value >= current_size) && (value < (current_size + dimm_size))) {
- value_start = current_size;
- value_up = current_size + dimm_size;
- value_down = current_size - ((i === 0) ? prev_dimm_size : dimm_size);
- }
- current_size += dimm_size;
- }
- prev_dimm_size = dimm_size;
- dimm_size = dimm_size*2;
- }
-
- return { up: value_up, down: value_down, start: value_start };
- },
-
- onSpinUp: function() {
- var me = this;
- if (!me.readOnly) {
- var res = me.computeUpDown(me.getValue());
- me.setValue(Ext.Number.constrain(res.up, me.minValue, me.maxValue));
- }
- },
-
- onSpinDown: function() {
- var me = this;
- if (!me.readOnly) {
- var res = me.computeUpDown(me.getValue());
- me.setValue(Ext.Number.constrain(res.down, me.minValue, me.maxValue));
- }
- },
-
- initComponent: function() {
- var me = this;
-
- if (me.hotplug) {
- me.minValue = 1024;
-
- me.on('blur', function(field) {
- var value = me.getValue();
- var res = me.computeUpDown(value);
- if (value === res.start || value === res.up || value === res.down) {
- return;
- }
- field.setValue(res.up);
- });
- }
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.NetworkCardSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: 'widget.pveNetworkCardSelector',
- comboItems: [
- ['e1000', 'Intel E1000'],
- ['virtio', 'VirtIO (' + gettext('paravirtualized') + ')'],
- ['rtl8139', 'Realtek RTL8139'],
- ['vmxnet3', 'VMware vmxnet3']
- ]
-});
-Ext.define('PVE.form.DiskFormatSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: 'widget.pveDiskFormatSelector',
- comboItems: [
- ['raw', gettext('Raw disk image') + ' (raw)'],
- ['qcow2', gettext('QEMU image format') + ' (qcow2)'],
- ['vmdk', gettext('VMware image format') + ' (vmdk)']
- ]
-});
-Ext.define('PVE.form.DiskSelector', {
- extend: 'Proxmox.form.ComboGrid',
- xtype: 'pveDiskSelector',
-
- // can be
- // undefined: all
- // unused: only unused
- // journal_disk: all disks with gpt
- diskType: undefined,
-
- valueField: 'devpath',
- displayField: 'devpath',
- emptyText: gettext('No Disks unused'),
- listConfig: {
- columns: [
- {
- header: gettext('Device'),
- width: 80,
- sortable: true,
- dataIndex: 'devpath'
- },
- {
- header: gettext('Size'),
- width: 60,
- sortable: false,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- },
- {
- header: gettext('Serial'),
- flex: 1,
- sortable: true,
- dataIndex: 'serial'
- }
- ]
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var store = Ext.create('Ext.data.Store', {
- filterOnLoad: true,
- model: 'pve-disk-list',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/disks/list",
- extraParams: { type: me.diskType }
- },
- sorters: [
- {
- property : 'devpath',
- direction: 'ASC'
- }
- ]
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- store.load();
- }
-}, function() {
-
- Ext.define('pve-disk-list', {
- extend: 'Ext.data.Model',
- fields: [ 'devpath', 'used', { name: 'size', type: 'number'},
- {name: 'osdid', type: 'number'},
- 'vendor', 'model', 'serial'],
- idProperty: 'devpath'
- });
-});
-Ext.define('PVE.form.BusTypeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: 'widget.pveBusSelector',
-
- noVirtIO: false,
-
- initComponent: function() {
- var me = this;
-
- me.comboItems = [['ide', 'IDE'], ['sata', 'SATA']];
-
- if (!me.noVirtIO) {
- me.comboItems.push(['virtio', 'VirtIO Block']);
- }
-
- me.comboItems.push(['scsi', 'SCSI']);
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.ControllerSelector', {
- extend: 'Ext.form.FieldContainer',
- alias: 'widget.pveControllerSelector',
-
- statics: {
- maxIds: {
- ide: 3,
- sata: 5,
- virtio: 15,
- scsi: 13
- }
- },
-
- noVirtIO: false,
-
- vmconfig: {}, // used to check for existing devices
-
- sortByPreviousUsage: function(vmconfig, controllerList) {
-
- var usedControllers = Ext.clone(PVE.form.ControllerSelector.maxIds);
-
- var type;
- for (type in usedControllers) {
- if(usedControllers.hasOwnProperty(type)) {
- usedControllers[type] = 0;
- }
- }
-
- var property;
- for (property in vmconfig) {
- if (vmconfig.hasOwnProperty(property)) {
- if (property.match(PVE.Utils.bus_match) && !vmconfig[property].match(/media=cdrom/)) {
- var foundController = property.match(PVE.Utils.bus_match)[1];
- usedControllers[foundController]++;
- }
- }
- }
-
- var vmDefaults = PVE.qemu.OSDefaults[vmconfig.ostype];
-
- var sortPriority = vmDefaults && vmDefaults.busPriority
- ? vmDefaults.busPriority : PVE.qemu.OSDefaults.generic;
-
- var sortedList = Ext.clone(controllerList);
- sortedList.sort(function(a,b) {
- if (usedControllers[b] == usedControllers[a]) {
- return sortPriority[b] - sortPriority[a];
- }
- return usedControllers[b] - usedControllers[a];
- });
-
- return sortedList;
- },
-
- setVMConfig: function(vmconfig, autoSelect) {
- var me = this;
-
- me.vmconfig = Ext.apply({}, vmconfig);
-
- var clist = ['ide', 'virtio', 'scsi', 'sata'];
- var bussel = me.down('field[name=controller]');
- var deviceid = me.down('field[name=deviceid]');
-
- if (autoSelect === 'cdrom') {
- clist = ['ide', 'scsi', 'sata'];
- if (!Ext.isDefined(me.vmconfig.ide2)) {
- bussel.setValue('ide');
- deviceid.setValue(2);
- return;
- }
- } else {
- // in most cases we want to add a disk to the same controller
- // we previously used
- clist = me.sortByPreviousUsage(me.vmconfig, clist);
- }
-
- Ext.Array.each(clist, function(controller) {
- var confid, i;
- bussel.setValue(controller);
- for (i = 0; i <= PVE.form.ControllerSelector.maxIds[controller]; i++) {
- confid = controller + i.toString();
- if (!Ext.isDefined(me.vmconfig[confid])) {
- deviceid.setValue(i);
- return false; // break
- }
- }
- });
- deviceid.validate();
- },
-
- initComponent: function() {
- var me = this;
-
- Ext.apply(me, {
- fieldLabel: gettext('Bus/Device'),
- layout: 'hbox',
- defaults: {
- hideLabel: true
- },
- items: [
- {
- xtype: 'pveBusSelector',
- name: 'controller',
- value: PVE.qemu.OSDefaults.generic.busType,
- noVirtIO: me.noVirtIO,
- allowBlank: false,
- flex: 2,
- listeners: {
- change: function(t, value) {
- if (!value) {
- return;
- }
- var field = me.down('field[name=deviceid]');
- field.setMaxValue(PVE.form.ControllerSelector.maxIds[value]);
- field.validate();
- }
- }
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'deviceid',
- minValue: 0,
- maxValue: PVE.form.ControllerSelector.maxIds.ide,
- value: '0',
- flex: 1,
- allowBlank: false,
- validator: function(value) {
- /*jslint confusion: true */
- if (!me.rendered) {
- return;
- }
- var field = me.down('field[name=controller]');
- var controller = field.getValue();
- var confid = controller + value;
- if (Ext.isDefined(me.vmconfig[confid])) {
- return "This device is already in use.";
- }
- return true;
- }
- }
- ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.EmailNotificationSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveEmailNotificationSelector'],
- comboItems: [
- ['always', gettext('Always')],
- ['failure', gettext('On failure only')]
- ]
-});
-/*global Proxmox*/
-Ext.define('PVE.form.RealmComboBox', {
- extend: 'Ext.form.field.ComboBox',
- alias: ['widget.pveRealmComboBox'],
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.store.on('load', this.onLoad, view);
- },
-
- onLoad: function(store, records, success) {
- if (!success) {
- return;
- }
- var me = this;
- var val = me.getValue();
- if (!val || !me.store.findRecord('realm', val)) {
- var def = 'pam';
- Ext.each(records, function(rec) {
- if (rec.data && rec.data['default']) {
- def = rec.data.realm;
- }
- });
- me.setValue(def);
- }
- }
- },
-
- fieldLabel: gettext('Realm'),
- name: 'realm',
- queryMode: 'local',
- allowBlank: false,
- editable: false,
- forceSelection: true,
- autoSelect: false,
- triggerAction: 'all',
- valueField: 'realm',
- displayField: 'descr',
- getState: function() {
- return { value: this.getValue() };
- },
- applyState : function(state) {
- if (state && state.value) {
- this.setValue(state.value);
- }
- },
- stateEvents: [ 'select' ],
- stateful: true, // last chosen auth realm is saved between page reloads
- id: 'pveloginrealm', // We need stable ids when using stateful, not autogenerated
- stateID: 'pveloginrealm',
-
- needOTP: function(realm) {
- var me = this;
- // use exact match
- var rec = me.store.findRecord('realm', realm, 0, false, false, true);
- return rec && rec.data && rec.data.tfa ? rec.data.tfa : undefined;
- },
-
- store: {
- model: 'pve-domains',
- autoLoad: true
- }
-});
-/*
- * Top left combobox, used to select a view of the underneath RessourceTree
- */
-Ext.define('PVE.form.ViewSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: ['widget.pveViewSelector'],
-
- editable: false,
- allowBlank: false,
- forceSelection: true,
- autoSelect: false,
- valueField: 'key',
- displayField: 'value',
- hideLabel: true,
- queryMode: 'local',
-
- initComponent: function() {
- var me = this;
-
- var default_views = {
- server: {
- text: gettext('Server View'),
- groups: ['node']
- },
- folder: {
- text: gettext('Folder View'),
- groups: ['type']
- },
- storage: {
- text: gettext('Storage View'),
- groups: ['node'],
- filterfn: function(node) {
- return node.data.type === 'storage' || node.data.type === 'node';
- }
- },
- pool: {
- text: gettext('Pool View'),
- groups: ['pool'],
- // Pool View only lists VMs and Containers
- filterfn: function(node) {
- return node.data.type === 'qemu' || node.data.type === 'lxc' || node.data.type === 'openvz' ||
- node.data.type === 'pool';
- }
- }
- };
-
- var groupdef = [];
- Ext.Object.each(default_views, function(viewname, value) {
- groupdef.push([viewname, value.text]);
- });
-
- var store = Ext.create('Ext.data.Store', {
- model: 'KeyValue',
- proxy: {
- type: 'memory',
- reader: 'array'
- },
- data: groupdef,
- autoload: true
- });
-
- Ext.apply(me, {
- store: store,
- value: groupdef[0][0],
- getViewFilter: function() {
- var view = me.getValue();
- return Ext.apply({ id: view }, default_views[view] || default_views.server);
- },
-
- getState: function() {
- return { value: me.getValue() };
- },
-
- applyState : function(state, doSelect) {
- var view = me.getValue();
- if (state && state.value && (view != state.value)) {
- var record = store.findRecord('key', state.value);
- if (record) {
- me.setValue(state.value, true);
- if (doSelect) {
- me.fireEvent('select', me, [record]);
- }
- }
- }
- },
- stateEvents: [ 'select' ],
- stateful: true,
- stateId: 'pveview',
- id: 'view'
- });
-
- me.callParent();
-
- var statechange = function(sp, key, value) {
- if (key === me.id) {
- me.applyState(value, true);
- }
- };
-
- var sp = Ext.state.Manager.getProvider();
- me.mon(sp, 'statechange', statechange, me);
- }
-});
-Ext.define('PVE.form.NodeSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveNodeSelector'],
-
- // invalidate nodes which are offline
- onlineValidator: false,
-
- selectCurNode: false,
-
- // do not allow those nodes (array)
- disallowedNodes: undefined,
-
- // only allow those nodes (array)
- allowedNodes: undefined,
- // set default value to empty array, else it inits it with
- // null and after the store load it is an empty array,
- // triggering dirtychange
- value: [],
- valueField: 'node',
- displayField: 'node',
- store: {
- fields: [ 'node', 'cpu', 'maxcpu', 'mem', 'maxmem', 'uptime' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes'
- },
- sorters: [
- {
- property : 'node',
- direction: 'ASC'
- },
- {
- property : 'mem',
- direction: 'DESC'
- }
- ]
- },
-
- listConfig: {
- columns: [
- {
- header: gettext('Node'),
- dataIndex: 'node',
- sortable: true,
- hideable: false,
- flex: 1
- },
- {
- header: gettext('Memory usage') + " %",
- renderer: PVE.Utils.render_mem_usage_percent,
- sortable: true,
- width: 100,
- dataIndex: 'mem'
- },
- {
- header: gettext('CPU usage'),
- renderer: PVE.Utils.render_cpu,
- sortable: true,
- width: 100,
- dataIndex: 'cpu'
- }
- ]
- },
-
- validator: function(value) {
- /*jslint confusion: true */
- var me = this;
- if (!me.onlineValidator || (me.allowBlank && !value)) {
- return true;
- }
-
- var offline = [];
- var notAllowed = [];
-
- Ext.Array.each(value.split(/\s*,\s*/), function(node) {
- var rec = me.store.findRecord(me.valueField, node);
- if (!(rec && rec.data) || !Ext.isNumeric(rec.data.mem)) {
- offline.push(node);
- } else if (me.allowedNodes && !Ext.Array.contains(me.allowedNodes, node)) {
- notAllowed.push(node);
- }
- });
-
- if (value && notAllowed.length !== 0) {
- return "Node " + notAllowed.join(', ') + " is not allowed for this action!";
- }
-
- if (value && offline.length !== 0) {
- return "Node " + offline.join(', ') + " seems to be offline!";
- }
- return true;
- },
-
- initComponent: function() {
- var me = this;
-
- if (me.selectCurNode && PVE.curSelectedNode && PVE.curSelectedNode.data.node) {
- me.preferredValue = PVE.curSelectedNode.data.node;
- }
-
- me.callParent();
- me.getStore().load();
-
- // filter out disallowed nodes
- me.getStore().addFilter(new Ext.util.Filter({
- filterFn: function(item) {
- if (Ext.isArray(me.disallowedNodes)) {
- return !Ext.Array.contains(me.disallowedNodes, item.data.node);
- } else {
- return true;
- }
- }
- }));
-
- me.mon(me.getStore(), 'load', function(){
- me.isValid();
- });
- }
-});
-Ext.define('PVE.form.FileSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.pveFileSelector',
-
- editable: true,
- anyMatch: true,
- forceSelection: true,
-
- listeners: {
- afterrender: function() {
- var me = this;
- if (!me.disabled) {
- me.setStorage(me.storage, me.nodename);
- }
- }
- },
-
- setStorage: function(storage, nodename) {
- var me = this;
-
- var change = false;
- if (storage && (me.storage !== storage)) {
- me.storage = storage;
- change = true;
- }
-
- if (nodename && (me.nodename !== nodename)) {
- me.nodename = nodename;
- change = true;
- }
-
- if (!(me.storage && me.nodename && change)) {
- return;
- }
-
- var url = '/api2/json/nodes/' + me.nodename + '/storage/' + me.storage + '/content';
- if (me.storageContent) {
- url += '?content=' + me.storageContent;
- }
-
- me.store.setProxy({
- type: 'proxmox',
- url: url
- });
-
- me.store.removeAll();
- me.store.load();
- },
-
- setNodename: function(nodename) {
- this.setStorage(undefined, nodename);
- },
-
- store: {
- model: 'pve-storage-content'
- },
-
- allowBlank: false,
- autoSelect: false,
- valueField: 'volid',
- displayField: 'text',
-
- listConfig: {
- width: 600,
- columns: [
- {
- header: gettext('Name'),
- dataIndex: 'text',
- hideable: false,
- flex: 1
- },
- {
- header: gettext('Format'),
- width: 60,
- dataIndex: 'format'
- },
- {
- header: gettext('Size'),
- width: 100,
- dataIndex: 'size',
- renderer: Proxmox.Utils.format_size
- }
- ]
- }
-});
-Ext.define('PVE.form.StorageSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.pveStorageSelector',
-
- allowBlank: false,
- valueField: 'storage',
- displayField: 'storage',
- listConfig: {
- columns: [
- {
- header: gettext('Name'),
- dataIndex: 'storage',
- hideable: false,
- flex: 1
- },
- {
- header: gettext('Type'),
- width: 60,
- dataIndex: 'type'
- },
- {
- header: gettext('Avail'),
- width: 80,
- dataIndex: 'avail',
- renderer: Proxmox.Utils.format_size
- },
- {
- header: gettext('Capacity'),
- width: 80,
- dataIndex: 'total',
- renderer: Proxmox.Utils.format_size
- }
- ]
- },
-
- reloadStorageList: function() {
- var me = this;
- if (!me.nodename) {
- return;
- }
-
- var params = {
- format: 1
- };
- var url = '/api2/json/nodes/' + me.nodename + '/storage';
- if (me.storageContent) {
- params.content = me.storageContent;
- }
- if (me.targetNode) {
- params.target = me.targetNode;
- params.enabled = 1; // skip disabled storages
- }
- me.store.setProxy({
- type: 'proxmox',
- url: url,
- extraParams: params
- });
-
- me.store.load();
-
- },
-
- setTargetNode: function(targetNode) {
- var me = this;
-
- if (!targetNode || (me.targetNode === targetNode)) {
- return;
- }
-
- me.targetNode = targetNode;
-
- me.reloadStorageList();
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
-
- me.reloadStorageList();
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- me.nodename = undefined;
-
- var store = Ext.create('Ext.data.Store', {
- model: 'pve-storage-status',
- sorters: {
- property: 'storage',
- order: 'DESC'
- }
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- if (nodename) {
- me.setNodename(nodename);
- }
- }
-}, function() {
-
- Ext.define('pve-storage-status', {
- extend: 'Ext.data.Model',
- fields: [ 'storage', 'active', 'type', 'avail', 'total' ],
- idProperty: 'storage'
- });
-
-});
-Ext.define('PVE.form.DiskStorageSelector', {
- extend: 'Ext.container.Container',
- alias: 'widget.pveDiskStorageSelector',
-
- layout: 'fit',
- defaults: {
- margin: '0 0 5 0'
- },
-
- // the fieldLabel for the storageselector
- storageLabel: gettext('Storage'),
-
- // the content to show (e.g., images or rootdir)
- storageContent: undefined,
-
- // if true, selects the first available storage
- autoSelect: false,
-
- allowBlank: false,
- emptyText: '',
-
- // hides the selection field
- // this is always hidden on creation,
- // and only shown when the storage needs a selection and
- // hideSelection is not true
- hideSelection: undefined,
-
- // hides the size field (e.g, for the efi disk dialog)
- hideSize: false,
-
- // sets the intial size value
- // string because else we get a type confusion
- defaultSize: '32',
-
- changeStorage: function(f, value) {
- var me = this;
- var formatsel = me.getComponent('diskformat');
- var hdfilesel = me.getComponent('hdimage');
- var hdsizesel = me.getComponent('disksize');
-
- // initial store load, and reset/deletion of the storage
- if (!value) {
- hdfilesel.setDisabled(true);
- hdfilesel.setVisible(false);
-
- formatsel.setDisabled(true);
- return;
- }
-
- var rec = f.store.getById(value);
- // if the storage is not defined, or valid,
- // we cannot know what to enable/disable
- if (!rec) {
- return;
- }
-
- var selectformat = false;
- if (rec.data.format) {
- var format = rec.data.format[0]; // 0 is the formats, 1 the default in the backend
- delete format.subvol; // we never need subvol in the gui
- selectformat = (Ext.Object.getSize(format) > 1);
- }
-
- var select = !!rec.data.select_existing && !me.hideSelection;
-
- formatsel.setDisabled(!selectformat);
- formatsel.setValue(selectformat ? 'qcow2' : 'raw');
-
- hdfilesel.setDisabled(!select);
- hdfilesel.setVisible(select);
- if (select) {
- hdfilesel.setStorage(value);
- }
-
- hdsizesel.setDisabled(select || me.hideSize);
- hdsizesel.setVisible(!select && !me.hideSize);
- },
-
- setNodename: function(nodename) {
- var me = this;
- var hdstorage = me.getComponent('hdstorage');
- var hdfilesel = me.getComponent('hdimage');
-
- hdstorage.setNodename(nodename);
- hdfilesel.setNodename(nodename);
- },
-
- setDisabled: function(value) {
- var me = this;
- var hdstorage = me.getComponent('hdstorage');
-
- // reset on disable
- if (value) {
- hdstorage.setValue();
- }
- hdstorage.setDisabled(value);
-
- // disabling does not always fire this event and we do not need
- // the value of the validity
- hdstorage.fireEvent('validitychange');
- },
-
- initComponent: function() {
- var me = this;
-
- me.items = [
- {
- xtype: 'pveStorageSelector',
- itemId: 'hdstorage',
- name: 'hdstorage',
- reference: 'hdstorage',
- fieldLabel: me.storageLabel,
- nodename: me.nodename,
- storageContent: me.storageContent,
- disabled: me.disabled,
- autoSelect: me.autoSelect,
- allowBlank: me.allowBlank,
- emptyText: me.emptyText,
- listeners: {
- change: {
- fn: me.changeStorage,
- scope: me
- }
- }
- },
- {
- xtype: 'pveFileSelector',
- name: 'hdimage',
- reference: 'hdimage',
- itemId: 'hdimage',
- fieldLabel: gettext('Disk image'),
- nodename: me.nodename,
- disabled: true,
- hidden: true
- },
- {
- xtype: 'numberfield',
- itemId: 'disksize',
- reference: 'disksize',
- name: 'disksize',
- fieldLabel: gettext('Disk size') + ' (GiB)',
- hidden: me.hideSize,
- disabled: me.hideSize,
- minValue: 0.001,
- maxValue: 128*1024,
- decimalPrecision: 3,
- value: me.defaultSize,
- allowBlank: false
- },
- {
- xtype: 'pveDiskFormatSelector',
- itemId: 'diskformat',
- reference: 'diskformat',
- name: 'diskformat',
- fieldLabel: gettext('Format'),
- nodename: me.nodename,
- disabled: true,
- hidden: me.storageContent === 'rootdir',
- value: 'qcow2',
- allowBlank: false
- }
- ];
-
- // use it to disable the children but not ourself
- me.disabled = false;
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.BridgeSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.PVE.form.BridgeSelector'],
-
- bridgeType: 'any_bridge', // bridge, OVSBridge or any_bridge
-
- store: {
- fields: [ 'iface', 'active', 'type' ],
- filterOnLoad: true,
- sorters: [
- {
- property : 'iface',
- direction: 'ASC'
- }
- ]
- },
- valueField: 'iface',
- displayField: 'iface',
- listConfig: {
- columns: [
- {
- header: gettext('Bridge'),
- dataIndex: 'iface',
- hideable: false,
- width: 100
- },
- {
- header: gettext('Active'),
- width: 60,
- dataIndex: 'active',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comments',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
-
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/network?type=' +
- me.bridgeType
- });
-
- me.store.load();
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- me.nodename = undefined;
-
- me.callParent();
-
- me.setNodename(nodename);
- }
-});
-
-Ext.define('PVE.form.PCISelector', {
- extend: 'Proxmox.form.ComboGrid',
- xtype: 'pvePCISelector',
-
- store: {
- fields: [ 'id','vendor_name', 'device_name', 'vendor', 'device', 'iommugroup', 'mdev' ],
- filterOnLoad: true,
- sorters: [
- {
- property : 'id',
- direction: 'ASC'
- }
- ]
- },
-
- autoSelect: false,
- valueField: 'id',
- displayField: 'id',
-
- // can contain a load callback for the store
- // useful to determine the state of the IOMMU
- onLoadCallBack: undefined,
-
- listConfig: {
- width: 800,
- columns: [
- {
- header: 'ID',
- dataIndex: 'id',
- width: 80
- },
- {
- header: gettext('IOMMU Group'),
- dataIndex: 'iommugroup',
- width: 50
- },
- {
- header: gettext('Vendor'),
- dataIndex: 'vendor_name',
- flex: 2
- },
- {
- header: gettext('Device'),
- dataIndex: 'device_name',
- flex: 6
- },
- {
- header: gettext('Mediated Devices'),
- dataIndex: 'mdev',
- flex: 1,
- renderer: function(val) {
- return Proxmox.Utils.format_boolean(!!val);
- }
- }
- ]
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
-
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/hardware/pci'
- });
-
- me.store.load();
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- me.nodename = undefined;
-
- me.callParent();
-
- if (me.onLoadCallBack !== undefined) {
- me.mon(me.getStore(), 'load', me.onLoadCallBack);
- }
-
- me.setNodename(nodename);
- }
-});
-
-Ext.define('PVE.form.MDevSelector', {
- extend: 'Proxmox.form.ComboGrid',
- xtype: 'pveMDevSelector',
-
- store: {
- fields: [ 'type','available', 'description' ],
- filterOnLoad: true,
- sorters: [
- {
- property : 'type',
- direction: 'ASC'
- }
- ]
- },
- autoSelect: false,
- valueField: 'type',
- displayField: 'type',
- listConfig: {
- columns: [
- {
- header: gettext('Type'),
- dataIndex: 'type',
- flex: 1
- },
- {
- header: gettext('Available'),
- dataIndex: 'available',
- width: 80
- },
- {
- header: gettext('Description'),
- dataIndex: 'description',
- flex: 1,
- renderer: function(value) {
- if (!value) {
- return '';
- }
-
- return value.split('\n').join(' ');
- }
- }
- ]
- },
-
- setPciID: function(pciid, force) {
- var me = this;
-
- if (!force && (!pciid || (me.pciid === pciid))) {
- return;
- }
-
- me.pciid = pciid;
- me.updateProxy();
- },
-
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
- me.updateProxy();
- },
-
- updateProxy: function() {
- var me = this;
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/hardware/pci/' + me.pciid + '/mdev'
- });
- me.store.load();
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw 'no node name specified';
- }
-
- me.callParent();
-
- if (me.pciid) {
- me.setPciID(me.pciid, true);
- }
- }
-});
-
-Ext.define('PVE.form.SecurityGroupsSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveSecurityGroupsSelector'],
-
- valueField: 'group',
- displayField: 'group',
- initComponent: function() {
- var me = this;
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: true,
- fields: [ 'group', 'comment' ],
- idProperty: 'group',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/firewall/groups"
- },
- sorters: {
- property: 'group',
- order: 'DESC'
- }
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: gettext('Security Group'),
- dataIndex: 'group',
- hideable: false,
- width: 100
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.form.IPRefSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveIPRefSelector'],
-
- base_url: undefined,
-
- preferredValue: '', // hack: else Form sets dirty flag?
-
- ref_type: undefined, // undefined = any [undefined, 'ipset' or 'alias']
-
- valueField: 'ref',
- displayField: 'ref',
-
- initComponent: function() {
- var me = this;
-
- if (!me.base_url) {
- throw "no base_url specified";
- }
-
- var url = "/api2/json" + me.base_url;
- if (me.ref_type) {
- url += "?type=" + me.ref_type;
- }
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: true,
- fields: [ 'type', 'name', 'ref', 'comment' ],
- idProperty: 'ref',
- proxy: {
- type: 'proxmox',
- url: url
- },
- sorters: {
- property: 'ref',
- order: 'DESC'
- }
- });
-
- var disable_query_for_ips = function(f, value) {
- if (value === null ||
- value.match(/^\d/)) { // IP address starts with \d
- f.queryDelay = 9999999999; // hack: disbale with long delay
- } else {
- f.queryDelay = 10;
- }
- };
-
- var columns = [];
-
- if (!me.ref_type) {
- columns.push({
- header: gettext('Type'),
- dataIndex: 'type',
- hideable: false,
- width: 60
- });
- }
-
- columns.push(
- {
- header: gettext('Name'),
- dataIndex: 'ref',
- hideable: false,
- width: 140
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- );
-
- Ext.apply(me, {
- store: store,
- listConfig: { columns: columns }
- });
-
- me.on('change', disable_query_for_ips);
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.form.IPProtocolSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveIPProtocolSelector'],
- valueField: 'p',
- displayField: 'p',
- listConfig: {
- columns: [
- {
- header: gettext('Protocol'),
- dataIndex: 'p',
- hideable: false,
- sortable: false,
- width: 100
- },
- {
- header: gettext('Number'),
- dataIndex: 'n',
- hideable: false,
- sortable: false,
- width: 50
- },
- {
- header: gettext('Description'),
- dataIndex: 'd',
- hideable: false,
- sortable: false,
- flex: 1
- }
- ]
- },
- store: {
- fields: [ 'p', 'd', 'n'],
- data: [
- { p: 'tcp', n: 6, d: 'Transmission Control Protocol' },
- { p: 'udp', n: 17, d: 'User Datagram Protocol' },
- { p: 'icmp', n: 1, d: 'Internet Control Message Protocol' },
- { p: 'igmp', n: 2, d: 'Internet Group Management' },
- { p: 'ggp', n: 3, d: 'gateway-gateway protocol' },
- { p: 'ipencap', n: 4, d: 'IP encapsulated in IP' },
- { p: 'st', n: 5, d: 'ST datagram mode' },
- { p: 'egp', n: 8, d: 'exterior gateway protocol' },
- { p: 'igp', n: 9, d: 'any private interior gateway (Cisco)' },
- { p: 'pup', n: 12, d: 'PARC universal packet protocol' },
- { p: 'hmp', n: 20, d: 'host monitoring protocol' },
- { p: 'xns-idp', n: 22, d: 'Xerox NS IDP' },
- { p: 'rdp', n: 27, d: '"reliable datagram" protocol' },
- { p: 'iso-tp4', n: 29, d: 'ISO Transport Protocol class 4 [RFC905]' },
- { p: 'dccp', n: 33, d: 'Datagram Congestion Control Prot. [RFC4340]' },
- { p: 'xtp', n: 36, d: 'Xpress Transfer Protocol' },
- { p: 'ddp', n: 37, d: 'Datagram Delivery Protocol' },
- { p: 'idpr-cmtp', n: 38, d: 'IDPR Control Message Transport' },
- { p: 'ipv6', n: 41, d: 'Internet Protocol, version 6' },
- { p: 'ipv6-route', n: 43, d: 'Routing Header for IPv6' },
- { p: 'ipv6-frag', n: 44, d: 'Fragment Header for IPv6' },
- { p: 'idrp', n: 45, d: 'Inter-Domain Routing Protocol' },
- { p: 'rsvp', n: 46, d: 'Reservation Protocol' },
- { p: 'gre', n: 47, d: 'General Routing Encapsulation' },
- { p: 'esp', n: 50, d: 'Encap Security Payload [RFC2406]' },
- { p: 'ah', n: 51, d: 'Authentication Header [RFC2402]' },
- { p: 'skip', n: 57, d: 'SKIP' },
- { p: 'ipv6-icmp', n: 58, d: 'ICMP for IPv6' },
- { p: 'ipv6-nonxt', n: 59, d: 'No Next Header for IPv6' },
- { p: 'ipv6-opts', n: 60, d: 'Destination Options for IPv6' },
- { p: 'vmtp', n: 81, d: 'Versatile Message Transport' },
- { p: 'eigrp', n: 88, d: 'Enhanced Interior Routing Protocol (Cisco)' },
- { p: 'ospf', n: 89, d: 'Open Shortest Path First IGP' },
- { p: 'ax.25', n: 93, d: 'AX.25 frames' },
- { p: 'ipip', n: 94, d: 'IP-within-IP Encapsulation Protocol' },
- { p: 'etherip', n: 97, d: 'Ethernet-within-IP Encapsulation [RFC3378]' },
- { p: 'encap', n: 98, d: 'Yet Another IP encapsulation [RFC1241]' },
- { p: 'pim', n: 103, d: 'Protocol Independent Multicast' },
- { p: 'ipcomp', n: 108, d: 'IP Payload Compression Protocol' },
- { p: 'vrrp', n: 112, d: 'Virtual Router Redundancy Protocol [RFC5798]' },
- { p: 'l2tp', n: 115, d: 'Layer Two Tunneling Protocol [RFC2661]' },
- { p: 'isis', n: 124, d: 'IS-IS over IPv4' },
- { p: 'sctp', n: 132, d: 'Stream Control Transmission Protocol' },
- { p: 'fc', n: 133, d: 'Fibre Channel' },
- { p: 'mobility-header', n: 135, d: 'Mobility Support for IPv6 [RFC3775]' },
- { p: 'udplite', n: 136, d: 'UDP-Lite [RFC3828]' },
- { p: 'mpls-in-ip', n: 137, d: 'MPLS-in-IP [RFC4023]' },
- { p: 'hip', n: 139, d: 'Host Identity Protocol' },
- { p: 'shim6', n: 140, d: 'Shim6 Protocol [RFC5533]' },
- { p: 'wesp', n: 141, d: 'Wrapped Encapsulating Security Payload' },
- { p: 'rohc', n: 142, d: 'Robust Header Compression' }
- ]
- }
-});
-Ext.define('PVE.form.CPUModelSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.CPUModelSelector'],
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText + ' (kvm64)'],
- ['486', '486'],
- ['athlon', 'athlon'],
- ['core2duo', 'core2duo'],
- ['coreduo', 'coreduo'],
- ['kvm32', 'kvm32'],
- ['kvm64', 'kvm64'],
- ['pentium', 'pentium'],
- ['pentium2', 'pentium2'],
- ['pentium3', 'pentium3'],
- ['phenom', 'phenom'],
- ['qemu32', 'qemu32'],
- ['qemu64', 'qemu64'],
- ['Conroe', 'Conroe'],
- ['Penryn', 'Penryn'],
- ['Nehalem', 'Nehalem'],
- ['Westmere', 'Westmere'],
- ['SandyBridge', 'SandyBridge'],
- ['IvyBridge', 'IvyBridge'],
- ['Haswell', 'Haswell'],
- ['Haswell-noTSX','Haswell-noTSX'],
- ['Broadwell', 'Broadwell'],
- ['Broadwell-noTSX','Broadwell-noTSX'],
- ['Skylake-Client','Skylake-Client'],
- ['Opteron_G1', 'Opteron_G1'],
- ['Opteron_G2', 'Opteron_G2'],
- ['Opteron_G3', 'Opteron_G3'],
- ['Opteron_G4', 'Opteron_G4'],
- ['Opteron_G5', 'Opteron_G5'],
- ['EPYC', 'EPYC'],
- ['host', 'host']
-
- ]
-});
-Ext.define('PVE.form.VNCKeyboardSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.VNCKeyboardSelector'],
- comboItems: PVE.Utils.kvm_keymap_array()
-});
-Ext.define('PVE.form.CacheTypeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.CacheTypeSelector'],
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText + " (" + gettext('No cache') + ")"],
- ['directsync', 'Direct sync'],
- ['writethrough', 'Write through'],
- ['writeback', 'Write back'],
- ['unsafe', 'Write back (' + gettext('unsafe') + ')'],
- ['none', gettext('No cache')]
- ]
-});
-Ext.define('PVE.form.SnapshotSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.PVE.form.SnapshotSelector'],
-
- valueField: 'name',
- displayField: 'name',
-
- loadStore: function(nodename, vmid) {
- var me = this;
-
- if (!nodename) {
- return;
- }
-
- me.nodename = nodename;
-
- if (!vmid) {
- return;
- }
-
- me.vmid = vmid;
-
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/' + me.guestType + '/' + me.vmid +'/snapshot'
- });
-
- me.store.load();
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.guestType) {
- throw "no guest type specified";
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'name'],
- filterOnLoad: true
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: gettext('Snapshot'),
- dataIndex: 'name',
- hideable: false,
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
-
- me.loadStore(me.nodename, me.vmid);
- }
-});
-Ext.define('PVE.form.ContentTypeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveContentTypeSelector'],
-
- cts: undefined,
-
- initComponent: function() {
- var me = this;
-
- me.comboItems = [];
-
- if (me.cts === undefined) {
- me.cts = ['images', 'iso', 'vztmpl', 'backup', 'rootdir', 'snippets'];
- }
-
- Ext.Array.each(me.cts, function(ct) {
- me.comboItems.push([ct, PVE.Utils.format_content_types(ct)]);
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.HotplugFeatureSelector', {
- extend: 'Ext.form.CheckboxGroup',
- alias: 'widget.pveHotplugFeatureSelector',
-
- columns: 1,
- vertical: true,
-
- defaults: {
- name: 'hotplug',
- submitValue: false
- },
- items: [
- {
- boxLabel: gettext('Disk'),
- inputValue: 'disk',
- checked: true
- },
- {
- boxLabel: gettext('Network'),
- inputValue: 'network',
- checked: true
- },
- {
- boxLabel: 'USB',
- inputValue: 'usb',
- checked: true
- },
- {
- boxLabel: gettext('Memory'),
- inputValue: 'memory'
- },
- {
- boxLabel: gettext('CPU'),
- inputValue: 'cpu'
- }
- ],
-
- setValue: function(value) {
- var me = this;
- var newVal = [];
- if (value === '1') {
- newVal = ['disk', 'network', 'usb'];
- } else if (value !== '0') {
- newVal = value.split(',');
- }
- me.callParent([{ hotplug: newVal }]);
- },
-
- // overide framework function to
- // assemble the hotplug value
- getSubmitData: function() {
- var me = this,
- boxes = me.getBoxes(),
- data = [];
- Ext.Array.forEach(boxes, function(box){
- if (box.getValue()) {
- data.push(box.inputValue);
- }
- });
-
- /* because above is hotplug an array */
- /*jslint confusion: true*/
- if (data.length === 0) {
- return { 'hotplug':'0' };
- } else {
- return { 'hotplug': data.join(',') };
- }
- }
-
-});
-Ext.define('PVE.form.AgentFeatureSelector', {
- extend: 'Proxmox.panel.InputPanel',
- alias: ['widget.pveAgentFeatureSelector'],
-
- initComponent: function() {
- var me = this;
- me.items= [
- {
- xtype: 'proxmoxcheckbox',
- boxLabel: gettext('Qemu Agent'),
- name: 'enabled',
- uncheckedValue: 0,
- listeners: {
- change: function(f, value, old) {
- var gtcb = me.down('proxmoxcheckbox[name=fstrim_cloned_disks]');
- if (value) {
- gtcb.setDisabled(false);
- } else {
- gtcb.setDisabled(true);
- }
- }
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- boxLabel: gettext('Run guest-trim after clone disk'),
- name: 'fstrim_cloned_disks',
- disabled: true
- }
- ];
- me.callParent();
- },
-
- onGetValues: function(values) {
- var agentstr = PVE.Parser.printPropertyString(values, 'enabled');
- return { agent: agentstr };
- },
-
- setValues: function(values) {
- var agent = values.agent || '';
- var res = PVE.Parser.parsePropertyString(agent, 'enabled');
- this.callParent([res]);
- }
-});
-Ext.define('PVE.form.iScsiProviderSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveiScsiProviderSelector'],
- comboItems: [
- ['comstar', 'Comstar'],
- [ 'istgt', 'istgt'],
- [ 'iet', 'IET'],
- [ 'LIO', 'LIO']
- ]
-});
-Ext.define('PVE.form.DayOfWeekSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveDayOfWeekSelector'],
- comboItems:[],
- initComponent: function(){
- var me = this;
- me.comboItems = [
- ['mon', Ext.util.Format.htmlDecode(Ext.Date.dayNames[1])],
- ['tue', Ext.util.Format.htmlDecode(Ext.Date.dayNames[2])],
- ['wed', Ext.util.Format.htmlDecode(Ext.Date.dayNames[3])],
- ['thu', Ext.util.Format.htmlDecode(Ext.Date.dayNames[4])],
- ['fri', Ext.util.Format.htmlDecode(Ext.Date.dayNames[5])],
- ['sat', Ext.util.Format.htmlDecode(Ext.Date.dayNames[6])],
- ['sun', Ext.util.Format.htmlDecode(Ext.Date.dayNames[0])]
- ];
- this.callParent();
- }
-});
-Ext.define('PVE.form.BackupModeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveBackupModeSelector'],
- comboItems: [
- ['snapshot', gettext('Snapshot')],
- ['suspend', gettext('Suspend')],
- ['stop', gettext('Stop')]
- ]
-});
-Ext.define('PVE.form.ScsiHwSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveScsiHwSelector'],
- comboItems: [
- ['__default__', PVE.Utils.render_scsihw('')],
- ['lsi', PVE.Utils.render_scsihw('lsi')],
- ['lsi53c810', PVE.Utils.render_scsihw('lsi53c810')],
- ['megasas', PVE.Utils.render_scsihw('megasas')],
- ['virtio-scsi-pci', PVE.Utils.render_scsihw('virtio-scsi-pci')],
- ['virtio-scsi-single', PVE.Utils.render_scsihw('virtio-scsi-single')],
- ['pvscsi', PVE.Utils.render_scsihw('pvscsi')]
- ]
-});
-Ext.define('PVE.form.FirewallPolicySelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveFirewallPolicySelector'],
- comboItems: [
- ['ACCEPT', 'ACCEPT'],
- ['REJECT', 'REJECT'],
- [ 'DROP', 'DROP']
- ]
-});
-/*
- * This is a global search field
- * it loads the /cluster/resources on focus
- * and displays the result in a floating grid
- *
- * it filters and sorts the objects by the algorithm in
- * the customFilter function
- *
- * also it does accept key up/down and enter for input
- * and it opens to ctrl+shift+f and ctrl+space
- */
-Ext.define('PVE.form.GlobalSearchField', {
- extend: 'Ext.form.field.Text',
- alias: 'widget.pveGlobalSearchField',
-
- emptyText: gettext('Search'),
- enableKeyEvents: true,
- selectOnFocus: true,
- padding: '0 5 0 5',
-
- grid: {
- xtype: 'gridpanel',
- focusOnToFront: false,
- floating: true,
- emptyText: Proxmox.Utils.noneText,
- width: 600,
- height: 400,
- scrollable: {
- xtype: 'scroller',
- y: true,
- x:false
- },
- store: {
- model: 'PVEResources',
- proxy:{
- type: 'proxmox',
- url: '/api2/extjs/cluster/resources'
- }
- },
- plugins: {
- ptype: 'bufferedrenderer',
- trailingBufferZone: 20,
- leadingBufferZone: 20
- },
-
- hideMe: function() {
- var me = this;
- if (typeof me.ctxMenu !== 'undefined' && me.ctxMenu.isVisible()) {
- return;
- }
- me.hasFocus = false;
- if (!me.textfield.hasFocus) {
- me.hide();
- }
- },
-
- setFocus: function() {
- var me = this;
- me.hasFocus = true;
- },
-
- listeners: {
- rowclick: function(grid, record) {
- var me = this;
- me.textfield.selectAndHide(record.id);
- },
- itemcontextmenu: function(v, record, item, index, event) {
- var me = this;
- me.ctxMenu = PVE.Utils.createCmdMenu(v, record, item, index, event);
- },
- /* because of lint */
- focusleave: {
- fn: 'hideMe'
- },
- focusenter: 'setFocus'
- },
-
- columns: [
- {
- text: gettext('Type'),
- dataIndex: 'type',
- width: 100,
- renderer: PVE.Utils.render_resource_type
- },
- {
- text: gettext('Description'),
- flex: 1,
- dataIndex: 'text'
- },
- {
- text: gettext('Node'),
- dataIndex: 'node'
- },
- {
- text: gettext('Pool'),
- dataIndex: 'pool'
- }
- ]
- },
-
- customFilter: function(item) {
- var me = this;
- var match = 0;
- var fieldArr = [];
- var i,j, fields;
-
- // different types of objects have different fields to search
- // for example, a node will never have a pool and vice versa
- switch (item.data.type) {
- case 'pool': fieldArr = ['type', 'pool', 'text']; break;
- case 'node': fieldArr = ['type', 'node', 'text']; break;
- case 'storage': fieldArr = ['type', 'pool', 'node', 'storage']; break;
- default: fieldArr = ['name', 'type', 'node', 'pool', 'vmid'];
- }
- if (me.filterVal === '') {
- item.data.relevance = 0;
- return true;
- }
-
- // all text is case insensitive and each word is
- // searched alone
- // for every partial match, the row gets
- // 1 match point, for every exact match
- // it gets 2 points
- //
- // results gets sorted by points (descending)
- fields = me.filterVal.split(/\s+/);
- for(i = 0; i < fieldArr.length; i++) {
- var v = item.data[fieldArr[i]];
- if (v !== undefined) {
- v = v.toString().toLowerCase();
- for(j = 0; j < fields.length; j++) {
- if (v.indexOf(fields[j]) !== -1) {
- match++;
- if(v === fields[j]) {
- match++;
- }
- }
- }
- }
- }
- // give the row the 'relevance' value
- item.data.relevance = match;
- return (match > 0);
- },
-
- updateFilter: function(field, newValue, oldValue) {
- var me = this;
- // parse input and filter store,
- // show grid
- me.grid.store.filterVal = newValue.toLowerCase().trim();
- me.grid.store.clearFilter(true);
- me.grid.store.filterBy(me.customFilter);
- me.grid.getSelectionModel().select(0);
- },
-
- selectAndHide: function(id) {
- var me = this;
- me.tree.selectById(id);
- me.grid.hide();
- me.setValue('');
- me.blur();
- },
-
- onKey: function(field, e) {
- var me = this;
- var key = e.getKey();
-
- switch(key) {
- case Ext.event.Event.ENTER:
- // go to first entry if there is one
- if (me.grid.store.getCount() > 0) {
- me.selectAndHide(me.grid.getSelection()[0].data.id);
- }
- break;
- case Ext.event.Event.UP:
- me.grid.getSelectionModel().selectPrevious();
- break;
- case Ext.event.Event.DOWN:
- me.grid.getSelectionModel().selectNext();
- break;
- case Ext.event.Event.ESC:
- me.grid.hide();
- me.blur();
- break;
- }
- },
-
- loadValues: function(field) {
- var me = this;
- var records = [];
-
- me.hasFocus = true;
- me.grid.textfield = me;
- me.grid.store.load();
- me.grid.showBy(me, 'tl-bl');
- },
-
- hideGrid: function() {
- var me = this;
-
- me.hasFocus = false;
- if (!me.grid.hasFocus) {
- me.grid.hide();
- }
- },
-
- listeners: {
- change: {
- fn: 'updateFilter',
- buffer: 250
- },
- specialkey: 'onKey',
- focusenter: 'loadValues',
- focusleave: {
- fn: 'hideGrid',
- delay: 100
- }
- },
-
- toggleFocus: function() {
- var me = this;
- if (!me.hasFocus) {
- me.focus();
- } else {
- me.blur();
- }
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.tree) {
- throw "no tree given";
- }
-
- me.grid = Ext.create(me.grid);
-
- me.callParent();
-
- /*jslint confusion: true*/
- /*because shift is also a function*/
- // bind ctrl+shift+f and ctrl+space
- // to open/close the search
- me.keymap = new Ext.KeyMap({
- target: Ext.get(document),
- binding: [{
- key:'F',
- ctrl: true,
- shift: true,
- fn: me.toggleFocus,
- scope: me
- },{
- key:' ',
- ctrl: true,
- fn: me.toggleFocus,
- scope: me
- }]
- });
-
- // always select first item and
- // sort by relevance after load
- me.mon(me.grid.store, 'load', function() {
- me.grid.getSelectionModel().select(0);
- me.grid.store.sort({
- property: 'relevance',
- direction: 'DESC'
- });
- });
- }
-
-});
-Ext.define('PVE.form.QemuBiosSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveQemuBiosSelector'],
-
- initComponent: function() {
- var me = this;
-
- me.comboItems = [
- ['__default__', PVE.Utils.render_qemu_bios('')],
- ['seabios', PVE.Utils.render_qemu_bios('seabios')],
- ['ovmf', PVE.Utils.render_qemu_bios('ovmf')]
- ];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-/* filter is a javascript builtin, but extjs calls it also filter */
-Ext.define('PVE.form.VMSelector', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.vmselector',
-
- mixins: {
- field: 'Ext.form.field.Field'
- },
-
- allowBlank: true,
- selectAll: false,
- isFormField: true,
-
- plugins: 'gridfilters',
-
- store: {
- model: 'PVEResources',
- autoLoad: true,
- sorters: 'vmid',
- filters: [{
- property: 'type',
- value: /lxc|qemu/
- }]
- },
- columns: [
- {
- header: 'ID',
- dataIndex: 'vmid',
- width: 80,
- filter: {
- type: 'number'
- }
- },
- {
- header: gettext('Node'),
- dataIndex: 'node'
- },
- {
- header: gettext('Status'),
- dataIndex: 'status',
- filter: {
- type: 'list'
- }
- },
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1,
- filter: {
- type: 'string'
- }
- },
- {
- header: gettext('Pool'),
- dataIndex: 'pool',
- filter: {
- type: 'list'
- }
- },
- {
- header: gettext('Type'),
- dataIndex: 'type',
- width: 120,
- renderer: function(value) {
- if (value === 'qemu') {
- return gettext('Virtual Machine');
- } else if (value === 'lxc') {
- return gettext('LXC Container');
- }
-
- return '';
- },
- filter: {
- type: 'list',
- store: {
- data: [
- {id: 'qemu', text: gettext('Virtual Machine')},
- {id: 'lxc', text: gettext('LXC Container')}
- ],
- // due to EXTJS-18711
- // we have to do a static list via a store
- // but to avoid creating an object,
- // we have to have a pseudo un function
- un: function(){}
- }
- }
- },
- {
- header: 'HA ' + gettext('Status'),
- dataIndex: 'hastate',
- flex: 1,
- filter: {
- type: 'list'
- }
- }
- ],
-
- selModel: {
- selType: 'checkboxmodel',
- mode: 'SIMPLE'
- },
-
- checkChangeEvents: [
- 'selectionchange',
- 'change'
- ],
-
- listeners: {
- selectionchange: function() {
- // to trigger validity and error checks
- this.checkChange();
- }
- },
-
- getValue: function() {
- var me = this;
- var sm = me.getSelectionModel();
- var selection = sm.getSelection();
- var values = [];
- var store = me.getStore();
- selection.forEach(function(item) {
- // only add if not filtered
- if (store.findExact('vmid', item.data.vmid) !== -1) {
- values.push(item.data.vmid);
- }
- });
- return values;
- },
-
- setValue: function(value) {
- console.log(value);
- var me = this;
- var sm = me.getSelectionModel();
- if (!Ext.isArray(value)) {
- value = value.split(',');
- }
- var selection = [];
- var store = me.getStore();
-
- value.forEach(function(item) {
- var rec = store.findRecord('vmid',item, 0, false, true, true);
- console.log(store);
-
- if (rec) {
- console.log(rec);
- selection.push(rec);
- }
- });
-
- sm.select(selection);
-
- return me.mixins.field.setValue.call(me, value);
- },
-
- getErrors: function(value) {
- var me = this;
- if (me.allowBlank === false &&
- me.getSelectionModel().getCount() === 0) {
- me.addBodyCls(['x-form-trigger-wrap-default','x-form-trigger-wrap-invalid']);
- return [gettext('No VM selected')];
- }
-
- me.removeBodyCls(['x-form-trigger-wrap-default','x-form-trigger-wrap-invalid']);
- return [];
- },
-
- initComponent: function() {
- var me = this;
-
- me.callParent();
-
- if (me.nodename) {
- me.store.filters.add({
- property: 'node',
- exactMatch: true,
- value: me.nodename
- });
- }
-
- // only show the relevant guests by default
- if (me.action) {
- var statusfilter = '';
- switch (me.action) {
- case 'startall':
- statusfilter = 'stopped';
- break;
- case 'stopall':
- statusfilter = 'running';
- break;
- }
- if (statusfilter !== '') {
- me.store.filters.add({
- property: 'template',
- value: 0
- },{
- id: 'x-gridfilter-status',
- operator: 'in',
- property: 'status',
- value: [statusfilter]
- });
- }
- }
-
- var store = me.getStore();
- var sm = me.getSelectionModel();
-
- if (me.selectAll) {
- me.mon(store,'load', function(){
- me.getSelectionModel().selectAll(false);
- });
- }
- }
-});
-
-
-Ext.define('PVE.form.VMComboSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.vmComboSelector',
-
- valueField: 'vmid',
- displayField: 'vmid',
-
- autoSelect: false,
- editable: true,
- anyMatch: true,
- forceSelection: true,
-
- store: {
- model: 'PVEResources',
- autoLoad: true,
- sorters: 'vmid',
- filters: [{
- property: 'type',
- value: /lxc|qemu/
- }]
- },
-
- listConfig: {
- width: 600,
- plugins: 'gridfilters',
- columns: [
- {
- header: 'ID',
- dataIndex: 'vmid',
- width: 80,
- filter: {
- type: 'number'
- }
- },
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1,
- filter: {
- type: 'string'
- }
- },
- {
- header: gettext('Node'),
- dataIndex: 'node'
- },
- {
- header: gettext('Status'),
- dataIndex: 'status',
- filter: {
- type: 'list'
- }
- },
- {
- header: gettext('Pool'),
- dataIndex: 'pool',
- hidden: true,
- filter: {
- type: 'list'
- }
- },
- {
- header: gettext('Type'),
- dataIndex: 'type',
- width: 120,
- renderer: function(value) {
- if (value === 'qemu') {
- return gettext('Virtual Machine');
- } else if (value === 'lxc') {
- return gettext('LXC Container');
- }
-
- return '';
- },
- filter: {
- type: 'list',
- store: {
- data: [
- {id: 'qemu', text: gettext('Virtual Machine')},
- {id: 'lxc', text: gettext('LXC Container')}
- ],
- un: function(){} // due to EXTJS-18711
- }
- }
- },
- {
- header: 'HA ' + gettext('Status'),
- dataIndex: 'hastate',
- hidden: true,
- flex: 1,
- filter: {
- type: 'list'
- }
- }
- ]
- }
-});
-Ext.define('PVE.form.USBSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveUSBSelector'],
- allowBlank: false,
- autoSelect: false,
- displayField: 'usbid',
- valueField: 'usbid',
- editable: true,
-
- getUSBValue: function() {
- var me = this;
- var rec = me.store.findRecord('usbid', me.value);
- var val = 'host='+ me.value;
- if (rec && rec.data.speed === "5000") {
- val = 'host=' + me.value + ",usb3=1";
- }
- return val;
- },
-
- validator: function(value) {
- var me = this;
- if (me.type === 'device') {
- return (/^[a-f0-9]{4}\:[a-f0-9]{4}$/i).test(value);
- } else if (me.type === 'port') {
- return (/^[0-9]+\-[0-9]+(\.[0-9]+)*$/).test(value);
- }
- return false;
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
-
- if (!nodename) {
- throw "no nodename specified";
- }
-
- if (me.type !== 'device' && me.type !== 'port') {
- throw "no valid type specified";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-usb-' + me.type,
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/scan/usb"
- },
- filters: [
- function (item) {
- return !!item.data.usbpath && !!item.data.prodid && item.data['class'] != 9;
- }
- ]
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: (me.type === 'device')?gettext('Device'):gettext('Port'),
- sortable: true,
- dataIndex: 'usbid',
- width: 80
- },
- {
- header: gettext('Manufacturer'),
- sortable: true,
- dataIndex: 'manufacturer',
- width: 100
- },
- {
- header: gettext('Product'),
- sortable: true,
- dataIndex: 'product',
- flex: 1
- },
- {
- header: gettext('Speed'),
- width: 70,
- sortable: true,
- dataIndex: 'speed',
- renderer: function(value) {
- if (value === "5000") {
- return "USB 3.0";
- } else if (value === "480") {
- return "USB 2.0";
- } else {
- return "USB 1.x";
- }
- }
- }
- ]
- }
- });
-
- me.callParent();
-
- store.load();
- }
-
-}, function() {
-
- Ext.define('pve-usb-device', {
- extend: 'Ext.data.Model',
- fields: [
- {
- name: 'usbid',
- convert: function(val, data) {
- if (val) {
- return val;
- }
- return data.get('vendid') + ':' + data.get('prodid');
- }
- },
- 'speed', 'product', 'manufacturer', 'vendid', 'prodid', 'usbpath',
- { name: 'port' , type: 'number' },
- { name: 'level' , type: 'number' },
- { name: 'class' , type: 'number' },
- { name: 'devnum' , type: 'number' },
- { name: 'busnum' , type: 'number' }
- ]
- });
-
- Ext.define('pve-usb-port', {
- extend: 'Ext.data.Model',
- fields: [
- {
- name: 'usbid',
- convert: function(val,data) {
- if (val) {
- return val;
- }
- return data.get('busnum') + '-' + data.get('usbpath');
- }
- },
- 'speed', 'product', 'manufacturer', 'vendid', 'prodid', 'usbpath',
- { name: 'port' , type: 'number' },
- { name: 'level' , type: 'number' },
- { name: 'class' , type: 'number' },
- { name: 'devnum' , type: 'number' },
- { name: 'busnum' , type: 'number' }
- ]
- });
-});
-Ext.define('PVE.form.CalendarEvent', {
- extend: 'Ext.form.field.ComboBox',
- xtype: 'pveCalendarEvent',
-
- editable: true,
-
- valueField: 'value',
- displayField: 'text',
- queryMode: 'local',
-
- store: {
- field: [ 'value', 'text'],
- data: [
- { value: '*/30', text: Ext.String.format(gettext("Every {0} minutes"), 30) },
- { value: '*/2:00', text: gettext("Every two hours")},
- { value: '2,22:30', text: gettext("Every day") + " 02:30, 22:30"},
- { value: 'mon..fri', text: gettext("Monday to Friday") + " 00:00"},
- { value: 'mon..fri */1:00', text: gettext("Monday to Friday") + ': ' + gettext("hourly")},
- { value: 'sun 01:00', text: gettext("Sunday") + " 01:00"}
- ]
- },
-
- tpl: [
- ''
- ],
-
- displayTpl: [
- '',
- '{value}',
- ' '
- ]
-
-});
-Ext.define('PVE.form.CephPoolSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveCephPoolSelector',
-
- allowBlank: false,
- valueField: 'pool_name',
- displayField: 'pool_name',
- editable: false,
- queryMode: 'local',
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: ['name'],
- sorters: 'name',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/ceph/pools'
- }
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- store.load({
- callback: function(rec, op, success){
- if (success && rec.length > 0) {
- me.select(rec[0]);
- }
- }
- });
- }
-
-});
-Ext.define('PVE.form.PermPathSelector', {
- extend: 'Ext.form.field.ComboBox',
- xtype: 'pvePermPathSelector',
-
- valueField: 'value',
- displayField: 'value',
- typeAhead: true,
- queryMode: 'local',
- store: {
- type: 'pvePermPath'
- }
-});
-/* This class defines the "Tasks" tab of the bottom status panel
- * Tasks are jobs with a start, end and log output
- */
-
-Ext.define('PVE.dc.Tasks', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveClusterTasks'],
-
- initComponent : function() {
- var me = this;
-
- var taskstore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'pve-cluster-tasks',
- model: 'proxmox-tasks',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/tasks'
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: taskstore,
- sortAfterUpdate: true,
- appendAtStart: true,
- sorters: [
- {
- property : 'pid',
- direction: 'DESC'
- },
- {
- property : 'starttime',
- direction: 'DESC'
- }
- ]
-
- });
-
- var run_task_viewer = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: rec.data.upid
- });
- win.show();
- };
-
- Ext.apply(me, {
- store: store,
- stateful: false,
-
- viewConfig: {
- trackOver: false,
- stripeRows: true, // does not work with getRowClass()
-
- getRowClass: function(record, index) {
- var status = record.get('status');
-
- if (status && status != 'OK') {
- return "proxmox-invalid-row";
- }
- }
- },
- sortableColumns: false,
- columns: [
- {
- header: gettext("Start Time"),
- dataIndex: 'starttime',
- width: 150,
- renderer: function(value) {
- return Ext.Date.format(value, "M d H:i:s");
- }
- },
- {
- header: gettext("End Time"),
- dataIndex: 'endtime',
- width: 150,
- renderer: function(value, metaData, record) {
- if (record.data.pid) {
- if (record.data.type == "vncproxy" ||
- record.data.type == "vncshell" ||
- record.data.type == "spiceproxy") {
- metaData.tdCls = "x-grid-row-console";
- } else {
- metaData.tdCls = "x-grid-row-loading";
- }
- return "";
- }
- return Ext.Date.format(value, "M d H:i:s");
- }
- },
- {
- header: gettext("Node"),
- dataIndex: 'node',
- width: 100
- },
- {
- header: gettext("User name"),
- dataIndex: 'user',
- width: 150
- },
- {
- header: gettext("Description"),
- dataIndex: 'upid',
- flex: 1,
- renderer: Proxmox.Utils.render_upid
- },
- {
- header: gettext("Status"),
- dataIndex: 'status',
- width: 200,
- renderer: function(value, metaData, record) {
- if (record.data.pid) {
- if (record.data.type != "vncproxy") {
- metaData.tdCls = "x-grid-row-loading";
- }
- return "";
- }
- if (value == 'OK') {
- return 'OK';
- }
- // metaData.attr = 'style="color:red;"';
- return Proxmox.Utils.errorText + ': ' + value;
- }
- }
- ],
- listeners: {
- itemdblclick: run_task_viewer,
- show: taskstore.startUpdate,
- destroy: taskstore.stopUpdate
- }
- });
-
- me.callParent();
- }
-});
-/* This class defines the "Cluster log" tab of the bottom status panel
- * A log entry is a timestamp associated with an action on a cluster
- */
-
-Ext.define('PVE.dc.Log', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveClusterLog'],
-
- initComponent : function() {
- var me = this;
-
- var logstore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'pve-cluster-log',
- model: 'proxmox-cluster-log',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/log'
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: logstore,
- appendAtStart: true
- });
-
- Ext.apply(me, {
- store: store,
- stateful: false,
-
- viewConfig: {
- trackOver: false,
- stripeRows: true,
-
- getRowClass: function(record, index) {
- var pri = record.get('pri');
-
- if (pri && pri <= 3) {
- return "proxmox-invalid-row";
- }
- }
- },
- sortableColumns: false,
- columns: [
- {
- header: gettext("Time"),
- dataIndex: 'time',
- width: 150,
- renderer: function(value) {
- return Ext.Date.format(value, "M d H:i:s");
- }
- },
- {
- header: gettext("Node"),
- dataIndex: 'node',
- width: 150
- },
- {
- header: gettext("Service"),
- dataIndex: 'tag',
- width: 100
- },
- {
- header: "PID",
- dataIndex: 'pid',
- width: 100
- },
- {
- header: gettext("User name"),
- dataIndex: 'user',
- width: 150
- },
- {
- header: gettext("Severity"),
- dataIndex: 'pri',
- renderer: PVE.Utils.render_serverity,
- width: 100
- },
- {
- header: gettext("Message"),
- dataIndex: 'msg',
- flex: 1
- }
- ],
- listeners: {
- activate: logstore.startUpdate,
- deactivate: logstore.stopUpdate,
- destroy: logstore.stopUpdate
- }
- });
-
- me.callParent();
- }
-});
-/*
- * This class describes the bottom panel
- */
-Ext.define('PVE.panel.StatusPanel', {
- extend: 'Ext.tab.Panel',
- alias: 'widget.pveStatusPanel',
-
-
- //title: "Logs",
- //tabPosition: 'bottom',
-
- initComponent: function() {
- var me = this;
-
- var stateid = 'ltab';
- var sp = Ext.state.Manager.getProvider();
-
- var state = sp.get(stateid);
- if (state && state.value) {
- me.activeTab = state.value;
- }
-
- Ext.apply(me, {
- listeners: {
- tabchange: function() {
- var atab = me.getActiveTab().itemId;
- var state = { value: atab };
- sp.set(stateid, state);
- }
- },
- items: [
- {
- itemId: 'tasks',
- title: gettext('Tasks'),
- xtype: 'pveClusterTasks'
- },
- {
- itemId: 'clog',
- title: gettext('Cluster log'),
- xtype: 'pveClusterLog'
- }
- ]
- });
-
- me.callParent();
-
- me.items.get(0).fireEvent('show', me.items.get(0));
-
- var statechange = function(sp, key, state) {
- if (key === stateid) {
- var atab = me.getActiveTab().itemId;
- var ntab = state.value;
- if (state && ntab && (atab != ntab)) {
- me.setActiveTab(ntab);
- }
- }
- };
-
- sp.on('statechange', statechange);
- me.on('destroy', function() {
- sp.un('statechange', statechange);
- });
-
- }
-});
-Ext.define('PVE.panel.StatusView', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveStatusView',
-
- layout: {
- type: 'column'
- },
-
- title: gettext('Status'),
-
- getRecordValue: function(key, store) {
- if (!key) {
- throw "no key given";
- }
- var me = this;
-
- if (store === undefined) {
- store = me.getStore();
- }
-
- var rec = store.getById(key);
- if (rec) {
- return rec.data.value;
- }
-
- return '';
- },
-
- fieldRenderer: function(val,max) {
- if (max === undefined) {
- return val;
- }
-
- if (!Ext.isNumeric(max) || max === 1) {
- return PVE.Utils.render_usage(val);
- }
- return PVE.Utils.render_size_usage(val,max);
- },
-
- fieldCalculator: function(used, max) {
- if (!Ext.isNumeric(max) && Ext.isNumeric(used)) {
- return used;
- } else if(!Ext.isNumeric(used)) {
- /* we come here if the field is from a node
- * where the records are not mem and maxmem
- * but mem.used and mem.total
- */
- if (used.used !== undefined &&
- used.total !== undefined) {
- return used.used/used.total;
- }
- }
-
- return used/max;
- },
-
- updateField: function(field) {
- var me = this;
- var text = '';
- var renderer = me.fieldRenderer;
- if (Ext.isFunction(field.renderer)) {
- renderer = field.renderer;
- }
- if (field.multiField === true) {
- field.updateValue(renderer.call(field, me.getStore().getRecord()));
- } else if (field.textField !== undefined) {
- field.updateValue(renderer.call(field, me.getRecordValue(field.textField)));
- } else if(field.valueField !== undefined) {
- var used = me.getRecordValue(field.valueField);
- /*jslint confusion: true*/
- /* string and int */
- var max = field.maxField !== undefined ? me.getRecordValue(field.maxField) : 1;
-
- var calculate = me.fieldCalculator;
-
- if (Ext.isFunction(field.calculate)) {
- calculate = field.calculate;
- }
- field.updateValue(renderer.call(field, used,max), calculate(used,max));
- }
- },
-
- getStore: function() {
- var me = this;
- if (!me.rstore) {
- throw "there is no rstore";
- }
-
- return me.rstore;
- },
-
- updateTitle: function() {
- var me = this;
- me.setTitle(me.getRecordValue('name'));
- },
-
- updateValues: function(store, records, success) {
- if (!success) {
- return; // do not update if store load was not successful
- }
- var me = this;
- var itemsToUpdate = me.query('pveInfoWidget');
-
- itemsToUpdate.forEach(me.updateField, me);
-
- me.updateTitle(store);
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.rstore) {
- throw "no rstore given";
- }
-
- if (!me.title) {
- throw "no title given";
- }
-
- Proxmox.Utils.monStoreErrors(me, me.rstore);
-
- me.callParent();
-
- me.mon(me.rstore, 'load', 'updateValues');
- }
-
-});
-Ext.define('PVE.panel.GuestStatusView', {
- extend: 'PVE.panel.StatusView',
- alias: 'widget.pveGuestStatusView',
- mixins: ['Proxmox.Mixin.CBind'],
-
- height: 300,
-
- cbindData: function (initialConfig) {
- var me = this;
- return {
- isQemu: me.pveSelNode.data.type === 'qemu',
- isLxc: me.pveSelNode.data.type === 'lxc'
- };
- },
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- defaults: {
- xtype: 'pveInfoWidget',
- padding: '2 25'
- },
- items: [
- {
- xtype: 'box',
- height: 20
- },
- {
- itemId: 'status',
- title: gettext('Status'),
- iconCls: 'fa fa-info fa-fw',
- printBar: false,
- multiField: true,
- renderer: function(record) {
- var me = this;
- var text = record.data.status;
- var qmpstatus = record.data.qmpstatus;
- if (qmpstatus && qmpstatus !== record.data.status) {
- text += ' (' + qmpstatus + ')';
- }
- return text;
- }
- },
- {
- itemId: 'hamanaged',
- iconCls: 'fa fa-heartbeat fa-fw',
- title: gettext('HA State'),
- printBar: false,
- textField: 'ha',
- renderer: PVE.Utils.format_ha
- },
- {
- xtype: 'pveInfoWidget',
- itemId: 'node',
- iconCls: 'fa fa-building fa-fw',
- title: gettext('Node'),
- cbind: {
- text: '{pveSelNode.data.node}'
- },
- printBar: false
- },
- {
- xtype: 'box',
- height: 15
- },
- {
- itemId: 'cpu',
- iconCls: 'fa fa-fw pve-itype-icon-processor pve-icon',
- title: gettext('CPU usage'),
- valueField: 'cpu',
- maxField: 'cpus',
- renderer: PVE.Utils.render_cpu_usage,
- // in this specific api call
- // we already have the correct value for the usage
- calculate: Ext.identityFn
- },
- {
- itemId: 'memory',
- iconCls: 'fa fa-fw pve-itype-icon-memory pve-icon',
- title: gettext('Memory usage'),
- valueField: 'mem',
- maxField: 'maxmem'
- },
- {
- itemId: 'swap',
- xtype: 'pveInfoWidget',
- iconCls: 'fa fa-refresh fa-fw',
- title: gettext('SWAP usage'),
- valueField: 'swap',
- maxField: 'maxswap',
- cbind: {
- hidden: '{isQemu}',
- disabled: '{isQemu}'
- }
- },
- {
- itemId: 'rootfs',
- iconCls: 'fa fa-hdd-o fa-fw',
- title: gettext('Bootdisk size'),
- valueField: 'disk',
- maxField: 'maxdisk',
- printBar: false,
- renderer: function(used, max) {
- var me = this;
- me.setPrintBar(used > 0);
- if (used === 0) {
- return PVE.Utils.render_size(max);
- } else {
- return PVE.Utils.render_size_usage(used,max);
- }
- }
- },
- {
- xtype: 'box',
- height: 15
- },
- {
- itemId: 'ips',
- xtype: 'pveAgentIPView',
- cbind: {
- rstore: '{rstore}',
- pveSelNode: '{pveSelNode}',
- hidden: '{isLxc}',
- disabled: '{isLxc}'
- }
- }
- ],
-
- updateTitle: function() {
- var me = this;
- var uptime = me.getRecordValue('uptime');
-
- var text = "";
- if (Number(uptime) > 0) {
- text = " (" + gettext('Uptime') + ': ' + Proxmox.Utils.format_duration_long(uptime)
- + ')';
- }
-
- me.setTitle(me.getRecordValue('name') + text);
- }
-});
-/*
- * This is a running chart widget
- * you add time datapoints to it,
- * and we only show the last x of it
- * used for ceph performance charts
- */
-Ext.define('PVE.widget.RunningChart', {
- extend: 'Ext.container.Container',
- alias: 'widget.pveRunningChart',
-
- layout: {
- type: 'hbox',
- align: 'center'
- },
- items: [
- {
- width: 80,
- xtype: 'box',
- itemId: 'title',
- data: {
- title: ''
- },
- tpl: '{title}: '
- },
- {
- flex: 1,
- xtype: 'cartesian',
- height: '100%',
- itemId: 'chart',
- border: false,
- axes: [
- {
- type: 'numeric',
- position: 'left',
- hidden: true,
- minimum: 0
- },
- {
- type: 'numeric',
- position: 'bottom',
- hidden: true
- }
- ],
-
- store: {
- data: {}
- },
-
- sprites: [{
- id: 'valueSprite',
- type: 'text',
- text: '0 B/s',
- textAlign: 'end',
- textBaseline: 'middle',
- fontSize: 14
- }],
-
- series: [{
- type: 'line',
- xField: 'time',
- yField: 'val',
- fill: 'true',
- colors: ['#cfcfcf'],
- tooltip: {
- trackMouse: true,
- renderer: function( tooltip, record, ctx) {
- var me = this.getChart();
- var date = new Date(record.data.time);
- var value = me.up().renderer(record.data.val);
- tooltip.setHtml(
- me.up().title + ': ' + value + ' ' +
- Ext.Date.format(date, 'H:i:s')
- );
- }
- },
- style: {
- lineWidth: 1.5,
- opacity: 0.60
- },
- marker: {
- opacity: 0,
- scaling: 0.01,
- fx: {
- duration: 200,
- easing: 'easeOut'
- }
- },
- highlightCfg: {
- opacity: 1,
- scaling: 1.5
- }
- }]
- }
- ],
-
- // the renderer for the tooltip and last value,
- // default just the value
- renderer: Ext.identityFn,
-
- // show the last x seconds
- // default is 5 minutes
- timeFrame: 5*60,
-
- addDataPoint: function(value, time) {
- var me = this.chart;
- var panel = me.up();
- var now = new Date();
- var begin = new Date(now.getTime() - (1000*panel.timeFrame));
-
- me.store.add({
- time: time || now.getTime(),
- val: value || 0
- });
-
- // delete all old records when we have 20 times more datapoints
- // than seconds in our timeframe (so even a subsecond graph does
- // not trigger this often)
- //
- // records in the store do not take much space, but like this,
- // we prevent a memory leak when someone has the site open for a long time
- // with minimal graphical glitches
- if (me.store.count() > panel.timeFrame * 20) {
- var oldData = me.store.getData().createFiltered(function(item) {
- return item.data.time < begin.getTime();
- });
-
- me.store.remove(oldData.getRange());
- }
-
- me.timeaxis.setMinimum(begin.getTime());
- me.timeaxis.setMaximum(now.getTime());
- me.valuesprite.setText(panel.renderer(value || 0).toString());
- me.valuesprite.setAttributes({
- x: me.getWidth() - 15,
- y: me.getHeight()/2
- }, true);
- me.redraw();
- },
-
- setTitle: function(title) {
- this.title = title;
- var me = this.getComponent('title');
- me.update({title: title});
- },
-
- initComponent: function(){
- var me = this;
- me.callParent();
-
- if (me.title) {
- me.getComponent('title').update({title: me.title});
- }
- me.chart = me.getComponent('chart');
- me.chart.timeaxis = me.chart.getAxes()[1];
- me.chart.valuesprite = me.chart.getSurface('chart').get('valueSprite');
- if (me.color) {
- me.chart.series[0].setStyle({
- fill: me.color,
- stroke: me.color
- });
- }
- }
-});
-Ext.define('PVE.widget.Info',{
- extend: 'Ext.container.Container',
- alias: 'widget.pveInfoWidget',
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- value: 0,
- maximum: 1,
- printBar: true,
- items: [
- {
- xtype: 'component',
- itemId: 'label',
- data: {
- title: '',
- usage: '',
- iconCls: undefined
- },
- tpl: [
- '',
- '',
- ' ',
- ' ',
- '{title}
{usage}
'
- ]
- },
- {
- height: 2,
- border: 0
- },
- {
- xtype: 'progressbar',
- itemId: 'progress',
- height: 5,
- value: 0,
- animate: true
- }
- ],
-
- warningThreshold: 0.6,
- criticalThreshold: 0.9,
-
- setPrintBar: function(enable) {
- var me = this;
- me.printBar = enable;
- me.getComponent('progress').setVisible(enable);
- },
-
- setIconCls: function(iconCls) {
- var me = this;
- me.getComponent('label').data.iconCls = iconCls;
- },
-
- updateValue: function(text, usage) {
- var me = this;
- var label = me.getComponent('label');
- label.update(Ext.apply(label.data, {title: me.title, usage:text}));
-
- if (usage !== undefined &&
- me.printBar &&
- Ext.isNumeric(usage) &&
- usage >= 0) {
- var progressBar = me.getComponent('progress');
- progressBar.updateProgress(usage, '');
- if (usage > me.criticalThreshold) {
- progressBar.removeCls('warning');
- progressBar.addCls('critical');
- } else if (usage > me.warningThreshold) {
- progressBar.removeCls('critical');
- progressBar.addCls('warning');
- } else {
- progressBar.removeCls('warning');
- progressBar.removeCls('critical');
- }
- }
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.title) {
- throw "no title defined";
- }
-
- me.callParent();
-
- me.getComponent('progress').setVisible(me.printBar);
-
- me.updateValue(me.text, me.value);
- me.setIconCls(me.iconCls);
- }
-
-});
-Ext.define('PVE.panel.TemplateStatusView',{
- extend: 'PVE.panel.StatusView',
- alias: 'widget.pveTemplateStatusView',
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- defaults: {
- xtype: 'pveInfoWidget',
- printBar: false,
- padding: '2 25'
- },
- items: [
- {
- xtype: 'box',
- height: 20
- },
- {
- itemId: 'hamanaged',
- iconCls: 'fa fa-heartbeat fa-fw',
- title: gettext('HA State'),
- printBar: false,
- textField: 'ha',
- renderer: PVE.Utils.format_ha
- },
- {
- itemId: 'node',
- iconCls: 'fa fa-fw fa-building',
- title: gettext('Node')
- },
- {
- xtype: 'box',
- height: 20
- },
- {
- itemId: 'cpus',
- iconCls: 'fa fa-fw pve-itype-icon-processor pve-icon',
- title: gettext('Processors'),
- textField: 'cpus'
- },
- {
- itemId: 'memory',
- iconCls: 'fa fa-fw pve-itype-icon-memory pve-icon',
- title: gettext('Memory'),
- textField: 'maxmem',
- renderer: PVE.Utils.render_size
- },
- {
- itemId: 'swap',
- iconCls: 'fa fa-refresh fa-fw',
- title: gettext('Swap'),
- textField: 'maxswap',
- renderer: PVE.Utils.render_size
- },
- {
- itemId: 'disk',
- iconCls: 'fa fa-hdd-o fa-fw',
- title: gettext('Bootdisk size'),
- textField: 'maxdisk',
- renderer: PVE.Utils.render_size
- },
- {
- xtype: 'box',
- height: 20
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- var name = me.pveSelNode.data.name;
- if (!name) {
- throw "no name specified";
- }
-
- me.title = name;
-
- me.callParent();
- if (me.pveSelNode.data.type !== 'lxc') {
- me.remove(me.getComponent('swap'));
- }
- me.getComponent('node').updateValue(me.pveSelNode.data.node);
- }
-});
-Ext.define('PVE.widget.HealthWidget', {
- extend: 'Ext.Component',
- alias: 'widget.pveHealthWidget',
-
- data: {
- iconCls: PVE.Utils.get_health_icon(undefined, true),
- text: '',
- title: ''
- },
-
- style: {
- 'text-align':'center'
- },
-
- tpl: [
- '{title} ',
- ' ',
- ' ',
- '{text}'
- ],
-
- updateHealth: function(data) {
- var me = this;
- me.update(Ext.apply(me.data, data));
- },
-
- initComponent: function(){
- var me = this;
-
- if (me.title) {
- me.config.data.title = me.title;
- }
-
- me.callParent();
- }
-
-});
-/*global u2f*/
-Ext.define('PVE.window.LoginWindow', {
- extend: 'Ext.window.Window',
-
- controller: {
-
- xclass: 'Ext.app.ViewController',
-
- onLogon: function() {
- var me = this;
-
- var form = this.lookupReference('loginForm');
- var unField = this.lookupReference('usernameField');
- var saveunField = this.lookupReference('saveunField');
- var view = this.getView();
-
- if (!form.isValid()) {
- return;
- }
-
- view.el.mask(gettext('Please wait...'), 'x-mask-loading');
-
- // set or clear username
- var sp = Ext.state.Manager.getProvider();
- if (saveunField.getValue() === true) {
- sp.set(unField.getStateId(), unField.getValue());
- } else {
- sp.clear(unField.getStateId());
- }
- sp.set(saveunField.getStateId(), saveunField.getValue());
-
- form.submit({
- failure: function(f, resp){
- me.failure(resp);
- },
- success: function(f, resp){
- view.el.unmask();
-
- var data = resp.result.data;
- if (Ext.isDefined(data.NeedTFA)) {
- // Store first factor login information first:
- data.LoggedOut = true;
- Proxmox.Utils.setAuthData(data);
-
- if (Ext.isDefined(data.U2FChallenge)) {
- me.perform_u2f(data);
- } else {
- me.perform_otp();
- }
- } else {
- me.success(data);
- }
- }
- });
-
- },
- failure: function(resp) {
- var me = this;
- var view = me.getView();
- view.el.unmask();
- var handler = function() {
- var uf = me.lookupReference('usernameField');
- uf.focus(true, true);
- };
-
- Ext.MessageBox.alert(gettext('Error'),
- gettext("Login failed. Please try again"),
- handler);
- },
- success: function(data) {
- var me = this;
- var view = me.getView();
- var handler = view.handler || Ext.emptyFn;
- handler.call(me, data);
- view.close();
- },
-
- perform_otp: function() {
- var me = this;
- var win = Ext.create('PVE.window.TFALoginWindow', {
- onLogin: function(value) {
- me.finish_tfa(value);
- },
- onCancel: function() {
- Proxmox.LoggedOut = false;
- Proxmox.Utils.authClear();
- me.getView().show();
- }
- });
- win.show();
- },
-
- perform_u2f: function(data) {
- var me = this;
- // Show the message:
- var msg = Ext.Msg.show({
- title: 'U2F: '+gettext('Verification'),
- message: gettext('Please press the button on your U2F Device'),
- buttons: []
- });
- var chlg = data.U2FChallenge;
- var key = {
- version: chlg.version,
- keyHandle: chlg.keyHandle
- };
- u2f.sign(chlg.appId, chlg.challenge, [key], function(res) {
- msg.close();
- if (res.errorCode) {
- Proxmox.Utils.authClear();
- Ext.Msg.alert(gettext('Error'), PVE.Utils.render_u2f_error(res.errorCode));
- return;
- }
- delete res.errorCode;
- me.finish_tfa(JSON.stringify(res));
- });
- },
- finish_tfa: function(res) {
- var me = this;
- var view = me.getView();
- view.el.mask(gettext('Please wait...'), 'x-mask-loading');
- var params = { response: res };
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'POST',
- timeout: 5000, // it'll delay both success & failure
- success: function(resp, opts) {
- view.el.unmask();
- // Fill in what we copy over from the 1st factor:
- var data = resp.result.data;
- data.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
- data.username = Proxmox.UserName;
- // Finish logging in:
- me.success(data);
- },
- failure: function(resp, opts) {
- Proxmox.Utils.authClear();
- me.failure(resp);
- }
- });
- },
-
- control: {
- 'field[name=username]': {
- specialkey: function(f, e) {
- if (e.getKey() === e.ENTER) {
- var pf = this.lookupReference('passwordField');
- if (!pf.getValue()) {
- pf.focus(false);
- }
- }
- }
- },
- 'field[name=lang]': {
- change: function(f, value) {
- var dt = Ext.Date.add(new Date(), Ext.Date.YEAR, 10);
- Ext.util.Cookies.set('PVELangCookie', value, dt);
- this.getView().mask(gettext('Please wait...'), 'x-mask-loading');
- window.location.reload();
- }
- },
- 'button[reference=loginButton]': {
- click: 'onLogon'
- },
- '#': {
- show: function() {
- var sp = Ext.state.Manager.getProvider();
- var checkboxField = this.lookupReference('saveunField');
- var unField = this.lookupReference('usernameField');
-
- var checked = sp.get(checkboxField.getStateId());
- checkboxField.setValue(checked);
-
- if(checked === true) {
- var username = sp.get(unField.getStateId());
- unField.setValue(username);
- var pwField = this.lookupReference('passwordField');
- pwField.focus();
- }
- }
- }
- }
- },
-
- width: 400,
-
- modal: true,
-
- border: false,
-
- draggable: true,
-
- closable: false,
-
- resizable: false,
-
- layout: 'auto',
-
- title: gettext('Proxmox VE Login'),
-
- defaultFocus: 'usernameField',
-
- defaultButton: 'loginButton',
-
- items: [{
- xtype: 'form',
- layout: 'form',
- url: '/api2/extjs/access/ticket',
- reference: 'loginForm',
-
- fieldDefaults: {
- labelAlign: 'right',
- allowBlank: false
- },
-
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('User name'),
- name: 'username',
- itemId: 'usernameField',
- reference: 'usernameField',
- stateId: 'login-username'
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- fieldLabel: gettext('Password'),
- name: 'password',
- reference: 'passwordField'
- },
- {
- xtype: 'pveRealmComboBox',
- name: 'realm'
- },
- {
- xtype: 'proxmoxLanguageSelector',
- fieldLabel: gettext('Language'),
- value: Ext.util.Cookies.get('PVELangCookie') || Proxmox.defaultLang || 'en',
- name: 'lang',
- reference: 'langField',
- submitValue: false
- }
- ],
- buttons: [
- {
- xtype: 'checkbox',
- fieldLabel: gettext('Save User name'),
- name: 'saveusername',
- reference: 'saveunField',
- stateId: 'login-saveusername',
- labelWidth: 'auto',
- labelAlign: 'right',
- submitValue: false
- },
- {
- text: gettext('Login'),
- reference: 'loginButton'
- }
- ]
- }]
- });
-Ext.define('PVE.window.TFALoginWindow', {
- extend: 'Ext.window.Window',
-
- modal: true,
- resizable: false,
- title: 'Two-Factor Authentication',
- layout: 'form',
- defaultButton: 'loginButton',
- defaultFocus: 'otpField',
-
- controller: {
- xclass: 'Ext.app.ViewController',
- login: function() {
- var me = this;
- var view = me.getView();
- view.onLogin(me.lookup('otpField').value);
- view.close();
- },
- cancel: function() {
- var me = this;
- var view = me.getView();
- view.onCancel();
- view.close();
- }
- },
-
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Please enter your OTP verification code:'),
- name: 'otp',
- itemId: 'otpField',
- reference: 'otpField',
- allowBlank: false
- }
- ],
-
- buttons: [
- {
- text: gettext('Login'),
- reference: 'loginButton',
- handler: 'login'
- },
- {
- text: gettext('Cancel'),
- handler: 'cancel'
- }
- ]
-});
-Ext.define('PVE.window.Wizard', {
- extend: 'Ext.window.Window',
-
- activeTitle: '', // used for automated testing
-
- width: 700,
- height: 510,
-
- modal: true,
- border: false,
-
- draggable: true,
- closable: true,
- resizable: false,
-
- layout: 'border',
-
- getValues: function(dirtyOnly) {
- var me = this;
-
- var values = {};
-
- var form = me.down('form').getForm();
-
- form.getFields().each(function(field) {
- if (!field.up('inputpanel') && (!dirtyOnly || field.isDirty())) {
- Proxmox.Utils.assemble_field_data(values, field.getSubmitData());
- }
- });
-
- Ext.Array.each(me.query('inputpanel'), function(panel) {
- Proxmox.Utils.assemble_field_data(values, panel.getValues(dirtyOnly));
- });
-
- return values;
- },
-
- initComponent: function() {
- var me = this;
-
- var tabs = me.items || [];
- delete me.items;
-
- /*
- * Items may have the following functions:
- * validator(): per tab custom validation
- * onSubmit(): submit handler
- * onGetValues(): overwrite getValues results
- */
-
- Ext.Array.each(tabs, function(tab) {
- tab.disabled = true;
- });
- tabs[0].disabled = false;
-
- var maxidx = 0;
- var curidx = 0;
-
- var check_card = function(card) {
- var valid = true;
- var fields = card.query('field, fieldcontainer');
- if (card.isXType('fieldcontainer')) {
- fields.unshift(card);
- }
- Ext.Array.each(fields, function(field) {
- // Note: not all fielcontainer have isValid()
- if (Ext.isFunction(field.isValid) && !field.isValid()) {
- valid = false;
- }
- });
-
- if (Ext.isFunction(card.validator)) {
- return card.validator();
- }
-
- return valid;
- };
-
- var disable_at = function(card) {
- var tp = me.down('#wizcontent');
- var idx = tp.items.indexOf(card);
- for(;idx < tp.items.getCount();idx++) {
- var nc = tp.items.getAt(idx);
- if (nc) {
- nc.disable();
- }
- }
- };
-
- var tabchange = function(tp, newcard, oldcard) {
- if (newcard.onSubmit) {
- me.down('#next').setVisible(false);
- me.down('#submit').setVisible(true);
- } else {
- me.down('#next').setVisible(true);
- me.down('#submit').setVisible(false);
- }
- var valid = check_card(newcard);
- me.down('#next').setDisabled(!valid);
- me.down('#submit').setDisabled(!valid);
- me.down('#back').setDisabled(tp.items.indexOf(newcard) == 0);
-
- var idx = tp.items.indexOf(newcard);
- if (idx > maxidx) {
- maxidx = idx;
- }
- curidx = idx;
-
- var next = idx + 1;
- var ntab = tp.items.getAt(next);
- if (valid && ntab && !newcard.onSubmit) {
- ntab.enable();
- }
- };
-
- if (me.subject && !me.title) {
- me.title = Proxmox.Utils.dialog_title(me.subject, true, false);
- }
-
- var sp = Ext.state.Manager.getProvider();
- var advchecked = sp.get('proxmox-advanced-cb');
-
- Ext.apply(me, {
- items: [
- {
- xtype: 'form',
- region: 'center',
- layout: 'fit',
- border: false,
- margins: '5 5 0 5',
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [{
- itemId: 'wizcontent',
- xtype: 'tabpanel',
- activeItem: 0,
- bodyPadding: 10,
- listeners: {
- afterrender: function(tp) {
- var atab = this.getActiveTab();
- tabchange(tp, atab);
- },
- tabchange: function(tp, newcard, oldcard) {
- tabchange(tp, newcard, oldcard);
- }
- },
- items: tabs
- }]
- }
- ],
- fbar: [
- {
- xtype: 'proxmoxHelpButton',
- itemId: 'help'
- },
- '->',
- {
- xtype: 'proxmoxcheckbox',
- boxLabelAlign: 'before',
- boxLabel: gettext('Advanced'),
- value: advchecked,
- listeners: {
- change: function(cb, val) {
- var tp = me.down('#wizcontent');
- tp.query('inputpanel').forEach(function(ip) {
- ip.setAdvancedVisible(val);
- });
-
- sp.set('proxmox-advanced-cb', val);
- }
- }
- },
- {
- text: gettext('Back'),
- disabled: true,
- itemId: 'back',
- minWidth: 60,
- handler: function() {
- var tp = me.down('#wizcontent');
- var atab = tp.getActiveTab();
- var prev = tp.items.indexOf(atab) - 1;
- if (prev < 0) {
- return;
- }
- var ntab = tp.items.getAt(prev);
- if (ntab) {
- tp.setActiveTab(ntab);
- }
- }
- },
- {
- text: gettext('Next'),
- disabled: true,
- itemId: 'next',
- minWidth: 60,
- handler: function() {
-
- var form = me.down('form').getForm();
-
- var tp = me.down('#wizcontent');
- var atab = tp.getActiveTab();
- if (!check_card(atab)) {
- return;
- }
-
- var next = tp.items.indexOf(atab) + 1;
- var ntab = tp.items.getAt(next);
- if (ntab) {
- ntab.enable();
- tp.setActiveTab(ntab);
- }
-
- }
- },
- {
- text: gettext('Finish'),
- minWidth: 60,
- hidden: true,
- itemId: 'submit',
- handler: function() {
- var tp = me.down('#wizcontent');
- var atab = tp.getActiveTab();
- atab.onSubmit();
- }
- }
- ]
- });
- me.callParent();
-
- Ext.Array.each(me.query('inputpanel'), function(panel) {
- panel.setAdvancedVisible(advchecked);
- });
-
- Ext.Array.each(me.query('field'), function(field) {
- var validcheck = function() {
- var tp = me.down('#wizcontent');
-
- // check tabs from current to the last enabled for validity
- // since we might have changed a validity on a later one
- var i;
- for (i = curidx; i <= maxidx && i < tp.items.getCount(); i++) {
- var tab = tp.items.getAt(i);
- var valid = check_card(tab);
-
- // only set the buttons on the current panel
- if (i === curidx) {
- me.down('#next').setDisabled(!valid);
- me.down('#submit').setDisabled(!valid);
- }
-
- // if a panel is invalid, then disable it and all following,
- // else enable it and go to the next
- var ntab = tp.items.getAt(i + 1);
- if (!valid) {
- disable_at(ntab);
- return;
- } else if (ntab && !tab.onSubmit) {
- ntab.enable();
- }
- }
- };
- field.on('change', validcheck);
- field.on('validitychange', validcheck);
- });
- }
-});
-Ext.define('PVE.window.NotesEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.apply(me, {
- title: gettext('Notes'),
- width: 600,
- height: '400px',
- resizable: true,
- layout: 'fit',
- defaultButton: undefined,
- items: {
- xtype: 'textarea',
- name: 'description',
- height: '100%',
- value: '',
- hideLabel: true
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('PVE.window.Backup', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.vmtype) {
- throw "no VM type specified";
- }
-
- var storagesel = Ext.create('PVE.form.StorageSelector', {
- nodename: me.nodename,
- name: 'storage',
- value: me.storage,
- fieldLabel: gettext('Storage'),
- storageContent: 'backup',
- allowBlank: false
- });
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [
- storagesel,
- {
- xtype: 'pveBackupModeSelector',
- fieldLabel: gettext('Mode'),
- value: 'snapshot',
- name: 'mode'
- },
- {
- xtype: 'pveCompressionSelector',
- name: 'compress',
- value: 'lzo',
- fieldLabel: gettext('Compression')
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Send email to'),
- name: 'mailto',
- emptyText: Proxmox.Utils.noneText
- }
- ]
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn = Ext.create('Ext.Button', {
- text: gettext('Backup'),
- handler: function(){
- var storage = storagesel.getValue();
- var values = form.getValues();
- var params = {
- storage: storage,
- vmid: me.vmid,
- mode: values.mode,
- remove: 0
- };
-
- if ( values.mailto ) {
- params.mailto = values.mailto;
- }
-
- if (values.compress) {
- params.compress = values.compress;
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/vzdump',
- params: params,
- method: 'POST',
- failure: function (response, opts) {
- Ext.Msg.alert('Error',response.htmlStatus);
- },
- success: function(response, options) {
- // close later so we reload the grid
- // after the task has completed
- me.hide();
-
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid,
- listeners: {
- close: function() {
- me.close();
- }
- }
- });
- win.show();
- }
- });
- }
- });
-
- var helpBtn = Ext.create('Proxmox.button.Help', {
- onlineHelp: 'chapter_vzdump',
- listenToGlobalEvent: false,
- hidden: false
- });
-
- var title = gettext('Backup') + " " +
- ((me.vmtype === 'lxc') ? "CT" : "VM") +
- " " + me.vmid;
-
- Ext.apply(me, {
- title: title,
- width: 350,
- modal: true,
- layout: 'auto',
- border: false,
- items: [ me.formPanel ],
- buttons: [ helpBtn, '->', submitBtn ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.window.Restore', {
- extend: 'Ext.window.Window', // fixme: Proxmox.window.Edit?
-
- resizable: false,
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.volid) {
- throw "no volume ID specified";
- }
-
- if (!me.vmtype) {
- throw "no vmtype specified";
- }
-
- var storagesel = Ext.create('PVE.form.StorageSelector', {
- nodename: me.nodename,
- name: 'storage',
- value: '',
- fieldLabel: gettext('Storage'),
- storageContent: (me.vmtype === 'lxc') ? 'rootdir' : 'images',
- allowBlank: true
- });
-
- var IDfield;
- if (me.vmid) {
- IDfield = Ext.create('Ext.form.field.Display', {
- name: 'vmid',
- value: me.vmid,
- fieldLabel: (me.vmtype === 'lxc') ? 'CT' : 'VM'
- });
- } else {
- IDfield = Ext.create('PVE.form.GuestIDSelector', {
- name: 'vmid',
- guestType: me.vmtype,
- loadNextFreeID: true,
- validateExists: false
- });
- }
-
- var items = [
- {
- xtype: 'displayfield',
- value: me.volidText || me.volid,
- fieldLabel: gettext('Source')
- },
- storagesel,
- IDfield,
- {
- xtype: 'proxmoxintegerfield',
- name: 'bwlimit',
- fieldLabel: gettext('Read Limit (MiB/s)'),
- minValue: 0,
- emptyText: gettext('Defaults to target storage restore limit'),
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext("Use '0' to disable all bandwidth limits.")
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'unique',
- fieldLabel: gettext('Unique'),
- hidden: !!me.vmid,
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext('Autogenerate unique properties, e.g., MAC addresses')
- },
- checked: false
- }
- ];
-
- /*jslint confusion: true*/
- if (me.vmtype === 'lxc') {
- items.push({
- xtype: 'proxmoxcheckbox',
- name: 'unprivileged',
- value: true,
- fieldLabel: gettext('Unprivileged container')
- });
- }
- /*jslint confusion: false*/
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var doRestore = function(url, params) {
- Proxmox.Utils.API2Request({
- url: url,
- params: params,
- method: 'POST',
- waitMsgTarget: me,
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- me.close();
- }
- });
- };
-
- var submitBtn = Ext.create('Ext.Button', {
- text: gettext('Restore'),
- handler: function(){
- var storage = storagesel.getValue();
- var values = form.getValues();
-
- var params = {
- storage: storage,
- vmid: me.vmid || values.vmid,
- force: me.vmid ? 1 : 0
- };
- if (values.unique) { params.unique = 1; }
-
- if (values.bwlimit !== undefined) {
- params.bwlimit = values.bwlimit * 1024;
- }
-
- var url;
- var msg;
- if (me.vmtype === 'lxc') {
- url = '/nodes/' + me.nodename + '/lxc';
- params.ostemplate = me.volid;
- params.restore = 1;
- if (values.unprivileged) { params.unprivileged = 1; }
- msg = Proxmox.Utils.format_task_description('vzrestore', params.vmid);
- } else if (me.vmtype === 'qemu') {
- url = '/nodes/' + me.nodename + '/qemu';
- params.archive = me.volid;
- msg = Proxmox.Utils.format_task_description('qmrestore', params.vmid);
- } else {
- throw 'unknown VM type';
- }
-
- if (me.vmid) {
- msg += '. ' + gettext('This will permanently erase current VM data.');
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
- doRestore(url, params);
- });
- } else {
- doRestore(url, params);
- }
- }
- });
-
- form.on('validitychange', function(f, valid) {
- submitBtn.setDisabled(!valid);
- });
-
- var title = gettext('Restore') + ": " + (
- (me.vmtype === 'lxc') ? 'CT' : 'VM');
-
- if (me.vmid) {
- title += " " + me.vmid;
- }
-
- Ext.apply(me, {
- title: title,
- width: 500,
- modal: true,
- layout: 'auto',
- border: false,
- items: [ me.formPanel ],
- buttons: [ submitBtn ]
- });
-
- me.callParent();
- }
-});
-/* Popup a message window
- * where the user has to manually enter the ressource ID
- * to enable the destroy button
- */
-Ext.define('PVE.window.SafeDestroy', {
- extend: 'Ext.window.Window',
- alias: 'widget.pveSafeDestroy',
-
- title: gettext('Confirm'),
- modal: true,
- buttonAlign: 'center',
- bodyPadding: 10,
- width: 450,
- layout: { type:'hbox' },
- defaultFocus: 'confirmField',
- showProgress: false,
-
- config: {
- item: {
- id: undefined,
- type: undefined
- },
- url: undefined,
- params: {}
- },
-
- getParams: function() {
- var me = this;
- if (Ext.Object.isEmpty(me.params)) {
- return '';
- }
- return '?' + Ext.Object.toQueryString(me.params);
- },
-
- controller: {
-
- xclass: 'Ext.app.ViewController',
-
- control: {
- 'field[name=confirm]': {
- change: function(f, value) {
- var view = this.getView();
- var removeButton = this.lookupReference('removeButton');
- if (value === view.getItem().id.toString()) {
- removeButton.enable();
- } else {
- removeButton.disable();
- }
- },
- specialkey: function (field, event) {
- var removeButton = this.lookupReference('removeButton');
- if (!removeButton.isDisabled() && event.getKey() == event.ENTER) {
- removeButton.fireEvent('click', removeButton, event);
- }
- }
- },
- 'button[reference=removeButton]': {
- click: function() {
- var view = this.getView();
- Proxmox.Utils.API2Request({
- url: view.getUrl() + view.getParams(),
- method: 'DELETE',
- waitMsgTarget: view,
- failure: function(response, opts) {
- view.close();
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- var hasProgressBar = view.showProgress &&
- response.result.data ? true : false;
-
- if (hasProgressBar) {
- // stay around so we can trigger our close events
- // when background action is completed
- view.hide();
-
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid,
- listeners: {
- destroy: function () {
- view.close();
- }
- }
- });
- win.show();
- } else {
- view.close();
- }
- }
- });
- }
- }
- }
- },
-
- items: [
- {
- xtype: 'component',
- cls: [ Ext.baseCSSPrefix + 'message-box-icon',
- Ext.baseCSSPrefix + 'message-box-warning',
- Ext.baseCSSPrefix + 'dlg-icon']
- },
- {
- xtype: 'container',
- flex: 1,
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- items: [
- {
- xtype: 'component',
- reference: 'messageCmp'
- },
- {
- itemId: 'confirmField',
- reference: 'confirmField',
- xtype: 'textfield',
- name: 'confirm',
- labelWidth: 300,
- hideTrigger: true,
- allowBlank: false
- }
- ]
- }
- ],
- buttons: [
- {
- reference: 'removeButton',
- text: gettext('Remove'),
- disabled: true
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- var item = me.getItem();
-
- if (!Ext.isDefined(item.id)) {
- throw "no ID specified";
- }
-
- if (!Ext.isDefined(item.type)) {
- throw "no VM type specified";
- }
-
- var messageCmp = me.lookupReference('messageCmp');
- var msg;
-
- if (item.type === 'VM') {
- msg = Proxmox.Utils.format_task_description('qmdestroy', item.id);
- } else if (item.type === 'CT') {
- msg = Proxmox.Utils.format_task_description('vzdestroy', item.id);
- } else if (item.type === 'CephPool') {
- msg = Proxmox.Utils.format_task_description('cephdestroypool', item.id);
- } else if (item.type === 'Image') {
- msg = Proxmox.Utils.format_task_description('unknownimgdel', item.id);
- } else {
- throw "unknown item type specified";
- }
-
- messageCmp.setHtml(msg);
-
- var confirmField = me.lookupReference('confirmField');
- msg = gettext('Please enter the ID to confirm') +
- ' (' + item.id + ')';
- confirmField.setFieldLabel(msg);
- }
-});
-Ext.define('PVE.window.BackupConfig', {
- extend: 'Ext.window.Window',
- title: gettext('Configuration'),
- width: 600,
- height: 400,
- layout: 'fit',
- modal: true,
- items: {
- xtype: 'component',
- itemId: 'configtext',
- autoScroll: true,
- style: {
- 'background-color': 'white',
- 'white-space': 'pre',
- 'font-family': 'monospace',
- padding: '5px'
- }
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.volume) {
- throw "no volume specified";
- }
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.callParent();
-
- Proxmox.Utils.API2Request({
- url: "/nodes/" + nodename + "/vzdump/extractconfig",
- method: 'GET',
- params: {
- volume: me.volume
- },
- failure: function(response, opts) {
- me.close();
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response,options) {
- me.show();
- me.down('#configtext').update(Ext.htmlEncode(response.result.data));
- }
- });
- }
-});
-Ext.define('PVE.window.Settings', {
- extend: 'Ext.window.Window',
-
- width: '800px',
- title: gettext('My Settings'),
- iconCls: 'fa fa-gear',
- modal: true,
- bodyPadding: 10,
- resizable: false,
-
- buttons: [
- {
- xtype: 'proxmoxHelpButton',
- onlineHelp: 'gui_my_settings',
- hidden: false
- },
- '->',
- {
- text: gettext('Close'),
- handler: function() {
- this.up('window').close();
- }
- }
- ],
-
- layout: {
- type: 'hbox',
- align: 'top'
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- var me = this;
- var sp = Ext.state.Manager.getProvider();
-
- var username = sp.get('login-username') || Proxmox.Utils.noneText;
- me.lookupReference('savedUserName').setValue(username);
-
- var settings = ['fontSize', 'fontFamily', 'letterSpacing', 'lineHeight'];
- settings.forEach(function(setting) {
- var val = localStorage.getItem('pve-xterm-' + setting);
- if (val !== undefined && val !== null) {
- var field = me.lookup(setting);
- field.setValue(val);
- field.resetOriginalValue();
- }
- });
- },
-
- set_button_status: function() {
- var me = this;
-
- var form = me.lookup('xtermform');
- var valid = form.isValid();
- var dirty = form.isDirty();
-
- var hasvalues = false;
- var values = form.getValues();
- Ext.Object.eachValue(values, function(value) {
- if (value) {
- hasvalues = true;
- return false;
- }
- });
-
- me.lookup('xtermsave').setDisabled(!dirty || !valid);
- me.lookup('xtermreset').setDisabled(!hasvalues);
- },
-
- control: {
- '#xtermjs form': {
- dirtychange: 'set_button_status',
- validitychange: 'set_button_status'
- },
- '#xtermjs button': {
- click: function(button) {
- var me = this;
- var settings = ['fontSize', 'fontFamily', 'letterSpacing', 'lineHeight'];
- settings.forEach(function(setting) {
- var field = me.lookup(setting);
- if (button.reference === 'xtermsave') {
- var value = field.getValue();
- if (value) {
- localStorage.setItem('pve-xterm-' + setting, value);
- } else {
- localStorage.removeItem('pve-xterm-' + setting);
- }
- } else if (button.reference === 'xtermreset') {
- field.setValue(undefined);
- localStorage.removeItem('pve-xterm-' + setting);
- }
- field.resetOriginalValue();
- });
- me.set_button_status();
- }
- },
- 'button[name=reset]': {
- click: function () {
- var blacklist = ['GuiCap', 'login-username', 'dash-storages'];
- var sp = Ext.state.Manager.getProvider();
- var state;
- for (state in sp.state) {
- if (sp.state.hasOwnProperty(state)) {
- if (blacklist.indexOf(state) !== -1) {
- continue;
- }
-
- sp.clear(state);
- }
- }
-
- window.location.reload();
- }
- },
- 'button[name=clear-username]': {
- click: function () {
- var me = this;
- var usernamefield = me.lookupReference('savedUserName');
- var sp = Ext.state.Manager.getProvider();
-
- usernamefield.setValue(Proxmox.Utils.noneText);
- sp.clear('login-username');
- }
- },
- 'grid[reference=dashboard-storages]': {
- selectionchange: function(grid, selected) {
- var me = this;
- var sp = Ext.state.Manager.getProvider();
-
- // saves the selected storageids as
- // "id1,id2,id3,..."
- // or clears the variable
- if (selected.length > 0) {
- sp.set('dash-storages',
- Ext.Array.pluck(selected, 'id').join(','));
- } else {
- sp.clear('dash-storages');
- }
- },
- afterrender: function(grid) {
- var me = grid;
- var sp = Ext.state.Manager.getProvider();
- var store = me.getStore();
- var items = [];
- me.suspendEvent('selectionchange');
- var storages = sp.get('dash-storages') || '';
- storages.split(',').forEach(function(storage){
- // we have to get the records
- // to be able to select them
- if (storage !== '') {
- var item = store.getById(storage);
- if (item) {
- items.push(item);
- }
- }
- });
- me.getSelectionModel().select(items);
- me.resumeEvent('selectionchange');
- }
- }
- }
- },
-
- items: [{
- xtype: 'fieldset',
- width: '50%',
- title: gettext('Webinterface Settings'),
- margin: '5',
- layout: {
- type: 'vbox',
- align: 'left'
- },
- defaults: {
- width: '100%',
- margin: '0 0 10 0'
- },
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Dashboard Storages'),
- labelAlign: 'left',
- labelWidth: '50%'
- },
- {
- xtype: 'grid',
- maxHeight: 150,
- reference: 'dashboard-storages',
- selModel: {
- selType: 'checkboxmodel'
- },
- columns: [{
- header: gettext('Name'),
- dataIndex: 'storage',
- flex: 1
- },{
- header: gettext('Node'),
- dataIndex: 'node',
- flex: 1
- }],
- store: {
- type: 'diff',
- field: ['type', 'storage', 'id', 'node'],
- rstore: PVE.data.ResourceStore,
- filters: [{
- property: 'type',
- value: 'storage'
- }],
- sorters: [ 'node','storage']
- }
- },
- {
- xtype: 'box',
- autoEl: { tag: 'hr'}
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Saved User name'),
- labelAlign: 'left',
- labelWidth: '50%',
- stateId: 'login-username',
- reference: 'savedUserName',
- value: ''
- },
- {
- xtype: 'button',
- cls: 'x-btn-default-toolbar-small proxmox-inline-button',
- text: gettext('Clear User name'),
- width: 'auto',
- name: 'clear-username'
- },
- {
- xtype: 'box',
- autoEl: { tag: 'hr'}
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Layout'),
- labelAlign: 'left',
- labelWidth: '50%'
- },
- {
- xtype: 'button',
- cls: 'x-btn-default-toolbar-small proxmox-inline-button',
- text: gettext('Reset Layout'),
- width: 'auto',
- name: 'reset'
- }
- ]
- },{
- xtype: 'fieldset',
- itemId: 'xtermjs',
- width: '50%',
- margin: '5',
- title: gettext('xterm.js Settings'),
- items: [{
- xtype: 'form',
- reference: 'xtermform',
- border: false,
- layout: {
- type: 'vbox',
- algin: 'left'
- },
- defaults: {
- width: '100%',
- margin: '0 0 10 0'
- },
- items: [
- {
- xtype: 'textfield',
- name: 'fontFamily',
- reference: 'fontFamily',
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('Font-Family')
- },
- {
- xtype: 'proxmoxintegerfield',
- emptyText: Proxmox.Utils.defaultText,
- name: 'fontSize',
- reference: 'fontSize',
- minValue: 1,
- fieldLabel: gettext('Font-Size')
- },
- {
- xtype: 'numberfield',
- name: 'letterSpacing',
- reference: 'letterSpacing',
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('Letter Spacing')
- },
- {
- xtype: 'numberfield',
- name: 'lineHeight',
- minValue: 0.1,
- reference: 'lineHeight',
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('Line Height')
- },
- {
- xtype: 'container',
- layout: {
- type: 'hbox',
- pack: 'end'
- },
- items: [
- {
- xtype: 'button',
- reference: 'xtermreset',
- disabled: true,
- text: gettext('Reset')
- },
- {
- xtype: 'button',
- reference: 'xtermsave',
- disabled: true,
- text: gettext('Save')
- }
- ]
- }
- ]
- }]
- }],
-
- onShow: function() {
- var me = this;
- me.callParent();
- }
-});
-Ext.define('PVE.panel.StartupInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- onlineHelp: 'qm_startup_and_shutdown',
-
- onGetValues: function(values) {
- var me = this;
-
- var res = PVE.Parser.printStartup(values);
-
- if (res === undefined || res === '') {
- return { 'delete': 'startup' };
- }
-
- return { startup: res };
- },
-
- setStartup: function(value) {
- var me = this;
-
- var startup = PVE.Parser.parseStartup(value);
- if (startup) {
- me.setValues(startup);
- }
- },
-
- initComponent : function() {
- var me = this;
-
- me.items = [
- {
- xtype: 'textfield',
- name: 'order',
- defaultValue: '',
- emptyText: 'any',
- fieldLabel: gettext('Start/Shutdown order')
- },
- {
- xtype: 'textfield',
- name: 'up',
- defaultValue: '',
- emptyText: 'default',
- fieldLabel: gettext('Startup delay')
- },
- {
- xtype: 'textfield',
- name: 'down',
- defaultValue: '',
- emptyText: 'default',
- fieldLabel: gettext('Shutdown timeout')
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.window.StartupEdit', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveWindowStartupEdit',
- onlineHelp: undefined,
-
- initComponent : function() {
-
- var me = this;
- var ipanelConfig = me.onlineHelp ? {onlineHelp: me.onlineHelp} : {};
- var ipanel = Ext.create('PVE.panel.StartupInputPanel', ipanelConfig);
-
- Ext.applyIf(me, {
- subject: gettext('Start/Shutdown order'),
- fieldDefaults: {
- labelWidth: 120
- },
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var i, confid;
- me.vmconfig = response.result.data;
- ipanel.setStartup(me.vmconfig.startup);
- }
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.ceph.Install', {
- extend: 'Ext.window.Window',
- xtype: 'pveCephInstallWindow',
- mixins: ['Proxmox.Mixin.CBind'],
-
- width: 220,
- header: false,
- resizable: false,
- draggable: false,
- modal: true,
- nodename: undefined,
- shadow: false,
- border: false,
- bodyBorder: false,
- closable: false,
- cls: 'install-mask',
- bodyCls: 'install-mask',
- layout: {
- align: 'stretch',
- pack: 'center',
- type: 'vbox'
- },
- viewModel: {
- data: {
- cephVersion: 'luminous',
- isInstalled: false
- },
- formulas: {
- buttonText: function (get){
- if (get('isInstalled')) {
- return gettext('Configure Ceph');
- } else {
- return gettext('Install Ceph-') + get('cephVersion');
- }
- },
- windowText: function (get) {
- if (get('isInstalled')) {
- return '' +
- Ext.String.format(gettext('{0} is not initialized.'), 'Ceph') + ' '+
- gettext('You need to create a initial config once.') + '
';
- } else {
- return '' +
- Ext.String.format(gettext('{0} is not installed on this node.'), 'Ceph') + ' ' +
- gettext('Would you like to install it now?') + '
';
- }
- }
- }
- },
- items: [
- {
- bind: {
- html: '{windowText}'
- },
- border: false,
- padding: 5,
- bodyCls: 'install-mask'
-
- },
- {
- xtype: 'button',
- bind: {
- text: '{buttonText}'
- },
- viewModel: {},
- cbind: {
- nodename: '{nodename}'
- },
- handler: function() {
- var me = this.up('pveCephInstallWindow');
- var win = Ext.create('PVE.ceph.CephInstallWizard',{
- nodename: me.nodename
- });
- win.getViewModel().set('isInstalled', this.getViewModel().get('isInstalled'));
- win.show();
- me.mon(win,'beforeClose', function(){
- me.fireEvent("cephInstallWindowClosed");
- me.close();
- });
-
- }
- }
- ]
-});
-/*jslint confusion: true*/
-Ext.define('PVE.FirewallEnableEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveFirewallEnableEdit'],
- mixins: ['Proxmox.Mixin.CBind'],
-
- subject: gettext('Firewall'),
- cbindData: {
- defaultValue: 0
- },
- width: 350,
-
- items: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- uncheckedValue: 0,
- cbind: {
- defaultValue: '{defaultValue}',
- checked: '{defaultValue}'
- },
- deleteDefaultValue: false,
- fieldLabel: gettext('Firewall')
- },
- {
- xtype: 'displayfield',
- name: 'warning',
- userCls: 'pve-hint',
- value: gettext('Warning: Firewall still disabled at datacenter level!'),
- hidden: true
- }
- ],
-
- beforeShow: function() {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/cluster/firewall/options',
- method: 'GET',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- if (!response.result.data.enable) {
- me.down('displayfield[name=warning]').setVisible(true);
- }
- }
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.FirewallLograteInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveFirewallLograteInputPanel',
-
- viewModel: {},
-
- items: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- reference: 'enable',
- fieldLabel: gettext('Enable'),
- value: false
- },
- {
- layout: 'hbox',
- border: false,
- items: [
- {
- xtype: 'numberfield',
- name: 'rate',
- fieldLabel: gettext('Log rate limit'),
- minValue: 1,
- maxValue: 99,
- allowBlank: false,
- flex: 2,
- value: 1
- },
- {
- html: '/
'
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'unit',
- comboItems: [['second', 'second'], ['minute', 'minute'],
- ['hour', 'hour'], ['day', 'day']],
- allowBlank: false,
- flex: 1,
- value: 'second'
- }
- ]
- },
- {
- xtype: 'numberfield',
- name: 'burst',
- fieldLabel: gettext('Log burst limit'),
- minValue: 1,
- maxValue: 99,
- value: 5
- }
- ],
-
- onGetValues: function(values) {
- var me = this;
-
- var vals = {};
- vals.enable = values.enable !== undefined ? 1 : 0;
- vals.rate = values.rate + '/' + values.unit;
- vals.burst = values.burst;
- var properties = PVE.Parser.printPropertyString(vals, undefined);
- if (properties == '') {
- return { 'delete': 'log_ratelimit' };
- }
- return { log_ratelimit: properties };
- },
-
- setValues: function(values) {
- var me = this;
-
- var properties = {};
- if (values.log_ratelimit !== undefined) {
- properties = PVE.Parser.parsePropertyString(values.log_ratelimit);
- var matches = properties.rate.match(/^(\d+)\/(second|minute|hour|day)$/);
- if (matches) {
- properties.rate = matches[1];
- properties.unit = matches[2];
- }
- }
- me.callParent([properties]);
- }
-});
-
-Ext.define('PVE.FirewallLograteEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveFirewallLograteEdit',
-
- subject: gettext('Log rate limit'),
-
- items: [{
- xtype: 'pveFirewallLograteInputPanel'
- }],
- autoLoad: true
-});
-Ext.define('PVE.panel.NotesView', {
- extend: 'Ext.panel.Panel',
- xtype: 'pveNotesView',
-
- title: gettext("Notes"),
- bodyStyle: 'white-space:pre',
- bodyPadding: 10,
- scrollable: true,
-
- tbar: {
- itemId: 'tbar',
- hidden: true,
- items: [
- {
- text: gettext('Edit'),
- handler: function() {
- var me = this.up('panel');
- me.run_editor();
- }
- }
- ]
- },
-
- run_editor: function() {
- var me = this;
- var win = Ext.create('PVE.window.NotesEdit', {
- pveSelNode: me.pveSelNode,
- url: me.url
- });
- win.show();
- win.on('destroy', me.load, me);
- },
-
- load: function() {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: me.url,
- waitMsgTarget: me,
- failure: function(response, opts) {
- me.update(gettext('Error') + " " + response.htmlStatus);
- },
- success: function(response, opts) {
- var data = response.result.data.description || '';
- me.update(Ext.htmlEncode(data));
- }
- });
- },
-
- listeners: {
- render: function(c) {
- var me = this;
- me.getEl().on('dblclick', me.run_editor, me);
- }
- },
-
- tools: [{
- type: 'gear',
- handler: function() {
- var me = this.up('panel');
- me.run_editor();
- }
- }],
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var type = me.pveSelNode.data.type;
- if (!Ext.Array.contains(['node', 'qemu', 'lxc'], type)) {
- throw 'invalid type specified';
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid && type !== 'node') {
- throw "no VM ID specified";
- }
-
- me.url = '/api2/extjs/nodes/' + nodename + '/';
-
- // add the type specific path if qemu/lxc
- if (type === 'qemu' || type === 'lxc') {
- me.url += type + '/' + vmid + '/';
- }
-
- me.url += 'config';
-
- me.callParent();
- if (type === 'node') {
- me.down('#tbar').setVisible(true);
- }
- me.load();
- }
-});
-Ext.define('PVE.grid.ResourceGrid', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveResourceGrid'],
-
- border: false,
- defaultSorter: {
- property: 'type',
- direction: 'ASC'
- },
- initComponent : function() {
- var me = this;
-
- var rstore = PVE.data.ResourceStore;
- var sp = Ext.state.Manager.getProvider();
-
- var coldef = rstore.defaultColumns();
-
- var store = Ext.create('Ext.data.Store', {
- model: 'PVEResources',
- sorters: me.defaultSorter,
- proxy: { type: 'memory' }
- });
-
- var textfilter = '';
-
- var textfilter_match = function(item) {
- var match = false;
- Ext.each(['name', 'storage', 'node', 'type', 'text'], function(field) {
- var v = item.data[field];
- if (v !== undefined) {
- v = v.toLowerCase();
- if (v.indexOf(textfilter) >= 0) {
- match = true;
- return false;
- }
- }
- });
- return match;
- };
-
- var updateGrid = function() {
-
- var filterfn = me.viewFilter ? me.viewFilter.filterfn : null;
-
- //console.log("START GRID UPDATE " + me.viewFilter);
-
- store.suspendEvents();
-
- var nodeidx = {};
- var gather_child_nodes = function(cn) {
- if (!cn) {
- return;
- }
- var cs = cn.childNodes;
- if (!cs) {
- return;
- }
- var len = cs.length, i = 0, n, res;
-
- for (; i < len; i++) {
- var child = cs[i];
- var orgnode = rstore.data.get(child.data.id);
- if (orgnode) {
- if ((!filterfn || filterfn(child)) &&
- (!textfilter || textfilter_match(child))) {
- nodeidx[child.data.id] = orgnode;
- }
- }
- gather_child_nodes(child);
- }
- };
- gather_child_nodes(me.pveSelNode);
-
- // remove vanished items
- var rmlist = [];
- store.each(function(olditem) {
- var item = nodeidx[olditem.data.id];
- if (!item) {
- //console.log("GRID REM UID: " + olditem.data.id);
- rmlist.push(olditem);
- }
- });
-
- if (rmlist.length) {
- store.remove(rmlist);
- }
-
- // add new items
- var addlist = [];
- var key;
- for (key in nodeidx) {
- if (nodeidx.hasOwnProperty(key)) {
- var item = nodeidx[key];
-
- // getById() use find(), which is slow (ExtJS4 DP5)
- //var olditem = store.getById(item.data.id);
- var olditem = store.data.get(item.data.id);
-
- if (!olditem) {
- //console.log("GRID ADD UID: " + item.data.id);
- var info = Ext.apply({}, item.data);
- var child = Ext.create(store.model, info);
- addlist.push(item);
- continue;
- }
- // try to detect changes
- var changes = false;
- var fieldkeys = PVE.data.ResourceStore.fieldNames;
- var fieldcount = fieldkeys.length;
- var fieldind;
- for (fieldind = 0; fieldind < fieldcount; fieldind++) {
- var field = fieldkeys[fieldind];
- if (field != 'id' && item.data[field] != olditem.data[field]) {
- changes = true;
- //console.log("changed item " + item.id + " " + field + " " + item.data[field] + " != " + olditem.data[field]);
- olditem.beginEdit();
- olditem.set(field, item.data[field]);
- }
- }
- if (changes) {
- olditem.endEdit(true);
- olditem.commit(true);
- }
- }
- }
-
- if (addlist.length) {
- store.add(addlist);
- }
-
- store.sort();
-
- store.resumeEvents();
-
- store.fireEvent('refresh', store);
-
- //console.log("END GRID UPDATE");
- };
-
- var filter_task = new Ext.util.DelayedTask(function(){
- updateGrid();
- });
-
- var load_cb = function() {
- updateGrid();
- };
-
- Ext.apply(me, {
- store: store,
- stateful: true,
- stateId: 'grid-resource',
- tbar: [
- '->',
- gettext('Search') + ':', ' ',
- {
- xtype: 'textfield',
- width: 200,
- value: textfilter,
- enableKeyEvents: true,
- listeners: {
- keyup: function(field, e) {
- var v = field.getValue();
- textfilter = v.toLowerCase();
- filter_task.delay(500);
- }
- }
- }
- ],
- viewConfig: {
- stripeRows: true
- },
- listeners: {
- itemcontextmenu: PVE.Utils.createCmdMenu,
- itemdblclick: function(v, record) {
- var ws = me.up('pveStdWorkspace');
- ws.selectById(record.data.id);
- },
- destroy: function() {
- rstore.un("load", load_cb);
- }
- },
- columns: coldef
- });
- me.callParent();
- updateGrid();
- rstore.on("load", load_cb);
- }
-});
-Ext.define('PVE.pool.AddVM', {
- extend: 'Proxmox.window.Edit',
- width: 600,
- height: 400,
- isAdd: true,
- isCreate: true,
- initComponent : function() {
-
- var me = this;
-
- if (!me.pool) {
- throw "no pool specified";
- }
-
- me.url = "/pools/" + me.pool;
- me.method = 'PUT';
-
- var vmsField = Ext.create('Ext.form.field.Text', {
- name: 'vms',
- hidden: true,
- allowBlank: false
- });
-
- var vmStore = Ext.create('Ext.data.Store', {
- model: 'PVEResources',
- sorters: [
- {
- property: 'vmid',
- order: 'ASC'
- }
- ],
- filters: [
- function(item) {
- return ((item.data.type === 'lxc' || item.data.type === 'qemu') && item.data.pool === '');
- }
- ]
- });
-
- var vmGrid = Ext.create('widget.grid',{
- store: vmStore,
- border: true,
- height: 300,
- scrollable: true,
- selModel: {
- selType: 'checkboxmodel',
- mode: 'SIMPLE',
- listeners: {
- selectionchange: function(model, selected, opts) {
- var selectedVms = [];
- selected.forEach(function(vm) {
- selectedVms.push(vm.data.vmid);
- });
- vmsField.setValue(selectedVms);
- }
- }
- },
- columns: [
- {
- header: 'ID',
- dataIndex: 'vmid',
- width: 60
- },
- {
- header: gettext('Node'),
- dataIndex: 'node'
- },
- {
- header: gettext('Status'),
- dataIndex: 'uptime',
- renderer: function(value) {
- if (value) {
- return Proxmox.Utils.runningText;
- } else {
- return Proxmox.Utils.stoppedText;
- }
- }
- },
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- header: gettext('Type'),
- dataIndex: 'type'
- }
- ]
- });
- Ext.apply(me, {
- subject: gettext('Virtual Machine'),
- items: [ vmsField, vmGrid ]
- });
-
- me.callParent();
- vmStore.load();
- }
-});
-
-Ext.define('PVE.pool.AddStorage', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
-
- var me = this;
-
- if (!me.pool) {
- throw "no pool specified";
- }
-
- me.isCreate = true;
- me.isAdd = true;
- me.url = "/pools/" + me.pool;
- me.method = 'PUT';
-
- Ext.apply(me, {
- subject: gettext('Storage'),
- width: 350,
- items: [
- {
- xtype: 'pveStorageSelector',
- name: 'storage',
- nodename: 'localhost',
- autoSelect: false,
- value: '',
- fieldLabel: gettext("Storage")
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.grid.PoolMembers', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pvePoolMembers'],
-
- // fixme: dynamic status update ?
-
- stateful: true,
- stateId: 'grid-pool-members',
-
- initComponent : function() {
- var me = this;
-
- if (!me.pool) {
- throw "no pool specified";
- }
-
- var store = Ext.create('Ext.data.Store', {
- model: 'PVEResources',
- sorters: [
- {
- property : 'type',
- direction: 'ASC'
- }
- ],
- proxy: {
- type: 'proxmox',
- root: 'data.members',
- url: "/api2/json/pools/" + me.pool
- }
- });
-
- var coldef = PVE.data.ResourceStore.defaultColumns();
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- confirmMsg: function (rec) {
- return Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.id + "'");
- },
- handler: function(btn, event, rec) {
- var params = { 'delete': 1 };
- if (rec.data.type === 'storage') {
- params.storage = rec.data.storage;
- } else if (rec.data.type === 'qemu' || rec.data.type === 'lxc' || rec.data.type === 'openvz') {
- params.vms = rec.data.vmid;
- } else {
- throw "unknown resource type";
- }
-
- Proxmox.Utils.API2Request({
- url: '/pools/' + me.pool,
- method: 'PUT',
- params: params,
- waitMsgTarget: me,
- callback: function() {
- reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Virtual Machine'),
- iconCls: 'pve-itype-icon-qemu',
- handler: function() {
- var win = Ext.create('PVE.pool.AddVM', { pool: me.pool });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('Storage'),
- iconCls: 'pve-itype-icon-storage',
- handler: function() {
- var win = Ext.create('PVE.pool.AddStorage', { pool: me.pool });
- win.on('destroy', reload);
- win.show();
- }
- }
- ]
- })
- },
- remove_btn
- ],
- viewConfig: {
- stripeRows: true
- },
- columns: coldef,
- listeners: {
- itemcontextmenu: PVE.Utils.createCmdMenu,
- itemdblclick: function(v, record) {
- var ws = me.up('pveStdWorkspace');
- ws.selectById(record.data.id);
- },
- activate: reload
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.FWMacroSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.pveFWMacroSelector',
- allowBlank: true,
- autoSelect: false,
- valueField: 'macro',
- displayField: 'macro',
- listConfig: {
- columns: [
- {
- header: gettext('Macro'),
- dataIndex: 'macro',
- hideable: false,
- width: 100
- },
- {
- header: gettext('Description'),
- renderer: Ext.String.htmlEncode,
- flex: 1,
- dataIndex: 'descr'
- }
- ]
- },
- initComponent: function() {
- var me = this;
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: true,
- fields: [ 'macro', 'descr' ],
- idProperty: 'macro',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/firewall/macros"
- },
- sorters: {
- property: 'macro',
- order: 'DESC'
- }
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.FirewallRulePanel', {
- extend: 'Proxmox.panel.InputPanel',
-
- allow_iface: false,
-
- list_refs_url: undefined,
-
- onGetValues: function(values) {
- var me = this;
-
- // hack: editable ComboGrid returns nothing when empty, so we need to set ''
- // Also, disabled text fields return nothing, so we need to set ''
-
- Ext.Array.each(['source', 'dest', 'macro', 'proto', 'sport', 'dport', 'log'], function(key) {
- if (values[key] === undefined) {
- values[key] = '';
- }
- });
-
- delete values.modified_marker;
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.list_refs_url) {
- throw "no list_refs_url specified";
- }
-
- me.column1 = [
- {
- // hack: we use this field to mark the form 'dirty' when the
- // record has errors- so that the user can safe the unmodified
- // form again.
- xtype: 'hiddenfield',
- name: 'modified_marker',
- value: ''
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'type',
- value: 'in',
- comboItems: [['in', 'in'], ['out', 'out']],
- fieldLabel: gettext('Direction'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'action',
- value: 'ACCEPT',
- comboItems: [['ACCEPT', 'ACCEPT'], ['DROP', 'DROP'], ['REJECT', 'REJECT']],
- fieldLabel: gettext('Action'),
- allowBlank: false
- }
- ];
-
- if (me.allow_iface) {
- me.column1.push({
- xtype: 'proxmoxtextfield',
- name: 'iface',
- deleteEmpty: !me.isCreate,
- value: '',
- fieldLabel: gettext('Interface')
- });
- } else {
- me.column1.push({
- xtype: 'displayfield',
- fieldLabel: '',
- value: ''
- });
- }
-
- me.column1.push(
- {
- xtype: 'displayfield',
- fieldLabel: '',
- height: 7,
- value: ''
- },
- {
- xtype: 'pveIPRefSelector',
- name: 'source',
- autoSelect: false,
- editable: true,
- base_url: me.list_refs_url,
- value: '',
- fieldLabel: gettext('Source')
-
- },
- {
- xtype: 'pveIPRefSelector',
- name: 'dest',
- autoSelect: false,
- editable: true,
- base_url: me.list_refs_url,
- value: '',
- fieldLabel: gettext('Destination')
- }
- );
-
-
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: gettext('Enable')
- },
- {
- xtype: 'pveFWMacroSelector',
- name: 'macro',
- fieldLabel: gettext('Macro'),
- editable: true,
- allowBlank: true,
- listeners: {
- change: function(f, value) {
- if (value === null) {
- me.down('field[name=proto]').setDisabled(false);
- me.down('field[name=sport]').setDisabled(false);
- me.down('field[name=dport]').setDisabled(false);
- } else {
- me.down('field[name=proto]').setDisabled(true);
- me.down('field[name=proto]').setValue('');
- me.down('field[name=sport]').setDisabled(true);
- me.down('field[name=sport]').setValue('');
- me.down('field[name=dport]').setDisabled(true);
- me.down('field[name=dport]').setValue('');
- }
- }
- }
- },
- {
- xtype: 'pveIPProtocolSelector',
- name: 'proto',
- autoSelect: false,
- editable: true,
- value: '',
- fieldLabel: gettext('Protocol')
- },
- {
- xtype: 'displayfield',
- fieldLabel: '',
- height: 7,
- value: ''
- },
- {
- xtype: 'textfield',
- name: 'sport',
- value: '',
- fieldLabel: gettext('Source port')
- },
- {
- xtype: 'textfield',
- name: 'dport',
- value: '',
- fieldLabel: gettext('Dest. port')
- }
- ];
-
- me.advancedColumn1 = [
- {
- xtype: 'pveFirewallLogLevels'
- }
- ];
-
- me.columnB = [
- {
- xtype: 'textfield',
- name: 'comment',
- value: '',
- fieldLabel: gettext('Comment')
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.FirewallRuleEdit', {
- extend: 'Proxmox.window.Edit',
-
- base_url: undefined,
- list_refs_url: undefined,
-
- allow_iface: false,
-
- initComponent : function() {
-
- var me = this;
-
- if (!me.base_url) {
- throw "no base_url specified";
- }
- if (!me.list_refs_url) {
- throw "no list_refs_url specified";
- }
-
- me.isCreate = (me.rule_pos === undefined);
-
- if (me.isCreate) {
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs' + me.base_url + '/' + me.rule_pos.toString();
- me.method = 'PUT';
- }
-
- var ipanel = Ext.create('PVE.FirewallRulePanel', {
- isCreate: me.isCreate,
- list_refs_url: me.list_refs_url,
- allow_iface: me.allow_iface,
- rule_pos: me.rule_pos
- });
-
- Ext.apply(me, {
- subject: gettext('Rule'),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- ipanel.setValues(values);
- if (values.errors) {
- var field = me.query('[isFormField][name=modified_marker]')[0];
- field.setValue(1);
- Ext.Function.defer(function() {
- var form = ipanel.up('form').getForm();
- form.markInvalid(values.errors);
- }, 100);
- }
- }
- });
- } else if (me.rec) {
- ipanel.setValues(me.rec.data);
- }
- }
-});
-
-Ext.define('PVE.FirewallGroupRuleEdit', {
- extend: 'Proxmox.window.Edit',
-
- base_url: undefined,
-
- allow_iface: false,
-
- initComponent : function() {
-
- var me = this;
-
- me.isCreate = (me.rule_pos === undefined);
-
- if (me.isCreate) {
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs' + me.base_url + '/' + me.rule_pos.toString();
- me.method = 'PUT';
- }
-
- var column1 = [
- {
- xtype: 'hiddenfield',
- name: 'type',
- value: 'group'
- },
- {
- xtype: 'pveSecurityGroupsSelector',
- name: 'action',
- value: '',
- fieldLabel: gettext('Security Group'),
- allowBlank: false
- }
- ];
-
- if (me.allow_iface) {
- column1.push({
- xtype: 'proxmoxtextfield',
- name: 'iface',
- deleteEmpty: !me.isCreate,
- value: '',
- fieldLabel: gettext('Interface')
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- isCreate: me.isCreate,
- column1: column1,
- column2: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: gettext('Enable')
- }
- ],
- columnB: [
- {
- xtype: 'textfield',
- name: 'comment',
- value: '',
- fieldLabel: gettext('Comment')
- }
- ]
- });
-
- Ext.apply(me, {
- subject: gettext('Rule'),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-
-Ext.define('PVE.FirewallRules', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveFirewallRules',
-
- onlineHelp: 'chapter_pve_firewall',
-
- stateful: true,
- stateId: 'grid-firewall-rules',
-
- base_url: undefined,
- list_refs_url: undefined,
-
- addBtn: undefined,
- removeBtn: undefined,
- editBtn: undefined,
- groupBtn: undefined,
-
- tbar_prefix: undefined,
-
- allow_groups: true,
- allow_iface: false,
-
- setBaseUrl: function(url) {
- var me = this;
-
- me.base_url = url;
-
- if (url === undefined) {
- me.addBtn.setDisabled(true);
- if (me.groupBtn) {
- me.groupBtn.setDisabled(true);
- }
- me.store.removeAll();
- } else {
- me.addBtn.setDisabled(false);
- me.removeBtn.baseurl = url + '/';
- if (me.groupBtn) {
- me.groupBtn.setDisabled(false);
- }
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json' + url
- });
-
- me.store.load();
- }
- },
-
- moveRule: function(from, to) {
- var me = this;
-
- if (!me.base_url) {
- return;
- }
-
- Proxmox.Utils.API2Request({
- url: me.base_url + "/" + from,
- method: 'PUT',
- params: { moveto: to },
- waitMsgTarget: me,
- failure: function(response, options) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- callback: function() {
- me.store.load();
- }
- });
- },
-
- updateRule: function(rule) {
- var me = this;
-
- if (!me.base_url) {
- return;
- }
-
- rule.enable = rule.enable ? 1 : 0;
-
- var pos = rule.pos;
- delete rule.pos;
- delete rule.errors;
-
- Proxmox.Utils.API2Request({
- url: me.base_url + '/' + pos.toString(),
- method: 'PUT',
- params: rule,
- waitMsgTarget: me,
- failure: function(response, options) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- callback: function() {
- me.store.load();
- }
- });
- },
-
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.list_refs_url) {
- throw "no list_refs_url specified";
- }
-
- var store = Ext.create('Ext.data.Store',{
- model: 'pve-fw-rule'
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var type = rec.data.type;
-
- var editor;
- if (type === 'in' || type === 'out') {
- editor = 'PVE.FirewallRuleEdit';
- } else if (type === 'group') {
- editor = 'PVE.FirewallGroupRuleEdit';
- } else {
- return;
- }
-
- var win = Ext.create(editor, {
- digest: rec.data.digest,
- allow_iface: me.allow_iface,
- base_url: me.base_url,
- list_refs_url: me.list_refs_url,
- rule_pos: rec.data.pos
- });
-
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = Ext.create('Proxmox.button.Button',{
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = Ext.create('Ext.Button', {
- text: gettext('Add'),
- disabled: true,
- handler: function() {
- var win = Ext.create('PVE.FirewallRuleEdit', {
- allow_iface: me.allow_iface,
- base_url: me.base_url,
- list_refs_url: me.list_refs_url
- });
- win.on('destroy', reload);
- win.show();
- }
- });
-
- var run_copy_editor = function() {
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- return;
- }
- var type = rec.data.type;
-
-
- if (!(type === 'in' || type === 'out')) {
- return;
- }
-
- var win = Ext.create('PVE.FirewallRuleEdit', {
- allow_iface: me.allow_iface,
- base_url: me.base_url,
- list_refs_url: me.list_refs_url,
- rec: rec
- });
-
- win.show();
- win.on('destroy', reload);
- };
-
- me.copyBtn = Ext.create('Proxmox.button.Button',{
- text: gettext('Copy'),
- selModel: sm,
- enableFn: function(rec) {
- return (rec.data.type === 'in' || rec.data.type === 'out');
- },
- disabled: true,
- handler: run_copy_editor
- });
-
- if (me.allow_groups) {
- me.groupBtn = Ext.create('Ext.Button', {
- text: gettext('Insert') + ': ' +
- gettext('Security Group'),
- disabled: true,
- handler: function() {
- var win = Ext.create('PVE.FirewallGroupRuleEdit', {
- allow_iface: me.allow_iface,
- base_url: me.base_url
- });
- win.on('destroy', reload);
- win.show();
- }
- });
- }
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton',{
- selModel: sm,
- baseurl: me.base_url + '/',
- confirmMsg: false,
- getRecordName: function(rec) {
- var rule = rec.data;
- return rule.pos.toString() +
- '?digest=' + encodeURIComponent(rule.digest);
- },
- callback: function() {
- me.store.load();
- }
- });
-
- var tbar = me.tbar_prefix ? [ me.tbar_prefix ] : [];
- tbar.push(me.addBtn, me.copyBtn);
- if (me.groupBtn) {
- tbar.push(me.groupBtn);
- }
- tbar.push(me.removeBtn, me.editBtn);
-
- var render_errors = function(name, value, metaData, record) {
- var errors = record.data.errors;
- if (errors && errors[name]) {
- metaData.tdCls = 'proxmox-invalid-row';
- var html = '' + Ext.htmlEncode(errors[name]) + '
';
- metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
- html.replace(/\"/g,'"') + '"';
- }
- return value;
- };
-
- var columns = [
- {
- // similar to xtype: 'rownumberer',
- dataIndex: 'pos',
- resizable: false,
- width: 23,
- sortable: false,
- align: 'right',
- hideable: false,
- menuDisabled: true,
- renderer: function(value, metaData, record, rowIdx, colIdx, store) {
- metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
- if (value >= 0) {
- return value;
- }
- return '';
- }
- },
- {
- xtype: 'checkcolumn',
- header: gettext('Enable'),
- dataIndex: 'enable',
- listeners: {
- checkchange: function(column, recordIndex, checked) {
- var record = me.getStore().getData().items[recordIndex];
- record.commit();
- var data = {};
- Ext.Array.forEach(record.getFields(), function(field) {
- data[field.name] = record.get(field.name);
- });
- if (!me.allow_iface || !data.iface) {
- delete data.iface;
- }
- me.updateRule(data);
- }
- },
- width: 50
- },
- {
- header: gettext('Type'),
- dataIndex: 'type',
- renderer: function(value, metaData, record) {
- return render_errors('type', value, metaData, record);
- },
- width: 50
- },
- {
- header: gettext('Action'),
- dataIndex: 'action',
- renderer: function(value, metaData, record) {
- return render_errors('action', value, metaData, record);
- },
- width: 80
- },
- {
- header: gettext('Macro'),
- dataIndex: 'macro',
- renderer: function(value, metaData, record) {
- return render_errors('macro', value, metaData, record);
- },
- width: 80
- }
- ];
-
- if (me.allow_iface) {
- columns.push({
- header: gettext('Interface'),
- dataIndex: 'iface',
- renderer: function(value, metaData, record) {
- return render_errors('iface', value, metaData, record);
- },
- width: 80
- });
- }
-
- columns.push(
- {
- header: gettext('Source'),
- dataIndex: 'source',
- renderer: function(value, metaData, record) {
- return render_errors('source', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Destination'),
- dataIndex: 'dest',
- renderer: function(value, metaData, record) {
- return render_errors('dest', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Protocol'),
- dataIndex: 'proto',
- renderer: function(value, metaData, record) {
- return render_errors('proto', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Dest. port'),
- dataIndex: 'dport',
- renderer: function(value, metaData, record) {
- return render_errors('dport', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Source port'),
- dataIndex: 'sport',
- renderer: function(value, metaData, record) {
- return render_errors('sport', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Log level'),
- dataIndex: 'log',
- renderer: function(value, metaData, record) {
- return render_errors('log', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comment',
- flex: 1,
- renderer: function(value, metaData, record) {
- return render_errors('comment', Ext.util.Format.htmlEncode(value), metaData, record);
- }
- }
- );
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- plugins: [
- {
- ptype: 'gridviewdragdrop',
- dragGroup: 'FWRuleDDGroup',
- dropGroup: 'FWRuleDDGroup'
- }
- ],
- listeners: {
- beforedrop: function(node, data, dropRec, dropPosition) {
- if (!dropRec) {
- return false; // empty view
- }
- var moveto = dropRec.get('pos');
- if (dropPosition === 'after') {
- moveto++;
- }
- var pos = data.records[0].get('pos');
- me.moveRule(pos, moveto);
- return 0;
- },
- itemdblclick: run_editor
- }
- },
- sortableColumns: false,
- columns: columns
- });
-
- me.callParent();
-
- if (me.base_url) {
- me.setBaseUrl(me.base_url); // load
- }
- }
-}, function() {
-
- Ext.define('pve-fw-rule', {
- extend: 'Ext.data.Model',
- fields: [ { name: 'enable', type: 'boolean' },
- 'type', 'action', 'macro', 'source', 'dest', 'proto', 'iface',
- 'dport', 'sport', 'comment', 'pos', 'digest', 'errors' ],
- idProperty: 'pos'
- });
-
-});
-Ext.define('PVE.FirewallAliasEdit', {
- extend: 'Proxmox.window.Edit',
-
- base_url: undefined,
-
- alias_name: undefined,
-
- initComponent : function() {
-
- var me = this;
-
- me.isCreate = (me.alias_name === undefined);
-
- if (me.isCreate) {
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs' + me.base_url + '/' + me.alias_name;
- me.method = 'PUT';
- }
-
- var items = [
- {
- xtype: 'textfield',
- name: me.isCreate ? 'name' : 'rename',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'cidr',
- fieldLabel: gettext('IP/CIDR'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- }
- ];
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- isCreate: me.isCreate,
- items: items
- });
-
- Ext.apply(me, {
- subject: gettext('Alias'),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- values.rename = values.name;
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-
-Ext.define('pve-fw-aliases', {
- extend: 'Ext.data.Model',
-
- fields: [ 'name', 'cidr', 'comment', 'digest' ],
- idProperty: 'name'
-});
-
-Ext.define('PVE.FirewallAliases', {
- extend: 'Ext.grid.Panel',
- alias: ['widget.pveFirewallAliases'],
-
- onlineHelp: 'pve_firewall_ip_aliases',
-
- stateful: true,
- stateId: 'grid-firewall-aliases',
-
- base_url: undefined,
-
- title: gettext('Alias'),
-
- initComponent : function() {
-
- var me = this;
-
- if (!me.base_url) {
- throw "missing base_url configuration";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-fw-aliases',
- proxy: {
- type: 'proxmox',
- url: "/api2/json" + me.base_url
- },
- sorters: {
- property: 'name',
- order: 'DESC'
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- var oldrec = sm.getSelection()[0];
- store.load(function(records, operation, success) {
- if (oldrec) {
- var rec = store.findRecord('name', oldrec.data.name);
- if (rec) {
- sm.select(rec);
- }
- }
- });
- };
-
- var run_editor = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.FirewallAliasEdit', {
- base_url: me.base_url,
- alias_name: rec.data.name
- });
-
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = Ext.create('Ext.Button', {
- text: gettext('Add'),
- handler: function() {
- var win = Ext.create('PVE.FirewallAliasEdit', {
- base_url: me.base_url
- });
- win.on('destroy', reload);
- win.show();
- }
- });
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: me.base_url + '/',
- callback: reload
- });
-
-
- Ext.apply(me, {
- store: store,
- tbar: [ me.addBtn, me.removeBtn, me.editBtn ],
- selModel: sm,
- columns: [
- { header: gettext('Name'), dataIndex: 'name', width: 100 },
- { header: gettext('IP/CIDR'), dataIndex: 'cidr', width: 100 },
- { header: gettext('Comment'), dataIndex: 'comment', renderer: Ext.String.htmlEncode, flex: 1 }
- ],
- listeners: {
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- me.on('activate', reload);
- }
-});
-Ext.define('PVE.FirewallOptions', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveFirewallOptions'],
-
- fwtype: undefined, // 'dc', 'node' or 'vm'
-
- base_url: undefined,
-
- initComponent : function() {
- /*jslint confusion: true */
-
- var me = this;
-
- if (!me.base_url) {
- throw "missing base_url configuration";
- }
-
- if (me.fwtype === 'dc' || me.fwtype === 'node' || me.fwtype === 'vm') {
- if (me.fwtype === 'node') {
- me.cwidth1 = 250;
- }
- } else {
- throw "unknown firewall option type";
- }
-
- me.rows = {};
-
- var add_boolean_row = function(name, text, defaultValue) {
- me.add_boolean_row(name, text, { defaultValue: defaultValue });
- };
- var add_integer_row = function(name, text, minValue, labelWidth) {
- me.add_integer_row(name, text, {
- minValue: minValue,
- deleteEmpty: true,
- labelWidth: labelWidth,
- renderer: function(value) {
- if (value === undefined) {
- return Proxmox.Utils.defaultText;
- }
-
- return value;
- }
- });
- };
-
- var add_log_row = function(name, labelWidth) {
- me.rows[name] = {
- header: name,
- required: true,
- defaultValue: 'nolog',
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: name,
- fieldDefaults: { labelWidth: labelWidth || 100 },
- items: {
- xtype: 'pveFirewallLogLevels',
- name: name,
- fieldLabel: name
- }
- }
- };
- };
-
- if (me.fwtype === 'node') {
- me.rows.enable = {
- required: true,
- defaultValue: 1,
- header: gettext('Firewall'),
- renderer: Proxmox.Utils.format_boolean,
- editor: {
- xtype: 'pveFirewallEnableEdit',
- defaultValue: 1
- }
- };
- add_boolean_row('nosmurfs', gettext('SMURFS filter'), 1);
- add_boolean_row('tcpflags', gettext('TCP flags filter'), 0);
- add_boolean_row('ndp', 'NDP', 1);
- add_integer_row('nf_conntrack_max', 'nf_conntrack_max', 32768, 120);
- add_integer_row('nf_conntrack_tcp_timeout_established',
- 'nf_conntrack_tcp_timeout_established', 7875, 250);
- add_log_row('log_level_in');
- add_log_row('log_level_out');
- add_log_row('tcp_flags_log_level', 120);
- add_log_row('smurf_log_level');
- } else if (me.fwtype === 'vm') {
- me.rows.enable = {
- required: true,
- defaultValue: 0,
- header: gettext('Firewall'),
- renderer: Proxmox.Utils.format_boolean,
- editor: {
- xtype: 'pveFirewallEnableEdit',
- defaultValue: 0
- }
- };
- add_boolean_row('dhcp', 'DHCP', 1);
- add_boolean_row('ndp', 'NDP', 1);
- add_boolean_row('radv', gettext('Router Advertisement'), 0);
- add_boolean_row('macfilter', gettext('MAC filter'), 1);
- add_boolean_row('ipfilter', gettext('IP filter'), 0);
- add_log_row('log_level_in');
- add_log_row('log_level_out');
- } else if (me.fwtype === 'dc') {
- add_boolean_row('enable', gettext('Firewall'), 0);
- add_boolean_row('ebtables', 'ebtables', 1);
- me.rows.log_ratelimit = {
- header: gettext('Log rate limit'),
- required: true,
- defaultValue: 'enable=0',
- editor: {
- xtype: 'pveFirewallLograteEdit'
- }
- };
- }
-
- if (me.fwtype === 'dc' || me.fwtype === 'vm') {
- me.rows.policy_in = {
- header: gettext('Input Policy'),
- required: true,
- defaultValue: 'DROP',
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Input Policy'),
- items: {
- xtype: 'pveFirewallPolicySelector',
- name: 'policy_in',
- value: 'DROP',
- fieldLabel: gettext('Input Policy')
- }
- }
- };
-
- me.rows.policy_out = {
- header: gettext('Output Policy'),
- required: true,
- defaultValue: 'ACCEPT',
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Output Policy'),
- items: {
- xtype: 'pveFirewallPolicySelector',
- name: 'policy_out',
- value: 'ACCEPT',
- fieldLabel: gettext('Output Policy')
- }
- }
- };
- }
-
- var edit_btn = new Ext.Button({
- text: gettext('Edit'),
- disabled: true,
- handler: function() { me.run_editor(); }
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- edit_btn.disable();
- return;
- }
- var rowdef = me.rows[rec.data.key];
- edit_btn.setDisabled(!rowdef.editor);
- };
-
- Ext.apply(me, {
- url: "/api2/json" + me.base_url,
- tbar: [ edit_btn ],
- editorConfig: {
- url: '/api2/extjs/' + me.base_url
- },
- listeners: {
- itemdblclick: me.run_editor,
- selectionchange: set_button_status
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
- }
-});
-
-
-Ext.define('PVE.FirewallLogLevels', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveFirewallLogLevels'],
-
- name: 'log',
- fieldLabel: gettext('Log level'),
- value: 'nolog',
- comboItems: [['nolog', 'nolog'], ['emerg', 'emerg'], ['alert', 'alert'],
- ['crit', 'crit'], ['err', 'err'], ['warning', 'warning'],
- ['notice', 'notice'], ['info', 'info'], ['debug', 'debug']]
-});
-/*
- * Left Treepanel, containing all the ressources we manage in this datacenter: server nodes, server storages, VMs and Containers
- */
-Ext.define('PVE.tree.ResourceTree', {
- extend: 'Ext.tree.TreePanel',
- alias: ['widget.pveResourceTree'],
-
- statics: {
- typeDefaults: {
- node: {
- iconCls: 'fa fa-building',
- text: gettext('Nodes')
- },
- pool: {
- iconCls: 'fa fa-tags',
- text: gettext('Resource Pool')
- },
- storage: {
- iconCls: 'fa fa-database',
- text: gettext('Storage')
- },
- qemu: {
- iconCls: 'fa fa-desktop',
- text: gettext('Virtual Machine')
- },
- lxc: {
- //iconCls: 'x-tree-node-lxc',
- iconCls: 'fa fa-cube',
- text: gettext('LXC Container')
- },
- template: {
- iconCls: 'fa fa-file-o'
- }
- }
- },
-
- useArrows: true,
-
- // private
- nodeSortFn: function(node1, node2) {
- var n1 = node1.data;
- var n2 = node2.data;
-
- if ((n1.groupbyid && n2.groupbyid) ||
- !(n1.groupbyid || n2.groupbyid)) {
-
- var tcmp;
-
- var v1 = n1.type;
- var v2 = n2.type;
-
- if ((tcmp = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)) != 0) {
- return tcmp;
- }
-
- // numeric compare for VM IDs
- // sort templates after regular VMs
- if (v1 === 'qemu' || v1 === 'lxc') {
- if (n1.template && !n2.template) {
- return 1;
- } else if (n2.template && !n1.template) {
- return -1;
- }
- v1 = n1.vmid;
- v2 = n2.vmid;
- if ((tcmp = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)) != 0) {
- return tcmp;
- }
- }
-
- return n1.id > n2.id ? 1 : (n1.id < n2.id ? -1 : 0);
- } else if (n1.groupbyid) {
- return -1;
- } else if (n2.groupbyid) {
- return 1;
- }
- },
-
- // private: fast binary search
- findInsertIndex: function(node, child, start, end) {
- var me = this;
-
- var diff = end - start;
-
- var mid = start + (diff>>1);
-
- if (diff <= 0) {
- return start;
- }
-
- var res = me.nodeSortFn(child, node.childNodes[mid]);
- if (res <= 0) {
- return me.findInsertIndex(node, child, start, mid);
- } else {
- return me.findInsertIndex(node, child, mid + 1, end);
- }
- },
-
- setIconCls: function(info) {
- var me = this;
-
- var cls = PVE.Utils.get_object_icon_class(info.type, info);
-
- if (cls !== '') {
- info.iconCls = cls;
- }
- },
-
- // add additional elements to text
- // at the moment only the usage indicator for storages
- setText: function(info) {
- var me = this;
-
- var status = '';
- if (info.type === 'storage') {
- var maxdisk = info.maxdisk;
- var disk = info.disk;
- var usage = disk/maxdisk;
- var cls = '';
- if (usage <= 1.0 && usage >= 0.0) {
- var height = (usage*100).toFixed(0);
- var neg_height = (100-usage*100).toFixed(0);
- status = '';
- status += '
';
- status += '
';
- status += '
';
- }
- }
-
- info.text = status + info.text;
- },
-
- setToolTip: function(info) {
- if (info.type === 'pool' || info.groupbyid !== undefined) {
- return;
- }
-
- var qtips = [gettext('Status') + ': ' + (info.qmpstatus || info.status)];
- if (info.hastate != 'unmanaged') {
- qtips.push(gettext('HA State') + ": " + info.hastate);
- }
-
- info.qtip = qtips.join(', ');
- },
-
- // private
- addChildSorted: function(node, info) {
- var me = this;
-
- me.setIconCls(info);
- me.setText(info);
- me.setToolTip(info);
-
- var defaults;
- if (info.groupbyid) {
- info.text = info.groupbyid;
- if (info.type === 'type') {
- defaults = PVE.tree.ResourceTree.typeDefaults[info.groupbyid];
- if (defaults && defaults.text) {
- info.text = defaults.text;
- }
- }
- }
- var child = Ext.create('PVETree', info);
-
- var cs = node.childNodes;
- var pos;
- if (cs) {
- pos = cs[me.findInsertIndex(node, child, 0, cs.length)];
- }
-
- node.insertBefore(child, pos);
-
- return child;
- },
-
- // private
- groupChild: function(node, info, groups, level) {
- var me = this;
-
- var groupby = groups[level];
- var v = info[groupby];
-
- if (v) {
- var group = node.findChild('groupbyid', v);
- if (!group) {
- var groupinfo;
- if (info.type === groupby) {
- groupinfo = info;
- } else {
- groupinfo = {
- type: groupby,
- id : groupby + "/" + v
- };
- if (groupby !== 'type') {
- groupinfo[groupby] = v;
- }
- }
- groupinfo.leaf = false;
- groupinfo.groupbyid = v;
- group = me.addChildSorted(node, groupinfo);
- }
- if (info.type === groupby) {
- return group;
- }
- if (group) {
- return me.groupChild(group, info, groups, level + 1);
- }
- }
-
- return me.addChildSorted(node, info);
- },
-
- initComponent : function() {
- var me = this;
-
- var rstore = PVE.data.ResourceStore;
- var sp = Ext.state.Manager.getProvider();
-
- if (!me.viewFilter) {
- me.viewFilter = {};
- }
-
- var pdata = {
- dataIndex: {},
- updateCount: 0
- };
-
- var store = Ext.create('Ext.data.TreeStore', {
- model: 'PVETree',
- root: {
- expanded: true,
- id: 'root',
- text: gettext('Datacenter'),
- iconCls: 'fa fa-server'
- }
- });
-
- var stateid = 'rid';
-
- var updateTree = function() {
- var tmp;
-
- store.suspendEvents();
-
- var rootnode = me.store.getRootNode();
- // remember selected node (and all parents)
- var sm = me.getSelectionModel();
-
- var lastsel = sm.getSelection()[0];
- var reselect = false;
- var parents = [];
- var p = lastsel;
- while (p && !!(p = p.parentNode)) {
- parents.push(p);
- }
-
- var index = pdata.dataIndex;
-
- var groups = me.viewFilter.groups || [];
- var filterfn = me.viewFilter.filterfn;
-
- // remove vanished or moved items
- // update in place changed items
- var key;
- for (key in index) {
- if (index.hasOwnProperty(key)) {
- var olditem = index[key];
-
- // getById() use find(), which is slow (ExtJS4 DP5)
- //var item = rstore.getById(olditem.data.id);
- var item = rstore.data.get(olditem.data.id);
-
- var changed = false;
- var moved = false;
- if (item) {
- // test if any grouping attributes changed
- // this will also catch migrated nodes
- // in server view
- var i, len;
- for (i = 0, len = groups.length; i < len; i++) {
- var attr = groups[i];
- if (item.data[attr] != olditem.data[attr]) {
- //console.log("changed " + attr);
- moved = true;
- break;
- }
- }
-
- // explicitely check for node, since
- // in some views, node is not a grouping
- // attribute
- if (!moved && item.data.node !== olditem.data.node) {
- moved = true;
- }
-
- // tree item has been updated
- if ((item.data.text !== olditem.data.text) ||
- (item.data.running !== olditem.data.running) ||
- (item.data.template !== olditem.data.template) ||
- (item.data.status !== olditem.data.status) ||
- (item.data.hastate!== olditem.data.hastate)) {
- //console.log("changed node/text/running " + olditem.data.id);
- changed = true;
- }
-
- // fixme: also test filterfn()?
- }
-
- if (changed) {
- olditem.beginEdit();
- //console.log("REM UPDATE UID: " + key + " ITEM " + item.data.running);
- var info = olditem.data;
- Ext.apply(info, item.data);
- me.setIconCls(info);
- me.setText(info);
- me.setToolTip(info);
- olditem.commit();
- }
- if ((!item || moved) && olditem.isLeaf()) {
- //console.log("REM UID: " + key + " ITEM " + olditem.data.id);
- delete index[key];
- var parentNode = olditem.parentNode;
- // when the selected item disappears,
- // we have to deselect it here, and reselect it
- // later
- if (lastsel && olditem.data.id === lastsel.data.id) {
- reselect = true;
- sm.deselect(olditem);
- }
- // since the store events are suspended, we
- // manually remove the item from the store also
- store.remove(olditem);
- parentNode.removeChild(olditem, true);
- }
- }
- }
-
- // add new items
- rstore.each(function(item) {
- var olditem = index[item.data.id];
- if (olditem) {
- return;
- }
-
- if (filterfn && !filterfn(item)) {
- return;
- }
-
- //console.log("ADD UID: " + item.data.id);
-
- var info = Ext.apply({ leaf: true }, item.data);
-
- var child = me.groupChild(rootnode, info, groups, 0);
- if (child) {
- index[item.data.id] = child;
- }
- });
-
- store.resumeEvents();
- store.fireEvent('refresh', store);
-
- // select parent node is selection vanished
- if (lastsel && !rootnode.findChild('id', lastsel.data.id, true)) {
- lastsel = rootnode;
- while (!!(p = parents.shift())) {
- if (!!(tmp = rootnode.findChild('id', p.data.id, true))) {
- lastsel = tmp;
- break;
- }
- }
- me.selectById(lastsel.data.id);
- } else if (lastsel && reselect) {
- me.selectById(lastsel.data.id);
- }
-
- // on first tree load set the selection from the stateful provider
- if (!pdata.updateCount) {
- rootnode.expand();
- me.applyState(sp.get(stateid));
- }
-
- pdata.updateCount++;
- };
-
- var statechange = function(sp, key, value) {
- if (key === stateid) {
- me.applyState(value);
- }
- };
-
- sp.on('statechange', statechange);
-
- Ext.apply(me, {
- allowSelection: true,
- store: store,
- viewConfig: {
- // note: animate cause problems with applyState
- animate: false
- },
- //useArrows: true,
- //rootVisible: false,
- //title: 'Resource Tree',
- listeners: {
- itemcontextmenu: PVE.Utils.createCmdMenu,
- destroy: function() {
- rstore.un("load", updateTree);
- },
- beforecellmousedown: function (tree, td, cellIndex, record, tr, rowIndex, ev) {
- var sm = me.getSelectionModel();
- // disable selection when right clicking
- // except the record is already selected
- me.allowSelection = (ev.button !== 2) || sm.isSelected(record);
- },
- beforeselect: function (tree, record, index, eopts) {
- var allow = me.allowSelection;
- me.allowSelection = true;
- return allow;
- },
- itemdblclick: PVE.Utils.openTreeConsole
- },
- setViewFilter: function(view) {
- me.viewFilter = view;
- me.clearTree();
- updateTree();
- },
- setDatacenterText: function(clustername) {
- var rootnode = me.store.getRootNode();
-
- var rnodeText = gettext('Datacenter');
- if (clustername !== undefined) {
- rnodeText += ' (' + clustername + ')';
- }
-
- rootnode.beginEdit();
- rootnode.data.text = rnodeText;
- rootnode.commit();
- },
- clearTree: function() {
- pdata.updateCount = 0;
- var rootnode = me.store.getRootNode();
- rootnode.collapse();
- rootnode.removeAll();
- pdata.dataIndex = {};
- me.getSelectionModel().deselectAll();
- },
- selectExpand: function(node) {
- var sm = me.getSelectionModel();
- if (!sm.isSelected(node)) {
- sm.select(node);
- var cn = node;
- while (!!(cn = cn.parentNode)) {
- if (!cn.isExpanded()) {
- cn.expand();
- }
- }
- me.getView().focusRow(node);
- }
- },
- selectById: function(nodeid) {
- var rootnode = me.store.getRootNode();
- var sm = me.getSelectionModel();
- var node;
- if (nodeid === 'root') {
- node = rootnode;
- } else {
- node = rootnode.findChild('id', nodeid, true);
- }
- if (node) {
- me.selectExpand(node);
- }
- return node;
- },
- applyState : function(state) {
- var sm = me.getSelectionModel();
- if (state && state.value) {
- me.selectById(state.value);
- } else {
- sm.deselectAll();
- }
- }
- });
-
- me.callParent();
-
- var sm = me.getSelectionModel();
- sm.on('select', function(sm, n) {
- sp.set(stateid, { value: n.data.id});
- });
-
- rstore.on("load", updateTree);
- rstore.startUpdate();
- //rstore.stopUpdate();
- }
-
-});
-Ext.define('pve-fw-ipsets', {
- extend: 'Ext.data.Model',
- fields: [ 'name', 'comment', 'digest' ],
- idProperty: 'name'
-});
-
-Ext.define('PVE.IPSetList', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveIPSetList',
-
- stateful: true,
- stateId: 'grid-firewall-ipsetlist',
-
- ipset_panel: undefined,
-
- base_url: undefined,
-
- addBtn: undefined,
- removeBtn: undefined,
- editBtn: undefined,
-
- initComponent: function() {
-
- var me = this;
-
- if (me.ipset_panel == undefined) {
- throw "no rule panel specified";
- }
-
- if (me.base_url == undefined) {
- throw "no base_url specified";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-fw-ipsets',
- proxy: {
- type: 'proxmox',
- url: "/api2/json" + me.base_url
- },
- sorters: {
- property: 'name',
- order: 'DESC'
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- var oldrec = sm.getSelection()[0];
- store.load(function(records, operation, success) {
- if (oldrec) {
- var rec = store.findRecord('name', oldrec.data.name);
- if (rec) {
- sm.select(rec);
- }
- }
- });
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var win = Ext.create('Proxmox.window.Edit', {
- subject: "IPSet '" + rec.data.name + "'",
- url: me.base_url,
- method: 'POST',
- digest: rec.data.digest,
- items: [
- {
- xtype: 'hiddenfield',
- name: 'rename',
- value: rec.data.name
- },
- {
- xtype: 'textfield',
- name: 'name',
- value: rec.data.name,
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'comment',
- value: rec.data.comment,
- fieldLabel: gettext('Comment')
- }
- ]
- });
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = new Proxmox.button.Button({
- text: gettext('Create'),
- handler: function() {
- sm.deselectAll();
- var win = Ext.create('Proxmox.window.Edit', {
- subject: 'IPSet',
- url: me.base_url,
- method: 'POST',
- items: [
- {
- xtype: 'textfield',
- name: 'name',
- value: '',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'comment',
- value: '',
- fieldLabel: gettext('Comment')
- }
- ]
- });
- win.show();
- win.on('destroy', reload);
-
- }
- });
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: me.base_url + '/',
- callback: reload
- });
-
- Ext.apply(me, {
- store: store,
- tbar: [ 'IPSet: ', me.addBtn, me.removeBtn, me.editBtn ],
- selModel: sm,
- columns: [
- { header: 'IPSet', dataIndex: 'name', width: '100' },
- { header: gettext('Comment'), dataIndex: 'comment', renderer: Ext.String.htmlEncode, flex: 1 }
- ],
- listeners: {
- itemdblclick: run_editor,
- select: function(sm, rec) {
- var url = me.base_url + '/' + rec.data.name;
- me.ipset_panel.setBaseUrl(url);
- },
- deselect: function() {
- me.ipset_panel.setBaseUrl(undefined);
- },
- show: reload
- }
- });
-
- me.callParent();
-
- store.load();
- }
-});
-
-Ext.define('PVE.IPSetCidrEdit', {
- extend: 'Proxmox.window.Edit',
-
- cidr: undefined,
-
- initComponent : function() {
-
- var me = this;
-
- me.isCreate = (me.cidr === undefined);
-
-
- if (me.isCreate) {
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs' + me.base_url + '/' + me.cidr;
- me.method = 'PUT';
- }
-
- var column1 = [];
-
- if (me.isCreate) {
- if (!me.list_refs_url) {
- throw "no alias_base_url specified";
- }
-
- column1.push({
- xtype: 'pveIPRefSelector',
- name: 'cidr',
- ref_type: 'alias',
- autoSelect: false,
- editable: true,
- base_url: me.list_refs_url,
- value: '',
- fieldLabel: gettext('IP/CIDR')
- });
- } else {
- column1.push({
- xtype: 'displayfield',
- name: 'cidr',
- value: '',
- fieldLabel: gettext('IP/CIDR')
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- isCreate: me.isCreate,
- column1: column1,
- column2: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'nomatch',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: 'nomatch'
- }
- ],
- columnB: [
- {
- xtype: 'textfield',
- name: 'comment',
- value: '',
- fieldLabel: gettext('Comment')
- }
- ]
- });
-
- Ext.apply(me, {
- subject: gettext('IP/CIDR'),
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-
-Ext.define('PVE.IPSetGrid', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveIPSetGrid',
-
- stateful: true,
- stateId: 'grid-firewall-ipsets',
-
- base_url: undefined,
- list_refs_url: undefined,
-
- addBtn: undefined,
- removeBtn: undefined,
- editBtn: undefined,
-
- setBaseUrl: function(url) {
- var me = this;
-
- me.base_url = url;
-
- if (url === undefined) {
- me.addBtn.setDisabled(true);
- me.store.removeAll();
- } else {
- me.addBtn.setDisabled(false);
- me.removeBtn.baseurl = url + '/';
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json' + url
- });
-
- me.store.load();
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.list_refs_url) {
- throw "no1 list_refs_url specified";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-ipset'
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var win = Ext.create('PVE.IPSetCidrEdit', {
- base_url: me.base_url,
- cidr: rec.data.cidr
- });
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = new Proxmox.button.Button({
- text: gettext('Add'),
- disabled: true,
- handler: function() {
- if (!me.base_url) {
- return;
- }
- var win = Ext.create('PVE.IPSetCidrEdit', {
- base_url: me.base_url,
- list_refs_url: me.list_refs_url
- });
- win.show();
- win.on('destroy', reload);
- }
- });
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: me.base_url + '/',
- callback: reload
- });
-
- var render_errors = function(value, metaData, record) {
- var errors = record.data.errors;
- if (errors) {
- var msg = errors.cidr || errors.nomatch;
- if (msg) {
- metaData.tdCls = 'proxmox-invalid-row';
- var html = '' + Ext.htmlEncode(msg) + '
';
- metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
- html.replace(/\"/g,'"') + '"';
- }
- }
- return value;
- };
-
- Ext.apply(me, {
- tbar: [ 'IP/CIDR: ', me.addBtn, me.removeBtn, me.editBtn ],
- store: store,
- selModel: sm,
- listeners: {
- itemdblclick: run_editor
- },
- columns: [
- {
- xtype: 'rownumberer'
- },
- {
- header: gettext('IP/CIDR'),
- dataIndex: 'cidr',
- width: 150,
- renderer: function(value, metaData, record) {
- value = render_errors(value, metaData, record);
- if (record.data.nomatch) {
- return '! ' + value;
- }
- return value;
- }
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comment',
- flex: 1,
- renderer: function(value) {
- return Ext.util.Format.htmlEncode(value);
- }
- }
- ]
- });
-
- me.callParent();
-
- if (me.base_url) {
- me.setBaseUrl(me.base_url); // load
- }
- }
-}, function() {
-
- Ext.define('pve-ipset', {
- extend: 'Ext.data.Model',
- fields: [ { name: 'nomatch', type: 'boolean' },
- 'cidr', 'comment', 'errors' ],
- idProperty: 'cidr'
- });
-
-});
-
-Ext.define('PVE.IPSet', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveIPSet',
-
- title: 'IPSet',
-
- onlineHelp: 'pve_firewall_ip_sets',
-
- list_refs_url: undefined,
-
- initComponent: function() {
- var me = this;
-
- if (!me.list_refs_url) {
- throw "no list_refs_url specified";
- }
-
- var ipset_panel = Ext.createWidget('pveIPSetGrid', {
- region: 'center',
- list_refs_url: me.list_refs_url,
- border: false
- });
-
- var ipset_list = Ext.createWidget('pveIPSetList', {
- region: 'west',
- ipset_panel: ipset_panel,
- base_url: me.base_url,
- width: '50%',
- border: false,
- split: true
- });
-
- Ext.apply(me, {
- layout: 'border',
- items: [ ipset_list, ipset_panel ],
- listeners: {
- show: function() {
- ipset_list.fireEvent('show', ipset_list);
- }
- }
- });
-
- me.callParent();
- }
-});
-/*
- * Base class for all the multitab config panels
- *
- * How to use this:
- *
- * You create a subclass of this, and then define your wanted tabs
- * as items like this:
- *
- * items: [{
- * title: "myTitle",
- * xytpe: "somextype",
- * iconCls: 'fa fa-icon',
- * groups: ['somegroup'],
- * expandedOnInit: true,
- * itemId: 'someId'
- * }]
- *
- * this has to be in the declarative syntax, else we
- * cannot save them for later
- * (so no Ext.create or Ext.apply of an item in the subclass)
- *
- * the groups array expects the itemids of the items
- * which are the parents, which have to come before they
- * are used
- *
- * if you want following the tree:
- *
- * Option1
- * Option2
- * -> SubOption1
- * -> SubSubOption1
- *
- * the suboption1 group array has to look like this:
- * groups: ['itemid-of-option2']
- *
- * and of subsuboption1:
- * groups: ['itemid-of-option2', 'itemid-of-suboption1']
- *
- * setting the expandedOnInit determines if the item/group is expanded
- * initially (false by default)
- */
-Ext.define('PVE.panel.Config', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pvePanelConfig',
-
- showSearch: true, // add a ressource grid with a search button as first tab
- viewFilter: undefined, // a filter to pass to that ressource grid
-
- tbarSpacing: true, // if true, adds a spacer after the title in tbar
-
- dockedItems: [{
- // this is needed for the overflow handler
- xtype: 'toolbar',
- overflowHandler: 'scroller',
- dock: 'left',
- style: {
- backgroundColor: '#f5f5f5',
- padding: 0,
- margin: 0
- },
- items: {
- xtype: 'treelist',
- itemId: 'menu',
- ui: 'nav',
- expanderOnly: true,
- expanderFirst: false,
- animation: false,
- singleExpand: false,
- listeners: {
- selectionchange: function(treeList, selection) {
- var me = this.up('panel');
- me.suspendLayout = true;
- me.activateCard(selection.data.id);
- me.suspendLayout = false;
- me.updateLayout();
- },
- itemclick: function(treelist, info) {
- var olditem = treelist.getSelection();
- var newitem = info.node;
-
- // when clicking on the expand arrow,
- // we dont select items, but still want
- // the original behaviour
- if (info.select === false) {
- return;
- }
-
- // if you click on a different item which is open,
- // leave it open
- // else toggle the clicked item
- if (olditem.data.id !== newitem.data.id &&
- newitem.data.expanded === true) {
- info.toggle = false;
- } else {
- info.toggle = true;
- }
- }
- }
- }
- },
- {
- xtype: 'toolbar',
- itemId: 'toolbar',
- dock: 'top',
- height: 36,
- overflowHandler: 'scroller'
- }],
-
- firstItem: '',
- layout: 'card',
- border: 0,
-
- // used for automated test
- selectById: function(cardid) {
- var me = this;
-
- var root = me.store.getRoot();
- var selection = root.findChild('id', cardid, true);
-
- if (selection) {
- selection.expand();
- var menu = me.down('#menu');
- menu.setSelection(selection);
- return cardid;
- }
- },
-
- activateCard: function(cardid) {
- var me = this;
- if (me.savedItems[cardid]) {
- var curcard = me.getLayout().getActiveItem();
- var newcard = me.add(me.savedItems[cardid]);
- me.helpButton.setOnlineHelp(newcard.onlineHelp || me.onlineHelp);
- if (curcard) {
- me.setActiveItem(cardid);
- me.remove(curcard, true);
-
- // trigger state change
-
- var ncard = cardid;
- // Note: '' is alias for first tab.
- // First tab can be 'search' or something else
- if (cardid === me.firstItem) {
- ncard = '';
- }
- if (me.hstateid) {
- me.sp.set(me.hstateid, { value: ncard });
- }
- }
- }
- },
-
- initComponent: function() {
- var me = this;
-
- var stateid = me.hstateid;
-
- me.sp = Ext.state.Manager.getProvider();
-
- var activeTab; // leaving this undefined means items[0] will be the default tab
-
- if (stateid) {
- var state = me.sp.get(stateid);
- if (state && state.value) {
- // if this tab does not exists, it chooses the first
- activeTab = state.value;
- }
- }
-
- // get title
- var title = me.title || me.pveSelNode.data.text;
- me.title = undefined;
-
- // create toolbar
- var tbar = me.tbar || [];
- me.tbar = undefined;
-
- if (!me.onlineHelp) {
- switch(me.pveSelNode.data.id) {
- case 'type/storage':me.onlineHelp = 'chapter-pvesm.html'; break;
- case 'type/qemu':me.onlineHelp = 'chapter-qm.html'; break;
- case 'type/lxc':me.onlineHelp = 'chapter-pct.html'; break;
- case 'type/pool':me.onlineHelp = 'chapter-pveum.html#_pools'; break;
- case 'type/node':me.onlineHelp = 'chapter-sysadmin.html'; break;
- }
- }
-
- if (me.tbarSpacing) {
- tbar.unshift('->');
- }
- tbar.unshift({
- xtype: 'tbtext',
- text: title,
- baseCls: 'x-panel-header-text'
- });
-
- me.helpButton = Ext.create('Proxmox.button.Help', {
- hidden: false,
- listenToGlobalEvent: false,
- onlineHelp: me.onlineHelp || undefined
- });
-
- tbar.push(me.helpButton);
-
- me.dockedItems[1].items = tbar;
-
- // include search tab
- me.items = me.items || [];
- if (me.showSearch) {
- me.items.unshift({
- itemId: 'search',
- title: gettext('Search'),
- iconCls: 'fa fa-search',
- xtype: 'pveResourceGrid',
- pveSelNode: me.pveSelNode
- });
- }
-
- me.savedItems = {};
- /*jslint confusion:true*/
- if (me.items[0]) {
- me.firstItem = me.items[0].itemId;
- }
- /*jslint confusion:false*/
-
- me.store = Ext.create('Ext.data.TreeStore', {
- root: {
- expanded: true
- }
- });
- var root = me.store.getRoot();
- me.items.forEach(function(item){
- var treeitem = Ext.create('Ext.data.TreeModel',{
- id: item.itemId,
- text: item.title,
- iconCls: item.iconCls,
- leaf: true,
- expanded: item.expandedOnInit
- });
- item.header = false;
- if (me.savedItems[item.itemId] !== undefined) {
- throw "itemId already exists, please use another";
- }
- me.savedItems[item.itemId] = item;
-
- var group;
- var curnode = root;
-
- // get/create the group items
- while (Ext.isArray(item.groups) && item.groups.length > 0) {
- group = item.groups.shift();
-
- var child = curnode.findChild('id', group);
- if (child === null) {
- // did not find the group item
- // so add it where we are
- break;
- }
- curnode = child;
- }
-
- // insert the item
-
- // lets see if it already exists
- var node = curnode.findChild('id', item.itemId);
-
- if (node === null) {
- curnode.appendChild(treeitem);
- } else {
- // should not happen!
- throw "id already exists";
- }
- });
-
- delete me.items;
- me.defaults = me.defaults || {};
- Ext.apply(me.defaults, {
- pveSelNode: me.pveSelNode,
- viewFilter: me.viewFilter,
- workspace: me.workspace,
- border: 0
- });
-
- me.callParent();
-
- var menu = me.down('#menu');
- var selection = root.findChild('id', activeTab, true) || root.firstChild;
- var node = selection;
- while (node !== root) {
- node.expand();
- node = node.parentNode;
- }
- menu.setStore(me.store);
- menu.setSelection(selection);
-
- // on a state change,
- // select the new item
- var statechange = function(sp, key, state) {
- // it the state change is for this panel
- if (stateid && (key === stateid) && state) {
- // get active item
- var acard = me.getLayout().getActiveItem().itemId;
- // get the itemid of the new value
- var ncard = state.value || me.firstItem;
- if (ncard && (acard != ncard)) {
- // select the chosen item
- menu.setSelection(root.findChild('id', ncard, true) || root.firstChild);
- }
- }
- };
-
- if (stateid) {
- me.mon(me.sp, 'statechange', statechange);
- }
- }
-});
-Ext.define('PVE.grid.BackupView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveBackupView'],
-
- onlineHelp: 'chapter_vzdump',
-
- stateful: true,
- stateId: 'grid-guest-backup',
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var vmtype = me.pveSelNode.data.type;
- if (!vmtype) {
- throw "no VM type specified";
- }
-
- var vmtypeFilter;
- if (vmtype === 'openvz') {
- vmtypeFilter = function(item) {
- return item.data.volid.match(':backup/vzdump-openvz-');
- };
- } else if (vmtype === 'lxc') {
- vmtypeFilter = function(item) {
- return item.data.volid.match(':backup/vzdump-lxc-');
- };
- } else if (vmtype === 'qemu') {
- vmtypeFilter = function(item) {
- return item.data.volid.match(':backup/vzdump-qemu-');
- };
- } else {
- throw "unsupported VM type '" + vmtype + "'";
- }
-
- var searchFilter = {
- property: 'volid',
- // on initial store display only our vmid backups
- // surround with minus sign to prevent the 2016 VMID bug
- value: vmtype + '-' + vmid + '-',
- anyMatch: true,
- caseSensitive: false
- };
-
- me.store = Ext.create('Ext.data.Store', {
- model: 'pve-storage-content',
- sorters: {
- property: 'volid',
- order: 'DESC'
- },
- filters: [
- vmtypeFilter,
- searchFilter
- ]
- });
-
- var reload = Ext.Function.createBuffered(function() {
- if (me.store) {
- me.store.load();
- }
- }, 100);
-
- var setStorage = function(storage) {
- var url = '/api2/json/nodes/' + nodename + '/storage/' + storage + '/content';
- url += '?content=backup';
-
- me.store.setProxy({
- type: 'proxmox',
- url: url
- });
-
- reload();
- };
-
- var storagesel = Ext.create('PVE.form.StorageSelector', {
- nodename: nodename,
- fieldLabel: gettext('Storage'),
- labelAlign: 'right',
- storageContent: 'backup',
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- setStorage(value);
- }
- }
- });
-
- var storagefilter = Ext.create('Ext.form.field.Text', {
- fieldLabel: gettext('Search'),
- labelWidth: 50,
- labelAlign: 'right',
- enableKeyEvents: true,
- value: searchFilter.value,
- listeners: {
- buffer: 500,
- keyup: function(field) {
- me.store.clearFilter(true);
- searchFilter.value = field.getValue();
- me.store.filter([
- vmtypeFilter,
- searchFilter
- ]);
- }
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var backup_btn = Ext.create('Ext.button.Button', {
- text: gettext('Backup now'),
- handler: function() {
- var win = Ext.create('PVE.window.Backup', {
- nodename: nodename,
- vmid: vmid,
- vmtype: vmtype,
- storage: storagesel.getValue(),
- listeners : {
- close: function() {
- reload();
- }
- }
- });
- win.show();
- }
- });
-
- var restore_btn = Ext.create('Proxmox.button.Button', {
- text: gettext('Restore'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- return !!rec;
- },
- handler: function(b, e, rec) {
- var volid = rec.data.volid;
-
- var win = Ext.create('PVE.window.Restore', {
- nodename: nodename,
- vmid: vmid,
- volid: rec.data.volid,
- volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
- vmtype: vmtype
- });
- win.show();
- win.on('destroy', reload);
- }
- });
-
- var delete_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- dangerous: true,
- confirmMsg: function(rec) {
- var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.volid + "'");
- msg += " " + gettext('This will permanently erase all data.');
-
- return msg;
- },
- getUrl: function(rec) {
- var storage = storagesel.getValue();
- return '/nodes/' + nodename + '/storage/' + storage + '/content/' + rec.data.volid;
- },
- callback: function() {
- reload();
- }
- });
-
- var config_btn = Ext.create('Proxmox.button.Button', {
- text: gettext('Show Configuration'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- return !!rec;
- },
- handler: function(b, e, rec) {
- var storage = storagesel.getValue();
- if (!storage) {
- return;
- }
-
- var win = Ext.create('PVE.window.BackupConfig', {
- volume: rec.data.volid,
- pveSelNode: me.pveSelNode
- });
-
- win.show();
- }
- });
-
- Ext.apply(me, {
- selModel: sm,
- tbar: [ backup_btn, restore_btn, delete_btn,config_btn, '->', storagesel, storagefilter ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- renderer: PVE.Utils.render_storage_content,
- dataIndex: 'volid'
- },
- {
- header: gettext('Format'),
- width: 100,
- dataIndex: 'format'
- },
- {
- header: gettext('Size'),
- width: 100,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- }
- ]
- });
-
- me.callParent();
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.CephCreateFS', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveCephCreateFS',
-
- showTaskViewer: true,
- onlineHelp: 'pveceph_fs_create',
-
- subject: 'Ceph FS',
- isCreate: true,
- method: 'POST',
-
- setFSName: function(fsName) {
- var me = this;
-
- if (fsName === '' || fsName === undefined) {
- fsName = 'cephfs';
- }
-
- me.url = "/nodes/" + me.nodename + "/ceph/fs/" + fsName;
- },
-
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Name'),
- name: 'name',
- value: 'cephfs',
- listeners: {
- change: function(f, value) {
- this.up('pveCephCreateFS').setFSName(value);
- }
- },
- submitValue: false, // already encoded in apicall URL
- emptyText: 'cephfs'
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: 'Placement Groups',
- name: 'pg_num',
- value: 128,
- emptyText: 128,
- minValue: 8,
- maxValue: 32768,
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Add Storage'),
- value: true,
- name: 'add-storage'
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
- me.setFSName();
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.CephCreateMDS', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveCephCreateMDS',
-
- showProgress: true,
- onlineHelp: 'pveceph_fs_mds',
-
- subject: 'Ceph MDS',
- isCreate: true,
- method: 'POST',
-
- setNode: function(nodename) {
- var me = this;
-
- me.nodename = nodename;
- me.url = "/nodes/" + nodename + "/ceph/mds/" + nodename;
- },
-
- items: [
- {
- xtype: 'pveNodeSelector',
- fieldLabel: gettext('Node'),
- selectCurNode: true,
- submitValue: false,
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- this.up('pveCephCreateMDS').setNode(value);
- }
- }
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
- me.setNode(me.nodename);
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.NodeCephFSPanel', {
- extend: 'Ext.panel.Panel',
- xtype: 'pveNodeCephFSPanel',
- mixins: ['Proxmox.Mixin.CBind'],
-
- title: gettext('CephFS'),
- onlineHelp: 'pveceph_fs',
-
- border: false,
- defaults: {
- border: false,
- cbind: {
- nodename: '{nodename}'
- }
- },
-
- viewModel: {
- parent: null,
- data: {
- cephfsConfigured: false,
- mdsCount: 0
- },
- formulas: {
- canCreateFS: function(get) {
- return (!get('cephfsConfigured') && get('mdsCount') > 0);
- }
- }
- },
-
- items: [
- {
- xtype: 'grid',
- emptyText: Ext.String.format(gettext('No {0} configured.'), 'CephFS'),
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.rstore = Ext.create('Proxmox.data.UpdateStore', {
- autoLoad: true,
- xtype: 'update',
- interval: 5 * 1000,
- autoStart: true,
- storeid: 'pve-ceph-fs',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + view.nodename + '/ceph/fs'
- },
- model: 'pve-ceph-fs'
- });
- view.setStore(Ext.create('Proxmox.data.DiffStore', {
- rstore: view.rstore,
- sorters: {
- property: 'name',
- order: 'DESC'
- }
- }));
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error){
- me.rstore.stopUpdate();
- PVE.Utils.showCephInstallOrMask(me.ownerCt, error.statusText, view.nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.rstore.startUpdate();
- });
- }
- );
- });
- view.rstore.on('load', this.onLoad, this);
- view.on('destroy', view.rstore.stopUpdate);
- },
-
- onCreate: function() {
- var view = this.getView();
- view.rstore.stopUpdate();
- var win = Ext.create('PVE.CephCreateFS', {
- autoShow: true,
- nodename: view.nodename,
- listeners: {
- destroy: function() {
- view.rstore.startUpdate();
- }
- }
- });
- },
-
- onLoad: function(store, records, success) {
- var vm = this.getViewModel();
- if (!(success && records && records.length > 0)) {
- vm.set('cephfsConfigured', false);
- return;
- }
- vm.set('cephfsConfigured', true);
- }
- },
- tbar: [
- {
- text: gettext('Create CephFS'),
- reference: 'createButton',
- handler: 'onCreate',
- bind: {
- // only one CephFS per Ceph cluster makes sense for now
- disabled: '{!canCreateFS}'
- }
- }
- ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- dataIndex: 'name'
- },
- {
- header: 'Data Pool',
- flex: 1,
- dataIndex: 'data_pool'
- },
- {
- header: 'Metadata Pool',
- flex: 1,
- dataIndex: 'metadata_pool'
- }
- ],
- cbind: {
- nodename: '{nodename}'
- }
- },
- {
- xtype: 'grid',
- title: gettext('Metadata Servers'),
- emptyText: Ext.String.format(gettext('No {0} configured.'), 'MDS'),
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.rstore = Ext.create('Proxmox.data.UpdateStore', {
- autoLoad: true,
- xtype: 'update',
- interval: 3 * 1000,
- autoStart: true,
- storeid: 'pve-ceph-mds',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/'+ view.nodename +'/ceph/mds'
- },
- model: 'pve-ceph-mds'
- });
- view.setStore(Ext.create('Proxmox.data.DiffStore', {
- rstore: view.rstore,
- sorters: {
- property: 'id',
- order: 'DESC'
- }
- }));
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error){
- me.rstore.stopUpdate();
- PVE.Utils.showCephInstallOrMask(me.ownerCt, error.statusText, view.nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.rstore.startUpdate();
- });
- }
- );
- });
- view.rstore.on('load', this.onLoad, this);
- view.on('destroy', view.rstore.stopUpdate);
- },
- onLoad: function(store, records, success) {
- var vm = this.getViewModel();
- if (!success || !records) {
- vm.set('mdsCount', 0);
- return;
- }
- vm.set('mdsCount', records.length);
- },
- onCreateMDS: function() {
- var view = this.getView();
- view.rstore.stopUpdate();
- var win = Ext.create('PVE.CephCreateMDS', {
- autoShow: true,
- nodename: view.nodename,
- listeners: {
- destroy: function() {
- view.rstore.startUpdate();
- }
- }
- });
- }
- },
- tbar: [
- {
- text: gettext('Create MDS'),
- reference: 'createButton',
- handler: 'onCreateMDS'
- },
- {
- text: gettext('Destroy MDS'),
- xtype: 'proxmoxStdRemoveButton',
- getUrl: function(rec) {
- if (!rec.data.host) {
- Ext.Msg.alert(gettext('Error'), "entry has no host");
- return;
- }
- return "/nodes/" + rec.data.host + "/ceph/mds/" + rec.data.name;
- },
- callback: function(options, success, response) {
- if (!success) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- return;
- }
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- }
- ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- dataIndex: 'name'
- },
- {
- header: gettext('Host'),
- flex: 1,
- dataIndex: 'host'
- },
- {
- header: gettext('Address'),
- flex: 1,
- dataIndex: 'addr'
- },
- {
- header: gettext('State'),
- flex: 1,
- dataIndex: 'state'
- }
- ],
- cbind: {
- nodename: '{nodename}'
- }
- }
- ]
-}, function() {
- Ext.define('pve-ceph-mds', {
- extend: 'Ext.data.Model',
- fields: [ 'name', 'host', 'addr', 'state' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/localhost/ceph/mds"
- },
- idProperty: 'name'
- });
- Ext.define('pve-ceph-fs', {
- extend: 'Ext.data.Model',
- fields: [ 'name', 'data_pool', 'metadata_pool' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/localhost/ceph/fs"
- },
- idProperty: 'name'
- });
-});
-Ext.define('PVE.CephCreatePool', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveCephCreatePool',
-
- showProgress: true,
- onlineHelp: 'pve_ceph_pools',
-
- subject: 'Ceph Pool',
- isCreate: true,
- method: 'POST',
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Name'),
- name: 'name',
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Size'),
- name: 'size',
- value: 3,
- minValue: 1,
- maxValue: 7,
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Min. Size'),
- name: 'min_size',
- value: 2,
- minValue: 1,
- maxValue: 7,
- allowBlank: false
- },
- {
- xtype: 'pveCephRuleSelector',
- fieldLabel: 'Crush Rule', // do not localize
- name: 'crush_rule',
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: 'pg_num',
- name: 'pg_num',
- value: 128,
- minValue: 8,
- maxValue: 32768,
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Add Storage'),
- name: 'add_storages'
- }
- ],
- initComponent : function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- url: "/nodes/" + me.nodename + "/ceph/pools",
- defaults: {
- nodename: me.nodename
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.CephPoolList', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pveNodeCephPoolList',
-
- onlineHelp: 'chapter_pveceph',
- stateful: true,
- stateId: 'grid-ceph-pools',
- bufferedRenderer: false,
- features: [ { ftype: 'summary'} ],
- columns: [
- {
- header: gettext('Name'),
- width: 100,
- sortable: true,
- dataIndex: 'pool_name'
- },
- {
- header: gettext('Size') + '/min',
- width: 80,
- sortable: false,
- renderer: function(v, meta, rec) {
- return v + '/' + rec.data.min_size;
- },
- dataIndex: 'size'
- },
- {
- header: 'pg_num',
- width: 100,
- sortable: false,
- dataIndex: 'pg_num'
- },
- {
- header: 'rule',
- width: 50,
- sortable: false,
- dataIndex: 'crush_rule'
- },
- {
- header: 'rule_name',
- width: 50,
- sortable: false,
- dataIndex: 'crush_rule_name'
- },
- {
- header: gettext('Used'),
- columns: [
- {
- header: '%',
- width: 80,
- sortable: true,
- align: 'right',
- renderer: Ext.util.Format.numberRenderer('0.00'),
- dataIndex: 'percent_used',
- summaryType: 'sum',
- summaryRenderer: Ext.util.Format.numberRenderer('0.00')
- },
- {
- header: gettext('Total'),
- width: 100,
- sortable: true,
- renderer: PVE.Utils.render_size,
- align: 'right',
- dataIndex: 'bytes_used',
- summaryType: 'sum',
- summaryRenderer: PVE.Utils.render_size
- }
- ]
- }
- ],
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var rstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 3000,
- storeid: 'ceph-pool-list' + nodename,
- model: 'ceph-pool-list',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/ceph/pools"
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', { rstore: rstore });
-
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(me, rstore, regex, function(me, error){
- me.store.rstore.stopUpdate();
- PVE.Utils.showCephInstallOrMask(me, error.statusText, nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.store.rstore.startUpdate();
- });
- }
- );
- });
-
- var create_btn = new Ext.Button({
- text: gettext('Create'),
- handler: function() {
- var win = Ext.create('PVE.CephCreatePool', {
- nodename: nodename
- });
- win.show();
- win.on('destroy', function() {
- rstore.load();
- });
- }
- });
-
- var destroy_btn = Ext.create('Proxmox.button.Button', {
- text: gettext('Destroy'),
- selModel: sm,
- disabled: true,
- handler: function() {
- var rec = sm.getSelection()[0];
-
- if (!rec.data.pool_name) {
- return;
- }
- var base_url = '/nodes/' + nodename + '/ceph/pools/' +
- rec.data.pool_name;
-
- var win = Ext.create('PVE.window.SafeDestroy', {
- showProgress: true,
- url: base_url,
- params: {
- remove_storages: 1
- },
- item: { type: 'CephPool', id: rec.data.pool_name }
- }).show();
- win.on('destroy', function() {
- rstore.load();
- });
- }
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [ create_btn, destroy_btn ],
- listeners: {
- activate: rstore.startUpdate,
- destroy: rstore.stopUpdate
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('ceph-pool-list', {
- extend: 'Ext.data.Model',
- fields: [ 'pool_name',
- { name: 'pool', type: 'integer'},
- { name: 'size', type: 'integer'},
- { name: 'min_size', type: 'integer'},
- { name: 'pg_num', type: 'integer'},
- { name: 'bytes_used', type: 'integer'},
- { name: 'percent_used', type: 'number'},
- { name: 'crush_rule', type: 'integer'},
- { name: 'crush_rule_name', type: 'string'}
- ],
- idProperty: 'pool_name'
- });
-});
-
-Ext.define('PVE.form.CephRuleSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveCephRuleSelector',
-
- allowBlank: false,
- valueField: 'name',
- displayField: 'name',
- editable: false,
- queryMode: 'local',
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: ['name'],
- sorters: 'name',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/ceph/rules'
- }
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- store.load({
- callback: function(rec, op, success){
- if (success && rec.length > 0) {
- me.select(rec[0]);
- }
- }
- });
- }
-
-});
-Ext.define('PVE.CephCreateOsd', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveCephCreateOsd'],
-
- subject: 'Ceph OSD',
-
- showProgress: true,
-
- onlineHelp: 'pve_ceph_osds',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/ceph/osd",
- method: 'POST',
- items: [
- {
- xtype: 'pveDiskSelector',
- name: 'dev',
- nodename: me.nodename,
- diskType: 'unused',
- fieldLabel: gettext('Disk'),
- allowBlank: false
- },
- {
- xtype: 'pveDiskSelector',
- name: 'journal_dev',
- nodename: me.nodename,
- diskType: 'journal_disks',
- fieldLabel: gettext('Journal/DB Disk'),
- value: '',
- autoSelect: false,
- allowBlank: true,
- emptyText: 'use OSD disk'
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'bluestore',
- fieldLabel: 'Bluestore',
- uncheckedValue: '0',
- value: '1'
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.CephRemoveOsd', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveCephRemoveOsd'],
-
- isRemove: true,
-
- showProgress: true,
- method: 'DELETE',
- items: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'cleanup',
- checked: true,
- labelWidth: 130,
- fieldLabel: gettext('Remove Partitions')
- }
- ],
- initComponent : function() {
-
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
- if (me.osdid === undefined || me.osdid < 0) {
- throw "no osdid specified";
- }
-
- me.isCreate = true;
-
- me.title = gettext('Destroy') + ': Ceph OSD osd.' + me.osdid.toString();
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/ceph/osd/" + me.osdid.toString()
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.CephOsdTree', {
- extend: 'Ext.tree.Panel',
- alias: ['widget.pveNodeCephOsdTree'],
- onlineHelp: 'chapter_pveceph',
- stateful: true,
- stateId: 'grid-ceph-osd',
- columns: [
- {
- xtype: 'treecolumn',
- text: 'Name',
- dataIndex: 'name',
- width: 150
- },
- {
- text: 'Type',
- dataIndex: 'type',
- align: 'right',
- width: 60
- },
- {
- text: gettext("Class"),
- dataIndex: 'device_class',
- align: 'right',
- width: 40
- },
- {
- text: "OSD Type",
- dataIndex: 'osdtype',
- align: 'right',
- width: 40
- },
- {
- text: "Bluestore Device",
- dataIndex: 'blfsdev',
- align: 'right',
- width: 40,
- hidden: true
- },
- {
- text: "DB Device",
- dataIndex: 'dbdev',
- align: 'right',
- width: 40,
- hidden: true
- },
- {
- text: "WAL Device",
- dataIndex: 'waldev',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (!value &&
- rec.data.osdtype === 'bluestore' &&
- rec.data.type === 'osd') {
- return 'N/A';
- }
- return value;
- },
- width: 40,
- hidden: true
- },
- {
- text: 'Status',
- dataIndex: 'status',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (!value) {
- return value;
- }
- var inout = rec.data['in'] ? 'in' : 'out';
- var updownicon = value === 'up' ? 'good fa-arrow-circle-up' :
- 'critical fa-arrow-circle-down';
-
- var inouticon = rec.data['in'] ? 'good fa-circle' :
- 'warning fa-circle-o';
-
- var text = value + ' / ' +
- inout + ' ';
-
- return text;
- },
- width: 80
- },
- {
- text: 'weight',
- dataIndex: 'crush_weight',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- return value;
- },
- width: 80
- },
- {
- text: 'reweight',
- dataIndex: 'reweight',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- return value;
- },
- width: 90
- },
- {
- header: gettext('Used'),
- columns: [
- {
- text: '%',
- dataIndex: 'percent_used',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- return Ext.util.Format.number(value, '0.00');
- },
- width: 80
- },
- {
- text: gettext('Total'),
- dataIndex: 'total_space',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- return PVE.Utils.render_size(value);
- },
- width: 100
- }
- ]
- },
- {
- header: gettext('Latency (ms)'),
- columns: [
- {
- text: 'Apply',
- dataIndex: 'apply_latency_ms',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- return value;
- },
- width: 60
- },
- {
- text: 'Commit',
- dataIndex: 'commit_latency_ms',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- return value;
- },
- width: 60
- }
- ]
- }
- ],
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- // we expect noout to be not set by default
- var noout = false;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var sm = Ext.create('Ext.selection.TreeModel', {});
-
- var set_button_status; // defined later
-
- var reload = function() {
- Proxmox.Utils.API2Request({
- url: "/nodes/" + nodename + "/ceph/osd",
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- var msg = response.htmlStatus;
- PVE.Utils.showCephInstallOrMask(me, msg, me.pveSelNode.data.node,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- reload();
- });
- }
- );
- },
- success: function(response, opts) {
- sm.deselectAll();
- me.setRootNode(response.result.data.root);
- me.expandAll();
- // extract noout flag
- if (response.result.data.flags &&
- response.result.data.flags.search(/noout/) !== -1) {
- noout = true;
- } else {
- noout = false;
- }
- set_button_status();
- }
- });
- };
-
- var osd_cmd = function(cmd) {
- var rec = sm.getSelection()[0];
- if (!(rec && (rec.data.id >= 0) && rec.data.host)) {
- return;
- }
- Proxmox.Utils.API2Request({
- url: "/nodes/" + rec.data.host + "/ceph/osd/" +
- rec.data.id + '/' + cmd,
- waitMsgTarget: me,
- method: 'POST',
- success: reload,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var service_cmd = function(cmd) {
- var rec = sm.getSelection()[0];
- if (!(rec && rec.data.name && rec.data.host)) {
- return;
- }
- Proxmox.Utils.API2Request({
- url: "/nodes/" + rec.data.host + "/ceph/" + cmd,
- params: { service: rec.data.name },
- waitMsgTarget: me,
- method: 'POST',
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- me.mon(win, 'close', reload, me);
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var create_btn = new Proxmox.button.Button({
- text: gettext('Create') + ': OSD',
- handler: function() {
- var rec = sm.getSelection()[0];
-
- var win = Ext.create('PVE.CephCreateOsd', {
- nodename: nodename
- });
- win.show();
- me.mon(win, 'close', reload, me);
- }
- });
-
- var start_btn = new Ext.Button({
- text: gettext('Start'),
- disabled: true,
- handler: function(){ service_cmd('start'); }
- });
-
- var stop_btn = new Ext.Button({
- text: gettext('Stop'),
- disabled: true,
- handler: function(){ service_cmd('stop'); }
- });
-
- var restart_btn = new Ext.Button({
- text: gettext('Restart'),
- disabled: true,
- handler: function(){ service_cmd('restart'); }
- });
-
- var osd_out_btn = new Ext.Button({
- text: 'Out',
- disabled: true,
- handler: function(){ osd_cmd('out'); }
- });
-
- var osd_in_btn = new Ext.Button({
- text: 'In',
- disabled: true,
- handler: function(){ osd_cmd('in'); }
- });
-
- var remove_btn = new Ext.Button({
- text: gettext('Destroy'),
- disabled: true,
- handler: function(){
- var rec = sm.getSelection()[0];
- if (!(rec && (rec.data.id >= 0) && rec.data.host)) {
- return;
- }
-
- var win = Ext.create('PVE.CephRemoveOsd', {
- nodename: rec.data.host,
- osdid: rec.data.id
- });
- win.show();
- me.mon(win, 'close', reload, me);
- }
- });
-
- var noout_btn = new Ext.Button({
- text: gettext('Set noout'),
- handler: function() {
- Proxmox.Utils.API2Request({
- url: "/nodes/" + nodename + "/ceph/flags/noout",
- waitMsgTarget: me,
- method: noout ? 'DELETE' : 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: reload
- });
- }
- });
-
- var osd_label = new Ext.toolbar.TextItem({
- data: {
- osd: undefined
- },
- tpl: [
- '',
- '{osd}:',
- '',
- gettext('No OSD selected'),
- ' '
- ]
- });
-
- set_button_status = function() {
- var rec = sm.getSelection()[0];
- noout_btn.setText(noout?gettext('Unset noout'):gettext('Set noout'));
-
- if (!rec) {
- start_btn.setDisabled(true);
- stop_btn.setDisabled(true);
- restart_btn.setDisabled(true);
- remove_btn.setDisabled(true);
- osd_out_btn.setDisabled(true);
- osd_in_btn.setDisabled(true);
- return;
- }
-
- var isOsd = (rec.data.host && (rec.data.type === 'osd') && (rec.data.id >= 0));
-
- start_btn.setDisabled(!(isOsd && (rec.data.status !== 'up')));
- stop_btn.setDisabled(!(isOsd && (rec.data.status !== 'down')));
- restart_btn.setDisabled(!(isOsd && (rec.data.status !== 'down')));
- remove_btn.setDisabled(!(isOsd && (rec.data.status === 'down')));
-
- osd_out_btn.setDisabled(!(isOsd && rec.data['in']));
- osd_in_btn.setDisabled(!(isOsd && !rec.data['in']));
-
- osd_label.update(isOsd?{osd:rec.data.name}:undefined);
- };
-
- sm.on('selectionchange', set_button_status);
-
- var reload_btn = new Ext.Button({
- text: gettext('Reload'),
- handler: reload
- });
-
- Ext.apply(me, {
- tbar: [ create_btn, reload_btn, noout_btn, '->', osd_label, start_btn, stop_btn, restart_btn, osd_out_btn, osd_in_btn, remove_btn ],
- rootVisible: false,
- useArrows: true,
- fields: ['name', 'type', 'status', 'host', 'in', 'id' ,
- { type: 'number', name: 'reweight' },
- { type: 'number', name: 'percent_used' },
- { type: 'integer', name: 'bytes_used' },
- { type: 'integer', name: 'total_space' },
- { type: 'integer', name: 'apply_latency_ms' },
- { type: 'integer', name: 'commit_latency_ms' },
- { type: 'string', name: 'device_class' },
- { type: 'string', name: 'osdtype' },
- { type: 'string', name: 'blfsdev' },
- { type: 'string', name: 'dbdev' },
- { type: 'string', name: 'waldev' },
- { type: 'string', name: 'iconCls', calculate: function(data) {
- var iconCls = 'fa x-fa-tree fa-';
- switch (data.type) {
- case 'host':
- iconCls += 'building';
- break;
- case 'osd':
- iconCls += 'hdd-o';
- break;
- case 'root':
- iconCls += 'server';
- break;
- default:
- return undefined;
- }
- return iconCls;
- } },
- { type: 'number', name: 'crush_weight' }],
- selModel: sm,
-
- listeners: {
- activate: function() {
- reload();
- }
- }
- });
-
- me.callParent();
-
- reload();
- }
-});
-Ext.define('PVE.CephCreateMon', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveCephCreateMon'],
-
- subject: 'Ceph Monitor/Manager',
- onlineHelp: 'pve_ceph_monitors',
-
- showProgress: true,
-
- setNode: function(nodename) {
- var me = this;
-
- me.nodename = nodename;
- me.url = "/nodes/" + nodename + "/ceph/mon";
- },
-
- initComponent : function() {
-
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.setNode(me.nodename);
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- method: 'POST',
- items: [
- {
- xtype: 'pveNodeSelector',
- submitValue: false,
- fieldLabel: gettext('Host'),
- selectCurNode: true,
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- me.setNode(value);
- }
- }
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.CephMonList', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveNodeCephMonList'],
-
- onlineHelp: 'chapter_pveceph',
-
- stateful: true,
- stateId: 'grid-ceph-monitor',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var rstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 3000,
- storeid: 'ceph-mon-list' + nodename,
- model: 'ceph-mon-list',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/ceph/mon"
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: rstore,
- sorters: [{ property: 'name'}]
- });
-
-
- var service_cmd = function(cmd) {
- var rec = sm.getSelection()[0];
- if (!rec.data.host) {
- Ext.Msg.alert(gettext('Error'), "entry has no host");
- return;
- }
- Proxmox.Utils.API2Request({
- url: "/nodes/" + rec.data.host + "/ceph/" + cmd,
- method: 'POST',
- params: { service: "mon." + rec.data.name },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var start_btn = new Proxmox.button.Button({
- text: gettext('Start'),
- selModel: sm,
- disabled: true,
- handler: function(){
- service_cmd("start");
- }
- });
-
- var stop_btn = new Proxmox.button.Button({
- text: gettext('Stop'),
- selModel: sm,
- disabled: true,
- handler: function(){
- service_cmd("stop");
- }
- });
-
- var restart_btn = new Proxmox.button.Button({
- text: gettext('Restart'),
- selModel: sm,
- disabled: true,
- handler: function(){
- service_cmd("restart");
- }
- });
-
- var create_btn = new Ext.Button({
- text: gettext('Create'),
- handler: function(){
- var win = Ext.create('PVE.CephCreateMon', {
- nodename: nodename
- });
- win.show();
- }
- });
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- selModel: sm,
- disabled: true,
- handler: function() {
- var rec = sm.getSelection()[0];
-
- if (!rec.data.host) {
- Ext.Msg.alert(gettext('Error'), "entry has no host");
- return;
- }
-
- Proxmox.Utils.API2Request({
- url: "/nodes/" + rec.data.host + "/ceph/mon/" +
- rec.data.name,
- method: 'DELETE',
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [ start_btn, stop_btn, restart_btn, '-', create_btn, remove_btn ],
- columns: [
- {
- header: gettext('Name'),
- width: 100,
- sortable: true,
- renderer: function(v) { return "mon." + v; },
- dataIndex: 'name'
- },
- {
- header: gettext('Host'),
- width: 100,
- sortable: true,
- renderer: function(v) {
- return v || 'unknown';
- },
- dataIndex: 'host'
- },
- {
- header: gettext('Quorum'),
- width: 70,
- sortable: false,
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'quorum'
- },
- {
- header: gettext('Address'),
- flex: 1,
- sortable: true,
- dataIndex: 'addr'
- }
- ],
- listeners: {
- activate: rstore.startUpdate,
- destroy: rstore.stopUpdate
- }
- });
-
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(me, rstore, regex, function(me, error){
- me.store.rstore.stopUpdate();
- PVE.Utils.showCephInstallOrMask(me, error.statusText, nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.store.rstore.startUpdate();
- });
- }
- );
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('ceph-mon-list', {
- extend: 'Ext.data.Model',
- fields: [ 'addr', 'name', 'rank', 'host', 'quorum' ],
- idProperty: 'name'
- });
-});
-Ext.define('PVE.node.CephCrushMap', {
- extend: 'Ext.panel.Panel',
- alias: ['widget.pveNodeCephCrushMap'],
- bodyStyle: 'white-space:pre',
- bodyPadding: 5,
- border: false,
- stateful: true,
- stateId: 'layout-ceph-crush',
- scrollable: true,
- load: function() {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: me.url,
- waitMsgTarget: me,
- failure: function(response, opts) {
- me.update(gettext('Error') + " " + response.htmlStatus);
- var msg = response.htmlStatus;
- PVE.Utils.showCephInstallOrMask(me.ownerCt, msg, me.pveSelNode.data.node,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.load();
- });
- }
- );
- },
- success: function(response, opts) {
- var data = response.result.data;
- me.update(Ext.htmlEncode(data));
- }
- });
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- url: '/nodes/' + nodename + '/ceph/crush',
-
- listeners: {
- activate: function() {
- me.load();
- }
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('PVE.node.CephStatus', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNodeCephStatus',
-
- onlineHelp: 'chapter_pveceph',
-
- scrollable: true,
-
- bodyPadding: 5,
-
- layout: {
- type: 'column'
- },
-
- defaults: {
- padding: 5
- },
-
- items: [
- {
- xtype: 'panel',
- title: gettext('Health'),
- bodyPadding: 10,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- },
- minHeight: 210,
- layout: {
- type: 'hbox',
- align: 'stretch'
- },
- items: [
- {
- flex: 1,
- itemId: 'overallhealth',
- xtype: 'pveHealthWidget',
- title: gettext('Status')
- },
- {
- flex: 2,
- itemId: 'warnings',
- stateful: true,
- stateId: 'ceph-status-warnings',
- xtype: 'grid',
- // since we load the store manually,
- // to show the emptytext, we have to
- // specify an empty store
- store: { data:[] },
- emptyText: gettext('No Warnings/Errors'),
- columns: [
- {
- dataIndex: 'severity',
- header: gettext('Severity'),
- align: 'center',
- width: 70,
- renderer: function(value) {
- var health = PVE.Utils.map_ceph_health[value];
- var classes = PVE.Utils.get_health_icon(health);
-
- return ' ';
- },
- sorter: {
- sorterFn: function(a,b) {
- var healthArr = ['HEALTH_ERR', 'HEALTH_WARN', 'HEALTH_OK'];
- return healthArr.indexOf(b.data.severity) - healthArr.indexOf(a.data.severity);
- }
- }
- },
- {
- dataIndex: 'summary',
- header: gettext('Summary'),
- flex: 1
- },
- {
- xtype: 'actioncolumn',
- width: 40,
- align: 'center',
- tooltip: gettext('Detail'),
- items: [
- {
- iconCls: 'x-fa fa-info-circle',
- handler: function(grid, rowindex, colindex, item, e, record) {
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Detail'),
- resizable: true,
- modal: true,
- width: 650,
- height: 400,
- layout: {
- type: 'fit'
- },
- items: [{
- scrollable: true,
- padding: 10,
- xtype: 'box',
- html: [
- '' + Ext.htmlEncode(record.data.summary) + ' ',
- '' + Ext.htmlEncode(record.data.detail) + ' '
- ]
- }]
- });
- win.show();
- }
- }
- ]
- }
- ]
- }
- ]
- },
- {
- xtype: 'pveCephStatusDetail',
- itemId: 'statusdetail',
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- },
- title: gettext('Status')
- },
- {
- xtype: 'panel',
- title: gettext('Performance'),
- columnWidth: 1,
- bodyPadding: 5,
- layout: {
- type: 'hbox',
- align: 'center'
- },
- items: [
- {
- flex: 1,
- xtype: 'proxmoxGauge',
- itemId: 'space',
- title: gettext('Usage')
- },
- {
- flex: 2,
- xtype: 'container',
- defaults: {
- padding: 0,
- height: 100
- },
- items: [
- {
- itemId: 'reads',
- xtype: 'pveRunningChart',
- title: gettext('Reads'),
- renderer: PVE.Utils.render_bandwidth
- },
- {
- itemId: 'writes',
- xtype: 'pveRunningChart',
- title: gettext('Writes'),
- renderer: PVE.Utils.render_bandwidth
- },
- {
- itemId: 'iops',
- xtype: 'pveRunningChart',
- hidden: true,
- title: 'IOPS', // do not localize
- renderer: Ext.util.Format.numberRenderer('0,000')
- },
- {
- itemId: 'readiops',
- xtype: 'pveRunningChart',
- hidden: true,
- title: 'IOPS: ' + gettext('Reads'),
- renderer: Ext.util.Format.numberRenderer('0,000')
- },
- {
- itemId: 'writeiops',
- xtype: 'pveRunningChart',
- hidden: true,
- title: 'IOPS: ' + gettext('Writes'),
- renderer: Ext.util.Format.numberRenderer('0,000')
- }
- ]
- }
- ]
- }
- ],
-
- generateCheckData: function(health) {
- var result = [];
- var checks = health.checks || {};
- var keys = Ext.Object.getKeys(checks).sort();
-
- Ext.Array.forEach(keys, function(key) {
- var details = checks[key].detail || [];
- result.push({
- id: key,
- summary: checks[key].summary.message,
- detail: Ext.Array.reduce(
- checks[key].detail,
- function(first, second) {
- return first + '\n' + second.message;
- },
- ''
- ),
- severity: checks[key].severity
- });
- });
-
- return result;
- },
-
- updateAll: function(store, records, success) {
- if (!success || records.length === 0) {
- return;
- }
-
- var me = this;
- var rec = records[0];
-
- // add health panel
- me.down('#overallhealth').updateHealth(PVE.Utils.render_ceph_health(rec.data.health || {}));
- // add errors to gridstore
- me.down('#warnings').getStore().loadRawData(me.generateCheckData(rec.data.health || {}), false);
-
- // update detailstatus panel
- me.getComponent('statusdetail').updateAll(
- rec.data.health || {},
- rec.data.monmap || {},
- rec.data.pgmap || {},
- rec.data.osdmap || {},
- rec.data.quorum_names || []);
-
- // add performance data
- var used = rec.data.pgmap.bytes_used;
- var total = rec.data.pgmap.bytes_total;
-
- var text = Ext.String.format(gettext('{0} of {1}'),
- PVE.Utils.render_size(used),
- PVE.Utils.render_size(total)
- );
-
- // update the usage widget
- me.down('#space').updateValue(used/total, text);
-
- // TODO: logic for jewel (iops splitted in read/write)
-
- var iops = rec.data.pgmap.op_per_sec;
- var readiops = rec.data.pgmap.read_op_per_sec;
- var writeiops = rec.data.pgmap.write_op_per_sec;
- var reads = rec.data.pgmap.read_bytes_sec || 0;
- var writes = rec.data.pgmap.write_bytes_sec || 0;
-
- if (iops !== undefined && me.version !== 'hammer') {
- me.change_version('hammer');
- } else if((readiops !== undefined || writeiops !== undefined) && me.version !== 'jewel') {
- me.change_version('jewel');
- }
- // update the graphs
- me.reads.addDataPoint(reads);
- me.writes.addDataPoint(writes);
- me.iops.addDataPoint(iops);
- me.readiops.addDataPoint(readiops);
- me.writeiops.addDataPoint(writeiops);
- },
-
- change_version: function(version) {
- var me = this;
- me.version = version;
- me.sp.set('ceph-version', version);
- me.iops.setVisible(version === 'hammer');
- me.readiops.setVisible(version === 'jewel');
- me.writeiops.setVisible(version === 'jewel');
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.callParent();
- me.store = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'ceph-status-' + nodename,
- interval: 5000,
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + nodename + '/ceph/status'
- }
- });
-
- // save references for the updatefunction
- me.iops = me.down('#iops');
- me.readiops = me.down('#readiops');
- me.writeiops = me.down('#writeiops');
- me.reads = me.down('#reads');
- me.writes = me.down('#writes');
-
- // get ceph version
- me.sp = Ext.state.Manager.getProvider();
- me.version = me.sp.get('ceph-version');
- me.change_version(me.version);
-
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(me, me.store, regex, function(me, error){
- me.store.stopUpdate();
- PVE.Utils.showCephInstallOrMask(me, error.statusText, nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.store.startUpdate();
- });
- }
- );
- });
-
- me.mon(me.store, 'load', me.updateAll, me);
- me.on('destroy', me.store.stopUpdate);
- me.store.startUpdate();
- }
-
-});
-Ext.define('PVE.ceph.StatusDetail', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveCephStatusDetail',
-
- layout: {
- type: 'hbox',
- align: 'stretch'
- },
-
- bodyPadding: '0 5 20',
- defaults: {
- xtype: 'box',
- style: {
- 'text-align':'center'
- }
- },
-
- items: [{
- flex: 1,
- itemId: 'monitors',
- xtype: 'container',
- items: [
- {
- xtype: 'box',
- width: '100%',
- html: '' + gettext('Monitors') + ' '
- }
- ]
- },{
- flex: 1,
- itemId: 'osds',
- data: {
- total: 0,
- upin: 0,
- upout: 0,
- downin: 0,
- downout: 0
- },
- tpl: [
- '' + 'OSDs' + ' ',
- '',
- ' ',
- ' ',
- gettext('In'),
- ' ',
- ' ',
- gettext('Out'),
- ' ',
- ' ',
- '',
- ' ',
- gettext('Up'),
- ' ',
- '{upin} ',
- '{upout} ',
- ' ',
- '',
- ' ',
- gettext('Down'),
- ' ',
- '{downin} ',
- '{downout} ',
- ' ',
- '
',
- '',
- gettext('Total'),
- ': {total}',
- '
'
- ]
- },
- {
- flex: 1.6,
- itemId: 'pgs',
- padding: '0 10',
- data: {
- states: []
- },
- tpl: [
- '' + 'PGs' + ' ',
- '',
- '{state_name}:
',
- '{count}
',
- '
',
- ' '
- ]
- }],
-
- updateAll: function(health, monmap, pgmap, osdmap, quorum_names) {
- var me = this;
- me.suspendLayout = true;
-
- // update pgs sorted
- var pgs_by_state = pgmap.pgs_by_state || [];
- pgs_by_state.sort(function(a,b){
- return (a.state_name < b.state_name)?-1:(a.state_name === b.state_name)?0:1;
- });
- me.getComponent('pgs').update({states: pgs_by_state});
-
- var downinregex = /(\d+) osds down/;
- var monnameregex = /^mon.(\S+) /;
- var downin_osds = 0;
- var monmsgs = {};
-
- // we collect monitor/osd information from the checks
- Ext.Object.each(health.checks, function(key, value, obj) {
- var found = null;
- if (key === 'OSD_DOWN') {
- found = value.summary.message.match(downinregex);
- if (found !== null) {
- downin_osds = parseInt(found[1],10);
- }
- }
- else if (Ext.String.startsWith(key, 'MON_')) {
- if (!value.detail) {
- return;
- }
- found = value.detail[0].message.match(monnameregex);
- if (found !== null) {
- if (!monmsgs[found[1]]) {
- monmsgs[found[1]] = [];
- }
- monmsgs[found[1]].push({
- text: Ext.Array.reduce(value.detail, function(first, second) {
- return first + '\n' + second.message;
- }, ''),
- severity: value.severity
- });
- }
- }
- });
-
- // update osds counts
-
- var total_osds = osdmap.osdmap.num_osds || 0;
- var in_osds = osdmap.osdmap.num_in_osds || 0;
- var up_osds = osdmap.osdmap.num_up_osds || 0;
- var out_osds = total_osds - in_osds;
- var down_osds = total_osds - up_osds;
-
- var downout_osds = down_osds - downin_osds;
- var upin_osds = in_osds - downin_osds;
- var upout_osds = up_osds - upin_osds;
- var osds = {
- total: total_osds,
- upin: upin_osds,
- upout: upout_osds,
- downin: downin_osds,
- downout: downout_osds
- };
- me.getComponent('osds').update(osds);
-
- // update the monitors
- var mons = monmap.mons.sort(function(a,b) {
- return (a.name < b.name)?-1:(a.name > b.name)?1:0;
- });
-
- var monContainer = me.getComponent('monitors');
-
- var i;
- for (i = 0; i < mons.length; i++) {
- var monitor = monContainer.getComponent('mon.' + mons[i].name);
- if (!monitor) {
- // since mons are already sorted, and
- // we always have a sorted list
- // we can add it at the mons+1 position (because of the title)
- monitor = monContainer.insert(i+1, {
- xtype: 'pveCephMonitorWidget',
- itemId: 'mon.' + mons[i].name
- });
- }
- monitor.updateMonitor(mons[i], monmsgs, quorum_names);
- }
- me.suspendLayout = false;
- me.updateLayout();
- }
-});
-
-Ext.define('PVE.ceph.MonitorWidget', {
- extend: 'Ext.Component',
- alias: 'widget.pveCephMonitorWidget',
-
- userCls: 'monitor inline-block',
- data: {
- name: '0',
- health: 'HEALTH_ERR',
- text: '',
- iconCls: PVE.Utils.get_health_icon(),
- addr: ''
- },
-
- tpl: [
- '{name}: ',
- ' '
- ],
-
- // expects 3 variables which are
- // timestate: the status from timechecks.mons
- // data: the monmap.mons data
- // quorum_names: the quorum_names array
- updateMonitor: function(data, monmsgs, quorum_names) {
- var me = this;
- var state = 'HEALTH_ERR';
- var text = '';
- var healthstates = {
- 'HEALTH_OK': 3,
- 'HEALTH_WARN': 2,
- 'HEALTH_ERR': 1
- };
-
- if (quorum_names &&
- quorum_names.indexOf(data.name) !== -1) {
- state = 'HEALTH_OK';
- }
-
- if (monmsgs[data.name]) {
- Ext.Array.forEach(monmsgs[data.name], function(msg) {
- if (healthstates[msg.severity] < healthstates[state]) {
- state = msg.severity;
- }
-
- text += msg.text + "\n";
- });
- }
-
- me.update(Ext.apply(me.data, {
- health: state,
- text: text,
- addr: data.addr,
- name: data.name,
- iconCls: PVE.Utils.get_health_icon(PVE.Utils.map_ceph_health[state])
- }));
- },
-
- listeners: {
- mouseenter: {
- element: 'el',
- fn: function(events, element) {
- var me = this.component;
- if (!me) {
- return;
- }
- if (!me.tooltip) {
- me.tooltip = Ext.create('Ext.tip.ToolTip', {
- target: me.el,
- trackMouse: true,
- renderTo: Ext.getBody(),
- html: gettext('Monitor') + ': ' + me.data.name + ' ' +
- gettext('Address') + ': ' + me.data.addr + ' ' +
- gettext('Health') + ': ' + me.data.health + ' ' +
- me.data.text
- });
- }
- me.tooltip.show();
- }
- },
- mouseleave: {
- element: 'el',
- fn: function(events, element) {
- var me = this.component;
- if (me.tooltip) {
- me.tooltip.destroy();
- delete me.tooltip;
- }
- }
- }
- }
-});
-Ext.define('PVE.node.CephConfig', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNodeCephConfig',
-
- bodyStyle: 'white-space:pre',
- bodyPadding: 5,
- border: false,
- scrollable: true,
- load: function() {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: me.url,
- waitMsgTarget: me,
- failure: function(response, opts) {
- me.update(gettext('Error') + " " + response.htmlStatus);
- var msg = response.htmlStatus;
- PVE.Utils.showCephInstallOrMask(me.ownerCt, msg, me.pveSelNode.data.node,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.load();
- });
- }
- );
-
- },
- success: function(response, opts) {
- var data = response.result.data;
- me.update(Ext.htmlEncode(data));
- }
- });
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- url: '/nodes/' + nodename + '/ceph/config',
- listeners: {
- activate: function() {
- me.load();
- }
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-
-Ext.define('PVE.node.CephConfigCrush', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNodeCephConfigCrush',
-
- onlineHelp: 'chapter_pveceph',
-
- layout: 'border',
- items: [{
- title: gettext('Configuration'),
- xtype: 'pveNodeCephConfig',
- region: 'center'
- },
- {
- title: 'Crush Map', // do not localize
- xtype: 'pveNodeCephCrushMap',
- region: 'east',
- split: true,
- width: '50%'
- }],
-
- initComponent: function() {
- var me = this;
- me.defaults = {
- pveSelNode: me.pveSelNode
- };
- me.callParent();
- }
-});
-Ext.define('PVE.ceph.Log', {
- extend: 'Proxmox.panel.LogView',
- xtype: 'cephLogView',
- nodename: undefined,
- failCallback: function(response) {
- var me = this;
- var msg = response.htmlStatus;
- var windowShow = PVE.Utils.showCephInstallOrMask(me, msg, me.nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.loadTask.delay(200);
- });
- }
- );
- if (!windowShow) {
- Proxmox.Utils.setErrorMask(me, msg);
- }
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.ceph.CephInstallWizard', {
- extend: 'PVE.window.Wizard',
- alias: 'widget.pveCephInstallWizard',
- mixins: ['Proxmox.Mixin.CBind'],
- resizable: false,
- nodename: undefined,
- viewModel: {
- data: {
- nodename: '',
- configuration: true,
- isInstalled: false
- }
- },
- cbindData: {
- nodename: undefined
- },
- title: gettext('Setup'),
- navigateNext: function() {
- var tp = this.down('#wizcontent');
- var atab = tp.getActiveTab();
-
- var next = tp.items.indexOf(atab) + 1;
- var ntab = tp.items.getAt(next);
- if (ntab) {
- ntab.enable();
- tp.setActiveTab(ntab);
- }
- },
- setInitialTab: function (index) {
- var tp = this.down('#wizcontent');
- var initialTab = tp.items.getAt(index);
- initialTab.enable();
- tp.setActiveTab(initialTab);
- },
- onShow: function() {
- this.callParent(arguments);
- var isInstalled = this.getViewModel().get('isInstalled');
- if (isInstalled) {
- this.getViewModel().set('configuration', false);
- this.setInitialTab(2);
- }
- },
- items: [
- {
- title: gettext('Info'),
- xtype: 'panel',
- border: false,
- bodyBorder: false,
- onlineHelp: 'chapter_pveceph',
- html: 'Ceph? '+
- '"Ceph is a unified, distributed storage system designed for excellent performance, reliability and scalability."
'+
- 'Ceph is currently not installed on this node, click on the next button below to start the installation.'+
- ' This wizard will guide you through the necessary steps, after the initial installation you will be offered to create a initial configuration.'+
- ' The configuration step is only needed once per cluster and will be skipped if a config is already present.
'+
- 'Please take a look at our documentation, by clicking the help button below, before starting the installation, '+
- 'if you want to gain deeper knowledge about Ceph visit ceph.com .
',
- listeners: {
- activate: function() {
- // notify owning container that it should display a help button
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
- }
- this.up('pveCephInstallWizard').down('#back').hide(true);
- this.up('pveCephInstallWizard').down('#next').setText(gettext('Start installation'));
- },
- deactivate: function() {
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
- }
- this.up('pveCephInstallWizard').down('#next').setText(gettext('Next'));
- }
- }
- },
- {
- title: gettext('Installation'),
- xtype: 'panel',
- layout: 'fit',
- cbind:{
- nodename: '{nodename}'
- },
- viewModel: {}, // needed to inherit parent viewModel data
- listeners: {
- afterrender: function() {
- var me = this;
- if (this.getViewModel().get('isInstalled')) {
- this.mask("Ceph is already installed, click next to create your configuration.",['pve-static-mask']);
- } else {
- me.down('pveNoVncConsole').fireEvent('activate');
- }
- },
- activate: function() {
- var me = this;
- var nodename = me.nodename;
- me.updateStore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'ceph-status-' + nodename,
- interval: 1000,
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + nodename + '/ceph/status'
- },
- listeners: {
- load: function(rec, response, success, operation) {
-
- if (success) {
- me.updateStore.stopUpdate();
- me.down('textfield').setValue('success');
- } else if (operation.error.statusText.match("not initialized", "i")) {
- me.updateStore.stopUpdate();
- me.up('pveCephInstallWizard').getViewModel().set('configuration',false);
- me.down('textfield').setValue('success');
- } else if (operation.error.statusText.match("rados_connect failed", "i")) {
- me.updateStore.stopUpdate();
- me.up('pveCephInstallWizard').getViewModel().set('configuration',true);
- me.down('textfield').setValue('success');
- } else if (!operation.error.statusText.match("not installed", "i")) {
- Proxmox.Utils.setErrorMask(me, operation.error.statusText);
- }
- }
- }
- });
- me.updateStore.startUpdate();
- },
- destroy: function() {
- var me = this;
- if (me.updateStore) {
- me.updateStore.stopUpdate();
- }
- }
- },
- items: [
- {
- itemId: 'jsconsole',
- consoleType: 'cmd',
- xtermjs: true,
- xtype: 'pveNoVncConsole',
- cbind:{
- nodename: '{nodename}'
- },
- cmd: 'ceph_install'
- },
- {
- xtype: 'textfield',
- name: 'installSuccess',
- value: '',
- allowBlank: false,
- submitValue: false,
- hidden: true
- }
- ]
- },
- {
- xtype: 'inputpanel',
- title: gettext('Configuration'),
- onlineHelp: 'chapter_pveceph',
- cbind: {
- nodename: '{nodename}'
- },
- viewModel: {
- data: {
- replicas: undefined,
- minreplicas: undefined
- }
- },
- listeners: {
- activate: function() {
- this.up('pveCephInstallWizard').down('#submit').setText(gettext('Next'));
- },
- beforeshow: function() {
- if (this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
- this.mask("Coniguration already initialized",['pve-static-mask']);
- } else {
- this.unmask();
- }
- },
- deactivate: function() {
- this.up('pveCephInstallWizard').down('#submit').setText(gettext('Finish'));
- }
- },
- column1: [
- {
- xtype: 'displayfield',
- value: gettext('Ceph cluster configuration') + ':'
- },
- {
- xtype: 'textfield',
- name: 'network',
- vtype: 'IPCIDRAddress',
- value: '',
- fieldLabel: 'Public Network IP/CIDR',
- bind: {
- allowBlank: '{configuration}'
- },
- setAllowBlank: function(allowBlank) {
- this.allowBlank = allowBlank;
- this.validate();
- }
- },
- {
- xtype: 'textfield',
- name: 'cluster-network',
- vtype: 'IPCIDRAddress',
- fieldLabel: 'Cluster Network IP/CIDR',
- allowBlank: true,
- emptyText: gettext('Same as Public Network')
- }
- // FIXME: add hint about cluster network and/or reference user to docs??
- ],
- column2: [
- {
- xtype: 'displayfield',
- value: gettext('First Ceph monitor') + ':'
- },
- {
- xtype: 'pveNodeSelector',
- fieldLabel: gettext('Monitor node'),
- name: 'mon-node',
- selectCurNode: true,
- allowBlank: false
- },
- {
- xtype: 'displayfield',
- value: gettext('Additional monitors are recommended. They can be created at any time in the Monitor tab.'),
- userCls: 'pve-hint'
- }
- ],
- advancedColumn1: [
- {
- xtype: 'numberfield',
- name: 'size',
- fieldLabel: 'Number of replicas',
- bind: {
- value: '{replicas}'
- },
- maxValue: 7,
- minValue: 2,
- emptyText: '3'
- },
- {
- xtype: 'numberfield',
- name: 'min_size',
- fieldLabel: 'Minimum replicas',
- bind: {
- maxValue: '{replicas}',
- value: '{minreplicas}'
- },
- minValue: 2,
- maxValue: 3,
- setMaxValue: function(value) {
- this.maxValue = Ext.Number.from(value, 2);
- // allow enough to avoid split brains with max 'size', but more makes simply no sense
- if (this.maxValue > 4) {
- this.maxValue = 4;
- }
- this.toggleSpinners();
- this.validate();
- },
- emptyText: '2'
- }
- ],
- onGetValues: function(values) {
- ['cluster-network', 'size', 'min_size'].forEach(function(field) {
- if (!values[field]) {
- delete values[field];
- }
- });
- return values;
- },
- onSubmit: function() {
- var me = this;
- if (!this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
- var wizard = me.up('window');
- var kv = wizard.getValues();
- delete kv['delete'];
- var monNode = kv['mon-node'];
- delete kv['mon-node'];
- var nodename = me.nodename;
- delete kv.nodename;
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/ceph/init',
- waitMsgTarget: wizard,
- method: 'POST',
- params: kv,
- success: function() {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + monNode + '/ceph/mon',
- waitMsgTarget: wizard,
- method: 'POST',
- success: function() {
- me.up('pveCephInstallWizard').navigateNext();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
-
- } else {
- me.up('pveCephInstallWizard').navigateNext();
- }
- }
- },
- {
- title: gettext('Success'),
- xtype: 'panel',
- border: false,
- bodyBorder: false,
- onlineHelp: 'pve_ceph_install',
- html: 'Installation successful! '+
- 'The basic installation and configuration is completed, depending on your setup some of the following steps are required to start using Ceph:
'+
- 'Install Ceph on other nodes '+
- 'Create additional Ceph Monitors '+
- 'Create Ceph OSDs '+
- 'Create Ceph Pools '+
- 'To learn more click on the help button below.
',
- listeners: {
- activate: function() {
- // notify owning container that it should display a help button
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
- }
-
- var tp = this.up('#wizcontent');
- var idx = tp.items.indexOf(this)-1;
- for(;idx >= 0;idx--) {
- var nc = tp.items.getAt(idx);
- if (nc) {
- nc.disable();
- }
- }
- },
- deactivate: function() {
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
- }
- }
- },
- onSubmit: function() {
- var wizard = this.up('pveCephInstallWizard');
- wizard.close();
- }
- }
- ]
- });
-Ext.define('PVE.node.DiskList', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pveNodeDiskList',
- emptyText: gettext('No Disks found'),
- stateful: true,
- stateId: 'grid-node-disks',
- columns: [
- {
- header: gettext('Device'),
- width: 100,
- sortable: true,
- dataIndex: 'devpath'
- },
- {
- header: gettext('Type'),
- width: 80,
- sortable: true,
- dataIndex: 'type',
- renderer: function(v) {
- if (v === 'ssd') {
- return 'SSD';
- } else if (v === 'hdd') {
- return 'Hard Disk';
- } else if (v === 'usb'){
- return 'USB';
- } else {
- return gettext('Unknown');
- }
- }
- },
- {
- header: gettext('Usage'),
- width: 80,
- sortable: false,
- renderer: function(v, metaData, rec) {
- if (rec) {
- if (rec.data.osdid >= 0) {
- var bluestore = '';
- if (rec.data.bluestore === 1) {
- bluestore = ' (Bluestore)';
- }
- return "Ceph osd." + rec.data.osdid.toString() + bluestore;
- }
-
- var types = [];
- if (rec.data.journals > 0) {
- types.push('Journal');
- }
-
- if (rec.data.db > 0) {
- types.push('DB');
- }
-
- if (rec.data.wal > 0) {
- types.push('WAL');
- }
-
- if (types.length > 0) {
- return 'Ceph (' + types.join(', ') + ')';
- }
- }
-
- return v || Proxmox.Utils.noText;
- },
- dataIndex: 'used'
- },
- {
- header: gettext('Size'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- },
- {
- header: 'GPT',
- width: 60,
- align: 'right',
- renderer: function(value) {
- if (value) {
- return Proxmox.Utils.yesText;
- } else {
- return Proxmox.Utils.noText;
- }
- },
- dataIndex: 'gpt'
- },
- {
- header: gettext('Vendor'),
- width: 100,
- sortable: true,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'vendor'
- },
- {
- header: gettext('Model'),
- width: 200,
- sortable: true,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'model'
- },
- {
- header: gettext('Serial'),
- width: 200,
- sortable: true,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'serial'
- },
- {
- header: 'S.M.A.R.T.',
- width: 100,
- sortable: true,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'health'
- },
- {
- header: 'Wearout',
- width: 100,
- sortable: true,
- dataIndex: 'wearout',
- renderer: function(value) {
- if (Ext.isNumeric(value)) {
- return (100 - value).toString() + '%';
- }
- return 'N/A';
- }
- }
- ],
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var store = Ext.create('Ext.data.Store', {
- storeid: 'node-disk-list' + nodename,
- model: 'node-disk-list',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/disks/list"
- },
- sorters: [
- {
- property : 'dev',
- direction: 'ASC'
- }
- ]
- });
-
- var reloadButton = Ext.create('Proxmox.button.Button', {
- text: gettext('Reload'),
- handler: function() {
- me.store.load();
- }
- });
-
- var smartButton = Ext.create('Proxmox.button.Button', {
- text: gettext('Show S.M.A.R.T. values'),
- selModel: sm,
- enableFn: function() {
- return !!sm.getSelection().length;
- },
- disabled: true,
- handler: function() {
- var rec = sm.getSelection()[0];
-
- var win = Ext.create('PVE.DiskSmartWindow', {
- nodename: nodename,
- dev: rec.data.devpath
- });
- win.show();
- }
- });
-
- var initButton = Ext.create('Proxmox.button.Button', {
- text: gettext('Initialize Disk with GPT'),
- selModel: sm,
- enableFn: function() {
- var selection = sm.getSelection();
-
- if (!selection.length || selection[0].data.used) {
- return false;
- } else {
- return true;
- }
- },
- disabled: true,
-
- handler: function() {
- var rec = sm.getSelection()[0];
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/nodes/' + nodename + '/disks/initgpt',
- waitMsgTarget: me,
- method: 'POST',
- params: { disk: rec.data.devpath},
- failure: function(response, options) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid
- });
- win.show();
- }
- });
- }
- });
-
- me.loadCount = 1; // avoid duplicate loadmask
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [ reloadButton, smartButton, initButton ],
- listeners: {
- itemdblclick: function() {
- var rec = sm.getSelection()[0];
-
- var win = Ext.create('PVE.DiskSmartWindow', {
- nodename: nodename,
- dev: rec.data.devpath
- });
- win.show();
- }
- }
- });
-
-
- me.callParent();
- me.store.load();
- }
-}, function() {
-
- Ext.define('node-disk-list', {
- extend: 'Ext.data.Model',
- fields: [ 'devpath', 'used', { name: 'size', type: 'number'},
- {name: 'osdid', type: 'number'},
- 'vendor', 'model', 'serial', 'rpm', 'type', 'health', 'wearout' ],
- idProperty: 'devpath'
- });
-});
-
-Ext.define('PVE.DiskSmartWindow', {
- extend: 'Ext.window.Window',
- alias: 'widget.pveSmartWindow',
-
- modal: true,
-
- items: [
- {
- xtype: 'gridpanel',
- layout: {
- type: 'fit'
- },
- emptyText: gettext('No S.M.A.R.T. Values'),
- scrollable: true,
- flex: 1,
- itemId: 'smarts',
- reserveScrollbar: true,
- columns: [
- { text: 'ID', dataIndex: 'id', width: 50 },
- { text: gettext('Attribute'), flex: 1, dataIndex: 'name', renderer: Ext.String.htmlEncode },
- { text: gettext('Value'), dataIndex: 'raw', renderer: Ext.String.htmlEncode },
- { text: gettext('Normalized'), dataIndex: 'value', width: 60},
- { text: gettext('Threshold'), dataIndex: 'threshold', width: 60},
- { text: gettext('Worst'), dataIndex: 'worst', width: 60},
- { text: gettext('Flags'), dataIndex: 'flags'},
- { text: gettext('Failing'), dataIndex: 'fail', renderer: Ext.String.htmlEncode }
- ]
- },
- {
- xtype: 'component',
- itemId: 'text',
- layout: {
- type: 'fit'
- },
- hidden: true,
- style: {
- 'background-color': '#23272a',
- 'white-space': 'pre',
- 'font-family': 'monospace'
- }
- }
- ],
-
- buttons: [
- {
- text: gettext('Reload'),
- name: 'reload',
- handler: function() {
- var me = this;
- me.up('window').store.reload();
- }
- },
- {
- text: gettext('Close'),
- name: 'close',
- handler: function() {
- var me = this;
- me.up('window').close();
- }
- }
- ],
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- width: 800,
- height: 500,
- minWidth: 600,
- minHeight: 400,
- bodyPadding: 5,
- title: gettext('S.M.A.R.T. Values'),
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var dev = me.dev;
- if (!dev) {
- throw "no device specified";
- }
-
- me.store = Ext.create('Ext.data.Store', {
- model: 'disk-smart',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/disks/smart?disk=" + dev
- }
- });
-
- me.callParent();
- var grid = me.down('#smarts');
- var text = me.down('#text');
-
- Proxmox.Utils.monStoreErrors(grid, me.store);
- me.mon(me.store, 'load', function(s, records, success) {
- if (success && records.length > 0) {
- var rec = records[0];
- switch (rec.data.type) {
- case 'text':
- grid.setVisible(false);
- text.setVisible(true);
- text.setHtml(Ext.String.htmlEncode(rec.data.text));
- break;
- default:
- // includes 'ata'
- // cannot use empty case because
- // of jslint
- grid.setVisible(true);
- text.setVisible(false);
- grid.setStore(rec.attributes());
- break;
- }
- }
- });
-
- me.store.load();
- }
-}, function() {
-
- Ext.define('disk-smart', {
- extend: 'Ext.data.Model',
- fields: [
- { name:'health'},
- { name:'type'},
- { name:'text'}
- ],
- hasMany: {model: 'smart-attribute', name: 'attributes'}
- });
- Ext.define('smart-attribute', {
- extend: 'Ext.data.Model',
- fields: [
- { name:'id', type:'number' }, 'name', 'value', 'worst', 'threshold', 'flags', 'fail', 'raw'
- ]
- });
-});
-Ext.define('PVE.node.CreateLVM', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCreateLVM',
-
- subject: 'LVM Volume Group',
-
- showProgress: true,
-
- onlineHelp: 'chapter_lvm',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/disks/lvm",
- method: 'POST',
- items: [
- {
- xtype: 'pveDiskSelector',
- name: 'device',
- nodename: me.nodename,
- diskType: 'unused',
- fieldLabel: gettext('Disk'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'add_storage',
- fieldLabel: gettext('Add Storage'),
- value: '1'
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.LVMList', {
- extend: 'Ext.tree.Panel',
- xtype: 'pveLVMList',
- emptyText: gettext('No Volume Groups found'),
- stateful: true,
- stateId: 'grid-node-lvm',
- columns: [
- {
- xtype: 'treecolumn',
- text: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- text: gettext('Number of LVs'),
- dataIndex: 'lvcount',
- width: 150,
- align: 'right'
- },
- {
- header: gettext('Usage'),
- width: 110,
- dataIndex: 'usage',
- tdCls: 'x-progressbar-default-cell',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Size'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- },
- {
- header: gettext('Free'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'free'
- }
- ],
-
- rootVisible: false,
- useArrows: true,
-
- tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
- var me = this.up('panel');
- me.reload();
- }
- },
- {
- text: gettext('Create') + ': Volume Group',
- handler: function() {
- var me = this.up('panel');
- var win = Ext.create('PVE.node.CreateLVM', {
- nodename: me.nodename,
- taskDone: function() {
- me.reload();
- }
- }).show();
- }
- }
- ],
-
- reload: function() {
- var me = this;
- var sm = me.getSelectionModel();
- Proxmox.Utils.API2Request({
- url: "/nodes/" + me.nodename + "/disks/lvm",
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- },
- success: function(response, opts) {
- sm.deselectAll();
- me.setRootNode(response.result.data);
- me.expandAll();
- }
- });
- },
-
- listeners: {
- activate: function() {
- var me = this;
- me.reload();
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var sm = Ext.create('Ext.selection.TreeModel', {});
-
- Ext.apply(me, {
- selModel: sm,
- fields: ['name', 'size', 'free',
- {
- type: 'string',
- name: 'iconCls',
- calculate: function(data) {
- var txt = 'fa x-fa-tree fa-';
- txt += (data.leaf) ? 'hdd-o' : 'object-group';
- return txt;
- }
- },
- {
- type: 'number',
- name: 'usage',
- calculate: function(data) {
- return ((data.size-data.free)/data.size);
- }
- }
- ],
- sorters: 'name'
- });
-
- me.callParent();
-
- me.reload();
- }
-});
-
-Ext.define('PVE.node.CreateLVMThin', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCreateLVMThin',
-
- subject: 'LVM Thinpool',
-
- showProgress: true,
-
- onlineHelp: 'chapter_lvm',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/disks/lvmthin",
- method: 'POST',
- items: [
- {
- xtype: 'pveDiskSelector',
- name: 'device',
- nodename: me.nodename,
- diskType: 'unused',
- fieldLabel: gettext('Disk'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'add_storage',
- fieldLabel: gettext('Add Storage'),
- value: '1'
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.LVMThinList', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveLVMThinList',
-
- emptyText: gettext('No thinpools found'),
- stateful: true,
- stateId: 'grid-node-lvmthin',
- columns: [
- {
- text: gettext('Name'),
- dataIndex: 'lv',
- flex: 1
- },
- {
- header: gettext('Usage'),
- width: 110,
- dataIndex: 'usage',
- tdCls: 'x-progressbar-default-cell',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Size'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'lv_size'
- },
- {
- header: gettext('Used'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'used'
- },
- {
- header: gettext('Metadata Usage'),
- width: 120,
- dataIndex: 'metadata_usage',
- tdCls: 'x-progressbar-default-cell',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Metadata Size'),
- width: 120,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'metadata_size'
- },
- {
- header: gettext('Metadata Used'),
- width: 125,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'metadata_used'
- }
- ],
-
- rootVisible: false,
- useArrows: true,
-
- tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
- var me = this.up('panel');
- me.reload();
- }
- },
- {
- text: gettext('Create') + ': Thinpool',
- handler: function() {
- var me = this.up('panel');
- var win = Ext.create('PVE.node.CreateLVMThin', {
- nodename: me.nodename,
- taskDone: function() {
- me.reload();
- }
- }).show();
- }
- }
- ],
-
- reload: function() {
- var me = this;
- me.store.load();
- me.store.sort();
- },
-
- listeners: {
- activate: function() {
- var me = this;
- me.reload();
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- store: {
- fields: ['lv', 'lv_size', 'used', 'metadata_size', 'metadata_used',
- {
- type: 'number',
- name: 'usage',
- calculate: function(data) {
- return data.used/data.lv_size;
- }
- },
- {
- type: 'number',
- name: 'metadata_usage',
- calculate: function(data) {
- return data.metadata_used/data.metadata_size;
- }
- }
- ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + '/disks/lvmthin'
- },
- sorters: 'lv'
- }
- });
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.getStore(), true);
- me.reload();
- }
-});
-
-Ext.define('PVE.node.CreateDirectory', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCreateDirectory',
-
- subject: Proxmox.Utils.directoryText,
-
- showProgress: true,
-
- onlineHelp: 'chapter_storage',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/disks/directory",
- method: 'POST',
- items: [
- {
- xtype: 'pveDiskSelector',
- name: 'device',
- nodename: me.nodename,
- diskType: 'unused',
- fieldLabel: gettext('Disk'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxKVComboBox',
- comboItems: [
- ['ext4', 'ext4'],
- ['xfs', 'xfs']
- ],
- fieldLabel: gettext('Filesystem'),
- name: 'filesystem',
- value: '',
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'add_storage',
- fieldLabel: gettext('Add Storage'),
- value: '1'
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.Directorylist', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveDirectoryList',
-
- stateful: true,
- stateId: 'grid-node-directory',
- columns: [
- {
- text: gettext('Path'),
- dataIndex: 'path',
- flex: 1
- },
- {
- header: gettext('Device'),
- flex: 1,
- dataIndex: 'device'
- },
- {
- header: gettext('Type'),
- width: 100,
- dataIndex: 'type'
- },
- {
- header: gettext('Options'),
- width: 100,
- dataIndex: 'options'
- },
- {
- header: gettext('Unit File'),
- hidden: true,
- dataIndex: 'unitfile'
- }
- ],
-
- rootVisible: false,
- useArrows: true,
-
- tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
- var me = this.up('panel');
- me.reload();
- }
- },
- {
- text: gettext('Create') + ': Directory',
- handler: function() {
- var me = this.up('panel');
- var win = Ext.create('PVE.node.CreateDirectory', {
- nodename: me.nodename
- }).show();
- win.on('destroy', function() { me.reload(); });
- }
- }
- ],
-
- reload: function() {
- var me = this;
- me.store.load();
- me.store.sort();
- },
-
- listeners: {
- activate: function() {
- var me = this;
- me.reload();
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- store: {
- fields: ['path', 'device', 'type', 'options', 'unitfile' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + '/disks/directory'
- },
- sorters: 'path'
- }
- });
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.getStore(), true);
- me.reload();
- }
-});
-
-/*jslint confusion: true*/
-Ext.define('PVE.node.CreateZFS', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCreateZFS',
-
- subject: 'ZFS',
-
- showProgress: true,
-
- onlineHelp: 'chapter_zfs',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- var update_disklist = function() {
- var grid = me.down('#disklist');
- var disks = grid.getSelection();
-
- var val = [];
- disks.sort(function(a,b) {
- var aorder = a.get('order') || 0;
- var border = b.get('order') || 0;
- return (aorder - border);
- });
-
- disks.forEach(function(disk) {
- val.push(disk.get('devpath'));
- });
-
- me.down('field[name=devices]').setValue(val.join(','));
- };
-
- Ext.apply(me, {
- url: '/nodes/' + me.nodename + '/disks/zfs',
- method: 'POST',
- items: [
- {
- xtype: 'inputpanel',
- onGetValues: function(values) {
- return values;
- },
- column1: [
- {
- xtype: 'textfield',
- hidden: true,
- name: 'devices',
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'add_storage',
- fieldLabel: gettext('Add Storage'),
- value: '1'
- }
- ],
- column2: [
- {
- xtype: 'proxmoxKVComboBox',
- fieldLabel: gettext('RAID Level'),
- name: 'raidlevel',
- value: 'single',
- comboItems: [
- ['single', gettext('Single Disk')],
- ['mirror', 'Mirror'],
- ['raid10', 'RAID10'],
- ['raidz', 'RAIDZ'],
- ['raidz2', 'RAIDZ2'],
- ['raidz3', 'RAIDZ3']
- ]
- },
- {
- xtype: 'proxmoxKVComboBox',
- fieldLabel: gettext('Compression'),
- name: 'compression',
- value: 'on',
- comboItems: [
- ['on', 'on'],
- ['off', 'off'],
- ['gzip', 'gzip'],
- ['lz4', 'lz4'],
- ['lzjb', 'lzjb'],
- ['zle', 'zle']
- ]
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('ashift'),
- minValue: 9,
- maxValue: 16,
- value: '12',
- name: 'ashift'
- }
- ],
- columnB: [
- {
- xtype: 'grid',
- height: 200,
- emptyText: gettext('No Disks unused'),
- itemId: 'disklist',
- selModel: 'checkboxmodel',
- listeners: {
- selectionchange: update_disklist
- },
- store: {
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/disks/list?type=unused'
- }
- },
- columns: [
- {
- text: gettext('Device'),
- dataIndex: 'devpath',
- flex: 1
- },
- {
- text: gettext('Serial'),
- dataIndex: 'serial'
- },
- {
- text: gettext('Size'),
- dataIndex: 'size',
- renderer: PVE.Utils.render_size
- },
- {
- header: gettext('Order'),
- xtype: 'widgetcolumn',
- dataIndex: 'order',
- sortable: true,
- widget: {
- xtype: 'proxmoxintegerfield',
- minValue: 1,
- isFormField: false,
- listeners: {
- change: function(numberfield, value, old_value) {
- var record = numberfield.getWidgetRecord();
- record.set('order', value);
- update_disklist(record);
- }
- }
- }
- }
- ]
- }
- ]
- }
- ]
- });
-
- me.callParent();
- me.down('#disklist').getStore().load();
- }
-});
-
-Ext.define('PVE.node.ZFSDevices', {
- extend: 'Ext.tree.Panel',
- xtype: 'pveZFSDevices',
- stateful: true,
- stateId: 'grid-node-zfsstatus',
- columns: [
- {
- xtype: 'treecolumn',
- text: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- text: gettext('Health'),
- renderer: PVE.Utils.render_zfs_health,
- dataIndex: 'state'
- },
- {
- text: 'READ',
- dataIndex: 'read'
- },
- {
- text: 'WRITE',
- dataIndex: 'write'
- },
- {
- text: 'CKSUM',
- dataIndex: 'cksum'
- },
- {
- text: gettext('Message'),
- dataIndex: 'msg'
- }
- ],
-
- rootVisible: true,
-
- reload: function() {
- var me = this;
- var sm = me.getSelectionModel();
- Proxmox.Utils.API2Request({
- url: "/nodes/" + me.nodename + "/disks/zfs/" + me.zpool,
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- },
- success: function(response, opts) {
- sm.deselectAll();
- me.setRootNode(response.result.data);
- me.expandAll();
- }
- });
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.zpool) {
- throw "no zpool specified";
- }
-
- var sm = Ext.create('Ext.selection.TreeModel', {});
-
- Ext.apply(me, {
- selModel: sm,
- fields: ['name', 'status',
- {
- type: 'string',
- name: 'iconCls',
- calculate: function(data) {
- var txt = 'fa x-fa-tree fa-';
- if (data.leaf) {
- return txt + 'hdd-o';
- }
- }
- }
- ],
- sorters: 'name'
- });
-
- me.callParent();
-
- me.reload();
- }
-});
-
-Ext.define('PVE.node.ZFSStatus', {
- extend: 'Proxmox.grid.ObjectGrid',
- xtype: 'pveZFSStatus',
- layout: 'fit',
- border: false,
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.zpool) {
- throw "no zpool specified";
- }
-
- me.url = "/api2/extjs/nodes/" + me.nodename + "/disks/zfs/" + me.zpool;
-
- me.rows = {
- scan: {
- header: gettext('Scan')
- },
- status: {
- header: gettext('Status')
- },
- action: {
- header: gettext('Action')
- },
- errors: {
- header: gettext('Errors')
- }
- };
-
- me.callParent();
- me.reload();
- }
-});
-
-Ext.define('PVE.node.ZFSList', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveZFSList',
-
- stateful: true,
- stateId: 'grid-node-zfs',
- columns: [
- {
- text: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- header: gettext('Size'),
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- },
- {
- header: gettext('Free'),
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'free'
- },
- {
- header: gettext('Allocated'),
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'alloc'
- },
- {
- header: gettext('Fragmentation'),
- renderer: function(value) {
- return value.toString() + '%';
- },
- dataIndex: 'frag'
- },
- {
- header: gettext('Health'),
- renderer: PVE.Utils.render_zfs_health,
- dataIndex: 'health'
- },
- {
- header: gettext('Deduplication'),
- hidden: true,
- renderer: function(value) {
- return value.toFixed(2).toString() + 'x';
- },
- dataIndex: 'dedup'
- }
- ],
-
- rootVisible: false,
- useArrows: true,
-
- tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
- var me = this.up('panel');
- me.reload();
- }
- },
- {
- text: gettext('Create') + ': ZFS',
- handler: function() {
- var me = this.up('panel');
- var win = Ext.create('PVE.node.CreateZFS', {
- nodename: me.nodename
- }).show();
- win.on('destroy', function() { me.reload(); });
- }
- },
- {
- text: gettext('Detail'),
- itemId: 'detailbtn',
- disabled: true,
- handler: function() {
- var me = this.up('panel');
- var selection = me.getSelection();
- if (selection.length < 1) {
- return;
- }
- me.show_detail(selection[0].get('name'));
- }
- }
- ],
-
- show_detail: function(zpool) {
- var me = this;
-
- var detailsgrid = Ext.create('PVE.node.ZFSStatus', {
- layout: 'fit',
- nodename: me.nodename,
- flex: 0,
- zpool: zpool
- });
-
- var devicetree = Ext.create('PVE.node.ZFSDevices', {
- title: gettext('Devices'),
- nodename: me.nodename,
- flex: 1,
- zpool: zpool
- });
-
-
- var win = Ext.create('Ext.window.Window', {
- modal: true,
- width: 800,
- height: 400,
- resizable: true,
- layout: 'fit',
- title: gettext('Status') + ': ' + zpool,
- items:[{
- xtype: 'panel',
- region: 'center',
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- items: [detailsgrid, devicetree],
- tbar: [{
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
-
- devicetree.reload();
- detailsgrid.reload();
- }
- }]
- }]
- }).show();
- },
-
- set_button_status: function() {
- var me = this;
- var selection = me.getSelection();
- me.down('#detailbtn').setDisabled(selection.length === 0);
- },
-
- reload: function() {
- var me = this;
- me.store.load();
- me.store.sort();
- },
-
- listeners: {
- activate: function() {
- var me = this;
- me.reload();
- },
- selectionchange: function() {
- this.set_button_status();
- },
- itemdblclick: function(grid, record) {
- var me = this;
- me.show_detail(record.get('name'));
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- store: {
- fields: ['name', 'size', 'free', 'alloc', 'dedup', 'frag', 'health'],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + '/disks/zfs'
- },
- sorters: 'name'
- }
- });
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.getStore(), true);
- me.reload();
- }
-});
-
-Ext.define('PVE.node.StatusView', {
- extend: 'PVE.panel.StatusView',
- alias: 'widget.pveNodeStatus',
-
- height: 300,
- bodyPadding: '20 15 20 15',
-
- layout: {
- type: 'table',
- columns: 2,
- tableAttrs: {
- style: {
- width: '100%'
- }
- }
- },
-
- defaults: {
- xtype: 'pveInfoWidget',
- padding: '0 15 5 15'
- },
-
- items: [
- {
- itemId: 'cpu',
- iconCls: 'fa fa-fw pve-itype-icon-processor pve-icon',
- title: gettext('CPU usage'),
- valueField: 'cpu',
- maxField: 'cpuinfo',
- renderer: PVE.Utils.render_node_cpu_usage
- },
- {
- itemId: 'wait',
- iconCls: 'fa fa-fw fa-clock-o',
- title: gettext('IO delay'),
- valueField: 'wait',
- rowspan: 2
- },
- {
- itemId: 'load',
- iconCls: 'fa fa-fw fa-tasks',
- title: gettext('Load average'),
- printBar: false,
- textField: 'loadavg'
- },
- {
- xtype: 'box',
- colspan: 2,
- padding: '0 0 20 0'
- },
- {
- iconCls: 'fa fa-fw pve-itype-icon-memory pve-icon',
- itemId: 'memory',
- title: gettext('RAM usage'),
- valueField: 'memory',
- maxField: 'memory',
- renderer: PVE.Utils.render_node_size_usage
- },
- {
- itemId: 'ksm',
- printBar: false,
- title: gettext('KSM sharing'),
- textField: 'ksm',
- renderer: function(record) {
- return PVE.Utils.render_size(record.shared);
- },
- padding: '0 15 10 15'
- },
- {
- iconCls: 'fa fa-fw fa-hdd-o',
- itemId: 'rootfs',
- title: gettext('HD space') + '(root)',
- valueField: 'rootfs',
- maxField: 'rootfs',
- renderer: PVE.Utils.render_node_size_usage
- },
- {
- iconCls: 'fa fa-fw fa-refresh',
- itemId: 'swap',
- printSize: true,
- title: gettext('SWAP usage'),
- valueField: 'swap',
- maxField: 'swap',
- renderer: PVE.Utils.render_node_size_usage
- },
- {
- xtype: 'box',
- colspan: 2,
- padding: '0 0 20 0'
- },
- {
- itemId: 'cpus',
- colspan: 2,
- printBar: false,
- title: gettext('CPU(s)'),
- textField: 'cpuinfo',
- renderer: function(cpuinfo) {
- return cpuinfo.cpus + " x " + cpuinfo.model + " (" +
- cpuinfo.sockets.toString() + " " +
- (cpuinfo.sockets > 1 ?
- gettext('Sockets') :
- gettext('Socket')
- ) + ")";
- },
- value: ''
- },
- {
- itemId: 'kversion',
- colspan: 2,
- title: gettext('Kernel Version'),
- printBar: false,
- textField: 'kversion',
- value: ''
- },
- {
- itemId: 'version',
- colspan: 2,
- printBar: false,
- title: gettext('PVE Manager Version'),
- textField: 'pveversion',
- value: ''
- }
- ],
-
- updateTitle: function() {
- var me = this;
- var uptime = Proxmox.Utils.render_uptime(me.getRecordValue('uptime'));
- me.setTitle(me.pveSelNode.data.node + ' (' + gettext('Uptime') + ': ' + uptime + ')');
- }
-
-});
-Ext.define('PVE.node.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNodeSummary',
-
- scrollable: true,
- bodyPadding: 5,
-
- showVersions: function() {
- var me = this;
-
- // Note: we use simply text/html here, because ExtJS grid has problems
- // with cut&paste
-
- var nodename = me.pveSelNode.data.node;
-
- var view = Ext.createWidget('component', {
- autoScroll: true,
- padding: 5,
- style: {
- 'background-color': '#23272a',
- 'white-space': 'pre',
- 'font-family': 'monospace'
- }
- });
-
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Package versions'),
- width: 600,
- height: 400,
- layout: 'fit',
- modal: true,
- items: [ view ]
- });
-
- Proxmox.Utils.API2Request({
- waitMsgTarget: me,
- url: "/nodes/" + nodename + "/apt/versions",
- method: 'GET',
- failure: function(response, opts) {
- win.close();
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- win.show();
- var text = '';
-
- Ext.Array.each(response.result.data, function(rec) {
- var version = "not correctly installed";
- var pkg = rec.Package;
- if (rec.OldVersion && rec.CurrentState === 'Installed') {
- version = rec.OldVersion;
- }
- if (rec.RunningKernel) {
- text += pkg + ': ' + version + ' (running kernel: ' +
- rec.RunningKernel + ')\n';
- } else if (rec.ManagerVersion) {
- text += pkg + ': ' + version + ' (running version: ' +
- rec.ManagerVersion + ')\n';
- } else {
- text += pkg + ': ' + version + '\n';
- }
- });
-
- view.update(Ext.htmlEncode(text));
- }
- });
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- if (!me.statusStore) {
- throw "no status storage specified";
- }
-
- var rstore = me.statusStore;
-
- var version_btn = new Ext.Button({
- text: gettext('Package versions'),
- handler: function(){
- Proxmox.Utils.checked_command(function() { me.showVersions(); });
- }
- });
-
- var rrdstore = Ext.create('Proxmox.data.RRDStore', {
- rrdurl: "/api2/json/nodes/" + nodename + "/rrddata",
- model: 'pve-rrd-node'
- });
-
- Ext.apply(me, {
- tbar: [version_btn, '->', { xtype: 'proxmoxRRDTypeSelector' } ],
- items: [
- {
- xtype: 'container',
- layout: 'column',
- defaults: {
- minHeight: 320,
- padding: 5,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- }
- },
- items: [
- {
- xtype: 'pveNodeStatus',
- rstore: rstore,
- width: 770,
- pveSelNode: me.pveSelNode
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('CPU usage'),
- fields: ['cpu','iowait'],
- fieldTitles: [gettext('CPU usage'), gettext('IO delay')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Server load'),
- fields: ['loadavg'],
- fieldTitles: [gettext('Load average')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Memory usage'),
- fields: ['memtotal','memused'],
- fieldTitles: [gettext('Total'), gettext('RAM usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Network traffic'),
- fields: ['netin','netout'],
- store: rrdstore
- }
- ]
- }
- ],
- listeners: {
- activate: function() { rstore.startUpdate(); rrdstore.startUpdate(); },
- destroy: function() { rstore.stopUpdate(); rrdstore.stopUpdate(); }
- }
- });
-
- me.callParent();
- }
-});
-/*global Blob*/
-Ext.define('PVE.node.SubscriptionKeyEdit', {
- extend: 'Proxmox.window.Edit',
- title: gettext('Upload Subscription Key'),
- width: 300,
- items: {
- xtype: 'textfield',
- name: 'key',
- value: '',
- fieldLabel: gettext('Subscription Key')
- },
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- me.load();
- }
-});
-
-Ext.define('PVE.node.Subscription', {
- extend: 'Proxmox.grid.ObjectGrid',
-
- alias: ['widget.pveNodeSubscription'],
-
- onlineHelp: 'getting_help',
-
- viewConfig: {
- enableTextSelection: true
- },
-
- showReport: function() {
- var me = this;
- var nodename = me.pveSelNode.data.node;
-
- var getReportFileName = function() {
- var now = Ext.Date.format(new Date(), 'D-d-F-Y-G-i');
- return me.nodename + '-report-' + now + '.txt';
- };
-
- var view = Ext.createWidget('component', {
- itemId: 'system-report-view',
- scrollable: true,
- style: {
- 'background-color': '#23272a',
- 'white-space': 'pre',
- 'font-family': 'monospace',
- padding: '5px'
- }
- });
-
- var reportWindow = Ext.create('Ext.window.Window', {
- title: gettext('System Report'),
- width: 1024,
- height: 600,
- layout: 'fit',
- modal: true,
- buttons: [
- '->',
- {
- text: gettext('Download'),
- handler: function() {
- var fileContent = reportWindow.getComponent('system-report-view').html;
- var fileName = getReportFileName();
-
- // Internet Explorer
- if (window.navigator.msSaveOrOpenBlob) {
- navigator.msSaveOrOpenBlob(new Blob([fileContent]), fileName);
- } else {
- var element = document.createElement('a');
- element.setAttribute('href', 'data:text/plain;charset=utf-8,'
- + encodeURIComponent(fileContent));
- element.setAttribute('download', fileName);
- element.style.display = 'none';
- document.body.appendChild(element);
- element.click();
- document.body.removeChild(element);
- }
- }
- }
- ],
- items: view
- });
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/nodes/' + me.nodename + '/report',
- method: 'GET',
- waitMsgTarget: me,
- failure: function(response) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response) {
- var report = Ext.htmlEncode(response.result.data);
- reportWindow.show();
- view.update(report);
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var reload = function() {
- me.rstore.load();
- };
-
- var baseurl = '/nodes/' + me.nodename + '/subscription';
-
- var render_status = function(value) {
-
- var message = me.getObjectValue('message');
-
- if (message) {
- return value + ": " + message;
- }
- return value;
- };
-
- var rows = {
- productname: {
- header: gettext('Type')
- },
- key: {
- header: gettext('Subscription Key')
- },
- status: {
- header: gettext('Status'),
- renderer: render_status
- },
- message: {
- visible: false
- },
- serverid: {
- header: gettext('Server ID')
- },
- sockets: {
- header: gettext('Sockets')
- },
- checktime: {
- header: gettext('Last checked'),
- renderer: Proxmox.Utils.render_timestamp
- },
- nextduedate: {
- header: gettext('Next due date')
- }
- };
-
- Ext.apply(me, {
- url: '/api2/json' + baseurl,
- cwidth1: 170,
- tbar: [
- {
- text: gettext('Upload Subscription Key'),
- handler: function() {
- var win = Ext.create('PVE.node.SubscriptionKeyEdit', {
- url: '/api2/extjs/' + baseurl
- });
- win.show();
- win.on('destroy', reload);
- }
- },
- {
- text: gettext('Check'),
- handler: function() {
- Proxmox.Utils.API2Request({
- params: { force: 1 },
- url: baseurl,
- method: 'POST',
- waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- callback: reload
- });
- }
- },
- {
- text: gettext('System Report'),
- handler: function() {
- Proxmox.Utils.checked_command(function (){ me.showReport(); });
- }
- }
- ],
- rows: rows,
- listeners: {
- activate: reload
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.node.CertificateView', {
- extend: 'Ext.container.Container',
- xtype: 'pveCertificatesView',
-
- onlineHelp: 'sysadmin_certificate_management',
-
- mixins: ['Proxmox.Mixin.CBind' ],
-
- items: [
- {
- xtype: 'pveCertView',
- border: 0,
- cbind: {
- nodename: '{nodename}'
- }
- },
- {
- xtype: 'pveACMEView',
- border: 0,
- cbind: {
- nodename: '{nodename}'
- }
- }
- ]
-
-});
-
-Ext.define('PVE.node.CertificateViewer', {
- extend: 'Proxmox.window.Edit',
-
- title: gettext('Certificate'),
-
- fieldDefaults: {
- labelWidth: 120
- },
- width: 800,
- resizable: true,
-
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Name'),
- name: 'filename'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Fingerprint'),
- name: 'fingerprint'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Issuer'),
- name: 'issuer'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Subject'),
- name: 'subject'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Valid Since'),
- renderer: Proxmox.Utils.render_timestamp,
- name: 'notbefore'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Expires'),
- renderer: Proxmox.Utils.render_timestamp,
- name: 'notafter'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Subject Alternative Names'),
- name: 'san',
- renderer: PVE.Utils.render_san
- },
- {
- xtype: 'textarea',
- editable: false,
- grow: true,
- growMax: 200,
- fieldLabel: gettext('Certificate'),
- name: 'pem'
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.cert) {
- throw "no cert given";
- }
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- me.url = '/nodes/' + me.nodename + '/certificates/info';
- me.callParent();
-
- // hide OK/Reset button, because we just want to show data
- me.down('toolbar[dock=bottom]').setVisible(false);
-
- me.load({
- success: function(response) {
- if (Ext.isArray(response.result.data)) {
- Ext.Array.each(response.result.data, function(item) {
- if (item.filename === me.cert) {
- me.setValues(item);
- return false;
- }
- });
- }
- }
- });
- }
-});
-
-Ext.define('PVE.node.CertUpload', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCertUpload',
-
- title: gettext('Upload Custom Certificate'),
- resizable: false,
- isCreate: true,
- submitText: gettext('Upload'),
- method: 'POST',
- width: 600,
-
- apiCallDone: function(success, response, options) {
- if (!success) {
- return;
- }
-
- var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
- Ext.getBody().mask(txt, ['pve-static-mask']);
- // reload after 10 seconds automatically
- Ext.defer(function() {
- window.location.reload(true);
- }, 10000);
- },
-
- items: [
- {
- fieldLabel: gettext('Private Key (Optional)'),
- labelAlign: 'top',
- emptyText: gettext('No change'),
- name: 'key',
- xtype: 'textarea'
- },
- {
- xtype: 'filebutton',
- text: gettext('From File'),
- listeners: {
- change: function(btn, e, value) {
- var me = this.up('form');
- e = e.event;
- Ext.Array.each(e.target.files, function(file) {
- PVE.Utils.loadSSHKeyFromFile(file, function(res) {
- me.down('field[name=key]').setValue(res);
- });
- });
- btn.reset();
- }
- }
- },
- {
- xtype: 'box',
- autoEl: 'hr'
- },
- {
- fieldLabel: gettext('Certificate Chain'),
- labelAlign: 'top',
- allowBlank: false,
- name: 'certificates',
- xtype: 'textarea'
- },
- {
- xtype: 'filebutton',
- text: gettext('From File'),
- listeners: {
- change: function(btn, e, value) {
- var me = this.up('form');
- e = e.event;
- Ext.Array.each(e.target.files, function(file) {
- PVE.Utils.loadSSHKeyFromFile(file, function(res) {
- me.down('field[name=certificates]').setValue(res);
- });
- });
- btn.reset();
- }
- }
- },
- {
- xtype: 'hidden',
- name: 'restart',
- value: '1'
- },
- {
- xtype: 'hidden',
- name: 'force',
- value: '1'
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- me.url = '/nodes/' + me.nodename + '/certificates/custom';
-
- me.callParent();
- }
-});
-
-Ext.define('pve-certificate', {
- extend: 'Ext.data.Model',
-
- fields: [ 'filename', 'fingerprint', 'issuer', 'notafter', 'notbefore', 'subject', 'san' ],
- idProperty: 'filename'
-});
-
-Ext.define('PVE.node.Certificates', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveCertView',
-
- tbar: [
- {
- xtype: 'button',
- text: gettext('Upload Custom Certificate'),
- handler: function() {
- var me = this.up('grid');
- var win = Ext.create('PVE.node.CertUpload', {
- nodename: me.nodename
- });
- win.show();
- win.on('destroy', me.reload, me);
- }
- },
- {
- xtype: 'button',
- itemId: 'deletebtn',
- text: gettext('Delete Custom Certificate'),
- handler: function() {
- var me = this.up('grid');
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/certificates/custom?restart=1',
- method: 'DELETE',
- success: function(response, opt) {
- var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
- Ext.getBody().mask(txt, ['pve-static-mask']);
- // reload after 10 seconds automatically
- Ext.defer(function() {
- window.location.reload(true);
- }, 10000);
- },
- failure: function(response, opt) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- },
- '-',
- {
- xtype: 'proxmoxButton',
- itemId: 'viewbtn',
- disabled: true,
- text: gettext('View Certificate'),
- handler: function() {
- var me = this.up('grid');
- me.view_certificate();
- }
- }
- ],
-
- columns: [
- {
- header: gettext('File'),
- width: 150,
- dataIndex: 'filename'
- },
- {
- header: gettext('Issuer'),
- flex: 1,
- dataIndex: 'issuer'
- },
- {
- header: gettext('Subject'),
- flex: 1,
- dataIndex: 'subject'
- },
- {
- header: gettext('Valid Since'),
- width: 150,
- dataIndex: 'notbefore',
- renderer: Proxmox.Utils.render_timestamp
- },
- {
- header: gettext('Expires'),
- width: 150,
- dataIndex: 'notafter',
- renderer: Proxmox.Utils.render_timestamp
- },
- {
- header: gettext('Subject Alternative Names'),
- flex: 1,
- dataIndex: 'san',
- renderer: PVE.Utils.render_san
- },
- {
- header: gettext('Fingerprint'),
- dataIndex: 'fingerprint',
- hidden: true
- },
- {
- header: gettext('PEM'),
- dataIndex: 'pem',
- hidden: true
- }
- ],
-
- reload: function() {
- var me = this;
- me.rstore.load();
- },
-
- set_button_status: function() {
- var me = this;
- var rec = me.rstore.getById('pveproxy-ssl.pem');
-
- me.down('#deletebtn').setDisabled(!rec);
- },
-
- view_certificate: function() {
- var me = this;
- var selection = me.getSelection();
- if (!selection || selection.length < 1) {
- return;
- }
- var win = Ext.create('PVE.node.CertificateViewer', {
- cert: selection[0].data.filename,
- nodename : me.nodename
- });
- win.show();
- },
-
- listeners: {
- itemdblclick: 'view_certificate'
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- me.rstore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'certs-' + me.nodename,
- model: 'pve-certificate',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/certificates/info'
- }
- });
-
- me.store = {
- type: 'diff',
- rstore: me.rstore
- };
-
- me.callParent();
-
- me.mon(me.rstore, 'load', me.set_button_status, me);
- me.rstore.startUpdate();
- }
-});
-Ext.define('PVE.node.ACMEEditor', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveACMEEditor',
-
- subject: gettext('Domains'),
- items: [
- {
- xtype: 'inputpanel',
- items: [
- {
- xtype: 'textarea',
- fieldLabel: gettext('Domains'),
- emptyText: "domain1.example.com\ndomain2.example.com",
- name: 'domains'
- }
- ],
- onGetValues: function(values) {
- if (!values.domains) {
- return {
- 'delete': 'acme'
- };
- }
- var domains = values.domains.split(/\n/).join(';');
- return {
- 'acme': 'domains=' + domains
- };
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
- me.callParent();
-
- me.load({
- success: function(response, opts) {
- var res = PVE.Parser.parseACME(response.result.data.acme);
- if (res) {
- res.domains = res.domains.join(' ');
- me.setValues(res);
- }
- }
- });
- }
-});
-
-Ext.define('PVE.node.ACMEAccountCreate', {
- extend: 'Proxmox.window.Edit',
-
- width: 400,
- title: gettext('Register Account'),
- isCreate: true,
- method: 'POST',
- submitText: gettext('Register'),
- url: '/cluster/acme/account',
- showTaskViewer: true,
-
- items: [
- {
- xtype: 'proxmoxComboGrid',
- name: 'directory',
- allowBlank: false,
- valueField: 'url',
- displayField: 'name',
- fieldLabel: gettext('ACME Directory'),
- store: {
- autoLoad: true,
- fields: ['name', 'url'],
- idProperty: ['name'],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/acme/directories'
- },
- sorters: {
- property: 'name',
- order: 'ASC'
- }
- },
- listConfig: {
- columns: [
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- header: gettext('URL'),
- dataIndex: 'url',
- flex: 1
- }
- ]
- },
- listeners: {
- change: function(combogrid, value) {
- var me = this;
- if (!value) {
- return;
- }
-
- var disp = me.up('window').down('#tos_url_display');
- var field = me.up('window').down('#tos_url');
- var checkbox = me.up('window').down('#tos_checkbox');
-
- disp.setValue(gettext('Loading'));
- field.setValue(undefined);
- checkbox.setValue(undefined);
-
- Proxmox.Utils.API2Request({
- url: '/cluster/acme/tos',
- method: 'GET',
- params: {
- directory: value
- },
- success: function(response, opt) {
- me.up('window').down('#tos_url').setValue(response.result.data);
- me.up('window').down('#tos_url_display').setValue(response.result.data);
- },
- failure: function(response, opt) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- }
- },
- {
- xtype: 'displayfield',
- itemId: 'tos_url_display',
- fieldLabel: gettext('Terms of Service'),
- renderer: PVE.Utils.render_optional_url,
- name: 'tos_url_display'
- },
- {
- xtype: 'hidden',
- itemId: 'tos_url',
- name: 'tos_url'
- },
- {
- xtype: 'proxmoxcheckbox',
- itemId: 'tos_checkbox',
- fieldLabel: gettext('Accept TOS'),
- submitValue: false,
- validateValue: function(value) {
- if (value && this.checked) {
- return true;
- }
- return false;
- }
- },
- {
- xtype: 'textfield',
- name: 'contact',
- vtype: 'email',
- allowBlank: false,
- fieldLabel: gettext('E-Mail')
- }
- ]
-
-});
-
-Ext.define('PVE.node.ACMEAccountView', {
- extend: 'Proxmox.window.Edit',
-
- width: 600,
- fieldDefaults: {
- labelWidth: 140
- },
-
- title: gettext('Account'),
-
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('E-Mail'),
- name: 'email'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Created'),
- name: 'createdAt'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Status'),
- name: 'status'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Directory'),
- renderer: PVE.Utils.render_optional_url,
- name: 'directory'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Terms of Services'),
- renderer: PVE.Utils.render_optional_url,
- name: 'tos'
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.accountname) {
- throw "no account name defined";
- }
-
- me.url = '/cluster/acme/account/' + me.accountname;
-
- me.callParent();
-
- // hide OK/Reset button, because we just want to show data
- me.down('toolbar[dock=bottom]').setVisible(false);
-
- me.load({
- success: function(response) {
- var data = response.result.data;
- data.email = data.account.contact[0];
- data.createdAt = data.account.createdAt;
- data.status = data.account.status;
- me.setValues(data);
- }
- });
- }
-});
-
-Ext.define('PVE.node.ACME', {
- extend: 'Proxmox.grid.ObjectGrid',
- xtype: 'pveACMEView',
-
- margin: '10 0 0 0',
- title: 'ACME',
-
- tbar: [
- {
- xtype: 'button',
- itemId: 'edit',
- text: gettext('Edit Domains'),
- handler: function() {
- this.up('grid').run_editor();
- }
- },
- {
- xtype: 'button',
- itemId: 'createaccount',
- text: gettext('Register Account'),
- handler: function() {
- var me = this.up('grid');
- var win = Ext.create('PVE.node.ACMEAccountCreate', {
- taskDone: function() {
- me.load_account();
- me.reload();
- }
- });
- win.show();
- }
- },
- {
- xtype: 'button',
- itemId: 'viewaccount',
- text: gettext('View Account'),
- handler: function() {
- var me = this.up('grid');
- var win = Ext.create('PVE.node.ACMEAccountView', {
- accountname: 'default'
- });
- win.show();
- }
- },
- {
- xtype: 'button',
- itemId: 'order',
- text: gettext('Order Certificate'),
- handler: function() {
- var me = this.up('grid');
-
- Proxmox.Utils.API2Request({
- method: 'POST',
- params: {
- force: 1
- },
- url: '/nodes/' + me.nodename + '/certificates/acme/certificate',
- success: function(response, opt) {
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: response.result.data,
- taskDone: function(success) {
- me.certificate_order_finished(success);
- }
- });
- win.show();
- },
- failure: function(response, opt) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- }
- ],
-
- certificate_order_finished: function(success) {
- if (!success) {
- return;
- }
- var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
- Ext.getBody().mask(txt, ['pve-static-mask']);
- // reload after 10 seconds automatically
- Ext.defer(function() {
- window.location.reload(true);
- }, 10000);
- },
-
- set_button_status: function() {
- var me = this;
-
- var account = !!me.account;
- var acmeObj = PVE.Parser.parseACME(me.getObjectValue('acme'));
- var domains = acmeObj ? acmeObj.domains.length : 0;
-
- var order = me.down('#order');
- order.setVisible(account);
- order.setDisabled(!account || !domains);
-
- me.down('#createaccount').setVisible(!account);
- me.down('#viewaccount').setVisible(account);
- },
-
- load_account: function() {
- var me = this;
-
- // for now we only use the 'default' account
- Proxmox.Utils.API2Request({
- url: '/cluster/acme/account/default',
- success: function(response, opt) {
- me.account = response.result.data;
- me.set_button_status();
- },
- failure: function(response, opt) {
- me.account = undefined;
- me.set_button_status();
- }
- });
- },
-
- run_editor: function() {
- var me = this;
- var win = Ext.create(me.rows.acme.editor, me.editorConfig);
- win.show();
- win.on('destroy', me.reload, me);
- },
-
- listeners: {
- itemdblclick: 'run_editor'
- },
-
- // account data gets loaded here
- account: undefined,
-
- disableSelection: true,
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- me.url = '/api2/json/nodes/' + me.nodename + '/config';
-
- me.editorConfig = {
- url: '/api2/extjs/nodes/' + me.nodename + '/config'
- };
- /*jslint confusion: true*/
- /*acme is a string above*/
- me.rows = {
- acme: {
- defaultValue: '',
- header: gettext('Domains'),
- editor: 'PVE.node.ACMEEditor',
- renderer: function(value) {
- var acmeObj = PVE.Parser.parseACME(value);
- if (acmeObj) {
- return acmeObj.domains.join(' ');
- }
- return Proxmox.Utils.noneText;
- }
- }
- };
- /*jslint confusion: false*/
-
- me.callParent();
- me.mon(me.rstore, 'load', me.set_button_status, me);
- me.rstore.startUpdate();
- me.load_account();
- }
-});
-Ext.define('PVE.node.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.node.Config',
-
- onlineHelp: 'chapter_system_administration',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: "/api2/json/nodes/" + nodename + "/status",
- interval: 1000
- });
-
- var node_command = function(cmd) {
- Proxmox.Utils.API2Request({
- params: { command: cmd },
- url: '/nodes/' + nodename + '/status',
- method: 'POST',
- waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var actionBtn = Ext.create('Ext.Button', {
- text: gettext('Bulk Actions'),
- iconCls: 'fa fa-fw fa-ellipsis-v',
- disabled: !caps.nodes['Sys.PowerMgmt'],
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Bulk Start'),
- iconCls: 'fa fa-fw fa-play',
- handler: function() {
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: nodename,
- title: gettext('Bulk Start'),
- btnText: gettext('Start'),
- action: 'startall'
- });
- win.show();
- }
- },
- {
- text: gettext('Bulk Stop'),
- iconCls: 'fa fa-fw fa-stop',
- handler: function() {
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: nodename,
- title: gettext('Bulk Stop'),
- btnText: gettext('Stop'),
- action: 'stopall'
- });
- win.show();
- }
- },
- {
- text: gettext('Bulk Migrate'),
- iconCls: 'fa fa-fw fa-send-o',
- handler: function() {
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: nodename,
- title: gettext('Bulk Migrate'),
- btnText: gettext('Migrate'),
- action: 'migrateall'
- });
- win.show();
- }
- }
- ]
- })
- });
-
- var restartBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('Reboot'),
- disabled: !caps.nodes['Sys.PowerMgmt'],
- dangerous: true,
- confirmMsg: Ext.String.format(gettext("Reboot node '{0}'?"), nodename),
- handler: function() {
- node_command('reboot');
- },
- iconCls: 'fa fa-undo'
- });
-
- var shutdownBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('Shutdown'),
- disabled: !caps.nodes['Sys.PowerMgmt'],
- dangerous: true,
- confirmMsg: Ext.String.format(gettext("Shutdown node '{0}'?"), nodename),
- handler: function() {
- node_command('shutdown');
- },
- iconCls: 'fa fa-power-off'
- });
-
- var shellBtn = Ext.create('PVE.button.ConsoleButton', {
- disabled: !caps.nodes['Sys.Console'],
- text: gettext('Shell'),
- consoleType: 'shell',
- nodename: nodename
- });
-
- me.items = [];
-
- Ext.apply(me, {
- title: gettext('Node') + " '" + nodename + "'",
- hstateid: 'nodetab',
- defaults: { statusStore: me.statusStore },
- tbar: [ restartBtn, shutdownBtn, shellBtn, actionBtn]
- });
-
- if (caps.nodes['Sys.Audit']) {
- me.items.push(
- {
- title: gettext('Summary'),
- iconCls: 'fa fa-book',
- itemId: 'summary',
- xtype: 'pveNodeSummary'
- },
- {
- title: gettext('Notes'),
- iconCls: 'fa fa-sticky-note-o',
- itemId: 'notes',
- xtype: 'pveNotesView'
- }
- );
- }
-
- if (caps.nodes['Sys.Console']) {
- me.items.push(
- {
- title: gettext('Shell'),
- iconCls: 'fa fa-terminal',
- itemId: 'jsconsole',
- xtype: 'pveNoVncConsole',
- consoleType: 'shell',
- xtermjs: true,
- nodename: nodename
- }
- );
- }
-
- if (caps.nodes['Sys.Audit']) {
- me.items.push(
- {
- title: gettext('System'),
- iconCls: 'fa fa-cogs',
- itemId: 'services',
- expandedOnInit: true,
- startOnlyServices: {
- 'pveproxy': true,
- 'pvedaemon': true,
- 'pve-cluster': true
- },
- nodename: nodename,
- onlineHelp: 'pve_service_daemons',
- xtype: 'proxmoxNodeServiceView'
- },
- {
- title: gettext('Network'),
- iconCls: 'fa fa-exchange',
- itemId: 'network',
- groups: ['services'],
- nodename: nodename,
- onlineHelp: 'sysadmin_network_configuration',
- xtype: 'proxmoxNodeNetworkView'
- },
- {
- title: gettext('Certificates'),
- iconCls: 'fa fa-certificate',
- itemId: 'certificates',
- groups: ['services'],
- nodename: nodename,
- xtype: 'pveCertificatesView'
- },
- {
- title: gettext('DNS'),
- iconCls: 'fa fa-globe',
- groups: ['services'],
- itemId: 'dns',
- nodename: nodename,
- onlineHelp: 'sysadmin_network_configuration',
- xtype: 'proxmoxNodeDNSView'
- },
- {
- title: gettext('Hosts'),
- iconCls: 'fa fa-globe',
- groups: ['services'],
- itemId: 'hosts',
- nodename: nodename,
- onlineHelp: 'sysadmin_network_configuration',
- xtype: 'proxmoxNodeHostsView'
- },
- {
- title: gettext('Time'),
- itemId: 'time',
- groups: ['services'],
- nodename: nodename,
- xtype: 'proxmoxNodeTimeView',
- iconCls: 'fa fa-clock-o'
- });
- }
-
- if (caps.nodes['Sys.Syslog']) {
- me.items.push({
- title: 'Syslog',
- iconCls: 'fa fa-list',
- groups: ['services'],
- disabled: !caps.nodes['Sys.Syslog'],
- itemId: 'syslog',
- xtype: 'proxmoxLogView',
- url: "/api2/extjs/nodes/" + nodename + "/syslog",
- log_select_timespan: 1
- });
-
- if (caps.nodes['Sys.Modify']) {
- me.items.push({
- title: gettext('Updates'),
- iconCls: 'fa fa-refresh',
- disabled: !caps.nodes['Sys.Console'],
- // do we want to link to system updates instead?
- itemId: 'apt',
- xtype: 'proxmoxNodeAPT',
- upgradeBtn: {
- xtype: 'pveConsoleButton',
- disabled: Proxmox.UserName !== 'root@pam',
- text: gettext('Upgrade'),
- consoleType: 'upgrade',
- nodename: nodename
- },
- nodename: nodename
- });
- }
- }
-
- if (caps.nodes['Sys.Audit']) {
- me.items.push(
- {
- xtype: 'pveFirewallRules',
- iconCls: 'fa fa-shield',
- title: gettext('Firewall'),
- allow_iface: true,
- base_url: '/nodes/' + nodename + '/firewall/rules',
- list_refs_url: '/cluster/firewall/refs',
- itemId: 'firewall'
- },
- {
- xtype: 'pveFirewallOptions',
- title: gettext('Options'),
- iconCls: 'fa fa-gear',
- onlineHelp: 'pve_firewall_host_specific_configuration',
- groups: ['firewall'],
- base_url: '/nodes/' + nodename + '/firewall/options',
- fwtype: 'node',
- itemId: 'firewall-options'
- });
- }
-
-
- if (caps.nodes['Sys.Audit']) {
- me.items.push(
- {
- title: gettext('Disks'),
- itemId: 'storage',
- expandedOnInit: true,
- iconCls: 'fa fa-hdd-o',
- xtype: 'pveNodeDiskList'
- },
- {
- title: 'LVM',
- itemId: 'lvm',
- onlineHelp: 'chapter_lvm',
- iconCls: 'fa fa-square',
- groups: ['storage'],
- xtype: 'pveLVMList'
- },
- {
- title: 'LVM-Thin',
- itemId: 'lvmthin',
- onlineHelp: 'chapter_lvm',
- iconCls: 'fa fa-square-o',
- groups: ['storage'],
- xtype: 'pveLVMThinList'
- },
- {
- title: Proxmox.Utils.directoryText,
- itemId: 'directory',
- onlineHelp: 'chapter_storage',
- iconCls: 'fa fa-folder',
- groups: ['storage'],
- xtype: 'pveDirectoryList'
- },
- {
- title: 'ZFS',
- itemId: 'zfs',
- onlineHelp: 'chapter_zfs',
- iconCls: 'fa fa-th-large',
- groups: ['storage'],
- xtype: 'pveZFSList'
- },
- {
- title: 'Ceph',
- itemId: 'ceph',
- iconCls: 'fa fa-ceph',
- xtype: 'pveNodeCephStatus'
- },
- {
- xtype: 'pveReplicaView',
- iconCls: 'fa fa-retweet',
- title: gettext('Replication'),
- itemId: 'replication'
- },
- {
- xtype: 'pveNodeCephConfigCrush',
- title: gettext('Configuration'),
- iconCls: 'fa fa-gear',
- groups: ['ceph'],
- itemId: 'ceph-config'
- },
- {
- xtype: 'pveNodeCephMonList',
- title: gettext('Monitor'),
- iconCls: 'fa fa-tv',
- groups: ['ceph'],
- itemId: 'ceph-monlist'
- },
- {
- xtype: 'pveNodeCephOsdTree',
- title: 'OSD',
- iconCls: 'fa fa-hdd-o',
- groups: ['ceph'],
- itemId: 'ceph-osdtree'
- },
- {
- xtype: 'pveNodeCephFSPanel',
- title: 'CephFS',
- iconCls: 'fa fa-folder',
- groups: ['ceph'],
- nodename: nodename,
- itemId: 'ceph-cephfspanel'
- },
- {
- xtype: 'pveNodeCephPoolList',
- title: 'Pools',
- iconCls: 'fa fa-sitemap',
- groups: ['ceph'],
- itemId: 'ceph-pools'
- }
- );
- }
-
- if (caps.nodes['Sys.Syslog']) {
- me.items.push(
- {
- xtype: 'proxmoxLogView',
- title: gettext('Log'),
- iconCls: 'fa fa-list',
- groups: ['firewall'],
- onlineHelp: 'chapter_pve_firewall',
- url: '/api2/extjs/nodes/' + nodename + '/firewall/log',
- itemId: 'firewall-fwlog'
- },
- {
- title: gettext('Log'),
- itemId: 'ceph-log',
- iconCls: 'fa fa-list',
- groups: ['ceph'],
- onlineHelp: 'chapter_pveceph',
- xtype: 'cephLogView',
- url: "/api2/extjs/nodes/" + nodename + "/ceph/log",
- nodename: nodename
- });
- }
-
- me.items.push(
- {
- title: gettext('Task History'),
- iconCls: 'fa fa-list',
- itemId: 'tasks',
- nodename: nodename,
- xtype: 'proxmoxNodeTasks'
- },
- {
- title: gettext('Subscription'),
- iconCls: 'fa fa-support',
- itemId: 'support',
- xtype: 'pveNodeSubscription',
- nodename: nodename
- }
- );
-
- me.callParent();
-
- me.mon(me.statusStore, 'load', function(s, records, success) {
- var uptimerec = s.data.get('uptime');
- var powermgmt = uptimerec ? uptimerec.data.value : false;
- if (!caps.nodes['Sys.PowerMgmt']) {
- powermgmt = false;
- }
- restartBtn.setDisabled(!powermgmt);
- shutdownBtn.setDisabled(!powermgmt);
- shellBtn.setDisabled(!powermgmt);
- });
-
- me.on('afterrender', function() {
- me.statusStore.startUpdate();
- });
-
- me.on('destroy', function() {
- me.statusStore.stopUpdate();
- });
- }
-});
-Ext.define('PVE.window.Migrate', {
- extend: 'Ext.window.Window',
-
- config: {
- vmtype: undefined,
- nodename: undefined,
- vmid: undefined
- },
- // private, used to store the migration mode after checking if the guest runs
- liveMode: undefined,
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'panel[reference=formPanel]': {
- validityChange: function(panel, isValid) {
- this.lookup('submitButton').setDisabled(!isValid);
- }
- },
- 'button[reference=submitButton]': {
- click: function() {
- var me = this;
- var view = me.getView();
-
- var values = me.lookup('formPanel').getValues();
- var params = {
- target: values.target
- };
-
- if (view.liveMode) {
- params[view.liveMode] = 1;
- }
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + view.nodename + '/' + view.vmtype + '/' + view.vmid + '/migrate',
- waitMsgTarget: view,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var extraTitle = Ext.String.format(' ({0} ---> {1})', view.nodename, params.target);
-
- Ext.create('Proxmox.window.TaskViewer', {
- upid: upid,
- extraTitle: extraTitle
- }).show();
-
- view.close();
- }
- });
- }
- }
- }
- },
-
- width: 350,
- modal: true,
- layout: 'auto',
- border: false,
- resizable: false,
- items: [
- {
- xtype: 'form',
- reference: 'formPanel',
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [
- {
- xtype: 'pveNodeSelector',
- reference: 'pveNodeSelector',
- name: 'target',
- fieldLabel: gettext('Target node'),
- allowBlank: false,
- disallowedNodes: undefined,
- onlineValidator: true
- },
- {
- xtype: 'displayfield',
- reference: 'migrationMode',
- fieldLabel: gettext('Mode'),
- value: gettext('Offline')
- }
- ]
- }
- ],
- buttons: [
- {
- xtype: 'proxmoxHelpButton',
- reference: 'proxmoxHelpButton',
- onlineHelp: 'pct_migration',
- listenToGlobalEvent: false,
- hidden: false
- },
- '->',
- {
- xtype: 'button',
- reference: 'submitButton',
- text: gettext('Migrate')
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.vmtype) {
- throw "no VM type specified";
- }
-
- me.callParent();
-
- var title = gettext('Migrate') + (' CT ') + me.vmid;
- me.liveMode = 'restart';
-
- if (me.vmtype === 'qemu') {
- me.lookup('proxmoxHelpButton').setHelpConfig({
- onlineHelp: 'qm_migration'
- });
- title = gettext('Migrate') + (' VM ') + me.vmid;
- me.liveMode = 'online';
- }
-
- var running = false;
- var vmrec = PVE.data.ResourceStore.findRecord('vmid', me.vmid,
- 0, false, false, true);
- if (vmrec && vmrec.data && vmrec.data.running) {
- running = true;
- }
-
- if (running) {
- var displayField = me.lookup('migrationMode');
- if (me.vmtype === 'qemu') {
- displayField.setValue(gettext('Online'));
- me.liveMode = 'online';
- } else {
- displayField.setValue(gettext('Restart Mode'));
- me.liveMode = 'restart';
- }
- }
-
- me.setTitle(title);
- me.lookup('pveNodeSelector').disallowedNodes = [me.nodename];
- me.lookup('formPanel').isValid();
- }
-});Ext.define('PVE.window.BulkAction', {
- extend: 'Ext.window.Window',
-
- resizable: true,
- width: 800,
- modal: true,
- layout: {
- type: 'fit'
- },
- border: false,
-
- // the action to be set
- // currently there are
- // startall
- // migrateall
- // stopall
- action: undefined,
-
- submit: function(params) {
- var me = this;
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/' + me.action,
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- me.hide();
- win.on('destroy', function() {
- me.close();
- });
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.action) {
- throw "no action specified";
- }
-
- if (!me.btnText) {
- throw "no button text specified";
- }
-
- if (!me.title) {
- throw "no title specified";
- }
-
- var items = [];
-
- if (me.action === 'migrateall') {
- /*jslint confusion: true*/
- /*value is string and number*/
- items.push(
- {
- xtype: 'pveNodeSelector',
- name: 'target',
- disallowedNodes: [me.nodename],
- fieldLabel: gettext('Target node'),
- allowBlank: false,
- onlineValidator: true
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'maxworkers',
- minValue: 1,
- maxValue: 100,
- value: 1,
- fieldLabel: gettext('Parallel jobs'),
- allowBlank: false
- },
- {
- itemId: 'lxcwarning',
- xtype: 'displayfield',
- userCls: 'pve-hint',
- value: 'Warning: Running CTs will be migrated in Restart Mode.',
- hidden: true // only visible if running container chosen
- }
- );
- /*jslint confusion: false*/
- } else if (me.action === 'startall') {
- items.push({
- xtype: 'hiddenfield',
- name: 'force',
- value: 1
- });
- }
-
- items.push({
- xtype: 'vmselector',
- itemId: 'vms',
- name: 'vms',
- flex: 1,
- height: 300,
- selectAll: true,
- allowBlank: false,
- nodename: me.nodename,
- action: me.action,
- listeners: {
- selectionchange: function(vmselector, records) {
- if (me.action == 'migrateall') {
- var showWarning = records.some(function(item) {
- return (item.data.type == 'lxc' &&
- item.data.status == 'running');
- });
- me.down('#lxcwarning').setVisible(showWarning);
- }
- }
- }
- });
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- fieldDefaults: {
- labelWidth: 300,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn = Ext.create('Ext.Button', {
- text: me.btnText,
- handler: function() {
- form.isValid();
- me.submit(form.getValues());
- }
- });
-
- Ext.apply(me, {
- items: [ me.formPanel ],
- buttons: [ submitBtn ]
- });
-
- me.callParent();
-
- form.on('validitychange', function() {
- var valid = form.isValid();
- submitBtn.setDisabled(!valid);
- });
- form.isValid();
- }
-});
-Ext.define('PVE.window.Clone', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- isTemplate: false,
-
- onlineHelp: 'qm_copy_and_clone',
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'panel[reference=cloneform]': {
- validitychange: 'disableSubmit'
- }
- },
- disableSubmit: function(form) {
- this.lookupReference('submitBtn').setDisabled(!form.isValid());
- }
- },
-
- statics: {
- // display a snapshot selector only if needed
- wrap: function(nodename, vmid, isTemplate, guestType) {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/' + guestType + '/' + vmid +'/snapshot',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, opts) {
- var snapshotList = response.result.data;
- var hasSnapshots = snapshotList.length === 1 &&
- snapshotList[0].name === 'current' ? false : true;
-
- Ext.create('PVE.window.Clone', {
- nodename: nodename,
- guestType: guestType,
- vmid: vmid,
- isTemplate: isTemplate,
- hasSnapshots: hasSnapshots
- }).show();
- }
- });
- }
- },
-
- create_clone: function(values) {
- var me = this;
-
- var params = { newid: values.newvmid };
-
- if (values.snapname && values.snapname !== 'current') {
- params.snapname = values.snapname;
- }
-
- if (values.pool) {
- params.pool = values.pool;
- }
-
- if (values.name) {
- if (me.guestType === 'lxc') {
- params.hostname = values.name;
- } else {
- params.name = values.name;
- }
- }
-
- if (values.target) {
- params.target = values.target;
- }
-
- if (values.clonemode === 'copy') {
- params.full = 1;
- if (values.hdstorage) {
- params.storage = values.hdstorage;
- if (values.diskformat && me.guestType !== 'lxc') {
- params.format = values.diskformat;
- }
- }
- }
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/' + me.guestType + '/' + me.vmid + '/clone',
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- me.close();
- }
- });
-
- },
-
- // disable the Storage selector when clone mode is linked clone
- updateVisibility: function() {
- var me = this;
- var clonemode = me.lookupReference('clonemodesel').getValue();
- var disksel = me.lookup('diskselector');
- disksel.setDisabled(clonemode === 'clone');
- },
-
- // add to the list of valid nodes each node where
- // all the VM disks are available
- verifyFeature: function() {
- var me = this;
-
- var snapname = me.lookupReference('snapshotsel').getValue();
- var clonemode = me.lookupReference('clonemodesel').getValue();
-
- var params = { feature: clonemode };
- if (snapname !== 'current') {
- params.snapname = snapname;
- }
-
- Proxmox.Utils.API2Request({
- waitMsgTarget: me,
- url: '/nodes/' + me.nodename + '/' + me.guestType + '/' + me.vmid + '/feature',
- params: params,
- method: 'GET',
- failure: function(response, opts) {
- me.lookupReference('submitBtn').setDisabled(true);
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- var res = response.result.data;
-
- me.lookupReference('targetsel').allowedNodes = res.nodes;
- me.lookupReference('targetsel').validate();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.snapname) {
- me.snapname = 'current';
- }
-
- if (!me.guestType) {
- throw "no Guest Type specified";
- }
-
- var titletext = me.guestType === 'lxc' ? 'CT' : 'VM';
- if (me.isTemplate) {
- titletext += ' Template';
- }
- me.title = "Clone " + titletext + " " + me.vmid;
-
- var col1 = [];
- var col2 = [];
-
- col1.push({
- xtype: 'pveNodeSelector',
- name: 'target',
- reference: 'targetsel',
- fieldLabel: gettext('Target node'),
- selectCurNode: true,
- allowBlank: false,
- onlineValidator: true,
- listeners: {
- change: function(f, value) {
- me.lookupReference('hdstorage').setTargetNode(value);
- }
- }
- });
-
- var modelist = [['copy', gettext('Full Clone')]];
- if (me.isTemplate) {
- modelist.push(['clone', gettext('Linked Clone')]);
- }
-
- col1.push({
- xtype: 'pveGuestIDSelector',
- name: 'newvmid',
- guestType: me.guestType,
- value: '',
- loadNextFreeID: true,
- validateExists: false
- },
- {
- xtype: 'textfield',
- name: 'name',
- allowBlank: true,
- fieldLabel: me.guestType === 'lxc' ? gettext('Hostname') : gettext('Name')
- },
- {
- xtype: 'pvePoolSelector',
- fieldLabel: gettext('Resource Pool'),
- name: 'pool',
- value: '',
- allowBlank: true
- }
- );
-
- col2.push({
- xtype: 'proxmoxKVComboBox',
- fieldLabel: gettext('Mode'),
- name: 'clonemode',
- reference: 'clonemodesel',
- allowBlank: false,
- hidden: !me.isTemplate,
- value: me.isTemplate ? 'clone' : 'copy',
- comboItems: modelist,
- listeners: {
- change: function(t, value) {
- me.updateVisibility();
- me.verifyFeature();
- }
- }
- },
- {
- xtype: 'PVE.form.SnapshotSelector',
- name: 'snapname',
- reference: 'snapshotsel',
- fieldLabel: gettext('Snapshot'),
- nodename: me.nodename,
- guestType: me.guestType,
- vmid: me.vmid,
- hidden: me.isTemplate || !me.hasSnapshots ? true : false,
- disabled: false,
- allowBlank: false,
- value : me.snapname,
- listeners: {
- change: function(f, value) {
- me.verifyFeature();
- }
- }
- },
- {
- xtype: 'pveDiskStorageSelector',
- reference: 'diskselector',
- nodename: me.nodename,
- autoSelect: false,
- hideSize: true,
- hideSelection: true,
- storageLabel: gettext('Target Storage'),
- allowBlank: true,
- storageContent: me.guestType === 'qemu' ? 'images' : 'rootdir',
- emptyText: gettext('Same as source'),
- disabled: me.isTemplate ? true : false // because default mode is clone for templates
- });
-
- var formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- reference: 'cloneform',
- border: false,
- layout: 'column',
- defaultType: 'container',
- columns: 2,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [
- {
- columnWidth: 0.5,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: col1
- },
- {
- columnWidth: 0.5,
- padding: '0 0 0 10',
- layout: 'anchor',
- items: col2
- }
- ]
- });
-
- Ext.apply(me, {
- modal: true,
- width: 600,
- height: 250,
- border: false,
- layout: 'fit',
- buttons: [ {
- xtype: 'proxmoxHelpButton',
- listenToGlobalEvent: false,
- hidden: false,
- onlineHelp: me.onlineHelp
- },
- '->',
- {
- reference: 'submitBtn',
- text: gettext('Clone'),
- disabled: true,
- handler: function() {
- var cloneForm = me.lookupReference('cloneform');
- if (cloneForm.isValid()) {
- me.create_clone(cloneForm.getValues());
- }
- }
- } ],
- items: [ formPanel ]
- });
-
- me.callParent();
-
- me.verifyFeature();
- }
-});
-Ext.define('PVE.qemu.Monitor', {
- extend: 'Ext.panel.Panel',
-
- alias: 'widget.pveQemuMonitor',
-
- maxLines: 500,
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var history = [];
- var histNum = -1;
- var lines = [];
-
- var textbox = Ext.createWidget('panel', {
- region: 'center',
- xtype: 'panel',
- autoScroll: true,
- border: true,
- margins: '5 5 5 5',
- bodyStyle: 'font-family: monospace;'
- });
-
- var scrollToEnd = function() {
- var el = textbox.getTargetEl();
- var dom = Ext.getDom(el);
-
- var clientHeight = dom.clientHeight;
- // BrowserBug: clientHeight reports 0 in IE9 StrictMode
- // Instead we are using offsetHeight and hardcoding borders
- if (Ext.isIE9 && Ext.isStrict) {
- clientHeight = dom.offsetHeight + 2;
- }
- dom.scrollTop = dom.scrollHeight - clientHeight;
- };
-
- var refresh = function() {
- textbox.update('' + lines.join('\n') + ' ');
- scrollToEnd();
- };
-
- var addLine = function(line) {
- lines.push(line);
- if (lines.length > me.maxLines) {
- lines.shift();
- }
- };
-
- var executeCmd = function(cmd) {
- addLine("# " + Ext.htmlEncode(cmd));
- if (cmd) {
- history.unshift(cmd);
- if (history.length > 20) {
- history.splice(20);
- }
- }
- histNum = -1;
-
- refresh();
- Proxmox.Utils.API2Request({
- params: { command: cmd },
- url: '/nodes/' + nodename + '/qemu/' + vmid + "/monitor",
- method: 'POST',
- waitMsgTarget: me,
- success: function(response, opts) {
- var res = response.result.data;
- Ext.Array.each(res.split('\n'), function(line) {
- addLine(Ext.htmlEncode(line));
- });
- refresh();
- },
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- Ext.apply(me, {
- layout: { type: 'border' },
- border: false,
- items: [
- textbox,
- {
- region: 'south',
- margins:'0 5 5 5',
- border: false,
- xtype: 'textfield',
- name: 'cmd',
- value: '',
- fieldStyle: 'font-family: monospace;',
- allowBlank: true,
- listeners: {
- afterrender: function(f) {
- f.focus(false);
- addLine("Type 'help' for help.");
- refresh();
- },
- specialkey: function(f, e) {
- var key = e.getKey();
- switch (key) {
- case e.ENTER:
- var cmd = f.getValue();
- f.setValue('');
- executeCmd(cmd);
- break;
- case e.PAGE_UP:
- textbox.scrollBy(0, -0.9*textbox.getHeight(), false);
- break;
- case e.PAGE_DOWN:
- textbox.scrollBy(0, 0.9*textbox.getHeight(), false);
- break;
- case e.UP:
- if (histNum + 1 < history.length) {
- f.setValue(history[++histNum]);
- }
- e.preventDefault();
- break;
- case e.DOWN:
- if (histNum > 0) {
- f.setValue(history[--histNum]);
- }
- e.preventDefault();
- break;
- default:
- break;
- }
- }
- }
- }
- ],
- listeners: {
- show: function() {
- var field = me.query('textfield[name="cmd"]')[0];
- field.focus(false, true);
- }
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.qemu.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveQemuSummary',
-
- scrollable: true,
- bodyPadding: 5,
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.workspace) {
- throw "no workspace specified";
- }
-
- if (!me.statusStore) {
- throw "no status storage specified";
- }
-
- var template = !!me.pveSelNode.data.template;
- var rstore = me.statusStore;
-
- var width = template ? 1 : 0.5;
- var items = [
- {
- xtype: template ? 'pveTemplateStatusView' : 'pveGuestStatusView',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: width
- },
- 'width >= 1900': {
- columnWidth: width / 2
- }
- },
- itemId: 'gueststatus',
- pveSelNode: me.pveSelNode,
- rstore: rstore
- },
- {
- xtype: 'pveNotesView',
- maxHeight: 330,
- itemId: 'notesview',
- pveSelNode: me.pveSelNode,
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: width
- },
- 'width >= 1900': {
- columnWidth: width / 2
- }
- }
- }
- ];
-
- var rrdstore;
- if (!template) {
-
- rrdstore = Ext.create('Proxmox.data.RRDStore', {
- rrdurl: "/api2/json/nodes/" + nodename + "/qemu/" + vmid + "/rrddata",
- model: 'pve-rrd-guest'
- });
-
- items.push(
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('CPU usage'),
- pveSelNode: me.pveSelNode,
- fields: ['cpu'],
- fieldTitles: [gettext('CPU usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Memory usage'),
- pveSelNode: me.pveSelNode,
- fields: ['maxmem', 'mem'],
- fieldTitles: [gettext('Total'), gettext('RAM usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Network traffic'),
- pveSelNode: me.pveSelNode,
- fields: ['netin','netout'],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Disk IO'),
- pveSelNode: me.pveSelNode,
- fields: ['diskread','diskwrite'],
- store: rrdstore
- }
- );
-
- }
-
- Ext.apply(me, {
- tbar: [ '->', { xtype: 'proxmoxRRDTypeSelector' } ],
- items: [
- {
- xtype: 'container',
- layout: {
- type: 'column'
- },
- defaults: {
- minHeight: 330,
- padding: 5,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- }
- },
- items: items
- }
- ]
- });
-
- me.callParent();
- if (!template) {
- rrdstore.startUpdate();
- me.on('destroy', rrdstore.stopUpdate);
- }
- }
-});
-Ext.define('PVE.qemu.OSTypeInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuOSTypePanel',
- onlineHelp: 'qm_os_settings',
- insideWizard: false,
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'combobox[name=osbase]': {
- change: 'onOSBaseChange'
- },
- 'combobox[name=ostype]': {
- afterrender: 'onOSTypeChange',
- change: 'onOSTypeChange'
- }
- },
- onOSBaseChange: function(field, value) {
- this.lookup('ostype').getStore().setData(PVE.Utils.kvm_ostypes[value]);
- },
- onOSTypeChange: function(field) {
- var me = this, ostype = field.getValue();
- if (!me.getView().insideWizard) {
- return;
- }
- var targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
-
- me.setWidget('pveBusSelector', targetValues.busType);
- me.setWidget('pveNetworkCardSelector', targetValues.networkCard);
- var scsihw = targetValues.scsihw || '__default__';
- this.getViewModel().set('current.scsihw', scsihw);
- },
- setWidget: function(widget, newValue) {
- // changing a widget is safe only if ComponentQuery.query returns us
- // a single value array
- var widgets = Ext.ComponentQuery.query('pveQemuCreateWizard ' + widget);
- if (widgets.length === 1) {
- widgets[0].setValue(newValue);
- } else {
- throw 'non unique widget :' + widget + ' in Wizard';
- }
- }
- },
-
- initComponent : function() {
- var me = this;
-
- /*jslint confusion: true */
- me.items = [
- {
- xtype: 'displayfield',
- value: gettext('Guest OS') + ':',
- hidden: !me.insideWizard
- },
- {
- xtype: 'combobox',
- submitValue: false,
- name: 'osbase',
- fieldLabel: gettext('Type'),
- editable: false,
- queryMode: 'local',
- value: 'Linux',
- store: Object.keys(PVE.Utils.kvm_ostypes)
- },
- {
- xtype: 'combobox',
- name: 'ostype',
- reference: 'ostype',
- fieldLabel: gettext('Version'),
- value: 'l26',
- allowBlank : false,
- editable: false,
- queryMode: 'local',
- valueField: 'val',
- displayField: 'desc',
- store: {
- fields: ['desc', 'val'],
- data: PVE.Utils.kvm_ostypes.Linux,
- listeners: {
- datachanged: function (store) {
- var ostype = me.lookup('ostype');
- var old_val = ostype.getValue();
- if (!me.insideWizard && old_val && store.find('val', old_val) != -1) {
- ostype.setValue(old_val);
- } else {
- ostype.setValue(store.getAt(0));
- }
- }
- }
- }
- }
- ];
- /*jslint confusion: false */
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.OSTypeEdit', {
- extend: 'Proxmox.window.Edit',
-
- subject: 'OS Type',
-
- items: [{ xtype: 'pveQemuOSTypePanel' }],
-
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var value = response.result.data.ostype || 'other';
- var osinfo = PVE.Utils.get_kvm_osinfo(value);
- me.setValues({ ostype: value, osbase: osinfo.base });
- }
- });
- }
-});
-/*
- * This class holds performance *recommended* settings for the PVE Qemu wizards
- * the *mandatory* settings are set in the PVE::QemuServer
- * config_to_command sub
- * We store this here until we get the data from the API server
-*/
-
-// this is how you would add an hypothetic FreeBSD > 10 entry
-//
-//virtio-blk is stable but virtIO net still
-// problematic as of 10.3
-// see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=165059
-// addOS({
-// parent: 'generic', // inherits defaults
-// pveOS: 'freebsd10', // must match a radiofield in OSTypeEdit.js
-// busType: 'virtio' // must match a pveBusController value
-// // networkCard muss match a pveNetworkCardSelector
-
-
-Ext.define('PVE.qemu.OSDefaults', {
- singleton: true, // will also force creation when loaded
-
- constructor: function() {
- var me = this;
-
- var addOS = function(settings) {
- if (me.hasOwnProperty(settings.parent)) {
- var child = Ext.clone(me[settings.parent]);
- me[settings.pveOS] = Ext.apply(child, settings);
-
- } else {
- throw("Could not find your genitor");
- }
- };
-
- // default values
- me.generic = {
- busType: 'ide',
- networkCard: 'e1000',
- busPriority: {
- ide: 4,
- sata: 3,
- scsi: 2,
- virtio: 1
- },
- scsihw: 'virtio-scsi-pci'
- };
-
- // virtio-net is in kernel since 2.6.25
- // virtio-scsi since 3.2 but backported in RHEL with 2.6 kernel
- addOS({
- pveOS: 'l26',
- parent : 'generic',
- busType: 'scsi',
- busPriority: {
- scsi: 4,
- virtio: 3,
- sata: 2,
- ide: 1
- },
- networkCard: 'virtio'
- });
-
- // recommandation from http://wiki.qemu.org/Windows2000
- addOS({
- pveOS: 'w2k',
- parent : 'generic',
- networkCard: 'rtl8139',
- scsihw: ''
- });
- // https://pve.proxmox.com/wiki/Windows_XP_Guest_Notes
- addOS({
- pveOS: 'wxp',
- parent : 'w2k'
- });
-
- me.getDefaults = function(ostype) {
- if (PVE.qemu.OSDefaults[ostype]) {
- return PVE.qemu.OSDefaults[ostype];
- } else {
- return PVE.qemu.OSDefaults.generic;
- }
- };
- }
-});
-Ext.define('PVE.qemu.ProcessorInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuProcessorPanel',
- onlineHelp: 'qm_cpu',
-
- insideWizard: false,
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- updateCores: function() {
- var me = this.getView();
- var sockets = me.down('field[name=sockets]').getValue();
- var cores = me.down('field[name=cores]').getValue();
- me.down('field[name=totalcores]').setValue(sockets*cores);
- var vcpus = me.down('field[name=vcpus]');
- vcpus.setMaxValue(sockets*cores);
- vcpus.setEmptyText(sockets*cores);
- vcpus.validate();
- },
-
- control: {
- 'field[name=sockets]': {
- change: 'updateCores'
- },
- 'field[name=cores]': {
- change: 'updateCores'
- }
- }
- },
-
- onGetValues: function(values) {
- var me = this;
-
- if (Array.isArray(values['delete'])) {
- values['delete'] = values['delete'].join(',');
- }
-
- PVE.Utils.delete_if_default(values, 'cpulimit', '0', 0);
- PVE.Utils.delete_if_default(values, 'cpuunits', '1024', 0);
-
- // build the cpu options:
- me.cpu.cputype = values.cputype;
-
- var flags = [];
-
- ['pcid', 'spec-ctrl'].forEach(function(flag) {
- if (values[flag]) {
- flags.push('+' + flag.toString());
- }
- delete values[flag];
- });
-
- me.cpu.flags = flags.length ? flags.join(';') : undefined;
-
- delete values.cputype;
- delete values.flags;
- var cpustring = PVE.Parser.printQemuCpu(me.cpu);
-
- // remove cputype delete request:
- var del = values['delete'];
- delete values['delete'];
- if (del) {
- del = del.split(',');
- Ext.Array.remove(del, 'cputype');
- } else {
- del = [];
- }
-
- if (cpustring) {
- values.cpu = cpustring;
- } else {
- del.push('cpu');
- }
-
- var delarr = del.join(',');
- if (delarr) {
- values['delete'] = delarr;
- }
-
- return values;
- },
-
- cpu: {},
-
- column1: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'sockets',
- minValue: 1,
- maxValue: 4,
- value: '1',
- fieldLabel: gettext('Sockets'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'cores',
- minValue: 1,
- maxValue: 128,
- value: '1',
- fieldLabel: gettext('Cores'),
- allowBlank: false
- }
- ],
-
- column2: [
- {
- xtype: 'CPUModelSelector',
- name: 'cputype',
- value: '__default__',
- fieldLabel: gettext('Type')
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Total cores'),
- name: 'totalcores',
- value: '1'
- }
- ],
-
- advancedColumn1: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'vcpus',
- minValue: 1,
- maxValue: 1,
- value: '',
- fieldLabel: gettext('VCPUs'),
- deleteEmpty: true,
- allowBlank: true,
- emptyText: '1'
- },
- {
- xtype: 'numberfield',
- name: 'cpulimit',
- minValue: 0,
- maxValue: 128, // api maximum
- value: '',
- step: 1,
- fieldLabel: gettext('CPU limit'),
- allowBlank: true,
- emptyText: gettext('unlimited')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'cpuunits',
- fieldLabel: gettext('CPU units'),
- minValue: 8,
- maxValue: 500000,
- value: '1024',
- deleteEmpty: true,
- allowBlank: true
- }
- ],
-
- advancedColumn2: [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Enable NUMA'),
- name: 'numa',
- uncheckedValue: 0
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: 'PCID',
- name: 'pcid',
- uncheckedValue: 0
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: 'SPEC-CTRL',
- name: 'spec-ctrl',
- uncheckedValue: 0
- }
- ]
-});
-
-Ext.define('PVE.qemu.ProcessorEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- var ipanel = Ext.create('PVE.qemu.ProcessorInputPanel');
-
- Ext.apply(me, {
- subject: gettext('Processors'),
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var data = response.result.data;
- var value = data.cpu;
- if (value) {
- var cpu = PVE.Parser.parseQemuCpu(value);
- ipanel.cpu = cpu;
- data.cputype = cpu.cputype;
- if (cpu.flags) {
- var flags = cpu.flags.split(';');
- flags.forEach(function(flag) {
- var sign = flag.substr(0,1);
- flag = flag.substr(1);
- data[flag] = (sign === '+');
- });
- }
- }
- me.setValues(data);
- }
- });
- }
-});
-Ext.define('PVE.qemu.BootOrderPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuBootOrderPanel',
- vmconfig: {}, // store loaded vm config
-
- bootdisk: undefined,
- selection: [],
- list: [],
- comboboxes: [],
-
- isBootDisk: function(value) {
- return PVE.Utils.bus_match.test(value);
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
- me.vmconfig = vmconfig;
- var order = me.vmconfig.boot || 'cdn';
- me.bootdisk = me.vmconfig.bootdisk || undefined;
-
- // get the first 3 characters
- // ignore the rest (there should never be more than 3)
- me.selection = order.split('').slice(0,3);
-
- // build bootdev list
- me.list = [];
- Ext.Object.each(me.vmconfig, function(key, value) {
- if (me.isBootDisk(key) &&
- !(/media=cdrom/).test(value)) {
- me.list.push([key, "Disk '" + key + "'"]);
- }
- });
-
- me.list.push(['d', 'CD-ROM']);
- me.list.push(['n', gettext('Network')]);
- me.list.push(['__none__', Proxmox.Utils.noneText]);
-
- me.recomputeList();
-
- me.comboboxes.forEach(function(box) {
- box.resetOriginalValue();
- });
- },
-
- onGetValues: function(values) {
- var me = this;
- var order = me.selection.join('');
- var res = { boot: order };
-
- if (me.bootdisk && order.indexOf('c') !== -1) {
- res.bootdisk = me.bootdisk;
- } else {
- res['delete'] = 'bootdisk';
- }
-
- return res;
- },
-
- recomputeSelection: function(combobox, newVal, oldVal) {
- var me = this.up('#inputpanel');
- me.selection = [];
- me.comboboxes.forEach(function(item) {
- var val = item.getValue();
-
- // when selecting an already selected item,
- // switch it around
- if ((val === newVal || (me.isBootDisk(val) && me.isBootDisk(newVal))) &&
- item.name !== combobox.name &&
- newVal !== '__none__') {
- // swap items
- val = oldVal;
- }
-
- // push 'c','d' or 'n' in the array
- if (me.isBootDisk(val)) {
- me.selection.push('c');
- me.bootdisk = val;
- } else if (val === 'd' ||
- val === 'n') {
- me.selection.push(val);
- }
- });
-
- me.recomputeList();
- },
-
- recomputeList: function(){
- var me = this;
- // set the correct values in the kvcomboboxes
- var cnt = 0;
- me.comboboxes.forEach(function(item) {
- if (cnt === 0) {
- // never show 'none' on first combobox
- item.store.loadData(me.list.slice(0, me.list.length-1));
- } else {
- item.store.loadData(me.list);
- }
- item.suspendEvent('change');
- if (cnt < me.selection.length) {
- item.setValue((me.selection[cnt] !== 'c')?me.selection[cnt]:me.bootdisk);
- } else if (cnt === 0){
- item.setValue('');
- } else {
- item.setValue('__none__');
- }
- cnt++;
- item.resumeEvent('change');
- item.validate();
- });
- },
-
- initComponent : function() {
- var me = this;
-
- // this has to be done here, because of
- // the way our inputPanel class handles items
- me.comboboxes = [
- Ext.createWidget('proxmoxKVComboBox', {
- fieldLabel: gettext('Boot device') + " 1",
- labelWidth: 120,
- name: 'bd1',
- allowBlank: false,
- listeners: {
- change: me.recomputeSelection
- }
- }),
- Ext.createWidget('proxmoxKVComboBox', {
- fieldLabel: gettext('Boot device') + " 2",
- labelWidth: 120,
- name: 'bd2',
- allowBlank: false,
- listeners: {
- change: me.recomputeSelection
- }
- }),
- Ext.createWidget('proxmoxKVComboBox', {
- fieldLabel: gettext('Boot device') + " 3",
- labelWidth: 120,
- name: 'bd3',
- allowBlank: false,
- listeners: {
- change: me.recomputeSelection
- }
- })
- ];
- Ext.apply(me, { items: me.comboboxes });
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.BootOrderEdit', {
- extend: 'Proxmox.window.Edit',
-
- items: [{
- xtype: 'pveQemuBootOrderPanel',
- itemId: 'inputpanel'
- }],
-
- subject: gettext('Boot Order'),
-
- initComponent : function() {
- var me = this;
- me.callParent();
- me.load({
- success: function(response, options) {
- me.down('#inputpanel').setVMConfig(response.result.data);
- }
- });
- }
-});
-Ext.define('PVE.qemu.MemoryInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuMemoryPanel',
- onlineHelp: 'qm_memory',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- var res = {};
-
- res.memory = values.memory;
- res.balloon = values.balloon;
-
- if (!values.ballooning) {
- res.balloon = 0;
- res['delete'] = 'shares';
- } else if (values.memory === values.balloon) {
- delete res.balloon;
- res['delete'] = 'balloon,shares';
- } else if (Ext.isDefined(values.shares) && (values.shares !== "")) {
- res.shares = values.shares;
- } else {
- res['delete'] = "shares";
- }
-
- return res;
- },
-
- initComponent: function() {
- var me = this;
- var labelWidth = 160;
-
- me.items= [
- {
- xtype: 'pveMemoryField',
- labelWidth: labelWidth,
- fieldLabel: gettext('Memory') + ' (MiB)',
- name: 'memory',
- minValue: 1,
- step: 32,
- hotplug: me.hotplug,
- listeners: {
- change: function(f, value, old) {
- var bf = me.down('field[name=balloon]');
- var balloon = bf.getValue();
- bf.setMaxValue(value);
- if (balloon === old) {
- bf.setValue(value);
- }
- bf.validate();
- }
- }
- }
- ];
-
- me.advancedItems= [
- {
- xtype: 'pveMemoryField',
- name: 'balloon',
- minValue: 1,
- step: 32,
- fieldLabel: gettext('Minimum memory') + ' (MiB)',
- hotplug: me.hotplug,
- labelWidth: labelWidth,
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- var memory = me.down('field[name=memory]').getValue();
- var shares = me.down('field[name=shares]');
- shares.setDisabled(value === memory);
- }
- }
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'shares',
- disabled: true,
- minValue: 0,
- maxValue: 50000,
- value: '',
- step: 10,
- fieldLabel: gettext('Shares'),
- labelWidth: labelWidth,
- allowBlank: true,
- emptyText: Proxmox.Utils.defaultText + ' (1000)',
- submitEmptyText: false
- },
- {
- xtype: 'proxmoxcheckbox',
- labelWidth: labelWidth,
- value: '1',
- name: 'ballooning',
- fieldLabel: gettext('Ballooning Device'),
- listeners: {
- change: function(f, value) {
- var bf = me.down('field[name=balloon]');
- var shares = me.down('field[name=shares]');
- var memory = me.down('field[name=memory]');
- bf.setDisabled(!value);
- shares.setDisabled(!value || (bf.getValue() === memory.getValue()));
- }
- }
- }
- ];
-
- if (me.insideWizard) {
- me.column1 = me.items;
- me.items = undefined;
- me.advancedColumn1 = me.advancedItems;
- me.advancedItems = undefined;
- }
- me.callParent();
- }
-
-});
-
-Ext.define('PVE.qemu.MemoryEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent: function() {
- var me = this;
-
- var memoryhotplug;
- if(me.hotplug) {
- Ext.each(me.hotplug.split(','), function(el) {
- if (el === 'memory') {
- memoryhotplug = 1;
- }
- });
- }
-
- var ipanel = Ext.create('PVE.qemu.MemoryInputPanel', {
- hotplug: memoryhotplug
- });
-
- Ext.apply(me, {
- subject: gettext('Memory'),
- items: [ ipanel ],
- // uncomment the following to use the async configiguration API
- // backgroundDelay: 5,
- width: 400
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var data = response.result.data;
-
- var values = {
- ballooning: data.balloon === 0 ? '0' : '1',
- shares: data.shares,
- memory: data.memory || '512',
- balloon: data.balloon > 0 ? data.balloon : (data.memory || '512')
- };
-
- ipanel.setValues(values);
- }
- });
- }
-});
-Ext.define('PVE.qemu.NetworkInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuNetworkInputPanel',
- onlineHelp: 'qm_network_device',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- me.network.model = values.model;
- if (values.nonetwork) {
- return {};
- } else {
- me.network.bridge = values.bridge;
- me.network.tag = values.tag;
- me.network.firewall = values.firewall;
- }
- me.network.macaddr = values.macaddr;
- me.network.disconnect = values.disconnect;
- me.network.queues = values.queues;
-
- if (values.rate) {
- me.network.rate = values.rate;
- } else {
- delete me.network.rate;
- }
-
- var params = {};
-
- params[me.confid] = PVE.Parser.printQemuNetwork(me.network);
-
- return params;
- },
-
- setNetwork: function(confid, data) {
- var me = this;
-
- me.confid = confid;
-
- if (data) {
- data.networkmode = data.bridge ? 'bridge' : 'nat';
- } else {
- data = {};
- data.networkmode = 'bridge';
- }
- me.network = data;
-
- me.setValues(me.network);
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- me.bridgesel.setNodename(nodename);
- },
-
- initComponent : function() {
- var me = this;
-
- me.network = {};
- me.confid = 'net0';
-
- me.column1 = [];
- me.column2 = [];
-
- me.bridgesel = Ext.create('PVE.form.BridgeSelector', {
- name: 'bridge',
- fieldLabel: gettext('Bridge'),
- nodename: me.nodename,
- autoSelect: true,
- allowBlank: false
- });
-
- me.column1 = [
- me.bridgesel,
- {
- xtype: 'pveVlanField',
- name: 'tag',
- value: ''
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Firewall'),
- name: 'firewall',
- checked: (me.insideWizard || me.isCreate)
- }
- ];
-
- me.advancedColumn1 = [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Disconnect'),
- name: 'disconnect'
- }
- ];
-
- if (me.insideWizard) {
- me.column1.unshift({
- xtype: 'checkbox',
- name: 'nonetwork',
- inputValue: 'none',
- boxLabel: gettext('No network device'),
- listeners: {
- change: function(cb, value) {
- var fields = [
- 'disconnect',
- 'bridge',
- 'tag',
- 'firewall',
- 'model',
- 'macaddr',
- 'rate',
- 'queues'
- ];
- fields.forEach(function(fieldname) {
- me.down('field[name='+fieldname+']').setDisabled(value);
- });
- me.down('field[name=bridge]').validate();
- }
- }
- });
- me.column2.unshift({
- xtype: 'displayfield'
- });
- }
-
- me.column2.push(
- {
- xtype: 'pveNetworkCardSelector',
- name: 'model',
- fieldLabel: gettext('Model'),
- value: PVE.qemu.OSDefaults.generic.networkCard,
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'macaddr',
- fieldLabel: gettext('MAC address'),
- vtype: 'MacAddress',
- allowBlank: true,
- emptyText: 'auto'
- });
- me.advancedColumn2 = [
- {
- xtype: 'numberfield',
- name: 'rate',
- fieldLabel: gettext('Rate limit') + ' (MB/s)',
- minValue: 0,
- maxValue: 10*1024,
- value: '',
- emptyText: 'unlimited',
- allowBlank: true
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'queues',
- fieldLabel: 'Multiqueue',
- minValue: 1,
- maxValue: 8,
- value: '',
- allowBlank: true
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.NetworkEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
-
- initComponent : function() {
- /*jslint confusion: true */
-
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = me.confid ? false : true;
-
- var ipanel = Ext.create('PVE.qemu.NetworkInputPanel', {
- confid: me.confid,
- nodename: nodename,
- isCreate: me.isCreate
- });
-
- Ext.applyIf(me, {
- subject: gettext('Network Device'),
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var i, confid;
- me.vmconfig = response.result.data;
- if (!me.isCreate) {
- var value = me.vmconfig[me.confid];
- var network = PVE.Parser.parseQemuNetwork(me.confid, value);
- if (!network) {
- Ext.Msg.alert(gettext('Error'), 'Unable to parse network options');
- me.close();
- return;
- }
- ipanel.setNetwork(me.confid, network);
- } else {
- for (i = 0; i < 100; i++) {
- confid = 'net' + i.toString();
- if (!Ext.isDefined(me.vmconfig[confid])) {
- me.confid = confid;
- break;
- }
- }
- ipanel.setNetwork(me.confid);
- }
- }
- });
- }
-});
-Ext.define('PVE.qemu.Smbios1InputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.PVE.qemu.Smbios1InputPanel',
-
- insideWizard: false,
-
- smbios1: {},
-
- onGetValues: function(values) {
- var me = this;
-
- var params = {
- smbios1: PVE.Parser.printQemuSmbios1(values)
- };
-
- return params;
- },
-
- setSmbios1: function(data) {
- var me = this;
-
- me.smbios1 = data;
-
- me.setValues(me.smbios1);
- },
-
- initComponent : function() {
- var me = this;
-
-
- me.items = [
- {
- xtype: 'textfield',
- fieldLabel: 'UUID',
- regex: /^[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$/,
- name: 'uuid'
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Manufacturer'),
- regex: /^\S+$/,
- name: 'manufacturer'
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Product'),
- regex: /^\S+$/,
- name: 'product'
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Version'),
- regex: /^\S+$/,
- name: 'version'
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Serial'),
- regex: /^\S+$/,
- name: 'serial'
- },
- {
- xtype: 'textfield',
- fieldLabel: 'SKU',
- regex: /^\S+$/,
- name: 'sku'
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Family'),
- regex: /^\S+$/,
- name: 'family'
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.Smbios1Edit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- /*jslint confusion: true */
-
- var me = this;
-
- var ipanel = Ext.create('PVE.qemu.Smbios1InputPanel', {});
-
- Ext.applyIf(me, {
- subject: gettext('SMBIOS settings (type1)'),
- width: 450,
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var i, confid;
- me.vmconfig = response.result.data;
- var value = me.vmconfig.smbios1;
- if (value) {
- var data = PVE.Parser.parseQemuSmbios1(value);
- if (!data) {
- Ext.Msg.alert(gettext('Error'), 'Unable to parse smbios options');
- me.close();
- return;
- }
- ipanel.setSmbios1(data);
- }
- }
- });
- }
-});
-Ext.define('PVE.qemu.CDInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuCDInputPanel',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- var confid = me.confid || (values.controller + values.deviceid);
-
- me.drive.media = 'cdrom';
- if (values.mediaType === 'iso') {
- me.drive.file = values.cdimage;
- } else if (values.mediaType === 'cdrom') {
- me.drive.file = 'cdrom';
- } else {
- me.drive.file = 'none';
- }
-
- var params = {};
-
- params[confid] = PVE.Parser.printQemuDrive(me.drive);
-
- return params;
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
-
- if (me.bussel) {
- me.bussel.setVMConfig(vmconfig, 'cdrom');
- }
- },
-
- setDrive: function(drive) {
- var me = this;
-
- var values = {};
- if (drive.file === 'cdrom') {
- values.mediaType = 'cdrom';
- } else if (drive.file === 'none') {
- values.mediaType = 'none';
- } else {
- values.mediaType = 'iso';
- var match = drive.file.match(/^([^:]+):/);
- if (match) {
- values.cdstorage = match[1];
- values.cdimage = drive.file;
- }
- }
-
- me.drive = drive;
-
- me.setValues(values);
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- me.cdstoragesel.setNodename(nodename);
- me.cdfilesel.setStorage(undefined, nodename);
- },
-
- initComponent : function() {
- var me = this;
-
- me.drive = {};
-
- var items = [];
-
- if (!me.confid) {
- me.bussel = Ext.create('PVE.form.ControllerSelector', {
- noVirtIO: true
- });
- items.push(me.bussel);
- }
-
- items.push({
- xtype: 'radiofield',
- name: 'mediaType',
- inputValue: 'iso',
- boxLabel: gettext('Use CD/DVD disc image file (iso)'),
- checked: true,
- listeners: {
- change: function(f, value) {
- if (!me.rendered) {
- return;
- }
- me.down('field[name=cdstorage]').setDisabled(!value);
- me.down('field[name=cdimage]').setDisabled(!value);
- me.down('field[name=cdimage]').validate();
- }
- }
- });
-
- me.cdfilesel = Ext.create('PVE.form.FileSelector', {
- name: 'cdimage',
- nodename: me.nodename,
- storageContent: 'iso',
- fieldLabel: gettext('ISO image'),
- labelAlign: 'right',
- allowBlank: false
- });
-
- me.cdstoragesel = Ext.create('PVE.form.StorageSelector', {
- name: 'cdstorage',
- nodename: me.nodename,
- fieldLabel: gettext('Storage'),
- labelAlign: 'right',
- storageContent: 'iso',
- allowBlank: false,
- autoSelect: me.insideWizard,
- listeners: {
- change: function(f, value) {
- me.cdfilesel.setStorage(value);
- }
- }
- });
-
- items.push(me.cdstoragesel);
- items.push(me.cdfilesel);
-
- items.push({
- xtype: 'radiofield',
- name: 'mediaType',
- inputValue: 'cdrom',
- boxLabel: gettext('Use physical CD/DVD Drive')
- });
-
- items.push({
- xtype: 'radiofield',
- name: 'mediaType',
- inputValue: 'none',
- boxLabel: gettext('Do not use any media')
- });
-
- me.items = items;
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.CDEdit', {
- extend: 'Proxmox.window.Edit',
-
- width: 400,
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = me.confid ? false : true;
-
- var ipanel = Ext.create('PVE.qemu.CDInputPanel', {
- confid: me.confid,
- nodename: nodename
- });
-
- Ext.applyIf(me, {
- subject: 'CD/DVD Drive',
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- if (me.confid) {
- var value = response.result.data[me.confid];
- var drive = PVE.Parser.parseQemuDrive(me.confid, value);
- if (!drive) {
- Ext.Msg.alert('Error', 'Unable to parse drive options');
- me.close();
- return;
- }
- ipanel.setDrive(drive);
- }
- }
- });
- }
-});
-/*jslint confusion: true */
-/* 'change' property is assigned a string and then a function */
-Ext.define('PVE.qemu.HDInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuHDInputPanel',
- onlineHelp: 'qm_hard_disk',
-
- insideWizard: false,
-
- unused: false, // ADD usused disk imaged
-
- vmconfig: {}, // used to select usused disks
-
- controller: {
-
- xclass: 'Ext.app.ViewController',
-
- onControllerChange: function(field) {
- var value = field.getValue();
-
- var allowIOthread = value.match(/^(virtio|scsi)/);
- this.lookup('iothread').setDisabled(!allowIOthread);
- if (!allowIOthread) {
- this.lookup('iothread').setValue(false);
- }
-
- var virtio = value.match(/^virtio/);
- this.lookup('discard').setDisabled(virtio);
- this.lookup('ssd').setDisabled(virtio);
- if (virtio) {
- this.lookup('discard').setValue(false);
- this.lookup('ssd').setValue(false);
- }
-
- this.lookup('scsiController').setVisible(value.match(/^scsi/));
- },
-
- control: {
- 'field[name=controller]': {
- change: 'onControllerChange',
- afterrender: 'onControllerChange'
- },
- 'field[name=iothread]' : {
- change: function(f, value) {
- if (!this.getView().insideWizard) {
- return;
- }
- var vmScsiType = value ? 'virtio-scsi-single': 'virtio-scsi-pci';
- this.lookupReference('scsiController').setValue(vmScsiType);
- }
- }
- }
- },
-
- onGetValues: function(values) {
- var me = this;
-
- var params = {};
- var confid = me.confid || (values.controller + values.deviceid);
-
- if (me.unused) {
- me.drive.file = me.vmconfig[values.unusedId];
- confid = values.controller + values.deviceid;
- } else if (me.isCreate) {
- if (values.hdimage) {
- me.drive.file = values.hdimage;
- } else {
- me.drive.file = values.hdstorage + ":" + values.disksize;
- }
- me.drive.format = values.diskformat;
- }
-
- if (values.nobackup) {
- me.drive.backup = 'no';
- } else {
- delete me.drive.backup;
- }
-
- if (values.noreplicate) {
- me.drive.replicate = 'no';
- } else {
- delete me.drive.replicate;
- }
-
- if (values.discard) {
- me.drive.discard = 'on';
- } else {
- delete me.drive.discard;
- }
-
- if (values.ssd) {
- me.drive.ssd = 'on';
- } else {
- delete me.drive.ssd;
- }
-
- if (values.iothread) {
- me.drive.iothread = 'on';
- } else {
- delete me.drive.iothread;
- }
-
- if (values.cache) {
- me.drive.cache = values.cache;
- } else {
- delete me.drive.cache;
- }
-
- var names = ['mbps_rd', 'mbps_wr', 'iops_rd', 'iops_wr'];
- Ext.Array.each(names, function(name) {
- if (values[name]) {
- me.drive[name] = values[name];
- } else {
- delete me.drive[name];
- }
- var burst_name = name + '_max';
- if (values[burst_name] && values[name]) {
- me.drive[burst_name] = values[burst_name];
- } else {
- delete me.drive[burst_name];
- }
- });
-
-
- params[confid] = PVE.Parser.printQemuDrive(me.drive);
-
- return params;
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
-
- me.vmconfig = vmconfig;
-
- if (me.bussel) {
- me.bussel.setVMConfig(vmconfig);
- me.scsiController.setValue(vmconfig.scsihw);
- }
- if (me.unusedDisks) {
- var disklist = [];
- Ext.Object.each(vmconfig, function(key, value) {
- if (key.match(/^unused\d+$/)) {
- disklist.push([key, value]);
- }
- });
- me.unusedDisks.store.loadData(disklist);
- me.unusedDisks.setValue(me.confid);
- }
- },
-
- setDrive: function(drive) {
- var me = this;
-
- me.drive = drive;
-
- var values = {};
- var match = drive.file.match(/^([^:]+):/);
- if (match) {
- values.hdstorage = match[1];
- }
-
- values.hdimage = drive.file;
- values.nobackup = !PVE.Parser.parseBoolean(drive.backup, 1);
- values.noreplicate = !PVE.Parser.parseBoolean(drive.replicate, 1);
- values.diskformat = drive.format || 'raw';
- values.cache = drive.cache || '__default__';
- values.discard = (drive.discard === 'on');
- values.ssd = PVE.Parser.parseBoolean(drive.ssd);
- values.iothread = PVE.Parser.parseBoolean(drive.iothread);
-
- values.mbps_rd = drive.mbps_rd;
- values.mbps_wr = drive.mbps_wr;
- values.iops_rd = drive.iops_rd;
- values.iops_wr = drive.iops_wr;
- values.mbps_rd_max = drive.mbps_rd_max;
- values.mbps_wr_max = drive.mbps_wr_max;
- values.iops_rd_max = drive.iops_rd_max;
- values.iops_wr_max = drive.iops_wr_max;
-
- me.setValues(values);
- },
-
- setNodename: function(nodename) {
- var me = this;
- me.down('#hdstorage').setNodename(nodename);
- me.down('#hdimage').setStorage(undefined, nodename);
- },
-
- initComponent : function() {
- var me = this;
-
- var labelWidth = 140;
-
- me.drive = {};
-
- me.column1 = [];
- me.column2 = [];
-
- me.advancedColumn1 = [];
- me.advancedColumn2 = [];
-
- if (!me.confid || me.unused) {
- me.bussel = Ext.create('PVE.form.ControllerSelector', {
- vmconfig: me.insideWizard ? {ide2: 'cdrom'} : {}
- });
- me.column1.push(me.bussel);
-
- me.scsiController = Ext.create('Ext.form.field.Display', {
- fieldLabel: gettext('SCSI Controller'),
- reference: 'scsiController',
- bind: me.insideWizard ? {
- value: '{current.scsihw}'
- } : undefined,
- renderer: PVE.Utils.render_scsihw,
- submitValue: false,
- hidden: true
- });
- me.column1.push(me.scsiController);
- }
-
- if (me.unused) {
- me.unusedDisks = Ext.create('Proxmox.form.KVComboBox', {
- name: 'unusedId',
- fieldLabel: gettext('Disk image'),
- matchFieldWidth: false,
- listConfig: {
- width: 350
- },
- data: [],
- allowBlank: false
- });
- me.column1.push(me.unusedDisks);
- } else if (me.isCreate) {
- me.column1.push({
- xtype: 'pveDiskStorageSelector',
- storageContent: 'images',
- name: 'disk',
- nodename: me.nodename,
- autoSelect: me.insideWizard
- });
- } else {
- me.column1.push({
- xtype: 'textfield',
- disabled: true,
- submitValue: false,
- fieldLabel: gettext('Disk image'),
- name: 'hdimage'
- });
- }
-
- me.column2.push(
- {
- xtype: 'CacheTypeSelector',
- name: 'cache',
- value: '__default__',
- fieldLabel: gettext('Cache')
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Discard'),
- disabled: me.confid && me.confid.match(/^virtio/),
- reference: 'discard',
- name: 'discard'
- }
- );
-
- me.advancedColumn1.push(
- {
- xtype: 'proxmoxcheckbox',
- disabled: me.confid && me.confid.match(/^virtio/),
- fieldLabel: gettext('SSD emulation'),
- labelWidth: labelWidth,
- name: 'ssd',
- reference: 'ssd'
- },
- {
- xtype: 'proxmoxcheckbox',
- disabled: me.confid && !me.confid.match(/^(virtio|scsi)/),
- fieldLabel: 'IO thread',
- labelWidth: labelWidth,
- reference: 'iothread',
- name: 'iothread'
- },
- {
- xtype: 'numberfield',
- name: 'mbps_rd',
- minValue: 1,
- step: 1,
- fieldLabel: gettext('Read limit') + ' (MB/s)',
- labelWidth: labelWidth,
- emptyText: gettext('unlimited')
- },
- {
- xtype: 'numberfield',
- name: 'mbps_wr',
- minValue: 1,
- step: 1,
- fieldLabel: gettext('Write limit') + ' (MB/s)',
- labelWidth: labelWidth,
- emptyText: gettext('unlimited')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'iops_rd',
- minValue: 10,
- step: 10,
- fieldLabel: gettext('Read limit') + ' (ops/s)',
- labelWidth: labelWidth,
- emptyText: gettext('unlimited')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'iops_wr',
- minValue: 10,
- step: 10,
- fieldLabel: gettext('Write limit') + ' (ops/s)',
- labelWidth: labelWidth,
- emptyText: gettext('unlimited')
- }
- );
-
- me.advancedColumn2.push(
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('No backup'),
- labelWidth: labelWidth,
- name: 'nobackup'
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Skip replication'),
- labelWidth: labelWidth,
- name: 'noreplicate'
- },
- {
- xtype: 'numberfield',
- name: 'mbps_rd_max',
- minValue: 1,
- step: 1,
- fieldLabel: gettext('Read max burst') + ' (MB)',
- labelWidth: labelWidth,
- emptyText: gettext('default')
- },
- {
- xtype: 'numberfield',
- name: 'mbps_wr_max',
- minValue: 1,
- step: 1,
- fieldLabel: gettext('Write max burst') + ' (MB)',
- labelWidth: labelWidth,
- emptyText: gettext('default')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'iops_rd_max',
- minValue: 10,
- step: 10,
- fieldLabel: gettext('Read max burst') + ' (ops)',
- labelWidth: labelWidth,
- emptyText: gettext('default')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'iops_wr_max',
- minValue: 10,
- step: 10,
- fieldLabel: gettext('Write max burst') + ' (ops)',
- labelWidth: labelWidth,
- emptyText: gettext('default')
- }
- );
-
- me.callParent();
- }
-});
-/*jslint confusion: false */
-
-Ext.define('PVE.qemu.HDEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
-
- backgroundDelay: 5,
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var unused = me.confid && me.confid.match(/^unused\d+$/);
-
- me.isCreate = me.confid ? unused : true;
-
- var ipanel = Ext.create('PVE.qemu.HDInputPanel', {
- confid: me.confid,
- nodename: nodename,
- unused: unused,
- isCreate: me.isCreate
- });
-
- var subject;
- if (unused) {
- me.subject = gettext('Unused Disk');
- } else if (me.isCreate) {
- me.subject = gettext('Hard Disk');
- } else {
- me.subject = gettext('Hard Disk') + ' (' + me.confid + ')';
- }
-
- me.items = [ ipanel ];
-
- me.callParent();
- /*jslint confusion: true*/
- /* 'data' is assigned an empty array in same file, and here we
- * use it like an object
- */
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- if (me.confid) {
- var value = response.result.data[me.confid];
- var drive = PVE.Parser.parseQemuDrive(me.confid, value);
- if (!drive) {
- Ext.Msg.alert(gettext('Error'), 'Unable to parse drive options');
- me.close();
- return;
- }
- ipanel.setDrive(drive);
- me.isValid(); // trigger validation
- }
- }
- });
- /*jslint confusion: false*/
- }
-});
-Ext.define('PVE.window.HDResize', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- resize_disk: function(disk, size) {
- var me = this;
- var params = { disk: disk, size: '+' + size + 'G' };
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/resize',
- waitMsgTarget: me,
- method: 'PUT',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- me.close();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- var items = [
- {
- xtype: 'displayfield',
- name: 'disk',
- value: me.disk,
- fieldLabel: gettext('Disk'),
- vtype: 'StorageId',
- allowBlank: false
- }
- ];
-
- me.hdsizesel = Ext.createWidget('numberfield', {
- name: 'size',
- minValue: 0,
- maxValue: 128*1024,
- decimalPrecision: 3,
- value: '0',
- fieldLabel: gettext('Size Increment') + ' (GiB)',
- allowBlank: false
- });
-
- items.push(me.hdsizesel);
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 140,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- me.title = gettext('Resize disk');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Resize disk'),
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.resize_disk(me.disk, values.size);
- }
- }
- });
-
- Ext.apply(me, {
- modal: true,
- width: 250,
- height: 150,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
-
- me.callParent();
-
- if (!me.disk) {
- return;
- }
-
- }
-});
-Ext.define('PVE.window.HDMove', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
-
- move_disk: function(disk, storage, format, delete_disk) {
- var me = this;
- var qemu = (me.type === 'qemu');
- var params = {};
- params.storage = storage;
- params[qemu ? 'disk':'volume'] = disk;
-
- if (format && qemu) {
- params.format = format;
- }
-
- if (delete_disk) {
- params['delete'] = 1;
- }
-
- var url = '/nodes/' + me.nodename + '/' + me.type + '/' + me.vmid + '/';
- url += qemu ? 'move_disk' : 'move_volume';
-
- Proxmox.Utils.API2Request({
- params: params,
- url: url,
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- win.on('destroy', function() { me.close(); });
- }
- });
-
- },
-
- initComponent : function() {
- var me = this;
-
- var diskarray = [];
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.type) {
- me.type = 'qemu';
- }
-
- var qemu = (me.type === 'qemu');
-
- var items = [
- {
- xtype: 'displayfield',
- name: qemu ? 'disk' : 'volume',
- value: me.disk,
- fieldLabel: qemu ? gettext('Disk') : gettext('Mount Point'),
- vtype: 'StorageId',
- allowBlank: false
- }
- ];
-
- items.push({
- xtype: 'pveDiskStorageSelector',
- storageLabel: gettext('Target Storage'),
- nodename: me.nodename,
- storageContent: qemu ? 'images' : 'rootdir',
- hideSize: true
- });
-
- items.push({
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Delete source'),
- name: 'deleteDisk',
- uncheckedValue: 0,
- checked: false
- });
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- me.title = qemu ? gettext("Move disk") : gettext('Move Volume');
- submitBtn = Ext.create('Ext.Button', {
- text: me.title,
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.move_disk(me.disk, values.hdstorage, values.diskformat,
- values.deleteDisk);
- }
- }
- });
-
- Ext.apply(me, {
- modal: true,
- width: 350,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
-
- me.callParent();
-
- me.mon(me.formPanel, 'validitychange', function(fp, isValid) {
- submitBtn.setDisabled(!isValid);
- });
-
- me.formPanel.isValid();
- }
-});
-Ext.define('PVE.qemu.EFIDiskInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveEFIDiskInputPanel',
-
- insideWizard: false,
-
- unused: false, // ADD usused disk imaged
-
- vmconfig: {}, // used to select usused disks
-
- onGetValues: function(values) {
- var me = this;
-
- var confid = 'efidisk0';
-
- if (values.hdimage) {
- me.drive.file = values.hdimage;
- } else {
- // we use 1 here, because for efi the size gets overridden from the backend
- me.drive.file = values.hdstorage + ":1";
- }
-
- me.drive.format = values.diskformat;
- var params = {};
- params[confid] = PVE.Parser.printQemuDrive(me.drive);
- return params;
- },
-
- setNodename: function(nodename) {
- var me = this;
- me.down('#hdstorage').setNodename(nodename);
- me.down('#hdimage').setStorage(undefined, nodename);
- },
-
- initComponent : function() {
- var me = this;
-
- me.drive = {};
-
- me.items= [];
-
- me.items.push({
- xtype: 'pveDiskStorageSelector',
- name: 'efidisk0',
- storageContent: 'images',
- nodename: me.nodename,
- hideSize: true
- });
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.EFIDiskEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
- subject: gettext('EFI Disk'),
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.items = [{
- xtype: 'pveEFIDiskInputPanel',
- onlineHelp: 'qm_bios_and_uefi',
- confid: me.confid,
- nodename: nodename,
- isCreate: true
- }];
-
- me.callParent();
- }
-});
-Ext.define('PVE.qemu.DisplayInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveDisplayInputPanel',
-
- onGetValues: function(values) {
- var ret = PVE.Parser.printPropertyString(values, 'type');
- if (ret === '') {
- return {
- 'delete': 'vga'
- };
- }
- return {
- vga: ret
- };
- },
-
- items: [{
- name: 'type',
- xtype: 'proxmoxKVComboBox',
- value: '__default__',
- deleteEmpty: false,
- fieldLabel: gettext('Graphic card'),
- comboItems: PVE.Utils.kvm_vga_driver_array(),
- validator: function() {
- var v = this.getValue();
- var cfg = this.up('proxmoxWindowEdit').vmconfig || {};
-
- if (v.match(/^serial\d+$/) && (!cfg[v] || cfg[v] !== 'socket')) {
- var fmt = gettext("Serial interface '{0}' is not correctly configured.");
- return Ext.String.format(fmt, v);
- }
- return true;
- },
- listeners: {
- change: function(cb, val) {
- var me = this.up('panel');
- if (!val) {
- return;
- }
- var disable = false;
- var emptyText = Proxmox.Utils.defaultText;
- switch (val) {
- case "cirrus":
- emptyText = "4";
- break;
- case "std":
- emptyText = "16";
- break;
- case "qxl":
- case "qxl2":
- case "qxl3":
- case "qxl4":
- emptyText = "16";
- break;
- case "vmware":
- emptyText = "16";
- break;
- case "none":
- case "serial0":
- case "serial1":
- case "serial2":
- case "serial3":
- emptyText = 'N/A';
- disable = true;
- break;
- case "virtio":
- emptyText = "256";
- break;
- default:
- break;
- }
- var memoryfield = me.down('field[name=memory]');
- memoryfield.setEmptyText(emptyText);
- memoryfield.setDisabled(disable);
- }
- }
- },{
- xtype: 'proxmoxintegerfield',
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('Memory') + ' (MiB)',
- minValue: 4,
- maxValue: 512,
- step: 4,
- name: 'memory'
- }]
-});
-
-Ext.define('PVE.qemu.DisplayEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmconfig: undefined,
-
- subject: gettext('Display'),
- width: 350,
-
- items: [{
- xtype: 'pveDisplayInputPanel'
- }],
-
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- me.load({
- success: function(response) {
- me.vmconfig = response.result.data;
- var vga = me.vmconfig.vga || '__default__';
- me.setValues(PVE.Parser.parsePropertyString(vga, 'type'));
- }
- });
- }
-});
-Ext.define('PVE.qemu.KeyboardEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.applyIf(me, {
- subject: gettext('Keyboard Layout'),
- items: {
- xtype: 'VNCKeyboardSelector',
- name: 'keyboard',
- value: '__default__',
- fieldLabel: gettext('Keyboard Layout')
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('PVE.qemu.HardwareView', {
- extend: 'Proxmox.grid.PendingObjectGrid',
- alias: ['widget.PVE.qemu.HardwareView'],
-
- onlineHelp: 'qm_virtual_machines_settings',
-
- renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var rowdef = rows[key] || {};
- var iconCls = rowdef.iconCls;
- var icon = '';
- var txt = (rowdef.header || key);
-
- metaData.tdAttr = "valign=middle";
-
- if (rowdef.tdCls) {
- metaData.tdCls = rowdef.tdCls;
- if (rowdef.tdCls == 'pve-itype-icon-storage') {
- var value = me.getObjectValue(key, '', false);
- if (value === '') {
- value = me.getObjectValue(key, '', true);
- }
- if (value.match(/vm-.*-cloudinit/)) {
- metaData.tdCls = 'pve-itype-icon-cloud';
- return rowdef.cloudheader;
- } else if (value.match(/media=cdrom/)) {
- metaData.tdCls = 'pve-itype-icon-cdrom';
- return rowdef.cdheader;
- }
- }
- } else if (iconCls) {
- icon = " ";
- metaData.tdCls += " pve-itype-fa";
- }
- return icon + txt;
- },
-
- initComponent : function() {
- var me = this;
- var i, confid;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
- var diskCap = caps.vms['VM.Config.Disk'];
-
- /*jslint confusion: true */
- var rows = {
- memory: {
- header: gettext('Memory'),
- editor: caps.vms['VM.Config.Memory'] ? 'PVE.qemu.MemoryEdit' : undefined,
- never_delete: true,
- defaultValue: '512',
- tdCls: 'pve-itype-icon-memory',
- group: 2,
- multiKey: ['memory', 'balloon', 'shares'],
- renderer: function(value, metaData, record, ri, ci, store, pending) {
- var res = '';
-
- var max = me.getObjectValue('memory', 512, pending);
- var balloon = me.getObjectValue('balloon', undefined, pending);
- var shares = me.getObjectValue('shares', undefined, pending);
-
- res = Proxmox.Utils.format_size(max*1024*1024);
-
- if (balloon !== undefined && balloon > 0) {
- res = Proxmox.Utils.format_size(balloon*1024*1024) + "/" + res;
-
- if (shares) {
- res += ' [shares=' + shares +']';
- }
- } else if (balloon === 0) {
- res += ' [balloon=0]';
- }
- return res;
- }
- },
- sockets: {
- header: gettext('Processors'),
- never_delete: true,
- editor: (caps.vms['VM.Config.CPU'] || caps.vms['VM.Config.HWType']) ?
- 'PVE.qemu.ProcessorEdit' : undefined,
- tdCls: 'pve-itype-icon-processor',
- group: 3,
- defaultValue: '1',
- multiKey: ['sockets', 'cpu', 'cores', 'numa', 'vcpus', 'cpulimit', 'cpuunits'],
- renderer: function(value, metaData, record, rowIndex, colIndex, store, pending) {
-
- var sockets = me.getObjectValue('sockets', 1, pending);
- var model = me.getObjectValue('cpu', undefined, pending);
- var cores = me.getObjectValue('cores', 1, pending);
- var numa = me.getObjectValue('numa', undefined, pending);
- var vcpus = me.getObjectValue('vcpus', undefined, pending);
- var cpulimit = me.getObjectValue('cpulimit', undefined, pending);
- var cpuunits = me.getObjectValue('cpuunits', undefined, pending);
-
- var res = Ext.String.format('{0} ({1} sockets, {2} cores)',
- sockets*cores, sockets, cores);
-
- if (model) {
- res += ' [' + model + ']';
- }
-
- if (numa) {
- res += ' [numa=' + numa +']';
- }
-
- if (vcpus) {
- res += ' [vcpus=' + vcpus +']';
- }
-
- if (cpulimit) {
- res += ' [cpulimit=' + cpulimit +']';
- }
-
- if (cpuunits) {
- res += ' [cpuunits=' + cpuunits +']';
- }
-
- return res;
- }
- },
- bios: {
- header: 'BIOS',
- group: 4,
- never_delete: true,
- editor: caps.vms['VM.Config.Options'] ? 'PVE.qemu.BiosEdit' : undefined,
- defaultValue: '',
- iconCls: 'microchip',
- renderer: PVE.Utils.render_qemu_bios
- },
- vga: {
- header: gettext('Display'),
- editor: caps.vms['VM.Config.HWType'] ? 'PVE.qemu.DisplayEdit' : undefined,
- never_delete: true,
- tdCls: 'pve-itype-icon-display',
- group:5,
- defaultValue: '',
- renderer: PVE.Utils.render_kvm_vga_driver
- },
- machine: {
- header: gettext('Machine'),
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Machine'),
- width: 350,
- items: [{
- xtype: 'proxmoxKVComboBox',
- name: 'machine',
- value: '__default__',
- fieldLabel: gettext('Machine'),
- comboItems: [
- ['__default__', PVE.Utils.render_qemu_machine('')],
- ['q35', 'q35']
- ]
- }]} : undefined,
- iconCls: 'cogs',
- never_delete: true,
- group: 6,
- defaultValue: '',
- renderer: PVE.Utils.render_qemu_machine
- },
- scsihw: {
- header: gettext('SCSI Controller'),
- iconCls: 'database',
- editor: caps.vms['VM.Config.Options'] ? 'PVE.qemu.ScsiHwEdit' : undefined,
- renderer: PVE.Utils.render_scsihw,
- group: 7,
- never_delete: true,
- defaultValue: ''
- },
- cores: {
- visible: false
- },
- cpu: {
- visible: false
- },
- numa: {
- visible: false
- },
- balloon: {
- visible: false
- },
- hotplug: {
- visible: false
- },
- vcpus: {
- visible: false
- },
- cpuunits: {
- visible: false
- },
- cpulimit: {
- visible: false
- },
- shares: {
- visible: false
- }
- };
- /*jslint confusion: false */
-
- PVE.Utils.forEachBus(undefined, function(type, id) {
- var confid = type + id;
- rows[confid] = {
- group: 10,
- tdCls: 'pve-itype-icon-storage',
- editor: 'PVE.qemu.HDEdit',
- never_delete: caps.vms['VM.Config.Disk'] ? false : true,
- header: gettext('Hard Disk') + ' (' + confid +')',
- cdheader: gettext('CD/DVD Drive') + ' (' + confid +')',
- cloudheader: gettext('CloudInit Drive') + ' (' + confid + ')'
- };
- });
- for (i = 0; i < 32; i++) {
- confid = "net" + i.toString();
- rows[confid] = {
- group: 15,
- order: i,
- tdCls: 'pve-itype-icon-network',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.qemu.NetworkEdit' : undefined,
- never_delete: caps.vms['VM.Config.Network'] ? false : true,
- header: gettext('Network Device') + ' (' + confid +')'
- };
- }
- rows.efidisk0 = {
- group: 20,
- tdCls: 'pve-itype-icon-storage',
- editor: null,
- never_delete: caps.vms['VM.Config.Disk'] ? false : true,
- header: gettext('EFI Disk')
- };
- for (i = 0; i < 5; i++) {
- confid = "usb" + i.toString();
- rows[confid] = {
- group: 25,
- order: i,
- tdCls: 'pve-itype-icon-usb',
- editor: caps.nodes['Sys.Console'] ? 'PVE.qemu.USBEdit' : undefined,
- never_delete: caps.nodes['Sys.Console'] ? false : true,
- header: gettext('USB Device') + ' (' + confid + ')'
- };
- }
- for (i = 0; i < 4; i++) {
- confid = "hostpci" + i.toString();
- rows[confid] = {
- group: 30,
- order: i,
- tdCls: 'pve-itype-icon-pci',
- never_delete: caps.nodes['Sys.Console'] ? false : true,
- editor: caps.nodes['Sys.Console'] ? 'PVE.qemu.PCIEdit' : undefined,
- header: gettext('PCI Device') + ' (' + confid + ')'
- };
- }
- for (i = 0; i < 4; i++) {
- confid = "serial" + i.toString();
- rows[confid] = {
- group: 35,
- order: i,
- tdCls: 'pve-itype-icon-serial',
- never_delete: caps.nodes['Sys.Console'] ? false : true,
- header: gettext('Serial Port') + ' (' + confid + ')'
- };
- }
- for (i = 0; i < 256; i++) {
- rows["unused" + i.toString()] = {
- group: 99,
- order: i,
- tdCls: 'pve-itype-icon-storage',
- editor: caps.vms['VM.Config.Disk'] ? 'PVE.qemu.HDEdit' : undefined,
- header: gettext('Unused Disk') + ' ' + i.toString()
- };
- }
-
- var sorterFn = function(rec1, rec2) {
- var v1 = rec1.data.key;
- var v2 = rec2.data.key;
- var g1 = rows[v1].group || 0;
- var g2 = rows[v2].group || 0;
- var order1 = rows[v1].order || 0;
- var order2 = rows[v2].order || 0;
-
- if ((g1 - g2) !== 0) {
- return g1 - g2;
- }
-
- if ((order1 - order2) !== 0) {
- return order1 - order2;
- }
-
- if (v1 > v2) {
- return 1;
- } else if (v1 < v2) {
- return -1;
- } else {
- return 0;
- }
- };
-
- var reload = function() {
- me.rstore.load();
- };
-
- var baseurl = 'nodes/' + nodename + '/qemu/' + vmid + '/config';
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var rowdef = rows[rec.data.key];
- if (!rowdef.editor) {
- return;
- }
-
- var editor = rowdef.editor;
- if (rowdef.tdCls == 'pve-itype-icon-storage') {
- if (!diskCap) {
- return;
- }
- var value = me.getObjectValue(rec.data.key, '', true);
- if (value.match(/vm-.*-cloudinit/)) {
- return;
- } else if (value.match(/media=cdrom/)) {
- editor = 'PVE.qemu.CDEdit';
- }
- }
-
- var win;
-
- if (Ext.isString(editor)) {
- win = Ext.create(editor, {
- pveSelNode: me.pveSelNode,
- confid: rec.data.key,
- url: '/api2/extjs/' + baseurl
- });
- } else {
- var config = Ext.apply({
- pveSelNode: me.pveSelNode,
- confid: rec.data.key,
- url: '/api2/extjs/' + baseurl
- }, rowdef.editor);
- win = Ext.createWidget(rowdef.editor.xtype, config);
- win.load();
- }
-
- win.show();
- win.on('destroy', reload);
- };
-
- var run_resize = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.window.HDResize', {
- disk: rec.data.key,
- nodename: nodename,
- vmid: vmid
- });
-
- win.show();
-
- win.on('destroy', reload);
- };
-
- var run_move = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.window.HDMove', {
- disk: rec.data.key,
- nodename: nodename,
- vmid: vmid
- });
-
- win.show();
-
- win.on('destroy', reload);
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- selModel: sm,
- disabled: true,
- handler: run_editor
- });
-
- var resize_btn = new Proxmox.button.Button({
- text: gettext('Resize disk'),
- selModel: sm,
- disabled: true,
- handler: run_resize
- });
-
- var move_btn = new Proxmox.button.Button({
- text: gettext('Move disk'),
- selModel: sm,
- disabled: true,
- handler: run_move
- });
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- defaultText: gettext('Remove'),
- altText: gettext('Detach'),
- selModel: sm,
- disabled: true,
- dangerous: true,
- RESTMethod: 'PUT',
- confirmMsg: function(rec) {
- var warn = gettext('Are you sure you want to remove entry {0}');
- if (this.text === this.altText) {
- warn = gettext('Are you sure you want to detach entry {0}');
- }
-
- var entry = rec.data.key;
- var msg = Ext.String.format(warn, "'"
- + me.renderKey(entry, {}, rec) + "'");
-
- if (entry.match(/^unused\d+$/)) {
- msg += " " + gettext('This will permanently erase all data.');
- }
-
- return msg;
- },
- handler: function(b, e, rec) {
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/' + baseurl,
- waitMsgTarget: me,
- method: b.RESTMethod,
- params: {
- 'delete': rec.data.key
- },
- callback: function() {
- reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- if (b.RESTMethod === 'POST') {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid,
- listeners: {
- destroy: function () {
- me.reload();
- }
- }
- });
- win.show();
- }
- }
- });
- },
- listeners: {
- render: function(btn) {
- // hack: calculate an optimal button width on first display
- // to prevent the whole toolbar to move when we switch
- // between the "Remove" and "Detach" labels
- var def = btn.getSize().width;
-
- btn.setText(btn.altText);
- var alt = btn.getSize().width;
-
- btn.setText(btn.defaultText);
-
- var optimal = alt > def ? alt : def;
- btn.setSize({ width: optimal });
- }
- }
- });
-
- var revert_btn = new Proxmox.button.Button({
- text: gettext('Revert'),
- selModel: sm,
- disabled: true,
- handler: function(b, e, rec) {
- var rowdef = me.rows[rec.data.key] || {};
- var keys = rowdef.multiKey || [ rec.data.key ];
- var revert = keys.join(',');
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/' + baseurl,
- waitMsgTarget: me,
- method: 'PUT',
- params: {
- 'revert': revert
- },
- callback: function() {
- reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert('Error',response.htmlStatus);
- }
- });
- }
- });
-
- var efidisk_menuitem = Ext.create('Ext.menu.Item',{
- text: gettext('EFI Disk'),
- iconCls: 'pve-itype-icon-storage',
- disabled: !caps.vms['VM.Config.Disk'],
- handler: function() {
-
- var rstoredata = me.rstore.getData().map;
- // check if ovmf is configured
- if (rstoredata.bios && rstoredata.bios.data.value === 'ovmf') {
- var win = Ext.create('PVE.qemu.EFIDiskEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- } else {
- Ext.Msg.alert('Error',gettext('Please select OVMF(UEFI) as BIOS first.'));
- }
-
- }
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- // disable button when we have an efidisk already
- // disable is ok in this case, because you can instantly
- // see that there is already one
- efidisk_menuitem.setDisabled(me.rstore.getData().map.efidisk0 !== undefined);
- // en/disable usb add button
- var usbcount = 0;
- var pcicount = 0;
- var hasCloudInit = false;
- me.rstore.getData().items.forEach(function(item){
- if (/^usb\d+/.test(item.id)) {
- usbcount++;
- } else if (/^hostpci\d+/.test(item.id)) {
- pcicount++;
- }
- if (!hasCloudInit && /vm-.*-cloudinit/.test(item.data.value)) {
- hasCloudInit = true;
- }
- });
-
- // heuristic only for disabling some stuff, the backend has the final word.
- var noSysConsolePerm = !caps.nodes['Sys.Console'];
-
- me.down('#addusb').setDisabled(noSysConsolePerm || (usbcount >= 5));
- me.down('#addpci').setDisabled(noSysConsolePerm || (pcicount >= 4));
- me.down('#addci').setDisabled(noSysConsolePerm || hasCloudInit);
-
- if (!rec) {
- remove_btn.disable();
- edit_btn.disable();
- resize_btn.disable();
- move_btn.disable();
- revert_btn.disable();
- return;
- }
- var key = rec.data.key;
- var value = rec.data.value;
- var rowdef = rows[key];
-
- var pending = rec.data['delete'] || me.hasPendingChanges(key);
- var isUnusedDisk = key.match(/^unused\d+/);
- var isUsedDisk = !isUnusedDisk &&
- rowdef.tdCls == 'pve-itype-icon-storage' &&
- (value && !value.match(/media=cdrom/));
-
- var isCloudInit = (value && value.toString().match(/vm-.*-cloudinit/));
-
- var isEfi = (key === 'efidisk0');
-
- remove_btn.setDisabled(rec.data['delete'] || (rowdef.never_delete === true) || (isUnusedDisk && !diskCap));
- remove_btn.setText((isUsedDisk && !isCloudInit) ? remove_btn.altText : remove_btn.defaultText);
- remove_btn.RESTMethod = isUnusedDisk ? 'POST':'PUT';
-
- edit_btn.setDisabled(rec.data['delete'] || !rowdef.editor || isCloudInit || !diskCap);
-
- resize_btn.setDisabled(pending || !isUsedDisk || !diskCap);
-
- move_btn.setDisabled(pending || !isUsedDisk || !diskCap);
-
- revert_btn.setDisabled(!pending);
-
- };
-
- Ext.apply(me, {
- url: '/api2/json/' + 'nodes/' + nodename + '/qemu/' + vmid + '/pending',
- interval: 5000,
- selModel: sm,
- run_editor: run_editor,
- tbar: [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Hard Disk'),
- iconCls: 'pve-itype-icon-storage',
- disabled: !caps.vms['VM.Config.Disk'],
- handler: function() {
- var win = Ext.create('PVE.qemu.HDEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('CD/DVD Drive'),
- iconCls: 'pve-itype-icon-cdrom',
- disabled: !caps.vms['VM.Config.Disk'],
- handler: function() {
- var win = Ext.create('PVE.qemu.CDEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('Network Device'),
- iconCls: 'pve-itype-icon-network',
- disabled: !caps.vms['VM.Config.Network'],
- handler: function() {
- var win = Ext.create('PVE.qemu.NetworkEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode,
- isCreate: true
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- efidisk_menuitem,
- {
- text: gettext('USB Device'),
- itemId: 'addusb',
- iconCls: 'pve-itype-icon-usb',
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.qemu.USBEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('PCI Device'),
- itemId: 'addpci',
- iconCls: 'pve-itype-icon-pci',
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.qemu.PCIEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('Serial Port'),
- itemId: 'addserial',
- iconCls: 'pve-itype-icon-serial',
- disabled: !caps.vms['VM.Config.Options'],
- handler: function() {
- var win = Ext.create('PVE.qemu.SerialEdit', {
- url: '/api2/extjs/' + baseurl
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('CloudInit Drive'),
- itemId: 'addci',
- iconCls: 'pve-itype-icon-cloud',
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.qemu.CIDriveEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- }
- ]
- })
- },
- remove_btn,
- edit_btn,
- resize_btn,
- move_btn,
- revert_btn
- ],
- rows: rows,
- sorterFn: sorterFn,
- listeners: {
- itemdblclick: run_editor,
- selectionchange: set_button_status
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
-
- me.mon(me.rstore, 'refresh', function() {
- set_button_status();
- });
- }
-});
-Ext.define('PVE.qemu.ScsiHwEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.applyIf(me, {
- subject: gettext('SCSI Controller Type'),
- items: {
- xtype: 'pveScsiHwSelector',
- name: 'scsihw',
- value: '__default__',
- fieldLabel: gettext('Type')
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('PVE.qemu.BiosEdit', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveQemuBiosEdit',
-
- initComponent : function() {
- var me = this;
-
- var EFIHint = Ext.createWidget({
- xtype: 'displayfield', //submitValue is false, so we don't get submitted
- userCls: 'pve-hint',
- value: 'You need to add an EFI disk for storing the ' +
- 'EFI settings. See the online help for details.',
- hidden: true
- });
-
- Ext.applyIf(me, {
- subject: 'BIOS',
- items: [ {
- xtype: 'pveQemuBiosSelector',
- onlineHelp: 'qm_bios_and_uefi',
- name: 'bios',
- value: '__default__',
- fieldLabel: 'BIOS',
- listeners: {
- 'change' : function(field, newValue) {
- if (newValue == 'ovmf') {
- Proxmox.Utils.API2Request({
- url : me.url,
- method : 'GET',
- failure : function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success : function(response, opts) {
- var vmConfig = response.result.data;
- // there can be only one
- if (!vmConfig.efidisk0) {
- EFIHint.setVisible(true);
- }
- }
- });
- } else {
- if (EFIHint.isVisible()) {
- EFIHint.setVisible(false);
- }
- }
- }
- }
- },
- EFIHint
- ] });
-
- me.callParent();
-
- me.load();
-
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.qemu.Options', {
- extend: 'Proxmox.grid.PendingObjectGrid',
- alias: ['widget.PVE.qemu.Options'],
-
- onlineHelp: 'qm_options',
-
- initComponent : function() {
- var me = this;
- var i;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var rows = {
- name: {
- required: true,
- defaultValue: me.pveSelNode.data.name,
- header: gettext('Name'),
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Name'),
- items: {
- xtype: 'inputpanel',
- items:{
- xtype: 'textfield',
- name: 'name',
- vtype: 'DnsName',
- value: '',
- fieldLabel: gettext('Name'),
- allowBlank: true
- },
- onGetValues: function(values) {
- var params = values;
- if (values.name === undefined ||
- values.name === null ||
- values.name === '') {
- params = { 'delete':'name'};
- }
- return params;
- }
- }
- } : undefined
- },
- onboot: {
- header: gettext('Start at boot'),
- defaultValue: '',
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Start at boot'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'onboot',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Start at boot')
- }
- } : undefined
- },
- startup: {
- header: gettext('Start/Shutdown order'),
- defaultValue: '',
- renderer: PVE.Utils.render_kvm_startup,
- editor: caps.vms['VM.Config.Options'] && caps.nodes['Sys.Modify'] ?
- {
- xtype: 'pveWindowStartupEdit',
- onlineHelp: 'qm_startup_and_shutdown'
- } : undefined
- },
- ostype: {
- header: gettext('OS Type'),
- editor: caps.vms['VM.Config.Options'] ? 'PVE.qemu.OSTypeEdit' : undefined,
- renderer: PVE.Utils.render_kvm_ostype,
- defaultValue: 'other'
- },
- bootdisk: {
- visible: false
- },
- boot: {
- header: gettext('Boot Order'),
- defaultValue: 'cdn',
- editor: caps.vms['VM.Config.Disk'] ? 'PVE.qemu.BootOrderEdit' : undefined,
- multiKey: ['boot', 'bootdisk'],
- renderer: function(order, metaData, record, rowIndex, colIndex, store, pending) {
- var i;
- var text = '';
- var bootdisk = me.getObjectValue('bootdisk', undefined, pending);
- order = order || 'cdn';
- for (i = 0; i < order.length; i++) {
- var sel = order.substring(i, i + 1);
- if (text) {
- text += ', ';
- }
- if (sel === 'c') {
- if (bootdisk) {
- text += "Disk '" + bootdisk + "'";
- } else {
- text += "Disk";
- }
- } else if (sel === 'n') {
- text += 'Network';
- } else if (sel === 'a') {
- text += 'Floppy';
- } else if (sel === 'd') {
- text += 'CD-ROM';
- } else {
- text += sel;
- }
- }
- return text;
- }
- },
- tablet: {
- header: gettext('Use tablet for pointer'),
- defaultValue: true,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Use tablet for pointer'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'tablet',
- checked: true,
- uncheckedValue: 0,
- defaultValue: 1,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- hotplug: {
- header: gettext('Hotplug'),
- defaultValue: 'disk,network,usb',
- renderer: PVE.Utils.render_hotplug_features,
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Hotplug'),
- items: {
- xtype: 'pveHotplugFeatureSelector',
- name: 'hotplug',
- value: '',
- multiSelect: true,
- fieldLabel: gettext('Hotplug'),
- allowBlank: true
- }
- } : undefined
- },
- acpi: {
- header: gettext('ACPI support'),
- defaultValue: true,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('ACPI support'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'acpi',
- checked: true,
- uncheckedValue: 0,
- defaultValue: 1,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- kvm: {
- header: gettext('KVM hardware virtualization'),
- defaultValue: true,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('KVM hardware virtualization'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'kvm',
- checked: true,
- uncheckedValue: 0,
- defaultValue: 1,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- freeze: {
- header: gettext('Freeze CPU at startup'),
- defaultValue: false,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.PowerMgmt'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Freeze CPU at startup'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'freeze',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- labelWidth: 140,
- fieldLabel: gettext('Freeze CPU at startup')
- }
- } : undefined
- },
- localtime: {
- header: gettext('Use local time for RTC'),
- defaultValue: false,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Use local time for RTC'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'localtime',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- labelWidth: 140,
- fieldLabel: gettext('Use local time for RTC')
- }
- } : undefined
- },
- startdate: {
- header: gettext('RTC start date'),
- defaultValue: 'now',
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('RTC start date'),
- items: {
- xtype: 'proxmoxtextfield',
- name: 'startdate',
- deleteEmpty: true,
- value: 'now',
- fieldLabel: gettext('RTC start date'),
- vtype: 'QemuStartDate',
- allowBlank: true
- }
- } : undefined
- },
- smbios1: {
- header: gettext('SMBIOS settings (type1)'),
- defaultValue: '',
- renderer: Ext.String.htmlEncode,
- editor: caps.vms['VM.Config.HWType'] ? 'PVE.qemu.Smbios1Edit' : undefined
- },
- agent: {
- header: gettext('Qemu Agent'),
- defaultValue: false,
- renderer: PVE.Utils.render_qga_features,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Qemu Agent'),
- items: {
- xtype: 'pveAgentFeatureSelector',
- name: 'agent'
- }
- } : undefined
- },
- protection: {
- header: gettext('Protection'),
- defaultValue: false,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Protection'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'protection',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- hookscript: {
- header: gettext('Hookscript')
- }
- };
-
- var baseurl = 'nodes/' + nodename + '/qemu/' + vmid + '/config';
-
- var edit_btn = new Ext.Button({
- text: gettext('Edit'),
- disabled: true,
- handler: function() { me.run_editor(); }
- });
-
- var revert_btn = new Proxmox.button.Button({
- text: gettext('Revert'),
- disabled: true,
- handler: function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var rowdef = me.rows[rec.data.key] || {};
- var keys = rowdef.multiKey || [ rec.data.key ];
- var revert = keys.join(',');
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/' + baseurl,
- waitMsgTarget: me,
- method: 'PUT',
- params: {
- 'revert': revert
- },
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert('Error',response.htmlStatus);
- }
- });
- }
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- edit_btn.disable();
- return;
- }
-
- var key = rec.data.key;
- var pending = rec.data['delete'] || me.hasPendingChanges(key);
- var rowdef = rows[key];
-
- edit_btn.setDisabled(!rowdef.editor);
- revert_btn.setDisabled(!pending);
- };
-
- Ext.apply(me, {
- url: "/api2/json/nodes/" + nodename + "/qemu/" + vmid + "/pending",
- interval: 5000,
- cwidth1: 250,
- tbar: [ edit_btn, revert_btn ],
- rows: rows,
- editorConfig: {
- url: "/api2/extjs/" + baseurl
- },
- listeners: {
- itemdblclick: me.run_editor,
- selectionchange: set_button_status
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
-
- me.rstore.on('datachanged', function() {
- set_button_status();
- });
- }
-});
-
-Ext.define('PVE.window.Snapshot', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- // needed for finding the reference to submitbutton
- // because we do not have a controller
- referenceHolder: true,
- defaultButton: 'submitbutton',
- defaultFocus: 'field',
-
- take_snapshot: function(snapname, descr, vmstate) {
- var me = this;
- var params = { snapname: snapname, vmstate: vmstate ? 1 : 0 };
- if (descr) {
- params.description = descr;
- }
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot",
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- me.close();
- }
- });
- },
-
- update_snapshot: function(snapname, descr) {
- var me = this;
- Proxmox.Utils.API2Request({
- params: { description: descr },
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot/" +
- snapname + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- me.close();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- var summarystore = Ext.create('Ext.data.Store', {
- model: 'KeyValue',
- sorters: [
- {
- property : 'key',
- direction: 'ASC'
- }
- ]
- });
-
- var items = [
- {
- xtype: me.snapname ? 'displayfield' : 'textfield',
- name: 'snapname',
- value: me.snapname,
- fieldLabel: gettext('Name'),
- vtype: 'ConfigId',
- allowBlank: false
- }
- ];
-
- if (me.snapname) {
- items.push({
- xtype: 'displayfield',
- name: 'snaptime',
- renderer: PVE.Utils.render_timestamp_human_readable,
- fieldLabel: gettext('Timestamp')
- });
- } else {
- items.push({
- xtype: 'proxmoxcheckbox',
- name: 'vmstate',
- uncheckedValue: 0,
- defaultValue: 0,
- checked: 1,
- fieldLabel: gettext('Include RAM')
- });
- }
-
- items.push({
- xtype: 'textareafield',
- grow: true,
- name: 'description',
- fieldLabel: gettext('Description')
- });
-
- if (me.snapname) {
- items.push({
- title: gettext('Settings'),
- xtype: 'grid',
- height: 200,
- store: summarystore,
- columns: [
- {header: gettext('Key'), width: 150, dataIndex: 'key'},
- {header: gettext('Value'), flex: 1, dataIndex: 'value'}
- ]
- });
- }
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- if (me.snapname) {
- me.title = gettext('Edit') + ': ' + gettext('Snapshot');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Update'),
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.update_snapshot(me.snapname, values.description);
- }
- }
- });
- } else {
- me.title ="VM " + me.vmid + ': ' + gettext('Take Snapshot');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Take Snapshot'),
- reference: 'submitbutton',
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.take_snapshot(values.snapname, values.description, values.vmstate);
- }
- }
- });
- }
-
- Ext.apply(me, {
- modal: true,
- width: 450,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
- if (me.snapname) {
- Ext.apply(me, {
- width: 620,
- height: 420
- });
- }
-
- me.callParent();
-
- if (!me.snapname) {
- return;
- }
-
- // else load data
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot/" +
- me.snapname + '/config',
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- me.close();
- },
- success: function(response, options) {
- var data = response.result.data;
- var kvarray = [];
- Ext.Object.each(data, function(key, value) {
- if (key === 'description' || key === 'snaptime') {
- return;
- }
- kvarray.push({ key: key, value: value });
- });
-
- summarystore.suspendEvents();
- summarystore.add(kvarray);
- summarystore.sort();
- summarystore.resumeEvents();
- summarystore.fireEvent('refresh', summarystore);
-
- form.findField('snaptime').setValue(data.snaptime);
- form.findField('description').setValue(data.description);
- }
- });
- }
-});
-Ext.define('PVE.qemu.SnapshotTree', {
- extend: 'Ext.tree.Panel',
- alias: ['widget.pveQemuSnapshotTree'],
-
- load_delay: 3000,
-
- old_digest: 'invalid',
-
- stateful: true,
- stateId: 'grid-qemu-snapshots',
-
- sorterFn: function(rec1, rec2) {
- var v1 = rec1.data.snaptime;
- var v2 = rec2.data.snaptime;
-
- if (rec1.data.name === 'current') {
- return 1;
- }
- if (rec2.data.name === 'current') {
- return -1;
- }
-
- return (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
- },
-
- reload: function(repeat) {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/snapshot',
- method: 'GET',
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- me.load_task.delay(me.load_delay);
- },
- success: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, false);
- var digest = 'invalid';
- var idhash = {};
- var root = { name: '__root', expanded: true, children: [] };
- Ext.Array.each(response.result.data, function(item) {
- item.leaf = true;
- item.children = [];
- if (item.name === 'current') {
- digest = item.digest + item.running;
- if (item.running) {
- item.iconCls = 'fa fa-fw fa-desktop x-fa-tree-running';
- } else {
- item.iconCls = 'fa fa-fw fa-desktop x-fa-tree';
- }
- } else {
- item.iconCls = 'fa fa-fw fa-history x-fa-tree';
- }
- idhash[item.name] = item;
- });
-
- if (digest !== me.old_digest) {
- me.old_digest = digest;
-
- Ext.Array.each(response.result.data, function(item) {
- if (item.parent && idhash[item.parent]) {
- var parent_item = idhash[item.parent];
- parent_item.children.push(item);
- parent_item.leaf = false;
- parent_item.expanded = true;
- parent_item.expandable = false;
- } else {
- root.children.push(item);
- }
- });
-
- me.setRootNode(root);
- }
-
- me.load_task.delay(me.load_delay);
- }
- });
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/feature',
- params: { feature: 'snapshot' },
- method: 'GET',
- success: function(response, options) {
- var res = response.result.data;
- if (res.hasFeature) {
- var snpBtns = Ext.ComponentQuery.query('#snapshotBtn');
- snpBtns.forEach(function(item){
- item.enable();
- });
- }
- }
- });
-
-
- },
-
- listeners: {
- beforestatesave: function(grid, state, eopts) {
- // extjs cannot serialize functions,
- // so a the sorter with only the sorterFn will
- // not be a valid sorter when restoring the state
- delete state.storeState.sorters;
- }
- },
-
- initComponent: function() {
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.vmid = me.pveSelNode.data.vmid;
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- me.load_task = new Ext.util.DelayedTask(me.reload, me);
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var valid_snapshot = function(record) {
- return record && record.data && record.data.name &&
- record.data.name !== 'current';
- };
-
- var valid_snapshot_rollback = function(record) {
- return record && record.data && record.data.name &&
- record.data.name !== 'current' && !record.data.snapstate;
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (valid_snapshot(rec)) {
- var win = Ext.create('PVE.window.Snapshot', {
- snapname: rec.data.name,
- nodename: me.nodename,
- vmid: me.vmid
- });
- win.show();
- me.mon(win, 'close', me.reload, me);
- }
- };
-
- var editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- enableFn: valid_snapshot,
- handler: run_editor
- });
-
- var rollbackBtn = new Proxmox.button.Button({
- text: gettext('Rollback'),
- disabled: true,
- selModel: sm,
- enableFn: valid_snapshot_rollback,
- confirmMsg: function(rec) {
- return Proxmox.Utils.format_task_description('qmrollback', me.vmid) +
- " '" + rec.data.name + "'";
- },
- handler: function(btn, event) {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var snapname = rec.data.name;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/snapshot/' + snapname + '/rollback',
- method: 'POST',
- waitMsgTarget: me,
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- });
- }
- });
-
- var removeBtn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- confirmMsg: function(rec) {
- var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.name + "'");
- return msg;
- },
- enableFn: valid_snapshot,
- handler: function(btn, event) {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var snapname = rec.data.name;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/snapshot/' + snapname,
- method: 'DELETE',
- waitMsgTarget: me,
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- });
- }
- });
-
- var snapshotBtn = Ext.create('Ext.Button', {
- itemId: 'snapshotBtn',
- text: gettext('Take Snapshot'),
- disabled: true,
- handler: function() {
- var win = Ext.create('PVE.window.Snapshot', {
- nodename: me.nodename,
- vmid: me.vmid
- });
- win.show();
- }
- });
-
- Ext.apply(me, {
- layout: 'fit',
- rootVisible: false,
- animate: false,
- sortableColumns: false,
- selModel: sm,
- tbar: [ snapshotBtn, rollbackBtn, removeBtn, editBtn ],
- fields: [
- 'name', 'description', 'snapstate', 'vmstate', 'running',
- { name: 'snaptime', type: 'date', dateFormat: 'timestamp' }
- ],
- columns: [
- {
- xtype: 'treecolumn',
- text: gettext('Name'),
- dataIndex: 'name',
- width: 200,
- renderer: function(value, metaData, record) {
- if (value === 'current') {
- return "NOW";
- } else {
- return value;
- }
- }
- },
- {
- text: gettext('RAM'),
- align: 'center',
- resizable: false,
- dataIndex: 'vmstate',
- width: 50,
- renderer: function(value, metaData, record) {
- if (record.data.name !== 'current') {
- return Proxmox.Utils.format_boolean(value);
- }
- }
- },
- {
- text: gettext('Date') + "/" + gettext("Status"),
- dataIndex: 'snaptime',
- width: 150,
- renderer: function(value, metaData, record) {
- if (record.data.snapstate) {
- return record.data.snapstate;
- }
- if (value) {
- return Ext.Date.format(value,'Y-m-d H:i:s');
- }
- }
- },
- {
- text: gettext('Description'),
- dataIndex: 'description',
- flex: 1,
- renderer: function(value, metaData, record) {
- if (record.data.name === 'current') {
- return gettext("You are here!");
- } else {
- return Ext.String.htmlEncode(value);
- }
- }
- }
- ],
- columnLines: true, // will work in 4.1?
- listeners: {
- activate: me.reload,
- destroy: me.load_task.cancel,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
-
- me.store.sorters.add(new Ext.util.Sorter({
- sorterFn: me.sorterFn
- }));
- }
-});
-
-Ext.define('PVE.qemu.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.qemu.Config',
-
- onlineHelp: 'chapter_virtual_machines',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var template = !!me.pveSelNode.data.template;
-
- var running = !!me.pveSelNode.data.uptime;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var base_url = '/nodes/' + nodename + "/qemu/" + vmid;
-
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: '/api2/json' + base_url + '/status/current',
- interval: 1000
- });
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: base_url + '/status/' + cmd,
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- var resumeBtn = Ext.create('Ext.Button', {
- text: gettext('Resume'),
- disabled: !caps.vms['VM.PowerMgmt'],
- hidden: true,
- handler: function() {
- vm_command('resume');
- },
- iconCls: 'fa fa-play'
- });
-
- var startBtn = Ext.create('Ext.Button', {
- text: gettext('Start'),
- disabled: !caps.vms['VM.PowerMgmt'] || running,
- hidden: template,
- handler: function() {
- vm_command('start');
- },
- iconCls: 'fa fa-play'
- });
-
- var migrateBtn = Ext.create('Ext.Button', {
- text: gettext('Migrate'),
- disabled: !caps.vms['VM.Migrate'],
- hidden: PVE.data.ResourceStore.getNodes().length < 2,
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: 'qemu',
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- },
- iconCls: 'fa fa-send-o'
- });
-
- var moreBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('More'),
- menu: { items: [
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- hidden: caps.vms['VM.Clone'] ? false : true,
- handler: function() {
- PVE.window.Clone.wrap(nodename, vmid, template, 'qemu');
- }
- },
- {
- text: gettext('Convert to template'),
- disabled: template,
- xtype: 'pveMenuItem',
- iconCls: 'fa fa-fw fa-file-o',
- hidden: caps.vms['VM.Allocate'] ? false : true,
- confirmMsg: Proxmox.Utils.format_task_description('qmtemplate', vmid),
- handler: function() {
- Proxmox.Utils.API2Request({
- url: base_url + '/template',
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- }
- },
- {
- iconCls: 'fa fa-heartbeat ',
- hidden: !caps.nodes['Sys.Console'],
- text: gettext('Manage HA'),
- handler: function() {
- var ha = me.pveSelNode.data.hastate;
- Ext.create('PVE.ha.VMResourceEdit', {
- vmid: vmid,
- isCreate: (!ha || ha === 'unmanaged')
- }).show();
- }
- },
- {
- text: gettext('Remove'),
- itemId: 'removeBtn',
- disabled: !caps.vms['VM.Allocate'],
- handler: function() {
- Ext.create('PVE.window.SafeDestroy', {
- url: base_url,
- item: { type: 'VM', id: vmid }
- }).show();
- },
- iconCls: 'fa fa-trash-o'
- }
- ]}
- });
-
- var shutdownBtn = Ext.create('PVE.button.Split', {
- text: gettext('Shutdown'),
- disabled: !caps.vms['VM.PowerMgmt'] || !running,
- hidden: template,
- confirmMsg: Proxmox.Utils.format_task_description('qmshutdown', vmid),
- handler: function() {
- vm_command('shutdown');
- },
- menu: {
- items: [{
- text: gettext('Pause'),
- disabled: !caps.vms['VM.PowerMgmt'],
- confirmMsg: Proxmox.Utils.format_task_description('qmpause', vmid),
- handler: function() {
- vm_command("suspend");
- },
- iconCls: 'fa fa-pause'
- },{
- text: gettext('Hibernate'),
- disabled: !caps.vms['VM.PowerMgmt'],
- confirmMsg: Proxmox.Utils.format_task_description('qmsuspend', vmid),
- tooltip: gettext('Suspend to disk'),
- handler: function() {
- vm_command("suspend", { todisk: 1 });
- },
- iconCls: 'fa fa-download'
- },{
- text: gettext('Stop'),
- disabled: !caps.vms['VM.PowerMgmt'],
- dangerous: true,
- tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'VM'),
- confirmMsg: Proxmox.Utils.format_task_description('qmstop', vmid),
- handler: function() {
- vm_command("stop", { timeout: 30 });
- },
- iconCls: 'fa fa-stop'
- },{
- text: gettext('Reset'),
- disabled: !caps.vms['VM.PowerMgmt'],
- confirmMsg: Proxmox.Utils.format_task_description('qmreset', vmid),
- handler: function() {
- vm_command("reset");
- },
- iconCls: 'fa fa-bolt'
- }]
- },
- iconCls: 'fa fa-power-off'
- });
-
- var vm = me.pveSelNode.data;
-
- var consoleBtn = Ext.create('PVE.button.ConsoleButton', {
- disabled: !caps.vms['VM.Console'],
- hidden: template,
- consoleType: 'kvm',
- consoleName: vm.name,
- nodename: nodename,
- vmid: vmid
- });
-
- var statusTxt = Ext.create('Ext.toolbar.TextItem', {
- data: {
- lock: undefined
- },
- tpl: [
- '',
- ' ({lock})',
- ' '
- ]
- });
-
- Ext.apply(me, {
- title: Ext.String.format(gettext("Virtual Machine {0} on node '{1}'"), vm.text, nodename),
- hstateid: 'kvmtab',
- tbarSpacing: false,
- tbar: [ statusTxt, '->', resumeBtn, startBtn, shutdownBtn, migrateBtn, consoleBtn, moreBtn ],
- defaults: { statusStore: me.statusStore },
- items: [
- {
- title: gettext('Summary'),
- xtype: 'pveQemuSummary',
- iconCls: 'fa fa-book',
- itemId: 'summary'
- }
- ]
- });
-
- if (caps.vms['VM.Console'] && !template) {
- me.items.push({
- title: gettext('Console'),
- itemId: 'console',
- iconCls: 'fa fa-terminal',
- xtype: 'pveNoVncConsole',
- vmid: vmid,
- consoleType: 'kvm',
- nodename: nodename
- });
- }
-
- me.items.push(
- {
- title: gettext('Hardware'),
- itemId: 'hardware',
- iconCls: 'fa fa-desktop',
- xtype: 'PVE.qemu.HardwareView'
- },
- {
- title: 'Cloud-Init',
- itemId: 'cloudinit',
- iconCls: 'fa fa-cloud',
- xtype: 'pveCiPanel'
- },
- {
- title: gettext('Options'),
- iconCls: 'fa fa-gear',
- itemId: 'options',
- xtype: 'PVE.qemu.Options'
- },
- {
- title: gettext('Task History'),
- itemId: 'tasks',
- xtype: 'proxmoxNodeTasks',
- iconCls: 'fa fa-list',
- nodename: nodename,
- vmidFilter: vmid
- }
- );
-
- if (caps.vms['VM.Monitor'] && !template) {
- me.items.push({
- title: gettext('Monitor'),
- iconCls: 'fa fa-eye',
- itemId: 'monitor',
- xtype: 'pveQemuMonitor'
- });
- }
-
- if (caps.vms['VM.Backup']) {
- me.items.push({
- title: gettext('Backup'),
- iconCls: 'fa fa-floppy-o',
- xtype: 'pveBackupView',
- itemId: 'backup'
- },
- {
- title: gettext('Replication'),
- iconCls: 'fa fa-retweet',
- xtype: 'pveReplicaView',
- itemId: 'replication'
- });
- }
-
- if ((caps.vms['VM.Snapshot'] || caps.vms['VM.Snapshot.Rollback']) && !template) {
- me.items.push({
- title: gettext('Snapshots'),
- iconCls: 'fa fa-history',
- xtype: 'pveQemuSnapshotTree',
- itemId: 'snapshot'
- });
- }
-
- if (caps.vms['VM.Console']) {
- me.items.push(
- {
- xtype: 'pveFirewallRules',
- title: gettext('Firewall'),
- iconCls: 'fa fa-shield',
- allow_iface: true,
- base_url: base_url + '/firewall/rules',
- list_refs_url: base_url + '/firewall/refs',
- itemId: 'firewall'
- },
- {
- xtype: 'pveFirewallOptions',
- groups: ['firewall'],
- iconCls: 'fa fa-gear',
- onlineHelp: 'pve_firewall_vm_container_configuration',
- title: gettext('Options'),
- base_url: base_url + '/firewall/options',
- fwtype: 'vm',
- itemId: 'firewall-options'
- },
- {
- xtype: 'pveFirewallAliases',
- title: gettext('Alias'),
- groups: ['firewall'],
- iconCls: 'fa fa-external-link',
- base_url: base_url + '/firewall/aliases',
- itemId: 'firewall-aliases'
- },
- {
- xtype: 'pveIPSet',
- title: gettext('IPSet'),
- groups: ['firewall'],
- iconCls: 'fa fa-list-ol',
- base_url: base_url + '/firewall/ipset',
- list_refs_url: base_url + '/firewall/refs',
- itemId: 'firewall-ipset'
- },
- {
- title: gettext('Log'),
- groups: ['firewall'],
- iconCls: 'fa fa-list',
- onlineHelp: 'chapter_pve_firewall',
- itemId: 'firewall-fwlog',
- xtype: 'proxmoxLogView',
- url: '/api2/extjs' + base_url + '/firewall/log'
- }
- );
- }
-
- if (caps.vms['Permissions.Modify']) {
- me.items.push({
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- iconCls: 'fa fa-unlock',
- itemId: 'permissions',
- path: '/vms/' + vmid
- });
- }
-
- me.callParent();
-
- me.mon(me.statusStore, 'load', function(s, records, success) {
- var status;
- var qmpstatus;
- var spice = false;
- var xtermjs = false;
- var lock;
-
- if (!success) {
- status = qmpstatus = 'unknown';
- } else {
- var rec = s.data.get('status');
- status = rec ? rec.data.value : 'unknown';
- rec = s.data.get('qmpstatus');
- qmpstatus = rec ? rec.data.value : 'unknown';
- rec = s.data.get('template');
- template = rec.data.value || false;
- rec = s.data.get('lock');
- lock = rec ? rec.data.value : undefined;
-
- spice = s.data.get('spice') ? true : false;
- xtermjs = s.data.get('serial') ? true : false;
-
- }
-
- if (template) {
- return;
- }
-
- var resume = (['prelaunch', 'paused', 'suspended'].indexOf(qmpstatus) !== -1);
-
- if (resume || lock === 'suspended') {
- startBtn.setVisible(false);
- resumeBtn.setVisible(true);
- } else {
- startBtn.setVisible(true);
- resumeBtn.setVisible(false);
- }
-
- consoleBtn.setEnableSpice(spice);
- consoleBtn.setEnableXtermJS(xtermjs);
-
- statusTxt.update({ lock: lock });
-
- startBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 'running' || template);
- shutdownBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status !== 'running');
- me.down('#removeBtn').setDisabled(!caps.vms['VM.Allocate'] || status !== 'stopped');
- consoleBtn.setDisabled(template);
- });
-
- me.on('afterrender', function() {
- me.statusStore.startUpdate();
- });
-
- me.on('destroy', function() {
- me.statusStore.stopUpdate();
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.qemu.CreateWizard', {
- extend: 'PVE.window.Wizard',
- alias: 'widget.pveQemuCreateWizard',
- mixins: ['Proxmox.Mixin.CBind'],
-
- viewModel: {
- data: {
- nodename: '',
- current: {
- scsihw: ''
- }
- }
- },
-
- cbindData: {
- nodename: undefined
- },
-
- subject: gettext('Virtual Machine'),
-
- items: [
- {
- xtype: 'inputpanel',
- title: gettext('General'),
- onlineHelp: 'qm_general_settings',
- column1: [
- {
- xtype: 'pveNodeSelector',
- name: 'nodename',
- cbind: {
- selectCurNode: '{!nodename}',
- preferredValue: '{nodename}'
- },
- bind: {
- value: '{nodename}'
- },
- fieldLabel: gettext('Node'),
- allowBlank: false,
- onlineValidator: true
- },
- {
- xtype: 'pveGuestIDSelector',
- name: 'vmid',
- guestType: 'qemu',
- value: '',
- loadNextFreeID: true,
- validateExists: false
- },
- {
- xtype: 'textfield',
- name: 'name',
- vtype: 'DnsName',
- value: '',
- fieldLabel: gettext('Name'),
- allowBlank: true
- }
- ],
- column2: [
- {
- xtype: 'pvePoolSelector',
- fieldLabel: gettext('Resource Pool'),
- name: 'pool',
- value: '',
- allowBlank: true
- }
- ],
- advancedColumn1: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'onboot',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Start at boot')
- }
- ],
- advancedColumn2: [
- {
- xtype: 'textfield',
- name: 'order',
- defaultValue: '',
- emptyText: 'any',
- labelWidth: 120,
- fieldLabel: gettext('Start/Shutdown order')
- },
- {
- xtype: 'textfield',
- name: 'up',
- defaultValue: '',
- emptyText: 'default',
- labelWidth: 120,
- fieldLabel: gettext('Startup delay')
- },
- {
- xtype: 'textfield',
- name: 'down',
- defaultValue: '',
- emptyText: 'default',
- labelWidth: 120,
- fieldLabel: gettext('Shutdown timeout')
- }
- ],
- onGetValues: function(values) {
-
- ['name', 'pool', 'onboot', 'agent'].forEach(function(field) {
- if (!values[field]) {
- delete values[field];
- }
- });
-
- var res = PVE.Parser.printStartup({
- order: values.order,
- up: values.up,
- down: values.down
- });
-
- if (res) {
- values.startup = res;
- }
-
- delete values.order;
- delete values.up;
- delete values.down;
-
- return values;
- }
- },
- {
- xtype: 'container',
- layout: 'hbox',
- defaults: {
- flex: 1,
- padding: '0 10'
- },
- title: gettext('OS'),
- items: [
- {
- xtype: 'pveQemuCDInputPanel',
- bind: {
- nodename: '{nodename}'
- },
- confid: 'ide2',
- insideWizard: true
- },
- {
- xtype: 'pveQemuOSTypePanel',
- insideWizard: true
- }
- ]
- },
- {
- xtype: 'pveQemuSystemPanel',
- title: gettext('System'),
- isCreate: true,
- insideWizard: true
- },
- {
- xtype: 'pveQemuHDInputPanel',
- bind: {
- nodename: '{nodename}'
- },
- title: gettext('Hard Disk'),
- isCreate: true,
- insideWizard: true
- },
- {
- xtype: 'pveQemuProcessorPanel',
- insideWizard: true,
- title: gettext('CPU')
- },
- {
- xtype: 'pveQemuMemoryPanel',
- insideWizard: true,
- title: gettext('Memory')
- },
- {
- xtype: 'pveQemuNetworkInputPanel',
- bind: {
- nodename: '{nodename}'
- },
- title: gettext('Network'),
- insideWizard: true
- },
- {
- title: gettext('Confirm'),
- layout: 'fit',
- items: [
- {
- xtype: 'grid',
- store: {
- model: 'KeyValue',
- sorters: [{
- property : 'key',
- direction: 'ASC'
- }]
- },
- columns: [
- {header: 'Key', width: 150, dataIndex: 'key'},
- {header: 'Value', flex: 1, dataIndex: 'value'}
- ]
- }
- ],
- dockedItems: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'start',
- dock: 'bottom',
- margin: '5 0 0 0',
- boxLabel: gettext('Start after created')
- }
- ],
- listeners: {
- show: function(panel) {
- var kv = this.up('window').getValues();
- var data = [];
- Ext.Object.each(kv, function(key, value) {
- if (key === 'delete') { // ignore
- return;
- }
- data.push({ key: key, value: value });
- });
-
- var summarystore = panel.down('grid').getStore();
- summarystore.suspendEvents();
- summarystore.removeAll();
- summarystore.add(data);
- summarystore.sort();
- summarystore.resumeEvents();
- summarystore.fireEvent('refresh');
-
- }
- },
- onSubmit: function() {
- var wizard = this.up('window');
- var kv = wizard.getValues();
- delete kv['delete'];
-
- var nodename = kv.nodename;
- delete kv.nodename;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/qemu',
- waitMsgTarget: wizard,
- method: 'POST',
- params: kv,
- success: function(response){
- wizard.close();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- }
- ]
-});
-
-
-
-
-Ext.define('PVE.qemu.USBInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- mixins: ['Proxmox.Mixin.CBind' ],
-
- autoComplete: false,
- onlineHelp: 'qm_usb_passthrough',
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- control: {
- 'field[name=usb]': {
- change: function(field, newValue, oldValue) {
- var hwidfield = this.lookupReference('hwid');
- var portfield = this.lookupReference('port');
- var usb3field = this.lookupReference('usb3');
- if (field.inputValue === 'hostdevice') {
- hwidfield.setDisabled(!newValue);
- } else if(field.inputValue === 'port') {
- portfield.setDisabled(!newValue);
- } else if(field.inputValue === 'spice') {
- usb3field.setDisabled(newValue);
- }
- }
- },
- 'pveUSBSelector': {
- change: function(field, newValue, oldValue) {
- var usbval = field.getUSBValue();
- var usb3field = this.lookupReference('usb3');
- var usb3 = /usb3/.test(usbval);
- if(usb3 && !usb3field.isDisabled()) {
- usb3field.savedVal = usb3field.getValue();
- usb3field.setValue(true);
- usb3field.setDisabled(true);
- } else if(!usb3 && usb3field.isDisabled()){
- var val = (usb3field.savedVal === undefined)?usb3field.originalValue:usb3field.savedVal;
- usb3field.setValue(val);
- usb3field.setDisabled(false);
- }
- }
- }
- }
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
- me.vmconfig = vmconfig;
- },
-
- onGetValues: function(values) {
- var me = this;
- if(!me.confid) {
- var i;
- for (i = 0; i < 6; i++) {
- if (!me.vmconfig['usb' + i.toString()]) {
- me.confid = 'usb' + i.toString();
- break;
- }
- }
- }
- var val = "";
- var type = me.down('radiofield').getGroupValue();
- switch (type) {
- case 'spice':
- val = 'spice'; break;
- case 'hostdevice':
- case 'port':
- val = me.down('pveUSBSelector[name=' + type + ']').getUSBValue();
- if (!/usb3/.test(val) && me.down('field[name=usb3]').getValue() === true) {
- val += ',usb3=1';
- }
- break;
- default:
- throw "invalid type selected";
- }
-
- values[me.confid] = val;
- return values;
- },
-
- items: [
- {
- xtype: 'fieldcontainer',
- defaultType: 'radiofield',
- items:[
- {
- name: 'usb',
- inputValue: 'spice',
- boxLabel: gettext('Spice Port'),
- submitValue: false,
- checked: true
- },
- {
- name: 'usb',
- inputValue: 'hostdevice',
- boxLabel: gettext('Use USB Vendor/Device ID'),
- submitValue: false
- },
- {
- xtype: 'pveUSBSelector',
- disabled: true,
- type: 'device',
- name: 'hostdevice',
- cbind: { pveSelNode: '{pveSelNode}' },
- editable: true,
- reference: 'hwid',
- allowBlank: false,
- fieldLabel: 'Choose Device',
- labelAlign: 'right',
- submitValue: false
- },
- {
- name: 'usb',
- inputValue: 'port',
- boxLabel: gettext('Use USB Port'),
- submitValue: false
- },
- {
- xtype: 'pveUSBSelector',
- disabled: true,
- name: 'port',
- cbind: { pveSelNode: '{pveSelNode}' },
- editable: true,
- type: 'port',
- reference: 'port',
- allowBlank: false,
- fieldLabel: gettext('Choose Port'),
- labelAlign: 'right',
- submitValue: false
- },
- {
- xtype: 'checkbox',
- name: 'usb3',
- submitValue: false,
- reference: 'usb3',
- fieldLabel: gettext('Use USB3')
- }
- ]
- }
- ]
-});
-
-Ext.define('PVE.qemu.USBEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmconfig: undefined,
-
- isAdd: true,
-
- subject: gettext('USB Device'),
-
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.confid;
-
- var ipanel = Ext.create('PVE.qemu.USBInputPanel', {
- confid: me.confid,
- pveSelNode: me.pveSelNode
- });
-
- Ext.apply(me, {
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- if (me.confid) {
- var data = response.result.data[me.confid].split(',');
- var port, hostdevice, usb3 = false;
- var type = 'spice';
- var i;
- for (i = 0; i < data.length; i++) {
- if (/^(host=)?(0x)?[a-zA-Z0-9]{4}\:(0x)?[a-zA-Z0-9]{4}$/.test(data[i])) {
- hostdevice = data[i];
- hostdevice = hostdevice.replace('host=', '').replace('0x','');
- type = 'hostdevice';
- } else if (/^(host=)?(\d+)\-(\d+(\.\d+)*)$/.test(data[i])) {
- port = data[i];
- port = port.replace('host=','');
- type = 'port';
- }
-
- if (/^usb3=(1|on|true)$/.test(data[i])) {
- usb3 = true;
- }
- }
- var values = {
- usb : type,
- hostdevice: hostdevice,
- port: port,
- usb3: usb3
- };
-
- ipanel.setValues(values);
- }
- }
- });
- }
-});
-Ext.define('PVE.qemu.PCIInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
-
- onlineHelp: 'qm_pci_passthrough',
-
- setVMConfig: function(vmconfig) {
- var me = this;
- me.vmconfig = vmconfig;
-
- var hostpci = me.vmconfig[me.confid] || '';
-
- var values = PVE.Parser.parsePropertyString(hostpci, 'host');
- if (values.host && values.host.length < 6) { // 00:00 format not 00:00.0
- values.host += ".0";
- values.multifunction = true;
- }
- values['x-vga'] = PVE.Parser.parseBoolean(values['x-vga'], 0);
- values.pcie = PVE.Parser.parseBoolean(values.pcie, 0);
- values.rombar = PVE.Parser.parseBoolean(values.rombar, 1);
-
- me.setValues(values);
- if (!me.vmconfig.machine || me.vmconfig.machine.indexOf('q35') === -1) {
- // machine is not set to some variant of q35, so we disable pcie
- var pcie = me.down('field[name=pcie]');
- pcie.setDisabled(true);
- pcie.setBoxLabel(gettext('Q35 only'));
- }
-
- if (values.romfile) {
- me.down('field[name=romfile]').setVisible(true);
- }
- },
-
- onGetValues: function(values) {
- var me = this;
- var ret = {};
- if(!me.confid) {
- var i;
- for (i = 0; i < 5; i++) {
- if (!me.vmconfig['hostpci' + i.toString()]) {
- me.confid = 'hostpci' + i.toString();
- break;
- }
- }
- }
- if (values.multifunction) {
- // modify host to skip the '.X'
- values.host = values.host.substring(0,5);
- delete values.multifunction;
- }
-
- if (values.rombar) {
- delete values.rombar;
- } else {
- values.rombar = 0;
- }
-
- if (!values.romfile) {
- delete values.romfile;
- }
-
- ret[me.confid] = PVE.Parser.printPropertyString(values, 'host');
- return ret;
- },
-
- initComponent: function() {
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.column1 = [
- {
- xtype: 'pvePCISelector',
- fieldLabel: gettext('Device'),
- name: 'host',
- nodename: me.nodename,
- allowBlank: false,
- onLoadCallBack: function(store, records, success) {
- if (!success || !records.length) {
- return;
- }
-
- var first = records[0];
- if (first.data.iommugroup === -1) {
- // no iommu groups
- var warning = Ext.create('Ext.form.field.Display', {
- columnWidth: 1,
- padding: '0 0 10 0',
- value: 'No IOMMU detected, please activate it.' +
- 'See Documentation for further information.',
- userCls: 'pve-hint'
- });
- me.items.insert(0, warning);
- me.updateLayout(); // insert does not trigger that
- }
- },
- listeners: {
- change: function(pcisel, value) {
- if (!value) {
- return;
- }
- var pcidev = pcisel.getStore().getById(value);
- var mdevfield = me.down('field[name=mdev]');
- mdevfield.setDisabled(!pcidev || !pcidev.data.mdev);
- if (!pcidev) {
- return;
- }
- var id = pcidev.data.id.substring(0,5); // 00:00
- var iommu = pcidev.data.iommugroup;
- // try to find out if there are more devices
- // in that iommu group
- if (iommu !== -1) {
- var count = 0;
- pcisel.getStore().each(function(record) {
- if (record.data.iommugroup === iommu &&
- record.data.id.substring(0,5) !== id)
- {
- count++;
- return false;
- }
- });
- var warning = me.down('#iommuwarning');
- if (count && !warning) {
- warning = Ext.create('Ext.form.field.Display', {
- columnWidth: 1,
- padding: '0 0 10 0',
- itemId: 'iommuwarning',
- value: 'The selected Device is not in a seperate' +
- 'IOMMU group, make sure this is intended.',
- userCls: 'pve-hint'
- });
- me.items.insert(0, warning);
- me.updateLayout(); // insert does not trigger that
- } else if (!count && warning) {
- me.remove(warning);
- }
- }
- if (pcidev.data.mdev) {
- mdevfield.setPciID(value);
- }
- }
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('All Functions'),
- name: 'multifunction'
- }
- ];
-
- me.column2 = [
- {
- xtype: 'pveMDevSelector',
- name: 'mdev',
- disabled: true,
- fieldLabel: gettext('MDev Type'),
- nodename: me.nodename,
- listeners: {
- change: function(field, value) {
- var mf = me.down('field[name=multifunction]');
- if (!!value) {
- mf.setValue(false);
- }
- mf.setDisabled(!!value);
- }
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Primary GPU'),
- name: 'x-vga'
- }
- ];
-
- me.advancedColumn1 = [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: 'ROM-Bar',
- name: 'rombar'
- },
- {
- xtype: 'displayfield',
- submitValue: true,
- hidden: true,
- fieldLabel: 'ROM-File',
- name: 'romfile'
- }
- ];
-
- me.advancedColumn2 = [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: 'PCI-Express',
- name: 'pcie'
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.PCIEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmconfig: undefined,
-
- isAdd: true,
-
- subject: gettext('PCI Device'),
-
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.confid;
-
- var ipanel = Ext.create('PVE.qemu.PCIInputPanel', {
- confid: me.confid,
- pveSelNode: me.pveSelNode
- });
-
- Ext.apply(me, {
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response) {
- ipanel.setVMConfig(response.result.data);
- }
- });
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.qemu.SerialnputPanel', {
- extend: 'Proxmox.panel.InputPanel',
-
- autoComplete: false,
-
- setVMConfig: function(vmconfig) {
- var me = this, i;
- me.vmconfig = vmconfig;
-
- for (i = 0; i < 4; i++) {
- var port = 'serial' + i.toString();
- if (!me.vmconfig[port]) {
- me.down('field[name=serialid]').setValue(i);
- break;
- }
- }
-
- },
-
- onGetValues: function(values) {
- var me = this;
-
- var id = 'serial' + values.serialid;
- delete values.serialid;
- values[id] = 'socket';
- return values;
- },
-
- items: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'serialid',
- fieldLabel: gettext('Serial Port'),
- minValue: 0,
- maxValue: 3,
- allowBlank: false,
- validator: function(id) {
- if (!this.rendered) {
- return true;
- }
- var me = this.up('panel');
- if (me.vmconfig !== undefined && Ext.isDefined(me.vmconfig['serial' + id])) {
- return "This device is already in use.";
- }
- return true;
- }
- }
- ]
-});
-
-Ext.define('PVE.qemu.SerialEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmconfig: undefined,
-
- isAdd: true,
-
- subject: gettext('Serial Port'),
-
- initComponent : function() {
- var me = this;
-
- // for now create of (socket) serial port only
- me.isCreate = true;
-
- var ipanel = Ext.create('PVE.qemu.SerialnputPanel', {});
-
- Ext.apply(me, {
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- }
- });
- }
-});
-Ext.define('PVE.window.IPInfo', {
- extend: 'Ext.window.Window',
- width: 600,
- title: gettext('Guest Agent Network Information'),
- height: 300,
- layout: {
- type: 'fit'
- },
- modal: true,
- items: [
- {
- xtype: 'grid',
- emptyText: gettext('No network information'),
- columns: [
- {
- dataIndex: 'name',
- text: gettext('Name'),
- flex: 3
- },
- {
- dataIndex: 'hardware-address',
- text: gettext('MAC address'),
- width: 140
- },
- {
- dataIndex: 'ip-addresses',
- text: gettext('IP address'),
- align: 'right',
- flex: 4,
- renderer: function(val) {
- if (!Ext.isArray(val)) {
- return '';
- }
- var ips = [];
- val.forEach(function(ip) {
- var addr = ip['ip-address'];
- var pref = ip.prefix;
- if (addr && pref) {
- ips.push(addr + '/' + pref);
- }
- });
- return ips.join(' ');
- }
- }
- ]
- }
- ]
-});
-
-Ext.define('PVE.qemu.AgentIPView', {
- extend: 'Ext.container.Container',
- xtype: 'pveAgentIPView',
-
- layout: {
- type: 'hbox',
- align: 'top'
- },
-
- nics: [],
-
- items: [
- {
- xtype: 'box',
- html: ' IPs'
- },
- {
- xtype: 'container',
- flex: 1,
- layout: {
- type: 'vbox',
- align: 'right',
- pack: 'end'
- },
- items: [
- {
- xtype: 'label',
- flex: 1,
- itemId: 'ipBox',
- style: {
- 'text-align': 'right'
- }
- },
- {
- xtype: 'button',
- itemId: 'moreBtn',
- hidden: true,
- ui: 'default-toolbar',
- handler: function(btn) {
- var me = this.up('pveAgentIPView');
-
- var win = Ext.create('PVE.window.IPInfo');
- win.down('grid').getStore().setData(me.nics);
- win.show();
- },
- text: gettext('More')
- }
- ]
- }
- ],
-
- getDefaultIps: function(nics) {
- var me = this;
- var ips = [];
- nics.forEach(function(nic) {
- if (nic['hardware-address'] &&
- nic['hardware-address'] != '00:00:00:00:00:00') {
-
- var nic_ips = nic['ip-addresses'] || [];
- nic_ips.forEach(function(ip) {
- var p = ip['ip-address'];
- // show 2 ips at maximum
- if (ips.length < 2) {
- ips.push(p);
- }
- });
- }
- });
-
- return ips;
- },
-
- startIPStore: function(store, records, success) {
- var me = this;
- var agentRec = store.getById('agent');
- /*jslint confusion: true*/
- /* value is number and string */
- me.agent = (agentRec && agentRec.data.value === 1);
- me.running = (store.getById('status').data.value === 'running');
- /*jslint confusion: false*/
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- if (!caps.vms['VM.Monitor']) {
- var errorText = gettext("Requires '{0}' Privileges");
- me.updateStatus(false, Ext.String.format(errorText, 'VM.Monitor'));
- return;
- }
-
- if (me.agent && me.running && me.ipStore.isStopped) {
- me.ipStore.startUpdate();
- } else if (me.ipStore.isStopped) {
- me.updateStatus();
- }
- },
-
- updateStatus: function(unsuccessful, defaulttext) {
- var me = this;
- var text = defaulttext || gettext('No network information');
- var more = false;
- if (unsuccessful) {
- text = gettext('Guest Agent not running');
- } else if (me.agent && me.running) {
- if (Ext.isArray(me.nics) && me.nics.length) {
- more = true;
- var ips = me.getDefaultIps(me.nics);
- if (ips.length !== 0) {
- text = ips.join(' ');
- }
- } else if (me.nics && me.nics.error) {
- var msg = gettext('Cannot get info from Guest Agent Error: {0}');
- text = Ext.String.format(text, me.nics.error.desc);
- }
- } else if (me.agent) {
- text = gettext('Guest Agent not running');
- } else {
- text = gettext('No Guest Agent configured');
- }
-
- var ipBox = me.down('#ipBox');
- ipBox.update(text);
-
- var moreBtn = me.down('#moreBtn');
- moreBtn.setVisible(more);
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.rstore) {
- throw 'rstore not given';
- }
-
- if (!me.pveSelNode) {
- throw 'pveSelNode not given';
- }
-
- var nodename = me.pveSelNode.data.node;
- var vmid = me.pveSelNode.data.vmid;
-
- me.ipStore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 10000,
- storeid: 'pve-qemu-agent-' + vmid,
- method: 'POST',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + nodename + '/qemu/' + vmid + '/agent/network-get-interfaces'
- }
- });
-
- me.callParent();
-
- me.mon(me.ipStore, 'load', function(store, records, success) {
- if (records && records.length) {
- me.nics = records[0].data.result;
- } else {
- me.nics = undefined;
- }
- me.updateStatus(!success);
- });
-
- me.on('destroy', me.ipStore.stopUpdate);
-
- // if we already have info about the vm, use it immediately
- if (me.rstore.getCount()) {
- me.startIPStore(me.rstore, me.rstore.getData(), false);
- }
-
- // check if the guest agent is there on every statusstore load
- me.mon(me.rstore, 'load', me.startIPStore, me);
- }
-});
-Ext.define('PVE.qemu.CloudInit', {
- extend: 'Proxmox.grid.PendingObjectGrid',
- xtype: 'pveCiPanel',
-
- onlineHelp: 'qm_cloud_init',
-
- tbar: [
- {
- xtype: 'proxmoxButton',
- disabled: true,
- dangerous: true,
- confirmMsg: function(rec) {
- var me = this.up('grid');
- var warn = gettext('Are you sure you want to remove entry {0}');
-
- var entry = rec.data.key;
- var msg = Ext.String.format(warn, "'"
- + me.renderKey(entry, {}, rec) + "'");
-
- return msg;
- },
- enableFn: function(record) {
- var me = this.up('grid');
- var caps = Ext.state.Manager.get('GuiCap');
- if (me.rows[record.data.key].never_delete ||
- !caps.vms['VM.Config.Network']) {
- return false;
- }
-
- if (record.data.key === 'cipassword' && !record.data.value) {
- return false;
- }
- return true;
- },
- handler: function() {
- var me = this.up('grid');
- var records = me.getSelection();
- if (!records || !records.length) {
- return;
- }
-
- var id = records[0].data.key;
- var match = id.match(/^net(\d+)$/);
- if (match) {
- id = 'ipconfig' + match[1];
- }
-
- var params = {};
- params['delete'] = id;
- Proxmox.Utils.API2Request({
- url: me.baseurl + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- params: params,
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- callback: function() {
- me.reload();
- }
- });
- },
- text: gettext('Remove')
- },
- {
- xtype: 'proxmoxButton',
- disabled: true,
- handler: function() {
- var me = this.up('grid');
- me.run_editor();
- },
- text: gettext('Edit')
- },
- '-',
- {
- xtype: 'button',
- itemId: 'savebtn',
- text: gettext('Regenerate Image'),
- handler: function() {
- var me = this.up('grid');
- var eject_params = {};
- var insert_params = {};
- var disk = PVE.Parser.parseQemuDrive(me.ciDriveId, me.ciDrive);
- var storage = '';
- var stormatch = disk.file.match(/^([^\:]+)\:/);
- if (stormatch) {
- storage = stormatch[1];
- }
- eject_params[me.ciDriveId] = 'none,media=cdrom';
- insert_params[me.ciDriveId] = storage + ':cloudinit';
-
- var failure = function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- };
-
- Proxmox.Utils.API2Request({
- url: me.baseurl + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- params: eject_params,
- failure: failure,
- callback: function() {
- Proxmox.Utils.API2Request({
- url: me.baseurl + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- params: insert_params,
- failure: failure,
- callback: function() {
- me.reload();
- }
- });
- }
- });
- }
- }
- ],
-
- border: false,
-
- set_button_status: function(rstore, records, success) {
- if (!success || records.length < 1) {
- return;
- }
- var me = this;
- var found;
- records.forEach(function(record) {
- if (found) {
- return;
- }
- var id = record.data.key;
- var value = record.data.value;
- var ciregex = new RegExp("vm-" + me.pveSelNode.data.vmid + "-cloudinit");
- if (id.match(/^(ide|scsi|sata)\d+$/) && ciregex.test(value)) {
- found = id;
- me.ciDriveId = found;
- me.ciDrive = value;
- }
- });
-
- me.down('#savebtn').setDisabled(!found);
- me.setDisabled(!found);
- if (!found) {
- me.getView().mask(gettext('No CloudInit Drive found'), ['pve-static-mask']);
- } else {
- me.getView().unmask();
- }
- },
-
- renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var rowdef = rows[key] || {};
-
- var icon = "";
- if (rowdef.iconCls) {
- icon = ' ';
- }
- return icon + (rowdef.header || key);
- },
-
- listeners: {
- activate: function () {
- var me = this;
- me.rstore.startUpdate();
- },
- itemdblclick: function() {
- var me = this;
- me.run_editor();
- }
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
- var caps = Ext.state.Manager.get('GuiCap');
- me.baseurl = '/api2/extjs/nodes/' + nodename + '/qemu/' + vmid;
- me.url = me.baseurl + '/pending';
- me.editorConfig.url = me.baseurl + '/config';
- me.editorConfig.pveSelNode = me.pveSelNode;
-
- /*jslint confusion: true*/
- /* editor is string and object */
- me.rows = {
- ciuser: {
- header: gettext('User'),
- iconCls: 'fa fa-user',
- never_delete: true,
- defaultValue: '',
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('User'),
- items: [
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: true,
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('User'),
- name: 'ciuser'
- }
- ]
- } : undefined,
- renderer: function(value) {
- return value || Proxmox.Utils.defaultText;
- }
- },
- cipassword: {
- header: gettext('Password'),
- iconCls: 'fa fa-unlock',
- defaultValue: '',
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Password'),
- items: [
- {
- xtype: 'proxmoxtextfield',
- inputType: 'password',
- deleteEmpty: true,
- emptyText: Proxmox.Utils.noneText,
- fieldLabel: gettext('Password'),
- name: 'cipassword'
- }
- ]
- } : undefined,
- renderer: function(value) {
- return value || Proxmox.Utils.noneText;
- }
- },
- searchdomain: {
- header: gettext('DNS domain'),
- iconCls: 'fa fa-globe',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
- never_delete: true,
- defaultValue: gettext('use host settings')
- },
- nameserver: {
- header: gettext('DNS servers'),
- iconCls: 'fa fa-globe',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
- never_delete: true,
- defaultValue: gettext('use host settings')
- },
- sshkeys: {
- header: gettext('SSH public key'),
- iconCls: 'fa fa-key',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.qemu.SSHKeyEdit' : undefined,
- never_delete: true,
- renderer: function(value) {
- value = decodeURIComponent(value);
- var keys = value.split('\n');
- var text = [];
- keys.forEach(function(key) {
- if (key.length) {
- // First erase all quoted strings (eg. command="foo"
- var v = key.replace(/"(?:\\.|[^"\\])*"/g, '');
- // Now try to detect the comment:
- var res = v.match(/^\s*(\S+\s+)?(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)\s+\S+\s+(.*?)\s*$/, '');
- if (res) {
- key = Ext.String.htmlEncode(res[2]);
- if (res[1]) {
- key += ' (' + gettext('with options') + ') ';
- }
- text.push(key);
- return;
- }
- // Most likely invalid at this point, so just stick to
- // the old value.
- text.push(Ext.String.htmlEncode(key));
- }
- });
- if (text.length) {
- return text.join(' ');
- } else {
- return Proxmox.Utils.noneText;
- }
- },
- defaultValue: ''
- }
- };
- var i;
- var ipconfig_renderer = function(value, md, record, ri, ci, store, pending) {
- var id = record.data.key;
- var match = id.match(/^net(\d+)$/);
- var val = '';
- if (match) {
- val = me.getObjectValue('ipconfig'+match[1], '', pending);
- }
- return val;
- };
- for (i = 0; i < 32; i++) {
- // we want to show an entry for every network device
- // even if it is empty
- me.rows['net' + i.toString()] = {
- multiKey: ['ipconfig' + i.toString(), 'net' + i.toString()],
- header: gettext('IP Config') + ' (net' + i.toString() +')',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.qemu.IPConfigEdit' : undefined,
- iconCls: 'fa fa-exchange',
- renderer: ipconfig_renderer
- };
- me.rows['ipconfig' + i.toString()] = {
- visible: false
- };
- }
- /*jslint confusion: false*/
-
- PVE.Utils.forEachBus(['ide', 'scsi', 'sata'], function(type, id) {
- me.rows[type+id] = {
- visible: false
- };
- });
- me.callParent();
- me.mon(me.rstore, 'load', me.set_button_status, me);
- }
-});
-Ext.define('PVE.qemu.CIDriveInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveCIDriveInputPanel',
-
- insideWizard: false,
-
- vmconfig: {}, // used to select usused disks
-
- onGetValues: function(values) {
- var me = this;
-
- var drive = {};
- var params = {};
- drive.file = values.hdstorage + ":cloudinit";
- drive.format = values.diskformat;
- params[values.controller + values.deviceid] = PVE.Parser.printQemuDrive(drive);
- return params;
- },
-
- setNodename: function(nodename) {
- var me = this;
- me.down('#hdstorage').setNodename(nodename);
- me.down('#hdimage').setStorage(undefined, nodename);
- },
-
- setVMConfig: function(config) {
- var me = this;
- me.down('#drive').setVMConfig(config, 'cdrom');
- },
-
- initComponent : function() {
- var me = this;
-
- me.drive = {};
-
- me.items = [
- {
- xtype: 'pveControllerSelector',
- noVirtIO: true,
- itemId: 'drive',
- fieldLabel: gettext('CloudInit Drive'),
- name: 'drive'
- },
- {
- xtype: 'pveDiskStorageSelector',
- itemId: 'storselector',
- storageContent: 'images',
- nodename: me.nodename,
- hideSize: true
- }
- ];
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.CIDriveEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCIDriveEdit',
-
- isCreate: true,
- subject: gettext('CloudInit Drive'),
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.items = [{
- xtype: 'pveCIDriveInputPanel',
- itemId: 'cipanel',
- nodename: nodename
- }];
-
- me.callParent();
-
- me.load({
- success: function(response, opts) {
- me.down('#cipanel').setVMConfig(response.result.data);
- }
- });
- }
-});
-Ext.define('PVE.qemu.SSHKeyInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveQemuSSHKeyInputPanel',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
- if (values.sshkeys) {
- values.sshkeys.trim();
- }
- if (!values.sshkeys.length) {
- values = {};
- values['delete'] = 'sshkeys';
- return values;
- } else {
- values.sshkeys = encodeURIComponent(values.sshkeys);
- }
- return values;
- },
-
- items: [
- {
- xtype: 'textarea',
- itemId: 'sshkeys',
- name: 'sshkeys',
- height: 250
- },
- {
- xtype: 'filebutton',
- itemId: 'filebutton',
- name: 'file',
- text: gettext('Load SSH Key File'),
- fieldLabel: 'test',
- listeners: {
- change: function(btn, e, value) {
- var me = this.up('inputpanel');
- e = e.event;
- Ext.Array.each(e.target.files, function(file) {
- PVE.Utils.loadSSHKeyFromFile(file, function(res) {
- var keysField = me.down('#sshkeys');
- var old = keysField.getValue();
- keysField.setValue(old + res);
- });
- });
- btn.reset();
- }
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- me.callParent();
- if (!window.FileReader) {
- me.down('#filebutton').setVisible(false);
- }
-
- }
-});
-
-Ext.define('PVE.qemu.SSHKeyEdit', {
- extend: 'Proxmox.window.Edit',
-
- width: 800,
-
- initComponent : function() {
- var me = this;
-
- var ipanel = Ext.create('PVE.qemu.SSHKeyInputPanel');
-
- Ext.apply(me, {
- subject: gettext('SSH Keys'),
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.create) {
- me.load({
- success: function(response, options) {
- var data = response.result.data;
- if (data.sshkeys) {
- data.sshkeys = decodeURIComponent(data.sshkeys);
- ipanel.setValues(data);
- }
- }
- });
- }
- }
-});
-Ext.define('PVE.qemu.IPConfigPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveIPConfigPanel',
-
- insideWizard: false,
-
- vmconfig: {},
-
- onGetValues: function(values) {
- var me = this;
-
- if (values.ipv4mode !== 'static') {
- values.ip = values.ipv4mode;
- }
-
- if (values.ipv6mode !== 'static') {
- values.ip6 = values.ipv6mode;
- }
-
- var params = {};
-
- var cfg = PVE.Parser.printIPConfig(values);
- if (cfg === '') {
- params['delete'] = [me.confid];
- } else {
- params[me.confid] = cfg;
- }
- return params;
- },
-
- setVMConfig: function(config) {
- var me = this;
- me.vmconfig = config;
- },
-
- setIPConfig: function(confid, data) {
- var me = this;
-
- me.confid = confid;
-
- if (data.ip === 'dhcp') {
- data.ipv4mode = data.ip;
- data.ip = '';
- } else {
- data.ipv4mode = 'static';
- }
- if (data.ip6 === 'dhcp' || data.ip6 === 'auto') {
- data.ipv6mode = data.ip6;
- data.ip6 = '';
- } else {
- data.ipv6mode = 'static';
- }
-
- me.ipconfig = data;
- me.setValues(me.ipconfig);
- },
-
- initComponent : function() {
- var me = this;
-
- me.ipconfig = {};
-
- me.column1 = [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Network Device'),
- value: me.netid
- },
- {
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- border: false,
- margin: '0 0 5 0',
- items: [
- {
- xtype: 'label',
- text: gettext('IPv4') + ':'
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('Static'),
- name: 'ipv4mode',
- inputValue: 'static',
- checked: false,
- margin: '0 0 0 10',
- listeners: {
- change: function(cb, value) {
- me.down('field[name=ip]').setDisabled(!value);
- me.down('field[name=gw]').setDisabled(!value);
- }
- }
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('DHCP'),
- name: 'ipv4mode',
- inputValue: 'dhcp',
- checked: false,
- margin: '0 0 0 10'
- }
- ]
- },
- {
- xtype: 'textfield',
- name: 'ip',
- vtype: 'IPCIDRAddress',
- value: '',
- disabled: true,
- fieldLabel: gettext('IPv4/CIDR')
- },
- {
- xtype: 'textfield',
- name: 'gw',
- value: '',
- vtype: 'IPAddress',
- disabled: true,
- fieldLabel: gettext('Gateway') + ' (' + gettext('IPv4') +')'
- }
- ];
-
- me.column2 = [
- {
- xtype: 'displayfield'
- },
- {
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- border: false,
- margin: '0 0 5 0',
- items: [
- {
- xtype: 'label',
- text: gettext('IPv6') + ':'
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('Static'),
- name: 'ipv6mode',
- inputValue: 'static',
- checked: false,
- margin: '0 0 0 10',
- listeners: {
- change: function(cb, value) {
- me.down('field[name=ip6]').setDisabled(!value);
- me.down('field[name=gw6]').setDisabled(!value);
- }
- }
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('DHCP'),
- name: 'ipv6mode',
- inputValue: 'dhcp',
- checked: false,
- margin: '0 0 0 10'
- }
- ]
- },
- {
- xtype: 'textfield',
- name: 'ip6',
- value: '',
- vtype: 'IP6CIDRAddress',
- disabled: true,
- fieldLabel: gettext('IPv6/CIDR')
- },
- {
- xtype: 'textfield',
- name: 'gw6',
- vtype: 'IP6Address',
- value: '',
- disabled: true,
- fieldLabel: gettext('Gateway') + ' (' + gettext('IPv6') +')'
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.IPConfigEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
-
- initComponent : function() {
- /*jslint confusion: true */
-
- var me = this;
-
- // convert confid from netX to ipconfigX
- var match = me.confid.match(/^net(\d+)$/);
- if (match) {
- me.netid = me.confid;
- me.confid = 'ipconfig' + match[1];
- }
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = me.confid ? false : true;
-
- var ipanel = Ext.create('PVE.qemu.IPConfigPanel', {
- confid: me.confid,
- netid: me.netid,
- nodename: nodename
- });
-
- Ext.applyIf(me, {
- subject: gettext('Network Config'),
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- me.vmconfig = response.result.data;
- var ipconfig = {};
- var value = me.vmconfig[me.confid];
- if (value) {
- ipconfig = PVE.Parser.parseIPConfig(me.confid, value);
- if (!ipconfig) {
- Ext.Msg.alert(gettext('Error'), gettext('Unable to parse network configuration'));
- me.close();
- return;
- }
- }
- ipanel.setIPConfig(me.confid, ipconfig);
- ipanel.setVMConfig(me.vmconfig);
- }
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.qemu.SystemInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveQemuSystemPanel',
-
- onlineHelp: 'qm_system_settings',
-
- viewModel: {
- data: {
- efi: false,
- addefi: true
- },
-
- formulas: {
- efidisk: function(get) {
- return get('efi') && get('addefi');
- }
- }
- },
-
- onGetValues: function(values) {
- if (values.vga && values.vga.substr(0,6) === 'serial') {
- values['serial' + values.vga.substr(6,1)] = 'socket';
- }
-
- var efidrive = {};
- if (values.hdimage) {
- efidrive.file = values.hdimage;
- } else if (values.hdstorage) {
- efidrive.file = values.hdstorage + ":1";
- }
-
- if (values.diskformat) {
- efidrive.format = values.diskformat;
- }
-
- delete values.hdimage;
- delete values.hdstorage;
- delete values.diskformat;
-
- if (efidrive.file) {
- values.efidisk0 = PVE.Parser.printQemuDrive(efidrive);
- }
-
- return values;
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- scsihwChange: function(field, value) {
- var me = this;
- if (me.getView().insideWizard) {
- me.getViewModel().set('current.scsihw', value);
- }
- },
-
- biosChange: function(field, value) {
- var me = this;
- if (me.getView().insideWizard) {
- me.getViewModel().set('efi', value === 'ovmf');
- }
- },
-
- control: {
- 'pveScsiHwSelector': {
- change: 'scsihwChange'
- },
- 'pveQemuBiosSelector': {
- change: 'biosChange'
- }
- }
- },
-
- column1: [
- {
- xtype: 'proxmoxKVComboBox',
- value: '__default__',
- deleteEmpty: false,
- fieldLabel: gettext('Graphic card'),
- name: 'vga',
- comboItems: PVE.Utils.kvm_vga_driver_array()
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'agent',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Qemu Agent')
- }
- ],
-
- column2: [
- {
- xtype: 'pveScsiHwSelector',
- name: 'scsihw',
- value: '__default__',
- bind: {
- value: '{current.scsihw}'
- },
- fieldLabel: gettext('SCSI Controller')
- }
- ],
-
- advancedColumn1: [
- {
- xtype: 'pveQemuBiosSelector',
- name: 'bios',
- value: '__default__',
- fieldLabel: 'BIOS'
- },
- {
- xtype: 'proxmoxcheckbox',
- bind: {
- value: '{addefi}',
- hidden: '{!efi}',
- disabled: '{!efi}'
- },
- hidden: true,
- submitValue: false,
- disabled: true,
- fieldLabel: gettext('Add EFI Disk')
- },
- {
- xtype: 'pveDiskStorageSelector',
- name: 'efidisk0',
- storageContent: 'images',
- bind: {
- nodename: '{nodename}',
- hidden: '{!efi}',
- disabled: '{!efidisk}'
- },
- autoSelect: false,
- disabled: true,
- hidden: true,
- hideSize: true
- }
- ],
-
- advancedColumn2: [
- {
- xtype: 'proxmoxKVComboBox',
- name: 'machine',
- value: '__default__',
- fieldLabel: gettext('Machine'),
- comboItems: [
- ['__default__', PVE.Utils.render_qemu_machine('')],
- ['q35', 'q35']
- ]
- }
- ]
-
-});
-Ext.define('PVE.lxc.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveLxcSummary',
-
- scrollable: true,
- bodyPadding: 5,
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.workspace) {
- throw "no workspace specified";
- }
-
- if (!me.statusStore) {
- throw "no status storage specified";
- }
-
- var template = !!me.pveSelNode.data.template;
- var rstore = me.statusStore;
-
- var width = template ? 1 : 0.5;
- var items = [
- {
- xtype: template ? 'pveTemplateStatusView' : 'pveGuestStatusView',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: width
- },
- 'width >= 1900': {
- columnWidth: width / 2
- }
- },
- itemId: 'gueststatus',
- pveSelNode: me.pveSelNode,
- rstore: rstore
- },
- {
- xtype: 'pveNotesView',
- maxHeight: 320,
- itemId: 'notesview',
- pveSelNode: me.pveSelNode,
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: width
- },
- 'width >= 1900': {
- columnWidth: width / 2
- }
- }
- }
- ];
-
- var rrdstore;
- if (!template) {
-
- rrdstore = Ext.create('Proxmox.data.RRDStore', {
- rrdurl: "/api2/json/nodes/" + nodename + "/lxc/" + vmid + "/rrddata",
- model: 'pve-rrd-guest'
- });
-
- items.push(
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('CPU usage'),
- pveSelNode: me.pveSelNode,
- fields: ['cpu'],
- fieldTitles: [gettext('CPU usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Memory usage'),
- pveSelNode: me.pveSelNode,
- fields: ['maxmem', 'mem'],
- fieldTitles: [gettext('Total'), gettext('RAM usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Network traffic'),
- pveSelNode: me.pveSelNode,
- fields: ['netin','netout'],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Disk IO'),
- pveSelNode: me.pveSelNode,
- fields: ['diskread','diskwrite'],
- store: rrdstore
- }
- );
-
- }
-
- Ext.apply(me, {
- tbar: [ '->', { xtype: 'proxmoxRRDTypeSelector' } ],
- items: [
- {
- xtype: 'container',
- layout: {
- type: 'column'
- },
- defaults: {
- minHeight: 320,
- padding: 5,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- }
- },
- items: items
- }
- ]
- });
-
- me.callParent();
- if (!template) {
- rrdstore.startUpdate();
- me.on('destroy', rrdstore.stopUpdate);
- }
- }
-});
-Ext.define('PVE.lxc.NetworkInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveLxcNetworkInputPanel',
-
- insideWizard: false,
-
- onlineHelp: 'pct_container_network',
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
-
- var bridgesel = me.query("[isFormField][name=bridge]")[0];
- bridgesel.setNodename(nodename);
- },
-
- onGetValues: function(values) {
- var me = this;
-
- var id;
- if (me.isCreate) {
- id = values.id;
- delete values.id;
- } else {
- id = me.ifname;
- }
-
- if (!id) {
- return {};
- }
-
- var newdata = {};
-
- if (values.ipv6mode !== 'static') {
- values.ip6 = values.ipv6mode;
- }
- if (values.ipv4mode !== 'static') {
- values.ip = values.ipv4mode;
- }
- newdata[id] = PVE.Parser.printLxcNetwork(values);
- return newdata;
- },
-
- initComponent : function() {
- var me = this;
-
- var cdata = {};
-
- if (me.insideWizard) {
- me.ifname = 'net0';
- cdata.name = 'eth0';
- me.dataCache = {};
- }
- cdata.firewall = (me.insideWizard || me.isCreate);
-
- if (!me.dataCache) {
- throw "no dataCache specified";
- }
-
- if (!me.isCreate) {
- if (!me.ifname) {
- throw "no interface name specified";
- }
- if (!me.dataCache[me.ifname]) {
- throw "no such interface '" + me.ifname + "'";
- }
-
- cdata = PVE.Parser.parseLxcNetwork(me.dataCache[me.ifname]);
- }
-
- var i;
- for (i = 0; i < 10; i++) {
- if (me.isCreate && !me.dataCache['net'+i.toString()]) {
- me.ifname = 'net' + i.toString();
- break;
- }
- }
-
- var idselector = {
- xtype: 'hidden',
- name: 'id',
- value: me.ifname
- };
-
- me.column1 = [
- idselector,
- {
- xtype: 'textfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- emptyText: '(e.g., eth0)',
- allowBlank: false,
- value: cdata.name,
- validator: function(value) {
- var result = '';
- Ext.Object.each(me.dataCache, function(key, netstr) {
- if (!key.match(/^net\d+/) || key === me.ifname) {
- return; // continue
- }
- var net = PVE.Parser.parseLxcNetwork(netstr);
- if (net.name === value) {
- result = "interface name already in use";
- return false;
- }
- });
- if (result !== '') {
- return result;
- }
- // validator can return bool/string
- /*jslint confusion:true*/
- return true;
- }
- },
- {
- xtype: 'textfield',
- name: 'hwaddr',
- fieldLabel: gettext('MAC address'),
- vtype: 'MacAddress',
- value: cdata.hwaddr,
- allowBlank: true,
- emptyText: 'auto'
- },
- {
- xtype: 'PVE.form.BridgeSelector',
- name: 'bridge',
- nodename: me.nodename,
- fieldLabel: gettext('Bridge'),
- value: cdata.bridge,
- allowBlank: false
- },
- {
- xtype: 'pveVlanField',
- name: 'tag',
- value: cdata.tag
- },
- {
- xtype: 'numberfield',
- name: 'rate',
- fieldLabel: gettext('Rate limit') + ' (MB/s)',
- minValue: 0,
- maxValue: 10*1024,
- value: cdata.rate,
- emptyText: 'unlimited',
- allowBlank: true
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Firewall'),
- name: 'firewall',
- value: cdata.firewall
- }
- ];
-
- var dhcp4 = (cdata.ip === 'dhcp');
- if (dhcp4) {
- cdata.ip = '';
- cdata.gw = '';
- }
-
- var auto6 = (cdata.ip6 === 'auto');
- var dhcp6 = (cdata.ip6 === 'dhcp');
- if (auto6 || dhcp6) {
- cdata.ip6 = '';
- cdata.gw6 = '';
- }
-
- me.column2 = [
- {
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- border: false,
- margin: '0 0 5 0',
- items: [
- {
- xtype: 'label',
- text: 'IPv4:' // do not localize
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('Static'),
- name: 'ipv4mode',
- inputValue: 'static',
- checked: !dhcp4,
- margin: '0 0 0 10',
- listeners: {
- change: function(cb, value) {
- me.down('field[name=ip]').setDisabled(!value);
- me.down('field[name=gw]').setDisabled(!value);
- }
- }
- },
- {
- xtype: 'radiofield',
- boxLabel: 'DHCP', // do not localize
- name: 'ipv4mode',
- inputValue: 'dhcp',
- checked: dhcp4,
- margin: '0 0 0 10'
- }
- ]
- },
- {
- xtype: 'textfield',
- name: 'ip',
- vtype: 'IPCIDRAddress',
- value: cdata.ip,
- disabled: dhcp4,
- fieldLabel: 'IPv4/CIDR' // do not localize
- },
- {
- xtype: 'textfield',
- name: 'gw',
- value: cdata.gw,
- vtype: 'IPAddress',
- disabled: dhcp4,
- fieldLabel: gettext('Gateway') + ' (IPv4)',
- margin: '0 0 3 0' // override bottom margin to account for the menuseparator
- },
- {
- xtype: 'menuseparator',
- height: '3',
- margin: '0'
- },
- {
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- border: false,
- margin: '0 0 5 0',
- items: [
- {
- xtype: 'label',
- text: 'IPv6:' // do not localize
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('Static'),
- name: 'ipv6mode',
- inputValue: 'static',
- checked: !(auto6 || dhcp6),
- margin: '0 0 0 10',
- listeners: {
- change: function(cb, value) {
- me.down('field[name=ip6]').setDisabled(!value);
- me.down('field[name=gw6]').setDisabled(!value);
- }
- }
- },
- {
- xtype: 'radiofield',
- boxLabel: 'DHCP', // do not localize
- name: 'ipv6mode',
- inputValue: 'dhcp',
- checked: dhcp6,
- margin: '0 0 0 10'
- },
- {
- xtype: 'radiofield',
- boxLabel: 'SLAAC', // do not localize
- name: 'ipv6mode',
- inputValue: 'auto',
- checked: auto6,
- margin: '0 0 0 10'
- }
- ]
- },
- {
- xtype: 'textfield',
- name: 'ip6',
- value: cdata.ip6,
- vtype: 'IP6CIDRAddress',
- disabled: (dhcp6 || auto6),
- fieldLabel: 'IPv6/CIDR' // do not localize
- },
- {
- xtype: 'textfield',
- name: 'gw6',
- vtype: 'IP6Address',
- value: cdata.gw6,
- disabled: (dhcp6 || auto6),
- fieldLabel: gettext('Gateway') + ' (IPv6)'
- }
- ];
-
- me.callParent();
- }
-});
-
-
-Ext.define('PVE.lxc.NetworkEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
-
- initComponent : function() {
- var me = this;
-
- if (!me.dataCache) {
- throw "no dataCache specified";
- }
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var ipanel = Ext.create('PVE.lxc.NetworkInputPanel', {
- ifname: me.ifname,
- nodename: me.nodename,
- dataCache: me.dataCache,
- isCreate: me.isCreate
- });
-
- Ext.apply(me, {
- subject: gettext('Network Device') + ' (veth)',
- digest: me.dataCache.digest,
- items: [ ipanel ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.lxc.NetworkView', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pveLxcNetworkView',
-
- onlineHelp: 'pct_container_network',
-
- dataCache: {}, // used to store result of last load
-
- stateful: true,
- stateId: 'grid-lxc-network',
-
- load: function() {
- var me = this;
-
- Proxmox.Utils.setErrorMask(me, true);
-
- Proxmox.Utils.API2Request({
- url: me.url,
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, gettext('Error') + ': ' + response.htmlStatus);
- },
- success: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, false);
- var result = Ext.decode(response.responseText);
- var data = result.data || {};
- me.dataCache = data;
- var records = [];
- Ext.Object.each(data, function(key, value) {
- if (!key.match(/^net\d+/)) {
- return; // continue
- }
- var net = PVE.Parser.parseLxcNetwork(value);
- net.id = key;
- records.push(net);
- });
- me.store.loadData(records);
- me.down('button[name=addButton]').setDisabled((records.length >= 10));
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- me.url = '/nodes/' + nodename + '/lxc/' + vmid + '/config';
-
- var store = new Ext.data.Store({
- model: 'pve-lxc-network',
- sorters: [
- {
- property : 'id',
- direction: 'ASC'
- }
- ]
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- return !!caps.vms['VM.Config.Network'];
- },
- confirmMsg: function (rec) {
- return Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.id + "'");
- },
- handler: function(btn, event, rec) {
- Proxmox.Utils.API2Request({
- url: me.url,
- waitMsgTarget: me,
- method: 'PUT',
- params: { 'delete': rec.data.id, digest: me.dataCache.digest },
- callback: function() {
- me.load();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- if (!caps.vms['VM.Config.Network']) {
- return false;
- }
-
- var win = Ext.create('PVE.lxc.NetworkEdit', {
- url: me.url,
- nodename: nodename,
- dataCache: me.dataCache,
- ifname: rec.data.id
- });
- win.on('destroy', me.load, me);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- selModel: sm,
- disabled: true,
- enableFn: function(rec) {
- if (!caps.vms['VM.Config.Network']) {
- return false;
- }
- return true;
- },
- handler: run_editor
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- {
- text: gettext('Add'),
- name: 'addButton',
- disabled: !caps.vms['VM.Config.Network'],
- handler: function() {
- var win = Ext.create('PVE.lxc.NetworkEdit', {
- url: me.url,
- nodename: nodename,
- isCreate: true,
- dataCache: me.dataCache
- });
- win.on('destroy', me.load, me);
- win.show();
- }
- },
- remove_btn,
- edit_btn
- ],
- columns: [
- {
- header: 'ID',
- width: 50,
- dataIndex: 'id'
- },
- {
- header: gettext('Name'),
- width: 80,
- dataIndex: 'name'
- },
- {
- header: gettext('Bridge'),
- width: 80,
- dataIndex: 'bridge'
- },
- {
- header: gettext('Firewall'),
- width: 80,
- dataIndex: 'firewall',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- header: gettext('VLAN Tag'),
- width: 80,
- dataIndex: 'tag'
- },
- {
- header: gettext('MAC address'),
- width: 110,
- dataIndex: 'hwaddr'
- },
- {
- header: gettext('IP address'),
- width: 150,
- dataIndex: 'ip',
- renderer: function(value, metaData, rec) {
- if (rec.data.ip && rec.data.ip6) {
- return rec.data.ip + " " + rec.data.ip6;
- } else if (rec.data.ip6) {
- return rec.data.ip6;
- } else {
- return rec.data.ip;
- }
- }
- },
- {
- header: gettext('Gateway'),
- width: 150,
- dataIndex: 'gw',
- renderer: function(value, metaData, rec) {
- if (rec.data.gw && rec.data.gw6) {
- return rec.data.gw + " " + rec.data.gw6;
- } else if (rec.data.gw6) {
- return rec.data.gw6;
- } else {
- return rec.data.gw;
- }
- }
- }
- ],
- listeners: {
- activate: me.load,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-lxc-network', {
- extend: "Ext.data.Model",
- proxy: { type: 'memory' },
- fields: [ 'id', 'name', 'hwaddr', 'bridge',
- 'ip', 'gw', 'ip6', 'gw6', 'tag', 'firewall' ]
- });
-
-});
-
-/*jslint confusion: true */
-Ext.define('PVE.lxc.RessourceView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveLxcRessourceView'],
-
- onlineHelp: 'pct_configuration',
-
- renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
- var me = this;
- var rowdef = me.rows[key] || {};
-
- metaData.tdAttr = "valign=middle";
- if (rowdef.tdCls) {
- metaData.tdCls = rowdef.tdCls;
- }
- return rowdef.header || key;
- },
-
- initComponent : function() {
- var me = this;
- var i, confid;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
- var diskCap = caps.vms['VM.Config.Disk'];
-
- var mpeditor = caps.vms['VM.Config.Disk'] ? 'PVE.lxc.MountPointEdit' : undefined;
-
- var rows = {
- memory: {
- header: gettext('Memory'),
- editor: caps.vms['VM.Config.Memory'] ? 'PVE.lxc.MemoryEdit' : undefined,
- defaultValue: 512,
- tdCls: 'pve-itype-icon-memory',
- group: 1,
- renderer: function(value) {
- return Proxmox.Utils.format_size(value*1024*1024);
- }
- },
- swap: {
- header: gettext('Swap'),
- editor: caps.vms['VM.Config.Memory'] ? 'PVE.lxc.MemoryEdit' : undefined,
- defaultValue: 512,
- tdCls: 'pve-itype-icon-swap',
- group: 2,
- renderer: function(value) {
- return Proxmox.Utils.format_size(value*1024*1024);
- }
- },
- cores: {
- header: gettext('Cores'),
- editor: caps.vms['VM.Config.CPU'] ? 'PVE.lxc.CPUEdit' : undefined,
- defaultValue: '',
- tdCls: 'pve-itype-icon-processor',
- group: 3,
- renderer: function(value) {
- var cpulimit = me.getObjectValue('cpulimit');
- var cpuunits = me.getObjectValue('cpuunits');
- var res;
- if (value) {
- res = value;
- } else {
- res = gettext('unlimited');
- }
-
- if (cpulimit) {
- res += ' [cpulimit=' + cpulimit + ']';
- }
-
- if (cpuunits) {
- res += ' [cpuunits=' + cpuunits + ']';
- }
- return res;
- }
- },
- rootfs: {
- header: gettext('Root Disk'),
- defaultValue: Proxmox.Utils.noneText,
- editor: mpeditor,
- tdCls: 'pve-itype-icon-storage',
- group: 4
- },
- cpulimit: {
- visible: false
- },
- cpuunits: {
- visible: false
- },
- unprivileged: {
- visible: false
- }
- };
-
- PVE.Utils.forEachMP(function(bus, i) {
- confid = bus + i;
- var group = 5;
- var header;
- if (bus === 'mp') {
- header = gettext('Mount Point') + ' (' + confid + ')';
- } else {
- header = gettext('Unused Disk') + ' ' + i;
- group += 1;
- }
- rows[confid] = {
- group: group,
- order: i,
- tdCls: 'pve-itype-icon-storage',
- editor: mpeditor,
- header: header
- };
- }, true);
-
- var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
-
- me.selModel = Ext.create('Ext.selection.RowModel', {});
-
- var run_resize = function() {
- var rec = me.selModel.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.window.MPResize', {
- disk: rec.data.key,
- nodename: nodename,
- vmid: vmid
- });
-
- win.show();
- };
-
- var run_remove = function(b, e, rec) {
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/' + baseurl,
- waitMsgTarget: me,
- method: 'PUT',
- params: {
- 'delete': rec.data.key
- },
- failure: function (response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- var run_move = function(b, e, rec) {
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.window.HDMove', {
- disk: rec.data.key,
- nodename: nodename,
- vmid: vmid,
- type: 'lxc'
- });
-
- win.show();
-
- win.on('destroy', me.reload, me);
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- selModel: me.selModel,
- disabled: true,
- enableFn: function(rec) {
- if (!rec) {
- return false;
- }
- var rowdef = rows[rec.data.key];
- return !!rowdef.editor;
- },
- handler: function() { me.run_editor(); }
- });
-
- var resize_btn = new Proxmox.button.Button({
- text: gettext('Resize disk'),
- selModel: me.selModel,
- disabled: true,
- handler: run_resize
- });
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- selModel: me.selModel,
- disabled: true,
- dangerous: true,
- confirmMsg: function(rec) {
- var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + me.renderKey(rec.data.key, {}, rec) + "'");
- if (rec.data.key.match(/^unused\d+$/)) {
- msg += " " + gettext('This will permanently erase all data.');
- }
-
- return msg;
- },
- handler: run_remove
- });
-
- var move_btn = new Proxmox.button.Button({
- text: gettext('Move Volume'),
- selModel: me.selModel,
- disabled: true,
- dangerous: true,
- handler: run_move
- });
-
- var set_button_status = function() {
- var rec = me.selModel.getSelection()[0];
-
- if (!rec) {
- edit_btn.disable();
- remove_btn.disable();
- resize_btn.disable();
- return;
- }
- var key = rec.data.key;
- var value = rec.data.value;
- var rowdef = rows[key];
-
- var isDisk = (rowdef.tdCls == 'pve-itype-icon-storage');
-
- var noedit = rec.data['delete'] || !rowdef.editor;
- if (!noedit && Proxmox.UserName !== 'root@pam' && key.match(/^mp\d+$/)) {
- var mp = PVE.Parser.parseLxcMountPoint(value);
- if (mp.type !== 'volume') {
- noedit = true;
- }
- }
- edit_btn.setDisabled(noedit);
-
- remove_btn.setDisabled(!isDisk || rec.data.key === 'rootfs' || !diskCap);
- resize_btn.setDisabled(!isDisk || !diskCap);
- move_btn.setDisabled(!isDisk || !diskCap);
-
- };
-
- var sorterFn = function(rec1, rec2) {
- var v1 = rec1.data.key;
- var v2 = rec2.data.key;
- var g1 = rows[v1].group || 0;
- var g2 = rows[v2].group || 0;
- var order1 = rows[v1].order || 0;
- var order2 = rows[v2].order || 0;
-
- if ((g1 - g2) !== 0) {
- return g1 - g2;
- }
-
- if ((order1 - order2) !== 0) {
- return order1 - order2;
- }
-
- if (v1 > v2) {
- return 1;
- } else if (v1 < v2) {
- return -1;
- } else {
- return 0;
- }
- };
-
- Ext.apply(me, {
- url: '/api2/json/' + baseurl,
- selModel: me.selModel,
- interval: 2000,
- cwidth1: 170,
- tbar: [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Mount Point'),
- iconCls: 'pve-itype-icon-storage',
- disabled: !caps.vms['VM.Config.Disk'],
- handler: function() {
- var win = Ext.create('PVE.lxc.MountPointEdit', {
- url: '/api2/extjs/' + baseurl,
- unprivileged: me.getObjectValue('unprivileged'),
- pveSelNode: me.pveSelNode
- });
- win.show();
- }
- }
- ]
- })
- },
- edit_btn,
- remove_btn,
- resize_btn,
- move_btn
- ],
- rows: rows,
- sorterFn: sorterFn,
- editorConfig: {
- pveSelNode: me.pveSelNode,
- url: '/api2/extjs/' + baseurl
- },
- listeners: {
- itemdblclick: me.run_editor,
- selectionchange: set_button_status
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
-
- Ext.apply(me.editorConfig, { unprivileged: me.getObjectValue('unprivileged') });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.lxc.FeaturesInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveLxcFeaturesInputPanel',
-
- // used to save the mounts fstypes until sending
- mounts: [],
-
- fstypes: ['nfs', 'cifs'],
-
- viewModel: {
- parent: null,
- data: {
- unprivileged: false
- },
- formulas: {
- privilegedOnly: function(get) {
- return (get('unprivileged') ? gettext('privileged only') : '');
- },
- unprivilegedOnly: function(get) {
- return (!get('unprivileged') ? gettext('unprivileged only') : '');
- }
- }
- },
-
- items: [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('keyctl'),
- name: 'keyctl',
- bind: {
- disabled: '{!unprivileged}',
- boxLabel: '{unprivilegedOnly}'
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Nesting'),
- name: 'nesting'
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'nfs',
- fieldLabel: 'NFS',
- bind: {
- disabled: '{unprivileged}',
- boxLabel: '{privilegedOnly}'
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'cifs',
- fieldLabel: 'CIFS',
- bind: {
- disabled: '{unprivileged}',
- boxLabel: '{privilegedOnly}'
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'fuse',
- fieldLabel: 'FUSE'
- }
- ],
-
- onGetValues: function(values) {
- var me = this;
- var mounts = me.mounts;
- me.fstypes.forEach(function(fs) {
- if (values[fs]) {
- mounts.push(fs);
- }
- delete values[fs];
- });
-
- if (mounts.length) {
- values.mount = mounts.join(';');
- }
-
- var featuresstring = PVE.Parser.printPropertyString(values, undefined);
- if (featuresstring == '') {
- return { 'delete': 'features' };
- }
- return { features: featuresstring };
- },
-
- setValues: function(values) {
- var me = this;
-
- me.viewModel.set({ unprivileged: values.unprivileged });
-
- if (values.features) {
- var res = PVE.Parser.parsePropertyString(values.features);
- me.mounts = [];
- if (res.mount) {
- res.mount.split(/[; ]/).forEach(function(item) {
- if (me.fstypes.indexOf(item) === -1) {
- me.mounts.push(item);
- } else {
- res[item] = 1;
- }
- });
- }
- this.callParent([res]);
- }
- }
-});
-
-Ext.define('PVE.lxc.FeaturesEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveLxcFeaturesEdit',
-
- subject: gettext('Features'),
-
- items: [{
- xtype: 'pveLxcFeaturesInputPanel'
- }],
-
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- me.load();
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.lxc.Options', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveLxcOptions'],
-
- onlineHelp: 'pct_options',
-
- initComponent : function() {
- var me = this;
- var i;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var rows = {
- onboot: {
- header: gettext('Start at boot'),
- defaultValue: '',
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Start at boot'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'onboot',
- uncheckedValue: 0,
- defaultValue: 0,
- fieldLabel: gettext('Start at boot')
- }
- } : undefined
- },
- startup: {
- header: gettext('Start/Shutdown order'),
- defaultValue: '',
- renderer: PVE.Utils.render_kvm_startup,
- editor: caps.vms['VM.Config.Options'] && caps.nodes['Sys.Modify'] ?
- {
- xtype: 'pveWindowStartupEdit',
- onlineHelp: 'pct_startup_and_shutdown'
- } : undefined
- },
- ostype: {
- header: gettext('OS Type'),
- defaultValue: Proxmox.Utils.unknownText
- },
- arch: {
- header: gettext('Architecture'),
- defaultValue: Proxmox.Utils.unknownText
- },
- console: {
- header: '/dev/console',
- defaultValue: 1,
- renderer: Proxmox.Utils.format_enabled_toggle,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: '/dev/console',
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'console',
- uncheckedValue: 0,
- defaultValue: 1,
- deleteDefaultValue: true,
- checked: true,
- fieldLabel: '/dev/console'
- }
- } : undefined
- },
- tty: {
- header: gettext('TTY count'),
- defaultValue: 2,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('TTY count'),
- items: {
- xtype: 'proxmoxintegerfield',
- name: 'tty',
- minValue: 0,
- maxValue: 6,
- value: 2,
- fieldLabel: gettext('TTY count'),
- emptyText: gettext('Default'),
- deleteEmpty: true
- }
- } : undefined
- },
- cmode: {
- header: gettext('Console mode'),
- defaultValue: 'tty',
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Console mode'),
- items: {
- xtype: 'proxmoxKVComboBox',
- name: 'cmode',
- deleteEmpty: true,
- value: '__default__',
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText + " (tty)"],
- ['tty', "/dev/tty[X]"],
- ['console', "/dev/console"],
- ['shell', "shell"]
- ],
- fieldLabel: gettext('Console mode')
- }
- } : undefined
- },
- protection: {
- header: gettext('Protection'),
- defaultValue: false,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Protection'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'protection',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- unprivileged: {
- header: gettext('Unprivileged container'),
- renderer: Proxmox.Utils.format_boolean,
- defaultValue: 0
- },
- features: {
- header: gettext('Features'),
- defaultValue: Proxmox.Utils.noneText,
- editor: Proxmox.UserName === 'root@pam' ?
- 'PVE.lxc.FeaturesEdit' : undefined
- },
- hookscript: {
- header: gettext('Hookscript')
- }
- };
-
- var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- var rowdef = rows[rec.data.key];
- return !!rowdef.editor;
- },
- handler: function() { me.run_editor(); }
- });
-
- Ext.apply(me, {
- url: "/api2/json/" + baseurl,
- selModel: sm,
- interval: 5000,
- tbar: [ edit_btn ],
- rows: rows,
- editorConfig: {
- url: '/api2/extjs/' + baseurl
- },
- listeners: {
- itemdblclick: me.run_editor
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
-
- }
-});
-
-Ext.define('PVE.lxc.DNSInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveLxcDNSInputPanel',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- var deletes = [];
- if (!values.searchdomain && !me.insideWizard) {
- deletes.push('searchdomain');
- }
-
- if (values.nameserver) {
- var list = values.nameserver.split(/[\ \,\;]+/);
- values.nameserver = list.join(' ');
- } else if(!me.insideWizard) {
- deletes.push('nameserver');
- }
-
- if (deletes.length) {
- values['delete'] = deletes.join(',');
- }
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
-
- var items = [
- {
- xtype: 'proxmoxtextfield',
- name: 'searchdomain',
- skipEmptyText: true,
- fieldLabel: gettext('DNS domain'),
- emptyText: gettext('use host settings'),
- allowBlank: true
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('DNS servers'),
- vtype: 'IP64AddressList',
- allowBlank: true,
- emptyText: gettext('use host settings'),
- name: 'nameserver',
- itemId: 'nameserver'
- }
- ];
-
- if (me.insideWizard) {
- me.column1 = items;
- } else {
- me.items = items;
- }
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.lxc.DNSEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- var ipanel = Ext.create('PVE.lxc.DNSInputPanel');
-
- Ext.apply(me, {
- subject: gettext('Resources'),
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
-
- if (values.nameserver) {
- values.nameserver.replace(/[,;]/, ' ');
- values.nameserver.replace(/^\s+/, '');
- }
-
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-
-/*jslint confusion: true */
-Ext.define('PVE.lxc.DNS', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveLxcDNS'],
-
- onlineHelp: 'pct_container_network',
-
- initComponent : function() {
- var me = this;
- var i;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var rows = {
- hostname: {
- required: true,
- defaultValue: me.pveSelNode.data.name,
- header: gettext('Hostname'),
- editor: caps.vms['VM.Config.Network'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Hostname'),
- items: {
- xtype: 'inputpanel',
- items:{
- fieldLabel: gettext('Hostname'),
- xtype: 'textfield',
- name: 'hostname',
- vtype: 'DnsName',
- allowBlank: true,
- emptyText: 'CT' + vmid.toString()
- },
- onGetValues: function(values) {
- var params = values;
- if (values.hostname === undefined ||
- values.hostname === null ||
- values.hostname === '') {
- params = { hostname: 'CT'+vmid.toString()};
- }
- return params;
- }
- }
- } : undefined
- },
- searchdomain: {
- header: gettext('DNS domain'),
- defaultValue: '',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
- renderer: function(value) {
- return value || gettext('use host settings');
- }
- },
- nameserver: {
- header: gettext('DNS server'),
- defaultValue: '',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
- renderer: function(value) {
- return value || gettext('use host settings');
- }
- }
- };
-
- var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
-
- var reload = function() {
- me.rstore.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var rowdef = rows[rec.data.key];
- if (!rowdef.editor) {
- return;
- }
-
- var win;
- if (Ext.isString(rowdef.editor)) {
- win = Ext.create(rowdef.editor, {
- pveSelNode: me.pveSelNode,
- confid: rec.data.key,
- url: '/api2/extjs/' + baseurl
- });
- } else {
- var config = Ext.apply({
- pveSelNode: me.pveSelNode,
- confid: rec.data.key,
- url: '/api2/extjs/' + baseurl
- }, rowdef.editor);
- win = Ext.createWidget(rowdef.editor.xtype, config);
- win.load();
- }
- //win.load();
- win.show();
- win.on('destroy', reload);
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- var rowdef = rows[rec.data.key];
- return !!rowdef.editor;
- },
- handler: run_editor
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- edit_btn.disable();
- return;
- }
- var rowdef = rows[rec.data.key];
- edit_btn.setDisabled(!rowdef.editor);
- };
-
- Ext.apply(me, {
- url: "/api2/json/nodes/" + nodename + "/lxc/" + vmid + "/config",
- selModel: sm,
- cwidth1: 150,
- run_editor: run_editor,
- tbar: [ edit_btn ],
- rows: rows,
- listeners: {
- itemdblclick: run_editor,
- selectionchange: set_button_status,
- activate: reload
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.lxc.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.lxc.Config',
-
- onlineHelp: 'chapter_pct',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var template = !!me.pveSelNode.data.template;
-
- var running = !!me.pveSelNode.data.uptime;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var base_url = '/nodes/' + nodename + '/lxc/' + vmid;
-
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: '/api2/json' + base_url + '/status/current',
- interval: 1000
- });
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: base_url + "/status/" + cmd,
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- var startBtn = Ext.create('Ext.Button', {
- text: gettext('Start'),
- disabled: !caps.vms['VM.PowerMgmt'] || running,
- hidden: template,
- handler: function() {
- vm_command('start');
- },
- iconCls: 'fa fa-play'
- });
-
- var stopBtn = Ext.create('Ext.menu.Item',{
- text: gettext('Stop'),
- disabled: !caps.vms['VM.PowerMgmt'],
- confirmMsg: Proxmox.Utils.format_task_description('vzstop', vmid),
- tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'CT'),
- dangerous: true,
- handler: function() {
- vm_command("stop");
- },
- iconCls: 'fa fa-stop'
- });
-
- var shutdownBtn = Ext.create('PVE.button.Split', {
- text: gettext('Shutdown'),
- disabled: !caps.vms['VM.PowerMgmt'] || !running,
- hidden: template,
- confirmMsg: Proxmox.Utils.format_task_description('vzshutdown', vmid),
- handler: function() {
- vm_command('shutdown');
- },
- menu: {
- items:[stopBtn]
- },
- iconCls: 'fa fa-power-off'
- });
-
- var migrateBtn = Ext.create('Ext.Button', {
- text: gettext('Migrate'),
- disabled: !caps.vms['VM.Migrate'],
- hidden: PVE.data.ResourceStore.getNodes().length < 2,
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: 'lxc',
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- },
- iconCls: 'fa fa-send-o'
- });
-
- var moreBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('More'),
- menu: { items: [
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- hidden: caps.vms['VM.Clone'] ? false : true,
- handler: function() {
- PVE.window.Clone.wrap(nodename, vmid, template, 'lxc');
- }
- },
- {
- text: gettext('Convert to template'),
- disabled: template,
- xtype: 'pveMenuItem',
- iconCls: 'fa fa-fw fa-file-o',
- hidden: caps.vms['VM.Allocate'] ? false : true,
- confirmMsg: Proxmox.Utils.format_task_description('vztemplate', vmid),
- handler: function() {
- Proxmox.Utils.API2Request({
- url: base_url + '/template',
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- }
- },
- {
- iconCls: 'fa fa-heartbeat ',
- hidden: !caps.nodes['Sys.Console'],
- text: gettext('Manage HA'),
- handler: function() {
- var ha = me.pveSelNode.data.hastate;
- Ext.create('PVE.ha.VMResourceEdit', {
- vmid: vmid,
- guestType: 'ct',
- isCreate: (!ha || ha === 'unmanaged')
- }).show();
- }
- },
- {
- text: gettext('Remove'),
- disabled: !caps.vms['VM.Allocate'],
- itemId: 'removeBtn',
- handler: function() {
- Ext.create('PVE.window.SafeDestroy', {
- url: base_url,
- item: { type: 'CT', id: vmid }
- }).show();
- },
- iconCls: 'fa fa-trash-o'
- }
- ]}
- });
-
- var vm = me.pveSelNode.data;
-
- var consoleBtn = Ext.create('PVE.button.ConsoleButton', {
- disabled: !caps.vms['VM.Console'],
- consoleType: 'lxc',
- consoleName: vm.name,
- hidden: template,
- nodename: nodename,
- vmid: vmid
- });
-
- var statusTxt = Ext.create('Ext.toolbar.TextItem', {
- data: {
- lock: undefined
- },
- tpl: [
- '',
- ' ({lock})',
- ' '
- ]
- });
-
-
- Ext.apply(me, {
- title: Ext.String.format(gettext("Container {0} on node '{1}'"), vm.text, nodename),
- hstateid: 'lxctab',
- tbarSpacing: false,
- tbar: [ statusTxt, '->', startBtn, shutdownBtn, migrateBtn, consoleBtn, moreBtn ],
- defaults: { statusStore: me.statusStore },
- items: [
- {
- title: gettext('Summary'),
- xtype: 'pveLxcSummary',
- iconCls: 'fa fa-book',
- itemId: 'summary'
- }
- ]
- });
-
- if (caps.vms['VM.Console'] && !template) {
- me.items.push(
- {
- title: gettext('Console'),
- itemId: 'consolejs',
- iconCls: 'fa fa-terminal',
- xtype: 'pveNoVncConsole',
- vmid: vmid,
- consoleType: 'lxc',
- xtermjs: true,
- nodename: nodename
- }
- );
- }
-
- me.items.push(
- {
- title: gettext('Resources'),
- itemId: 'resources',
- expandedOnInit: true,
- iconCls: 'fa fa-cube',
- xtype: 'pveLxcRessourceView'
- },
- {
- title: gettext('Network'),
- iconCls: 'fa fa-exchange',
- itemId: 'network',
- xtype: 'pveLxcNetworkView'
- },
- {
- title: gettext('DNS'),
- iconCls: 'fa fa-globe',
- itemId: 'dns',
- xtype: 'pveLxcDNS'
- },
- {
- title: gettext('Options'),
- itemId: 'options',
- iconCls: 'fa fa-gear',
- xtype: 'pveLxcOptions'
- },
- {
- title: gettext('Task History'),
- itemId: 'tasks',
- iconCls: 'fa fa-list',
- xtype: 'proxmoxNodeTasks',
- nodename: nodename,
- vmidFilter: vmid
- }
- );
-
- if (caps.vms['VM.Backup']) {
- me.items.push({
- title: gettext('Backup'),
- iconCls: 'fa fa-floppy-o',
- xtype: 'pveBackupView',
- itemId: 'backup'
- },
- {
- title: gettext('Replication'),
- iconCls: 'fa fa-retweet',
- xtype: 'pveReplicaView',
- itemId: 'replication'
- });
- }
-
- if ((caps.vms['VM.Snapshot'] || caps.vms['VM.Snapshot.Rollback']) && !template) {
- me.items.push({
- title: gettext('Snapshots'),
- iconCls: 'fa fa-history',
- xtype: 'pveLxcSnapshotTree',
- itemId: 'snapshot'
- });
- }
-
- if (caps.vms['VM.Console']) {
- me.items.push(
- {
- xtype: 'pveFirewallRules',
- title: gettext('Firewall'),
- iconCls: 'fa fa-shield',
- allow_iface: true,
- base_url: base_url + '/firewall/rules',
- list_refs_url: base_url + '/firewall/refs',
- itemId: 'firewall'
- },
- {
- xtype: 'pveFirewallOptions',
- groups: ['firewall'],
- iconCls: 'fa fa-gear',
- onlineHelp: 'pve_firewall_vm_container_configuration',
- title: gettext('Options'),
- base_url: base_url + '/firewall/options',
- fwtype: 'vm',
- itemId: 'firewall-options'
- },
- {
- xtype: 'pveFirewallAliases',
- title: gettext('Alias'),
- groups: ['firewall'],
- iconCls: 'fa fa-external-link',
- base_url: base_url + '/firewall/aliases',
- itemId: 'firewall-aliases'
- },
- {
- xtype: 'pveIPSet',
- title: gettext('IPSet'),
- groups: ['firewall'],
- iconCls: 'fa fa-list-ol',
- base_url: base_url + '/firewall/ipset',
- list_refs_url: base_url + '/firewall/refs',
- itemId: 'firewall-ipset'
- },
- {
- title: gettext('Log'),
- groups: ['firewall'],
- iconCls: 'fa fa-list',
- onlineHelp: 'chapter_pve_firewall',
- itemId: 'firewall-fwlog',
- xtype: 'proxmoxLogView',
- url: '/api2/extjs' + base_url + '/firewall/log'
- }
- );
- }
-
- if (caps.vms['Permissions.Modify']) {
- me.items.push({
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- itemId: 'permissions',
- iconCls: 'fa fa-unlock',
- path: '/vms/' + vmid
- });
- }
-
- me.callParent();
-
- me.mon(me.statusStore, 'load', function(s, records, success) {
- var status;
- var lock;
- if (!success) {
- status = 'unknown';
- } else {
- var rec = s.data.get('status');
- status = rec ? rec.data.value : 'unknown';
- rec = s.data.get('template');
- template = rec.data.value || false;
- rec = s.data.get('lock');
- lock = rec ? rec.data.value : undefined;
- }
-
- statusTxt.update({ lock: lock });
-
- startBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 'running' || template);
- shutdownBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status !== 'running');
- stopBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 'stopped');
- me.down('#removeBtn').setDisabled(!caps.vms['VM.Allocate'] || status !== 'stopped');
- consoleBtn.setDisabled(template);
- });
-
- me.on('afterrender', function() {
- me.statusStore.startUpdate();
- });
-
- me.on('destroy', function() {
- me.statusStore.stopUpdate();
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.lxc.CreateWizard', {
- extend: 'PVE.window.Wizard',
- mixins: ['Proxmox.Mixin.CBind'],
-
- viewModel: {
- data: {
- nodename: '',
- storage: '',
- unprivileged: true
- }
- },
-
- cbindData: {
- nodename: undefined
- },
-
- subject: gettext('LXC Container'),
-
- items: [
- {
- xtype: 'inputpanel',
- title: gettext('General'),
- onlineHelp: 'pct_general',
- column1: [
- {
- xtype: 'pveNodeSelector',
- name: 'nodename',
- cbind: {
- selectCurNode: '{!nodename}',
- preferredValue: '{nodename}'
- },
- bind: {
- value: '{nodename}'
- },
- fieldLabel: gettext('Node'),
- allowBlank: false,
- onlineValidator: true
- },
- {
- xtype: 'pveGuestIDSelector',
- name: 'vmid', // backend only knows vmid
- guestType: 'lxc',
- value: '',
- loadNextFreeID: true,
- validateExists: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'hostname',
- vtype: 'DnsName',
- value: '',
- fieldLabel: gettext('Hostname'),
- skipEmptyText: true,
- allowBlank: true
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'unprivileged',
- value: true,
- bind: {
- value: '{unprivileged}'
- },
- fieldLabel: gettext('Unprivileged container')
- }
- ],
- column2: [
- {
- xtype: 'pvePoolSelector',
- fieldLabel: gettext('Resource Pool'),
- name: 'pool',
- value: '',
- allowBlank: true
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- name: 'password',
- value: '',
- fieldLabel: gettext('Password'),
- allowBlank: false,
- minLength: 5,
- change: function(f, value) {
- if (f.rendered) {
- f.up().down('field[name=confirmpw]').validate();
- }
- }
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- name: 'confirmpw',
- value: '',
- fieldLabel: gettext('Confirm password'),
- allowBlank: true,
- submitValue: false,
- validator: function(value) {
- var pw = this.up().down('field[name=password]').getValue();
- if (pw !== value) {
- return "Passwords do not match!";
- }
- return true;
- }
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'ssh-public-keys',
- value: '',
- fieldLabel: gettext('SSH public key'),
- allowBlank: true,
- validator: function(value) {
- var pwfield = this.up().down('field[name=password]');
- if (value.length) {
- var key = PVE.Parser.parseSSHKey(value);
- if (!key) {
- return "Failed to recognize ssh key";
- }
- pwfield.allowBlank = true;
- } else {
- pwfield.allowBlank = false;
- }
- pwfield.validate();
- return true;
- },
- afterRender: function() {
- if (!window.FileReader) {
- // No FileReader support in this browser
- return;
- }
- var cancel = function(ev) {
- ev = ev.event;
- if (ev.preventDefault) {
- ev.preventDefault();
- }
- };
- var field = this;
- field.inputEl.on('dragover', cancel);
- field.inputEl.on('dragenter', cancel);
- field.inputEl.on('drop', function(ev) {
- ev = ev.event;
- if (ev.preventDefault) {
- ev.preventDefault();
- }
- var files = ev.dataTransfer.files;
- PVE.Utils.loadSSHKeyFromFile(files[0], function(v) {
- field.setValue(v);
- });
- });
- }
- },
- {
- xtype: 'filebutton',
- name: 'file',
- hidden: !window.FileReader,
- text: gettext('Load SSH Key File'),
- listeners: {
- change: function(btn, e, value) {
- e = e.event;
- var field = this.up().down('proxmoxtextfield[name=ssh-public-keys]');
- PVE.Utils.loadSSHKeyFromFile(e.target.files[0], function(v) {
- field.setValue(v);
- });
- btn.reset();
- }
- }
- }
- ]
- },
- {
- xtype: 'inputpanel',
- title: gettext('Template'),
- onlineHelp: 'pct_container_images',
- column1: [
- {
- xtype: 'pveStorageSelector',
- name: 'tmplstorage',
- fieldLabel: gettext('Storage'),
- storageContent: 'vztmpl',
- autoSelect: true,
- allowBlank: false,
- bind: {
- value: '{storage}',
- nodename: '{nodename}'
- }
- },
- {
- xtype: 'pveFileSelector',
- name: 'ostemplate',
- storageContent: 'vztmpl',
- fieldLabel: gettext('Template'),
- bind: {
- storage: '{storage}',
- nodename: '{nodename}'
- },
- allowBlank: false
- }
- ]
- },
- {
- xtype: 'pveLxcMountPointInputPanel',
- title: gettext('Root Disk'),
- insideWizard: true,
- isCreate: true,
- unused: false,
- bind: {
- nodename: '{nodename}',
- unprivileged: '{unprivileged}'
- },
- confid: 'rootfs'
- },
- {
- xtype: 'pveLxcCPUInputPanel',
- title: gettext('CPU'),
- insideWizard: true
- },
- {
- xtype: 'pveLxcMemoryInputPanel',
- title: gettext('Memory'),
- insideWizard: true
- },
- {
- xtype: 'pveLxcNetworkInputPanel',
- title: gettext('Network'),
- insideWizard: true,
- bind: {
- nodename: '{nodename}'
- },
- isCreate: true
- },
- {
- xtype: 'pveLxcDNSInputPanel',
- title: gettext('DNS'),
- insideWizard: true
- },
- {
- title: gettext('Confirm'),
- layout: 'fit',
- items: [
- {
- xtype: 'grid',
- store: {
- model: 'KeyValue',
- sorters: [{
- property : 'key',
- direction: 'ASC'
- }]
- },
- columns: [
- {header: 'Key', width: 150, dataIndex: 'key'},
- {header: 'Value', flex: 1, dataIndex: 'value'}
- ]
- }
- ],
- dockedItems: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'start',
- dock: 'bottom',
- margin: '5 0 0 0',
- boxLabel: gettext('Start after created')
- }
- ],
- listeners: {
- show: function(panel) {
- var wizard = this.up('window');
- var kv = wizard.getValues();
- var data = [];
- Ext.Object.each(kv, function(key, value) {
- if (key === 'delete' || key === 'tmplstorage') { // ignore
- return;
- }
- if (key === 'password') { // don't show pw
- return;
- }
- var html = Ext.htmlEncode(Ext.JSON.encode(value));
- data.push({ key: key, value: value });
- });
-
- var summarystore = panel.down('grid').getStore();
- summarystore.suspendEvents();
- summarystore.removeAll();
- summarystore.add(data);
- summarystore.sort();
- summarystore.resumeEvents();
- summarystore.fireEvent('refresh');
- }
- },
- onSubmit: function() {
- var wizard = this.up('window');
- var kv = wizard.getValues();
- delete kv['delete'];
-
- var nodename = kv.nodename;
- delete kv.nodename;
- delete kv.tmplstorage;
-
- if (!kv.pool.length) {
- delete kv.pool;
- }
-
- if (!kv.password.length && kv['ssh-public-keys']) {
- delete kv.password;
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/lxc',
- waitMsgTarget: wizard,
- method: 'POST',
- params: kv,
- success: function(response, opts){
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- wizard.close();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- }
- ]
-});
-
-
-
-Ext.define('PVE.lxc.SnapshotTree', {
- extend: 'Ext.tree.Panel',
- alias: ['widget.pveLxcSnapshotTree'],
-
- onlineHelp: 'pct_snapshots',
-
- load_delay: 3000,
-
- old_digest: 'invalid',
-
- stateful: true,
- stateId: 'grid-lxc-snapshots',
-
- sorterFn: function(rec1, rec2) {
- var v1 = rec1.data.snaptime;
- var v2 = rec2.data.snaptime;
-
- if (rec1.data.name === 'current') {
- return 1;
- }
- if (rec2.data.name === 'current') {
- return -1;
- }
-
- return (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
- },
-
- reload: function(repeat) {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/snapshot',
- method: 'GET',
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- me.load_task.delay(me.load_delay);
- },
- success: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, false);
- var digest = 'invalid';
- var idhash = {};
- var root = { name: '__root', expanded: true, children: [] };
- Ext.Array.each(response.result.data, function(item) {
- item.leaf = true;
- item.children = [];
- if (item.name === 'current') {
- digest = item.digest + item.running;
- if (item.running) {
- item.iconCls = 'fa fa-fw fa-desktop x-fa-tree-running';
- } else {
- item.iconCls = 'fa fa-fw fa-desktop x-fa-tree';
- }
- } else {
- item.iconCls = 'fa fa-fw fa-history x-fa-tree';
- }
- idhash[item.name] = item;
- });
-
- if (digest !== me.old_digest) {
- me.old_digest = digest;
-
- Ext.Array.each(response.result.data, function(item) {
- if (item.parent && idhash[item.parent]) {
- var parent_item = idhash[item.parent];
- parent_item.children.push(item);
- parent_item.leaf = false;
- parent_item.expanded = true;
- parent_item.expandable = false;
- } else {
- root.children.push(item);
- }
- });
-
- me.setRootNode(root);
- }
-
- me.load_task.delay(me.load_delay);
- }
- });
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/feature',
- params: { feature: 'snapshot' },
- method: 'GET',
- success: function(response, options) {
- var res = response.result.data;
- if (res.hasFeature) {
- var snpBtns = Ext.ComponentQuery.query('#snapshotBtn');
- snpBtns.forEach(function(item){
- item.enable();
- });
- }
- }
- });
-
-
- },
-
- listeners: {
- beforestatesave: function(grid, state, eopts) {
- // extjs cannot serialize functions,
- // so a the sorter with only the sorterFn will
- // not be a valid sorter when restoring the state
- delete state.storeState.sorters;
- }
- },
-
- initComponent: function() {
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.vmid = me.pveSelNode.data.vmid;
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- me.load_task = new Ext.util.DelayedTask(me.reload, me);
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var valid_snapshot = function(record) {
- return record && record.data && record.data.name &&
- record.data.name !== 'current';
- };
-
- var valid_snapshot_rollback = function(record) {
- return record && record.data && record.data.name &&
- record.data.name !== 'current' && !record.data.snapstate;
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (valid_snapshot(rec)) {
- var win = Ext.create('PVE.window.LxcSnapshot', {
- snapname: rec.data.name,
- nodename: me.nodename,
- vmid: me.vmid
- });
- win.show();
- me.mon(win, 'close', me.reload, me);
- }
- };
-
- var editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- enableFn: valid_snapshot,
- handler: run_editor
- });
-
- var rollbackBtn = new Proxmox.button.Button({
- text: gettext('Rollback'),
- disabled: true,
- dangerous: true,
- selModel: sm,
- enableFn: valid_snapshot_rollback,
- confirmMsg: function(rec) {
- var taskdescription = Proxmox.Utils.format_task_description('vzrollback', me.vmid);
- var snaptime = Ext.Date.format(rec.data.snaptime,'Y-m-d H:i:s');
- var snapname = rec.data.name;
-
- var msg = Ext.String.format(gettext('{0} to {1} ({2})'),
- taskdescription, snapname, snaptime);
- msg += '' + gettext('Note: Rollback stops CT') + '
';
-
- return msg;
- },
- handler: function(btn, event) {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var snapname = rec.data.name;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/snapshot/' + snapname + '/rollback',
- method: 'POST',
- waitMsgTarget: me,
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- });
- }
- });
-
- var removeBtn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- confirmMsg: function(rec) {
- var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.name + "'");
- return msg;
- },
- enableFn: valid_snapshot,
- handler: function(btn, event) {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var snapname = rec.data.name;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/snapshot/' + snapname,
- method: 'DELETE',
- waitMsgTarget: me,
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- });
- }
- });
-
- var snapshotBtn = Ext.create('Ext.Button', {
- itemId: 'snapshotBtn',
- text: gettext('Take Snapshot'),
- disabled: true,
- handler: function() {
- var win = Ext.create('PVE.window.LxcSnapshot', {
- nodename: me.nodename,
- vmid: me.vmid
- });
- win.show();
- }
- });
-
- Ext.apply(me, {
- layout: 'fit',
- rootVisible: false,
- animate: false,
- sortableColumns: false,
- selModel: sm,
- tbar: [ snapshotBtn, rollbackBtn, removeBtn, editBtn ],
- fields: [
- 'name', 'description', 'snapstate', 'vmstate', 'running',
- { name: 'snaptime', type: 'date', dateFormat: 'timestamp' }
- ],
- columns: [
- {
- xtype: 'treecolumn',
- text: gettext('Name'),
- dataIndex: 'name',
- width: 200,
- renderer: function(value, metaData, record) {
- if (value === 'current') {
- return "NOW";
- } else {
- return value;
- }
- }
- },
-// {
-// text: gettext('RAM'),
-// align: 'center',
-// resizable: false,
-// dataIndex: 'vmstate',
-// width: 50,
-// renderer: function(value, metaData, record) {
-// if (record.data.name !== 'current') {
-// return Proxmox.Utils.format_boolean(value);
-// }
-// }
-// },
- {
- text: gettext('Date') + "/" + gettext("Status"),
- dataIndex: 'snaptime',
- resizable: false,
- width: 150,
- renderer: function(value, metaData, record) {
- if (record.data.snapstate) {
- return record.data.snapstate;
- }
- if (value) {
- return Ext.Date.format(value,'Y-m-d H:i:s');
- }
- }
- },
- {
- text: gettext('Description'),
- dataIndex: 'description',
- flex: 1,
- renderer: function(value, metaData, record) {
- if (record.data.name === 'current') {
- return gettext("You are here!");
- } else {
- return Ext.String.htmlEncode(value);
- }
- }
- }
- ],
- columnLines: true,
- listeners: {
- activate: me.reload,
- destroy: me.load_task.cancel,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
-
- me.store.sorters.add(new Ext.util.Sorter({
- sorterFn: me.sorterFn
- }));
- }
-});
-Ext.define('PVE.window.LxcSnapshot', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- // needed for finding the reference to submitbutton
- // because we do not have a controller
- referenceHolder: true,
- defaultButton: 'submitbutton',
- defaultFocus: 'field',
-
- take_snapshot: function(snapname, descr, vmstate) {
- var me = this;
- var params = { snapname: snapname };
- if (descr) {
- params.description = descr;
- }
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot",
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- me.close();
- }
- });
- },
-
- update_snapshot: function(snapname, descr) {
- var me = this;
- Proxmox.Utils.API2Request({
- params: { description: descr },
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot/" +
- snapname + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- me.close();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- var summarystore = Ext.create('Ext.data.Store', {
- model: 'KeyValue',
- sorters: [
- {
- property : 'key',
- direction: 'ASC'
- }
- ]
- });
-
- var items = [
- {
- xtype: me.snapname ? 'displayfield' : 'textfield',
- name: 'snapname',
- value: me.snapname,
- fieldLabel: gettext('Name'),
- vtype: 'ConfigId',
- allowBlank: false
- }
- ];
-
- if (me.snapname) {
- items.push({
- xtype: 'displayfield',
- name: 'snaptime',
- renderer: PVE.Utils.render_timestamp_human_readable,
- fieldLabel: gettext('Timestamp')
- });
- }
-
- items.push({
- xtype: 'textareafield',
- grow: true,
- name: 'description',
- fieldLabel: gettext('Description')
- });
-
- if (me.snapname) {
- items.push({
- title: gettext('Settings'),
- xtype: 'grid',
- height: 200,
- store: summarystore,
- columns: [
- {header: gettext('Key'), width: 150, dataIndex: 'key'},
- {header: gettext('Value'), flex: 1, dataIndex: 'value'}
- ]
- });
- }
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- if (me.snapname) {
- me.title = gettext('Edit') + ': ' + gettext('Snapshot');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Update'),
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.update_snapshot(me.snapname, values.description);
- }
- }
- });
- } else {
- me.title ="VM " + me.vmid + ': ' + gettext('Take Snapshot');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Take Snapshot'),
- reference: 'submitbutton',
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.take_snapshot(values.snapname, values.description);
- }
- }
- });
- }
-
- Ext.apply(me, {
- modal: true,
- width: 450,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
- if (me.snapname) {
- Ext.apply(me, {
- width: 620,
- height: 420
- });
- }
-
- me.callParent();
-
- if (!me.snapname) {
- return;
- }
-
- // else load data
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot/" +
- me.snapname + '/config',
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- me.close();
- },
- success: function(response, options) {
- var data = response.result.data;
- var kvarray = [];
- Ext.Object.each(data, function(key, value) {
- if (key === 'description' || key === 'snaptime') {
- return;
- }
- kvarray.push({ key: key, value: value });
- });
-
- summarystore.suspendEvents();
- summarystore.add(kvarray);
- summarystore.sort();
- summarystore.resumeEvents();
- summarystore.fireEvent('refresh', summarystore);
-
- form.findField('snaptime').setValue(data.snaptime);
- form.findField('description').setValue(data.description);
- }
- });
- }
-});
-/*jslint confusion: true */
-var labelWidth = 120;
-
-Ext.define('PVE.lxc.MemoryEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.apply(me, {
- subject: gettext('Memory'),
- items: Ext.create('PVE.lxc.MemoryInputPanel')
- });
-
- me.callParent();
-
- me.load();
- }
-});
-
-
-Ext.define('PVE.lxc.CPUEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.apply(me, {
- subject: gettext('CPU'),
- items: Ext.create('PVE.lxc.CPUInputPanel')
- });
-
- me.callParent();
-
- me.load();
- }
-});
-
-Ext.define('PVE.lxc.CPUInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveLxcCPUInputPanel',
-
- onlineHelp: 'pct_cpu',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- PVE.Utils.delete_if_default(values, 'cores', '', me.insideWizard);
- // cpu{limit,unit} aren't in the wizard so create is always false
- PVE.Utils.delete_if_default(values, 'cpulimit', '0', 0);
- PVE.Utils.delete_if_default(values, 'cpuunits', '1024', 0);
-
- return values;
- },
-
- advancedColumn1: [
- {
- xtype: 'numberfield',
- name: 'cpulimit',
- minValue: 0,
- value: '',
- step: 1,
- fieldLabel: gettext('CPU limit'),
- allowBlank: true,
- emptyText: gettext('unlimited')
- }
- ],
-
- advancedColumn2: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'cpuunits',
- fieldLabel: gettext('CPU units'),
- value: 1024,
- minValue: 8,
- maxValue: 500000,
- labelWidth: labelWidth,
- allowBlank: false
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: 'proxmoxintegerfield',
- name: 'cores',
- minValue: 1,
- maxValue: 128,
- value: me.insideWizard ? 1 : '',
- fieldLabel: gettext('Cores'),
- allowBlank: true,
- deleteEmpty: true,
- emptyText: gettext('unlimited')
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.lxc.MemoryInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveLxcMemoryInputPanel',
-
- onlineHelp: 'pct_memory',
-
- insideWizard: false,
-
- initComponent : function() {
- var me = this;
-
- var items = [
- {
- xtype: 'proxmoxintegerfield',
- name: 'memory',
- minValue: 16,
- value: '512',
- step: 32,
- fieldLabel: gettext('Memory') + ' (MiB)',
- labelWidth: labelWidth,
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'swap',
- minValue: 0,
- value: '512',
- step: 32,
- fieldLabel: gettext('Swap') + ' (MiB)',
- labelWidth: labelWidth,
- allowBlank: false
- }
- ];
-
- if (me.insideWizard) {
- me.column1 = items;
- } else {
- me.items = items;
- }
-
- me.callParent();
- }
-});
-Ext.define('PVE.window.MPResize', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- resize_disk: function(disk, size) {
- var me = this;
- var params = { disk: disk, size: '+' + size + 'G' };
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/resize',
- waitMsgTarget: me,
- method: 'PUT',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskViewer', { upid: upid });
- win.show();
- me.close();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- var items = [
- {
- xtype: 'displayfield',
- name: 'disk',
- value: me.disk,
- fieldLabel: gettext('Disk'),
- vtype: 'StorageId',
- allowBlank: false
- }
- ];
-
- me.hdsizesel = Ext.createWidget('numberfield', {
- name: 'size',
- minValue: 0,
- maxValue: 128*1024,
- decimalPrecision: 3,
- value: '0',
- fieldLabel: gettext('Size Increment') + ' (GiB)',
- allowBlank: false
- });
-
- items.push(me.hdsizesel);
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 120,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- me.title = gettext('Resize disk');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Resize disk'),
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.resize_disk(me.disk, values.size);
- }
- }
- });
-
- Ext.apply(me, {
- modal: true,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
-
- me.callParent();
-
- if (!me.disk) {
- return;
- }
-
- }
-});
-/*jslint confusion: true*/
-/* hidden: boolean and string
- * bind: function and object
- * disabled: boolean and string
- */
-Ext.define('PVE.lxc.MountPointInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveLxcMountPointInputPanel',
-
- insideWizard: false,
-
- onlineHelp: 'pct_container_storage',
-
- unused: false, // add unused disk imaged
-
- unprivileged: false,
-
- vmconfig: {}, // used to select unused disks
-
- setUnprivileged: function(unprivileged) {
- var me = this;
- var vm = me.getViewModel();
- me.unprivileged = unprivileged;
- vm.set('unpriv', unprivileged);
- },
-
- onGetValues: function(values) {
- var me = this;
-
- var confid = me.confid || "mp"+values.mpid;
- values.file = me.down('field[name=file]').getValue();
-
- if (me.unused) {
- confid = "mp"+values.mpid;
- } else if (me.isCreate) {
- values.file = values.hdstorage + ':' + values.disksize;
- }
-
- // delete unnecessary fields
- delete values.mpid;
- delete values.hdstorage;
- delete values.disksize;
- delete values.diskformat;
-
- var res = {};
- res[confid] = PVE.Parser.printLxcMountPoint(values);
- return res;
- },
-
-
- setMountPoint: function(mp) {
- var me = this;
- var vm = this.getViewModel();
- vm.set('mptype', mp.type);
- me.setValues(mp);
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
- var vm = me.getViewModel();
- me.vmconfig = vmconfig;
- vm.set('unpriv', vmconfig.unprivileged);
- vm.notify();
-
- PVE.Utils.forEachMP(function(bus, i) {
- var name = "mp" + i.toString();
- if (!Ext.isDefined(vmconfig[name])) {
- me.down('field[name=mpid]').setValue(i);
- return false;
- }
- });
- },
-
- setNodename: function(nodename) {
- var me = this;
- var vm = me.getViewModel();
- vm.set('node', nodename);
- vm.notify();
- me.down('#diskstorage').setNodename(nodename);
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- control: {
- 'field[name=mpid]': {
- change: function(field, value) {
- field.validate();
- }
- },
- '#hdstorage': {
- change: function(field, newValue) {
- var me = this;
- if (!newValue) {
- return;
- }
-
- var rec = field.store.getById(newValue);
- if (!rec) {
- return;
- }
-
- var vm = me.getViewModel();
- vm.set('type', rec.data.type);
- vm.notify();
- }
- }
- },
-
- init: function(view) {
- var me = this;
- var vm = this.getViewModel();
- vm.set('confid', view.confid);
- vm.set('unused', view.unused);
- vm.set('node', view.nodename);
- vm.set('unpriv', view.unprivileged);
- vm.set('hideStorSelector', view.unused || !view.isCreate);
- vm.notify();
- }
- },
-
- viewModel: {
- data: {
- unpriv: false,
- unused: false,
- showStorageSelector: false,
- mptype: '',
- type: '',
- confid: '',
- node: ''
- },
-
- formulas: {
- quota: function(get) {
- return !(get('type') === 'zfs' ||
- get('type') === 'zfspool' ||
- get('unpriv') ||
- get('isBind'));
- },
- hasMP: function(get) {
- return !!get('confid') && !get('unused');
- },
- isRoot: function(get) {
- return get('confid') === 'rootfs';
- },
- isBind: function(get) {
- return get('mptype') === 'bind';
- },
- isBindOrRoot: function(get) {
- return get('isBind') || get('isRoot');
- }
- }
- },
-
- column1: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'mpid',
- fieldLabel: gettext('Mount Point ID'),
- minValue: 0,
- maxValue: PVE.Utils.mp_counts.mps - 1,
- hidden: true,
- allowBlank: false,
- disabled: true,
- bind: {
- hidden: '{hasMP}',
- disabled: '{hasMP}'
- },
- validator: function(value) {
- var me = this.up('inputpanel');
- if (!me.rendered) {
- return;
- }
- if (Ext.isDefined(me.vmconfig["mp"+value])) {
- return "Mount point is already in use.";
- }
- /*jslint confusion: true*/
- /* returns a string above */
- return true;
- }
- },
- {
- xtype: 'pveDiskStorageSelector',
- itemId: 'diskstorage',
- storageContent: 'rootdir',
- hidden: true,
- autoSelect: true,
- selectformat: false,
- defaultSize: 8,
- bind: {
- hidden: '{hideStorSelector}',
- disabled: '{hideStorSelector}',
- nodename: '{node}'
- }
- },
- {
- xtype: 'textfield',
- disabled: true,
- submitValue: false,
- fieldLabel: gettext('Disk image'),
- name: 'file',
- bind: {
- hidden: '{!hideStorSelector}'
- }
- }
- ],
-
- column2: [
- {
- xtype: 'textfield',
- name: 'mp',
- value: '',
- emptyText: gettext('/some/path'),
- allowBlank: false,
- disabled: true,
- fieldLabel: gettext('Path'),
- bind: {
- hidden: '{isRoot}',
- disabled: '{isRoot}'
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'backup',
- fieldLabel: gettext('Backup'),
- bind: {
- hidden: '{isRoot}',
- disabled: '{isBindOrRoot}'
- }
- }
- ],
-
- advancedColumn1: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'quota',
- defaultValue: 0,
- bind: {
- disabled: '{!quota}'
- },
- fieldLabel: gettext('Enable quota'),
- listeners: {
- disable: function() {
- this.reset();
- }
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'ro',
- defaultValue: 0,
- bind: {
- hidden: '{isRoot}',
- disabled: '{isRoot}'
- },
- fieldLabel: gettext('Read-only')
- }
- ],
-
- advancedColumn2: [
- {
- xtype: 'proxmoxKVComboBox',
- name: 'acl',
- fieldLabel: 'ACLs',
- deleteEmpty: false,
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText],
- ['1', Proxmox.Utils.enabledText],
- ['0', Proxmox.Utils.disabledText]
- ],
- value: '__default__',
- bind: {
- disabled: '{isBind}'
- },
- allowBlank: true
- },
- {
- xtype: 'proxmoxcheckbox',
- inputValue: '0', // reverses the logic
- name: 'replicate',
- fieldLabel: gettext('Skip replication')
- }
- ]
-});
-
-Ext.define('PVE.lxc.MountPointEdit', {
- extend: 'Proxmox.window.Edit',
-
- unprivileged: false,
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var unused = me.confid && me.confid.match(/^unused\d+$/);
-
- me.isCreate = me.confid ? unused : true;
-
- var ipanel = Ext.create('PVE.lxc.MountPointInputPanel', {
- confid: me.confid,
- nodename: nodename,
- unused: unused,
- unprivileged: me.unprivileged,
- isCreate: me.isCreate
- });
-
- var subject;
- if (unused) {
- subject = gettext('Unused Disk');
- } else if (me.isCreate) {
- subject = gettext('Mount Point');
- } else {
- subject = gettext('Mount Point') + ' (' + me.confid + ')';
- }
-
- Ext.apply(me, {
- subject: subject,
- defaultFocus: me.confid !== 'rootfs' ? 'textfield[name=mp]' : 'tool',
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- if (me.confid) {
- /*jslint confusion: true*/
- /*data is defined as array above*/
- var value = response.result.data[me.confid];
- /*jslint confusion: false*/
- var mp = PVE.Parser.parseLxcMountPoint(value);
-
- if (!mp) {
- Ext.Msg.alert(gettext('Error'), 'Unable to parse mount point options');
- me.close();
- return;
- }
-
- ipanel.setMountPoint(mp);
- me.isValid(); // trigger validation
- }
- }
- });
- }
-});
-Ext.define('PVE.pool.StatusView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pvePoolStatusView'],
- disabled: true,
-
- title: gettext('Status'),
- cwidth1: 150,
- interval: 30000,
- //height: 195,
- initComponent : function() {
- var me = this;
-
- var pool = me.pveSelNode.data.pool;
- if (!pool) {
- throw "no pool specified";
- }
-
- var rows = {
- comment: {
- header: gettext('Comment'),
- renderer: Ext.String.htmlEncode,
- required: true
- }
- };
-
- Ext.apply(me, {
- url: "/api2/json/pools/" + pool,
- rows: rows
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.pool.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pvePoolSummary',
-
- initComponent: function() {
- var me = this;
-
- var pool = me.pveSelNode.data.pool;
- if (!pool) {
- throw "no pool specified";
- }
-
- var statusview = Ext.create('PVE.pool.StatusView', {
- pveSelNode: me.pveSelNode,
- style: 'padding-top:0px'
- });
-
- var rstore = statusview.rstore;
-
- Ext.apply(me, {
- autoScroll: true,
- bodyStyle: 'padding:10px',
- defaults: {
- style: 'padding-top:10px',
- width: 800
- },
- items: [ statusview ]
- });
-
- me.on('activate', rstore.startUpdate);
- me.on('destroy', rstore.stopUpdate);
-
- me.callParent();
- }
-});
-Ext.define('PVE.pool.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.pvePoolConfig',
-
- onlineHelp: 'pveum_pools',
-
- initComponent: function() {
- var me = this;
-
- var pool = me.pveSelNode.data.pool;
- if (!pool) {
- throw "no pool specified";
- }
-
- Ext.apply(me, {
- title: Ext.String.format(gettext("Resource Pool") + ': ' + pool),
- hstateid: 'pooltab',
- items: [
- {
- title: gettext('Summary'),
- iconCls: 'fa fa-book',
- xtype: 'pvePoolSummary',
- itemId: 'summary'
- },
- {
- title: gettext('Members'),
- xtype: 'pvePoolMembers',
- iconCls: 'fa fa-th',
- pool: pool,
- itemId: 'members'
- },
- {
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- iconCls: 'fa fa-unlock',
- itemId: 'permissions',
- path: '/pool/' + pool
- }
- ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.panel.StorageBase', {
- extend: 'Proxmox.panel.InputPanel',
- controller: 'storageEdit',
-
- type: '',
-
- onGetValues: function(values) {
- var me = this;
-
- if (me.isCreate) {
- values.type = me.type;
- } else {
- delete values.storage;
- }
-
- values.disable = values.enable ? 0 : 1;
- delete values.enable;
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
-
- me.column1.unshift({
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'storage',
- value: me.storageId || '',
- fieldLabel: 'ID',
- vtype: 'StorageId',
- allowBlank: false
- });
-
- me.column2.unshift(
- {
- xtype: 'pveNodeSelector',
- name: 'nodes',
- disabled: me.storageId === 'local',
- fieldLabel: gettext('Nodes'),
- emptyText: gettext('All') + ' (' + gettext('No restrictions') +')',
- multiSelect: true,
- autoSelect: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- checked: true,
- uncheckedValue: 0,
- fieldLabel: gettext('Enable')
- }
- );
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.BaseEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.storageId;
-
- if (me.isCreate) {
- me.url = '/api2/extjs/storage';
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs/storage/' + me.storageId;
- me.method = 'PUT';
- }
-
- var ipanel = Ext.create(me.paneltype, {
- type: me.type,
- isCreate: me.isCreate,
- storageId: me.storageId
- });
-
- Ext.apply(me, {
- subject: PVE.Utils.format_storage_type(me.type),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- var ctypes = values.content || '';
-
- values.content = ctypes.split(',');
-
- if (values.nodes) {
- values.nodes = values.nodes.split(',');
- }
- values.enable = values.disable ? 0 : 1;
-
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-Ext.define('PVE.grid.TemplateSelector', {
- extend: 'Ext.grid.GridPanel',
-
- alias: 'widget.pveTemplateSelector',
-
- stateful: true,
- stateId: 'grid-template-selector',
- viewConfig: {
- trackOver: false
- },
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var baseurl = "/nodes/" + me.nodename + "/aplinfo";
- var store = new Ext.data.Store({
- model: 'pve-aplinfo',
- groupField: 'section',
- proxy: {
- type: 'proxmox',
- url: '/api2/json' + baseurl
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
- groupHeaderTpl: '{[ "Section: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
- });
-
- var reload = function() {
- store.load();
- };
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- '->',
- gettext('Search'),
- {
- xtype: 'textfield',
- width: 200,
- enableKeyEvents: true,
- listeners: {
- buffer: 500,
- keyup: function(field) {
- var value = field.getValue().toLowerCase();
- store.clearFilter(true);
- store.filterBy(function(rec) {
- return (rec.data['package'].toLowerCase().indexOf(value) !== -1)
- || (rec.data.headline.toLowerCase().indexOf(value) !== -1);
- });
- }
- }
- }
- ],
- features: [ groupingFeature ],
- columns: [
- {
- header: gettext('Type'),
- width: 80,
- dataIndex: 'type'
- },
- {
- header: gettext('Package'),
- flex: 1,
- dataIndex: 'package'
- },
- {
- header: gettext('Version'),
- width: 80,
- dataIndex: 'version'
- },
- {
- header: gettext('Description'),
- flex: 1.5,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'headline'
- }
- ],
- listeners: {
- afterRender: reload
- }
- });
-
- me.callParent();
- }
-
-}, function() {
-
- Ext.define('pve-aplinfo', {
- extend: 'Ext.data.Model',
- fields: [
- 'template', 'type', 'package', 'version', 'headline', 'infopage',
- 'description', 'os', 'section'
- ],
- idProperty: 'template'
- });
-
-});
-
-Ext.define('PVE.storage.TemplateDownload', {
- extend: 'Ext.window.Window',
- alias: 'widget.pveTemplateDownload',
-
- modal: true,
- title: gettext('Templates'),
- layout: 'fit',
- width: 900,
- height: 600,
- initComponent : function() {
- /*jslint confusion: true */
- var me = this;
-
- var grid = Ext.create('PVE.grid.TemplateSelector', {
- border: false,
- scrollable: true,
- nodename: me.nodename
- });
-
- var sm = grid.getSelectionModel();
-
- var submitBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('Download'),
- disabled: true,
- selModel: sm,
- handler: function(button, event, rec) {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/aplinfo',
- params: {
- storage: me.storage,
- template: rec.data.template
- },
- method: 'POST',
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
-
- Ext.create('Proxmox.window.TaskViewer', {
- upid: upid,
- listeners: {
- destroy: me.reloadGrid
- }
- }).show();
-
- me.close();
- }
- });
- }
- });
-
- Ext.apply(me, {
- items: grid,
- buttons: [ submitBtn ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.Upload', {
- extend: 'Ext.window.Window',
- alias: 'widget.pveStorageUpload',
-
- resizable: false,
-
- modal: true,
-
- initComponent : function() {
- /*jslint confusion: true */
- var me = this;
-
- var xhr;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.storage) {
- throw "no storage ID specified";
- }
-
- var baseurl = "/nodes/" + me.nodename + "/storage/" + me.storage + "/upload";
-
- var pbar = Ext.create('Ext.ProgressBar', {
- text: 'Ready',
- hidden: true
- });
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- method: 'POST',
- waitMsgTarget: true,
- bodyPadding: 10,
- border: false,
- width: 300,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [
- {
- xtype: 'pveContentTypeSelector',
- cts: me.contents,
- fieldLabel: gettext('Content'),
- name: 'content',
- value: me.contents[0] || '',
- allowBlank: false
- },
- {
- xtype: 'filefield',
- name: 'filename',
- buttonText: gettext('Select File...'),
- allowBlank: false
- },
- pbar
- ]
- });
-
- var form = me.formPanel.getForm();
-
- var doStandardSubmit = function() {
- form.submit({
- url: "/api2/htmljs" + baseurl,
- waitMsg: gettext('Uploading file...'),
- success: function(f, action) {
- me.close();
- },
- failure: function(f, action) {
- var msg = PVE.Utils.extractFormActionError(action);
- Ext.Msg.alert(gettext('Error'), msg);
- }
- });
- };
-
- var updateProgress = function(per, bytes) {
- var text = (per * 100).toFixed(2) + '%';
- if (bytes) {
- text += " (" + Proxmox.Utils.format_size(bytes) + ')';
- }
- pbar.updateProgress(per, text);
- };
-
- var abortBtn = Ext.create('Ext.Button', {
- text: gettext('Abort'),
- disabled: true,
- handler: function() {
- me.close();
- }
- });
-
- var submitBtn = Ext.create('Ext.Button', {
- text: gettext('Upload'),
- disabled: true,
- handler: function(button) {
- var fd;
- try {
- fd = new FormData();
- } catch (err) {
- doStandardSubmit();
- return;
- }
-
- button.setDisabled(true);
- abortBtn.setDisabled(false);
-
- var field = form.findField('content');
- fd.append("content", field.getValue());
- field.setDisabled(true);
-
- field = form.findField('filename');
- var file = field.fileInputEl.dom;
- fd.append("filename", file.files[0]);
- field.setDisabled(true);
-
- pbar.setVisible(true);
- updateProgress(0);
-
- xhr = new XMLHttpRequest();
-
- xhr.addEventListener("load", function(e) {
- if (xhr.status == 200) {
- me.close();
- } else {
- var msg = gettext('Error') + " " + xhr.status.toString() + ": " + Ext.htmlEncode(xhr.statusText);
- var result = Ext.decode(xhr.responseText);
- result.message = msg;
- var htmlStatus = Proxmox.Utils.extractRequestError(result, true);
- Ext.Msg.alert(gettext('Error'), htmlStatus, function(btn) {
- me.close();
- });
-
- }
- }, false);
-
- xhr.addEventListener("error", function(e) {
- var msg = "Error " + e.target.status.toString() + " occurred while receiving the document.";
- Ext.Msg.alert(gettext('Error'), msg, function(btn) {
- me.close();
- });
- });
-
- xhr.upload.addEventListener("progress", function(evt) {
- if (evt.lengthComputable) {
- var percentComplete = evt.loaded / evt.total;
- updateProgress(percentComplete, evt.loaded);
- }
- }, false);
-
- xhr.open("POST", "/api2/json" + baseurl, true);
- xhr.send(fd);
- }
- });
-
- form.on('validitychange', function(f, valid) {
- submitBtn.setDisabled(!valid);
- });
-
- Ext.apply(me, {
- title: gettext('Upload'),
- items: me.formPanel,
- buttons: [ abortBtn, submitBtn ],
- listeners: {
- close: function() {
- if (xhr) {
- xhr.abort();
- }
- }
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.ContentView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: 'widget.pveStorageContentView',
-
- stateful: true,
- stateId: 'grid-storage-content',
- viewConfig: {
- trackOver: false,
- loadMask: false
- },
- features: [
- {
- ftype: 'grouping',
- groupHeaderTpl: '{name} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
- }
- ],
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var storage = me.pveSelNode.data.storage;
- if (!storage) {
- throw "no storage ID specified";
- }
-
- var baseurl = "/nodes/" + nodename + "/storage/" + storage + "/content";
- var store = Ext.create('Ext.data.Store',{
- model: 'pve-storage-content',
- groupField: 'content',
- proxy: {
- type: 'proxmox',
- url: '/api2/json' + baseurl
- },
- sorters: {
- property: 'volid',
- order: 'DESC'
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- store.load();
- me.statusStore.load();
- };
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- var templateButton = Ext.create('Proxmox.button.Button',{
- itemId: 'tmpl-btn',
- text: gettext('Templates'),
- handler: function() {
- var win = Ext.create('PVE.storage.TemplateDownload', {
- nodename: nodename,
- storage: storage,
- reloadGrid: reload
- });
- win.show();
- }
- });
-
- var uploadButton = Ext.create('Proxmox.button.Button', {
- contents : ['iso','vztmpl'],
- text: gettext('Upload'),
- handler: function() {
- var me = this;
- var win = Ext.create('PVE.storage.Upload', {
- nodename: nodename,
- storage: storage,
- contents: me.contents
- });
- win.show();
- win.on('destroy', reload);
- }
- });
-
- var imageRemoveButton;
- var removeButton = Ext.create('Proxmox.button.StdRemoveButton',{
- selModel: sm,
- enableFn: function(rec) {
- if (rec && rec.data.content !== 'images') {
- imageRemoveButton.setVisible(false);
- removeButton.setVisible(true);
- return true;
- }
- return false;
- },
- callback: function() {
- reload();
- },
- baseurl: baseurl + '/'
- });
-
- imageRemoveButton = Ext.create('Proxmox.button.Button',{
- selModel: sm,
- hidden: true,
- text: gettext('Remove'),
- enableFn: function(rec) {
- if (rec && rec.data.content === 'images') {
- removeButton.setVisible(false);
- imageRemoveButton.setVisible(true);
- return true;
- }
- return false;
- },
- handler: function(btn, event, rec) {
- me = this;
-
- var url = baseurl + '/' + rec.data.volid;
- var vmid = rec.data.vmid;
-
- var store = PVE.data.ResourceStore;
-
- if (vmid && store.findVMID(vmid)) {
- var guest_node = store.guestNode(vmid);
- var storage_path = 'storage/' + nodename + '/' + storage;
-
- // allow to delete local backed images if a VMID exists on another node.
- if (store.storageIsShared(storage_path) || guest_node == nodename) {
- var msg = Ext.String.format(
- gettext("Cannot remove image, a guest with VMID '{0}' exists!"), vmid);
- msg += ' ' + gettext("You can delete the image from the guest's hardware pane");
-
- Ext.Msg.show({
- title: gettext('Cannot remove disk image.'),
- icon: Ext.Msg.ERROR,
- msg: msg
- });
- return;
- }
- }
- var win = Ext.create('PVE.window.SafeDestroy', {
- title: Ext.String.format(gettext("Destroy '{0}'"), rec.data.volid),
- showProgress: true,
- url: url,
- item: { type: 'Image', id: vmid }
- }).show();
- win.on('destroy', function() {
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: '/api2/json/nodes/' + nodename + '/storage/' + storage + '/status'
- });
- reload();
-
- });
- }
- });
-
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: '/api2/json/nodes/' + nodename + '/storage/' + storage + '/status'
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- {
- xtype: 'proxmoxButton',
- text: gettext('Restore'),
- selModel: sm,
- disabled: true,
- enableFn: function(rec) {
- return rec && rec.data.content === 'backup';
- },
- handler: function(b, e, rec) {
- var vmtype;
- if (rec.data.volid.match(/vzdump-qemu-/)) {
- vmtype = 'qemu';
- } else if (rec.data.volid.match(/vzdump-openvz-/) || rec.data.volid.match(/vzdump-lxc-/)) {
- vmtype = 'lxc';
- } else {
- return;
- }
-
- var win = Ext.create('PVE.window.Restore', {
- nodename: nodename,
- volid: rec.data.volid,
- volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
- vmtype: vmtype
- });
- win.show();
- win.on('destroy', reload);
- }
- },
- removeButton,
- imageRemoveButton,
- templateButton,
- uploadButton,
- {
- xtype: 'proxmoxButton',
- text: gettext('Show Configuration'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- return rec && rec.data.content === 'backup';
- },
- handler: function(b,e,rec) {
- var win = Ext.create('PVE.window.BackupConfig', {
- volume: rec.data.volid,
- pveSelNode: me.pveSelNode
- });
-
- win.show();
- }
- },
- '->',
- gettext('Search') + ':', ' ',
- {
- xtype: 'textfield',
- width: 200,
- enableKeyEvents: true,
- listeners: {
- buffer: 500,
- keyup: function(field) {
- store.clearFilter(true);
- store.filter([
- {
- property: 'text',
- value: field.getValue(),
- anyMatch: true,
- caseSensitive: false
- }
- ]);
- }
- }
- }
- ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- renderer: PVE.Utils.render_storage_content,
- dataIndex: 'text'
- },
- {
- header: gettext('Format'),
- width: 100,
- dataIndex: 'format'
- },
- {
- header: gettext('Type'),
- width: 100,
- dataIndex: 'content',
- renderer: PVE.Utils.format_content_types
- },
- {
- header: gettext('Size'),
- width: 100,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- }
- ],
- listeners: {
- activate: reload
- }
- });
-
- me.callParent();
-
- // disable the buttons/restrict the upload window
- // if templates or uploads are not allowed
- me.mon(me.statusStore, 'load', function(s,records,succes) {
- var availcontent = [];
- Ext.Array.each(records, function(item){
- if (item.id === 'content') {
- availcontent = item.data.value.split(',');
- }
- });
- var templ = false;
- var upload = false;
- var cts = [];
-
- Ext.Array.each(availcontent, function(content) {
- if (content === 'vztmpl') {
- templ = true;
- cts.push('vztmpl');
- } else if (content === 'iso') {
- upload = true;
- cts.push('iso');
- }
- });
-
- if (templ !== upload) {
- uploadButton.contents = cts;
- }
-
- templateButton.setDisabled(!templ);
- uploadButton.setDisabled(!upload && !templ);
- });
- }
-}, function() {
-
- Ext.define('pve-storage-content', {
- extend: 'Ext.data.Model',
- fields: [
- 'volid', 'content', 'format', 'size', 'used', 'vmid',
- 'channel', 'id', 'lun',
- {
- name: 'text',
- convert: function(value, record) {
- // check for volid, because if you click on a grouping header,
- // it calls convert (but with an empty volid)
- if (value || record.data.volid === null) {
- return value;
- }
- return PVE.Utils.render_storage_content(value, {}, record);
- }
- }
- ],
- idProperty: 'volid'
- });
-
-});
-Ext.define('PVE.storage.StatusView', {
- extend: 'PVE.panel.StatusView',
- alias: 'widget.pveStorageStatusView',
-
- height: 230,
- title: gettext('Status'),
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- defaults: {
- xtype: 'pveInfoWidget',
- padding: '0 30 5 30'
- },
- items: [
- {
- xtype: 'box',
- height: 30
- },
- {
- itemId: 'enabled',
- title: gettext('Enabled'),
- printBar: false,
- textField: 'disabled',
- renderer: Proxmox.Utils.format_neg_boolean
- },
- {
- itemId: 'active',
- title: gettext('Active'),
- printBar: false,
- textField: 'active',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- itemId: 'content',
- title: gettext('Content'),
- printBar: false,
- textField: 'content',
- renderer: PVE.Utils.format_content_types
- },
- {
- itemId: 'type',
- title: gettext('Type'),
- printBar: false,
- textField: 'type',
- renderer: PVE.Utils.format_storage_type
- },
- {
- xtype: 'box',
- height: 10
- },
- {
- itemId: 'usage',
- title: gettext('Usage'),
- valueField: 'used',
- maxField: 'total'
- }
- ],
-
- updateTitle: function() {
- return;
- }
-});
-Ext.define('PVE.storage.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveStorageSummary',
- scrollable: true,
- bodyPadding: 5,
- tbar: [
- '->',
- {
- xtype: 'proxmoxRRDTypeSelector'
- }
- ],
- layout: {
- type: 'column'
- },
- defaults: {
- padding: 5,
- columnWidth: 1
- },
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var storage = me.pveSelNode.data.storage;
- if (!storage) {
- throw "no storage ID specified";
- }
-
- var rstore = Ext.create('Proxmox.data.ObjectStore', {
- url: "/api2/json/nodes/" + nodename + "/storage/" + storage + "/status",
- interval: 1000
- });
-
- var rrdstore = Ext.create('Proxmox.data.RRDStore', {
- rrdurl: "/api2/json/nodes/" + nodename + "/storage/" + storage + "/rrddata",
- model: 'pve-rrd-storage'
- });
-
- Ext.apply(me, {
- items: [
- {
- xtype: 'pveStorageStatusView',
- pveSelNode: me.pveSelNode,
- rstore: rstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Usage'),
- fields: ['total','used'],
- fieldTitles: ['Total Size', 'Used Size'],
- store: rrdstore
- }
- ],
- listeners: {
- activate: function() { rstore.startUpdate(); rrdstore.startUpdate(); },
- destroy: function() { rstore.stopUpdate(); rrdstore.stopUpdate(); }
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.Browser', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.storage.Browser',
-
- onlineHelp: 'chapter_storage',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var storeid = me.pveSelNode.data.storage;
- if (!storeid) {
- throw "no storage ID specified";
- }
-
-
- me.items = [
- {
- title: gettext('Summary'),
- xtype: 'pveStorageSummary',
- iconCls: 'fa fa-book',
- itemId: 'summary'
- }
- ];
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- Ext.apply(me, {
- title: Ext.String.format(gettext("Storage {0} on node {1}"),
- "'" + storeid + "'", "'" + nodename + "'"),
- hstateid: 'storagetab'
- });
-
- if (caps.storage['Datastore.Allocate'] ||
- caps.storage['Datastore.AllocateSpace'] ||
- caps.storage['Datastore.Audit']) {
- me.items.push({
- xtype: 'pveStorageContentView',
- title: gettext('Content'),
- iconCls: 'fa fa-th',
- itemId: 'content'
- });
- }
-
- if (caps.storage['Permissions.Modify']) {
- me.items.push({
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- iconCls: 'fa fa-unlock',
- itemId: 'permissions',
- path: '/storage/' + storeid
- });
- }
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.DirInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_directory',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'path',
- value: '',
- fieldLabel: gettext('Directory'),
- allowBlank: false
- },
- {
- xtype: 'pveContentTypeSelector',
- name: 'content',
- value: 'images',
- multiSelect: true,
- fieldLabel: gettext('Content'),
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'shared',
- uncheckedValue: 0,
- fieldLabel: gettext('Shared')
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- disabled: true,
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.NFSScan', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveNFSScan',
-
- queryParam: 'server',
-
- valueField: 'path',
- displayField: 'path',
- matchFieldWidth: false,
- listConfig: {
- loadingText: gettext('Scanning...'),
- width: 350
- },
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.nfsServer) {
- me.store.removeAll();
- }
-
- me.allQuery = me.nfsServer;
-
- me.callParent();
- },
-
- setServer: function(server) {
- var me = this;
-
- me.nfsServer = server;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'path', 'options' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/nfs'
- }
- });
-
- store.sort('path', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.NFSInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_nfs',
-
- onGetValues: function(values) {
- var me = this;
-
- if (me.isCreate) {
- // hack: for now we always create nvf v3
- // fixme: make this configurable
- values.options = 'vers=3';
- }
-
- return me.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'server',
- value: '',
- fieldLabel: gettext('Server'),
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- var exportField = me.down('field[name=export]');
- exportField.setServer(value);
- exportField.setValue('');
- }
- }
- }
- },
- {
- xtype: me.isCreate ? 'pveNFSScan' : 'displayfield',
- name: 'export',
- value: '',
- fieldLabel: 'Export',
- allowBlank: false
- },
- {
- xtype: 'pveContentTypeSelector',
- name: 'content',
- value: 'images',
- multiSelect: true,
- fieldLabel: gettext('Content'),
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- disabled: true,
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.CIFSScan', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveCIFSScan',
-
- queryParam: 'server',
-
- valueField: 'share',
- displayField: 'share',
- matchFieldWidth: false,
- listConfig: {
- loadingText: gettext('Scanning...'),
- width: 350
- },
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.cifsServer) {
- me.store.removeAll();
- }
-
- var params = {};
- if (me.cifsUsername && me.cifsPassword) {
- params.username = me.cifsUsername;
- params.password = me.cifsPassword;
- }
-
- if (me.cifsDomain) {
- params.domain = me.cifsDomain;
- }
-
- me.store.getProxy().setExtraParams(params);
- me.allQuery = me.cifsServer;
-
- me.callParent();
- },
-
- setServer: function(server) {
- this.cifsServer = server;
- },
-
- setUsername: function(username) {
- this.cifsUsername = username;
- },
-
- setPassword: function(password) {
- this.cifsPassword = password;
- },
-
- setDomain: function(domain) {
- this.cifsDomain = domain;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: ['description', 'share'],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/cifs'
- }
- });
- store.sort('share', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.CIFSInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_cifs',
-
- initComponent : function() {
- var me = this;
-
- var passwordfield = Ext.createWidget(me.isCreate ? 'textfield' : 'displayfield', {
- inputType: 'password',
- name: 'password',
- value: me.isCreate ? '' : '********',
- fieldLabel: gettext('Password'),
- allowBlank: false,
- disabled: me.isCreate,
- minLength: 1,
- listeners: {
- change: function(f, value) {
-
- if (me.isCreate) {
- var exportField = me.down('field[name=share]');
- exportField.setPassword(value);
- }
- }
- }
- });
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'server',
- value: '',
- fieldLabel: gettext('Server'),
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- var exportField = me.down('field[name=share]');
- exportField.setServer(value);
- }
- }
- }
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'username',
- value: '',
- fieldLabel: gettext('Username'),
- emptyText: gettext('Guest user'),
- allowBlank: true,
- listeners: {
- change: function(f, value) {
- if (!me.isCreate) {
- return;
- }
- var exportField = me.down('field[name=share]');
- exportField.setUsername(value);
-
- if (value == "") {
- passwordfield.disable();
- } else {
- passwordfield.enable();
- }
- passwordfield.validate();
- }
- }
- },
- passwordfield,
- {
- xtype: me.isCreate ? 'pveCIFSScan' : 'displayfield',
- name: 'share',
- value: '',
- fieldLabel: 'Share',
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- },
- {
- xtype: 'pveContentTypeSelector',
- name: 'content',
- value: 'images',
- multiSelect: true,
- fieldLabel: gettext('Content'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'domain',
- value: me.isCreate ? '' : undefined,
- fieldLabel: gettext('Domain'),
- allowBlank: true,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
-
- var exportField = me.down('field[name=share]');
- exportField.setDomain(value);
- }
- }
- }
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.GlusterFsScan', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveGlusterFsScan',
-
- queryParam: 'server',
-
- valueField: 'volname',
- displayField: 'volname',
- matchFieldWidth: false,
- listConfig: {
- loadingText: 'Scanning...',
- width: 350
- },
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.glusterServer) {
- me.store.removeAll();
- }
-
- me.allQuery = me.glusterServer;
-
- me.callParent();
- },
-
- setServer: function(server) {
- var me = this;
-
- me.glusterServer = server;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'volname' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/glusterfs'
- }
- });
-
- store.sort('volname', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.GlusterFsInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_glusterfs',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'server',
- value: '',
- fieldLabel: gettext('Server'),
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- var volumeField = me.down('field[name=volume]');
- volumeField.setServer(value);
- volumeField.setValue('');
- }
- }
- }
- },
- {
- xtype: me.isCreate ? 'proxmoxtextfield' : 'displayfield',
- name: 'server2',
- value: '',
- fieldLabel: gettext('Second Server'),
- allowBlank: true
- },
- {
- xtype: me.isCreate ? 'pveGlusterFsScan' : 'displayfield',
- name: 'volume',
- value: '',
- fieldLabel: 'Volume name',
- allowBlank: false
- },
- {
- xtype: 'pveContentTypeSelector',
- cts: ['images', 'iso', 'backup', 'vztmpl', 'snippets'],
- name: 'content',
- value: 'images',
- multiSelect: true,
- fieldLabel: gettext('Content'),
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- disabled: true,
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.IScsiScan', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveIScsiScan',
-
- queryParam: 'portal',
- valueField: 'target',
- displayField: 'target',
- matchFieldWidth: false,
- listConfig: {
- loadingText: gettext('Scanning...'),
- width: 350
- },
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.portal) {
- me.store.removeAll();
- }
-
- me.allQuery = me.portal;
-
- me.callParent();
- },
-
- setPortal: function(portal) {
- var me = this;
-
- me.portal = portal;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'target', 'portal' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/iscsi'
- }
- });
-
- store.sort('target', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.IScsiInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_open_iscsi',
-
- onGetValues: function(values) {
- var me = this;
-
- values.content = values.luns ? 'images' : 'none';
- delete values.luns;
-
- return me.callParent([values]);
- },
-
- setValues: function(values) {
- values.luns = (values.content.indexOf('images') !== -1) ? true : false;
- this.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'portal',
- value: '',
- fieldLabel: 'Portal',
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- var exportField = me.down('field[name=target]');
- exportField.setPortal(value);
- exportField.setValue('');
- }
- }
- }
- },
- {
- readOnly: !me.isCreate,
- xtype: me.isCreate ? 'pveIScsiScan' : 'displayfield',
- name: 'target',
- value: '',
- fieldLabel: 'Target',
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'checkbox',
- name: 'luns',
- checked: true,
- fieldLabel: gettext('Use LUNs directly')
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.VgSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveVgSelector',
- valueField: 'vg',
- displayField: 'vg',
- queryMode: 'local',
- editable: false,
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: {}, // true,
- fields: [ 'vg', 'size', 'free' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/lvm'
- }
- });
-
- store.sort('vg', 'ASC');
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- loadingText: gettext('Scanning...')
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.BaseStorageSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveBaseStorageSelector',
-
- existingGroupsText: gettext("Existing volume groups"),
- queryMode: 'local',
- editable: false,
- value: '',
- valueField: 'storage',
- displayField: 'text',
- initComponent : function() {
- var me = this;
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: {
- addRecords: true,
- params: {
- type: 'iscsi'
- }
- },
- fields: [ 'storage', 'type', 'content',
- {
- name: 'text',
- convert: function(value, record) {
- if (record.data.storage) {
- return record.data.storage + " (iSCSI)";
- } else {
- return me.existingGroupsText;
- }
- }
- }],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/storage/'
- }
- });
-
- store.loadData([{ storage: '' }], true);
-
- store.sort('storage', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.LVMInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_lvm',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [];
-
- var vgnameField = Ext.createWidget(me.isCreate ? 'textfield' : 'displayfield', {
- name: 'vgname',
- hidden: !!me.isCreate,
- disabled: !!me.isCreate,
- value: '',
- fieldLabel: gettext('Volume group'),
- allowBlank: false
- });
-
- if (me.isCreate) {
- var vgField = Ext.create('PVE.storage.VgSelector', {
- name: 'vgname',
- fieldLabel: gettext('Volume group'),
- allowBlank: false
- });
-
- var baseField = Ext.createWidget('pveFileSelector', {
- name: 'base',
- hidden: true,
- disabled: true,
- nodename: 'localhost',
- storageContent: 'images',
- fieldLabel: gettext('Base volume'),
- allowBlank: false
- });
-
- me.column1.push({
- xtype: 'pveBaseStorageSelector',
- name: 'basesel',
- fieldLabel: gettext('Base storage'),
- submitValue: false,
- listeners: {
- change: function(f, value) {
- if (value) {
- vgnameField.setVisible(true);
- vgnameField.setDisabled(false);
- vgField.setVisible(false);
- vgField.setDisabled(true);
- baseField.setVisible(true);
- baseField.setDisabled(false);
- } else {
- vgnameField.setVisible(false);
- vgnameField.setDisabled(true);
- vgField.setVisible(true);
- vgField.setDisabled(false);
- baseField.setVisible(false);
- baseField.setDisabled(true);
- }
- baseField.setStorage(value);
- }
- }
- });
-
- me.column1.push(baseField);
-
- me.column1.push(vgField);
- }
-
- me.column1.push(vgnameField);
-
- // here value is an array,
- // while before it was a string
- /*jslint confusion: true*/
- me.column1.push({
- xtype: 'pveContentTypeSelector',
- cts: ['images', 'rootdir'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: ['images', 'rootdir'],
- multiSelect: true,
- allowBlank: false
- });
- /*jslint confusion: false*/
-
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'shared',
- uncheckedValue: 0,
- fieldLabel: gettext('Shared')
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.TPoolSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveTPSelector',
-
- queryParam: 'vg',
- valueField: 'lv',
- displayField: 'lv',
- editable: false,
-
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.vg) {
- me.store.removeAll();
- }
-
- me.allQuery = me.vg;
-
- me.callParent();
- },
-
- setVG: function(myvg) {
- var me = this;
-
- me.vg = myvg;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'lv' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/lvmthin'
- }
- });
-
- store.sort('lv', 'ASC');
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- loadingText: gettext('Scanning...')
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.BaseVGSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveBaseVGSelector',
-
- valueField: 'vg',
- displayField: 'vg',
- queryMode: 'local',
- editable: false,
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: {},
- fields: [ 'vg', 'size', 'free'],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/lvm'
- }
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- loadingText: gettext('Scanning...')
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.LvmThinInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_lvmthin',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [];
-
- var vgnameField = Ext.createWidget(me.isCreate ? 'textfield' : 'displayfield', {
- name: 'vgname',
- hidden: !!me.isCreate,
- disabled: !!me.isCreate,
- value: '',
- fieldLabel: gettext('Volume group'),
- allowBlank: false
- });
-
- var thinpoolField = Ext.createWidget(me.isCreate ? 'textfield' : 'displayfield', {
- name: 'thinpool',
- hidden: !!me.isCreate,
- disabled: !!me.isCreate,
- value: '',
- fieldLabel: gettext('Thin Pool'),
- allowBlank: false
- });
-
- if (me.isCreate) {
- var vgField = Ext.create('PVE.storage.TPoolSelector', {
- name: 'thinpool',
- fieldLabel: gettext('Thin Pool'),
- allowBlank: false
- });
-
- me.column1.push({
- xtype: 'pveBaseVGSelector',
- name: 'vgname',
- fieldLabel: gettext('Volume group'),
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- vgField.setVG(value);
- vgField.setValue('');
- }
- }
- }
- });
-
- me.column1.push(vgField);
- }
-
- me.column1.push(vgnameField);
-
- me.column1.push(thinpoolField);
-
- // here value is an array,
- // while before it was a string
- /*jslint confusion: true*/
- me.column1.push({
- xtype: 'pveContentTypeSelector',
- cts: ['images', 'rootdir'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: ['images', 'rootdir'],
- multiSelect: true,
- allowBlank: false
- });
- /*jslint confusion: false*/
-
- me.column2 = [];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.storage.CephFSInputPanel', {
- extend: 'PVE.panel.StorageBase',
- controller: 'cephstorage',
-
- onlineHelp: 'storage_cephfs',
-
- viewModel: {
- type: 'cephstorage'
- },
-
- setValues: function(values) {
- if (values.monhost) {
- this.viewModel.set('pveceph', false);
- this.lookupReference('pvecephRef').setValue(false);
- this.lookupReference('pvecephRef').resetOriginalValue();
- }
- this.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
- me.type = 'cephfs';
-
- me.column1 = [];
-
- me.column1.push(
- {
- xtype: 'textfield',
- name: 'monhost',
- vtype: 'HostList',
- value: '',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}',
- hidden: '{pveceph}'
- },
- fieldLabel: 'Monitor(s)',
- allowBlank: false
- },
- {
- xtype: 'displayfield',
- reference: 'monhost',
- bind: {
- disabled: '{!pveceph}',
- hidden: '{!pveceph}'
- },
- value: '',
- fieldLabel: 'Monitor(s)'
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'username',
- value: 'admin',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}'
- },
- fieldLabel: gettext('User name'),
- allowBlank: true
- }
- );
-
- me.column2 = [
- {
- xtype: 'pveContentTypeSelector',
- cts: ['backup', 'iso', 'vztmpl', 'snippets'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: 'backup',
- multiSelect: true,
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- }
- ];
-
- me.columnB = [{
- xtype: 'proxmoxcheckbox',
- name: 'pveceph',
- reference: 'pvecephRef',
- bind : {
- disabled: '{!pvecephPossible}',
- value: '{pveceph}'
- },
- checked: true,
- uncheckedValue: 0,
- submitValue: false,
- hidden: !me.isCreate,
- boxLabel: gettext('Use Proxmox VE managed hyper-converged cephFS')
- }];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.storage.Ceph.Model', {
- extend: 'Ext.app.ViewModel',
- alias: 'viewmodel.cephstorage',
-
- data: {
- pveceph: true,
- pvecephPossible: true
- }
-});
-
-Ext.define('PVE.storage.Ceph.Controller', {
- extend: 'PVE.controller.StorageEdit',
- alias: 'controller.cephstorage',
-
- control: {
- '#': {
- afterrender: 'queryMonitors'
- },
- 'textfield[name=username]': {
- disable: 'resetField'
- },
- 'displayfield[name=monhost]': {
- enable: 'queryMonitors'
- },
- 'textfield[name=monhost]': {
- disable: 'resetField',
- enable: 'resetField'
- }
- },
- resetField: function(field) {
- field.reset();
- },
- queryMonitors: function(field, newVal, oldVal) {
- // we get called with two signatures, the above one for a field
- // change event and the afterrender from the view, this check only
- // can be true for the field change one and omit the API request if
- // pveceph got unchecked - as it's not needed there.
- if (field && !newVal && oldVal) {
- return;
- }
- var view = this.getView();
- var vm = this.getViewModel();
- if (!(view.isCreate || vm.get('pveceph'))) {
- return; // only query on create or if editing a pveceph store
- }
-
- var monhostField = this.lookupReference('monhost');
-
- Proxmox.Utils.API2Request({
- url: '/api2/json/nodes/localhost/ceph/mon',
- method: 'GET',
- scope: this,
- callback: function(options, success, response) {
- var data = response.result.data;
- if (response.status === 200) {
- if (data.length > 0) {
- var monhost = Ext.Array.pluck(data, 'name').sort().join(',');
- monhostField.setValue(monhost);
- monhostField.resetOriginalValue();
- if (view.isCreate) {
- vm.set('pvecephPossible', true);
- }
- } else {
- vm.set('pveceph', false);
- }
- } else {
- vm.set('pveceph', false);
- vm.set('pvecephPossible', false);
- }
- }
- });
- }
-});
-
-Ext.define('PVE.storage.RBDInputPanel', {
- extend: 'PVE.panel.StorageBase',
- controller: 'cephstorage',
-
- onlineHelp: 'ceph_rados_block_devices',
-
- viewModel: {
- type: 'cephstorage'
- },
-
- setValues: function(values) {
- if (values.monhost) {
- this.viewModel.set('pveceph', false);
- this.lookupReference('pvecephRef').setValue(false);
- this.lookupReference('pvecephRef').resetOriginalValue();
- }
- this.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
- me.type = 'rbd';
-
- me.column1 = [];
-
- if (me.isCreate) {
- me.column1.push({
- xtype: 'pveCephPoolSelector',
- nodename: me.nodename,
- name: 'pool',
- bind: {
- disabled: '{!pveceph}',
- submitValue: '{pveceph}',
- hidden: '{!pveceph}'
- },
- fieldLabel: gettext('Pool'),
- allowBlank: false
- },{
- xtype: 'textfield',
- name: 'pool',
- value: 'rbd',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}',
- hidden: '{pveceph}'
- },
- fieldLabel: gettext('Pool'),
- allowBlank: false
- });
- } else {
- me.column1.push({
- xtype: 'displayfield',
- nodename: me.nodename,
- name: 'pool',
- fieldLabel: gettext('Pool'),
- allowBlank: false
- });
- }
-
- me.column1.push(
- {
- xtype: 'textfield',
- name: 'monhost',
- vtype: 'HostList',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}',
- hidden: '{pveceph}'
- },
- value: '',
- fieldLabel: 'Monitor(s)',
- allowBlank: false
- },
- {
- xtype: 'displayfield',
- reference: 'monhost',
- bind: {
- disabled: '{!pveceph}',
- hidden: '{!pveceph}'
- },
- value: '',
- fieldLabel: 'Monitor(s)'
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'username',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}'
- },
- value: 'admin',
- fieldLabel: gettext('User name'),
- allowBlank: true
- }
- );
-
- me.column2 = [
- {
- xtype: 'pveContentTypeSelector',
- cts: ['images', 'rootdir'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: ['images'],
- multiSelect: true,
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'krbd',
- uncheckedValue: 0,
- fieldLabel: 'KRBD'
- }
- ];
-
- me.columnB = [{
- xtype: 'proxmoxcheckbox',
- name: 'pveceph',
- reference: 'pvecephRef',
- bind : {
- disabled: '{!pvecephPossible}',
- value: '{pveceph}'
- },
- checked: true,
- uncheckedValue: 0,
- submitValue: false,
- hidden: !me.isCreate,
- boxLabel: gettext('Use Proxmox VE managed hyper-converged ceph pool')
- }];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.SheepdogInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onGetValues: function(values) {
- var me = this;
-
- if (me.isCreate) {
- values.content = 'images';
- }
-
- return me.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'portal',
- value: '127.0.0.1:7000',
- fieldLabel: gettext('Gateway'),
- allowBlank: false
- }
- ];
- me.column2 = [];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.storage.ZFSInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- viewModel: {
- parent: null,
- data: {
- isLIO: false,
- isComstar: true,
- hasWriteCacheOption: true
- }
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'field[name=iscsiprovider]': {
- change: 'changeISCSIProvider'
- }
- },
- changeISCSIProvider: function(f, newVal, oldVal) {
- var vm = this.getViewModel();
- vm.set('isLIO', newVal === 'LIO');
- vm.set('isComstar', newVal === 'comstar');
- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt');
- }
- },
-
- onGetValues: function(values) {
- var me = this;
-
- if (me.isCreate) {
- values.content = 'images';
- }
-
- values.nowritecache = values.writecache ? 0 : 1;
- delete values.writecache;
-
- return me.callParent([values]);
- },
-
- setValues: function diff(values) {
- values.writecache = values.nowritecache ? 0 : 1;
- this.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'portal',
- value: '',
- fieldLabel: gettext('Portal'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'pool',
- value: '',
- fieldLabel: gettext('Pool'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'blocksize',
- value: '4k',
- fieldLabel: gettext('Block Size'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'target',
- value: '',
- fieldLabel: gettext('Target'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'comstar_tg',
- value: '',
- fieldLabel: gettext('Target group'),
- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' },
- allowBlank: true
- }
- ];
-
- me.column2 = [
- {
- xtype: me.isCreate ? 'pveiScsiProviderSelector' : 'displayfield',
- name: 'iscsiprovider',
- value: 'comstar',
- fieldLabel: gettext('iSCSI Provider'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'sparse',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: gettext('Thin provision')
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'writecache',
- checked: true,
- bind: me.isCreate ? { disabled: '{!hasWriteCacheOption}' } : { hidden: '{!hasWriteCacheOption}' },
- uncheckedValue: 0,
- fieldLabel: gettext('Write cache')
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'comstar_hg',
- value: '',
- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' },
- fieldLabel: gettext('Host group'),
- allowBlank: true
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'lio_tpg',
- value: '',
- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' },
- allowBlank: false,
- fieldLabel: gettext('Target portal group')
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.ZFSPoolSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveZFSPoolSelector',
- valueField: 'pool',
- displayField: 'pool',
- queryMode: 'local',
- editable: false,
- listConfig: {
- loadingText: gettext('Scanning...')
- },
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: {}, // true,
- fields: [ 'pool', 'size', 'free' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/zfs'
- }
- });
-
- store.sort('pool', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.ZFSPoolInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_zfspool',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [];
-
- if (me.isCreate) {
- me.column1.push(Ext.create('PVE.storage.ZFSPoolSelector', {
- name: 'pool',
- fieldLabel: gettext('ZFS Pool'),
- allowBlank: false
- }));
- } else {
- me.column1.push(Ext.createWidget('displayfield', {
- name: 'pool',
- value: '',
- fieldLabel: gettext('ZFS Pool'),
- allowBlank: false
- }));
- }
-
- // value is an array,
- // while before it was a string
- /*jslint confusion: true*/
- me.column1.push(
- {xtype: 'pveContentTypeSelector',
- cts: ['images', 'rootdir'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: ['images', 'rootdir'],
- multiSelect: true,
- allowBlank: false
- });
- /*jslint confusion: false*/
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'sparse',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: gettext('Thin provision')
- },
- {
- xtype: 'textfield',
- name: 'blocksize',
- emptyText: '8k',
- fieldLabel: gettext('Block Size'),
- allowBlank: true
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.ha.StatusView', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveHAStatusView'],
-
- onlineHelp: 'chapter_ha_manager',
-
- sortPriority: {
- quorum: 1,
- master: 2,
- lrm: 3,
- service: 4
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.rstore) {
- throw "no rstore given";
- }
-
- Proxmox.Utils.monStoreErrors(me, me.rstore);
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: me.rstore,
- sortAfterUpdate: true,
- sorters: [{
- sorterFn: function(rec1, rec2) {
- var p1 = me.sortPriority[rec1.data.type];
- var p2 = me.sortPriority[rec2.data.type];
- return (p1 !== p2) ? ((p1 > p2) ? 1 : -1) : 0;
- }
- }],
- filters: {
- property: 'type',
- value: 'service',
- operator: '!='
- }
- });
-
- Ext.apply(me, {
- store: store,
- stateful: false,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Type'),
- width: 80,
- dataIndex: 'type'
- },
- {
- header: gettext('Status'),
- width: 80,
- flex: 1,
- dataIndex: 'status'
- }
- ]
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
-
- }
-}, function() {
-
- Ext.define('pve-ha-status', {
- extend: 'Ext.data.Model',
- fields: [
- 'id', 'type', 'node', 'status', 'sid',
- 'state', 'group', 'comment',
- 'max_restart', 'max_relocate', 'type',
- 'crm_state', 'request_state'
- ],
- idProperty: 'id'
- });
-
-});
-Ext.define('PVE.ha.Status', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveHAStatus',
-
- onlineHelp: 'chapter_ha_manager',
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- initComponent: function() {
- var me = this;
-
- me.rstore = Ext.create('Proxmox.data.ObjectStore', {
- interval: me.interval,
- model: 'pve-ha-status',
- storeid: 'pve-store-' + (++Ext.idSeed),
- groupField: 'type',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/ha/status/current'
- }
- });
-
- me.items = [{
- xtype: 'pveHAStatusView',
- title: gettext('Status'),
- rstore: me.rstore,
- border: 0,
- collapsible: true,
- padding: '0 0 20 0'
- },{
- xtype: 'pveHAResourcesView',
- flex: 1,
- collapsible: true,
- title: gettext('Resources'),
- border: 0,
- rstore: me.rstore
- }];
-
- me.callParent();
- me.on('activate', me.rstore.startUpdate);
- }
-});
-Ext.define('PVE.ha.GroupSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveHAGroupSelector'],
-
- value: [],
- autoSelect: false,
- valueField: 'group',
- displayField: 'group',
- listConfig: {
- columns: [
- {
- header: gettext('Group'),
- width: 100,
- sortable: true,
- dataIndex: 'group'
- },
- {
- header: gettext('Nodes'),
- width: 100,
- sortable: false,
- dataIndex: 'nodes'
- },
- {
- header: gettext('Comment'),
- flex: 1,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode
- }
- ]
- },
- store: {
- model: 'pve-ha-groups',
- sorters: {
- property: 'group',
- order: 'DESC'
- }
- },
-
- initComponent: function() {
- var me = this;
- me.callParent();
- me.getStore().load();
- }
-
-}, function() {
-
- Ext.define('pve-ha-groups', {
- extend: 'Ext.data.Model',
- fields: [
- 'group', 'type', 'digest', 'nodes', 'comment',
- {
- name : 'restricted',
- type: 'boolean'
- },
- {
- name : 'nofailback',
- type: 'boolean'
- }
- ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/ha/groups"
- },
- idProperty: 'group'
- });
-});
-Ext.define('PVE.ha.VMResourceInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- onlineHelp: 'ha_manager_resource_config',
- vmid: undefined,
-
- onGetValues: function(values) {
- var me = this;
-
- if (values.vmid) {
- values.sid = values.vmid;
- }
- delete values.vmid;
-
- PVE.Utils.delete_if_default(values, 'group', '', me.isCreate);
- PVE.Utils.delete_if_default(values, 'max_restart', '1', me.isCreate);
- PVE.Utils.delete_if_default(values, 'max_relocate', '1', me.isCreate);
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
- var MIN_QUORUM_VOTES = 3;
-
- var disabledHint = Ext.createWidget({
- xtype: 'displayfield', // won't get submitted by default
- userCls: 'pve-hint',
- value: 'Disabling the resource will stop the guest system. ' +
- 'See the online help for details.',
- hidden: true
- });
-
- var fewVotesHint = Ext.createWidget({
- itemId: 'fewVotesHint',
- xtype: 'displayfield',
- userCls: 'pve-hint',
- value: 'At least three quorum votes are recommended for reliable HA.',
- hidden: true
- });
-
- Proxmox.Utils.API2Request({
- url: '/cluster/config/nodes',
- method: 'GET',
- failure: function(response) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response) {
- var nodes = response.result.data;
- var votes = 0;
- Ext.Array.forEach(nodes, function(node) {
- var vote = parseInt(node.quorum_votes, 10); // parse as base 10
- votes += vote || 0; // parseInt might return NaN, which is false
- });
-
- if (votes < MIN_QUORUM_VOTES) {
- fewVotesHint.setVisible(true);
- }
- }
- });
-
- /*jslint confusion: true */
- var vmidStore = (me.vmid) ? {} : {
- model: 'PVEResources',
- autoLoad: true,
- sorters: 'vmid',
- filters: [
- {
- property: 'type',
- value: /lxc|qemu/
- },
- {
- property: 'hastate',
- value: /unmanaged/
- }
- ]
- };
-
- // value is a string above, but a number below
- me.column1 = [
- {
- xtype: me.vmid ? 'displayfield' : 'vmComboSelector',
- submitValue: me.isCreate,
- name: 'vmid',
- fieldLabel: (me.vmid && me.guestType === 'ct') ? 'CT' : 'VM',
- value: me.vmid,
- store: vmidStore,
- validateExists: true
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'max_restart',
- fieldLabel: gettext('Max. Restart'),
- value: 1,
- minValue: 0,
- maxValue: 10,
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'max_relocate',
- fieldLabel: gettext('Max. Relocate'),
- value: 1,
- minValue: 0,
- maxValue: 10,
- allowBlank: false
- }
- ];
- /*jslint confusion: false */
-
- me.column2 = [
- {
- xtype: 'pveHAGroupSelector',
- name: 'group',
- fieldLabel: gettext('Group')
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'state',
- value: 'started',
- fieldLabel: gettext('Request State'),
- comboItems: [
- ['started', 'started'],
- ['stopped', 'stopped'],
- ['ignored', 'ignored'],
- ['disabled', 'disabled']
- ],
- listeners: {
- 'change': function(field, newValue) {
- if (newValue === 'disabled') {
- disabledHint.setVisible(true);
- }
- else {
- if (disabledHint.isVisible()) {
- disabledHint.setVisible(false);
- }
- }
- }
- }
- },
- disabledHint
- ];
-
- me.columnB = [
- {
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- },
- fewVotesHint
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.ha.VMResourceEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmid: undefined,
- guestType: undefined,
- isCreate: undefined,
-
- initComponent : function() {
- var me = this;
-
- if (me.isCreate === undefined) {
- me.isCreate = !me.vmid;
- }
-
- if (me.isCreate) {
- me.url = '/api2/extjs/cluster/ha/resources';
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs/cluster/ha/resources/' + me.vmid;
- me.method = 'PUT';
- }
-
- var ipanel = Ext.create('PVE.ha.VMResourceInputPanel', {
- isCreate: me.isCreate,
- vmid: me.vmid,
- guestType: me.guestType
- });
-
- Ext.apply(me, {
- subject: gettext('Resource') + ': ' + gettext('Container') +
- '/' + gettext('Virtual Machine'),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
-
- var regex = /^(\S+):(\S+)$/;
- var res = regex.exec(values.sid);
-
- if (res[1] !== 'vm' && res[1] !== 'ct') {
- throw "got unexpected resource type";
- }
-
- values.vmid = res[2];
-
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-Ext.define('PVE.ha.ResourcesView', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveHAResourcesView'],
-
- onlineHelp: 'ha_manager_resources',
-
- stateful: true,
- stateId: 'grid-ha-resources',
-
- initComponent : function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- if (!me.rstore) {
- throw "no store given";
- }
-
- Proxmox.Utils.monStoreErrors(me, me.rstore);
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: me.rstore,
- filters: {
- property: 'type',
- value: 'service'
- }
- });
-
- var reload = function() {
- me.rstore.load();
- };
-
- var render_error = function(dataIndex, value, metaData, record) {
- var errors = record.data.errors;
- if (errors) {
- var msg = errors[dataIndex];
- if (msg) {
- metaData.tdCls = 'proxmox-invalid-row';
- var html = '' + Ext.htmlEncode(msg) + '
';
- metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
- html.replace(/\"/g,'"') + '"';
- }
- }
- return value;
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- var sid = rec.data.sid;
-
- var regex = /^(\S+):(\S+)$/;
- var res = regex.exec(sid);
-
- if (res[1] !== 'vm' && res[1] !== 'ct') {
- return;
- }
- var guestType = res[1];
- var vmid = res[2];
-
- var win = Ext.create('PVE.ha.VMResourceEdit',{
- guestType: guestType,
- vmid: vmid
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/cluster/ha/resources/',
- getUrl: function(rec) {
- var me = this;
- return me.baseurl + '/' + rec.get('sid');
- },
- callback: function() {
- reload();
- }
- });
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- viewConfig: {
- trackOver: false
- },
- tbar: [
- {
- text: gettext('Add'),
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.ha.VMResourceEdit',{});
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn
- ],
-
- columns: [
- {
- header: 'ID',
- width: 100,
- sortable: true,
- dataIndex: 'sid'
- },
- {
- header: gettext('State'),
- width: 100,
- sortable: true,
- dataIndex: 'state'
- },
- {
- header: gettext('Node'),
- width: 100,
- sortable: true,
- dataIndex: 'node'
- },
- {
- header: gettext('Request State'),
- width: 100,
- hidden: true,
- sortable: true,
- renderer: function(v) {
- return v || 'started';
- },
- dataIndex: 'request_state'
- },
- {
- header: gettext('CRM State'),
- width: 100,
- hidden: true,
- sortable: true,
- dataIndex: 'crm_state'
- },
- {
- header: gettext('Max. Restart'),
- width: 100,
- sortable: true,
- renderer: function(v) {
- return v || '1';
- },
- dataIndex: 'max_restart'
- },
- {
- header: gettext('Max. Relocate'),
- width: 100,
- sortable: true,
- renderer: function(v) {
- return v || '1';
- },
- dataIndex: 'max_relocate'
- },
- {
- header: gettext('Group'),
- width: 200,
- sortable: true,
- renderer: function(value, metaData, record) {
- return render_error('group', value, metaData, record);
- },
- dataIndex: 'group'
- },
- {
- header: gettext('Description'),
- flex: 1,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment'
- }
- ],
- listeners: {
- beforeselect: function(grid, record, index, eOpts) {
- if (!caps.nodes['Sys.Console']) {
- return false;
- }
- },
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-ha-resources', {
- extend: 'Ext.data.Model',
- fields: [
- 'sid', 'state', 'digest', 'errors', 'group', 'comment',
- 'max_restart', 'max_relocate', 'type', 'status', 'node',
- 'crm_state', 'request_state'
- ],
- idProperty: 'sid'
- });
-
-});
-Ext.define('PVE.ha.GroupInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- onlineHelp: 'ha_manager_groups',
-
- groupId: undefined,
-
- onGetValues: function(values) {
- var me = this;
-
- if (me.isCreate) {
- values.type = 'group';
- }
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
-
- var update_nodefield, update_node_selection;
-
- var sm = Ext.create('Ext.selection.CheckboxModel', {
- mode: 'SIMPLE',
- listeners: {
- selectionchange: function(model, selected) {
- update_nodefield(selected);
- }
- }
- });
-
- // use already cached data to avoid an API call
- var data = PVE.data.ResourceStore.getNodes();
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'node', 'mem', 'cpu', 'priority' ],
- data: data,
- proxy: {
- type: 'memory',
- reader: {type: 'json'}
- },
- sorters: [
- {
- property : 'node',
- direction: 'ASC'
- }
- ]
- });
-
- var nodegrid = Ext.createWidget('grid', {
- store: store,
- border: true,
- height: 300,
- selModel: sm,
- columns: [
- {
- header: gettext('Node'),
- flex: 1,
- dataIndex: 'node'
- },
- {
- header: gettext('Memory usage') + " %",
- renderer: PVE.Utils.render_mem_usage_percent,
- sortable: true,
- width: 150,
- dataIndex: 'mem'
- },
- {
- header: gettext('CPU usage'),
- renderer: PVE.Utils.render_cpu,
- sortable: true,
- width: 150,
- dataIndex: 'cpu'
- },
- {
- header: 'Priority',
- xtype: 'widgetcolumn',
- dataIndex: 'priority',
- sortable: true,
- stopSelection: true,
- widget: {
- xtype: 'proxmoxintegerfield',
- minValue: 0,
- maxValue: 1000,
- isFormField: false,
- listeners: {
- change: function(numberfield, value, old_value) {
- var record = numberfield.getWidgetRecord();
- record.set('priority', value);
- update_nodefield(sm.getSelection());
- }
- }
- }
- }
- ]
- });
-
- var nodefield = Ext.create('Ext.form.field.Hidden', {
- name: 'nodes',
- value: '',
- listeners: {
- change: function (nodefield, value) {
- update_node_selection(value);
- }
- },
- isValid: function () {
- var value = nodefield.getValue();
- return (value && 0 !== value.length);
- }
- });
-
- update_node_selection = function(string) {
- sm.deselectAll(true);
-
- string.split(',').forEach(function (e, idx, array) {
- var res = e.split(':');
-
- store.each(function(record) {
- var node = record.get('node');
-
- if (node == res[0]) {
- sm.select(record, true);
- record.set('priority', res[1]);
- record.commit();
- }
- });
- });
- nodegrid.reconfigure(store);
-
- };
-
- update_nodefield = function(selected) {
- var nodes = '';
- var first_iteration = true;
- Ext.Array.each(selected, function(record) {
- if (!first_iteration) {
- nodes += ',';
- }
- first_iteration = false;
-
- nodes += record.data.node;
- if (record.data.priority) {
- nodes += ':' + record.data.priority;
- }
- });
-
- // nodefield change listener calls us again, which results in a
- // endless recursion, suspend the event temporary to avoid this
- nodefield.suspendEvent('change');
- nodefield.setValue(nodes);
- nodefield.resumeEvent('change');
- };
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'group',
- value: me.groupId || '',
- fieldLabel: 'ID',
- vtype: 'StorageId',
- allowBlank: false
- },
- nodefield
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'restricted',
- uncheckedValue: 0,
- fieldLabel: 'restricted'
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'nofailback',
- uncheckedValue: 0,
- fieldLabel: 'nofailback'
- }
- ];
-
- me.columnB = [
- {
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- },
- nodegrid
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.ha.GroupEdit', {
- extend: 'Proxmox.window.Edit',
-
- groupId: undefined,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.groupId;
-
- if (me.isCreate) {
- me.url = '/api2/extjs/cluster/ha/groups';
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs/cluster/ha/groups/' + me.groupId;
- me.method = 'PUT';
- }
-
- var ipanel = Ext.create('PVE.ha.GroupInputPanel', {
- isCreate: me.isCreate,
- groupId: me.groupId
- });
-
- Ext.apply(me, {
- subject: gettext('HA Group'),
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
-
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-Ext.define('PVE.ha.GroupsView', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveHAGroupsView'],
-
- onlineHelp: 'ha_manager_groups',
-
- stateful: true,
- stateId: 'grid-ha-groups',
-
- initComponent : function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var store = new Ext.data.Store({
- model: 'pve-ha-groups',
- sorters: {
- property: 'group',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
-
- var win = Ext.create('PVE.ha.GroupEdit',{
- groupId: rec.data.group
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/cluster/ha/groups/',
- callback: function() {
- reload();
- }
- });
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- viewConfig: {
- trackOver: false
- },
- tbar: [
- {
- text: gettext('Create'),
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.ha.GroupEdit',{});
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn
- ],
- columns: [
- {
- header: gettext('Group'),
- width: 150,
- sortable: true,
- dataIndex: 'group'
- },
- {
- header: 'restricted',
- width: 100,
- sortable: true,
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'restricted'
- },
- {
- header: 'nofailback',
- width: 100,
- sortable: true,
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'nofailback'
- },
- {
- header: gettext('Nodes'),
- flex: 1,
- sortable: false,
- dataIndex: 'nodes'
- },
- {
- header: gettext('Comment'),
- flex: 1,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment'
- }
- ],
- listeners: {
- activate: reload,
- beforeselect: function(grid, record, index, eOpts) {
- if (!caps.nodes['Sys.Console']) {
- return false;
- }
- },
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.ha.FencingView', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveFencingView'],
-
- onlineHelp: 'ha_manager_fencing',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-ha-fencing',
- data: []
- });
-
- Ext.apply(me, {
- store: store,
- stateful: false,
- viewConfig: {
- trackOver: false,
- deferEmptyText: false,
- emptyText: 'Use watchdog based fencing.'
- },
- columns: [
- {
- header: 'Node',
- width: 100,
- sortable: true,
- dataIndex: 'node'
- },
- {
- header: gettext('Command'),
- flex: 1,
- dataIndex: 'command'
- }
- ]
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-ha-fencing', {
- extend: 'Ext.data.Model',
- fields: [
- 'node', 'command', 'digest'
- ]
- });
-
-});
-Ext.define('PVE.dc.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveDcSummary',
-
- scrollable: true,
-
- bodyPadding: 5,
-
- layout: 'column',
-
- defaults: {
- padding: 5,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- }
- },
-
- items: [
- {
- itemId: 'dcHealth',
- xtype: 'pveDcHealth'
- },
- {
- itemId: 'dcGuests',
- xtype: 'pveDcGuests'
- },
- {
- title: gettext('Resources'),
- xtype: 'panel',
- minHeight: 250,
- bodyPadding: 5,
- layout: 'hbox',
- defaults: {
- xtype: 'proxmoxGauge',
- flex: 1
- },
- items:[
- {
- title: gettext('CPU'),
- itemId: 'cpu'
- },
- {
- title: gettext('Memory'),
- itemId: 'memory'
- },
- {
- title: gettext('Storage'),
- itemId: 'storage'
- }
- ]
- },
- {
- itemId: 'nodeview',
- xtype: 'pveDcNodeView',
- height: 250
- },
- {
- title: gettext('Subscriptions'),
- height: 220,
- items: [
- {
- itemId: 'subscriptions',
- xtype: 'pveHealthWidget',
- userCls: 'pointer',
- listeners: {
- element: 'el',
- click: function() {
- if (this.component.userCls === 'pointer') {
- window.open('https://www.proxmox.com/en/proxmox-ve/pricing', '_blank');
- }
- }
- }
- }
- ]
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- var rstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 3000,
- storeid: 'pve-cluster-status',
- model: 'pve-dc-nodes',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/status"
- }
- });
-
- var gridstore = Ext.create('Proxmox.data.DiffStore', {
- rstore: rstore,
- filters: {
- property: 'type',
- value: 'node'
- },
- sorters: {
- property: 'id',
- direction: 'ASC'
- }
- });
-
- me.callParent();
-
- me.getComponent('nodeview').setStore(gridstore);
-
- var gueststatus = me.getComponent('dcGuests');
-
- var cpustat = me.down('#cpu');
- var memorystat = me.down('#memory');
- var storagestat = me.down('#storage');
- var sp = Ext.state.Manager.getProvider();
-
- me.mon(PVE.data.ResourceStore, 'load', function(curstore, results) {
- me.suspendLayout = true;
-
- var cpu = 0;
- var maxcpu = 0;
-
- var nodes = 0;
-
- var memory = 0;
- var maxmem = 0;
-
- var countedStorages = {};
- var used = 0;
- var total = 0;
- var usableStorages = {};
- var storages = sp.get('dash-storages') || '';
- storages.split(',').forEach(function(storage){
- if (storage !== '') {
- usableStorages[storage] = true;
- }
- });
-
- var qemu = {
- running: 0,
- paused: 0,
- stopped: 0,
- template: 0
- };
- var lxc = {
- running: 0,
- paused: 0,
- stopped: 0,
- template: 0
- };
- var error = 0;
-
- var i;
-
- for (i = 0; i < results.length; i++) {
- var item = results[i];
- switch(item.data.type) {
- case 'node':
- cpu += (item.data.cpu * item.data.maxcpu);
- maxcpu += item.data.maxcpu || 0;
- memory += item.data.mem || 0;
- maxmem += item.data.maxmem || 0;
- nodes++;
-
- // update grid also
- var griditem = gridstore.getById(item.data.id);
- if (griditem) {
- griditem.set('cpuusage', item.data.cpu);
- var max = item.data.maxmem || 1;
- var val = item.data.mem || 0;
- griditem.set('memoryusage', val/max);
- griditem.set('uptime', item.data.uptime);
- griditem.commit(); //else it marks the fields as dirty
- }
- break;
- case 'storage':
- if (!Ext.Object.isEmpty(usableStorages)) {
- if (usableStorages[item.data.id] === true) {
- used += item.data.disk;
- total += item.data.maxdisk;
- }
- break;
- }
- if (!countedStorages[item.data.storage] ||
- (item.data.storage === 'local' &&
- !countedStorages[item.data.id])) {
- used += item.data.disk;
- total += item.data.maxdisk;
-
- countedStorages[item.data.storage === 'local'?item.data.id:item.data.storage] = true;
- }
- break;
- case 'qemu':
- qemu[item.data.template ? 'template' : item.data.status]++;
- if (item.data.hastate === 'error') {
- error++;
- }
- break;
- case 'lxc':
- lxc[item.data.template ? 'template' : item.data.status]++;
- if (item.data.hastate === 'error') {
- error++;
- }
- break;
- default: break;
- }
- }
-
- var text = Ext.String.format(gettext('of {0} CPU(s)'), maxcpu);
- cpustat.updateValue((cpu/maxcpu), text);
-
- text = Ext.String.format(gettext('{0} of {1}'), PVE.Utils.render_size(memory), PVE.Utils.render_size(maxmem));
- memorystat.updateValue((memory/maxmem), text);
-
- text = Ext.String.format(gettext('{0} of {1}'), PVE.Utils.render_size(used), PVE.Utils.render_size(total));
- storagestat.updateValue((used/total), text);
-
- gueststatus.updateValues(qemu,lxc,error);
-
- me.suspendLayout = false;
- me.updateLayout(true);
- });
-
- var dcHealth = me.getComponent('dcHealth');
- me.mon(rstore, 'load', dcHealth.updateStatus, dcHealth);
-
- var subs = me.down('#subscriptions');
- me.mon(rstore, 'load', function(store, records, success) {
- var i;
- var level;
- var curlevel;
- for (i = 0; i < records.length; i++) {
- if (records[i].get('type') !== 'node') {
- continue;
- }
-
- curlevel = records[i].get('level');
- if (level === undefined || !curlevel) {
- level = curlevel;
- continue;
- }
-
- if (level !== curlevel) {
- break;
- }
- }
-
- if (level === '') {
- subs.setData({
- title: gettext('No Subscription'),
- iconCls: PVE.Utils.get_health_icon('critical', true),
- text: gettext('You have at least one node without subscription.')
- });
- subs.setUserCls('pointer');
- } else if (level !== curlevel) {
- subs.setData({
- title: gettext('Mixed Subscriptions'),
- iconCls: PVE.Utils.get_health_icon('warning', true),
- text: gettext('Warning: Your subscription levels are not the same.')
- });
- subs.setUserCls('pointer');
- } else {
- subs.setData({
- title: PVE.Utils.render_support_level(level),
- iconCls: PVE.Utils.get_health_icon('good', true),
- text: gettext('Your subscription status is valid.')
- });
- subs.setUserCls('');
- }
- });
-
- me.on('destroy', function(){
- rstore.stopUpdate();
- });
-
- rstore.startUpdate();
- }
-
-});
-Ext.define('PVE.window.ReplicaEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveReplicaEdit',
-
- subject: gettext('Replication Job'),
-
-
- url: '/cluster/replication',
- method: 'POST',
-
- initComponent: function() {
- var me = this;
-
- var vmid = me.pveSelNode.data.vmid;
- var nodename = me.pveSelNode.data.node;
-
- var items = [];
-
- items.push({
- xtype: (me.isCreate && !vmid)?'pveGuestIDSelector':'displayfield',
- name: 'guest',
- fieldLabel: 'CT/VM ID',
- value: vmid || ''
- });
-
- items.push(
- {
- xtype: me.isCreate ? 'pveNodeSelector':'displayfield',
- name: 'target',
- disallowedNodes: [nodename],
- allowBlank: false,
- onlineValidator: true,
- fieldLabel: gettext("Target")
- },
- {
- xtype: 'pveCalendarEvent',
- fieldLabel: gettext('Schedule'),
- emptyText: '*/15 - ' + Ext.String.format(gettext('Every {0} minutes'), 15),
- name: 'schedule'
- },
- {
- xtype: 'numberfield',
- fieldLabel: gettext('Rate limit') + ' (MB/s)',
- step: 1,
- minValue: 1,
- emptyText: gettext('unlimited'),
- name: 'rate'
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Comment'),
- name: 'comment'
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'enabled',
- defaultValue: 'on',
- checked: true,
- fieldLabel: gettext('Enabled')
- }
- );
-
- me.items = [
- {
- xtype: 'inputpanel',
- itemId: 'ipanel',
- onlineHelp: 'pvesr_schedule_time_format',
-
- onGetValues: function(values) {
- var me = this.up('window');
-
- values.disable = values.enabled ? 0 : 1;
- delete values.enabled;
-
- PVE.Utils.delete_if_default(values, 'rate', '', me.isCreate);
- PVE.Utils.delete_if_default(values, 'disable', 0, me.isCreate);
- PVE.Utils.delete_if_default(values, 'schedule', '*/15', me.isCreate);
- PVE.Utils.delete_if_default(values, 'comment', '', me.isCreate);
-
- if (me.isCreate) {
- values.type = 'local';
- var vm = vmid || values.guest;
- var id = -1;
- if (me.highestids[vm] !== undefined) {
- id = me.highestids[vm];
- }
- id++;
- values.id = vm + '-' + id.toString();
- delete values.guest;
- }
- return values;
- },
- items: items
- }
- ];
-
- me.callParent();
-
- if (me.isCreate) {
- me.load({
- success: function(response) {
- var jobs = response.result.data;
- var highestids = {};
- Ext.Array.forEach(jobs, function(job) {
- var match = /^([0-9]+)\-([0-9]+)$/.exec(job.id);
- if (match) {
- var vmid = parseInt(match[1],10);
- var id = parseInt(match[2],10);
- if (highestids[vmid] < id ||
- highestids[vmid] === undefined) {
- highestids[vmid] = id;
- }
- }
- });
-
- me.highestids = highestids;
- }
- });
-
- } else {
- me.load({
- success: function(response, options) {
- response.result.data.enabled = !response.result.data.disable;
- me.setValues(response.result.data);
- me.digest = response.result.data.digest;
- }
- });
- }
- }
-});
-
-/*jslint confusion: true */
-/* callback is a function and string */
-Ext.define('PVE.grid.ReplicaView', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveReplicaView',
-
- onlineHelp: 'chapter_pvesr',
-
- stateful: true,
- stateId: 'grid-pve-replication-status',
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- addJob: function(button,event,rec) {
- var me = this.getView();
- var controller = this;
- var win = Ext.create('PVE.window.ReplicaEdit', {
- isCreate: true,
- method: 'POST',
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', function() { controller.reload(); });
- win.show();
- },
-
- editJob: function(button,event,rec) {
- var me = this.getView();
- var controller = this;
- var data = rec.data;
- var win = Ext.create('PVE.window.ReplicaEdit', {
- url: '/cluster/replication/' + data.id,
- method: 'PUT',
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', function() { controller.reload(); });
- win.show();
- },
-
- scheduleJobNow: function(button,event,rec) {
- var me = this.getView();
- var controller = this;
-
- Proxmox.Utils.API2Request({
- url: "/api2/extjs/nodes/" + me.nodename + "/replication/" + rec.data.id + "/schedule_now",
- method: 'POST',
- waitMsgTarget: me,
- callback: function() { controller.reload(); },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- showLog: function(button, event, rec) {
- var me = this.getView();
- var controller = this;
- var logView = Ext.create('Proxmox.panel.LogView', {
- border: false,
- url: "/api2/extjs/nodes/" + me.nodename + "/replication/" + rec.data.id + "/log"
- });
- var win = Ext.create('Ext.window.Window', {
- items: [ logView ],
- layout: 'fit',
- width: 800,
- height: 400,
- modal: true,
- title: gettext("Replication Log")
- });
- var task = {
- run: function() {
- logView.requestUpdate();
- },
- interval: 1000
- };
- Ext.TaskManager.start(task);
- win.on('destroy', function() {
- Ext.TaskManager.stop(task);
- controller.reload();
- });
- win.show();
- },
-
- reload: function() {
- var me = this.getView();
- me.rstore.load();
- },
-
- dblClick: function(grid, record, item) {
- var me = this;
- me.editJob(undefined, undefined, record);
- },
-
- // check for cluster
- // currently replication is for cluster only, so we disable the whole
- // component
- checkPrerequisites: function() {
- var me = this.getView();
- if (PVE.data.ResourceStore.getNodes().length < 2) {
- me.mask(gettext("Replication needs at least two nodes"), ['pve-static-mask']);
- }
- },
-
- control: {
- '#': {
- itemdblclick: 'dblClick',
- afterlayout: 'checkPrerequisites'
- }
- }
- },
-
- tbar: [
- {
- text: gettext('Add'),
- itemId: 'addButton',
- handler: 'addJob'
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Edit'),
- itemId: 'editButton',
- handler: 'editJob',
- disabled: true
- },
- {
- xtype: 'proxmoxStdRemoveButton',
- itemId: 'removeButton',
- baseurl: '/api2/extjs/cluster/replication/',
- dangerous: true,
- callback: 'reload'
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Log'),
- itemId: 'logButton',
- handler: 'showLog',
- disabled: true
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Schedule now'),
- itemId: 'scheduleNowButton',
- handler: 'scheduleJobNow',
- disabled: true
- }
- ],
-
- initComponent: function() {
- var me = this;
- var mode = '';
- var url = '/cluster/replication';
-
- me.nodename = me.pveSelNode.data.node;
- me.vmid = me.pveSelNode.data.vmid;
-
- me.columns = [
- {
- text: gettext('Enabled'),
- dataIndex: 'enabled',
- xtype: 'checkcolumn',
- sortable: true,
- disabled: true
- },
- {
- text: 'ID',
- dataIndex: 'id',
- width: 60,
- hidden: true
- },
- {
- text: gettext('Guest'),
- dataIndex: 'guest',
- width: 75
- },
- {
- text: gettext('Job'),
- dataIndex: 'jobnum',
- width: 60
- },
- {
- text: gettext('Target'),
- dataIndex: 'target'
- }
- ];
-
- if (!me.nodename) {
- mode = 'dc';
- me.stateId = 'grid-pve-replication-dc';
- } else if (!me.vmid) {
- mode = 'node';
- url = '/nodes/' + me.nodename + '/replication';
- } else {
- mode = 'vm';
- url = '/nodes/' + me.nodename + '/replication' + '?guest=' + me.vmid;
- }
-
- if (mode !== 'dc') {
- me.columns.push(
- {
- text: gettext('Status'),
- dataIndex: 'state',
- minWidth: 160,
- flex: 1,
- renderer: function(value, metadata, record) {
-
- if (record.data.pid) {
- metadata.tdCls = 'x-grid-row-loading';
- return '';
- }
-
- var icons = [];
- var states = [];
-
- if (record.data.remove_job) {
- icons.push(' ');
- states.push(gettext("Removal Scheduled"));
- }
-
- if (record.data.error) {
- icons.push(' ');
- states.push(record.data.error);
- }
-
- if (icons.length == 0) {
- icons.push(' ');
- states.push(gettext('OK'));
- }
-
- return icons.join(',') + ' ' + states.join(',');
- }
- },
- {
- text: gettext('Last Sync'),
- dataIndex: 'last_sync',
- width: 150,
- renderer: function(value, metadata, record) {
- if (!value) {
- return '-';
- }
-
- if (record.data.pid) {
- return gettext('syncing');
- }
-
- return Proxmox.Utils.render_timestamp(value);
- }
- },
- {
- text: gettext('Duration'),
- dataIndex: 'duration',
- width: 60,
- renderer: PVE.Utils.render_duration
- },
- {
- text: gettext('Next Sync'),
- dataIndex: 'next_sync',
- width: 150,
- renderer: function(value) {
- if (!value) {
- return '-';
- }
-
- var now = new Date();
- var next = new Date(value*1000);
-
- if (next < now) {
- return gettext('pending');
- }
-
- return Proxmox.Utils.render_timestamp(value);
- }
- }
- );
- }
-
- me.columns.push(
- {
- text: gettext('Schedule'),
- width: 75,
- dataIndex: 'schedule'
- },
- {
- text: gettext('Rate limit'),
- dataIndex: 'rate',
- renderer: function(value) {
- if (!value) {
- return gettext('unlimited');
- }
-
- return value.toString() + ' MB/s';
- },
- hidden: true
- },
- {
- text: gettext('Comment'),
- dataIndex: 'comment',
- renderer: Ext.htmlEncode
- }
- );
-
- me.rstore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'pve-replica-' + me.nodename + me.vmid,
- model: (mode === 'dc')? 'pve-replication' : 'pve-replication-state',
- interval: 3000,
- proxy: {
- type: 'proxmox',
- url: "/api2/json" + url
- }
- });
-
- me.store = Ext.create('Proxmox.data.DiffStore', {
- rstore: me.rstore,
- sorters: [
- {
- property: 'guest'
- },
- {
- property: 'jobnum'
- }
- ]
- });
-
- me.callParent();
-
- // we cannot access the log and scheduleNow button
- // in the datacenter, because
- // we do not know where/if the jobs runs
- if (mode === 'dc') {
- me.down('#logButton').setHidden(true);
- me.down('#scheduleNowButton').setHidden(true);
- }
-
- // if we set the warning mask, we do not want to load
- // or set the mask on store errors
- if (PVE.data.ResourceStore.getNodes().length < 2) {
- return;
- }
-
- Proxmox.Utils.monStoreErrors(me, me.rstore);
-
- me.on('destroy', me.rstore.stopUpdate);
- me.rstore.startUpdate();
- }
-}, function() {
-
- Ext.define('pve-replication', {
- extend: 'Ext.data.Model',
- fields: [
- 'id', 'target', 'comment', 'rate', 'type',
- { name: 'guest', type: 'integer' },
- { name: 'jobnum', type: 'integer' },
- { name: 'schedule', defaultValue: '*/15' },
- { name: 'disable', defaultValue: '' },
- { name: 'enabled', calculate: function(data) { return !data.disable; } }
- ]
- });
-
- Ext.define('pve-replication-state', {
- extend: 'pve-replication',
- fields: [
- 'last_sync', 'next_sync', 'error', 'duration', 'state',
- 'fail_count', 'remove_job', 'pid'
- ]
- });
-
-});
-Ext.define('PVE.dc.Health', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveDcHealth',
-
- title: gettext('Health'),
-
- bodyPadding: 10,
- height: 220,
- layout: {
- type: 'hbox',
- align: 'stretch'
- },
-
- defaults: {
- flex: 1,
- xtype: 'box',
- style: {
- 'text-align':'center'
- }
- },
-
- nodeList: [],
- nodeIndex: 0,
-
- updateStatus: function(store, records, success) {
- var me = this;
- if (!success) {
- return;
- }
-
- var cluster = {
- iconCls: PVE.Utils.get_health_icon('good', true),
- text: gettext("Standalone node - no cluster defined")
- };
-
- var nodes = {
- online: 0,
- offline: 0
- };
-
- // by default we have one node
- var numNodes = 1;
- var i;
-
- for (i = 0; i < records.length; i++) {
- var item = records[i];
- if (item.data.type === 'node') {
- nodes[item.data.online === 1 ? 'online':'offline']++;
- } else if(item.data.type === 'cluster') {
- cluster.text = gettext("Cluster") + ": ";
- cluster.text += item.data.name + ", ";
- cluster.text += gettext("Quorate") + ": ";
- cluster.text += Proxmox.Utils.format_boolean(item.data.quorate);
- if (item.data.quorate != 1) {
- cluster.iconCls = PVE.Utils.get_health_icon('critical', true);
- }
-
- numNodes = item.data.nodes;
- }
- }
-
- if (numNodes !== (nodes.online + nodes.offline)) {
- nodes.offline = numNodes - nodes.online;
- }
-
- me.getComponent('clusterstatus').updateHealth(cluster);
- me.getComponent('nodestatus').update(nodes);
- },
-
- updateCeph: function(store, records, success) {
- var me = this;
- var cephstatus = me.getComponent('ceph');
- if (!success || records.length < 1) {
-
- // if ceph status is already visible
- // dont stop to update
- if (cephstatus.isVisible()) {
- return;
- }
-
- // try all nodes until we either get a successfull api call,
- // or we tried all nodes
- if (++me.nodeIndex >= me.nodeList.length) {
- me.cephstore.stopUpdate();
- } else {
- store.getProxy().setUrl('/api2/json/nodes/' + me.nodeList[me.nodeIndex].node + '/ceph/status');
- }
-
- return;
- }
-
- var state = PVE.Utils.render_ceph_health(records[0].data.health || {});
- cephstatus.updateHealth(state);
- cephstatus.setVisible(true);
- },
-
- listeners: {
- destroy: function() {
- var me = this;
- me.cephstore.stopUpdate();
- }
- },
-
- items: [
- {
- itemId: 'clusterstatus',
- xtype: 'pveHealthWidget',
- title: gettext('Status')
- },
- {
- itemId: 'nodestatus',
- data: {
- online: 0,
- offline: 0
- },
- tpl: [
- '' + gettext('Nodes') + ' ',
- '',
- '
',
- ' ',
- gettext('Online'),
- '
',
- '
{online}
',
- '
',
- '
',
- ' ',
- gettext('Offline'),
- '
',
- '
{offline}
',
- '
'
- ]
- },
- {
- itemId: 'ceph',
- width: 250,
- columnWidth: undefined,
- userCls: 'pointer',
- title: 'Ceph',
- xtype: 'pveHealthWidget',
- hidden: true,
- listeners: {
- element: 'el',
- click: function() {
- var me = this.component.up('pveDcHealth');
- var sp = Ext.state.Manager.getProvider();
-
- // preselect the ceph tab
- sp.set('nodetab', {value:'ceph'});
-
- // select the node that had the successfull api call
- var id = me.nodeList[me.nodeIndex].id;
- Ext.ComponentQuery.query('pveResourceTree')[0].selectById(id);
- }
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- me.nodeList = PVE.data.ResourceStore.getNodes();
- me.nodeIndex = 0;
- me.cephstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 3000,
- storeid: 'pve-cluster-ceph',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodeList[me.nodeIndex].node + '/ceph/status'
- }
- });
- me.callParent();
- me.mon(me.cephstore, 'load', me.updateCeph, me);
- me.cephstore.startUpdate();
- }
-});
-Ext.define('PVE.dc.Guests', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveDcGuests',
-
-
- title: gettext('Guests'),
- height: 220,
- layout: {
- type: 'table',
- columns: 2,
- tableAttrs: {
- style: {
- width: '100%'
- }
- }
- },
- bodyPadding: '0 20 20 20',
-
- defaults: {
- xtype: 'box',
- padding: '0 50 0 50',
- style: {
- 'text-align':'center',
- 'line-height':'1.2'
- }
- },
- items: [{
- itemId: 'qemu',
- data: {
- running: 0,
- paused: 0,
- stopped: 0,
- template: 0
- },
- tpl: [
- '' + gettext("Virtual Machines") + ' ',
- '',
- ' ',
- gettext('Running'),
- '
',
- '{running}
' + ' ',
- '',
- '',
- ' ',
- gettext('Paused'),
- '
',
- '{paused}
' + ' ',
- ' ',
- '',
- ' ',
- gettext('Stopped'),
- '
',
- '{stopped}
' + ' ',
- '',
- '',
- ' ',
- gettext('Templates'),
- '
',
- '{template}
',
- ' '
- ]
- },{
- itemId: 'lxc',
- data: {
- running: 0,
- paused: 0,
- stopped: 0,
- template: 0
- },
- tpl: [
- '' + gettext("LXC Container") + ' ',
- '',
- ' ',
- gettext('Running'),
- '
',
- '{running}
' + ' ',
- '',
- '',
- ' ',
- gettext('Paused'),
- '
',
- '{paused}
' + ' ',
- ' ',
- '',
- ' ',
- gettext('Stopped'),
- '
',
- '{stopped}
' + ' ',
- '',
- '',
- ' ',
- gettext('Templates'),
- '
',
- '{template}
',
- ' '
- ]
- },{
- itemId: 'error',
- colspan: 2,
- data: {
- num: 0
- },
- columnWidth: 1,
- padding: '10 250 0 250',
- tpl: [
- '',
- '',
- ' ',
- gettext('Error'),
- '
',
- '{num}
',
- ' '
- ]
- }],
-
- updateValues: function(qemu, lxc, error) {
- var me = this;
- me.getComponent('qemu').update(qemu);
- me.getComponent('lxc').update(lxc);
- me.getComponent('error').update({num: error});
- }
-});
- /*jslint confusion: true*/
-Ext.define('PVE.dc.OptionView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveDcOptionView'],
-
- onlineHelp: 'datacenter_configuration_file',
-
- monStoreErrors: true,
-
- add_inputpanel_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {};
- me.rows = me.rows || {};
-
- var canEdit = (opts.caps === undefined || opts.caps);
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue,
- header: text,
- renderer: opts.renderer,
- editor: canEdit ? {
- xtype: 'proxmoxWindowEdit',
- width: 350,
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- setValues: function(values) {
- // FIXME: run through parsePropertyString if not an object?
- var edit_value = values[name];
- Ext.Array.each(this.query('inputpanel'), function(panel) {
- panel.setValues(edit_value);
- });
- },
- url: opts.url,
- items: [{
- xtype: 'inputpanel',
- onGetValues: function(values) {
- if (values === undefined || Object.keys(values).length === 0) {
- return { 'delete': name };
- }
- var ret_val = {};
- ret_val[name] = PVE.Parser.printPropertyString(values);
- return ret_val;
- },
- items: opts.items
- }]
- } : undefined
- };
- },
-
- initComponent : function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- me.add_combobox_row('keyboard', gettext('Keyboard Layout'), {
- renderer: PVE.Utils.render_kvm_language,
- comboItems: PVE.Utils.kvm_keymap_array(),
- defaultValue: '__default__',
- deleteEmpty: true
- });
- me.add_text_row('http_proxy', gettext('HTTP proxy'), {
- defaultValue: Proxmox.Utils.noneText,
- vtype: 'HttpProxy',
- deleteEmpty: true
- });
- me.add_combobox_row('console', gettext('Console Viewer'), {
- renderer: PVE.Utils.render_console_viewer,
- comboItems: PVE.Utils.console_viewer_array(),
- defaultValue: '__default__',
- deleteEmpty: true
- });
- me.add_text_row('email_from', gettext('Email from address'), {
- deleteEmpty: true,
- vtype: 'proxmoxMail',
- defaultValue: 'root@$hostname'
- });
- me.add_text_row('mac_prefix', gettext('MAC address prefix'), {
- deleteEmpty: true,
- vtype: 'MacPrefix',
- defaultValue: Proxmox.Utils.noneText
- });
- me.add_inputpanel_row('migration', gettext('Migration Settings'), {
- renderer: PVE.Utils.render_dc_ha_opts,
- caps: caps.vms['Sys.Modify'],
- labelWidth: 120,
- url: "/api2/extjs/cluster/options",
- defaultKey: 'type',
- items: [{
- xtype: 'displayfield',
- name: 'type',
- fieldLabel: gettext('Type'),
- value: 'secure',
- submitValue: true,
- vtype: 'IPCIDRAddress'
- }, {
- xtype: 'textfield',
- name: 'network',
- fieldLabel: gettext('Network'),
- vtype: 'IPCIDRAddress',
- emptyText: Proxmox.Utils.defaultText,
- value: ''
- }]
- });
- me.add_inputpanel_row('ha', gettext('HA Settings'), {
- renderer: PVE.Utils.render_dc_ha_opts,
- caps: caps.vms['Sys.Modify'],
- labelWidth: 120,
- url: "/api2/extjs/cluster/options",
- items: [{
- xtype: 'proxmoxKVComboBox',
- name: 'shutdown_policy',
- fieldLabel: gettext('Shutdown Policy'),
- deleteEmpty: false,
- value: '__default__',
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText + ' (conditional)' ],
- ['freeze', 'freeze'],
- ['failover', 'failover'],
- ['conditional', 'conditional']
- ],
- defaultValue: '__default__'
- }]
- });
-
- // TODO: bwlimits, migration net, u2f?
-
- me.selModel = Ext.create('Ext.selection.RowModel', {});
-
- Ext.apply(me, {
- tbar: [{
- text: gettext('Edit'),
- xtype: 'proxmoxButton',
- disabled: true,
- handler: function() { me.run_editor(); },
- selModel: me.selModel
- }],
- url: "/api2/json/cluster/options",
- editorConfig: {
- url: "/api2/extjs/cluster/options"
- },
- interval: 5000,
- cwidth1: 200,
- listeners: {
- itemdblclick: me.run_editor
- }
- });
-
- me.callParent();
-
- // set the new value for the default console
- me.mon(me.rstore, 'load', function(store, records, success) {
- if (!success) {
- return;
- }
-
- var rec = store.getById('console');
- PVE.VersionInfo.console = rec.data.value;
- if (rec.data.value === '__default__') {
- delete PVE.VersionInfo.console;
- }
- });
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
- }
-});
-Ext.define('PVE.dc.StorageView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveStorageView'],
-
- onlineHelp: 'chapter_storage',
-
- stateful: true,
- stateId: 'grid-dc-storage',
-
- createStorageEditWindow: function(type, sid) {
- var schema = PVE.Utils.storageSchema[type];
- if (!schema || !schema.ipanel) {
- throw "no editor registered for storage type: " + type;
- }
-
- Ext.create('PVE.storage.BaseEdit', {
- paneltype: 'PVE.storage.' + schema.ipanel,
- type: type,
- storageId: sid,
- autoShow: true,
- listeners: {
- destroy: this.reloadStore
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-storage',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/storage"
- },
- sorters: {
- property: 'storage',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var type = rec.data.type,
- sid = rec.data.storage;
-
- me.createStorageEditWindow(type, sid);
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/storage/',
- callback: reload
- });
-
- // else we cannot dynamically generate the add menu handlers
- var addHandleGenerator = function(type) {
- return function() { me.createStorageEditWindow(type); };
- };
- var addMenuItems = [], type;
- /*jslint forin: true */
- for (type in PVE.Utils.storageSchema) {
- var storage = PVE.Utils.storageSchema[type];
- if (storage.hideAdd) {
- continue;
- }
- addMenuItems.push({
- text: PVE.Utils.format_storage_type(type),
- iconCls: 'fa fa-fw fa-' + storage.faIcon,
- handler: addHandleGenerator(type)
- });
- }
-
- Ext.apply(me, {
- store: store,
- reloadStore: reload,
- selModel: sm,
- viewConfig: {
- trackOver: false
- },
- tbar: [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: addMenuItems
- })
- },
- remove_btn,
- edit_btn
- ],
- columns: [
- {
- header: 'ID',
- flex: 2,
- sortable: true,
- dataIndex: 'storage'
- },
- {
- header: gettext('Type'),
- flex: 1,
- sortable: true,
- dataIndex: 'type',
- renderer: PVE.Utils.format_storage_type
- },
- {
- header: gettext('Content'),
- flex: 3,
- sortable: true,
- dataIndex: 'content',
- renderer: PVE.Utils.format_content_types
- },
- {
- header: gettext('Path') + '/' + gettext('Target'),
- flex: 2,
- sortable: true,
- dataIndex: 'path',
- renderer: function(value, metaData, record) {
- if (record.data.target) {
- return record.data.target;
- }
- return value;
- }
- },
- {
- header: gettext('Shared'),
- flex: 1,
- sortable: true,
- dataIndex: 'shared',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- header: gettext('Enabled'),
- flex: 1,
- sortable: true,
- dataIndex: 'disable',
- renderer: Proxmox.Utils.format_neg_boolean
- },
- {
- header: gettext('Bandwidth Limit'),
- flex: 2,
- sortable: true,
- dataIndex: 'bwlimit'
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-storage', {
- extend: 'Ext.data.Model',
- fields: [
- 'path', 'type', 'content', 'server', 'portal', 'target', 'export', 'storage',
- { name: 'shared', type: 'boolean'},
- { name: 'disable', type: 'boolean'}
- ],
- idProperty: 'storage'
- });
-
-});
-/*global u2f,QRCode,Uint8Array*/
-/*jslint confusion: true*/
-Ext.define('PVE.window.TFAEdit', {
- extend: 'Ext.window.Window',
- mixins: ['Proxmox.Mixin.CBind'],
-
- onlineHelp: 'pveum_tfa_auth', // fake to ensure this gets a link target
-
- modal: true,
- resizable: false,
- title: gettext('Two Factor Authentication'),
- subject: 'TFA',
- url: '/api2/extjs/access/tfa',
- width: 512,
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- updateQrCode: function() {
- var me = this;
- var values = me.lookup('totp_form').getValues();
- var algorithm = values.algorithm;
- if (!algorithm) {
- algorithm = 'SHA1';
- }
-
- me.qrcode.makeCode(
- 'otpauth://totp/' + encodeURIComponent(me.userid) +
- '?secret=' + values.secret +
- '&period=' + values.step +
- '&digits=' + values.digits +
- '&algorithm=' + algorithm +
- '&issuer=' + encodeURIComponent(values.issuer)
- );
-
- me.lookup('challenge').setVisible(true);
- me.down('#qrbox').setVisible(true);
- },
-
- showError: function(error) {
- Ext.Msg.alert(
- gettext('Error'),
- PVE.Utils.render_u2f_error(error)
- );
- },
-
- doU2FChallenge: function(response) {
- var me = this;
-
- var data = response.result.data;
- me.lookup('password').setDisabled(true);
- var msg = Ext.Msg.show({
- title: 'U2F: '+gettext('Setup'),
- message: gettext('Please press the button on your U2F Device'),
- buttons: []
- });
- Ext.Function.defer(function() {
- u2f.register(data.appId, [data], [], function(data) {
- msg.close();
- if (data.errorCode) {
- me.showError(data.errorCode);
- } else {
- me.respondToU2FChallenge(data);
- }
- });
- }, 500, me);
- },
-
- respondToU2FChallenge: function(data) {
- var me = this;
- var params = {
- userid: me.userid,
- action: 'confirm',
- response: JSON.stringify(data)
- };
- if (Proxmox.UserName !== 'root@pam') {
- params.password = me.lookup('password').value;
- }
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'PUT',
- success: function() {
- me.close();
- Ext.Msg.show({
- title: gettext('Success'),
- message: gettext('U2F Device successfully connected.'),
- buttons: Ext.Msg.OK
- });
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- viewModel: {
- data: {
- in_totp_tab: true,
- tfa_required: false,
- has_tfa: false,
- valid: false,
- u2f_available: true
- },
- formulas: {
- canDeleteTFA: function(get) {
- return (get('has_tfa') && !get('tfa_required'));
- }
- }
- },
-
- afterLoadingRealm: function(realm_tfa_type) {
- var me = this;
- var viewmodel = me.getViewModel();
- if (!realm_tfa_type) {
- // There's no TFA enforced by the realm, everything works.
- viewmodel.set('u2f_available', true);
- viewmodel.set('tfa_required', false);
- } else if (realm_tfa_type === 'oath') {
- // The realm explicitly requires TOTP
- viewmodel.set('tfa_required', true);
- viewmodel.set('u2f_available', false);
- } else {
- // The realm enforces some other TFA type (yubico)
- me.close();
- Ext.Msg.alert(
- gettext('Error'),
- Ext.String.format(
- gettext("Custom 2nd factor configuration is not supported on realms with '{0}' TFA."),
- realm_tfa_type
- )
- );
- }
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'field[qrupdate=true]': {
- change: function() {
- var me = this.getView();
- me.updateQrCode();
- }
- },
- 'field': {
- validitychange: function(field, valid) {
- var me = this;
- var viewModel = me.getViewModel();
- var form = me.lookup('totp_form');
- var challenge = me.lookup('challenge');
- var password = me.lookup('password');
- viewModel.set('valid', form.isValid() && challenge.isValid() && password.isValid());
- }
- },
- '#': {
- show: function() {
- var me = this.getView();
- var viewmodel = this.getViewModel();
-
- me.qrdiv = document.createElement('center');
- me.qrcode = new QRCode(me.qrdiv, {
- width: 256,
- height: 256,
- correctLevel: QRCode.CorrectLevel.M
- });
- me.down('#qrbox').getEl().appendChild(me.qrdiv);
-
- viewmodel.set('has_tfa', me.hasTFA);
- if (!me.hasTFA) {
- this.randomizeSecret();
- } else {
- me.down('#qrbox').setVisible(false);
- me.lookup('challenge').setVisible(false);
- }
-
- if (Proxmox.UserName === 'root@pam') {
- me.lookup('password').setVisible(false);
- me.lookup('password').setDisabled(true);
- }
- }
- },
- '#tfatabs': {
- tabchange: function(panel, newcard) {
- var viewmodel = this.getViewModel();
- viewmodel.set('in_totp_tab', newcard.itemId === 'totp-panel');
- }
- }
- },
-
- applySettings: function() {
- var me = this;
- var values = me.lookup('totp_form').getValues();
- var params = {
- userid: me.getView().userid,
- action: 'new',
- key: values.secret,
- config: PVE.Parser.printPropertyString({
- type: 'oath',
- digits: values.digits,
- step: values.step
- }),
- // this is used to verify that the client generates the correct codes:
- response: me.lookup('challenge').value
- };
-
- if (Proxmox.UserName !== 'root@pam') {
- params.password = me.lookup('password').value;
- }
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'PUT',
- waitMsgTarget: me.getView(),
- success: function(response, opts) {
- me.getView().close();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- deleteTFA: function() {
- var me = this;
- var values = me.lookup('totp_form').getValues();
- var params = {
- userid: me.getView().userid,
- action: 'delete'
- };
-
- if (Proxmox.UserName !== 'root@pam') {
- params.password = me.lookup('password').value;
- }
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'PUT',
- waitMsgTarget: me.getView(),
- success: function(response, opts) {
- me.getView().close();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- randomizeSecret: function() {
- var me = this;
- var rnd = new Uint8Array(16);
- window.crypto.getRandomValues(rnd);
- var data = '';
- rnd.forEach(function(b) {
- // just use the first 5 bit
- b = b & 0x1f;
- if (b < 26) {
- // A..Z
- data += String.fromCharCode(b + 0x41);
- } else {
- // 2..7
- data += String.fromCharCode(b-26 + 0x32);
- }
- });
- me.lookup('tfa_secret').setValue(data);
- },
-
- startU2FRegistration: function() {
- var me = this;
-
- var params = {
- userid: me.getView().userid,
- action: 'new'
- };
-
- if (Proxmox.UserName !== 'root@pam') {
- params.password = me.lookup('password').value;
- }
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'PUT',
- waitMsgTarget: me.getView(),
- success: function(response) {
- me.getView().doU2FChallenge(response);
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- },
-
- items: [
- {
- xtype: 'tabpanel',
- itemId: 'tfatabs',
- border: false,
- items: [
- {
- xtype: 'panel',
- title: 'TOTP',
- itemId: 'totp-panel',
- border: false,
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- items: [
- {
- xtype: 'form',
- layout: 'anchor',
- border: false,
- reference: 'totp_form',
- fieldDefaults: {
- anchor: '100%',
- padding: '0 5'
- },
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('User name'),
- cbind: {
- value: '{userid}'
- }
- },
- {
- layout: 'hbox',
- border: false,
- padding: '0 0 5 0',
- items: [{
- xtype: 'textfield',
- fieldLabel: gettext('Secret'),
- emptyText: gettext('Unchanged'),
- name: 'secret',
- reference: 'tfa_secret',
- regex: /^[A-Z2-7=]+$/,
- regexText: 'Must be base32 [A-Z2-7=]',
- maskRe: /[A-Z2-7=]/,
- qrupdate: true,
- flex: 4
- },
- {
- xtype: 'button',
- text: gettext('Randomize'),
- reference: 'randomize_button',
- handler: 'randomizeSecret',
- flex: 1
- }]
- },
- {
- xtype: 'numberfield',
- fieldLabel: gettext('Time period'),
- name: 'step',
- // Google Authenticator ignores this and generates bogus data
- hidden: true,
- value: 30,
- minValue: 10,
- qrupdate: true
- },
- {
- xtype: 'numberfield',
- fieldLabel: gettext('Digits'),
- name: 'digits',
- value: 6,
- // Google Authenticator ignores this and generates bogus data
- hidden: true,
- minValue: 6,
- maxValue: 8,
- qrupdate: true
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Issuer Name'),
- name: 'issuer',
- value: 'Proxmox Web UI',
- qrupdate: true
- }
- ]
- },
- {
- xtype: 'box',
- itemId: 'qrbox',
- visible: false, // will be enabled when generating a qr code
- style: {
- 'background-color': '#23272a',
- padding: '5px',
- width: '266px',
- height: '266px'
- }
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Verification Code'),
- allowBlank: false,
- reference: 'challenge',
- padding: '0 5',
- emptyText: gettext('Scan QR code and enter TOTP auth. code to verify')
- }
- ]
- },
- {
- title: 'U2F',
- itemId: 'u2f-panel',
- reference: 'u2f_panel',
- border: false,
- padding: '5 5',
- layout: {
- type: 'vbox',
- align: 'middle'
- },
- bind: {
- disabled: '{!u2f_available}'
- },
- items: [
- {
- xtype: 'label',
- width: 500,
- text: gettext('To register a U2F device, connect the device, then click the button and follow the instructions.')
- }
- ]
- }
- ]
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- fieldLabel: gettext('Password'),
- minLength: 5,
- reference: 'password',
- allowBlank: false,
- validateBlank: true,
- padding: '0 0 5 5',
- emptyText: gettext('verify current password')
- }
- ],
-
- buttons: [
- {
- xtype: 'proxmoxHelpButton'
- },
- '->',
- {
- text: gettext('Apply'),
- handler: 'applySettings',
- bind: {
- hidden: '{!in_totp_tab}',
- disabled: '{!valid}'
- }
- },
- {
- xtype: 'button',
- text: gettext('Register U2F Device'),
- handler: 'startU2FRegistration',
- bind: {
- hidden: '{in_totp_tab}'
- }
- },
- {
- text: gettext('Delete'),
- reference: 'delete_button',
- handler: 'deleteTFA',
- bind: {
- disabled: '{!canDeleteTFA}'
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-domains',
- autoLoad: true
- });
-
- store.on('load', function() {
- var user_realm = me.userid.split('@')[1];
- var realm = me.store.findRecord('realm', user_realm);
- me.afterLoadingRealm(realm && realm.data && realm.data.tfa);
- }, me);
-
- Ext.apply(me, { store: store });
-
- me.callParent();
-
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', 'pveum_tfa_auth');
- }
-});
-Ext.define('PVE.dc.UserEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcUserEdit'],
-
- isAdd: true,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.userid;
-
- var url;
- var method;
- var realm;
-
- if (me.isCreate) {
- url = '/api2/extjs/access/users';
- method = 'POST';
- } else {
- url = '/api2/extjs/access/users/' + me.userid;
- method = 'PUT';
- }
-
- var verifypw;
- var pwfield;
-
- var validate_pw = function() {
- if (verifypw.getValue() !== pwfield.getValue()) {
- return gettext("Passwords do not match");
- }
- return true;
- };
-
- verifypw = Ext.createWidget('textfield', {
- inputType: 'password',
- fieldLabel: gettext('Confirm password'),
- name: 'verifypassword',
- submitValue: false,
- disabled: true,
- hidden: true,
- validator: validate_pw
- });
-
- pwfield = Ext.createWidget('textfield', {
- inputType: 'password',
- fieldLabel: gettext('Password'),
- minLength: 5,
- name: 'password',
- disabled: true,
- hidden: true,
- validator: validate_pw
- });
-
- var update_passwd_field = function(realm) {
- if (realm === 'pve') {
- pwfield.setVisible(true);
- pwfield.setDisabled(false);
- verifypw.setVisible(true);
- verifypw.setDisabled(false);
- } else {
- pwfield.setVisible(false);
- pwfield.setDisabled(true);
- verifypw.setVisible(false);
- verifypw.setDisabled(true);
- }
-
- };
-
- var column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'userid',
- fieldLabel: gettext('User name'),
- value: me.userid,
- allowBlank: false,
- submitValue: me.isCreate ? true : false
- },
- pwfield, verifypw,
- {
- xtype: 'pveGroupSelector',
- name: 'groups',
- multiSelect: true,
- allowBlank: true,
- fieldLabel: gettext('Group')
- },
- {
- xtype: 'datefield',
- name: 'expire',
- emptyText: 'never',
- format: 'Y-m-d',
- submitFormat: 'U',
- fieldLabel: gettext('Expire')
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Enabled'),
- name: 'enable',
- uncheckedValue: 0,
- defaultValue: 1,
- checked: true
- }
- ];
-
- var column2 = [
- {
- xtype: 'textfield',
- name: 'firstname',
- fieldLabel: gettext('First Name')
- },
- {
- xtype: 'textfield',
- name: 'lastname',
- fieldLabel: gettext('Last Name')
- },
- {
- xtype: 'textfield',
- name: 'email',
- fieldLabel: gettext('E-Mail'),
- vtype: 'proxmoxMail'
- }
- ];
-
- if (me.isCreate) {
- column1.splice(1,0,{
- xtype: 'pveRealmComboBox',
- name: 'realm',
- fieldLabel: gettext('Realm'),
- allowBlank: false,
- matchFieldWidth: false,
- listConfig: { width: 300 },
- listeners: {
- change: function(combo, newValue){
- realm = newValue;
- update_passwd_field(realm);
- }
- },
- submitValue: false
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- column1: column1,
- column2: column2,
- columnB: [
- {
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- }
- ],
- advancedItems: [
- {
- xtype: 'textfield',
- name: 'keys',
- fieldLabel: gettext('Key IDs')
- }
- ],
- onGetValues: function(values) {
- // hack: ExtJS datefield does not submit 0, so we need to set that
- if (!values.expire) {
- values.expire = 0;
- }
-
- if (realm) {
- values.userid = values.userid + '@' + realm;
- }
-
- if (!values.password) {
- delete values.password;
- }
-
- return values;
- }
- });
-
- Ext.applyIf(me, {
- subject: gettext('User'),
- url: url,
- method: method,
- fieldDefaults: {
- labelWidth: 110 // for spanish translation
- },
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var data = response.result.data;
- if (Ext.isDefined(data.expire)) {
- if (data.expire) {
- data.expire = new Date(data.expire * 1000);
- } else {
- // display 'never' instead of '1970-01-01'
- data.expire = null;
- }
- }
- me.setValues(data);
- }
- });
- }
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.dc.UserView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveUserView'],
-
- onlineHelp: 'pveum_users',
-
- stateful: true,
- stateId: 'grid-users',
-
- initComponent : function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var store = new Ext.data.Store({
- id: "users",
- model: 'pve-users',
- sorters: {
- property: 'userid',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/access/users/',
- enableFn: function(rec) {
- if (!caps.access['User.Modify']) {
- return false;
- }
- return rec.data.userid !== 'root@pam';
- },
- callback: function() {
- reload();
- }
- });
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec || !caps.access['User.Modify']) {
- return;
- }
-
- var win = Ext.create('PVE.dc.UserEdit',{
- userid: rec.data.userid
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- enableFn: function(rec) {
- return !!caps.access['User.Modify'];
- },
- selModel: sm,
- handler: run_editor
- });
-
- var pwchange_btn = new Proxmox.button.Button({
- text: gettext('Password'),
- disabled: true,
- selModel: sm,
- handler: function(btn, event, rec) {
- var win = Ext.create('Proxmox.window.PasswordEdit', {
- userid: rec.data.userid
- });
- win.on('destroy', reload);
- win.show();
- }
- });
-
- var tfachange_btn = new Proxmox.button.Button({
- text: 'TFA',
- disabled: true,
- selModel: sm,
- handler: function(btn, event, rec) {
- var d = rec.data;
- var win = Ext.create('PVE.window.TFAEdit',{
- hasTFA: d.keys != undefined && d.keys.length,
- userid: d.userid
- });
- win.on('destroy', reload);
- win.show();
- }
- });
-
- var tbar = [
- {
- text: gettext('Add'),
- disabled: !caps.access['User.Modify'],
- handler: function() {
- var win = Ext.create('PVE.dc.UserEdit',{
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn, pwchange_btn, tfachange_btn
- ];
-
- var render_username = function(userid) {
- return userid.match(/^(.+)(@[^@]+)$/)[1];
- };
-
- var render_realm = function(userid) {
- return userid.match(/@([^@]+)$/)[1];
- };
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('User name'),
- width: 200,
- sortable: true,
- renderer: render_username,
- dataIndex: 'userid'
- },
- {
- header: gettext('Realm'),
- width: 100,
- sortable: true,
- renderer: render_realm,
- dataIndex: 'userid'
- },
- {
- header: gettext('Enabled'),
- width: 80,
- sortable: true,
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'enable'
- },
- {
- header: gettext('Expire'),
- width: 80,
- sortable: true,
- renderer: Proxmox.Utils.format_expire,
- dataIndex: 'expire'
- },
- {
- header: gettext('Name'),
- width: 150,
- sortable: true,
- renderer: PVE.Utils.render_full_name,
- dataIndex: 'firstname'
- },
- {
- header: 'TFA',
- width: 50,
- sortable: true,
- renderer: function(v) {
- return Proxmox.Utils.format_boolean(v !== undefined && v.length);
- },
- dataIndex: 'keys'
- },
- {
- header: gettext('Comment'),
- sortable: false,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment',
- flex: 1
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.PoolView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pvePoolView'],
-
- onlineHelp: 'pveum_pools',
-
- stateful: true,
- stateId: 'grid-pools',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-pools',
- sorters: {
- property: 'poolid',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/pools/',
- callback: function () {
- reload();
- }
- });
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.dc.PoolEdit',{
- poolid: rec.data.poolid
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var tbar = [
- {
- text: gettext('Create'),
- handler: function() {
- var win = Ext.create('PVE.dc.PoolEdit', {});
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn
- ];
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Name'),
- width: 200,
- sortable: true,
- dataIndex: 'poolid'
- },
- {
- header: gettext('Comment'),
- sortable: false,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment',
- flex: 1
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.PoolEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcPoolEdit'],
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.poolid;
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = '/api2/extjs/pools';
- method = 'POST';
- } else {
- url = '/api2/extjs/pools/' + me.poolid;
- method = 'PUT';
- }
-
- Ext.applyIf(me, {
- subject: gettext('Pool'),
- url: url,
- method: method,
- items: [
- {
- xtype: me.isCreate ? 'proxmoxtextfield' : 'displayfield',
- fieldLabel: gettext('Name'),
- name: 'poolid',
- value: me.poolid,
- allowBlank: false
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Comment'),
- name: 'comment',
- allowBlank: true
- }
- ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load();
- }
- }
-});
-Ext.define('PVE.dc.GroupView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveGroupView'],
-
- onlineHelp: 'pveum_groups',
-
- stateful: true,
- stateId: 'grid-groups',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-groups',
- sorters: {
- property: 'groupid',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- callback: function() {
- reload();
- },
- baseurl: '/access/groups/'
- });
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.dc.GroupEdit',{
- groupid: rec.data.groupid
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var tbar = [
- {
- text: gettext('Create'),
- handler: function() {
- var win = Ext.create('PVE.dc.GroupEdit', {});
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn
- ];
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Name'),
- width: 200,
- sortable: true,
- dataIndex: 'groupid'
- },
- {
- header: gettext('Comment'),
- sortable: false,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment',
- flex: 1
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.GroupEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcGroupEdit'],
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.groupid;
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = '/api2/extjs/access/groups';
- method = 'POST';
- } else {
- url = '/api2/extjs/access/groups/' + me.groupid;
- method = 'PUT';
- }
-
- Ext.applyIf(me, {
- subject: gettext('Group'),
- url: url,
- method: method,
- items: [
- {
- xtype: me.isCreate ? 'proxmoxtextfield' : 'displayfield',
- fieldLabel: gettext('Name'),
- name: 'groupid',
- value: me.groupid,
- allowBlank: false
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Comment'),
- name: 'comment',
- allowBlank: true
- }
- ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load();
- }
- }
-});
-Ext.define('PVE.dc.RoleView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveRoleView'],
-
- onlineHelp: 'pveum_roles',
-
- stateful: true,
- stateId: 'grid-roles',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-roles',
- sorters: {
- property: 'roleid',
- order: 'DESC'
- }
- });
-
- var render_privs = function(value, metaData) {
-
- if (!value) {
- return '-';
- }
-
- // allow word wrap
- metaData.style = 'white-space:normal;';
-
- return value.replace(/\,/g, ' ');
- };
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- store.load();
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- if (rec.data.special === "1") {
- return;
- }
-
- var win = Ext.create('PVE.dc.RoleEdit',{
- roleid: rec.data.roleid,
- privs: rec.data.privs
- });
- win.on('destroy', reload);
- win.show();
- };
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
-
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Built-In'),
- width: 65,
- sortable: true,
- dataIndex: 'special',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- header: gettext('Name'),
- width: 150,
- sortable: true,
- dataIndex: 'roleid'
- },
- {
- itemid: 'privs',
- header: gettext('Privileges'),
- sortable: false,
- renderer: render_privs,
- dataIndex: 'privs',
- flex: 1
- }
- ],
- listeners: {
- activate: function() {
- store.load();
- },
- itemdblclick: run_editor
- },
- tbar: [
- {
- text: gettext('Create'),
- handler: function() {
- var win = Ext.create('PVE.dc.RoleEdit', {});
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor,
- enableFn: function(record) {
- return record.data.special !== '1';
- }
- },
- {
- xtype: 'proxmoxStdRemoveButton',
- selModel: sm,
- callback: function() {
- reload();
- },
- baseurl: '/access/roles/',
- enableFn: function(record) {
- return record.data.special !== '1';
- }
- }
- ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.RoleEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveDcRoleEdit',
-
- width: 400,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.roleid;
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = '/api2/extjs/access/roles';
- method = 'POST';
- } else {
- url = '/api2/extjs/access/roles/' + me.roleid;
- method = 'PUT';
- }
-
- Ext.applyIf(me, {
- subject: gettext('Role'),
- url: url,
- method: method,
- items: [
- {
- xtype: me.isCreate ? 'proxmoxtextfield' : 'displayfield',
- name: 'roleid',
- value: me.roleid,
- allowBlank: false,
- fieldLabel: gettext('Name')
- },
- {
- xtype: 'pvePrivilegesSelector',
- name: 'privs',
- value: me.privs,
- allowBlank: false,
- fieldLabel: gettext('Privileges')
- }
- ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response) {
- var data = response.result.data;
- var keys = Ext.Object.getKeys(data);
-
- me.setValues({
- privs: keys,
- roleid: me.roleid
- });
- }
- });
- }
- }
-});
-Ext.define('PVE.dc.ACLAdd', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveACLAdd'],
- url: '/access/acl',
- method: 'PUT',
- isAdd: true,
- initComponent : function() {
-
- var me = this;
-
- me.isCreate = true;
-
- var items = [
- {
- xtype: me.path ? 'hiddenfield' : 'pvePermPathSelector',
- name: 'path',
- value: me.path,
- allowBlank: false,
- fieldLabel: gettext('Path')
- }
- ];
-
- if (me.aclType === 'group') {
- me.subject = gettext("Group Permission");
- items.push({
- xtype: 'pveGroupSelector',
- name: 'groups',
- fieldLabel: gettext('Group')
- });
- } else if (me.aclType === 'user') {
- me.subject = gettext("User Permission");
- items.push({
- xtype: 'pveUserSelector',
- name: 'users',
- fieldLabel: gettext('User')
- });
- } else {
- throw "unknown ACL type";
- }
-
- items.push({
- xtype: 'pveRoleSelector',
- name: 'roles',
- value: 'NoAccess',
- fieldLabel: gettext('Role')
- });
-
- if (!me.path) {
- items.push({
- xtype: 'proxmoxcheckbox',
- name: 'propagate',
- checked: true,
- uncheckedValue: 0,
- fieldLabel: gettext('Propagate')
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- items: items,
- onlineHelp: 'pveum_permission_management'
- });
-
- Ext.apply(me, {
- items: [ ipanel ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.dc.ACLView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveACLView'],
-
- onlineHelp: 'chapter_user_management',
-
- stateful: true,
- stateId: 'grid-acls',
-
- // use fixed path
- path: undefined,
-
- initComponent : function() {
- var me = this;
-
- var store = Ext.create('Ext.data.Store',{
- model: 'pve-acl',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/acl"
- },
- sorters: {
- property: 'path',
- order: 'DESC'
- }
- });
-
- if (me.path) {
- store.addFilter(Ext.create('Ext.util.Filter',{
- filterFn: function(item) {
- if (item.data.path === me.path) {
- return true;
- }
- }
- }));
- }
-
- var render_ugid = function(ugid, metaData, record) {
- if (record.data.type == 'group') {
- return '@' + ugid;
- }
-
- return ugid;
- };
-
- var columns = [
- {
- header: gettext('User') + '/' + gettext('Group'),
- flex: 1,
- sortable: true,
- renderer: render_ugid,
- dataIndex: 'ugid'
- },
- {
- header: gettext('Role'),
- flex: 1,
- sortable: true,
- dataIndex: 'roleid'
- }
- ];
-
- if (!me.path) {
- columns.unshift({
- header: gettext('Path'),
- flex: 1,
- sortable: true,
- dataIndex: 'path'
- });
- columns.push({
- header: gettext('Propagate'),
- width: 80,
- sortable: true,
- dataIndex: 'propagate'
- });
- }
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- store.load();
- };
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- confirmMsg: gettext('Are you sure you want to remove this entry'),
- handler: function(btn, event, rec) {
- var params = {
- 'delete': 1,
- path: rec.data.path,
- roles: rec.data.roleid
- };
- if (rec.data.type === 'group') {
- params.groups = rec.data.ugid;
- } else if (rec.data.type === 'user') {
- params.users = rec.data.ugid;
- } else {
- throw 'unknown data type';
- }
-
- Proxmox.Utils.API2Request({
- url: '/access/acl',
- params: params,
- method: 'PUT',
- waitMsgTarget: me,
- callback: function() {
- reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- {
- text: gettext('Add'),
- menu: {
- xtype: 'menu',
- items: [
- {
- text: gettext('Group Permission'),
- iconCls: 'fa fa-fw fa-group',
- handler: function() {
- var win = Ext.create('PVE.dc.ACLAdd',{
- aclType: 'group',
- path: me.path
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('User Permission'),
- iconCls: 'fa fa-fw fa-user',
- handler: function() {
- var win = Ext.create('PVE.dc.ACLAdd',{
- aclType: 'user',
- path: me.path
- });
- win.on('destroy', reload);
- win.show();
- }
- }
- ]
- }
- },
- remove_btn
- ],
- viewConfig: {
- trackOver: false
- },
- columns: columns,
- listeners: {
- activate: reload
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-acl', {
- extend: 'Ext.data.Model',
- fields: [
- 'path', 'type', 'ugid', 'roleid',
- {
- name: 'propagate',
- type: 'boolean'
- }
- ]
- });
-
-});
-Ext.define('PVE.dc.AuthView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveAuthView'],
-
- onlineHelp: 'pveum_authentication_realms',
-
- stateful: true,
- stateId: 'grid-authrealms',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-domains',
- sorters: {
- property: 'realm',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.dc.AuthEdit',{
- realm: rec.data.realm,
- authType: rec.data.type
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- baseurl: '/access/domains/',
- selModel: sm,
- enableFn: function(rec) {
- return !(rec.data.type === 'pve' || rec.data.type === 'pam');
- },
- callback: function() {
- reload();
- }
- });
-
- var tbar = [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Active Directory Server'),
- handler: function() {
- var win = Ext.create('PVE.dc.AuthEdit', {
- authType: 'ad'
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('LDAP Server'),
- handler: function() {
- var win = Ext.create('PVE.dc.AuthEdit',{
- authType: 'ldap'
- });
- win.on('destroy', reload);
- win.show();
- }
- }
- ]
- })
- },
- edit_btn, remove_btn
- ];
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Realm'),
- width: 100,
- sortable: true,
- dataIndex: 'realm'
- },
- {
- header: gettext('Type'),
- width: 100,
- sortable: true,
- dataIndex: 'type'
- },
- {
- header: gettext('TFA'),
- width: 100,
- sortable: true,
- dataIndex: 'tfa'
- },
- {
- header: gettext('Comment'),
- sortable: false,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.AuthEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcAuthEdit'],
-
- isAdd: true,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.realm;
-
- var url;
- var method;
- var serverlist;
-
- if (me.isCreate) {
- url = '/api2/extjs/access/domains';
- method = 'POST';
- } else {
- url = '/api2/extjs/access/domains/' + me.realm;
- method = 'PUT';
- }
-
- var column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'realm',
- fieldLabel: gettext('Realm'),
- value: me.realm,
- allowBlank: false
- }
- ];
-
- if (me.authType === 'ad') {
-
- me.subject = gettext('Active Directory Server');
-
- column1.push({
- xtype: 'textfield',
- name: 'domain',
- fieldLabel: gettext('Domain'),
- emptyText: 'company.net',
- allowBlank: false
- });
-
- } else if (me.authType === 'ldap') {
-
- me.subject = gettext('LDAP Server');
-
- column1.push({
- xtype: 'textfield',
- name: 'base_dn',
- fieldLabel: gettext('Base Domain Name'),
- emptyText: 'CN=Users,DC=Company,DC=net',
- allowBlank: false
- });
-
- column1.push({
- xtype: 'textfield',
- name: 'user_attr',
- emptyText: 'uid / sAMAccountName',
- fieldLabel: gettext('User Attribute Name'),
- allowBlank: false
- });
- } else if (me.authType === 'pve') {
-
- if (me.isCreate) {
- throw 'unknown auth type';
- }
-
- me.subject = 'Proxmox VE authentication server';
-
- } else if (me.authType === 'pam') {
-
- if (me.isCreate) {
- throw 'unknown auth type';
- }
-
- me.subject = 'linux PAM';
-
- } else {
- throw 'unknown auth type ';
- }
-
- column1.push({
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Default'),
- name: 'default',
- uncheckedValue: 0
- });
-
- var column2 = [];
-
- if (me.authType === 'ldap' || me.authType === 'ad') {
- column2.push(
- {
- xtype: 'textfield',
- fieldLabel: gettext('Server'),
- name: 'server1',
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('Fallback Server'),
- deleteEmpty: !me.isCreate,
- name: 'server2'
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'port',
- fieldLabel: gettext('Port'),
- minValue: 1,
- maxValue: 65535,
- emptyText: gettext('Default'),
- submitEmptyText: false
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: 'SSL',
- name: 'secure',
- uncheckedValue: 0
- }
- );
- }
-
- // Two Factor Auth settings
-
- column2.push({
- xtype: 'proxmoxKVComboBox',
- name: 'tfa',
- deleteEmpty: !me.isCreate,
- value: '',
- fieldLabel: gettext('TFA'),
- comboItems: [ ['__default__', Proxmox.Utils.noneText], ['oath', 'OATH'], ['yubico', 'Yubico']],
- listeners: {
- change: function(f, value) {
- if (!me.rendered) {
- return;
- }
- me.down('field[name=oath_step]').setVisible(value === 'oath');
- me.down('field[name=oath_digits]').setVisible(value === 'oath');
- me.down('field[name=yubico_api_id]').setVisible(value === 'yubico');
- me.down('field[name=yubico_api_key]').setVisible(value === 'yubico');
- me.down('field[name=yubico_url]').setVisible(value === 'yubico');
- }
- }
- });
-
- column2.push({
- xtype: 'proxmoxintegerfield',
- name: 'oath_step',
- value: '',
- minValue: 10,
- emptyText: Proxmox.Utils.defaultText + ' (30)',
- submitEmptyText: false,
- hidden: true,
- fieldLabel: 'OATH time step'
- });
-
- column2.push({
- xtype: 'proxmoxintegerfield',
- name: 'oath_digits',
- value: '',
- minValue: 6,
- maxValue: 8,
- emptyText: Proxmox.Utils.defaultText + ' (6)',
- submitEmptyText: false,
- hidden: true,
- fieldLabel: 'OATH password length'
- });
-
- column2.push({
- xtype: 'textfield',
- name: 'yubico_api_id',
- hidden: true,
- fieldLabel: 'Yubico API Id'
- });
-
- column2.push({
- xtype: 'textfield',
- name: 'yubico_api_key',
- hidden: true,
- fieldLabel: 'Yubico API Key'
- });
-
- column2.push({
- xtype: 'textfield',
- name: 'yubico_url',
- hidden: true,
- fieldLabel: 'Yubico URL'
- });
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- column1: column1,
- column2: column2,
- columnB: [{
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- }],
- onGetValues: function(values) {
- if (!values.port) {
- if (!me.isCreate) {
- Proxmox.Utils.assemble_field_data(values, { 'delete': 'port' });
- }
- delete values.port;
- }
-
- if (me.isCreate) {
- values.type = me.authType;
- }
-
- if (values.tfa === 'oath') {
- values.tfa = "type=oath";
- if (values.oath_step) {
- values.tfa += ",step=" + values.oath_step;
- }
- if (values.oath_digits) {
- values.tfa += ",digits=" + values.oath_digits;
- }
- } else if (values.tfa === 'yubico') {
- values.tfa = "type=yubico";
- values.tfa += ",id=" + values.yubico_api_id;
- values.tfa += ",key=" + values.yubico_api_key;
- if (values.yubico_url) {
- values.tfa += ",url=" + values.yubico_url;
- }
- } else {
- delete values.tfa;
- }
-
- delete values.oath_step;
- delete values.oath_digits;
- delete values.yubico_api_id;
- delete values.yubico_api_key;
- delete values.yubico_url;
-
- return values;
- }
- });
-
- Ext.applyIf(me, {
- url: url,
- method: method,
- fieldDefaults: {
- labelWidth: 120
- },
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var data = response.result.data || {};
- // just to be sure (should not happen)
- if (data.type !== me.authType) {
- me.close();
- throw "got wrong auth type";
- }
-
- if (data.tfa) {
- var tfacfg = PVE.Parser.parseTfaConfig(data.tfa);
- data.tfa = tfacfg.type;
- if (tfacfg.type === 'yubico') {
- data.yubico_api_key = tfacfg.key;
- data.yubico_api_id = tfacfg.id;
- data.yubico_url = tfacfg.url;
- } else if (tfacfg.type === 'oath') {
- // step is a number before
- /*jslint confusion: true*/
- data.oath_step = tfacfg.step;
- data.oath_digits = tfacfg.digits;
- /*jslint confusion: false*/
- }
- }
-
- me.setValues(data);
- }
- });
- }
- }
-});
-Ext.define('PVE.dc.BackupEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcBackupEdit'],
-
- defaultFocus: undefined,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.jobid;
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = '/api2/extjs/cluster/backup';
- method = 'POST';
- } else {
- url = '/api2/extjs/cluster/backup/' + me.jobid;
- method = 'PUT';
- }
-
- var vmidField = Ext.create('Ext.form.field.Hidden', {
- name: 'vmid'
- });
-
- /*jslint confusion: true*/
- // 'value' can be assigned a string or an array
- var selModeField = Ext.create('Proxmox.form.KVComboBox', {
- xtype: 'proxmoxKVComboBox',
- comboItems: [
- ['include', gettext('Include selected VMs')],
- ['all', gettext('All')],
- ['exclude', gettext('Exclude selected VMs')]
- ],
- fieldLabel: gettext('Selection mode'),
- name: 'selMode',
- value: ''
- });
-
- var sm = Ext.create('Ext.selection.CheckboxModel', {
- mode: 'SIMPLE',
- listeners: {
- selectionchange: function(model, selected) {
- var sel = [];
- Ext.Array.each(selected, function(record) {
- sel.push(record.data.vmid);
- });
-
- // to avoid endless recursion suspend the vmidField change
- // event temporary as it calls us again
- vmidField.suspendEvent('change');
- vmidField.setValue(sel);
- vmidField.resumeEvent('change');
- }
- }
- });
-
- var storagesel = Ext.create('PVE.form.StorageSelector', {
- fieldLabel: gettext('Storage'),
- nodename: 'localhost',
- storageContent: 'backup',
- allowBlank: false,
- name: 'storage'
- });
-
- var store = new Ext.data.Store({
- model: 'PVEResources',
- sorters: {
- property: 'vmid',
- order: 'ASC'
- }
- });
-
- var vmgrid = Ext.createWidget('grid', {
- store: store,
- border: true,
- height: 300,
- selModel: sm,
- disabled: true,
- columns: [
- {
- header: 'ID',
- dataIndex: 'vmid',
- width: 60
- },
- {
- header: gettext('Node'),
- dataIndex: 'node'
- },
- {
- header: gettext('Status'),
- dataIndex: 'uptime',
- renderer: function(value) {
- if (value) {
- return Proxmox.Utils.runningText;
- } else {
- return Proxmox.Utils.stoppedText;
- }
- }
- },
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- header: gettext('Type'),
- dataIndex: 'type'
- }
- ]
- });
-
- var nodesel = Ext.create('PVE.form.NodeSelector', {
- name: 'node',
- fieldLabel: gettext('Node'),
- allowBlank: true,
- editable: true,
- autoSelect: false,
- emptyText: '-- ' + gettext('All') + ' --',
- listeners: {
- change: function(f, value) {
- storagesel.setNodename(value || 'localhost');
- var mode = selModeField.getValue();
- store.clearFilter();
- store.filterBy(function(rec) {
- return (!value || rec.get('node') === value);
- });
- if (mode === 'all') {
- sm.selectAll(true);
- }
- }
- }
- });
-
- var column1 = [
- nodesel,
- storagesel,
- {
- xtype: 'pveDayOfWeekSelector',
- name: 'dow',
- fieldLabel: gettext('Day of week'),
- multiSelect: true,
- value: ['sat'],
- allowBlank: false
- },
- {
- xtype: 'timefield',
- fieldLabel: gettext('Start Time'),
- name: 'starttime',
- format: 'H:i',
- formatText: 'HH:MM',
- value: '00:00',
- allowBlank: false
- },
- selModeField
- ];
-
- var column2 = [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Send email to'),
- name: 'mailto'
- },
- {
- xtype: 'pveEmailNotificationSelector',
- fieldLabel: gettext('Email notification'),
- name: 'mailnotification',
- deleteEmpty: me.isCreate ? false : true,
- value: me.isCreate ? 'always' : ''
- },
- {
- xtype: 'pveCompressionSelector',
- fieldLabel: gettext('Compression'),
- name: 'compress',
- deleteEmpty: me.isCreate ? false : true,
- value: 'lzo'
- },
- {
- xtype: 'pveBackupModeSelector',
- fieldLabel: gettext('Mode'),
- value: 'snapshot',
- name: 'mode'
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Enable'),
- name: 'enabled',
- uncheckedValue: 0,
- defaultValue: 1,
- checked: true
- },
- vmidField
- ];
- /*jslint confusion: false*/
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- onlineHelp: 'chapter_vzdump',
- column1: column1,
- column2: column2,
- onGetValues: function(values) {
- if (!values.node) {
- if (!me.isCreate) {
- Proxmox.Utils.assemble_field_data(values, { 'delete': 'node' });
- }
- delete values.node;
- }
-
- var selMode = values.selMode;
- delete values.selMode;
-
- if (selMode === 'all') {
- values.all = 1;
- values.exclude = '';
- delete values.vmid;
- } else if (selMode === 'exclude') {
- values.all = 1;
- values.exclude = values.vmid;
- delete values.vmid;
- }
- return values;
- }
- });
-
- var update_vmid_selection = function(list, mode) {
- if (mode !== 'all') {
- sm.deselectAll(true);
- if (list) {
- Ext.Array.each(list.split(','), function(vmid) {
- var rec = store.findRecord('vmid', vmid);
- if (rec) {
- sm.select(rec, true);
- }
- });
- }
- }
- };
-
- vmidField.on('change', function(f, value) {
- var mode = selModeField.getValue();
- update_vmid_selection(value, mode);
- });
-
- selModeField.on('change', function(f, value, oldValue) {
- if (value === 'all') {
- sm.selectAll(true);
- vmgrid.setDisabled(true);
- } else {
- vmgrid.setDisabled(false);
- }
- if (oldValue === 'all') {
- sm.deselectAll(true);
- vmidField.setValue('');
- }
- var list = vmidField.getValue();
- update_vmid_selection(list, value);
- });
-
- var reload = function() {
- store.load({
- params: { type: 'vm' },
- callback: function() {
- var node = nodesel.getValue();
- store.clearFilter();
- store.filterBy(function(rec) {
- return (!node || node.length === 0 || rec.get('node') === node);
- });
- var list = vmidField.getValue();
- var mode = selModeField.getValue();
- if (mode === 'all') {
- sm.selectAll(true);
- } else {
- update_vmid_selection(list, mode);
- }
- }
- });
- };
-
- Ext.applyIf(me, {
- subject: gettext("Backup Job"),
- url: url,
- method: method,
- items: [ ipanel, vmgrid ]
- });
-
- me.callParent();
-
- if (me.isCreate) {
- selModeField.setValue('include');
- } else {
- me.load({
- success: function(response, options) {
- var data = response.result.data;
-
- data.dow = data.dow.split(',');
-
- if (data.all || data.exclude) {
- if (data.exclude) {
- data.vmid = data.exclude;
- data.selMode = 'exclude';
- } else {
- data.vmid = '';
- data.selMode = 'all';
- }
- } else {
- data.selMode = 'include';
- }
-
- me.setValues(data);
- }
- });
- }
-
- reload();
- }
-});
-
-
-Ext.define('PVE.dc.BackupView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveDcBackupView'],
-
- onlineHelp: 'chapter_vzdump',
-
- allText: '-- ' + gettext('All') + ' --',
- allExceptText: gettext('All except {0}'),
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-cluster-backup',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/backup"
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.dc.BackupEdit',{
- jobid: rec.data.id
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/cluster/backup',
- callback: function() {
- reload();
- }
- });
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- stateful: true,
- stateId: 'grid-dc-backup',
- viewConfig: {
- trackOver: false
- },
- tbar: [
- {
- text: gettext('Add'),
- handler: function() {
- var win = Ext.create('PVE.dc.BackupEdit',{});
- win.on('destroy', reload);
- win.show();
- }
- },
- remove_btn,
- edit_btn
- ],
- columns: [
- {
- header: gettext('Enabled'),
- width: 80,
- dataIndex: 'enabled',
- xtype: 'checkcolumn',
- sortable: true,
- disabled: true,
- disabledCls: 'x-item-enabled',
- stopSelection: false
- },
- {
- header: gettext('Node'),
- width: 100,
- sortable: true,
- dataIndex: 'node',
- renderer: function(value) {
- if (value) {
- return value;
- }
- return me.allText;
- }
- },
- {
- header: gettext('Day of week'),
- width: 200,
- sortable: false,
- dataIndex: 'dow',
- renderer: function(val) {
- var dows = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
- var selected = [];
- var cur = -1;
- val.split(',').forEach(function(day){
- cur++;
- var dow = (dows.indexOf(day)+6)%7;
- if (cur === dow) {
- if (selected.length === 0 || selected[selected.length-1] === 0) {
- selected.push(1);
- } else {
- selected[selected.length-1]++;
- }
- } else {
- while (cur < dow) {
- cur++;
- selected.push(0);
- }
- selected.push(1);
- }
- });
-
- cur = -1;
- var days = [];
- selected.forEach(function(item) {
- cur++;
- if (item > 2) {
- days.push(Ext.Date.dayNames[(cur+1)] + '-' + Ext.Date.dayNames[(cur+item)%7]);
- cur += item-1;
- } else if (item == 2) {
- days.push(Ext.Date.dayNames[cur+1]);
- days.push(Ext.Date.dayNames[(cur+2)%7]);
- cur++;
- } else if (item == 1) {
- days.push(Ext.Date.dayNames[(cur+1)%7]);
- }
- });
- return days.join(', ');
- }
- },
- {
- header: gettext('Start Time'),
- width: 60,
- sortable: true,
- dataIndex: 'starttime'
- },
- {
- header: gettext('Storage'),
- width: 100,
- sortable: true,
- dataIndex: 'storage'
- },
- {
- header: gettext('Selection'),
- flex: 1,
- sortable: false,
- dataIndex: 'vmid',
- renderer: function(value, metaData, record) {
- /*jslint confusion: true */
- if (record.data.all) {
- if (record.data.exclude) {
- return Ext.String.format(me.allExceptText, record.data.exclude);
- }
- return me.allText;
- }
- if (record.data.vmid) {
- return record.data.vmid;
- }
-
- return "-";
- }
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-cluster-backup', {
- extend: 'Ext.data.Model',
- fields: [
- 'id', 'starttime', 'dow',
- 'storage', 'node', 'vmid', 'exclude',
- 'mailto',
- { name: 'enabled', type: 'boolean' },
- { name: 'all', type: 'boolean' },
- { name: 'snapshot', type: 'boolean' },
- { name: 'stop', type: 'boolean' },
- { name: 'suspend', type: 'boolean' },
- { name: 'compress', type: 'boolean' }
- ]
- });
-});
-Ext.define('PVE.dc.Support', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveDcSupport',
- pveGuidePath: '/pve-docs/index.html',
- onlineHelp: 'getting_help',
-
- invalidHtml: 'No valid subscription ' + PVE.Utils.noSubKeyHtml,
-
- communityHtml: 'Please use the public community forum for any questions.',
-
- activeHtml: 'Please use our support portal for any questions. You can also use the public community forum to get additional information.',
-
- bugzillaHtml: 'Bug Tracking Our bug tracking system is available here .',
-
- docuHtml: function() {
- var me = this;
- var guideUrl = window.location.origin + me.pveGuidePath;
- var text = Ext.String.format('Documentation '
- + 'The official Proxmox VE Administration Guide'
- + ' is included with this installation and can be browsed at '
- + '{0} ', guideUrl);
- return text;
- },
-
- updateActive: function(data) {
- var me = this;
-
- var html = '' + data.productname + ' ' + me.activeHtml;
- html += ' ' + me.docuHtml();
- html += ' ' + me.bugzillaHtml;
-
- me.update(html);
- },
-
- updateCommunity: function(data) {
- var me = this;
-
- var html = '' + data.productname + ' ' + me.communityHtml;
- html += ' ' + me.docuHtml();
- html += ' ' + me.bugzillaHtml;
-
- me.update(html);
- },
-
- updateInactive: function(data) {
- var me = this;
- me.update(me.invalidHtml);
- },
-
- initComponent: function() {
- var me = this;
-
- var reload = function() {
- Proxmox.Utils.API2Request({
- url: '/nodes/localhost/subscription',
- method: 'GET',
- waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- me.update('Unable to load subscription status' + ": " + response.htmlStatus);
- },
- success: function(response, opts) {
- var data = response.result.data;
-
- if (data.status === 'Active') {
- if (data.level === 'c') {
- me.updateCommunity(data);
- } else {
- me.updateActive(data);
- }
- } else {
- me.updateInactive(data);
- }
- }
- });
- };
-
- Ext.apply(me, {
- autoScroll: true,
- bodyStyle: 'padding:10px',
- listeners: {
- activate: reload
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('pve-security-groups', {
- extend: 'Ext.data.Model',
-
- fields: [ 'group', 'comment', 'digest' ],
- idProperty: 'group'
-});
-
-Ext.define('PVE.SecurityGroupEdit', {
- extend: 'Proxmox.window.Edit',
-
- base_url: "/cluster/firewall/groups",
-
- allow_iface: false,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = (me.group_name === undefined);
-
- var subject;
-
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
-
- var items = [
- {
- xtype: 'textfield',
- name: 'group',
- value: me.group_name || '',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'comment',
- value: me.group_comment || '',
- fieldLabel: gettext('Comment')
- }
- ];
-
- if (me.isCreate) {
- subject = gettext('Security Group');
- } else {
- subject = gettext('Security Group') + " '" + me.group_name + "'";
- items.push({
- xtype: 'hiddenfield',
- name: 'rename',
- value: me.group_name
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- // InputPanel does not have a 'create' property, does it need a 'isCreate'
- isCreate: me.isCreate,
- items: items
- });
-
-
- Ext.apply(me, {
- subject: subject,
- items: [ ipanel ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.SecurityGroupList', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveSecurityGroupList',
-
- stateful: true,
- stateId: 'grid-securitygroups',
-
- rule_panel: undefined,
-
- addBtn: undefined,
- removeBtn: undefined,
- editBtn: undefined,
-
- base_url: "/cluster/firewall/groups",
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (me.rule_panel == undefined) {
- throw "no rule panel specified";
- }
-
- if (me.base_url == undefined) {
- throw "no base_url specified";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-security-groups',
- proxy: {
- type: 'proxmox',
- url: '/api2/json' + me.base_url
- },
- sorters: {
- property: 'group',
- order: 'DESC'
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- var oldrec = sm.getSelection()[0];
- store.load(function(records, operation, success) {
- if (oldrec) {
- var rec = store.findRecord('group', oldrec.data.group);
- if (rec) {
- sm.select(rec);
- }
- }
- });
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var win = Ext.create('PVE.SecurityGroupEdit', {
- digest: rec.data.digest,
- group_name: rec.data.group,
- group_comment: rec.data.comment
- });
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = new Proxmox.button.Button({
- text: gettext('Create'),
- handler: function() {
- sm.deselectAll();
- var win = Ext.create('PVE.SecurityGroupEdit', {});
- win.show();
- win.on('destroy', reload);
- }
- });
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: me.base_url + '/',
- enableFn: function(rec) {
- return (rec && me.base_url);
- },
- callback: function() {
- reload();
- }
- });
-
- Ext.apply(me, {
- store: store,
- tbar: [ '' + gettext('Group') + ': ', me.addBtn, me.removeBtn, me.editBtn ],
- selModel: sm,
- columns: [
- { header: gettext('Group'), dataIndex: 'group', width: '100' },
- { header: gettext('Comment'), dataIndex: 'comment', renderer: Ext.String.htmlEncode, flex: 1 }
- ],
- listeners: {
- itemdblclick: run_editor,
- select: function(sm, rec) {
- var url = '/cluster/firewall/groups/' + rec.data.group;
- me.rule_panel.setBaseUrl(url);
- },
- deselect: function() {
- me.rule_panel.setBaseUrl(undefined);
- },
- show: reload
- }
- });
-
- me.callParent();
-
- store.load();
- }
-});
-
-Ext.define('PVE.SecurityGroups', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveSecurityGroups',
-
- title: 'Security Groups',
-
- initComponent: function() {
- var me = this;
-
- var rule_panel = Ext.createWidget('pveFirewallRules', {
- region: 'center',
- allow_groups: false,
- list_refs_url: '/cluster/firewall/refs',
- tbar_prefix: '' + gettext('Rules') + ': ',
- border: false
- });
-
- var sglist = Ext.createWidget('pveSecurityGroupList', {
- region: 'west',
- rule_panel: rule_panel,
- width: '25%',
- border: false,
- split: true
- });
-
-
- Ext.apply(me, {
- layout: 'border',
- items: [ sglist, rule_panel ],
- listeners: {
- show: function() {
- sglist.fireEvent('show', sglist);
- }
- }
- });
-
- me.callParent();
- }
-});
-/*
- * Datacenter config panel, located in the center of the ViewPort after the Datacenter view is selected
- */
-
-Ext.define('PVE.dc.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.dc.Config',
-
- onlineHelp: 'pve_admin_guide',
-
- initComponent: function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- me.items = [];
-
- Ext.apply(me, {
- title: gettext("Datacenter"),
- hstateid: 'dctab'
- });
-
- if (caps.dc['Sys.Audit']) {
- me.items.push({
- title: gettext('Summary'),
- xtype: 'pveDcSummary',
- iconCls: 'fa fa-book',
- itemId: 'summary'
- },
- {
- title: gettext('Cluster'),
- xtype: 'pveClusterAdministration',
- iconCls: 'fa fa-server',
- itemId: 'cluster'
- },
- {
- xtype: 'pveDcOptionView',
- title: gettext('Options'),
- iconCls: 'fa fa-gear',
- itemId: 'options'
- });
- }
-
- if (caps.storage['Datastore.Allocate'] || caps.dc['Sys.Audit']) {
- me.items.push({
- xtype: 'pveStorageView',
- title: gettext('Storage'),
- iconCls: 'fa fa-database',
- itemId: 'storage'
- });
- }
-
- if (caps.dc['Sys.Audit']) {
- me.items.push({
- xtype: 'pveDcBackupView',
- iconCls: 'fa fa-floppy-o',
- title: gettext('Backup'),
- itemId: 'backup'
- },
- {
- xtype: 'pveReplicaView',
- iconCls: 'fa fa-retweet',
- title: gettext('Replication'),
- itemId: 'replication'
- },
- {
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- iconCls: 'fa fa-unlock',
- itemId: 'permissions',
- expandedOnInit: true
- });
- }
-
- me.items.push({
- xtype: 'pveUserView',
- groups: ['permissions'],
- iconCls: 'fa fa-user',
- title: gettext('Users'),
- itemId: 'users'
- });
-
- if (caps.dc['Sys.Audit']) {
- me.items.push({
- xtype: 'pveGroupView',
- title: gettext('Groups'),
- iconCls: 'fa fa-users',
- groups: ['permissions'],
- itemId: 'groups'
- },
- {
- xtype: 'pvePoolView',
- title: gettext('Pools'),
- iconCls: 'fa fa-tags',
- groups: ['permissions'],
- itemId: 'pools'
- },
- {
- xtype: 'pveRoleView',
- title: gettext('Roles'),
- iconCls: 'fa fa-male',
- groups: ['permissions'],
- itemId: 'roles'
- },
- {
- xtype: 'pveAuthView',
- title: gettext('Authentication'),
- groups: ['permissions'],
- iconCls: 'fa fa-key',
- itemId: 'domains'
- },
- {
- xtype: 'pveHAStatus',
- title: 'HA',
- iconCls: 'fa fa-heartbeat',
- itemId: 'ha'
- },
- {
- title: gettext('Groups'),
- groups: ['ha'],
- xtype: 'pveHAGroupsView',
- iconCls: 'fa fa-object-group',
- itemId: 'ha-groups'
- },
- {
- title: gettext('Fencing'),
- groups: ['ha'],
- iconCls: 'fa fa-bolt',
- xtype: 'pveFencingView',
- itemId: 'ha-fencing'
- },
- {
- xtype: 'pveFirewallRules',
- title: gettext('Firewall'),
- allow_iface: true,
- base_url: '/cluster/firewall/rules',
- list_refs_url: '/cluster/firewall/refs',
- iconCls: 'fa fa-shield',
- itemId: 'firewall'
- },
- {
- xtype: 'pveFirewallOptions',
- title: gettext('Options'),
- groups: ['firewall'],
- iconCls: 'fa fa-gear',
- base_url: '/cluster/firewall/options',
- onlineHelp: 'pve_firewall_cluster_wide_setup',
- fwtype: 'dc',
- itemId: 'firewall-options'
- },
- {
- xtype: 'pveSecurityGroups',
- title: gettext('Security Group'),
- groups: ['firewall'],
- iconCls: 'fa fa-group',
- itemId: 'firewall-sg'
- },
- {
- xtype: 'pveFirewallAliases',
- title: gettext('Alias'),
- groups: ['firewall'],
- iconCls: 'fa fa-external-link',
- base_url: '/cluster/firewall/aliases',
- itemId: 'firewall-aliases'
- },
- {
- xtype: 'pveIPSet',
- title: 'IPSet',
- groups: ['firewall'],
- iconCls: 'fa fa-list-ol',
- base_url: '/cluster/firewall/ipset',
- list_refs_url: '/cluster/firewall/refs',
- itemId: 'firewall-ipset'
- },
- {
- xtype: 'pveDcSupport',
- title: gettext('Support'),
- itemId: 'support',
- iconCls: 'fa fa-comments-o'
- });
- }
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.NodeView', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pveDcNodeView',
-
- title: gettext('Nodes'),
- disableSelection: true,
- scrollable: true,
-
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- dataIndex: 'name'
- },
- {
- header: 'ID',
- width: 40,
- sortable: true,
- dataIndex: 'nodeid'
- },
- {
- header: gettext('Online'),
- width: 60,
- sortable: true,
- dataIndex: 'online',
- renderer: function(value) {
- var cls = (value)?'good':'critical';
- return ' ';
- }
- },
- {
- header: gettext('Support'),
- width: 100,
- sortable: true,
- dataIndex: 'level',
- renderer: PVE.Utils.render_support_level
- },
- {
- header: gettext('Server Address'),
- width: 115,
- sortable: true,
- dataIndex: 'ip'
- },
- {
- header: gettext('CPU usage'),
- sortable: true,
- width: 110,
- dataIndex: 'cpuusage',
- tdCls: 'x-progressbar-default-cell',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Memory usage'),
- width: 110,
- sortable: true,
- tdCls: 'x-progressbar-default-cell',
- dataIndex: 'memoryusage',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Uptime'),
- sortable: true,
- dataIndex: 'uptime',
- align: 'right',
- renderer: Proxmox.Utils.render_uptime
- }
- ],
-
- stateful: true,
- stateId: 'grid-cluster-nodes',
- tools: [
- {
- type: 'up',
- handler: function(){
- var me = this.up('grid');
- var height = Math.max(me.getHeight()-50, 250);
- me.setHeight(height);
- }
- },
- {
- type: 'down',
- handler: function(){
- var me = this.up('grid');
- var height = me.getHeight()+50;
- me.setHeight(height);
- }
- }
- ]
-}, function() {
-
- Ext.define('pve-dc-nodes', {
- extend: 'Ext.data.Model',
- fields: [ 'id', 'type', 'name', 'nodeid', 'ip', 'level', 'local', 'online'],
- idProperty: 'id'
- });
-
-});
-
-Ext.define('PVE.widget.ProgressBar',{
- extend: 'Ext.Progress',
- alias: 'widget.pveProgressBar',
-
- animate: true,
- textTpl: [
- '{percent}%'
- ],
-
- setValue: function(value){
- var me = this;
- me.callParent([value]);
-
- me.removeCls(['warning', 'critical']);
-
- if (value > 0.89) {
- me.addCls('critical');
- } else if (value > 0.59) {
- me.addCls('warning');
- }
- }
-});
-/*jslint confusion: true*/
-Ext.define('pve-cluster-nodes', {
- extend: 'Ext.data.Model',
- fields: [
- 'node', { type: 'integer', name: 'nodeid' }, 'ring0_addr', 'ring1_addr',
- { type: 'integer', name: 'quorum_votes' }
- ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/config/nodes"
- },
- idProperty: 'nodeid'
-});
-
-Ext.define('pve-cluster-info', {
- extend: 'Ext.data.Model',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/config/join"
- }
-});
-
-Ext.define('PVE.ClusterAdministration', {
- extend: 'Ext.panel.Panel',
- xtype: 'pveClusterAdministration',
-
- title: gettext('Cluster Administration'),
- onlineHelp: 'chapter_pvecm',
-
- border: false,
- defaults: { border: false },
-
- viewModel: {
- parent: null,
- data: {
- totem: {},
- nodelist: [],
- preferred_node: {
- name: '',
- fp: '',
- addr: ''
- },
- isInCluster: false,
- nodecount: 0
- }
- },
-
- items: [
- {
- xtype: 'panel',
- title: gettext('Cluster Information'),
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.store = Ext.create('Proxmox.data.UpdateStore', {
- autoStart: true,
- interval: 15 * 1000,
- storeid: 'pve-cluster-info',
- model: 'pve-cluster-info'
- });
- view.store.on('load', this.onLoad, this);
- view.on('destroy', view.store.stopUpdate);
- },
-
- onLoad: function(store, records, success) {
- var vm = this.getViewModel();
- if (!success || !records || !records[0].data) {
- vm.set('totem', {});
- vm.set('isInCluster', false);
- vm.set('nodelist', []);
- vm.set('preferred_node', {
- name: '',
- addr: '',
- fp: ''
- });
- return;
- }
- var data = records[0].data;
- vm.set('totem', data.totem);
- vm.set('isInCluster', !!data.totem.cluster_name);
- vm.set('nodelist', data.nodelist);
-
- var nodeinfo = Ext.Array.findBy(data.nodelist, function (el) {
- return el.name === data.preferred_node;
- });
-
- vm.set('preferred_node', {
- name: data.preferred_node,
- addr: nodeinfo.pve_addr,
- ring_addr: [ nodeinfo.ring0_addr, nodeinfo.ring1_addr ],
- fp: nodeinfo.pve_fp
- });
- },
-
- onCreate: function() {
- var view = this.getView();
- view.store.stopUpdate();
- var win = Ext.create('PVE.ClusterCreateWindow', {
- autoShow: true,
- listeners: {
- destroy: function() {
- view.store.startUpdate();
- }
- }
- });
- },
-
- onClusterInfo: function() {
- var vm = this.getViewModel();
- var win = Ext.create('PVE.ClusterInfoWindow', {
- joinInfo: {
- ipAddress: vm.get('preferred_node.addr'),
- fingerprint: vm.get('preferred_node.fp'),
- ring_addr: vm.get('preferred_node.ring_addr'),
- totem: vm.get('totem')
- }
- });
- win.show();
- },
-
- onJoin: function() {
- var view = this.getView();
- view.store.stopUpdate();
- var win = Ext.create('PVE.ClusterJoinNodeWindow', {
- autoShow: true,
- listeners: {
- destroy: function() {
- view.store.startUpdate();
- }
- }
- });
- }
- },
- tbar: [
- {
- text: gettext('Create Cluster'),
- reference: 'createButton',
- handler: 'onCreate',
- bind: {
- disabled: '{isInCluster}'
- }
- },
- {
- text: gettext('Join Information'),
- reference: 'addButton',
- handler: 'onClusterInfo',
- bind: {
- disabled: '{!isInCluster}'
- }
- },
- {
- text: gettext('Join Cluster'),
- reference: 'joinButton',
- handler: 'onJoin',
- bind: {
- disabled: '{isInCluster}'
- }
- }
- ],
- layout: 'hbox',
- bodyPadding: 5,
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Cluster Name'),
- bind: {
- value: '{totem.cluster_name}',
- hidden: '{!isInCluster}'
- },
- flex: 1
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Config Version'),
- bind: {
- value: '{totem.config_version}',
- hidden: '{!isInCluster}'
- },
- flex: 1
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Number of Nodes'),
- labelWidth: 120,
- bind: {
- value: '{nodecount}',
- hidden: '{!isInCluster}'
- },
- flex: 1
- },
- {
- xtype: 'displayfield',
- value: gettext('Standalone node - no cluster defined'),
- bind: {
- hidden: '{isInCluster}'
- },
- flex: 1
- }
- ]
- },
- {
- xtype: 'grid',
- title: gettext('Cluster Nodes'),
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.rstore = Ext.create('Proxmox.data.UpdateStore', {
- autoLoad: true,
- xtype: 'update',
- interval: 5 * 1000,
- autoStart: true,
- storeid: 'pve-cluster-nodes',
- model: 'pve-cluster-nodes'
- });
- view.setStore(Ext.create('Proxmox.data.DiffStore', {
- rstore: view.rstore,
- sorters: {
- property: 'nodeid',
- order: 'DESC'
- }
- }));
- Proxmox.Utils.monStoreErrors(view, view.rstore);
- view.rstore.on('load', this.onLoad, this);
- view.on('destroy', view.rstore.stopUpdate);
- },
-
- onLoad: function(store, records, success) {
- var vm = this.getViewModel();
- if (!success || !records) {
- vm.set('nodecount', 0);
- return;
- }
- vm.set('nodecount', records.length);
- }
- },
- columns: [
- {
- header: gettext('Nodename'),
- flex: 2,
- dataIndex: 'name'
- },
- {
- header: gettext('ID'),
- flex: 1,
- dataIndex: 'nodeid'
- },
- {
- header: gettext('Votes'),
- flex: 1,
- dataIndex: 'quorum_votes'
- },
- {
- header: gettext('Ring 0'),
- flex: 2,
- dataIndex: 'ring0_addr'
- },
- {
- header: gettext('Ring 1'),
- flex: 2,
- dataIndex: 'ring1_addr'
- }
- ]
- }
- ]
-});
-/*jslint confusion: true*/
-Ext.define('PVE.ClusterCreateWindow', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveClusterCreateWindow',
-
- title: gettext('Create Cluster'),
- width: 600,
-
- method: 'POST',
- url: '/cluster/config',
-
- isCreate: true,
- subject: gettext('Cluster'),
- showTaskViewer: true,
-
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Cluster Name'),
- allowBlank: false,
- name: 'clustername'
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('Ring 0 Address'),
- emptyText: gettext("Optional, defaults to IP resolved by node's hostname"),
- name: 'ring0_addr',
- skipEmptyText: true
- }
- // TODO: for advanced options: ring1_addr
- ]
-});
-
-Ext.define('PVE.ClusterInfoWindow', {
- extend: 'Ext.window.Window',
- xtype: 'pveClusterInfoWindow',
- mixins: ['Proxmox.Mixin.CBind'],
-
- width: 800,
- modal: true,
- resizable: false,
- title: gettext('Cluster Join Information'),
-
- joinInfo: {
- ipAddress: undefined,
- fingerprint: undefined,
- totem: {}
- },
-
- items: [
- {
- xtype: 'component',
- border: false,
- padding: '10 10 10 10',
- html: gettext("Copy the Join Information here and use it on the node you want to add.")
- },
- {
- xtype: 'container',
- layout: 'form',
- border: false,
- padding: '0 10 10 10',
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('IP Address'),
- cbind: { value: '{joinInfo.ipAddress}' },
- editable: false
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Fingerprint'),
- cbind: { value: '{joinInfo.fingerprint}' },
- editable: false
- },
- {
- xtype: 'textarea',
- inputId: 'pveSerializedClusterInfo',
- fieldLabel: gettext('Join Information'),
- grow: true,
- cbind: { joinInfo: '{joinInfo}' },
- editable: false,
- listeners: {
- afterrender: function(field) {
- if (!field.joinInfo) {
- return;
- }
- var jsons = Ext.JSON.encode(field.joinInfo);
- var base64s = Ext.util.Base64.encode(jsons);
- field.setValue(base64s);
- }
- }
- }
- ]
- }
- ],
- dockedItems: [{
- dock: 'bottom',
- xtype: 'toolbar',
- items: [{
- xtype: 'button',
- handler: function(b) {
- var el = document.getElementById('pveSerializedClusterInfo');
- el.select();
- document.execCommand("copy");
- },
- text: gettext('Copy Information')
- }]
- }]
-});
-
-Ext.define('PVE.ClusterJoinNodeWindow', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveClusterJoinNodeWindow',
-
- title: gettext('Cluster Join'),
- width: 800,
-
- method: 'POST',
- url: '/cluster/config/join',
-
- defaultFocus: 'textarea[name=serializedinfo]',
- isCreate: true,
- submitText: gettext('Join'),
- showTaskViewer: true,
-
- onlineHelp: 'chapter_pvecm',
-
- viewModel: {
- parent: null,
- data: {
- info: {
- fp: '',
- ip: '',
- ring0Needed: false,
- ring1Possible: false,
- ring1Needed: false
- }
- },
- formulas: {
- ring0EmptyText: function(get) {
- if (get('info.ring0Needed')) {
- return gettext("Cannot use default address safely");
- } else {
- return gettext("Default: IP resolved by node's hostname");
- }
- }
- }
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- '#': {
- close: function() {
- delete PVE.Utils.silenceAuthFailures;
- }
- },
- 'proxmoxcheckbox[name=assistedEntry]': {
- change: 'onInputTypeChange'
- },
- 'textarea[name=serializedinfo]': {
- change: 'recomputeSerializedInfo',
- enable: 'resetField'
- },
- 'proxmoxtextfield[name=ring1_addr]': {
- enable: 'ring1Needed'
- },
- 'textfield': {
- disable: 'resetField'
- }
- },
- resetField: function(field) {
- field.reset();
- },
- ring1Needed: function(f) {
- var vm = this.getViewModel();
- f.allowBlank = !vm.get('info.ring1Needed');
- },
- onInputTypeChange: function(field, assistedInput) {
- var vm = this.getViewModel();
- if (!assistedInput) {
- vm.set('info.ring1Possible', true);
- }
- },
- recomputeSerializedInfo: function(field, value) {
- var vm = this.getViewModel();
- var jsons = Ext.util.Base64.decode(value);
- var joinInfo = Ext.JSON.decode(jsons, true);
-
- var info = {
- fp: '',
- ring1Needed: false,
- ring1Possible: false,
- ip: ''
- };
-
- var totem = {};
- if (!(joinInfo && joinInfo.totem)) {
- field.valid = false;
- } else {
- var ring0Needed = false;
- if (joinInfo.ring_addr !== undefined) {
- ring0Needed = joinInfo.ring_addr[0] !== joinInfo.ipAddress;
- }
-
- info = {
- ip: joinInfo.ipAddress,
- fp: joinInfo.fingerprint,
- ring0Needed: ring0Needed,
- ring1Possible: !!joinInfo.totem['interface']['1'],
- ring1Needed: !!joinInfo.totem['interface']['1']
- };
- totem = joinInfo.totem;
- field.valid = true;
- }
-
- vm.set('info', info);
- }
- },
-
- submit: function() {
- // joining may produce temporarily auth failures, ignore as long the task runs
- PVE.Utils.silenceAuthFailures = true;
- this.callParent();
- },
-
- taskDone: function(success) {
- delete PVE.Utils.silenceAuthFailures;
- if (success) {
- var txt = gettext('Cluster join task finished, node certificate may have changed, reload GUI!');
- // ensure user cannot do harm
- Ext.getBody().mask(txt, ['pve-static-mask']);
- // TaskView may hide above mask, so tell him directly
- Ext.Msg.show({
- title: gettext('Join Task Finished'),
- icon: Ext.Msg.INFO,
- msg: txt
- });
- // reload always (if user wasn't faster), but wait a bit for pveproxy
- Ext.defer(function() {
- window.location.reload(true);
- }, 5000);
- }
- },
-
- items: [{
- xtype: 'proxmoxcheckbox',
- reference: 'assistedEntry',
- name: 'assistedEntry',
- submitValue: false,
- value: true,
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext('Select if join information should be extracted from pasted cluster information, deselect for manual entering')
- },
- boxLabel: gettext('Assisted join: Paste encoded cluster join information and enter password.')
- },
- {
- xtype: 'textarea',
- name: 'serializedinfo',
- submitValue: false,
- allowBlank: false,
- fieldLabel: gettext('Information'),
- emptyText: gettext('Paste encoded Cluster Information here'),
- validator: function(val) {
- return val === '' || this.valid ||
- gettext('Does not seem like a valid encoded Cluster Information!');
- },
- bind: {
- disabled: '{!assistedEntry.checked}',
- hidden: '{!assistedEntry.checked}'
- },
- value: ''
- },
- {
- xtype: 'inputpanel',
- column1: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Peer Address'),
- allowBlank: false,
- bind: {
- value: '{info.ip}',
- readOnly: '{assistedEntry.checked}'
- },
- name: 'hostname'
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- emptyText: gettext("Peer's root password"),
- fieldLabel: gettext('Password'),
- allowBlank: false,
- name: 'password'
- }
- ],
- column2: [
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('Corosync Ring 0'),
- bind: {
- emptyText: '{ring0EmptyText}',
- allowBlank: '{!info.ring0Needed}'
- },
- skipEmptyText: true,
- name: 'ring0_addr'
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('Corosync Ring 1'),
- skipEmptyText: true,
- bind: {
- disabled: '{!info.ring1Possible}'
- },
- name: 'ring1_addr'
- }
- ],
- columnB: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Fingerprint'),
- allowBlank: false,
- bind: {
- value: '{info.fp}',
- readOnly: '{assistedEntry.checked}'
- },
- name: 'fingerprint'
- }
- ]
- }]
-});
-/*
- * Workspace base class
- *
- * popup login window when auth fails (call onLogin handler)
- * update (re-login) ticket every 15 minutes
- *
- */
-
-Ext.define('PVE.Workspace', {
- extend: 'Ext.container.Viewport',
-
- title: 'Proxmox Virtual Environment',
-
- loginData: null, // Data from last login call
-
- onLogin: function(loginData) {},
-
- // private
- updateLoginData: function(loginData) {
- var me = this;
- me.loginData = loginData;
- Proxmox.Utils.setAuthData(loginData);
-
- var rt = me.down('pveResourceTree');
- rt.setDatacenterText(loginData.clustername);
-
- if (loginData.cap) {
- Ext.state.Manager.set('GuiCap', loginData.cap);
- }
-
- me.onLogin(loginData);
- },
-
- // private
- showLogin: function() {
- var me = this;
-
- Proxmox.Utils.authClear();
- Proxmox.UserName = null;
- me.loginData = null;
-
- if (!me.login) {
- me.login = Ext.create('PVE.window.LoginWindow', {
- handler: function(data) {
- me.login = null;
- me.updateLoginData(data);
- Proxmox.Utils.checked_command(function() {}); // display subscription status
- }
- });
- }
- me.onLogin(null);
- me.login.show();
- },
-
- initComponent : function() {
- var me = this;
-
- Ext.tip.QuickTipManager.init();
-
- // fixme: what about other errors
- Ext.Ajax.on('requestexception', function(conn, response, options) {
- if (response.status == 401 && !PVE.Utils.silenceAuthFailures) { // auth failure
- me.showLogin();
- }
- });
-
- me.callParent();
-
- if (!Proxmox.Utils.authOK()) {
- me.showLogin();
- } else {
- if (me.loginData) {
- me.onLogin(me.loginData);
- }
- }
-
- Ext.TaskManager.start({
- run: function() {
- var ticket = Proxmox.Utils.authOK();
- if (!ticket || !Proxmox.UserName) {
- return;
- }
-
- Ext.Ajax.request({
- params: {
- username: Proxmox.UserName,
- password: ticket
- },
- url: '/api2/json/access/ticket',
- method: 'POST',
- success: function(response, opts) {
- var obj = Ext.decode(response.responseText);
- me.updateLoginData(obj.data);
- }
- });
- },
- interval: 15*60*1000
- });
-
- }
-});
-
-Ext.define('PVE.StdWorkspace', {
- extend: 'PVE.Workspace',
-
- alias: ['widget.pveStdWorkspace'],
-
- // private
- setContent: function(comp) {
- var me = this;
-
- var cont = me.child('#content');
-
- var lay = cont.getLayout();
-
- var cur = lay.getActiveItem();
-
- if (comp) {
- Proxmox.Utils.setErrorMask(cont, false);
- comp.border = false;
- cont.add(comp);
- if (cur !== null && lay.getNext()) {
- lay.next();
- var task = Ext.create('Ext.util.DelayedTask', function(){
- cont.remove(cur);
- });
- task.delay(10);
- }
- }
- else {
- // helper for cleaning the content when logging out
- cont.removeAll();
- }
- },
-
- selectById: function(nodeid) {
- var me = this;
- var tree = me.down('pveResourceTree');
- tree.selectById(nodeid);
- },
-
- onLogin: function(loginData) {
- var me = this;
-
- me.updateUserInfo();
-
- if (loginData) {
- PVE.data.ResourceStore.startUpdate();
-
- Proxmox.Utils.API2Request({
- url: '/version',
- method: 'GET',
- success: function(response) {
- PVE.VersionInfo = response.result.data;
- me.updateVersionInfo();
- }
- });
- }
- },
-
- updateUserInfo: function() {
- var me = this;
-
- var ui = me.query('#userinfo')[0];
-
- if (Proxmox.UserName) {
- var msg = Ext.String.format(gettext("You are logged in as {0}"), "'" + Proxmox.UserName + "'");
- ui.update('' + msg + '
');
- } else {
- ui.update('');
- }
- ui.updateLayout();
- },
-
- updateVersionInfo: function() {
- var me = this;
-
- var ui = me.query('#versioninfo')[0];
-
- if (PVE.VersionInfo) {
- var version = PVE.VersionInfo.version + '-' + PVE.VersionInfo.release;
- ui.update('Virtual Environment ' + version);
- } else {
- ui.update('Virtual Environment');
- }
- ui.updateLayout();
- },
-
- initComponent : function() {
- var me = this;
-
- Ext.History.init();
-
- var sprovider = Ext.create('PVE.StateProvider');
- Ext.state.Manager.setProvider(sprovider);
-
- var selview = Ext.create('PVE.form.ViewSelector');
-
- var rtree = Ext.createWidget('pveResourceTree', {
- viewFilter: selview.getViewFilter(),
- flex: 1,
- selModel: {
- selType: 'treemodel',
- listeners: {
- selectionchange: function(sm, selected) {
- if (selected.length > 0) {
- var n = selected[0];
- var tlckup = {
- root: 'PVE.dc.Config',
- node: 'PVE.node.Config',
- qemu: 'PVE.qemu.Config',
- lxc: 'PVE.lxc.Config',
- storage: 'PVE.storage.Browser',
- pool: 'pvePoolConfig'
- };
- var comp = {
- xtype: tlckup[n.data.type || 'root'] ||
- 'pvePanelConfig',
- showSearch: (n.data.id === 'root') ||
- Ext.isDefined(n.data.groupbyid),
- pveSelNode: n,
- workspace: me,
- viewFilter: selview.getViewFilter()
- };
- PVE.curSelectedNode = n;
- me.setContent(comp);
- }
- }
- }
- }
- });
-
- selview.on('select', function(combo, records) {
- if (records) {
- var view = combo.getViewFilter();
- rtree.setViewFilter(view);
- }
- });
-
- var caps = sprovider.get('GuiCap');
-
- var createVM = Ext.createWidget('button', {
- pack: 'end',
- margin: '3 5 0 0',
- baseCls: 'x-btn',
- iconCls: 'fa fa-desktop',
- text: gettext("Create VM"),
- disabled: !caps.vms['VM.Allocate'],
- handler: function() {
- var wiz = Ext.create('PVE.qemu.CreateWizard', {});
- wiz.show();
- }
- });
-
- var createCT = Ext.createWidget('button', {
- pack: 'end',
- margin: '3 5 0 0',
- baseCls: 'x-btn',
- iconCls: 'fa fa-cube',
- text: gettext("Create CT"),
- disabled: !caps.vms['VM.Allocate'],
- handler: function() {
- var wiz = Ext.create('PVE.lxc.CreateWizard', {});
- wiz.show();
- }
- });
-
- sprovider.on('statechange', function(sp, key, value) {
- if (key === 'GuiCap' && value) {
- caps = value;
- createVM.setDisabled(!caps.vms['VM.Allocate']);
- createCT.setDisabled(!caps.vms['VM.Allocate']);
- }
- });
-
- Ext.apply(me, {
- layout: { type: 'border' },
- border: false,
- items: [
- {
- region: 'north',
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- baseCls: 'x-plain',
- defaults: {
- baseCls: 'x-plain'
- },
- border: false,
- margin: '2 0 2 5',
- items: [
- {
- html: '' +
- ' '
- },
- {
- minWidth: 150,
- id: 'versioninfo',
- html: 'Virtual Environment'
- },
- {
- xtype: 'pveGlobalSearchField',
- tree: rtree
- },
- {
- flex: 1
- },
- {
- pack: 'end',
- id: 'userinfo',
- stateful: false
- },
- {
- xtype: 'button',
- margin: '0 10 0 3',
- iconCls: 'fa black fa-gear',
- userCls: 'pointer',
- handler: function() {
- var win = Ext.create('PVE.window.Settings');
- win.show();
- }
- },
- {
- xtype: 'proxmoxHelpButton',
- hidden: false,
- baseCls: 'x-btn',
- iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ',
- listenToGlobalEvent: false,
- onlineHelp: 'pve_documentation_index',
- text: gettext('Documentation'),
- margin: '0 5 0 0'
- },
- createVM,
- createCT,
- {
- pack: 'end',
- margin: '0 5 0 0',
- xtype: 'button',
- baseCls: 'x-btn',
- iconCls: 'fa fa-sign-out',
- text: gettext("Logout"),
- handler: function() {
- PVE.data.ResourceStore.loadData([], false);
- me.showLogin();
- me.setContent(null);
- var rt = me.down('pveResourceTree');
- rt.setDatacenterText(undefined);
- rt.clearTree();
-
- // empty the stores of the StatusPanel child items
- var statusPanels = Ext.ComponentQuery.query('pveStatusPanel grid');
- Ext.Array.forEach(statusPanels, function(comp) {
- if (comp.getStore()) {
- comp.getStore().loadData([], false);
- }
- });
- }
- }
- ]
- },
- {
- region: 'center',
- stateful: true,
- stateId: 'pvecenter',
- minWidth: 100,
- minHeight: 100,
- id: 'content',
- xtype: 'container',
- layout: { type: 'card' },
- border: false,
- margin: '0 5 0 0',
- items: []
- },
- {
- region: 'west',
- stateful: true,
- stateId: 'pvewest',
- itemId: 'west',
- xtype: 'container',
- border: false,
- layout: { type: 'vbox', align: 'stretch' },
- margin: '0 0 0 5',
- split: true,
- width: 200,
- items: [ selview, rtree ],
- listeners: {
- resize: function(panel, width, height) {
- var viewWidth = me.getSize().width;
- if (width > viewWidth - 100) {
- panel.setWidth(viewWidth - 100);
- }
- }
- }
- },
- {
- xtype: 'pveStatusPanel',
- stateful: true,
- stateId: 'pvesouth',
- itemId: 'south',
- region: 'south',
- margin:'0 5 5 5',
- title: gettext('Logs'),
- collapsible: true,
- header: false,
- height: 200,
- split:true,
- listeners: {
- resize: function(panel, width, height) {
- var viewHeight = me.getSize().height;
- if (height > (viewHeight - 150)) {
- panel.setHeight(viewHeight - 150);
- }
- }
- }
- }
- ]
- });
-
- me.callParent();
-
- me.updateUserInfo();
-
- // on resize, center all modal windows
- Ext.on('resize', function(){
- var wins = Ext.ComponentQuery.query('window[modal]');
- if (wins.length > 0) {
- wins.forEach(function(win){
- win.alignTo(me, 'c-c');
- });
- }
- });
- }
-});
-
diff --git a/serverside/jsmod/6.0-4.sh b/serverside/jsmod/6.0-4.sh
deleted file mode 100644
index 66c0f54..0000000
--- a/serverside/jsmod/6.0-4.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-
-Say () {
- printf "\e[1;34m $1 \e[0m \n";
-}
-
-DotSay () {
- printf "[\e[1;34m*\e[0m] \e[1;34m $1 \e[0m \n";
-}
-
-
-Say '[PVE Discord Dark UI Theme JSMOD Installer]'
-Say 'Internet connection REQUIRED.'
-Say '!!ONLY FOR PVE 6.0-4 - 6.1-x!!'
-Say '>Press any key to begin installation'
-read -p ""
-Say ' '
-DotSay 'Backing up files'
-cp /usr/share/pve-manager/js/pvemanagerlib.js /usr/share/pve-manager/js/pvemanagerlib.js.bak
-cp /usr/share/javascript/extjs/charts.js /usr/share/javascript/extjs/charts.js.bak
-cp /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.bak
-DotSay 'Replacing files with modded versions'
-rm /usr/share/pve-manager/js/pvemanagerlib.js
-wget https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/serverside/jsmod/6.0-4/pvemanagerlib.js -P /usr/share/pve-manager/js/ &> /dev/null
-rm /usr/share/javascript/extjs/charts.js
-wget https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/serverside/jsmod/6.0-4/charts.js -P /usr/share/javascript/extjs/ &> /dev/null
-rm /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
-wget https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/serverside/jsmod/6.0-4/proxmoxlib.js -P /usr/share/javascript/proxmox-widget-toolkit/ &> /dev/null
-DotSay 'Applied successfully.'
-Say ''
-Say 'Installation finished!'
-Say 'o7'
diff --git a/serverside/jsmod/6.0-4/charts.js b/serverside/jsmod/6.0-4/charts.js
deleted file mode 100644
index 713bec3..0000000
--- a/serverside/jsmod/6.0-4/charts.js
+++ /dev/null
@@ -1,22013 +0,0 @@
-Ext.define("Ext.draw.ContainerBase", {
- extend: "Ext.panel.Panel",
- requires: ["Ext.window.Window"],
- previewTitleText: "Chart Preview",
- previewAltText: "Chart preview",
- layout: "container",
- addElementListener: function() {
- var b = this,
- a = arguments;
- if (b.rendered) {
- b.el.on.apply(b.el, a)
- } else {
- b.on("render", function() {
- b.el.on.apply(b.el, a)
- })
- }
- },
- removeElementListener: function() {
- var b = this,
- a = arguments;
- if (b.rendered) {
- b.el.un.apply(b.el, a)
- }
- },
- afterRender: function() {
- this.callParent(arguments);
- this.initAnimator()
- },
- getItems: function() {
- var b = this,
- a = b.items;
- if (!a || !a.isMixedCollection) {
- b.initItems()
- }
- return b.items
- },
- onRender: function() {
- this.callParent(arguments);
- this.element = this.el;
- this.innerElement = this.body
- },
- setItems: function(a) {
- this.items = a;
- return a
- },
- setSurfaceSize: function(b, a) {
- this.resizeHandler({
- width: b,
- height: a
- });
- this.renderFrame()
- },
- onResize: function(c, a, b, e) {
- var d = this;
- d.callParent([c, a, b, e]);
- d.setBodySize({
- width: c,
- height: a
- })
- },
- preview: function() {
- var a = this.getImage();
- new Ext.window.Window({
- title: this.previewTitleText,
- closeable: true,
- renderTo: Ext.getBody(),
- autoShow: true,
- maximizeable: true,
- maximized: true,
- border: true,
- layout: {
- type: "hbox",
- pack: "center",
- align: "middle"
- },
- items: {
- xtype: "container",
- items: {
- xtype: "image",
- mode: "img",
- cls: Ext.baseCSSPrefix + "chart-image",
- alt: this.previewAltText,
- src: a.data,
- listeners: {
- afterrender: function() {
- var e = this,
- b = e.imgEl.dom,
- d = a.type === "svg" ? 1 : (window.devicePixelRatio || 1),
- c;
- if (!b.naturalWidth || !b.naturalHeight) {
- b.onload = function() {
- var g = b.naturalWidth,
- f = b.naturalHeight;
- e.setWidth(Math.floor(g / d));
- e.setHeight(Math.floor(f / d))
- }
- } else {
- c = e.getSize();
- e.setWidth(Math.floor(c.width / d));
- e.setHeight(Math.floor(c.height / d))
- }
- }
- }
- }
- }
- })
- },
- privates: {
- getTargetEl: function() {
- return this.innerElement
- },
- reattachToBody: function() {
- var a = this;
- if (a.pendingDetachSize) {
- a.onBodyResize()
- }
- a.pendingDetachSize = false;
- a.callParent()
- }
- }
-});
-Ext.define("Ext.draw.SurfaceBase", {
- extend: "Ext.Widget",
- getOwnerBody: function() {
- return this.ownerCt.body
- },
- destroy: function() {
- var a = this;
- if (a.hasListeners.destroy) {
- a.fireEvent("destroy", a)
- }
- a.callParent()
- }
-});
-Ext.define("Ext.draw.Color", {
- statics: {
- colorToHexRe: /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
- rgbToHexRe: /\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
- rgbaToHexRe: /\s*rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\.\d]+)\)/,
- hexRe: /\s*#([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)\s*/,
- NONE: "none",
- RGBA_NONE: "rgba(0, 0, 0, 0)"
- },
- isColor: true,
- lightnessFactor: 0.2,
- constructor: function(d, b, a, c) {
- this.setRGB(d, b, a, c)
- },
- setRGB: function(e, c, a, d) {
- var b = this;
- b.r = Math.min(255, Math.max(0, e));
- b.g = Math.min(255, Math.max(0, c));
- b.b = Math.min(255, Math.max(0, a));
- if (d === undefined) {
- b.a = 1
- } else {
- b.a = Math.min(1, Math.max(0, d))
- }
- },
- getGrayscale: function() {
- return this.r * 0.3 + this.g * 0.59 + this.b * 0.11
- },
- getHSL: function() {
- var i = this,
- a = i.r / 255,
- f = i.g / 255,
- j = i.b / 255,
- k = Math.max(a, f, j),
- d = Math.min(a, f, j),
- m = k - d,
- e, n = 0,
- c = 0.5 * (k + d);
- if (d !== k) {
- n = (c <= 0.5) ? m / (k + d) : m / (2 - k - d);
- if (a === k) {
- e = 60 * (f - j) / m
- } else {
- if (f === k) {
- e = 120 + 60 * (j - a) / m
- } else {
- e = 240 + 60 * (a - f) / m
- }
- }
- if (e < 0) {
- e += 360
- }
- if (e >= 360) {
- e -= 360
- }
- }
- return [e, n, c]
- },
- getHSV: function() {
- var i = this,
- a = i.r / 255,
- f = i.g / 255,
- j = i.b / 255,
- k = Math.max(a, f, j),
- d = Math.min(a, f, j),
- c = k - d,
- e, m = 0,
- l = k;
- if (d != k) {
- m = l ? c / l : 0;
- if (a === k) {
- e = 60 * (f - j) / c
- } else {
- if (f === k) {
- e = 60 * (j - a) / c + 120
- } else {
- e = 60 * (a - f) / c + 240
- }
- }
- if (e < 0) {
- e += 360
- }
- if (e >= 360) {
- e -= 360
- }
- }
- return [e, m, l]
- },
- setHSL: function(g, f, e) {
- var i = this,
- d = Math.abs,
- j, b, a;
- g = (g % 360 + 360) % 360;
- f = f > 1 ? 1 : f < 0 ? 0 : f;
- e = e > 1 ? 1 : e < 0 ? 0 : e;
- if (f === 0 || g === null) {
- e *= 255;
- i.setRGB(e, e, e)
- } else {
- g /= 60;
- j = f * (1 - d(2 * e - 1));
- b = j * (1 - d(g % 2 - 1));
- a = e - j / 2;
- a *= 255;
- j *= 255;
- b *= 255;
- switch (Math.floor(g)) {
- case 0:
- i.setRGB(j + a, b + a, a);
- break;
- case 1:
- i.setRGB(b + a, j + a, a);
- break;
- case 2:
- i.setRGB(a, j + a, b + a);
- break;
- case 3:
- i.setRGB(a, b + a, j + a);
- break;
- case 4:
- i.setRGB(b + a, a, j + a);
- break;
- case 5:
- i.setRGB(j + a, a, b + a);
- break
- }
- }
- return i
- },
- setHSV: function(f, e, d) {
- var g = this,
- i, b, a;
- f = (f % 360 + 360) % 360;
- e = e > 1 ? 1 : e < 0 ? 0 : e;
- d = d > 1 ? 1 : d < 0 ? 0 : d;
- if (e === 0 || f === null) {
- d *= 255;
- g.setRGB(d, d, d)
- } else {
- f /= 60;
- i = d * e;
- b = i * (1 - Math.abs(f % 2 - 1));
- a = d - i;
- a *= 255;
- i *= 255;
- b *= 255;
- switch (Math.floor(f)) {
- case 0:
- g.setRGB(i + a, b + a, a);
- break;
- case 1:
- g.setRGB(b + a, i + a, a);
- break;
- case 2:
- g.setRGB(a, i + a, b + a);
- break;
- case 3:
- g.setRGB(a, b + a, i + a);
- break;
- case 4:
- g.setRGB(b + a, a, i + a);
- break;
- case 5:
- g.setRGB(i + a, a, b + a);
- break
- }
- }
- return g
- },
- createLighter: function(b) {
- if (!b && b !== 0) {
- b = this.lightnessFactor
- }
- var a = this.getHSL();
- a[2] = Ext.Number.constrain(a[2] + b, 0, 1);
- return Ext.draw.Color.fromHSL(a[0], a[1], a[2])
- },
- createDarker: function(a) {
- if (!a && a !== 0) {
- a = this.lightnessFactor
- }
- return this.createLighter(-a)
- },
- toString: function() {
- var f = this,
- c = Math.round;
- if (f.a === 1) {
- var e = c(f.r).toString(16),
- d = c(f.g).toString(16),
- a = c(f.b).toString(16);
- e = (e.length === 1) ? "0" + e : e;
- d = (d.length === 1) ? "0" + d : d;
- a = (a.length === 1) ? "0" + a : a;
- return ["#", e, d, a].join("")
- } else {
- return "rgba(" + [c(f.r), c(f.g), c(f.b), f.a === 0 ? 0 : f.a.toFixed(15)].join(", ") + ")"
- }
- },
- toHex: function(b) {
- if (Ext.isArray(b)) {
- b = b[0]
- }
- if (!Ext.isString(b)) {
- return ""
- }
- if (b.substr(0, 1) === "#") {
- return b
- }
- var e = Ext.draw.Color.colorToHexRe.exec(b);
- if (Ext.isArray(e)) {
- var f = parseInt(e[2], 10),
- d = parseInt(e[3], 10),
- a = parseInt(e[4], 10),
- c = a | (d << 8) | (f << 16);
- return e[1] + "#" + ("000000" + c.toString(16)).slice(-6)
- } else {
- return ""
- }
- },
- setFromString: function(j) {
- var e, h, f, c, d = 1,
- i = parseInt;
- if (j === Ext.draw.Color.NONE) {
- this.r = this.g = this.b = this.a = 0;
- return this
- }
- if ((j.length === 4 || j.length === 7) && j.substr(0, 1) === "#") {
- e = j.match(Ext.draw.Color.hexRe);
- if (e) {
- h = i(e[1], 16) >> 0;
- f = i(e[2], 16) >> 0;
- c = i(e[3], 16) >> 0;
- if (j.length === 4) {
- h += (h * 16);
- f += (f * 16);
- c += (c * 16)
- }
- }
- } else {
- if ((e = j.match(Ext.draw.Color.rgbToHexRe))) {
- h = +e[1];
- f = +e[2];
- c = +e[3]
- } else {
- if ((e = j.match(Ext.draw.Color.rgbaToHexRe))) {
- h = +e[1];
- f = +e[2];
- c = +e[3];
- d = +e[4]
- } else {
- if (Ext.draw.Color.ColorList.hasOwnProperty(j.toLowerCase())) {
- return this.setFromString(Ext.draw.Color.ColorList[j.toLowerCase()])
- }
- }
- }
- }
- if (typeof h === "undefined") {
- return this
- }
- this.r = h;
- this.g = f;
- this.b = c;
- this.a = d;
- return this
- }
-}, function() {
- var a = new this();
- this.addStatics({
- fly: function(f, e, c, d) {
- switch (arguments.length) {
- case 1:
- a.setFromString(f);
- break;
- case 3:
- case 4:
- a.setRGB(f, e, c, d);
- break;
- default:
- return null
- }
- return a
- },
- ColorList: {
- aliceblue: "#f0f8ff",
- antiquewhite: "#faebd7",
- aqua: "#00ffff",
- aquamarine: "#7fffd4",
- azure: "#f0ffff",
- beige: "#f5f5dc",
- bisque: "#ffe4c4",
- black: "#000000",
- blanchedalmond: "#ffebcd",
- blue: "#0000ff",
- blueviolet: "#8a2be2",
- brown: "#a52a2a",
- burlywood: "#deb887",
- cadetblue: "#5f9ea0",
- chartreuse: "#7fff00",
- chocolate: "#d2691e",
- coral: "#ff7f50",
- cornflowerblue: "#6495ed",
- cornsilk: "#fff8dc",
- crimson: "#dc143c",
- cyan: "#00ffff",
- darkblue: "#00008b",
- darkcyan: "#008b8b",
- darkgoldenrod: "#b8860b",
- darkgray: "#a9a9a9",
- darkgreen: "#006400",
- darkkhaki: "#bdb76b",
- darkmagenta: "#8b008b",
- darkolivegreen: "#556b2f",
- darkorange: "#ff8c00",
- darkorchid: "#9932cc",
- darkred: "#8b0000",
- darksalmon: "#e9967a",
- darkseagreen: "#8fbc8f",
- darkslateblue: "#483d8b",
- darkslategray: "#2f4f4f",
- darkturquoise: "#00ced1",
- darkviolet: "#9400d3",
- deeppink: "#ff1493",
- deepskyblue: "#00bfff",
- dimgray: "#696969",
- dodgerblue: "#1e90ff",
- firebrick: "#b22222",
- floralwhite: "#fffaf0",
- forestgreen: "#228b22",
- fuchsia: "#ff00ff",
- gainsboro: "#dcdcdc",
- ghostwhite: "#f8f8ff",
- gold: "#ffd700",
- goldenrod: "#daa520",
- gray: "#808080",
- green: "#008000",
- greenyellow: "#adff2f",
- honeydew: "#f0fff0",
- hotpink: "#ff69b4",
- indianred: "#cd5c5c",
- indigo: "#4b0082",
- ivory: "#fffff0",
- khaki: "#f0e68c",
- lavender: "#e6e6fa",
- lavenderblush: "#fff0f5",
- lawngreen: "#7cfc00",
- lemonchiffon: "#fffacd",
- lightblue: "#add8e6",
- lightcoral: "#f08080",
- lightcyan: "#e0ffff",
- lightgoldenrodyellow: "#fafad2",
- lightgray: "#d3d3d3",
- lightgrey: "#d3d3d3",
- lightgreen: "#90ee90",
- lightpink: "#ffb6c1",
- lightsalmon: "#ffa07a",
- lightseagreen: "#20b2aa",
- lightskyblue: "#87cefa",
- lightslategray: "#778899",
- lightsteelblue: "#b0c4de",
- lightyellow: "#ffffe0",
- lime: "#00ff00",
- limegreen: "#32cd32",
- linen: "#faf0e6",
- magenta: "#ff00ff",
- maroon: "#800000",
- mediumaquamarine: "#66cdaa",
- mediumblue: "#0000cd",
- mediumorchid: "#ba55d3",
- mediumpurple: "#9370d8",
- mediumseagreen: "#3cb371",
- mediumslateblue: "#7b68ee",
- mediumspringgreen: "#00fa9a",
- mediumturquoise: "#48d1cc",
- mediumvioletred: "#c71585",
- midnightblue: "#191970",
- mintcream: "#f5fffa",
- mistyrose: "#ffe4e1",
- moccasin: "#ffe4b5",
- navajowhite: "#ffdead",
- navy: "#000080",
- oldlace: "#fdf5e6",
- olive: "#808000",
- olivedrab: "#6b8e23",
- orange: "#ffa500",
- orangered: "#ff4500",
- orchid: "#da70d6",
- palegoldenrod: "#eee8aa",
- palegreen: "#98fb98",
- paleturquoise: "#afeeee",
- palevioletred: "#d87093",
- papayawhip: "#ffefd5",
- peachpuff: "#ffdab9",
- peru: "#cd853f",
- pink: "#ffc0cb",
- plum: "#dda0dd",
- powderblue: "#b0e0e6",
- purple: "#800080",
- red: "#ff0000",
- rosybrown: "#bc8f8f",
- royalblue: "#4169e1",
- saddlebrown: "#8b4513",
- salmon: "#fa8072",
- sandybrown: "#f4a460",
- seagreen: "#2e8b57",
- seashell: "#fff5ee",
- sienna: "#a0522d",
- silver: "#c0c0c0",
- skyblue: "#87ceeb",
- slateblue: "#6a5acd",
- slategray: "#708090",
- snow: "#fffafa",
- springgreen: "#00ff7f",
- steelblue: "#4682b4",
- tan: "#d2b48c",
- teal: "#008080",
- thistle: "#d8bfd8",
- tomato: "#ff6347",
- turquoise: "#40e0d0",
- violet: "#ee82ee",
- wheat: "#f5deb3",
- white: "#ffffff",
- whitesmoke: "#f5f5f5",
- yellow: "#ffff00",
- yellowgreen: "#9acd32"
- },
- fromHSL: function(d, c, b) {
- return (new this(0, 0, 0, 0)).setHSL(d, c, b)
- },
- fromHSV: function(d, c, b) {
- return (new this(0, 0, 0, 0)).setHSL(d, c, b)
- },
- fromString: function(b) {
- return (new this(0, 0, 0, 0)).setFromString(b)
- },
- create: function(b) {
- if (b instanceof this) {
- return b
- } else {
- if (Ext.isArray(b)) {
- return new Ext.draw.Color(b[0], b[1], b[2], b[3])
- } else {
- if (Ext.isString(b)) {
- return Ext.draw.Color.fromString(b)
- } else {
- if (arguments.length > 2) {
- return new Ext.draw.Color(arguments[0], arguments[1], arguments[2], arguments[3])
- } else {
- return new Ext.draw.Color(0, 0, 0, 0)
- }
- }
- }
- }
- }
- })
-});
-Ext.define("Ext.draw.sprite.AnimationParser", function() {
- function a(d, c, b) {
- return d + (c - d) * b
- }
- return {
- singleton: true,
- attributeRe: /^url\(#([a-zA-Z\-]+)\)$/,
- requires: ["Ext.draw.Color"],
- color: {
- parseInitial: function(c, b) {
- if (Ext.isString(c)) {
- c = Ext.draw.Color.create(c)
- }
- if (Ext.isString(b)) {
- b = Ext.draw.Color.create(b)
- }
- if ((c instanceof Ext.draw.Color) && (b instanceof Ext.draw.Color)) {
- return [
- [c.r, c.g, c.b, c.a],
- [b.r, b.g, b.b, b.a]
- ]
- } else {
- return [c || b, b || c]
- }
- },
- compute: function(d, c, b) {
- if (!Ext.isArray(d) || !Ext.isArray(c)) {
- return c || d
- } else {
- return [a(d[0], c[0], b), a(d[1], c[1], b), a(d[2], c[2], b), a(d[3], c[3], b)]
- }
- },
- serve: function(c) {
- var b = Ext.draw.Color.fly(c[0], c[1], c[2], c[3]);
- return b.toString()
- }
- },
- number: {
- parse: function(b) {
- return b === null ? null : +b
- },
- compute: function(d, c, b) {
- if (!Ext.isNumber(d) || !Ext.isNumber(c)) {
- return c || d
- } else {
- return a(d, c, b)
- }
- }
- },
- angle: {
- parseInitial: function(c, b) {
- if (b - c > Math.PI) {
- b -= Math.PI * 2
- } else {
- if (b - c < -Math.PI) {
- b += Math.PI * 2
- }
- }
- return [c, b]
- },
- compute: function(d, c, b) {
- if (!Ext.isNumber(d) || !Ext.isNumber(c)) {
- return c || d
- } else {
- return a(d, c, b)
- }
- }
- },
- path: {
- parseInitial: function(m, n) {
- var c = m.toStripes(),
- o = n.toStripes(),
- e, d, k = c.length,
- p = o.length,
- h, f, b, g = o[p - 1],
- l = [g[g.length - 2], g[g.length - 1]];
- for (e = k; e < p; e++) {
- c.push(c[k - 1].slice(0))
- }
- for (e = p; e < k; e++) {
- o.push(l.slice(0))
- }
- b = c.length;
- o.path = n;
- o.temp = new Ext.draw.Path();
- for (e = 0; e < b; e++) {
- h = c[e];
- f = o[e];
- k = h.length;
- p = f.length;
- o.temp.commands.push("M");
- for (d = p; d < k; d += 6) {
- f.push(l[0], l[1], l[0], l[1], l[0], l[1])
- }
- g = o[o.length - 1];
- l = [g[g.length - 2], g[g.length - 1]];
- for (d = k; d < p; d += 6) {
- h.push(l[0], l[1], l[0], l[1], l[0], l[1])
- }
- for (e = 0; e < f.length; e++) {
- f[e] -= h[e]
- }
- for (e = 2; e < f.length; e += 6) {
- o.temp.commands.push("C")
- }
- }
- return [c, o]
- },
- compute: function(c, l, m) {
- if (m >= 1) {
- return l.path
- }
- var e = 0,
- f = c.length,
- d = 0,
- b, k, h, n = l.temp.params,
- g = 0;
- for (; e < f; e++) {
- k = c[e];
- h = l[e];
- b = k.length;
- for (d = 0; d < b; d++) {
- n[g++] = h[d] * m + k[d]
- }
- }
- return l.temp
- }
- },
- data: {
- compute: function(h, j, k, g) {
- var m = h.length - 1,
- b = j.length - 1,
- e = Math.max(m, b),
- d, l, c;
- if (!g || g === h) {
- g = []
- }
- g.length = e + 1;
- for (c = 0; c <= e; c++) {
- d = h[Math.min(c, m)];
- l = j[Math.min(c, b)];
- if (Ext.isNumber(d)) {
- if (!Ext.isNumber(l)) {
- l = 0
- }
- g[c] = (l - d) * k + d
- } else {
- g[c] = l
- }
- }
- return g
- }
- },
- text: {
- compute: function(d, c, b) {
- return d.substr(0, Math.round(d.length * (1 - b))) + c.substr(Math.round(c.length * (1 - b)))
- }
- },
- limited: "number",
- limited01: "number"
- }
-});
-(function() {
- if (!Ext.global.Float32Array) {
- var a = function(d) {
- if (typeof d === "number") {
- this.length = d
- } else {
- if ("length" in d) {
- this.length = d.length;
- for (var c = 0, b = d.length; c < b; c++) {
- this[c] = +d[c]
- }
- }
- }
- };
- a.prototype = [];
- Ext.global.Float32Array = a
- }
-})();
-Ext.define("Ext.draw.Draw", {
- singleton: true,
- radian: Math.PI / 180,
- pi2: Math.PI * 2,
- reflectFn: function(b) {
- return b
- },
- rad: function(a) {
- return (a % 360) * this.radian
- },
- degrees: function(a) {
- return (a / this.radian) % 360
- },
- isBBoxIntersect: function(b, a, c) {
- c = c || 0;
- return (Math.max(b.x, a.x) - c > Math.min(b.x + b.width, a.x + a.width)) || (Math.max(b.y, a.y) - c > Math.min(b.y + b.height, a.y + a.height))
- },
- isPointInBBox: function(a, c, b) {
- return !!b && a >= b.x && a <= (b.x + b.width) && c >= b.y && c <= (b.y + b.height)
- },
- spline: function(m) {
- var e, c, k = m.length,
- b, h, l, f, a = 0,
- g = new Float32Array(m.length),
- n = new Float32Array(m.length * 3 - 2);
- g[0] = 0;
- g[k - 1] = 0;
- for (e = 1; e < k - 1; e++) {
- g[e] = (m[e + 1] + m[e - 1] - 2 * m[e]) - g[e - 1];
- a = 1 / (4 - a);
- g[e] *= a
- }
- for (e = k - 2; e > 0; e--) {
- a = 3.732050807568877 + 48.248711305964385 / (-13.928203230275537 + Math.pow(0.07179676972449123, e));
- g[e] -= g[e + 1] * a
- }
- f = m[0];
- b = f - g[0];
- for (e = 0, c = 0; e < k - 1; c += 3) {
- l = f;
- h = b;
- e++;
- f = m[e];
- b = f - g[e];
- n[c] = l;
- n[c + 1] = (b + 2 * h) / 3;
- n[c + 2] = (b * 2 + h) / 3
- }
- n[c] = f;
- return n
- },
- getAnchors: function(e, d, i, h, t, s, o) {
- o = o || 4;
- var n = Math.PI,
- p = n / 2,
- k = Math.abs,
- a = Math.sin,
- b = Math.cos,
- f = Math.atan,
- r, q, g, j, m, l, v, u, c;
- r = (i - e) / o;
- q = (t - i) / o;
- if ((h >= d && h >= s) || (h <= d && h <= s)) {
- g = j = p
- } else {
- g = f((i - e) / k(h - d));
- if (d < h) {
- g = n - g
- }
- j = f((t - i) / k(h - s));
- if (s < h) {
- j = n - j
- }
- }
- c = p - ((g + j) % (n * 2)) / 2;
- if (c > p) {
- c -= n
- }
- g += c;
- j += c;
- m = i - r * a(g);
- l = h + r * b(g);
- v = i + q * a(j);
- u = h + q * b(j);
- if ((h > d && l < d) || (h < d && l > d)) {
- m += k(d - l) * (m - i) / (l - h);
- l = d
- }
- if ((h > s && u < s) || (h < s && u > s)) {
- v -= k(s - u) * (v - i) / (u - h);
- u = s
- }
- return {
- x1: m,
- y1: l,
- x2: v,
- y2: u
- }
- },
- smooth: function(l, j, o) {
- var k = l.length,
- h, g, c, b, q, p, n, m, f = [],
- e = [],
- d, a;
- for (d = 0; d < k - 1; d++) {
- h = l[d];
- g = j[d];
- if (d === 0) {
- n = h;
- m = g;
- f.push(n);
- e.push(m);
- if (k === 1) {
- break
- }
- }
- c = l[d + 1];
- b = j[d + 1];
- q = l[d + 2];
- p = j[d + 2];
- if (!Ext.isNumber(q + p)) {
- f.push(n, c, c);
- e.push(m, b, b);
- break
- }
- a = this.getAnchors(h, g, c, b, q, p, o);
- f.push(n, a.x1, c);
- e.push(m, a.y1, b);
- n = a.x2;
- m = a.y2
- }
- return {
- smoothX: f,
- smoothY: e
- }
- },
- beginUpdateIOS: Ext.os.is.iOS ? function() {
- this.iosUpdateEl = Ext.getBody().createChild({
- style: "position: absolute; top: 0px; bottom: 0px; left: 0px; right: 0px; background: rgba(0,0,0,0.001); z-index: 100000"
- })
- } : Ext.emptyFn,
- endUpdateIOS: function() {
- this.iosUpdateEl = Ext.destroy(this.iosUpdateEl)
- }
-});
-Ext.define("Ext.draw.gradient.Gradient", {
- requires: ["Ext.draw.Color"],
- isGradient: true,
- config: {
- stops: []
- },
- applyStops: function(f) {
- var e = [],
- d = f.length,
- c, b, a;
- for (c = 0; c < d; c++) {
- b = f[c];
- a = b.color;
- if (!(a && a.isColor)) {
- a = Ext.draw.Color.fly(a || Ext.draw.Color.NONE)
- }
- e.push({
- offset: Math.min(1, Math.max(0, "offset" in b ? b.offset : b.position || 0)),
- color: a.toString()
- })
- }
- e.sort(function(h, g) {
- return h.offset - g.offset
- });
- return e
- },
- onClassExtended: function(a, b) {
- if (!b.alias && b.type) {
- b.alias = "gradient." + b.type
- }
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- generateGradient: Ext.emptyFn
-});
-Ext.define("Ext.draw.gradient.GradientDefinition", {
- singleton: true,
- urlStringRe: /^url\(#([\w\-]+)\)$/,
- gradients: {},
- add: function(a) {
- var b = this.gradients,
- c, e, d;
- for (c = 0, e = a.length; c < e; c++) {
- d = a[c];
- if (Ext.isString(d.id)) {
- b[d.id] = d
- }
- }
- },
- get: function(d) {
- var a = this.gradients,
- b = d.match(this.urlStringRe),
- c;
- if (b && b[1] && (c = a[b[1]])) {
- return c || d
- }
- return d
- }
-});
-Ext.define("Ext.draw.sprite.AttributeParser", {
- singleton: true,
- attributeRe: /^url\(#([a-zA-Z\-]+)\)$/,
- requires: ["Ext.draw.Color", "Ext.draw.gradient.GradientDefinition"],
- "default": Ext.identityFn,
- string: function(a) {
- return String(a)
- },
- number: function(a) {
- if (Ext.isNumber(+a)) {
- return a
- }
- },
- angle: function(a) {
- if (Ext.isNumber(a)) {
- a %= Math.PI * 2;
- if (a < -Math.PI) {
- a += Math.PI * 2
- } else {
- if (a >= Math.PI) {
- a -= Math.PI * 2
- }
- }
- return a
- }
- },
- data: function(a) {
- if (Ext.isArray(a)) {
- return a.slice()
- } else {
- if (a instanceof Float32Array) {
- return new Float32Array(a)
- }
- }
- },
- bool: function(a) {
- return !!a
- },
- color: function(a) {
- if (a instanceof Ext.draw.Color) {
- return a.toString()
- } else {
- if (a instanceof Ext.draw.gradient.Gradient) {
- return a
- } else {
- if (!a) {
- return Ext.draw.Color.NONE
- } else {
- if (Ext.isString(a)) {
- if (a.substr(0, 3) === "url") {
- a = Ext.draw.gradient.GradientDefinition.get(a);
- if (Ext.isString(a)) {
- return a
- }
- } else {
- return Ext.draw.Color.fly(a).toString()
- }
- }
- }
- }
- }
- if (a.type === "linear") {
- return Ext.create("Ext.draw.gradient.Linear", a)
- } else {
- if (a.type === "radial") {
- return Ext.create("Ext.draw.gradient.Radial", a)
- } else {
- if (a.type === "pattern") {
- return Ext.create("Ext.draw.gradient.Pattern", a)
- } else {
- return Ext.draw.Color.NONE
- }
- }
- }
- },
- limited: function(a, b) {
- return function(c) {
- c = +c;
- return Ext.isNumber(c) ? Math.min(Math.max(c, a), b) : undefined
- }
- },
- limited01: function(a) {
- a = +a;
- return Ext.isNumber(a) ? Math.min(Math.max(a, 0), 1) : undefined
- },
- enums: function() {
- var d = {},
- a = Array.prototype.slice.call(arguments, 0),
- b, c;
- for (b = 0, c = a.length; b < c; b++) {
- d[a[b]] = true
- }
- return function(e) {
- return e in d ? e : undefined
- }
- }
-});
-Ext.define("Ext.draw.sprite.AttributeDefinition", {
- requires: ["Ext.draw.sprite.AttributeParser", "Ext.draw.sprite.AnimationParser"],
- config: {
- defaults: {
- $value: {},
- lazy: true
- },
- aliases: {},
- animationProcessors: {},
- processors: {
- $value: {},
- lazy: true
- },
- dirtyTriggers: {},
- triggers: {},
- updaters: {}
- },
- inheritableStatics: {
- processorFactoryRe: /^(\w+)\(([\w\-,]*)\)$/
- },
- spriteClass: null,
- constructor: function(a) {
- var b = this;
- b.initConfig(a)
- },
- applyDefaults: function(b, a) {
- a = Ext.apply(a || {}, this.normalize(b));
- return a
- },
- applyAliases: function(b, a) {
- return Ext.apply(a || {}, b)
- },
- applyProcessors: function(e, i) {
- this.getAnimationProcessors();
- var j = i || {},
- h = Ext.draw.sprite.AttributeParser,
- a = this.self.processorFactoryRe,
- g = {},
- d, b, c, f;
- for (b in e) {
- f = e[b];
- if (typeof f === "string") {
- c = f.match(a);
- if (c) {
- f = h[c[1]].apply(h, c[2].split(","))
- } else {
- if (h[f]) {
- g[b] = f;
- d = true;
- f = h[f]
- }
- }
- }
- j[b] = f
- }
- if (d) {
- this.setAnimationProcessors(g)
- }
- return j
- },
- applyAnimationProcessors: function(c, a) {
- var e = Ext.draw.sprite.AnimationParser,
- b, d;
- if (!a) {
- a = {}
- }
- for (b in c) {
- d = c[b];
- if (d === "none") {
- a[b] = null
- } else {
- if (Ext.isString(d) && !(b in a)) {
- if (d in e) {
- while (Ext.isString(e[d])) {
- d = e[d]
- }
- a[b] = e[d]
- }
- } else {
- if (Ext.isObject(d)) {
- a[b] = d
- }
- }
- }
- }
- return a
- },
- updateDirtyTriggers: function(a) {
- this.setTriggers(a)
- },
- applyTriggers: function(b, c) {
- if (!c) {
- c = {}
- }
- for (var a in b) {
- c[a] = b[a].split(",")
- }
- return c
- },
- applyUpdaters: function(b, a) {
- return Ext.apply(a || {}, b)
- },
- batchedNormalize: function(f, n) {
- if (!f) {
- return {}
- }
- var j = this.getProcessors(),
- d = this.getAliases(),
- a = f.translation || f.translate,
- o = {},
- g, h, b, e, p, c, m, l, k;
- if ("rotation" in f) {
- p = f.rotation
- } else {
- p = ("rotate" in f) ? f.rotate : undefined
- }
- if ("scaling" in f) {
- c = f.scaling
- } else {
- c = ("scale" in f) ? f.scale : undefined
- }
- if (typeof c !== "undefined") {
- if (Ext.isNumber(c)) {
- o.scalingX = c;
- o.scalingY = c
- } else {
- if ("x" in c) {
- o.scalingX = c.x
- }
- if ("y" in c) {
- o.scalingY = c.y
- }
- if ("centerX" in c) {
- o.scalingCenterX = c.centerX
- }
- if ("centerY" in c) {
- o.scalingCenterY = c.centerY
- }
- }
- }
- if (typeof p !== "undefined") {
- if (Ext.isNumber(p)) {
- p = Ext.draw.Draw.rad(p);
- o.rotationRads = p
- } else {
- if ("rads" in p) {
- o.rotationRads = p.rads
- } else {
- if ("degrees" in p) {
- if (Ext.isArray(p.degrees)) {
- o.rotationRads = Ext.Array.map(p.degrees, function(i) {
- return Ext.draw.Draw.rad(i)
- })
- } else {
- o.rotationRads = Ext.draw.Draw.rad(p.degrees)
- }
- }
- }
- if ("centerX" in p) {
- o.rotationCenterX = p.centerX
- }
- if ("centerY" in p) {
- o.rotationCenterY = p.centerY
- }
- }
- }
- if (typeof a !== "undefined") {
- if ("x" in a) {
- o.translationX = a.x
- }
- if ("y" in a) {
- o.translationY = a.y
- }
- }
- if ("matrix" in f) {
- m = Ext.draw.Matrix.create(f.matrix);
- k = m.split();
- o.matrix = m;
- o.rotationRads = k.rotation;
- o.rotationCenterX = 0;
- o.rotationCenterY = 0;
- o.scalingX = k.scaleX;
- o.scalingY = k.scaleY;
- o.scalingCenterX = 0;
- o.scalingCenterY = 0;
- o.translationX = k.translateX;
- o.translationY = k.translateY
- }
- for (b in f) {
- e = f[b];
- if (typeof e === "undefined") {
- continue
- } else {
- if (Ext.isArray(e)) {
- if (b in d) {
- b = d[b]
- }
- if (b in j) {
- o[b] = [];
- for (g = 0, h = e.length; g < h; g++) {
- l = j[b].call(this, e[g]);
- if (typeof l !== "undefined") {
- o[b][g] = l
- }
- }
- } else {
- if (n) {
- o[b] = e
- }
- }
- } else {
- if (b in d) {
- b = d[b]
- }
- if (b in j) {
- e = j[b].call(this, e);
- if (typeof e !== "undefined") {
- o[b] = e
- }
- } else {
- if (n) {
- o[b] = e
- }
- }
- }
- }
- }
- return o
- },
- normalize: function(i, j) {
- if (!i) {
- return {}
- }
- var f = this.getProcessors(),
- d = this.getAliases(),
- a = i.translation || i.translate,
- k = {},
- b, e, l, c, h, g;
- if ("rotation" in i) {
- l = i.rotation
- } else {
- l = ("rotate" in i) ? i.rotate : undefined
- }
- if ("scaling" in i) {
- c = i.scaling
- } else {
- c = ("scale" in i) ? i.scale : undefined
- }
- if (a) {
- if ("x" in a) {
- k.translationX = a.x
- }
- if ("y" in a) {
- k.translationY = a.y
- }
- }
- if (typeof c !== "undefined") {
- if (Ext.isNumber(c)) {
- k.scalingX = c;
- k.scalingY = c
- } else {
- if ("x" in c) {
- k.scalingX = c.x
- }
- if ("y" in c) {
- k.scalingY = c.y
- }
- if ("centerX" in c) {
- k.scalingCenterX = c.centerX
- }
- if ("centerY" in c) {
- k.scalingCenterY = c.centerY
- }
- }
- }
- if (typeof l !== "undefined") {
- if (Ext.isNumber(l)) {
- l = Ext.draw.Draw.rad(l);
- k.rotationRads = l
- } else {
- if ("rads" in l) {
- k.rotationRads = l.rads
- } else {
- if ("degrees" in l) {
- k.rotationRads = Ext.draw.Draw.rad(l.degrees)
- }
- }
- if ("centerX" in l) {
- k.rotationCenterX = l.centerX
- }
- if ("centerY" in l) {
- k.rotationCenterY = l.centerY
- }
- }
- }
- if ("matrix" in i) {
- h = Ext.draw.Matrix.create(i.matrix);
- g = h.split();
- k.matrix = h;
- k.rotationRads = g.rotation;
- k.rotationCenterX = 0;
- k.rotationCenterY = 0;
- k.scalingX = g.scaleX;
- k.scalingY = g.scaleY;
- k.scalingCenterX = 0;
- k.scalingCenterY = 0;
- k.translationX = g.translateX;
- k.translationY = g.translateY
- }
- for (b in i) {
- e = i[b];
- if (typeof e === "undefined") {
- continue
- }
- if (b in d) {
- b = d[b]
- }
- if (b in f) {
- e = f[b].call(this, e);
- if (typeof e !== "undefined") {
- k[b] = e
- }
- } else {
- if (j) {
- k[b] = e
- }
- }
- }
- return k
- },
- setBypassingNormalization: function(a, c, b) {
- return c.pushDown(a, b)
- },
- set: function(a, c, b) {
- b = this.normalize(b);
- return this.setBypassingNormalization(a, c, b)
- }
-});
-Ext.define("Ext.draw.Matrix", {
- isMatrix: true,
- statics: {
- createAffineMatrixFromTwoPair: function(h, t, g, s, k, o, i, j) {
- var v = g - h,
- u = s - t,
- e = i - k,
- q = j - o,
- d = 1 / (v * v + u * u),
- p = v * e + u * q,
- n = e * u - v * q,
- m = -p * h - n * t,
- l = n * h - p * t;
- return new this(p * d, -n * d, n * d, p * d, m * d + k, l * d + o)
- },
- createPanZoomFromTwoPair: function(q, e, p, c, h, s, n, g) {
- if (arguments.length === 2) {
- return this.createPanZoomFromTwoPair.apply(this, q.concat(e))
- }
- var k = p - q,
- j = c - e,
- d = (q + p) * 0.5,
- b = (e + c) * 0.5,
- o = n - h,
- a = g - s,
- f = (h + n) * 0.5,
- l = (s + g) * 0.5,
- m = k * k + j * j,
- i = o * o + a * a,
- t = Math.sqrt(i / m);
- return new this(t, 0, 0, t, f - t * d, l - t * b)
- },
- fly: (function() {
- var a = null,
- b = function(c) {
- a.elements = c;
- return a
- };
- return function(c) {
- if (!a) {
- a = new Ext.draw.Matrix()
- }
- a.elements = c;
- Ext.draw.Matrix.fly = b;
- return a
- }
- })(),
- create: function(a) {
- if (a instanceof this) {
- return a
- }
- return new this(a)
- }
- },
- constructor: function(e, d, a, f, c, b) {
- if (e && e.length === 6) {
- this.elements = e.slice()
- } else {
- if (e !== undefined) {
- this.elements = [e, d, a, f, c, b]
- } else {
- this.elements = [1, 0, 0, 1, 0, 0]
- }
- }
- },
- prepend: function(a, l, h, g, m, k) {
- var b = this.elements,
- d = b[0],
- j = b[1],
- e = b[2],
- c = b[3],
- i = b[4],
- f = b[5];
- b[0] = a * d + h * j;
- b[1] = l * d + g * j;
- b[2] = a * e + h * c;
- b[3] = l * e + g * c;
- b[4] = a * i + h * f + m;
- b[5] = l * i + g * f + k;
- return this
- },
- prependMatrix: function(a) {
- return this.prepend.apply(this, a.elements)
- },
- append: function(a, l, h, g, m, k) {
- var b = this.elements,
- d = b[0],
- j = b[1],
- e = b[2],
- c = b[3],
- i = b[4],
- f = b[5];
- b[0] = a * d + l * e;
- b[1] = a * j + l * c;
- b[2] = h * d + g * e;
- b[3] = h * j + g * c;
- b[4] = m * d + k * e + i;
- b[5] = m * j + k * c + f;
- return this
- },
- appendMatrix: function(a) {
- return this.append.apply(this, a.elements)
- },
- set: function(f, e, a, g, c, b) {
- var d = this.elements;
- d[0] = f;
- d[1] = e;
- d[2] = a;
- d[3] = g;
- d[4] = c;
- d[5] = b;
- return this
- },
- inverse: function(i) {
- var g = this.elements,
- o = g[0],
- m = g[1],
- l = g[2],
- k = g[3],
- j = g[4],
- h = g[5],
- n = 1 / (o * k - m * l);
- o *= n;
- m *= n;
- l *= n;
- k *= n;
- if (i) {
- i.set(k, -m, -l, o, l * h - k * j, m * j - o * h);
- return i
- } else {
- return new Ext.draw.Matrix(k, -m, -l, o, l * h - k * j, m * j - o * h)
- }
- },
- translate: function(a, c, b) {
- if (b) {
- return this.prepend(1, 0, 0, 1, a, c)
- } else {
- return this.append(1, 0, 0, 1, a, c)
- }
- },
- scale: function(f, e, c, a, b) {
- var d = this;
- if (e == null) {
- e = f
- }
- if (c === undefined) {
- c = 0
- }
- if (a === undefined) {
- a = 0
- }
- if (b) {
- return d.prepend(f, 0, 0, e, c - c * f, a - a * e)
- } else {
- return d.append(f, 0, 0, e, c - c * f, a - a * e)
- }
- },
- rotate: function(g, e, c, b) {
- var d = this,
- f = Math.cos(g),
- a = Math.sin(g);
- e = e || 0;
- c = c || 0;
- if (b) {
- return d.prepend(f, a, -a, f, e - f * e + c * a, c - f * c - e * a)
- } else {
- return d.append(f, a, -a, f, e - f * e + c * a, c - f * c - e * a)
- }
- },
- rotateFromVector: function(a, h, c) {
- var e = this,
- g = Math.sqrt(a * a + h * h),
- f = a / g,
- b = h / g;
- if (c) {
- return e.prepend(f, b, -b, f, 0, 0)
- } else {
- return e.append(f, b, -b, f, 0, 0)
- }
- },
- clone: function() {
- return new Ext.draw.Matrix(this.elements)
- },
- flipX: function() {
- return this.append(-1, 0, 0, 1, 0, 0)
- },
- flipY: function() {
- return this.append(1, 0, 0, -1, 0, 0)
- },
- skewX: function(a) {
- return this.append(1, 0, Math.tan(a), 1, 0, 0)
- },
- skewY: function(a) {
- return this.append(1, Math.tan(a), 0, 1, 0, 0)
- },
- shearX: function(a) {
- return this.append(1, 0, a, 1, 0, 0)
- },
- shearY: function(a) {
- return this.append(1, a, 0, 1, 0, 0)
- },
- reset: function() {
- return this.set(1, 0, 0, 1, 0, 0)
- },
- precisionCompensate: function(j, g) {
- var c = this.elements,
- f = c[0],
- e = c[1],
- i = c[2],
- h = c[3],
- d = c[4],
- b = c[5],
- a = e * i - f * h;
- g.b = j * e / f;
- g.c = j * i / h;
- g.d = j;
- g.xx = f / j;
- g.yy = h / j;
- g.dx = (b * f * i - d * f * h) / a / j;
- g.dy = (d * e * h - b * f * h) / a / j
- },
- precisionCompensateRect: function(j, g) {
- var b = this.elements,
- f = b[0],
- e = b[1],
- i = b[2],
- h = b[3],
- c = b[4],
- a = b[5],
- d = i / f;
- g.b = j * e / f;
- g.c = j * d;
- g.d = j * h / f;
- g.xx = f / j;
- g.yy = f / j;
- g.dx = (a * i - c * h) / (e * d - h) / j;
- g.dy = -(a * f - c * e) / (e * d - h) / j
- },
- x: function(a, c) {
- var b = this.elements;
- return a * b[0] + c * b[2] + b[4]
- },
- y: function(a, c) {
- var b = this.elements;
- return a * b[1] + c * b[3] + b[5]
- },
- get: function(b, a) {
- return +this.elements[b + a * 2].toFixed(4)
- },
- transformPoint: function(b) {
- var c = this.elements,
- a, d;
- if (b.isPoint) {
- a = b.x;
- d = b.y
- } else {
- a = b[0];
- d = b[1]
- }
- return [a * c[0] + d * c[2] + c[4], a * c[1] + d * c[3] + c[5]]
- },
- transformBBox: function(q, i, j) {
- var b = this.elements,
- d = q.x,
- r = q.y,
- g = q.width * 0.5,
- o = q.height * 0.5,
- a = b[0],
- s = b[1],
- n = b[2],
- k = b[3],
- e = d + g,
- c = r + o,
- p, f, m;
- if (i) {
- g -= i;
- o -= i;
- m = [Math.sqrt(b[0] * b[0] + b[2] * b[2]), Math.sqrt(b[1] * b[1] + b[3] * b[3])];
- p = Math.abs(g * a) + Math.abs(o * n) + Math.abs(m[0] * i);
- f = Math.abs(g * s) + Math.abs(o * k) + Math.abs(m[1] * i)
- } else {
- p = Math.abs(g * a) + Math.abs(o * n);
- f = Math.abs(g * s) + Math.abs(o * k)
- }
- if (!j) {
- j = {}
- }
- j.x = e * a + c * n + b[4] - p;
- j.y = e * s + c * k + b[5] - f;
- j.width = p + p;
- j.height = f + f;
- return j
- },
- transformList: function(e) {
- var b = this.elements,
- a = b[0],
- h = b[2],
- l = b[4],
- k = b[1],
- g = b[3],
- j = b[5],
- f = e.length,
- c, d;
- for (d = 0; d < f; d++) {
- c = e[d];
- e[d] = [c[0] * a + c[1] * h + l, c[0] * k + c[1] * g + j]
- }
- return e
- },
- isIdentity: function() {
- var a = this.elements;
- return a[0] === 1 && a[1] === 0 && a[2] === 0 && a[3] === 1 && a[4] === 0 && a[5] === 0
- },
- isEqual: function(a) {
- var c = a && a.isMatrix ? a.elements : a,
- b = this.elements;
- return b[0] === c[0] && b[1] === c[1] && b[2] === c[2] && b[3] === c[3] && b[4] === c[4] && b[5] === c[5]
- },
- equals: function(a) {
- return this.isEqual(a)
- },
- toArray: function() {
- var a = this.elements;
- return [a[0], a[2], a[4], a[1], a[3], a[5]]
- },
- toVerticalArray: function() {
- return this.elements.slice()
- },
- toString: function() {
- var a = this;
- return [a.get(0, 0), a.get(0, 1), a.get(1, 0), a.get(1, 1), a.get(2, 0), a.get(2, 1)].join(",")
- },
- toContext: function(a) {
- a.transform.apply(a, this.elements);
- return this
- },
- toSvg: function() {
- var a = this.elements;
- return "matrix(" + a[0].toFixed(9) + "," + a[1].toFixed(9) + "," + a[2].toFixed(9) + "," + a[3].toFixed(9) + "," + a[4].toFixed(9) + "," + a[5].toFixed(9) + ")"
- },
- getScaleX: function() {
- var a = this.elements;
- return Math.sqrt(a[0] * a[0] + a[2] * a[2])
- },
- getScaleY: function() {
- var a = this.elements;
- return Math.sqrt(a[1] * a[1] + a[3] * a[3])
- },
- getXX: function() {
- return this.elements[0]
- },
- getXY: function() {
- return this.elements[1]
- },
- getYX: function() {
- return this.elements[2]
- },
- getYY: function() {
- return this.elements[3]
- },
- getDX: function() {
- return this.elements[4]
- },
- getDY: function() {
- return this.elements[5]
- },
- split: function() {
- var b = this.elements,
- d = b[0],
- c = b[1],
- e = b[3],
- a = {
- translateX: b[4],
- translateY: b[5]
- };
- a.rotate = a.rotation = Math.atan2(c, d);
- a.scaleX = d / Math.cos(a.rotate);
- a.scaleY = e / d * a.scaleX;
- return a
- }
-}, function() {
- function b(e, c, d) {
- e[c] = {
- get: function() {
- return this.elements[d]
- },
- set: function(f) {
- this.elements[d] = f
- }
- }
- }
- if (Object.defineProperties) {
- var a = {};
- b(a, "a", 0);
- b(a, "b", 1);
- b(a, "c", 2);
- b(a, "d", 3);
- b(a, "e", 4);
- b(a, "f", 5);
- Object.defineProperties(this.prototype, a)
- }
- this.prototype.multiply = this.prototype.appendMatrix
-});
-Ext.define("Ext.draw.modifier.Modifier", {
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- previous: null,
- next: null,
- sprite: null
- },
- constructor: function(a) {
- this.mixins.observable.constructor.call(this, a)
- },
- updateNext: function(a) {
- if (a) {
- a.setPrevious(this)
- }
- },
- updatePrevious: function(a) {
- if (a) {
- a.setNext(this)
- }
- },
- prepareAttributes: function(a) {
- if (this._previous) {
- this._previous.prepareAttributes(a)
- }
- },
- popUp: function(a, b) {
- if (this._next) {
- this._next.popUp(a, b)
- } else {
- Ext.apply(a, b)
- }
- },
- pushDown: function(a, c) {
- if (this._previous) {
- return this._previous.pushDown(a, c)
- } else {
- for (var b in c) {
- if (c[b] === a[b]) {
- delete c[b]
- }
- }
- return c
- }
- }
-});
-Ext.define("Ext.draw.modifier.Target", {
- requires: ["Ext.draw.Matrix"],
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.target",
- statics: {
- uniqueId: 0
- },
- prepareAttributes: function(a) {
- var b = this.getPrevious();
- if (b) {
- b.prepareAttributes(a)
- }
- a.attributeId = "attribute-" + Ext.draw.modifier.Target.uniqueId++;
- if (!a.hasOwnProperty("canvasAttributes")) {
- a.bbox = {
- plain: {
- dirty: true
- },
- transform: {
- dirty: true
- }
- };
- a.dirty = true;
- a.pendingUpdaters = {};
- a.canvasAttributes = {};
- a.matrix = new Ext.draw.Matrix();
- a.inverseMatrix = new Ext.draw.Matrix()
- }
- },
- applyChanges: function(f, k) {
- Ext.apply(f, k);
- var l = this.getSprite(),
- o = f.pendingUpdaters,
- h = l.self.def.getTriggers(),
- p, a, m, b, e, n, d, c, g;
- for (b in k) {
- e = true;
- if ((p = h[b])) {
- l.scheduleUpdaters(f, p, [b])
- }
- if (f.template && k.removeFromInstance && k.removeFromInstance[b]) {
- delete f[b]
- }
- }
- if (!e) {
- return
- }
- if (o.canvas) {
- n = o.canvas;
- delete o.canvas;
- for (d = 0, g = n.length; d < g; d++) {
- b = n[d];
- f.canvasAttributes[b] = f[b]
- }
- }
- if (f.hasOwnProperty("children")) {
- a = f.children;
- for (d = 0, g = a.length; d < g; d++) {
- m = a[d];
- Ext.apply(m.pendingUpdaters, o);
- if (n) {
- for (c = 0; c < n.length; c++) {
- b = n[c];
- m.canvasAttributes[b] = m[b]
- }
- }
- l.callUpdaters(m)
- }
- }
- l.setDirty(true);
- l.callUpdaters(f)
- },
- popUp: function(a, b) {
- this.applyChanges(a, b)
- },
- pushDown: function(a, b) {
- var c = this.getPrevious();
- if (c) {
- b = c.pushDown(a, b)
- }
- this.applyChanges(a, b);
- return b
- }
-});
-Ext.define("Ext.draw.TimingFunctions", function() {
- var g = Math.pow,
- j = Math.sin,
- m = Math.cos,
- l = Math.sqrt,
- e = Math.PI,
- b = ["quad", "cube", "quart", "quint"],
- c = {
- pow: function(o, i) {
- return g(o, i || 6)
- },
- expo: function(i) {
- return g(2, 8 * (i - 1))
- },
- circ: function(i) {
- return 1 - l(1 - i * i)
- },
- sine: function(i) {
- return 1 - j((1 - i) * e / 2)
- },
- back: function(i, o) {
- o = o || 1.616;
- return i * i * ((o + 1) * i - o)
- },
- bounce: function(q) {
- for (var o = 0, i = 1; 1; o += i, i /= 2) {
- if (q >= (7 - 4 * o) / 11) {
- return i * i - g((11 - 6 * o - 11 * q) / 4, 2)
- }
- }
- },
- elastic: function(o, i) {
- return g(2, 10 * --o) * m(20 * o * e * (i || 1) / 3)
- }
- },
- k = {},
- a, f, d;
-
- function h(i) {
- return function(o) {
- return g(o, i)
- }
- }
-
- function n(i, o) {
- k[i + "In"] = function(p) {
- return o(p)
- };
- k[i + "Out"] = function(p) {
- return 1 - o(1 - p)
- };
- k[i + "InOut"] = function(p) {
- return (p <= 0.5) ? o(2 * p) / 2 : (2 - o(2 * (1 - p))) / 2
- }
- }
- for (d = 0, f = b.length; d < f; ++d) {
- c[b[d]] = h(d + 2)
- }
- for (a in c) {
- n(a, c[a])
- }
- k.linear = Ext.identityFn;
- k.easeIn = k.quadIn;
- k.easeOut = k.quadOut;
- k.easeInOut = k.quadInOut;
- return {
- singleton: true,
- easingMap: k
- }
-}, function(a) {
- Ext.apply(a, a.easingMap)
-});
-Ext.define("Ext.draw.Animator", {
- uses: ["Ext.draw.Draw"],
- singleton: true,
- frameCallbacks: {},
- frameCallbackId: 0,
- scheduled: 0,
- frameStartTimeOffset: Ext.now(),
- animations: [],
- running: false,
- animationTime: function() {
- return Ext.AnimationQueue.frameStartTime - this.frameStartTimeOffset
- },
- add: function(b) {
- var a = this;
- if (!a.contains(b)) {
- a.animations.push(b);
- a.ignite();
- if ("fireEvent" in b) {
- b.fireEvent("animationstart", b)
- }
- }
- },
- remove: function(d) {
- var c = this,
- e = c.animations,
- b = 0,
- a = e.length;
- for (; b < a; ++b) {
- if (e[b] === d) {
- e.splice(b, 1);
- if ("fireEvent" in d) {
- d.fireEvent("animationend", d)
- }
- return
- }
- }
- },
- contains: function(a) {
- return Ext.Array.indexOf(this.animations, a) > -1
- },
- empty: function() {
- return this.animations.length === 0
- },
- step: function(d) {
- var c = this,
- f = c.animations,
- e, a = 0,
- b = f.length;
- for (; a < b; a++) {
- e = f[a];
- e.step(d);
- if (!e.animating) {
- f.splice(a, 1);
- a--;
- b--;
- if (e.fireEvent) {
- e.fireEvent("animationend", e)
- }
- }
- }
- },
- schedule: function(c, a) {
- a = a || this;
- var b = "frameCallback" + (this.frameCallbackId++);
- if (Ext.isString(c)) {
- c = a[c]
- }
- Ext.draw.Animator.frameCallbacks[b] = {
- fn: c,
- scope: a,
- once: true
- };
- this.scheduled++;
- Ext.draw.Animator.ignite();
- return b
- },
- scheduleIf: function(e, b) {
- b = b || this;
- var c = Ext.draw.Animator.frameCallbacks,
- a, d;
- if (Ext.isString(e)) {
- e = b[e]
- }
- for (d in c) {
- a = c[d];
- if (a.once && a.fn === e && a.scope === b) {
- return null
- }
- }
- return this.schedule(e, b)
- },
- cancel: function(a) {
- if (Ext.draw.Animator.frameCallbacks[a] && Ext.draw.Animator.frameCallbacks[a].once) {
- this.scheduled--;
- delete Ext.draw.Animator.frameCallbacks[a]
- }
- },
- addFrameCallback: function(c, a) {
- a = a || this;
- if (Ext.isString(c)) {
- c = a[c]
- }
- var b = "frameCallback" + (this.frameCallbackId++);
- Ext.draw.Animator.frameCallbacks[b] = {
- fn: c,
- scope: a
- };
- return b
- },
- removeFrameCallback: function(a) {
- delete Ext.draw.Animator.frameCallbacks[a]
- },
- fireFrameCallbacks: function() {
- var c = this.frameCallbacks,
- d, b, a;
- for (d in c) {
- a = c[d];
- b = a.fn;
- if (Ext.isString(b)) {
- b = a.scope[b]
- }
- b.call(a.scope);
- if (c[d] && a.once) {
- this.scheduled--;
- delete c[d]
- }
- }
- },
- handleFrame: function() {
- this.step(this.animationTime());
- this.fireFrameCallbacks();
- if (!this.scheduled && this.empty()) {
- Ext.AnimationQueue.stop(this.handleFrame, this);
- this.running = false;
- Ext.draw.Draw.endUpdateIOS()
- }
- },
- ignite: function() {
- if (!this.running) {
- this.running = true;
- Ext.AnimationQueue.start(this.handleFrame, this);
- Ext.draw.Draw.beginUpdateIOS()
- }
- }
-});
-Ext.define("Ext.draw.modifier.Animation", {
- requires: ["Ext.draw.TimingFunctions", "Ext.draw.Animator"],
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.animation",
- config: {
- easing: Ext.identityFn,
- duration: 0,
- customEasings: {},
- customDurations: {},
- customDuration: null
- },
- constructor: function(a) {
- var b = this;
- b.anyAnimation = b.anySpecialAnimations = false;
- b.animating = 0;
- b.animatingPool = [];
- b.callParent([a])
- },
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("timers")) {
- a.animating = false;
- a.timers = {};
- a.animationOriginal = Ext.Object.chain(a);
- a.animationOriginal.prototype = a
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.animationOriginal)
- }
- },
- updateSprite: function(a) {
- this.setConfig(a.config.fx)
- },
- updateDuration: function(a) {
- this.anyAnimation = a > 0
- },
- applyEasing: function(a) {
- if (typeof a === "string") {
- a = Ext.draw.TimingFunctions.easingMap[a]
- }
- return a
- },
- applyCustomEasings: function(a, e) {
- e = e || {};
- var g, d, b, h, c, f;
- for (d in a) {
- g = true;
- h = a[d];
- b = d.split(",");
- if (typeof h === "string") {
- h = Ext.draw.TimingFunctions.easingMap[h]
- }
- for (c = 0, f = b.length; c < f; c++) {
- e[b[c]] = h
- }
- }
- if (g) {
- this.anySpecialAnimations = g
- }
- return e
- },
- setEasingOn: function(a, e) {
- a = Ext.Array.from(a).slice();
- var c = {},
- d = a.length,
- b = 0;
- for (; b < d; b++) {
- c[a[b]] = e
- }
- this.setCustomEasings(c)
- },
- clearEasingOn: function(a) {
- a = Ext.Array.from(a, true);
- var b = 0,
- c = a.length;
- for (; b < c; b++) {
- delete this._customEasings[a[b]]
- }
- },
- applyCustomDurations: function(g, h) {
- h = h || {};
- var e, c, f, a, b, d;
- for (c in g) {
- e = true;
- f = g[c];
- a = c.split(",");
- for (b = 0, d = a.length; b < d; b++) {
- h[a[b]] = f
- }
- }
- if (e) {
- this.anySpecialAnimations = e
- }
- return h
- },
- applyCustomDuration: function(a, b) {
- if (a) {
- this.getCustomDurations();
- this.setCustomDurations(a)
- }
- },
- setDurationOn: function(b, e) {
- b = Ext.Array.from(b).slice();
- var a = {},
- c = 0,
- d = b.length;
- for (; c < d; c++) {
- a[b[c]] = e
- }
- this.setCustomDurations(a)
- },
- clearDurationOn: function(a) {
- a = Ext.Array.from(a, true);
- var b = 0,
- c = a.length;
- for (; b < c; b++) {
- delete this._customDurations[a[b]]
- }
- },
- setAnimating: function(a, b) {
- var e = this,
- d = e.animatingPool;
- if (a.animating !== b) {
- a.animating = b;
- if (b) {
- d.push(a);
- if (e.animating === 0) {
- Ext.draw.Animator.add(e)
- }
- e.animating++
- } else {
- for (var c = d.length; c--;) {
- if (d[c] === a) {
- d.splice(c, 1)
- }
- }
- e.animating = d.length
- }
- }
- },
- setAttrs: function(r, t) {
- var s = this,
- m = r.timers,
- h = s._sprite.self.def._animationProcessors,
- f = s._easing,
- e = s._duration,
- j = s._customDurations,
- i = s._customEasings,
- g = s.anySpecialAnimations,
- n = s.anyAnimation || g,
- o = r.animationOriginal,
- d = false,
- k, u, l, p, c, q, a;
- if (!n) {
- for (u in t) {
- if (r[u] === t[u]) {
- delete t[u]
- } else {
- r[u] = t[u]
- }
- delete o[u];
- delete m[u]
- }
- return t
- } else {
- for (u in t) {
- l = t[u];
- p = r[u];
- if (l !== p && p !== undefined && p !== null && (c = h[u])) {
- q = f;
- a = e;
- if (g) {
- if (u in i) {
- q = i[u]
- }
- if (u in j) {
- a = j[u]
- }
- }
- if (p && p.isGradient || l && l.isGradient) {
- a = 0
- }
- if (a) {
- if (!m[u]) {
- m[u] = {}
- }
- k = m[u];
- k.start = 0;
- k.easing = q;
- k.duration = a;
- k.compute = c.compute;
- k.serve = c.serve || Ext.identityFn;
- k.remove = t.removeFromInstance && t.removeFromInstance[u];
- if (c.parseInitial) {
- var b = c.parseInitial(p, l);
- k.source = b[0];
- k.target = b[1]
- } else {
- if (c.parse) {
- k.source = c.parse(p);
- k.target = c.parse(l)
- } else {
- k.source = p;
- k.target = l
- }
- }
- o[u] = l;
- delete t[u];
- d = true;
- continue
- } else {
- delete o[u]
- }
- } else {
- delete o[u]
- }
- delete m[u]
- }
- }
- if (d && !r.animating) {
- s.setAnimating(r, true)
- }
- return t
- },
- updateAttributes: function(g) {
- if (!g.animating) {
- return {}
- }
- var h = {},
- e = false,
- d = g.timers,
- f = g.animationOriginal,
- c = Ext.draw.Animator.animationTime(),
- a, b, i;
- if (g.lastUpdate === c) {
- return null
- }
- for (a in d) {
- b = d[a];
- if (!b.start) {
- b.start = c;
- i = 0
- } else {
- i = (c - b.start) / b.duration
- }
- if (i >= 1) {
- h[a] = f[a];
- delete f[a];
- if (d[a].remove) {
- h.removeFromInstance = h.removeFromInstance || {};
- h.removeFromInstance[a] = true
- }
- delete d[a]
- } else {
- h[a] = b.serve(b.compute(b.source, b.target, b.easing(i), g[a]));
- e = true
- }
- }
- g.lastUpdate = c;
- this.setAnimating(g, e);
- return h
- },
- pushDown: function(a, b) {
- b = this.callParent([a.animationOriginal, b]);
- return this.setAttrs(a, b)
- },
- popUp: function(a, b) {
- a = a.prototype;
- b = this.setAttrs(a, b);
- if (this._next) {
- return this._next.popUp(a, b)
- } else {
- return Ext.apply(a, b)
- }
- },
- step: function(g) {
- var f = this,
- c = f.animatingPool.slice(),
- e = c.length,
- b = 0,
- a, d;
- for (; b < e; b++) {
- a = c[b];
- d = f.updateAttributes(a);
- if (d && f._next) {
- f._next.popUp(a, d)
- }
- }
- },
- stop: function() {
- this.step();
- var d = this,
- b = d.animatingPool,
- a, c;
- for (a = 0, c = b.length; a < c; a++) {
- b[a].animating = false
- }
- d.animatingPool.length = 0;
- d.animating = 0;
- Ext.draw.Animator.remove(d)
- },
- destroy: function() {
- this.animatingPool.length = 0;
- this.animating = 0;
- this.callParent()
- }
-});
-Ext.define("Ext.draw.modifier.Highlight", {
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.highlight",
- config: {
- enabled: false,
- highlightStyle: null
- },
- preFx: true,
- applyHighlightStyle: function(b, a) {
- a = a || {};
- if (this.getSprite()) {
- Ext.apply(a, this.getSprite().self.def.normalize(b))
- } else {
- Ext.apply(a, b)
- }
- return a
- },
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("highlightOriginal")) {
- a.highlighted = false;
- a.highlightOriginal = Ext.Object.chain(a);
- a.highlightOriginal.prototype = a;
- a.highlightOriginal.removeFromInstance = {}
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.highlightOriginal)
- }
- },
- updateSprite: function(b, a) {
- if (b) {
- if (this.getHighlightStyle()) {
- this._highlightStyle = b.self.def.normalize(this.getHighlightStyle())
- }
- this.setHighlightStyle(b.config.highlight)
- }
- b.self.def.setConfig({
- defaults: {
- highlighted: false
- },
- processors: {
- highlighted: "bool"
- }
- });
- this.setSprite(b)
- },
- filterChanges: function(a, d) {
- var e = this,
- f = a.highlightOriginal,
- c = e.getHighlightStyle(),
- b;
- if (a.highlighted) {
- for (b in d) {
- if (c.hasOwnProperty(b)) {
- f[b] = d[b];
- delete d[b]
- }
- }
- }
- for (b in d) {
- if (b !== "highlighted" && f[b] === d[b]) {
- delete d[b]
- }
- }
- return d
- },
- pushDown: function(e, g) {
- var f = this.getHighlightStyle(),
- c = e.highlightOriginal,
- i = c.removeFromInstance,
- d, a, h, b;
- if (g.hasOwnProperty("highlighted")) {
- d = g.highlighted;
- delete g.highlighted;
- if (this._previous) {
- g = this._previous.pushDown(c, g)
- }
- g = this.filterChanges(e, g);
- if (d !== e.highlighted) {
- if (d) {
- for (a in f) {
- if (a in g) {
- c[a] = g[a]
- } else {
- h = e.template && e.template.ownAttr;
- if (h && !e.prototype.hasOwnProperty(a)) {
- i[a] = true;
- c[a] = h.animationOriginal[a]
- } else {
- b = c.timers[a];
- if (b && b.remove) {
- i[a] = true
- }
- c[a] = e[a]
- }
- }
- if (c[a] !== f[a]) {
- g[a] = f[a]
- }
- }
- } else {
- for (a in f) {
- if (!(a in g)) {
- g[a] = c[a]
- }
- delete c[a]
- }
- g.removeFromInstance = g.removeFromInstance || {};
- Ext.apply(g.removeFromInstance, i);
- c.removeFromInstance = {}
- }
- g.highlighted = d
- }
- } else {
- if (this._previous) {
- g = this._previous.pushDown(c, g)
- }
- g = this.filterChanges(e, g)
- }
- return g
- },
- popUp: function(a, b) {
- b = this.filterChanges(a, b);
- Ext.draw.modifier.Modifier.prototype.popUp.call(this, a, b)
- }
-});
-Ext.define("Ext.draw.sprite.Sprite", {
- alias: "sprite.sprite",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- requires: ["Ext.draw.Draw", "Ext.draw.gradient.Gradient", "Ext.draw.sprite.AttributeDefinition", "Ext.draw.modifier.Target", "Ext.draw.modifier.Animation", "Ext.draw.modifier.Highlight"],
- isSprite: true,
- statics: {
- defaultHitTestOptions: {
- fill: true,
- stroke: true
- }
- },
- inheritableStatics: {
- def: {
- processors: {
- strokeStyle: "color",
- fillStyle: "color",
- strokeOpacity: "limited01",
- fillOpacity: "limited01",
- lineWidth: "number",
- lineCap: "enums(butt,round,square)",
- lineJoin: "enums(round,bevel,miter)",
- lineDash: "data",
- lineDashOffset: "number",
- miterLimit: "number",
- shadowColor: "color",
- shadowOffsetX: "number",
- shadowOffsetY: "number",
- shadowBlur: "number",
- globalAlpha: "limited01",
- globalCompositeOperation: "enums(source-over,destination-over,source-in,destination-in,source-out,destination-out,source-atop,destination-atop,lighter,xor,copy)",
- hidden: "bool",
- transformFillStroke: "bool",
- zIndex: "number",
- translationX: "number",
- translationY: "number",
- rotationRads: "number",
- rotationCenterX: "number",
- rotationCenterY: "number",
- scalingX: "number",
- scalingY: "number",
- scalingCenterX: "number",
- scalingCenterY: "number",
- constrainGradients: "bool"
- },
- aliases: {
- stroke: "strokeStyle",
- fill: "fillStyle",
- color: "fillStyle",
- "stroke-width": "lineWidth",
- "stroke-linecap": "lineCap",
- "stroke-linejoin": "lineJoin",
- "stroke-miterlimit": "miterLimit",
- "text-anchor": "textAlign",
- opacity: "globalAlpha",
- translateX: "translationX",
- translateY: "translationY",
- rotateRads: "rotationRads",
- rotateCenterX: "rotationCenterX",
- rotateCenterY: "rotationCenterY",
- scaleX: "scalingX",
- scaleY: "scalingY",
- scaleCenterX: "scalingCenterX",
- scaleCenterY: "scalingCenterY"
- },
- defaults: {
- hidden: false,
- zIndex: 0,
- strokeStyle: "none",
- fillStyle: "none",
- lineWidth: 1,
- lineDash: [],
- lineDashOffset: 0,
- lineCap: "butt",
- lineJoin: "miter",
- miterLimit: 10,
- shadowColor: "none",
- shadowOffsetX: 0,
- shadowOffsetY: 0,
- shadowBlur: 0,
- globalAlpha: 1,
- strokeOpacity: 1,
- fillOpacity: 1,
- transformFillStroke: false,
- translationX: 0,
- translationY: 0,
- rotationRads: 0,
- rotationCenterX: null,
- rotationCenterY: null,
- scalingX: 1,
- scalingY: 1,
- scalingCenterX: null,
- scalingCenterY: null,
- constrainGradients: false
- },
- triggers: {
- zIndex: "zIndex",
- globalAlpha: "canvas",
- globalCompositeOperation: "canvas",
- transformFillStroke: "canvas",
- strokeStyle: "canvas",
- fillStyle: "canvas",
- strokeOpacity: "canvas",
- fillOpacity: "canvas",
- lineWidth: "canvas",
- lineCap: "canvas",
- lineJoin: "canvas",
- lineDash: "canvas",
- lineDashOffset: "canvas",
- miterLimit: "canvas",
- shadowColor: "canvas",
- shadowOffsetX: "canvas",
- shadowOffsetY: "canvas",
- shadowBlur: "canvas",
- translationX: "transform",
- translationY: "transform",
- rotationRads: "transform",
- rotationCenterX: "transform",
- rotationCenterY: "transform",
- scalingX: "transform",
- scalingY: "transform",
- scalingCenterX: "transform",
- scalingCenterY: "transform",
- constrainGradients: "canvas"
- },
- updaters: {
- bbox: "bboxUpdater",
- zIndex: function(a) {
- a.dirtyZIndex = true
- },
- transform: function(a) {
- a.dirtyTransform = true;
- a.bbox.transform.dirty = true
- }
- }
- }
- },
- config: {
- parent: null,
- surface: null
- },
- onClassExtended: function(d, c) {
- var b = d.superclass.self.def.initialConfig,
- e = c.inheritableStatics && c.inheritableStatics.def,
- a;
- if (e) {
- a = Ext.Object.merge({}, b, e);
- d.def = new Ext.draw.sprite.AttributeDefinition(a);
- delete c.inheritableStatics.def
- } else {
- d.def = new Ext.draw.sprite.AttributeDefinition(b)
- }
- d.def.spriteClass = d
- },
- constructor: function(b) {
- var d = this,
- c = d.self.def,
- e = c.getDefaults(),
- a;
- b = Ext.isObject(b) ? b : {};
- d.id = b.id || Ext.id(null, "ext-sprite-");
- d.attr = {};
- d.mixins.observable.constructor.apply(d, arguments);
- a = Ext.Array.from(b.modifiers, true);
- d.prepareModifiers(a);
- d.initializeAttributes();
- d.setAttributes(e, true);
- d.setAttributes(b)
- },
- getDirty: function() {
- return this.attr.dirty
- },
- setDirty: function(b) {
- this.attr.dirty = b;
- if (b) {
- var a = this.getParent();
- if (a) {
- a.setDirty(true)
- }
- }
- },
- addModifier: function(a, b) {
- var c = this;
- if (!(a instanceof Ext.draw.modifier.Modifier)) {
- a = Ext.factory(a, null, null, "modifier")
- }
- a.setSprite(c);
- if (a.preFx || a.config && a.config.preFx) {
- if (c.fx.getPrevious()) {
- c.fx.getPrevious().setNext(a)
- }
- a.setNext(c.fx)
- } else {
- c.topModifier.getPrevious().setNext(a);
- a.setNext(c.topModifier)
- }
- if (b) {
- c.initializeAttributes()
- }
- return a
- },
- prepareModifiers: function(d) {
- var c = this,
- a, b;
- c.topModifier = new Ext.draw.modifier.Target({
- sprite: c
- });
- c.fx = new Ext.draw.modifier.Animation({
- sprite: c
- });
- c.fx.setNext(c.topModifier);
- for (a = 0, b = d.length; a < b; a++) {
- c.addModifier(d[a], false)
- }
- },
- getAnimation: function() {
- return this.fx
- },
- setAnimation: function(a) {
- this.fx.setConfig(a)
- },
- initializeAttributes: function() {
- this.topModifier.prepareAttributes(this.attr)
- },
- callUpdaters: function(d) {
- var e = this,
- h = d.pendingUpdaters,
- i = e.self.def.getUpdaters(),
- c = false,
- a = false,
- b, g, f;
- e.callUpdaters = Ext.emptyFn;
- do {
- c = false;
- for (g in h) {
- c = true;
- b = h[g];
- delete h[g];
- f = i[g];
- if (typeof f === "string") {
- f = e[f]
- }
- if (f) {
- f.call(e, d, b)
- }
- }
- a = a || c
- } while (c);
- delete e.callUpdaters;
- if (a) {
- e.setDirty(true)
- }
- },
- scheduleUpdaters: function(a, e, c) {
- var f;
- if (c) {
- for (var b = 0, d = e.length; b < d; b++) {
- f = e[b];
- this.scheduleUpdater(a, f, c)
- }
- } else {
- for (f in e) {
- c = e[f];
- this.scheduleUpdater(a, f, c)
- }
- }
- },
- scheduleUpdater: function(a, c, b) {
- b = b || [];
- var d = a.pendingUpdaters;
- if (c in d) {
- if (b.length) {
- d[c] = Ext.Array.merge(d[c], b)
- }
- } else {
- d[c] = b
- }
- },
- setAttributes: function(d, g, c) {
- var a = this.attr,
- b, e, f;
- if (g) {
- if (c) {
- this.topModifier.pushDown(a, d)
- } else {
- f = {};
- for (b in d) {
- e = d[b];
- if (e !== a[b]) {
- f[b] = e
- }
- }
- this.topModifier.pushDown(a, f)
- }
- } else {
- this.topModifier.pushDown(a, this.self.def.normalize(d))
- }
- },
- setAttributesBypassingNormalization: function(b, a) {
- return this.setAttributes(b, true, a)
- },
- bboxUpdater: function(b) {
- var c = b.rotationRads !== 0,
- a = b.scalingX !== 1 || b.scalingY !== 1,
- d = b.rotationCenterX === null || b.rotationCenterY === null,
- e = b.scalingCenterX === null || b.scalingCenterY === null;
- b.bbox.plain.dirty = true;
- b.bbox.transform.dirty = true;
- if (c && d || a && e) {
- this.scheduleUpdater(b, "transform")
- }
- },
- getBBox: function(d) {
- var e = this,
- a = e.attr,
- f = a.bbox,
- c = f.plain,
- b = f.transform;
- if (c.dirty) {
- e.updatePlainBBox(c);
- c.dirty = false
- }
- if (!d) {
- e.applyTransformations();
- if (b.dirty) {
- e.updateTransformedBBox(b, c);
- b.dirty = false
- }
- return b
- }
- return c
- },
- updatePlainBBox: Ext.emptyFn,
- updateTransformedBBox: function(a, b) {
- this.attr.matrix.transformBBox(b, 0, a)
- },
- getBBoxCenter: function(a) {
- var b = this.getBBox(a);
- if (b) {
- return [b.x + b.width * 0.5, b.y + b.height * 0.5]
- } else {
- return [0, 0]
- }
- },
- hide: function() {
- this.attr.hidden = true;
- this.setDirty(true);
- return this
- },
- show: function() {
- this.attr.hidden = false;
- this.setDirty(true);
- return this
- },
- useAttributes: function(i, f) {
- this.applyTransformations();
- var d = this.attr,
- h = d.canvasAttributes,
- e = h.strokeStyle,
- g = h.fillStyle,
- b = h.lineDash,
- c = h.lineDashOffset,
- a;
- if (e) {
- if (e.isGradient) {
- i.strokeStyle = "black";
- i.strokeGradient = e
- } else {
- i.strokeGradient = false
- }
- }
- if (g) {
- if (g.isGradient) {
- i.fillStyle = "black";
- i.fillGradient = g
- } else {
- i.fillGradient = false
- }
- }
- if (b) {
- i.setLineDash(b)
- }
- if (Ext.isNumber(c + i.lineDashOffset)) {
- i.lineDashOffset = c
- }
- for (a in h) {
- if (h[a] !== undefined && h[a] !== i[a]) {
- i[a] = h[a]
- }
- }
- this.setGradientBBox(i, f)
- },
- setGradientBBox: function(b, c) {
- var a = this.attr;
- if (a.constrainGradients) {
- b.setGradientBBox({
- x: c[0],
- y: c[1],
- width: c[2],
- height: c[3]
- })
- } else {
- b.setGradientBBox(this.getBBox(a.transformFillStroke))
- }
- },
- applyTransformations: function(b) {
- if (!b && !this.attr.dirtyTransform) {
- return
- }
- var r = this,
- k = r.attr,
- p = r.getBBoxCenter(true),
- g = p[0],
- f = p[1],
- q = k.translationX,
- o = k.translationY,
- j = k.scalingX,
- i = k.scalingY === null ? k.scalingX : k.scalingY,
- m = k.scalingCenterX === null ? g : k.scalingCenterX,
- l = k.scalingCenterY === null ? f : k.scalingCenterY,
- s = k.rotationRads,
- e = k.rotationCenterX === null ? g : k.rotationCenterX,
- d = k.rotationCenterY === null ? f : k.rotationCenterY,
- c = Math.cos(s),
- a = Math.sin(s),
- n, h;
- if (j === 1 && i === 1) {
- m = 0;
- l = 0
- }
- if (s === 0) {
- e = 0;
- d = 0
- }
- n = m * (1 - j) - e;
- h = l * (1 - i) - d;
- k.matrix.elements = [c * j, a * j, -a * i, c * i, c * n - a * h + e + q, a * n + c * h + d + o];
- k.matrix.inverse(k.inverseMatrix);
- k.dirtyTransform = false;
- k.bbox.transform.dirty = true
- },
- transform: function(b, c) {
- var a = this.attr,
- e = a.matrix,
- d;
- if (b && b.isMatrix) {
- d = b.elements
- } else {
- d = b
- }
- e.prepend.apply(e, d.slice());
- e.inverse(a.inverseMatrix);
- if (c) {
- this.updateTransformAttributes()
- }
- a.dirtyTransform = false;
- a.bbox.transform.dirty = true;
- this.setDirty(true);
- return this
- },
- updateTransformAttributes: function() {
- var a = this.attr,
- b = a.matrix.split();
- a.rotationRads = b.rotate;
- a.rotationCenterX = 0;
- a.rotationCenterY = 0;
- a.scalingX = b.scaleX;
- a.scalingY = b.scaleY;
- a.scalingCenterX = 0;
- a.scalingCenterY = 0;
- a.translationX = b.translateX;
- a.translationY = b.translateY
- },
- resetTransform: function(b) {
- var a = this.attr;
- a.matrix.reset();
- a.inverseMatrix.reset();
- if (!b) {
- this.updateTransformAttributes()
- }
- a.dirtyTransform = false;
- a.bbox.transform.dirty = true;
- this.setDirty(true);
- return this
- },
- setTransform: function(a, b) {
- this.resetTransform(true);
- this.transform.call(this, a, b);
- return this
- },
- preRender: Ext.emptyFn,
- render: Ext.emptyFn,
- hitTest: function(b, c) {
- if (this.isVisible()) {
- var a = b[0],
- f = b[1],
- e = this.getBBox(),
- d = e && a >= e.x && a <= (e.x + e.width) && f >= e.y && f <= (e.y + e.height);
- if (d) {
- return {
- sprite: this
- }
- }
- }
- return null
- },
- isVisible: function() {
- var e = this.attr,
- f = this.getParent(),
- g = f && (f.isSurface || f.isVisible()),
- d = g && !e.hidden && e.globalAlpha,
- b = Ext.draw.Color.NONE,
- a = Ext.draw.Color.RGBA_NONE,
- c = e.fillOpacity && e.fillStyle !== b && e.fillStyle !== a,
- i = e.strokeOpacity && e.strokeStyle !== b && e.strokeStyle !== a,
- h = d && (c || i);
- return !!h
- },
- repaint: function() {
- var a = this.getSurface();
- if (a) {
- a.renderFrame()
- }
- },
- remove: function() {
- var a = this.getSurface();
- if (a && a.isSurface) {
- return a.remove(this)
- }
- return null
- },
- destroy: function() {
- var b = this,
- a = b.topModifier,
- c;
- while (a) {
- c = a;
- a = a.getPrevious();
- c.destroy()
- }
- delete b.attr;
- b.remove();
- if (b.fireEvent("beforedestroy", b) !== false) {
- b.fireEvent("destroy", b)
- }
- b.callParent()
- }
-}, function() {
- this.def = new Ext.draw.sprite.AttributeDefinition(this.def);
- this.def.spriteClass = this
-});
-Ext.define("Ext.draw.Path", {
- requires: ["Ext.draw.Draw"],
- statics: {
- pathRe: /,?([achlmqrstvxz]),?/gi,
- pathRe2: /-/gi,
- pathSplitRe: /\s|,/g
- },
- svgString: "",
- constructor: function(a) {
- var b = this;
- b.commands = [];
- b.params = [];
- b.cursor = null;
- b.startX = 0;
- b.startY = 0;
- if (a) {
- b.fromSvgString(a)
- }
- },
- clear: function() {
- var a = this;
- a.params.length = 0;
- a.commands.length = 0;
- a.cursor = null;
- a.startX = 0;
- a.startY = 0;
- a.dirt()
- },
- dirt: function() {
- this.svgString = ""
- },
- moveTo: function(a, c) {
- var b = this;
- if (!b.cursor) {
- b.cursor = [a, c]
- }
- b.params.push(a, c);
- b.commands.push("M");
- b.startX = a;
- b.startY = c;
- b.cursor[0] = a;
- b.cursor[1] = c;
- b.dirt()
- },
- lineTo: function(a, c) {
- var b = this;
- if (!b.cursor) {
- b.cursor = [a, c];
- b.params.push(a, c);
- b.commands.push("M")
- } else {
- b.params.push(a, c);
- b.commands.push("L")
- }
- b.cursor[0] = a;
- b.cursor[1] = c;
- b.dirt()
- },
- bezierCurveTo: function(c, e, b, d, a, g) {
- var f = this;
- if (!f.cursor) {
- f.moveTo(c, e)
- }
- f.params.push(c, e, b, d, a, g);
- f.commands.push("C");
- f.cursor[0] = a;
- f.cursor[1] = g;
- f.dirt()
- },
- quadraticCurveTo: function(b, e, a, d) {
- var c = this;
- if (!c.cursor) {
- c.moveTo(b, e)
- }
- c.bezierCurveTo((2 * b + c.cursor[0]) / 3, (2 * e + c.cursor[1]) / 3, (2 * b + a) / 3, (2 * e + d) / 3, a, d)
- },
- closePath: function() {
- var a = this;
- if (a.cursor) {
- a.cursor = null;
- a.commands.push("Z");
- a.dirt()
- }
- },
- arcTo: function(A, f, z, d, j, i, v) {
- var E = this;
- if (i === undefined) {
- i = j
- }
- if (v === undefined) {
- v = 0
- }
- if (!E.cursor) {
- E.moveTo(A, f);
- return
- }
- if (j === 0 || i === 0) {
- E.lineTo(A, f);
- return
- }
- z -= A;
- d -= f;
- var B = E.cursor[0] - A,
- g = E.cursor[1] - f,
- C = z * g - d * B,
- b, a, l, r, k, q, x = Math.sqrt(B * B + g * g),
- u = Math.sqrt(z * z + d * d),
- t, e, c;
- if (C === 0) {
- E.lineTo(A, f);
- return
- }
- if (i !== j) {
- b = Math.cos(v);
- a = Math.sin(v);
- l = b / j;
- r = a / i;
- k = -a / j;
- q = b / i;
- var D = l * B + r * g;
- g = k * B + q * g;
- B = D;
- D = l * z + r * d;
- d = k * z + q * d;
- z = D
- } else {
- B /= j;
- g /= i;
- z /= j;
- d /= i
- }
- e = B * u + z * x;
- c = g * u + d * x;
- t = 1 / (Math.sin(Math.asin(Math.abs(C) / (x * u)) * 0.5) * Math.sqrt(e * e + c * c));
- e *= t;
- c *= t;
- var o = (e * B + c * g) / (B * B + g * g),
- m = (e * z + c * d) / (z * z + d * d);
- var n = B * o - e,
- p = g * o - c,
- h = z * m - e,
- y = d * m - c,
- w = Math.atan2(p, n),
- s = Math.atan2(y, h);
- if (C > 0) {
- if (s < w) {
- s += Math.PI * 2
- }
- } else {
- if (w < s) {
- w += Math.PI * 2
- }
- }
- if (i !== j) {
- e = b * e * j - a * c * i + A;
- c = a * c * i + b * c * i + f;
- E.lineTo(b * j * n - a * i * p + e, a * j * n + b * i * p + c);
- E.ellipse(e, c, j, i, v, w, s, C < 0)
- } else {
- e = e * j + A;
- c = c * i + f;
- E.lineTo(j * n + e, i * p + c);
- E.ellipse(e, c, j, i, v, w, s, C < 0)
- }
- },
- ellipse: function(h, f, c, a, q, n, d, e) {
- var o = this,
- g = o.params,
- b = g.length,
- m, l, k;
- if (d - n >= Math.PI * 2) {
- o.ellipse(h, f, c, a, q, n, n + Math.PI, e);
- o.ellipse(h, f, c, a, q, n + Math.PI, d, e);
- return
- }
- if (!e) {
- if (d < n) {
- d += Math.PI * 2
- }
- m = o.approximateArc(g, h, f, c, a, q, n, d)
- } else {
- if (n < d) {
- n += Math.PI * 2
- }
- m = o.approximateArc(g, h, f, c, a, q, d, n);
- for (l = b, k = g.length - 2; l < k; l += 2, k -= 2) {
- var p = g[l];
- g[l] = g[k];
- g[k] = p;
- p = g[l + 1];
- g[l + 1] = g[k + 1];
- g[k + 1] = p
- }
- }
- if (!o.cursor) {
- o.cursor = [g[g.length - 2], g[g.length - 1]];
- o.commands.push("M")
- } else {
- o.cursor[0] = g[g.length - 2];
- o.cursor[1] = g[g.length - 1];
- o.commands.push("L")
- }
- for (l = 2; l < m; l += 6) {
- o.commands.push("C")
- }
- o.dirt()
- },
- arc: function(b, f, a, d, c, e) {
- this.ellipse(b, f, a, a, 0, d, c, e)
- },
- rect: function(b, e, c, a) {
- if (c == 0 || a == 0) {
- return
- }
- var d = this;
- d.moveTo(b, e);
- d.lineTo(b + c, e);
- d.lineTo(b + c, e + a);
- d.lineTo(b, e + a);
- d.closePath()
- },
- approximateArc: function(s, i, f, o, n, d, x, v) {
- var e = Math.cos(d),
- z = Math.sin(d),
- k = Math.cos(x),
- l = Math.sin(x),
- q = e * k * o - z * l * n,
- y = -e * l * o - z * k * n,
- p = z * k * o + e * l * n,
- w = -z * l * o + e * k * n,
- m = Math.PI / 2,
- r = 2,
- j = q,
- u = y,
- h = p,
- t = w,
- b = 0.547443256150549,
- C, g, A, a, B, c;
- v -= x;
- if (v < 0) {
- v += Math.PI * 2
- }
- s.push(q + i, p + f);
- while (v >= m) {
- s.push(j + u * b + i, h + t * b + f, j * b + u + i, h * b + t + f, u + i, t + f);
- r += 6;
- v -= m;
- C = j;
- j = u;
- u = -C;
- C = h;
- h = t;
- t = -C
- }
- if (v) {
- g = (0.3294738052815987 + 0.012120855841304373 * v) * v;
- A = Math.cos(v);
- a = Math.sin(v);
- B = A + g * a;
- c = a - g * A;
- s.push(j + u * g + i, h + t * g + f, j * B + u * c + i, h * B + t * c + f, j * A + u * a + i, h * A + t * a + f);
- r += 6
- }
- return r
- },
- arcSvg: function(j, h, r, m, w, t, c) {
- if (j < 0) {
- j = -j
- }
- if (h < 0) {
- h = -h
- }
- var x = this,
- u = x.cursor[0],
- f = x.cursor[1],
- a = (u - t) / 2,
- y = (f - c) / 2,
- d = Math.cos(r),
- s = Math.sin(r),
- o = a * d + y * s,
- v = -a * s + y * d,
- i = o / j,
- g = v / h,
- p = i * i + g * g,
- e = (u + t) * 0.5,
- b = (f + c) * 0.5,
- l = 0,
- k = 0;
- if (p >= 1) {
- p = Math.sqrt(p);
- j *= p;
- h *= p
- } else {
- p = Math.sqrt(1 / p - 1);
- if (m === w) {
- p = -p
- }
- l = p * j * g;
- k = -p * h * i;
- e += d * l - s * k;
- b += s * l + d * k
- }
- var q = Math.atan2((v - k) / h, (o - l) / j),
- n = Math.atan2((-v - k) / h, (-o - l) / j) - q;
- if (w) {
- if (n <= 0) {
- n += Math.PI * 2
- }
- } else {
- if (n >= 0) {
- n -= Math.PI * 2
- }
- }
- x.ellipse(e, b, j, h, r, q, q + n, 1 - w)
- },
- fromSvgString: function(e) {
- if (!e) {
- return
- }
- var m = this,
- h, l = {
- a: 7,
- c: 6,
- h: 1,
- l: 2,
- m: 2,
- q: 4,
- s: 4,
- t: 2,
- v: 1,
- z: 0,
- A: 7,
- C: 6,
- H: 1,
- L: 2,
- M: 2,
- Q: 4,
- S: 4,
- T: 2,
- V: 1,
- Z: 0
- },
- k = "",
- g, f, c = 0,
- b = 0,
- d = false,
- j, n, a;
- if (Ext.isString(e)) {
- h = e.replace(Ext.draw.Path.pathRe, " $1 ").replace(Ext.draw.Path.pathRe2, " -").split(Ext.draw.Path.pathSplitRe)
- } else {
- if (Ext.isArray(e)) {
- h = e.join(",").split(Ext.draw.Path.pathSplitRe)
- }
- }
- for (j = 0, n = 0; j < h.length; j++) {
- if (h[j] !== "") {
- h[n++] = h[j]
- }
- }
- h.length = n;
- m.clear();
- for (j = 0; j < h.length;) {
- k = d;
- d = h[j];
- a = (d.toUpperCase() !== d);
- j++;
- switch (d) {
- case "M":
- m.moveTo(c = +h[j], b = +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2
- }
- break;
- case "L":
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2
- }
- break;
- case "A":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.arcSvg(+h[j], +h[j + 1], +h[j + 2] * Math.PI / 180, +h[j + 3], +h[j + 4], c = +h[j + 5], b = +h[j + 6]);
- j += 7
- }
- break;
- case "C":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(+h[j], +h[j + 1], g = +h[j + 2], f = +h[j + 3], c = +h[j + 4], b = +h[j + 5]);
- j += 6
- }
- break;
- case "Z":
- m.closePath();
- break;
- case "m":
- m.moveTo(c += +h[j], b += +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2
- }
- break;
- case "l":
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2
- }
- break;
- case "a":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.arcSvg(+h[j], +h[j + 1], +h[j + 2] * Math.PI / 180, +h[j + 3], +h[j + 4], c += +h[j + 5], b += +h[j + 6]);
- j += 7
- }
- break;
- case "c":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + (+h[j]), b + (+h[j + 1]), g = c + (+h[j + 2]), f = b + (+h[j + 3]), c += +h[j + 4], b += +h[j + 5]);
- j += 6
- }
- break;
- case "z":
- m.closePath();
- break;
- case "s":
- if (!(k === "c" || k === "C" || k === "s" || k === "S")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + c - g, b + b - f, g = c + (+h[j]), f = b + (+h[j + 1]), c += +h[j + 2], b += +h[j + 3]);
- j += 4
- }
- break;
- case "S":
- if (!(k === "c" || k === "C" || k === "s" || k === "S")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + c - g, b + b - f, g = +h[j], f = +h[j + 1], c = (+h[j + 2]), b = (+h[j + 3]));
- j += 4
- }
- break;
- case "q":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + (+h[j]), f = b + (+h[j + 1]), c += +h[j + 2], b += +h[j + 3]);
- j += 4
- }
- break;
- case "Q":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = +h[j], f = +h[j + 1], c = +h[j + 2], b = +h[j + 3]);
- j += 4
- }
- break;
- case "t":
- if (!(k === "q" || k === "Q" || k === "t" || k === "T")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + c - g, f = b + b - f, c += +h[j + 1], b += +h[j + 2]);
- j += 2
- }
- break;
- case "T":
- if (!(k === "q" || k === "Q" || k === "t" || k === "T")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + c - g, f = b + b - f, c = (+h[j + 1]), b = (+h[j + 2]));
- j += 2
- }
- break;
- case "h":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b);
- j++
- }
- break;
- case "H":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b);
- j++
- }
- break;
- case "v":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c, b += +h[j]);
- j++
- }
- break;
- case "V":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c, b = +h[j]);
- j++
- }
- break
- }
- }
- },
- clone: function() {
- var a = this,
- b = new Ext.draw.Path();
- b.params = a.params.slice(0);
- b.commands = a.commands.slice(0);
- b.cursor = a.cursor ? a.cursor.slice(0) : null;
- b.startX = a.startX;
- b.startY = a.startY;
- b.svgString = a.svgString;
- return b
- },
- transform: function(j) {
- if (j.isIdentity()) {
- return
- }
- var a = j.getXX(),
- f = j.getYX(),
- m = j.getDX(),
- l = j.getXY(),
- e = j.getYY(),
- k = j.getDY(),
- b = this.params,
- c = 0,
- d = b.length,
- h, g;
- for (; c < d; c += 2) {
- h = b[c];
- g = b[c + 1];
- b[c] = h * a + g * f + m;
- b[c + 1] = h * l + g * e + k
- }
- this.dirt()
- },
- getDimension: function(f) {
- if (!f) {
- f = {}
- }
- if (!this.commands || !this.commands.length) {
- f.x = 0;
- f.y = 0;
- f.width = 0;
- f.height = 0;
- return f
- }
- f.left = Infinity;
- f.top = Infinity;
- f.right = -Infinity;
- f.bottom = -Infinity;
- var d = 0,
- c = 0,
- b = this.commands,
- g = this.params,
- e = b.length,
- a, h;
- for (; d < e; d++) {
- switch (b[d]) {
- case "M":
- case "L":
- a = g[c];
- h = g[c + 1];
- f.left = Math.min(a, f.left);
- f.top = Math.min(h, f.top);
- f.right = Math.max(a, f.right);
- f.bottom = Math.max(h, f.bottom);
- c += 2;
- break;
- case "C":
- this.expandDimension(f, a, h, g[c], g[c + 1], g[c + 2], g[c + 3], a = g[c + 4], h = g[c + 5]);
- c += 6;
- break
- }
- }
- f.x = f.left;
- f.y = f.top;
- f.width = f.right - f.left;
- f.height = f.bottom - f.top;
- return f
- },
- getDimensionWithTransform: function(n, f) {
- if (!this.commands || !this.commands.length) {
- if (!f) {
- f = {}
- }
- f.x = 0;
- f.y = 0;
- f.width = 0;
- f.height = 0;
- return f
- }
- f.left = Infinity;
- f.top = Infinity;
- f.right = -Infinity;
- f.bottom = -Infinity;
- var a = n.getXX(),
- k = n.getYX(),
- q = n.getDX(),
- p = n.getXY(),
- h = n.getYY(),
- o = n.getDY(),
- e = 0,
- d = 0,
- b = this.commands,
- c = this.params,
- g = b.length,
- m, l;
- for (; e < g; e++) {
- switch (b[e]) {
- case "M":
- case "L":
- m = c[d] * a + c[d + 1] * k + q;
- l = c[d] * p + c[d + 1] * h + o;
- f.left = Math.min(m, f.left);
- f.top = Math.min(l, f.top);
- f.right = Math.max(m, f.right);
- f.bottom = Math.max(l, f.bottom);
- d += 2;
- break;
- case "C":
- this.expandDimension(f, m, l, c[d] * a + c[d + 1] * k + q, c[d] * p + c[d + 1] * h + o, c[d + 2] * a + c[d + 3] * k + q, c[d + 2] * p + c[d + 3] * h + o, m = c[d + 4] * a + c[d + 5] * k + q, l = c[d + 4] * p + c[d + 5] * h + o);
- d += 6;
- break
- }
- }
- if (!f) {
- f = {}
- }
- f.x = f.left;
- f.y = f.top;
- f.width = f.right - f.left;
- f.height = f.bottom - f.top;
- return f
- },
- expandDimension: function(i, d, p, k, g, j, e, c, o) {
- var m = this,
- f = i.left,
- a = i.right,
- q = i.top,
- n = i.bottom,
- h = m.dim || (m.dim = []);
- m.curveDimension(d, k, j, c, h);
- f = Math.min(f, h[0]);
- a = Math.max(a, h[1]);
- m.curveDimension(p, g, e, o, h);
- q = Math.min(q, h[0]);
- n = Math.max(n, h[1]);
- i.left = f;
- i.right = a;
- i.top = q;
- i.bottom = n
- },
- curveDimension: function(p, n, k, j, h) {
- var i = 3 * (-p + 3 * (n - k) + j),
- g = 6 * (p - 2 * n + k),
- f = -3 * (p - n),
- o, m, e = Math.min(p, j),
- l = Math.max(p, j),
- q;
- if (i === 0) {
- if (g === 0) {
- h[0] = e;
- h[1] = l;
- return
- } else {
- o = -f / g;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- }
- } else {
- q = g * g - 4 * i * f;
- if (q >= 0) {
- q = Math.sqrt(q);
- o = (q - g) / 2 / i;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- if (q > 0) {
- o -= q / i;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- }
- }
- }
- h[0] = e;
- h[1] = l
- },
- interpolate: function(f, e, j, i, g) {
- if (g === 0) {
- return f
- }
- if (g === 1) {
- return i
- }
- var h = (1 - g) / g;
- return g * g * g * (i + h * (3 * j + h * (3 * e + h * f)))
- },
- fromStripes: function(g) {
- var e = this,
- c = 0,
- d = g.length,
- b, a, f;
- e.clear();
- for (; c < d; c++) {
- f = g[c];
- e.params.push.apply(e.params, f);
- e.commands.push("M");
- for (b = 2, a = f.length; b < a; b += 6) {
- e.commands.push("C")
- }
- }
- if (!e.cursor) {
- e.cursor = []
- }
- e.cursor[0] = e.params[e.params.length - 2];
- e.cursor[1] = e.params[e.params.length - 1];
- e.dirt()
- },
- toStripes: function(k) {
- var o = k || [],
- p, n, m, b, a, h, g, f, e, c = this.commands,
- d = this.params,
- l = c.length;
- for (f = 0, e = 0; f < l; f++) {
- switch (c[f]) {
- case "M":
- p = [h = b = d[e++], g = a = d[e++]];
- o.push(p);
- break;
- case "L":
- n = d[e++];
- m = d[e++];
- p.push((b + b + n) / 3, (a + a + m) / 3, (b + n + n) / 3, (a + m + m) / 3, b = n, a = m);
- break;
- case "C":
- p.push(d[e++], d[e++], d[e++], d[e++], b = d[e++], a = d[e++]);
- break;
- case "Z":
- n = h;
- m = g;
- p.push((b + b + n) / 3, (a + a + m) / 3, (b + n + n) / 3, (a + m + m) / 3, b = n, a = m);
- break
- }
- }
- return o
- },
- updateSvgString: function() {
- var b = [],
- a = this.commands,
- f = this.params,
- e = a.length,
- d = 0,
- c = 0;
- for (; d < e; d++) {
- switch (a[d]) {
- case "M":
- b.push("M" + f[c] + "," + f[c + 1]);
- c += 2;
- break;
- case "L":
- b.push("L" + f[c] + "," + f[c + 1]);
- c += 2;
- break;
- case "C":
- b.push("C" + f[c] + "," + f[c + 1] + " " + f[c + 2] + "," + f[c + 3] + " " + f[c + 4] + "," + f[c + 5]);
- c += 6;
- break;
- case "Z":
- b.push("Z");
- break
- }
- }
- this.svgString = b.join("")
- },
- toString: function() {
- if (!this.svgString) {
- this.updateSvgString()
- }
- return this.svgString
- }
-});
-Ext.define("Ext.draw.overrides.Path", {
- override: "Ext.draw.Path",
- rayOrigin: {
- x: -10000,
- y: -10000
- },
- isPointInPath: function(o, n) {
- var m = this,
- c = m.commands,
- q = Ext.draw.PathUtil,
- p = m.rayOrigin,
- f = m.params,
- l = c.length,
- e = null,
- d = null,
- b = 0,
- a = 0,
- k = 0,
- h, g;
- for (h = 0, g = 0; h < l; h++) {
- switch (c[h]) {
- case "M":
- if (e !== null) {
- if (q.linesIntersection(e, d, b, a, p.x, p.y, o, n)) {
- k += 1
- }
- }
- e = b = f[g];
- d = a = f[g + 1];
- g += 2;
- break;
- case "L":
- if (q.linesIntersection(b, a, f[g], f[g + 1], p.x, p.y, o, n)) {
- k += 1
- }
- b = f[g];
- a = f[g + 1];
- g += 2;
- break;
- case "C":
- k += q.cubicLineIntersections(b, f[g], f[g + 2], f[g + 4], a, f[g + 1], f[g + 3], f[g + 5], p.x, p.y, o, n).length;
- b = f[g + 4];
- a = f[g + 5];
- g += 6;
- break;
- case "Z":
- if (e !== null) {
- if (q.linesIntersection(e, d, b, a, p.x, p.y, o, n)) {
- k += 1
- }
- }
- break
- }
- }
- return k % 2 === 1
- },
- isPointOnPath: function(n, m) {
- var l = this,
- c = l.commands,
- o = Ext.draw.PathUtil,
- f = l.params,
- k = c.length,
- e = null,
- d = null,
- b = 0,
- a = 0,
- h, g;
- for (h = 0, g = 0; h < k; h++) {
- switch (c[h]) {
- case "M":
- if (e !== null) {
- if (o.pointOnLine(e, d, b, a, n, m)) {
- return true
- }
- }
- e = b = f[g];
- d = a = f[g + 1];
- g += 2;
- break;
- case "L":
- if (o.pointOnLine(b, a, f[g], f[g + 1], n, m)) {
- return true
- }
- b = f[g];
- a = f[g + 1];
- g += 2;
- break;
- case "C":
- if (o.pointOnCubic(b, f[g], f[g + 2], f[g + 4], a, f[g + 1], f[g + 3], f[g + 5], n, m)) {
- return true
- }
- b = f[g + 4];
- a = f[g + 5];
- g += 6;
- break;
- case "Z":
- if (e !== null) {
- if (o.pointOnLine(e, d, b, a, n, m)) {
- return true
- }
- }
- break
- }
- }
- return false
- },
- getSegmentIntersections: function(t, d, s, c, r, b, o, a) {
- var w = this,
- g = arguments.length,
- v = Ext.draw.PathUtil,
- f = w.commands,
- u = w.params,
- k = f.length,
- m = null,
- l = null,
- h = 0,
- e = 0,
- x = [],
- q, n, p;
- for (q = 0, n = 0; q < k; q++) {
- switch (f[q]) {
- case "M":
- if (m !== null) {
- switch (g) {
- case 4:
- p = v.linesIntersection(m, l, h, e, t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, m, l, h, e);
- x.push.apply(x, p);
- break
- }
- }
- m = h = u[n];
- l = e = u[n + 1];
- n += 2;
- break;
- case "L":
- switch (g) {
- case 4:
- p = v.linesIntersection(h, e, u[n], u[n + 1], t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, h, e, u[n], u[n + 1]);
- x.push.apply(x, p);
- break
- }
- h = u[n];
- e = u[n + 1];
- n += 2;
- break;
- case "C":
- switch (g) {
- case 4:
- p = v.cubicLineIntersections(h, u[n], u[n + 2], u[n + 4], e, u[n + 1], u[n + 3], u[n + 5], t, d, s, c);
- x.push.apply(x, p);
- break;
- case 8:
- p = v.cubicsIntersections(h, u[n], u[n + 2], u[n + 4], e, u[n + 1], u[n + 3], u[n + 5], t, s, r, o, d, c, b, a);
- x.push.apply(x, p);
- break
- }
- h = u[n + 4];
- e = u[n + 5];
- n += 6;
- break;
- case "Z":
- if (m !== null) {
- switch (g) {
- case 4:
- p = v.linesIntersection(m, l, h, e, t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, m, l, h, e);
- x.push.apply(x, p);
- break
- }
- }
- break
- }
- }
- return x
- },
- getIntersections: function(o) {
- var m = this,
- c = m.commands,
- g = m.params,
- l = c.length,
- f = null,
- e = null,
- b = 0,
- a = 0,
- d = [],
- k, h, n;
- for (k = 0, h = 0; k < l; k++) {
- switch (c[k]) {
- case "M":
- if (f !== null) {
- n = o.getSegmentIntersections.call(o, f, e, b, a);
- d.push.apply(d, n)
- }
- f = b = g[h];
- e = a = g[h + 1];
- h += 2;
- break;
- case "L":
- n = o.getSegmentIntersections.call(o, b, a, g[h], g[h + 1]);
- d.push.apply(d, n);
- b = g[h];
- a = g[h + 1];
- h += 2;
- break;
- case "C":
- n = o.getSegmentIntersections.call(o, b, a, g[h], g[h + 1], g[h + 2], g[h + 3], g[h + 4], g[h + 5]);
- d.push.apply(d, n);
- b = g[h + 4];
- a = g[h + 5];
- h += 6;
- break;
- case "Z":
- if (f !== null) {
- n = o.getSegmentIntersections.call(o, f, e, b, a);
- d.push.apply(d, n)
- }
- break
- }
- }
- return d
- }
-});
-Ext.define("Ext.draw.sprite.Path", {
- extend: "Ext.draw.sprite.Sprite",
- requires: ["Ext.draw.Draw", "Ext.draw.Path"],
- alias: ["sprite.path", "Ext.draw.Sprite"],
- type: "path",
- isPath: true,
- inheritableStatics: {
- def: {
- processors: {
- path: function(b, a) {
- if (!(b instanceof Ext.draw.Path)) {
- b = new Ext.draw.Path(b)
- }
- return b
- }
- },
- aliases: {
- d: "path"
- },
- triggers: {
- path: "bbox"
- },
- updaters: {
- path: function(a) {
- var b = a.path;
- if (!b || b.bindAttr !== a) {
- b = new Ext.draw.Path();
- b.bindAttr = a;
- a.path = b
- }
- b.clear();
- this.updatePath(b, a);
- this.scheduleUpdater(a, "bbox", ["path"])
- }
- }
- }
- },
- updatePlainBBox: function(a) {
- if (this.attr.path) {
- this.attr.path.getDimension(a)
- }
- },
- updateTransformedBBox: function(a) {
- if (this.attr.path) {
- this.attr.path.getDimensionWithTransform(this.attr.matrix, a)
- }
- },
- render: function(b, c) {
- var d = this.attr.matrix,
- a = this.attr;
- if (!a.path || a.path.params.length === 0) {
- return
- }
- d.toContext(c);
- c.appendPath(a.path);
- c.fillStroke(a)
- },
- updatePath: function(b, a) {}
-});
-Ext.define("Ext.draw.overrides.sprite.Path", {
- override: "Ext.draw.sprite.Path",
- requires: ["Ext.draw.Color"],
- isPointInPath: function(c, g) {
- var b = this.attr;
- if (b.fillStyle === Ext.draw.Color.RGBA_NONE) {
- return this.isPointOnPath(c, g)
- }
- var e = b.path,
- d = b.matrix,
- f, a;
- if (!d.isIdentity()) {
- f = e.params.slice(0);
- e.transform(b.matrix)
- }
- a = e.isPointInPath(c, g);
- if (f) {
- e.params = f
- }
- return a
- },
- isPointOnPath: function(c, g) {
- var b = this.attr,
- e = b.path,
- d = b.matrix,
- f, a;
- if (!d.isIdentity()) {
- f = e.params.slice(0);
- e.transform(b.matrix)
- }
- a = e.isPointOnPath(c, g);
- if (f) {
- e.params = f
- }
- return a
- },
- hitTest: function(i, l) {
- var e = this,
- c = e.attr,
- k = c.path,
- g = c.matrix,
- h = i[0],
- f = i[1],
- d = e.callParent([i, l]),
- j = null,
- a, b;
- if (!d) {
- return j
- }
- l = l || Ext.draw.sprite.Sprite.defaultHitTestOptions;
- if (!g.isIdentity()) {
- a = k.params.slice(0);
- k.transform(c.matrix)
- }
- if (l.fill && l.stroke) {
- b = c.fillStyle !== Ext.draw.Color.NONE && c.fillStyle !== Ext.draw.Color.RGBA_NONE;
- if (b) {
- if (k.isPointInPath(h, f)) {
- j = {
- sprite: e
- }
- }
- } else {
- if (k.isPointInPath(h, f) || k.isPointOnPath(h, f)) {
- j = {
- sprite: e
- }
- }
- }
- } else {
- if (l.stroke && !l.fill) {
- if (k.isPointOnPath(h, f)) {
- j = {
- sprite: e
- }
- }
- } else {
- if (l.fill && !l.stroke) {
- if (k.isPointInPath(h, f)) {
- j = {
- sprite: e
- }
- }
- }
- }
- }
- if (a) {
- k.params = a
- }
- return j
- },
- getIntersections: function(j) {
- if (!(j.isSprite && j.isPath)) {
- return []
- }
- var e = this.attr,
- d = j.attr,
- i = e.path,
- h = d.path,
- g = e.matrix,
- a = d.matrix,
- c, f, b;
- if (!g.isIdentity()) {
- c = i.params.slice(0);
- i.transform(e.matrix)
- }
- if (!a.isIdentity()) {
- f = h.params.slice(0);
- h.transform(d.matrix)
- }
- b = i.getIntersections(h);
- if (c) {
- i.params = c
- }
- if (f) {
- h.params = f
- }
- return b
- }
-});
-Ext.define("Ext.draw.sprite.Circle", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.circle",
- type: "circle",
- inheritableStatics: {
- def: {
- processors: {
- cx: "number",
- cy: "number",
- r: "number"
- },
- aliases: {
- radius: "r",
- x: "cx",
- y: "cy",
- centerX: "cx",
- centerY: "cy"
- },
- defaults: {
- cx: 0,
- cy: 0,
- r: 4
- },
- triggers: {
- cx: "path",
- cy: "path",
- r: "path"
- }
- }
- },
- updatePlainBBox: function(c) {
- var b = this.attr,
- a = b.cx,
- e = b.cy,
- d = b.r;
- c.x = a - d;
- c.y = e - d;
- c.width = d + d;
- c.height = d + d
- },
- updateTransformedBBox: function(d) {
- var g = this.attr,
- f = g.cx,
- e = g.cy,
- a = g.r,
- h = g.matrix,
- j = h.getScaleX(),
- i = h.getScaleY(),
- c, b;
- c = j * a;
- b = i * a;
- d.x = h.x(f, e) - c;
- d.y = h.y(f, e) - b;
- d.width = c + c;
- d.height = b + b
- },
- updatePath: function(b, a) {
- b.arc(a.cx, a.cy, a.r, 0, Math.PI * 2, false)
- }
-});
-Ext.define("Ext.draw.sprite.Arc", {
- extend: "Ext.draw.sprite.Circle",
- alias: "sprite.arc",
- type: "arc",
- inheritableStatics: {
- def: {
- processors: {
- startAngle: "number",
- endAngle: "number",
- anticlockwise: "bool"
- },
- aliases: {
- from: "startAngle",
- to: "endAngle",
- start: "startAngle",
- end: "endAngle"
- },
- defaults: {
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false
- },
- triggers: {
- startAngle: "path",
- endAngle: "path",
- anticlockwise: "path"
- }
- }
- },
- updatePath: function(b, a) {
- b.arc(a.cx, a.cy, a.r, a.startAngle, a.endAngle, a.anticlockwise)
- }
-});
-Ext.define("Ext.draw.sprite.Arrow", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.arrow",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 1.5,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c * 0.7, ",", e - c * 0.4, "l", [c * 0.6, 0, 0, -c * 0.4, c, c * 0.8, -c, c * 0.8, 0, -c * 0.4, -c * 0.6, 0], "z"))
- }
-});
-Ext.define("Ext.draw.sprite.Composite", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.composite",
- type: "composite",
- isComposite: true,
- config: {
- sprites: []
- },
- constructor: function() {
- this.sprites = [];
- this.sprites.map = {};
- this.callParent(arguments)
- },
- add: function(c) {
- if (!c) {
- return null
- }
- if (!c.isSprite) {
- c = Ext.create("sprite." + c.type, c);
- c.setParent(this);
- c.setSurface(this.getSurface())
- }
- var d = this,
- a = d.attr,
- b = c.applyTransformations;
- c.applyTransformations = function() {
- if (c.attr.dirtyTransform) {
- a.dirtyTransform = true;
- a.bbox.plain.dirty = true;
- a.bbox.transform.dirty = true
- }
- b.call(c)
- };
- d.sprites.push(c);
- d.sprites.map[c.id] = c.getId();
- a.bbox.plain.dirty = true;
- a.bbox.transform.dirty = true;
- return c
- },
- updateSurface: function(a) {
- for (var b = 0, c = this.sprites.length; b < c; b++) {
- this.sprites[b].setSurface(a)
- }
- },
- addAll: function(b) {
- if (b.isSprite || b.type) {
- this.add(b)
- } else {
- if (Ext.isArray(b)) {
- var a = 0;
- while (a < b.length) {
- this.add(b[a++])
- }
- }
- }
- },
- updatePlainBBox: function(g) {
- var e = this,
- b = Infinity,
- h = -Infinity,
- f = Infinity,
- a = -Infinity,
- j, k, c, d;
- for (c = 0, d = e.sprites.length; c < d; c++) {
- j = e.sprites[c];
- j.applyTransformations();
- k = j.getBBox();
- if (b > k.x) {
- b = k.x
- }
- if (h < k.x + k.width) {
- h = k.x + k.width
- }
- if (f > k.y) {
- f = k.y
- }
- if (a < k.y + k.height) {
- a = k.y + k.height
- }
- }
- g.x = b;
- g.y = f;
- g.width = h - b;
- g.height = a - f
- },
- render: function(a, b, f) {
- var d = this.attr.matrix,
- c, e;
- d.toContext(b);
- for (c = 0, e = this.sprites.length; c < e; c++) {
- a.renderSprite(this.sprites[c], f)
- }
- },
- destroy: function() {
- var c = this,
- d = c.sprites,
- b = d.length,
- a;
- c.callParent();
- for (a = 0; a < b; a++) {
- d[a].destroy()
- }
- d.length = 0
- }
-});
-Ext.define("Ext.draw.sprite.Cross", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.cross",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size / 1.7,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c, ",", e, "l", [-c, -c, c, -c, c, c, c, -c, c, c, -c, c, c, c, -c, c, -c, -c, -c, c, -c, -c, "z"]))
- }
-});
-Ext.define("Ext.draw.sprite.Diamond", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.diamond",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 1.25,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString(["M", a, e - c, "l", c, c, -c, c, -c, -c, c, -c, "z"])
- }
-});
-Ext.define("Ext.draw.sprite.Ellipse", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.ellipse",
- type: "ellipse",
- inheritableStatics: {
- def: {
- processors: {
- cx: "number",
- cy: "number",
- rx: "number",
- ry: "number",
- axisRotation: "number"
- },
- aliases: {
- radius: "r",
- x: "cx",
- y: "cy",
- centerX: "cx",
- centerY: "cy",
- radiusX: "rx",
- radiusY: "ry"
- },
- defaults: {
- cx: 0,
- cy: 0,
- rx: 1,
- ry: 1,
- axisRotation: 0
- },
- triggers: {
- cx: "path",
- cy: "path",
- rx: "path",
- ry: "path",
- axisRotation: "path"
- }
- }
- },
- updatePlainBBox: function(c) {
- var b = this.attr,
- a = b.cx,
- f = b.cy,
- e = b.rx,
- d = b.ry;
- c.x = a - e;
- c.y = f - d;
- c.width = e + e;
- c.height = d + d
- },
- updateTransformedBBox: function(d) {
- var i = this.attr,
- f = i.cx,
- e = i.cy,
- c = i.rx,
- b = i.ry,
- l = b / c,
- m = i.matrix.clone(),
- a, q, k, j, p, o, n, g;
- m.append(1, 0, 0, l, 0, e * (1 - l));
- a = m.getXX();
- k = m.getYX();
- p = m.getDX();
- q = m.getXY();
- j = m.getYY();
- o = m.getDY();
- n = Math.sqrt(a * a + k * k) * c;
- g = Math.sqrt(q * q + j * j) * c;
- d.x = f * a + e * k + p - n;
- d.y = f * q + e * j + o - g;
- d.width = n + n;
- d.height = g + g
- },
- updatePath: function(b, a) {
- b.ellipse(a.cx, a.cy, a.rx, a.ry, a.axisRotation, 0, Math.PI * 2, false)
- }
-});
-Ext.define("Ext.draw.sprite.EllipticalArc", {
- extend: "Ext.draw.sprite.Ellipse",
- alias: "sprite.ellipticalArc",
- type: "ellipticalArc",
- inheritableStatics: {
- def: {
- processors: {
- startAngle: "number",
- endAngle: "number",
- anticlockwise: "bool"
- },
- aliases: {
- from: "startAngle",
- to: "endAngle",
- start: "startAngle",
- end: "endAngle"
- },
- defaults: {
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false
- },
- triggers: {
- startAngle: "path",
- endAngle: "path",
- anticlockwise: "path"
- }
- }
- },
- updatePath: function(b, a) {
- b.ellipse(a.cx, a.cy, a.rx, a.ry, a.axisRotation, a.startAngle, a.endAngle, a.anticlockwise)
- }
-});
-Ext.define("Ext.draw.sprite.Rect", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.rect",
- type: "rect",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number",
- radius: "number"
- },
- aliases: {},
- triggers: {
- x: "path",
- y: "path",
- width: "path",
- height: "path",
- radius: "path"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 8,
- height: 8,
- radius: 0
- }
- }
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.x;
- b.y = a.y;
- b.width = a.width;
- b.height = a.height
- },
- updateTransformedBBox: function(a, b) {
- this.attr.matrix.transformBBox(b, this.attr.radius, a)
- },
- updatePath: function(f, d) {
- var c = d.x,
- g = d.y,
- e = d.width,
- b = d.height,
- a = Math.min(d.radius, Math.abs(d.height) * 0.5, Math.abs(d.width) * 0.5);
- if (a === 0) {
- f.rect(c, g, e, b)
- } else {
- f.moveTo(c + a, g);
- f.arcTo(c + e, g, c + e, g + b, a);
- f.arcTo(c + e, g + b, c, g + b, a);
- f.arcTo(c, g + b, c, g, a);
- f.arcTo(c, g, c + a, g, a)
- }
- }
-});
-Ext.define("Ext.draw.sprite.Image", {
- extend: "Ext.draw.sprite.Rect",
- alias: "sprite.image",
- type: "image",
- statics: {
- imageLoaders: {}
- },
- inheritableStatics: {
- def: {
- processors: {
- src: "string"
- },
- defaults: {
- src: "",
- width: null,
- height: null
- }
- }
- },
- render: function(c, o) {
- var j = this,
- h = j.attr,
- n = h.matrix,
- a = h.src,
- l = h.x,
- k = h.y,
- b = h.width,
- m = h.height,
- g = Ext.draw.sprite.Image.imageLoaders[a],
- f, d, e;
- if (g && g.done) {
- n.toContext(o);
- d = g.image;
- o.drawImage(d, l, k, b || (d.naturalWidth || d.width) / c.devicePixelRatio, m || (d.naturalHeight || d.height) / c.devicePixelRatio)
- } else {
- if (!g) {
- f = new Image();
- g = Ext.draw.sprite.Image.imageLoaders[a] = {
- image: f,
- done: false,
- pendingSprites: [j],
- pendingSurfaces: [c]
- };
- f.width = b;
- f.height = m;
- f.onload = function() {
- if (!g.done) {
- g.done = true;
- for (e = 0; e < g.pendingSprites.length; e++) {
- g.pendingSprites[e].setDirty(true)
- }
- for (e in g.pendingSurfaces) {
- g.pendingSurfaces[e].renderFrame()
- }
- }
- };
- f.src = a
- } else {
- Ext.Array.include(g.pendingSprites, j);
- Ext.Array.include(g.pendingSurfaces, c)
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Instancing", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.instancing",
- type: "instancing",
- isInstancing: true,
- config: {
- template: null
- },
- instances: null,
- applyTemplate: function(a) {
- if (!a.isSprite) {
- if (!a.xclass && !a.type) {
- a.type = "circle"
- }
- a = Ext.create(a.xclass || "sprite." + a.type, a)
- }
- a.setParent(this);
- return a
- },
- updateTemplate: function(a, b) {
- if (b) {
- delete b.ownAttr
- }
- a.setSurface(this.getSurface());
- a.ownAttr = a.attr;
- this.clearAll()
- },
- updateSurface: function(a) {
- var b = this.getTemplate();
- if (b) {
- b.setSurface(a)
- }
- },
- get: function(a) {
- return this.instances[a]
- },
- getCount: function() {
- return this.instances.length
- },
- clearAll: function() {
- var a = this.getTemplate();
- a.attr.children = this.instances = [];
- this.position = 0
- },
- createInstance: function(d, f, c) {
- var e = this.getTemplate(),
- b = e.attr,
- a = Ext.Object.chain(b);
- e.topModifier.prepareAttributes(a);
- e.attr = a;
- e.setAttributes(d, f, c);
- a.template = e;
- this.instances.push(a);
- e.attr = b;
- this.position++;
- return a
- },
- getBBox: function() {
- return null
- },
- getBBoxFor: function(b, d) {
- var c = this.getTemplate(),
- a = c.attr,
- e;
- c.attr = this.instances[b];
- e = c.getBBox(d);
- c.attr = a;
- return e
- },
- isVisible: function() {
- var b = this.attr,
- c = this.getParent(),
- a;
- a = c && c.isSurface && !b.hidden && b.globalAlpha;
- return !!a
- },
- isInstanceVisible: function(c) {
- var e = this,
- d = e.getTemplate(),
- b = d.attr,
- f = e.instances,
- a = false;
- if (!Ext.isNumber(c) || c < 0 || c >= f.length || !e.isVisible()) {
- return a
- }
- d.attr = f[c];
- a = d.isVisible(point, options);
- d.attr = b;
- return a
- },
- render: function(b, l, d, h) {
- var g = this,
- j = g.getTemplate(),
- k = g.attr.matrix,
- c = j.attr,
- a = g.instances,
- e, f = g.position;
- k.toContext(l);
- j.preRender(b, l, d, h);
- j.useAttributes(l, h);
- for (e = 0; e < f; e++) {
- if (a[e].dirtyZIndex) {
- break
- }
- }
- for (e = 0; e < f; e++) {
- if (a[e].hidden) {
- continue
- }
- l.save();
- j.attr = a[e];
- j.useAttributes(l, h);
- j.render(b, l, d, h);
- l.restore()
- }
- j.attr = c
- },
- setAttributesFor: function(c, e, f) {
- var d = this.getTemplate(),
- b = d.attr,
- a = this.instances[c];
- if (!a) {
- return
- }
- d.attr = a;
- if (f) {
- e = Ext.apply({}, e)
- } else {
- e = d.self.def.normalize(e)
- }
- d.topModifier.pushDown(a, e);
- d.attr = b
- },
- destroy: function() {
- var b = this,
- a = b.getTemplate();
- b.instances = null;
- if (a) {
- a.destroy()
- }
- b.callParent()
- }
-});
-Ext.define("Ext.draw.overrides.sprite.Instancing", {
- override: "Ext.draw.sprite.Instancing",
- hitTest: function(f, j) {
- var e = this,
- g = e.getTemplate(),
- b = g.attr,
- a = e.instances,
- d = a.length,
- c = 0,
- h = null;
- if (!e.isVisible()) {
- return h
- }
- for (; c < d; c++) {
- g.attr = a[c];
- h = g.hitTest(f, j);
- if (h) {
- h.isInstance = true;
- h.template = h.sprite;
- h.sprite = this;
- h.instance = a[c];
- h.index = c;
- return h
- }
- }
- g.attr = b;
- return h
- }
-});
-Ext.define("Ext.draw.sprite.Line", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.line",
- type: "line",
- inheritableStatics: {
- def: {
- processors: {
- fromX: "number",
- fromY: "number",
- toX: "number",
- toY: "number"
- },
- defaults: {
- fromX: 0,
- fromY: 0,
- toX: 1,
- toY: 1,
- strokeStyle: "black"
- },
- aliases: {
- x1: "fromX",
- y1: "fromY",
- x2: "toX",
- y2: "toY"
- }
- }
- },
- updateLineBBox: function(b, i, s, g, r, f) {
- var o = this.attr,
- q = o.matrix,
- h = o.lineWidth / 2,
- m, l, d, c, k, j, n;
- if (i) {
- n = q.transformPoint([s, g]);
- s = n[0];
- g = n[1];
- n = q.transformPoint([r, f]);
- r = n[0];
- f = n[1]
- }
- m = Math.min(s, r);
- d = Math.max(s, r);
- l = Math.min(g, f);
- c = Math.max(g, f);
- var t = Math.atan2(d - m, c - l),
- a = Math.sin(t),
- e = Math.cos(t),
- k = h * e,
- j = h * a;
- m -= k;
- l -= j;
- d += k;
- c += j;
- b.x = m;
- b.y = l;
- b.width = d - m;
- b.height = c - l
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- this.updateLineBBox(b, false, a.fromX, a.fromY, a.toX, a.toY)
- },
- updateTransformedBBox: function(b, c) {
- var a = this.attr;
- this.updateLineBBox(b, true, a.fromX, a.fromY, a.toX, a.toY)
- },
- render: function(b, c) {
- var a = this.attr,
- d = this.attr.matrix;
- d.toContext(c);
- c.beginPath();
- c.moveTo(a.fromX, a.fromY);
- c.lineTo(a.toX, a.toY);
- c.stroke()
- }
-});
-Ext.define("Ext.draw.sprite.Plus", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.plus",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size / 1.3,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c / 2, ",", e - c / 2, "l", [0, -c, c, 0, 0, c, c, 0, 0, c, -c, 0, 0, c, -c, 0, 0, -c, -c, 0, 0, -c, "z"]))
- }
-});
-Ext.define("Ext.draw.sprite.Sector", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.sector",
- type: "sector",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- margin: "number"
- },
- aliases: {
- rho: "endRho"
- },
- triggers: {
- centerX: "path,bbox",
- centerY: "path,bbox",
- startAngle: "path,bbox",
- endAngle: "path,bbox",
- startRho: "path,bbox",
- endRho: "path,bbox",
- margin: "path,bbox"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: 0,
- endAngle: 0,
- startRho: 0,
- endRho: 150,
- margin: 0,
- path: "M 0,0"
- }
- }
- },
- getMidAngle: function() {
- return this.midAngle || 0
- },
- updatePath: function(j, h) {
- var g = Math.min(h.startAngle, h.endAngle),
- c = Math.max(h.startAngle, h.endAngle),
- b = this.midAngle = (g + c) * 0.5,
- d = h.margin,
- f = h.centerX,
- e = h.centerY,
- i = Math.min(h.startRho, h.endRho),
- a = Math.max(h.startRho, h.endRho);
- if (d) {
- f += d * Math.cos(b);
- e += d * Math.sin(b)
- }
- j.moveTo(f + i * Math.cos(g), e + i * Math.sin(g));
- j.lineTo(f + a * Math.cos(g), e + a * Math.sin(g));
- j.arc(f, e, a, g, c, false);
- j.lineTo(f + i * Math.cos(c), e + i * Math.sin(c));
- j.arc(f, e, i, c, g, true)
- }
-});
-Ext.define("Ext.draw.sprite.Square", {
- extend: "Ext.draw.sprite.Rect",
- alias: "sprite.square",
- inheritableStatics: {
- def: {
- processors: {
- size: "number"
- },
- defaults: {
- size: 4
- },
- triggers: {
- size: "size"
- },
- updaters: {
- size: function(a) {
- var c = a.size,
- b = a.lineWidth / 2;
- this.setAttributes({
- x: a.x - c - b,
- y: a.y - c,
- height: 2 * c,
- width: 2 * c
- })
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.TextMeasurer", {
- singleton: true,
- requires: ["Ext.util.TextMetrics"],
- measureDiv: null,
- measureCache: {},
- precise: Ext.isIE8,
- measureDivTpl: {
- tag: "div",
- style: {
- overflow: "hidden",
- position: "relative",
- "float": "left",
- width: 0,
- height: 0
- },
- children: {
- tag: "div",
- style: {
- display: "block",
- position: "absolute",
- x: -100000,
- y: -100000,
- padding: 0,
- margin: 0,
- "z-index": -100000,
- "white-space": "nowrap"
- }
- }
- },
- actualMeasureText: function(g, b) {
- var e = Ext.draw.TextMeasurer,
- f = e.measureDiv,
- a = 100000,
- c;
- if (!f) {
- var d = Ext.Element.create({
- style: {
- overflow: "hidden",
- position: "relative",
- "float": "left",
- width: 0,
- height: 0
- }
- });
- e.measureDiv = f = Ext.Element.create({
- style: {
- position: "absolute",
- x: a,
- y: a,
- "z-index": -a,
- "white-space": "nowrap",
- display: "block",
- padding: 0,
- margin: 0
- }
- });
- Ext.getBody().appendChild(d);
- d.appendChild(f)
- }
- if (b) {
- f.setStyle({
- font: b,
- lineHeight: "normal"
- })
- }
- f.setText("(" + g + ")");
- c = f.getSize();
- f.setText("()");
- c.width -= f.getSize().width;
- return c
- },
- measureTextSingleLine: function(h, d) {
- if (this.precise) {
- return this.preciseMeasureTextSingleLine(h, d)
- }
- h = h.toString();
- var a = this.measureCache,
- g = h.split(""),
- c = 0,
- j = 0,
- l, b, e, f, k;
- if (!a[d]) {
- a[d] = {}
- }
- a = a[d];
- if (a[h]) {
- return a[h]
- }
- for (e = 0, f = g.length; e < f; e++) {
- b = g[e];
- if (!(l = a[b])) {
- k = this.actualMeasureText(b, d);
- l = a[b] = k
- }
- c += l.width;
- j = Math.max(j, l.height)
- }
- return a[h] = {
- width: c,
- height: j
- }
- },
- preciseMeasureTextSingleLine: function(c, a) {
- c = c.toString();
- var b = this.measureDiv || (this.measureDiv = Ext.getBody().createChild(this.measureDivTpl).down("div"));
- b.setStyle({
- font: a || ""
- });
- return Ext.util.TextMetrics.measure(b, c)
- },
- measureText: function(e, b) {
- var h = e.split("\n"),
- d = h.length,
- f = 0,
- a = 0,
- j, c, g;
- if (d === 1) {
- return this.measureTextSingleLine(e, b)
- }
- g = [];
- for (c = 0; c < d; c++) {
- j = this.measureTextSingleLine(h[c], b);
- g.push(j);
- f += j.height;
- a = Math.max(a, j.width)
- }
- return {
- width: a,
- height: f,
- sizes: g
- }
- }
-});
-Ext.define("Ext.draw.sprite.Text", function() {
- var d = {
- "xx-small": true,
- "x-small": true,
- small: true,
- medium: true,
- large: true,
- "x-large": true,
- "xx-large": true
- };
- var b = {
- normal: true,
- bold: true,
- bolder: true,
- lighter: true,
- 100: true,
- 200: true,
- 300: true,
- 400: true,
- 500: true,
- 600: true,
- 700: true,
- 800: true,
- 900: true
- };
- var a = {
- start: "start",
- left: "start",
- center: "center",
- middle: "center",
- end: "end",
- right: "end"
- };
- var c = {
- top: "top",
- hanging: "hanging",
- middle: "middle",
- center: "middle",
- alphabetic: "alphabetic",
- ideographic: "ideographic",
- bottom: "bottom"
- };
- return {
- extend: "Ext.draw.sprite.Sprite",
- requires: ["Ext.draw.TextMeasurer", "Ext.draw.Color"],
- alias: "sprite.text",
- type: "text",
- lineBreakRe: /\r?\n/g,
- inheritableStatics: {
- def: {
- animationProcessors: {
- text: "text"
- },
- processors: {
- x: "number",
- y: "number",
- text: "string",
- fontSize: function(e) {
- if (Ext.isNumber(+e)) {
- return e + "px"
- } else {
- if (e.match(Ext.dom.Element.unitRe)) {
- return e
- } else {
- if (e in d) {
- return e
- }
- }
- }
- },
- fontStyle: "enums(,italic,oblique)",
- fontVariant: "enums(,small-caps)",
- fontWeight: function(e) {
- if (e in b) {
- return String(e)
- } else {
- return ""
- }
- },
- fontFamily: "string",
- textAlign: function(e) {
- return a[e] || "center"
- },
- textBaseline: function(e) {
- return c[e] || "alphabetic"
- },
- font: "string"
- },
- aliases: {
- "font-size": "fontSize",
- "font-family": "fontFamily",
- "font-weight": "fontWeight",
- "font-variant": "fontVariant",
- "text-anchor": "textAlign"
- },
- defaults: {
- fontStyle: "",
- fontVariant: "",
- fontWeight: "",
- fontSize: "10px",
- fontFamily: "sans-serif",
- font: "10px sans-serif",
- textBaseline: "alphabetic",
- textAlign: "start",
- strokeStyle: "rgba(0, 0, 0, 0)",
- fillStyle: "#000",
- x: 0,
- y: 0,
- text: ""
- },
- triggers: {
- fontStyle: "fontX,bbox",
- fontVariant: "fontX,bbox",
- fontWeight: "fontX,bbox",
- fontSize: "fontX,bbox",
- fontFamily: "fontX,bbox",
- font: "font,bbox,canvas",
- textBaseline: "bbox",
- textAlign: "bbox",
- x: "bbox",
- y: "bbox",
- text: "bbox"
- },
- updaters: {
- fontX: "makeFontShorthand",
- font: "parseFontShorthand"
- }
- }
- },
- constructor: function(e) {
- if (e && e.font) {
- e = Ext.clone(e);
- for (var f in e) {
- if (f !== "font" && f.indexOf("font") === 0) {
- delete e[f]
- }
- }
- }
- Ext.draw.sprite.Sprite.prototype.constructor.call(this, e)
- },
- fontValuesMap: {
- italic: "fontStyle",
- oblique: "fontStyle",
- "small-caps": "fontVariant",
- bold: "fontWeight",
- bolder: "fontWeight",
- lighter: "fontWeight",
- "100": "fontWeight",
- "200": "fontWeight",
- "300": "fontWeight",
- "400": "fontWeight",
- "500": "fontWeight",
- "600": "fontWeight",
- "700": "fontWeight",
- "800": "fontWeight",
- "900": "fontWeight",
- "xx-small": "fontSize",
- "x-small": "fontSize",
- small: "fontSize",
- medium: "fontSize",
- large: "fontSize",
- "x-large": "fontSize",
- "xx-large": "fontSize"
- },
- makeFontShorthand: function(e) {
- var f = [];
- if (e.fontStyle) {
- f.push(e.fontStyle)
- }
- if (e.fontVariant) {
- f.push(e.fontVariant)
- }
- if (e.fontWeight) {
- f.push(e.fontWeight)
- }
- if (e.fontSize) {
- f.push(e.fontSize)
- }
- if (e.fontFamily) {
- f.push(e.fontFamily)
- }
- this.setAttributes({
- font: f.join(" ")
- }, true)
- },
- parseFontShorthand: function(j) {
- var m = j.font,
- k = m.length,
- l = {},
- n = this.fontValuesMap,
- e = 0,
- i, g, f, h;
- while (e < k && i !== -1) {
- i = m.indexOf(" ", e);
- if (i < 0) {
- f = m.substr(e)
- } else {
- if (i > e) {
- f = m.substr(e, i - e)
- } else {
- continue
- }
- }
- g = f.indexOf("/");
- if (g > 0) {
- f = f.substr(0, g)
- } else {
- if (g === 0) {
- continue
- }
- }
- if (f !== "normal" && f !== "inherit") {
- h = n[f];
- if (h) {
- l[h] = f
- } else {
- if (f.match(Ext.dom.Element.unitRe)) {
- l.fontSize = f
- } else {
- l.fontFamily = m.substr(e);
- break
- }
- }
- }
- e = i + 1
- }
- if (!l.fontStyle) {
- l.fontStyle = ""
- }
- if (!l.fontVariant) {
- l.fontVariant = ""
- }
- if (!l.fontWeight) {
- l.fontWeight = ""
- }
- this.setAttributes(l, true)
- },
- fontProperties: {
- fontStyle: true,
- fontVariant: true,
- fontWeight: true,
- fontSize: true,
- fontFamily: true
- },
- setAttributes: function(g, i, e) {
- var f, h;
- if (g && g.font) {
- h = {};
- for (f in g) {
- if (!(f in this.fontProperties)) {
- h[f] = g[f]
- }
- }
- g = h
- }
- this.callParent([g, i, e])
- },
- getBBox: function(g) {
- var h = this,
- f = h.attr.bbox.plain,
- e = h.getSurface();
- if (f.dirty) {
- h.updatePlainBBox(f);
- f.dirty = false
- }
- if (e.getInherited().rtl && e.getFlipRtlText()) {
- h.updatePlainBBox(f, true)
- }
- return h.callParent([g])
- },
- rtlAlignments: {
- start: "end",
- center: "center",
- end: "start"
- },
- updatePlainBBox: function(k, B) {
- var C = this,
- w = C.attr,
- o = w.x,
- n = w.y,
- q = [],
- t = w.font,
- r = w.text,
- s = w.textBaseline,
- l = w.textAlign,
- u = (B && C.oldSize) ? C.oldSize : (C.oldSize = Ext.draw.TextMeasurer.measureText(r, t)),
- z = C.getSurface(),
- p = z.getInherited().rtl,
- v = p && z.getFlipRtlText(),
- h = z.getRect(),
- f = u.sizes,
- g = u.height,
- j = u.width,
- m = f ? f.length : 0,
- e, A = 0;
- switch (s) {
- case "hanging":
- case "top":
- break;
- case "ideographic":
- case "bottom":
- n -= g;
- break;
- case "alphabetic":
- n -= g * 0.8;
- break;
- case "middle":
- n -= g * 0.5;
- break
- }
- if (v) {
- o = h[2] - h[0] - o;
- l = C.rtlAlignments[l]
- }
- switch (l) {
- case "start":
- if (p) {
- for (; A < m; A++) {
- e = f[A].width;
- q.push(-(j - e))
- }
- }
- break;
- case "end":
- o -= j;
- if (p) {
- break
- }
- for (; A < m; A++) {
- e = f[A].width;
- q.push(j - e)
- }
- break;
- case "center":
- o -= j * 0.5;
- for (; A < m; A++) {
- e = f[A].width;
- q.push((p ? -1 : 1) * (j - e) * 0.5)
- }
- break
- }
- w.textAlignOffsets = q;
- k.x = o;
- k.y = n;
- k.width = j;
- k.height = g
- },
- setText: function(e) {
- this.setAttributes({
- text: e
- }, true)
- },
- render: function(e, q, k) {
- var h = this,
- g = h.attr,
- p = Ext.draw.Matrix.fly(g.matrix.elements.slice(0)),
- o = h.getBBox(true),
- s = g.textAlignOffsets,
- m = Ext.draw.Color.RGBA_NONE,
- l, j, f, r, n;
- if (g.text.length === 0) {
- return
- }
- r = g.text.split(h.lineBreakRe);
- n = o.height / r.length;
- l = g.bbox.plain.x;
- j = g.bbox.plain.y + n * 0.78;
- p.toContext(q);
- if (e.getInherited().rtl) {
- l += g.bbox.plain.width
- }
- for (f = 0; f < r.length; f++) {
- if (q.fillStyle !== m) {
- q.fillText(r[f], l + (s[f] || 0), j + n * f)
- }
- if (q.strokeStyle !== m) {
- q.strokeText(r[f], l + (s[f] || 0), j + n * f)
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Tick", {
- extend: "Ext.draw.sprite.Line",
- alias: "sprite.tick",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "tick",
- y: "tick",
- size: "tick"
- },
- updaters: {
- tick: function(b) {
- var d = b.size * 1.5,
- c = b.lineWidth / 2,
- a = b.x,
- e = b.y;
- this.setAttributes({
- fromX: a - c,
- fromY: e - d,
- toX: a - c,
- toY: e + d
- })
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Triangle", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.triangle",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 2.2,
- a = b.x,
- e = b.y;
- d.fromSvgString("M".concat(a, ",", e, "m0-", c * 0.58, "l", c * 0.5, ",", c * 0.87, "-", c, ",0z"))
- }
-});
-Ext.define("Ext.draw.gradient.Linear", {
- extend: "Ext.draw.gradient.Gradient",
- requires: ["Ext.draw.Color"],
- type: "linear",
- config: {
- degrees: 0,
- radians: 0
- },
- applyRadians: function(b, a) {
- if (Ext.isNumber(b)) {
- return b
- }
- return a
- },
- applyDegrees: function(b, a) {
- if (Ext.isNumber(b)) {
- return b
- }
- return a
- },
- updateRadians: function(a) {
- this.setDegrees(Ext.draw.Draw.degrees(a))
- },
- updateDegrees: function(a) {
- this.setRadians(Ext.draw.Draw.rad(a))
- },
- generateGradient: function(q, o) {
- var c = this.getRadians(),
- p = Math.cos(c),
- j = Math.sin(c),
- m = o.width,
- f = o.height,
- d = o.x + m * 0.5,
- b = o.y + f * 0.5,
- n = this.getStops(),
- g = n.length,
- k, a, e;
- if (Ext.isNumber(d + b) && f > 0 && m > 0) {
- a = (Math.sqrt(f * f + m * m) * Math.abs(Math.cos(c - Math.atan(f / m)))) / 2;
- k = q.createLinearGradient(d + p * a, b + j * a, d - p * a, b - j * a);
- for (e = 0; e < g; e++) {
- k.addColorStop(n[e].offset, n[e].color)
- }
- return k
- }
- return Ext.draw.Color.NONE
- }
-});
-Ext.define("Ext.draw.gradient.Radial", {
- extend: "Ext.draw.gradient.Gradient",
- type: "radial",
- config: {
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- }
- },
- applyStart: function(a, b) {
- if (!b) {
- return a
- }
- var c = {
- x: b.x,
- y: b.y,
- r: b.r
- };
- if ("x" in a) {
- c.x = a.x
- } else {
- if ("centerX" in a) {
- c.x = a.centerX
- }
- }
- if ("y" in a) {
- c.y = a.y
- } else {
- if ("centerY" in a) {
- c.y = a.centerY
- }
- }
- if ("r" in a) {
- c.r = a.r
- } else {
- if ("radius" in a) {
- c.r = a.radius
- }
- }
- return c
- },
- applyEnd: function(b, a) {
- if (!a) {
- return b
- }
- var c = {
- x: a.x,
- y: a.y,
- r: a.r
- };
- if ("x" in b) {
- c.x = b.x
- } else {
- if ("centerX" in b) {
- c.x = b.centerX
- }
- }
- if ("y" in b) {
- c.y = b.y
- } else {
- if ("centerY" in b) {
- c.y = b.centerY
- }
- }
- if ("r" in b) {
- c.r = b.r
- } else {
- if ("radius" in b) {
- c.r = b.radius
- }
- }
- return c
- },
- generateGradient: function(n, m) {
- var a = this.getStart(),
- b = this.getEnd(),
- k = m.width * 0.5,
- d = m.height * 0.5,
- j = m.x + k,
- f = m.y + d,
- g = n.createRadialGradient(j + a.x * k, f + a.y * d, a.r * Math.max(k, d), j + b.x * k, f + b.y * d, b.r * Math.max(k, d)),
- l = this.getStops(),
- e = l.length,
- c;
- for (c = 0; c < e; c++) {
- g.addColorStop(l[c].offset, l[c].color)
- }
- return g
- }
-});
-Ext.define("Ext.draw.Surface", {
- extend: "Ext.draw.SurfaceBase",
- xtype: "surface",
- requires: ["Ext.draw.sprite.*", "Ext.draw.gradient.*", "Ext.draw.sprite.AttributeDefinition", "Ext.draw.Matrix", "Ext.draw.Draw"],
- uses: ["Ext.draw.engine.Canvas"],
- devicePixelRatio: window.devicePixelRatio || window.screen.deviceXDPI / window.screen.logicalXDPI,
- deprecated: {
- "5.1.0": {
- statics: {
- methods: {
- stableSort: function(a) {
- return Ext.Array.sort(a, function(d, c) {
- return d.attr.zIndex - c.attr.zIndex
- })
- }
- }
- }
- }
- },
- config: {
- cls: Ext.baseCSSPrefix + "surface",
- rect: null,
- background: null,
- items: [],
- dirty: false,
- flipRtlText: false
- },
- isSurface: true,
- isPendingRenderFrame: false,
- dirtyPredecessorCount: 0,
- constructor: function(a) {
- var b = this;
- b.predecessors = [];
- b.successors = [];
- b.map = {};
- b.callParent([a]);
- b.matrix = new Ext.draw.Matrix();
- b.inverseMatrix = b.matrix.inverse()
- },
- roundPixel: function(a) {
- return Math.round(this.devicePixelRatio * a) / this.devicePixelRatio
- },
- waitFor: function(a) {
- var b = this,
- c = b.predecessors;
- if (!Ext.Array.contains(c, a)) {
- c.push(a);
- a.successors.push(b);
- if (a.getDirty()) {
- b.dirtyPredecessorCount++
- }
- }
- },
- updateDirty: function(d) {
- var c = this.successors,
- e = c.length,
- b = 0,
- a;
- for (; b < e; b++) {
- a = c[b];
- if (d) {
- a.dirtyPredecessorCount++;
- a.setDirty(true)
- } else {
- a.dirtyPredecessorCount--;
- if (a.dirtyPredecessorCount === 0 && a.isPendingRenderFrame) {
- a.renderFrame()
- }
- }
- }
- },
- applyBackground: function(a, b) {
- this.setDirty(true);
- if (Ext.isString(a)) {
- a = {
- fillStyle: a
- }
- }
- return Ext.factory(a, Ext.draw.sprite.Rect, b)
- },
- applyRect: function(a, b) {
- if (b && a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]) {
- return
- }
- if (Ext.isArray(a)) {
- return [a[0], a[1], a[2], a[3]]
- } else {
- if (Ext.isObject(a)) {
- return [a.x || a.left, a.y || a.top, a.width || (a.right - a.left), a.height || (a.bottom - a.top)]
- }
- }
- },
- updateRect: function(i) {
- var h = this,
- c = i[0],
- f = i[1],
- g = c + i[2],
- a = f + i[3],
- e = h.getBackground(),
- d = h.element;
- d.setLocalXY(Math.floor(c), Math.floor(f));
- d.setSize(Math.ceil(g - Math.floor(c)), Math.ceil(a - Math.floor(f)));
- if (e) {
- e.setAttributes({
- x: 0,
- y: 0,
- width: Math.ceil(g - Math.floor(c)),
- height: Math.ceil(a - Math.floor(f))
- })
- }
- h.setDirty(true)
- },
- resetTransform: function() {
- this.matrix.set(1, 0, 0, 1, 0, 0);
- this.inverseMatrix.set(1, 0, 0, 1, 0, 0);
- this.setDirty(true)
- },
- get: function(a) {
- return this.map[a] || this.getItems()[a]
- },
- add: function() {
- var g = this,
- e = Array.prototype.slice.call(arguments),
- j = Ext.isArray(e[0]),
- a = g.map,
- c = [],
- f, k, h, b, d;
- f = Ext.Array.clean(j ? e[0] : e);
- if (!f.length) {
- return c
- }
- for (b = 0, d = f.length; b < d; b++) {
- k = f[b];
- h = null;
- if (k.isSprite && !a[k.getId()]) {
- h = k
- } else {
- if (!a[k.id]) {
- h = this.createItem(k)
- }
- }
- if (h) {
- a[h.getId()] = h;
- c.push(h);
- h.setParent(g);
- h.setSurface(g);
- g.onAdd(h)
- }
- }
- f = g.getItems();
- if (f) {
- f.push.apply(f, c)
- }
- g.dirtyZIndex = true;
- g.setDirty(true);
- if (!j && c.length === 1) {
- return c[0]
- } else {
- return c
- }
- },
- onAdd: Ext.emptyFn,
- remove: function(a, c) {
- var b = this,
- e, d;
- if (a) {
- if (a.charAt) {
- a = b.map[a]
- }
- if (!a || !a.isSprite) {
- return null
- }
- if (a.isDestroyed || a.isDestroying) {
- return a
- }
- e = a.getId();
- d = b.map[e];
- delete b.map[e];
- if (c) {
- a.destroy()
- }
- if (!d) {
- return a
- }
- a.setParent(null);
- a.setSurface(null);
- Ext.Array.remove(b.getItems(), a);
- b.dirtyZIndex = true;
- b.setDirty(true)
- }
- return a || null
- },
- removeAll: function(d) {
- var a = this.getItems(),
- b = a.length - 1,
- c;
- if (d) {
- for (; b >= 0; b--) {
- a[b].destroy()
- }
- } else {
- for (; b >= 0; b--) {
- c = a[b];
- c.setParent(null);
- c.setSurface(null)
- }
- }
- a.length = 0;
- this.map = {};
- this.dirtyZIndex = true
- },
- applyItems: function(a) {
- if (this.getItems()) {
- this.removeAll(true)
- }
- return Ext.Array.from(this.add(a))
- },
- createItem: function(a) {
- return Ext.create(a.xclass || "sprite." + a.type, a)
- },
- getBBox: function(f, b) {
- var f = Ext.Array.from(f),
- c = Infinity,
- h = -Infinity,
- g = Infinity,
- a = -Infinity,
- j, k, d, e;
- for (d = 0, e = f.length; d < e; d++) {
- j = f[d];
- k = j.getBBox(b);
- if (c > k.x) {
- c = k.x
- }
- if (h < k.x + k.width) {
- h = k.x + k.width
- }
- if (g > k.y) {
- g = k.y
- }
- if (a < k.y + k.height) {
- a = k.y + k.height
- }
- }
- return {
- x: c,
- y: g,
- width: h - c,
- height: a - g
- }
- },
- emptyRect: [0, 0, 0, 0],
- getEventXY: function(d) {
- var g = this,
- f = g.getInherited().rtl,
- c = d.getXY(),
- a = g.getOwnerBody(),
- i = a.getXY(),
- h = g.getRect() || g.emptyRect,
- j = [],
- b;
- if (f) {
- b = a.getWidth();
- j[0] = i[0] - c[0] - h[0] + b
- } else {
- j[0] = c[0] - i[0] - h[0]
- }
- j[1] = c[1] - i[1] - h[1];
- return j
- },
- clear: Ext.emptyFn,
- orderByZIndex: function() {
- var d = this,
- a = d.getItems(),
- e = false,
- b, c;
- if (d.getDirty()) {
- for (b = 0, c = a.length; b < c; b++) {
- if (a[b].attr.dirtyZIndex) {
- e = true;
- break
- }
- }
- if (e) {
- Ext.Array.sort(a, function(g, f) {
- return g.attr.zIndex - f.attr.zIndex
- });
- this.setDirty(true)
- }
- for (b = 0, c = a.length; b < c; b++) {
- a[b].attr.dirtyZIndex = false
- }
- }
- },
- repaint: function() {
- var a = this;
- a.repaint = Ext.emptyFn;
- Ext.defer(function() {
- delete a.repaint;
- a.element.repaint()
- }, 1)
- },
- renderFrame: function() {
- var g = this;
- if (!g.element) {
- return
- }
- if (g.dirtyPredecessorCount > 0) {
- g.isPendingRenderFrame = true;
- return
- }
- var f = g.getRect(),
- c = g.getBackground(),
- a = g.getItems(),
- e, b, d;
- if (!f) {
- return
- }
- g.orderByZIndex();
- if (g.getDirty()) {
- g.clear();
- g.clearTransform();
- if (c) {
- g.renderSprite(c)
- }
- for (b = 0, d = a.length; b < d; b++) {
- e = a[b];
- if (g.renderSprite(e) === false) {
- return
- }
- e.attr.textPositionCount = g.textPosition
- }
- g.setDirty(false)
- }
- },
- renderSprite: Ext.emptyFn,
- clearTransform: Ext.emptyFn,
- destroy: function() {
- var a = this;
- a.removeAll(true);
- a.predecessors = null;
- a.successors = null;
- a.callParent()
- }
-});
-Ext.define("Ext.draw.overrides.Surface", {
- override: "Ext.draw.Surface",
- hitTest: function(b, c) {
- var f = this,
- g = f.getItems(),
- e, d, a;
- c = c || Ext.draw.sprite.Sprite.defaultHitTestOptions;
- for (e = g.length - 1; e >= 0; e--) {
- d = g[e];
- if (d.hitTest) {
- a = d.hitTest(b, c);
- if (a) {
- return a
- }
- }
- }
- return null
- },
- hitTestEvent: function(b, a) {
- var c = this.getEventXY(b);
- return this.hitTest(c, a)
- }
-});
-Ext.define("Ext.draw.engine.SvgContext", {
- requires: ["Ext.draw.Color"],
- toSave: ["strokeOpacity", "strokeStyle", "fillOpacity", "fillStyle", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "lineDash", "lineDashOffset", "miterLimit", "shadowOffsetX", "shadowOffsetY", "shadowBlur", "shadowColor", "globalCompositeOperation", "position", "fillGradient", "strokeGradient"],
- strokeOpacity: 1,
- strokeStyle: "none",
- fillOpacity: 1,
- fillStyle: "none",
- lineDash: [],
- lineDashOffset: 0,
- globalAlpha: 1,
- lineWidth: 1,
- lineCap: "butt",
- lineJoin: "miter",
- miterLimit: 10,
- shadowOffsetX: 0,
- shadowOffsetY: 0,
- shadowBlur: 0,
- shadowColor: "none",
- globalCompositeOperation: "src",
- urlStringRe: /^url\(#([\w\-]+)\)$/,
- constructor: function(a) {
- this.surface = a;
- this.state = [];
- this.matrix = new Ext.draw.Matrix();
- this.path = null;
- this.clear()
- },
- clear: function() {
- this.group = this.surface.mainGroup;
- this.position = 0;
- this.path = null
- },
- getElement: function(a) {
- return this.surface.getSvgElement(this.group, a, this.position++)
- },
- removeElement: function(d) {
- var d = Ext.fly(d),
- h, g, b, f, a, e, c;
- if (!d) {
- return
- }
- if (d.dom.tagName === "g") {
- a = d.dom.gradients;
- for (c in a) {
- a[c].destroy()
- }
- } else {
- h = d.getAttribute("fill");
- g = d.getAttribute("stroke");
- b = h && h.match(this.urlStringRe);
- f = g && g.match(this.urlStringRe);
- if (b && b[1]) {
- e = Ext.fly(b[1]);
- if (e) {
- e.destroy()
- }
- }
- if (f && f[1]) {
- e = Ext.fly(f[1]);
- if (e) {
- e.destroy()
- }
- }
- }
- d.destroy()
- },
- save: function() {
- var c = this.toSave,
- e = {},
- d = this.getElement("g"),
- b, a;
- for (a = 0; a < c.length; a++) {
- b = c[a];
- if (b in this) {
- e[b] = this[b]
- }
- }
- this.position = 0;
- e.matrix = this.matrix.clone();
- this.state.push(e);
- this.group = d;
- return d
- },
- restore: function() {
- var d = this.toSave,
- e = this.state.pop(),
- c = this.group.dom.childNodes,
- b, a;
- while (c.length > this.position) {
- this.removeElement(c[c.length - 1])
- }
- for (a = 0; a < d.length; a++) {
- b = d[a];
- if (b in e) {
- this[b] = e[b]
- } else {
- delete this[b]
- }
- }
- this.setTransform.apply(this, e.matrix.elements);
- this.group = this.group.getParent()
- },
- transform: function(f, b, e, g, d, c) {
- if (this.path) {
- var a = Ext.draw.Matrix.fly([f, b, e, g, d, c]).inverse();
- this.path.transform(a)
- }
- this.matrix.append(f, b, e, g, d, c)
- },
- setTransform: function(e, a, d, f, c, b) {
- if (this.path) {
- this.path.transform(this.matrix)
- }
- this.matrix.reset();
- this.transform(e, a, d, f, c, b)
- },
- scale: function(a, b) {
- this.transform(a, 0, 0, b, 0, 0)
- },
- rotate: function(d) {
- var c = Math.cos(d),
- a = Math.sin(d),
- b = -Math.sin(d),
- e = Math.cos(d);
- this.transform(c, a, b, e, 0, 0)
- },
- translate: function(a, b) {
- this.transform(1, 0, 0, 1, a, b)
- },
- setGradientBBox: function(a) {
- this.bbox = a
- },
- beginPath: function() {
- this.path = new Ext.draw.Path()
- },
- moveTo: function(a, b) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.moveTo(a, b);
- this.path.element = null
- },
- lineTo: function(a, b) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.lineTo(a, b);
- this.path.element = null
- },
- rect: function(b, d, c, a) {
- this.moveTo(b, d);
- this.lineTo(b + c, d);
- this.lineTo(b + c, d + a);
- this.lineTo(b, d + a);
- this.closePath()
- },
- strokeRect: function(b, d, c, a) {
- this.beginPath();
- this.rect(b, d, c, a);
- this.stroke()
- },
- fillRect: function(b, d, c, a) {
- this.beginPath();
- this.rect(b, d, c, a);
- this.fill()
- },
- closePath: function() {
- if (!this.path) {
- this.beginPath()
- }
- this.path.closePath();
- this.path.element = null
- },
- arcSvg: function(d, a, f, g, c, b, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arcSvg(d, a, f, g, c, b, e);
- this.path.element = null
- },
- arc: function(b, f, a, d, c, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arc(b, f, a, d, c, e);
- this.path.element = null
- },
- ellipse: function(a, h, g, f, d, c, b, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.ellipse(a, h, g, f, d, c, b, e);
- this.path.element = null
- },
- arcTo: function(b, e, a, d, g, f, c) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arcTo(b, e, a, d, g, f, c);
- this.path.element = null
- },
- bezierCurveTo: function(d, f, b, e, a, c) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.bezierCurveTo(d, f, b, e, a, c);
- this.path.element = null
- },
- strokeText: function(d, a, e) {
- d = String(d);
- if (this.strokeStyle) {
- var b = this.getElement("text"),
- c = this.surface.getSvgElement(b, "tspan", 0);
- this.surface.setElementAttributes(b, {
- x: a,
- y: e,
- transform: this.matrix.toSvg(),
- stroke: this.strokeStyle,
- fill: "none",
- opacity: this.globalAlpha,
- "stroke-opacity": this.strokeOpacity,
- style: "font: " + this.font,
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- });
- if (this.lineDash.length) {
- this.surface.setElementAttributes(b, {
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- })
- }
- if (c.dom.firstChild) {
- c.dom.removeChild(c.dom.firstChild)
- }
- this.surface.setElementAttributes(c, {
- "alignment-baseline": "alphabetic"
- });
- c.dom.appendChild(document.createTextNode(Ext.String.htmlDecode(d)))
- }
- },
- fillText: function(d, a, e) {
- d = String(d);
- if (this.fillStyle) {
- var b = this.getElement("text"),
- c = this.surface.getSvgElement(b, "tspan", 0);
- this.surface.setElementAttributes(b, {
- x: a,
- y: e,
- transform: this.matrix.toSvg(),
- fill: this.fillStyle,
- opacity: this.globalAlpha,
- "fill-opacity": this.fillOpacity,
- style: "font: " + this.font
- });
- if (c.dom.firstChild) {
- c.dom.removeChild(c.dom.firstChild)
- }
- this.surface.setElementAttributes(c, {
- "alignment-baseline": "alphabetic"
- });
- c.dom.appendChild(document.createTextNode(Ext.String.htmlDecode(d)))
- }
- },
- drawImage: function(c, k, i, l, e, p, n, a, g) {
- var f = this,
- d = f.getElement("image"),
- j = k,
- h = i,
- b = typeof l === "undefined" ? c.width : l,
- m = typeof e === "undefined" ? c.height : e,
- o = null;
- if (typeof g !== "undefined") {
- o = k + " " + i + " " + l + " " + e;
- j = p;
- h = n;
- b = a;
- m = g
- }
- d.dom.setAttributeNS("http://www.w3.org/1999/xlink", "href", c.src);
- f.surface.setElementAttributes(d, {
- viewBox: o,
- x: j,
- y: h,
- width: b,
- height: m,
- opacity: f.globalAlpha,
- transform: f.matrix.toSvg()
- })
- },
- fill: function() {
- if (!this.path) {
- return
- }
- if (this.fillStyle) {
- var c, a = this.fillGradient,
- d = this.bbox,
- b = this.path.element;
- if (!b) {
- c = this.path.toString();
- b = this.path.element = this.getElement("path");
- this.surface.setElementAttributes(b, {
- d: c,
- transform: this.matrix.toSvg()
- })
- }
- this.surface.setElementAttributes(b, {
- fill: a && d ? a.generateGradient(this, d) : this.fillStyle,
- "fill-opacity": this.fillOpacity * this.globalAlpha
- })
- }
- },
- stroke: function() {
- if (!this.path) {
- return
- }
- if (this.strokeStyle) {
- var c, b = this.strokeGradient,
- d = this.bbox,
- a = this.path.element;
- if (!a || !this.path.svgString) {
- c = this.path.toString();
- if (!c) {
- return
- }
- a = this.path.element = this.getElement("path");
- this.surface.setElementAttributes(a, {
- fill: "none",
- d: c,
- transform: this.matrix.toSvg()
- })
- }
- this.surface.setElementAttributes(a, {
- stroke: b && d ? b.generateGradient(this, d) : this.strokeStyle,
- "stroke-linecap": this.lineCap,
- "stroke-linejoin": this.lineJoin,
- "stroke-width": this.lineWidth,
- "stroke-opacity": this.strokeOpacity * this.globalAlpha,
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- });
- if (this.lineDash.length) {
- this.surface.setElementAttributes(a, {
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- })
- }
- }
- },
- fillStroke: function(a, e) {
- var b = this,
- d = b.fillStyle,
- g = b.strokeStyle,
- c = b.fillOpacity,
- f = b.strokeOpacity;
- if (e === undefined) {
- e = a.transformFillStroke
- }
- if (!e) {
- a.inverseMatrix.toContext(b)
- }
- if (d && c !== 0) {
- b.fill()
- }
- if (g && f !== 0) {
- b.stroke()
- }
- },
- appendPath: function(a) {
- this.path = a.clone()
- },
- setLineDash: function(a) {
- this.lineDash = a
- },
- getLineDash: function() {
- return this.lineDash
- },
- createLinearGradient: function(d, g, b, e) {
- var f = this,
- c = f.surface.getNextDef("linearGradient"),
- a = f.group.dom.gradients || (f.group.dom.gradients = {}),
- h;
- f.surface.setElementAttributes(c, {
- x1: d,
- y1: g,
- x2: b,
- y2: e,
- gradientUnits: "userSpaceOnUse"
- });
- h = new Ext.draw.engine.SvgContext.Gradient(f, f.surface, c);
- a[c.dom.id] = h;
- return h
- },
- createRadialGradient: function(b, j, d, a, i, c) {
- var g = this,
- e = g.surface.getNextDef("radialGradient"),
- f = g.group.dom.gradients || (g.group.dom.gradients = {}),
- h;
- g.surface.setElementAttributes(e, {
- fx: b,
- fy: j,
- cx: a,
- cy: i,
- r: c,
- gradientUnits: "userSpaceOnUse"
- });
- h = new Ext.draw.engine.SvgContext.Gradient(g, g.surface, e, d / c);
- f[e.dom.id] = h;
- return h
- }
-});
-Ext.define("Ext.draw.engine.SvgContext.Gradient", {
- statics: {
- map: {}
- },
- constructor: function(c, a, d, b) {
- var f = this.statics().map,
- e;
- e = f[d.dom.id];
- if (e) {
- e.element = null
- }
- f[d.dom.id] = this;
- this.ctx = c;
- this.surface = a;
- this.element = d;
- this.position = 0;
- this.compression = b || 0
- },
- addColorStop: function(d, b) {
- var c = this.surface.getSvgElement(this.element, "stop", this.position++),
- a = this.compression;
- this.surface.setElementAttributes(c, {
- offset: (((1 - a) * d + a) * 100).toFixed(2) + "%",
- "stop-color": b,
- "stop-opacity": Ext.draw.Color.fly(b).a.toFixed(15)
- })
- },
- toString: function() {
- var a = this.element.dom.childNodes;
- while (a.length > this.position) {
- Ext.fly(a[a.length - 1]).destroy()
- }
- return "url(#" + this.element.getId() + ")"
- },
- destroy: function() {
- var b = this.statics().map,
- a = this.element;
- if (a && a.dom) {
- delete b[a.dom.id];
- a.destroy()
- }
- this.callParent()
- }
-});
-Ext.define("Ext.draw.engine.Svg", {
- extend: "Ext.draw.Surface",
- requires: ["Ext.draw.engine.SvgContext"],
- statics: {
- BBoxTextCache: {}
- },
- config: {
- highPrecision: false
- },
- getElementConfig: function() {
- return {
- reference: "element",
- style: {
- position: "absolute"
- },
- children: [{
- reference: "innerElement",
- style: {
- width: "100%",
- height: "100%",
- position: "relative"
- },
- children: [{
- tag: "svg",
- reference: "svgElement",
- namespace: "http://www.w3.org/2000/svg",
- width: "100%",
- height: "100%",
- version: 1.1
- }]
- }]
- }
- },
- constructor: function(a) {
- var b = this;
- b.callParent([a]);
- b.mainGroup = b.createSvgNode("g");
- b.defElement = b.createSvgNode("defs");
- b.svgElement.appendChild(b.mainGroup);
- b.svgElement.appendChild(b.defElement);
- b.ctx = new Ext.draw.engine.SvgContext(b)
- },
- createSvgNode: function(a) {
- var b = document.createElementNS("http://www.w3.org/2000/svg", a);
- return Ext.get(b)
- },
- getSvgElement: function(d, b, a) {
- var c;
- if (d.dom.childNodes.length > a) {
- c = d.dom.childNodes[a];
- if (c.tagName === b) {
- return Ext.get(c)
- } else {
- Ext.destroy(c)
- }
- }
- c = Ext.get(this.createSvgNode(b));
- if (a === 0) {
- d.insertFirst(c)
- } else {
- c.insertAfter(Ext.fly(d.dom.childNodes[a - 1]))
- }
- c.cache = {};
- return c
- },
- setElementAttributes: function(d, b) {
- var f = d.dom,
- a = d.cache,
- c, e;
- for (c in b) {
- e = b[c];
- if (a[c] !== e) {
- a[c] = e;
- f.setAttribute(c, e)
- }
- }
- },
- getNextDef: function(a) {
- return this.getSvgElement(this.defElement, a, this.defPosition++)
- },
- clearTransform: function() {
- var a = this;
- a.mainGroup.set({
- transform: a.matrix.toSvg()
- })
- },
- clear: function() {
- this.ctx.clear();
- this.defPosition = 0
- },
- renderSprite: function(b) {
- var d = this,
- c = d.getRect(),
- a = d.ctx;
- if (b.attr.hidden || b.attr.globalAlpha === 0) {
- a.save();
- a.restore();
- return
- }
- b.element = a.save();
- b.preRender(this);
- b.useAttributes(a, c);
- if (false === b.render(this, a, [0, 0, c[2], c[3]])) {
- return false
- }
- b.setDirty(false);
- a.restore()
- },
- flatten: function(e, b) {
- var c = '',
- f = Ext.getClassName(this),
- a, g, d;
- c += '';
- for (d = 0; d < b.length; d++) {
- a = b[d];
- if (Ext.getClassName(a) !== f) {
- continue
- }
- g = a.getRect();
- c += '';
- c += this.serializeNode(a.svgElement.dom);
- c += " "
- }
- c += " ";
- return {
- data: "data:image/svg+xml;utf8," + encodeURIComponent(c),
- type: "svg"
- }
- },
- serializeNode: function(d) {
- var b = "",
- c, f, a, e;
- if (d.nodeType === document.TEXT_NODE) {
- return d.nodeValue
- }
- b += "<" + d.nodeName;
- if (d.attributes.length) {
- for (c = 0, f = d.attributes.length; c < f; c++) {
- a = d.attributes[c];
- b += " " + a.name + '="' + a.value + '"'
- }
- }
- b += ">";
- if (d.childNodes && d.childNodes.length) {
- for (c = 0, f = d.childNodes.length; c < f; c++) {
- e = d.childNodes[c];
- b += this.serializeNode(e)
- }
- }
- b += "" + d.nodeName + ">";
- return b
- },
- destroy: function() {
- var a = this;
- a.ctx.destroy();
- a.mainGroup.destroy();
- delete a.mainGroup;
- delete a.ctx;
- a.callParent()
- },
- remove: function(a, b) {
- if (a && a.element) {
- if (this.ctx) {
- this.ctx.removeElement(a.element)
- } else {
- a.element.destroy()
- }
- a.element = null
- }
- this.callParent(arguments)
- }
-});
-Ext.draw || (Ext.draw = {});
-Ext.draw.engine || (Ext.draw.engine = {});
-Ext.draw.engine.excanvas = true;
-if (!document.createElement("canvas").getContext) {
- (function() {
- var ab = Math;
- var n = ab.round;
- var l = ab.sin;
- var A = ab.cos;
- var H = ab.abs;
- var N = ab.sqrt;
- var d = 10;
- var f = d / 2;
- var z = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];
-
- function y() {
- return this.context_ || (this.context_ = new D(this))
- }
- var t = Array.prototype.slice;
-
- function g(j, m, p) {
- var i = t.call(arguments, 2);
- return function() {
- return j.apply(m, i.concat(t.call(arguments)))
- }
- }
-
- function af(i) {
- return String(i).replace(/&/g, "&").replace(/"/g, """)
- }
-
- function Y(m, j, i) {
- Ext.onReady(function() {
- if (!m.namespaces[j]) {
- m.namespaces.add(j, i, "#default#VML")
- }
- })
- }
-
- function R(j) {
- Y(j, "g_vml_", "urn:schemas-microsoft-com:vml");
- Y(j, "g_o_", "urn:schemas-microsoft-com:office:office");
- if (!j.styleSheets.ex_canvas_) {
- var i = j.createStyleSheet();
- i.owningElement.id = "ex_canvas_";
- i.cssText = "canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"
- }
- }
- R(document);
- var e = {
- init: function(i) {
- var j = i || document;
- j.createElement("canvas");
- j.attachEvent("onreadystatechange", g(this.init_, this, j))
- },
- init_: function(p) {
- var m = p.getElementsByTagName("canvas");
- for (var j = 0; j < m.length; j++) {
- this.initElement(m[j])
- }
- },
- initElement: function(j) {
- if (!j.getContext) {
- j.getContext = y;
- R(j.ownerDocument);
- j.innerHTML = "";
- j.attachEvent("onpropertychange", x);
- j.attachEvent("onresize", W);
- var i = j.attributes;
- if (i.width && i.width.specified) {
- j.style.width = i.width.nodeValue + "px"
- } else {
- j.width = j.clientWidth
- }
- if (i.height && i.height.specified) {
- j.style.height = i.height.nodeValue + "px"
- } else {
- j.height = j.clientHeight
- }
- }
- return j
- }
- };
-
- function x(j) {
- var i = j.srcElement;
- switch (j.propertyName) {
- case "width":
- i.getContext().clearRect();
- i.style.width = i.attributes.width.nodeValue + "px";
- i.firstChild.style.width = i.clientWidth + "px";
- break;
- case "height":
- i.getContext().clearRect();
- i.style.height = i.attributes.height.nodeValue + "px";
- i.firstChild.style.height = i.clientHeight + "px";
- break
- }
- }
-
- function W(j) {
- var i = j.srcElement;
- if (i.firstChild) {
- i.firstChild.style.width = i.clientWidth + "px";
- i.firstChild.style.height = i.clientHeight + "px"
- }
- }
- e.init();
- var k = [];
- for (var ae = 0; ae < 16; ae++) {
- for (var ad = 0; ad < 16; ad++) {
- k[ae * 16 + ad] = ae.toString(16) + ad.toString(16)
- }
- }
-
- function B() {
- return [
- [1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]
- ]
- }
-
- function J(p, m) {
- var j = B();
- for (var i = 0; i < 3; i++) {
- for (var ah = 0; ah < 3; ah++) {
- var Z = 0;
- for (var ag = 0; ag < 3; ag++) {
- Z += p[i][ag] * m[ag][ah]
- }
- j[i][ah] = Z
- }
- }
- return j
- }
-
- function v(j, i) {
- i.fillStyle = j.fillStyle;
- i.lineCap = j.lineCap;
- i.lineJoin = j.lineJoin;
- i.lineDash = j.lineDash;
- i.lineWidth = j.lineWidth;
- i.miterLimit = j.miterLimit;
- i.shadowBlur = j.shadowBlur;
- i.shadowColor = j.shadowColor;
- i.shadowOffsetX = j.shadowOffsetX;
- i.shadowOffsetY = j.shadowOffsetY;
- i.strokeStyle = j.strokeStyle;
- i.globalAlpha = j.globalAlpha;
- i.font = j.font;
- i.textAlign = j.textAlign;
- i.textBaseline = j.textBaseline;
- i.arcScaleX_ = j.arcScaleX_;
- i.arcScaleY_ = j.arcScaleY_;
- i.lineScale_ = j.lineScale_
- }
- var b = {
- aliceblue: "#F0F8FF",
- antiquewhite: "#FAEBD7",
- aquamarine: "#7FFFD4",
- azure: "#F0FFFF",
- beige: "#F5F5DC",
- bisque: "#FFE4C4",
- black: "#000000",
- blanchedalmond: "#FFEBCD",
- blueviolet: "#8A2BE2",
- brown: "#A52A2A",
- burlywood: "#DEB887",
- cadetblue: "#5F9EA0",
- chartreuse: "#7FFF00",
- chocolate: "#D2691E",
- coral: "#FF7F50",
- cornflowerblue: "#6495ED",
- cornsilk: "#FFF8DC",
- crimson: "#DC143C",
- cyan: "#00FFFF",
- darkblue: "#00008B",
- darkcyan: "#008B8B",
- darkgoldenrod: "#B8860B",
- darkgray: "#A9A9A9",
- darkgreen: "#006400",
- darkgrey: "#A9A9A9",
- darkkhaki: "#BDB76B",
- darkmagenta: "#8B008B",
- darkolivegreen: "#556B2F",
- darkorange: "#FF8C00",
- darkorchid: "#9932CC",
- darkred: "#8B0000",
- darksalmon: "#E9967A",
- darkseagreen: "#8FBC8F",
- darkslateblue: "#483D8B",
- darkslategray: "#2F4F4F",
- darkslategrey: "#2F4F4F",
- darkturquoise: "#00CED1",
- darkviolet: "#9400D3",
- deeppink: "#FF1493",
- deepskyblue: "#00BFFF",
- dimgray: "#696969",
- dimgrey: "#696969",
- dodgerblue: "#1E90FF",
- firebrick: "#B22222",
- floralwhite: "#FFFAF0",
- forestgreen: "#228B22",
- gainsboro: "#DCDCDC",
- ghostwhite: "#F8F8FF",
- gold: "#FFD700",
- goldenrod: "#DAA520",
- grey: "#808080",
- greenyellow: "#ADFF2F",
- honeydew: "#F0FFF0",
- hotpink: "#FF69B4",
- indianred: "#CD5C5C",
- indigo: "#4B0082",
- ivory: "#FFFFF0",
- khaki: "#F0E68C",
- lavender: "#E6E6FA",
- lavenderblush: "#FFF0F5",
- lawngreen: "#7CFC00",
- lemonchiffon: "#FFFACD",
- lightblue: "#ADD8E6",
- lightcoral: "#F08080",
- lightcyan: "#E0FFFF",
- lightgoldenrodyellow: "#FAFAD2",
- lightgreen: "#90EE90",
- lightgrey: "#D3D3D3",
- lightpink: "#FFB6C1",
- lightsalmon: "#FFA07A",
- lightseagreen: "#20B2AA",
- lightskyblue: "#87CEFA",
- lightslategray: "#778899",
- lightslategrey: "#778899",
- lightsteelblue: "#B0C4DE",
- lightyellow: "#FFFFE0",
- limegreen: "#32CD32",
- linen: "#FAF0E6",
- magenta: "#FF00FF",
- mediumaquamarine: "#66CDAA",
- mediumblue: "#0000CD",
- mediumorchid: "#BA55D3",
- mediumpurple: "#9370DB",
- mediumseagreen: "#3CB371",
- mediumslateblue: "#7B68EE",
- mediumspringgreen: "#00FA9A",
- mediumturquoise: "#48D1CC",
- mediumvioletred: "#C71585",
- midnightblue: "#191970",
- mintcream: "#F5FFFA",
- mistyrose: "#FFE4E1",
- moccasin: "#FFE4B5",
- navajowhite: "#FFDEAD",
- oldlace: "#FDF5E6",
- olivedrab: "#6B8E23",
- orange: "#FFA500",
- orangered: "#FF4500",
- orchid: "#DA70D6",
- palegoldenrod: "#EEE8AA",
- palegreen: "#98FB98",
- paleturquoise: "#AFEEEE",
- palevioletred: "#DB7093",
- papayawhip: "#FFEFD5",
- peachpuff: "#FFDAB9",
- peru: "#CD853F",
- pink: "#FFC0CB",
- plum: "#DDA0DD",
- powderblue: "#B0E0E6",
- rosybrown: "#BC8F8F",
- royalblue: "#4169E1",
- saddlebrown: "#8B4513",
- salmon: "#FA8072",
- sandybrown: "#F4A460",
- seagreen: "#2E8B57",
- seashell: "#FFF5EE",
- sienna: "#A0522D",
- skyblue: "#87CEEB",
- slateblue: "#6A5ACD",
- slategray: "#708090",
- slategrey: "#708090",
- snow: "#FFFAFA",
- springgreen: "#00FF7F",
- steelblue: "#4682B4",
- tan: "#D2B48C",
- thistle: "#D8BFD8",
- tomato: "#FF6347",
- turquoise: "#40E0D0",
- violet: "#EE82EE",
- wheat: "#F5DEB3",
- whitesmoke: "#F5F5F5",
- yellowgreen: "#9ACD32"
- };
-
- function M(j) {
- var p = j.indexOf("(", 3);
- var i = j.indexOf(")", p + 1);
- var m = j.substring(p + 1, i).split(",");
- if (m.length != 4 || j.charAt(3) != "a") {
- m[3] = 1
- }
- return m
- }
-
- function c(i) {
- return parseFloat(i) / 100
- }
-
- function r(j, m, i) {
- return Math.min(i, Math.max(m, j))
- }
-
- function I(ag) {
- var i, ai, aj, ah, ak, Z;
- ah = parseFloat(ag[0]) / 360 % 360;
- if (ah < 0) {
- ah++
- }
- ak = r(c(ag[1]), 0, 1);
- Z = r(c(ag[2]), 0, 1);
- if (ak == 0) {
- i = ai = aj = Z
- } else {
- var j = Z < 0.5 ? Z * (1 + ak) : Z + ak - Z * ak;
- var m = 2 * Z - j;
- i = a(m, j, ah + 1 / 3);
- ai = a(m, j, ah);
- aj = a(m, j, ah - 1 / 3)
- }
- return "#" + k[Math.floor(i * 255)] + k[Math.floor(ai * 255)] + k[Math.floor(aj * 255)]
- }
-
- function a(j, i, m) {
- if (m < 0) {
- m++
- }
- if (m > 1) {
- m--
- }
- if (6 * m < 1) {
- return j + (i - j) * 6 * m
- } else {
- if (2 * m < 1) {
- return i
- } else {
- if (3 * m < 2) {
- return j + (i - j) * (2 / 3 - m) * 6
- } else {
- return j
- }
- }
- }
- }
- var C = {};
-
- function F(j) {
- if (j in C) {
- return C[j]
- }
- var ag, Z = 1;
- j = String(j);
- if (j.charAt(0) == "#") {
- ag = j
- } else {
- if (/^rgb/.test(j)) {
- var p = M(j);
- var ag = "#",
- ah;
- for (var m = 0; m < 3; m++) {
- if (p[m].indexOf("%") != -1) {
- ah = Math.floor(c(p[m]) * 255)
- } else {
- ah = +p[m]
- }
- ag += k[r(ah, 0, 255)]
- }
- Z = +p[3]
- } else {
- if (/^hsl/.test(j)) {
- var p = M(j);
- ag = I(p);
- Z = p[3]
- } else {
- ag = b[j] || j
- }
- }
- }
- return C[j] = {
- color: ag,
- alpha: Z
- }
- }
- var o = {
- style: "normal",
- variant: "normal",
- weight: "normal",
- size: 10,
- family: "sans-serif"
- };
- var L = {};
-
- function E(i) {
- if (L[i]) {
- return L[i]
- }
- var p = document.createElement("div");
- var m = p.style;
- try {
- m.font = i
- } catch (j) {}
- return L[i] = {
- style: m.fontStyle || o.style,
- variant: m.fontVariant || o.variant,
- weight: m.fontWeight || o.weight,
- size: m.fontSize || o.size,
- family: m.fontFamily || o.family
- }
- }
-
- function u(m, j) {
- var i = {};
- for (var ah in m) {
- i[ah] = m[ah]
- }
- var ag = parseFloat(j.currentStyle.fontSize),
- Z = parseFloat(m.size);
- if (typeof m.size == "number") {
- i.size = m.size
- } else {
- if (m.size.indexOf("px") != -1) {
- i.size = Z
- } else {
- if (m.size.indexOf("em") != -1) {
- i.size = ag * Z
- } else {
- if (m.size.indexOf("%") != -1) {
- i.size = (ag / 100) * Z
- } else {
- if (m.size.indexOf("pt") != -1) {
- i.size = Z / 0.75
- } else {
- i.size = ag
- }
- }
- }
- }
- }
- i.size *= 0.981;
- return i
- }
-
- function ac(i) {
- return i.style + " " + i.variant + " " + i.weight + " " + i.size + "px " + i.family
- }
- var s = {
- butt: "flat",
- round: "round"
- };
-
- function S(i) {
- return s[i] || "square"
- }
-
- function D(i) {
- this.m_ = B();
- this.mStack_ = [];
- this.aStack_ = [];
- this.currentPath_ = [];
- this.strokeStyle = "#000";
- this.fillStyle = "#000";
- this.lineWidth = 1;
- this.lineJoin = "miter";
- this.lineDash = [];
- this.lineCap = "butt";
- this.miterLimit = d * 1;
- this.globalAlpha = 1;
- this.font = "10px sans-serif";
- this.textAlign = "left";
- this.textBaseline = "alphabetic";
- this.canvas = i;
- var m = "width:" + i.clientWidth + "px;height:" + i.clientHeight + "px;overflow:hidden;position:absolute";
- var j = i.ownerDocument.createElement("div");
- j.style.cssText = m;
- i.appendChild(j);
- var p = j.cloneNode(false);
- p.style.backgroundColor = "red";
- p.style.filter = "alpha(opacity=0)";
- i.appendChild(p);
- this.element_ = j;
- this.arcScaleX_ = 1;
- this.arcScaleY_ = 1;
- this.lineScale_ = 1
- }
- var q = D.prototype;
- q.clearRect = function() {
- if (this.textMeasureEl_) {
- this.textMeasureEl_.removeNode(true);
- this.textMeasureEl_ = null
- }
- this.element_.innerHTML = ""
- };
- q.beginPath = function() {
- this.currentPath_ = []
- };
- q.moveTo = function(j, i) {
- var m = V(this, j, i);
- this.currentPath_.push({
- type: "moveTo",
- x: m.x,
- y: m.y
- });
- this.currentX_ = m.x;
- this.currentY_ = m.y
- };
- q.lineTo = function(j, i) {
- var m = V(this, j, i);
- this.currentPath_.push({
- type: "lineTo",
- x: m.x,
- y: m.y
- });
- this.currentX_ = m.x;
- this.currentY_ = m.y
- };
- q.bezierCurveTo = function(m, j, ak, aj, ai, ag) {
- var i = V(this, ai, ag);
- var ah = V(this, m, j);
- var Z = V(this, ak, aj);
- K(this, ah, Z, i)
- };
-
- function K(i, Z, m, j) {
- i.currentPath_.push({
- type: "bezierCurveTo",
- cp1x: Z.x,
- cp1y: Z.y,
- cp2x: m.x,
- cp2y: m.y,
- x: j.x,
- y: j.y
- });
- i.currentX_ = j.x;
- i.currentY_ = j.y
- }
- q.quadraticCurveTo = function(ai, m, j, i) {
- var ah = V(this, ai, m);
- var ag = V(this, j, i);
- var aj = {
- x: this.currentX_ + 2 / 3 * (ah.x - this.currentX_),
- y: this.currentY_ + 2 / 3 * (ah.y - this.currentY_)
- };
- var Z = {
- x: aj.x + (ag.x - this.currentX_) / 3,
- y: aj.y + (ag.y - this.currentY_) / 3
- };
- K(this, aj, Z, ag)
- };
- q.arc = function(al, aj, ak, ag, j, m) {
- ak *= d;
- var ap = m ? "at" : "wa";
- var am = al + A(ag) * ak - f;
- var ao = aj + l(ag) * ak - f;
- var i = al + A(j) * ak - f;
- var an = aj + l(j) * ak - f;
- if (am == i && !m) {
- am += 0.125
- }
- var Z = V(this, al, aj);
- var ai = V(this, am, ao);
- var ah = V(this, i, an);
- this.currentPath_.push({
- type: ap,
- x: Z.x,
- y: Z.y,
- radius: ak,
- xStart: ai.x,
- yStart: ai.y,
- xEnd: ah.x,
- yEnd: ah.y
- })
- };
- q.rect = function(m, j, i, p) {
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath()
- };
- q.strokeRect = function(m, j, i, p) {
- var Z = this.currentPath_;
- this.beginPath();
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath();
- this.stroke();
- this.currentPath_ = Z
- };
- q.fillRect = function(m, j, i, p) {
- var Z = this.currentPath_;
- this.beginPath();
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath();
- this.fill();
- this.currentPath_ = Z
- };
- q.createLinearGradient = function(j, p, i, m) {
- var Z = new U("gradient");
- Z.x0_ = j;
- Z.y0_ = p;
- Z.x1_ = i;
- Z.y1_ = m;
- return Z
- };
- q.createRadialGradient = function(p, ag, m, j, Z, i) {
- var ah = new U("gradientradial");
- ah.x0_ = p;
- ah.y0_ = ag;
- ah.r0_ = m;
- ah.x1_ = j;
- ah.y1_ = Z;
- ah.r1_ = i;
- return ah
- };
- q.drawImage = function(an, j) {
- var ah, Z, aj, ar, al, ak, ao, av;
- var ai = an.runtimeStyle.width;
- var am = an.runtimeStyle.height;
- an.runtimeStyle.width = "auto";
- an.runtimeStyle.height = "auto";
- var ag = an.width;
- var aq = an.height;
- an.runtimeStyle.width = ai;
- an.runtimeStyle.height = am;
- if (arguments.length == 3) {
- ah = arguments[1];
- Z = arguments[2];
- al = ak = 0;
- ao = aj = ag;
- av = ar = aq
- } else {
- if (arguments.length == 5) {
- ah = arguments[1];
- Z = arguments[2];
- aj = arguments[3];
- ar = arguments[4];
- al = ak = 0;
- ao = ag;
- av = aq
- } else {
- if (arguments.length == 9) {
- al = arguments[1];
- ak = arguments[2];
- ao = arguments[3];
- av = arguments[4];
- ah = arguments[5];
- Z = arguments[6];
- aj = arguments[7];
- ar = arguments[8]
- } else {
- throw Error("Invalid number of arguments")
- }
- }
- }
- var au = V(this, ah, Z);
- var at = [];
- var i = 10;
- var p = 10;
- var ap = this.m_;
- at.push(" ', ' ", " ");
- this.element_.insertAdjacentHTML("BeforeEnd", at.join(""))
- };
- q.setLineDash = function(i) {
- if (i.length === 1) {
- i = i.slice();
- i[1] = i[0]
- }
- this.lineDash = i
- };
- q.getLineDash = function() {
- return this.lineDash
- };
- q.stroke = function(ak) {
- var ai = [];
- var m = 10;
- var al = 10;
- ai.push(" aj.x) {
- aj.x = j.x
- }
- if (Z.y == null || j.y < Z.y) {
- Z.y = j.y
- }
- if (aj.y == null || j.y > aj.y) {
- aj.y = j.y
- }
- }
- }
- ai.push(' ">');
- if (!ak) {
- w(this, ai)
- } else {
- G(this, ai, Z, aj)
- }
- ai.push(" ");
- this.element_.insertAdjacentHTML("beforeEnd", ai.join(""))
- };
-
- function w(m, ag) {
- var j = F(m.strokeStyle);
- var p = j.color;
- var Z = j.alpha * m.globalAlpha;
- var i = m.lineScale_ * m.lineWidth;
- if (i < 1) {
- Z *= i
- }
- ag.push(" ')
- }
-
- function G(aq, ai, aK, ar) {
- var aj = aq.fillStyle;
- var aB = aq.arcScaleX_;
- var aA = aq.arcScaleY_;
- var j = ar.x - aK.x;
- var p = ar.y - aK.y;
- if (aj instanceof U) {
- var an = 0;
- var aF = {
- x: 0,
- y: 0
- };
- var ax = 0;
- var am = 1;
- if (aj.type_ == "gradient") {
- var al = aj.x0_ / aB;
- var m = aj.y0_ / aA;
- var ak = aj.x1_ / aB;
- var aM = aj.y1_ / aA;
- var aJ = V(aq, al, m);
- var aI = V(aq, ak, aM);
- var ag = aI.x - aJ.x;
- var Z = aI.y - aJ.y;
- an = Math.atan2(ag, Z) * 180 / Math.PI;
- if (an < 0) {
- an += 360
- }
- if (an < 0.000001) {
- an = 0
- }
- } else {
- var aJ = V(aq, aj.x0_, aj.y0_);
- aF = {
- x: (aJ.x - aK.x) / j,
- y: (aJ.y - aK.y) / p
- };
- j /= aB * d;
- p /= aA * d;
- var aD = ab.max(j, p);
- ax = 2 * aj.r0_ / aD;
- am = 2 * aj.r1_ / aD - ax
- }
- var av = aj.colors_;
- av.sort(function(aN, i) {
- return aN.offset - i.offset
- });
- var ap = av.length;
- var au = av[0].color;
- var at = av[ap - 1].color;
- var az = av[0].alpha * aq.globalAlpha;
- var ay = av[ap - 1].alpha * aq.globalAlpha;
- var aE = [];
- for (var aH = 0; aH < ap; aH++) {
- var ao = av[aH];
- aE.push(ao.offset * am + ax + " " + ao.color)
- }
- ai.push(' ')
- } else {
- if (aj instanceof T) {
- if (j && p) {
- var ah = -aK.x;
- var aC = -aK.y;
- ai.push(" ')
- }
- } else {
- var aL = F(aq.fillStyle);
- var aw = aL.color;
- var aG = aL.alpha * aq.globalAlpha;
- ai.push(' ')
- }
- }
- }
- q.fill = function() {
- this.$stroke(true)
- };
- q.closePath = function() {
- this.currentPath_.push({
- type: "close"
- })
- };
-
- function V(j, Z, p) {
- var i = j.m_;
- return {
- x: d * (Z * i[0][0] + p * i[1][0] + i[2][0]) - f,
- y: d * (Z * i[0][1] + p * i[1][1] + i[2][1]) - f
- }
- }
- q.save = function() {
- var i = {};
- v(this, i);
- this.aStack_.push(i);
- this.mStack_.push(this.m_);
- this.m_ = J(B(), this.m_)
- };
- q.restore = function() {
- if (this.aStack_.length) {
- v(this.aStack_.pop(), this);
- this.m_ = this.mStack_.pop()
- }
- };
-
- function h(i) {
- return isFinite(i[0][0]) && isFinite(i[0][1]) && isFinite(i[1][0]) && isFinite(i[1][1]) && isFinite(i[2][0]) && isFinite(i[2][1])
- }
-
- function aa(j, i, p) {
- if (!h(i)) {
- return
- }
- j.m_ = i;
- if (p) {
- var Z = i[0][0] * i[1][1] - i[0][1] * i[1][0];
- j.lineScale_ = N(H(Z))
- }
- }
- q.translate = function(m, j) {
- var i = [
- [1, 0, 0],
- [0, 1, 0],
- [m, j, 1]
- ];
- aa(this, J(i, this.m_), false)
- };
- q.rotate = function(j) {
- var p = A(j);
- var m = l(j);
- var i = [
- [p, m, 0],
- [-m, p, 0],
- [0, 0, 1]
- ];
- aa(this, J(i, this.m_), false)
- };
- q.scale = function(m, j) {
- this.arcScaleX_ *= m;
- this.arcScaleY_ *= j;
- var i = [
- [m, 0, 0],
- [0, j, 0],
- [0, 0, 1]
- ];
- aa(this, J(i, this.m_), true)
- };
- q.transform = function(Z, p, ah, ag, j, i) {
- var m = [
- [Z, p, 0],
- [ah, ag, 0],
- [j, i, 1]
- ];
- aa(this, J(m, this.m_), true)
- };
- q.setTransform = function(ag, Z, ai, ah, p, j) {
- var i = [
- [ag, Z, 0],
- [ai, ah, 0],
- [p, j, 1]
- ];
- aa(this, i, true)
- };
- q.drawText_ = function(am, ak, aj, ap, ai) {
- var ao = this.m_,
- at = 1000,
- j = 0,
- ar = at,
- ah = {
- x: 0,
- y: 0
- },
- ag = [];
- var i = u(E(this.font), this.element_);
- var p = ac(i);
- var au = this.element_.currentStyle;
- var Z = this.textAlign.toLowerCase();
- switch (Z) {
- case "left":
- case "center":
- case "right":
- break;
- case "end":
- Z = au.direction == "ltr" ? "right" : "left";
- break;
- case "start":
- Z = au.direction == "rtl" ? "right" : "left";
- break;
- default:
- Z = "left"
- }
- switch (this.textBaseline) {
- case "hanging":
- case "top":
- ah.y = i.size / 1.75;
- break;
- case "middle":
- break;
- default:
- case null:
- case "alphabetic":
- case "ideographic":
- case "bottom":
- ah.y = -i.size / 3;
- break
- }
- switch (Z) {
- case "right":
- j = at;
- ar = 0.05;
- break;
- case "center":
- j = ar = at / 2;
- break
- }
- var aq = V(this, ak + ah.x, aj + ah.y);
- ag.push('');
- if (ai) {
- w(this, ag)
- } else {
- G(this, ag, {
- x: -j,
- y: 0
- }, {
- x: ar,
- y: i.size
- })
- }
- var an = ao[0][0].toFixed(3) + "," + ao[1][0].toFixed(3) + "," + ao[0][1].toFixed(3) + "," + ao[1][1].toFixed(3) + ",0,0";
- var al = n(aq.x / d) + "," + n(aq.y / d);
- ag.push(' ', ' ', ' ');
- this.element_.insertAdjacentHTML("beforeEnd", ag.join(""))
- };
- q.fillText = function(m, i, p, j) {
- this.drawText_(m, i, p, j, false)
- };
- q.strokeText = function(m, i, p, j) {
- this.drawText_(m, i, p, j, true)
- };
- q.measureText = function(m) {
- if (!this.textMeasureEl_) {
- var i = ' ';
- this.element_.insertAdjacentHTML("beforeEnd", i);
- this.textMeasureEl_ = this.element_.lastChild
- }
- var j = this.element_.ownerDocument;
- this.textMeasureEl_.innerHTML = "";
- this.textMeasureEl_.style.font = this.font;
- this.textMeasureEl_.appendChild(j.createTextNode(m));
- return {
- width: this.textMeasureEl_.offsetWidth
- }
- };
- q.clip = function() {};
- q.arcTo = function() {};
- q.createPattern = function(j, i) {
- return new T(j, i)
- };
-
- function U(i) {
- this.type_ = i;
- this.x0_ = 0;
- this.y0_ = 0;
- this.r0_ = 0;
- this.x1_ = 0;
- this.y1_ = 0;
- this.r1_ = 0;
- this.colors_ = []
- }
- U.prototype.addColorStop = function(j, i) {
- i = F(i);
- this.colors_.push({
- offset: j,
- color: i.color,
- alpha: i.alpha
- })
- };
-
- function T(j, i) {
- Q(j);
- switch (i) {
- case "repeat":
- case null:
- case "":
- this.repetition_ = "repeat";
- break;
- case "repeat-x":
- case "repeat-y":
- case "no-repeat":
- this.repetition_ = i;
- break;
- default:
- O("SYNTAX_ERR")
- }
- this.src_ = j.src;
- this.width_ = j.width;
- this.height_ = j.height
- }
-
- function O(i) {
- throw new P(i)
- }
-
- function Q(i) {
- if (!i || i.nodeType != 1 || i.tagName != "IMG") {
- O("TYPE_MISMATCH_ERR")
- }
- if (i.readyState != "complete") {
- O("INVALID_STATE_ERR")
- }
- }
-
- function P(i) {
- this.code = this[i];
- this.message = i + ": DOM Exception " + this.code
- }
- var X = P.prototype = new Error();
- X.INDEX_SIZE_ERR = 1;
- X.DOMSTRING_SIZE_ERR = 2;
- X.HIERARCHY_REQUEST_ERR = 3;
- X.WRONG_DOCUMENT_ERR = 4;
- X.INVALID_CHARACTER_ERR = 5;
- X.NO_DATA_ALLOWED_ERR = 6;
- X.NO_MODIFICATION_ALLOWED_ERR = 7;
- X.NOT_FOUND_ERR = 8;
- X.NOT_SUPPORTED_ERR = 9;
- X.INUSE_ATTRIBUTE_ERR = 10;
- X.INVALID_STATE_ERR = 11;
- X.SYNTAX_ERR = 12;
- X.INVALID_MODIFICATION_ERR = 13;
- X.NAMESPACE_ERR = 14;
- X.INVALID_ACCESS_ERR = 15;
- X.VALIDATION_ERR = 16;
- X.TYPE_MISMATCH_ERR = 17;
- G_vmlCanvasManager = e;
- CanvasRenderingContext2D = D;
- CanvasGradient = U;
- CanvasPattern = T;
- DOMException = P
- })()
-}
-Ext.define("Ext.draw.engine.Canvas", {
- extend: "Ext.draw.Surface",
- requires: ["Ext.draw.engine.excanvas", "Ext.draw.Animator", "Ext.draw.Color"],
- config: {
- highPrecision: false
- },
- statics: {
- contextOverrides: {
- setGradientBBox: function(a) {
- this.bbox = a
- },
- fill: function() {
- var c = this.fillStyle,
- a = this.fillGradient,
- b = this.fillOpacity,
- d = this.globalAlpha,
- e = this.bbox;
- if (c !== Ext.draw.Color.RGBA_NONE && b !== 0) {
- if (a && e) {
- this.fillStyle = a.generateGradient(this, e)
- }
- if (b !== 1) {
- this.globalAlpha = d * b
- }
- this.$fill();
- if (b !== 1) {
- this.globalAlpha = d
- }
- if (a && e) {
- this.fillStyle = c
- }
- }
- },
- stroke: function() {
- var e = this.strokeStyle,
- c = this.strokeGradient,
- a = this.strokeOpacity,
- b = this.globalAlpha,
- d = this.bbox;
- if (e !== Ext.draw.Color.RGBA_NONE && a !== 0) {
- if (c && d) {
- this.strokeStyle = c.generateGradient(this, d)
- }
- if (a !== 1) {
- this.globalAlpha = b * a
- }
- this.$stroke();
- if (a !== 1) {
- this.globalAlpha = b
- }
- if (c && d) {
- this.strokeStyle = e
- }
- }
- },
- fillStroke: function(d, e) {
- var j = this,
- i = this.fillStyle,
- h = this.fillOpacity,
- f = this.strokeStyle,
- c = this.strokeOpacity,
- b = j.shadowColor,
- a = j.shadowBlur,
- g = Ext.draw.Color.RGBA_NONE;
- if (e === undefined) {
- e = d.transformFillStroke
- }
- if (!e) {
- d.inverseMatrix.toContext(j)
- }
- if (i !== g && h !== 0) {
- j.fill();
- j.shadowColor = g;
- j.shadowBlur = 0
- }
- if (f !== g && c !== 0) {
- j.stroke()
- }
- j.shadowColor = b;
- j.shadowBlur = a
- },
- setLineDash: function(a) {
- if (this.$setLineDash) {
- this.$setLineDash(a)
- }
- },
- getLineDash: function() {
- if (this.$getLineDash) {
- return this.$getLineDash()
- }
- },
- ellipse: function(g, e, c, a, j, b, f, d) {
- var i = Math.cos(j),
- h = Math.sin(j);
- this.transform(i * c, h * c, -h * a, i * a, g, e);
- this.arc(0, 0, 1, b, f, d);
- this.transform(i / c, -h / a, h / c, i / a, -(i * g + h * e) / c, (h * g - i * e) / a)
- },
- appendPath: function(f) {
- var e = this,
- c = 0,
- b = 0,
- a = f.commands,
- g = f.params,
- d = a.length;
- e.beginPath();
- for (; c < d; c++) {
- switch (a[c]) {
- case "M":
- e.moveTo(g[b], g[b + 1]);
- b += 2;
- break;
- case "L":
- e.lineTo(g[b], g[b + 1]);
- b += 2;
- break;
- case "C":
- e.bezierCurveTo(g[b], g[b + 1], g[b + 2], g[b + 3], g[b + 4], g[b + 5]);
- b += 6;
- break;
- case "Z":
- e.closePath();
- break
- }
- }
- },
- save: function() {
- var c = this.toSave,
- d = c.length,
- e = d && {},
- b = 0,
- a;
- for (; b < d; b++) {
- a = c[b];
- if (a in this) {
- e[a] = this[a]
- }
- }
- this.state.push(e);
- this.$save()
- },
- restore: function() {
- var b = this.state.pop(),
- a;
- if (b) {
- for (a in b) {
- this[a] = b[a]
- }
- }
- this.$restore()
- }
- }
- },
- splitThreshold: 3000,
- toSave: ["fillGradient", "strokeGradient"],
- element: {
- reference: "element",
- style: {
- position: "absolute"
- },
- children: [{
- reference: "innerElement",
- style: {
- width: "100%",
- height: "100%",
- position: "relative"
- }
- }]
- },
- createCanvas: function() {
- var c = Ext.Element.create({
- tag: "canvas",
- cls: Ext.baseCSSPrefix + "surface-canvas"
- });
- window.G_vmlCanvasManager && G_vmlCanvasManager.initElement(c.dom);
- var d = Ext.draw.engine.Canvas.contextOverrides,
- a = c.dom.getContext("2d"),
- b;
- if (a.ellipse) {
- delete d.ellipse
- }
- a.state = [];
- a.toSave = this.toSave;
- for (b in d) {
- a["$" + b] = a[b]
- }
- Ext.apply(a, d);
- if (this.getHighPrecision()) {
- this.enablePrecisionCompensation(a)
- } else {
- this.disablePrecisionCompensation(a)
- }
- this.innerElement.appendChild(c);
- this.canvases.push(c);
- this.contexts.push(a)
- },
- updateHighPrecision: function(d) {
- var e = this.contexts,
- c = e.length,
- b, a;
- for (b = 0; b < c; b++) {
- a = e[b];
- if (d) {
- this.enablePrecisionCompensation(a)
- } else {
- this.disablePrecisionCompensation(a)
- }
- }
- },
- precisionNames: ["rect", "fillRect", "strokeRect", "clearRect", "moveTo", "lineTo", "arc", "arcTo", "save", "restore", "updatePrecisionCompensate", "setTransform", "transform", "scale", "translate", "rotate", "quadraticCurveTo", "bezierCurveTo", "createLinearGradient", "createRadialGradient", "fillText", "strokeText", "drawImage"],
- disablePrecisionCompensation: function(b) {
- var a = Ext.draw.engine.Canvas.contextOverrides,
- f = this.precisionNames,
- e = f.length,
- d, c;
- for (d = 0; d < e; d++) {
- c = f[d];
- if (!(c in a)) {
- delete b[c]
- }
- }
- this.setDirty(true)
- },
- enablePrecisionCompensation: function(j) {
- var c = this,
- a = 1,
- g = 1,
- l = 0,
- k = 0,
- i = new Ext.draw.Matrix(),
- b = [],
- e = {},
- d = Ext.draw.engine.Canvas.contextOverrides,
- h = j.constructor.prototype;
- var f = {
- toSave: c.toSave,
- rect: function(m, p, n, o) {
- return h.rect.call(this, m * a + l, p * g + k, n * a, o * g)
- },
- fillRect: function(m, p, n, o) {
- this.updatePrecisionCompensateRect();
- h.fillRect.call(this, m * a + l, p * g + k, n * a, o * g);
- this.updatePrecisionCompensate()
- },
- strokeRect: function(m, p, n, o) {
- this.updatePrecisionCompensateRect();
- h.strokeRect.call(this, m * a + l, p * g + k, n * a, o * g);
- this.updatePrecisionCompensate()
- },
- clearRect: function(m, p, n, o) {
- return h.clearRect.call(this, m * a + l, p * g + k, n * a, o * g)
- },
- moveTo: function(m, n) {
- return h.moveTo.call(this, m * a + l, n * g + k)
- },
- lineTo: function(m, n) {
- return h.lineTo.call(this, m * a + l, n * g + k)
- },
- arc: function(n, r, m, p, o, q) {
- this.updatePrecisionCompensateRect();
- h.arc.call(this, n * a + l, r * a + k, m * a, p, o, q);
- this.updatePrecisionCompensate()
- },
- arcTo: function(o, q, n, p, m) {
- this.updatePrecisionCompensateRect();
- h.arcTo.call(this, o * a + l, q * g + k, n * a + l, p * g + k, m * a);
- this.updatePrecisionCompensate()
- },
- save: function() {
- b.push(i);
- i = i.clone();
- d.save.call(this);
- h.save.call(this)
- },
- restore: function() {
- i = b.pop();
- d.restore.call(this);
- h.restore.call(this);
- this.updatePrecisionCompensate()
- },
- updatePrecisionCompensate: function() {
- i.precisionCompensate(c.devicePixelRatio, e);
- a = e.xx;
- g = e.yy;
- l = e.dx;
- k = e.dy;
- h.setTransform.call(this, c.devicePixelRatio, e.b, e.c, e.d, 0, 0)
- },
- updatePrecisionCompensateRect: function() {
- i.precisionCompensateRect(c.devicePixelRatio, e);
- a = e.xx;
- g = e.yy;
- l = e.dx;
- k = e.dy;
- h.setTransform.call(this, c.devicePixelRatio, e.b, e.c, e.d, 0, 0)
- },
- setTransform: function(q, o, n, m, r, p) {
- i.set(q, o, n, m, r, p);
- this.updatePrecisionCompensate()
- },
- transform: function(q, o, n, m, r, p) {
- i.append(q, o, n, m, r, p);
- this.updatePrecisionCompensate()
- },
- scale: function(n, m) {
- this.transform(n, 0, 0, m, 0, 0)
- },
- translate: function(n, m) {
- this.transform(1, 0, 0, 1, n, m)
- },
- rotate: function(o) {
- var n = Math.cos(o),
- m = Math.sin(o);
- this.transform(n, m, -m, n, 0, 0)
- },
- quadraticCurveTo: function(n, p, m, o) {
- h.quadraticCurveTo.call(this, n * a + l, p * g + k, m * a + l, o * g + k)
- },
- bezierCurveTo: function(r, p, o, n, m, q) {
- h.bezierCurveTo.call(this, r * a + l, p * g + k, o * a + l, n * g + k, m * a + l, q * g + k)
- },
- createLinearGradient: function(n, p, m, o) {
- this.updatePrecisionCompensateRect();
- var q = h.createLinearGradient.call(this, n * a + l, p * g + k, m * a + l, o * g + k);
- this.updatePrecisionCompensate();
- return q
- },
- createRadialGradient: function(p, r, o, n, q, m) {
- this.updatePrecisionCompensateRect();
- var s = h.createLinearGradient.call(this, p * a + l, r * a + k, o * a, n * a + l, q * a + k, m * a);
- this.updatePrecisionCompensate();
- return s
- },
- fillText: function(o, m, p, n) {
- h.setTransform.apply(this, i.elements);
- if (typeof n === "undefined") {
- h.fillText.call(this, o, m, p)
- } else {
- h.fillText.call(this, o, m, p, n)
- }
- this.updatePrecisionCompensate()
- },
- strokeText: function(o, m, p, n) {
- h.setTransform.apply(this, i.elements);
- if (typeof n === "undefined") {
- h.strokeText.call(this, o, m, p)
- } else {
- h.strokeText.call(this, o, m, p, n)
- }
- this.updatePrecisionCompensate()
- },
- fill: function() {
- var m = this.fillGradient,
- n = this.bbox;
- this.updatePrecisionCompensateRect();
- if (m && n) {
- this.fillStyle = m.generateGradient(this, n)
- }
- h.fill.call(this);
- this.updatePrecisionCompensate()
- },
- stroke: function() {
- var m = this.strokeGradient,
- n = this.bbox;
- this.updatePrecisionCompensateRect();
- if (m && n) {
- this.strokeStyle = m.generateGradient(this, n)
- }
- h.stroke.call(this);
- this.updatePrecisionCompensate()
- },
- drawImage: function(u, s, r, q, p, o, n, m, t) {
- switch (arguments.length) {
- case 3:
- return h.drawImage.call(this, u, s * a + l, r * g + k);
- case 5:
- return h.drawImage.call(this, u, s * a + l, r * g + k, q * a, p * g);
- case 9:
- return h.drawImage.call(this, u, s, r, q, p, o * a + l, n * g * k, m * a, t * g)
- }
- }
- };
- Ext.apply(j, f);
- this.setDirty(true)
- },
- updateRect: function(a) {
- this.callParent([a]);
- var C = this,
- p = Math.floor(a[0]),
- e = Math.floor(a[1]),
- g = Math.ceil(a[0] + a[2]),
- B = Math.ceil(a[1] + a[3]),
- u = C.devicePixelRatio,
- D = C.canvases,
- d = g - p,
- y = B - e,
- n = Math.round(C.splitThreshold / u),
- c = C.xSplits = Math.ceil(d / n),
- f = C.ySplits = Math.ceil(y / n),
- v, s, q, A, z, x, o, m;
- for (s = 0, z = 0; s < f; s++, z += n) {
- for (v = 0, A = 0; v < c; v++, A += n) {
- q = s * c + v;
- if (q >= D.length) {
- C.createCanvas()
- }
- x = D[q].dom;
- x.style.left = A + "px";
- x.style.top = z + "px";
- m = Math.min(n, y - z);
- if (m * u !== x.height) {
- x.height = m * u;
- x.style.height = m + "px"
- }
- o = Math.min(n, d - A);
- if (o * u !== x.width) {
- x.width = o * u;
- x.style.width = o + "px"
- }
- C.applyDefaults(C.contexts[q])
- }
- }
- for (q += 1; q < D.length; q++) {
- D[q].destroy()
- }
- C.activeCanvases = c * f;
- D.length = C.activeCanvases;
- C.clear()
- },
- clearTransform: function() {
- var f = this,
- a = f.xSplits,
- g = f.ySplits,
- d = f.contexts,
- h = f.splitThreshold,
- l = f.devicePixelRatio,
- e, c, b, m;
- for (e = 0; e < a; e++) {
- for (c = 0; c < g; c++) {
- b = c * a + e;
- m = d[b];
- m.translate(-h * e, -h * c);
- m.scale(l, l);
- f.matrix.toContext(m)
- }
- }
- },
- renderSprite: function(q) {
- var C = this,
- b = C.getRect(),
- e = C.matrix,
- g = q.getParent(),
- v = Ext.draw.Matrix.fly([1, 0, 0, 1, 0, 0]),
- p = C.splitThreshold / C.devicePixelRatio,
- c = C.xSplits,
- m = C.ySplits,
- A, z, s, a, r, o, d = 0,
- B, n = 0,
- f, l = b[2],
- y = b[3],
- x, u, t;
- while (g && (g !== C)) {
- v.prependMatrix(g.matrix || g.attr && g.attr.matrix);
- g = g.getParent()
- }
- v.prependMatrix(e);
- a = q.getBBox();
- if (a) {
- a = v.transformBBox(a)
- }
- q.preRender(C);
- if (q.attr.hidden || q.attr.globalAlpha === 0) {
- q.setDirty(false);
- return
- }
- for (u = 0, z = 0; u < m; u++, z += p) {
- for (x = 0, A = 0; x < c; x++, A += p) {
- t = u * c + x;
- s = C.contexts[t];
- r = Math.min(p, l - A);
- o = Math.min(p, y - z);
- d = A;
- B = d + r;
- n = z;
- f = n + o;
- if (a) {
- if (a.x > B || a.x + a.width < d || a.y > f || a.y + a.height < n) {
- continue
- }
- }
- s.save();
- q.useAttributes(s, b);
- if (false === q.render(C, s, [d, n, r, o], b)) {
- return false
- }
- s.restore()
- }
- }
- q.setDirty(false)
- },
- flatten: function(n, a) {
- var k = document.createElement("canvas"),
- f = Ext.getClassName(this),
- g = this.devicePixelRatio,
- l = k.getContext("2d"),
- b, c, h, e, d, m;
- k.width = Math.ceil(n.width * g);
- k.height = Math.ceil(n.height * g);
- for (e = 0; e < a.length; e++) {
- b = a[e];
- if (Ext.getClassName(b) !== f) {
- continue
- }
- h = b.getRect();
- for (d = 0; d < b.canvases.length; d++) {
- c = b.canvases[d];
- m = c.getOffsetsTo(c.getParent());
- l.drawImage(c.dom, (h[0] + m[0]) * g, (h[1] + m[1]) * g)
- }
- }
- return {
- data: k.toDataURL(),
- type: "png"
- }
- },
- applyDefaults: function(a) {
- var b = Ext.draw.Color.RGBA_NONE;
- a.strokeStyle = b;
- a.fillStyle = b;
- a.textAlign = "start";
- a.textBaseline = "alphabetic";
- a.miterLimit = 1
- },
- clear: function() {
- var d = this,
- e = d.activeCanvases,
- c, b, a;
- for (c = 0; c < e; c++) {
- b = d.canvases[c].dom;
- a = d.contexts[c];
- a.setTransform(1, 0, 0, 1, 0, 0);
- a.clearRect(0, 0, b.width, b.height)
- }
- d.setDirty(true)
- },
- destroy: function() {
- var c = this,
- a, b = c.canvases.length;
- for (a = 0; a < b; a++) {
- c.contexts[a] = null;
- c.canvases[a].destroy();
- c.canvases[a] = null
- }
- delete c.contexts;
- delete c.canvases;
- c.callParent()
- },
- privates: {
- initElement: function() {
- var a = this;
- a.callParent();
- a.canvases = [];
- a.contexts = [];
- a.activeCanvases = (a.xSplits = 0) * (a.ySplits = 0)
- }
- }
-}, function() {
- var c = this,
- b = c.prototype,
- a = 10000000000;
- if (Ext.os.is.Android4 && Ext.browser.is.Chrome) {
- a = 3000
- } else {
- if (Ext.is.iOS) {
- a = 2200
- }
- }
- b.splitThreshold = a
-});
-Ext.define("Ext.draw.Container", {
- extend: "Ext.draw.ContainerBase",
- alternateClassName: "Ext.draw.Component",
- xtype: "draw",
- defaultType: "surface",
- isDrawContainer: true,
- requires: ["Ext.draw.Surface", "Ext.draw.engine.Svg", "Ext.draw.engine.Canvas", "Ext.draw.gradient.GradientDefinition"],
- engine: "Ext.draw.engine.Canvas",
- config: {
- cls: Ext.baseCSSPrefix + "draw-container",
- resizeHandler: null,
- sprites: null,
- gradients: []
- },
- defaultDownloadServerUrl: "http://svg.sencha.io",
- supportedFormats: ["png", "pdf", "jpeg", "gif"],
- supportedOptions: {
- version: Ext.isNumber,
- data: Ext.isString,
- format: function(a) {
- return Ext.Array.indexOf(this.supportedFormats, a) >= 0
- },
- filename: Ext.isString,
- width: Ext.isNumber,
- height: Ext.isNumber,
- scale: Ext.isNumber,
- pdf: Ext.isObject,
- jpeg: Ext.isObject
- },
- initAnimator: function() {
- this.frameCallbackId = Ext.draw.Animator.addFrameCallback("renderFrame", this)
- },
- applyGradients: function(b) {
- var a = [],
- c, f, d, e;
- if (!Ext.isArray(b)) {
- return a
- }
- for (c = 0, f = b.length; c < f; c++) {
- d = b[c];
- if (!Ext.isObject(d)) {
- continue
- }
- if (typeof d.type !== "string") {
- d.type = "linear"
- }
- if (d.angle) {
- d.degrees = d.angle;
- delete d.angle
- }
- if (Ext.isObject(d.stops)) {
- d.stops = (function(i) {
- var g = [],
- h;
- for (e in i) {
- h = i[e];
- h.offset = e / 100;
- g.push(h)
- }
- return g
- })(d.stops)
- }
- a.push(d)
- }
- Ext.draw.gradient.GradientDefinition.add(a);
- return a
- },
- applySprites: function(f) {
- if (!f) {
- return
- }
- f = Ext.Array.from(f);
- var e = f.length,
- b = [],
- d, a, c;
- for (d = 0; d < e; d++) {
- c = f[d];
- a = c.surface;
- if (!(a && a.isSurface)) {
- if (Ext.isString(a)) {
- a = this.getSurface(a)
- } else {
- a = this.getSurface("main")
- }
- }
- c = a.add(c);
- b.push(c)
- }
- return b
- },
- onBodyResize: function() {
- var b = this.element,
- a;
- if (!b) {
- return
- }
- a = b.getSize();
- if (a.width && a.height) {
- this.setBodySize(a)
- }
- },
- setBodySize: function(c) {
- var d = this,
- b = d.getResizeHandler() || d.defaultResizeHandler,
- a;
- d.fireEvent("bodyresize", d, c);
- a = b.call(d, c);
- if (a !== false) {
- d.renderFrame()
- }
- },
- defaultResizeHandler: function(a) {
- this.getItems().each(function(b) {
- b.setRect([0, 0, a.width, a.height])
- })
- },
- getSurface: function(d) {
- d = this.getId() + "-" + (d || "main");
- var c = this,
- b = c.getItems(),
- a = b.get(d);
- if (!a) {
- a = c.add({
- xclass: c.engine,
- id: d
- });
- c.onBodyResize()
- }
- return a
- },
- renderFrame: function() {
- var e = this,
- a = e.getItems(),
- b, d, c;
- for (b = 0, d = a.length; b < d; b++) {
- c = a.items[b];
- if (c.isSurface) {
- c.renderFrame()
- }
- }
- },
- getImage: function(k) {
- var l = this.innerElement.getSize(),
- a = Array.prototype.slice.call(this.items.items),
- d, g, c = this.surfaceZIndexes,
- f, e, b, h;
- for (e = 1; e < a.length; e++) {
- b = a[e];
- h = c[b.type];
- f = e - 1;
- while (f >= 0 && c[a[f].type] > h) {
- a[f + 1] = a[f];
- f--
- }
- a[f + 1] = b
- }
- d = a[0].flatten(l, a);
- if (k === "image") {
- g = new Image();
- g.src = d.data;
- d.data = g;
- return d
- }
- if (k === "stream") {
- d.data = d.data.replace(/^data:image\/[^;]+/, "data:application/octet-stream");
- return d
- }
- return d
- },
- download: function(d) {
- var e = this,
- a = [],
- b, c, f;
- d = Ext.apply({
- version: 2,
- data: e.getImage().data
- }, d);
- for (c in d) {
- if (d.hasOwnProperty(c)) {
- f = d[c];
- if (c in e.supportedOptions) {
- if (e.supportedOptions[c].call(e, f)) {
- a.push({
- tag: "input",
- type: "hidden",
- name: c,
- value: Ext.String.htmlEncode(Ext.isObject(f) ? Ext.JSON.encode(f) : f)
- })
- }
- }
- }
- }
- b = Ext.dom.Helper.markup({
- tag: "html",
- children: [{
- tag: "head"
- }, {
- tag: "body",
- children: [{
- tag: "form",
- method: "POST",
- action: d.url || e.defaultDownloadServerUrl,
- children: a
- }, {
- tag: "script",
- type: "text/javascript",
- children: 'document.getElementsByTagName("form")[0].submit();'
- }]
- }]
- });
- window.open("", "ImageDownload_" + Date.now()).document.write(b)
- },
- destroy: function() {
- var a = this.frameCallbackId;
- if (a) {
- Ext.draw.Animator.removeFrameCallback(a)
- }
- this.callParent()
- }
-}, function() {
- if (location.search.match("svg")) {
- Ext.draw.Container.prototype.engine = "Ext.draw.engine.Svg"
- } else {
- if ((Ext.os.is.BlackBerry && Ext.os.version.getMajor() === 10) || (Ext.browser.is.AndroidStock4 && (Ext.os.version.getMinor() === 1 || Ext.os.version.getMinor() === 2 || Ext.os.version.getMinor() === 3))) {
- Ext.draw.Container.prototype.engine = "Ext.draw.engine.Svg"
- }
- }
-});
-Ext.define("Ext.chart.theme.Base", {
- mixins: {
- factoryable: "Ext.mixin.Factoryable"
- },
- requires: ["Ext.draw.Color"],
- factoryConfig: {
- type: "chart.theme"
- },
- isTheme: true,
- config: {
- baseColor: null,
- colors: undefined,
- gradients: null,
- chart: {
- defaults: {
- background: "#23272a"
- }
- },
- axis: {
- defaults: {
- label: {
- x: 0,
- y: 0,
- textBaseline: "middle",
- textAlign: "center",
- fontSize: "default",
- fontFamily: "default",
- fontWeight: "default",
- fillStyle: "black",
- color: "white"
- },
- title: {
- fillStyle: "black",
- fontSize: "default*1.23",
- fontFamily: "default",
- fontWeight: "default",
- color: "white"
- },
- style: {
- strokeStyle: "black"
- },
- grid: {
- strokeStyle: "rgba(44, 47, 51, 1)"
- }
- },
- top: {
- style: {
- textPadding: 5
- }
- },
- bottom: {
- style: {
- textPadding: 5
- }
- }
- },
- series: {
- defaults: {
- label: {
- fillStyle: "black",
- strokeStyle: "none",
- fontFamily: "default",
- fontWeight: "default",
- fontSize: "default*1.077",
- textBaseline: "middle",
- textAlign: "center"
- },
- labelOverflowPadding: 5
- }
- },
- sprites: {
- text: {
- fontSize: "default",
- fontWeight: "default",
- fontFamily: "default",
- fillStyle: "black",
- color: "white"
- }
- },
- seriesThemes: undefined,
- markerThemes: {
- type: ["circle", "cross", "plus", "square", "triangle", "diamond"]
- },
- useGradients: false,
- background: null
- },
- colorDefaults: ["#94ae0a", "#115fa6", "#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
- constructor: function(a) {
- this.initConfig(a);
- this.resolveDefaults()
- },
- defaultRegEx: /^default([+\-/\*]\d+(?:\.\d+)?)?$/,
- defaultOperators: {
- "*": function(b, a) {
- return b * a
- },
- "+": function(b, a) {
- return b + a
- },
- "-": function(b, a) {
- return b - a
- }
- },
- resolveDefaults: function() {
- var a = this;
- Ext.onReady(function() {
- var f = Ext.clone(a.getSprites()),
- e = Ext.clone(a.getAxis()),
- d = Ext.clone(a.getSeries()),
- g, c, b;
- if (!a.superclass.defaults) {
- g = Ext.getBody().createChild({
- tag: "div",
- cls: "x-component"
- });
- a.superclass.defaults = {
- fontFamily: g.getStyle("fontFamily"),
- fontWeight: g.getStyle("fontWeight"),
- fontSize: parseFloat(g.getStyle("fontSize")),
- fontVariant: g.getStyle("fontVariant"),
- fontStyle: g.getStyle("fontStyle")
- };
- g.destroy()
- }
- a.replaceDefaults(f.text);
- a.setSprites(f);
- for (c in e) {
- b = e[c];
- a.replaceDefaults(b.label);
- a.replaceDefaults(b.title)
- }
- a.setAxis(e);
- for (c in d) {
- b = d[c];
- a.replaceDefaults(b.label)
- }
- a.setSeries(d)
- })
- },
- replaceDefaults: function(h) {
- var e = this,
- g = e.superclass.defaults,
- a = e.defaultRegEx,
- d, f, c, b;
- if (Ext.isObject(h)) {
- for (d in g) {
- c = a.exec(h[d]);
- if (c) {
- f = g[d];
- c = c[1];
- if (c) {
- b = e.defaultOperators[c.charAt(0)];
- f = Math.round(b(f, parseFloat(c.substr(1))))
- }
- h[d] = f
- }
- }
- }
- },
- applyBaseColor: function(c) {
- var a, b;
- if (c) {
- a = c.isColor ? c : Ext.draw.Color.fromString(c);
- b = a.getHSL()[2];
- if (b < 0.15) {
- a = a.createLighter(0.3)
- } else {
- if (b < 0.3) {
- a = a.createLighter(0.15)
- } else {
- if (b > 0.85) {
- a = a.createDarker(0.3)
- } else {
- if (b > 0.7) {
- a = a.createDarker(0.15)
- }
- }
- }
- }
- this.setColors([a.createDarker(0.3).toString(), a.createDarker(0.15).toString(), a.toString(), a.createLighter(0.12).toString(), a.createLighter(0.24).toString(), a.createLighter(0.31).toString()])
- }
- return c
- },
- applyColors: function(a) {
- return a || this.colorDefaults
- },
- updateUseGradients: function(a) {
- if (a) {
- this.updateGradients({
- type: "linear",
- degrees: 90
- })
- }
- },
- updateBackground: function(a) {
- if (a) {
- var b = this.getChart();
- b.defaults.background = a;
- this.setChart(b)
- }
- },
- updateGradients: function(a) {
- var c = this.getColors(),
- e = [],
- h, b, d, f, g;
- if (Ext.isObject(a)) {
- for (f = 0, g = c && c.length || 0; f < g; f++) {
- b = Ext.draw.Color.fromString(c[f]);
- if (b) {
- d = b.createLighter(0.15).toString();
- h = Ext.apply(Ext.Object.chain(a), {
- stops: [{
- offset: 1,
- color: b.toString()
- }, {
- offset: 0,
- color: d.toString()
- }]
- });
- e.push(h)
- }
- }
- this.setColors(e)
- }
- },
- applySeriesThemes: function(a) {
- this.getBaseColor();
- this.getUseGradients();
- this.getGradients();
- var b = this.getColors();
- if (!a) {
- a = {
- fillStyle: Ext.Array.clone(b),
- strokeStyle: Ext.Array.map(b, function(d) {
- var c = Ext.draw.Color.fromString(d.stops ? d.stops[0].color : d);
- return c.createDarker(0.15).toString()
- })
- }
- }
- return a
- }
-});
-Ext.define("Ext.chart.theme.Default", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.default", "chart.theme.Base"]
-});
-Ext.define("Ext.chart.Markers", {
- extend: "Ext.draw.sprite.Instancing",
- isMarkers: true,
- defaultCategory: "default",
- constructor: function() {
- this.callParent(arguments);
- this.categories = {};
- this.revisions = {}
- },
- destroy: function() {
- this.categories = null;
- this.revisions = null;
- this.callParent()
- },
- getMarkerFor: function(b, a) {
- if (b in this.categories) {
- var c = this.categories[b];
- if (a in c) {
- return this.get(c[a])
- }
- }
- },
- clear: function(a) {
- a = a || this.defaultCategory;
- if (!(a in this.revisions)) {
- this.revisions[a] = 1
- } else {
- this.revisions[a]++
- }
- },
- putMarkerFor: function(e, b, c, h, f) {
- e = e || this.defaultCategory;
- var d = this,
- g = d.categories[e] || (d.categories[e] = {}),
- a;
- if (c in g) {
- d.setAttributesFor(g[c], b, h)
- } else {
- g[c] = d.getCount();
- d.createInstance(b, h)
- }
- a = d.get(g[c]);
- if (a) {
- a.category = e;
- if (!f) {
- a.revision = d.revisions[e] || (d.revisions[e] = 1)
- }
- }
- },
- getMarkerBBoxFor: function(c, a, b) {
- if (c in this.categories) {
- var d = this.categories[c];
- if (a in d) {
- return this.getBBoxFor(d[a], b)
- }
- }
- },
- getBBox: function() {
- return null
- },
- render: function(a, l, b) {
- var f = this,
- k = f.revisions,
- j = f.attr.matrix,
- h = f.getTemplate(),
- d = h.attr,
- g, c, e;
- j.toContext(l);
- h.preRender(a, l, b);
- h.useAttributes(l, b);
- for (c = 0, e = f.instances.length; c < e; c++) {
- g = f.get(c);
- if (g.hidden || g.revision !== k[g.category]) {
- continue
- }
- l.save();
- h.attr = g;
- h.useAttributes(l, b);
- h.render(a, l, b);
- l.restore()
- }
- h.attr = d
- }
-});
-Ext.define("Ext.chart.label.Callout", {
- extend: "Ext.draw.modifier.Modifier",
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("calloutOriginal")) {
- a.calloutOriginal = Ext.Object.chain(a);
- a.calloutOriginal.prototype = a
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.calloutOriginal)
- }
- },
- setAttrs: function(e, h) {
- var d = e.callout,
- i = e.calloutOriginal,
- l = e.bbox.plain,
- c = (l.width || 0) + e.labelOverflowPadding,
- m = (l.height || 0) + e.labelOverflowPadding,
- p, o;
- if ("callout" in h) {
- d = h.callout
- }
- if ("callout" in h || "calloutPlaceX" in h || "calloutPlaceY" in h || "x" in h || "y" in h) {
- var n = "rotationRads" in h ? i.rotationRads = h.rotationRads : i.rotationRads,
- g = "x" in h ? (i.x = h.x) : i.x,
- f = "y" in h ? (i.y = h.y) : i.y,
- b = "calloutPlaceX" in h ? h.calloutPlaceX : e.calloutPlaceX,
- a = "calloutPlaceY" in h ? h.calloutPlaceY : e.calloutPlaceY,
- k = "calloutVertical" in h ? h.calloutVertical : e.calloutVertical,
- j;
- n %= Math.PI * 2;
- if (Math.cos(n) < 0) {
- n = (n + Math.PI) % (Math.PI * 2)
- }
- if (n > Math.PI) {
- n -= Math.PI * 2
- }
- if (k) {
- n = n * (1 - d) - Math.PI / 2 * d;
- j = c;
- c = m;
- m = j
- } else {
- n = n * (1 - d)
- }
- h.rotationRads = n;
- h.x = g * (1 - d) + b * d;
- h.y = f * (1 - d) + a * d;
- p = b - g;
- o = a - f;
- if (Math.abs(o * c) > Math.abs(p * m)) {
- if (o > 0) {
- h.calloutEndX = h.x - (m / 2) * (p / o) * d;
- h.calloutEndY = h.y - (m / 2) * d
- } else {
- h.calloutEndX = h.x + (m / 2) * (p / o) * d;
- h.calloutEndY = h.y + (m / 2) * d
- }
- } else {
- if (p > 0) {
- h.calloutEndX = h.x - c / 2;
- h.calloutEndY = h.y - (c / 2) * (o / p) * d
- } else {
- h.calloutEndX = h.x + c / 2;
- h.calloutEndY = h.y + (c / 2) * (o / p) * d
- }
- }
- if (h.calloutStartX && h.calloutStartY) {
- h.calloutHasLine = (p > 0 && h.calloutStartX < h.calloutEndX) || (p <= 0 && h.calloutStartX > h.calloutEndX) || (o > 0 && h.calloutStartY < h.calloutEndY) || (o <= 0 && h.calloutStartY > h.calloutEndY)
- } else {
- h.calloutHasLine = true
- }
- }
- return h
- },
- pushDown: function(a, b) {
- b = this.callParent([a.calloutOriginal, b]);
- return this.setAttrs(a, b)
- },
- popUp: function(a, b) {
- a = a.prototype;
- b = this.setAttrs(a, b);
- if (this._next) {
- return this._next.popUp(a, b)
- } else {
- return Ext.apply(a, b)
- }
- }
-});
-Ext.define("Ext.chart.label.Label", {
- extend: "Ext.draw.sprite.Text",
- requires: ["Ext.chart.label.Callout"],
- inheritableStatics: {
- def: {
- processors: {
- callout: "limited01",
- calloutHasLine: "bool",
- calloutPlaceX: "number",
- calloutPlaceY: "number",
- calloutStartX: "number",
- calloutStartY: "number",
- calloutEndX: "number",
- calloutEndY: "number",
- calloutColor: "color",
- calloutWidth: "number",
- calloutVertical: "bool",
- labelOverflowPadding: "number",
- display: "enums(none,under,over,rotate,insideStart,insideEnd,inside,outside)",
- orientation: "enums(horizontal,vertical)",
- renderer: "default"
- },
- defaults: {
- callout: 0,
- calloutHasLine: true,
- calloutPlaceX: 0,
- calloutPlaceY: 0,
- calloutStartX: 0,
- calloutStartY: 0,
- calloutEndX: 0,
- calloutEndY: 0,
- calloutWidth: 1,
- calloutVertical: false,
- calloutColor: "black",
- labelOverflowPadding: 5,
- display: "none",
- orientation: "",
- renderer: null
- },
- triggers: {
- callout: "transform",
- calloutPlaceX: "transform",
- calloutPlaceY: "transform",
- labelOverflowPadding: "transform",
- calloutRotation: "transform",
- display: "hidden"
- },
- updaters: {
- hidden: function(a) {
- a.hidden = a.display === "none"
- }
- }
- }
- },
- config: {
- fx: {
- customDurations: {
- callout: 200
- }
- },
- field: null,
- calloutLine: true
- },
- applyCalloutLine: function(a) {
- if (a) {
- return Ext.apply({}, a)
- }
- },
- prepareModifiers: function() {
- this.callParent(arguments);
- this.calloutModifier = new Ext.chart.label.Callout({
- sprite: this
- });
- this.fx.setNext(this.calloutModifier);
- this.calloutModifier.setNext(this.topModifier)
- },
- render: function(b, c) {
- var e = this,
- a = e.attr,
- d = a.calloutColor;
- c.save();
- c.globalAlpha *= a.callout;
- if (c.globalAlpha > 0 && a.calloutHasLine) {
- if (d && d.isGradient) {
- d = d.getStops()[0].color
- }
- c.strokeStyle = d;
- c.fillStyle = d;
- c.lineWidth = a.calloutWidth;
- c.beginPath();
- c.moveTo(e.attr.calloutStartX, e.attr.calloutStartY);
- c.lineTo(e.attr.calloutEndX, e.attr.calloutEndY);
- c.stroke();
- c.beginPath();
- c.arc(e.attr.calloutStartX, e.attr.calloutStartY, 1 * a.calloutWidth, 0, 2 * Math.PI, true);
- c.fill();
- c.beginPath();
- c.arc(e.attr.calloutEndX, e.attr.calloutEndY, 1 * a.calloutWidth, 0, 2 * Math.PI, true);
- c.fill()
- }
- c.restore();
- Ext.draw.sprite.Text.prototype.render.apply(e, arguments)
- }
-});
-Ext.define("Ext.chart.series.Series", {
- requires: ["Ext.chart.Markers", "Ext.chart.label.Label", "Ext.tip.ToolTip"],
- mixins: ["Ext.mixin.Observable", "Ext.mixin.Bindable"],
- isSeries: true,
- defaultBindProperty: "store",
- type: null,
- seriesType: "sprite",
- identifiablePrefix: "ext-line-",
- observableType: "series",
- darkerStrokeRatio: 0.15,
- config: {
- chart: null,
- title: null,
- renderer: null,
- showInLegend: true,
- triggerAfterDraw: false,
- style: {},
- subStyle: {},
- themeStyle: {},
- colors: null,
- useDarkerStrokeColor: true,
- store: null,
- label: {},
- labelOverflowPadding: null,
- showMarkers: true,
- marker: null,
- markerSubStyle: null,
- itemInstancing: null,
- background: null,
- highlightItem: null,
- surface: null,
- overlaySurface: null,
- hidden: false,
- highlight: false,
- highlightCfg: {
- merge: function(a) {
- return a
- },
- $value: {
- fillStyle: "yellow",
- strokeStyle: "red"
- }
- },
- animation: null,
- tooltip: null
- },
- directions: [],
- sprites: null,
- themeColorCount: function() {
- return 1
- },
- isStoreDependantColorCount: false,
- themeMarkerCount: function() {
- return 0
- },
- getFields: function(f) {
- var e = this,
- a = [],
- c, b, d;
- for (b = 0, d = f.length; b < d; b++) {
- c = e["get" + f[b] + "Field"]();
- if (Ext.isArray(c)) {
- a.push.apply(a, c)
- } else {
- a.push(c)
- }
- }
- return a
- },
- applyAnimation: function(a, b) {
- if (!a) {
- a = {
- duration: 0
- }
- } else {
- if (a === true) {
- a = {
- easing: "easeInOut",
- duration: 500
- }
- }
- }
- return b ? Ext.apply({}, a, b) : a
- },
- getAnimation: function() {
- var a = this.getChart();
- if (a && a.animationSuspendCount) {
- return {
- duration: 0
- }
- } else {
- return this.callParent()
- }
- },
- updateTitle: function(a) {
- var j = this,
- g = j.getChart();
- if (!g || g.isInitializing) {
- return
- }
- a = Ext.Array.from(a);
- var c = g.getSeries(),
- b = Ext.Array.indexOf(c, j),
- e = g.getLegendStore(),
- h = j.getYField(),
- d, l, k, f;
- if (e.getCount() && b !== -1) {
- f = h ? Math.min(a.length, h.length) : a.length;
- for (d = 0; d < f; d++) {
- k = a[d];
- l = e.getAt(b + d);
- if (k && l) {
- l.set("name", k)
- }
- }
- }
- },
- applyHighlight: function(a, b) {
- if (Ext.isObject(a)) {
- a = Ext.merge({}, this.config.highlightCfg, a)
- } else {
- if (a === true) {
- a = this.config.highlightCfg
- }
- }
- return Ext.apply(b || {}, a)
- },
- updateHighlight: function(a) {
- this.getStyle();
- if (!Ext.Object.isEmpty(a)) {
- this.addItemHighlight()
- }
- },
- updateHighlightCfg: function(a) {
- if (!Ext.Object.equals(a, this.defaultConfig.highlightCfg)) {
- this.addItemHighlight()
- }
- },
- applyItemInstancing: function(a, b) {
- return Ext.merge(b || {}, a)
- },
- setAttributesForItem: function(c, d) {
- var b = c && c.sprite,
- a;
- if (b) {
- if (b.itemsMarker && c.category === "items") {
- b.putMarker(c.category, d, c.index, false, true)
- }
- if (b.isMarkerHolder && c.category === "markers") {
- b.putMarker(c.category, d, c.index, false, true)
- } else {
- if (b.isInstancing) {
- b.setAttributesFor(c.index, d)
- } else {
- if (Ext.isArray(b)) {
- for (a = 0; a < b.length; a++) {
- b[a].setAttributes(d)
- }
- } else {
- b.setAttributes(d)
- }
- }
- }
- }
- },
- getBBoxForItem: function(a) {
- if (a && a.sprite) {
- if (a.sprite.itemsMarker && a.category === "items") {
- return a.sprite.getMarkerBBox(a.category, a.index)
- } else {
- if (a.sprite instanceof Ext.draw.sprite.Instancing) {
- return a.sprite.getBBoxFor(a.index)
- } else {
- return a.sprite.getBBox()
- }
- }
- }
- return null
- },
- applyHighlightItem: function(d, a) {
- if (d === a) {
- return
- }
- if (Ext.isObject(d) && Ext.isObject(a)) {
- var c = d.sprite === a.sprite,
- b = d.index === a.index;
- if (c && b) {
- return
- }
- }
- return d
- },
- updateHighlightItem: function(b, a) {
- this.setAttributesForItem(a, {
- highlighted: false
- });
- this.setAttributesForItem(b, {
- highlighted: true
- })
- },
- constructor: function(a) {
- var b = this,
- c;
- a = a || {};
- if (a.tips) {
- a = Ext.apply({
- tooltip: a.tips
- }, a)
- }
- if (a.highlightCfg) {
- a = Ext.apply({
- highlight: a.highlightCfg
- }, a)
- }
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.sprites = [];
- b.dataRange = [];
- b.mixins.observable.constructor.call(b, a);
- b.initBindable()
- },
- lookupViewModel: function(a) {
- var b = this.getChart();
- return b ? b.lookupViewModel(a) : null
- },
- applyTooltip: function(c, b) {
- var a = Ext.apply({
- xtype: "tooltip",
- renderer: Ext.emptyFn,
- constrainPosition: true,
- shrinkWrapDock: true,
- autoHide: true,
- offsetX: 10,
- offsetY: 10
- }, c);
- return Ext.create(a)
- },
- updateTooltip: function() {
- this.addItemHighlight()
- },
- addItemHighlight: function() {
- var d = this.getChart();
- if (!d) {
- return
- }
- var e = d.getInteractions(),
- c, a, b;
- for (c = 0; c < e.length; c++) {
- a = e[c];
- if (a.isItemHighlight || a.isItemEdit) {
- b = true;
- break
- }
- }
- if (!b) {
- e.push("itemhighlight");
- d.setInteractions(e)
- }
- },
- showTooltip: function(l, m) {
- var d = this,
- n = d.getTooltip(),
- j, a, i, f, h, k, g, e, b, c;
- if (!n) {
- return
- }
- clearTimeout(d.tooltipTimeout);
- b = n.config;
- if (n.trackMouse) {
- m[0] += b.offsetX;
- m[1] += b.offsetY
- } else {
- j = l.sprite;
- a = j.getSurface();
- i = Ext.get(a.getId());
- if (i) {
- k = l.series.getBBoxForItem(l);
- g = k.x + k.width / 2;
- e = k.y + k.height / 2;
- h = a.matrix.transformPoint([g, e]);
- f = i.getXY();
- c = a.getInherited().rtl;
- g = c ? f[0] + i.getWidth() - h[0] : f[0] + h[0];
- e = f[1] + h[1];
- m = [g, e]
- }
- }
- Ext.callback(n.renderer, n.scope, [n, l.record, l], 0, d);
- n.show(m)
- },
- hideTooltip: function(b) {
- var a = this,
- c = a.getTooltip();
- if (!c) {
- return
- }
- clearTimeout(a.tooltipTimeout);
- a.tooltipTimeout = Ext.defer(function() {
- c.hide()
- }, 1)
- },
- applyStore: function(a) {
- return a && Ext.StoreManager.lookup(a)
- },
- getStore: function() {
- return this._store || this.getChart() && this.getChart().getStore()
- },
- updateStore: function(b, a) {
- var h = this,
- g = h.getChart(),
- c = g && g.getStore(),
- f, j, e, d;
- a = a || c;
- if (a && a !== b) {
- a.un({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: h
- })
- }
- if (b) {
- b.on({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: h
- });
- f = h.getSprites();
- for (d = 0, e = f.length; d < e; d++) {
- j = f[d];
- if (j.setStore) {
- j.setStore(b)
- }
- }
- h.onDataChanged()
- }
- h.fireEvent("storechange", h, b, a)
- },
- onStoreChange: function(b, a, c) {
- if (!this._store) {
- this.updateStore(a, c)
- }
- },
- coordinate: function(o, m, e) {
- var l = this,
- p = l.getStore(),
- h = l.getHidden(),
- k = p.getData().items,
- b = l["get" + o + "Axis"](),
- f = {
- min: Infinity,
- max: -Infinity
- },
- q = l["fieldCategory" + o] || [o],
- g = l.getFields(q),
- d, n, c, a = {},
- j = l.getSprites();
- if (j.length > 0) {
- if (!Ext.isBoolean(h) || !h) {
- for (d = 0; d < q.length; d++) {
- n = g[d];
- c = l.coordinateData(k, n, b);
- l.getRangeOfData(c, f);
- a["data" + q[d]] = c
- }
- }
- l.dataRange[m] = f.min;
- l.dataRange[m + e] = f.max;
- a["dataMin" + o] = f.min;
- a["dataMax" + o] = f.max;
- if (b) {
- b.range = null;
- a["range" + o] = b.getRange()
- }
- for (d = 0; d < j.length; d++) {
- j[d].setAttributes(a)
- }
- }
- },
- coordinateData: function(b, h, d) {
- var g = [],
- f = b.length,
- e = d && d.getLayout(),
- c, a;
- for (c = 0; c < f; c++) {
- a = b[c].data[h];
- if (!Ext.isEmpty(a, true)) {
- if (e) {
- g[c] = e.getCoordFor(a, h, c, b)
- } else {
- g[c] = +a
- }
- } else {
- g[c] = a
- }
- }
- return g
- },
- getRangeOfData: function(g, b) {
- var e = g.length,
- d = b.min,
- a = b.max,
- c, f;
- for (c = 0; c < e; c++) {
- f = g[c];
- if (f < d) {
- d = f
- }
- if (f > a) {
- a = f
- }
- }
- b.min = d;
- b.max = a
- },
- updateLabelData: function() {
- var h = this,
- l = h.getStore(),
- g = l.getData().items,
- f = h.getSprites(),
- a = h.getLabel().getTemplate(),
- n = Ext.Array.from(a.getField()),
- c, b, e, d, m, k;
- if (!f.length || !n.length) {
- return
- }
- for (c = 0; c < f.length; c++) {
- d = [];
- m = f[c];
- k = m.getField();
- if (Ext.Array.indexOf(n, k) < 0) {
- k = n[c]
- }
- for (b = 0, e = g.length; b < e; b++) {
- d.push(g[b].get(k))
- }
- m.setAttributes({
- labels: d
- })
- }
- },
- processData: function() {
- if (!this.getStore()) {
- return
- }
- var d = this,
- f = this.directions,
- a, c = f.length,
- e, b;
- for (a = 0; a < c; a++) {
- e = f[a];
- b = d["get" + e + "Axis"]();
- if (b) {
- b.processData(d);
- continue
- }
- if (d["coordinate" + e]) {
- d["coordinate" + e]()
- }
- }
- d.updateLabelData()
- },
- applyBackground: function(a) {
- if (this.getChart()) {
- this.getSurface().setBackground(a);
- return this.getSurface().getBackground()
- } else {
- return a
- }
- },
- updateChart: function(d, a) {
- var c = this,
- b = c._store;
- if (a) {
- a.un("axeschange", "onAxesChange", c);
- c.clearSprites();
- c.setSurface(null);
- c.setOverlaySurface(null);
- a.unregister(c);
- c.onChartDetached(a);
- if (!b) {
- c.updateStore(null)
- }
- }
- if (d) {
- c.setSurface(d.getSurface("series"));
- c.setOverlaySurface(d.getSurface("overlay"));
- d.on("axeschange", "onAxesChange", c);
- if (d.getAxes()) {
- c.onAxesChange(d)
- }
- c.onChartAttached(d);
- d.register(c);
- if (!b) {
- c.updateStore(d.getStore())
- }
- }
- },
- onAxesChange: function(h) {
- var k = this,
- g = h.getAxes(),
- c, a = {},
- b = {},
- e = false,
- j = this.directions,
- l, d, f;
- for (d = 0, f = j.length; d < f; d++) {
- l = j[d];
- b[l] = k.getFields(k["fieldCategory" + l])
- }
- for (d = 0, f = g.length; d < f; d++) {
- c = g[d];
- if (!a[c.getDirection()]) {
- a[c.getDirection()] = [c]
- } else {
- a[c.getDirection()].push(c)
- }
- }
- for (d = 0, f = j.length; d < f; d++) {
- l = j[d];
- if (k["get" + l + "Axis"]()) {
- continue
- }
- if (a[l]) {
- c = k.findMatchingAxis(a[l], b[l]);
- if (c) {
- k["set" + l + "Axis"](c);
- if (c.getNeedHighPrecision()) {
- e = true
- }
- }
- }
- }
- this.getSurface().setHighPrecision(e)
- },
- findMatchingAxis: function(f, e) {
- var d, c, b, a;
- for (b = 0; b < f.length; b++) {
- d = f[b];
- c = d.getFields();
- if (!c.length) {
- return d
- } else {
- if (e) {
- for (a = 0; a < e.length; a++) {
- if (Ext.Array.indexOf(c, e[a]) >= 0) {
- return d
- }
- }
- }
- }
- }
- },
- onChartDetached: function(a) {
- var b = this;
- b.fireEvent("chartdetached", a, b);
- a.un("storechange", "onStoreChange", b)
- },
- onChartAttached: function(a) {
- var b = this;
- b.setBackground(b.getBackground());
- b.fireEvent("chartattached", a, b);
- a.on("storechange", "onStoreChange", b);
- b.processData()
- },
- updateOverlaySurface: function(a) {
- var b = this;
- if (a) {
- if (b.getLabel()) {
- b.getOverlaySurface().add(b.getLabel())
- }
- }
- },
- applyLabel: function(a, b) {
- if (!b) {
- b = new Ext.chart.Markers({
- zIndex: 10
- });
- b.setTemplate(new Ext.chart.label.Label(a))
- } else {
- b.getTemplate().setAttributes(a)
- }
- return b
- },
- createItemInstancingSprite: function(c, b) {
- var e = this,
- f = new Ext.chart.Markers(),
- a, d;
- f.setAttributes({
- zIndex: Number.MAX_VALUE
- });
- a = Ext.apply({}, b);
- if (e.getHighlight()) {
- a.highlight = e.getHighlight();
- a.modifiers = ["highlight"]
- }
- f.setTemplate(a);
- d = f.getTemplate();
- d.setAttributes(e.getStyle());
- d.fx.on("animationstart", "onSpriteAnimationStart", this);
- d.fx.on("animationend", "onSpriteAnimationEnd", this);
- c.bindMarker("items", f);
- e.getSurface().add(f);
- return f
- },
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer()
- }
- },
- updateRenderer: function(c) {
- var b = this,
- a = b.getChart(),
- d;
- if (a && a.isInitializing) {
- return
- }
- d = b.getSprites();
- if (d.length) {
- d[0].setAttributes({
- renderer: c || null
- });
- if (a && !a.isInitializing) {
- a.redraw()
- }
- }
- },
- updateShowMarkers: function(a) {
- var d = this.getSprites(),
- b = d && d[0],
- c = b && b.getMarker("markers");
- if (c) {
- c.getTemplate().setAttributes({
- hidden: !a
- })
- }
- },
- createSprite: function() {
- var f = this,
- a = f.getSurface(),
- e = f.getItemInstancing(),
- d = a.add(f.getDefaultSpriteConfig()),
- b = f.getMarker(),
- g, c;
- d.setAttributes(f.getStyle());
- d.setSeries(f);
- if (e) {
- d.itemsMarker = f.createItemInstancingSprite(d, e)
- }
- if (d.bindMarker) {
- if (b) {
- g = new Ext.chart.Markers();
- c = Ext.Object.merge({}, b);
- if (f.getHighlight()) {
- c.highlight = f.getHighlight();
- c.modifiers = ["highlight"]
- }
- g.setTemplate(c);
- g.getTemplate().fx.setCustomDurations({
- translationX: 0,
- translationY: 0
- });
- d.dataMarker = g;
- d.bindMarker("markers", g);
- f.getOverlaySurface().add(g)
- }
- if (f.getLabel().getTemplate().getField()) {
- d.bindMarker("labels", f.getLabel())
- }
- }
- if (d.setStore) {
- d.setStore(f.getStore())
- }
- d.fx.on("animationstart", "onSpriteAnimationStart", f);
- d.fx.on("animationend", "onSpriteAnimationEnd", f);
- f.sprites.push(d);
- return d
- },
- getSprites: Ext.emptyFn,
- onDataChanged: function() {
- var d = this,
- c = d.getChart(),
- b = c && c.getStore(),
- a = d.getStore();
- if (a !== b) {
- d.processData()
- }
- },
- isXType: function(a) {
- return a === "series"
- },
- getItemId: function() {
- return this.getId()
- },
- applyThemeStyle: function(e, a) {
- var b = this,
- d, c;
- d = e && e.subStyle && e.subStyle.fillStyle;
- c = d && e.subStyle.strokeStyle;
- if (d && !c) {
- e.subStyle.strokeStyle = b.getStrokeColorsFromFillColors(d)
- }
- d = e && e.markerSubStyle && e.markerSubStyle.fillStyle;
- c = d && e.markerSubStyle.strokeStyle;
- if (d && !c) {
- e.markerSubStyle.strokeStyle = b.getStrokeColorsFromFillColors(d)
- }
- return Ext.apply(a || {}, e)
- },
- applyStyle: function(c, b) {
- var a = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + this.seriesType));
- if (a && a.def) {
- c = a.def.normalize(c)
- }
- return Ext.apply({}, c, b)
- },
- applySubStyle: function(b, c) {
- var a = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + this.seriesType));
- if (a && a.def) {
- b = a.def.batchedNormalize(b, true)
- }
- return Ext.merge({}, c, b)
- },
- applyMarker: function(c, a) {
- var d = (c && c.type) || (a && a.type) || "circle",
- b = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + d));
- if (b && b.def) {
- c = b.def.normalize(Ext.isObject(c) ? c : {}, true);
- c.type = d
- }
- return Ext.merge(a || {}, c)
- },
- applyMarkerSubStyle: function(c, a) {
- var d = (c && c.type) || (a && a.type) || "circle",
- b = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + d));
- if (b && b.def) {
- c = b.def.batchedNormalize(c, true)
- }
- return Ext.merge(a || {}, c)
- },
- updateHidden: function(b) {
- var a = this;
- a.getColors();
- a.getSubStyle();
- a.setSubStyle({
- hidden: b
- });
- a.processData();
- a.doUpdateStyles();
- if (!Ext.isArray(b)) {
- a.updateLegendStore(b)
- }
- },
- updateLegendStore: function(f, b) {
- var e = this,
- d = e.getChart(),
- c = d.getLegendStore(),
- g = e.getId(),
- a;
- if (c) {
- if (arguments.length > 1) {
- a = c.findBy(function(h) {
- return h.get("series") === g && h.get("index") === b
- });
- if (a !== -1) {
- a = c.getAt(a)
- }
- } else {
- a = c.findRecord("series", g)
- }
- if (a && a.get("disabled") !== f) {
- a.set("disabled", f)
- }
- }
- },
- setHiddenByIndex: function(a, c) {
- var b = this;
- if (Ext.isArray(b.getHidden())) {
- b.getHidden()[a] = c;
- b.updateHidden(b.getHidden());
- b.updateLegendStore(c, a)
- } else {
- b.setHidden(c)
- }
- },
- getStrokeColorsFromFillColors: function(a) {
- var c = this,
- e = c.getUseDarkerStrokeColor(),
- b = (Ext.isNumber(e) ? e : c.darkerStrokeRatio),
- d;
- if (e) {
- d = Ext.Array.map(a, function(f) {
- f = Ext.isString(f) ? f : f.stops[0].color;
- f = Ext.draw.Color.fromString(f);
- return f.createDarker(b).toString()
- })
- } else {
- d = Ext.Array.clone(a)
- }
- return d
- },
- updateThemeColors: function(b) {
- var c = this,
- d = c.getThemeStyle(),
- a = Ext.Array.clone(b),
- f = c.getStrokeColorsFromFillColors(b),
- e = {
- fillStyle: a,
- strokeStyle: f
- };
- d.subStyle = Ext.apply(d.subStyle || {}, e);
- d.markerSubStyle = Ext.apply(d.markerSubStyle || {}, e);
- c.doUpdateStyles()
- },
- themeOnlyIfConfigured: {},
- updateTheme: function(d) {
- var h = this,
- a = d.getSeries(),
- n = h.getInitialConfig(),
- c = h.defaultConfig,
- f = h.getConfigurator().configs,
- j = a.defaults,
- k = a[h.type],
- g = h.themeOnlyIfConfigured,
- l, i, o, b, m, e;
- a = Ext.merge({}, j, k);
- for (l in a) {
- i = a[l];
- e = f[l];
- if (i !== null && i !== undefined && e) {
- m = n[l];
- o = Ext.isObject(i);
- b = m === c[l];
- if (o) {
- if (b && g[l]) {
- continue
- }
- i = Ext.merge({}, i, m)
- }
- if (b || o) {
- h[e.names.set](i)
- }
- }
- }
- },
- updateChartColors: function(a) {
- var b = this;
- if (!b.getColors()) {
- b.updateThemeColors(a)
- }
- },
- updateColors: function(a) {
- this.updateThemeColors(a)
- },
- updateStyle: function() {
- this.doUpdateStyles()
- },
- updateSubStyle: function() {
- this.doUpdateStyles()
- },
- updateThemeStyle: function() {
- this.doUpdateStyles()
- },
- doUpdateStyles: function() {
- var g = this,
- h = g.sprites,
- d = g.getItemInstancing(),
- c = 0,
- f = h && h.length,
- a = g.getConfig("showMarkers", true),
- b = g.getMarker(),
- e;
- for (; c < f; c++) {
- e = g.getStyleByIndex(c);
- if (d) {
- h[c].itemsMarker.getTemplate().setAttributes(e)
- }
- h[c].setAttributes(e);
- if (b && h[c].dataMarker) {
- h[c].dataMarker.getTemplate().setAttributes(g.getMarkerStyleByIndex(c))
- }
- }
- },
- getStyleWithTheme: function() {
- var b = this,
- c = b.getThemeStyle(),
- d = (c && c.style) || {},
- a = Ext.applyIf(Ext.apply({}, b.getStyle()), d);
- return a
- },
- getSubStyleWithTheme: function() {
- var c = this,
- d = c.getThemeStyle(),
- a = (d && d.subStyle) || {},
- b = Ext.applyIf(Ext.apply({}, c.getSubStyle()), a);
- return b
- },
- getStyleByIndex: function(b) {
- var e = this,
- h = e.getThemeStyle(),
- d, g, c, f, a = {};
- d = e.getStyle();
- g = (h && h.style) || {};
- c = e.styleDataForIndex(e.getSubStyle(), b);
- f = e.styleDataForIndex((h && h.subStyle), b);
- Ext.apply(a, g);
- Ext.apply(a, f);
- Ext.apply(a, d);
- Ext.apply(a, c);
- return a
- },
- getMarkerStyleByIndex: function(d) {
- var g = this,
- c = g.getThemeStyle(),
- a, e, k, j, b, l, h, f, m = {};
- a = g.getStyle();
- e = (c && c.style) || {};
- k = g.styleDataForIndex(g.getSubStyle(), d);
- if (k.hasOwnProperty("hidden")) {
- k.hidden = k.hidden || !this.getConfig("showMarkers", true)
- }
- j = g.styleDataForIndex((c && c.subStyle), d);
- b = g.getMarker();
- l = (c && c.marker) || {};
- h = g.getMarkerSubStyle();
- f = g.styleDataForIndex((c && c.markerSubStyle), d);
- Ext.apply(m, e);
- Ext.apply(m, j);
- Ext.apply(m, l);
- Ext.apply(m, f);
- Ext.apply(m, a);
- Ext.apply(m, k);
- Ext.apply(m, b);
- Ext.apply(m, h);
- return m
- },
- styleDataForIndex: function(d, c) {
- var e, b, a = {};
- if (d) {
- for (b in d) {
- e = d[b];
- if (Ext.isArray(e)) {
- a[b] = e[c % e.length]
- } else {
- a[b] = e
- }
- }
- }
- return a
- },
- getItemForPoint: Ext.emptyFn,
- getItemByIndex: function(a, e) {
- var d = this,
- f = d.getSprites(),
- b = f && f[0],
- c;
- if (!b) {
- return
- }
- if (e === undefined && b.isMarkerHolder) {
- e = d.getItemInstancing() ? "items" : "markers"
- } else {
- if (!e || e === "" || e === "sprites") {
- b = f[a]
- }
- }
- if (b) {
- c = {
- series: d,
- category: e,
- index: a,
- record: d.getStore().getData().items[a],
- field: d.getYField(),
- sprite: b
- };
- return c
- }
- },
- onSpriteAnimationStart: function(a) {
- this.fireEvent("animationstart", this, a)
- },
- onSpriteAnimationEnd: function(a) {
- this.fireEvent("animationend", this, a)
- },
- resolveListenerScope: function(e) {
- var d = this,
- a = Ext._namedScopes[e],
- c = d.getChart(),
- b;
- if (!a) {
- b = c ? c.resolveListenerScope(e, false) : (e || d)
- } else {
- if (a.isThis) {
- b = d
- } else {
- if (a.isController) {
- b = c ? c.resolveListenerScope(e, false) : d
- } else {
- if (a.isSelf) {
- b = c ? c.resolveListenerScope(e, false) : d;
- if (b === c && !c.getInheritedConfig("defaultListenerScope")) {
- b = d
- }
- }
- }
- }
- }
- return b
- },
- provideLegendInfo: function(a) {
- a.push({
- name: this.getTitle() || this.getId(),
- mark: "black",
- disabled: this.getHidden(),
- series: this.getId(),
- index: 0
- })
- },
- clearSprites: function() {
- var d = this.sprites,
- b, a, c;
- for (a = 0, c = d.length; a < c; a++) {
- b = d[a];
- if (b && b.isSprite) {
- b.destroy()
- }
- }
- this.sprites = []
- },
- destroy: function() {
- var b = this,
- a = b._store,
- c = b.getConfig("tooltip", true);
- if (a && a.getAutoDestroy()) {
- Ext.destroy(a)
- }
- b.setChart(null);
- b.clearListeners();
- if (c) {
- Ext.destroy(c);
- clearTimeout(b.tooltipTimeout)
- }
- b.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.Abstract", {
- xtype: "interaction",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- gestures: {
- tap: "onGesture"
- },
- chart: null,
- enabled: true
- },
- throttleGap: 0,
- stopAnimationBeforeSync: false,
- constructor: function(a) {
- var b = this,
- c;
- a = a || {};
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.mixins.observable.constructor.call(b, a)
- },
- initialize: Ext.emptyFn,
- updateChart: function(c, a) {
- var b = this;
- if (a === c) {
- return
- }
- if (a) {
- a.unregister(b);
- b.removeChartListener(a)
- }
- if (c) {
- c.register(b);
- b.addChartListener()
- }
- },
- updateEnabled: function(a) {
- var c = this,
- b = c.getChart();
- if (b) {
- if (a) {
- c.addChartListener()
- } else {
- c.removeChartListener(b)
- }
- }
- },
- onGesture: Ext.emptyFn,
- getItemForEvent: function(d) {
- var b = this,
- a = b.getChart(),
- c = a.getEventXY(d);
- return a.getItemForPoint(c[0], c[1])
- },
- getItemsForEvent: function(d) {
- var b = this,
- a = b.getChart(),
- c = a.getEventXY(d);
- return a.getItemsForPoint(c[0], c[1])
- },
- addChartListener: function() {
- var c = this,
- b = c.getChart(),
- e = c.getGestures(),
- a;
- if (!c.getEnabled()) {
- return
- }
-
- function d(f, g) {
- b.addElementListener(f, c.listeners[f] = function(j) {
- var i = c.getLocks(),
- h;
- if (c.getEnabled() && (!(f in i) || i[f] === c)) {
- h = (Ext.isFunction(g) ? g : c[g]).apply(this, arguments);
- if (h === false && j && j.stopPropagation) {
- j.stopPropagation()
- }
- return h
- }
- }, c)
- }
- c.listeners = c.listeners || {};
- for (a in e) {
- d(a, e[a])
- }
- },
- removeChartListener: function(c) {
- var d = this,
- e = d.getGestures(),
- b;
-
- function a(f) {
- var g = d.listeners[f];
- if (g) {
- c.removeElementListener(f, g);
- delete d.listeners[f]
- }
- }
- if (d.listeners) {
- for (b in e) {
- a(b)
- }
- }
- },
- lockEvents: function() {
- var d = this,
- c = d.getLocks(),
- a = Array.prototype.slice.call(arguments),
- b = a.length;
- while (b--) {
- c[a[b]] = d
- }
- },
- unlockEvents: function() {
- var c = this.getLocks(),
- a = Array.prototype.slice.call(arguments),
- b = a.length;
- while (b--) {
- delete c[a[b]]
- }
- },
- getLocks: function() {
- var a = this.getChart();
- return a.lockedEvents || (a.lockedEvents = {})
- },
- isMultiTouch: function() {
- if (Ext.browser.is.IE10) {
- return true
- }
- return !Ext.os.is.Desktop
- },
- initializeDefaults: Ext.emptyFn,
- doSync: function() {
- var b = this,
- a = b.getChart();
- if (b.syncTimer) {
- clearTimeout(b.syncTimer);
- b.syncTimer = null
- }
- if (b.stopAnimationBeforeSync) {
- a.animationSuspendCount++
- }
- a.redraw();
- if (b.stopAnimationBeforeSync) {
- a.animationSuspendCount--
- }
- b.syncThrottle = Date.now() + b.throttleGap
- },
- sync: function() {
- var a = this;
- if (a.throttleGap && Ext.frameStartTime < a.syncThrottle) {
- if (a.syncTimer) {
- return
- }
- a.syncTimer = Ext.defer(function() {
- a.doSync()
- }, a.throttleGap)
- } else {
- a.doSync()
- }
- },
- getItemId: function() {
- return this.getId()
- },
- isXType: function(a) {
- return a === "interaction"
- },
- destroy: function() {
- var a = this;
- a.setChart(null);
- delete a.listeners;
- a.callParent()
- }
-}, function() {
- if (Ext.os.is.Android4) {
- this.prototype.throttleGap = 40
- }
-});
-Ext.define("Ext.chart.MarkerHolder", {
- extend: "Ext.Mixin",
- mixinConfig: {
- id: "markerHolder",
- after: {
- constructor: "constructor",
- preRender: "preRender"
- },
- before: {
- destroy: "destroy"
- }
- },
- isMarkerHolder: true,
- surfaceMatrix: null,
- inverseSurfaceMatrix: null,
- deprecated: {
- 6: {
- methods: {
- getBoundMarker: {
- message: "Please use the 'getMarker' method instead.",
- fn: function(b) {
- var a = this.boundMarkers[b];
- return a ? [a] : a
- }
- }
- }
- }
- },
- constructor: function() {
- this.boundMarkers = {};
- this.cleanRedraw = false
- },
- bindMarker: function(b, a) {
- var c = this,
- d = c.boundMarkers;
- if (a && a.isMarkers) {
- c.releaseMarker(b);
- d[b] = a;
- a.on("destroy", c.onMarkerDestroy, c)
- }
- },
- onMarkerDestroy: function(a) {
- this.releaseMarker(a)
- },
- releaseMarker: function(a) {
- var c = this.boundMarkers,
- b;
- if (a && a.isMarkers) {
- for (b in c) {
- if (c[b] === a) {
- delete c[b];
- break
- }
- }
- } else {
- b = a;
- a = c[b];
- delete c[b]
- }
- return a || null
- },
- getMarker: function(a) {
- return this.boundMarkers[a] || null
- },
- preRender: function() {
- var f = this,
- g = f.getId(),
- d = f.boundMarkers,
- e = f.getParent(),
- c, a, b;
- if (f.surfaceMatrix) {
- b = f.surfaceMatrix.set(1, 0, 0, 1, 0, 0)
- } else {
- b = f.surfaceMatrix = new Ext.draw.Matrix()
- }
- f.cleanRedraw = !f.attr.dirty;
- if (!f.cleanRedraw) {
- for (c in d) {
- a = d[c];
- if (a) {
- a.clear(g)
- }
- }
- }
- while (e && e.attr && e.attr.matrix) {
- b.prependMatrix(e.attr.matrix);
- e = e.getParent()
- }
- b.prependMatrix(e.matrix);
- f.surfaceMatrix = b;
- f.inverseSurfaceMatrix = b.inverse(f.inverseSurfaceMatrix)
- },
- putMarker: function(d, a, c, g, e) {
- var b = this.boundMarkers[d],
- f = this.getId();
- if (b) {
- b.putMarkerFor(f, a, c, g, e)
- }
- },
- getMarkerBBox: function(c, b, d) {
- var a = this.boundMarkers[c],
- e = this.getId();
- if (a) {
- return a.getMarkerBBoxFor(e, b, d)
- }
- },
- destroy: function() {
- var c = this.boundMarkers,
- b, a;
- for (b in c) {
- a = c[b];
- a.destroy()
- }
- }
-});
-Ext.define("Ext.chart.axis.sprite.Axis", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.axis",
- type: "axis",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- requires: ["Ext.draw.sprite.Text"],
- inheritableStatics: {
- def: {
- processors: {
- grid: "bool",
- axisLine: "bool",
- minorTicks: "bool",
- minorTickSize: "number",
- majorTicks: "bool",
- majorTickSize: "number",
- length: "number",
- startGap: "number",
- endGap: "number",
- dataMin: "number",
- dataMax: "number",
- visibleMin: "number",
- visibleMax: "number",
- position: "enums(left,right,top,bottom,angular,radial,gauge)",
- minStepSize: "number",
- estStepSize: "number",
- titleOffset: "number",
- textPadding: "number",
- min: "number",
- max: "number",
- centerX: "number",
- centerY: "number",
- radius: "number",
- totalAngle: "number",
- baseRotation: "number",
- data: "default",
- enlargeEstStepSizeByText: "bool"
- },
- defaults: {
- grid: false,
- axisLine: true,
- minorTicks: false,
- minorTickSize: 3,
- majorTicks: true,
- majorTickSize: 5,
- length: 0,
- startGap: 0,
- endGap: 0,
- visibleMin: 0,
- visibleMax: 1,
- dataMin: 0,
- dataMax: 1,
- position: "",
- minStepSize: 0,
- estStepSize: 20,
- min: 0,
- max: 1,
- centerX: 0,
- centerY: 0,
- radius: 1,
- baseRotation: 0,
- data: null,
- titleOffset: 0,
- textPadding: 0,
- scalingCenterY: 0,
- scalingCenterX: 0,
- strokeStyle: "black",
- enlargeEstStepSizeByText: false
- },
- triggers: {
- minorTickSize: "bbox",
- majorTickSize: "bbox",
- position: "bbox,layout",
- axisLine: "bbox,layout",
- min: "layout",
- max: "layout",
- length: "layout",
- minStepSize: "layout",
- estStepSize: "layout",
- data: "layout",
- dataMin: "layout",
- dataMax: "layout",
- visibleMin: "layout",
- visibleMax: "layout",
- enlargeEstStepSizeByText: "layout"
- },
- updaters: {
- layout: "layoutUpdater"
- }
- }
- },
- config: {
- label: null,
- layout: null,
- segmenter: null,
- renderer: null,
- layoutContext: null,
- axis: null
- },
- thickness: 0,
- stepSize: 0,
- getBBox: function() {
- return null
- },
- defaultRenderer: function(a) {
- return this.segmenter.renderer(a, this)
- },
- layoutUpdater: function() {
- var h = this,
- f = h.getAxis().getChart();
- if (f.isInitializing) {
- return
- }
- var e = h.attr,
- d = h.getLayout(),
- g = f.getInherited().rtl,
- b = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMin,
- i = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMax,
- c = e.position,
- a = {
- attr: e,
- segmenter: h.getSegmenter(),
- renderer: h.defaultRenderer
- };
- if (c === "left" || c === "right") {
- e.translationX = 0;
- e.translationY = i * e.length / (i - b);
- e.scalingX = 1;
- e.scalingY = -e.length / (i - b);
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- } else {
- if (c === "top" || c === "bottom") {
- if (g) {
- e.translationX = e.length + b * e.length / (i - b) + 1
- } else {
- e.translationX = -b * e.length / (i - b)
- }
- e.translationY = 0;
- e.scalingX = (g ? -1 : 1) * e.length / (i - b);
- e.scalingY = 1;
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- }
- }
- if (d) {
- d.calculateLayout(a);
- h.setLayoutContext(a)
- }
- },
- iterate: function(e, j) {
- var c, g, a, b, h, d, k = Ext.Array.some,
- m = Math.abs,
- f;
- if (e.getLabel) {
- if (e.min < e.from) {
- j.call(this, e.min, e.getLabel(e.min), -1, e)
- }
- for (c = 0; c <= e.steps; c++) {
- j.call(this, e.get(c), e.getLabel(c), c, e)
- }
- if (e.max > e.to) {
- j.call(this, e.max, e.getLabel(e.max), e.steps + 1, e)
- }
- } else {
- b = this.getAxis();
- h = b.floatingAxes;
- d = [];
- f = (e.to - e.from) / (e.steps + 1);
- if (b.getFloating()) {
- for (a in h) {
- d.push(h[a])
- }
- }
-
- function l(i) {
- return !d.length || k(d, function(n) {
- return m(n - i) > f
- })
- }
- if (e.min < e.from && l(e.min)) {
- j.call(this, e.min, e.min, -1, e)
- }
- for (c = 0; c <= e.steps; c++) {
- g = e.get(c);
- if (l(g)) {
- j.call(this, g, g, c, e)
- }
- }
- if (e.max > e.to && l(e.max)) {
- j.call(this, e.max, e.max, e.steps + 1, e)
- }
- }
- },
- renderTicks: function(l, m, s, p) {
- var v = this,
- k = v.attr,
- u = k.position,
- n = k.matrix,
- e = 0.5 * k.lineWidth,
- f = n.getXX(),
- i = n.getDX(),
- j = n.getYY(),
- h = n.getDY(),
- o = s.majorTicks,
- d = k.majorTickSize,
- a = s.minorTicks,
- r = k.minorTickSize;
- if (o) {
- switch (u) {
- case "right":
- function q(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * j + h) + e;
- m.moveTo(0, x);
- m.lineTo(w, x)
- }
- }
- v.iterate(o, q(d));
- a && v.iterate(a, q(r));
- break;
- case "left":
- function t(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * j + h) + e;
- m.moveTo(p[2] - w, x);
- m.lineTo(p[2], x)
- }
- }
- v.iterate(o, t(d));
- a && v.iterate(a, t(r));
- break;
- case "bottom":
- function c(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * f + i) - e;
- m.moveTo(x, 0);
- m.lineTo(x, w)
- }
- }
- v.iterate(o, c(d));
- a && v.iterate(a, c(r));
- break;
- case "top":
- function b(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * f + i) - e;
- m.moveTo(x, p[3]);
- m.lineTo(x, p[3] - w)
- }
- }
- v.iterate(o, b(d));
- a && v.iterate(a, b(r));
- break;
- case "angular":
- v.iterate(o, function(w, y, x) {
- w = w / (k.max + 1) * Math.PI * 2 + k.baseRotation;
- m.moveTo(k.centerX + (k.length) * Math.cos(w), k.centerY + (k.length) * Math.sin(w));
- m.lineTo(k.centerX + (k.length + d) * Math.cos(w), k.centerY + (k.length + d) * Math.sin(w))
- });
- break;
- case "gauge":
- var g = v.getGaugeAngles();
- v.iterate(o, function(w, y, x) {
- w = (w - k.min) / (k.max - k.min + 1) * k.totalAngle - k.totalAngle + g.start;
- m.moveTo(k.centerX + (k.length) * Math.cos(w), k.centerY + (k.length) * Math.sin(w));
- m.lineTo(k.centerX + (k.length + d) * Math.cos(w), k.centerY + (k.length + d) * Math.sin(w))
- });
- break
- }
- }
- },
- renderLabels: function(E, q, D, K) {
- var o = this,
- k = o.attr,
- i = 0.5 * k.lineWidth,
- u = k.position,
- y = k.matrix,
- A = k.textPadding,
- x = y.getXX(),
- d = y.getDX(),
- g = y.getYY(),
- c = y.getDY(),
- n = 0,
- I = D.majorTicks,
- G = Math.max(k.majorTickSize, k.minorTickSize) + k.lineWidth,
- f = Ext.draw.Draw.isBBoxIntersect,
- F = o.getLabel(),
- J, s, r = null,
- w = 0,
- b = 0,
- m = D.segmenter,
- B = o.getRenderer(),
- t = o.getAxis(),
- z = t.getTitle(),
- a = z && z.attr.text !== "" && z.getBBox(),
- l, h = null,
- p, C, v, e, H;
- if (I && F && !F.attr.hidden) {
- J = F.attr.font;
- if (q.font !== J) {
- q.font = J
- }
- F.setAttributes({
- translationX: 0,
- translationY: 0
- }, true);
- F.applyTransformations();
- l = F.attr.inverseMatrix.elements.slice(0);
- switch (u) {
- case "left":
- e = a ? a.x + a.width : 0;
- switch (F.attr.textAlign) {
- case "start":
- H = E.roundPixel(e + d) - i;
- break;
- case "end":
- H = E.roundPixel(K[2] - G + d) - i;
- break;
- default:
- H = E.roundPixel(e + (K[2] - e - G) / 2 + d) - i
- }
- F.setAttributes({
- translationX: H
- }, true);
- break;
- case "right":
- e = a ? K[2] - a.x : 0;
- switch (F.attr.textAlign) {
- case "start":
- H = E.roundPixel(G + d) + i;
- break;
- case "end":
- H = E.roundPixel(K[2] - e + d) + i;
- break;
- default:
- H = E.roundPixel(G + (K[2] - G - e) / 2 + d) + i
- }
- F.setAttributes({
- translationX: H
- }, true);
- break;
- case "top":
- e = a ? a.y + a.height : 0;
- F.setAttributes({
- translationY: E.roundPixel(e + (K[3] - e - G) / 2) - i
- }, true);
- break;
- case "bottom":
- e = a ? K[3] - a.y : 0;
- F.setAttributes({
- translationY: E.roundPixel(G + (K[3] - G - e) / 2) + i
- }, true);
- break;
- case "radial":
- F.setAttributes({
- translationX: k.centerX
- }, true);
- break;
- case "angular":
- F.setAttributes({
- translationY: k.centerY
- }, true);
- break;
- case "gauge":
- F.setAttributes({
- translationY: k.centerY
- }, true);
- break
- }
- if (u === "left" || u === "right") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- F.setAttributes({
- text: String(v),
- translationY: E.roundPixel(L * g + c)
- }, true);
- F.applyTransformations();
- n = Math.max(n, F.getBBox().width + G);
- if (n <= o.thickness) {
- C = Ext.draw.Matrix.fly(F.attr.matrix.elements.slice(0));
- p = C.prepend.apply(C, l).transformBBox(F.getBBox(true));
- if (h && !f(p, h, A)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.height;
- b++
- }
- })
- } else {
- if (u === "top" || u === "bottom") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- F.setAttributes({
- text: String(v),
- translationX: E.roundPixel(L * x + d)
- }, true);
- F.applyTransformations();
- n = Math.max(n, F.getBBox().height + G);
- if (n <= o.thickness) {
- C = Ext.draw.Matrix.fly(F.attr.matrix.elements.slice(0));
- p = C.prepend.apply(C, l).transformBBox(F.getBBox(true));
- if (h && !f(p, h, A)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "radial") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- if (typeof v !== "undefined") {
- F.setAttributes({
- text: String(v),
- translationX: k.centerX - E.roundPixel(L) / k.max * k.length * Math.cos(k.baseRotation + Math.PI / 2),
- translationY: k.centerY - E.roundPixel(L) / k.max * k.length * Math.sin(k.baseRotation + Math.PI / 2)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "angular") {
- s = k.majorTickSize + k.lineWidth * 0.5 + (parseInt(F.attr.fontSize, 10) || 10) / 2;
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- n = Math.max(n, Math.max(k.majorTickSize, k.minorTickSize) + (k.lineCap !== "butt" ? k.lineWidth * 0.5 : 0));
- if (typeof v !== "undefined") {
- var O = L / (k.max + 1) * Math.PI * 2 + k.baseRotation;
- F.setAttributes({
- text: String(v),
- translationX: k.centerX + (k.length + s) * Math.cos(O),
- translationY: k.centerY + (k.length + s) * Math.sin(O)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "gauge") {
- var j = o.getGaugeAngles();
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- if (typeof v !== "undefined") {
- var O = (L - k.min) / (k.max - k.min + 1) * k.totalAngle - k.totalAngle + j.start;
- F.setAttributes({
- text: String(v),
- translationX: k.centerX + (k.length + 10) * Math.cos(O),
- translationY: k.centerY + (k.length + 10) * Math.sin(O)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- }
- }
- }
- }
- }
- if (k.enlargeEstStepSizeByText && b) {
- w /= b;
- w += G;
- w *= 2;
- if (k.estStepSize < w) {
- k.estStepSize = w
- }
- }
- if (Math.abs(o.thickness - (n)) > 1) {
- o.thickness = n;
- k.bbox.plain.dirty = true;
- k.bbox.transform.dirty = true;
- o.doThicknessChanged();
- return false
- }
- }
- },
- renderAxisLine: function(a, i, e, c) {
- var h = this,
- g = h.attr,
- b = g.lineWidth * 0.5,
- j = g.position,
- d, f;
- if (g.axisLine && g.length) {
- switch (j) {
- case "left":
- d = a.roundPixel(c[2]) - b;
- i.moveTo(d, -g.endGap);
- i.lineTo(d, g.length + g.startGap + 1);
- break;
- case "right":
- i.moveTo(b, -g.endGap);
- i.lineTo(b, g.length + g.startGap + 1);
- break;
- case "bottom":
- i.moveTo(-g.startGap, b);
- i.lineTo(g.length + g.endGap, b);
- break;
- case "top":
- d = a.roundPixel(c[3]) - b;
- i.moveTo(-g.startGap, d);
- i.lineTo(g.length + g.endGap, d);
- break;
- case "angular":
- i.moveTo(g.centerX + g.length, g.centerY);
- i.arc(g.centerX, g.centerY, g.length, 0, Math.PI * 2, true);
- break;
- case "gauge":
- f = h.getGaugeAngles();
- i.moveTo(g.centerX + Math.cos(f.start) * g.length, g.centerY + Math.sin(f.start) * g.length);
- i.arc(g.centerX, g.centerY, g.length, f.start, f.end, true);
- break
- }
- }
- },
- getGaugeAngles: function() {
- var a = this,
- c = a.attr.totalAngle,
- b;
- if (c <= Math.PI) {
- b = (Math.PI - c) * 0.5
- } else {
- b = -(Math.PI * 2 - c) * 0.5
- }
- b = Math.PI * 2 - b;
- return {
- start: b,
- end: b - c
- }
- },
- renderGridLines: function(m, n, s, r) {
- var t = this,
- b = t.getAxis(),
- l = t.attr,
- p = l.matrix,
- d = l.startGap,
- a = l.endGap,
- c = p.getXX(),
- k = p.getYY(),
- h = p.getDX(),
- g = p.getDY(),
- u = l.position,
- f = b.getGridAlignment(),
- q = s.majorTicks,
- e, o, i;
- if (l.grid) {
- if (q) {
- if (u === "left" || u === "right") {
- i = l.min * k + g + a + d;
- t.iterate(q, function(j, w, v) {
- e = j * k + g + a;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- y: e,
- height: i - e
- }, o = v, true);
- i = e
- });
- o++;
- e = 0;
- t.putMarker(f + "-" + (o % 2 ? "odd" : "even"), {
- y: e,
- height: i - e
- }, o, true)
- } else {
- if (u === "top" || u === "bottom") {
- i = l.min * c + h + d;
- if (d) {
- t.putMarker(f + "-even", {
- x: 0,
- width: i
- }, -1, true)
- }
- t.iterate(q, function(j, w, v) {
- e = j * c + h + d;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- x: e,
- width: i - e
- }, o = v, true);
- i = e
- });
- o++;
- e = l.length + l.startGap + l.endGap;
- t.putMarker(f + "-" + (o % 2 ? "odd" : "even"), {
- x: e,
- width: i - e
- }, o, true)
- } else {
- if (u === "radial") {
- t.iterate(q, function(j, w, v) {
- if (!j) {
- return
- }
- e = j / l.max * l.length;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- scalingX: e,
- scalingY: e
- }, v, true);
- i = e
- })
- } else {
- if (u === "angular") {
- t.iterate(q, function(j, w, v) {
- if (!l.length) {
- return
- }
- e = j / (l.max + 1) * Math.PI * 2 + l.baseRotation;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- rotationRads: e,
- rotationCenterX: 0,
- rotationCenterY: 0,
- scalingX: l.length,
- scalingY: l.length
- }, v, true);
- i = e
- })
- }
- }
- }
- }
- }
- }
- },
- renderLimits: function(o) {
- var t = this,
- a = t.getAxis(),
- h = a.getChart(),
- p = h.getInnerPadding(),
- d = Ext.Array.from(a.getLimits());
- if (!d.length) {
- return
- }
- var r = a.limits.surface.getRect(),
- m = t.attr,
- n = m.matrix,
- u = m.position,
- k = Ext.Object.chain,
- v = a.limits.titles,
- c, j, b, s, l, q, f, g, e;
- v.instances = [];
- v.position = 0;
- if (u === "left" || u === "right") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l * n.getYY() + n.getDY();
- s.line.y = l + p.top;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("horizontal-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- j = s.line.title.position || (u === "left" ? "start" : "end");
- switch (j) {
- case "start":
- g = 10;
- break;
- case "end":
- g = r[2] - 10;
- break;
- case "middle":
- g = r[2] / 2;
- break
- }
- v.setAttributesFor(v.position - 1, {
- x: g,
- y: s.line.y - c.height / 2,
- textAlign: j,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "top" || u === "bottom") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l * n.getXX() + n.getDX();
- s.line.x = l + p.left;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("vertical-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- j = s.line.title.position || (u === "top" ? "end" : "start");
- switch (j) {
- case "start":
- e = r[3] - c.width / 2 - 10;
- break;
- case "end":
- e = c.width / 2 + 10;
- break;
- case "middle":
- e = r[3] / 2;
- break
- }
- v.setAttributesFor(v.position - 1, {
- x: s.line.x + c.height / 2,
- y: e,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle,
- rotationRads: Math.PI / 2
- })
- }
- }
- } else {
- if (u === "radial") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- if (l > m.max) {
- continue
- }
- l = l / m.max * m.length;
- s.line.cx = m.centerX;
- s.line.cy = m.centerY;
- s.line.scalingX = l;
- s.line.scalingY = l;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("circular-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- v.setAttributesFor(v.position - 1, {
- x: m.centerX,
- y: m.centerY - l - c.height / 2,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "angular") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l / (m.max + 1) * Math.PI * 2 + m.baseRotation;
- s.line.translationX = m.centerX;
- s.line.translationY = m.centerY;
- s.line.rotationRads = l;
- s.line.rotationCenterX = 0;
- s.line.rotationCenterY = 0;
- s.line.scalingX = m.length;
- s.line.scalingY = m.length;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("radial-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- b = ((l > -0.5 * Math.PI && l < 0.5 * Math.PI) || (l > 1.5 * Math.PI && l < 2 * Math.PI)) ? 1 : -1;
- v.setAttributesFor(v.position - 1, {
- x: m.centerX + 0.5 * m.length * Math.cos(l) + b * c.height / 2 * Math.sin(l),
- y: m.centerY + 0.5 * m.length * Math.sin(l) - b * c.height / 2 * Math.cos(l),
- rotationRads: b === 1 ? l : l - Math.PI,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "gauge") {}
- }
- }
- }
- }
- },
- doThicknessChanged: function() {
- var a = this.getAxis();
- if (a) {
- a.onThicknessChanged()
- }
- },
- render: function(a, c, d) {
- var e = this,
- b = e.getLayoutContext();
- if (b) {
- if (false === e.renderLabels(a, c, b, d)) {
- return false
- }
- c.beginPath();
- e.renderTicks(a, c, b, d);
- e.renderAxisLine(a, c, b, d);
- e.renderGridLines(a, c, b, d);
- e.renderLimits(d);
- c.stroke()
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Segmenter", {
- config: {
- axis: null
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- renderer: function(b, a) {
- return String(b)
- },
- from: function(a) {
- return a
- },
- diff: Ext.emptyFn,
- align: Ext.emptyFn,
- add: Ext.emptyFn,
- preferredStep: Ext.emptyFn
-});
-Ext.define("Ext.chart.axis.segmenter.Names", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.names",
- renderer: function(b, a) {
- return b
- },
- diff: function(b, a, c) {
- return Math.floor(a - b)
- },
- align: function(c, b, a) {
- return Math.floor(c)
- },
- add: function(c, b, a) {
- return c + b
- },
- preferredStep: function(c, a, b, d) {
- return {
- unit: 1,
- step: 1
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Numeric", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.numeric",
- isNumeric: true,
- renderer: function(b, a) {
- return b.toFixed(Math.max(0, a.majorTicks.unit.fixes))
- },
- diff: function(b, a, c) {
- return Math.floor((a - b) / c.scale)
- },
- align: function(c, b, a) {
- return Math.floor(c / (a.scale * b)) * a.scale * b
- },
- add: function(c, b, a) {
- return c + b * a.scale
- },
- preferredStep: function(c, b) {
- var a = Math.floor(Math.log(b) * Math.LOG10E),
- d = Math.pow(10, a);
- b /= d;
- if (b < 2) {
- b = 2
- } else {
- if (b < 5) {
- b = 5
- } else {
- if (b < 10) {
- b = 10;
- a++
- }
- }
- }
- return {
- unit: {
- fixes: -a,
- scale: d
- },
- step: b
- }
- },
- exactStep: function(c, b) {
- var a = Math.floor(Math.log(b) * Math.LOG10E),
- d = Math.pow(10, a);
- return {
- unit: {
- fixes: -a + (b % d === 0 ? 0 : 1),
- scale: 1
- },
- step: b
- }
- },
- adjustByMajorUnit: function(e, g, c) {
- var d = c[0],
- b = c[1],
- a = e * g,
- f = d % a;
- if (f !== 0) {
- c[0] = d - f + (d < 0 ? -a : 0)
- }
- f = b % a;
- if (f !== 0) {
- c[1] = b - f + (b > 0 ? a : 0)
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Time", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.time",
- config: {
- step: null
- },
- renderer: function(c, b) {
- var a = Ext.Date;
- switch (b.majorTicks.unit) {
- case "y":
- return a.format(c, "Y");
- case "mo":
- return a.format(c, "Y-m");
- case "d":
- return a.format(c, "Y-m-d")
- }
- return a.format(c, "Y-m-d\nH:i:s")
- },
- from: function(a) {
- return new Date(a)
- },
- diff: function(b, a, c) {
- if (isFinite(b)) {
- b = new Date(b)
- }
- if (isFinite(a)) {
- a = new Date(a)
- }
- return Ext.Date.diff(b, a, c)
- },
- align: function(a, c, b) {
- if (b === "d" && c >= 7) {
- a = Ext.Date.align(a, "d", c);
- a.setDate(a.getDate() - a.getDay() + 1);
- return a
- } else {
- return Ext.Date.align(a, b, c)
- }
- },
- add: function(c, b, a) {
- return Ext.Date.add(new Date(c), a, b)
- },
- stepUnits: [
- [Ext.Date.YEAR, 1, 2, 5, 10, 20, 50, 100, 200, 500],
- [Ext.Date.MONTH, 1, 3, 6],
- [Ext.Date.DAY, 1, 7, 14],
- [Ext.Date.HOUR, 1, 6, 12],
- [Ext.Date.MINUTE, 1, 5, 15, 30],
- [Ext.Date.SECOND, 1, 5, 15, 30],
- [Ext.Date.MILLI, 1, 2, 5, 10, 20, 50, 100, 200, 500]
- ],
- preferredStep: function(b, e) {
- if (this.getStep()) {
- return this.getStep()
- }
- var f = new Date(+b),
- g = new Date(+b + Math.ceil(e)),
- d = this.stepUnits,
- l, k, h, c, a;
- for (c = 0; c < d.length; c++) {
- k = d[c][0];
- h = this.diff(f, g, k);
- if (h > 0) {
- for (a = 1; a < d[c].length; a++) {
- if (h <= d[c][a]) {
- l = {
- unit: k,
- step: d[c][a]
- };
- break
- }
- }
- if (!l) {
- c--;
- l = {
- unit: d[c][0],
- step: 1
- }
- }
- break
- }
- }
- if (!l) {
- l = {
- unit: Ext.Date.DAY,
- step: 1
- }
- }
- return l
- }
-});
-Ext.define("Ext.chart.axis.layout.Layout", {
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- axis: null
- },
- constructor: function(a) {
- this.mixins.observable.constructor.call(this, a)
- },
- processData: function(b) {
- var e = this,
- c = e.getAxis(),
- f = c.getDirection(),
- g = c.boundSeries,
- a, d;
- if (b) {
- b["coordinate" + f]()
- } else {
- for (a = 0, d = g.length; a < d; a++) {
- g[a]["coordinate" + f]()
- }
- }
- },
- calculateMajorTicks: function(a) {
- var f = this,
- e = a.attr,
- d = e.max - e.min,
- i = d / Math.max(1, e.length) * (e.visibleMax - e.visibleMin),
- h = e.min + d * e.visibleMin,
- b = e.min + d * e.visibleMax,
- g = e.estStepSize * i,
- c = f.snapEnds(a, e.min, e.max, g);
- if (c) {
- f.trimByRange(a, c, h, b);
- a.majorTicks = c
- }
- },
- calculateMinorTicks: function(a) {
- if (this.snapMinorEnds) {
- a.minorTicks = this.snapMinorEnds(a)
- }
- },
- calculateLayout: function(b) {
- var c = this,
- a = b.attr;
- if (a.length === 0) {
- return null
- }
- if (a.majorTicks) {
- c.calculateMajorTicks(b);
- if (a.minorTicks) {
- c.calculateMinorTicks(b)
- }
- }
- },
- snapEnds: Ext.emptyFn,
- trimByRange: function(b, f, i, a) {
- var g = b.segmenter,
- j = f.unit,
- h = g.diff(f.from, i, j),
- d = g.diff(f.from, a, j),
- c = Math.max(0, Math.ceil(h / f.step)),
- e = Math.min(f.steps, Math.floor(d / f.step));
- if (e < f.steps) {
- f.to = g.add(f.from, e * f.step, j)
- }
- if (f.max > a) {
- f.max = f.to
- }
- if (f.from < i) {
- f.from = g.add(f.from, c * f.step, j);
- while (f.from < i) {
- c++;
- f.from = g.add(f.from, f.step, j)
- }
- }
- if (f.min < i) {
- f.min = f.from
- }
- f.steps = e - c
- }
-});
-Ext.define("Ext.chart.axis.layout.Discrete", {
- extend: "Ext.chart.axis.layout.Layout",
- alias: "axisLayout.discrete",
- isDiscrete: true,
- processData: function() {
- var f = this,
- d = f.getAxis(),
- c = d.boundSeries,
- g = d.getDirection(),
- b, e, a;
- f.labels = [];
- f.labelMap = {};
- for (b = 0, e = c.length; b < e; b++) {
- a = c[b];
- if (a["get" + g + "Axis"]() === d) {
- a["coordinate" + g]()
- }
- }
- d.getSprites()[0].setAttributes({
- data: f.labels
- });
- f.fireEvent("datachange", f.labels)
- },
- calculateLayout: function(a) {
- a.data = this.labels;
- this.callParent([a])
- },
- calculateMajorTicks: function(a) {
- var g = this,
- f = a.attr,
- d = a.data,
- e = f.max - f.min,
- j = e / Math.max(1, f.length) * (f.visibleMax - f.visibleMin),
- i = f.min + e * f.visibleMin,
- b = f.min + e * f.visibleMax,
- h = f.estStepSize * j;
- var c = g.snapEnds(a, Math.max(0, f.min), Math.min(f.max, d.length - 1), h);
- if (c) {
- g.trimByRange(a, c, i, b);
- a.majorTicks = c
- }
- },
- snapEnds: function(e, d, a, b) {
- b = Math.ceil(b);
- var c = Math.floor((a - d) / b),
- f = e.data;
- return {
- min: d,
- max: a,
- from: d,
- to: c * b + d,
- step: b,
- steps: c,
- unit: 1,
- getLabel: function(g) {
- return f[this.from + this.step * g]
- },
- get: function(g) {
- return this.from + this.step * g
- }
- }
- },
- trimByRange: function(b, f, h, a) {
- var i = f.unit,
- g = Math.ceil((h - f.from) / i) * i,
- d = Math.floor((a - f.from) / i) * i,
- c = Math.max(0, Math.ceil(g / f.step)),
- e = Math.min(f.steps, Math.floor(d / f.step));
- if (e < f.steps) {
- f.to = e
- }
- if (f.max > a) {
- f.max = f.to
- }
- if (f.from < h && f.step > 0) {
- f.from = f.from + c * f.step * i;
- while (f.from < h) {
- c++;
- f.from += f.step * i
- }
- }
- if (f.min < h) {
- f.min = f.from
- }
- f.steps = e - c
- },
- getCoordFor: function(c, d, a, b) {
- this.labels.push(c);
- return this.labels.length - 1
- }
-});
-Ext.define("Ext.chart.axis.layout.CombineDuplicate", {
- extend: "Ext.chart.axis.layout.Discrete",
- alias: "axisLayout.combineDuplicate",
- getCoordFor: function(d, e, b, c) {
- if (!(d in this.labelMap)) {
- var a = this.labelMap[d] = this.labels.length;
- this.labels.push(d);
- return a
- }
- return this.labelMap[d]
- }
-});
-Ext.define("Ext.chart.axis.layout.Continuous", {
- extend: "Ext.chart.axis.layout.Layout",
- alias: "axisLayout.continuous",
- isContinuous: true,
- config: {
- adjustMinimumByMajorUnit: false,
- adjustMaximumByMajorUnit: false
- },
- getCoordFor: function(c, d, a, b) {
- return +c
- },
- snapEnds: function(a, d, i, h) {
- var f = a.segmenter,
- c = this.getAxis(),
- l = c.getMajorTickSteps(),
- e = l && f.exactStep ? f.exactStep(d, (i - d) / l) : f.preferredStep(d, h),
- k = e.unit,
- b = e.step,
- j = f.align(d, b, k),
- g = (l || f.diff(d, i, k)) + 1;
- return {
- min: f.from(d),
- max: f.from(i),
- from: j,
- to: f.add(j, g * b, k),
- step: b,
- steps: g,
- unit: k,
- get: function(m) {
- return f.add(this.from, this.step * m, k)
- }
- }
- },
- snapMinorEnds: function(a) {
- var e = a.majorTicks,
- m = this.getAxis().getMinorTickSteps(),
- f = a.segmenter,
- d = e.min,
- i = e.max,
- k = e.from,
- l = e.unit,
- b = e.step / m,
- n = b * l.scale,
- j = k - d,
- c = Math.floor(j / n),
- h = c + Math.floor((i - e.to) / n) + 1,
- g = e.steps * m + h;
- return {
- min: d,
- max: i,
- from: d + j % n,
- to: f.add(k, g * b, l),
- step: b,
- steps: g,
- unit: l,
- get: function(o) {
- return (o % m + c + 1 !== 0) ? f.add(this.from, this.step * o, l) : null
- }
- }
- }
-});
-Ext.define("Ext.chart.axis.Axis", {
- xtype: "axis",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- requires: ["Ext.chart.axis.sprite.Axis", "Ext.chart.axis.segmenter.*", "Ext.chart.axis.layout.*"],
- isAxis: true,
- config: {
- position: "bottom",
- fields: [],
- label: undefined,
- grid: false,
- limits: null,
- renderer: null,
- chart: null,
- style: null,
- margin: 0,
- titleMargin: 4,
- background: null,
- minimum: NaN,
- maximum: NaN,
- reconcileRange: false,
- minZoom: 1,
- maxZoom: 10000,
- layout: "continuous",
- segmenter: "numeric",
- hidden: false,
- majorTickSteps: 0,
- minorTickSteps: 0,
- adjustByMajorUnit: true,
- title: null,
- increment: 0.5,
- length: 0,
- center: null,
- radius: null,
- totalAngle: Math.PI,
- rotation: null,
- labelInSpan: null,
- visibleRange: [0, 1],
- needHighPrecision: false,
- linkedTo: null,
- floating: null
- },
- titleOffset: 0,
- spriteAnimationCount: 0,
- prevMin: 0,
- prevMax: 1,
- boundSeries: [],
- sprites: null,
- surface: null,
- range: null,
- xValues: [],
- yValues: [],
- masterAxis: null,
- applyRotation: function(b) {
- var a = Math.PI * 2;
- return (b % a + Math.PI) % a - Math.PI
- },
- updateRotation: function(b) {
- var c = this.getSprites(),
- a = this.getPosition();
- if (!this.getHidden() && a === "angular" && c[0]) {
- c[0].setAttributes({
- baseRotation: b
- })
- }
- },
- applyTitle: function(c, b) {
- var a;
- if (Ext.isString(c)) {
- c = {
- text: c
- }
- }
- if (!b) {
- b = Ext.create("sprite.text", c);
- if ((a = this.getSurface())) {
- a.add(b)
- }
- } else {
- b.setAttributes(c)
- }
- return b
- },
- applyFloating: function(b, a) {
- if (b === null) {
- b = {
- value: null,
- alongAxis: null
- }
- } else {
- if (Ext.isNumber(b)) {
- b = {
- value: b,
- alongAxis: null
- }
- }
- }
- if (Ext.isObject(b)) {
- if (a && a.alongAxis) {
- delete this.getChart().getAxis(a.alongAxis).floatingAxes[this.getId()]
- }
- return b
- }
- return a
- },
- constructor: function(a) {
- var b = this,
- c;
- b.sprites = [];
- b.labels = [];
- b.floatingAxes = {};
- a = a || {};
- if (a.position === "angular") {
- a.style = a.style || {};
- a.style.estStepSize = 1
- }
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.mixins.observable.constructor.apply(b, arguments)
- },
- getAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "vertical";
- case "top":
- case "bottom":
- return "horizontal";
- case "radial":
- return "radial";
- case "angular":
- return "angular"
- }
- },
- getGridAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "horizontal";
- case "top":
- case "bottom":
- return "vertical";
- case "radial":
- return "circular";
- case "angular":
- return "radial"
- }
- },
- getSurface: function() {
- var e = this,
- d = e.getChart();
- if (d && !e.surface) {
- var b = e.surface = d.getSurface(e.getId(), "axis"),
- c = e.gridSurface = d.getSurface("main"),
- a = e.getSprites()[0],
- f = e.getGridAlignment();
- c.waitFor(b);
- e.getGrid();
- if (e.getLimits() && f) {
- f = f.replace("3d", "");
- e.limits = {
- surface: d.getSurface("overlay"),
- lines: new Ext.chart.Markers(),
- titles: new Ext.draw.sprite.Instancing()
- };
- e.limits.lines.setTemplate({
- xclass: "grid." + f
- });
- e.limits.lines.getTemplate().setAttributes({
- strokeStyle: "black"
- }, true);
- e.limits.surface.add(e.limits.lines);
- a.bindMarker(f + "-limit-lines", e.limits.lines);
- e.limitTitleTpl = new Ext.draw.sprite.Text();
- e.limits.titles.setTemplate(e.limitTitleTpl);
- e.limits.surface.add(e.limits.titles);
- d.on("redraw", e.renderLimits, e)
- }
- }
- return e.surface
- },
- applyGrid: function(a) {
- if (a === true) {
- return {}
- }
- return a
- },
- updateGrid: function(b) {
- var e = this,
- d = e.getChart();
- if (!d) {
- e.on({
- chartattached: Ext.bind(e.updateGrid, e, [b]),
- single: true
- });
- return
- }
- var c = e.gridSurface,
- a = e.getSprites()[0],
- f = e.getGridAlignment(),
- g;
- if (b) {
- g = e.gridSpriteEven;
- if (!g) {
- g = e.gridSpriteEven = new Ext.chart.Markers();
- g.setTemplate({
- xclass: "grid." + f
- });
- c.add(g);
- a.bindMarker(f + "-even", g)
- }
- if (Ext.isObject(b)) {
- g.getTemplate().setAttributes(b);
- if (Ext.isObject(b.even)) {
- g.getTemplate().setAttributes(b.even)
- }
- }
- g = e.gridSpriteOdd;
- if (!g) {
- g = e.gridSpriteOdd = new Ext.chart.Markers();
- g.setTemplate({
- xclass: "grid." + f
- });
- c.add(g);
- a.bindMarker(f + "-odd", g)
- }
- if (Ext.isObject(b)) {
- g.getTemplate().setAttributes(b);
- if (Ext.isObject(b.odd)) {
- g.getTemplate().setAttributes(b.odd)
- }
- }
- }
- },
- renderLimits: function() {
- this.getSprites()[0].renderLimits()
- },
- getCoordFor: function(c, d, a, b) {
- return this.getLayout().getCoordFor(c, d, a, b)
- },
- applyPosition: function(a) {
- return a.toLowerCase()
- },
- applyLength: function(b, a) {
- return b > 0 ? b : a
- },
- applyLabel: function(b, a) {
- if (!a) {
- a = new Ext.draw.sprite.Text({})
- }
- if (this.limitTitleTpl) {
- this.limitTitleTpl.setAttributes(b)
- }
- a.setAttributes(b);
- return a
- },
- applyLayout: function(b, a) {
- b = Ext.factory(b, null, a, "axisLayout");
- b.setAxis(this);
- return b
- },
- applySegmenter: function(a, b) {
- a = Ext.factory(a, null, b, "segmenter");
- a.setAxis(this);
- return a
- },
- updateMinimum: function() {
- this.range = null
- },
- updateMaximum: function() {
- this.range = null
- },
- hideLabels: function() {
- this.getSprites()[0].setDirty(true);
- this.setLabel({
- hidden: true
- })
- },
- showLabels: function() {
- this.getSprites()[0].setDirty(true);
- this.setLabel({
- hidden: false
- })
- },
- renderFrame: function() {
- this.getSurface().renderFrame()
- },
- updateChart: function(d, b) {
- var c = this,
- a;
- if (b) {
- b.unregister(c);
- b.un("serieschange", c.onSeriesChange, c);
- b.un("redraw", c.renderLimits, c);
- c.linkAxis();
- c.fireEvent("chartdetached", b, c)
- }
- if (d) {
- d.on("serieschange", c.onSeriesChange, c);
- c.surface = null;
- a = c.getSurface();
- c.getLabel().setSurface(a);
- a.add(c.getSprites());
- a.add(c.getTitle());
- d.register(c);
- c.fireEvent("chartattached", d, c)
- }
- },
- applyBackground: function(a) {
- var b = Ext.ClassManager.getByAlias("sprite.rect");
- return b.def.normalize(a)
- },
- processData: function() {
- this.getLayout().processData();
- this.range = null
- },
- getDirection: function() {
- return this.getChart().getDirectionForAxis(this.getPosition())
- },
- isSide: function() {
- var a = this.getPosition();
- return a === "left" || a === "right"
- },
- applyFields: function(a) {
- return Ext.Array.from(a)
- },
- applyVisibleRange: function(a, c) {
- this.getChart();
- if (a[0] > a[1]) {
- var b = a[0];
- a[0] = a[1];
- a[0] = b
- }
- if (a[1] === a[0]) {
- a[1] += 1 / this.getMaxZoom()
- }
- if (a[1] > a[0] + 1) {
- a[0] = 0;
- a[1] = 1
- } else {
- if (a[0] < 0) {
- a[1] -= a[0];
- a[0] = 0
- } else {
- if (a[1] > 1) {
- a[0] -= a[1] - 1;
- a[1] = 1
- }
- }
- }
- if (c && a[0] === c[0] && a[1] === c[1]) {
- return undefined
- }
- return a
- },
- updateVisibleRange: function(a) {
- this.fireEvent("visiblerangechange", this, a)
- },
- onSeriesChange: function(e) {
- var f = this,
- b = e.getSeries(),
- j = "get" + f.getDirection() + "Axis",
- g = [],
- c, d = b.length,
- a, h;
- for (c = 0; c < d; c++) {
- if (this === b[c][j]()) {
- g.push(b[c])
- }
- }
- f.boundSeries = g;
- a = f.getLinkedTo();
- h = !Ext.isEmpty(a) && e.getAxis(a);
- if (h) {
- f.linkAxis(h)
- } else {
- f.getLayout().processData()
- }
- },
- linkAxis: function(a) {
- var c = this;
-
- function b(f, d, e) {
- e.getLayout()[f]("datachange", "onDataChange", d);
- e[f]("rangechange", "onMasterAxisRangeChange", d)
- }
- if (c.masterAxis) {
- b("un", c, c.masterAxis);
- c.masterAxis = null
- }
- if (a) {
- if (a.type !== this.type) {
- Ext.Error.raise("Linked axes must be of the same type.")
- }
- b("on", c, a);
- c.onDataChange(a.getLayout().labels);
- c.onMasterAxisRangeChange(a, a.range);
- c.setStyle(Ext.apply({}, c.config.style, a.config.style));
- c.setTitle(Ext.apply({}, c.config.title, a.config.title));
- c.setLabel(Ext.apply({}, c.config.label, a.config.label));
- c.masterAxis = a
- }
- },
- onDataChange: function(a) {
- this.getLayout().labels = a
- },
- onMasterAxisRangeChange: function(b, a) {
- this.range = a
- },
- applyRange: function(a) {
- if (!a) {
- return this.dataRange.slice(0)
- } else {
- return [a[0] === null ? this.dataRange[0] : a[0], a[1] === null ? this.dataRange[1] : a[1]]
- }
- },
- getRange: function() {
- var m = this;
- if (m.range) {
- return m.range
- } else {
- if (m.masterAxis) {
- return m.masterAxis.range
- }
- }
- if (Ext.isNumber(m.getMinimum() + m.getMaximum())) {
- return m.range = [m.getMinimum(), m.getMaximum()]
- }
- var d = Infinity,
- n = -Infinity,
- o = m.boundSeries,
- h = m.getLayout(),
- l = m.getSegmenter(),
- p = m.getVisibleRange(),
- b = "get" + m.getDirection() + "Range",
- a, j, g, f, e, k;
- for (e = 0, k = o.length; e < k; e++) {
- f = o[e];
- var c = f[b]();
- if (c) {
- if (c[0] < d) {
- d = c[0]
- }
- if (c[1] > n) {
- n = c[1]
- }
- }
- }
- if (!isFinite(n)) {
- n = m.prevMax
- }
- if (!isFinite(d)) {
- d = m.prevMin
- }
- if (m.getLabelInSpan() || d === n) {
- n += m.getIncrement();
- d -= m.getIncrement()
- }
- if (Ext.isNumber(m.getMinimum())) {
- d = m.getMinimum()
- } else {
- m.prevMin = d
- }
- if (Ext.isNumber(m.getMaximum())) {
- n = m.getMaximum()
- } else {
- m.prevMax = n
- }
- m.range = [Ext.Number.correctFloat(d), Ext.Number.correctFloat(n)];
- if (m.getReconcileRange()) {
- m.reconcileRange()
- }
- if (m.getAdjustByMajorUnit() && l.adjustByMajorUnit && !m.getMajorTickSteps()) {
- j = Ext.Object.chain(m.getSprites()[0].attr);
- j.min = m.range[0];
- j.max = m.range[1];
- j.visibleMin = p[0];
- j.visibleMax = p[1];
- a = {
- attr: j,
- segmenter: l
- };
- h.calculateLayout(a);
- g = a.majorTicks;
- if (g) {
- l.adjustByMajorUnit(g.step, g.unit.scale, m.range);
- j.min = m.range[0];
- j.max = m.range[1];
- delete a.majorTicks;
- h.calculateLayout(a);
- g = a.majorTicks;
- l.adjustByMajorUnit(g.step, g.unit.scale, m.range)
- } else {
- if (!m.hasClearRangePending) {
- m.hasClearRangePending = true;
- m.getChart().on("layout", "clearRange", m)
- }
- }
- }
- if (!Ext.Array.equals(m.range, m.oldRange || [])) {
- m.fireEvent("rangechange", m, m.range);
- m.oldRange = m.range
- }
- return m.range
- },
- clearRange: function() {
- delete this.hasClearRangePending;
- this.range = null
- },
- reconcileRange: function() {
- var e = this,
- g = e.getChart().getAxes(),
- f = e.getDirection(),
- b, d, c, a;
- if (!g) {
- return
- }
- for (b = 0, d = g.length; b < d; b++) {
- c = g[b];
- a = c.getRange();
- if (c === e || c.getDirection() !== f || !a || !c.getReconcileRange()) {
- continue
- }
- if (a[0] < e.range[0]) {
- e.range[0] = a[0]
- }
- if (a[1] > e.range[1]) {
- e.range[1] = a[1]
- }
- }
- },
- applyStyle: function(c, b) {
- var a = Ext.ClassManager.getByAlias("sprite." + this.seriesType);
- if (a && a.def) {
- c = a.def.normalize(c)
- }
- b = Ext.apply(b || {}, c);
- return b
- },
- themeOnlyIfConfigured: {
- grid: true
- },
- updateTheme: function(d) {
- var i = this,
- k = d.getAxis(),
- e = i.getPosition(),
- o = i.getInitialConfig(),
- c = i.defaultConfig,
- g = i.getConfigurator().configs,
- a = k.defaults,
- n = k[e],
- h = i.themeOnlyIfConfigured,
- l, j, p, b, m, f;
- k = Ext.merge({}, a, n);
- for (l in k) {
- j = k[l];
- f = g[l];
- if (j !== null && j !== undefined && f) {
- m = o[l];
- p = Ext.isObject(j);
- b = m === c[l];
- if (p) {
- if (b && h[l]) {
- continue
- }
- j = Ext.merge({}, j, m)
- }
- if (b || p) {
- i[f.names.set](j)
- }
- }
- }
- },
- updateCenter: function(b) {
- var e = this.getSprites(),
- a = e[0],
- d = b[0],
- c = b[1];
- if (a) {
- a.setAttributes({
- centerX: d,
- centerY: c
- })
- }
- if (this.gridSpriteEven) {
- this.gridSpriteEven.getTemplate().setAttributes({
- translationX: d,
- translationY: c,
- rotationCenterX: d,
- rotationCenterY: c
- })
- }
- if (this.gridSpriteOdd) {
- this.gridSpriteOdd.getTemplate().setAttributes({
- translationX: d,
- translationY: c,
- rotationCenterX: d,
- rotationCenterY: c
- })
- }
- },
- getSprites: function() {
- if (!this.getChart()) {
- return
- }
- var i = this,
- e = i.getRange(),
- f = i.getPosition(),
- g = i.getChart(),
- c = g.getAnimation(),
- d, a, b = i.getLength(),
- h = i.superclass;
- if (c === false) {
- c = {
- duration: 0
- }
- }
- if (e) {
- a = Ext.applyIf({
- position: f,
- axis: i,
- min: e[0],
- max: e[1],
- length: b,
- grid: i.getGrid(),
- hidden: i.getHidden(),
- titleOffset: i.titleOffset,
- layout: i.getLayout(),
- segmenter: i.getSegmenter(),
- totalAngle: i.getTotalAngle(),
- label: i.getLabel()
- }, i.getStyle());
- if (!i.sprites.length) {
- while (!h.xtype) {
- h = h.superclass
- }
- d = Ext.create("sprite." + h.xtype, a);
- d.fx.setCustomDurations({
- baseRotation: 0
- });
- d.fx.on("animationstart", "onAnimationStart", i);
- d.fx.on("animationend", "onAnimationEnd", i);
- d.setLayout(i.getLayout());
- d.setSegmenter(i.getSegmenter());
- d.setLabel(i.getLabel());
- i.sprites.push(d);
- i.updateTitleSprite()
- } else {
- d = i.sprites[0];
- d.setAnimation(c);
- d.setAttributes(a)
- }
- if (i.getRenderer()) {
- d.setRenderer(i.getRenderer())
- }
- }
- return i.sprites
- },
- updateTitleSprite: function() {
- var f = this,
- b = f.getLength();
- if (!f.sprites[0] || !Ext.isNumber(b)) {
- return
- }
- var h = this.sprites[0].thickness,
- a = f.getSurface(),
- g = f.getTitle(),
- e = f.getPosition(),
- c = f.getMargin(),
- i = f.getTitleMargin(),
- d = a.roundPixel(b / 2);
- if (g) {
- switch (e) {
- case "top":
- g.setAttributes({
- x: d,
- y: c + i / 2,
- textBaseline: "top",
- textAlign: "center"
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().height + i;
- break;
- case "bottom":
- g.setAttributes({
- x: d,
- y: h + i / 2,
- textBaseline: "top",
- textAlign: "center"
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().height + i;
- break;
- case "left":
- g.setAttributes({
- x: c + i / 2,
- y: d,
- textBaseline: "top",
- textAlign: "center",
- rotationCenterX: c + i / 2,
- rotationCenterY: d,
- rotationRads: -Math.PI / 2
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().width + i;
- break;
- case "right":
- g.setAttributes({
- x: h - c + i / 2,
- y: d,
- textBaseline: "bottom",
- textAlign: "center",
- rotationCenterX: h + i / 2,
- rotationCenterY: d,
- rotationRads: Math.PI / 2
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().width + i;
- break
- }
- }
- },
- onThicknessChanged: function() {
- this.getChart().onThicknessChanged()
- },
- getThickness: function() {
- if (this.getHidden()) {
- return 0
- }
- return (this.sprites[0] && this.sprites[0].thickness || 1) + this.titleOffset + this.getMargin()
- },
- onAnimationStart: function() {
- this.spriteAnimationCount++;
- if (this.spriteAnimationCount === 1) {
- this.fireEvent("animationstart", this)
- }
- },
- onAnimationEnd: function() {
- this.spriteAnimationCount--;
- if (this.spriteAnimationCount === 0) {
- this.fireEvent("animationend", this)
- }
- },
- getItemId: function() {
- return this.getId()
- },
- getAncestorIds: function() {
- return [this.getChart().getId()]
- },
- isXType: function(a) {
- return a === "axis"
- },
- resolveListenerScope: function(e) {
- var d = this,
- a = Ext._namedScopes[e],
- c = d.getChart(),
- b;
- if (!a) {
- b = c ? c.resolveListenerScope(e, false) : (e || d)
- } else {
- if (a.isThis) {
- b = d
- } else {
- if (a.isController) {
- b = c ? c.resolveListenerScope(e, false) : d
- } else {
- if (a.isSelf) {
- b = c ? c.resolveListenerScope(e, false) : d;
- if (b === c && !c.getInheritedConfig("defaultListenerScope")) {
- b = d
- }
- }
- }
- }
- }
- return b
- },
- destroy: function() {
- var a = this;
- a.setChart(null);
- a.surface.destroy();
- a.surface = null;
- a.callParent()
- }
-});
-Ext.define("Ext.chart.LegendBase", {
- extend: "Ext.view.View",
- config: {
- tpl: ['', '
', '', "', " {name}", "
", " ", "
"],
- nodeContainerSelector: "div." + Ext.baseCSSPrefix + "legend-container",
- itemSelector: "div." + Ext.baseCSSPrefix + "legend-item",
- docked: "bottom"
- },
- setDocked: function(d) {
- var c = this,
- a = c.ownerCt,
- b;
- c.docked = d;
- switch (d) {
- case "top":
- case "bottom":
- c.addCls(Ext.baseCSSPrefix + "horizontal");
- b = "hbox";
- break;
- case "left":
- case "right":
- c.removeCls(Ext.baseCSSPrefix + "horizontal");
- b = "vbox";
- break
- }
- if (a) {
- a.setDocked(d)
- }
- },
- setStore: function(a) {
- this.bindStore(a)
- },
- clearViewEl: function() {
- this.callParent(arguments);
- Ext.removeNode(this.getNodeContainer())
- },
- onItemClick: function(a, c, b, d) {
- this.callParent(arguments);
- this.toggleItem(b)
- }
-});
-Ext.define("Ext.chart.Legend", {
- xtype: "legend",
- extend: "Ext.chart.LegendBase",
- config: {
- baseCls: Ext.baseCSSPrefix + "legend",
- padding: 5,
- rect: null,
- disableSelection: true,
- toggleable: true
- },
- toggleItem: function(c) {
- if (!this.getToggleable()) {
- return
- }
- var b = this.getStore(),
- h = 0,
- e, g = true,
- d, f, a;
- if (b) {
- f = b.getCount();
- for (d = 0; d < f; d++) {
- a = b.getAt(d);
- if (a.get("disabled")) {
- h++
- }
- }
- g = f - h > 1;
- a = b.getAt(c);
- if (a) {
- e = a.get("disabled");
- if (e || g) {
- a.set("disabled", !e)
- }
- }
- }
- }
-});
-Ext.define("Ext.chart.AbstractChart", {
- extend: "Ext.draw.Container",
- requires: ["Ext.chart.theme.Default", "Ext.chart.series.Series", "Ext.chart.interactions.Abstract", "Ext.chart.axis.Axis", "Ext.data.StoreManager", "Ext.chart.Legend", "Ext.data.Store"],
- isChart: true,
- defaultBindProperty: "store",
- config: {
- store: "ext-empty-store",
- theme: "default",
- style: null,
- animation: !Ext.isIE8,
- series: [],
- axes: [],
- legend: null,
- colors: null,
- insetPadding: {
- top: 10,
- left: 10,
- right: 10,
- bottom: 10
- },
- background: null,
- interactions: [],
- mainRect: null,
- resizeHandler: null,
- highlightItem: null
- },
- animationSuspendCount: 0,
- chartLayoutSuspendCount: 0,
- axisThicknessSuspendCount: 0,
- isThicknessChanged: false,
- surfaceZIndexes: {
- background: 0,
- main: 1,
- grid: 2,
- series: 3,
- axis: 4,
- chart: 5,
- overlay: 6,
- events: 7
- },
- constructor: function(a) {
- var b = this;
- b.itemListeners = {};
- b.surfaceMap = {};
- b.chartComponents = {};
- b.isInitializing = true;
- b.suspendChartLayout();
- b.animationSuspendCount++;
- b.callParent(arguments);
- delete b.isInitializing;
- b.getSurface("main");
- b.getSurface("chart").setFlipRtlText(b.getInherited().rtl);
- b.getSurface("overlay").waitFor(b.getSurface("series"));
- b.animationSuspendCount--;
- b.resumeChartLayout()
- },
- applyAnimation: function(a, b) {
- if (!a) {
- a = {
- duration: 0
- }
- } else {
- if (a === true) {
- a = {
- easing: "easeInOut",
- duration: 500
- }
- }
- }
- return b ? Ext.apply({}, a, b) : a
- },
- getAnimation: function() {
- if (this.animationSuspendCount) {
- return {
- duration: 0
- }
- } else {
- return this.callParent()
- }
- },
- applyInsetPadding: function(b, a) {
- if (!Ext.isObject(b)) {
- return Ext.util.Format.parseBox(b)
- } else {
- if (!a) {
- return b
- } else {
- return Ext.apply(a, b)
- }
- }
- },
- suspendAnimation: function() {
- var d = this,
- c = d.getSeries(),
- e = c.length,
- b = -1,
- a;
- d.animationSuspendCount++;
- if (d.animationSuspendCount === 1) {
- while (++b < e) {
- a = c[b];
- a.setAnimation(a.getAnimation())
- }
- }
- },
- resumeAnimation: function() {
- var d = this,
- c = d.getSeries(),
- f = c.length,
- b = -1,
- a, e;
- d.animationSuspendCount--;
- if (d.animationSuspendCount === 0) {
- while (++b < f) {
- a = c[b];
- e = a.getAnimation();
- a.setAnimation(e.duration && e || d.getAnimation())
- }
- }
- },
- suspendChartLayout: function() {
- this.chartLayoutSuspendCount++;
- if (this.chartLayoutSuspendCount === 1) {
- if (this.scheduledLayoutId) {
- this.layoutInSuspension = true;
- this.cancelChartLayout()
- } else {
- this.layoutInSuspension = false
- }
- }
- },
- resumeChartLayout: function() {
- this.chartLayoutSuspendCount--;
- if (this.chartLayoutSuspendCount === 0) {
- if (this.layoutInSuspension) {
- this.scheduleLayout()
- }
- }
- },
- cancelChartLayout: function() {
- if (this.scheduledLayoutId) {
- Ext.draw.Animator.cancel(this.scheduledLayoutId);
- this.scheduledLayoutId = null
- }
- },
- scheduleLayout: function() {
- var a = this;
- if (a.allowSchedule() && !a.scheduledLayoutId) {
- a.scheduledLayoutId = Ext.draw.Animator.schedule("doScheduleLayout", a)
- }
- },
- allowSchedule: function() {
- return true
- },
- doScheduleLayout: function() {
- if (this.chartLayoutSuspendCount) {
- this.layoutInSuspension = true
- } else {
- this.performLayout()
- }
- },
- suspendThicknessChanged: function() {
- this.axisThicknessSuspendCount++
- },
- resumeThicknessChanged: function() {
- if (this.axisThicknessSuspendCount > 0) {
- this.axisThicknessSuspendCount--;
- if (this.axisThicknessSuspendCount === 0 && this.isThicknessChanged) {
- this.onThicknessChanged()
- }
- }
- },
- onThicknessChanged: function() {
- if (this.axisThicknessSuspendCount === 0) {
- this.isThicknessChanged = false;
- this.performLayout()
- } else {
- this.isThicknessChanged = true
- }
- },
- applySprites: function(b) {
- var a = this.getSurface("chart");
- b = Ext.Array.from(b);
- a.removeAll(true);
- a.add(b);
- return b
- },
- initItems: function() {
- var a = this.items,
- b, d, c;
- if (a && !a.isMixedCollection) {
- this.items = [];
- a = Ext.Array.from(a);
- for (b = 0, d = a.length; b < d; b++) {
- c = a[b];
- if (c.type) {
- Ext.raise("To add custom sprites to the chart use the 'sprites' config.")
- } else {
- this.items.push(c)
- }
- }
- }
- this.callParent()
- },
- applyBackground: function(c, e) {
- var b = this.getSurface("background"),
- d, a, f;
- if (c) {
- if (e) {
- d = e.attr.width;
- a = e.attr.height;
- f = e.type === (c.type || "rect")
- }
- if (c.isSprite) {
- e = c
- } else {
- if (c.type === "image" && Ext.isString(c.src)) {
- if (f) {
- e.setAttributes({
- src: c.src
- })
- } else {
- b.remove(e, true);
- e = b.add(c)
- }
- } else {
- if (f) {
- e.setAttributes({
- fillStyle: c
- })
- } else {
- b.remove(e, true);
- e = b.add({
- type: "rect",
- fillStyle: c,
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0
- }
- }
- })
- }
- }
- }
- }
- if (d && a) {
- e.setAttributes({
- width: d,
- height: a
- })
- }
- e.setAnimation(this.getAnimation());
- return e
- },
- getLegendStore: function() {
- return this.legendStore
- },
- refreshLegendStore: function() {
- if (this.getLegendStore()) {
- var d, e, c = this.getSeries(),
- b, a = [];
- if (c) {
- for (d = 0, e = c.length; d < e; d++) {
- b = c[d];
- if (b.getShowInLegend()) {
- b.provideLegendInfo(a)
- }
- }
- }
- this.getLegendStore().setData(a)
- }
- },
- resetLegendStore: function() {
- var c = this.getLegendStore(),
- e, d, a, b;
- if (c) {
- e = this.getLegendStore().getData().items;
- for (d = 0, a = e.length; d < a; d++) {
- b = e[d];
- b.beginEdit();
- b.set("disabled", false);
- b.commit()
- }
- }
- },
- onUpdateLegendStore: function(b, a) {
- var d = this.getSeries(),
- c;
- if (a && d) {
- c = d.map[a.get("series")];
- if (c) {
- c.setHiddenByIndex(a.get("index"), a.get("disabled"));
- this.redraw()
- }
- }
- },
- defaultResizeHandler: function(a) {
- this.scheduleLayout();
- return false
- },
- applyMainRect: function(a, b) {
- if (!b) {
- return a
- }
- this.getSeries();
- this.getAxes();
- if (a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]) {
- return b
- } else {
- return a
- }
- },
- register: function(a) {
- var b = this.chartComponents,
- c = a.getId();
- b[c] = a
- },
- unregister: function(a) {
- var b = this.chartComponents,
- c = a.getId();
- delete b[c]
- },
- get: function(a) {
- return this.chartComponents[a]
- },
- getAxis: function(a) {
- if (a instanceof Ext.chart.axis.Axis) {
- return a
- } else {
- if (Ext.isNumber(a)) {
- return this.getAxes()[a]
- } else {
- if (Ext.isString(a)) {
- return this.get(a)
- }
- }
- }
- },
- getSurface: function(b, c) {
- b = b || "main";
- c = c || b;
- var d = this,
- a = this.callParent([b]),
- f = d.surfaceZIndexes,
- e = d.surfaceMap;
- if (c in f) {
- a.element.setStyle("zIndex", f[c])
- }
- if (!e[c]) {
- e[c] = []
- }
- if (Ext.Array.indexOf(e[c], a) < 0) {
- a.type = c;
- e[c].push(a);
- a.on("destroy", d.forgetSurface, d)
- }
- return a
- },
- forgetSurface: function(a) {
- var d = this.surfaceMap;
- if (!d || this.isDestroying) {
- return
- }
- var c = d[a.type],
- b = c ? Ext.Array.indexOf(c, a) : -1;
- if (b >= 0) {
- c.splice(b, 1)
- }
- },
- applyAxes: function(b, k) {
- var l = this,
- g = {
- left: "right",
- right: "left"
- },
- m = [],
- c, d, e, a, f, h, j;
- l.animationSuspendCount++;
- l.getStore();
- if (!k) {
- k = [];
- k.map = {}
- }
- j = k.map;
- m.map = {};
- b = Ext.Array.from(b, true);
- for (f = 0, h = b.length; f < h; f++) {
- c = b[f];
- if (!c) {
- continue
- }
- if (c instanceof Ext.chart.axis.Axis) {
- d = j[c.getId()];
- c.setChart(l)
- } else {
- c = Ext.Object.chain(c);
- e = c.linkedTo;
- a = c.id;
- if (Ext.isNumber(e)) {
- c = Ext.merge({}, b[e], c)
- } else {
- if (Ext.isString(e)) {
- Ext.Array.each(b, function(i) {
- if (i.id === c.linkedTo) {
- c = Ext.merge({}, i, c);
- return false
- }
- })
- }
- }
- c.id = a;
- c.chart = l;
- if (l.getInherited().rtl) {
- c.position = g[c.position] || c.position
- }
- a = c.getId && c.getId() || c.id;
- c = Ext.factory(c, null, d = j[a], "axis")
- }
- if (c) {
- m.push(c);
- m.map[c.getId()] = c;
- if (!d) {
- c.on("animationstart", "onAnimationStart", l);
- c.on("animationend", "onAnimationEnd", l)
- }
- }
- }
- for (f in j) {
- if (!m.map[f]) {
- j[f].destroy()
- }
- }
- l.animationSuspendCount--;
- return m
- },
- updateAxes: function() {
- if (!this.isDestroying) {
- this.scheduleLayout()
- }
- },
- circularCopyArray: function(e, f, d) {
- var c = [],
- b, a = e && e.length;
- if (a) {
- for (b = 0; b < d; b++) {
- c.push(e[(f + b) % a])
- }
- }
- return c
- },
- circularCopyObject: function(f, g, d) {
- var c = this,
- b, e, a = {};
- if (d) {
- for (b in f) {
- if (f.hasOwnProperty(b)) {
- e = f[b];
- if (Ext.isArray(e)) {
- a[b] = c.circularCopyArray(e, g, d)
- } else {
- a[b] = e
- }
- }
- }
- }
- return a
- },
- getColors: function() {
- var b = this,
- a = b.config.colors,
- c = b.getTheme();
- if (Ext.isArray(a) && a.length > 0) {
- a = b.applyColors(a)
- }
- return a || (c && c.getColors())
- },
- applyColors: function(a) {
- a = Ext.Array.map(a, function(b) {
- if (Ext.isString(b)) {
- return b
- } else {
- return b.toString()
- }
- });
- return a
- },
- updateColors: function(c) {
- var k = this,
- e = k.getTheme(),
- a = c || (e && e.getColors()),
- l = 0,
- f = k.getSeries(),
- d = f && f.length,
- g, j, b, h;
- if (a.length) {
- for (g = 0; g < d; g++) {
- j = f[g];
- h = j.themeColorCount();
- b = k.circularCopyArray(a, l, h);
- l += h;
- j.updateChartColors(b)
- }
- }
- k.refreshLegendStore()
- },
- applyTheme: function(a) {
- if (a && a.isTheme) {
- return a
- }
- return Ext.Factory.chartTheme(a)
- },
- updateTheme: function(g) {
- var e = this,
- f = e.getAxes(),
- d = e.getSeries(),
- a = e.getColors(),
- c, b;
- e.updateChartTheme(g);
- for (b = 0; b < f.length; b++) {
- f[b].updateTheme(g)
- }
- for (b = 0; b < d.length; b++) {
- c = d[b];
- c.updateTheme(g)
- }
- e.updateSpriteTheme(g);
- e.updateColors(a);
- e.redraw()
- },
- themeOnlyIfConfigured: {},
- updateChartTheme: function(c) {
- var i = this,
- k = c.getChart(),
- n = i.getInitialConfig(),
- b = i.defaultConfig,
- e = i.getConfigurator().configs,
- f = k.defaults,
- g = k[i.xtype],
- h = i.themeOnlyIfConfigured,
- l, j, o, a, m, d;
- k = Ext.merge({}, f, g);
- for (l in k) {
- j = k[l];
- d = e[l];
- if (j !== null && j !== undefined && d) {
- m = n[l];
- o = Ext.isObject(j);
- a = m === b[l];
- if (o) {
- if (a && h[l]) {
- continue
- }
- j = Ext.merge({}, j, m)
- }
- if (a || o) {
- i[d.names.set](j)
- }
- }
- }
- },
- updateSpriteTheme: function(c) {
- this.getSprites();
- var j = this,
- e = j.getSurface("chart"),
- h = e.getItems(),
- m = c.getSprites(),
- k, a, l, f, d, b, g;
- for (b = 0, g = h.length; b < g; b++) {
- k = h[b];
- a = m[k.type];
- if (a) {
- f = {};
- d = k.type === "text";
- for (l in a) {
- if (!(l in k.config)) {
- if (!(d && l.indexOf("font") === 0 && k.config.font)) {
- f[l] = a[l]
- }
- }
- }
- k.setAttributes(f)
- }
- }
- },
- addSeries: function(b) {
- var a = this.getSeries();
- Ext.Array.push(a, b);
- this.setSeries(a)
- },
- removeSeries: function(d) {
- d = Ext.Array.from(d);
- var b = this.getSeries(),
- f = [],
- a = d.length,
- g = {},
- c, e;
- for (c = 0; c < a; c++) {
- e = d[c];
- if (typeof e !== "string") {
- e = e.getId()
- }
- g[e] = true
- }
- for (c = 0, a = b.length; c < a; c++) {
- if (!g[b[c].getId()]) {
- f.push(b[c])
- }
- }
- this.setSeries(f)
- },
- applySeries: function(e, d) {
- var g = this,
- j = [],
- h, a, c, f, b;
- g.animationSuspendCount++;
- g.getAxes();
- if (d) {
- h = d.map
- } else {
- d = [];
- h = d.map = {}
- }
- j.map = {};
- e = Ext.Array.from(e, true);
- for (c = 0, f = e.length; c < f; c++) {
- b = e[c];
- if (!b) {
- continue
- }
- a = h[b.getId && b.getId() || b.id];
- if (b instanceof Ext.chart.series.Series) {
- if (a && a !== b) {
- a.destroy()
- }
- b.setChart(g)
- } else {
- if (Ext.isObject(b)) {
- if (a) {
- a.setConfig(b);
- b = a
- } else {
- if (Ext.isString(b)) {
- b = {
- type: b
- }
- }
- b.chart = g;
- b = Ext.create(b.xclass || ("series." + b.type), b);
- b.on("animationstart", "onAnimationStart", g);
- b.on("animationend", "onAnimationEnd", g)
- }
- }
- }
- j.push(b);
- j.map[b.getId()] = b
- }
- for (c in h) {
- if (!j.map[h[c].getId()]) {
- h[c].destroy()
- }
- }
- g.animationSuspendCount--;
- return j
- },
- applyLegend: function(b, a) {
- return Ext.factory(b, Ext.chart.Legend, a)
- },
- updateLegend: function(b, a) {
- if (a) {
- a.destroy()
- }
- if (b) {
- this.getItems();
- this.legendStore = new Ext.data.Store({
- autoDestroy: true,
- fields: ["id", "name", "mark", "disabled", "series", "index"]
- });
- b.setStore(this.legendStore);
- this.refreshLegendStore();
- this.legendStore.on("update", "onUpdateLegendStore", this)
- }
- },
- updateSeries: function(b, a) {
- var c = this;
- if (c.isDestroying) {
- return
- }
- c.animationSuspendCount++;
- c.fireEvent("serieschange", c, b, a);
- c.refreshLegendStore();
- if (!Ext.isEmpty(b)) {
- c.updateTheme(c.getTheme())
- }
- c.scheduleLayout();
- c.animationSuspendCount--
- },
- applyInteractions: function(h, d) {
- if (!d) {
- d = [];
- d.map = {}
- }
- var g = this,
- a = [],
- c = d.map,
- e, f, b;
- a.map = {};
- h = Ext.Array.from(h, true);
- for (e = 0, f = h.length; e < f; e++) {
- b = h[e];
- if (!b) {
- continue
- }
- b = Ext.factory(b, null, c[b.getId && b.getId() || b.id], "interaction");
- if (b) {
- b.setChart(g);
- a.push(b);
- a.map[b.getId()] = b
- }
- }
- for (e in c) {
- if (!a.map[e]) {
- c[e].destroy()
- }
- }
- return a
- },
- getInteraction: function(e) {
- var f = this.getInteractions(),
- a = f && f.length,
- c = null,
- b, d;
- if (a) {
- for (d = 0; d < a; ++d) {
- b = f[d];
- if (b.type === e) {
- c = b;
- break
- }
- }
- }
- return c
- },
- applyStore: function(a) {
- return a && Ext.StoreManager.lookup(a)
- },
- updateStore: function(a, c) {
- var b = this;
- if (c) {
- c.un({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: b,
- order: "after"
- });
- if (c.autoDestroy) {
- c.destroy()
- }
- }
- if (a) {
- a.on({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: b,
- order: "after"
- })
- }
- b.fireEvent("storechange", b, a, c);
- b.onDataChanged()
- },
- redraw: function() {
- this.fireEvent("redraw", this)
- },
- performLayout: function() {
- var d = this,
- b = d.getChartSize(true),
- c = [0, 0, b.width, b.height],
- a = d.getBackground();
- d.hasFirstLayout = true;
- d.fireEvent("layout", d);
- d.cancelChartLayout();
- d.getSurface("background").setRect(c);
- d.getSurface("chart").setRect(c);
- a.setAttributes({
- width: b.width,
- height: b.height
- })
- },
- getChartSize: function(b) {
- var a = this;
- if (b) {
- a.chartSize = null
- }
- return a.chartSize || (a.chartSize = a.innerElement.getSize())
- },
- getEventXY: function(a) {
- return this.getSurface().getEventXY(a)
- },
- getItemForPoint: function(h, g) {
- var f = this,
- a = f.getSeries(),
- e = f.getMainRect(),
- d = a.length,
- b = f.hasFirstLayout ? d - 1 : -1,
- c, j;
- if (!(e && h >= 0 && h <= e[2] && g >= 0 && g <= e[3])) {
- return null
- }
- for (; b >= 0; b--) {
- c = a[b];
- j = c.getItemForPoint(h, g);
- if (j) {
- return j
- }
- }
- return null
- },
- getItemsForPoint: function(h, g) {
- var f = this,
- a = f.getSeries(),
- d = a.length,
- b = f.hasFirstLayout ? d - 1 : -1,
- e = [],
- c, j;
- for (; b >= 0; b--) {
- c = a[b];
- j = c.getItemForPoint(h, g);
- if (j) {
- e.push(j)
- }
- }
- return e
- },
- onAnimationStart: function() {
- this.fireEvent("animationstart", this)
- },
- onAnimationEnd: function() {
- this.fireEvent("animationend", this)
- },
- onDataChanged: function() {
- var d = this;
- if (d.isInitializing) {
- return
- }
- var c = d.getMainRect(),
- a = d.getStore(),
- b = d.getSeries(),
- e = d.getAxes();
- if (!a || !e || !b) {
- return
- }
- if (!c) {
- d.on({
- redraw: d.onDataChanged,
- scope: d,
- single: true
- });
- return
- }
- d.processData();
- d.redraw()
- },
- recordCount: 0,
- processData: function() {
- var g = this,
- e = g.getStore().getCount(),
- c = g.getSeries(),
- f = c.length,
- d = false,
- b = 0,
- a;
- for (; b < f; b++) {
- a = c[b];
- a.processData();
- if (!d && a.isStoreDependantColorCount) {
- d = true
- }
- }
- if (d && e > g.recordCount) {
- g.updateColors(g.getColors());
- g.recordCount = e
- }
- },
- bindStore: function(a) {
- this.setStore(a)
- },
- applyHighlightItem: function(f, a) {
- if (f === a) {
- return
- }
- if (Ext.isObject(f) && Ext.isObject(a)) {
- var e = f,
- d = a,
- c = e.sprite && (e.sprite[0] || e.sprite),
- b = d.sprite && (d.sprite[0] || d.sprite);
- if (c === b && e.index === d.index) {
- return
- }
- }
- return f
- },
- updateHighlightItem: function(b, a) {
- if (a) {
- a.series.setAttributesForItem(a, {
- highlighted: false
- })
- }
- if (b) {
- b.series.setAttributesForItem(b, {
- highlighted: true
- });
- this.fireEvent("itemhighlight", this, b, a)
- }
- this.fireEvent("itemhighlightchange", this, b, a)
- },
- destroyChart: function() {
- var f = this,
- d = f.getLegend(),
- g = f.getAxes(),
- c = f.getSeries(),
- h = f.getInteractions(),
- b = [],
- a, e;
- f.surfaceMap = null;
- for (a = 0, e = h.length; a < e; a++) {
- h[a].destroy()
- }
- for (a = 0, e = g.length; a < e; a++) {
- g[a].destroy()
- }
- for (a = 0, e = c.length; a < e; a++) {
- c[a].destroy()
- }
- f.setInteractions(b);
- f.setAxes(b);
- f.setSeries(b);
- if (d) {
- d.destroy();
- f.setLegend(null)
- }
- f.legendStore = null;
- f.setStore(null);
- f.cancelChartLayout()
- },
- getRefItems: function(b) {
- var g = this,
- e = g.getSeries(),
- h = g.getAxes(),
- a = g.getInteractions(),
- c = [],
- d, f;
- for (d = 0, f = e.length; d < f; d++) {
- c.push(e[d]);
- if (e[d].getRefItems) {
- c.push.apply(c, e[d].getRefItems(b))
- }
- }
- for (d = 0, f = h.length; d < f; d++) {
- c.push(h[d]);
- if (h[d].getRefItems) {
- c.push.apply(c, h[d].getRefItems(b))
- }
- }
- for (d = 0, f = a.length; d < f; d++) {
- c.push(a[d]);
- if (a[d].getRefItems) {
- c.push.apply(c, a[d].getRefItems(b))
- }
- }
- return c
- }
-});
-Ext.define("Ext.chart.overrides.AbstractChart", {
- override: "Ext.chart.AbstractChart",
- updateLegend: function(b, a) {
- var c;
- this.callParent([b, a]);
- if (b) {
- c = b.docked;
- this.addDocked({
- dock: c,
- xtype: "panel",
- shrinkWrap: true,
- scrollable: true,
- layout: {
- type: c === "top" || c === "bottom" ? "hbox" : "vbox",
- pack: "center"
- },
- items: b,
- cls: Ext.baseCSSPrefix + "legend-panel"
- })
- }
- },
- performLayout: function() {
- if (this.isVisible(true)) {
- return this.callParent()
- }
- this.cancelChartLayout();
- return false
- },
- afterComponentLayout: function(c, a, b, d) {
- this.callParent([c, a, b, d]);
- this.scheduleLayout()
- },
- allowSchedule: function() {
- return this.rendered
- },
- onDestroy: function() {
- this.destroyChart();
- this.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.grid.HorizontalGrid", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "grid.horizontal",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 1,
- height: 1,
- strokeStyle: "#DDD"
- }
- }
- },
- render: function(b, c, e) {
- var a = this.attr,
- f = b.roundPixel(a.y),
- d = c.lineWidth * 0.5;
- c.beginPath();
- c.rect(e[0] - b.matrix.getDX(), f + d, +e[2], a.height);
- c.fill();
- c.beginPath();
- c.moveTo(e[0] - b.matrix.getDX(), f + d);
- c.lineTo(e[0] + e[2] - b.matrix.getDX(), f + d);
- c.stroke()
- }
-});
-Ext.define("Ext.chart.grid.VerticalGrid", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "grid.vertical",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 1,
- height: 1,
- strokeStyle: "#DDD"
- }
- }
- },
- render: function(c, d, f) {
- var b = this.attr,
- a = c.roundPixel(b.x),
- e = d.lineWidth * 0.5;
- d.beginPath();
- d.rect(a - e, f[1] - c.matrix.getDY(), b.width, f[3]);
- d.fill();
- d.beginPath();
- d.moveTo(a - e, f[1] - c.matrix.getDY());
- d.lineTo(a - e, f[1] + f[3] - c.matrix.getDY());
- d.stroke()
- }
-});
-Ext.define("Ext.chart.CartesianChart", {
- extend: "Ext.chart.AbstractChart",
- alternateClassName: "Ext.chart.Chart",
- requires: ["Ext.chart.grid.HorizontalGrid", "Ext.chart.grid.VerticalGrid"],
- xtype: ["cartesian", "chart"],
- isCartesian: true,
- config: {
- flipXY: false,
- innerRect: [0, 0, 1, 1],
- innerPadding: {
- top: 0,
- left: 0,
- right: 0,
- bottom: 0
- }
- },
- applyInnerPadding: function(b, a) {
- if (!Ext.isObject(b)) {
- return Ext.util.Format.parseBox(b)
- } else {
- if (!a) {
- return b
- } else {
- return Ext.apply(a, b)
- }
- }
- },
- getDirectionForAxis: function(a) {
- var b = this.getFlipXY();
- if (a === "left" || a === "right") {
- if (b) {
- return "X"
- } else {
- return "Y"
- }
- } else {
- if (b) {
- return "Y"
- } else {
- return "X"
- }
- }
- },
- performLayout: function() {
- var A = this;
- A.animationSuspendCount++;
- if (A.callParent() === false) {
- --A.animationSuspendCount;
- return
- }
- A.suspendThicknessChanged();
- var d = A.getSurface("chart").getRect(),
- o = d[2],
- n = d[3],
- z = A.getAxes(),
- b, q = A.getSeries(),
- h, l, a, f = A.getInsetPadding(),
- v = A.getInnerPadding(),
- r, c, e = Ext.apply({}, f),
- u, p, s, k, m, y, t, x, g, j = A.getInherited().rtl,
- w = A.getFlipXY();
- if (o <= 0 || n <= 0) {
- return
- }
- for (x = 0; x < z.length; x++) {
- b = z[x];
- l = b.getSurface();
- m = b.getFloating();
- y = m ? m.value : null;
- a = b.getThickness();
- switch (b.getPosition()) {
- case "top":
- l.setRect([0, e.top + 1, o, a]);
- break;
- case "bottom":
- l.setRect([0, n - (e.bottom + a), o, a]);
- break;
- case "left":
- l.setRect([e.left, 0, a, n]);
- break;
- case "right":
- l.setRect([o - (e.right + a), 0, a, n]);
- break
- }
- if (y === null) {
- e[b.getPosition()] += a
- }
- }
- o -= e.left + e.right;
- n -= e.top + e.bottom;
- u = [e.left, e.top, o, n];
- e.left += v.left;
- e.top += v.top;
- e.right += v.right;
- e.bottom += v.bottom;
- p = o - v.left - v.right;
- s = n - v.top - v.bottom;
- A.setInnerRect([e.left, e.top, p, s]);
- if (p <= 0 || s <= 0) {
- return
- }
- A.setMainRect(u);
- A.getSurface().setRect(u);
- for (x = 0, g = A.surfaceMap.grid && A.surfaceMap.grid.length; x < g; x++) {
- c = A.surfaceMap.grid[x];
- c.setRect(u);
- c.matrix.set(1, 0, 0, 1, v.left, v.top);
- c.matrix.inverse(c.inverseMatrix)
- }
- for (x = 0; x < z.length; x++) {
- b = z[x];
- l = b.getSurface();
- t = l.matrix;
- k = t.elements;
- switch (b.getPosition()) {
- case "top":
- case "bottom":
- k[4] = e.left;
- b.setLength(p);
- break;
- case "left":
- case "right":
- k[5] = e.top;
- b.setLength(s);
- break
- }
- b.updateTitleSprite();
- t.inverse(l.inverseMatrix)
- }
- for (x = 0, g = q.length; x < g; x++) {
- h = q[x];
- r = h.getSurface();
- r.setRect(u);
- if (w) {
- if (j) {
- r.matrix.set(0, -1, -1, 0, v.left + p, v.top + s)
- } else {
- r.matrix.set(0, -1, 1, 0, v.left, v.top + s)
- }
- } else {
- r.matrix.set(1, 0, 0, -1, v.left, v.top + s)
- }
- r.matrix.inverse(r.inverseMatrix);
- h.getOverlaySurface().setRect(u)
- }
- A.redraw();
- A.animationSuspendCount--;
- A.resumeThicknessChanged()
- },
- refloatAxes: function() {
- var h = this,
- g = h.getAxes(),
- o = (g && g.length) || 0,
- c, d, n, f, l, b, k, r = h.getChartSize(),
- q = h.getInsetPadding(),
- p = h.getInnerPadding(),
- a = r.width - q.left - q.right,
- m = r.height - q.top - q.bottom,
- j, e;
- for (e = 0; e < o; e++) {
- c = g[e];
- f = c.getFloating();
- l = f ? f.value : null;
- if (l === null) {
- delete c.floatingAtCoord;
- continue
- }
- d = c.getSurface();
- n = d.getRect();
- if (!n) {
- continue
- }
- n = n.slice();
- b = h.getAxis(f.alongAxis);
- if (b) {
- j = b.getAlignment() === "horizontal";
- if (Ext.isString(l)) {
- l = b.getCoordFor(l)
- }
- b.floatingAxes[c.getId()] = l;
- k = b.getSprites()[0].attr.matrix;
- if (j) {
- l = l * k.getXX() + k.getDX();
- c.floatingAtCoord = l + p.left + p.right
- } else {
- l = l * k.getYY() + k.getDY();
- c.floatingAtCoord = l + p.top + p.bottom
- }
- } else {
- j = c.getAlignment() === "horizontal";
- if (j) {
- c.floatingAtCoord = l + p.top + p.bottom
- } else {
- c.floatingAtCoord = l + p.left + p.right
- }
- l = d.roundPixel(0.01 * l * (j ? m : a))
- }
- switch (c.getPosition()) {
- case "top":
- n[1] = q.top + p.top + l - n[3] + 1;
- break;
- case "bottom":
- n[1] = q.top + p.top + (b ? l : m - l);
- break;
- case "left":
- n[0] = q.left + p.left + l - n[2];
- break;
- case "right":
- n[0] = q.left + p.left + (b ? l : a - l) - 1;
- break
- }
- d.setRect(n)
- }
- },
- redraw: function() {
- var C = this,
- r = C.getSeries(),
- z = C.getAxes(),
- b = C.getMainRect(),
- p, t, w = C.getInnerPadding(),
- f, l, s, e, q, A, v, g, d, c, a, k, n, y = C.getFlipXY(),
- x = 1000,
- m, u, h, o, B;
- if (!b) {
- return
- }
- p = b[2] - w.left - w.right;
- t = b[3] - w.top - w.bottom;
- for (A = 0; A < r.length; A++) {
- h = r[A];
- if ((c = h.getXAxis())) {
- n = c.getVisibleRange();
- l = c.getRange();
- l = [l[0] + (l[1] - l[0]) * n[0], l[0] + (l[1] - l[0]) * n[1]]
- } else {
- l = h.getXRange()
- }
- if ((a = h.getYAxis())) {
- n = a.getVisibleRange();
- s = a.getRange();
- s = [s[0] + (s[1] - s[0]) * n[0], s[0] + (s[1] - s[0]) * n[1]]
- } else {
- s = h.getYRange()
- }
- q = {
- visibleMinX: l[0],
- visibleMaxX: l[1],
- visibleMinY: s[0],
- visibleMaxY: s[1],
- innerWidth: p,
- innerHeight: t,
- flipXY: y
- };
- f = h.getSprites();
- for (v = 0, g = f.length; v < g; v++) {
- o = f[v];
- m = o.attr.zIndex;
- if (m < x) {
- m += (A + 1) * 100 + x;
- o.attr.zIndex = m;
- B = o.getMarker("items");
- if (B) {
- u = B.attr.zIndex;
- if (u === Number.MAX_VALUE) {
- B.attr.zIndex = m
- } else {
- if (u < x) {
- B.attr.zIndex = m + u
- }
- }
- }
- }
- o.setAttributes(q, true)
- }
- }
- for (A = 0; A < z.length; A++) {
- d = z[A];
- e = d.isSide();
- f = d.getSprites();
- k = d.getRange();
- n = d.getVisibleRange();
- q = {
- dataMin: k[0],
- dataMax: k[1],
- visibleMin: n[0],
- visibleMax: n[1]
- };
- if (e) {
- q.length = t;
- q.startGap = w.bottom;
- q.endGap = w.top
- } else {
- q.length = p;
- q.startGap = w.left;
- q.endGap = w.right
- }
- for (v = 0, g = f.length; v < g; v++) {
- f[v].setAttributes(q, true)
- }
- }
- C.renderFrame();
- C.callParent(arguments)
- },
- renderFrame: function() {
- this.refloatAxes();
- this.callParent()
- }
-});
-Ext.define("Ext.chart.grid.CircularGrid", {
- extend: "Ext.draw.sprite.Circle",
- alias: "grid.circular",
- inheritableStatics: {
- def: {
- defaults: {
- r: 1,
- strokeStyle: "#DDD"
- }
- }
- }
-});
-Ext.define("Ext.chart.grid.RadialGrid", {
- extend: "Ext.draw.sprite.Path",
- alias: "grid.radial",
- inheritableStatics: {
- def: {
- processors: {
- startRadius: "number",
- endRadius: "number"
- },
- defaults: {
- startRadius: 0,
- endRadius: 1,
- scalingCenterX: 0,
- scalingCenterY: 0,
- strokeStyle: "#DDD"
- },
- triggers: {
- startRadius: "path,bbox",
- endRadius: "path,bbox"
- }
- }
- },
- render: function() {
- this.callParent(arguments)
- },
- updatePath: function(d, a) {
- var b = a.startRadius,
- c = a.endRadius;
- d.moveTo(b, 0);
- d.lineTo(c, 0)
- }
-});
-Ext.define("Ext.chart.PolarChart", {
- extend: "Ext.chart.AbstractChart",
- requires: ["Ext.chart.grid.CircularGrid", "Ext.chart.grid.RadialGrid"],
- xtype: "polar",
- isPolar: true,
- config: {
- center: [0, 0],
- radius: 0,
- innerPadding: 0
- },
- getDirectionForAxis: function(a) {
- return a === "radial" ? "Y" : "X"
- },
- applyCenter: function(a, b) {
- if (b && a[0] === b[0] && a[1] === b[1]) {
- return
- }
- return [+a[0], +a[1]]
- },
- updateCenter: function(a) {
- var g = this,
- h = g.getAxes(),
- d = g.getSeries(),
- c, f, e, b;
- for (c = 0, f = h.length; c < f; c++) {
- e = h[c];
- e.setCenter(a)
- }
- for (c = 0, f = d.length; c < f; c++) {
- b = d[c];
- b.setCenter(a)
- }
- },
- applyInnerPadding: function(b, a) {
- return Ext.isNumber(b) ? b : a
- },
- doSetSurfaceRect: function(b, c) {
- var a = this.getMainRect();
- b.setRect(c);
- b.matrix.set(1, 0, 0, 1, a[0] - c[0], a[1] - c[1]);
- b.inverseMatrix.set(1, 0, 0, 1, c[0] - a[0], c[1] - a[1])
- },
- applyAxes: function(f, h) {
- var e = this,
- g = Ext.Array.from(e.config.series)[0],
- b, d, c, a;
- if (g.type === "radar" && f && f.length) {
- for (b = 0, d = f.length; b < d; b++) {
- c = f[b];
- if (c.position === "angular") {
- a = true;
- break
- }
- }
- if (!a) {
- f.push({
- type: "category",
- position: "angular",
- fields: g.xField || g.angleField,
- style: {
- estStepSize: 1
- },
- grid: true
- })
- }
- }
- return this.callParent(arguments)
- },
- performLayout: function() {
- var F = this,
- g = true;
- try {
- F.animationSuspendCount++;
- if (this.callParent() === false) {
- g = false;
- return
- }
- F.suspendThicknessChanged();
- var h = F.getSurface("chart").getRect(),
- v = F.getInsetPadding(),
- G = F.getInnerPadding(),
- l = Ext.apply({}, v),
- d, s = h[2] - v.left - v.right,
- r = h[3] - v.top - v.bottom,
- x = [v.left, v.top, s, r],
- u = F.getSeries(),
- p, t = s - G * 2,
- w = r - G * 2,
- D = [t * 0.5 + G, w * 0.5 + G],
- j = Math.min(t, w) * 0.5,
- A = F.getAxes(),
- f, a, k, m = [],
- o = [],
- E = j - G,
- z, n, b, q, y, c, C;
- F.setMainRect(x);
- F.doSetSurfaceRect(F.getSurface(), x);
- for (z = 0, n = F.surfaceMap.grid && F.surfaceMap.grid.length; z < n; z++) {
- F.doSetSurfaceRect(F.surfaceMap.grid[z], h)
- }
- for (z = 0, n = A.length; z < n; z++) {
- f = A[z];
- switch (f.getPosition()) {
- case "angular":
- m.push(f);
- break;
- case "radial":
- o.push(f);
- break
- }
- }
- for (z = 0, n = m.length; z < n; z++) {
- f = m[z];
- q = f.getFloating();
- y = q ? q.value : null;
- F.doSetSurfaceRect(f.getSurface(), h);
- a = f.getThickness();
- for (d in l) {
- l[d] += a
- }
- s = h[2] - l.left - l.right;
- r = h[3] - l.top - l.bottom;
- b = Math.min(s, r) * 0.5;
- if (z === 0) {
- E = b - G
- }
- f.setMinimum(0);
- f.setLength(b);
- f.getSprites();
- k = f.sprites[0].attr.lineWidth * 0.5;
- for (d in l) {
- l[d] += k
- }
- }
- for (z = 0, n = o.length; z < n; z++) {
- f = o[z];
- F.doSetSurfaceRect(f.getSurface(), h);
- f.setMinimum(0);
- f.setLength(E);
- f.getSprites()
- }
- for (z = 0, n = u.length; z < n; z++) {
- p = u[z];
- if (p.type === "gauge" && !c) {
- c = p
- } else {
- p.setRadius(E)
- }
- F.doSetSurfaceRect(p.getSurface(), x)
- }
- F.doSetSurfaceRect(F.getSurface("overlay"), h);
- if (c) {
- c.setRect(x);
- C = c.getRadius() - G;
- F.setRadius(C);
- F.setCenter(c.getCenter());
- c.setRadius(C);
- if (A.length && A[0].getPosition() === "gauge") {
- f = A[0];
- F.doSetSurfaceRect(f.getSurface(), h);
- f.setTotalAngle(c.getTotalAngle());
- f.setLength(C)
- }
- } else {
- F.setRadius(j);
- F.setCenter(D)
- }
- F.redraw()
- } catch (B) {
- throw B
- } finally {
- F.animationSuspendCount--;
- if (g) {
- F.resumeThicknessChanged()
- }
- }
- },
- refloatAxes: function() {
- var j = this,
- g = j.getAxes(),
- h = j.getMainRect(),
- f, k, b, d, a, c, e;
- if (!h) {
- return
- }
- e = 0.5 * Math.min(h[2], h[3]);
- for (d = 0, a = g.length; d < a; d++) {
- c = g[d];
- f = c.getFloating();
- k = f ? f.value : null;
- if (k !== null) {
- b = j.getAxis(f.alongAxis);
- if (c.getPosition() === "angular") {
- if (b) {
- k = b.getLength() * k / b.getRange()[1]
- } else {
- k = 0.01 * k * e
- }
- c.sprites[0].setAttributes({
- length: k
- }, true)
- } else {
- if (b) {
- if (Ext.isString(k)) {
- k = b.getCoordFor(k)
- }
- k = k / (b.getRange()[1] + 1) * Math.PI * 2 - Math.PI * 1.5 + c.getRotation()
- } else {
- k = Ext.draw.Draw.rad(k)
- }
- c.sprites[0].setAttributes({
- baseRotation: k
- }, true)
- }
- }
- }
- },
- redraw: function() {
- var f = this,
- g = f.getAxes(),
- d, c = f.getSeries(),
- b, a, e;
- for (a = 0, e = g.length; a < e; a++) {
- d = g[a];
- d.getSprites()
- }
- for (a = 0, e = c.length; a < e; a++) {
- b = c[a];
- b.getSprites()
- }
- f.renderFrame();
- f.callParent(arguments)
- },
- renderFrame: function() {
- this.refloatAxes();
- this.callParent()
- }
-});
-Ext.define("Ext.chart.SpaceFillingChart", {
- extend: "Ext.chart.AbstractChart",
- xtype: "spacefilling",
- config: {},
- performLayout: function() {
- var j = this;
- try {
- j.animationSuspendCount++;
- if (j.callParent() === false) {
- return
- }
- var k = j.getSurface("chart").getRect(),
- l = j.getInsetPadding(),
- a = k[2] - l.left - l.right,
- m = k[3] - l.top - l.bottom,
- h = [l.left, l.top, a, m],
- b = j.getSeries(),
- d, c, g;
- j.getSurface().setRect(h);
- j.setMainRect(h);
- for (c = 0, g = b.length; c < g; c++) {
- d = b[c];
- d.getSurface().setRect(h);
- if (d.setRect) {
- d.setRect(h)
- }
- d.getOverlaySurface().setRect(k)
- }
- j.redraw()
- } catch (f) {
- throw f
- } finally {
- j.animationSuspendCount--
- }
- },
- redraw: function() {
- var e = this,
- c = e.getSeries(),
- b, a, d;
- for (a = 0, d = c.length; a < d; a++) {
- b = c[a];
- b.getSprites()
- }
- e.renderFrame();
- e.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.axis.sprite.Axis3D", {
- extend: "Ext.chart.axis.sprite.Axis",
- alias: "sprite.axis3d",
- type: "axis3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- },
- triggers: {
- depth: "layout"
- }
- }
- },
- config: {
- fx: {
- customDurations: {
- depth: 0
- }
- }
- },
- layoutUpdater: function() {
- var h = this,
- f = h.getAxis().getChart();
- if (f.isInitializing) {
- return
- }
- var e = h.attr,
- d = h.getLayout(),
- c = d.isDiscrete ? 0 : e.depth,
- g = f.getInherited().rtl,
- b = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMin,
- i = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMax,
- a = {
- attr: e,
- segmenter: h.getSegmenter(),
- renderer: h.defaultRenderer
- };
- if (e.position === "left" || e.position === "right") {
- e.translationX = 0;
- e.translationY = i * (e.length - c) / (i - b) + c;
- e.scalingX = 1;
- e.scalingY = (-e.length + c) / (i - b);
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- } else {
- if (e.position === "top" || e.position === "bottom") {
- if (g) {
- e.translationX = e.length + b * e.length / (i - b) + 1
- } else {
- e.translationX = -b * e.length / (i - b)
- }
- e.translationY = 0;
- e.scalingX = (g ? -1 : 1) * (e.length - c) / (i - b);
- e.scalingY = 1;
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- }
- }
- if (d) {
- d.calculateLayout(a);
- h.setLayoutContext(a)
- }
- },
- renderAxisLine: function(a, j, f, c) {
- var i = this,
- h = i.attr,
- b = h.lineWidth * 0.5,
- f = i.getLayout(),
- d = f.isDiscrete ? 0 : h.depth,
- k = h.position,
- e, g;
- if (h.axisLine && h.length) {
- switch (k) {
- case "left":
- e = a.roundPixel(c[2]) - b;
- j.moveTo(e, -h.endGap + d);
- j.lineTo(e, h.length + h.startGap);
- break;
- case "right":
- j.moveTo(b, -h.endGap);
- j.lineTo(b, h.length + h.startGap);
- break;
- case "bottom":
- j.moveTo(-h.startGap, b);
- j.lineTo(h.length - d + h.endGap, b);
- break;
- case "top":
- e = a.roundPixel(c[3]) - b;
- j.moveTo(-h.startGap, e);
- j.lineTo(h.length + h.endGap, e);
- break;
- case "angular":
- j.moveTo(h.centerX + h.length, h.centerY);
- j.arc(h.centerX, h.centerY, h.length, 0, Math.PI * 2, true);
- break;
- case "gauge":
- g = i.getGaugeAngles();
- j.moveTo(h.centerX + Math.cos(g.start) * h.length, h.centerY + Math.sin(g.start) * h.length);
- j.arc(h.centerX, h.centerY, h.length, g.start, g.end, true);
- break
- }
- }
- }
-});
-Ext.define("Ext.chart.axis.Axis3D", {
- extend: "Ext.chart.axis.Axis",
- xtype: "axis3d",
- requires: ["Ext.chart.axis.sprite.Axis3D"],
- config: {
- depth: 0
- },
- onSeriesChange: function(e) {
- var g = this,
- b = "depthchange",
- f = "onSeriesDepthChange",
- d, c;
-
- function a(h) {
- var i = g.boundSeries;
- for (d = 0; d < i.length; d++) {
- c = i[d];
- c[h](b, f, g)
- }
- }
- a("un");
- g.callParent(arguments);
- a("on")
- },
- onSeriesDepthChange: function(b, f) {
- var d = this,
- g = f,
- e = d.boundSeries,
- a, c;
- if (f > d.getDepth()) {
- g = f
- } else {
- for (a = 0; a < e.length; a++) {
- c = e[a];
- if (c !== b && c.getDepth) {
- f = c.getDepth();
- if (f > g) {
- g = f
- }
- }
- }
- }
- d.setDepth(g)
- },
- updateDepth: function(d) {
- var b = this,
- c = b.getSprites(),
- a = {
- depth: d
- };
- if (c && c.length) {
- c[0].setAttributes(a)
- }
- if (b.gridSpriteEven && b.gridSpriteOdd) {
- b.gridSpriteEven.getTemplate().setAttributes(a);
- b.gridSpriteOdd.getTemplate().setAttributes(a)
- }
- },
- getGridAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "horizontal3d";
- case "top":
- case "bottom":
- return "vertical3d"
- }
- }
-});
-Ext.define("Ext.chart.axis.Category", {
- requires: ["Ext.chart.axis.layout.CombineDuplicate", "Ext.chart.axis.segmenter.Names"],
- extend: "Ext.chart.axis.Axis",
- alias: "axis.category",
- type: "category",
- config: {
- layout: "combineDuplicate",
- segmenter: "names"
- }
-});
-Ext.define("Ext.chart.axis.Category3D", {
- requires: ["Ext.chart.axis.layout.CombineDuplicate", "Ext.chart.axis.segmenter.Names"],
- extend: "Ext.chart.axis.Axis3D",
- alias: "axis.category3d",
- type: "category3d",
- config: {
- layout: "combineDuplicate",
- segmenter: "names"
- }
-});
-Ext.define("Ext.chart.axis.Numeric", {
- extend: "Ext.chart.axis.Axis",
- type: "numeric",
- alias: ["axis.numeric", "axis.radial"],
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Numeric"],
- config: {
- layout: "continuous",
- segmenter: "numeric",
- aggregator: "double"
- }
-});
-Ext.define("Ext.chart.axis.Numeric3D", {
- extend: "Ext.chart.axis.Axis3D",
- alias: ["axis.numeric3d"],
- type: "numeric3d",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Numeric"],
- config: {
- layout: "continuous",
- segmenter: "numeric",
- aggregator: "double"
- }
-});
-Ext.define("Ext.chart.axis.Time", {
- extend: "Ext.chart.axis.Numeric",
- alias: "axis.time",
- type: "time",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Time"],
- config: {
- calculateByLabelSize: true,
- dateFormat: null,
- fromDate: null,
- toDate: null,
- step: [Ext.Date.DAY, 1],
- layout: "continuous",
- segmenter: "time",
- aggregator: "time"
- },
- updateDateFormat: function(a) {
- this.setRenderer(function(c, b) {
- return Ext.Date.format(new Date(b), a)
- })
- },
- updateFromDate: function(a) {
- this.setMinimum(+a)
- },
- updateToDate: function(a) {
- this.setMaximum(+a)
- },
- getCoordFor: function(a) {
- if (Ext.isString(a)) {
- a = new Date(a)
- }
- return +a
- }
-});
-Ext.define("Ext.chart.axis.Time3D", {
- extend: "Ext.chart.axis.Numeric3D",
- alias: "axis.time3d",
- type: "time3d",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Time"],
- config: {
- calculateByLabelSize: true,
- dateFormat: null,
- fromDate: null,
- toDate: null,
- step: [Ext.Date.DAY, 1],
- layout: "continuous",
- segmenter: "time",
- aggregator: "time"
- },
- updateDateFormat: function(a) {
- this.setRenderer(function(c, b) {
- return Ext.Date.format(new Date(b), a)
- })
- },
- updateFromDate: function(a) {
- this.setMinimum(+a)
- },
- updateToDate: function(a) {
- this.setMaximum(+a)
- },
- getCoordFor: function(a) {
- if (Ext.isString(a)) {
- a = new Date(a)
- }
- return +a
- }
-});
-Ext.define("Ext.chart.grid.HorizontalGrid3D", {
- extend: "Ext.chart.grid.HorizontalGrid",
- alias: "grid.horizontal3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- }
- }
- },
- render: function(a, k, d) {
- var f = this.attr,
- i = a.roundPixel(f.x),
- h = a.roundPixel(f.y),
- l = a.matrix.getDX(),
- c = k.lineWidth * 0.5,
- j = f.height,
- e = f.depth,
- b, g;
- if (h <= d[1]) {
- return
- }
- b = d[0] + e - l;
- g = h + c - e;
- k.beginPath();
- k.rect(b, g, d[2], j);
- k.fill();
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + d[2], g);
- k.stroke();
- b = d[0] + i - l;
- g = h + c;
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + e, g - e);
- k.lineTo(b + e, g - e + j);
- k.lineTo(b, g + j);
- k.closePath();
- k.fill();
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + e, g - e);
- k.stroke()
- }
-});
-Ext.define("Ext.chart.grid.VerticalGrid3D", {
- extend: "Ext.chart.grid.VerticalGrid",
- alias: "grid.vertical3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- }
- }
- },
- render_: function(c, d, f) {
- var b = this.attr,
- a = c.roundPixel(b.x),
- e = d.lineWidth * 0.5;
- d.beginPath();
- d.rect(a - e, f[1] - c.matrix.getDY(), b.width, f[3]);
- d.fill();
- d.beginPath();
- d.moveTo(a - e, f[1] - c.matrix.getDY());
- d.lineTo(a - e, f[1] + f[3] - c.matrix.getDY());
- d.stroke()
- },
- render: function(b, j, e) {
- var g = this.attr,
- i = b.roundPixel(g.x),
- k = b.matrix.getDY(),
- d = j.lineWidth * 0.5,
- a = g.width,
- f = g.depth,
- c, h;
- if (i >= e[2]) {
- return
- }
- c = i - d + f;
- h = e[1] - f - k;
- j.beginPath();
- j.rect(c, h, a, e[3]);
- j.fill();
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c, h + e[3]);
- j.stroke();
- c = i - d;
- h = e[3];
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c + f, h - f);
- j.lineTo(c + f + a, h - f);
- j.lineTo(c + a, h);
- j.closePath();
- j.fill();
- c = i - d;
- h = e[3];
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c + f, h - f);
- j.stroke()
- }
-});
-Ext.define("Ext.chart.interactions.CrossZoom", {
- extend: "Ext.chart.interactions.Abstract",
- type: "crosszoom",
- alias: "interaction.crosszoom",
- isCrossZoom: true,
- config: {
- axes: true,
- gestures: {
- dragstart: "onGestureStart",
- drag: "onGesture",
- dragend: "onGestureEnd",
- dblclick: "onDoubleTap"
- },
- undoButton: {}
- },
- stopAnimationBeforeSync: false,
- zoomAnimationInProgress: false,
- constructor: function() {
- this.callParent(arguments);
- this.zoomHistory = []
- },
- applyAxes: function(b) {
- var a = {};
- if (b === true) {
- return {
- top: {},
- right: {},
- bottom: {},
- left: {}
- }
- } else {
- if (Ext.isArray(b)) {
- a = {};
- Ext.each(b, function(c) {
- a[c] = {}
- })
- } else {
- if (Ext.isObject(b)) {
- Ext.iterate(b, function(c, d) {
- if (d === true) {
- a[c] = {}
- } else {
- if (d !== false) {
- a[c] = d
- }
- }
- })
- }
- }
- }
- return a
- },
- applyUndoButton: function(b, a) {
- var c = this;
- if (a) {
- a.destroy()
- }
- if (b) {
- return Ext.create("Ext.Button", Ext.apply({
- cls: [],
- text: "Undo Zoom",
- disabled: true,
- handler: function() {
- c.undoZoom()
- }
- }, b))
- }
- },
- getSurface: function() {
- return this.getChart() && this.getChart().getSurface("main")
- },
- setSeriesOpacity: function(b) {
- var a = this.getChart() && this.getChart().getSurface("series");
- if (a) {
- a.element.setStyle("opacity", b)
- }
- },
- onGestureStart: function(h) {
- var j = this,
- i = j.getChart(),
- d = j.getSurface(),
- l = i.getInnerRect(),
- c = i.getInnerPadding(),
- g = c.left,
- b = g + l[2],
- f = c.top,
- a = f + l[3],
- n = i.getEventXY(h),
- m = n[0],
- k = n[1];
- if (j.zoomAnimationInProgress) {
- return
- }
- if (m > g && m < b && k > f && k < a) {
- j.gestureEvent = "drag";
- j.lockEvents(j.gestureEvent);
- j.startX = m;
- j.startY = k;
- j.selectionRect = d.add({
- type: "rect",
- globalAlpha: 0.5,
- fillStyle: "rgba(80,80,140,0.5)",
- strokeStyle: "rgba(80,80,140,1)",
- lineWidth: 2,
- x: m,
- y: k,
- width: 0,
- height: 0,
- zIndex: 10000
- });
- j.setSeriesOpacity(0.8);
- return false
- }
- },
- onGesture: function(h) {
- var j = this;
- if (j.zoomAnimationInProgress) {
- return
- }
- if (j.getLocks()[j.gestureEvent] === j) {
- var i = j.getChart(),
- d = j.getSurface(),
- l = i.getInnerRect(),
- c = i.getInnerPadding(),
- g = c.left,
- b = g + l[2],
- f = c.top,
- a = f + l[3],
- n = i.getEventXY(h),
- m = n[0],
- k = n[1];
- if (m < g) {
- m = g
- } else {
- if (m > b) {
- m = b
- }
- }
- if (k < f) {
- k = f
- } else {
- if (k > a) {
- k = a
- }
- }
- j.selectionRect.setAttributes({
- width: m - j.startX,
- height: k - j.startY
- });
- if (Math.abs(j.startX - m) < 11 || Math.abs(j.startY - k) < 11) {
- j.selectionRect.setAttributes({
- globalAlpha: 0.5
- })
- } else {
- j.selectionRect.setAttributes({
- globalAlpha: 1
- })
- }
- d.renderFrame();
- return false
- }
- },
- onGestureEnd: function(i) {
- var l = this;
- if (l.zoomAnimationInProgress) {
- return
- }
- if (l.getLocks()[l.gestureEvent] === l) {
- var k = l.getChart(),
- d = l.getSurface(),
- n = k.getInnerRect(),
- c = k.getInnerPadding(),
- g = c.left,
- b = g + n[2],
- f = c.top,
- a = f + n[3],
- h = n[2],
- j = n[3],
- p = k.getEventXY(i),
- o = p[0],
- m = p[1];
- if (o < g) {
- o = g
- } else {
- if (o > b) {
- o = b
- }
- }
- if (m < f) {
- m = f
- } else {
- if (m > a) {
- m = a
- }
- }
- if (Math.abs(l.startX - o) < 11 || Math.abs(l.startY - m) < 11) {
- d.remove(l.selectionRect)
- } else {
- l.zoomBy([Math.min(l.startX, o) / h, 1 - Math.max(l.startY, m) / j, Math.max(l.startX, o) / h, 1 - Math.min(l.startY, m) / j]);
- l.selectionRect.setAttributes({
- x: Math.min(l.startX, o),
- y: Math.min(l.startY, m),
- width: Math.abs(l.startX - o),
- height: Math.abs(l.startY - m)
- });
- l.selectionRect.setAnimation(k.getAnimation() || {
- duration: 0
- });
- l.selectionRect.setAttributes({
- globalAlpha: 0,
- x: 0,
- y: 0,
- width: h,
- height: j
- });
- l.zoomAnimationInProgress = true;
- k.suspendThicknessChanged();
- l.selectionRect.fx.on("animationend", function() {
- k.resumeThicknessChanged();
- d.remove(l.selectionRect);
- l.selectionRect = null;
- l.zoomAnimationInProgress = false
- })
- }
- d.renderFrame();
- l.sync();
- l.unlockEvents(l.gestureEvent);
- l.setSeriesOpacity(1);
- if (!l.zoomAnimationInProgress) {
- d.remove(l.selectionRect);
- l.selectionRect = null
- }
- }
- },
- zoomBy: function(o) {
- var n = this,
- a = n.getAxes(),
- k = n.getChart(),
- j = k.getAxes(),
- l = k.getInherited().rtl,
- f, d = {},
- c, b;
- if (l) {
- o = o.slice();
- c = 1 - o[0];
- b = 1 - o[2];
- o[0] = Math.min(c, b);
- o[2] = Math.max(c, b)
- }
- for (var h = 0; h < j.length; h++) {
- var g = j[h];
- f = a[g.getPosition()];
- if (f && f.allowZoom !== false) {
- var e = g.isSide(),
- m = g.getVisibleRange();
- d[g.getId()] = m.slice(0);
- if (!e) {
- g.setVisibleRange([(m[1] - m[0]) * o[0] + m[0], (m[1] - m[0]) * o[2] + m[0]])
- } else {
- g.setVisibleRange([(m[1] - m[0]) * o[1] + m[0], (m[1] - m[0]) * o[3] + m[0]])
- }
- }
- }
- n.zoomHistory.push(d);
- n.getUndoButton().setDisabled(false)
- },
- undoZoom: function() {
- var c = this.zoomHistory.pop(),
- d = this.getChart().getAxes();
- if (c) {
- for (var a = 0; a < d.length; a++) {
- var b = d[a];
- if (c[b.getId()]) {
- b.setVisibleRange(c[b.getId()])
- }
- }
- }
- this.getUndoButton().setDisabled(this.zoomHistory.length === 0);
- this.sync()
- },
- onDoubleTap: function(a) {
- this.undoZoom()
- },
- destroy: function() {
- this.setUndoButton(null);
- this.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.interactions.Crosshair", {
- extend: "Ext.chart.interactions.Abstract",
- requires: ["Ext.chart.grid.HorizontalGrid", "Ext.chart.grid.VerticalGrid", "Ext.chart.CartesianChart", "Ext.chart.axis.layout.Discrete"],
- type: "crosshair",
- alias: "interaction.crosshair",
- config: {
- axes: {
- top: {
- label: {},
- rect: {}
- },
- right: {
- label: {},
- rect: {}
- },
- bottom: {
- label: {},
- rect: {}
- },
- left: {
- label: {},
- rect: {}
- }
- },
- lines: {
- horizontal: {
- strokeStyle: "black",
- lineDash: [5, 5]
- },
- vertical: {
- strokeStyle: "black",
- lineDash: [5, 5]
- }
- },
- gesture: "drag"
- },
- applyAxes: function(b, a) {
- return Ext.merge(a || {}, b)
- },
- applyLines: function(a, b) {
- return Ext.merge(b || {}, a)
- },
- updateChart: function(a) {
- if (a && !a.isCartesian) {
- Ext.raise("Crosshair interaction can only be used on cartesian charts.")
- }
- this.callParent(arguments)
- },
- getGestures: function() {
- var a = this,
- b = {};
- b[a.getGesture()] = "onGesture";
- b[a.getGesture() + "start"] = "onGestureStart";
- b[a.getGesture() + "end"] = "onGestureEnd";
- return b
- },
- onGestureStart: function(N) {
- var m = this,
- O = m.getChart(),
- B = O.getTheme().getAxis(),
- A, F = O.getSurface("overlay"),
- s = O.getInnerRect(),
- n = s[2],
- M = s[3],
- r = O.getEventXY(N),
- D = r[0],
- C = r[1],
- E = O.getAxes(),
- u = m.getAxes(),
- h = m.getLines(),
- q, v, b, d, k, z, G, L, J, o, I, w, l, f, p, j, t, a, g, H, c, K;
- if (D > 0 && D < n && C > 0 && C < M) {
- m.lockEvents(m.getGesture());
- H = Ext.apply({
- xclass: "Ext.chart.grid.HorizontalGrid",
- x: 0,
- y: C,
- width: n
- }, h.horizontal);
- c = Ext.apply({
- xclass: "Ext.chart.grid.VerticalGrid",
- x: D,
- y: 0,
- height: M
- }, h.vertical);
- m.axesLabels = m.axesLabels || {};
- for (K = 0; K < E.length; K++) {
- q = E[K];
- v = q.getSurface();
- b = v.getRect();
- w = q.getSprites()[0];
- d = b[2];
- k = b[3];
- z = q.getPosition();
- G = q.getAlignment();
- t = q.getTitle();
- a = t && t.attr.text !== "" && t.getBBox();
- l = w.attr;
- f = w.thickness;
- p = l.axisLine ? l.lineWidth : 0;
- j = p / 2;
- I = Math.max(l.majorTickSize, l.minorTickSize) + p;
- L = m.axesLabels[z] = v.add({
- type: "composite"
- });
- L.labelRect = L.add(Ext.apply({
- type: "rect",
- fillStyle: "white",
- x: z === "right" ? p : 0,
- y: z === "bottom" ? p : 0,
- width: d - p - (G === "vertical" && a ? a.width : 0),
- height: k - p - (G === "horizontal" && a ? a.height : 0),
- translationX: z === "left" && a ? a.width : 0,
- translationY: z === "top" && a ? a.height : 0
- }, u.rect || u[z].rect));
- if (G === "vertical" && !c.strokeStyle) {
- c.strokeStyle = l.strokeStyle
- }
- if (G === "horizontal" && !H.strokeStyle) {
- H.strokeStyle = l.strokeStyle
- }
- A = Ext.merge({}, B.defaults, B[z]);
- J = Ext.apply({}, q.config.label, A.label);
- o = u.label || u[z].label;
- L.labelText = L.add(Ext.apply(J, o, {
- type: "text",
- x: (function() {
- switch (z) {
- case "left":
- g = a ? a.x + a.width : 0;
- return g + (d - g - I) / 2 - j;
- case "right":
- g = a ? d - a.x : 0;
- return I + (d - I - g) / 2 + j;
- default:
- return 0
- }
- })(),
- y: (function() {
- switch (z) {
- case "top":
- g = a ? a.y + a.height : 0;
- return g + (k - g - I) / 2 - j;
- case "bottom":
- g = a ? k - a.y : 0;
- return I + (k - I - g) / 2 + j;
- default:
- return 0
- }
- })()
- }))
- }
- m.horizontalLine = F.add(H);
- m.verticalLine = F.add(c);
- return false
- }
- },
- onGesture: function(G) {
- var K = this;
- if (K.getLocks()[K.getGesture()] !== K) {
- return
- }
- var u = K.getChart(),
- z = u.getSurface("overlay"),
- a = Ext.Array.slice(u.getInnerRect()),
- r = u.getInnerPadding(),
- t = r.left,
- q = r.top,
- E = a[2],
- f = a[3],
- d = u.getEventXY(G),
- k = d[0],
- j = d[1],
- D = u.getAxes(),
- c, h, m, p, J, w, I, H, s, b, C, g, v, n, l, A, F, o, B;
- if (k < 0) {
- k = 0
- } else {
- if (k > E) {
- k = E
- }
- }
- if (j < 0) {
- j = 0
- } else {
- if (j > f) {
- j = f
- }
- }
- k += t;
- j += q;
- for (B = 0; B < D.length; B++) {
- c = D[B];
- h = c.getPosition();
- m = c.getAlignment();
- p = c.getSurface();
- J = c.getSprites()[0];
- w = J.attr.matrix;
- C = J.attr.textPadding * 2;
- s = K.axesLabels[h];
- I = J.getLayoutContext();
- H = c.getSegmenter();
- if (s) {
- if (m === "vertical") {
- v = w.getYY();
- l = w.getDY();
- F = (j - l - q) / v;
- if (c.getLayout() instanceof Ext.chart.axis.layout.Discrete) {
- j = Math.round(F) * v + l + q;
- F = H.from(Math.round(F));
- F = J.attr.data[F]
- } else {
- F = H.from(F)
- }
- o = H.renderer(F, I);
- s.setAttributes({
- translationY: j - q
- });
- s.labelText.setAttributes({
- text: o
- });
- b = s.labelText.getBBox();
- s.labelRect.setAttributes({
- height: b.height + C,
- y: -(b.height + C) / 2
- });
- p.renderFrame()
- } else {
- g = w.getXX();
- n = w.getDX();
- A = (k - n - t) / g;
- if (c.getLayout() instanceof Ext.chart.axis.layout.Discrete) {
- k = Math.round(A) * g + n + t;
- A = H.from(Math.round(A));
- A = J.attr.data[A]
- } else {
- A = H.from(A)
- }
- o = H.renderer(A, I);
- s.setAttributes({
- translationX: k - t
- });
- s.labelText.setAttributes({
- text: o
- });
- b = s.labelText.getBBox();
- s.labelRect.setAttributes({
- width: b.width + C,
- x: -(b.width + C) / 2
- });
- p.renderFrame()
- }
- }
- }
- K.horizontalLine.setAttributes({
- y: j,
- strokeStyle: J.attr.strokeStyle
- });
- K.verticalLine.setAttributes({
- x: k,
- strokeStyle: J.attr.strokeStyle
- });
- z.renderFrame();
- return false
- },
- onGestureEnd: function(h) {
- var l = this,
- k = l.getChart(),
- a = k.getSurface("overlay"),
- j = k.getAxes(),
- c, g, d, b, f;
- a.remove(l.verticalLine);
- a.remove(l.horizontalLine);
- for (f = 0; f < j.length; f++) {
- c = j[f];
- g = c.getPosition();
- d = c.getSurface();
- b = l.axesLabels[g];
- if (b) {
- delete l.axesLabels[g];
- d.remove(b)
- }
- d.renderFrame()
- }
- a.renderFrame();
- l.unlockEvents(l.getGesture())
- }
-});
-Ext.define("Ext.chart.interactions.ItemHighlight", {
- extend: "Ext.chart.interactions.Abstract",
- type: "itemhighlight",
- alias: "interaction.itemhighlight",
- isItemHighlight: true,
- config: {
- gestures: {
- tap: "onTapGesture",
- mousemove: "onMouseMoveGesture",
- mousedown: "onMouseDownGesture",
- mouseup: "onMouseUpGesture",
- mouseleave: "onMouseUpGesture"
- },
- sticky: false
- },
- stickyHighlightItem: null,
- onMouseMoveGesture: function(g) {
- var d = this,
- h = d.tipItem,
- a = g.pointerType === "mouse",
- c, f, b;
- if (d.getSticky()) {
- return true
- }
- if (d.isDragging) {
- if (h && a) {
- h.series.hideTooltip(h);
- d.tipItem = null
- }
- } else {
- if (!d.stickyHighlightItem) {
- c = d.getItemForEvent(g);
- b = d.getChart();
- if (c !== b.getHighlightItem()) {
- d.highlight(c);
- d.sync()
- }
- if (a) {
- if (h && (!c || h.field !== c.field || h.record !== c.record)) {
- h.series.hideTooltip(h);
- d.tipItem = h = null
- }
- if (c && (f = c.series.getTooltip())) {
- if (f.trackMouse || !h) {
- c.series.showTooltip(c, g.getXY())
- }
- d.tipItem = c
- }
- }
- return false
- }
- }
- },
- highlight: function(a) {
- this.getChart().setHighlightItem(a)
- },
- showTooltip: function(b, a) {
- a.series.showTooltip(a, b.getXY());
- this.tipItem = a
- },
- onMouseDownGesture: function() {
- this.isDragging = true
- },
- onMouseUpGesture: function() {
- this.isDragging = false
- },
- onTapGesture: function(c) {
- var b = this;
- if (c.pointerType === "mouse" && !b.getSticky()) {
- return
- }
- var a = b.getItemForEvent(c);
- if (b.stickyHighlightItem && a && (b.stickyHighlightItem.index === a.index)) {
- a = null
- }
- b.stickyHighlightItem = a;
- b.highlight(a)
- }
-});
-Ext.define("Ext.chart.interactions.ItemEdit", {
- extend: "Ext.chart.interactions.ItemHighlight",
- requires: ["Ext.tip.ToolTip"],
- type: "itemedit",
- alias: "interaction.itemedit",
- isItemEdit: true,
- config: {
- style: null,
- renderer: null,
- tooltip: true,
- gestures: {
- dragstart: "onDragStart",
- drag: "onDrag",
- dragend: "onDragEnd"
- },
- cursors: {
- ewResize: "ew-resize",
- nsResize: "ns-resize",
- move: "move"
- }
- },
- item: null,
- applyTooltip: function(b) {
- if (b) {
- var a = Ext.apply({}, b, {
- renderer: this.defaultTooltipRenderer,
- constrainPosition: true,
- shrinkWrapDock: true,
- autoHide: true,
- offsetX: 10,
- offsetY: 10
- });
- b = new Ext.tip.ToolTip(a)
- }
- return b
- },
- defaultTooltipRenderer: function(b, a, f, d) {
- var c = [];
- if (f.xField) {
- c.push(f.xField + ": " + f.xValue)
- }
- if (f.yField) {
- c.push(f.yField + ": " + f.yValue)
- }
- b.setHtml(c.join(" "))
- },
- onDragStart: function(d) {
- var c = this,
- a = c.getChart(),
- b = a.getHighlightItem();
- if (b) {
- a.fireEvent("beginitemedit", a, c, c.item = b);
- return false
- }
- },
- onDrag: function(f) {
- var d = this,
- b = d.getChart(),
- c = b.getHighlightItem(),
- a = c && c.sprite.type;
- if (c) {
- switch (a) {
- case "barSeries":
- return d.onDragBar(f);
- break;
- case "scatterSeries":
- return d.onDragScatter(f);
- break
- }
- }
- },
- highlight: function(f) {
- var e = this,
- d = e.getChart(),
- a = d.getFlipXY(),
- g = e.getCursors(),
- c = f && f.sprite.type,
- b = d.el.dom.style;
- e.callParent([f]);
- if (f) {
- switch (c) {
- case "barSeries":
- if (a) {
- b.cursor = g.ewResize
- } else {
- b.cursor = g.nsResize
- }
- break;
- case "scatterSeries":
- b.cursor = g.move;
- break
- }
- } else {
- d.el.dom.style.cursor = "default"
- }
- },
- onDragBar: function(i) {
- var m = this,
- k = m.getChart(),
- l = k.getInherited().rtl,
- f = k.isCartesian && k.getFlipXY(),
- q = k.getHighlightItem(),
- g = q.sprite.getMarker("items"),
- p = g.getMarkerFor(q.sprite.getId(), q.index),
- b = q.sprite.getSurface(),
- c = b.getRect(),
- r = b.getEventXY(i),
- o = q.sprite.attr.matrix,
- j = m.getRenderer(),
- a, n, d, h;
- if (f) {
- h = l ? c[2] - r[0] : r[0]
- } else {
- h = c[3] - r[1]
- }
- a = {
- x: p.x,
- y: h,
- width: p.width,
- height: p.height + (p.y - h),
- radius: p.radius,
- fillStyle: "none",
- lineDash: [4, 4],
- zIndex: 100
- };
- Ext.apply(a, m.getStyle());
- if (Ext.isArray(q.series.getYField())) {
- h = h - p.y - p.height
- }
- m.target = {
- index: q.index,
- yField: q.field,
- yValue: (h - o.getDY()) / o.getYY()
- };
- d = [k, {
- target: m.target,
- style: a,
- item: q
- }];
- n = Ext.callback(j, null, d, 0, k);
- if (n) {
- Ext.apply(a, n)
- }
- q.sprite.putMarker("items", a, "itemedit");
- m.showTooltip(i, m.target, q);
- b.renderFrame()
- },
- onDragScatter: function(n) {
- var t = this,
- g = t.getChart(),
- d = g.getInherited().rtl,
- l = g.isCartesian && g.getFlipXY(),
- o = g.getHighlightItem(),
- b = o.sprite.getMarker("items"),
- p = b.getMarkerFor(o.sprite.getId(), o.index),
- j = o.sprite.getSurface(),
- h = j.getRect(),
- a = j.getEventXY(n),
- k = o.sprite.attr.matrix,
- c = o.series.getXAxis(),
- f = c && c.getLayout().isContinuous,
- i = t.getRenderer(),
- m, u, q, s, r;
- if (l) {
- r = d ? h[2] - a[0] : a[0]
- } else {
- r = h[3] - a[1]
- }
- if (f) {
- if (l) {
- s = h[3] - a[1]
- } else {
- s = a[0]
- }
- } else {
- s = p.translationX
- }
- m = {
- translationX: s,
- translationY: r,
- scalingX: p.scalingX,
- scalingY: p.scalingY,
- r: p.r,
- fillStyle: "none",
- lineDash: [4, 4],
- zIndex: 100
- };
- Ext.apply(m, t.getStyle());
- t.target = {
- index: o.index,
- yField: o.field,
- yValue: (r - k.getDY()) / k.getYY()
- };
- if (f) {
- Ext.apply(t.target, {
- xField: o.series.getXField(),
- xValue: (s - k.getDX()) / k.getXX()
- })
- }
- q = [g, {
- target: t.target,
- style: m,
- item: o
- }];
- u = Ext.callback(i, null, q, 0, g);
- if (u) {
- Ext.apply(m, u)
- }
- o.sprite.putMarker("items", m, "itemedit");
- t.showTooltip(n, t.target, o);
- j.renderFrame()
- },
- showTooltip: function(g, f, c) {
- var d = this.getTooltip(),
- a, b;
- if (d && Ext.toolkit !== "modern") {
- a = d.config;
- b = this.getChart();
- Ext.callback(a.renderer, null, [d, c, f, g], 0, b);
- d.show([g.x + a.offsetX, g.y + a.offsetY])
- }
- },
- hideTooltip: function() {
- var a = this.getTooltip();
- if (a && Ext.toolkit !== "modern") {
- a.hide()
- }
- },
- onDragEnd: function(g) {
- var d = this,
- f = d.target,
- c = d.getChart(),
- b = c.getStore(),
- a;
- if (f) {
- a = b.getAt(f.index);
- if (f.yField) {
- a.set(f.yField, f.yValue, {
- convert: false
- })
- }
- if (f.xField) {
- a.set(f.xField, f.xValue, {
- convert: false
- })
- }
- if (f.yField || f.xField) {
- d.getChart().onDataChanged()
- }
- d.target = null
- }
- d.hideTooltip();
- if (d.item) {
- c.fireEvent("enditemedit", c, d, d.item, f)
- }
- d.highlight(d.item = null)
- },
- destroy: function() {
- var a = this.getConfig("tooltip", true);
- Ext.destroy(a);
- this.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.PanZoom", {
- extend: "Ext.chart.interactions.Abstract",
- type: "panzoom",
- alias: "interaction.panzoom",
- requires: ["Ext.draw.Animator"],
- config: {
- axes: {
- top: {},
- right: {},
- bottom: {},
- left: {}
- },
- minZoom: null,
- maxZoom: null,
- showOverflowArrows: true,
- panGesture: "drag",
- zoomGesture: "pinch",
- zoomOnPanGesture: false,
- modeToggleButton: {
- xtype: "segmentedbutton",
- width: 200,
- defaults: {
- ui: "default-toolbar"
- },
- cls: Ext.baseCSSPrefix + "panzoom-toggle",
- items: [{
- text: "Pan"
- }, {
- text: "Zoom"
- }]
- },
- hideLabelInGesture: false
- },
- stopAnimationBeforeSync: true,
- applyAxes: function(b, a) {
- return Ext.merge(a || {}, b)
- },
- applyZoomOnPanGesture: function(a) {
- this.getChart();
- if (this.isMultiTouch()) {
- return false
- }
- return a
- },
- updateZoomOnPanGesture: function(b) {
- var a = this.getModeToggleButton();
- if (!this.isMultiTouch()) {
- a.show();
- a.setValue(b ? 1 : 0)
- } else {
- a.hide()
- }
- },
- toggleMode: function() {
- var a = this;
- if (!a.isMultiTouch()) {
- a.setZoomOnPanGesture(!a.getZoomOnPanGesture())
- }
- },
- applyModeToggleButton: function(c, b) {
- var d = this,
- a = Ext.factory(c, "Ext.button.Segmented", b);
- if (!a && b) {
- b.destroy()
- }
- if (a && !b) {
- a.addListener("toggle", function(e) {
- d.setZoomOnPanGesture(e.getValue() === 1)
- })
- }
- return a
- },
- getGestures: function() {
- var c = this,
- e = {},
- d = c.getPanGesture(),
- b = c.getZoomGesture(),
- a = Ext.supports.Touch;
- e[b] = "onZoomGestureMove";
- e[b + "start"] = "onZoomGestureStart";
- e[b + "end"] = "onZoomGestureEnd";
- e[d] = "onPanGestureMove";
- e[d + "start"] = "onPanGestureStart";
- e[d + "end"] = "onPanGestureEnd";
- e.doubletap = "onDoubleTap";
- return e
- },
- onDoubleTap: function(h) {
- var f = this,
- c = f.getChart(),
- g = c.getAxes(),
- b, a, d;
- for (a = 0, d = g.length; a < d; a++) {
- b = g[a];
- b.setVisibleRange([0, 1])
- }
- c.redraw()
- },
- onPanGestureStart: function(d) {
- if (!d || !d.touches || d.touches.length < 2) {
- var b = this,
- a = b.getChart().getInnerRect(),
- c = b.getChart().element.getXY();
- b.startX = d.getX() - c[0] - a[0];
- b.startY = d.getY() - c[1] - a[1];
- b.oldVisibleRanges = null;
- b.hideLabels();
- b.getChart().suspendThicknessChanged();
- b.lockEvents(b.getPanGesture());
- return false
- }
- },
- onPanGestureMove: function(d) {
- var b = this;
- if (b.getLocks()[b.getPanGesture()] === b) {
- var a = b.getChart().getInnerRect(),
- c = b.getChart().element.getXY();
- if (b.getZoomOnPanGesture()) {
- b.transformAxesBy(b.getZoomableAxes(d), 0, 0, (d.getX() - c[0] - a[0]) / b.startX, b.startY / (d.getY() - c[1] - a[1]))
- } else {
- b.transformAxesBy(b.getPannableAxes(d), d.getX() - c[0] - a[0] - b.startX, d.getY() - c[1] - a[1] - b.startY, 1, 1)
- }
- b.sync();
- return false
- }
- },
- onPanGestureEnd: function(b) {
- var a = this,
- c = a.getPanGesture();
- if (a.getLocks()[c] === a) {
- a.getChart().resumeThicknessChanged();
- a.showLabels();
- a.sync();
- a.unlockEvents(c);
- return false
- }
- },
- onZoomGestureStart: function(b) {
- if (b.touches && b.touches.length === 2) {
- var c = this,
- i = c.getChart().element.getXY(),
- f = c.getChart().getInnerRect(),
- h = i[0] + f[0],
- d = i[1] + f[1],
- j = [b.touches[0].point.x - h, b.touches[0].point.y - d, b.touches[1].point.x - h, b.touches[1].point.y - d],
- g = Math.max(44, Math.abs(j[2] - j[0])),
- a = Math.max(44, Math.abs(j[3] - j[1]));
- c.getChart().suspendThicknessChanged();
- c.lastZoomDistances = [g, a];
- c.lastPoints = j;
- c.oldVisibleRanges = null;
- c.hideLabels();
- c.lockEvents(c.getZoomGesture());
- return false
- }
- },
- onZoomGestureMove: function(d) {
- var f = this;
- if (f.getLocks()[f.getZoomGesture()] === f) {
- var i = f.getChart().getInnerRect(),
- n = f.getChart().element.getXY(),
- k = n[0] + i[0],
- h = n[1] + i[1],
- o = Math.abs,
- c = f.lastPoints,
- m = [d.touches[0].point.x - k, d.touches[0].point.y - h, d.touches[1].point.x - k, d.touches[1].point.y - h],
- g = Math.max(44, o(m[2] - m[0])),
- b = Math.max(44, o(m[3] - m[1])),
- a = this.lastZoomDistances || [g, b],
- l = g / a[0],
- j = b / a[1];
- f.transformAxesBy(f.getZoomableAxes(d), i[2] * (l - 1) / 2 + m[2] - c[2] * l, i[3] * (j - 1) / 2 + m[3] - c[3] * j, l, j);
- f.sync();
- return false
- }
- },
- onZoomGestureEnd: function(c) {
- var b = this,
- a = b.getZoomGesture();
- if (b.getLocks()[a] === b) {
- b.getChart().resumeThicknessChanged();
- b.showLabels();
- b.sync();
- b.unlockEvents(a);
- return false
- }
- },
- hideLabels: function() {
- if (this.getHideLabelInGesture()) {
- this.eachInteractiveAxes(function(a) {
- a.hideLabels()
- })
- }
- },
- showLabels: function() {
- if (this.getHideLabelInGesture()) {
- this.eachInteractiveAxes(function(a) {
- a.showLabels()
- })
- }
- },
- isEventOnAxis: function(c, a) {
- var b = a.getSurface().getRect();
- return b[0] <= c.getX() && c.getX() <= b[0] + b[2] && b[1] <= c.getY() && c.getY() <= b[1] + b[3]
- },
- getPannableAxes: function(d) {
- var h = this,
- a = h.getAxes(),
- f = h.getChart().getAxes(),
- c, g = f.length,
- k = [],
- j = false,
- b;
- if (d) {
- for (c = 0; c < g; c++) {
- if (this.isEventOnAxis(d, f[c])) {
- j = true;
- break
- }
- }
- }
- for (c = 0; c < g; c++) {
- b = a[f[c].getPosition()];
- if (b && b.allowPan !== false && (!j || this.isEventOnAxis(d, f[c]))) {
- k.push(f[c])
- }
- }
- return k
- },
- getZoomableAxes: function(f) {
- var j = this,
- a = j.getAxes(),
- g = j.getChart().getAxes(),
- l = [],
- d, h = g.length,
- c, k = false,
- b;
- if (f) {
- for (d = 0; d < h; d++) {
- if (this.isEventOnAxis(f, g[d])) {
- k = true;
- break
- }
- }
- }
- for (d = 0; d < h; d++) {
- c = g[d];
- b = a[c.getPosition()];
- if (b && b.allowZoom !== false && (!k || this.isEventOnAxis(f, c))) {
- l.push(c)
- }
- }
- return l
- },
- eachInteractiveAxes: function(c) {
- var d = this,
- b = d.getAxes(),
- e = d.getChart().getAxes();
- for (var a = 0; a < e.length; a++) {
- if (b[e[a].getPosition()]) {
- if (false === c.call(this, e[a])) {
- return
- }
- }
- }
- },
- transformAxesBy: function(d, j, g, h, e) {
- var f = this.getChart().getInnerRect(),
- a = this.getAxes(),
- k, b = this.oldVisibleRanges,
- l = false;
- if (!b) {
- this.oldVisibleRanges = b = {};
- this.eachInteractiveAxes(function(i) {
- b[i.getId()] = i.getVisibleRange()
- })
- }
- if (!f) {
- return
- }
- for (var c = 0; c < d.length; c++) {
- k = a[d[c].getPosition()];
- l = this.transformAxisBy(d[c], b[d[c].getId()], j, g, h, e, this.minZoom || k.minZoom, this.maxZoom || k.maxZoom) || l
- }
- return l
- },
- transformAxisBy: function(c, o, r, q, k, i, h, m) {
- var s = this,
- b = o[1] - o[0],
- l = c.getVisibleRange(),
- g = h || s.getMinZoom() || c.config.minZoom,
- j = m || s.getMaxZoom() || c.config.maxZoom,
- a = s.getChart().getInnerRect(),
- f, p;
- if (!a) {
- return
- }
- var d = c.isSide(),
- e = d ? a[3] : a[2],
- n = d ? -q : r;
- b /= d ? i : k;
- if (b < 0) {
- b = -b
- }
- if (b * g > 1) {
- b = 1
- }
- if (b * j < 1) {
- b = 1 / j
- }
- f = o[0];
- p = o[1];
- l = l[1] - l[0];
- if (b === l && l === 1) {
- return
- }
- c.setVisibleRange([(o[0] + o[1] - b) * 0.5 - n / e * b, (o[0] + o[1] + b) * 0.5 - n / e * b]);
- return (Math.abs(f - c.getVisibleRange()[0]) > 1e-10 || Math.abs(p - c.getVisibleRange()[1]) > 1e-10)
- },
- destroy: function() {
- this.setModeToggleButton(null);
- this.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.Rotate", {
- extend: "Ext.chart.interactions.Abstract",
- type: "rotate",
- alias: "interaction.rotate",
- config: {
- gesture: "rotate",
- gestures: {
- rotate: "onRotate",
- rotateend: "onRotate",
- dragstart: "onGestureStart",
- drag: "onGesture",
- dragend: "onGestureEnd"
- },
- rotation: 0
- },
- oldRotations: null,
- getAngle: function(f) {
- var c = this,
- b = c.getChart(),
- d = b.getEventXY(f),
- a = b.getCenter();
- return Math.atan2(d[1] - a[1], d[0] - a[0])
- },
- getRadius: function(a) {
- return this.getChart().getRadius()
- },
- getEventRadius: function(h) {
- var f = this,
- d = f.getChart(),
- g = d.getEventXY(h),
- a = d.getCenter(),
- c = g[0] - a[0],
- b = g[1] - a[1];
- return Math.sqrt(c * c + b * b)
- },
- onGestureStart: function(d) {
- var c = this,
- b = c.getRadius(d),
- a = c.getEventRadius(d);
- if (b >= a) {
- c.lockEvents("drag");
- c.angle = c.getAngle(d);
- c.oldRotations = {};
- return false
- }
- },
- onGesture: function(b) {
- var a = this,
- c = a.getAngle(b) - a.angle;
- if (a.getLocks().drag === a) {
- a.doRotateTo(c, true);
- return false
- }
- },
- doRotateTo: function(d, a, b) {
- var n = this,
- l = n.getChart(),
- k = l.getAxes(),
- f = l.getSeries(),
- m = n.oldRotations,
- c, j, g, e, h;
- if (!b) {
- l.suspendAnimation()
- }
- for (e = 0, h = k.length; e < h; e++) {
- c = k[e];
- g = m[c.getId()] || (m[c.getId()] = c.getRotation());
- c.setRotation(d + (a ? g : 0))
- }
- for (e = 0, h = f.length; e < h; e++) {
- j = f[e];
- g = m[j.getId()] || (m[j.getId()] = j.getRotation());
- j.setRotation(d + (a ? g : 0))
- }
- n.setRotation(d + (a ? g : 0));
- n.fireEvent("rotate", n, n.getRotation());
- n.sync();
- if (!b) {
- l.resumeAnimation()
- }
- },
- rotateTo: function(c, b, a) {
- this.doRotateTo(c, b, a);
- this.oldRotations = {}
- },
- onGestureEnd: function(b) {
- var a = this;
- if (a.getLocks().drag === a) {
- a.onGesture(b);
- a.unlockEvents("drag");
- a.fireEvent("rotationEnd", a, a.getRotation());
- return false
- }
- },
- onRotate: function(a) {}
-});
-Ext.define("Ext.chart.interactions.RotatePie3D", {
- extend: "Ext.chart.interactions.Rotate",
- type: "rotatePie3d",
- alias: "interaction.rotatePie3d",
- getAngle: function(g) {
- var a = this.getChart(),
- f = a.getInherited().rtl,
- d = f ? -1 : 1,
- h = g.getXY(),
- c = a.element.getXY(),
- b = a.getMainRect();
- return d * Math.atan2(h[1] - c[1] - b[3] * 0.5, h[0] - c[0] - b[2] * 0.5)
- },
- getRadius: function(j) {
- var f = this.getChart(),
- a = f.getRadius(),
- d = f.getSeries(),
- h = d.length,
- c = 0,
- b, g;
- for (; c < h; c++) {
- b = d[c];
- if (b.isPie3D) {
- g = b.getRadius();
- if (g > a) {
- a = g
- }
- }
- }
- return a
- }
-});
-Ext.define("Ext.chart.plugin.ItemEvents", {
- extend: "Ext.plugin.Abstract",
- alias: "plugin.chartitemevents",
- moveEvents: false,
- mouseMoveEvents: {
- mousemove: true,
- mouseover: true,
- mouseout: true
- },
- itemMouseMoveEvents: {
- itemmousemove: true,
- itemmouseover: true,
- itemmouseout: true
- },
- init: function(b) {
- var a = "handleEvent";
- this.chart = b;
- b.addElementListener({
- click: a,
- dblclick: a,
- mousedown: a,
- mousemove: a,
- mouseup: a,
- mouseover: a,
- mouseout: a,
- priority: 1001,
- scope: this
- })
- },
- hasItemMouseMoveListeners: function() {
- var b = this.chart.hasListeners,
- a;
- for (a in this.itemMouseMoveEvents) {
- if (a in b) {
- return true
- }
- }
- return false
- },
- handleEvent: function(g) {
- var d = this,
- a = d.chart,
- h = g.type in d.mouseMoveEvents,
- c = d.lastItem,
- f, b;
- if (h && !d.hasItemMouseMoveListeners() && !d.moveEvents) {
- return
- }
- f = a.getEventXY(g);
- b = a.getItemForPoint(f[0], f[1]);
- if (h && !Ext.Object.equals(b, c)) {
- if (c) {
- a.fireEvent("itemmouseout", a, c, g);
- c.series.fireEvent("itemmouseout", c.series, c, g)
- }
- if (b) {
- a.fireEvent("itemmouseover", a, b, g);
- b.series.fireEvent("itemmouseover", b.series, b, g)
- }
- }
- if (b) {
- a.fireEvent("item" + g.type, a, b, g);
- b.series.fireEvent("item" + g.type, b.series, b, g)
- }
- d.lastItem = b
- }
-});
-Ext.define("Ext.chart.series.Cartesian", {
- extend: "Ext.chart.series.Series",
- config: {
- xField: null,
- yField: null,
- xAxis: null,
- yAxis: null
- },
- directions: ["X", "Y"],
- fieldCategoryX: ["X"],
- fieldCategoryY: ["Y"],
- applyXAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- applyYAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- updateXAxis: function(a) {
- a.processData(this)
- },
- updateYAxis: function(a) {
- a.processData(this)
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- getItemForPoint: function(a, g) {
- if (this.getSprites()) {
- var f = this,
- d = f.getSprites()[0],
- b = f.getStore(),
- e, c;
- if (f.getHidden()) {
- return null
- }
- if (d) {
- c = d.getIndexNearPoint(a, g);
- if (c !== -1) {
- e = {
- series: f,
- category: f.getItemInstancing() ? "items" : "markers",
- index: c,
- record: b.getData().items[c],
- field: f.getYField(),
- sprite: d
- };
- return e
- }
- }
- }
- },
- createSprite: function() {
- var c = this,
- a = c.callParent(),
- b = c.getChart(),
- d = c.getXAxis();
- a.setAttributes({
- flipXY: b.getFlipXY(),
- xAxis: d
- });
- if (a.setAggregator && d && d.getAggregator) {
- if (d.getAggregator) {
- a.setAggregator({
- strategy: d.getAggregator()
- })
- } else {
- a.setAggregator({})
- }
- }
- return a
- },
- getSprites: function() {
- var d = this,
- c = this.getChart(),
- e = d.getAnimation() || c && c.getAnimation(),
- b = d.getItemInstancing(),
- f = d.sprites,
- a;
- if (!c) {
- return []
- }
- if (!f.length) {
- a = d.createSprite()
- } else {
- a = f[0]
- }
- if (e) {
- if (b) {
- a.itemsMarker.getTemplate().setAnimation(e)
- }
- a.setAnimation(e)
- }
- return f
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getSubStyleWithTheme(),
- c = a.fillStyle;
- if (Ext.isArray(c)) {
- c = c[0]
- }
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- },
- getXRange: function() {
- return [this.dataRange[0], this.dataRange[2]]
- },
- getYRange: function() {
- return [this.dataRange[1], this.dataRange[3]]
- }
-});
-Ext.define("Ext.chart.series.StackedCartesian", {
- extend: "Ext.chart.series.Cartesian",
- config: {
- stacked: true,
- splitStacks: true,
- fullStack: false,
- fullStackTotal: 100,
- hidden: []
- },
- spriteAnimationCount: 0,
- themeColorCount: function() {
- var b = this,
- a = b.getYField();
- return Ext.isArray(a) ? a.length : 1
- },
- updateStacked: function() {
- this.processData()
- },
- updateSplitStacks: function() {
- this.processData()
- },
- coordinateY: function() {
- return this.coordinateStacked("Y", 1, 2)
- },
- coordinateStacked: function(D, e, m) {
- var F = this,
- f = F.getStore(),
- r = f.getData().items,
- B = r.length,
- c = F["get" + D + "Axis"](),
- x = F.getHidden(),
- a = F.getSplitStacks(),
- z = F.getFullStack(),
- l = F.getFullStackTotal(),
- p = {
- min: 0,
- max: 0
- },
- n = F["fieldCategory" + D],
- C = [],
- o = [],
- E = [],
- h, A = F.getStacked(),
- g = F.getSprites(),
- q = [],
- w, v, u, s, H, y, b, d, G, t;
- if (!g.length) {
- return
- }
- for (w = 0; w < n.length; w++) {
- d = n[w];
- s = F.getFields([d]);
- H = s.length;
- for (v = 0; v < B; v++) {
- C[v] = 0;
- o[v] = 0;
- E[v] = 0
- }
- for (v = 0; v < H; v++) {
- if (!x[v]) {
- q[v] = F.coordinateData(r, s[v], c)
- }
- }
- if (A && z) {
- y = [];
- if (a) {
- b = []
- }
- for (v = 0; v < B; v++) {
- y[v] = 0;
- if (a) {
- b[v] = 0
- }
- for (u = 0; u < H; u++) {
- G = q[u];
- if (!G) {
- continue
- }
- G = G[v];
- if (G >= 0 || !a) {
- y[v] += G
- } else {
- if (G < 0) {
- b[v] += G
- }
- }
- }
- }
- }
- for (v = 0; v < H; v++) {
- t = {};
- if (x[v]) {
- t["dataStart" + d] = C;
- t["data" + d] = C;
- g[v].setAttributes(t);
- continue
- }
- G = q[v];
- if (A) {
- h = [];
- for (u = 0; u < B; u++) {
- if (!G[u]) {
- G[u] = 0
- }
- if (G[u] >= 0 || !a) {
- if (z && y[u]) {
- G[u] *= l / y[u]
- }
- C[u] = o[u];
- o[u] += G[u];
- h[u] = o[u]
- } else {
- if (z && b[u]) {
- G[u] *= l / b[u]
- }
- C[u] = E[u];
- E[u] += G[u];
- h[u] = E[u]
- }
- }
- t["dataStart" + d] = C;
- t["data" + d] = h;
- F.getRangeOfData(C, p);
- F.getRangeOfData(h, p)
- } else {
- t["dataStart" + d] = C;
- t["data" + d] = G;
- F.getRangeOfData(G, p)
- }
- g[v].setAttributes(t)
- }
- }
- F.dataRange[e] = p.min;
- F.dataRange[e + m] = p.max;
- t = {};
- t["dataMin" + D] = p.min;
- t["dataMax" + D] = p.max;
- for (w = 0; w < g.length; w++) {
- g[w].setAttributes(t)
- }
- },
- getFields: function(f) {
- var e = this,
- a = [],
- c, b, d;
- for (b = 0, d = f.length; b < d; b++) {
- c = e["get" + f[b] + "Field"]();
- if (Ext.isArray(c)) {
- a.push.apply(a, c)
- } else {
- a.push(c)
- }
- }
- return a
- },
- updateLabelOverflowPadding: function(a) {
- this.getLabel().setAttributes({
- labelOverflowPadding: a
- })
- },
- getSprites: function() {
- var k = this,
- j = k.getChart(),
- c = k.getAnimation() || j && j.getAnimation(),
- f = k.getFields(k.fieldCategoryY),
- b = k.getItemInstancing(),
- h = k.sprites,
- l, e = k.getHidden(),
- g = false,
- d, a = f.length;
- if (!j) {
- return []
- }
- for (d = 0; d < a; d++) {
- l = h[d];
- if (!l) {
- l = k.createSprite();
- l.setAttributes({
- zIndex: -d
- });
- l.setField(f[d]);
- g = true;
- e.push(false);
- if (b) {
- l.itemsMarker.getTemplate().setAttributes(k.getStyleByIndex(d))
- } else {
- l.setAttributes(k.getStyleByIndex(d))
- }
- }
- if (c) {
- if (b) {
- l.itemsMarker.getTemplate().setAnimation(c)
- }
- l.setAnimation(c)
- }
- }
- if (g) {
- k.updateHidden(e)
- }
- return h
- },
- getItemForPoint: function(k, j) {
- if (this.getSprites()) {
- var h = this,
- b, g, m, a = h.getItemInstancing(),
- f = h.getSprites(),
- l = h.getStore(),
- c = h.getHidden(),
- n, d, e;
- for (b = 0, g = f.length; b < g; b++) {
- if (!c[b]) {
- m = f[b];
- d = m.getIndexNearPoint(k, j);
- if (d !== -1) {
- e = h.getYField();
- n = {
- series: h,
- index: d,
- category: a ? "items" : "markers",
- record: l.getData().items[d],
- field: typeof e === "string" ? e : e[b],
- sprite: m
- };
- return n
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(e) {
- var g = this,
- f = g.getSprites(),
- h = g.getTitle(),
- j = g.getYField(),
- d = g.getHidden(),
- k = f.length === 1,
- b, l, c, a;
- for (c = 0; c < f.length; c++) {
- b = g.getStyleByIndex(c);
- l = b.fillStyle;
- if (h) {
- if (Ext.isArray(h)) {
- a = h[c]
- } else {
- if (k) {
- a = h
- }
- }
- } else {
- if (Ext.isArray(j)) {
- a = j[c]
- } else {
- a = g.getId()
- }
- }
- e.push({
- name: a,
- mark: (Ext.isObject(l) ? l.stops && l.stops[0].color : l) || b.strokeStyle || "black",
- disabled: d[c],
- series: g.getId(),
- index: c
- })
- }
- },
- onSpriteAnimationStart: function(a) {
- this.spriteAnimationCount++;
- if (this.spriteAnimationCount === 1) {
- this.fireEvent("animationstart")
- }
- },
- onSpriteAnimationEnd: function(a) {
- this.spriteAnimationCount--;
- if (this.spriteAnimationCount === 0) {
- this.fireEvent("animationend")
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Series", {
- extend: "Ext.draw.sprite.Sprite",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- inheritableStatics: {
- def: {
- processors: {
- dataMinX: "number",
- dataMaxX: "number",
- dataMinY: "number",
- dataMaxY: "number",
- rangeX: "data",
- rangeY: "data",
- dataX: "data",
- dataY: "data"
- },
- defaults: {
- dataMinX: 0,
- dataMaxX: 1,
- dataMinY: 0,
- dataMaxY: 1,
- rangeX: null,
- rangeY: null,
- dataX: null,
- dataY: null
- },
- triggers: {
- dataX: "bbox",
- dataY: "bbox",
- dataMinX: "bbox",
- dataMaxX: "bbox",
- dataMinY: "bbox",
- dataMaxY: "bbox"
- }
- }
- },
- config: {
- store: null,
- series: null,
- field: null
- }
-});
-Ext.define("Ext.chart.series.sprite.Cartesian", {
- extend: "Ext.chart.series.sprite.Series",
- inheritableStatics: {
- def: {
- processors: {
- labels: "default",
- labelOverflowPadding: "number",
- selectionTolerance: "number",
- flipXY: "bool",
- renderer: "default",
- visibleMinX: "number",
- visibleMinY: "number",
- visibleMaxX: "number",
- visibleMaxY: "number",
- innerWidth: "number",
- innerHeight: "number"
- },
- defaults: {
- labels: null,
- labelOverflowPadding: 10,
- selectionTolerance: 20,
- flipXY: false,
- renderer: null,
- transformFillStroke: false,
- visibleMinX: 0,
- visibleMinY: 0,
- visibleMaxX: 1,
- visibleMaxY: 1,
- innerWidth: 1,
- innerHeight: 1
- },
- triggers: {
- dataX: "dataX,bbox",
- dataY: "dataY,bbox",
- visibleMinX: "panzoom",
- visibleMinY: "panzoom",
- visibleMaxX: "panzoom",
- visibleMaxY: "panzoom",
- innerWidth: "panzoom",
- innerHeight: "panzoom"
- },
- updaters: {
- dataX: function(a) {
- this.processDataX();
- this.scheduleUpdater(a, "dataY", ["dataY"])
- },
- dataY: function() {
- this.processDataY()
- },
- panzoom: function(c) {
- var e = c.visibleMaxX - c.visibleMinX,
- d = c.visibleMaxY - c.visibleMinY,
- b = c.flipXY ? c.innerHeight : c.innerWidth,
- g = !c.flipXY ? c.innerHeight : c.innerWidth,
- a = this.getSurface(),
- f = a ? a.getInherited().rtl : false;
- if (f && !c.flipXY) {
- c.translationX = b + c.visibleMinX * b / e
- } else {
- c.translationX = -c.visibleMinX * b / e
- }
- c.translationY = -c.visibleMinY * g / d;
- c.scalingX = (f && !c.flipXY ? -1 : 1) * b / e;
- c.scalingY = g / d;
- c.scalingCenterX = 0;
- c.scalingCenterY = 0;
- this.applyTransformations(true)
- }
- }
- }
- },
- processDataY: Ext.emptyFn,
- processDataX: Ext.emptyFn,
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.dataMinX;
- b.y = a.dataMinY;
- b.width = a.dataMaxX - a.dataMinX;
- b.height = a.dataMaxY - a.dataMinY
- },
- binarySearch: function(d) {
- var b = this.attr.dataX,
- f = 0,
- a = b.length;
- if (d <= b[0]) {
- return f
- }
- if (d >= b[a - 1]) {
- return a - 1
- }
- while (f + 1 < a) {
- var c = (f + a) >> 1,
- e = b[c];
- if (e === d) {
- return c
- } else {
- if (e < d) {
- f = c
- } else {
- a = c
- }
- }
- }
- return f
- },
- render: function(b, c, g) {
- var f = this,
- a = f.attr,
- e = a.inverseMatrix.clone();
- e.appendMatrix(b.inverseMatrix);
- if (a.dataX === null || a.dataX === undefined) {
- return
- }
- if (a.dataY === null || a.dataY === undefined) {
- return
- }
- if (e.getXX() * e.getYX() || e.getXY() * e.getYY()) {
- console.log("Cartesian Series sprite does not support rotation/sheering");
- return
- }
- var d = e.transformList([
- [g[0] - 1, g[3] + 1],
- [g[0] + g[2] + 1, -1]
- ]);
- d = d[0].concat(d[1]);
- f.renderClipped(b, c, d, g)
- },
- renderClipped: Ext.emptyFn,
- getIndexNearPoint: function(f, e) {
- var w = this,
- q = w.attr.matrix,
- h = w.attr.dataX,
- g = w.attr.dataY,
- k = w.attr.selectionTolerance,
- t, r, c = -1,
- j = q.clone().prependMatrix(w.surfaceMatrix).inverse(),
- u = j.transformPoint([f, e]),
- b = j.transformPoint([f - k, e - k]),
- n = j.transformPoint([f + k, e + k]),
- a = Math.min(b[0], n[0]),
- s = Math.max(b[0], n[0]),
- l = Math.min(b[1], n[1]),
- d = Math.max(b[1], n[1]),
- m, v, o, p;
- for (o = 0, p = h.length; o < p; o++) {
- m = h[o];
- v = g[o];
- if (m > a && m < s && v > l && v < d) {
- if (c === -1 || (Math.abs(m - u[0]) < t) && (Math.abs(v - u[1]) < r)) {
- t = Math.abs(m - u[0]);
- r = Math.abs(v - u[1]);
- c = o
- }
- }
- }
- return c
- }
-});
-Ext.define("Ext.chart.series.sprite.StackedCartesian", {
- extend: "Ext.chart.series.sprite.Cartesian",
- inheritableStatics: {
- def: {
- processors: {
- groupCount: "number",
- groupOffset: "number",
- dataStartY: "data"
- },
- defaults: {
- selectionTolerance: 20,
- groupCount: 1,
- groupOffset: 0,
- dataStartY: null
- },
- triggers: {
- dataStartY: "dataY,bbox"
- }
- }
- },
- getIndexNearPoint: function(e, d) {
- var o = this,
- q = o.attr.matrix,
- h = o.attr.dataX,
- f = o.attr.dataY,
- u = o.attr.dataStartY,
- l = o.attr.selectionTolerance,
- s = 0.5,
- r = Infinity,
- b = -1,
- k = q.clone().prependMatrix(this.surfaceMatrix).inverse(),
- t = k.transformPoint([e, d]),
- a = k.transformPoint([e - l, d - l]),
- n = k.transformPoint([e + l, d + l]),
- m = Math.min(a[1], n[1]),
- c = Math.max(a[1], n[1]),
- j, g;
- for (var p = 0; p < h.length; p++) {
- if (Math.min(u[p], f[p]) <= c && m <= Math.max(u[p], f[p])) {
- j = Math.abs(h[p] - t[0]);
- g = Math.max(-Math.min(f[p] - t[1], t[1] - u[p]), 0);
- if (j < s && g <= r) {
- s = j;
- r = g;
- b = p
- }
- }
- }
- return b
- }
-});
-Ext.define("Ext.chart.series.sprite.Area", {
- alias: "sprite.areaSeries",
- extend: "Ext.chart.series.sprite.StackedCartesian",
- inheritableStatics: {
- def: {
- processors: {
- step: "bool"
- },
- defaults: {
- step: false
- }
- }
- },
- renderClipped: function(q, s, A) {
- var B = this,
- p = B.attr,
- l = p.dataX,
- j = p.dataY,
- C = p.dataStartY,
- t = p.matrix,
- h, g, v, f, d, z, w, e = t.elements[0],
- m = t.elements[4],
- o = t.elements[3],
- k = t.elements[5],
- c = B.surfaceMatrix,
- n = {},
- r = Math.min(A[0], A[2]),
- u = Math.max(A[0], A[2]),
- b = Math.max(0, this.binarySearch(r)),
- a = Math.min(l.length - 1, this.binarySearch(u) + 1);
- s.beginPath();
- z = l[b] * e + m;
- w = j[b] * o + k;
- s.moveTo(z, w);
- if (p.step) {
- d = w;
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, d);
- s.lineTo(h, d = g)
- }
- } else {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, g)
- }
- }
- if (C) {
- if (p.step) {
- f = l[a] * e + m;
- for (v = a; v >= b; v--) {
- h = l[v] * e + m;
- g = C[v] * o + k;
- s.lineTo(f, g);
- s.lineTo(f = h, g)
- }
- } else {
- for (v = a; v >= b; v--) {
- h = l[v] * e + m;
- g = C[v] * o + k;
- s.lineTo(h, g)
- }
- }
- } else {
- s.lineTo(l[a] * e + m, g);
- s.lineTo(l[a] * e + m, k);
- s.lineTo(z, k);
- s.lineTo(z, j[v] * o + k)
- }
- if (p.transformFillStroke) {
- p.matrix.toContext(s)
- }
- s.fill();
- if (p.transformFillStroke) {
- p.inverseMatrix.toContext(s)
- }
- s.beginPath();
- s.moveTo(z, w);
- if (p.step) {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, d);
- s.lineTo(h, d = g);
- n.translationX = c.x(h, g);
- n.translationY = c.y(h, g);
- B.putMarker("markers", n, v, !p.renderer)
- }
- } else {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, g);
- n.translationX = c.x(h, g);
- n.translationY = c.y(h, g);
- B.putMarker("markers", n, v, !p.renderer)
- }
- }
- if (p.transformFillStroke) {
- p.matrix.toContext(s)
- }
- s.stroke()
- }
-});
-Ext.define("Ext.chart.series.Area", {
- extend: "Ext.chart.series.StackedCartesian",
- alias: "series.area",
- type: "area",
- seriesType: "areaSeries",
- requires: ["Ext.chart.series.sprite.Area"],
- config: {
- splitStacks: false
- }
-});
-Ext.define("Ext.chart.series.sprite.Bar", {
- alias: "sprite.barSeries",
- extend: "Ext.chart.series.sprite.StackedCartesian",
- inheritableStatics: {
- def: {
- processors: {
- minBarWidth: "number",
- maxBarWidth: "number",
- minGapWidth: "number",
- radius: "number",
- inGroupGapWidth: "number"
- },
- defaults: {
- minBarWidth: 2,
- maxBarWidth: 100,
- minGapWidth: 5,
- inGroupGapWidth: 3,
- radius: 0
- }
- }
- },
- drawLabel: function(k, i, s, h, o) {
- var q = this,
- n = q.attr,
- f = q.getMarker("labels"),
- d = f.getTemplate(),
- l = q.labelCfg || (q.labelCfg = {}),
- c = q.surfaceMatrix,
- j = n.labelOverflowPadding,
- b = d.attr.display,
- m = d.attr.orientation,
- g, e, a, r, t, p;
- l.x = c.x(i, h);
- l.y = c.y(i, h);
- if (!n.flipXY) {
- l.rotationRads = -Math.PI * 0.5
- } else {
- l.rotationRads = 0
- }
- l.calloutVertical = !n.flipXY;
- switch (m) {
- case "horizontal":
- l.rotationRads = 0;
- l.calloutVertical = false;
- break;
- case "vertical":
- l.rotationRads = -Math.PI * 0.5;
- l.calloutVertical = true;
- break
- }
- l.text = k;
- if (d.attr.renderer) {
- p = [k, f, l, {
- store: q.getStore()
- }, o];
- r = Ext.callback(d.attr.renderer, null, p, 0, q.getSeries());
- if (typeof r === "string") {
- l.text = r
- } else {
- if (typeof r === "object") {
- if ("text" in r) {
- l.text = r.text
- }
- t = true
- }
- }
- }
- a = q.getMarkerBBox("labels", o, true);
- if (!a) {
- q.putMarker("labels", l, o);
- a = q.getMarkerBBox("labels", o, true)
- }
- e = (a.width / 2 + j);
- if (s > h) {
- e = -e
- }
- if ((m === "horizontal" && n.flipXY) || (m === "vertical" && !n.flipXY) || !m) {
- g = (b === "insideStart") ? s + e : h - e
- } else {
- g = (b === "insideStart") ? s + j * 2 : h - j * 2
- }
- l.x = c.x(i, g);
- l.y = c.y(i, g);
- g = (b === "insideStart") ? s - e : h + e;
- l.calloutPlaceX = c.x(i, g);
- l.calloutPlaceY = c.y(i, g);
- g = (b === "insideStart") ? s : h;
- l.calloutStartX = c.x(i, g);
- l.calloutStartY = c.y(i, g);
- if (s > h) {
- e = -e
- }
- if (Math.abs(h - s) <= e * 2 || b === "outside") {
- l.callout = 1
- } else {
- l.callout = 0
- }
- if (t) {
- Ext.apply(l, r)
- }
- q.putMarker("labels", l, o)
- },
- drawBar: function(l, b, d, c, h, k, a, e) {
- var g = this,
- j = {},
- f = g.attr.renderer,
- i;
- j.x = c;
- j.y = h;
- j.width = k - c;
- j.height = a - h;
- j.radius = g.attr.radius;
- if (f) {
- i = Ext.callback(f, null, [g, j, {
- store: g.getStore()
- }, e], 0, g.getSeries());
- Ext.apply(j, i)
- }
- g.putMarker("items", j, e, !f)
- },
- renderClipped: function(G, u, F, C) {
- if (this.cleanRedraw) {
- return
- }
- var q = this,
- o = q.attr,
- w = o.dataX,
- v = o.dataY,
- H = o.labels,
- n = o.dataStartY,
- m = o.groupCount,
- E = o.groupOffset - (m - 1) * 0.5,
- z = o.inGroupGapWidth,
- t = u.lineWidth,
- D = o.matrix,
- B = D.elements[0],
- j = D.elements[3],
- e = D.elements[4],
- d = G.roundPixel(D.elements[5]) - 1,
- J = (B < 0 ? -1 : 1) * B - o.minGapWidth,
- k = (Math.min(J, o.maxBarWidth) - z * (m - 1)) / m,
- A = G.roundPixel(Math.max(o.minBarWidth, k)),
- c = q.surfaceMatrix,
- g, I, b, h, K, a, l = 0.5 * o.lineWidth,
- L = Math.min(F[0], F[2]),
- x = Math.max(F[0], F[2]),
- y = Math.max(0, Math.floor(L)),
- p = Math.min(w.length - 1, Math.ceil(x)),
- f = H && q.getMarker("labels"),
- s, r;
- for (K = y; K <= p; K++) {
- s = n ? n[K] : 0;
- r = v[K];
- a = w[K] * B + e + E * (A + z);
- g = G.roundPixel(a - A / 2) + l;
- h = G.roundPixel(r * j + d + t);
- I = G.roundPixel(a + A / 2) - l;
- b = G.roundPixel(s * j + d + t);
- q.drawBar(u, G, F, g, h - l, I, b - l, K);
- if (f && H[K] != null) {
- q.drawLabel(H[K], a, b, h, K)
- }
- q.putMarker("markers", {
- translationX: c.x(a, h),
- translationY: c.y(a, h)
- }, K, true)
- }
- },
- getIndexNearPoint: function(l, k) {
- var m = this,
- g = m.attr,
- h = g.dataX,
- a = m.getSurface(),
- b = a.getRect() || [0, 0, 0, 0],
- j = b[3],
- e, d, c, n, f = -1;
- if (g.flipXY) {
- e = j - k;
- if (a.getInherited().rtl) {
- d = b[2] - l
- } else {
- d = l
- }
- } else {
- e = l;
- d = j - k
- }
- for (c = 0; c < h.length; c++) {
- n = m.getMarkerBBox("items", c);
- if (Ext.draw.Draw.isPointInBBox(e, d, n)) {
- f = c;
- break
- }
- }
- return f
- }
-});
-Ext.define("Ext.chart.series.Bar", {
- extend: "Ext.chart.series.StackedCartesian",
- alias: "series.bar",
- type: "bar",
- seriesType: "barSeries",
- requires: ["Ext.chart.series.sprite.Bar", "Ext.draw.sprite.Rect"],
- config: {
- itemInstancing: {
- type: "rect",
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- radius: 0
- }
- }
- }
- },
- getItemForPoint: function(a, f) {
- if (this.getSprites()) {
- var d = this,
- c = d.getChart(),
- e = c.getInnerPadding(),
- b = c.getInherited().rtl;
- arguments[0] = a + (b ? e.right : -e.left);
- arguments[1] = f + e.bottom;
- return d.callParent(arguments)
- }
- },
- updateXAxis: function(a) {
- a.setLabelInSpan(true);
- this.callParent(arguments)
- },
- updateHidden: function(a) {
- this.callParent(arguments);
- this.updateStacked()
- },
- updateStacked: function(c) {
- var e = this,
- g = e.getSprites(),
- d = g.length,
- f = [],
- a = {},
- b;
- for (b = 0; b < d; b++) {
- if (!g[b].attr.hidden) {
- f.push(g[b])
- }
- }
- d = f.length;
- if (e.getStacked()) {
- a.groupCount = 1;
- a.groupOffset = 0;
- for (b = 0; b < d; b++) {
- f[b].setAttributes(a)
- }
- } else {
- a.groupCount = f.length;
- for (b = 0; b < d; b++) {
- a.groupOffset = b;
- f[b].setAttributes(a)
- }
- }
- e.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.series.sprite.Bar3D", {
- extend: "Ext.chart.series.sprite.Bar",
- alias: "sprite.bar3dSeries",
- requires: ["Ext.draw.gradient.Linear"],
- inheritableStatics: {
- def: {
- processors: {
- depthWidthRatio: "number",
- saturationFactor: "number",
- brightnessFactor: "number",
- colorSpread: "number"
- },
- defaults: {
- depthWidthRatio: 1 / 3,
- saturationFactor: 1,
- brightnessFactor: 1,
- colorSpread: 1,
- transformFillStroke: true
- },
- triggers: {
- groupCount: "panzoom"
- },
- updaters: {
- panzoom: function(c) {
- var g = this,
- e = c.visibleMaxX - c.visibleMinX,
- d = c.visibleMaxY - c.visibleMinY,
- b = c.flipXY ? c.innerHeight : c.innerWidth,
- h = !c.flipXY ? c.innerHeight : c.innerWidth,
- a = g.getSurface(),
- f = a ? a.getInherited().rtl : false;
- if (f && !c.flipXY) {
- c.translationX = b + c.visibleMinX * b / e
- } else {
- c.translationX = -c.visibleMinX * b / e
- }
- c.translationY = -c.visibleMinY * (h - g.depth) / d;
- c.scalingX = (f && !c.flipXY ? -1 : 1) * b / e;
- c.scalingY = (h - g.depth) / d;
- c.scalingCenterX = 0;
- c.scalingCenterY = 0;
- g.applyTransformations(true)
- }
- }
- }
- },
- config: {
- showStroke: false
- },
- depth: 0,
- drawBar: function(p, b, d, c, l, o, a, h) {
- var k = this,
- i = k.attr,
- n = {},
- j = i.renderer,
- m, g, f, e;
- n.x = (c + o) * 0.5;
- n.y = l;
- n.width = (o - c) * 0.75;
- n.height = a - l;
- n.depth = g = n.width * i.depthWidthRatio;
- n.orientation = i.flipXY ? "horizontal" : "vertical";
- n.saturationFactor = i.saturationFactor;
- n.brightnessFactor = i.brightnessFactor;
- n.colorSpread = i.colorSpread;
- if (g !== k.depth) {
- k.depth = g;
- f = k.getSeries();
- f.fireEvent("depthchange", f, g)
- }
- if (j) {
- e = [k, n, {
- store: k.getStore()
- }, h];
- m = Ext.callback(j, null, e, 0, k.getSeries());
- Ext.apply(n, m)
- }
- k.putMarker("items", n, h, !j)
- }
-});
-Ext.define("Ext.chart.series.sprite.Box", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.box",
- type: "box",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number",
- depth: "number",
- orientation: "enums(vertical,horizontal)",
- showStroke: "bool",
- saturationFactor: "number",
- brightnessFactor: "number",
- colorSpread: "number"
- },
- triggers: {
- x: "bbox",
- y: "bbox",
- width: "bbox",
- height: "bbox",
- depth: "bbox",
- orientation: "bbox"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 8,
- height: 8,
- depth: 8,
- orientation: "vertical",
- showStroke: false,
- saturationFactor: 1,
- brightnessFactor: 1,
- colorSpread: 1,
- lineJoin: "bevel"
- }
- }
- },
- constructor: function(a) {
- this.callParent([a]);
- this.topGradient = new Ext.draw.gradient.Linear({});
- this.rightGradient = new Ext.draw.gradient.Linear({});
- this.frontGradient = new Ext.draw.gradient.Linear({})
- },
- updatePlainBBox: function(d) {
- var c = this.attr,
- b = c.x,
- g = c.y,
- e = c.width,
- a = c.height,
- f = c.depth;
- d.x = b - e * 0.5;
- d.width = e + f;
- if (a > 0) {
- d.y = g;
- d.height = a + f
- } else {
- d.y = g + f;
- d.height = a - f
- }
- },
- render: function(l, m) {
- var u = this,
- k = u.attr,
- r = k.x,
- j = k.y,
- f = j + k.height,
- i = j < f,
- e = k.width * 0.5,
- v = k.depth,
- d = k.orientation === "horizontal",
- g = k.globalAlpha < 1,
- c = k.fillStyle,
- n = Ext.draw.Color.create(c.isGradient ? c.getStops()[0].color : c),
- h = k.saturationFactor,
- o = k.brightnessFactor,
- t = k.colorSpread,
- b = n.getHSV(),
- a = {},
- s, q, p;
- if (!k.showStroke) {
- m.strokeStyle = Ext.draw.Color.RGBA_NONE
- }
- if (i) {
- p = j;
- j = f;
- f = p
- }
- u.topGradient.setDegrees(d ? 0 : 80);
- u.topGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 + t * 0.1) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.11) * o, 0, 1))
- }]);
- u.rightGradient.setDegrees(d ? 45 : 90);
- u.rightGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.14) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 + t * 0.4) * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.32) * o, 0, 1))
- }]);
- if (d) {
- u.frontGradient.setDegrees(0)
- } else {
- u.frontGradient.setRadians(Math.atan2(j - f, e * 2))
- }
- u.frontGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 - t * 0.1) * h, 0, 1), Ext.Number.constrain((0.5 + t * 0.1) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 + t * 0.1) * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.23) * o, 0, 1))
- }]);
- if (g || i) {
- m.beginPath();
- m.moveTo(r - e, f);
- m.lineTo(r - e + v, f + v);
- m.lineTo(r + e + v, f + v);
- m.lineTo(r + e, f);
- m.closePath();
- a.x = r - e;
- a.y = j;
- a.width = e + v;
- a.height = v;
- m.fillStyle = (d ? u.rightGradient : u.topGradient).generateGradient(m, a);
- m.fillStroke(k)
- }
- if (g) {
- m.beginPath();
- m.moveTo(r - e, j);
- m.lineTo(r - e + v, j + v);
- m.lineTo(r - e + v, f + v);
- m.lineTo(r - e, f);
- m.closePath();
- a.x = r + e;
- a.y = f;
- a.width = v;
- a.height = j + v - f;
- m.fillStyle = (d ? u.topGradient : u.rightGradient).generateGradient(m, a);
- m.fillStroke(k)
- }
- q = l.roundPixel(j);
- m.beginPath();
- m.moveTo(r - e, q);
- m.lineTo(r - e + v, j + v);
- m.lineTo(r + e + v, j + v);
- m.lineTo(r + e, q);
- m.closePath();
- a.x = r - e;
- a.y = j;
- a.width = e + v;
- a.height = v;
- m.fillStyle = (d ? u.rightGradient : u.topGradient).generateGradient(m, a);
- m.fillStroke(k);
- s = l.roundPixel(r + e);
- m.beginPath();
- m.moveTo(s, l.roundPixel(j));
- m.lineTo(r + e + v, j + v);
- m.lineTo(r + e + v, f + v);
- m.lineTo(s, f);
- m.closePath();
- a.x = r + e;
- a.y = f;
- a.width = v;
- a.height = j + v - f;
- m.fillStyle = (d ? u.topGradient : u.rightGradient).generateGradient(m, a);
- m.fillStroke(k);
- s = l.roundPixel(r + e);
- q = l.roundPixel(j);
- m.beginPath();
- m.moveTo(r - e, f);
- m.lineTo(r - e, q);
- m.lineTo(s, q);
- m.lineTo(s, f);
- m.closePath();
- a.x = r - e;
- a.y = f;
- a.width = e * 2;
- a.height = j - f;
- m.fillStyle = u.frontGradient.generateGradient(m, a);
- m.fillStroke(k)
- }
-});
-Ext.define("Ext.chart.series.Bar3D", {
- extend: "Ext.chart.series.Bar",
- requires: ["Ext.chart.series.sprite.Bar3D", "Ext.chart.series.sprite.Box"],
- alias: "series.bar3d",
- type: "bar3d",
- seriesType: "bar3dSeries",
- config: {
- itemInstancing: {
- type: "box",
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- depth: 0
- }
- }
- },
- highlightCfg: {
- opacity: 0.8
- }
- },
- getSprites: function() {
- var c = this.callParent(arguments),
- b, d, a;
- for (a = 0; a < c.length; a++) {
- b = c[a];
- d = b.attr.zIndex;
- if (d < 0) {
- b.setAttributes({
- zIndex: -d
- })
- }
- if (b.setSeries) {
- b.setSeries(this)
- }
- }
- return c
- },
- getDepth: function() {
- var a = this.getSprites()[0];
- return a ? (a.depth || 0) : 0
- },
- getItemForPoint: function(m, k) {
- if (this.getSprites()) {
- var j = this,
- b, o, a = j.getItemInstancing(),
- h = j.getSprites(),
- n = j.getStore(),
- c = j.getHidden(),
- g = j.getChart(),
- l = g.getInnerPadding(),
- f = g.getInherited().rtl,
- p, d, e;
- m = m + (f ? l.right : -l.left);
- k = k + l.bottom;
- for (b = h.length - 1; b >= 0; b--) {
- if (!c[b]) {
- o = h[b];
- d = o.getIndexNearPoint(m, k);
- if (d !== -1) {
- e = j.getYField();
- p = {
- series: j,
- index: d,
- category: a ? "items" : "markers",
- record: n.getData().items[d],
- field: typeof e === "string" ? e : e[b],
- sprite: o
- };
- return p
- }
- }
- }
- return null
- }
- }
-});
-Ext.define("Ext.draw.LimitedCache", {
- config: {
- limit: 40,
- feeder: function() {
- return 0
- },
- scope: null
- },
- cache: null,
- constructor: function(a) {
- this.cache = {};
- this.cache.list = [];
- this.cache.tail = 0;
- this.initConfig(a)
- },
- get: function(e) {
- var c = this.cache,
- b = this.getLimit(),
- a = this.getFeeder(),
- d = this.getScope() || this;
- if (c[e]) {
- return c[e].value
- }
- if (c.list[c.tail]) {
- delete c[c.list[c.tail].cacheId]
- }
- c[e] = c.list[c.tail] = {
- value: a.apply(d, Array.prototype.slice.call(arguments, 1)),
- cacheId: e
- };
- c.tail++;
- if (c.tail === b) {
- c.tail = 0
- }
- return c[e].value
- },
- clear: function() {
- this.cache = {};
- this.cache.list = [];
- this.cache.tail = 0
- }
-});
-Ext.define("Ext.draw.SegmentTree", {
- config: {
- strategy: "double"
- },
- time: function(m, l, n, c, E, d, e) {
- var f = 0,
- o, A, s = new Date(n[m.startIdx[0]]),
- x = new Date(n[m.endIdx[l - 1]]),
- D = Ext.Date,
- u = [
- [D.MILLI, 1, "ms1", null],
- [D.MILLI, 2, "ms2", "ms1"],
- [D.MILLI, 5, "ms5", "ms1"],
- [D.MILLI, 10, "ms10", "ms5"],
- [D.MILLI, 50, "ms50", "ms10"],
- [D.MILLI, 100, "ms100", "ms50"],
- [D.MILLI, 500, "ms500", "ms100"],
- [D.SECOND, 1, "s1", "ms500"],
- [D.SECOND, 10, "s10", "s1"],
- [D.SECOND, 30, "s30", "s10"],
- [D.MINUTE, 1, "mi1", "s10"],
- [D.MINUTE, 5, "mi5", "mi1"],
- [D.MINUTE, 10, "mi10", "mi5"],
- [D.MINUTE, 30, "mi30", "mi10"],
- [D.HOUR, 1, "h1", "mi30"],
- [D.HOUR, 6, "h6", "h1"],
- [D.HOUR, 12, "h12", "h6"],
- [D.DAY, 1, "d1", "h12"],
- [D.DAY, 7, "d7", "d1"],
- [D.MONTH, 1, "mo1", "d1"],
- [D.MONTH, 3, "mo3", "mo1"],
- [D.MONTH, 6, "mo6", "mo3"],
- [D.YEAR, 1, "y1", "mo3"],
- [D.YEAR, 5, "y5", "y1"],
- [D.YEAR, 10, "y10", "y5"],
- [D.YEAR, 100, "y100", "y10"]
- ],
- z, b, k = f,
- F = l,
- j = false,
- r = m.startIdx,
- h = m.endIdx,
- w = m.minIdx,
- C = m.maxIdx,
- a = m.open,
- y = m.close,
- g = m.minX,
- q = m.minY,
- p = m.maxX,
- B = m.maxY,
- v, t;
- for (z = 0; l > f + 1 && z < u.length; z++) {
- s = new Date(n[r[0]]);
- b = u[z];
- s = D.align(s, b[0], b[1]);
- if (D.diff(s, x, b[0]) > n.length * 2 * b[1]) {
- continue
- }
- if (b[3] && m.map["time_" + b[3]]) {
- o = m.map["time_" + b[3]][0];
- A = m.map["time_" + b[3]][1]
- } else {
- o = k;
- A = F
- }
- f = l;
- t = s;
- j = true;
- r[l] = r[o];
- h[l] = h[o];
- w[l] = w[o];
- C[l] = C[o];
- a[l] = a[o];
- y[l] = y[o];
- g[l] = g[o];
- q[l] = q[o];
- p[l] = p[o];
- B[l] = B[o];
- t = Ext.Date.add(t, b[0], b[1]);
- for (v = o + 1; v < A; v++) {
- if (n[h[v]] < +t) {
- h[l] = h[v];
- y[l] = y[v];
- if (B[v] > B[l]) {
- B[l] = B[v];
- p[l] = p[v];
- C[l] = C[v]
- }
- if (q[v] < q[l]) {
- q[l] = q[v];
- g[l] = g[v];
- w[l] = w[v]
- }
- } else {
- l++;
- r[l] = r[v];
- h[l] = h[v];
- w[l] = w[v];
- C[l] = C[v];
- a[l] = a[v];
- y[l] = y[v];
- g[l] = g[v];
- q[l] = q[v];
- p[l] = p[v];
- B[l] = B[v];
- t = Ext.Date.add(t, b[0], b[1])
- }
- }
- if (l > f) {
- m.map["time_" + b[2]] = [f, l]
- }
- }
- },
- "double": function(h, u, j, a, t, b, c) {
- var e = 0,
- k, f = 1,
- n, d, v, g, s, l, m, r, q, p, o;
- while (u > e + 1) {
- k = e;
- e = u;
- f += f;
- for (n = k; n < e; n += 2) {
- if (n === e - 1) {
- d = h.startIdx[n];
- v = h.endIdx[n];
- g = h.minIdx[n];
- s = h.maxIdx[n];
- l = h.open[n];
- m = h.close[n];
- r = h.minX[n];
- q = h.minY[n];
- p = h.maxX[n];
- o = h.maxY[n]
- } else {
- d = h.startIdx[n];
- v = h.endIdx[n + 1];
- l = h.open[n];
- m = h.close[n];
- if (h.minY[n] <= h.minY[n + 1]) {
- g = h.minIdx[n];
- r = h.minX[n];
- q = h.minY[n]
- } else {
- g = h.minIdx[n + 1];
- r = h.minX[n + 1];
- q = h.minY[n + 1]
- }
- if (h.maxY[n] >= h.maxY[n + 1]) {
- s = h.maxIdx[n];
- p = h.maxX[n];
- o = h.maxY[n]
- } else {
- s = h.maxIdx[n + 1];
- p = h.maxX[n + 1];
- o = h.maxY[n + 1]
- }
- }
- h.startIdx[u] = d;
- h.endIdx[u] = v;
- h.minIdx[u] = g;
- h.maxIdx[u] = s;
- h.open[u] = l;
- h.close[u] = m;
- h.minX[u] = r;
- h.minY[u] = q;
- h.maxX[u] = p;
- h.maxY[u] = o;
- u++
- }
- h.map["double_" + f] = [e, u]
- }
- },
- none: Ext.emptyFn,
- aggregateData: function(h, a, r, c, d) {
- var b = h.length,
- e = [],
- s = [],
- f = [],
- q = [],
- j = [],
- p = [],
- n = [],
- o = [],
- m = [],
- k = [],
- g = {
- startIdx: e,
- endIdx: s,
- minIdx: f,
- maxIdx: q,
- open: j,
- minX: p,
- minY: n,
- maxX: o,
- maxY: m,
- close: k
- },
- l;
- for (l = 0; l < b; l++) {
- e[l] = l;
- s[l] = l;
- f[l] = l;
- q[l] = l;
- j[l] = a[l];
- p[l] = h[l];
- n[l] = c[l];
- o[l] = h[l];
- m[l] = r[l];
- k[l] = d[l]
- }
- g.map = {
- original: [0, b]
- };
- if (b) {
- this[this.getStrategy()](g, b, h, a, r, c, d)
- }
- return g
- },
- binarySearchMin: function(c, g, a, e) {
- var b = this.dataX;
- if (e <= b[c.startIdx[0]]) {
- return g
- }
- if (e >= b[c.startIdx[a - 1]]) {
- return a - 1
- }
- while (g + 1 < a) {
- var d = (g + a) >> 1,
- f = b[c.startIdx[d]];
- if (f === e) {
- return d
- } else {
- if (f < e) {
- g = d
- } else {
- a = d
- }
- }
- }
- return g
- },
- binarySearchMax: function(c, g, a, e) {
- var b = this.dataX;
- if (e <= b[c.endIdx[0]]) {
- return g
- }
- if (e >= b[c.endIdx[a - 1]]) {
- return a - 1
- }
- while (g + 1 < a) {
- var d = (g + a) >> 1,
- f = b[c.endIdx[d]];
- if (f === e) {
- return d
- } else {
- if (f < e) {
- g = d
- } else {
- a = d
- }
- }
- }
- return a
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- setData: function(d, a, b, c, e) {
- if (!b) {
- e = c = b = a
- }
- this.dataX = d;
- this.dataOpen = a;
- this.dataHigh = b;
- this.dataLow = c;
- this.dataClose = e;
- if (d.length === b.length && d.length === c.length) {
- this.cache = this.aggregateData(d, a, b, c, e)
- }
- },
- getAggregation: function(d, k, i) {
- if (!this.cache) {
- return null
- }
- var c = Infinity,
- g = this.dataX[this.dataX.length - 1] - this.dataX[0],
- l = this.cache.map,
- m = l.original,
- a, e, j, b, f, h;
- for (a in l) {
- e = l[a];
- j = e[1] - e[0] - 1;
- b = g / j;
- if (i <= b && b < c) {
- m = e;
- c = b
- }
- }
- f = Math.max(this.binarySearchMin(this.cache, m[0], m[1], d), m[0]);
- h = Math.min(this.binarySearchMax(this.cache, m[0], m[1], k) + 1, m[1]);
- return {
- data: this.cache,
- start: f,
- end: h
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Aggregative", {
- extend: "Ext.chart.series.sprite.Cartesian",
- requires: ["Ext.draw.LimitedCache", "Ext.draw.SegmentTree"],
- inheritableStatics: {
- def: {
- processors: {
- dataHigh: "data",
- dataLow: "data",
- dataClose: "data"
- },
- aliases: {
- dataOpen: "dataY"
- },
- defaults: {
- dataHigh: null,
- dataLow: null,
- dataClose: null
- }
- }
- },
- config: {
- aggregator: {}
- },
- applyAggregator: function(b, a) {
- return Ext.factory(b, Ext.draw.SegmentTree, a)
- },
- constructor: function() {
- this.callParent(arguments)
- },
- processDataY: function() {
- var d = this,
- b = d.attr,
- e = b.dataHigh,
- a = b.dataLow,
- f = b.dataClose,
- c = b.dataY;
- d.callParent(arguments);
- if (b.dataX && c && c.length > 0) {
- if (e) {
- d.getAggregator().setData(b.dataX, b.dataY, e, a, f)
- } else {
- d.getAggregator().setData(b.dataX, b.dataY)
- }
- }
- },
- getGapWidth: function() {
- return 1
- },
- renderClipped: function(b, c, g, f) {
- var e = this,
- d = Math.min(g[0], g[2]),
- a = Math.max(g[0], g[2]),
- h = e.getAggregator() && e.getAggregator().getAggregation(d, a, (a - d) / f[2] * e.getGapWidth());
- if (h) {
- e.dataStart = h.data.startIdx[h.start];
- e.dataEnd = h.data.endIdx[h.end - 1];
- e.renderAggregates(h.data, h.start, h.end, b, c, g, f)
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.CandleStick", {
- alias: "sprite.candlestickSeries",
- extend: "Ext.chart.series.sprite.Aggregative",
- inheritableStatics: {
- def: {
- processors: {
- raiseStyle: function(b, a) {
- return Ext.merge({}, a || {}, b)
- },
- dropStyle: function(b, a) {
- return Ext.merge({}, a || {}, b)
- },
- barWidth: "number",
- padding: "number",
- ohlcType: "enums(candlestick,ohlc)"
- },
- defaults: {
- raiseStyle: {
- strokeStyle: "green",
- fillStyle: "green"
- },
- dropStyle: {
- strokeStyle: "red",
- fillStyle: "red"
- },
- planar: false,
- barWidth: 15,
- padding: 3,
- lineJoin: "miter",
- miterLimit: 5,
- ohlcType: "candlestick"
- },
- triggers: {
- raiseStyle: "raiseStyle",
- dropStyle: "dropStyle"
- },
- updaters: {
- raiseStyle: function() {
- this.raiseTemplate && this.raiseTemplate.setAttributes(this.attr.raiseStyle)
- },
- dropStyle: function() {
- this.dropTemplate && this.dropTemplate.setAttributes(this.attr.dropStyle)
- }
- }
- }
- },
- candlestick: function(i, c, a, e, h, f, b) {
- var d = Math.min(c, h),
- g = Math.max(c, h);
- i.moveTo(f, e);
- i.lineTo(f, g);
- i.moveTo(f + b, g);
- i.lineTo(f + b, d);
- i.lineTo(f - b, d);
- i.lineTo(f - b, g);
- i.closePath();
- i.moveTo(f, a);
- i.lineTo(f, d)
- },
- ohlc: function(b, d, e, a, f, c, g) {
- b.moveTo(c, e);
- b.lineTo(c, a);
- b.moveTo(c, d);
- b.lineTo(c - g, d);
- b.moveTo(c, f);
- b.lineTo(c + g, f)
- },
- constructor: function() {
- this.callParent(arguments);
- this.raiseTemplate = new Ext.draw.sprite.Rect({
- parent: this
- });
- this.dropTemplate = new Ext.draw.sprite.Rect({
- parent: this
- })
- },
- getGapWidth: function() {
- var a = this.attr,
- b = a.barWidth,
- c = a.padding;
- return b + c
- },
- renderAggregates: function(d, c, b, t, u, z) {
- var D = this,
- s = this.attr,
- j = s.dataX,
- v = s.matrix,
- e = v.getXX(),
- r = v.getYY(),
- l = v.getDX(),
- h = v.getDY(),
- o = s.barWidth / e,
- C, k = s.ohlcType,
- f = Math.round(o * 0.5 * e),
- a = d.open,
- y = d.close,
- B = d.maxY,
- p = d.minY,
- q = d.startIdx,
- m, g, E, n, A, x, w = s.lineWidth * t.devicePixelRatio / 2;
- w -= Math.floor(w);
- u.save();
- C = this.raiseTemplate;
- C.useAttributes(u, z);
- u.beginPath();
- for (x = c; x < b; x++) {
- if (a[x] <= y[x]) {
- m = Math.round(a[x] * r + h) + w;
- g = Math.round(B[x] * r + h) + w;
- E = Math.round(p[x] * r + h) + w;
- n = Math.round(y[x] * r + h) + w;
- A = Math.round(j[q[x]] * e + l) + w;
- D[k](u, m, g, E, n, A, f)
- }
- }
- u.fillStroke(C.attr);
- u.restore();
- u.save();
- C = this.dropTemplate;
- C.useAttributes(u, z);
- u.beginPath();
- for (x = c; x < b; x++) {
- if (a[x] > y[x]) {
- m = Math.round(a[x] * r + h) + w;
- g = Math.round(B[x] * r + h) + w;
- E = Math.round(p[x] * r + h) + w;
- n = Math.round(y[x] * r + h) + w;
- A = Math.round(j[q[x]] * e + l) + w;
- D[k](u, m, g, E, n, A, f)
- }
- }
- u.fillStroke(C.attr);
- u.restore()
- }
-});
-Ext.define("Ext.chart.series.CandleStick", {
- extend: "Ext.chart.series.Cartesian",
- requires: ["Ext.chart.series.sprite.CandleStick"],
- alias: "series.candlestick",
- type: "candlestick",
- seriesType: "candlestickSeries",
- config: {
- openField: null,
- highField: null,
- lowField: null,
- closeField: null
- },
- fieldCategoryY: ["Open", "High", "Low", "Close"],
- themeColorCount: function() {
- return 2
- }
-});
-Ext.define("Ext.chart.series.Polar", {
- extend: "Ext.chart.series.Series",
- config: {
- rotation: 0,
- radius: null,
- center: [0, 0],
- offsetX: 0,
- offsetY: 0,
- showInLegend: true,
- xField: null,
- yField: null,
- angleField: null,
- radiusField: null,
- xAxis: null,
- yAxis: null
- },
- directions: ["X", "Y"],
- fieldCategoryX: ["X"],
- fieldCategoryY: ["Y"],
- deprecatedConfigs: {
- field: "angleField",
- lengthField: "radiusField"
- },
- constructor: function(b) {
- var c = this,
- a = c.getConfigurator(),
- e = a.configs,
- d;
- if (b) {
- for (d in c.deprecatedConfigs) {
- if (d in b && !(b in e)) {
- Ext.raise("'" + d + "' config has been deprecated. Please use the '" + c.deprecatedConfigs[d] + "' config instead.")
- }
- }
- }
- c.callParent([b])
- },
- getXField: function() {
- return this.getAngleField()
- },
- updateXField: function(a) {
- this.setAngleField(a)
- },
- getYField: function() {
- return this.getRadiusField()
- },
- updateYField: function(a) {
- this.setRadiusField(a)
- },
- applyXAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- applyYAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- getXRange: function() {
- return [this.dataRange[0], this.dataRange[2]]
- },
- getYRange: function() {
- return [this.dataRange[1], this.dataRange[3]]
- },
- themeColorCount: function() {
- var c = this,
- a = c.getStore(),
- b = a && a.getCount() || 0;
- return b
- },
- isStoreDependantColorCount: true,
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer(),
- centerX: 0,
- centerY: 0,
- rotationCenterX: 0,
- rotationCenterY: 0
- }
- },
- applyRotation: function(a) {
- return Ext.draw.sprite.AttributeParser.angle(a)
- },
- updateRotation: function(a) {
- var b = this.getSprites();
- if (b && b[0]) {
- b[0].setAttributes({
- baseRotation: a
- })
- }
- }
-});
-Ext.define("Ext.chart.series.Gauge", {
- alias: "series.gauge",
- extend: "Ext.chart.series.Polar",
- type: "gauge",
- seriesType: "pieslice",
- requires: ["Ext.draw.sprite.Sector"],
- config: {
- needle: false,
- needleLength: 90,
- needleWidth: 4,
- donut: 30,
- showInLegend: false,
- value: null,
- colors: null,
- sectors: null,
- minimum: 0,
- maximum: 100,
- rotation: 0,
- totalAngle: Math.PI / 2,
- rect: [0, 0, 1, 1],
- center: [0.5, 0.75],
- radius: 0.5,
- wholeDisk: false
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- updateNeedle: function(b) {
- var a = this,
- d = a.getSprites(),
- c = a.valueToAngle(a.getValue());
- if (d && d.length) {
- d[0].setAttributes({
- startAngle: (b ? c : 0),
- endAngle: c,
- strokeOpacity: (b ? 1 : 0),
- lineWidth: (b ? a.getNeedleWidth() : 0)
- });
- a.doUpdateStyles()
- }
- },
- themeColorCount: function() {
- var c = this,
- a = c.getStore(),
- b = a && a.getCount() || 0;
- return b + (c.getNeedle() ? 0 : 1)
- },
- updateColors: function(a, b) {
- var f = this,
- h = f.getSectors(),
- j = h && h.length,
- e = f.getSprites(),
- c = Ext.Array.clone(a),
- g = a && a.length,
- d;
- if (!g || !a[0]) {
- return
- }
- for (d = 0; d < j; d++) {
- c[d + 1] = h[d].color || c[d + 1] || a[d % g]
- }
- if (e.length) {
- e[0].setAttributes({
- strokeStyle: c[0]
- })
- }
- this.setSubStyle({
- fillStyle: c,
- strokeStyle: c
- });
- this.doUpdateStyles()
- },
- updateRect: function(f) {
- var d = this.getWholeDisk(),
- c = d ? Math.PI : this.getTotalAngle() / 2,
- g = this.getDonut() / 100,
- e, b, a;
- if (c <= Math.PI / 2) {
- e = 2 * Math.sin(c);
- b = 1 - g * Math.cos(c)
- } else {
- e = 2;
- b = 1 - Math.cos(c)
- }
- a = Math.min(f[2] / e, f[3] / b);
- this.setRadius(a);
- this.setCenter([f[2] / 2, a + (f[3] - b * a) / 2])
- },
- updateCenter: function(a) {
- this.setStyle({
- centerX: a[0],
- centerY: a[1],
- rotationCenterX: a[0],
- rotationCenterY: a[1]
- });
- this.doUpdateStyles()
- },
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a - (this.getTotalAngle() + Math.PI) / 2
- });
- this.doUpdateStyles()
- },
- doUpdateShape: function(b, f) {
- var a, d = this.getSectors(),
- c = (d && d.length) || 0,
- e = this.getNeedleLength() / 100;
- a = [b * e, b];
- while (c--) {
- a.push(b)
- }
- this.setSubStyle({
- endRho: a,
- startRho: b / 100 * f
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- var b = this.getDonut();
- this.doUpdateShape(a, b)
- },
- updateDonut: function(b) {
- var a = this.getRadius();
- this.doUpdateShape(a, b)
- },
- valueToAngle: function(a) {
- a = this.applyValue(a);
- return this.getTotalAngle() * (a - this.getMinimum()) / (this.getMaximum() - this.getMinimum())
- },
- applyValue: function(a) {
- return Math.min(this.getMaximum(), Math.max(a, this.getMinimum()))
- },
- updateValue: function(b) {
- var a = this,
- c = a.getNeedle(),
- e = a.valueToAngle(b),
- d = a.getSprites();
- d[0].rendererData.value = b;
- d[0].setAttributes({
- startAngle: (c ? e : 0),
- endAngle: e
- });
- a.doUpdateStyles()
- },
- processData: function() {
- var f = this,
- j = f.getStore(),
- a, d, h, b, g, e = j && j.first(),
- c, i;
- if (e) {
- c = f.getXField();
- if (c) {
- i = e.get(c)
- }
- }
- if (a = f.getXAxis()) {
- d = a.getMinimum();
- h = a.getMaximum();
- b = a.getSprites()[0].fx;
- g = b.getDuration();
- b.setDuration(0);
- if (Ext.isNumber(d)) {
- f.setMinimum(d)
- } else {
- a.setMinimum(f.getMinimum())
- }
- if (Ext.isNumber(h)) {
- f.setMaximum(h)
- } else {
- a.setMaximum(f.getMaximum())
- }
- b.setDuration(g)
- }
- if (!Ext.isNumber(i)) {
- i = f.getMinimum()
- }
- f.setValue(i)
- },
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer(),
- fx: {
- customDurations: {
- translationX: 0,
- translationY: 0,
- rotationCenterX: 0,
- rotationCenterY: 0,
- centerX: 0,
- centerY: 0,
- startRho: 0,
- endRho: 0,
- baseRotation: 0
- }
- }
- }
- },
- normalizeSectors: function(f) {
- var d = this,
- c = (f && f.length) || 0,
- b, e, g, a;
- if (c) {
- for (b = 0; b < c; b++) {
- e = f[b];
- if (typeof e === "number") {
- f[b] = {
- start: (b > 0 ? f[b - 1].end : d.getMinimum()),
- end: Math.min(e, d.getMaximum())
- };
- if (b == (c - 1) && f[b].end < d.getMaximum()) {
- f[b + 1] = {
- start: f[b].end,
- end: d.getMaximum()
- }
- }
- } else {
- if (typeof e.start === "number") {
- g = Math.max(e.start, d.getMinimum())
- } else {
- g = (b > 0 ? f[b - 1].end : d.getMinimum())
- }
- if (typeof e.end === "number") {
- a = Math.min(e.end, d.getMaximum())
- } else {
- a = d.getMaximum()
- }
- f[b].start = g;
- f[b].end = a
- }
- }
- } else {
- f = [{
- start: d.getMinimum(),
- end: d.getMaximum()
- }]
- }
- return f
- },
- getSprites: function() {
- var j = this,
- m = j.getStore(),
- l = j.getValue(),
- c, g;
- if (!m && !Ext.isNumber(l)) {
- return []
- }
- var h = j.getChart(),
- b = j.getAnimation() || h && h.getAnimation(),
- f = j.sprites,
- k = 0,
- o, n, e, d, a = [];
- if (f && f.length) {
- f[0].setAnimation(b);
- return f
- }
- d = {
- store: m,
- field: j.getXField(),
- angleField: j.getXField(),
- value: l,
- series: j
- };
- o = j.createSprite();
- o.setAttributes({
- zIndex: 10
- }, true);
- o.rendererData = d;
- o.rendererIndex = k++;
- a.push(j.getNeedleWidth());
- j.getLabel().getTemplate().setField(true);
- n = j.normalizeSectors(j.getSectors());
- for (c = 0, g = n.length; c < g; c++) {
- e = {
- startAngle: j.valueToAngle(n[c].start),
- endAngle: j.valueToAngle(n[c].end),
- label: n[c].label,
- fillStyle: n[c].color,
- strokeOpacity: 0,
- doCallout: false,
- labelOverflowPadding: -1
- };
- Ext.apply(e, n[c].style);
- o = j.createSprite();
- o.rendererData = d;
- o.rendererIndex = k++;
- o.setAttributes(e, true);
- a.push(e.lineWidth)
- }
- j.setSubStyle({
- lineWidth: a
- });
- j.doUpdateStyles();
- return f
- }
-});
-Ext.define("Ext.chart.series.sprite.Line", {
- alias: "sprite.lineSeries",
- extend: "Ext.chart.series.sprite.Aggregative",
- inheritableStatics: {
- def: {
- processors: {
- smooth: "bool",
- fillArea: "bool",
- step: "bool",
- preciseStroke: "bool",
- xAxis: "default",
- yCap: "default"
- },
- defaults: {
- smooth: false,
- fillArea: false,
- step: false,
- preciseStroke: true,
- xAxis: null,
- yCap: Math.pow(2, 20),
- yJump: 50
- },
- triggers: {
- dataX: "dataX,bbox,smooth",
- dataY: "dataY,bbox,smooth",
- smooth: "smooth"
- },
- updaters: {
- smooth: function(a) {
- var c = a.dataX,
- b = a.dataY;
- if (a.smooth && c && b && c.length > 2 && b.length > 2) {
- this.smoothX = Ext.draw.Draw.spline(c);
- this.smoothY = Ext.draw.Draw.spline(b)
- } else {
- delete this.smoothX;
- delete this.smoothY
- }
- }
- }
- }
- },
- list: null,
- updatePlainBBox: function(d) {
- var b = this.attr,
- c = Math.min(0, b.dataMinY),
- a = Math.max(0, b.dataMaxY);
- d.x = b.dataMinX;
- d.y = c;
- d.width = b.dataMaxX - b.dataMinX;
- d.height = a - c
- },
- drawStrip: function(a, c) {
- a.moveTo(c[0], c[1]);
- for (var b = 2, d = c.length; b < d; b += 2) {
- a.lineTo(c[b], c[b + 1])
- }
- },
- drawStraightStroke: function(p, q, e, d, u, h) {
- var w = this,
- o = w.attr,
- n = o.renderer,
- g = o.step,
- a = true,
- l = {
- type: "line",
- smooth: false,
- step: g
- },
- m = [],
- l, z, v, f, k, j, t, c, s, b, r;
- for (r = 3; r < u.length; r += 3) {
- t = u[r - 3];
- c = u[r - 2];
- k = u[r];
- j = u[r + 1];
- s = u[r + 3];
- b = u[r + 4];
- if (n) {
- l.x = k;
- l.y = j;
- l.x0 = t;
- l.y0 = c;
- v = [w, l, w.rendererData, e + r / 3];
- z = Ext.callback(n, null, v, 0, w.getSeries())
- }
- if (Ext.isNumber(k + j + t + c)) {
- if (a) {
- q.beginPath();
- q.moveTo(t, c);
- m.push(t, c);
- f = t;
- a = false
- }
- } else {
- continue
- }
- if (g) {
- q.lineTo(k, c);
- m.push(k, c)
- }
- q.lineTo(k, j);
- m.push(k, j);
- if (z || !(Ext.isNumber(s + b))) {
- q.save();
- Ext.apply(q, z);
- if (o.fillArea) {
- q.lineTo(k, h);
- q.lineTo(f, h);
- q.closePath();
- q.fill()
- }
- q.beginPath();
- w.drawStrip(q, m);
- m = [];
- q.stroke();
- q.restore();
- q.beginPath();
- a = true
- }
- }
- },
- calculateScale: function(c, a) {
- var b = 0,
- d = c;
- while (d < a && c > 0) {
- b++;
- d += c >> b
- }
- return Math.pow(2, b > 0 ? b - 1 : b)
- },
- drawSmoothStroke: function(u, v, c, b, C, f) {
- var G = this,
- t = G.attr,
- d = t.step,
- z = t.matrix,
- s = t.renderer,
- e = z.getXX(),
- p = z.getYY(),
- m = z.getDX(),
- k = z.getDY(),
- r = G.smoothX,
- q = G.smoothY,
- I = G.calculateScale(t.dataX.length, b),
- o, F, n, E, h, g, B, a, A, w, H, D, l = {
- type: "line",
- smooth: true,
- step: d
- };
- v.beginPath();
- v.moveTo(r[c * 3] * e + m, q[c * 3] * p + k);
- for (A = 0, w = c * 3 + 1; A < C.length - 3; A += 3, w += 3 * I) {
- o = r[w] * e + m;
- F = q[w] * p + k;
- n = r[w + 1] * e + m;
- E = q[w + 1] * p + k;
- h = u.roundPixel(C[A + 3]);
- g = C[A + 4];
- B = u.roundPixel(C[A]);
- a = C[A + 1];
- if (s) {
- l.x0 = B;
- l.y0 = a;
- l.cx1 = o;
- l.cy1 = F;
- l.cx2 = n;
- l.cy2 = E;
- l.x = h;
- l.y = g;
- D = [G, l, G.rendererData, c + A / 3 + 1];
- H = Ext.callback(s, null, D, 0, G.getSeries());
- v.save();
- Ext.apply(v, H)
- }
- if (t.fillArea) {
- v.moveTo(B, a);
- v.bezierCurveTo(o, F, n, E, h, g);
- v.lineTo(h, f);
- v.lineTo(B, f);
- v.lineTo(B, a);
- v.closePath();
- v.fill();
- v.beginPath()
- }
- v.moveTo(B, a);
- v.bezierCurveTo(o, F, n, E, h, g);
- v.stroke();
- v.moveTo(B, a);
- v.closePath();
- if (s) {
- v.restore()
- }
- v.beginPath();
- v.moveTo(h, g)
- }
- v.beginPath()
- },
- drawLabel: function(k, i, h, o, a) {
- var q = this,
- n = q.attr,
- e = q.getMarker("labels"),
- d = e.getTemplate(),
- m = q.labelCfg || (q.labelCfg = {}),
- c = q.surfaceMatrix,
- g, f, j = n.labelOverflowPadding,
- l, b, r, p, s;
- m.x = c.x(i, h);
- m.y = c.y(i, h);
- if (n.flipXY) {
- m.rotationRads = Math.PI * 0.5
- } else {
- m.rotationRads = 0
- }
- m.text = k;
- if (d.attr.renderer) {
- p = [k, e, m, q.rendererData, o];
- r = Ext.callback(d.attr.renderer, null, p, 0, q.getSeries());
- if (typeof r === "string") {
- m.text = r
- } else {
- if (typeof r === "object") {
- if ("text" in r) {
- m.text = r.text
- }
- s = true
- }
- }
- }
- b = q.getMarkerBBox("labels", o, true);
- if (!b) {
- q.putMarker("labels", m, o);
- b = q.getMarkerBBox("labels", o, true)
- }
- l = b.height / 2;
- g = i;
- switch (d.attr.display) {
- case "under":
- f = h - l - j;
- break;
- case "rotate":
- g += j;
- f = h - j;
- m.rotationRads = -Math.PI / 4;
- break;
- default:
- f = h + l + j
- }
- m.x = c.x(g, f);
- m.y = c.y(g, f);
- if (s) {
- Ext.apply(m, r)
- }
- q.putMarker("labels", m, o)
- },
- drawMarker: function(j, h, d) {
- var g = this,
- e = g.attr,
- f = e.renderer,
- c = g.surfaceMatrix,
- b = {},
- i, a;
- if (f && g.getMarker("markers")) {
- b.type = "marker";
- b.x = j;
- b.y = h;
- a = [g, b, g.rendererData, d];
- i = Ext.callback(f, null, a, 0, g.getSeries());
- if (i) {
- Ext.apply(b, i)
- }
- }
- b.translationX = c.x(j, h);
- b.translationY = c.y(j, h);
- delete b.x;
- delete b.y;
- g.putMarker("markers", b, d, !f)
- },
- drawStroke: function(a, c, h, b, f, e) {
- var d = this,
- g = d.attr.smooth && d.smoothX && d.smoothY;
- if (g) {
- d.drawSmoothStroke(a, c, h, b, f, e)
- } else {
- d.drawStraightStroke(a, c, h, b, f, e)
- }
- },
- renderAggregates: function(B, w, l, N, o, I, D) {
- var m = this,
- k = m.attr,
- s = k.dataX,
- r = k.dataY,
- h = k.labels,
- v = k.xAxis,
- a = k.yCap,
- g = k.smooth && m.smoothX && m.smoothY,
- d = h && m.getMarker("labels"),
- t = m.getMarker("markers"),
- E = k.matrix,
- u = N.devicePixelRatio,
- C = E.getXX(),
- f = E.getYY(),
- c = E.getDX(),
- b = E.getDY(),
- q = m.list || (m.list = []),
- F = B.minX,
- e = B.maxX,
- j = B.minY,
- P = B.maxY,
- U = B.startIdx,
- S = true,
- Q, T, L, K, R, G;
- m.rendererData = {
- store: m.getStore()
- };
- q.length = 0;
- for (R = w; R < l; R++) {
- var O = F[R],
- p = e[R],
- M = j[R],
- n = P[R];
- if (O < p) {
- q.push(O * C + c, M * f + b, U[R]);
- q.push(p * C + c, n * f + b, U[R])
- } else {
- if (O > p) {
- q.push(p * C + c, n * f + b, U[R]);
- q.push(O * C + c, M * f + b, U[R])
- } else {
- q.push(p * C + c, n * f + b, U[R])
- }
- }
- }
- if (q.length) {
- for (R = 0; R < q.length; R += 3) {
- L = q[R];
- K = q[R + 1];
- if (Ext.isNumber(L + K)) {
- if (K > a) {
- K = a
- } else {
- if (K < -a) {
- K = -a
- }
- }
- q[R + 1] = K
- } else {
- S = false;
- continue
- }
- G = q[R + 2];
- if (t) {
- m.drawMarker(L, K, G)
- }
- if (d && h[G]) {
- m.drawLabel(h[G], L, K, G, D)
- }
- }
- m.isContinuousLine = S;
- if (g && !S) {
- Ext.raise("Line smoothing in only supported for gapless data, where all data points are finite numbers.")
- }
- if (v) {
- T = v.getAlignment() === "vertical";
- if (Ext.isNumber(v.floatingAtCoord)) {
- Q = (T ? D[2] : D[3]) - v.floatingAtCoord
- } else {
- Q = T ? D[0] : D[1]
- }
- } else {
- Q = k.flipXY ? D[0] : D[1]
- }
- if (k.preciseStroke) {
- if (k.fillArea) {
- o.fill()
- }
- if (k.transformFillStroke) {
- k.inverseMatrix.toContext(o)
- }
- m.drawStroke(N, o, w, l, q, Q);
- if (k.transformFillStroke) {
- k.matrix.toContext(o)
- }
- o.stroke()
- } else {
- m.drawStroke(N, o, w, l, q, Q);
- if (S && g && k.fillArea && !k.renderer) {
- var A = s[s.length - 1] * C + c + u,
- z = r[r.length - 1] * f + b,
- J = s[0] * C + c - u,
- H = r[0] * f + b;
- o.lineTo(A, z);
- o.lineTo(A, Q - k.lineWidth);
- o.lineTo(J, Q - k.lineWidth);
- o.lineTo(J, H)
- }
- if (k.transformFillStroke) {
- k.matrix.toContext(o)
- }
- if (k.fillArea) {
- o.fillStroke(k, true)
- } else {
- o.stroke(true)
- }
- }
- }
- }
-});
-Ext.define("Ext.chart.series.Line", {
- extend: "Ext.chart.series.Cartesian",
- alias: "series.line",
- type: "line",
- seriesType: "lineSeries",
- requires: ["Ext.chart.series.sprite.Line"],
- config: {
- selectionTolerance: 20,
- smooth: false,
- step: false,
- fill: undefined,
- aggregator: {
- strategy: "double"
- }
- },
- defaultSmoothness: 3,
- overflowBuffer: 1,
- themeMarkerCount: function() {
- return 1
- },
- getDefaultSpriteConfig: function() {
- var d = this,
- e = d.callParent(arguments),
- c = Ext.apply({}, d.getStyle()),
- b, a = false;
- if (typeof d.config.fill != "undefined") {
- if (d.config.fill) {
- a = true;
- if (typeof c.fillStyle == "undefined") {
- if (typeof c.strokeStyle == "undefined") {
- b = d.getStyleWithTheme();
- c.fillStyle = b.fillStyle;
- c.strokeStyle = b.strokeStyle
- } else {
- c.fillStyle = c.strokeStyle
- }
- }
- }
- } else {
- if (c.fillStyle) {
- a = true
- }
- }
- if (!a) {
- delete c.fillStyle
- }
- c = Ext.apply(e || {}, c);
- return Ext.apply(c, {
- fillArea: a,
- step: d.config.step,
- smooth: d.config.smooth,
- selectionTolerance: d.config.selectionTolerance
- })
- },
- updateStep: function(b) {
- var a = this.getSprites()[0];
- if (a && a.attr.step !== b) {
- a.setAttributes({
- step: b
- })
- }
- },
- updateFill: function(b) {
- var a = this.getSprites()[0];
- if (a && a.attr.fillArea !== b) {
- a.setAttributes({
- fillArea: b
- })
- }
- },
- updateSmooth: function(a) {
- var b = this.getSprites()[0];
- if (b && b.attr.smooth !== a) {
- b.setAttributes({
- smooth: a
- })
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.PieSlice", {
- extend: "Ext.draw.sprite.Sector",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- alias: "sprite.pieslice",
- inheritableStatics: {
- def: {
- processors: {
- doCallout: "bool",
- label: "string",
- rotateLabels: "bool",
- labelOverflowPadding: "number",
- renderer: "default"
- },
- defaults: {
- doCallout: true,
- rotateLabels: true,
- label: "",
- labelOverflowPadding: 10,
- renderer: null
- }
- }
- },
- config: {
- rendererData: null,
- rendererIndex: 0,
- series: null
- },
- setGradientBBox: function(q, k) {
- var j = this,
- i = j.attr,
- g = (i.fillStyle && i.fillStyle.isGradient) || (i.strokeStyle && i.strokeStyle.isGradient);
- if (g && !i.constrainGradients) {
- var b = j.getMidAngle(),
- d = i.margin,
- e = i.centerX,
- c = i.centerY,
- a = i.endRho,
- l = i.matrix,
- o = l.getScaleX(),
- n = l.getScaleY(),
- m = o * a,
- f = n * a,
- p = {
- width: m + m,
- height: f + f
- };
- if (d) {
- e += d * Math.cos(b);
- c += d * Math.sin(b)
- }
- p.x = l.x(e, c) - m;
- p.y = l.y(e, c) - f;
- q.setGradientBBox(p)
- } else {
- j.callParent([q, k])
- }
- },
- render: function(b, c, g, f) {
- var e = this,
- a = e.attr,
- h = {},
- d;
- if (a.renderer) {
- h = {
- type: "sector",
- text: a.text,
- centerX: a.centerX,
- centerY: a.centerY,
- margin: a.margin,
- startAngle: Math.min(a.startAngle, a.endAngle),
- endAngle: Math.max(a.startAngle, a.endAngle),
- startRho: Math.min(a.startRho, a.endRho),
- endRho: Math.max(a.startRho, a.endRho)
- };
- d = Ext.callback(a.renderer, null, [e, h, e.rendererData, e.rendererIndex], 0, e.getSeries());
- e.setAttributes(d);
- e.useAttributes(c, g)
- }
- e.callParent([b, c, g, f]);
- if (a.label && e.getMarker("labels")) {
- e.placeLabel()
- }
- },
- placeLabel: function() {
- var z = this,
- s = z.attr,
- r = s.attributeId,
- t = Math.min(s.startAngle, s.endAngle),
- p = Math.max(s.startAngle, s.endAngle),
- k = (t + p) * 0.5,
- n = s.margin,
- h = s.centerX,
- g = s.centerY,
- f = Math.sin(k),
- c = Math.cos(k),
- v = Math.min(s.startRho, s.endRho) + n,
- m = Math.max(s.startRho, s.endRho) + n,
- l = (v + m) * 0.5,
- b = z.surfaceMatrix,
- o = z.labelCfg || (z.labelCfg = {}),
- e = z.getMarker("labels"),
- d = e.getTemplate(),
- a = d.getCalloutLine(),
- q = a && a.length || 40,
- u, j, i, A, w;
- b.appendMatrix(s.matrix);
- o.text = s.label;
- j = h + c * l;
- i = g + f * l;
- o.x = b.x(j, i);
- o.y = b.y(j, i);
- j = h + c * m;
- i = g + f * m;
- o.calloutStartX = b.x(j, i);
- o.calloutStartY = b.y(j, i);
- j = h + c * (m + q);
- i = g + f * (m + q);
- o.calloutPlaceX = b.x(j, i);
- o.calloutPlaceY = b.y(j, i);
- if (!s.rotateLabels) {
- o.rotationRads = 0
- } else {
- switch (d.attr.orientation) {
- case "horizontal":
- o.rotationRads = k + Math.atan2(b.y(1, 0) - b.y(0, 0), b.x(1, 0) - b.x(0, 0)) + Math.PI / 2;
- break;
- case "vertical":
- o.rotationRads = k + Math.atan2(b.y(1, 0) - b.y(0, 0), b.x(1, 0) - b.x(0, 0));
- break
- }
- }
- o.calloutColor = (a && a.color) || z.attr.fillStyle;
- if (a) {
- if (a.width) {
- o.calloutWidth = a.width
- }
- } else {
- o.calloutHasLine = false
- }
- o.globalAlpha = s.globalAlpha * s.fillOpacity;
- o.hidden = (s.startAngle == s.endAngle);
- if (d.attr.renderer) {
- w = [z.attr.label, e, o, z.rendererData, z.rendererIndex];
- A = Ext.callback(d.attr.renderer, null, w, 0, z.getSeries());
- if (typeof A === "string") {
- o.text = A
- } else {
- Ext.apply(o, A)
- }
- }
- z.putMarker("labels", o, r);
- u = z.getMarkerBBox("labels", r, true);
- if (u) {
- if (s.doCallout) {
- if (d.attr.display === "outside") {
- z.putMarker("labels", {
- callout: 1
- }, r)
- } else {
- if (d.attr.display === "inside") {
- z.putMarker("labels", {
- callout: 0
- }, r)
- } else {
- z.putMarker("labels", {
- callout: 1 - z.sliceContainsLabel(s, u)
- }, r)
- }
- }
- } else {
- z.putMarker("labels", {
- globalAlpha: z.sliceContainsLabel(s, u)
- }, r)
- }
- }
- },
- sliceContainsLabel: function(d, f) {
- var e = d.labelOverflowPadding,
- h = (d.endRho + d.startRho) / 2,
- g = h + (f.width + e) / 2,
- i = h - (f.width + e) / 2,
- j, c, b, a;
- if (e < 0) {
- return 1
- }
- if (f.width + e * 2 > (d.endRho - d.startRho)) {
- return 0
- }
- c = Math.sqrt(d.endRho * d.endRho - g * g);
- b = Math.sqrt(d.endRho * d.endRho - i * i);
- j = Math.abs(d.endAngle - d.startAngle);
- a = (j > Math.PI / 2 ? i : Math.abs(Math.tan(j / 2)) * i);
- if (f.height + e * 2 > Math.min(c, b, a) * 2) {
- return 0
- }
- return 1
- }
-});
-Ext.define("Ext.chart.series.Pie", {
- extend: "Ext.chart.series.Polar",
- requires: ["Ext.chart.series.sprite.PieSlice"],
- type: "pie",
- alias: "series.pie",
- seriesType: "pieslice",
- config: {
- donut: 0,
- rotation: 0,
- clockwise: true,
- totalAngle: 2 * Math.PI,
- hidden: [],
- radiusFactor: 100,
- highlightCfg: {
- margin: 20
- },
- style: {}
- },
- directions: ["X"],
- applyLabel: function(a, b) {
- if (Ext.isObject(a) && !Ext.isString(a.orientation)) {
- Ext.apply(a = Ext.Object.chain(a), {
- orientation: "vertical"
- })
- }
- return this.callParent([a, b])
- },
- updateLabelData: function() {
- var h = this,
- j = h.getStore(),
- g = j.getData().items,
- e = h.getSprites(),
- a = h.getLabel().getTemplate().getField(),
- d = h.getHidden(),
- b, f, c, k;
- if (e.length && a) {
- c = [];
- for (b = 0, f = g.length; b < f; b++) {
- c.push(g[b].get(a))
- }
- for (b = 0, f = e.length; b < f; b++) {
- k = e[b];
- k.setAttributes({
- label: c[b]
- });
- k.putMarker("labels", {
- hidden: d[b]
- }, k.attr.attributeId)
- }
- }
- },
- coordinateX: function() {
- var t = this,
- f = t.getStore(),
- q = f.getData().items,
- c = q.length,
- b = t.getXField(),
- e = t.getYField(),
- l, a = 0,
- m, k, s = 0,
- o = t.getHidden(),
- d = [],
- p, g = 0,
- h = t.getTotalAngle(),
- r = t.getClockwise() ? 1 : -1,
- j = t.getSprites(),
- n;
- if (!j) {
- return
- }
- for (p = 0; p < c; p++) {
- l = Math.abs(Number(q[p].get(b))) || 0;
- k = e && Math.abs(Number(q[p].get(e))) || 0;
- if (!o[p]) {
- a += l;
- if (k > s) {
- s = k
- }
- }
- d[p] = a;
- if (p >= o.length) {
- o[p] = false
- }
- }
- o.length = c;
- t.maxY = s;
- if (a !== 0) {
- m = h / a
- }
- for (p = 0; p < c; p++) {
- j[p].setAttributes({
- startAngle: g,
- endAngle: g = (m ? r * d[p] * m : 0),
- globalAlpha: 1
- })
- }
- if (c < t.sprites.length) {
- for (p = c; p < t.sprites.length; p++) {
- n = t.sprites[p];
- n.getMarker("labels").clear(n.getId());
- n.releaseMarker("labels");
- n.destroy()
- }
- t.sprites.length = c
- }
- for (p = c; p < t.sprites.length; p++) {
- j[p].setAttributes({
- startAngle: h,
- endAngle: h,
- globalAlpha: 0
- })
- }
- t.getChart().refreshLegendStore()
- },
- updateCenter: function(a) {
- this.setStyle({
- translationX: a[0] + this.getOffsetX(),
- translationY: a[1] + this.getOffsetY()
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- this.setStyle({
- startRho: a * this.getDonut() * 0.01,
- endRho: a * this.getRadiusFactor() * 0.01
- });
- this.doUpdateStyles()
- },
- getStyleByIndex: function(c) {
- var g = this,
- j = g.getStore(),
- k = j.getAt(c),
- f = g.getYField(),
- d = g.getRadius(),
- a = {},
- e, b, h;
- if (k) {
- h = f && Math.abs(Number(k.get(f))) || 0;
- e = d * g.getDonut() * 0.01;
- b = d * g.getRadiusFactor() * 0.01;
- a = g.callParent([c]);
- a.startRho = e;
- a.endRho = g.maxY ? (e + (b - e) * h / g.maxY) : b
- }
- return a
- },
- updateDonut: function(b) {
- var a = this.getRadius();
- this.setStyle({
- startRho: a * b * 0.01,
- endRho: a * this.getRadiusFactor() * 0.01
- });
- this.doUpdateStyles()
- },
- rotationOffset: -Math.PI / 2,
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a + this.rotationOffset
- });
- this.doUpdateStyles()
- },
- updateTotalAngle: function(a) {
- this.processData()
- },
- getSprites: function() {
- var k = this,
- h = k.getChart(),
- n = k.getStore();
- if (!h || !n) {
- return []
- }
- k.getColors();
- k.getSubStyle();
- var j = n.getData().items,
- b = j.length,
- d = k.getAnimation() || h && h.getAnimation(),
- g = k.sprites,
- o, l = 0,
- f, e, c = false,
- m = k.getLabel(),
- a = m.getTemplate();
- f = {
- store: n,
- field: k.getXField(),
- angleField: k.getXField(),
- radiusField: k.getYField(),
- series: k
- };
- for (e = 0; e < b; e++) {
- o = g[e];
- if (!o) {
- o = k.createSprite();
- if (k.getHighlight()) {
- o.config.highlight = k.getHighlight();
- o.addModifier("highlight", true)
- }
- if (a.getField()) {
- a.setAttributes({
- labelOverflowPadding: k.getLabelOverflowPadding()
- });
- a.fx.setCustomDurations({
- callout: 200
- })
- }
- o.setAttributes(k.getStyleByIndex(e));
- o.rendererData = f;
- o.rendererIndex = l++;
- c = true
- }
- o.setAnimation(d)
- }
- if (c) {
- k.doUpdateStyles()
- }
- return k.sprites
- },
- betweenAngle: function(d, f, c) {
- var e = Math.PI * 2,
- g = this.rotationOffset;
- if (!this.getClockwise()) {
- d *= -1;
- f *= -1;
- c *= -1;
- f -= g;
- c -= g
- } else {
- f += g;
- c += g
- }
- d -= f;
- c -= f;
- d %= e;
- c %= e;
- d += e;
- c += e;
- d %= e;
- c %= e;
- return d < c || c === 0
- },
- getItemForAngle: function(a) {
- var h = this,
- f = h.getSprites(),
- d;
- a %= Math.PI * 2;
- while (a < 0) {
- a += Math.PI * 2
- }
- if (f) {
- var j = h.getStore(),
- g = j.getData().items,
- c = h.getHidden(),
- b = 0,
- e = j.getCount();
- for (; b < e; b++) {
- if (!c[b]) {
- d = f[b].attr;
- if (d.startAngle <= a && d.endAngle >= a) {
- return {
- series: h,
- sprite: f[b],
- index: b,
- record: g[b],
- field: h.getXField()
- }
- }
- }
- }
- }
- return null
- },
- getItemForPoint: function(f, e) {
- var t = this,
- c = t.getSprites();
- if (c) {
- var s = t.getCenter(),
- q = t.getOffsetX(),
- p = t.getOffsetY(),
- j = f - s[0] + q,
- h = e - s[1] + p,
- b = t.getStore(),
- g = t.getDonut(),
- o = b.getData().items,
- r = Math.atan2(h, j) - t.getRotation(),
- a = Math.sqrt(j * j + h * h),
- l = t.getRadius() * g * 0.01,
- m = t.getHidden(),
- n, d, k;
- for (n = 0, d = o.length; n < d; n++) {
- if (!m[n]) {
- k = c[n].attr;
- if (a >= l + k.margin && a <= k.endRho + k.margin) {
- if (t.betweenAngle(r, k.startAngle, k.endAngle)) {
- return {
- series: t,
- sprite: c[n],
- index: n,
- record: o[n],
- field: t.getXField()
- }
- }
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(f) {
- var h = this,
- j = h.getStore();
- if (j) {
- var g = j.getData().items,
- b = h.getLabel().getTemplate().getField(),
- c = h.getXField(),
- e = h.getHidden(),
- d, a, k;
- for (d = 0; d < g.length; d++) {
- a = h.getStyleByIndex(d);
- k = a.fillStyle;
- if (Ext.isObject(k)) {
- k = k.stops && k.stops[0].color
- }
- f.push({
- name: b ? String(g[d].get(b)) : c + " " + d,
- mark: k || a.strokeStyle || "black",
- disabled: e[d],
- series: h.getId(),
- index: d
- })
- }
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Pie3DPart", {
- extend: "Ext.draw.sprite.Path",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- alias: "sprite.pie3dPart",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- margin: "number",
- thickness: "number",
- bevelWidth: "number",
- distortion: "number",
- baseColor: "color",
- colorSpread: "number",
- baseRotation: "number",
- part: "enums(top,bottom,start,end,innerFront,innerBack,outerFront,outerBack)",
- label: "string"
- },
- aliases: {
- rho: "endRho"
- },
- triggers: {
- centerX: "path,bbox",
- centerY: "path,bbox",
- startAngle: "path,partZIndex",
- endAngle: "path,partZIndex",
- startRho: "path",
- endRho: "path,bbox",
- margin: "path,bbox",
- thickness: "path",
- distortion: "path",
- baseRotation: "path,partZIndex",
- baseColor: "partZIndex,partColor",
- colorSpread: "partColor",
- part: "path,partZIndex",
- globalAlpha: "canvas,alpha"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: Math.PI * 2,
- endAngle: Math.PI * 2,
- startRho: 0,
- endRho: 150,
- margin: 0,
- thickness: 35,
- distortion: 0.5,
- baseRotation: 0,
- baseColor: "white",
- colorSpread: 1,
- miterLimit: 1,
- bevelWidth: 5,
- strokeOpacity: 0,
- part: "top",
- label: ""
- },
- updaters: {
- alpha: "alphaUpdater",
- partColor: "partColorUpdater",
- partZIndex: "partZIndexUpdater"
- }
- }
- },
- bevelParams: [],
- constructor: function(a) {
- this.callParent([a]);
- this.bevelGradient = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: "rgba(255,255,255,0)"
- }, {
- offset: 0.7,
- color: "rgba(255,255,255,0.6)"
- }, {
- offset: 1,
- color: "rgba(255,255,255,0)"
- }]
- })
- },
- alphaUpdater: function(a) {
- var d = this,
- c = a.globalAlpha,
- b = d.oldOpacity;
- if (c !== b && (c === 1 || b === 1)) {
- d.scheduleUpdater(a, "path", ["globalAlpha"]);
- d.oldOpacity = c
- }
- },
- partColorUpdater: function(a) {
- var d = Ext.draw.Color.fly(a.baseColor),
- b = d.toString(),
- e = a.colorSpread,
- c;
- switch (a.part) {
- case "top":
- c = new Ext.draw.gradient.Radial({
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- },
- stops: [{
- offset: 0,
- color: d.createLighter(0.1 * e)
- }, {
- offset: 1,
- color: d.createDarker(0.1 * e)
- }]
- });
- break;
- case "bottom":
- c = new Ext.draw.gradient.Radial({
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- },
- stops: [{
- offset: 0,
- color: d.createDarker(0.2 * e)
- }, {
- offset: 1,
- color: d.toString()
- }]
- });
- break;
- case "outerFront":
- case "outerBack":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.15 * e).toString()
- }, {
- offset: 0.3,
- color: b
- }, {
- offset: 0.8,
- color: d.createLighter(0.2 * e).toString()
- }, {
- offset: 1,
- color: d.createDarker(0.25 * e).toString()
- }]
- });
- break;
- case "start":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 1,
- color: d.createLighter(0.2 * e).toString()
- }]
- });
- break;
- case "end":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 1,
- color: d.createLighter(0.2 * e).toString()
- }]
- });
- break;
- case "innerFront":
- case "innerBack":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 0.2,
- color: d.createLighter(0.2 * e).toString()
- }, {
- offset: 0.7,
- color: b
- }, {
- offset: 1,
- color: d.createDarker(0.1 * e).toString()
- }]
- });
- break
- }
- a.fillStyle = c;
- a.canvasAttributes.fillStyle = c
- },
- partZIndexUpdater: function(a) {
- var c = Ext.draw.sprite.AttributeParser.angle,
- e = a.baseRotation,
- d = a.startAngle,
- b = a.endAngle,
- f;
- switch (a.part) {
- case "top":
- a.zIndex = 5;
- break;
- case "outerFront":
- d = c(d + e);
- b = c(b + e);
- if (d >= 0 && b < 0) {
- f = Math.sin(d)
- } else {
- if (d <= 0 && b > 0) {
- f = Math.sin(b)
- } else {
- if (d >= 0 && b > 0) {
- if (d > b) {
- f = 0
- } else {
- f = Math.max(Math.sin(d), Math.sin(b))
- }
- } else {
- f = 1
- }
- }
- }
- a.zIndex = 4 + f;
- break;
- case "outerBack":
- a.zIndex = 1;
- break;
- case "start":
- a.zIndex = 4 + Math.sin(c(d + e));
- break;
- case "end":
- a.zIndex = 4 + Math.sin(c(b + e));
- break;
- case "innerFront":
- a.zIndex = 2;
- break;
- case "innerBack":
- a.zIndex = 4 + Math.sin(c((d + b) / 2 + e));
- break;
- case "bottom":
- a.zIndex = 0;
- break
- }
- a.dirtyZIndex = true
- },
- updatePlainBBox: function(k) {
- var f = this.attr,
- a = f.part,
- b = f.baseRotation,
- e = f.centerX,
- d = f.centerY,
- j, c, i, h, g, l;
- if (a === "start") {
- c = f.startAngle + b
- } else {
- if (a === "end") {
- c = f.endAngle + b
- }
- }
- if (Ext.isNumber(c)) {
- g = Math.sin(c);
- l = Math.cos(c);
- i = Math.min(e + l * f.startRho, e + l * f.endRho);
- h = d + g * f.startRho * f.distortion;
- k.x = i;
- k.y = h;
- k.width = l * (f.endRho - f.startRho);
- k.height = f.thickness + g * (f.endRho - f.startRho) * 2;
- return
- }
- if (a === "innerFront" || a === "innerBack") {
- j = f.startRho
- } else {
- j = f.endRho
- }
- k.width = j * 2;
- k.height = j * f.distortion * 2 + f.thickness;
- k.x = f.centerX - j;
- k.y = f.centerY - j * f.distortion
- },
- updateTransformedBBox: function(a) {
- if (this.attr.part === "start" || this.attr.part === "end") {
- return this.callParent(arguments)
- }
- return this.updatePlainBBox(a)
- },
- updatePath: function(a) {
- if (!this.attr.globalAlpha) {
- return
- }
- if (this.attr.endAngle < this.attr.startAngle) {
- return
- }
- this[this.attr.part + "Renderer"](a)
- },
- render: function(b, c) {
- var d = this,
- a = d.attr;
- if (!a.globalAlpha) {
- return
- }
- d.callParent([b, c]);
- d.bevelRenderer(b, c);
- if (a.label && d.getMarker("labels")) {
- d.placeLabel()
- }
- },
- placeLabel: function() {
- var z = this,
- u = z.attr,
- t = u.attributeId,
- p = u.margin,
- c = u.distortion,
- i = u.centerX,
- h = u.centerY,
- j = u.baseRotation,
- v = u.startAngle + j,
- r = u.endAngle + j,
- m = (v + r) / 2,
- w = u.startRho + p,
- o = u.endRho + p,
- n = (w + o) / 2,
- a = Math.sin(m),
- b = Math.cos(m),
- e = z.surfaceMatrix,
- g = z.getMarker("labels"),
- f = g.getTemplate(),
- d = f.getCalloutLine(),
- s = d && d.length || 40,
- q = {},
- l, k;
- e.appendMatrix(u.matrix);
- q.text = u.label;
- l = i + b * n;
- k = h + a * n * c;
- q.x = e.x(l, k);
- q.y = e.y(l, k);
- l = i + b * o;
- k = h + a * o * c;
- q.calloutStartX = e.x(l, k);
- q.calloutStartY = e.y(l, k);
- l = i + b * (o + s);
- k = h + a * (o + s) * c;
- q.calloutPlaceX = e.x(l, k);
- q.calloutPlaceY = e.y(l, k);
- q.calloutWidth = 2;
- z.putMarker("labels", q, t);
- z.putMarker("labels", {
- callout: 1
- }, t)
- },
- bevelRenderer: function(b, c) {
- var f = this,
- a = f.attr,
- e = a.bevelWidth,
- g = f.bevelParams,
- d;
- for (d = 0; d < g.length; d++) {
- c.beginPath();
- c.ellipse.apply(c, g[d]);
- c.save();
- c.lineWidth = e;
- c.strokeOpacity = e ? 1 : 0;
- c.strokeGradient = f.bevelGradient;
- c.stroke(a);
- c.restore()
- }
- },
- lidRenderer: function(o, m) {
- var k = this.attr,
- g = k.margin,
- c = k.distortion,
- i = k.centerX,
- h = k.centerY,
- f = k.baseRotation,
- j = k.startAngle + f,
- e = k.endAngle + f,
- d = (j + e) / 2,
- l = k.startRho,
- b = k.endRho,
- n = Math.sin(e),
- a = Math.cos(e);
- i += Math.cos(d) * g;
- h += Math.sin(d) * g * c;
- o.ellipse(i, h + m, l, l * c, 0, j, e, false);
- o.lineTo(i + a * b, h + m + n * b * c);
- o.ellipse(i, h + m, b, b * c, 0, e, j, true);
- o.closePath()
- },
- topRenderer: function(a) {
- this.lidRenderer(a, 0)
- },
- bottomRenderer: function(b) {
- var a = this.attr;
- if (a.globalAlpha < 1 || a.shadowColor !== Ext.draw.Color.RGBA_NONE) {
- this.lidRenderer(b, a.thickness)
- }
- },
- sideRenderer: function(l, s) {
- var o = this.attr,
- k = o.margin,
- g = o.centerX,
- f = o.centerY,
- e = o.distortion,
- h = o.baseRotation,
- p = o.startAngle + h,
- m = o.endAngle + h,
- a = o.thickness,
- q = o.startRho,
- j = o.endRho,
- r = (s === "start" && p) || (s === "end" && m),
- b = Math.sin(r),
- d = Math.cos(r),
- c = o.globalAlpha < 1,
- n = s === "start" && d < 0 || s === "end" && d > 0 || c,
- i;
- if (n) {
- i = (p + m) / 2;
- g += Math.cos(i) * k;
- f += Math.sin(i) * k * e;
- l.moveTo(g + d * q, f + b * q * e);
- l.lineTo(g + d * j, f + b * j * e);
- l.lineTo(g + d * j, f + b * j * e + a);
- l.lineTo(g + d * q, f + b * q * e + a);
- l.closePath()
- }
- },
- startRenderer: function(a) {
- this.sideRenderer(a, "start")
- },
- endRenderer: function(a) {
- this.sideRenderer(a, "end")
- },
- rimRenderer: function(q, e, o, j) {
- var w = this,
- s = w.attr,
- p = s.margin,
- h = s.centerX,
- g = s.centerY,
- d = s.distortion,
- i = s.baseRotation,
- t = Ext.draw.sprite.AttributeParser.angle,
- u = s.startAngle + i,
- r = s.endAngle + i,
- k = t((u + r) / 2),
- a = s.thickness,
- b = s.globalAlpha < 1,
- c, n, v;
- w.bevelParams = [];
- u = t(u);
- r = t(r);
- h += Math.cos(k) * p;
- g += Math.sin(k) * p * d;
- c = u >= 0 && r >= 0;
- n = u <= 0 && r <= 0;
-
- function l() {
- q.ellipse(h, g + a, e, e * d, 0, Math.PI, u, true);
- q.lineTo(h + Math.cos(u) * e, g + Math.sin(u) * e * d);
- v = [h, g, e, e * d, 0, u, Math.PI, false];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function f() {
- q.ellipse(h, g + a, e, e * d, 0, 0, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, 0, true];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function x() {
- q.ellipse(h, g + a, e, e * d, 0, Math.PI, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, Math.PI, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function m() {
- q.ellipse(h, g + a, e, e * d, 0, u, 0, false);
- q.lineTo(h + e, g);
- v = [h, g, e, e * d, 0, 0, u, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- if (j) {
- if (!o || b) {
- if (u >= 0 && r < 0) {
- l()
- } else {
- if (u <= 0 && r > 0) {
- f()
- } else {
- if (u <= 0 && r < 0) {
- if (u > r) {
- q.ellipse(h, g + a, e, e * d, 0, 0, Math.PI, false);
- q.lineTo(h - e, g);
- v = [h, g, e, e * d, 0, Math.PI, 0, true];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- } else {
- if (u > r) {
- l();
- f()
- } else {
- v = [h, g, e, e * d, 0, u, r, false];
- if (c && !o || n && o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d + a);
- q.ellipse(h, g + a, e, e * d, 0, r, u, true);
- q.closePath()
- }
- }
- }
- }
- }
- } else {
- if (o || b) {
- if (u >= 0 && r < 0) {
- x()
- } else {
- if (u <= 0 && r > 0) {
- m()
- } else {
- if (u <= 0 && r < 0) {
- if (u > r) {
- x();
- m()
- } else {
- q.ellipse(h, g + a, e, e * d, 0, u, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, u, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- } else {
- if (u > r) {
- q.ellipse(h, g + a, e, e * d, 0, -Math.PI, 0, false);
- q.lineTo(h + e, g);
- v = [h, g, e, e * d, 0, 0, -Math.PI, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- }
- }
- }
- }
- }
- },
- innerFrontRenderer: function(a) {
- this.rimRenderer(a, this.attr.startRho, true, true)
- },
- innerBackRenderer: function(a) {
- this.rimRenderer(a, this.attr.startRho, true, false)
- },
- outerFrontRenderer: function(a) {
- this.rimRenderer(a, this.attr.endRho, false, true)
- },
- outerBackRenderer: function(a) {
- this.rimRenderer(a, this.attr.endRho, false, false)
- }
-});
-Ext.define("Ext.draw.PathUtil", function() {
- var a = Math.abs,
- c = Math.pow,
- e = Math.cos,
- b = Math.acos,
- d = Math.sqrt,
- f = Math.PI;
- return {
- singleton: true,
- requires: ["Ext.draw.overrides.Path", "Ext.draw.overrides.sprite.Path", "Ext.draw.overrides.sprite.Instancing", "Ext.draw.overrides.Surface"],
- cubicRoots: function(m) {
- var z = m[0],
- x = m[1],
- w = m[2],
- v = m[3];
- if (z === 0) {
- return this.quadraticRoots(x, w, v)
- }
- var s = x / z,
- r = w / z,
- q = v / z,
- k = (3 * r - c(s, 2)) / 9,
- j = (9 * s * r - 27 * q - 2 * c(s, 3)) / 54,
- p = c(k, 3) + c(j, 2),
- n = [],
- h, g, o, l, u, y = Ext.Number.sign;
- if (p >= 0) {
- h = y(j + d(p)) * c(a(j + d(p)), 1 / 3);
- g = y(j - d(p)) * c(a(j - d(p)), 1 / 3);
- n[0] = -s / 3 + (h + g);
- n[1] = -s / 3 - (h + g) / 2;
- n[2] = n[1];
- o = a(d(3) * (h - g) / 2);
- if (o !== 0) {
- n[1] = -1;
- n[2] = -1
- }
- } else {
- l = b(j / d(-c(k, 3)));
- n[0] = 2 * d(-k) * e(l / 3) - s / 3;
- n[1] = 2 * d(-k) * e((l + 2 * f) / 3) - s / 3;
- n[2] = 2 * d(-k) * e((l + 4 * f) / 3) - s / 3
- }
- for (u = 0; u < 3; u++) {
- if (n[u] < 0 || n[u] > 1) {
- n[u] = -1
- }
- }
- return n
- },
- quadraticRoots: function(h, g, n) {
- var m, l, k, j;
- if (h === 0) {
- return this.linearRoot(g, n)
- }
- m = g * g - 4 * h * n;
- if (m === 0) {
- k = [-g / (2 * h)]
- } else {
- if (m > 0) {
- l = d(m);
- k = [(-g - l) / (2 * h), (-g + l) / (2 * h)]
- } else {
- return []
- }
- }
- for (j = 0; j < k.length; j++) {
- if (k[j] < 0 || k[j] > 1) {
- k[j] = -1
- }
- }
- return k
- },
- linearRoot: function(h, g) {
- var i = -g / h;
- if (h === 0 || i < 0 || i > 1) {
- return []
- }
- return [i]
- },
- bezierCoeffs: function(h, g, k, j) {
- var i = [];
- i[0] = -h + 3 * g - 3 * k + j;
- i[1] = 3 * h - 6 * g + 3 * k;
- i[2] = -3 * h + 3 * g;
- i[3] = h;
- return i
- },
- cubicLineIntersections: function(I, G, F, E, l, k, j, h, M, p, K, n) {
- var u = [],
- N = [],
- D = p - n,
- z = K - M,
- y = M * (n - p) - p * (K - M),
- L = this.bezierCoeffs(I, G, F, E),
- J = this.bezierCoeffs(l, k, j, h),
- H, x, w, v, g, q, o, m;
- u[0] = D * L[0] + z * J[0];
- u[1] = D * L[1] + z * J[1];
- u[2] = D * L[2] + z * J[2];
- u[3] = D * L[3] + z * J[3] + y;
- x = this.cubicRoots(u);
- for (H = 0; H < x.length; H++) {
- v = x[H];
- if (v < 0 || v > 1) {
- continue
- }
- g = v * v;
- q = g * v;
- o = L[0] * q + L[1] * g + L[2] * v + L[3];
- m = J[0] * q + J[1] * g + J[2] * v + J[3];
- if ((K - M) !== 0) {
- w = (o - M) / (K - M)
- } else {
- w = (m - p) / (n - p)
- }
- if (!(w < 0 || w > 1)) {
- N.push([o, m])
- }
- }
- return N
- },
- splitCubic: function(g, q, p, o, m) {
- var j = m * m,
- n = m * j,
- i = m - 1,
- h = i * i,
- k = i * h,
- l = n * o - 3 * j * i * p + 3 * m * h * q - k * g;
- return [
- [g, m * q - i * g, j * p - 2 * m * i * q + h * g, l],
- [l, j * o - 2 * m * i * p + h * q, m * o - i * p, o]
- ]
- },
- cubicDimension: function(p, o, l, k) {
- var j = 3 * (-p + 3 * (o - l) + k),
- i = 6 * (p - 2 * o + l),
- h = -3 * (p - o),
- q, n, g = Math.min(p, k),
- m = Math.max(p, k),
- r;
- if (j === 0) {
- if (i === 0) {
- return [g, m]
- } else {
- q = -h / i;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- }
- } else {
- r = i * i - 4 * j * h;
- if (r >= 0) {
- r = d(r);
- q = (r - i) / 2 / j;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- if (r > 0) {
- q -= r / j;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- }
- }
- }
- return [g, m]
- },
- interpolateCubic: function(h, g, l, k, i) {
- if (i === 0) {
- return h
- }
- if (i === 1) {
- return k
- }
- var j = (1 - i) / i;
- return i * i * i * (k + j * (3 * l + j * (3 * g + j * h)))
- },
- cubicsIntersections: function(r, q, p, o, A, z, y, v, g, F, E, D, m, l, k, i) {
- var C = this,
- x = C.cubicDimension(r, q, p, o),
- B = C.cubicDimension(A, z, y, v),
- n = C.cubicDimension(g, F, E, D),
- s = C.cubicDimension(m, l, k, i),
- j, h, u, t, w = [];
- if (x[0] > n[1] || x[1] < n[0] || B[0] > s[1] || B[1] < s[0]) {
- return []
- }
- if (a(A - z) < 1 && a(y - v) < 1 && a(r - o) < 1 && a(q - p) < 1 && a(m - l) < 1 && a(k - i) < 1 && a(g - D) < 1 && a(F - E) < 1) {
- return [
- [(r + o) * 0.5, (A + z) * 0.5]
- ]
- }
- j = C.splitCubic(r, q, p, o, 0.5);
- h = C.splitCubic(A, z, y, v, 0.5);
- u = C.splitCubic(g, F, E, D, 0.5);
- t = C.splitCubic(m, l, k, i, 0.5);
- w.push.apply(w, C.cubicsIntersections.apply(C, j[0].concat(h[0], u[0], t[0])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[0].concat(h[0], u[1], t[1])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[1].concat(h[1], u[0], t[0])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[1].concat(h[1], u[1], t[1])));
- return w
- },
- linesIntersection: function(k, p, j, o, h, n, q, m) {
- var l = (j - k) * (m - n) - (o - p) * (q - h),
- i, g;
- if (l === 0) {
- return null
- }
- i = ((q - h) * (p - n) - (k - h) * (m - n)) / l;
- g = ((j - k) * (p - n) - (o - p) * (k - h)) / l;
- if (i >= 0 && i <= 1 && g >= 0 && g <= 1) {
- return [k + i * (j - k), p + i * (o - p)]
- }
- return null
- },
- pointOnLine: function(j, m, h, l, g, n) {
- var k, i;
- if (a(h - j) < a(l - m)) {
- i = j;
- j = m;
- m = i;
- i = h;
- h = l;
- l = i;
- i = g;
- g = n;
- n = i
- }
- k = (g - j) / (h - j);
- if (k < 0 || k > 1) {
- return false
- }
- return a(m + k * (l - m) - n) < 4
- },
- pointOnCubic: function(w, u, s, r, l, k, h, g, p, o) {
- var C = this,
- B = C.bezierCoeffs(w, u, s, r),
- A = C.bezierCoeffs(l, k, h, g),
- z, v, n, m, q;
- B[3] -= p;
- A[3] -= o;
- n = C.cubicRoots(B);
- m = C.cubicRoots(A);
- for (z = 0; z < n.length; z++) {
- q = n[z];
- for (v = 0; v < m.length; v++) {
- if (q >= 0 && q <= 1 && a(q - m[v]) < 0.05) {
- return true
- }
- }
- }
- return false
- }
- }
-});
-Ext.define("Ext.chart.series.Pie3D", {
- extend: "Ext.chart.series.Polar",
- requires: ["Ext.chart.series.sprite.Pie3DPart", "Ext.draw.PathUtil"],
- type: "pie3d",
- seriesType: "pie3d",
- alias: "series.pie3d",
- isPie3D: true,
- config: {
- rect: [0, 0, 0, 0],
- thickness: 35,
- distortion: 0.5,
- donut: false,
- hidden: [],
- highlightCfg: {
- margin: 20
- },
- shadow: false
- },
- rotationOffset: -Math.PI / 2,
- setField: function(a) {
- return this.setXField(a)
- },
- getField: function() {
- return this.getXField()
- },
- updateRotation: function(a) {
- this.setStyle({
- baseRotation: a + this.rotationOffset
- });
- this.doUpdateStyles()
- },
- updateDistortion: function() {
- this.setRadius()
- },
- updateThickness: function() {
- this.setRadius()
- },
- updateColors: function(a) {
- this.setSubStyle({
- baseColor: a
- })
- },
- applyShadow: function(a) {
- if (a === true) {
- a = {
- shadowColor: "rgba(0,0,0,0.8)",
- shadowBlur: 30
- }
- } else {
- if (!Ext.isObject(a)) {
- a = {
- shadowColor: Ext.draw.Color.RGBA_NONE
- }
- }
- }
- return a
- },
- updateShadow: function(g) {
- var e = this,
- f = e.getSprites(),
- d = e.spritesPerSlice,
- c = f && f.length,
- b, a;
- for (b = 1; b < c; b += d) {
- a = f[b];
- if (a.attr.part = "bottom") {
- a.setAttributes(g)
- }
- }
- },
- getStyleByIndex: function(b) {
- var d = this.callParent([b]),
- c = this.getStyle(),
- a = d.fillStyle || d.fill || d.color,
- e = c.strokeStyle || c.stroke;
- if (a) {
- d.baseColor = a;
- delete d.fillStyle;
- delete d.fill;
- delete d.color
- }
- if (e) {
- d.strokeStyle = e
- }
- return d
- },
- doUpdateStyles: function() {
- var g = this,
- h = g.getSprites(),
- f = g.spritesPerSlice,
- e = h && h.length,
- c = 0,
- b = 0,
- a, d;
- for (; c < e; c += f, b++) {
- d = g.getStyleByIndex(b);
- for (a = 0; a < f; a++) {
- h[c + a].setAttributes(d)
- }
- }
- },
- coordinateX: function() {
- var w = this,
- m = w.getChart(),
- u = m && m.getAnimation(),
- f = w.getStore(),
- t = f.getData().items,
- d = t.length,
- b = w.getXField(),
- p = w.getRotation(),
- s = w.getHidden(),
- n, c = 0,
- h, e = [],
- k = w.getSprites(),
- a = k.length,
- l = w.spritesPerSlice,
- g = 0,
- o = Math.PI * 2,
- v = 1e-10,
- r, q;
- for (r = 0; r < d; r++) {
- n = Math.abs(Number(t[r].get(b))) || 0;
- if (!s[r]) {
- c += n
- }
- e[r] = c;
- if (r >= s.length) {
- s[r] = false
- }
- }
- s.length = d;
- if (c === 0) {
- return
- }
- h = 2 * Math.PI / c;
- for (r = 0; r < d; r++) {
- e[r] *= h
- }
- for (r = 0; r < a; r++) {
- k[r].setAnimation(u)
- }
- for (r = 0; r < d; r++) {
- for (q = 0; q < l; q++) {
- k[r * l + q].setAttributes({
- startAngle: g,
- endAngle: e[r] - v,
- globalAlpha: 1,
- baseRotation: p
- })
- }
- g = e[r]
- }
- for (r *= l; r < a; r++) {
- k[r].setAnimation(u);
- k[r].setAttributes({
- startAngle: o,
- endAngle: o,
- globalAlpha: 0,
- baseRotation: p
- })
- }
- },
- updateLabelData: function() {
- var l = this,
- m = l.getStore(),
- k = m.getData().items,
- h = l.getSprites(),
- b = l.getLabel().getTemplate().getField(),
- f = l.getHidden(),
- a = l.spritesPerSlice,
- d, c, g, e, n;
- if (h.length && b) {
- e = [];
- for (d = 0, g = k.length; d < g; d++) {
- e.push(k[d].get(b))
- }
- for (d = 0, c = 0, g = h.length; d < g; d += a, c++) {
- n = h[d];
- n.setAttributes({
- label: e[c]
- });
- n.putMarker("labels", {
- hidden: f[c]
- }, n.attr.attributeId)
- }
- }
- },
- applyRadius: function() {
- var f = this,
- d = f.getChart(),
- h = d.getInnerPadding(),
- e = d.getMainRect() || [0, 0, 1, 1],
- c = e[2] - h * 2,
- a = e[3] - h * 2 - f.getThickness(),
- g = c / 2,
- b = g * f.getDistortion();
- if (b > a / 2) {
- return a / (f.getDistortion() * 2)
- } else {
- return g
- }
- },
- getSprites: function() {
- var y = this,
- e = y.getStore();
- if (!e) {
- return []
- }
- var n = y.getChart(),
- p = y.getSurface(),
- t = e.getData().items,
- l = y.spritesPerSlice,
- a = t.length,
- v = y.getAnimation() || n && n.getAnimation(),
- x = y.getCenter(),
- w = y.getOffsetX(),
- u = y.getOffsetY(),
- b = y.getRadius(),
- q = y.getRotation(),
- d = y.getHighlight(),
- c = {
- centerX: x[0] + w,
- centerY: x[1] + u - y.getThickness() / 2,
- endRho: b,
- startRho: b * y.getDonut() / 100,
- thickness: y.getThickness(),
- distortion: y.getDistortion()
- },
- k = y.sprites,
- h = y.getLabel(),
- f = h.getTemplate(),
- m, g, o, s, r;
- for (s = 0; s < a; s++) {
- g = Ext.apply({}, this.getStyleByIndex(s), c);
- if (!k[s * l]) {
- for (r = 0; r < y.partNames.length; r++) {
- o = p.add({
- type: "pie3dPart",
- part: y.partNames[r]
- });
- if (r === 0 && f.getField()) {
- o.bindMarker("labels", h)
- }
- o.fx.setDurationOn("baseRotation", q);
- if (d) {
- o.config.highlight = d;
- o.addModifier("highlight", true)
- }
- o.setAttributes(g);
- k.push(o)
- }
- } else {
- m = k.slice(s * l, (s + 1) * l);
- for (r = 0; r < m.length; r++) {
- o = m[r];
- if (v) {
- o.setAnimation(v)
- }
- o.setAttributes(g)
- }
- }
- }
- return k
- },
- betweenAngle: function(d, f, c) {
- var e = Math.PI * 2,
- g = this.rotationOffset;
- f += g;
- c += g;
- d -= f;
- c -= f;
- d %= e;
- c %= e;
- d += e;
- c += e;
- d %= e;
- c %= e;
- return d < c || c === 0
- },
- getItemForPoint: function(k, j) {
- var h = this,
- g = h.getSprites();
- if (g) {
- var l = h.getStore(),
- b = l.getData().items,
- a = h.spritesPerSlice,
- e = h.getHidden(),
- c, f, m, d;
- for (c = 0, f = b.length; c < f; c++) {
- if (!e[c]) {
- d = c * a;
- m = g[d];
- if (m.hitTest([k, j])) {
- return {
- series: h,
- sprite: g.slice(d, d + a),
- index: c,
- record: b[c],
- category: "sprites",
- field: h.getXField()
- }
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(f) {
- var h = this,
- k = h.getStore();
- if (k) {
- var g = k.getData().items,
- b = h.getLabel().getTemplate().getField(),
- j = h.getField(),
- e = h.getHidden(),
- d, a, c;
- for (d = 0; d < g.length; d++) {
- a = h.getStyleByIndex(d);
- c = a.baseColor;
- f.push({
- name: b ? String(g[d].get(b)) : j + " " + d,
- mark: c || "black",
- disabled: e[d],
- series: h.getId(),
- index: d
- })
- }
- }
- }
-}, function() {
- var b = this.prototype,
- a = Ext.chart.series.sprite.Pie3DPart.def.getInitialConfig().processors.part;
- b.partNames = a.replace(/^enums\(|\)/g, "").split(",");
- b.spritesPerSlice = b.partNames.length
-});
-Ext.define("Ext.chart.series.sprite.Polar", {
- extend: "Ext.chart.series.sprite.Series",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- baseRotation: "number",
- labels: "default",
- labelOverflowPadding: "number"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: 0,
- endAngle: Math.PI,
- startRho: 0,
- endRho: 150,
- baseRotation: 0,
- labels: null,
- labelOverflowPadding: 10
- },
- triggers: {
- centerX: "bbox",
- centerY: "bbox",
- startAngle: "bbox",
- endAngle: "bbox",
- startRho: "bbox",
- endRho: "bbox",
- baseRotation: "bbox"
- }
- }
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.centerX - a.endRho;
- b.y = a.centerY + a.endRho;
- b.width = a.endRho * 2;
- b.height = a.endRho * 2
- }
-});
-Ext.define("Ext.chart.series.sprite.Radar", {
- alias: "sprite.radar",
- extend: "Ext.chart.series.sprite.Polar",
- getDataPointXY: function(d) {
- var u = this,
- n = u.attr,
- f = n.centerX,
- e = n.centerY,
- o = n.matrix,
- t = n.dataMinX,
- s = n.dataMaxX,
- k = n.dataX,
- j = n.dataY,
- l = n.endRho,
- p = n.startRho,
- g = n.baseRotation,
- i, h, m, c, b, a, q;
- if (n.rangeY) {
- q = n.rangeY[1]
- } else {
- q = n.dataMaxY
- }
- c = (k[d] - t) / (s - t + 1) * 2 * Math.PI + g;
- m = j[d] / q * (l - p) + p;
- b = f + Math.cos(c) * m;
- a = e + Math.sin(c) * m;
- i = o.x(b, a);
- h = o.y(b, a);
- return [i, h]
- },
- render: function(a, l) {
- var h = this,
- f = h.attr,
- g = f.dataX,
- b = g.length,
- e = h.surfaceMatrix,
- d = {},
- c, k, j, m;
- l.beginPath();
- for (c = 0; c < b; c++) {
- m = h.getDataPointXY(c);
- k = m[0];
- j = m[1];
- if (c === 0) {
- l.moveTo(k, j)
- }
- l.lineTo(k, j);
- d.translationX = e.x(k, j);
- d.translationY = e.y(k, j);
- h.putMarker("markers", d, c, true)
- }
- l.closePath();
- l.fillStroke(f)
- }
-});
-Ext.define("Ext.chart.series.Radar", {
- extend: "Ext.chart.series.Polar",
- type: "radar",
- seriesType: "radar",
- alias: "series.radar",
- requires: ["Ext.chart.series.sprite.Radar"],
- themeColorCount: function() {
- return 1
- },
- isStoreDependantColorCount: false,
- themeMarkerCount: function() {
- return 1
- },
- updateAngularAxis: function(a) {
- a.processData(this)
- },
- updateRadialAxis: function(a) {
- a.processData(this)
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- updateCenter: function(a) {
- this.setStyle({
- translationX: a[0] + this.getOffsetX(),
- translationY: a[1] + this.getOffsetY()
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- this.setStyle({
- endRho: a
- });
- this.doUpdateStyles()
- },
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a
- });
- this.doUpdateStyles()
- },
- updateTotalAngle: function(a) {
- this.processData()
- },
- getItemForPoint: function(k, j) {
- var h = this,
- m = h.sprites && h.sprites[0],
- f = m.attr,
- g = f.dataX,
- a = g.length,
- l = h.getStore(),
- e = h.getMarker(),
- b, o, p, d, n, c;
- if (h.getHidden()) {
- return null
- }
- if (m && e) {
- c = m.getMarker("markers");
- for (d = 0; d < a; d++) {
- n = c.getBBoxFor(d);
- b = (n.width + n.height) * 0.25;
- p = m.getDataPointXY(d);
- if (Math.abs(p[0] - k) < b && Math.abs(p[1] - j) < b) {
- o = {
- series: h,
- sprite: m,
- index: d,
- category: "markers",
- record: l.getData().items[d],
- field: h.getYField()
- };
- return o
- }
- }
- }
- return h.callParent(arguments)
- },
- getDefaultSpriteConfig: function() {
- var a = this.callParent(),
- b = {
- customDurations: {
- translationX: 0,
- translationY: 0,
- rotationRads: 0,
- dataMinX: 0,
- dataMaxX: 0
- }
- };
- if (a.fx) {
- Ext.apply(a.fx, b)
- } else {
- a.fx = b
- }
- return a
- },
- getSprites: function() {
- var d = this,
- c = d.getChart(),
- e = d.getAnimation() || c && c.getAnimation(),
- b = d.sprites[0],
- a;
- if (!c) {
- return []
- }
- if (!b) {
- b = d.createSprite()
- }
- if (e) {
- a = b.getMarker("markers");
- if (a) {
- a.getTemplate().setAnimation(e)
- }
- b.setAnimation(e)
- }
- return d.sprites
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getSubStyleWithTheme(),
- c = a.fillStyle;
- if (Ext.isArray(c)) {
- c = c[0]
- }
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- }
-});
-Ext.define("Ext.chart.series.sprite.Scatter", {
- alias: "sprite.scatterSeries",
- extend: "Ext.chart.series.sprite.Cartesian",
- renderClipped: function(r, s, w, u) {
- if (this.cleanRedraw) {
- return
- }
- var C = this,
- q = C.attr,
- l = q.dataX,
- h = q.dataY,
- z = q.labels,
- j = C.getSeries(),
- b = z && C.getMarker("labels"),
- t = C.attr.matrix,
- c = t.getXX(),
- p = t.getYY(),
- m = t.getDX(),
- k = t.getDY(),
- n = {},
- D, B, d = r.getInherited().rtl && !q.flipXY ? -1 : 1,
- a, A, o, e, g, f, v;
- if (q.flipXY) {
- a = u[1] - c * d;
- A = u[1] + u[3] + c * d;
- o = u[0] - p;
- e = u[0] + u[2] + p
- } else {
- a = u[0] - c * d;
- A = u[0] + u[2] + c * d;
- o = u[1] - p;
- e = u[1] + u[3] + p
- }
- for (v = 0; v < l.length; v++) {
- g = l[v];
- f = h[v];
- g = g * c + m;
- f = f * p + k;
- if (a <= g && g <= A && o <= f && f <= e) {
- if (q.renderer) {
- n = {
- type: "items",
- translationX: g,
- translationY: f
- };
- B = [C, n, {
- store: C.getStore()
- }, v];
- D = Ext.callback(q.renderer, null, B, 0, j);
- n = Ext.apply(n, D)
- } else {
- n.translationX = g;
- n.translationY = f
- }
- C.putMarker("items", n, v, !q.renderer);
- if (b && z[v]) {
- C.drawLabel(z[v], g, f, v, u)
- }
- }
- }
- },
- drawLabel: function(j, h, g, p, a) {
- var r = this,
- m = r.attr,
- d = r.getMarker("labels"),
- c = d.getTemplate(),
- l = r.labelCfg || (r.labelCfg = {}),
- b = r.surfaceMatrix,
- f, e, i = m.labelOverflowPadding,
- o = m.flipXY,
- k, n, s, q;
- l.text = j;
- n = r.getMarkerBBox("labels", p, true);
- if (!n) {
- r.putMarker("labels", l, p);
- n = r.getMarkerBBox("labels", p, true)
- }
- if (o) {
- l.rotationRads = Math.PI * 0.5
- } else {
- l.rotationRads = 0
- }
- k = n.height / 2;
- f = h;
- switch (c.attr.display) {
- case "under":
- e = g - k - i;
- break;
- case "rotate":
- f += i;
- e = g - i;
- l.rotationRads = -Math.PI / 4;
- break;
- default:
- e = g + k + i
- }
- l.x = b.x(f, e);
- l.y = b.y(f, e);
- if (c.attr.renderer) {
- q = [j, d, l, {
- store: r.getStore()
- }, p];
- s = Ext.callback(c.attr.renderer, null, q, 0, r.getSeries());
- if (typeof s === "string") {
- l.text = s
- } else {
- Ext.apply(l, s)
- }
- }
- r.putMarker("labels", l, p)
- }
-});
-Ext.define("Ext.chart.series.Scatter", {
- extend: "Ext.chart.series.Cartesian",
- alias: "series.scatter",
- type: "scatter",
- seriesType: "scatterSeries",
- requires: ["Ext.chart.series.sprite.Scatter"],
- config: {
- itemInstancing: {
- fx: {
- customDurations: {
- translationX: 0,
- translationY: 0
- }
- }
- }
- },
- themeMarkerCount: function() {
- return 1
- },
- applyMarker: function(b, a) {
- this.getItemInstancing();
- this.setItemInstancing(b);
- return this.callParent(arguments)
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getMarkerStyleByIndex(0),
- c = a.fillStyle;
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- }
-});
-Ext.define("Ext.chart.theme.Blue", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.blue", "chart.theme.Blue"],
- config: {
- baseColor: "#4d7fe6"
- }
-});
-Ext.define("Ext.chart.theme.BlueGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.blue-gradients", "chart.theme.Blue:gradients"],
- config: {
- baseColor: "#4d7fe6",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category1", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category1", "chart.theme.Category1"],
- config: {
- colors: ["#f0a50a", "#c20024", "#2044ba", "#810065", "#7eae29"]
- }
-});
-Ext.define("Ext.chart.theme.Category1Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category1-gradients", "chart.theme.Category1:gradients"],
- config: {
- colors: ["#f0a50a", "#c20024", "#2044ba", "#810065", "#7eae29"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category2", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category2", "chart.theme.Category2"],
- config: {
- colors: ["#6d9824", "#87146e", "#2a9196", "#d39006", "#1e40ac"]
- }
-});
-Ext.define("Ext.chart.theme.Category2Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category2-gradients", "chart.theme.Category2:gradients"],
- config: {
- colors: ["#6d9824", "#87146e", "#2a9196", "#d39006", "#1e40ac"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category3", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category3", "chart.theme.Category3"],
- config: {
- colors: ["#fbbc29", "#ce2e4e", "#7e0062", "#158b90", "#57880e"]
- }
-});
-Ext.define("Ext.chart.theme.Category3Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category3-gradients", "chart.theme.Category3:gradients"],
- config: {
- colors: ["#fbbc29", "#ce2e4e", "#7e0062", "#158b90", "#57880e"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category4", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category4", "chart.theme.Category4"],
- config: {
- colors: ["#ef5773", "#fcbd2a", "#4f770d", "#1d3eaa", "#9b001f"]
- }
-});
-Ext.define("Ext.chart.theme.Category4Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category4-gradients", "chart.theme.Category4:gradients"],
- config: {
- colors: ["#ef5773", "#fcbd2a", "#4f770d", "#1d3eaa", "#9b001f"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category5", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category5", "chart.theme.Category5"],
- config: {
- colors: ["#7eae29", "#fdbe2a", "#910019", "#27b4bc", "#d74dbc"]
- }
-});
-Ext.define("Ext.chart.theme.Category5Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category5-gradients", "chart.theme.Category5:gradients"],
- config: {
- colors: ["#7eae29", "#fdbe2a", "#910019", "#27b4bc", "#d74dbc"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category6", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category6", "chart.theme.Category6"],
- config: {
- colors: ["#44dce1", "#0b2592", "#996e05", "#7fb325", "#b821a1"]
- }
-});
-Ext.define("Ext.chart.theme.Category6Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category6-gradients", "chart.theme.Category6:gradients"],
- config: {
- colors: ["#44dce1", "#0b2592", "#996e05", "#7fb325", "#b821a1"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.DefaultGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.default-gradients", "chart.theme.Base:gradients"],
- config: {
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Green", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.green", "chart.theme.Green"],
- config: {
- baseColor: "#b1da5a"
- }
-});
-Ext.define("Ext.chart.theme.GreenGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.green-gradients", "chart.theme.Green:gradients"],
- config: {
- baseColor: "#b1da5a",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Midnight", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.midnight", "chart.theme.Midnight"],
- config: {
- colors: ["#A837FF", "#4AC0F2", "#FF4D35", "#FF8809", "#61C102", "#FF37EA"],
- chart: {
- defaults: {
- background: "rgb(52, 52, 53)"
- }
- },
- axis: {
- defaults: {
- style: {
- strokeStyle: "rgb(224, 224, 227)"
- },
- label: {
- fillStyle: "rgb(224, 224, 227)"
- },
- title: {
- fillStyle: "rgb(224, 224, 227)"
- },
- grid: {
- strokeStyle: "rgb(112, 112, 115)"
- }
- }
- },
- series: {
- defaults: {
- label: {
- fillStyle: "rgb(224, 224, 227)"
- }
- }
- },
- sprites: {
- text: {
- fillStyle: "rgb(224, 224, 227)"
- }
- }
- }
-});
-Ext.define("Ext.chart.theme.Muted", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.muted", "chart.theme.Muted"],
- config: {
- colors: ["#8ca640", "#974144", "#4091ba", "#8e658e", "#3b8d8b", "#b86465", "#d2af69", "#6e8852", "#3dcc7e", "#a6bed1", "#cbaa4b", "#998baa"]
- }
-});
-Ext.define("Ext.chart.theme.Purple", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.purple", "chart.theme.Purple"],
- config: {
- baseColor: "#da5abd"
- }
-});
-Ext.define("Ext.chart.theme.PurpleGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.purple-gradients", "chart.theme.Purple:gradients"],
- config: {
- baseColor: "#da5abd",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Red", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.red", "chart.theme.Red"],
- config: {
- baseColor: "#e84b67"
- }
-});
-Ext.define("Ext.chart.theme.RedGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.red-gradients", "chart.theme.Red:gradients"],
- config: {
- baseColor: "#e84b67",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Sky", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.sky", "chart.theme.Sky"],
- config: {
- baseColor: "#4ce0e7"
- }
-});
-Ext.define("Ext.chart.theme.SkyGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.sky-gradients", "chart.theme.Sky:gradients"],
- config: {
- baseColor: "#4ce0e7",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Yellow", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.yellow", "chart.theme.Yellow"],
- config: {
- baseColor: "#fec935"
- }
-});
-Ext.define("Ext.chart.theme.YellowGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.yellow-gradients", "chart.theme.Yellow:gradients"],
- config: {
- baseColor: "#fec935",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.draw.Point", {
- requires: ["Ext.draw.Draw", "Ext.draw.Matrix"],
- isPoint: true,
- x: 0,
- y: 0,
- length: 0,
- angle: 0,
- angleUnits: "degrees",
- statics: {
- fly: (function() {
- var a = null;
- return function(b, c) {
- if (!a) {
- a = new Ext.draw.Point()
- }
- a.constructor(b, c);
- return a
- }
- })()
- },
- constructor: function(a, c) {
- var b = this;
- if (typeof a === "number") {
- b.x = a;
- if (typeof c === "number") {
- b.y = c
- } else {
- b.y = a
- }
- } else {
- if (Ext.isArray(a)) {
- b.x = a[0];
- b.y = a[1]
- } else {
- if (a) {
- b.x = a.x;
- b.y = a.y
- }
- }
- }
- b.calculatePolar()
- },
- calculateCartesian: function() {
- var b = this,
- a = b.length,
- c = b.angle;
- if (b.angleUnits === "degrees") {
- c = Ext.draw.Draw.rad(c)
- }
- b.x = Math.cos(c) * a;
- b.y = Math.sin(c) * a
- },
- calculatePolar: function() {
- var b = this,
- a = b.x,
- c = b.y;
- b.length = Math.sqrt(a * a + c * c);
- b.angle = Math.atan2(c, a);
- if (b.angleUnits === "degrees") {
- b.angle = Ext.draw.Draw.degrees(b.angle)
- }
- },
- setX: function(a) {
- this.x = a;
- this.calculatePolar()
- },
- setY: function(a) {
- this.y = a;
- this.calculatePolar()
- },
- set: function(a, b) {
- this.constructor(a, b)
- },
- setAngle: function(a) {
- this.angle = a;
- this.calculateCartesian()
- },
- setLength: function(a) {
- this.length = a;
- this.calculateCartesian()
- },
- setPolar: function(b, a) {
- this.angle = b;
- this.length = a;
- this.calculateCartesian()
- },
- clone: function() {
- return new Ext.draw.Point(this.x, this.y)
- },
- add: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return new Ext.draw.Point(this.x + b.x, this.y + b.y)
- },
- sub: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return new Ext.draw.Point(this.x - b.x, this.y - b.y)
- },
- mul: function(a) {
- return new Ext.draw.Point(this.x * a, this.y * a)
- },
- div: function(a) {
- return new Ext.draw.Point(this.x / a, this.y / a)
- },
- dot: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return this.x * b.x + this.y * b.y
- },
- equals: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return this.x === b.x && this.y === b.y
- },
- rotate: function(f, c) {
- var d, e, b, g, a;
- if (this.angleUnits === "degrees") {
- f = Ext.draw.Draw.rad(f);
- d = Math.sin(f);
- e = Math.cos(f)
- }
- if (c) {
- b = c.x;
- g = c.y
- } else {
- b = 0;
- g = 0
- }
- a = Ext.draw.Matrix.fly([e, d, -d, e, b - e * b + g * d, g - e * g + b * -d]).transformPoint(this);
- return new Ext.draw.Point(a)
- },
- transform: function(a) {
- if (a && a.isMatrix) {
- return new Ext.draw.Point(a.transformPoint(this))
- } else {
- if (arguments.length === 6) {
- return new Ext.draw.Point(Ext.draw.Matrix.fly(arguments).transformPoint(this))
- } else {
- Ext.raise("Invalid parameters.")
- }
- }
- },
- round: function() {
- return new Ext.draw.Point(Math.round(this.x), Math.round(this.y))
- },
- ceil: function() {
- return new Ext.draw.Point(Math.ceil(this.x), Math.ceil(this.y))
- },
- floor: function() {
- return new Ext.draw.Point(Math.floor(this.x), Math.floor(this.y))
- },
- abs: function(a, b) {
- return new Ext.draw.Point(Math.abs(this.x), Math.abs(this.y))
- },
- normalize: function(c) {
- var b = this.x,
- f = this.y,
- a, e, d;
- c = c || 1;
- if (b === 0) {
- a = 0;
- e = c * Ext.Number.sign(f)
- } else {
- d = f / b;
- a = c / Math.sqrt(1 + d * d);
- e = a * d
- }
- return new Ext.draw.Point(a, e)
- },
- getDistanceToLine: function(c, b) {
- if (arguments.length === 4) {
- c = new Ext.draw.Point(arguments[0], arguments[1]);
- b = new Ext.draw.Point(arguments[2], arguments[3])
- }
- var d = b.sub(c).normalize(),
- a = c.sub(this);
- return a.sub(d.mul(a.dot(d)))
- },
- isZero: function() {
- return this.x === 0 && this.y === 0
- },
- isNumber: function() {
- return Ext.isNumber(this.x + this.y)
- }
-});
-Ext.define("Ext.draw.plugin.SpriteEvents", {
- extend: "Ext.plugin.Abstract",
- alias: "plugin.spriteevents",
- requires: ["Ext.draw.PathUtil"],
- mouseMoveEvents: {
- mousemove: true,
- mouseover: true,
- mouseout: true
- },
- spriteMouseMoveEvents: {
- spritemousemove: true,
- spritemouseover: true,
- spritemouseout: true
- },
- init: function(a) {
- var b = "handleEvent";
- this.drawContainer = a;
- a.addElementListener({
- click: b,
- dblclick: b,
- mousedown: b,
- mousemove: b,
- mouseup: b,
- mouseover: b,
- mouseout: b,
- priority: 1001,
- scope: this
- })
- },
- hasSpriteMouseMoveListeners: function() {
- var b = this.drawContainer.hasListeners,
- a;
- for (a in this.spriteMouseMoveEvents) {
- if (a in b) {
- return true
- }
- }
- return false
- },
- hitTestEvent: function(f) {
- var b = this.drawContainer.getItems(),
- a, d, c;
- for (c = b.length - 1; c >= 0; c--) {
- a = b.get(c);
- d = a.hitTestEvent(f);
- if (d) {
- return d
- }
- }
- return null
- },
- handleEvent: function(f) {
- var d = this,
- b = d.drawContainer,
- g = f.type in d.mouseMoveEvents,
- a = d.lastSprite,
- c;
- if (g && !d.hasSpriteMouseMoveListeners()) {
- return
- }
- c = d.hitTestEvent(f);
- if (g && !Ext.Object.equals(c, a)) {
- if (a) {
- b.fireEvent("spritemouseout", a, f)
- }
- if (c) {
- b.fireEvent("spritemouseover", c, f)
- }
- }
- if (c) {
- b.fireEvent("sprite" + f.type, c, f)
- }
- d.lastSprite = c
- }
-});
-Ext.define("Ext.chart.TipSurface", {
- extend: "Ext.draw.Container",
- spriteArray: false,
- renderFirst: true,
- constructor: function(a) {
- this.callParent([a]);
- if (a.sprites) {
- this.spriteArray = [].concat(a.sprites);
- delete a.sprites
- }
- },
- onRender: function() {
- var c = this,
- b = 0,
- a = 0,
- d, e;
- this.callParent(arguments);
- e = c.spriteArray;
- if (c.renderFirst && e) {
- c.renderFirst = false;
- for (a = e.length; b < a; b++) {
- d = c.surface.add(e[b]);
- d.setAttributes({
- hidden: false
- }, true)
- }
- }
- }
-});
-Ext.define("Ext.chart.interactions.ItemInfo", {
- extend: "Ext.chart.interactions.Abstract",
- type: "iteminfo",
- alias: "interaction.iteminfo",
- config: {
- extjsGestures: {
- start: {
- event: "click",
- handler: "onInfoGesture"
- },
- move: {
- event: "mousemove",
- handler: "onInfoGesture"
- },
- end: {
- event: "mouseleave",
- handler: "onInfoGesture"
- }
- }
- },
- item: null,
- onInfoGesture: function(f, a) {
- var c = this,
- b = c.getItemForEvent(f),
- d = b && b.series.tooltip;
- if (d) {
- d.onMouseMove.call(d, f)
- }
- if (b !== c.item) {
- if (b) {
- b.series.showTip(b)
- } else {
- c.item.series.hideTip(c.item)
- }
- c.item = b
- }
- return false
- }
-});
\ No newline at end of file
diff --git a/serverside/jsmod/6.0-4/proxmoxlib.js b/serverside/jsmod/6.0-4/proxmoxlib.js
deleted file mode 100644
index cb8b6d1..0000000
--- a/serverside/jsmod/6.0-4/proxmoxlib.js
+++ /dev/null
@@ -1,7357 +0,0 @@
-// 2.0-5
-Ext.ns('Proxmox');
-Ext.ns('Proxmox.Setup');
-
-if (!Ext.isDefined(Proxmox.Setup.auth_cookie_name)) {
- throw "Proxmox library not initialized";
-}
-
-// 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
-
- yesText: gettext('Yes'),
- noText: gettext('No'),
- enabledText: gettext('Enabled'),
- disabledText: gettext('Disabled'),
- noneText: gettext('none'),
- errorText: gettext('Error'),
- unknownText: gettext('Unknown'),
- defaultText: gettext('Default'),
- daysText: gettext('days'),
- dayText: gettext('day'),
- runningText: gettext('running'),
- stoppedText: gettext('stopped'),
- neverText: gettext('never'),
- totalText: gettext('Total'),
- usedText: gettext('Used'),
- directoryText: gettext('Directory'),
- stateText: gettext('State'),
- groupText: gettext('Group'),
-
- language_map: {
- zh_CN: 'Chinese (Simplified)',
- zh_TW: 'Chinese (Traditional)',
- ca: 'Catalan',
- da: 'Danish',
- en: 'English',
- eu: 'Euskera (Basque)',
- fr: 'French',
- de: 'German',
- it: 'Italian',
- es: 'Spanish',
- ja: 'Japanese',
- nb: 'Norwegian (Bokmal)',
- nn: 'Norwegian (Nynorsk)',
- fa: 'Persian (Farsi)',
- pl: 'Polish',
- pt_BR: 'Portuguese (Brazil)',
- ru: 'Russian',
- sl: 'Slovenian',
- sv: 'Swedish',
- tr: 'Turkish'
- },
-
- render_language: function (value) {
- if (!value) {
- return Proxmox.Utils.defaultText + ' (English)';
- }
- var text = Proxmox.Utils.language_map[value];
- if (text) {
- return text + ' (' + value + ')';
- }
- return value;
- },
-
- language_array: function() {
- var data = [['__default__', Proxmox.Utils.render_language('')]];
- Ext.Object.each(Proxmox.Utils.language_map, function(key, value) {
- data.push([key, Proxmox.Utils.render_language(value)]);
- });
-
- return data;
- },
-
- bond_mode_gettext_map: {
- '802.3ad': 'LACP (802.3ad)',
- 'lacp-balance-slb': 'LACP (balance-slb)',
- 'lacp-balance-tcp': 'LACP (balance-tcp)',
- },
-
- render_bond_mode: value => Proxmox.Utils.bond_mode_gettext_map[value] || value || '',
-
- bond_mode_array: function(modes) {
- return modes.map(mode => [mode, Proxmox.Utils.render_bond_mode(mode)]);
- },
-
- getNoSubKeyHtml: function(url) {
- // url http://www.proxmox.com/products/proxmox-ve/subscription-service-plans
- return Ext.String.format('You do not have a valid subscription for this server. Please visit www.proxmox.com to get a list of available options.', url || 'https://www.proxmox.com');
- },
-
- format_boolean_with_default: function(value) {
- if (Ext.isDefined(value) && value !== '__default__') {
- return value ? Proxmox.Utils.yesText : Proxmox.Utils.noText;
- }
- return Proxmox.Utils.defaultText;
- },
-
- format_boolean: function(value) {
- return value ? Proxmox.Utils.yesText : Proxmox.Utils.noText;
- },
-
- format_neg_boolean: function(value) {
- return !value ? Proxmox.Utils.yesText : Proxmox.Utils.noText;
- },
-
- format_enabled_toggle: function(value) {
- return value ? Proxmox.Utils.enabledText : Proxmox.Utils.disabledText;
- },
-
- format_expire: function(date) {
- if (!date) {
- return Proxmox.Utils.neverText;
- }
- return Ext.Date.format(date, "Y-m-d");
- },
-
- format_duration_long: function(ut) {
-
- var days = Math.floor(ut / 86400);
- ut -= days*86400;
- var hours = Math.floor(ut / 3600);
- ut -= hours*3600;
- var mins = Math.floor(ut / 60);
- ut -= mins*60;
-
- var hours_str = '00' + hours.toString();
- hours_str = hours_str.substr(hours_str.length - 2);
- var mins_str = "00" + mins.toString();
- mins_str = mins_str.substr(mins_str.length - 2);
- var ut_str = "00" + ut.toString();
- ut_str = ut_str.substr(ut_str.length - 2);
-
- if (days) {
- var ds = days > 1 ? Proxmox.Utils.daysText : Proxmox.Utils.dayText;
- return days.toString() + ' ' + ds + ' ' +
- hours_str + ':' + mins_str + ':' + ut_str;
- } else {
- return hours_str + ':' + mins_str + ':' + ut_str;
- }
- },
-
- format_subscription_level: function(level) {
- if (level === 'c') {
- return 'Community';
- } else if (level === 'b') {
- return 'Basic';
- } else if (level === 's') {
- return 'Standard';
- } else if (level === 'p') {
- return 'Premium';
- } else {
- return Proxmox.Utils.noneText;
- }
- },
-
- compute_min_label_width: function(text, width) {
-
- if (width === undefined) { width = 100; }
-
- var tm = new Ext.util.TextMetrics();
- var min = tm.getWidth(text + ':');
-
- return min < width ? width : min;
- },
-
- setAuthData: function(data) {
- Proxmox.CSRFPreventionToken = data.CSRFPreventionToken;
- Proxmox.UserName = data.username;
- Proxmox.LoggedOut = data.LoggedOut;
- // creates a session cookie (expire = null)
- // that way the cookie gets deleted after the browser window is closed
- Ext.util.Cookies.set(Proxmox.Setup.auth_cookie_name, data.ticket, null, '/', null, true);
- },
-
- authOK: function() {
- if (Proxmox.LoggedOut) {
- return undefined;
- }
- return (Proxmox.UserName !== '') && Ext.util.Cookies.get(Proxmox.Setup.auth_cookie_name);
- },
-
- authClear: function() {
- if (Proxmox.LoggedOut) {
- return undefined;
- }
- 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, clearMaskBeforeLoad) {
- if (clearMaskBeforeLoad) {
- me.mon(store, 'beforeload', function(s, operation, eOpts) {
- Proxmox.Utils.setErrorMask(me, false);
- });
- } else {
- 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 += " ";
- Ext.Object.each(result.errors, function(prop, desc) {
- msg += "" + Ext.htmlEncode(prop) + " : " +
- 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) {
- if (Proxmox.Utils.toolkit === 'touch') {
- options.waitMsgTarget.setMasked(false);
- } else {
- 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) {
- if (Proxmox.Utils.toolkit === 'touch') {
- options.waitMsgTarget.setMasked(false);
- } else {
- 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) {
- if (Proxmox.Utils.toolkit === 'touch') {
- target.setMasked({ xtype: 'loadmask', message: newopts.waitMsg} );
- } else {
- // Note: ExtJS bug - this does not work when component is not rendered
- target.setLoading(newopts.waitMsg);
- }
- }
- Ext.Ajax.request(newopts);
- },
-
- checked_command: function(orig_cmd) {
- Proxmox.Utils.API2Request({
- url: '/nodes/localhost/subscription',
- method: 'GET',
- //waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- var data = response.result.data;
-
- if (data.status !== 'Active') {
- Ext.Msg.show({
- title: gettext('No valid subscription'),
- icon: Ext.Msg.WARNING,
- msg: Proxmox.Utils.getNoSubKeyHtml(data.url),
- buttons: Ext.Msg.OK,
- callback: function(btn) {
- if (btn !== 'ok') {
- return;
- }
- orig_cmd();
- }
- });
- } else {
- orig_cmd();
- }
- }
- });
- },
-
- assemble_field_data: function(values, data) {
- if (Ext.isObject(data)) {
- Ext.Object.each(data, function(name, val) {
- if (values.hasOwnProperty(name)) {
- var bucket = values[name];
- if (!Ext.isArray(bucket)) {
- bucket = values[name] = [bucket];
- }
- if (Ext.isArray(val)) {
- values[name] = bucket.concat(val);
- } else {
- bucket.push(val);
- }
- } else {
- values[name] = val;
- }
- });
- }
- },
-
- dialog_title: function(subject, create, isAdd) {
- if (create) {
- if (isAdd) {
- return gettext('Add') + ': ' + subject;
- } else {
- return gettext('Create') + ': ' + subject;
- }
- } else {
- return gettext('Edit') + ': ' + subject;
- }
- },
-
- network_iface_types: {
- eth: gettext("Network Device"),
- bridge: 'Linux Bridge',
- bond: 'Linux Bond',
- vlan: 'Linux VLAN',
- OVSBridge: 'OVS Bridge',
- OVSBond: 'OVS Bond',
- OVSPort: 'OVS Port',
- OVSIntPort: 'OVS IntPort'
- },
-
- render_network_iface_type: function(value) {
- return Proxmox.Utils.network_iface_types[value] ||
- Proxmox.Utils.unknownText;
- },
-
- task_desc_table: {
- acmenewcert: [ 'SRV', gettext('Order Certificate') ],
- acmeregister: [ 'ACME Account', gettext('Register') ],
- acmedeactivate: [ 'ACME Account', gettext('Deactivate') ],
- acmeupdate: [ 'ACME Account', gettext('Update') ],
- acmerefresh: [ 'ACME Account', gettext('Refresh') ],
- acmerenew: [ 'SRV', gettext('Renew Certificate') ],
- acmerevoke: [ 'SRV', gettext('Revoke Certificate') ],
- 'move_volume': [ 'CT', gettext('Move Volume') ],
- clustercreate: [ '', gettext('Create Cluster') ],
- clusterjoin: [ '', gettext('Join Cluster') ],
- diskinit: [ 'Disk', gettext('Initialize Disk with GPT') ],
- vncproxy: [ 'VM/CT', gettext('Console') ],
- spiceproxy: [ 'VM/CT', gettext('Console') + ' (Spice)' ],
- vncshell: [ '', gettext('Shell') ],
- spiceshell: [ '', gettext('Shell') + ' (Spice)' ],
- qmsnapshot: [ 'VM', gettext('Snapshot') ],
- qmrollback: [ 'VM', gettext('Rollback') ],
- qmdelsnapshot: [ 'VM', gettext('Delete Snapshot') ],
- qmcreate: [ 'VM', gettext('Create') ],
- qmrestore: [ 'VM', gettext('Restore') ],
- qmdestroy: [ 'VM', gettext('Destroy') ],
- qmigrate: [ 'VM', gettext('Migrate') ],
- qmclone: [ 'VM', gettext('Clone') ],
- qmmove: [ 'VM', gettext('Move disk') ],
- qmtemplate: [ 'VM', gettext('Convert to template') ],
- qmstart: [ 'VM', gettext('Start') ],
- qmstop: [ 'VM', gettext('Stop') ],
- qmreset: [ 'VM', gettext('Reset') ],
- qmshutdown: [ 'VM', gettext('Shutdown') ],
- qmsuspend: [ 'VM', gettext('Hibernate') ],
- qmpause: [ 'VM', gettext('Pause') ],
- qmresume: [ 'VM', gettext('Resume') ],
- qmconfig: [ 'VM', gettext('Configure') ],
- vzsnapshot: [ 'CT', gettext('Snapshot') ],
- vzrollback: [ 'CT', gettext('Rollback') ],
- vzdelsnapshot: [ 'CT', gettext('Delete Snapshot') ],
- vzcreate: ['CT', gettext('Create') ],
- vzrestore: ['CT', gettext('Restore') ],
- vzdestroy: ['CT', gettext('Destroy') ],
- vzmigrate: [ 'CT', gettext('Migrate') ],
- vzclone: [ 'CT', gettext('Clone') ],
- vztemplate: [ 'CT', gettext('Convert to template') ],
- vzstart: ['CT', gettext('Start') ],
- vzstop: ['CT', gettext('Stop') ],
- vzmount: ['CT', gettext('Mount') ],
- vzumount: ['CT', gettext('Unmount') ],
- vzshutdown: ['CT', gettext('Shutdown') ],
- vzsuspend: [ 'CT', gettext('Suspend') ],
- vzresume: [ 'CT', gettext('Resume') ],
- hamigrate: [ 'HA', gettext('Migrate') ],
- hastart: [ 'HA', gettext('Start') ],
- hastop: [ 'HA', gettext('Stop') ],
- srvstart: ['SRV', gettext('Start') ],
- srvstop: ['SRV', gettext('Stop') ],
- srvrestart: ['SRV', gettext('Restart') ],
- srvreload: ['SRV', gettext('Reload') ],
- cephcreatemgr: ['Ceph Manager', gettext('Create') ],
- cephdestroymgr: ['Ceph Manager', gettext('Destroy') ],
- cephcreatemon: ['Ceph Monitor', gettext('Create') ],
- cephdestroymon: ['Ceph Monitor', gettext('Destroy') ],
- cephcreateosd: ['Ceph OSD', gettext('Create') ],
- cephdestroyosd: ['Ceph OSD', gettext('Destroy') ],
- cephcreatepool: ['Ceph Pool', gettext('Create') ],
- cephdestroypool: ['Ceph Pool', gettext('Destroy') ],
- cephfscreate: ['CephFS', gettext('Create') ],
- cephcreatemds: ['Ceph Metadata Server', gettext('Create') ],
- cephdestroymds: ['Ceph Metadata Server', gettext('Destroy') ],
- imgcopy: ['', gettext('Copy data') ],
- imgdel: ['', gettext('Erase data') ],
- unknownimgdel: ['', gettext('Destroy image from unknown guest') ],
- download: ['', gettext('Download') ],
- vzdump: ['VM/CT', gettext('Backup') ],
- aptupdate: ['', gettext('Update package database') ],
- startall: [ '', gettext('Start all VMs and Containers') ],
- stopall: [ '', gettext('Stop all VMs and Containers') ],
- migrateall: [ '', gettext('Migrate all VMs and Containers') ],
- dircreate: [ gettext('Directory Storage'), gettext('Create') ],
- lvmcreate: [ gettext('LVM Storage'), gettext('Create') ],
- lvmthincreate: [ gettext('LVM-Thin Storage'), gettext('Create') ],
- zfscreate: [ gettext('ZFS Storage'), gettext('Create') ]
- },
-
- format_task_description: function(type, id) {
- var farray = Proxmox.Utils.task_desc_table[type];
- var text;
- if (!farray) {
- text = type;
- if (id) {
- type += ' ' + id;
- }
- return text;
- }
- var prefix = farray[0];
- text = farray[1];
- if (prefix) {
- return prefix + ' ' + id + ' - ' + text;
- }
- return text;
- },
-
- format_size: function(size) {
- /*jslint confusion: true */
-
- var units = ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'];
- var num = 0;
-
- while (size >= 1024 && ((num++)+1) < units.length) {
- size = size / 1024;
- }
-
- return size.toFixed((num > 0)?2:0) + " " + units[num] + "B";
- },
-
- render_upid: function(value, metaData, record) {
- var type = record.data.type;
- var id = record.data.id;
-
- return Proxmox.Utils.format_task_description(type, id);
- },
-
- render_uptime: function(value) {
-
- var uptime = value;
-
- if (uptime === undefined) {
- return '';
- }
-
- if (uptime <= 0) {
- return '-';
- }
-
- return Proxmox.Utils.format_duration_long(uptime);
- },
-
- parse_task_upid: function(upid) {
- var task = {};
-
- 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]+):$/);
- if (!res) {
- throw "unable to parse upid '" + upid + "'";
- }
- task.node = res[1];
- task.pid = parseInt(res[2], 16);
- task.pstart = parseInt(res[3], 16);
- task.starttime = parseInt(res[4], 16);
- task.type = res[5];
- task.id = res[6];
- task.user = res[7];
-
- task.desc = Proxmox.Utils.format_task_description(task.type, task.id);
-
- return task;
- },
-
- render_timestamp: function(value, metaData, record, rowIndex, colIndex, store) {
- var servertime = new Date(value * 1000);
- return Ext.Date.format(servertime, 'Y-m-d H:i:s');
- },
-
- get_help_info: function(section) {
- var helpMap;
- if (typeof proxmoxOnlineHelpInfo !== 'undefined') {
- helpMap = proxmoxOnlineHelpInfo;
- } else if (typeof pveOnlineHelpInfo !== 'undefined') {
- // be backward compatible with older pve-doc-generators
- helpMap = pveOnlineHelpInfo;
- } else {
- throw "no global OnlineHelpInfo map declared";
- }
-
- return helpMap[section];
- },
-
- get_help_link: function(section) {
- var info = Proxmox.Utils.get_help_info(section);
- if (!info) {
- return;
- }
-
- return window.location.origin + info.link;
- },
-
- openXtermJsViewer: function(vmtype, vmid, nodename, vmname, cmd) {
- var url = Ext.Object.toQueryString({
- console: vmtype, // kvm, lxc, upgrade or shell
- xtermjs: 1,
- vmid: vmid,
- vmname: vmname,
- node: nodename,
- cmd: cmd,
-
- });
- var nw = window.open("?" + url, '_blank', 'toolbar=no,location=no,status=no,menubar=no,resizable=yes,width=800,height=420');
- if (nw) {
- nw.focus();
- }
- }
-
-},
-
- 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 + ")";
- var IPV4_CIDR_MASK = "([0-9]{1,2})";
- var IPV6_CIDR_MASK = "([0-9]{1,3})";
-
-
- me.IP4_match = new RegExp("^(?:" + IPV4_REGEXP + ")$");
- me.IP4_cidr_match = new RegExp("^(?:" + IPV4_REGEXP + ")\/" + IPV4_CIDR_MASK + "$");
-
- 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 + ")\/" + IPV6_CIDR_MASK + "$");
- me.IP6_bracket_match = new RegExp("^\\[(" + IPV6_REGEXP + ")\\]");
-
- me.IP64_match = new RegExp("^(?:" + IPV6_REGEXP + "|" + IPV4_REGEXP + ")$");
- me.IP64_cidr_match = new RegExp("^(?:" + IPV6_REGEXP + "\/" + IPV6_CIDR_MASK + ")|(?:" + IPV4_REGEXP + "\/" + IPV4_CIDR_MASK + ")$");
-
- 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+)?$");
- }
-});
-// ExtJS related things
-
- // do not send '_dc' parameter
-Ext.Ajax.disableCaching = false;
-
-// custom Vtypes
-Ext.apply(Ext.form.field.VTypes, {
- IPAddress: function(v) {
- return Proxmox.Utils.IP4_match.test(v);
- },
- IPAddressText: gettext('Example') + ': 192.168.1.1',
- IPAddressMask: /[\d\.]/i,
-
- IPCIDRAddress: function(v) {
- var result = Proxmox.Utils.IP4_cidr_match.exec(v);
- // limits according to JSON Schema see
- // pve-common/src/PVE/JSONSchema.pm
- return (result !== null && result[1] >= 8 && result[1] <= 32);
- },
- IPCIDRAddressText: gettext('Example') + ': 192.168.1.1/24' + " " + gettext('Valid CIDR Range') + ': 8-32',
- IPCIDRAddressMask: /[\d\.\/]/i,
-
- IP6Address: function(v) {
- return Proxmox.Utils.IP6_match.test(v);
- },
- IP6AddressText: gettext('Example') + ': 2001:DB8::42',
- IP6AddressMask: /[A-Fa-f0-9:]/,
-
- IP6CIDRAddress: function(v) {
- var result = Proxmox.Utils.IP6_cidr_match.exec(v);
- // limits according to JSON Schema see
- // pve-common/src/PVE/JSONSchema.pm
- return (result !== null && result[1] >= 8 && result[1] <= 128);
- },
- IP6CIDRAddressText: gettext('Example') + ': 2001:DB8::42/64' + " " + gettext('Valid CIDR Range') + ': 8-128',
- IP6CIDRAddressMask: /[A-Fa-f0-9:\/]/,
-
- IP6PrefixLength: function(v) {
- return v >= 0 && v <= 128;
- },
- IP6PrefixLengthText: gettext('Example') + ': X, where 0 <= X <= 128',
- IP6PrefixLengthMask: /[0-9]/,
-
- IP64Address: function(v) {
- return Proxmox.Utils.IP64_match.test(v);
- },
- IP64AddressText: gettext('Example') + ': 192.168.1.1 2001:DB8::42',
- IP64AddressMask: /[A-Fa-f0-9\.:]/,
-
- IP64CIDRAddress: function(v) {
- var result = Proxmox.Utils.IP64_cidr_match.exec(v);
- if (result === null) {
- return false;
- }
- if (result[1] !== undefined) {
- return result[1] >= 8 && result[1] <= 128;
- } else if (result[2] !== undefined) {
- return result[2] >= 8 && result[2] <= 32;
- } else {
- return false;
- }
- },
- IP64CIDRAddressText: gettext('Example') + ': 192.168.1.1/24 2001:DB8::42/64',
- IP64CIDRAddressMask: /[A-Fa-f0-9\.:\/]/,
-
- MacAddress: function(v) {
- return (/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/).test(v);
- },
- MacAddressMask: /[a-fA-F0-9:]/,
- MacAddressText: gettext('Example') + ': 01:23:45:67:89:ab',
-
- MacPrefix: function(v) {
- return (/^[a-f0-9][02468ace](?::[a-f0-9]{2}){0,2}:?$/i).test(v);
- },
- MacPrefixMask: /[a-fA-F0-9:]/,
- MacPrefixText: gettext('Example') + ': 02:8f - ' + gettext('only unicast addresses are allowed'),
-
- BridgeName: function(v) {
- return (/^vmbr\d{1,4}$/).test(v);
- },
- BridgeNameText: gettext('Format') + ': vmbrN , where 0 <= N <= 9999',
-
- BondName: function(v) {
- return (/^bond\d{1,4}$/).test(v);
- },
- BondNameText: gettext('Format') + ': bondN , where 0 <= N <= 9999',
-
- InterfaceName: function(v) {
- return (/^[a-z][a-z0-9_]{1,20}$/).test(v);
- },
- InterfaceNameText: gettext("Allowed characters") + ": 'a-z', '0-9', '_'" + " " +
- gettext("Minimum characters") + ": 2" + " " +
- gettext("Maximum characters") + ": 21" + " " +
- gettext("Must start with") + ": 'a-z'",
-
- StorageId: function(v) {
- return (/^[a-z][a-z0-9\-\_\.]*[a-z0-9]$/i).test(v);
- },
- StorageIdText: gettext("Allowed characters") + ": 'A-Z', 'a-z', '0-9', '-', '_', '.'" + " " +
- gettext("Minimum characters") + ": 2" + " " +
- gettext("Must start with") + ": 'A-Z', 'a-z' " +
- gettext("Must end with") + ": 'A-Z', 'a-z', '0-9' ",
-
- ConfigId: function(v) {
- return (/^[a-z][a-z0-9\_]+$/i).test(v);
- },
- ConfigIdText: gettext("Allowed characters") + ": 'A-Z', 'a-z', '0-9', '_'" + " " +
- gettext("Minimum characters") + ": 2" + " " +
- gettext("Must start with") + ": " + gettext("letter"),
-
- HttpProxy: function(v) {
- return (/^http:\/\/.*$/).test(v);
- },
- HttpProxyText: gettext('Example') + ": http://username:password@host:port/",
-
- DnsName: function(v) {
- return Proxmox.Utils.DnsName_match.test(v);
- },
- DnsNameText: gettext('This is not a valid DNS name'),
-
- // workaround for https://www.sencha.com/forum/showthread.php?302150
- proxmoxMail: function(v) {
- return (/^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,63}$/).test(v);
- },
- proxmoxMailText: gettext('Example') + ": user@example.com",
-
- DnsOrIp: function(v) {
- if (!Proxmox.Utils.DnsName_match.test(v) &&
- !Proxmox.Utils.IP64_match.test(v)) {
- return false;
- }
-
- return true;
- },
- DnsOrIpText: gettext('Not a valid DNS name or IP address.'),
-
- HostList: function(v) {
- var list = v.split(/[\ \,\;]+/);
- var i;
- for (i = 0; i < list.length; i++) {
- if (list[i] == "") {
- continue;
- }
-
- if (!Proxmox.Utils.HostPort_match.test(list[i]) &&
- !Proxmox.Utils.HostPortBrackets_match.test(list[i]) &&
- !Proxmox.Utils.IP6_dotnotation_match.test(list[i])) {
- return false;
- }
- }
-
- return true;
- },
- HostListText: gettext('Not a valid list of hosts'),
-
- password: function(val, field) {
- if (field.initialPassField) {
- var pwd = field.up('form').down(
- '[name=' + field.initialPassField + ']');
- return (val == pwd.getValue());
- }
- return true;
- },
-
- passwordText: gettext('Passwords do not match')
-});
-
-// Firefox 52+ Touchscreen bug
-// see https://www.sencha.com/forum/showthread.php?336762-Examples-don-t-work-in-Firefox-52-touchscreen/page2
-// and https://bugzilla.proxmox.com/show_bug.cgi?id=1223
-Ext.define('EXTJS_23846.Element', {
- override: 'Ext.dom.Element'
-}, function(Element) {
- var supports = Ext.supports,
- proto = Element.prototype,
- eventMap = proto.eventMap,
- additiveEvents = proto.additiveEvents;
-
- if (Ext.os.is.Desktop && supports.TouchEvents && !supports.PointerEvents) {
- eventMap.touchstart = 'mousedown';
- eventMap.touchmove = 'mousemove';
- eventMap.touchend = 'mouseup';
- eventMap.touchcancel = 'mouseup';
-
- additiveEvents.mousedown = 'mousedown';
- additiveEvents.mousemove = 'mousemove';
- additiveEvents.mouseup = 'mouseup';
- additiveEvents.touchstart = 'touchstart';
- additiveEvents.touchmove = 'touchmove';
- additiveEvents.touchend = 'touchend';
- additiveEvents.touchcancel = 'touchcancel';
-
- additiveEvents.pointerdown = 'mousedown';
- additiveEvents.pointermove = 'mousemove';
- additiveEvents.pointerup = 'mouseup';
- additiveEvents.pointercancel = 'mouseup';
- }
-});
-
-Ext.define('EXTJS_23846.Gesture', {
- override: 'Ext.event.publisher.Gesture'
-}, function(Gesture) {
- var me = Gesture.instance;
-
- if (Ext.supports.TouchEvents && !Ext.isWebKit && Ext.os.is.Desktop) {
- me.handledDomEvents.push('mousedown', 'mousemove', 'mouseup');
- me.registerEvents();
- }
-});
-
-Ext.define('EXTJS_18900.Pie', {
- override: 'Ext.chart.series.Pie',
-
- // from 6.0.2
- betweenAngle: function (x, a, b) {
- var pp = Math.PI * 2,
- offset = this.rotationOffset;
-
- if (a === b) {
- return false;
- }
-
- if (!this.getClockwise()) {
- x *= -1;
- a *= -1;
- b *= -1;
- a -= offset;
- b -= offset;
- } else {
- a += offset;
- b += offset;
- }
-
- x -= a;
- b -= a;
-
- // Normalize, so that both x and b are in the [0,360) interval.
- x %= pp;
- b %= pp;
- x += pp;
- b += pp;
- x %= pp;
- b %= pp;
-
- // Because 360 * n angles will be normalized to 0,
- // we need to treat b === 0 as a special case.
- return x < b || b === 0;
- },
-});
-
-// we always want the number in x.y format and never in, e.g., x,y
-Ext.define('PVE.form.field.Number', {
- override: 'Ext.form.field.Number',
- submitLocaleSeparator: false
-});
-
-// ExtJs 5-6 has an issue with caching
-// see https://www.sencha.com/forum/showthread.php?308989
-Ext.define('Proxmox.UnderlayPool', {
- override: 'Ext.dom.UnderlayPool',
-
- checkOut: function () {
- var cache = this.cache,
- len = cache.length,
- el;
-
- // do cleanup because some of the objects might have been destroyed
- while (len--) {
- if (cache[len].destroyed) {
- cache.splice(len, 1);
- }
- }
- // end do cleanup
-
- el = cache.shift();
-
- if (!el) {
- el = Ext.Element.create(this.elementConfig);
- el.setVisibilityMode(2);
- //
- // tell the spec runner to ignore this element when checking if the dom is clean
- el.dom.setAttribute('data-sticky', true);
- //
- }
-
- return el;
- }
-});
-
-// 'Enter' in Textareas and aria multiline fields should not activate the
-// defaultbutton, fixed in extjs 6.0.2
-Ext.define('PVE.panel.Panel', {
- override: 'Ext.panel.Panel',
-
- fireDefaultButton: function(e) {
- if (e.target.getAttribute('aria-multiline') === 'true' ||
- e.target.tagName === "TEXTAREA") {
- return true;
- }
- return this.callParent(arguments);
- }
-});
-
-// if the order of the values are not the same in originalValue and value
-// extjs will not overwrite value, but marks the field dirty and thus
-// the reset button will be enabled (but clicking it changes nothing)
-// so if the arrays are not the same after resetting, we
-// clear and set it
-Ext.define('Proxmox.form.ComboBox', {
- override: 'Ext.form.field.ComboBox',
-
- reset: function() {
- // copied from combobox
- var me = this;
- me.callParent();
-
- // clear and set when not the same
- var value = me.getValue();
- if (Ext.isArray(me.originalValue) && Ext.isArray(value) && !Ext.Array.equals(value, me.originalValue)) {
- me.clearValue();
- me.setValue(me.originalValue);
- }
- }
-});
-
-// when refreshing a grid/tree view, restoring the focus moves the view back to
-// the previously focused item. Save scroll position before refocusing.
-Ext.define(null, {
- override: 'Ext.view.Table',
-
- jumpToFocus: false,
-
- saveFocusState: function() {
- var me = this,
- store = me.dataSource,
- actionableMode = me.actionableMode,
- navModel = me.getNavigationModel(),
- focusPosition = actionableMode ? me.actionPosition : navModel.getPosition(true),
- refocusRow, refocusCol;
-
- if (focusPosition) {
- // Separate this from the instance that the nav model is using.
- focusPosition = focusPosition.clone();
-
- // Exit actionable mode.
- // We must inform any Actionables that they must relinquish control.
- // Tabbability must be reset.
- if (actionableMode) {
- me.ownerGrid.setActionableMode(false);
- }
-
- // Blur the focused descendant, but do not trigger focusLeave.
- me.el.dom.focus();
-
- // Exiting actionable mode navigates to the owning cell, so in either focus mode we must
- // clear the navigation position
- navModel.setPosition();
-
- // The following function will attempt to refocus back in the same mode to the same cell
- // as it was at before based upon the previous record (if it's still inthe store), or the row index.
- return function() {
- // If we still have data, attempt to refocus in the same mode.
- if (store.getCount()) {
-
- // Adjust expectations of where we are able to refocus according to what kind of destruction
- // might have been wrought on this view's DOM during focus save.
- refocusRow = Math.min(focusPosition.rowIdx, me.all.getCount() - 1);
- refocusCol = Math.min(focusPosition.colIdx, me.getVisibleColumnManager().getColumns().length - 1);
- focusPosition = new Ext.grid.CellContext(me).setPosition(
- store.contains(focusPosition.record) ? focusPosition.record : refocusRow, refocusCol);
-
- if (actionableMode) {
- me.ownerGrid.setActionableMode(true, focusPosition);
- } else {
- me.cellFocused = true;
-
- // we sometimes want to scroll back to where we were
- var x = me.getScrollX();
- var y = me.getScrollY();
-
- // Pass "preventNavigation" as true so that that does not cause selection.
- navModel.setPosition(focusPosition, null, null, null, true);
-
- if (!me.jumpToFocus) {
- me.scrollTo(x,y);
- }
- }
- }
- // No rows - focus associated column header
- else {
- focusPosition.column.focus();
- }
- };
- }
- return Ext.emptyFn;
- }
-});
-
-// should be fixed with ExtJS 6.0.2, see:
-// https://www.sencha.com/forum/showthread.php?307244-Bug-with-datefield-in-window-with-scroll
-Ext.define('Proxmox.Datepicker', {
- override: 'Ext.picker.Date',
- hideMode: 'visibility'
-});
-
-// ExtJS 6.0.1 has no setSubmitValue() (although you find it in the docs).
-// Note: this.submitValue is a boolean flag, whereas getSubmitValue() returns
-// data to be submitted.
-Ext.define('Proxmox.form.field.Text', {
- override: 'Ext.form.field.Text',
-
- setSubmitValue: function(v) {
- this.submitValue = v;
- },
-});
-
-// this should be fixed with ExtJS 6.0.2
-// make mousescrolling work in firefox in the containers overflowhandler
-Ext.define(null, {
- override: 'Ext.layout.container.boxOverflow.Scroller',
-
- createWheelListener: function() {
- var me = this;
- if (Ext.isFirefox) {
- me.wheelListener = me.layout.innerCt.on('wheel', me.onMouseWheelFirefox, me, {destroyable: true});
- } else {
- me.wheelListener = me.layout.innerCt.on('mousewheel', me.onMouseWheel, me, {destroyable: true});
- }
- },
-
- // special wheel handler for firefox. differs from the default onMouseWheel
- // handler by using deltaY instead of wheelDeltaY and no normalizing,
- // because it is already
- onMouseWheelFirefox: function(e) {
- e.stopEvent();
- var delta = e.browserEvent.deltaY || 0;
- this.scrollBy(delta * this.wheelIncrement, false);
- }
-
-});
-
-// add '@' to the valid id
-Ext.define('Proxmox.validIdReOverride', {
- override: 'Ext.Component',
- validIdRe: /^[a-z_][a-z0-9\-_\@]*$/i,
-});
-
-// force alert boxes to be rendered with an Error Icon
-// since Ext.Msg is an object and not a prototype, we need to override it
-// after the framework has been initiated
-Ext.onReady(function() {
-/*jslint confusion: true */
- Ext.override(Ext.Msg, {
- alert: function(title, message, fn, scope) {
- if (Ext.isString(title)) {
- var config = {
- title: title,
- message: message,
- icon: this.ERROR,
- buttons: this.OK,
- fn: fn,
- scope : scope,
- minWidth: this.minWidth
- };
- return this.show(config);
- }
- }
- });
-/*jslint confusion: false */
-});
-Ext.define('Ext.ux.IFrame', {
- extend: 'Ext.Component',
-
- alias: 'widget.uxiframe',
-
- loadMask: 'Loading...',
-
- src: 'about:blank',
-
- renderTpl: [
- ''
- ],
- childEls: ['iframeEl'],
-
- initComponent: function () {
- this.callParent();
-
- this.frameName = this.frameName || this.id + '-frame';
- },
-
- initEvents : function() {
- var me = this;
- me.callParent();
- me.iframeEl.on('load', me.onLoad, me);
- },
-
- initRenderData: function() {
- return Ext.apply(this.callParent(), {
- src: this.src,
- frameName: this.frameName
- });
- },
-
- getBody: function() {
- var doc = this.getDoc();
- return doc.body || doc.documentElement;
- },
-
- getDoc: function() {
- try {
- return this.getWin().document;
- } catch (ex) {
- return null;
- }
- },
-
- getWin: function() {
- var me = this,
- name = me.frameName,
- win = Ext.isIE
- ? me.iframeEl.dom.contentWindow
- : window.frames[name];
- return win;
- },
-
- getFrame: function() {
- var me = this;
- return me.iframeEl.dom;
- },
-
- beforeDestroy: function () {
- this.cleanupListeners(true);
- this.callParent();
- },
-
- cleanupListeners: function(destroying){
- var doc, prop;
-
- if (this.rendered) {
- try {
- doc = this.getDoc();
- if (doc) {
- /*jslint nomen: true*/
- Ext.get(doc).un(this._docListeners);
- /*jslint nomen: false*/
- if (destroying && doc.hasOwnProperty) {
- for (prop in doc) {
- if (doc.hasOwnProperty(prop)) {
- delete doc[prop];
- }
- }
- }
- }
- } catch(e) { }
- }
- },
-
- onLoad: function() {
- var me = this,
- doc = me.getDoc(),
- fn = me.onRelayedEvent;
-
- if (doc) {
- try {
- // These events need to be relayed from the inner document (where they stop
- // bubbling) up to the outer document. This has to be done at the DOM level so
- // the event reaches listeners on elements like the document body. The effected
- // mechanisms that depend on this bubbling behavior are listed to the right
- // of the event.
- /*jslint nomen: true*/
- Ext.get(doc).on(
- me._docListeners = {
- mousedown: fn, // menu dismisal (MenuManager) and Window onMouseDown (toFront)
- mousemove: fn, // window resize drag detection
- mouseup: fn, // window resize termination
- click: fn, // not sure, but just to be safe
- dblclick: fn, // not sure again
- scope: me
- }
- );
- /*jslint nomen: false*/
- } catch(e) {
- // cannot do this xss
- }
-
- // We need to be sure we remove all our events from the iframe on unload or we're going to LEAK!
- Ext.get(this.getWin()).on('beforeunload', me.cleanupListeners, me);
-
- this.el.unmask();
- this.fireEvent('load', this);
-
- } else if (me.src) {
-
- this.el.unmask();
- this.fireEvent('error', this);
- }
-
-
- },
-
- onRelayedEvent: function (event) {
- // relay event from the iframe's document to the document that owns the iframe...
-
- var iframeEl = this.iframeEl,
-
- // Get the left-based iframe position
- iframeXY = iframeEl.getTrueXY(),
- originalEventXY = event.getXY(),
-
- // Get the left-based XY position.
- // This is because the consumer of the injected event will
- // perform its own RTL normalization.
- eventXY = event.getTrueXY();
-
- // the event from the inner document has XY relative to that document's origin,
- // so adjust it to use the origin of the iframe in the outer document:
- event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
-
- event.injectEvent(iframeEl); // blame the iframe for the event...
-
- event.xy = originalEventXY; // restore the original XY (just for safety)
- },
-
- load: function (src) {
- var me = this,
- text = me.loadMask,
- frame = me.getFrame();
-
- if (me.fireEvent('beforeload', me, src) !== false) {
- if (text && me.el) {
- me.el.mask(text);
- }
-
- frame.src = me.src = (src || me.src);
- }
- }
-});
-Ext.define('Proxmox.Mixin.CBind', {
- extend: 'Ext.Mixin',
-
- mixinConfig: {
- before: {
- initComponent: 'cloneTemplates'
- }
- },
-
- cloneTemplates: function() {
- var me = this;
-
- if (typeof(me.cbindData) == "function") {
- me.cbindData = me.cbindData(me.initialConfig) || {};
- }
-
- var getConfigValue = function(cname) {
-
- if (cname in me.initialConfig) {
- return me.initialConfig[cname];
- }
- if (cname in me.cbindData) {
- return me.cbindData[cname];
- }
- if (cname in me) {
- return me[cname];
- }
- throw "unable to get cbind data for '" + cname + "'";
- };
-
- var applyCBind = function(obj) {
- var cbind = obj.cbind, prop, cdata, cvalue, match, found;
- if (!cbind) return;
-
- for (prop in cbind) {
- cdata = cbind[prop];
-
- found = false;
- if (match = /^\{(!)?([a-z_][a-z0-9_]*)\}$/i.exec(cdata)) {
- var cvalue = getConfigValue(match[2]);
- if (match[1]) cvalue = !cvalue;
- obj[prop] = cvalue;
- found = true;
- } else if (match = /^\{(!)?([a-z_][a-z0-9_]*(\.[a-z_][a-z0-9_]*)+)\}$/i.exec(cdata)) {
- var keys = match[2].split('.');
- var cvalue = getConfigValue(keys.shift());
- keys.forEach(function(k) {
- if (k in cvalue) {
- cvalue = cvalue[k];
- } else {
- throw "unable to get cbind data for '" + match[2] + "'";
- }
- });
- if (match[1]) cvalue = !cvalue;
- obj[prop] = cvalue;
- found = true;
- } else {
- obj[prop] = cdata.replace(/{([a-z_][a-z0-9_]*)\}/ig, function(match, cname) {
- var cvalue = getConfigValue(cname);
- found = true;
- return cvalue;
- });
- }
- if (!found) {
- throw "unable to parse cbind template '" + cdata + "'";
- }
-
- }
- };
-
- if (me.cbind) {
- applyCBind(me);
- }
-
- var cloneTemplateArray = function(org) {
- var copy, i, found, el, elcopy, arrayLength;
-
- arrayLength = org.length;
- found = false;
- for (i = 0; i < arrayLength; i++) {
- el = org[i];
- if (el.constructor == Object && el.xtype) {
- found = true;
- break;
- }
- }
-
- if (!found) return org; // no need to copy
-
- copy = [];
- for (i = 0; i < arrayLength; i++) {
- el = org[i];
- if (el.constructor == Object && el.xtype) {
- elcopy = cloneTemplateObject(el);
- if (elcopy.cbind) {
- applyCBind(elcopy);
- }
- copy.push(elcopy);
- } else if (el.constructor == Array) {
- elcopy = cloneTemplateArray(el);
- copy.push(elcopy);
- } else {
- copy.push(el);
- }
- }
- return copy;
- };
-
- var cloneTemplateObject = function(org) {
- var res = {}, prop, el, copy;
- for (prop in org) {
- el = org[prop];
- if (el.constructor == Object && el.xtype) {
- copy = cloneTemplateObject(el);
- if (copy.cbind) {
- applyCBind(copy);
- }
- res[prop] = copy;
- } else if (el.constructor == Array) {
- copy = cloneTemplateArray(el);
- res[prop] = copy;
- } else {
- res[prop] = el;
- }
- }
- return res;
- };
-
- var condCloneProperties = function() {
- var prop, el, i, tmp;
-
- for (prop in me) {
- el = me[prop];
- if (el === undefined || el === null) continue;
- if (typeof(el) === 'object' && el.constructor == Object) {
- if (el.xtype && prop != 'config') {
- me[prop] = cloneTemplateObject(el);
- }
- } else if (el.constructor == Array) {
- tmp = cloneTemplateArray(el);
- me[prop] = tmp;
- }
- }
- };
-
- condCloneProperties();
- }
-});
-/* 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;
- }
-});
-
-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]);
- }
-}, function() {
-
- Ext.define('KeyValue', {
- extend: "Ext.data.Model",
- fields: [ 'key', 'value' ],
- idProperty: 'key'
- });
-
- Ext.define('KeyValuePendingDelete', {
- extend: "Ext.data.Model",
- fields: [ 'key', 'value', 'pending', 'delete' ],
- idProperty: 'key'
- });
-
- Ext.define('proxmox-tasks', {
- extend: 'Ext.data.Model',
- fields: [
- { name: 'starttime', type : 'date', dateFormat: 'timestamp' },
- { name: 'endtime', type : 'date', dateFormat: 'timestamp' },
- { name: 'pid', type: 'int' },
- 'node', 'upid', 'user', 'status', 'type', 'id'
- ],
- idProperty: 'upid'
- });
-
- Ext.define('proxmox-cluster-log', {
- extend: 'Ext.data.Model',
- fields: [
- { name: 'uid' , type: 'int' },
- { name: 'time', type : 'date', dateFormat: 'timestamp' },
- { name: 'pri', type: 'int' },
- { name: 'pid', type: 'int' },
- 'node', 'user', 'tag', 'msg',
- {
- name: 'id',
- convert: function(value, record) {
- var info = record.data;
- var text;
-
- if (value) {
- return value;
- }
- // compute unique ID
- return info.uid + ':' + info.node;
- }
- }
- ],
- idProperty: 'id'
- });
-
-});
-/* 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',
- alias: 'store.update',
-
- isStopped: true,
-
- autoStart: false,
-
- destroy: function() {
- var me = this;
- me.stopUpdate();
- me.callParent();
- },
-
- 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()) {
- var start = new Date();
- me.load(function() {
- var runtime = (new Date()) - start;
- 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(); this makes problems with chrome
- load_task.delay(1, run_load_task);
- },
- stopUpdate: function() {
- me.isStopped = true;
- load_task.cancel();
- }
- });
-
- me.callParent([config]);
-
- me.load_task = load_task;
-
- if (me.autoStart) {
- me.startUpdate();
- }
- }
-});
-/*
- * 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);
- }
-});
-/* 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',
-
- getRecord: function() {
- var me = this;
- var record = Ext.create('Ext.data.Model');
- me.getData().each(function(item) {
- record.set(item.data.key, item.data.value);
- });
- record.commit(true);
- return record;
- },
-
- 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]);
- }
-});
-/* Extends the Proxmox.data.UpdateStore type
- *
- *
- */
-Ext.define('Proxmox.data.RRDStore', {
- extend: 'Proxmox.data.UpdateStore',
- alias: 'store.proxmoxRRDStore',
-
- setRRDUrl: function(timeframe, cf) {
- var me = this;
- if (!timeframe) {
- timeframe = me.timeframe;
- }
-
- if (!cf) {
- cf = me.cf;
- }
-
- me.proxy.url = me.rrdurl + "?timeframe=" + timeframe + "&cf=" + cf;
- },
-
- proxy: {
- type: 'proxmox'
- },
-
- timeframe: 'hour',
-
- cf: 'AVERAGE',
-
- constructor: function(config) {
- var me = this;
-
- config = config || {};
-
- // set default interval to 30seconds
- if (!config.interval) {
- config.interval = 30000;
- }
-
- // set a new storeid
- if (!config.storeid) {
- config.storeid = 'rrdstore-' + (++Ext.idSeed);
- }
-
- // rrdurl is required
- if (!config.rrdurl) {
- throw "no rrdurl specified";
- }
-
- var stateid = 'proxmoxRRDTypeSelection';
- var sp = Ext.state.Manager.getProvider();
- var stateinit = sp.get(stateid);
-
- if (stateinit) {
- if(stateinit.timeframe !== me.timeframe || stateinit.cf !== me.rrdcffn){
- me.timeframe = stateinit.timeframe;
- me.rrdcffn = stateinit.cf;
- }
- }
-
- me.callParent([config]);
-
- me.setRRDUrl();
- me.mon(sp, 'statechange', function(prov, key, state){
- if (key === stateid) {
- if (state && state.id) {
- if (state.timeframe !== me.timeframe || state.cf !== me.cf) {
- me.timeframe = state.timeframe;
- me.cf = state.cf;
- me.setRRDUrl();
- me.reload();
- }
- }
- }
- });
- }
-});
-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'],
- ['UTC']
- ]
-});
-Ext.define('Proxmox.form.field.Integer',{
- extend: 'Ext.form.field.Number',
- alias: 'widget.proxmoxintegerfield',
-
- config: {
- deleteEmpty: false
- },
-
- allowDecimals: false,
- allowExponential: false,
- step: 1,
-
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue && !me.isFileUpload()) {
- val = me.getSubmitValue();
- if (val !== undefined && val !== null && val !== '') {
- data = {};
- data[me.getName()] = val;
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- }
-
-});
-Ext.define('Proxmox.form.field.Textfield', {
- extend: 'Ext.form.field.Text',
- alias: ['widget.proxmoxtextfield'],
-
- config: {
- skipEmptyText: true,
-
- deleteEmpty: false,
- },
-
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue && !me.isFileUpload()) {
- val = me.getSubmitValue();
- if (val !== null) {
- data = {};
- data[me.getName()] = val;
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- getSubmitValue: function() {
- var me = this;
-
- var value = this.processRawValue(this.getRawValue());
- if (value !== '') {
- return value;
- }
-
- return me.getSkipEmptyText() ? null: value;
- },
-
- setAllowBlank: function(allowBlank) {
- this.allowBlank = allowBlank;
- this.validate();
- }
-});
-Ext.define('Proxmox.DateTimeField', {
- extend: 'Ext.form.FieldContainer',
- xtype: 'promxoxDateTimeField',
-
- layout: 'hbox',
-
- referenceHolder: true,
-
- submitFormat: 'U',
-
- getValue: function() {
- var me = this;
- var d = me.lookupReference('dateentry').getValue();
-
- if (d === undefined || d === null) { return null; }
-
- var t = me.lookupReference('timeentry').getValue();
-
- if (t === undefined || t === null) { return null; }
-
- var offset = (t.getHours()*3600+t.getMinutes()*60)*1000;
-
- return new Date(d.getTime() + offset);
- },
-
- getSubmitValue: function() {
- var me = this;
- var format = me.submitFormat;
- var value = me.getValue();
-
- return value ? Ext.Date.format(value, format) : null;
- },
-
- items: [
- {
- xtype: 'datefield',
- editable: false,
- reference: 'dateentry',
- flex: 1,
- format: 'Y-m-d'
- },
- {
- xtype: 'timefield',
- reference: 'timeentry',
- format: 'H:i',
- width: 80,
- value: '00:00',
- increment: 60
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- me.callParent();
-
- var value = me.value || new Date();
-
- me.lookupReference('dateentry').setValue(value);
- me.lookupReference('timeentry').setValue(value);
-
- me.relayEvents(me.lookupReference('dateentry'), ['change']);
- me.relayEvents(me.lookupReference('timeentry'), ['change']);
- }
-});
-Ext.define('Proxmox.form.Checkbox', {
- extend: 'Ext.form.field.Checkbox',
- alias: ['widget.proxmoxcheckbox'],
-
- config: {
- defaultValue: undefined,
- deleteDefaultValue: false,
- deleteEmpty: false
- },
-
- inputValue: '1',
-
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue) {
- val = me.getSubmitValue();
- if (val !== null) {
- data = {};
- if ((val == me.getDefaultValue()) && me.getDeleteDefaultValue()) {
- data['delete'] = me.getName();
- } else {
- data[me.getName()] = val;
- }
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- // also accept integer 1 as true
- setRawValue: function(value) {
- var me = this;
-
- if (value === 1) {
- me.callParent([true]);
- } else {
- me.callParent([value]);
- }
- }
-
-});
-/* Key-Value ComboBox
- *
- * config properties:
- * comboItems: an array of Key - Value pairs
- * deleteEmpty: if set to true (default), an empty value received from the
- * comboBox will reset the property to its default value
- */
-Ext.define('Proxmox.form.KVComboBox', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.proxmoxKVComboBox',
-
- config: {
- deleteEmpty: true
- },
-
- comboItems: undefined,
- displayField: 'value',
- valueField: 'key',
- queryMode: 'local',
-
- // overide framework function to implement deleteEmpty behaviour
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue) {
- val = me.getSubmitValue();
- if (val !== null && val !== '' && val !== '__default__') {
- data = {};
- data[me.getName()] = val;
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- validator: function(val) {
- var me = this;
-
- if (me.editable || val === null || val === '') {
- return true;
- }
-
- if (me.store.getCount() > 0) {
- var values = me.multiSelect ? val.split(me.delimiter) : [val];
- var items = me.store.getData().collect('value', 'data');
- if (Ext.Array.every(values, function(value) {
- return Ext.Array.contains(items, value);
- })) {
- return true;
- }
- }
-
- // returns a boolean or string
- /*jslint confusion: true */
- return "value '" + val + "' not allowed!";
- },
-
- initComponent: function() {
- var me = this;
-
- me.store = Ext.create('Ext.data.ArrayStore', {
- model: 'KeyValue',
- data : me.comboItems
- });
-
- if (me.initialConfig.editable === undefined) {
- me.editable = false;
- }
-
- me.callParent();
- },
-
- setComboItems: function(items) {
- var me = this;
-
- me.getStore().setData(items);
- }
-
-});
-Ext.define('Proxmox.form.LanguageSelector', {
- extend: 'Proxmox.form.KVComboBox',
- xtype: 'proxmoxLanguageSelector',
-
- comboItems: Proxmox.Utils.language_array()
-});
-/*
- * ComboGrid component: a ComboBox where the dropdown menu (the
- * "Picker") is a Grid with Rows and Columns expects a listConfig
- * object with a columns property roughly based on the GridPicker from
- * https://www.sencha.com/forum/showthread.php?299909
- *
-*/
-
-Ext.define('Proxmox.form.ComboGrid', {
- extend: 'Ext.form.field.ComboBox',
- alias: ['widget.proxmoxComboGrid'],
-
- // this value is used as default value after load()
- preferredValue: undefined,
-
- // hack: allow to select empty value
- // seems extjs does not allow that when 'editable == false'
- onKeyUp: function(e, t) {
- var me = this;
- var key = e.getKey();
-
- if (!me.editable && me.allowBlank && !me.multiSelect &&
- (key == e.BACKSPACE || key == e.DELETE)) {
- me.setValue('');
- }
-
- me.callParent(arguments);
- },
-
- config: {
- skipEmptyText: false,
- deleteEmpty: false,
- },
-
- // needed to trigger onKeyUp etc.
- enableKeyEvents: true,
-
- editable: false,
-
- // override ExtJS method
- // if the field has multiSelect enabled, the store is not loaded, and
- // the displayfield == valuefield, it saves the rawvalue as an array
- // but the getRawValue method is only defined in the textfield class
- // (which has not to deal with arrays) an returns the string in the
- // field (not an array)
- //
- // so if we have multiselect enabled, return the rawValue (which
- // should be an array) and else we do callParent so
- // it should not impact any other use of the class
- getRawValue: function() {
- var me = this;
- if (me.multiSelect) {
- return me.rawValue;
- } else {
- return me.callParent();
- }
- },
-
- getSubmitData: function() {
- var me = this;
-
- let data = null;
- if (!me.disabled && me.submitValue) {
- let val = me.getSubmitValue();
- if (val !== null) {
- data = {};
- data[me.getName()] = val;
- } else if (me.getDeleteEmpty()) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- getSubmitValue: function() {
- var me = this;
-
- var value = me.callParent();
- if (value !== '') {
- return value;
- }
-
- return me.getSkipEmptyText() ? null: value;
- },
-
- setAllowBlank: function(allowBlank) {
- this.allowBlank = allowBlank;
- this.validate();
- },
-
-// override ExtJS protected method
- onBindStore: function(store, initial) {
- var me = this,
- picker = me.picker,
- extraKeySpec,
- valueCollectionConfig;
-
- // We're being bound, not unbound...
- if (store) {
- // If store was created from a 2 dimensional array with generated field names 'field1' and 'field2'
- if (store.autoCreated) {
- me.queryMode = 'local';
- me.valueField = me.displayField = 'field1';
- if (!store.expanded) {
- me.displayField = 'field2';
- }
-
- // displayTpl config will need regenerating with the autogenerated displayField name 'field1'
- me.setDisplayTpl(null);
- }
- if (!Ext.isDefined(me.valueField)) {
- me.valueField = me.displayField;
- }
-
- // Add a byValue index to the store so that we can efficiently look up records by the value field
- // when setValue passes string value(s).
- // The two indices (Ext.util.CollectionKeys) are configured unique: false, so that if duplicate keys
- // are found, they are all returned by the get call.
- // This is so that findByText and findByValue are able to return the *FIRST* matching value. By default,
- // if unique is true, CollectionKey keeps the *last* matching value.
- extraKeySpec = {
- byValue: {
- rootProperty: 'data',
- unique: false
- }
- };
- extraKeySpec.byValue.property = me.valueField;
- store.setExtraKeys(extraKeySpec);
-
- if (me.displayField === me.valueField) {
- store.byText = store.byValue;
- } else {
- extraKeySpec.byText = {
- rootProperty: 'data',
- unique: false
- };
- extraKeySpec.byText.property = me.displayField;
- store.setExtraKeys(extraKeySpec);
- }
-
- // We hold a collection of the values which have been selected, keyed by this field's valueField.
- // This collection also functions as the selected items collection for the BoundList's selection model
- valueCollectionConfig = {
- rootProperty: 'data',
- extraKeys: {
- byInternalId: {
- property: 'internalId'
- },
- byValue: {
- property: me.valueField,
- rootProperty: 'data'
- }
- },
- // Whenever this collection is changed by anyone, whether by this field adding to it,
- // or the BoundList operating, we must refresh our value.
- listeners: {
- beginupdate: me.onValueCollectionBeginUpdate,
- endupdate: me.onValueCollectionEndUpdate,
- scope: me
- }
- };
-
- // This becomes our collection of selected records for the Field.
- me.valueCollection = new Ext.util.Collection(valueCollectionConfig);
-
- // We use the selected Collection as our value collection and the basis
- // for rendering the tag list.
-
- //proxmox override: since the picker is represented by a grid panel,
- // we changed here the selection to RowModel
- me.pickerSelectionModel = new Ext.selection.RowModel({
- mode: me.multiSelect ? 'SIMPLE' : 'SINGLE',
- // There are situations when a row is selected on mousedown but then the mouse is dragged to another row
- // and released. In these situations, the event target for the click event won't be the row where the mouse
- // was released but the boundview. The view will then determine that it should fire a container click, and
- // the DataViewModel will then deselect all prior selections. Setting `deselectOnContainerClick` here will
- // prevent the model from deselecting.
- deselectOnContainerClick: false,
- enableInitialSelection: false,
- pruneRemoved: false,
- selected: me.valueCollection,
- store: store,
- listeners: {
- scope: me,
- lastselectedchanged: me.updateBindSelection
- }
- });
-
- if (!initial) {
- me.resetToDefault();
- }
-
- if (picker) {
- picker.setSelectionModel(me.pickerSelectionModel);
- if (picker.getStore() !== store) {
- picker.bindStore(store);
- }
- }
- }
- },
-
- // copied from ComboBox
- createPicker: function() {
- var me = this;
- var picker;
-
- var pickerCfg = Ext.apply({
- // proxmox overrides: display a grid for selection
- xtype: 'gridpanel',
- id: me.pickerId,
- pickerField: me,
- floating: true,
- hidden: true,
- store: me.store,
- displayField: me.displayField,
- preserveScrollOnRefresh: true,
- pageSize: me.pageSize,
- tpl: me.tpl,
- selModel: me.pickerSelectionModel,
- focusOnToFront: false
- }, me.listConfig, me.defaultListConfig);
-
- picker = me.picker || Ext.widget(pickerCfg);
-
- if (picker.getStore() !== me.store) {
- picker.bindStore(me.store);
- }
-
- if (me.pageSize) {
- picker.pagingToolbar.on('beforechange', me.onPageChange, me);
- }
-
- // proxmox overrides: pass missing method in gridPanel to its view
- picker.refresh = function() {
- picker.getSelectionModel().select(me.valueCollection.getRange());
- picker.getView().refresh();
- };
- picker.getNodeByRecord = function() {
- picker.getView().getNodeByRecord(arguments);
- };
-
- // We limit the height of the picker to fit in the space above
- // or below this field unless the picker has its own ideas about that.
- if (!picker.initialConfig.maxHeight) {
- picker.on({
- beforeshow: me.onBeforePickerShow,
- scope: me
- });
- }
- picker.getSelectionModel().on({
- beforeselect: me.onBeforeSelect,
- beforedeselect: me.onBeforeDeselect,
- focuschange: me.onFocusChange,
- selectionChange: function (sm, selectedRecords) {
- var me = this;
- if (selectedRecords.length) {
- me.setValue(selectedRecords);
- me.fireEvent('select', me, selectedRecords);
- }
- },
- scope: me
- });
-
- // hack for extjs6
- // when the clicked item is the same as the previously selected,
- // it does not select the item
- // instead we hide the picker
- if (!me.multiSelect) {
- picker.on('itemclick', function (sm,record) {
- if (picker.getSelection()[0] === record) {
- picker.hide();
- }
- });
- }
-
- // when our store is not yet loaded, we increase
- // the height of the gridpanel, so that we can see
- // the loading mask
- //
- // we save the minheight to reset it after the load
- picker.on('show', function() {
- if (me.enableLoadMask) {
- me.savedMinHeight = picker.getMinHeight();
- picker.setMinHeight(100);
- }
- });
-
- picker.getNavigationModel().navigateOnSpace = false;
-
- return picker;
- },
-
- initComponent: function() {
- var me = this;
-
- Ext.apply(me, {
- queryMode: 'local',
- matchFieldWidth: false
- });
-
- Ext.applyIf(me, { value: ''}); // hack: avoid ExtJS validate() bug
-
- Ext.applyIf(me.listConfig, { width: 400 });
-
- me.callParent();
-
- // Create the picker at an early stage, so it is available to store the previous selection
- if (!me.picker) {
- me.createPicker();
- }
-
- if (me.editable) {
- // The trigger.picker causes first a focus event on the field then
- // toggles the selection picker. Thus skip expanding in this case,
- // else our focus listner expands and the picker.trigger then
- // collapses it directly afterwards.
- Ext.override(me.triggers.picker, {
- onMouseDown : function (e) {
- // copied "should we focus" check from Ext.form.trigger.Trigger
- if (e.pointerType !== 'touch' && !this.field.owns(Ext.Element.getActiveElement())) {
- me.skip_expand_on_focus = true;
- }
- this.callParent(arguments);
- }
- });
-
- me.on("focus", function(me) {
- if (!me.isExpanded && !me.skip_expand_on_focus) {
- me.expand();
- }
- me.skip_expand_on_focus = false;
- });
- }
-
- me.mon(me.store, 'beforeload', function() {
- if (!me.isDisabled()) {
- me.enableLoadMask = true;
- }
- });
-
- // hack: autoSelect does not work
- me.mon(me.store, 'load', function(store, r, success, o) {
- if (success) {
- me.clearInvalid();
-
- if (me.enableLoadMask) {
- delete me.enableLoadMask;
-
- // if the picker exists,
- // we reset its minheight to the saved var/0
- // we have to update the layout, otherwise the height
- // gets not recalculated
- if (me.picker) {
- me.picker.setMinHeight(me.savedMinHeight || 0);
- delete me.savedMinHeight;
- me.picker.updateLayout();
- }
- }
-
- var def = me.getValue() || me.preferredValue;
- if (def) {
- me.setValue(def, true); // sync with grid
- }
- var found = false;
- if (def) {
- if (Ext.isArray(def)) {
- Ext.Array.each(def, function(v) {
- if (store.findRecord(me.valueField, v)) {
- found = true;
- return false; // break
- }
- });
- } else {
- found = store.findRecord(me.valueField, def);
- }
- }
-
- if (!found) {
- var rec = me.store.first();
- if (me.autoSelect && rec && rec.data) {
- def = rec.data[me.valueField];
- me.setValue(def, true);
- } else {
- me.setValue(me.editable ? def : '', true);
- }
- }
- }
- });
- }
-});
-Ext.define('Proxmox.form.RRDTypeSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: ['widget.proxmoxRRDTypeSelector'],
-
- displayField: 'text',
- valueField: 'id',
- editable: false,
- queryMode: 'local',
- value: 'hour',
- stateEvents: [ 'select' ],
- stateful: true,
- stateId: 'proxmoxRRDTypeSelection',
- store: {
- type: 'array',
- fields: [ 'id', 'timeframe', 'cf', 'text' ],
- data : [
- [ 'hour', 'hour', 'AVERAGE',
- gettext('Hour') + ' (' + gettext('average') +')' ],
- [ 'hourmax', 'hour', 'MAX',
- gettext('Hour') + ' (' + gettext('maximum') + ')' ],
- [ 'day', 'day', 'AVERAGE',
- gettext('Day') + ' (' + gettext('average') + ')' ],
- [ 'daymax', 'day', 'MAX',
- gettext('Day') + ' (' + gettext('maximum') + ')' ],
- [ 'week', 'week', 'AVERAGE',
- gettext('Week') + ' (' + gettext('average') + ')' ],
- [ 'weekmax', 'week', 'MAX',
- gettext('Week') + ' (' + gettext('maximum') + ')' ],
- [ 'month', 'month', 'AVERAGE',
- gettext('Month') + ' (' + gettext('average') + ')' ],
- [ 'monthmax', 'month', 'MAX',
- gettext('Month') + ' (' + gettext('maximum') + ')' ],
- [ 'year', 'year', 'AVERAGE',
- gettext('Year') + ' (' + gettext('average') + ')' ],
- [ 'yearmax', 'year', 'MAX',
- gettext('Year') + ' (' + gettext('maximum') + ')' ]
- ]
- },
- // save current selection in the state Provider so RRDView can read it
- getState: function() {
- var ind = this.getStore().findExact('id', this.getValue());
- var rec = this.getStore().getAt(ind);
- if (!rec) {
- return;
- }
- return {
- id: rec.data.id,
- timeframe: rec.data.timeframe,
- cf: rec.data.cf
- };
- },
- // set selection based on last saved state
- applyState : function(state) {
- if (state && state.id) {
- this.setValue(state.id);
- }
- }
-});
-Ext.define('Proxmox.form.BondModeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.bondModeSelector'],
-
- openvswitch: false,
-
- initComponent: function() {
- var me = this;
-
- if (me.openvswitch) {
- me.comboItems = Proxmox.Utils.bond_mode_array([
- 'active-backup',
- 'balance-slb',
- 'lacp-balance-slb',
- 'lacp-balance-tcp',
- ]);
- } else {
- me.comboItems = Proxmox.Utils.bond_mode_array([
- 'balance-rr',
- 'active-backup',
- 'balance-xor',
- 'broadcast',
- '802.3ad',
- 'balance-tlb',
- 'balance-alb',
- ]);
- }
-
- me.callParent();
- }
-});
-
-Ext.define('Proxmox.form.BondPolicySelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.bondPolicySelector'],
- comboItems: [
- ['layer2', 'layer2'],
- ['layer2+3', 'layer2+3'],
- ['layer3+4', 'layer3+4']
- ]
-});
-
-Ext.define('Proxmox.form.NetworkSelectorController', {
- extend: 'Ext.app.ViewController',
- alias: 'controller.proxmoxNetworkSelectorController',
-
- init: function(view) {
- var me = this;
-
- if (!view.nodename) {
- throw "missing custom view config: nodename";
- }
- view.getStore().getProxy().setUrl('/api2/json/nodes/'+ view.nodename + '/network');
- }
-});
-
-Ext.define('Proxmox.data.NetworkSelector', {
- extend: 'Ext.data.Model',
- fields: [
- {name: 'active'},
- {name: 'cidr'},
- {name: 'cidr6'},
- {name: 'address'},
- {name: 'address6'},
- {name: 'comments'},
- {name: 'iface'},
- {name: 'slaves'},
- {name: 'type'}
- ]
-});
-
-Ext.define('Proxmox.form.NetworkSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.proxmoxNetworkSelector',
-
- controller: 'proxmoxNetworkSelectorController',
-
- nodename: 'localhost',
- setNodename: function(nodename) {
- this.nodename = nodename;
- var networkSelectorStore = this.getStore();
- networkSelectorStore.removeAll();
- // because of manual local copy of data for ip4/6
- this.getPicker().refresh();
- if (networkSelectorStore && typeof networkSelectorStore.getProxy === 'function') {
- networkSelectorStore.getProxy().setUrl('/api2/json/nodes/'+ nodename + '/network');
- networkSelectorStore.load();
- }
- },
- // set default value to empty array, else it inits it with
- // null and after the store load it is an empty array,
- // triggering dirtychange
- value: [],
- valueField: 'cidr',
- displayField: 'cidr',
- store: {
- autoLoad: true,
- model: 'Proxmox.data.NetworkSelector',
- proxy: {
- type: 'proxmox'
- },
- sorters: [
- {
- property : 'iface',
- direction: 'ASC'
- }
- ],
- filters: [
- function(item) {
- return item.data.cidr;
- }
- ],
- listeners: {
- load: function(store, records, successfull) {
-
- if (successfull) {
- records.forEach(function(record) {
- if (record.data.cidr6) {
- let dest = (record.data.cidr) ? record.copy(null) : record;
- dest.data.cidr = record.data.cidr6;
- dest.data.address = record.data.address6;
- delete record.data.cidr6;
- dest.data.comments = record.data.comments6;
- delete record.data.comments6;
- store.add(dest);
- }
- });
- }
- }
- }
- },
- listConfig: {
- width: 600,
- columns: [
- {
-
- header: gettext('CIDR'),
- dataIndex: 'cidr',
- hideable: false,
- flex: 1
- },
- {
-
- header: gettext('IP'),
- dataIndex: 'address',
- hidden: true,
- },
- {
- header: gettext('Interface'),
- width: 90,
- dataIndex: 'iface'
- },
- {
- header: gettext('Active'),
- renderer: Proxmox.Utils.format_boolean,
- width: 60,
- dataIndex: 'active'
- },
- {
- header: gettext('Type'),
- width: 80,
- hidden: true,
- dataIndex: 'type'
- },
- {
- header: gettext('Comment'),
- flex: 2,
- dataIndex: 'comments'
- }
- ]
- }
-});
-/* Button features:
- * - observe selection changes to enable/disable the button using enableFn()
- * - pop up confirmation dialog using confirmMsg()
- */
-Ext.define('Proxmox.button.Button', {
- extend: 'Ext.button.Button',
- alias: 'widget.proxmoxButton',
-
- // the selection model to observe
- selModel: undefined,
-
- // if 'false' handler will not be called (button disabled)
- enableFn: function(record) { },
-
- // function(record) or text
- confirmMsg: false,
-
- // take special care in confirm box (select no as default).
- dangerous: false,
-
- initComponent: function() {
- /*jslint confusion: true */
-
- var me = this;
-
- if (me.handler) {
-
- // Note: me.realHandler may be a string (see named scopes)
- var realHandler = me.handler;
-
- me.handler = function(button, event) {
- var rec, msg;
- if (me.selModel) {
- rec = me.selModel.getSelection()[0];
- if (!rec || (me.enableFn(rec) === false)) {
- return;
- }
- }
-
- if (me.confirmMsg) {
- msg = me.confirmMsg;
- if (Ext.isFunction(me.confirmMsg)) {
- msg = me.confirmMsg(rec);
- }
- Ext.MessageBox.defaultButton = me.dangerous ? 2 : 1;
- Ext.Msg.show({
- title: gettext('Confirm'),
- icon: me.dangerous ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
- msg: msg,
- buttons: Ext.Msg.YESNO,
- defaultFocus: me.dangerous ? 'no' : 'yes',
- callback: function(btn) {
- if (btn !== 'yes') {
- return;
- }
- Ext.callback(realHandler, me.scope, [button, event, rec], 0, me);
- }
- });
- } else {
- Ext.callback(realHandler, me.scope, [button, event, rec], 0, me);
- }
- };
- }
-
- me.callParent();
-
- var grid;
- if (!me.selModel && me.selModel !== null) {
- grid = me.up('grid');
- if (grid && grid.selModel) {
- me.selModel = grid.selModel;
- }
- }
-
- if (me.waitMsgTarget === true) {
- grid = me.up('grid');
- if (grid) {
- me.waitMsgTarget = grid;
- } else {
- throw "unable to find waitMsgTarget";
- }
- }
-
- if (me.selModel) {
-
- me.mon(me.selModel, "selectionchange", function() {
- var rec = me.selModel.getSelection()[0];
- if (!rec || (me.enableFn(rec) === false)) {
- me.setDisabled(true);
- } else {
- me.setDisabled(false);
- }
- });
- }
- }
-});
-
-
-Ext.define('Proxmox.button.StdRemoveButton', {
- extend: 'Proxmox.button.Button',
- alias: 'widget.proxmoxStdRemoveButton',
-
- text: gettext('Remove'),
-
- disabled: true,
-
- config: {
- baseurl: undefined
- },
-
- getUrl: function(rec) {
- var me = this;
-
- return me.baseurl + '/' + rec.getId();
- },
-
- // also works with names scopes
- callback: function(options, success, response) {},
-
- getRecordName: function(rec) { return rec.getId() },
-
- confirmMsg: function (rec) {
- var me = this;
-
- var name = me.getRecordName(rec);
- return Ext.String.format(
- gettext('Are you sure you want to remove entry {0}'),
- "'" + name + "'");
- },
-
- handler: function(btn, event, rec) {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: me.getUrl(rec),
- method: 'DELETE',
- waitMsgTarget: me.waitMsgTarget,
- callback: function(options, success, response) {
- Ext.callback(me.callback, me.scope, [options, success, response], 0, me);
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
-});
-/* help button pointing to an online documentation
- for components contained in a modal window
-*/
-/*global
- proxmoxOnlineHelpInfo
-*/
-Ext.define('Proxmox.button.Help', {
- extend: 'Ext.button.Button',
- xtype: 'proxmoxHelpButton',
-
- text: gettext('Help'),
-
- // make help button less flashy by styling it like toolbar buttons
- iconCls: ' x-btn-icon-el-default-toolbar-small fa fa-question-circle',
- cls: 'x-btn-default-toolbar-small proxmox-inline-button',
-
- hidden: true,
-
- listenToGlobalEvent: true,
-
- controller: {
- xclass: 'Ext.app.ViewController',
- listen: {
- global: {
- proxmoxShowHelp: 'onProxmoxShowHelp',
- proxmoxHideHelp: 'onProxmoxHideHelp'
- }
- },
- onProxmoxShowHelp: function(helpLink) {
- var me = this.getView();
- if (me.listenToGlobalEvent === true) {
- me.setOnlineHelp(helpLink);
- me.show();
- }
- },
- onProxmoxHideHelp: function() {
- var me = this.getView();
- if (me.listenToGlobalEvent === true) {
- me.hide();
- }
- }
- },
-
- // this sets the link and the tooltip text
- setOnlineHelp:function(blockid) {
- var me = this;
-
- var info = Proxmox.Utils.get_help_info(blockid);
- if (info) {
- me.onlineHelp = blockid;
- var title = info.title;
- if (info.subtitle) {
- title += ' - ' + info.subtitle;
- }
- me.setTooltip(title);
- }
- },
-
- // helper to set the onlineHelp via a config object
- setHelpConfig: function(config) {
- var me = this;
- me.setOnlineHelp(config.onlineHelp);
- },
-
- handler: function() {
- var me = this;
- var docsURI;
-
- if (me.onlineHelp) {
- docsURI = Proxmox.Utils.get_help_link(me.onlineHelp);
- }
-
- if (docsURI) {
- window.open(docsURI);
- } else {
- Ext.Msg.alert(gettext('Help'), gettext('No Help available'));
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.callParent();
-
- if (me.onlineHelp) {
- me.setOnlineHelp(me.onlineHelp); // set tooltip
- }
- }
-});
-/* Renders a list of key values objets
-
-mandatory config parameters:
-rows: an object container where each propery is a key-value object we want to render
- var rows = {
- keyboard: {
- header: gettext('Keyboard Layout'),
- editor: 'Your.KeyboardEdit',
- required: true
- },
-
-optional:
-disabled: setting this parameter to true will disable selection and focus on the
-proxmoxObjectGrid as well as greying out input elements.
-Useful for a readonly tabular display
-
-*/
-
-Ext.define('Proxmox.grid.ObjectGrid', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.proxmoxObjectGrid'],
- disabled: false,
- hideHeaders: true,
-
- monStoreErrors: false,
-
- add_combobox_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {};
- me.rows = me.rows || {};
-
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue,
- header: text,
- renderer: opts.renderer,
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- items: {
- xtype: 'proxmoxKVComboBox',
- name: name,
- comboItems: opts.comboItems,
- value: opts.defaultValue,
- deleteEmpty: opts.deleteEmpty ? true : false,
- emptyText: opts.defaultValue,
- labelWidth: Proxmox.Utils.compute_min_label_width(
- text, opts.labelWidth),
- fieldLabel: text
- }
- }
- };
- },
-
- add_text_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {};
- me.rows = me.rows || {};
-
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue,
- header: text,
- renderer: opts.renderer,
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- items: {
- xtype: 'proxmoxtextfield',
- name: name,
- deleteEmpty: opts.deleteEmpty ? true : false,
- emptyText: opts.defaultValue,
- labelWidth: Proxmox.Utils.compute_min_label_width(
- text, opts.labelWidth),
- vtype: opts.vtype,
- fieldLabel: text
- }
- }
- };
- },
-
- add_boolean_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {};
- me.rows = me.rows || {};
-
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue || 0,
- header: text,
- renderer: opts.renderer || Proxmox.Utils.format_boolean,
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- items: {
- xtype: 'proxmoxcheckbox',
- name: name,
- uncheckedValue: 0,
- defaultValue: opts.defaultValue || 0,
- checked: opts.defaultValue ? true : false,
- deleteDefaultValue: opts.deleteDefaultValue ? true : false,
- labelWidth: Proxmox.Utils.compute_min_label_width(
- text, opts.labelWidth),
- fieldLabel: text
- }
- }
- };
- },
-
- add_integer_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {}
- me.rows = me.rows || {};
-
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue,
- header: text,
- renderer: opts.renderer,
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- items: {
- xtype: 'proxmoxintegerfield',
- name: name,
- minValue: opts.minValue,
- maxValue: opts.maxValue,
- emptyText: gettext('Default'),
- deleteEmpty: opts.deleteEmpty ? true : false,
- value: opts.defaultValue,
- labelWidth: Proxmox.Utils.compute_min_label_width(
- text, opts.labelWidth),
- fieldLabel: text
- }
- }
- };
- },
-
- editorConfig: {}, // default config passed to editor
-
- run_editor: function() {
- var me = this;
-
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var rows = me.rows;
- var rowdef = rows[rec.data.key];
- if (!rowdef.editor) {
- return;
- }
-
- var win;
- var config;
- if (Ext.isString(rowdef.editor)) {
- config = Ext.apply({
- confid: rec.data.key,
- }, me.editorConfig);
- win = Ext.create(rowdef.editor, config);
- } else {
- config = Ext.apply({
- confid: rec.data.key,
- }, me.editorConfig);
- Ext.apply(config, rowdef.editor);
- win = Ext.createWidget(rowdef.editor.xtype, config);
- win.load();
- }
-
- win.show();
- win.on('destroy', me.reload, me);
- },
-
- reload: function() {
- var me = this;
- me.rstore.load();
- },
-
- getObjectValue: function(key, defaultValue) {
- var me = this;
- var rec = me.store.getById(key);
- if (rec) {
- return rec.data.value;
- }
- return defaultValue;
- },
-
- renderKey: function(key, metaData, record, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var rowdef = (rows && rows[key]) ? rows[key] : {};
- return rowdef.header || key;
- },
-
- renderValue: function(value, metaData, record, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var key = record.data.key;
- var rowdef = (rows && rows[key]) ? rows[key] : {};
-
- var renderer = rowdef.renderer;
- if (renderer) {
- return renderer(value, metaData, record, rowIndex, colIndex, store);
- }
-
- return value;
- },
-
- listeners: {
- itemkeydown: function(view, record, item, index, e) {
- if (e.getKey() === e.ENTER) {
- this.pressedIndex = index;
- }
- },
- itemkeyup: function(view, record, item, index, e) {
- if (e.getKey() === e.ENTER && index == this.pressedIndex) {
- this.run_editor();
- }
-
- this.pressedIndex = undefined;
- }
- },
-
- initComponent : function() {
- var me = this;
-
- var rows = me.rows;
-
- if (!me.rstore) {
- if (!me.url) {
- throw "no url specified";
- }
-
- me.rstore = Ext.create('Proxmox.data.ObjectStore', {
- url: me.url,
- interval: me.interval,
- extraParams: me.extraParams,
- rows: me.rows
- });
- }
-
- var rstore = me.rstore;
-
- var store = Ext.create('Proxmox.data.DiffStore', { rstore: rstore,
- sorters: [],
- filters: []
- });
-
- if (rows) {
- Ext.Object.each(rows, function(key, rowdef) {
- if (Ext.isDefined(rowdef.defaultValue)) {
- store.add({ key: key, value: rowdef.defaultValue });
- } else if (rowdef.required) {
- store.add({ key: key, value: undefined });
- }
- });
- }
-
- if (me.sorterFn) {
- store.sorters.add(Ext.create('Ext.util.Sorter', {
- sorterFn: me.sorterFn
- }));
- }
-
- store.filters.add(Ext.create('Ext.util.Filter', {
- filterFn: function(item) {
- if (rows) {
- var rowdef = rows[item.data.key];
- if (!rowdef || (rowdef.visible === false)) {
- return false;
- }
- }
- return true;
- }
- }));
-
- Proxmox.Utils.monStoreErrors(me, rstore);
-
- Ext.applyIf(me, {
- store: store,
- stateful: false,
- columns: [
- {
- header: gettext('Name'),
- width: me.cwidth1 || 200,
- dataIndex: 'key',
- renderer: me.renderKey
- },
- {
- flex: 1,
- header: gettext('Value'),
- dataIndex: 'value',
- renderer: me.renderValue
- }
- ]
- });
-
- me.callParent();
-
- if (me.monStoreErrors) {
- Proxmox.Utils.monStoreErrors(me, me.store);
- }
- }
-});
-Ext.define('Proxmox.grid.PendingObjectGrid', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.proxmoxPendingObjectGrid'],
-
- getObjectValue: function(key, defaultValue, pending) {
- var me = this;
- var rec = me.store.getById(key);
- if (rec) {
- var value = rec.data.value;
- if (pending) {
- if (Ext.isDefined(rec.data.pending) && rec.data.pending !== '') {
- value = rec.data.pending;
- } else if (rec.data['delete'] === 1) {
- value = defaultValue;
- }
- }
-
- if (Ext.isDefined(value) && (value !== '')) {
- return value;
- } else {
- return defaultValue;
- }
- }
- return defaultValue;
- },
-
- hasPendingChanges: function(key) {
- var me = this;
- var rows = me.rows;
- var rowdef = (rows && rows[key]) ? rows[key] : {};
- var keys = rowdef.multiKey || [ key ];
- var pending = false;
-
- Ext.Array.each(keys, function(k) {
- var rec = me.store.getById(k);
- if (rec && rec.data && (
- (Ext.isDefined(rec.data.pending) && rec.data.pending !== '') ||
- rec.data['delete'] === 1
- )) {
- pending = true;
- return false; // break
- }
- });
-
- return pending;
- },
-
- renderValue: function(value, metaData, record, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var key = record.data.key;
- var rowdef = (rows && rows[key]) ? rows[key] : {};
- var renderer = rowdef.renderer;
- var current = '';
- var pendingdelete = '';
- var pending = '';
-
- if (renderer) {
- current = renderer(value, metaData, record, rowIndex, colIndex, store, false);
- if (me.hasPendingChanges(key)) {
- pending = renderer(record.data.pending, metaData, record, rowIndex, colIndex, store, true);
- }
- if (pending == current) {
- pending = undefined;
- }
- } else {
- current = value || '';
- pending = record.data.pending;
- }
-
- if (record.data['delete']) {
- var delete_all = true;
- if (rowdef.multiKey) {
- Ext.Array.each(rowdef.multiKey, function(k) {
- var rec = me.store.getById(k);
- if (rec && rec.data && rec.data['delete'] !== 1) {
- delete_all = false;
- return false; // break
- }
- });
- }
- if (delete_all) {
- pending = ''+ current +'
';
- }
- }
-
- if (pending) {
- return current + '' + pending + '
';
- } else {
- return current;
- }
- },
-
- initComponent : function() {
- var me = this;
-
- var rows = me.rows;
-
- if (!me.rstore) {
- if (!me.url) {
- throw "no url specified";
- }
-
- me.rstore = Ext.create('Proxmox.data.ObjectStore', {
- model: 'KeyValuePendingDelete',
- readArray: true,
- url: me.url,
- interval: me.interval,
- extraParams: me.extraParams,
- rows: me.rows
- });
- }
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.panel.InputPanel', {
- extend: 'Ext.panel.Panel',
- alias: ['widget.inputpanel'],
- listeners: {
- activate: function() {
- // notify owning container that it should display a help button
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
- }
- },
- deactivate: function() {
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
- }
- }
- },
- border: false,
-
- // override this with an URL to a relevant chapter of the pve manual
- // setting this will display a help button in our parent panel
- onlineHelp: undefined,
-
- // will be set if the inputpanel has advanced items
- hasAdvanced: false,
-
- // if the panel has advanced items,
- // this will determine if they are shown by default
- showAdvanced: false,
-
- // overwrite this to modify submit data
- onGetValues: function(values) {
- return values;
- },
-
- getValues: function(dirtyOnly) {
- var me = this;
-
- if (Ext.isFunction(me.onGetValues)) {
- dirtyOnly = false;
- }
-
- var values = {};
-
- Ext.Array.each(me.query('[isFormField]'), function(field) {
- if (!dirtyOnly || field.isDirty()) {
- Proxmox.Utils.assemble_field_data(values, field.getSubmitData());
- }
- });
-
- return me.onGetValues(values);
- },
-
- setAdvancedVisible: function(visible) {
- var me = this;
- var advItems = me.getComponent('advancedContainer');
- if (advItems) {
- advItems.setVisible(visible);
- }
- },
-
- setValues: function(values) {
- var me = this;
-
- var form = me.up('form');
-
- Ext.iterate(values, function(fieldId, val) {
- var field = me.query('[isFormField][name=' + fieldId + ']')[0];
- if (field) {
- field.setValue(val);
- if (form.trackResetOnLoad) {
- field.resetOriginalValue();
- }
- }
- });
- },
-
- initComponent: function() {
- var me = this;
-
- var items;
-
- if (me.items) {
- me.columns = 1;
- items = [
- {
- columnWidth: 1,
- layout: 'anchor',
- items: me.items
- }
- ];
- me.items = undefined;
- } else if (me.column4) {
- me.columns = 4;
- items = [
- {
- columnWidth: 0.25,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.column1
- },
- {
- columnWidth: 0.25,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.column2
- },
- {
- columnWidth: 0.25,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.column3
- },
- {
- columnWidth: 0.25,
- padding: '0 0 0 10',
- layout: 'anchor',
- items: me.column4
- }
- ];
- if (me.columnB) {
- items.push({
- columnWidth: 1,
- padding: '10 0 0 0',
- layout: 'anchor',
- items: me.columnB
- });
- }
- } else if (me.column1) {
- me.columns = 2;
- items = [
- {
- columnWidth: 0.5,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.column1
- },
- {
- columnWidth: 0.5,
- padding: '0 0 0 10',
- layout: 'anchor',
- items: me.column2 || [] // allow empty column
- }
- ];
- if (me.columnB) {
- items.push({
- columnWidth: 1,
- padding: '10 0 0 0',
- layout: 'anchor',
- items: me.columnB
- });
- }
- } else {
- throw "unsupported config";
- }
-
- var advItems;
- if (me.advancedItems) {
- advItems = [
- {
- columnWidth: 1,
- layout: 'anchor',
- items: me.advancedItems
- }
- ];
- me.advancedItems = undefined;
- } else if (me.advancedColumn1) {
- advItems = [
- {
- columnWidth: 0.5,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: me.advancedColumn1
- },
- {
- columnWidth: 0.5,
- padding: '0 0 0 10',
- layout: 'anchor',
- items: me.advancedColumn2 || [] // allow empty column
- }
- ];
-
- me.advancedColumn1 = undefined;
- me.advancedColumn2 = undefined;
-
- if (me.advancedColumnB) {
- advItems.push({
- columnWidth: 1,
- padding: '10 0 0 0',
- layout: 'anchor',
- items: me.advancedColumnB
- });
- me.advancedColumnB = undefined;
- }
- }
-
- if (advItems) {
- me.hasAdvanced = true;
- advItems.unshift({
- columnWidth: 1,
- xtype: 'box',
- hidden: false,
- border: true,
- autoEl: {
- tag: 'hr'
- }
- });
- items.push({
- columnWidth: 1,
- xtype: 'container',
- itemId: 'advancedContainer',
- hidden: !me.showAdvanced,
- layout: 'column',
- defaults: {
- border: false
- },
- items: advItems
- });
- }
-
- if (me.useFieldContainer) {
- Ext.apply(me, {
- layout: 'fit',
- items: Ext.apply(me.useFieldContainer, {
- layout: 'column',
- defaultType: 'container',
- items: items
- })
- });
- } else {
- Ext.apply(me, {
- layout: 'column',
- defaultType: 'container',
- items: items
- });
- }
-
- me.callParent();
- }
-});
-/*
- * Display log entries in a panel with scrollbar
- * The log entries are automatically refreshed via a background task,
- * with newest entries comming at the bottom
- */
-Ext.define('Proxmox.panel.LogView', {
- extend: 'Ext.panel.Panel',
- xtype: 'proxmoxLogView',
-
- pageSize: 500,
- viewBuffer: 50,
- lineHeight: 16,
-
- scrollToEnd: true,
-
- // callback for load failure, used for ceph
- failCallback: undefined,
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- updateParams: function() {
- var me = this;
- var viewModel = me.getViewModel();
- var since = viewModel.get('since');
- var until = viewModel.get('until');
- if (viewModel.get('hide_timespan')) {
- return;
- }
-
- if (since > until) {
- Ext.Msg.alert('Error', 'Since date must be less equal than Until date.');
- return;
- }
-
- viewModel.set('params.since', Ext.Date.format(since, 'Y-m-d'));
- viewModel.set('params.until', Ext.Date.format(until, 'Y-m-d') + ' 23:59:59');
- me.getView().loadTask.delay(200);
- },
-
- scrollPosBottom: function() {
- var view = this.getView();
- var pos = view.getScrollY();
- var maxPos = view.getScrollable().getMaxPosition().y;
- return maxPos - pos;
- },
-
- updateView: function(text, first, total) {
- var me = this;
- var view = me.getView();
- var viewModel = me.getViewModel();
- var content = me.lookup('content');
- var data = viewModel.get('data');
-
- if (first === data.first && total === data.total && text.length === data.textlen) {
- return; // same content, skip setting and scrolling
- }
- viewModel.set('data', {
- first: first,
- total: total,
- textlen: text.length
- });
-
- var scrollPos = me.scrollPosBottom();
-
- content.update(text);
-
- if (view.scrollToEnd && scrollPos <= 0) {
- // we use setTimeout to work around scroll handling on touchscreens
- setTimeout(function() { view.scrollTo(0, Infinity); }, 10);
- }
- },
-
- doLoad: function() {
- var me = this;
- if (me.running) {
- me.requested = true;
- return;
- }
- me.running = true;
- var view = me.getView();
- var viewModel = me.getViewModel();
- Proxmox.Utils.API2Request({
- url: me.getView().url,
- params: viewModel.get('params'),
- method: 'GET',
- success: function(response) {
- Proxmox.Utils.setErrorMask(me, false);
- var total = response.result.total;
- var lines = new Array();
- var first = Infinity;
-
- Ext.Array.each(response.result.data, function(line) {
- if (first > line.n) {
- first = line.n;
- }
- lines[line.n - 1] = Ext.htmlEncode(line.t);
- });
-
- lines.length = total;
- me.updateView(lines.join(' '), first - 1, total);
- me.running = false;
- if (me.requested) {
- me.requested = false;
- view.loadTask.delay(200);
- }
- },
- failure: function(response) {
- if (view.failCallback) {
- view.failCallback(response);
- } else {
- var msg = response.htmlStatus;
- Proxmox.Utils.setErrorMask(me, msg);
- }
- me.running = false;
- if (me.requested) {
- me.requested = false;
- view.loadTask.delay(200);
- }
- }
- });
- },
-
- onScroll: function(x, y) {
- var me = this;
- var view = me.getView();
- var viewModel = me.getViewModel();
-
- var lineHeight = view.lineHeight;
- var line = view.getScrollY()/lineHeight;
- var start = viewModel.get('params.start');
- var limit = viewModel.get('params.limit');
- var viewLines = view.getHeight()/lineHeight;
-
- var viewStart = Math.max(parseInt(line - 1 - view.viewBuffer, 10), 0);
- var viewEnd = parseInt(line + viewLines + 1 + view.viewBuffer, 10);
-
- if (viewStart < start || viewEnd > (start+limit)) {
- viewModel.set('params.start',
- Math.max(parseInt(line - limit/2 + 10, 10), 0));
- view.loadTask.delay(200);
- }
- },
-
- init: function(view) {
- var me = this;
-
- if (!view.url) {
- throw "no url specified";
- }
-
- var viewModel = this.getViewModel();
- var since = new Date();
- since.setDate(since.getDate() - 3);
- viewModel.set('until', new Date());
- viewModel.set('since', since);
- viewModel.set('params.limit', view.pageSize);
- viewModel.set('hide_timespan', !view.log_select_timespan);
- me.lookup('content').setStyle('line-height', view.lineHeight + 'px');
-
- view.loadTask = new Ext.util.DelayedTask(me.doLoad, me);
-
- me.updateParams();
- view.task = Ext.TaskManager.start({
- run: function() {
- if (!view.isVisible() || !view.scrollToEnd) {
- return;
- }
-
- if (me.scrollPosBottom() <= 1) {
- view.loadTask.delay(200);
- }
- },
- interval: 1000
- });
- }
- },
-
- onDestroy: function() {
- var me = this;
- me.loadTask.cancel();
- Ext.TaskManager.stop(me.task);
- },
-
- // for user to initiate a load from outside
- requestUpdate: function() {
- var me = this;
- me.loadTask.delay(200);
- },
-
- viewModel: {
- data: {
- until: null,
- since: null,
- hide_timespan: false,
- data: {
- start: 0,
- total: 0,
- textlen: 0
- },
- params: {
- start: 0,
- limit: 500,
- }
- }
- },
-
- layout: 'auto',
- bodyPadding: 5,
- scrollable: {
- x: 'auto',
- y: 'auto',
- listeners: {
- // we have to have this here, since we cannot listen to events
- // of the scroller in the viewcontroller (extjs bug?), nor does
- // the panel have a 'scroll' event'
- scroll: {
- fn: function(scroller, x, y) {
- var controller = this.component.getController();
- if (controller) { // on destroy, controller can be gone
- controller.onScroll(x,y);
- }
- },
- buffer: 200
- },
- }
- },
-
- tbar: {
- bind: {
- hidden: '{hide_timespan}'
- },
- items: [
- '->',
- 'Since: ',
- {
- xtype: 'datefield',
- name: 'since_date',
- reference: 'since',
- format: 'Y-m-d',
- bind: {
- value: '{since}',
- maxValue: '{until}'
- }
- },
- 'Until: ',
- {
- xtype: 'datefield',
- name: 'until_date',
- reference: 'until',
- format: 'Y-m-d',
- bind: {
- value: '{until}',
- minValue: '{since}'
- }
- },
- {
- xtype: 'button',
- text: 'Update',
- handler: 'updateParams'
- }
- ],
- },
-
- items: [
- {
- xtype: 'box',
- reference: 'content',
- style: {
- font: 'normal 11px tahoma, arial, verdana, sans-serif',
- 'white-space': 'pre'
- },
- }
- ]
-});
-/*
- * Display log entries in a panel with scrollbar
- * The log entries are automatically refreshed via a background task,
- * with newest entries comming at the bottom
- */
-Ext.define('Proxmox.panel.JournalView', {
- extend: 'Ext.panel.Panel',
- xtype: 'proxmoxJournalView',
-
- numEntries: 500,
- lineHeight: 16,
-
- scrollToEnd: true,
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- updateParams: function() {
- var me = this;
- var viewModel = me.getViewModel();
- var since = viewModel.get('since');
- var until = viewModel.get('until');
-
- since.setHours(0, 0, 0, 0);
- until.setHours(0, 0, 0, 0);
- until.setDate(until.getDate()+1);
-
- me.getView().loadTask.delay(200, undefined, undefined, [
- false,
- false,
- Ext.Date.format(since, "U"),
- Ext.Date.format(until, "U")
- ]);
- },
-
- scrollPosBottom: function() {
- var view = this.getView();
- var pos = view.getScrollY();
- var maxPos = view.getScrollable().getMaxPosition().y;
- return maxPos - pos;
- },
-
- scrollPosTop: function() {
- var view = this.getView();
- return view.getScrollY();
- },
-
- updateScroll: function(livemode, num, scrollPos, scrollPosTop) {
- var me = this;
- var view = me.getView();
-
- if (!livemode) {
- setTimeout(function() { view.scrollTo(0, 0); }, 10);
- } else if (view.scrollToEnd && scrollPos <= 0) {
- setTimeout(function() { view.scrollTo(0, Infinity); }, 10);
- } else if (!view.scrollToEnd && scrollPosTop < 20*view.lineHeight) {
- setTimeout(function() { view.scrollTo(0, num*view.lineHeight + scrollPosTop); }, 10);
- }
- },
-
- updateView: function(lines, livemode, top) {
- var me = this;
- var view = me.getView();
- var viewmodel = me.getViewModel();
- if (viewmodel.get('livemode') !== livemode) {
- return; // we switched mode, do not update the content
- }
- var contentEl = me.lookup('content');
-
- // save old scrollpositions
- var scrollPos = me.scrollPosBottom();
- var scrollPosTop = me.scrollPosTop();
-
- var newend = lines.shift();
- var newstart = lines.pop();
-
- var num = lines.length;
- var text = lines.map(Ext.htmlEncode).join(' ');
-
- if (!livemode) {
- if (num) {
- view.content = text;
- } else {
- view.content = 'nothing logged or no timespan selected';
- }
- } else {
- // update content
- if (top && num) {
- view.content = view.content ? text + ' ' + view.content : text;
- } else if (!top && num) {
- view.content = view.content ? view.content + ' ' + text : text;
- }
-
- // update cursors
- if (!top || !view.startcursor) {
- view.startcursor = newstart;
- }
-
- if (top || !view.endcursor) {
- view.endcursor = newend;
- }
- }
-
- contentEl.update(view.content);
-
- me.updateScroll(livemode, num, scrollPos, scrollPosTop);
- },
-
- doLoad: function(livemode, top, since, until) {
- var me = this;
- if (me.running) {
- me.requested = true;
- return;
- }
- me.running = true;
- var view = me.getView();
- var params = {
- lastentries: view.numEntries || 500,
- };
- if (livemode) {
- if (!top && view.startcursor) {
- params = {
- startcursor: view.startcursor
- };
- } else if (view.endcursor) {
- params.endcursor = view.endcursor;
- }
- } else {
- params = {
- since: since,
- until: until
- };
- }
- Proxmox.Utils.API2Request({
- url: view.url,
- params: params,
- waitMsgTarget: (!livemode) ? view : undefined,
- method: 'GET',
- success: function(response) {
- Proxmox.Utils.setErrorMask(me, false);
- var lines = response.result.data;
- me.updateView(lines, livemode, top);
- me.running = false;
- if (me.requested) {
- me.requested = false;
- view.loadTask.delay(200);
- }
- },
- failure: function(response) {
- var msg = response.htmlStatus;
- Proxmox.Utils.setErrorMask(me, msg);
- me.running = false;
- if (me.requested) {
- me.requested = false;
- view.loadTask.delay(200);
- }
- }
- });
- },
-
- onScroll: function(x, y) {
- var me = this;
- var view = me.getView();
- var viewmodel = me.getViewModel();
- var livemode = viewmodel.get('livemode');
- if (!livemode) {
- return;
- }
-
- if (me.scrollPosTop() < 20*view.lineHeight) {
- view.scrollToEnd = false;
- view.loadTask.delay(200, undefined, undefined, [true, true]);
- } else if (me.scrollPosBottom() <= 1) {
- view.scrollToEnd = true;
- }
- },
-
- init: function(view) {
- var me = this;
-
- if (!view.url) {
- throw "no url specified";
- }
-
- var viewmodel = me.getViewModel();
- var viewModel = this.getViewModel();
- var since = new Date();
- since.setDate(since.getDate() - 3);
- viewModel.set('until', new Date());
- viewModel.set('since', since);
- me.lookup('content').setStyle('line-height', view.lineHeight + 'px');
-
- view.loadTask = new Ext.util.DelayedTask(me.doLoad, me, [true, false]);
-
- me.updateParams();
- view.task = Ext.TaskManager.start({
- run: function() {
- if (!view.isVisible() || !view.scrollToEnd || !viewmodel.get('livemode')) {
- return;
- }
-
- if (me.scrollPosBottom() <= 1) {
- view.loadTask.delay(200, undefined, undefined, [true, false]);
- }
- },
- interval: 1000
- });
- },
-
- onLiveMode: function() {
- var me = this;
- var view = me.getView();
- delete view.startcursor;
- delete view.endcursor;
- delete view.content;
- me.getViewModel().set('livemode', true);
- view.scrollToEnd = true;
- me.updateView([], true, false);
- },
-
- onTimespan: function() {
- var me = this;
- me.getViewModel().set('livemode', false);
- me.updateView([], false);
- }
- },
-
- onDestroy: function() {
- var me = this;
- me.loadTask.cancel();
- Ext.TaskManager.stop(me.task);
- delete me.content;
- },
-
- // for user to initiate a load from outside
- requestUpdate: function() {
- var me = this;
- me.loadTask.delay(200);
- },
-
- viewModel: {
- data: {
- livemode: true,
- until: null,
- since: null
- }
- },
-
- layout: 'auto',
- bodyPadding: 5,
- scrollable: {
- x: 'auto',
- y: 'auto',
- listeners: {
- // we have to have this here, since we cannot listen to events
- // of the scroller in the viewcontroller (extjs bug?), nor does
- // the panel have a 'scroll' event'
- scroll: {
- fn: function(scroller, x, y) {
- var controller = this.component.getController();
- if (controller) { // on destroy, controller can be gone
- controller.onScroll(x,y);
- }
- },
- buffer: 200
- },
- }
- },
-
- tbar: {
-
- items: [
- '->',
- {
- xtype: 'segmentedbutton',
- items: [
- {
- text: gettext('Live Mode'),
- bind: {
- pressed: '{livemode}'
- },
- handler: 'onLiveMode',
- },
- {
- text: gettext('Select Timespan'),
- bind: {
- pressed: '{!livemode}'
- },
- handler: 'onTimespan',
- }
- ]
- },
- {
- xtype: 'box',
- bind: { disabled: '{livemode}' },
- autoEl: { cn: gettext('Since') + ':' }
- },
- {
- xtype: 'datefield',
- name: 'since_date',
- reference: 'since',
- format: 'Y-m-d',
- bind: {
- disabled: '{livemode}',
- value: '{since}',
- maxValue: '{until}'
- }
- },
- {
- xtype: 'box',
- bind: { disabled: '{livemode}' },
- autoEl: { cn: gettext('Until') + ':' }
- },
- {
- xtype: 'datefield',
- name: 'until_date',
- reference: 'until',
- format: 'Y-m-d',
- bind: {
- disabled: '{livemode}',
- value: '{until}',
- minValue: '{since}'
- }
- },
- {
- xtype: 'button',
- text: 'Update',
- reference: 'updateBtn',
- handler: 'updateParams',
- bind: {
- disabled: '{livemode}'
- }
- }
- ]
- },
-
- items: [
- {
- xtype: 'box',
- reference: 'content',
- style: {
- font: 'normal 11px tahoma, arial, verdana, sans-serif',
- 'white-space': 'pre'
- },
- }
- ]
-});
-Ext.define('Proxmox.widget.RRDChart', {
- extend: 'Ext.chart.CartesianChart',
- alias: 'widget.proxmoxRRDChart',
-
- unit: undefined, // bytes, bytespersecond, percent
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- convertToUnits: function(value) {
- var units = ['', 'k','M','G','T', 'P'];
- var si = 0;
- while(value >= 1000 && si < (units.length -1)){
- value = value / 1000;
- si++;
- }
-
- // javascript floating point weirdness
- value = Ext.Number.correctFloat(value);
-
- // limit to 2 decimal points
- value = Ext.util.Format.number(value, "0.##");
-
- return value.toString() + " " + units[si];
- },
-
- leftAxisRenderer: function(axis, label, layoutContext) {
- var me = this;
-
- return me.convertToUnits(label);
- },
-
- onSeriesTooltipRender: function(tooltip, record, item) {
- var me = this.getView();
-
- var suffix = '';
-
- if (me.unit === 'percent') {
- suffix = '%';
- } else if (me.unit === 'bytes') {
- suffix = 'B';
- } else if (me.unit === 'bytespersecond') {
- suffix = 'B/s';
- }
-
- var prefix = item.field;
- if (me.fieldTitles && me.fieldTitles[me.fields.indexOf(item.field)]) {
- prefix = me.fieldTitles[me.fields.indexOf(item.field)];
- }
- tooltip.setHtml(prefix + ': ' + this.convertToUnits(record.get(item.field)) + suffix +
- ' ' + new Date(record.get('time')));
- },
-
- onAfterAnimation: function(chart, eopts) {
- // if the undobuton is disabled,
- // disable our tool
-
- var ourUndoZoomButton = chart.tools[0];
- var undoButton = chart.interactions[0].getUndoButton();
- ourUndoZoomButton.setDisabled(undoButton.isDisabled());
- }
- },
-
- width: 770,
- height: 300,
- animation: false,
- interactions: [{
- type: 'crosszoom'
- }],
- axes: [{
- type: 'numeric',
- position: 'left',
- grid: true,
- renderer: 'leftAxisRenderer',
- //renderer: function(axis, label) { return label; },
- minimum: 0
- }, {
- type: 'time',
- position: 'bottom',
- grid: true,
- fields: ['time']
- }],
- legend: {
- docked: 'bottom'
- },
- listeners: {
- animationend: 'onAfterAnimation'
- },
-
-
- initComponent: function() {
- var me = this;
- var series = {};
-
- if (!me.store) {
- throw "cannot work without store";
- }
-
- if (!me.fields) {
- throw "cannot work without fields";
- }
-
- me.callParent();
-
- // add correct label for left axis
- var axisTitle = "";
- if (me.unit === 'percent') {
- axisTitle = "%";
- } else if (me.unit === 'bytes') {
- axisTitle = "Bytes";
- } else if (me.unit === 'bytespersecond') {
- axisTitle = "Bytes/s";
- } else if (me.fieldTitles && me.fieldTitles.length === 1) {
- axisTitle = me.fieldTitles[0];
- } else if (me.fields.length === 1) {
- axisTitle = me.fields[0];
- }
-
- me.axes[0].setTitle(axisTitle);
-
- if (!me.noTool) {
- me.addTool([{
- type: 'minus',
- disabled: true,
- tooltip: gettext('Undo Zoom'),
- handler: function(){
- var undoButton = me.interactions[0].getUndoButton();
- if (undoButton.handler) {
- undoButton.handler();
- }
- }
- },{
- type: 'restore',
- tooltip: gettext('Toggle Legend'),
- handler: function(){
- if (me.legend) {
- me.legend.setVisible(!me.legend.isVisible());
- }
- }
- }]);
- }
-
- // add a series for each field we get
- me.fields.forEach(function(item, index){
- var title = item;
- if (me.fieldTitles && me.fieldTitles[index]) {
- title = me.fieldTitles[index];
- }
- me.addSeries(Ext.apply(
- {
- type: 'line',
- xField: 'time',
- yField: item,
- title: title,
- fill: true,
- style: {
- lineWidth: 1.5,
- opacity: 0.60
- },
- marker: {
- opacity: 0,
- scaling: 0.01,
- fx: {
- duration: 200,
- easing: 'easeOut'
- }
- },
- highlightCfg: {
- opacity: 1,
- scaling: 1.5
- },
- tooltip: {
- trackMouse: true,
- renderer: 'onSeriesTooltipRender'
- }
- },
- me.seriesConfig
- ));
- });
-
- // enable animation after the store is loaded
- me.store.onAfter('load', function() {
- me.setAnimation(true);
- }, this, {single: true});
- }
-});
-Ext.define('Proxmox.panel.GaugeWidget', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.proxmoxGauge',
-
- defaults: {
- style: {
- 'text-align':'center'
- }
- },
- items: [
- {
- xtype: 'box',
- itemId: 'title',
- data: {
- title: ''
- },
- tpl: '{title} '
- },
- {
- xtype: 'polar',
- height: 120,
- border: false,
- itemId: 'chart',
- series: [{
- type: 'gauge',
- value: 0,
- colors: ['#f5f5f5'],
- sectors: [0],
- donut: 90,
- needleLength: 100,
- totalAngle: Math.PI
- }],
- sprites: [{
- id: 'valueSprite',
- type: 'text',
- text: '',
- textAlign: 'center',
- textBaseline: 'bottom',
- x: 125,
- y: 110,
- fontSize: 30
- }]
- },
- {
- xtype: 'box',
- itemId: 'text'
- }
- ],
-
- header: false,
- border: false,
-
- warningThreshold: 0.6,
- criticalThreshold: 0.9,
- warningColor: '#fc0',
- criticalColor: '#FF6C59',
- defaultColor: '#7289DA',
- backgroundColor: '#2C2F33',
-
- initialValue: 0,
-
-
- updateValue: function(value, text) {
- var me = this;
- var color = me.defaultColor;
- var attr = {};
-
- if (value >= me.criticalThreshold) {
- color = me.criticalColor;
- } else if (value >= me.warningThreshold) {
- color = me.warningColor;
- }
-
- me.chart.series[0].setColors([color, me.backgroundColor]);
- me.chart.series[0].setValue(value*100);
-
- me.valueSprite.setText(' '+(value*100).toFixed(0) + '%');
- attr.x = me.chart.getWidth()/2;
- attr.y = me.chart.getHeight()-20;
- if (me.spriteFontSize) {
- attr.fontSize = me.spriteFontSize;
- }
- me.valueSprite.setAttributes(attr, true);
-
- if (text !== undefined) {
- me.text.setHtml(text);
- }
- },
-
- initComponent: function() {
- var me = this;
-
- me.callParent();
-
- if (me.title) {
- me.getComponent('title').update({title: me.title});
- }
- me.text = me.getComponent('text');
- me.chart = me.getComponent('chart');
- me.valueSprite = me.chart.getSurface('chart').get('valueSprite');
- }
-});
-// fixme: how can we avoid those lint errors?
-/*jslint confusion: true */
-Ext.define('Proxmox.window.Edit', {
- extend: 'Ext.window.Window',
- alias: 'widget.proxmoxWindowEdit',
-
- // autoLoad trigger a load() after component creation
- autoLoad: false,
-
- resizable: false,
-
- // use this tio atimatically generate a title like
- // Create:
- subject: undefined,
-
- // set isCreate to true if you want a Create button (instead
- // OK and RESET)
- isCreate: false,
-
- // set to true if you want an Add button (instead of Create)
- isAdd: false,
-
- // set to true if you want an Remove button (instead of Create)
- isRemove: false,
-
- // custom submitText
- submitText: undefined,
-
- backgroundDelay: 0,
-
- // needed for finding the reference to submitbutton
- // because we do not have a controller
- referenceHolder: true,
- defaultButton: 'submitbutton',
-
- // finds the first form field
- defaultFocus: 'field[disabled=false][hidden=false]',
-
- showProgress: false,
-
- showTaskViewer: false,
-
- // gets called if we have a progress bar or taskview and it detected that
- // the task finished. function(success)
- taskDone: Ext.emptyFn,
-
- // gets called when the api call is finished, right at the beginning
- // function(success, response, options)
- apiCallDone: Ext.emptyFn,
-
- // assign a reference from docs, to add a help button docked to the
- // bottom of the window. If undefined we magically fall back to the
- // onlineHelp of our first item, if set.
- onlineHelp: undefined,
-
- isValid: function() {
- var me = this;
-
- var form = me.formPanel.getForm();
- return form.isValid();
- },
-
- getValues: function(dirtyOnly) {
- var me = this;
-
- var values = {};
-
- var form = me.formPanel.getForm();
-
- form.getFields().each(function(field) {
- if (!field.up('inputpanel') && (!dirtyOnly || field.isDirty())) {
- Proxmox.Utils.assemble_field_data(values, field.getSubmitData());
- }
- });
-
- Ext.Array.each(me.query('inputpanel'), function(panel) {
- Proxmox.Utils.assemble_field_data(values, panel.getValues(dirtyOnly));
- });
-
- return values;
- },
-
- setValues: function(values) {
- var me = this;
-
- var form = me.formPanel.getForm();
-
- Ext.iterate(values, function(fieldId, val) {
- var field = form.findField(fieldId);
- if (field && !field.up('inputpanel')) {
- field.setValue(val);
- if (form.trackResetOnLoad) {
- field.resetOriginalValue();
- }
- }
- });
-
- Ext.Array.each(me.query('inputpanel'), function(panel) {
- panel.setValues(values);
- });
- },
-
- submit: function() {
- var me = this;
-
- var form = me.formPanel.getForm();
-
- var values = me.getValues();
- Ext.Object.each(values, function(name, val) {
- if (values.hasOwnProperty(name)) {
- if (Ext.isArray(val) && !val.length) {
- values[name] = '';
- }
- }
- });
-
- if (me.digest) {
- values.digest = me.digest;
- }
-
- if (me.backgroundDelay) {
- values.background_delay = me.backgroundDelay;
- }
-
- var url = me.url;
- if (me.method === 'DELETE') {
- url = url + "?" + Ext.Object.toQueryString(values);
- values = undefined;
- }
-
- Proxmox.Utils.API2Request({
- url: url,
- waitMsgTarget: me,
- method: me.method || (me.backgroundDelay ? 'POST' : 'PUT'),
- params: values,
- failure: function(response, options) {
- me.apiCallDone(false, response, options);
-
- if (response.result && response.result.errors) {
- form.markInvalid(response.result.errors);
- }
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var hasProgressBar = (me.backgroundDelay || me.showProgress || me.showTaskViewer) &&
- response.result.data ? true : false;
-
- me.apiCallDone(true, response, options);
-
- if (hasProgressBar) {
- // stay around so we can trigger our close events
- // when background action is completed
- me.hide();
-
- var upid = response.result.data;
- var viewerClass = me.showTaskViewer ? 'Viewer' : 'Progress';
- var win = Ext.create('Proxmox.window.Task' + viewerClass, {
- upid: upid,
- taskDone: me.taskDone,
- listeners: {
- destroy: function () {
- me.close();
- }
- }
- });
- win.show();
- } else {
- me.close();
- }
- }
- });
- },
-
- load: function(options) {
- var me = this;
-
- var form = me.formPanel.getForm();
-
- options = options || {};
-
- var newopts = Ext.apply({
- waitMsgTarget: me
- }, options);
-
- var createWrapper = function(successFn) {
- Ext.apply(newopts, {
- url: me.url,
- method: 'GET',
- success: function(response, opts) {
- form.clearInvalid();
- me.digest = response.result.data.digest;
- if (successFn) {
- successFn(response, opts);
- } else {
- me.setValues(response.result.data);
- }
- // hack: fix ExtJS bug
- Ext.Array.each(me.query('radiofield'), function(f) {
- f.resetOriginalValue();
- });
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus, function() {
- me.close();
- });
- }
- });
- };
-
- createWrapper(options.success);
-
- Proxmox.Utils.API2Request(newopts);
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.url) {
- throw "no url specified";
- }
-
- if (me.create) {throw "deprecated parameter, use isCreate";}
-
- var items = Ext.isArray(me.items) ? me.items : [ me.items ];
-
- me.items = undefined;
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- url: me.url,
- method: me.method || 'PUT',
- trackResetOnLoad: true,
- bodyPadding: 10,
- border: false,
- defaults: Ext.apply({}, me.defaults, {
- border: false
- }),
- fieldDefaults: Ext.apply({}, me.fieldDefaults, {
- labelWidth: 100,
- anchor: '100%'
- }),
- items: items
- });
-
- var inputPanel = me.formPanel.down('inputpanel');
-
- var form = me.formPanel.getForm();
-
- var submitText;
- if (me.isCreate) {
- if (me.submitText) {
- submitText = me.submitText;
- } else if (me.isAdd) {
- submitText = gettext('Add');
- } else if (me.isRemove) {
- submitText = gettext('Remove');
- } else {
- submitText = gettext('Create');
- }
- } else {
- submitText = me.submitText || gettext('OK');
- }
-
- var submitBtn = Ext.create('Ext.Button', {
- reference: 'submitbutton',
- text: submitText,
- disabled: !me.isCreate,
- handler: function() {
- me.submit();
- }
- });
-
- var resetBtn = Ext.create('Ext.Button', {
- text: 'Reset',
- disabled: true,
- handler: function(){
- form.reset();
- }
- });
-
- var set_button_status = function() {
- var valid = form.isValid();
- var dirty = form.isDirty();
- submitBtn.setDisabled(!valid || !(dirty || me.isCreate));
- resetBtn.setDisabled(!dirty);
-
- if (inputPanel && inputPanel.hasAdvanced) {
- // we want to show the advanced options
- // as soon as some of it is not valid
- var advancedItems = me.down('#advancedContainer').query('field');
- var valid = true;
- advancedItems.forEach(function(field) {
- if (!field.isValid()) {
- valid = false;
- }
- });
-
- if (!valid) {
- inputPanel.setAdvancedVisible(true);
- me.down('#advancedcb').setValue(true);
- }
- }
- };
-
- form.on('dirtychange', set_button_status);
- form.on('validitychange', set_button_status);
-
- var colwidth = 300;
- if (me.fieldDefaults && me.fieldDefaults.labelWidth) {
- colwidth += me.fieldDefaults.labelWidth - 100;
- }
-
- var twoColumn = inputPanel &&
- (inputPanel.column1 || inputPanel.column2);
-
- if (me.subject && !me.title) {
- me.title = Proxmox.Utils.dialog_title(me.subject, me.isCreate, me.isAdd);
- }
-
- if (me.isCreate) {
- me.buttons = [ submitBtn ] ;
- } else {
- me.buttons = [ submitBtn, resetBtn ];
- }
-
- if (inputPanel && inputPanel.hasAdvanced) {
- var sp = Ext.state.Manager.getProvider();
- var advchecked = sp.get('proxmox-advanced-cb');
- inputPanel.setAdvancedVisible(advchecked);
- me.buttons.unshift(
- {
- xtype: 'proxmoxcheckbox',
- itemId: 'advancedcb',
- boxLabelAlign: 'before',
- boxLabel: gettext('Advanced'),
- stateId: 'proxmox-advanced-cb',
- value: advchecked,
- listeners: {
- change: function(cb, val) {
- inputPanel.setAdvancedVisible(val);
- sp.set('proxmox-advanced-cb', val);
- }
- }
- }
- );
- }
-
- var onlineHelp = me.onlineHelp;
- if (!onlineHelp && inputPanel && inputPanel.onlineHelp) {
- onlineHelp = inputPanel.onlineHelp;
- }
-
- if (onlineHelp) {
- var helpButton = Ext.create('Proxmox.button.Help');
- me.buttons.unshift(helpButton, '->');
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', onlineHelp);
- }
-
- Ext.applyIf(me, {
- modal: true,
- width: twoColumn ? colwidth*2 : colwidth,
- border: false,
- items: [ me.formPanel ]
- });
-
- me.callParent();
-
- // always mark invalid fields
- me.on('afterlayout', function() {
- // on touch devices, the isValid function
- // triggers a layout, which triggers an isValid
- // and so on
- // to prevent this we disable the layouting here
- // and enable it afterwards
- me.suspendLayout = true;
- me.isValid();
- me.suspendLayout = false;
- });
-
- if (me.autoLoad) {
- me.load();
- }
- }
-});
-Ext.define('Proxmox.window.PasswordEdit', {
- extend: 'Proxmox.window.Edit',
- alias: 'proxmoxWindowPasswordEdit',
-
- subject: gettext('Password'),
-
- url: '/api2/extjs/access/password',
-
- fieldDefaults: {
- labelWidth: 120
- },
-
- items: [
- {
- xtype: 'textfield',
- inputType: 'password',
- fieldLabel: gettext('Password'),
- minLength: 5,
- allowBlank: false,
- name: 'password',
- listeners: {
- change: function(field){
- field.next().validate();
- },
- blur: function(field){
- field.next().validate();
- }
- }
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- fieldLabel: gettext('Confirm password'),
- name: 'verifypassword',
- allowBlank: false,
- vtype: 'password',
- initialPassField: 'password',
- submitValue: false
- },
- {
- xtype: 'hiddenfield',
- name: 'userid'
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.userid) {
- throw "no userid specified";
- }
-
- me.callParent();
- me.down('[name=userid]').setValue(me.userid);
- }
-});
-Ext.define('Proxmox.window.TaskProgress', {
- extend: 'Ext.window.Window',
- alias: 'widget.proxmoxTaskProgress',
-
- taskDone: Ext.emptyFn,
-
- initComponent: function() {
- var me = this;
-
- if (!me.upid) {
- throw "no task specified";
- }
-
- var task = Proxmox.Utils.parse_task_upid(me.upid);
-
- var statstore = Ext.create('Proxmox.data.ObjectStore', {
- url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + "/status",
- interval: 1000,
- rows: {
- status: { defaultValue: 'unknown' },
- exitstatus: { defaultValue: 'unknown' }
- }
- });
-
- me.on('destroy', statstore.stopUpdate);
-
- var getObjectValue = function(key, defaultValue) {
- var rec = statstore.getById(key);
- if (rec) {
- return rec.data.value;
- }
- return defaultValue;
- };
-
- var pbar = Ext.create('Ext.ProgressBar', { text: 'running...' });
-
- me.mon(statstore, 'load', function() {
- var status = getObjectValue('status');
- if (status === 'stopped') {
- var exitstatus = getObjectValue('exitstatus');
- if (exitstatus == 'OK') {
- pbar.reset();
- pbar.updateText("Done!");
- Ext.Function.defer(me.close, 1000, me);
- } else {
- me.close();
- Ext.Msg.alert('Task failed', exitstatus);
- }
- me.taskDone(exitstatus == 'OK');
- }
- });
-
- var descr = Proxmox.Utils.format_task_description(task.type, task.id);
-
- Ext.apply(me, {
- title: gettext('Task') + ': ' + descr,
- width: 300,
- layout: 'auto',
- modal: true,
- bodyPadding: 5,
- items: pbar,
- buttons: [
- {
- text: gettext('Details'),
- handler: function() {
- var win = Ext.create('Proxmox.window.TaskViewer', {
- taskDone: me.taskDone,
- upid: me.upid
- });
- win.show();
- me.close();
- }
- }
- ]
- });
-
- me.callParent();
-
- statstore.startUpdate();
-
- pbar.wait();
- }
-});
-
-// fixme: how can we avoid those lint errors?
-/*jslint confusion: true */
-
-Ext.define('Proxmox.window.TaskViewer', {
- extend: 'Ext.window.Window',
- alias: 'widget.proxmoxTaskViewer',
-
- extraTitle: '', // string to prepend after the generic task title
-
- taskDone: Ext.emptyFn,
-
- initComponent: function() {
- var me = this;
-
- if (!me.upid) {
- throw "no task specified";
- }
-
- var task = Proxmox.Utils.parse_task_upid(me.upid);
-
- var statgrid;
-
- var rows = {
- status: {
- header: gettext('Status'),
- defaultValue: 'unknown',
- renderer: function(value) {
- if (value != 'stopped') {
- return value;
- }
- var es = statgrid.getObjectValue('exitstatus');
- if (es) {
- return value + ': ' + es;
- }
- }
- },
- exitstatus: {
- visible: false
- },
- type: {
- header: gettext('Task type'),
- required: true
- },
- user: {
- header: gettext('User name'),
- required: true
- },
- node: {
- header: gettext('Node'),
- required: true
- },
- pid: {
- header: gettext('Process ID'),
- required: true
- },
- starttime: {
- header: gettext('Start Time'),
- required: true,
- renderer: Proxmox.Utils.render_timestamp
- },
- upid: {
- header: gettext('Unique task ID')
- }
- };
-
- var statstore = Ext.create('Proxmox.data.ObjectStore', {
- url: "/api2/json/nodes/" + task.node + "/tasks/" + me.upid + "/status",
- interval: 1000,
- rows: rows
- });
-
- me.on('destroy', statstore.stopUpdate);
-
- var stop_task = function() {
- Proxmox.Utils.API2Request({
- url: "/nodes/" + task.node + "/tasks/" + me.upid,
- waitMsgTarget: me,
- method: 'DELETE',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var stop_btn1 = new Ext.Button({
- text: gettext('Stop'),
- disabled: true,
- handler: stop_task
- });
-
- var stop_btn2 = new Ext.Button({
- text: gettext('Stop'),
- disabled: true,
- handler: stop_task
- });
-
- statgrid = Ext.create('Proxmox.grid.ObjectGrid', {
- title: gettext('Status'),
- layout: 'fit',
- tbar: [ stop_btn1 ],
- rstore: statstore,
- rows: rows,
- border: false
- });
-
- var logView = Ext.create('Proxmox.panel.LogView', {
- title: gettext('Output'),
- tbar: [ stop_btn2 ],
- border: false,
- url: "/api2/extjs/nodes/" + task.node + "/tasks/" + me.upid + "/log"
- });
-
- me.mon(statstore, 'load', function() {
- var status = statgrid.getObjectValue('status');
-
- if (status === 'stopped') {
- logView.scrollToEnd = false;
- logView.requestUpdate();
- statstore.stopUpdate();
- me.taskDone(statgrid.getObjectValue('exitstatus') == 'OK');
- }
-
- stop_btn1.setDisabled(status !== 'running');
- stop_btn2.setDisabled(status !== 'running');
- });
-
- statstore.startUpdate();
-
- Ext.apply(me, {
- title: "Task viewer: " + task.desc + me.extraTitle,
- width: 800,
- height: 400,
- layout: 'fit',
- modal: true,
- items: [{
- xtype: 'tabpanel',
- region: 'center',
- items: [ logView, statgrid ]
- }]
- });
-
- me.callParent();
-
- logView.fireEvent('show', logView);
- }
-});
-
-Ext.define('apt-pkglist', {
- extend: 'Ext.data.Model',
- fields: [ 'Package', 'Title', 'Description', 'Section', 'Arch',
- 'Priority', 'Version', 'OldVersion', 'ChangeLogUrl', 'Origin' ],
- idProperty: 'Package'
-});
-
-Ext.define('Proxmox.node.APT', {
- extend: 'Ext.grid.GridPanel',
-
- xtype: 'proxmoxNodeAPT',
-
- upgradeBtn: undefined,
-
- columns: [
- {
- header: gettext('Package'),
- width: 200,
- sortable: true,
- dataIndex: 'Package'
- },
- {
- text: gettext('Version'),
- columns: [
- {
- header: gettext('current'),
- width: 100,
- sortable: false,
- dataIndex: 'OldVersion'
- },
- {
- header: gettext('new'),
- width: 100,
- sortable: false,
- dataIndex: 'Version'
- }
- ]
- },
- {
- header: gettext('Description'),
- sortable: false,
- dataIndex: 'Title',
- flex: 1
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var store = Ext.create('Ext.data.Store', {
- model: 'apt-pkglist',
- groupField: 'Origin',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + "/apt/update"
- },
- sorters: [
- {
- property : 'Package',
- direction: 'ASC'
- }
- ]
- });
-
- var groupingFeature = Ext.create('Ext.grid.feature.Grouping', {
- groupHeaderTpl: '{[ "Origin: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})',
- enableGroupingMenu: false
- });
-
- var rowBodyFeature = Ext.create('Ext.grid.feature.RowBody', {
- getAdditionalData: function (data, rowIndex, record, orig) {
- var headerCt = this.view.headerCt;
- var colspan = headerCt.getColumnCount();
- return {
- rowBody: '' +
- Ext.String.htmlEncode(data.Description) +
- '
',
- rowBodyCls: me.full_description ? '' : Ext.baseCSSPrefix + 'grid-row-body-hidden',
- rowBodyColspan: colspan
- };
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- Proxmox.Utils.monStoreErrors(me, store, true);
-
- var apt_command = function(cmd){
- Proxmox.Utils.API2Request({
- url: "/nodes/" + me.nodename + "/apt/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- me.mon(win, 'close', reload);
- }
- });
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var update_btn = new Ext.Button({
- text: gettext('Refresh'),
- handler: function() {
- Proxmox.Utils.checked_command(function() { apt_command('update'); });
- }
- });
-
- var show_changelog = function(rec) {
- if (!rec || !rec.data || !(rec.data.ChangeLogUrl && rec.data.Package)) {
- return;
- }
-
- var view = Ext.createWidget('component', {
- autoScroll: true,
- style: {
- 'background-color': 'white',
- 'white-space': 'pre',
- 'font-family': 'monospace',
- padding: '5px'
- }
- });
-
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Changelog') + ": " + rec.data.Package,
- width: 800,
- height: 400,
- layout: 'fit',
- modal: true,
- items: [ view ]
- });
-
- Proxmox.Utils.API2Request({
- waitMsgTarget: me,
- url: "/nodes/" + me.nodename + "/apt/changelog",
- params: {
- name: rec.data.Package,
- version: rec.data.Version
- },
- method: 'GET',
- failure: function(response, opts) {
- win.close();
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- win.show();
- view.update(Ext.htmlEncode(response.result.data));
- }
- });
-
- };
-
- var changelog_btn = new Proxmox.button.Button({
- text: gettext('Changelog'),
- selModel: sm,
- disabled: true,
- enableFn: function(rec) {
- if (!rec || !rec.data || !(rec.data.ChangeLogUrl && rec.data.Package)) {
- return false;
- }
- return true;
- },
- handler: function(b, e, rec) {
- show_changelog(rec);
- }
- });
-
- var verbose_desc_checkbox = new Ext.form.field.Checkbox({
- boxLabel: gettext('Show details'),
- value: false,
- listeners: {
- change: (f, val) => {
- me.full_description = val;
- me.getView().refresh();
- }
- }
- });
-
- if (me.upgradeBtn) {
- me.tbar = [ update_btn, me.upgradeBtn, changelog_btn, '->', verbose_desc_checkbox ];
- } else {
- me.tbar = [ update_btn, changelog_btn, '->', verbose_desc_checkbox ];
- }
-
- Ext.apply(me, {
- store: store,
- stateful: true,
- stateId: 'grid-update',
- selModel: sm,
- viewConfig: {
- stripeRows: false,
- emptyText: '' + gettext('No updates available.') + '
'
- },
- features: [ groupingFeature, rowBodyFeature ],
- listeners: {
- activate: reload,
- itemdblclick: function(v, rec) {
- show_changelog(rec);
- }
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.node.NetworkEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.proxmoxNodeNetworkEdit'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.iftype) {
- throw "no network device type specified";
- }
-
- me.isCreate = !me.iface;
-
- var iface_vtype;
-
- if (me.iftype === 'bridge') {
- iface_vtype = 'BridgeName';
- } else if (me.iftype === 'bond') {
- iface_vtype = 'BondName';
- } else if (me.iftype === 'eth' && !me.isCreate) {
- iface_vtype = 'InterfaceName';
- } else if (me.iftype === 'vlan' && !me.isCreate) {
- iface_vtype = 'InterfaceName';
- } else if (me.iftype === 'OVSBridge') {
- iface_vtype = 'BridgeName';
- } else if (me.iftype === 'OVSBond') {
- iface_vtype = 'BondName';
- } else if (me.iftype === 'OVSIntPort') {
- iface_vtype = 'InterfaceName';
- } else if (me.iftype === 'OVSPort') {
- iface_vtype = 'InterfaceName';
- } else {
- console.log(me.iftype);
- throw "unknown network device type specified";
- }
-
- me.subject = Proxmox.Utils.render_network_iface_type(me.iftype);
-
- var column2 = [];
-
- if (!(me.iftype === 'OVSIntPort' || me.iftype === 'OVSPort' ||
- me.iftype === 'OVSBond')) {
- column2.push({
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Autostart'),
- name: 'autostart',
- uncheckedValue: 0,
- checked: me.isCreate ? true : undefined
- });
- }
-
- if (me.iftype === 'bridge') {
- column2.push({
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('VLAN aware'),
- name: 'bridge_vlan_aware',
- deleteEmpty: !me.isCreate
- });
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('Bridge ports'),
- name: 'bridge_ports'
- });
- } else if (me.iftype === 'OVSBridge') {
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('Bridge ports'),
- name: 'ovs_ports'
- });
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('OVS options'),
- name: 'ovs_options'
- });
- } else if (me.iftype === 'OVSPort' || me.iftype === 'OVSIntPort') {
- column2.push({
- xtype: me.isCreate ? 'PVE.form.BridgeSelector' : 'displayfield',
- fieldLabel: Proxmox.Utils.render_network_iface_type('OVSBridge'),
- allowBlank: false,
- nodename: me.nodename,
- bridgeType: 'OVSBridge',
- name: 'ovs_bridge'
- });
- column2.push({
- xtype: 'pveVlanField',
- deleteEmpty: !me.isCreate,
- name: 'ovs_tag',
- value: ''
- });
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('OVS options'),
- name: 'ovs_options'
- });
- } else if (me.iftype === 'bond') {
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('Slaves'),
- name: 'slaves'
- });
-
- var policySelector = Ext.createWidget('bondPolicySelector', {
- fieldLabel: gettext('Hash policy'),
- name: 'bond_xmit_hash_policy',
- deleteEmpty: !me.isCreate,
- disabled: true
- });
-
- column2.push({
- xtype: 'bondModeSelector',
- fieldLabel: gettext('Mode'),
- name: 'bond_mode',
- value: me.isCreate ? 'balance-rr' : undefined,
- listeners: {
- change: function(f, value) {
- if (value === 'balance-xor' ||
- value === '802.3ad') {
- policySelector.setDisabled(false);
- } else {
- policySelector.setDisabled(true);
- policySelector.setValue('');
- }
- }
- },
- allowBlank: false
- });
-
- column2.push(policySelector);
-
- } else if (me.iftype === 'OVSBond') {
- column2.push({
- xtype: me.isCreate ? 'PVE.form.BridgeSelector' : 'displayfield',
- fieldLabel: Proxmox.Utils.render_network_iface_type('OVSBridge'),
- allowBlank: false,
- nodename: me.nodename,
- bridgeType: 'OVSBridge',
- name: 'ovs_bridge'
- });
- column2.push({
- xtype: 'pveVlanField',
- deleteEmpty: !me.isCreate,
- name: 'ovs_tag',
- value: ''
- });
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('OVS options'),
- name: 'ovs_options'
- });
- }
-
- column2.push({
- xtype: 'textfield',
- fieldLabel: gettext('Comment'),
- allowBlank: true,
- nodename: me.nodename,
- name: 'comments'
- });
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = "/api2/extjs/nodes/" + me.nodename + "/network";
- method = 'POST';
- } else {
- url = "/api2/extjs/nodes/" + me.nodename + "/network/" + me.iface;
- method = 'PUT';
- }
-
- var column1 = [
- {
- xtype: 'hiddenfield',
- name: 'type',
- value: me.iftype
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- fieldLabel: gettext('Name'),
- name: 'iface',
- value: me.iface,
- vtype: iface_vtype,
- allowBlank: false
- }
- ];
-
- if (me.iftype === 'OVSBond') {
- column1.push(
- {
- xtype: 'bondModeSelector',
- fieldLabel: gettext('Mode'),
- name: 'bond_mode',
- openvswitch: true,
- value: me.isCreate ? 'active-backup' : undefined,
- allowBlank: false
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Slaves'),
- name: 'ovs_bonds'
- }
- );
- } else {
-
- column1.push(
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: 'IPv4/CIDR',
- vtype: 'IPCIDRAddress',
- name: 'cidr'
- },
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: gettext('Gateway') + ' (IPv4)',
- vtype: 'IPAddress',
- name: 'gateway'
- },
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: 'IPv6/CIDR',
- vtype: 'IP6CIDRAddress',
- name: 'cidr6'
- },
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: !me.isCreate,
- fieldLabel: gettext('Gateway') + ' (IPv6)',
- vtype: 'IP6Address',
- name: 'gateway6'
- }
- );
- }
-
- Ext.applyIf(me, {
- url: url,
- method: method,
- items: {
- xtype: 'inputpanel',
- column1: column1,
- column2: column2
- }
- });
-
- me.callParent();
-
- if (me.isCreate) {
- me.down('field[name=iface]').setValue(me.iface_default);
- } else {
- me.load({
- success: function(response, options) {
- var data = response.result.data;
- if (data.type !== me.iftype) {
- var msg = "Got unexpected device type";
- Ext.Msg.alert(gettext('Error'), msg, function() {
- me.close();
- });
- return;
- }
- me.setValues(data);
- me.isValid(); // trigger validation
- }
- });
- }
- }
-});
-Ext.define('proxmox-networks', {
- extend: 'Ext.data.Model',
- fields: [
- 'iface', 'type', 'active', 'autostart',
- 'bridge_ports', 'slaves',
- 'address', 'netmask', 'gateway',
- 'address6', 'netmask6', 'gateway6',
- 'cidr', 'cidr6',
- 'comments'
- ],
- idProperty: 'iface'
-});
-
-Ext.define('Proxmox.node.NetworkView', {
- extend: 'Ext.panel.Panel',
-
- alias: ['widget.proxmoxNodeNetworkView'],
-
- // defines what types of network devices we want to create
- // order is always the same
- types: ['bridge', 'bond', 'ovs'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var baseUrl = '/nodes/' + me.nodename + '/network';
-
- var store = Ext.create('Ext.data.Store', {
- model: 'proxmox-networks',
- proxy: {
- type: 'proxmox',
- url: '/api2/json' + baseUrl
- },
- sorters: [
- {
- property : 'iface',
- direction: 'ASC'
- }
- ]
- });
-
- var reload = function() {
- var changeitem = me.down('#changes');
- Proxmox.Utils.API2Request({
- url: baseUrl,
- failure: function(response, opts) {
- store.loadData({});
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- changeitem.update('');
- changeitem.setHidden(true);
- },
- success: function(response, opts) {
- var result = Ext.decode(response.responseText);
- store.loadData(result.data);
- var changes = result.changes;
- if (changes === undefined || changes === '') {
- changes = gettext("No changes");
- changeitem.setHidden(true);
- } else {
- changeitem.update("" + Ext.htmlEncode(changes) + " ");
- changeitem.setHidden(false);
- }
- }
- });
- };
-
- var run_editor = function() {
- var grid = me.down('gridpanel');
- var sm = grid.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iface: rec.data.iface,
- iftype: rec.data.type
- });
- win.show();
- win.on('destroy', reload);
- };
-
- var edit_btn = new Ext.Button({
- text: gettext('Edit'),
- disabled: true,
- handler: run_editor
- });
-
- var del_btn = new Ext.Button({
- text: gettext('Remove'),
- disabled: true,
- handler: function(){
- var grid = me.down('gridpanel');
- var sm = grid.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var iface = rec.data.iface;
-
- Proxmox.Utils.API2Request({
- url: baseUrl + '/' + iface,
- method: 'DELETE',
- waitMsgTarget: me,
- callback: function() {
- reload();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- var set_button_status = function() {
- var grid = me.down('gridpanel');
- var sm = grid.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- edit_btn.setDisabled(!rec);
- del_btn.setDisabled(!rec);
- };
-
- var render_ports = function(value, metaData, record) {
- if (value === 'bridge') {
- return record.data.bridge_ports;
- } else if (value === 'bond') {
- return record.data.slaves;
- } else if (value === 'OVSBridge') {
- return record.data.ovs_ports;
- } else if (value === 'OVSBond') {
- return record.data.ovs_bonds;
- }
- };
-
- var find_next_iface_id = function(prefix) {
- var next;
- for (next = 0; next <= 9999; next++) {
- if (!store.getById(prefix + next.toString())) {
- break;
- }
- }
- return prefix + next.toString();
- };
-
- var menu_items = [];
-
- if (me.types.indexOf('bridge') !== -1) {
- menu_items.push({
- text: Proxmox.Utils.render_network_iface_type('bridge'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'bridge',
- iface_default: find_next_iface_id('vmbr')
- });
- win.on('destroy', reload);
- win.show();
- }
- });
- }
-
- if (me.types.indexOf('bond') !== -1) {
- menu_items.push({
- text: Proxmox.Utils.render_network_iface_type('bond'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'bond',
- iface_default: find_next_iface_id('bond')
- });
- win.on('destroy', reload);
- win.show();
- }
- });
- }
-
- if (me.types.indexOf('ovs') !== -1) {
- if (menu_items.length > 0) {
- menu_items.push({ xtype: 'menuseparator' });
- }
-
- menu_items.push(
- {
- text: Proxmox.Utils.render_network_iface_type('OVSBridge'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'OVSBridge',
- iface_default: find_next_iface_id('vmbr')
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: Proxmox.Utils.render_network_iface_type('OVSBond'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'OVSBond',
- iface_default: find_next_iface_id('bond')
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: Proxmox.Utils.render_network_iface_type('OVSIntPort'),
- handler: function() {
- var win = Ext.create('Proxmox.node.NetworkEdit', {
- nodename: me.nodename,
- iftype: 'OVSIntPort'
- });
- win.on('destroy', reload);
- win.show();
- }
- }
- );
- }
-
- var renderer_generator = function(fieldname) {
- return function(val, metaData, rec) {
- var tmp = [];
- if (rec.data[fieldname]) {
- tmp.push(rec.data[fieldname]);
- }
- if (rec.data[fieldname + '6']) {
- tmp.push(rec.data[fieldname + '6']);
- }
- return tmp.join(' ') || '';
- };
- };
-
- Ext.apply(me, {
- layout: 'border',
- tbar: [
- {
- text: gettext('Create'),
- menu: {
- plain: true,
- items: menu_items
- }
- }, ' ',
- {
- text: gettext('Revert'),
- handler: function() {
- Proxmox.Utils.API2Request({
- url: baseUrl,
- method: 'DELETE',
- waitMsgTarget: me,
- callback: function() {
- reload();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- },
- edit_btn,
- del_btn
- ],
- items: [
- {
- xtype: 'gridpanel',
- stateful: true,
- stateId: 'grid-node-network',
- store: store,
- region: 'center',
- border: false,
- columns: [
- {
- header: gettext('Name'),
- sortable: true,
- dataIndex: 'iface'
- },
- {
- header: gettext('Type'),
- sortable: true,
- width: 120,
- renderer: Proxmox.Utils.render_network_iface_type,
- dataIndex: 'type'
- },
- {
- xtype: 'booleancolumn',
- header: gettext('Active'),
- width: 80,
- sortable: true,
- dataIndex: 'active',
- trueText: Proxmox.Utils.yesText,
- falseText: Proxmox.Utils.noText,
- undefinedText: Proxmox.Utils.noText,
- },
- {
- xtype: 'booleancolumn',
- header: gettext('Autostart'),
- width: 80,
- sortable: true,
- dataIndex: 'autostart',
- trueText: Proxmox.Utils.yesText,
- falseText: Proxmox.Utils.noText,
- undefinedText: Proxmox.Utils.noText
- },
- {
- xtype: 'booleancolumn',
- header: gettext('VLAN aware'),
- width: 80,
- sortable: true,
- dataIndex: 'bridge_vlan_aware',
- trueText: Proxmox.Utils.yesText,
- falseText: Proxmox.Utils.noText,
- undefinedText: Proxmox.Utils.noText
- },
- {
- header: gettext('Ports/Slaves'),
- dataIndex: 'type',
- renderer: render_ports
- },
- {
- header: gettext('Bond Mode'),
- dataIndex: 'bond_mode',
- renderer: Proxmox.Utils.render_bond_mode,
- },
- {
- header: gettext('Hash Policy'),
- hidden: true,
- dataIndex: 'bond_xmit_hash_policy',
- },
- {
- header: gettext('IP address'),
- sortable: true,
- width: 120,
- hidden: true,
- dataIndex: 'address',
- renderer: renderer_generator('address'),
- },
- {
- header: gettext('Subnet mask'),
- width: 120,
- sortable: true,
- hidden: true,
- dataIndex: 'netmask',
- renderer: renderer_generator('netmask'),
- },
- {
- header: gettext('CIDR'),
- width: 120,
- sortable: true,
- dataIndex: 'cidr',
- renderer: renderer_generator('cidr'),
- },
- {
- header: gettext('Gateway'),
- width: 120,
- sortable: true,
- dataIndex: 'gateway',
- renderer: renderer_generator('gateway'),
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comments',
- flex: 1,
- renderer: Ext.String.htmlEncode
- }
- ],
- listeners: {
- selectionchange: set_button_status,
- itemdblclick: run_editor
- }
- },
- {
- border: false,
- region: 'south',
- autoScroll: true,
- hidden: true,
- itemId: 'changes',
- tbar: [
- gettext('Pending changes') + ' (' +
- gettext('Please reboot to activate changes') + ')'
- ],
- split: true,
- bodyPadding: 5,
- flex: 0.6,
- html: gettext("No changes")
- }
- ],
- });
-
- me.callParent();
- reload();
- }
-});
-Ext.define('Proxmox.node.DNSEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.proxmoxNodeDNSEdit'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.items = [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Search domain'),
- name: 'search',
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('DNS server') + " 1",
- vtype: 'IP64Address',
- skipEmptyText: true,
- name: 'dns1'
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('DNS server') + " 2",
- vtype: 'IP64Address',
- skipEmptyText: true,
- name: 'dns2'
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('DNS server') + " 3",
- vtype: 'IP64Address',
- skipEmptyText: true,
- name: 'dns3'
- }
- ];
-
- Ext.applyIf(me, {
- subject: gettext('DNS'),
- url: "/api2/extjs/nodes/" + me.nodename + "/dns",
- fieldDefaults: {
- labelWidth: 120
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('Proxmox.node.HostsView', {
- extend: 'Ext.panel.Panel',
- xtype: 'proxmoxNodeHostsView',
-
- reload: function() {
- var me = this;
- me.store.load();
- },
-
- tbar: [
- {
- text: gettext('Save'),
- disabled: true,
- itemId: 'savebtn',
- handler: function() {
- var me = this.up('panel');
- Proxmox.Utils.API2Request({
- params: {
- digest: me.digest,
- data: me.down('#hostsfield').getValue()
- },
- method: 'POST',
- url: '/nodes/' + me.nodename + '/hosts',
- waitMsgTarget: me,
- success: function(response, opts) {
- me.reload();
- },
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- }
- },
- {
- text: gettext('Revert'),
- disabled: true,
- itemId: 'resetbtn',
- handler: function() {
- var me = this.up('panel');
- me.down('#hostsfield').reset();
- }
- }
- ],
-
- layout: 'fit',
-
- items: [
- {
- xtype: 'textarea',
- itemId: 'hostsfield',
- fieldStyle: {
- 'font-family': 'monospace',
- 'white-space': 'pre'
- },
- listeners: {
- dirtychange: function(ta, dirty) {
- var me = this.up('panel');
- me.down('#savebtn').setDisabled(!dirty);
- me.down('#resetbtn').setDisabled(!dirty);
- }
- }
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.store = Ext.create('Ext.data.Store', {
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + "/hosts",
- }
- });
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.store);
-
- me.mon(me.store, 'load', function(store, records, success) {
- if (!success || records.length < 1) {
- return;
- }
- me.digest = records[0].data.digest;
- var data = records[0].data.data;
- me.down('#hostsfield').setValue(data);
- me.down('#hostsfield').resetOriginalValue();
- });
-
- me.reload();
- }
-});
-Ext.define('Proxmox.node.DNSView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.proxmoxNodeDNSView'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var run_editor = function() {
- var win = Ext.create('Proxmox.node.DNSEdit', {
- nodename: me.nodename
- });
- win.show();
- };
-
- Ext.apply(me, {
- url: "/api2/json/nodes/" + me.nodename + "/dns",
- cwidth1: 130,
- interval: 1000,
- run_editor: run_editor,
- rows: {
- search: {
- header: 'Search domain',
- required: true,
- renderer: Ext.htmlEncode
- },
- dns1: {
- header: gettext('DNS server') + " 1",
- required: true,
- renderer: Ext.htmlEncode
- },
- dns2: {
- header: gettext('DNS server') + " 2",
- renderer: Ext.htmlEncode
- },
- dns3: {
- header: gettext('DNS server') + " 3",
- renderer: Ext.htmlEncode
- }
- },
- tbar: [
- {
- text: gettext("Edit"),
- handler: run_editor
- }
- ],
- listeners: {
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- }
-});
-Ext.define('Proxmox.node.Tasks', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.proxmoxNodeTasks'],
- stateful: true,
- stateId: 'grid-node-tasks',
- loadMask: true,
- sortableColumns: false,
- vmidFilter: 0,
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var store = Ext.create('Ext.data.BufferedStore', {
- pageSize: 500,
- autoLoad: true,
- remoteFilter: true,
- model: 'proxmox-tasks',
- proxy: {
- type: 'proxmox',
- startParam: 'start',
- limitParam: 'limit',
- url: "/api2/json/nodes/" + me.nodename + "/tasks"
- }
- });
-
- var userfilter = '';
- var filter_errors = 0;
-
- var updateProxyParams = function() {
- var params = {
- errors: filter_errors
- };
- if (userfilter) {
- params.userfilter = userfilter;
- }
- if (me.vmidFilter) {
- params.vmid = me.vmidFilter;
- }
- store.proxy.extraParams = params;
- };
-
- updateProxyParams();
-
- var reload_task = Ext.create('Ext.util.DelayedTask',function() {
- updateProxyParams();
- store.reload();
- });
-
- var run_task_viewer = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: rec.data.upid
- });
- win.show();
- };
-
- var view_btn = new Ext.Button({
- text: gettext('View'),
- disabled: true,
- handler: run_task_viewer
- });
-
- Proxmox.Utils.monStoreErrors(me, store, true);
-
- Ext.apply(me, {
- store: store,
- viewConfig: {
- trackOver: false,
- stripeRows: false, // does not work with getRowClass()
-
- getRowClass: function(record, index) {
- var status = record.get('status');
-
- if (status && status != 'OK') {
- return "proxmox-invalid-row";
- }
- }
- },
- tbar: [
- view_btn, '->', gettext('User name') +':', ' ',
- {
- xtype: 'textfield',
- width: 200,
- value: userfilter,
- enableKeyEvents: true,
- listeners: {
- keyup: function(field, e) {
- userfilter = field.getValue();
- reload_task.delay(500);
- }
- }
- }, ' ', gettext('Only Errors') + ':', ' ',
- {
- xtype: 'checkbox',
- hideLabel: true,
- checked: filter_errors,
- listeners: {
- change: function(field, checked) {
- filter_errors = checked ? 1 : 0;
- reload_task.delay(10);
- }
- }
- }, ' '
- ],
- columns: [
- {
- header: gettext("Start Time"),
- dataIndex: 'starttime',
- width: 100,
- renderer: function(value) {
- return Ext.Date.format(value, "M d H:i:s");
- }
- },
- {
- header: gettext("End Time"),
- dataIndex: 'endtime',
- width: 100,
- renderer: function(value, metaData, record) {
- return Ext.Date.format(value,"M d H:i:s");
- }
- },
- {
- header: gettext("Node"),
- dataIndex: 'node',
- width: 100
- },
- {
- header: gettext("User name"),
- dataIndex: 'user',
- width: 150
- },
- {
- header: gettext("Description"),
- dataIndex: 'upid',
- flex: 1,
- renderer: Proxmox.Utils.render_upid
- },
- {
- header: gettext("Status"),
- dataIndex: 'status',
- width: 200,
- renderer: function(value, metaData, record) {
- if (value == 'OK') {
- return 'OK';
- }
- // metaData.attr = 'style="color:red;"';
- return "ERROR: " + value;
- }
- }
- ],
- listeners: {
- itemdblclick: run_task_viewer,
- selectionchange: function(v, selections) {
- view_btn.setDisabled(!(selections && selections[0]));
- },
- show: function() { reload_task.delay(10); },
- destroy: function() { reload_task.cancel(); }
- }
- });
-
- me.callParent();
-
- }
-});
-Ext.define('proxmox-services', {
- extend: 'Ext.data.Model',
- fields: [ 'service', 'name', 'desc', 'state' ],
- idProperty: 'service'
-});
-
-Ext.define('Proxmox.node.ServiceView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.proxmoxNodeServiceView'],
-
- startOnlyServices: {},
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var rstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 1000,
- storeid: 'proxmox-services' + me.nodename,
- model: 'proxmox-services',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + "/services"
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: rstore,
- sortAfterUpdate: true,
- sorters: [
- {
- property : 'name',
- direction: 'ASC'
- }
- ]
- });
-
- var view_service_log = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Syslog') + ': ' + rec.data.service,
- modal: true,
- width: 800,
- height: 400,
- layout: 'fit',
- items: {
- xtype: 'proxmoxLogView',
- url: "/api2/extjs/nodes/" + me.nodename + "/syslog?service=" +
- rec.data.service,
- log_select_timespan: 1
- }
- });
- win.show();
- };
-
- var service_cmd = function(cmd) {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- Proxmox.Utils.API2Request({
- url: "/nodes/" + me.nodename + "/services/" + rec.data.service + "/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- me.loading = true;
- },
- success: function(response, opts) {
- rstore.startUpdate();
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid
- });
- win.show();
- }
- });
- };
-
- var start_btn = new Ext.Button({
- text: gettext('Start'),
- disabled: true,
- handler: function(){
- service_cmd("start");
- }
- });
-
- var stop_btn = new Ext.Button({
- text: gettext('Stop'),
- disabled: true,
- handler: function(){
- service_cmd("stop");
- }
- });
-
- var restart_btn = new Ext.Button({
- text: gettext('Restart'),
- disabled: true,
- handler: function(){
- service_cmd("restart");
- }
- });
-
- var syslog_btn = new Ext.Button({
- text: gettext('Syslog'),
- disabled: true,
- handler: view_service_log
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- start_btn.disable();
- stop_btn.disable();
- restart_btn.disable();
- syslog_btn.disable();
- return;
- }
- var service = rec.data.service;
- var state = rec.data.state;
-
- syslog_btn.enable();
-
- if (me.startOnlyServices[service]) {
- if (state == 'running') {
- start_btn.disable();
- restart_btn.enable();
- } else {
- start_btn.enable();
- restart_btn.disable();
- }
- stop_btn.disable();
- } else {
- if (state == 'running') {
- start_btn.disable();
- restart_btn.enable();
- stop_btn.enable();
- } else {
- start_btn.enable();
- restart_btn.disable();
- stop_btn.disable();
- }
- }
- };
-
- me.mon(store, 'refresh', set_button_status);
-
- Proxmox.Utils.monStoreErrors(me, rstore);
-
- Ext.apply(me, {
- store: store,
- stateful: false,
- tbar: [ start_btn, stop_btn, restart_btn, syslog_btn ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- dataIndex: 'name'
- },
- {
- header: gettext('Status'),
- width: 100,
- sortable: true,
- dataIndex: 'state'
- },
- {
- header: gettext('Description'),
- renderer: Ext.String.htmlEncode,
- dataIndex: 'desc',
- flex: 2
- }
- ],
- listeners: {
- selectionchange: set_button_status,
- itemdblclick: view_service_log,
- activate: rstore.startUpdate,
- destroy: rstore.stopUpdate
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.node.TimeEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.proxmoxNodeTimeEdit'],
-
- subject: gettext('Time zone'),
-
- width: 400,
-
- autoLoad: true,
-
- fieldDefaults: {
- labelWidth: 70
- },
-
- items: {
- xtype: 'combo',
- fieldLabel: gettext('Time zone'),
- name: 'timezone',
- queryMode: 'local',
- store: Ext.create('Proxmox.data.TimezoneStore'),
- displayField: 'zone',
- editable: true,
- anyMatch: true,
- forceSelection: true,
- allowBlank: false
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
- me.url = "/api2/extjs/nodes/" + me.nodename + "/time";
-
- me.callParent();
- }
-});
-Ext.define('Proxmox.node.TimeView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.proxmoxNodeTimeView'],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var tzoffset = (new Date()).getTimezoneOffset()*60000;
- var renderlocaltime = function(value) {
- var servertime = new Date((value * 1000) + tzoffset);
- return Ext.Date.format(servertime, 'Y-m-d H:i:s');
- };
-
- var run_editor = function() {
- var win = Ext.create('Proxmox.node.TimeEdit', {
- nodename: me.nodename
- });
- win.show();
- };
-
- Ext.apply(me, {
- url: "/api2/json/nodes/" + me.nodename + "/time",
- cwidth1: 150,
- interval: 1000,
- run_editor: run_editor,
- rows: {
- timezone: {
- header: gettext('Time zone'),
- required: true
- },
- localtime: {
- header: gettext('Server time'),
- required: true,
- renderer: renderlocaltime
- }
- },
- tbar: [
- {
- text: gettext("Edit"),
- handler: run_editor
- }
- ],
- listeners: {
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- }
-});
diff --git a/serverside/jsmod/6.0-4/pvemanagerlib.js b/serverside/jsmod/6.0-4/pvemanagerlib.js
deleted file mode 100644
index add3e49..0000000
--- a/serverside/jsmod/6.0-4/pvemanagerlib.js
+++ /dev/null
@@ -1,39779 +0,0 @@
-var pveOnlineHelpInfo = {
- "ceph_rados_block_devices" : {
- "link" : "/pve-docs/chapter-pvesm.html#ceph_rados_block_devices",
- "title" : "Ceph RADOS Block Devices (RBD)"
- },
- "chapter_ha_manager" : {
- "link" : "/pve-docs/chapter-ha-manager.html#chapter_ha_manager",
- "title" : "High Availability"
- },
- "chapter_lvm" : {
- "link" : "/pve-docs/chapter-sysadmin.html#chapter_lvm",
- "title" : "Logical Volume Manager (LVM)"
- },
- "chapter_pct" : {
- "link" : "/pve-docs/chapter-pct.html#chapter_pct",
- "title" : "Proxmox Container Toolkit"
- },
- "chapter_pve_firewall" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#chapter_pve_firewall",
- "title" : "Proxmox VE Firewall"
- },
- "chapter_pveceph" : {
- "link" : "/pve-docs/chapter-pveceph.html#chapter_pveceph",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "chapter_pvecm" : {
- "link" : "/pve-docs/chapter-pvecm.html#chapter_pvecm",
- "title" : "Cluster Manager"
- },
- "chapter_pvesr" : {
- "link" : "/pve-docs/chapter-pvesr.html#chapter_pvesr",
- "title" : "Storage Replication"
- },
- "chapter_storage" : {
- "link" : "/pve-docs/chapter-pvesm.html#chapter_storage",
- "title" : "Proxmox VE Storage"
- },
- "chapter_system_administration" : {
- "link" : "/pve-docs/chapter-sysadmin.html#chapter_system_administration",
- "title" : "Host System Administration"
- },
- "chapter_user_management" : {
- "link" : "/pve-docs/chapter-pveum.html#chapter_user_management",
- "title" : "User Management"
- },
- "chapter_virtual_machines" : {
- "link" : "/pve-docs/chapter-qm.html#chapter_virtual_machines",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "chapter_vzdump" : {
- "link" : "/pve-docs/chapter-vzdump.html#chapter_vzdump",
- "title" : "Backup and Restore"
- },
- "chapter_zfs" : {
- "link" : "/pve-docs/chapter-sysadmin.html#chapter_zfs",
- "title" : "ZFS on Linux"
- },
- "datacenter_configuration_file" : {
- "link" : "/pve-docs/pve-admin-guide.html#datacenter_configuration_file",
- "title" : "Datacenter Configuration"
- },
- "getting_help" : {
- "link" : "/pve-docs/pve-admin-guide.html#getting_help",
- "title" : "Getting Help"
- },
- "gui_my_settings" : {
- "link" : "/pve-docs/chapter-pve-gui.html#gui_my_settings",
- "subtitle" : "My Settings",
- "title" : "Graphical User Interface"
- },
- "ha_manager_fencing" : {
- "link" : "/pve-docs/chapter-ha-manager.html#ha_manager_fencing",
- "subtitle" : "Fencing",
- "title" : "High Availability"
- },
- "ha_manager_groups" : {
- "link" : "/pve-docs/chapter-ha-manager.html#ha_manager_groups",
- "subtitle" : "Groups",
- "title" : "High Availability"
- },
- "ha_manager_resource_config" : {
- "link" : "/pve-docs/chapter-ha-manager.html#ha_manager_resource_config",
- "subtitle" : "Resources",
- "title" : "High Availability"
- },
- "ha_manager_resources" : {
- "link" : "/pve-docs/chapter-ha-manager.html#ha_manager_resources",
- "subtitle" : "Resources",
- "title" : "High Availability"
- },
- "pct_configuration" : {
- "link" : "/pve-docs/chapter-pct.html#pct_configuration",
- "subtitle" : "Configuration",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_container_images" : {
- "link" : "/pve-docs/chapter-pct.html#pct_container_images",
- "subtitle" : "Container Images",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_container_network" : {
- "link" : "/pve-docs/chapter-pct.html#pct_container_network",
- "subtitle" : "Network",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_container_storage" : {
- "link" : "/pve-docs/chapter-pct.html#pct_container_storage",
- "subtitle" : "Container Storage",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_cpu" : {
- "link" : "/pve-docs/chapter-pct.html#pct_cpu",
- "subtitle" : "CPU",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_general" : {
- "link" : "/pve-docs/chapter-pct.html#pct_general",
- "subtitle" : "General Settings",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_memory" : {
- "link" : "/pve-docs/chapter-pct.html#pct_memory",
- "subtitle" : "Memory",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_migration" : {
- "link" : "/pve-docs/chapter-pct.html#pct_migration",
- "subtitle" : "Migration",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_options" : {
- "link" : "/pve-docs/chapter-pct.html#pct_options",
- "subtitle" : "Options",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_snapshots" : {
- "link" : "/pve-docs/chapter-pct.html#pct_snapshots",
- "subtitle" : "Snapshots",
- "title" : "Proxmox Container Toolkit"
- },
- "pct_startup_and_shutdown" : {
- "link" : "/pve-docs/chapter-pct.html#pct_startup_and_shutdown",
- "subtitle" : "Automatic Start and Shutdown of Containers",
- "title" : "Proxmox Container Toolkit"
- },
- "pve_admin_guide" : {
- "link" : "/pve-docs/pve-admin-guide.html",
- "title" : "Proxmox VE Administration Guide"
- },
- "pve_ceph_install" : {
- "link" : "/pve-docs/chapter-pveceph.html#pve_ceph_install",
- "subtitle" : "Installation of Ceph Packages",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pve_ceph_osds" : {
- "link" : "/pve-docs/chapter-pveceph.html#pve_ceph_osds",
- "subtitle" : "Creating Ceph OSDs",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pve_ceph_pools" : {
- "link" : "/pve-docs/chapter-pveceph.html#pve_ceph_pools",
- "subtitle" : "Creating Ceph Pools",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pve_documentation_index" : {
- "link" : "/pve-docs/index.html",
- "title" : "Proxmox VE Documentation Index"
- },
- "pve_firewall_cluster_wide_setup" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_cluster_wide_setup",
- "subtitle" : "Cluster Wide Setup",
- "title" : "Proxmox VE Firewall"
- },
- "pve_firewall_host_specific_configuration" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_host_specific_configuration",
- "subtitle" : "Host Specific Configuration",
- "title" : "Proxmox VE Firewall"
- },
- "pve_firewall_ip_aliases" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_ip_aliases",
- "subtitle" : "IP Aliases",
- "title" : "Proxmox VE Firewall"
- },
- "pve_firewall_ip_sets" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_ip_sets",
- "subtitle" : "IP Sets",
- "title" : "Proxmox VE Firewall"
- },
- "pve_firewall_vm_container_configuration" : {
- "link" : "/pve-docs/chapter-pve-firewall.html#pve_firewall_vm_container_configuration",
- "subtitle" : "VM/Container Configuration",
- "title" : "Proxmox VE Firewall"
- },
- "pve_service_daemons" : {
- "link" : "/pve-docs/index.html#_service_daemons",
- "title" : "Service Daemons"
- },
- "pveceph_fs" : {
- "link" : "/pve-docs/chapter-pveceph.html#pveceph_fs",
- "subtitle" : "CephFS",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pveceph_fs_create" : {
- "link" : "/pve-docs/chapter-pveceph.html#pveceph_fs_create",
- "subtitle" : "Create a CephFS",
- "title" : "Manage Ceph Services on Proxmox VE Nodes"
- },
- "pvecm_create_cluster" : {
- "link" : "/pve-docs/chapter-pvecm.html#pvecm_create_cluster",
- "subtitle" : "Create the Cluster",
- "title" : "Cluster Manager"
- },
- "pvesr_schedule_time_format" : {
- "link" : "/pve-docs/chapter-pvesr.html#pvesr_schedule_time_format",
- "subtitle" : "Schedule Format",
- "title" : "Storage Replication"
- },
- "pveum_authentication_realms" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_authentication_realms",
- "subtitle" : "Authentication Realms",
- "title" : "User Management"
- },
- "pveum_groups" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_groups",
- "subtitle" : "Groups",
- "title" : "User Management"
- },
- "pveum_permission_management" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_permission_management",
- "subtitle" : "Permission Management",
- "title" : "User Management"
- },
- "pveum_pools" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_pools",
- "subtitle" : "Pools",
- "title" : "User Management"
- },
- "pveum_roles" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_roles",
- "subtitle" : "Roles",
- "title" : "User Management"
- },
- "pveum_tfa_auth" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_tfa_auth",
- "subtitle" : "Two factor authentication",
- "title" : "User Management"
- },
- "pveum_users" : {
- "link" : "/pve-docs/chapter-pveum.html#pveum_users",
- "subtitle" : "Users",
- "title" : "User Management"
- },
- "qm_bios_and_uefi" : {
- "link" : "/pve-docs/chapter-qm.html#qm_bios_and_uefi",
- "subtitle" : "BIOS and UEFI",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_cloud_init" : {
- "link" : "/pve-docs/chapter-qm.html#qm_cloud_init",
- "title" : "Cloud-Init Support"
- },
- "qm_copy_and_clone" : {
- "link" : "/pve-docs/chapter-qm.html#qm_copy_and_clone",
- "subtitle" : "Copies and Clones",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_cpu" : {
- "link" : "/pve-docs/chapter-qm.html#qm_cpu",
- "subtitle" : "CPU",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_general_settings" : {
- "link" : "/pve-docs/chapter-qm.html#qm_general_settings",
- "subtitle" : "General Settings",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_hard_disk" : {
- "link" : "/pve-docs/chapter-qm.html#qm_hard_disk",
- "subtitle" : "Hard Disk",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_memory" : {
- "link" : "/pve-docs/chapter-qm.html#qm_memory",
- "subtitle" : "Memory",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_migration" : {
- "link" : "/pve-docs/chapter-qm.html#qm_migration",
- "subtitle" : "Migration",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_network_device" : {
- "link" : "/pve-docs/chapter-qm.html#qm_network_device",
- "subtitle" : "Network Device",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_options" : {
- "link" : "/pve-docs/chapter-qm.html#qm_options",
- "subtitle" : "Options",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_os_settings" : {
- "link" : "/pve-docs/chapter-qm.html#qm_os_settings",
- "subtitle" : "OS Settings",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_pci_passthrough" : {
- "link" : "/pve-docs/chapter-qm.html#qm_pci_passthrough",
- "title" : "PCI(e) Passthrough"
- },
- "qm_startup_and_shutdown" : {
- "link" : "/pve-docs/chapter-qm.html#qm_startup_and_shutdown",
- "subtitle" : "Automatic Start and Shutdown of Virtual Machines",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_system_settings" : {
- "link" : "/pve-docs/chapter-qm.html#qm_system_settings",
- "subtitle" : "System Settings",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_usb_passthrough" : {
- "link" : "/pve-docs/chapter-qm.html#qm_usb_passthrough",
- "subtitle" : "USB Passthrough",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "qm_virtual_machines_settings" : {
- "link" : "/pve-docs/chapter-qm.html#qm_virtual_machines_settings",
- "subtitle" : "Virtual Machines Settings",
- "title" : "Qemu/KVM Virtual Machines"
- },
- "storage_cephfs" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_cephfs",
- "title" : "Ceph Filesystem (CephFS)"
- },
- "storage_cifs" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_cifs",
- "title" : "CIFS Backend"
- },
- "storage_directory" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_directory",
- "title" : "Directory Backend"
- },
- "storage_glusterfs" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_glusterfs",
- "title" : "GlusterFS Backend"
- },
- "storage_lvm" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_lvm",
- "title" : "LVM Backend"
- },
- "storage_lvmthin" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_lvmthin",
- "title" : "LVM thin Backend"
- },
- "storage_nfs" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_nfs",
- "title" : "NFS Backend"
- },
- "storage_open_iscsi" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_open_iscsi",
- "title" : "Open-iSCSI initiator"
- },
- "storage_zfspool" : {
- "link" : "/pve-docs/chapter-pvesm.html#storage_zfspool",
- "title" : "Local ZFS Pool Backend"
- },
- "sysadmin_certificate_management" : {
- "link" : "/pve-docs/chapter-sysadmin.html#sysadmin_certificate_management",
- "title" : "Certificate Management"
- },
- "sysadmin_network_configuration" : {
- "link" : "/pve-docs/chapter-sysadmin.html#sysadmin_network_configuration",
- "title" : "Network Configuration"
- }
-};
-Ext.ns('PVE');
-
-// 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 = {
- log: function() {}
- };
-}
-console.log("Starting PVE Manager");
-
-Ext.Ajax.defaultHeaders = {
- 'Accept': 'application/json'
-};
-
-/*jslint confusion: true */
-Ext.define('PVE.Utils', { utilities: {
-
- // this singleton contains miscellaneous utilities
-
- toolkit: undefined, // (extjs|touch), set inside Toolkit.js
-
- bus_match: /^(ide|sata|virtio|scsi)\d+$/,
-
- log_severity_hash: {
- 0: "panic",
- 1: "alert",
- 2: "critical",
- 3: "error",
- 4: "warning",
- 5: "notice",
- 6: "info",
- 7: "debug"
- },
-
- support_level_hash: {
- 'c': gettext('Community'),
- 'b': gettext('Basic'),
- 's': gettext('Standard'),
- 'p': gettext('Premium')
- },
-
- noSubKeyHtml: 'You do not have a valid subscription for this server. Please visit www.proxmox.com to get a list of available options.',
-
- kvm_ostypes: {
- 'Linux': [
- { desc: '5.x - 2.6 Kernel', val: 'l26' },
- { desc: '2.4 Kernel', val: 'l24' }
- ],
- 'Microsoft Windows': [
- { desc: '10/2016', val: 'win10' },
- { desc: '8.x/2012/2012r2', val: 'win8' },
- { desc: '7/2008r2', val: 'win7' },
- { desc: 'Vista/2008', val: 'w2k8' },
- { desc: 'XP/2003', val: 'wxp' },
- { desc: '2000', val: 'w2k' }
- ],
- 'Solaris Kernel': [
- { desc: '-', val: 'solaris'}
- ],
- 'Other': [
- { desc: '-', val: 'other'}
- ]
- },
-
- get_health_icon: function(state, circle) {
- if (circle === undefined) {
- circle = false;
- }
-
- if (state === undefined) {
- state = 'uknown';
- }
-
- var icon = 'faded fa-question';
- switch(state) {
- case 'good':
- icon = 'good fa-check';
- break;
- case 'old':
- icon = 'warning fa-refresh';
- break;
- case 'warning':
- icon = 'warning fa-exclamation';
- break;
- case 'critical':
- icon = 'critical fa-times';
- break;
- default: break;
- }
-
- if (circle) {
- icon += '-circle';
- }
-
- return icon;
- },
-
- parse_ceph_version: function(service) {
- if (service.ceph_version_short) {
- return service.ceph_version_short;
- }
-
- if (service.ceph_version) {
- var match = service.ceph_version.match(/version (\d+(\.\d+)*)/);
- if (match) {
- return match[1];
- }
- }
-
- return undefined;
- },
-
- compare_ceph_versions: function(a, b) {
- if (a === b) {
- return 0;
- }
- let avers = a.toString().split('.');
- let bvers = b.toString().split('.');
-
- while (true) {
- let av = avers.shift();
- let bv = bvers.shift();
-
- if (av === undefined && bv === undefined) {
- return 0;
- } else if (av === undefined) {
- return -1;
- } else if (bv === undefined) {
- return 1;
- } else {
- let diff = parseInt(av, 10) - parseInt(bv, 10);
- if (diff != 0) return diff;
- // else we need to look at the next parts
- }
- }
-
- },
-
- get_ceph_icon_html: function(health, fw) {
- var state = PVE.Utils.map_ceph_health[health];
- var cls = PVE.Utils.get_health_icon(state);
- if (fw) {
- cls += ' fa-fw';
- }
- return " ";
- },
-
- map_ceph_health: {
- 'HEALTH_OK':'good',
- 'HEALTH_OLD':'old',
- 'HEALTH_WARN':'warning',
- 'HEALTH_ERR':'critical'
- },
-
- render_ceph_health: function(healthObj) {
- var state = {
- iconCls: PVE.Utils.get_health_icon(),
- text: ''
- };
-
- if (!healthObj || !healthObj.status) {
- return state;
- }
-
- var health = PVE.Utils.map_ceph_health[healthObj.status];
-
- state.iconCls = PVE.Utils.get_health_icon(health, true);
- state.text = healthObj.status;
-
- return state;
- },
-
- render_zfs_health: function(value) {
- if (typeof value == 'undefined'){
- return "";
- }
- var iconCls = 'question-circle';
- switch (value) {
- case 'AVAIL':
- case 'ONLINE':
- iconCls = 'check-circle good';
- break;
- case 'REMOVED':
- case 'DEGRADED':
- iconCls = 'exclamation-circle warning';
- break;
- case 'UNAVAIL':
- case 'FAULTED':
- case 'OFFLINE':
- iconCls = 'times-circle critical';
- break;
- default: //unknown
- }
-
- return ' ' + value;
-
- },
-
- get_kvm_osinfo: function(value) {
- var info = { base: 'Other' }; // default
- if (value) {
- Ext.each(Object.keys(PVE.Utils.kvm_ostypes), function(k) {
- Ext.each(PVE.Utils.kvm_ostypes[k], function(e) {
- if (e.val === value) {
- info = { desc: e.desc, base: k };
- }
- });
- });
- }
- return info;
- },
-
- render_kvm_ostype: function (value) {
- var osinfo = PVE.Utils.get_kvm_osinfo(value);
- if (osinfo.desc && osinfo.desc !== '-') {
- return osinfo.base + ' ' + osinfo.desc;
- } else {
- return osinfo.base;
- }
- },
-
- render_hotplug_features: function (value) {
- var fa = [];
-
- if (!value || (value === '0')) {
- return gettext('Disabled');
- }
-
- if (value === '1') {
- value = 'disk,network,usb';
- }
-
- Ext.each(value.split(','), function(el) {
- if (el === 'disk') {
- fa.push(gettext('Disk'));
- } else if (el === 'network') {
- fa.push(gettext('Network'));
- } else if (el === 'usb') {
- fa.push('USB');
- } else if (el === 'memory') {
- fa.push(gettext('Memory'));
- } else if (el === 'cpu') {
- fa.push(gettext('CPU'));
- } else {
- fa.push(el);
- }
- });
-
- return fa.join(', ');
- },
-
- render_qga_features: function(value) {
- if (!value) {
- return Proxmox.Utils.defaultText + ' (' + Proxmox.Utils.disabledText + ')';
- }
- var props = PVE.Parser.parsePropertyString(value, 'enabled');
- if (!PVE.Parser.parseBoolean(props.enabled)) {
- return Proxmox.Utils.disabledText;
- }
-
- delete props.enabled;
- var agentstring = Proxmox.Utils.enabledText;
-
- Ext.Object.each(props, function(key, value) {
- var keystring = '' ;
- agentstring += ', ' + key + ': ';
-
- if (PVE.Parser.parseBoolean(value)) {
- agentstring += Proxmox.Utils.enabledText;
- } else {
- agentstring += Proxmox.Utils.disabledText;
- }
- });
-
- return agentstring;
- },
-
- render_qemu_machine: function(value) {
- return value || (Proxmox.Utils.defaultText + ' (i440fx)');
- },
-
- render_qemu_bios: function(value) {
- if (!value) {
- return Proxmox.Utils.defaultText + ' (SeaBIOS)';
- } else if (value === 'seabios') {
- return "SeaBIOS";
- } else if (value === 'ovmf') {
- return "OVMF (UEFI)";
- } else {
- return value;
- }
- },
-
- render_dc_ha_opts: function(value) {
- if (!value) {
- return Proxmox.Utils.defaultText;
- } else {
- return PVE.Parser.printPropertyString(value);
- }
- },
- render_as_property_string: function(value) {
- return (!value) ? Proxmox.Utils.defaultText
- : PVE.Parser.printPropertyString(value);
- },
-
- render_scsihw: function(value) {
- if (!value) {
- return Proxmox.Utils.defaultText + ' (LSI 53C895A)';
- } else if (value === 'lsi') {
- return 'LSI 53C895A';
- } else if (value === 'lsi53c810') {
- return 'LSI 53C810';
- } else if (value === 'megasas') {
- return 'MegaRAID SAS 8708EM2';
- } else if (value === 'virtio-scsi-pci') {
- return 'VirtIO SCSI';
- } else if (value === 'virtio-scsi-single') {
- return 'VirtIO SCSI single';
- } else if (value === 'pvscsi') {
- return 'VMware PVSCSI';
- } else {
- return value;
- }
- },
-
- // fixme: auto-generate this
- // for now, please keep in sync with PVE::Tools::kvmkeymaps
- kvm_keymaps: {
- //ar: 'Arabic',
- da: 'Danish',
- de: 'German',
- 'de-ch': 'German (Swiss)',
- 'en-gb': 'English (UK)',
- 'en-us': 'English (USA)',
- es: 'Spanish',
- //et: 'Estonia',
- fi: 'Finnish',
- //fo: 'Faroe Islands',
- fr: 'French',
- 'fr-be': 'French (Belgium)',
- 'fr-ca': 'French (Canada)',
- 'fr-ch': 'French (Swiss)',
- //hr: 'Croatia',
- hu: 'Hungarian',
- is: 'Icelandic',
- it: 'Italian',
- ja: 'Japanese',
- lt: 'Lithuanian',
- //lv: 'Latvian',
- mk: 'Macedonian',
- nl: 'Dutch',
- //'nl-be': 'Dutch (Belgium)',
- no: 'Norwegian',
- pl: 'Polish',
- pt: 'Portuguese',
- 'pt-br': 'Portuguese (Brazil)',
- //ru: 'Russian',
- sl: 'Slovenian',
- sv: 'Swedish',
- //th: 'Thai',
- tr: 'Turkish'
- },
-
- kvm_vga_drivers: {
- std: gettext('Standard VGA'),
- vmware: gettext('VMware compatible'),
- qxl: 'SPICE',
- qxl2: 'SPICE dual monitor',
- qxl3: 'SPICE three monitors',
- qxl4: 'SPICE four monitors',
- serial0: gettext('Serial terminal') + ' 0',
- serial1: gettext('Serial terminal') + ' 1',
- serial2: gettext('Serial terminal') + ' 2',
- serial3: gettext('Serial terminal') + ' 3',
- virtio: 'VirtIO-GPU',
- none: Proxmox.Utils.noneText
- },
-
- render_kvm_language: function (value) {
- if (!value || value === '__default__') {
- return Proxmox.Utils.defaultText;
- }
- var text = PVE.Utils.kvm_keymaps[value];
- if (text) {
- return text + ' (' + value + ')';
- }
- return value;
- },
-
- kvm_keymap_array: function() {
- var data = [['__default__', PVE.Utils.render_kvm_language('')]];
- Ext.Object.each(PVE.Utils.kvm_keymaps, function(key, value) {
- data.push([key, PVE.Utils.render_kvm_language(value)]);
- });
-
- return data;
- },
-
- console_map: {
- '__default__': Proxmox.Utils.defaultText + ' (xterm.js)',
- 'vv': 'SPICE (remote-viewer)',
- 'html5': 'HTML5 (noVNC)',
- 'xtermjs': 'xterm.js'
- },
-
- render_console_viewer: function(value) {
- value = value || '__default__';
- if (PVE.Utils.console_map[value]) {
- return PVE.Utils.console_map[value];
- }
- return value;
- },
-
- console_viewer_array: function() {
- return Ext.Array.map(Object.keys(PVE.Utils.console_map), function(v) {
- return [v, PVE.Utils.render_console_viewer(v)];
- });
- },
-
- render_kvm_vga_driver: function (value) {
- if (!value) {
- return Proxmox.Utils.defaultText;
- }
- var vga = PVE.Parser.parsePropertyString(value, 'type');
- var text = PVE.Utils.kvm_vga_drivers[vga.type];
- if (!vga.type) {
- text = Proxmox.Utils.defaultText;
- }
- if (text) {
- return text + ' (' + value + ')';
- }
- return value;
- },
-
- kvm_vga_driver_array: function() {
- var data = [['__default__', PVE.Utils.render_kvm_vga_driver('')]];
- Ext.Object.each(PVE.Utils.kvm_vga_drivers, function(key, value) {
- data.push([key, PVE.Utils.render_kvm_vga_driver(value)]);
- });
-
- return data;
- },
-
- render_kvm_startup: function(value) {
- var startup = PVE.Parser.parseStartup(value);
-
- var res = 'order=';
- if (startup.order === undefined) {
- res += 'any';
- } else {
- res += startup.order;
- }
- if (startup.up !== undefined) {
- res += ',up=' + startup.up;
- }
- if (startup.down !== undefined) {
- res += ',down=' + startup.down;
- }
-
- return res;
- },
-
- extractFormActionError: function(action) {
- var msg;
- switch (action.failureType) {
- case Ext.form.action.Action.CLIENT_INVALID:
- msg = gettext('Form fields may not be submitted with invalid values');
- break;
- case Ext.form.action.Action.CONNECT_FAILURE:
- msg = gettext('Connection error');
- var resp = action.response;
- if (resp.status && resp.statusText) {
- msg += " " + resp.status + ": " + resp.statusText;
- }
- break;
- case Ext.form.action.Action.LOAD_FAILURE:
- case Ext.form.action.Action.SERVER_INVALID:
- msg = Proxmox.Utils.extractRequestError(action.result, true);
- break;
- }
- return msg;
- },
-
- format_duration_short: function(ut) {
-
- if (ut < 60) {
- return ut.toFixed(1) + 's';
- }
-
- if (ut < 3600) {
- var mins = ut / 60;
- return mins.toFixed(1) + 'm';
- }
-
- if (ut < 86400) {
- var hours = ut / 3600;
- return hours.toFixed(1) + 'h';
- }
-
- var days = ut / 86400;
- return days.toFixed(1) + 'd';
- },
-
- contentTypes: {
- 'images': gettext('Disk image'),
- 'backup': gettext('VZDump backup file'),
- 'vztmpl': gettext('Container template'),
- 'iso': gettext('ISO image'),
- 'rootdir': gettext('Container'),
- 'snippets': gettext('Snippets')
- },
-
- storageSchema: {
- dir: {
- name: Proxmox.Utils.directoryText,
- ipanel: 'DirInputPanel',
- faIcon: 'folder'
- },
- lvm: {
- name: 'LVM',
- ipanel: 'LVMInputPanel',
- faIcon: 'folder'
- },
- lvmthin: {
- name: 'LVM-Thin',
- ipanel: 'LvmThinInputPanel',
- faIcon: 'folder'
- },
- nfs: {
- name: 'NFS',
- ipanel: 'NFSInputPanel',
- faIcon: 'building'
- },
- cifs: {
- name: 'CIFS',
- ipanel: 'CIFSInputPanel',
- faIcon: 'building'
- },
- glusterfs: {
- name: 'GlusterFS',
- ipanel: 'GlusterFsInputPanel',
- faIcon: 'building'
- },
- iscsi: {
- name: 'iSCSI',
- ipanel: 'IScsiInputPanel',
- faIcon: 'building'
- },
- cephfs: {
- name: 'CephFS',
- ipanel: 'CephFSInputPanel',
- faIcon: 'building'
- },
- pvecephfs: {
- name: 'CephFS (PVE)',
- ipanel: 'CephFSInputPanel',
- hideAdd: true,
- faIcon: 'building'
- },
- rbd: {
- name: 'RBD',
- ipanel: 'RBDInputPanel',
- faIcon: 'building'
- },
- pveceph: {
- name: 'RBD (PVE)',
- ipanel: 'RBDInputPanel',
- hideAdd: true,
- faIcon: 'building'
- },
- zfs: {
- name: 'ZFS over iSCSI',
- ipanel: 'ZFSInputPanel',
- faIcon: 'building'
- },
- zfspool: {
- name: 'ZFS',
- ipanel: 'ZFSPoolInputPanel',
- faIcon: 'folder'
- },
- drbd: {
- name: 'DRBD',
- hideAdd: true
- }
- },
-
- format_storage_type: function(value, md, record) {
- if (value === 'rbd') {
- value = (!record || record.get('monhost') ? 'rbd' : 'pveceph');
- } else if (value === 'cephfs') {
- value = (!record || record.get('monhost') ? 'cephfs' : 'pvecephfs');
- }
-
- var schema = PVE.Utils.storageSchema[value];
- if (schema) {
- return schema.name;
- }
- return Proxmox.Utils.unknownText;
- },
-
- format_ha: function(value) {
- var text = Proxmox.Utils.noneText;
-
- if (value.managed) {
- text = value.state || Proxmox.Utils.noneText;
-
- text += ', ' + Proxmox.Utils.groupText + ': ';
- text += value.group || Proxmox.Utils.noneText;
- }
-
- return text;
- },
-
- format_content_types: function(value) {
- return value.split(',').sort().map(function(ct) {
- return PVE.Utils.contentTypes[ct] || ct;
- }).join(', ');
- },
-
- render_storage_content: function(value, metaData, record) {
- var data = record.data;
- if (Ext.isNumber(data.channel) &&
- Ext.isNumber(data.id) &&
- Ext.isNumber(data.lun)) {
- return "CH " +
- Ext.String.leftPad(data.channel,2, '0') +
- " ID " + data.id + " LUN " + data.lun;
- }
- return data.volid.replace(/^.*:(.*\/)?/,'');
- },
-
- render_serverity: function (value) {
- return PVE.Utils.log_severity_hash[value] || value;
- },
-
- render_cpu: function(value, metaData, record, rowIndex, colIndex, store) {
-
- if (!(record.data.uptime && Ext.isNumeric(value))) {
- return '';
- }
-
- var maxcpu = record.data.maxcpu || 1;
-
- if (!Ext.isNumeric(maxcpu) && (maxcpu >= 1)) {
- return '';
- }
-
- var per = value * 100;
-
- return per.toFixed(1) + '% of ' + maxcpu.toString() + (maxcpu > 1 ? 'CPUs' : 'CPU');
- },
-
- render_size: function(value, metaData, record, rowIndex, colIndex, store) {
- /*jslint confusion: true */
-
- if (!Ext.isNumeric(value)) {
- return '';
- }
-
- return Proxmox.Utils.format_size(value);
- },
-
- render_bandwidth: function(value) {
- if (!Ext.isNumeric(value)) {
- return '';
- }
-
- return Proxmox.Utils.format_size(value) + '/s';
- },
-
- render_timestamp_human_readable: function(value) {
- return Ext.Date.format(new Date(value * 1000), 'l d F Y H:i:s');
- },
-
- render_duration: function(value) {
- if (value === undefined) {
- return '-';
- }
- return PVE.Utils.format_duration_short(value);
- },
-
- calculate_mem_usage: function(data) {
- if (!Ext.isNumeric(data.mem) ||
- data.maxmem === 0 ||
- data.uptime < 1) {
- return -1;
- }
-
- return (data.mem / data.maxmem);
- },
-
- render_mem_usage_percent: function(value, metaData, record, rowIndex, colIndex, store) {
- if (!Ext.isNumeric(value) || value === -1) {
- return '';
- }
- if (value > 1 ) {
- // we got no percentage but bytes
- var mem = value;
- var maxmem = record.data.maxmem;
- if (!record.data.uptime ||
- maxmem === 0 ||
- !Ext.isNumeric(mem)) {
- return '';
- }
-
- return ((mem*100)/maxmem).toFixed(1) + " %";
- }
- return (value*100).toFixed(1) + " %";
- },
-
- render_mem_usage: function(value, metaData, record, rowIndex, colIndex, store) {
-
- var mem = value;
- var maxmem = record.data.maxmem;
-
- if (!record.data.uptime) {
- return '';
- }
-
- if (!(Ext.isNumeric(mem) && maxmem)) {
- return '';
- }
-
- return PVE.Utils.render_size(value);
- },
-
- calculate_disk_usage: function(data) {
-
- if (!Ext.isNumeric(data.disk) ||
- data.type === 'qemu' ||
- (data.type === 'lxc' && data.uptime === 0) ||
- data.maxdisk === 0) {
- return -1;
- }
-
- return (data.disk / data.maxdisk);
- },
-
- render_disk_usage_percent: function(value, metaData, record, rowIndex, colIndex, store) {
- if (!Ext.isNumeric(value) || value === -1) {
- return '';
- }
-
- return (value * 100).toFixed(1) + " %";
- },
-
- render_disk_usage: function(value, metaData, record, rowIndex, colIndex, store) {
-
- var disk = value;
- var maxdisk = record.data.maxdisk;
- var type = record.data.type;
-
- if (!Ext.isNumeric(disk) ||
- type === 'qemu' ||
- maxdisk === 0 ||
- (type === 'lxc' && record.data.uptime === 0)) {
- return '';
- }
-
- return PVE.Utils.render_size(value);
- },
-
- get_object_icon_class: function(type, record) {
- var status = '';
- var objType = type;
-
- if (type === 'type') {
- // for folder view
- objType = record.groupbyid;
- } else if (record.template) {
- // templates
- objType = 'template';
- status = type;
- } else {
- // everything else
- status = record.status + ' ha-' + record.hastate;
- }
-
- if (record.lock) {
- status += ' locked lock-' + record.lock;
- }
-
- var defaults = PVE.tree.ResourceTree.typeDefaults[objType];
- if (defaults && defaults.iconCls) {
- var retVal = defaults.iconCls + ' ' + status;
- return retVal;
- }
-
- return '';
- },
-
- render_resource_type: function(value, metaData, record, rowIndex, colIndex, store) {
-
- var cls = PVE.Utils.get_object_icon_class(value,record.data);
-
- var fa = ' ';
- return fa + value;
- },
-
- render_support_level: function(value, metaData, record) {
- return PVE.Utils.support_level_hash[value] || '-';
- },
-
- render_upid: function(value, metaData, record) {
- var type = record.data.type;
- var id = record.data.id;
-
- return Proxmox.Utils.format_task_description(type, id);
- },
-
- /* render functions for new status panel */
-
- render_usage: function(val) {
- return (val*100).toFixed(2) + '%';
- },
-
- render_cpu_usage: function(val, max) {
- return Ext.String.format(gettext('{0}% of {1}') +
- ' ' + gettext('CPU(s)'), (val*100).toFixed(2), max);
- },
-
- render_size_usage: function(val, max) {
- if (max === 0) {
- return gettext('N/A');
- }
- return (val*100/max).toFixed(2) + '% '+ '(' +
- Ext.String.format(gettext('{0} of {1}'),
- PVE.Utils.render_size(val), PVE.Utils.render_size(max)) + ')';
- },
-
- /* this is different for nodes */
- render_node_cpu_usage: function(value, record) {
- return PVE.Utils.render_cpu_usage(value, record.cpus);
- },
-
- /* this is different for nodes */
- render_node_size_usage: function(record) {
- return PVE.Utils.render_size_usage(record.used, record.total);
- },
-
- render_optional_url: function(value) {
- var match;
- if (value && (match = value.match(/^https?:\/\//)) !== null) {
- return '' + value + ' ';
- }
- return value;
- },
-
- render_san: function(value) {
- var names = [];
- if (Ext.isArray(value)) {
- value.forEach(function(val) {
- if (!Ext.isNumber(val)) {
- names.push(val);
- }
- });
- return names.join(' ');
- }
- return value;
- },
-
- render_full_name: function(firstname, metaData, record) {
- var first = firstname || '';
- var last = record.data.lastname || '';
- return Ext.htmlEncode(first + " " + last);
- },
-
- render_u2f_error: function(error) {
- var ErrorNames = {
- '1': gettext('Other Error'),
- '2': gettext('Bad Request'),
- '3': gettext('Configuration Unsupported'),
- '4': gettext('Device Ineligible'),
- '5': gettext('Timeout')
- };
- return "U2F Error: " + ErrorNames[error] || Proxmox.Utils.unknownText;
- },
-
- windowHostname: function() {
- return window.location.hostname.replace(Proxmox.Utils.IP6_bracket_match,
- function(m, addr, offset, original) { return addr; });
- },
-
- openDefaultConsoleWindow: function(consoles, vmtype, vmid, nodename, vmname, cmd) {
- var dv = PVE.Utils.defaultViewer(consoles);
- PVE.Utils.openConsoleWindow(dv, vmtype, vmid, nodename, vmname, cmd);
- },
-
- openConsoleWindow: function(viewer, vmtype, vmid, nodename, vmname, cmd) {
- // kvm, lxc, shell, upgrade
-
- if (vmid == undefined && (vmtype === 'kvm' || vmtype === 'lxc')) {
- throw "missing vmid";
- }
-
- if (!nodename) {
- throw "no nodename specified";
- }
-
- if (viewer === 'html5') {
- PVE.Utils.openVNCViewer(vmtype, vmid, nodename, vmname, cmd);
- } else if (viewer === 'xtermjs') {
- Proxmox.Utils.openXtermJsViewer(vmtype, vmid, nodename, vmname, cmd);
- } else if (viewer === 'vv') {
- var url;
- var params = { proxy: PVE.Utils.windowHostname() };
- if (vmtype === 'kvm') {
- url = '/nodes/' + nodename + '/qemu/' + vmid.toString() + '/spiceproxy';
- PVE.Utils.openSpiceViewer(url, params);
- } else if (vmtype === 'lxc') {
- url = '/nodes/' + nodename + '/lxc/' + vmid.toString() + '/spiceproxy';
- PVE.Utils.openSpiceViewer(url, params);
- } else if (vmtype === 'shell') {
- url = '/nodes/' + nodename + '/spiceshell';
- PVE.Utils.openSpiceViewer(url, params);
- } else if (vmtype === 'upgrade') {
- url = '/nodes/' + nodename + '/spiceshell';
- params.upgrade = 1;
- PVE.Utils.openSpiceViewer(url, params);
- } else if (vmtype === 'cmd') {
- url = '/nodes/' + nodename + '/spiceshell';
- params.cmd = cmd;
- PVE.Utils.openSpiceViewer(url, params);
- }
- } else {
- throw "unknown viewer type";
- }
- },
-
- defaultViewer: function(consoles) {
-
- var allowSpice, allowXtermjs;
-
- if (consoles === true) {
- allowSpice = true;
- allowXtermjs = true;
- } else if (typeof consoles === 'object') {
- allowSpice = consoles.spice;
- allowXtermjs = !!consoles.xtermjs;
- }
- var dv = PVE.VersionInfo.console || 'xtermjs';
- if (dv === 'vv' && !allowSpice) {
- dv = (allowXtermjs) ? 'xtermjs' : 'html5';
- } else if (dv === 'xtermjs' && !allowXtermjs) {
- dv = (allowSpice) ? 'vv' : 'html5';
- }
-
- return dv;
- },
-
- openVNCViewer: function(vmtype, vmid, nodename, vmname, cmd) {
- var url = Ext.Object.toQueryString({
- console: vmtype, // kvm, lxc, upgrade or shell
- novnc: 1,
- vmid: vmid,
- vmname: vmname,
- node: nodename,
- resize: 'off',
- cmd: cmd
- });
- var nw = window.open("?" + url, '_blank', "innerWidth=745,innerheight=427");
- if (nw) {
- nw.focus();
- }
- },
-
- openSpiceViewer: function(url, params){
-
- var downloadWithName = function(uri, name) {
- var link = Ext.DomHelper.append(document.body, {
- tag: 'a',
- href: uri,
- css : 'display:none;visibility:hidden;height:0px;'
- });
-
- // Note: we need to tell android the correct file name extension
- // but we do not set 'download' tag for other environments, because
- // It can have strange side effects (additional user prompt on firefox)
- var andriod = navigator.userAgent.match(/Android/i) ? true : false;
- if (andriod) {
- link.download = name;
- }
-
- if (link.fireEvent) {
- link.fireEvent('onclick');
- } else {
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
- link.dispatchEvent(evt);
- }
- };
-
- Proxmox.Utils.API2Request({
- url: url,
- params: params,
- method: 'POST',
- failure: function(response, opts){
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, opts){
- var raw = "[virt-viewer]\n";
- Ext.Object.each(response.result.data, function(k, v) {
- raw += k + "=" + v + "\n";
- });
- var url = 'data:application/x-virt-viewer;charset=UTF-8,' +
- encodeURIComponent(raw);
-
- downloadWithName(url, "pve-spice.vv");
- }
- });
- },
-
- openTreeConsole: function(tree, record, item, index, e) {
- e.stopEvent();
- var nodename = record.data.node;
- var vmid = record.data.vmid;
- var vmname = record.data.name;
- if (record.data.type === 'qemu' && !record.data.template) {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/qemu/' + vmid + '/status/current',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, opts) {
- let conf = response.result.data;
- var consoles = {
- spice: !!conf.spice,
- xtermjs: !!conf.serial,
- };
- PVE.Utils.openDefaultConsoleWindow(consoles, 'kvm', vmid, nodename, vmname);
- }
- });
- } else if (record.data.type === 'lxc' && !record.data.template) {
- PVE.Utils.openDefaultConsoleWindow(true, 'lxc', vmid, nodename, vmname);
- }
- },
-
- // test automation helper
- call_menu_handler: function(menu, text) {
-
- var list = menu.query('menuitem');
-
- Ext.Array.each(list, function(item) {
- if (item.text === text) {
- if (item.handler) {
- item.handler();
- return 1;
- } else {
- return undefined;
- }
- }
- });
- },
-
- createCmdMenu: function(v, record, item, index, event) {
- event.stopEvent();
- if (!(v instanceof Ext.tree.View)) {
- v.select(record);
- }
- var menu;
- var template = !!record.data.template;
- var type = record.data.type;
-
- if (template) {
- if (type === 'qemu' || type == 'lxc') {
- menu = Ext.create('PVE.menu.TemplateMenu', {
- pveSelNode: record
- });
- }
- } else if (type === 'qemu' ||
- type === 'lxc' ||
- type === 'node') {
- menu = Ext.create('PVE.' + type + '.CmdMenu', {
- pveSelNode: record,
- nodename: record.data.node
- });
- } else {
- return;
- }
-
- menu.showAt(event.getXY());
- return menu;
- },
-
- // helper for deleting field which are set to there default values
- delete_if_default: function(values, fieldname, default_val, create) {
- if (values[fieldname] === '' || values[fieldname] === default_val) {
- if (!create) {
- if (values['delete']) {
- values['delete'] += ',' + fieldname;
- } else {
- values['delete'] = fieldname;
- }
- }
-
- delete values[fieldname];
- }
- },
-
- loadSSHKeyFromFile: function(file, callback) {
- // ssh-keygen produces 740 bytes for an average 4096 bit rsa key, with
- // a user@host comment, 1420 for 8192 bits; current max is 16kbit
- // assume: 740*8 for max. 32kbit (5920 byte file)
- // round upwards to nearest nice number => 8192 bytes, leaves lots of comment space
- if (file.size > 8192) {
- Ext.Msg.alert(gettext('Error'), gettext("Invalid file size: ") + file.size);
- return;
- }
- /*global
- FileReader
- */
- var reader = new FileReader();
- reader.onload = function(evt) {
- callback(evt.target.result);
- };
- reader.readAsText(file);
- },
-
- bus_counts: { ide: 4, sata: 6, scsi: 16, virtio: 16 },
-
- // types is either undefined (all busses), an array of busses, or a single bus
- forEachBus: function(types, func) {
- var busses = Object.keys(PVE.Utils.bus_counts);
- var i, j, count, cont;
-
- if (Ext.isArray(types)) {
- busses = types;
- } else if (Ext.isDefined(types)) {
- busses = [ types ];
- }
-
- // check if we only have valid busses
- for (i = 0; i < busses.length; i++) {
- if (!PVE.Utils.bus_counts[busses[i]]) {
- throw "invalid bus: '" + busses[i] + "'";
- }
- }
-
- for (i = 0; i < busses.length; i++) {
- count = PVE.Utils.bus_counts[busses[i]];
- for (j = 0; j < count; j++) {
- cont = func(busses[i], j);
- if (!cont && cont !== undefined) {
- return;
- }
- }
- }
- },
-
- mp_counts: { mps: 256, unused: 256 },
-
- forEachMP: function(func, includeUnused) {
- var i, cont;
- for (i = 0; i < PVE.Utils.mp_counts.mps; i++) {
- cont = func('mp', i);
- if (!cont && cont !== undefined) {
- return;
- }
- }
-
- if (!includeUnused) {
- return;
- }
-
- for (i = 0; i < PVE.Utils.mp_counts.unused; i++) {
- cont = func('unused', i);
- if (!cont && cont !== undefined) {
- return;
- }
- }
- },
-
- cleanEmptyObjectKeys: function (obj) {
- var propName;
- for (propName in obj) {
- if (obj.hasOwnProperty(propName)) {
- if (obj[propName] === null || obj[propName] === undefined) {
- delete obj[propName];
- }
- }
- }
- },
-
- handleStoreErrorOrMask: function(me, store, regex, callback) {
-
- me.mon(store, 'load', function (proxy, response, success, operation) {
-
- if (success) {
- Proxmox.Utils.setErrorMask(me, false);
- return;
- }
- var msg;
-
- if (operation.error.statusText) {
- if (operation.error.statusText.match(regex)) {
- callback(me, operation.error);
- return;
- } else {
- msg = operation.error.statusText + ' (' + operation.error.status + ')';
- }
- } else {
- msg = gettext('Connection error');
- }
- Proxmox.Utils.setErrorMask(me, msg);
- });
- },
-
- showCephInstallOrMask: function(container, msg, nodename, callback){
- var regex = new RegExp("not (installed|initialized)", "i");
- if (msg.match(regex)) {
- if (Proxmox.UserName === 'root@pam') {
- container.el.mask();
- if (!container.down('pveCephInstallWindow')){
- var isInstalled = msg.match(/not initialized/i) ? true : false;
- var win = Ext.create('PVE.ceph.Install', {
- nodename: nodename
- });
- win.getViewModel().set('isInstalled', isInstalled);
- container.add(win);
- win.show();
- callback(win);
- }
- } else {
- container.mask(Ext.String.format(gettext('{0} not installed.') +
- ' ' + gettext('Log in as root to install.'), 'Ceph'), ['pve-static-mask']);
- }
- return true;
- } else {
- return false;
- }
- }
-},
-
- singleton: true,
- constructor: function() {
- var me = this;
- Ext.apply(me, me.utilities);
- }
-
-});
-
-// ExtJS related things
-
-Proxmox.Utils.toolkit = 'extjs';
-
-// custom PVE specific VTypes
-Ext.apply(Ext.form.field.VTypes, {
-
- QemuStartDate: function(v) {
- return (/^(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)$/).test(v);
- },
- QemuStartDateText: gettext('Format') + ': "now" or "2006-06-17T16:01:21" or "2006-06-17"',
- IP64AddressList: function(v) {
- var list = v.split(/[\ \,\;]+/);
- var i;
- for (i = 0; i < list.length; i++) {
- if (list[i] == '') {
- continue;
- }
-
- if (!Proxmox.Utils.IP64_match.test(list[i])) {
- return false;
- }
- }
-
- return true;
- },
- IP64AddressListText: gettext('Example') + ': 192.168.1.1,192.168.1.2',
- IP64AddressListMask: /[A-Fa-f0-9\,\:\.\;\ ]/
-});
-
-Ext.define('PVE.form.field.Display', {
- override: 'Ext.form.field.Display',
-
- setSubmitValue: function(value) {
- // do nothing, this is only to allow generalized bindings for the:
- // `me.isCreate ? 'textfield' : 'displayfield'` cases we have.
- }
-});
-// Some configuration values are complex strings -
-// so we need parsers/generators for them.
-
-Ext.define('PVE.Parser', { statics: {
-
- // this class only contains static functions
-
- parseACME: function(value) {
- if (!value) {
- return;
- }
-
- var res = {};
- var errors = false;
-
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; //continue
- }
-
- var match_res;
- if ((match_res = p.match(/^(?:domains=)?((?:[a-zA-Z0-9\-\.]+[;, ]?)+)$/)) !== null) {
- res.domains = match_res[1].split(/[;, ]/);
- } else {
- errors = true;
- return false;
- }
- });
-
- if (errors || !res) {
- return;
- }
-
- return res;
- },
-
- parseBoolean: function(value, default_value) {
- if (!Ext.isDefined(value)) {
- return default_value;
- }
- value = value.toLowerCase();
- return value === '1' ||
- value === 'on' ||
- value === 'yes' ||
- value === 'true';
- },
-
- parsePropertyString: function(value, defaultKey) {
- var res = {},
- error;
-
- Ext.Array.each(value.split(','), function(p) {
- var kv = p.split('=', 2);
- if (Ext.isDefined(kv[1])) {
- res[kv[0]] = kv[1];
- } else if (Ext.isDefined(defaultKey)) {
- if (Ext.isDefined(res[defaultKey])) {
- error = 'defaultKey may be only defined once in propertyString';
- return false; // break
- }
- res[defaultKey] = kv[0];
- } else {
- error = 'invalid propertyString, not a key=value pair and no defaultKey defined';
- return false; // break
- }
- });
-
- if (error !== undefined) {
- console.error(error);
- return;
- }
-
- return res;
- },
-
- printPropertyString: function(data, defaultKey) {
- var stringparts = [],
- gotDefaultKeyVal = false,
- defaultKeyVal;
-
- Ext.Object.each(data, function(key, value) {
- if (defaultKey !== undefined && key === defaultKey) {
- gotDefaultKeyVal = true;
- defaultKeyVal = value;
- } else {
- stringparts.push(key + '=' + value);
- }
- });
-
- stringparts = stringparts.sort();
- if (gotDefaultKeyVal) {
- stringparts.unshift(defaultKeyVal);
- }
-
- return stringparts.join(',');
- },
-
- parseQemuNetwork: function(key, value) {
- if (!(key && value)) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
-
- var match_res;
-
- if ((match_res = p.match(/^(ne2k_pci|e1000|e1000-82540em|e1000-82544gc|e1000-82545em|vmxnet3|rtl8139|pcnet|virtio|ne2k_isa|i82551|i82557b|i82559er)(=([0-9a-f]{2}(:[0-9a-f]{2}){5}))?$/i)) !== null) {
- res.model = match_res[1].toLowerCase();
- if (match_res[3]) {
- res.macaddr = match_res[3];
- }
- } else if ((match_res = p.match(/^bridge=(\S+)$/)) !== null) {
- res.bridge = match_res[1];
- } else if ((match_res = p.match(/^rate=(\d+(\.\d+)?)$/)) !== null) {
- res.rate = match_res[1];
- } else if ((match_res = p.match(/^tag=(\d+(\.\d+)?)$/)) !== null) {
- res.tag = match_res[1];
- } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
- res.firewall = match_res[1];
- } else if ((match_res = p.match(/^link_down=(\d+)$/)) !== null) {
- res.disconnect = match_res[1];
- } else if ((match_res = p.match(/^queues=(\d+)$/)) !== null) {
- res.queues = match_res[1];
- } else if ((match_res = p.match(/^trunks=(\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*)$/)) !== null) {
- res.trunks = match_res[1];
- } else {
- errors = true;
- return false; // break
- }
- });
-
- if (errors || !res.model) {
- return;
- }
-
- return res;
- },
-
- printQemuNetwork: function(net) {
-
- var netstr = net.model;
- if (net.macaddr) {
- netstr += "=" + net.macaddr;
- }
- if (net.bridge) {
- netstr += ",bridge=" + net.bridge;
- if (net.tag) {
- netstr += ",tag=" + net.tag;
- }
- if (net.firewall) {
- netstr += ",firewall=" + net.firewall;
- }
- }
- if (net.rate) {
- netstr += ",rate=" + net.rate;
- }
- if (net.queues) {
- netstr += ",queues=" + net.queues;
- }
- if (net.disconnect) {
- netstr += ",link_down=" + net.disconnect;
- }
- if (net.trunks) {
- netstr += ",trunks=" + net.trunks;
- }
- return netstr;
- },
-
- parseQemuDrive: function(key, value) {
- if (!(key && value)) {
- return;
- }
-
- var res = {};
-
- var match_res = key.match(/^([a-z]+)(\d+)$/);
- if (!match_res) {
- return;
- }
- res['interface'] = match_res[1];
- res.index = match_res[2];
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
- var match_res = p.match(/^([a-z_]+)=(\S+)$/);
- if (!match_res) {
- if (!p.match(/\=/)) {
- res.file = p;
- return; // continue
- }
- errors = true;
- return false; // break
- }
- var k = match_res[1];
- if (k === 'volume') {
- k = 'file';
- }
-
- if (Ext.isDefined(res[k])) {
- errors = true;
- return false; // break
- }
-
- var v = match_res[2];
-
- if (k === 'cache' && v === 'off') {
- v = 'none';
- }
-
- res[k] = v;
- });
-
- if (errors || !res.file) {
- return;
- }
-
- return res;
- },
-
- printQemuDrive: function(drive) {
-
- var drivestr = drive.file;
-
- Ext.Object.each(drive, function(key, value) {
- if (!Ext.isDefined(value) || key === 'file' ||
- key === 'index' || key === 'interface') {
- return; // continue
- }
- drivestr += ',' + key + '=' + value;
- });
-
- return drivestr;
- },
-
- parseIPConfig: function(key, value) {
- if (!(key && value)) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
-
- var match_res;
- if ((match_res = p.match(/^ip=(\S+)$/)) !== null) {
- res.ip = match_res[1];
- } else if ((match_res = p.match(/^gw=(\S+)$/)) !== null) {
- res.gw = match_res[1];
- } else if ((match_res = p.match(/^ip6=(\S+)$/)) !== null) {
- res.ip6 = match_res[1];
- } else if ((match_res = p.match(/^gw6=(\S+)$/)) !== null) {
- res.gw6 = match_res[1];
- } else {
- errors = true;
- return false; // break
- }
- });
-
- if (errors) {
- return;
- }
-
- return res;
- },
-
- printIPConfig: function(cfg) {
- var c = "";
- var str = "";
- if (cfg.ip) {
- str += "ip=" + cfg.ip;
- c = ",";
- }
- if (cfg.gw) {
- str += c + "gw=" + cfg.gw;
- c = ",";
- }
- if (cfg.ip6) {
- str += c + "ip6=" + cfg.ip6;
- c = ",";
- }
- if (cfg.gw6) {
- str += c + "gw6=" + cfg.gw6;
- c = ",";
- }
- return str;
- },
-
- parseOpenVZNetIf: function(value) {
- if (!value) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(';'), function(item) {
- if (!item || item.match(/^\s*$/)) {
- return; // continue
- }
-
- var data = {};
- Ext.Array.each(item.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
- var match_res = p.match(/^(ifname|mac|bridge|host_ifname|host_mac|mac_filter)=(\S+)$/);
- if (!match_res) {
- errors = true;
- return false; // break
- }
- if (match_res[1] === 'bridge'){
- var bridgevlanf = match_res[2];
- var bridge_res = bridgevlanf.match(/^(vmbr(\d+))(v(\d+))?(f)?$/);
- if (!bridge_res) {
- errors = true;
- return false; // break
- }
- data.bridge = bridge_res[1];
- data.tag = bridge_res[4];
- /*jslint confusion: true*/
- data.firewall = bridge_res[5] ? 1 : 0;
- /*jslint confusion: false*/
- } else {
- data[match_res[1]] = match_res[2];
- }
- });
-
- if (errors || !data.ifname) {
- errors = true;
- return false; // break
- }
-
- data.raw = item;
-
- res[data.ifname] = data;
- });
-
- return errors ? undefined: res;
- },
-
- printOpenVZNetIf: function(netif) {
- var netarray = [];
-
- Ext.Object.each(netif, function(iface, data) {
- var tmparray = [];
- Ext.Array.each(['ifname', 'mac', 'bridge', 'host_ifname' , 'host_mac', 'mac_filter', 'tag', 'firewall'], function(key) {
- var value = data[key];
- if (key === 'bridge'){
- if(data.tag){
- value = value + 'v' + data.tag;
- }
- if (data.firewall){
- value = value + 'f';
- }
- }
- if (value) {
- tmparray.push(key + '=' + value);
- }
-
- });
- netarray.push(tmparray.join(','));
- });
-
- return netarray.join(';');
- },
-
- parseLxcNetwork: function(value) {
- if (!value) {
- return;
- }
-
- var data = {};
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
- var match_res = p.match(/^(bridge|hwaddr|mtu|name|ip|ip6|gw|gw6|tag|rate)=(\S+)$/);
- if (match_res) {
- data[match_res[1]] = match_res[2];
- } else if ((match_res = p.match(/^firewall=(\d+)$/)) !== null) {
- data.firewall = PVE.Parser.parseBoolean(match_res[1]);
- } else {
- // todo: simply ignore errors ?
- return; // continue
- }
- });
-
- return data;
- },
-
- printLxcNetwork: function(data) {
- var tmparray = [];
- Ext.Array.each(['bridge', 'hwaddr', 'mtu', 'name', 'ip',
- 'gw', 'ip6', 'gw6', 'firewall', 'tag'], function(key) {
- var value = data[key];
- if (value) {
- tmparray.push(key + '=' + value);
- }
- });
-
- /*jslint confusion: true*/
- if (data.rate > 0) {
- tmparray.push('rate=' + data.rate);
- }
- /*jslint confusion: false*/
- return tmparray.join(',');
- },
-
- parseLxcMountPoint: function(value) {
- if (!value) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
- var match_res = p.match(/^([a-z_]+)=(.+)$/);
- if (!match_res) {
- if (!p.match(/\=/)) {
- res.file = p;
- return; // continue
- }
- errors = true;
- return false; // break
- }
- var k = match_res[1];
- if (k === 'volume') {
- k = 'file';
- }
-
- if (Ext.isDefined(res[k])) {
- errors = true;
- return false; // break
- }
-
- var v = match_res[2];
-
- res[k] = v;
- });
-
- if (errors || !res.file) {
- return;
- }
-
- var m = res.file.match(/^([a-z][a-z0-9\-\_\.]*[a-z0-9]):/i);
- if (m) {
- res.storage = m[1];
- res.type = 'volume';
- } else if (res.file.match(/^\/dev\//)) {
- res.type = 'device';
- } else {
- res.type = 'bind';
- }
-
- return res;
- },
-
- printLxcMountPoint: function(mp) {
- var drivestr = mp.file;
-
- Ext.Object.each(mp, function(key, value) {
- if (!Ext.isDefined(value) || key === 'file' ||
- key === 'type' || key === 'storage') {
- return; // continue
- }
- drivestr += ',' + key + '=' + value;
- });
-
- return drivestr;
- },
-
- parseStartup: function(value) {
- if (value === undefined) {
- return;
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
-
- var match_res;
-
- if ((match_res = p.match(/^(order)?=(\d+)$/)) !== null) {
- res.order = match_res[2];
- } else if ((match_res = p.match(/^up=(\d+)$/)) !== null) {
- res.up = match_res[1];
- } else if ((match_res = p.match(/^down=(\d+)$/)) !== null) {
- res.down = match_res[1];
- } else {
- errors = true;
- return false; // break
- }
- });
-
- if (errors) {
- return;
- }
-
- return res;
- },
-
- printStartup: function(startup) {
- var arr = [];
- if (startup.order !== undefined && startup.order !== '') {
- arr.push('order=' + startup.order);
- }
- if (startup.up !== undefined && startup.up !== '') {
- arr.push('up=' + startup.up);
- }
- if (startup.down !== undefined && startup.down !== '') {
- arr.push('down=' + startup.down);
- }
-
- return arr.join(',');
- },
-
- parseQemuSmbios1: function(value) {
- var res = value.split(',').reduce(function (accumulator, currentValue) {
- var splitted = currentValue.split(new RegExp("=(.+)"));
- accumulator[splitted[0]] = splitted[1];
- return accumulator;
- }, {});
-
- if (PVE.Parser.parseBoolean(res.base64, false)) {
- Ext.Object.each(res, function(key, value) {
- if (key === 'uuid') { return; }
- res[key] = Ext.util.Base64.decode(value);
- });
- }
-
- return res;
- },
-
- printQemuSmbios1: function(data) {
-
- var datastr = '';
- var base64 = false;
- Ext.Object.each(data, function(key, value) {
- if (value === '') { return; }
- if (key === 'uuid') {
- datastr += (datastr !== '' ? ',' : '') + key + '=' + value;
- } else {
- // values should be base64 encoded from now on, mark config strings correspondingly
- if (!base64) {
- base64 = true;
- datastr += (datastr !== '' ? ',' : '') + 'base64=1';
- }
- datastr += (datastr !== '' ? ',' : '') + key + '=' + Ext.util.Base64.encode(value);
- }
- });
-
- return datastr;
- },
-
- parseTfaConfig: function(value) {
- var res = {};
-
- Ext.Array.each(value.split(','), function(p) {
- var kva = p.split('=', 2);
- res[kva[0]] = kva[1];
- });
-
- return res;
- },
-
- parseTfaType: function(value) {
- /*jslint confusion: true*/
- var match;
- if (!value || !value.length) {
- return undefined;
- } else if (value === 'x!oath') {
- return 'totp';
- } else if (!!(match = value.match(/^x!(.+)$/))) {
- return match[1];
- } else {
- return 1;
- }
- },
-
- parseQemuCpu: function(value) {
- if (!value) {
- return {};
- }
-
- var res = {};
-
- var errors = false;
- Ext.Array.each(value.split(','), function(p) {
- if (!p || p.match(/^\s*$/)) {
- return; // continue
- }
-
- if (!p.match(/\=/)) {
- if (Ext.isDefined(res.cpu)) {
- errors = true;
- return false; // break
- }
- res.cputype = p;
- return; // continue
- }
-
- var match_res = p.match(/^([a-z_]+)=(\S+)$/);
- if (!match_res) {
- errors = true;
- return false; // break
- }
-
- var k = match_res[1];
- if (Ext.isDefined(res[k])) {
- errors = true;
- return false; // break
- }
-
- res[k] = match_res[2];
- });
-
- if (errors || !res.cputype) {
- return;
- }
-
- return res;
- },
-
- printQemuCpu: function(cpu) {
- var cpustr = cpu.cputype;
- var optstr = '';
-
- Ext.Object.each(cpu, function(key, value) {
- if (!Ext.isDefined(value) || key === 'cputype') {
- return; // continue
- }
- optstr += ',' + key + '=' + value;
- });
-
- if (!cpustr) {
- if (optstr) {
- return 'kvm64' + optstr;
- }
- return;
- }
-
- return cpustr + optstr;
- },
-
- parseSSHKey: function(key) {
- // |--- options can have quotes--| type key comment
- var keyre = /^(?:((?:[^\s"]|\"(?:\\.|[^"\\])*")+)\s+)?(\S+)\s+(\S+)(?:\s+(.*))?$/;
- var typere = /^(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)$/;
-
- var m = key.match(keyre);
- if (!m) {
- return null;
- }
- if (m.length < 3 || !m[2]) { // [2] is always either type or key
- return null;
- }
- if (m[1] && m[1].match(typere)) {
- return {
- type: m[1],
- key: m[2],
- comment: m[3]
- };
- }
- if (m[2].match(typere)) {
- return {
- options: m[1],
- type: m[2],
- key: m[3],
- comment: m[4]
- };
- }
- return null;
- }
-}});
-/* This state provider keeps part of the state inside
- * the browser history.
- *
- * We compress (shorten) url using dictionary based compression
- * i.e. use column separated list instead of url encoded hash:
- * #v\d* version/format
- * := indicates string values
- * :\d+ lookup value in dictionary hash
- * #v1:=value1:5:=value2:=value3:...
-*/
-
-Ext.define('PVE.StateProvider', {
- extend: 'Ext.state.LocalStorageProvider',
-
- // private
- setHV: function(name, newvalue, fireEvents) {
- var me = this;
-
- var changes = false;
- var oldtext = Ext.encode(me.UIState[name]);
- var newtext = Ext.encode(newvalue);
- if (newtext != oldtext) {
- changes = true;
- me.UIState[name] = newvalue;
- //console.log("changed old " + name + " " + oldtext);
- //console.log("changed new " + name + " " + newtext);
- if (fireEvents) {
- me.fireEvent("statechange", me, name, { value: newvalue });
- }
- }
- return changes;
- },
-
- // private
- hslist: [
- // order is important for notifications
- // [ name, default ]
- ['view', 'server'],
- ['rid', 'root'],
- ['ltab', 'tasks'],
- ['nodetab', ''],
- ['storagetab', ''],
- ['pooltab', ''],
- ['kvmtab', ''],
- ['lxctab', ''],
- ['dctab', '']
- ],
-
- hprefix: 'v1',
-
- compDict: {
- cloudinit: 52,
- replication: 51,
- system: 50,
- monitor: 49,
- 'ha-fencing': 48,
- 'ha-groups': 47,
- 'ha-resources': 46,
- 'ceph-log': 45,
- 'ceph-crushmap':44,
- 'ceph-pools': 43,
- 'ceph-osdtree': 42,
- 'ceph-disklist': 41,
- 'ceph-monlist': 40,
- 'ceph-config': 39,
- ceph: 38,
- 'firewall-fwlog': 37,
- 'firewall-options': 36,
- 'firewall-ipset': 35,
- 'firewall-aliases': 34,
- 'firewall-sg': 33,
- firewall: 32,
- apt: 31,
- members: 30,
- snapshot: 29,
- ha: 28,
- support: 27,
- pools: 26,
- syslog: 25,
- ubc: 24,
- initlog: 23,
- openvz: 22,
- backup: 21,
- resources: 20,
- content: 19,
- root: 18,
- domains: 17,
- roles: 16,
- groups: 15,
- users: 14,
- time: 13,
- dns: 12,
- network: 11,
- services: 10,
- options: 9,
- console: 8,
- hardware: 7,
- permissions: 6,
- summary: 5,
- tasks: 4,
- clog: 3,
- storage: 2,
- folder: 1,
- server: 0
- },
-
- decodeHToken: function(token) {
- var me = this;
-
- var state = {};
- if (!token) {
- Ext.Array.each(me.hslist, function(rec) {
- state[rec[0]] = rec[1];
- });
- return state;
- }
-
- // return Ext.urlDecode(token);
-
- var items = token.split(':');
- var prefix = items.shift();
-
- if (prefix != me.hprefix) {
- return me.decodeHToken();
- }
-
- Ext.Array.each(me.hslist, function(rec) {
- var value = items.shift();
- if (value) {
- if (value[0] === '=') {
- value = decodeURIComponent(value.slice(1));
- } else {
- Ext.Object.each(me.compDict, function(key, cv) {
- if (value == cv) {
- value = key;
- return false;
- }
- });
- }
- }
- state[rec[0]] = value;
- });
-
- return state;
- },
-
- encodeHToken: function(state) {
- var me = this;
-
- // return Ext.urlEncode(state);
-
- var ctoken = me.hprefix;
- Ext.Array.each(me.hslist, function(rec) {
- var value = state[rec[0]];
- if (!Ext.isDefined(value)) {
- value = rec[1];
- }
- value = encodeURIComponent(value);
- if (!value) {
- ctoken += ':';
- } else {
- var comp = me.compDict[value];
- if (Ext.isDefined(comp)) {
- ctoken += ":" + comp;
- } else {
- ctoken += ":=" + value;
- }
- }
- });
-
- return ctoken;
- },
-
- constructor: function(config){
- var me = this;
-
- me.callParent([config]);
-
- me.UIState = me.decodeHToken(); // set default
-
- var history_change_cb = function(token) {
- //console.log("HC " + token);
- if (!token) {
- var res = window.confirm(gettext('Are you sure you want to navigate away from this page?'));
- if (res){
- // process text value and close...
- Ext.History.back();
- } else {
- Ext.History.forward();
- }
- return;
- }
-
- var newstate = me.decodeHToken(token);
- Ext.Array.each(me.hslist, function(rec) {
- if (typeof newstate[rec[0]] == "undefined") {
- return;
- }
- me.setHV(rec[0], newstate[rec[0]], true);
- });
- };
-
- var start_token = Ext.History.getToken();
- if (start_token) {
- history_change_cb(start_token);
- } else {
- var htext = me.encodeHToken(me.UIState);
- Ext.History.add(htext);
- }
-
- Ext.History.on('change', history_change_cb);
- },
-
- get: function(name, defaultValue){
- /*jslint confusion: true */
- var me = this;
- var data;
-
- if (typeof me.UIState[name] != "undefined") {
- data = { value: me.UIState[name] };
- } else {
- data = me.callParent(arguments);
- if (!data && name === 'GuiCap') {
- data = { vms: {}, storage: {}, access: {}, nodes: {}, dc: {} };
- }
- }
-
- //console.log("GET " + name + " " + Ext.encode(data));
- return data;
- },
-
- clear: function(name){
- var me = this;
-
- if (typeof me.UIState[name] != "undefined") {
- me.UIState[name] = null;
- }
-
- me.callParent(arguments);
- },
-
- set: function(name, value, fireevent){
- var me = this;
-
- //console.log("SET " + name + " " + Ext.encode(value));
- if (typeof me.UIState[name] != "undefined") {
- var newvalue = value ? value.value : null;
- if (me.setHV(name, newvalue, fireevent)) {
- var htext = me.encodeHToken(me.UIState);
- Ext.History.add(htext);
- }
- } else {
- me.callParent(arguments);
- }
- }
-});
-Ext.define('PVE.menu.Item', {
- extend: 'Ext.menu.Item',
- alias: 'widget.pveMenuItem',
-
- // set to wrap the handler callback in a confirm dialog showing this text
- confirmMsg: false,
-
- // set to focus 'No' instead of 'Yes' button and show a warning symbol
- dangerous: false,
-
- initComponent: function() {
- var me = this;
-
- if (me.handler) {
- me.setHandler(me.handler, me.scope);
- }
-
- me.callParent();
- },
-
- setHandler: function(fn, scope) {
- var me = this;
- me.scope = scope;
- me.handler = function(button, e) {
- var rec, msg;
- if (me.confirmMsg) {
- msg = me.confirmMsg;
- Ext.MessageBox.defaultButton = me.dangerous ? 2 : 1;
- Ext.Msg.show({
- title: gettext('Confirm'),
- icon: me.dangerous ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
- msg: msg,
- buttons: Ext.Msg.YESNO,
- defaultFocus: me.dangerous ? 'no' : 'yes',
- callback: function(btn) {
- if (btn === 'yes') {
- Ext.callback(fn, me.scope, [me, e], 0, me);
- }
- }
- });
- } else {
- Ext.callback(fn, me.scope, [me, e], 0, me);
- }
- };
- }
-});
-Ext.define('PVE.menu.TemplateMenu', {
- extend: 'Ext.menu.Menu',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var guestType = me.pveSelNode.data.type;
- if (guestType !== 'qemu' && guestType != 'lxc') {
- throw "invalid guest type";
- }
-
- var vmname = me.pveSelNode.data.name;
-
- var template = me.pveSelNode.data.template;
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + nodename + '/' + guestType + '/' + vmid + "/status/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- me.title = (guestType === 'qemu' ? 'VM ' : 'CT ') + vmid;
-
- me.items = [
- {
- text: gettext('Migrate'),
- iconCls: 'fa fa-fw fa-send-o',
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: guestType,
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- }
- },
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- handler: function() {
- var win = Ext.create('PVE.window.Clone', {
- nodename: nodename,
- guestType: guestType,
- vmid: vmid,
- isTemplate: template
- });
- win.show();
- }
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.button.ConsoleButton', {
- extend: 'Ext.button.Split',
- alias: 'widget.pveConsoleButton',
-
- consoleType: 'shell', // one of 'shell', 'kvm', 'lxc', 'upgrade', 'cmd'
-
- cmd: undefined,
-
- consoleName: undefined,
-
- iconCls: 'fa fa-terminal',
-
- enableSpice: true,
- enableXtermjs: true,
-
- nodename: undefined,
-
- vmid: 0,
-
- text: gettext('Console'),
-
- setEnableSpice: function(enable){
- var me = this;
-
- me.enableSpice = enable;
- me.down('#spicemenu').setDisabled(!enable);
- },
-
- setEnableXtermJS: function(enable){
- var me = this;
-
- me.enableXtermjs = enable;
- me.down('#xtermjs').setDisabled(!enable);
- },
-
- handler: function() {
- var me = this;
- var consoles = {
- spice: me.enableSpice,
- xtermjs: me.enableXtermjs
- };
- PVE.Utils.openDefaultConsoleWindow(consoles, me.consoleType, me.vmid,
- me.nodename, me.consoleName, me.cmd);
- },
-
- menu: [
- {
- xtype:'menuitem',
- text: 'noVNC',
- iconCls: 'pve-itype-icon-novnc',
- type: 'html5',
- handler: function(button) {
- var me = this.up('button');
- PVE.Utils.openConsoleWindow(button.type, me.consoleType, me.vmid, me.nodename, me.consoleName, me.cmd);
- }
- },
- {
- xterm: 'menuitem',
- itemId: 'spicemenu',
- text: 'SPICE',
- type: 'vv',
- iconCls: 'pve-itype-icon-virt-viewer',
- handler: function(button) {
- var me = this.up('button');
- PVE.Utils.openConsoleWindow(button.type, me.consoleType, me.vmid, me.nodename, me.consoleName, me.cmd);
- }
- },
- {
- text: 'xterm.js',
- itemId: 'xtermjs',
- iconCls: 'pve-itype-icon-xtermjs',
- type: 'xtermjs',
- handler: function(button) {
- var me = this.up('button');
- PVE.Utils.openConsoleWindow(button.type, me.consoleType, me.vmid, me.nodename, me.consoleName, me.cmd);
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.callParent();
- }
-});
-/* Button features:
- * - observe selection changes to enable/disable the button using enableFn()
- * - pop up confirmation dialog using confirmMsg()
- *
- * does this for the button and every menu item
- */
-Ext.define('PVE.button.Split', {
- extend: 'Ext.button.Split',
- alias: 'widget.pveSplitButton',
-
- // the selection model to observe
- selModel: undefined,
-
- // if 'false' handler will not be called (button disabled)
- enableFn: function(record) { },
-
- // function(record) or text
- confirmMsg: false,
-
- // take special care in confirm box (select no as default).
- dangerous: false,
-
- handlerWrapper: function(button, event) {
- var me = this;
- var rec, msg;
- if (me.selModel) {
- rec = me.selModel.getSelection()[0];
- if (!rec || (me.enableFn(rec) === false)) {
- return;
- }
- }
-
- if (me.confirmMsg) {
- msg = me.confirmMsg;
- // confirMsg can be boolean or function
- /*jslint confusion: true*/
- if (Ext.isFunction(me.confirmMsg)) {
- msg = me.confirmMsg(rec);
- }
- /*jslint confusion: false*/
- Ext.MessageBox.defaultButton = me.dangerous ? 2 : 1;
- Ext.Msg.show({
- title: gettext('Confirm'),
- icon: me.dangerous ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
- msg: msg,
- buttons: Ext.Msg.YESNO,
- callback: function(btn) {
- if (btn !== 'yes') {
- return;
- }
- me.realHandler(button, event, rec);
- }
- });
- } else {
- me.realHandler(button, event, rec);
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
-
- var me = this;
-
- if (me.handler) {
- me.realHandler = me.handler;
- me.handler = me.handlerWrapper;
- }
-
- if (me.menu && me.menu.items) {
- me.menu.items.forEach(function(item) {
- if (item.handler) {
- item.realHandler = item.handler;
- item.handler = me.handlerWrapper;
- }
-
- if (item.selModel) {
- me.mon(item.selModel, "selectionchange", function() {
- var rec = item.selModel.getSelection()[0];
- if (!rec || (item.enableFn(rec) === false )) {
- item.setDisabled(true);
- } else {
- item.setDisabled(false);
- }
- });
- }
- });
- }
-
- me.callParent();
-
- if (me.selModel) {
-
- me.mon(me.selModel, "selectionchange", function() {
- var rec = me.selModel.getSelection()[0];
- if (!rec || (me.enableFn(rec) === false)) {
- me.setDisabled(true);
- } else {
- me.setDisabled(false);
- }
- });
- }
- }
-});
-Ext.define('PVE.controller.StorageEdit', {
- extend: 'Ext.app.ViewController',
- alias: 'controller.storageEdit',
- control: {
- 'field[name=content]': {
- change: function(field, value) {
- var hasBackups = Ext.Array.contains(value, 'backup');
- var maxfiles = this.lookupReference('maxfiles');
- if (!maxfiles) {
- return;
- }
-
- if (!hasBackups) {
- // clear values which will never be submitted
- maxfiles.reset();
- }
- maxfiles.setDisabled(!hasBackups);
- }
- }
- }
-});
-Ext.define('PVE.qemu.CmdMenu', {
- extend: 'Ext.menu.Menu',
-
- showSeparator: false,
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var vmname = me.pveSelNode.data.name;
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + nodename + '/qemu/' + vmid + "/status/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var running = false;
- var stopped = true;
- var suspended = false;
- var standalone = PVE.data.ResourceStore.getNodes().length < 2;
-
- switch (me.pveSelNode.data.status) {
- case 'running':
- running = true;
- stopped = false;
- break;
- case 'suspended':
- stopped = false;
- suspended = true;
- break;
- case 'paused':
- stopped = false;
- suspended = true;
- break;
- default: break;
- }
-
- me.title = "VM " + vmid;
-
- me.items = [
- {
- text: gettext('Start'),
- iconCls: 'fa fa-fw fa-play',
- hidden: running || suspended,
- disabled: running || suspended,
- handler: function() {
- vm_command('start');
- }
- },
- {
- text: gettext('Pause'),
- iconCls: 'fa fa-fw fa-pause',
- hidden: stopped || suspended,
- disabled: stopped || suspended,
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmpause', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
- vm_command('suspend');
- });
- }
- },
- {
- text: gettext('Hibernate'),
- iconCls: 'fa fa-fw fa-download',
- hidden: stopped || suspended,
- disabled: stopped || suspended,
- tooltip: gettext('Suspend to disk'),
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmsuspend', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
- vm_command('suspend', { todisk: 1 });
- });
- }
- },
- {
- text: gettext('Resume'),
- iconCls: 'fa fa-fw fa-play',
- hidden: !suspended,
- handler: function() {
- vm_command('resume');
- }
- },
- {
- text: gettext('Shutdown'),
- iconCls: 'fa fa-fw fa-power-off',
- disabled: stopped || suspended,
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmshutdown', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- vm_command('shutdown');
- });
- }
- },
- {
- text: gettext('Stop'),
- iconCls: 'fa fa-fw fa-stop',
- disabled: stopped,
- tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'VM'),
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmstop', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- vm_command("stop");
- });
- }
- },
- {
- xtype: 'menuseparator',
- hidden: (standalone || !caps.vms['VM.Migrate']) && !caps.vms['VM.Allocate'] && !caps.vms['VM.Clone']
- },
- {
- text: gettext('Migrate'),
- iconCls: 'fa fa-fw fa-send-o',
- hidden: standalone || !caps.vms['VM.Migrate'],
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: 'qemu',
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- }
- },
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- hidden: !caps.vms['VM.Clone'],
- handler: function() {
- PVE.window.Clone.wrap(nodename, vmid, me.isTemplate, 'qemu');
- }
- },
- {
- text: gettext('Convert to template'),
- iconCls: 'fa fa-fw fa-file-o',
- hidden: !caps.vms['VM.Allocate'],
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('qmtemplate', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/qemu/' + vmid + '/template',
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- });
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Console'),
- iconCls: 'fa fa-fw fa-terminal',
- handler: function() {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/qemu/' + vmid + '/status/current',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, opts) {
- var allowSpice = response.result.data.spice;
- var allowXtermjs = response.result.data.serial;
- var consoles = {
- spice: allowSpice,
- xtermjs: allowXtermjs
- };
- PVE.Utils.openDefaultConsoleWindow(consoles, 'kvm', vmid, nodename, vmname);
- }
- });
- }
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.lxc.CmdMenu', {
- extend: 'Ext.menu.Menu',
-
- showSeparator: false,
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no CT ID specified";
- }
- var vmname = me.pveSelNode.data.name;
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + nodename + '/lxc/' + vmid + "/status/" + cmd,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var running = false;
- var stopped = true;
- var suspended = false;
- var standalone = PVE.data.ResourceStore.getNodes().length < 2;
-
- switch (me.pveSelNode.data.status) {
- case 'running':
- running = true;
- stopped = false;
- break;
- case 'paused':
- stopped = false;
- suspended = true;
- break;
- default: break;
- }
-
- me.title = 'CT ' + vmid;
-
- me.items = [
- {
- text: gettext('Start'),
- iconCls: 'fa fa-fw fa-play',
- disabled: running,
- handler: function() {
- vm_command('start');
- }
- },
-// {
-// text: gettext('Suspend'),
-// iconCls: 'fa fa-fw fa-pause',
-// hidde: suspended,
-// disabled: stopped || suspended,
-// handler: function() {
-// var msg = Proxmox.Utils.format_task_description('vzsuspend', vmid);
-// Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
-// if (btn !== 'yes') {
-// return;
-// }
-//
-// vm_command('suspend');
-// });
-// }
-// },
-// {
-// text: gettext('Resume'),
-// iconCls: 'fa fa-fw fa-play',
-// hidden: !suspended,
-// handler: function() {
-// vm_command('resume');
-// }
-// },
- {
- text: gettext('Shutdown'),
- iconCls: 'fa fa-fw fa-power-off',
- disabled: stopped || suspended,
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('vzshutdown', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- vm_command('shutdown');
- });
- }
- },
- {
- text: gettext('Stop'),
- iconCls: 'fa fa-fw fa-stop',
- disabled: stopped,
- tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'CT'),
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('vzstop', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- vm_command("stop");
- });
- }
- },
- {
- xtype: 'menuseparator',
- hidden: standalone || !caps.vms['VM.Migrate']
- },
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- hidden: !caps.vms['VM.Clone'],
- handler: function() {
- PVE.window.Clone.wrap(nodename, vmid, me.isTemplate, 'lxc');
- }
- },
- {
- text: gettext('Migrate'),
- iconCls: 'fa fa-fw fa-send-o',
- hidden: standalone || !caps.vms['VM.Migrate'],
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: 'lxc',
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- }
- },
- {
- text: gettext('Convert to template'),
- iconCls: 'fa fa-fw fa-file-o',
- handler: function() {
- var msg = Proxmox.Utils.format_task_description('vztemplate', vmid);
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/lxc/' + vmid + '/template',
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- });
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Console'),
- iconCls: 'fa fa-fw fa-terminal',
- handler: function() {
- PVE.Utils.openDefaultConsoleWindow(true, 'lxc', vmid, nodename, vmname);
- }
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.node.CmdMenu', {
- extend: 'Ext.menu.Menu',
- xtype: 'nodeCmdMenu',
-
- showSeparator: false,
-
- items: [
- {
- text: gettext('Create VM'),
- itemId: 'createvm',
- iconCls: 'fa fa-desktop',
- handler: function() {
- var me = this.up('menu');
- var wiz = Ext.create('PVE.qemu.CreateWizard', {
- nodename: me.nodename
- });
- wiz.show();
- }
- },
- {
- text: gettext('Create CT'),
- itemId: 'createct',
- iconCls: 'fa fa-cube',
- handler: function() {
- var me = this.up('menu');
- var wiz = Ext.create('PVE.lxc.CreateWizard', {
- nodename: me.nodename
- });
- wiz.show();
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Bulk Start'),
- itemId: 'bulkstart',
- iconCls: 'fa fa-fw fa-play',
- handler: function() {
- var me = this.up('menu');
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: me.nodename,
- title: gettext('Bulk Start'),
- btnText: gettext('Start'),
- action: 'startall'
- });
- win.show();
- }
- },
- {
- text: gettext('Bulk Stop'),
- itemId: 'bulkstop',
- iconCls: 'fa fa-fw fa-stop',
- handler: function() {
- var me = this.up('menu');
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: me.nodename,
- title: gettext('Bulk Stop'),
- btnText: gettext('Stop'),
- action: 'stopall'
- });
- win.show();
- }
- },
- {
- text: gettext('Bulk Migrate'),
- itemId: 'bulkmigrate',
- iconCls: 'fa fa-fw fa-send-o',
- handler: function() {
- var me = this.up('menu');
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: me.nodename,
- title: gettext('Bulk Migrate'),
- btnText: gettext('Migrate'),
- action: 'migrateall'
- });
- win.show();
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Shell'),
- itemId: 'shell',
- iconCls: 'fa fa-fw fa-terminal',
- handler: function() {
- var me = this.up('menu');
- PVE.Utils.openDefaultConsoleWindow(true, 'shell', undefined, me.nodename, undefined);
- }
- },
- { xtype: 'menuseparator' },
- {
- text: gettext('Wake-on-LAN'),
- itemId: 'wakeonlan',
- iconCls: 'fa fa-fw fa-power-off',
- handler: function() {
- var me = this.up('menu');
- Proxmox.Utils.API2Request({
- param: {},
- url: '/nodes/' + me.nodename + '/wakeonlan',
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- Ext.Msg.show({
- title: 'Success',
- icon: Ext.Msg.INFO,
- msg: Ext.String.format(gettext("Wake on LAN packet send for '{0}': '{1}'"), me.nodename, response.result.data)
- });
- }
- });
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw 'no nodename specified';
- }
-
- me.title = gettext('Node') + " '" + me.nodename + "'";
- me.callParent();
-
- var caps = Ext.state.Manager.get('GuiCap');
- // disable not allowed options
- if (!caps.vms['VM.Allocate']) {
- me.getComponent('createct').setDisabled(true);
- me.getComponent('createvm').setDisabled(true);
- }
-
- if (!caps.nodes['Sys.PowerMgmt']) {
- me.getComponent('bulkstart').setDisabled(true);
- me.getComponent('bulkstop').setDisabled(true);
- me.getComponent('bulkmigrate').setDisabled(true);
- me.getComponent('wakeonlan').setDisabled(true);
- }
-
- if (!caps.nodes['Sys.Console']) {
- me.getComponent('shell').setDisabled(true);
- }
-
- if (me.pveSelNode.data.running) {
- me.getComponent('wakeonlan').setDisabled(true);
- }
- }
-});
-Ext.define('PVE.noVncConsole', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNoVncConsole',
-
- nodename: undefined,
-
- vmid: undefined,
-
- cmd: undefined,
-
- consoleType: undefined, // lxc, kvm, shell, cmd
-
- layout: 'fit',
-
- xtermjs: false,
-
- border: false,
-
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.consoleType) {
- throw "no console type specified";
- }
-
- if (!me.vmid && me.consoleType !== 'shell' && me.consoleType !== 'cmd') {
- throw "no VM ID specified";
- }
-
- // always use same iframe, to avoid running several noVnc clients
- // at same time (to avoid performance problems)
- var box = Ext.create('Ext.ux.IFrame', { itemid : "vncconsole" });
-
- var type = me.xtermjs ? 'xtermjs' : 'novnc';
- Ext.apply(me, {
- items: box,
- listeners: {
- activate: function() {
- var queryDict = {
- console: me.consoleType, // kvm, lxc, upgrade or shell
- vmid: me.vmid,
- node: me.nodename,
- cmd: me.cmd,
- resize: 'scale'
- };
- queryDict[type] = 1;
- PVE.Utils.cleanEmptyObjectKeys(queryDict);
- var url = '/?' + Ext.Object.toQueryString(queryDict);
- box.load(url);
- }
- }
- });
-
- me.callParent();
-
- me.on('afterrender', function() {
- me.focus();
- });
- }
-});
-
-Ext.define('PVE.data.PermPathStore', {
- extend: 'Ext.data.Store',
- alias: 'store.pvePermPath',
- fields: [ 'value' ],
- autoLoad: false,
- data: [
- {'value': '/'},
- {'value': '/access'},
- {'value': '/nodes'},
- {'value': '/pool'},
- {'value': '/storage'},
- {'value': '/vms'}
- ],
-
- constructor: function(config) {
- var me = this;
-
- config = config || {};
-
- me.callParent([config]);
-
- me.suspendEvents();
- PVE.data.ResourceStore.each(function(record) {
- switch (record.get('type')) {
- case 'node':
- me.add({value: '/nodes/' + record.get('text')});
- break;
-
- case 'qemu':
- me.add({value: '/vms/' + record.get('vmid')});
- break;
-
- case 'lxc':
- me.add({value: '/vms/' + record.get('vmid')});
- break;
-
- case 'storage':
- me.add({value: '/storage/' + record.get('storage')});
- break;
- case 'pool':
- me.add({value: '/pool/' + record.get('pool')});
- break;
- }
- });
- me.resumeEvents();
-
- me.fireEvent('refresh', me);
- me.fireEvent('datachanged', me);
-
- me.sort({
- property: 'value',
- direction: 'ASC'
- });
- }
-});
-Ext.define('PVE.data.ResourceStore', {
- extend: 'Proxmox.data.UpdateStore',
- singleton: true,
-
- findVMID: function(vmid) {
- var me = this, i;
-
- return (me.findExact('vmid', parseInt(vmid, 10)) >= 0);
- },
-
- // returns the cached data from all nodes
- getNodes: function() {
- var me = this;
-
- var nodes = [];
- me.each(function(record) {
- if (record.get('type') == "node") {
- nodes.push( record.getData() );
- }
- });
-
- return nodes;
- },
-
- storageIsShared: function(storage_path) {
- var me = this;
-
- var index = me.findExact('id', storage_path);
-
- return me.getAt(index).data.shared;
- },
-
- guestNode: function(vmid) {
- var me = this;
-
- var index = me.findExact('vmid', parseInt(vmid, 10));
-
- return me.getAt(index).data.node;
- },
-
- constructor: function(config) {
- // fixme: how to avoid those warnings
- /*jslint confusion: true */
-
- var me = this;
-
- config = config || {};
-
- var field_defaults = {
- type: {
- header: gettext('Type'),
- type: 'string',
- renderer: PVE.Utils.render_resource_type,
- sortable: true,
- hideable: false,
- width: 100
- },
- id: {
- header: 'ID',
- type: 'string',
- hidden: true,
- sortable: true,
- width: 80
- },
- running: {
- header: gettext('Online'),
- type: 'boolean',
- renderer: Proxmox.Utils.format_boolean,
- hidden: true,
- convert: function(value, record) {
- var info = record.data;
- return (Ext.isNumeric(info.uptime) && (info.uptime > 0));
- }
- },
- text: {
- header: gettext('Description'),
- type: 'string',
- sortable: true,
- width: 200,
- convert: function(value, record) {
- var info = record.data;
- var text;
-
- if (value) {
- return value;
- }
-
- if (Ext.isNumeric(info.vmid) && info.vmid > 0) {
- text = String(info.vmid);
- if (info.name) {
- text += " (" + info.name + ')';
- }
- } else { // node, pool, storage
- text = info[info.type] || info.id;
- if (info.node && info.type !== 'node') {
- text += " (" + info.node + ")";
- }
- }
-
- return text;
- }
- },
- vmid: {
- header: 'VMID',
- type: 'integer',
- hidden: true,
- sortable: true,
- width: 80
- },
- name: {
- header: gettext('Name'),
- hidden: true,
- sortable: true,
- type: 'string'
- },
- disk: {
- header: gettext('Disk usage'),
- type: 'integer',
- renderer: PVE.Utils.render_disk_usage,
- sortable: true,
- width: 100,
- hidden: true
- },
- diskuse: {
- header: gettext('Disk usage') + " %",
- type: 'number',
- sortable: true,
- renderer: PVE.Utils.render_disk_usage_percent,
- width: 100,
- calculate: PVE.Utils.calculate_disk_usage,
- sortType: 'asFloat'
- },
- maxdisk: {
- header: gettext('Disk size'),
- type: 'integer',
- renderer: PVE.Utils.render_size,
- sortable: true,
- hidden: true,
- width: 100
- },
- mem: {
- header: gettext('Memory usage'),
- type: 'integer',
- renderer: PVE.Utils.render_mem_usage,
- sortable: true,
- hidden: true,
- width: 100
- },
- memuse: {
- header: gettext('Memory usage') + " %",
- type: 'number',
- renderer: PVE.Utils.render_mem_usage_percent,
- calculate: PVE.Utils.calculate_mem_usage,
- sortType: 'asFloat',
- sortable: true,
- width: 100
- },
- maxmem: {
- header: gettext('Memory size'),
- type: 'integer',
- renderer: PVE.Utils.render_size,
- hidden: true,
- sortable: true,
- width: 100
- },
- cpu: {
- header: gettext('CPU usage'),
- type: 'float',
- renderer: PVE.Utils.render_cpu,
- sortable: true,
- width: 100
- },
- maxcpu: {
- header: gettext('maxcpu'),
- type: 'integer',
- hidden: true,
- sortable: true,
- width: 60
- },
- diskread: {
- header: gettext('Total Disk Read'),
- type: 'integer',
- hidden: true,
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- width: 100
- },
- diskwrite: {
- header: gettext('Total Disk Write'),
- type: 'integer',
- hidden: true,
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- width: 100
- },
- netin: {
- header: gettext('Total NetIn'),
- type: 'integer',
- hidden: true,
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- width: 100
- },
- netout: {
- header: gettext('Total NetOut'),
- type: 'integer',
- hidden: true,
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- width: 100
- },
- template: {
- header: gettext('Template'),
- type: 'integer',
- hidden: true,
- sortable: true,
- width: 60
- },
- uptime: {
- header: gettext('Uptime'),
- type: 'integer',
- renderer: Proxmox.Utils.render_uptime,
- sortable: true,
- width: 110
- },
- node: {
- header: gettext('Node'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- },
- storage: {
- header: gettext('Storage'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- },
- pool: {
- header: gettext('Pool'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- },
- hastate: {
- header: gettext('HA State'),
- type: 'string',
- defaultValue: 'unmanaged',
- hidden: true,
- sortable: true
- },
- status: {
- header: gettext('Status'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- },
- lock: {
- header: gettext('Lock'),
- type: 'string',
- hidden: true,
- sortable: true,
- width: 110
- }
- };
-
- var fields = [];
- var fieldNames = [];
- Ext.Object.each(field_defaults, function(key, value) {
- var field = {name: key, type: value.type};
- if (Ext.isDefined(value.convert)) {
- field.convert = value.convert;
- }
-
- if (Ext.isDefined(value.calculate)) {
- field.calculate = value.calculate;
- }
-
- if (Ext.isDefined(value.defaultValue)) {
- field.defaultValue = value.defaultValue;
- }
-
- fields.push(field);
- fieldNames.push(key);
- });
-
- Ext.define('PVEResources', {
- extend: "Ext.data.Model",
- fields: fields,
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/resources'
- }
- });
-
- Ext.define('PVETree', {
- extend: "Ext.data.Model",
- fields: fields,
- proxy: { type: 'memory' }
- });
-
- Ext.apply(config, {
- storeid: 'PVEResources',
- model: 'PVEResources',
- defaultColumns: function() {
- var res = [];
- Ext.Object.each(field_defaults, function(field, info) {
- var fi = Ext.apply({ dataIndex: field }, info);
- res.push(fi);
- });
- return res;
- },
- fieldNames: fieldNames
- });
-
- me.callParent([config]);
- }
-});
-Ext.define('pve-domains', {
- extend: "Ext.data.Model",
- fields: [
- 'realm', 'type', 'comment', 'default', 'tfa',
- {
- name: 'descr',
- // Note: We use this in the RealmComboBox.js (see Bug #125)
- convert: function(value, record) {
- if (value) {
- return value;
- }
-
- var info = record.data;
- // return realm if there is no comment
- var text = info.comment || info.realm;
-
- if (info.tfa) {
- text += " (+ " + info.tfa + ")";
- }
-
- return Ext.String.htmlEncode(text);
- }
- }
- ],
- idProperty: 'realm',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/domains"
- }
-});
-Ext.define('pve-rrd-node', {
- extend: 'Ext.data.Model',
- fields: [
- {
- name:'cpu',
- // percentage
- convert: function(value) {
- return value*100;
- }
- },
- {
- name:'iowait',
- // percentage
- convert: function(value) {
- return value*100;
- }
- },
- 'loadavg',
- 'maxcpu',
- 'memtotal',
- 'memused',
- 'netin',
- 'netout',
- 'roottotal',
- 'rootused',
- 'swaptotal',
- 'swapused',
- { type: 'date', dateFormat: 'timestamp', name: 'time' }
- ]
-});
-
-Ext.define('pve-rrd-guest', {
- extend: 'Ext.data.Model',
- fields: [
- {
- name:'cpu',
- // percentage
- convert: function(value) {
- return value*100;
- }
- },
- 'maxcpu',
- 'netin',
- 'netout',
- 'mem',
- 'maxmem',
- 'disk',
- 'maxdisk',
- 'diskread',
- 'diskwrite',
- { type: 'date', dateFormat: 'timestamp', name: 'time' }
- ]
-});
-
-Ext.define('pve-rrd-storage', {
- extend: 'Ext.data.Model',
- fields: [
- 'used',
- 'total',
- { type: 'date', dateFormat: 'timestamp', name: 'time' }
- ]
-});
-Ext.define('PVE.form.VlanField', {
- extend: 'Ext.form.field.Number',
- alias: ['widget.pveVlanField'],
-
- deleteEmpty: false,
-
- emptyText: 'no VLAN',
-
- fieldLabel: gettext('VLAN Tag'),
-
- allowBlank: true,
-
- getSubmitData: function() {
- var me = this,
- data = null,
- val;
- if (!me.disabled && me.submitValue) {
- val = me.getSubmitValue();
- if (val) {
- data = {};
- data[me.getName()] = val;
- } else if (me.deleteEmpty) {
- data = {};
- data['delete'] = me.getName();
- }
- }
- return data;
- },
-
- initComponent: function() {
- var me = this;
-
- Ext.apply(me, {
- minValue: 1,
- maxValue: 4094
- });
-
- me.callParent();
- }
-});
-// boolean type including 'Default' (delete property from file)
-Ext.define('PVE.form.Boolean', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.booleanfield'],
- comboItems: [
- ['__default__', gettext('Default')],
- [1, gettext('Yes')],
- [0, gettext('No')]
- ]
-});
-Ext.define('PVE.form.CompressionSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveCompressionSelector'],
- comboItems: [
- ['0', Proxmox.Utils.noneText],
- ['lzo', 'LZO (' + gettext('fast') + ')'],
- ['gzip', 'GZIP (' + gettext('good') + ')']
- ]
-});
-Ext.define('PVE.form.PoolSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pvePoolSelector'],
-
- allowBlank: false,
- valueField: 'poolid',
- displayField: 'poolid',
-
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-pools',
- sorters: 'poolid'
- });
-
- Ext.apply(me, {
- store: store,
- autoSelect: false,
- listConfig: {
- columns: [
- {
- header: gettext('Pool'),
- sortable: true,
- dataIndex: 'poolid',
- flex: 1
- },
- {
- header: gettext('Comment'),
- sortable: false,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
-
- store.load();
- }
-
-}, function() {
-
- Ext.define('pve-pools', {
- extend: 'Ext.data.Model',
- fields: [ 'poolid', 'comment' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/pools"
- },
- idProperty: 'poolid'
- });
-
-});
-Ext.define('PVE.form.PrivilegesSelector', {
- extend: 'Proxmox.form.KVComboBox',
- xtype: 'pvePrivilegesSelector',
-
- multiSelect: true,
-
- initComponent: function() {
- var me = this;
-
- // So me.store is available.
- me.callParent();
-
- Proxmox.Utils.API2Request({
- url: '/access/roles/Administrator',
- method: 'GET',
- success: function(response, options) {
- var data = [], key;
- /*jslint forin: true */
- for (key in response.result.data) {
- data.push([key, key]);
- }
- /*jslint forin: false */
-
- me.store.setData(data);
-
- me.store.sort({
- property: 'key',
- direction: 'ASC'
- });
- },
-
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
-});
-Ext.define('pve-groups', {
- extend: 'Ext.data.Model',
- fields: [ 'groupid', 'comment' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/groups"
- },
- idProperty: 'groupid'
-});
-
-Ext.define('PVE.form.GroupSelector', {
- extend: 'Proxmox.form.ComboGrid',
- xtype: 'pveGroupSelector',
-
- allowBlank: false,
- autoSelect: false,
- valueField: 'groupid',
- displayField: 'groupid',
- listConfig: {
- columns: [
- {
- header: gettext('Group'),
- sortable: true,
- dataIndex: 'groupid',
- flex: 1
- },
- {
- header: gettext('Comment'),
- sortable: false,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- },
-
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-groups',
- sorters: [{
- property: 'groupid'
- }]
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- store.load();
- }
-});
-Ext.define('PVE.form.UserSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveUserSelector'],
-
- allowBlank: false,
- autoSelect: false,
- valueField: 'userid',
- displayField: 'userid',
-
- editable: true,
- anyMatch: true,
- forceSelection: true,
-
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-users',
- sorters: [{
- property: 'userid'
- }]
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: gettext('User'),
- sortable: true,
- dataIndex: 'userid',
- flex: 1
- },
- {
- header: gettext('Name'),
- sortable: true,
- renderer: PVE.Utils.render_full_name,
- dataIndex: 'firstname',
- flex: 1
- },
- {
- header: gettext('Comment'),
- sortable: false,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
-
- store.load({ params: { enabled: 1 }});
- }
-
-}, function() {
-
- Ext.define('pve-users', {
- extend: 'Ext.data.Model',
- fields: [
- 'userid', 'firstname', 'lastname' , 'email', 'comment',
- { type: 'boolean', name: 'enable' },
- { type: 'date', dateFormat: 'timestamp', name: 'expire' }
- ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/users"
- },
- idProperty: 'userid'
- });
-
-});
-
-
-Ext.define('PVE.form.RoleSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveRoleSelector'],
-
- allowBlank: false,
- autoSelect: false,
- valueField: 'roleid',
- displayField: 'roleid',
- initComponent: function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-roles',
- sorters: [{
- property: 'roleid'
- }]
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: gettext('Role'),
- sortable: true,
- dataIndex: 'roleid',
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
-
- store.load();
- }
-
-}, function() {
-
- Ext.define('pve-roles', {
- extend: 'Ext.data.Model',
- fields: [ 'roleid', 'privs' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/roles"
- },
- idProperty: 'roleid'
- });
-
-});
-Ext.define('PVE.form.GuestIDSelector', {
- extend: 'Ext.form.field.Number',
- alias: 'widget.pveGuestIDSelector',
-
- allowBlank: false,
-
- minValue: 100,
-
- maxValue: 999999999,
-
- validateExists: undefined,
-
- loadNextFreeID: false,
-
- guestType: undefined,
-
- validator: function(value) {
- var me = this;
-
- if (!Ext.isNumeric(value) ||
- value < me.minValue ||
- value > me.maxValue) {
- // check is done by ExtJS
- return true;
- }
-
- if (me.validateExists === true && !me.exists) {
- return me.unknownID;
- }
-
- if (me.validateExists === false && me.exists) {
- return me.inUseID;
- }
-
- return true;
- },
-
- initComponent: function() {
- var me = this;
- var label = '{0} ID';
- var unknownID = gettext('This {0} ID does not exists');
- var inUseID = gettext('This {0} ID is already in use');
- var type = 'CT/VM';
-
- if (me.guestType === 'lxc') {
- type = 'CT';
- } else if (me.guestType === 'qemu') {
- type = 'VM';
- }
-
- me.label = Ext.String.format(label, type);
- me.unknownID = Ext.String.format(unknownID, type);
- me.inUseID = Ext.String.format(inUseID, type);
-
- Ext.apply(me, {
- fieldLabel: me.label,
- listeners: {
- 'change': function(field, newValue, oldValue) {
- if (!Ext.isDefined(me.validateExists)) {
- return;
- }
- Proxmox.Utils.API2Request({
- params: { vmid: newValue },
- url: '/cluster/nextid',
- method: 'GET',
- success: function(response, opts) {
- me.exists = false;
- me.validate();
- },
- failure: function(response, opts) {
- me.exists = true;
- me.validate();
- }
- });
- }
- }
- });
-
- me.callParent();
-
- if (me.loadNextFreeID) {
- Proxmox.Utils.API2Request({
- url: '/cluster/nextid',
- method: 'GET',
- success: function(response, opts) {
- me.setRawValue(response.result.data);
- }
- });
- }
- }
-});
-Ext.define('PVE.form.MemoryField', {
- extend: 'Ext.form.field.Number',
- alias: 'widget.pveMemoryField',
-
- allowBlank: false,
-
- hotplug: false,
-
- minValue: 32,
-
- maxValue: 4178944,
-
- step: 32,
-
- value: '512', // qm default
-
- allowDecimals: false,
-
- allowExponential: false,
-
- computeUpDown: function(value) {
- var me = this;
-
- if (!me.hotplug) {
- return { up: value + me.step, down: value - me.step };
- }
-
- var dimm_size = 512;
- var prev_dimm_size = 0;
- var min_size = 1024;
- var current_size = min_size;
- var value_up = min_size;
- var value_down = min_size;
- var value_start = min_size;
-
- var i, j;
- for (j = 0; j < 9; j++) {
- for (i = 0; i < 32; i++) {
- if ((value >= current_size) && (value < (current_size + dimm_size))) {
- value_start = current_size;
- value_up = current_size + dimm_size;
- value_down = current_size - ((i === 0) ? prev_dimm_size : dimm_size);
- }
- current_size += dimm_size;
- }
- prev_dimm_size = dimm_size;
- dimm_size = dimm_size*2;
- }
-
- return { up: value_up, down: value_down, start: value_start };
- },
-
- onSpinUp: function() {
- var me = this;
- if (!me.readOnly) {
- var res = me.computeUpDown(me.getValue());
- me.setValue(Ext.Number.constrain(res.up, me.minValue, me.maxValue));
- }
- },
-
- onSpinDown: function() {
- var me = this;
- if (!me.readOnly) {
- var res = me.computeUpDown(me.getValue());
- me.setValue(Ext.Number.constrain(res.down, me.minValue, me.maxValue));
- }
- },
-
- initComponent: function() {
- var me = this;
-
- if (me.hotplug) {
- me.minValue = 1024;
-
- me.on('blur', function(field) {
- var value = me.getValue();
- var res = me.computeUpDown(value);
- if (value === res.start || value === res.up || value === res.down) {
- return;
- }
- field.setValue(res.up);
- });
- }
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.NetworkCardSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: 'widget.pveNetworkCardSelector',
- comboItems: [
- ['e1000', 'Intel E1000'],
- ['virtio', 'VirtIO (' + gettext('paravirtualized') + ')'],
- ['rtl8139', 'Realtek RTL8139'],
- ['vmxnet3', 'VMware vmxnet3']
- ]
-});
-Ext.define('PVE.form.DiskFormatSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: 'widget.pveDiskFormatSelector',
- comboItems: [
- ['raw', gettext('Raw disk image') + ' (raw)'],
- ['qcow2', gettext('QEMU image format') + ' (qcow2)'],
- ['vmdk', gettext('VMware image format') + ' (vmdk)']
- ]
-});
-Ext.define('PVE.form.DiskSelector', {
- extend: 'Proxmox.form.ComboGrid',
- xtype: 'pveDiskSelector',
-
- // can be
- // undefined: all
- // unused: only unused
- // journal_disk: all disks with gpt
- diskType: undefined,
-
- valueField: 'devpath',
- displayField: 'devpath',
- emptyText: gettext('No Disks unused'),
- listConfig: {
- width: 600,
- columns: [
- {
- header: gettext('Device'),
- flex: 3,
- sortable: true,
- dataIndex: 'devpath'
- },
- {
- header: gettext('Size'),
- flex: 2,
- sortable: false,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- },
- {
- header: gettext('Serial'),
- flex: 5,
- sortable: true,
- dataIndex: 'serial'
- }
- ]
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var store = Ext.create('Ext.data.Store', {
- filterOnLoad: true,
- model: 'pve-disk-list',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/disks/list",
- extraParams: { type: me.diskType }
- },
- sorters: [
- {
- property : 'devpath',
- direction: 'ASC'
- }
- ]
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- store.load();
- }
-}, function() {
-
- Ext.define('pve-disk-list', {
- extend: 'Ext.data.Model',
- fields: [ 'devpath', 'used', { name: 'size', type: 'number'},
- {name: 'osdid', type: 'number'},
- 'vendor', 'model', 'serial'],
- idProperty: 'devpath'
- });
-});
-Ext.define('PVE.form.BusTypeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: 'widget.pveBusSelector',
-
- noVirtIO: false,
-
- initComponent: function() {
- var me = this;
-
- me.comboItems = [['ide', 'IDE'], ['sata', 'SATA']];
-
- if (!me.noVirtIO) {
- me.comboItems.push(['virtio', 'VirtIO Block']);
- }
-
- me.comboItems.push(['scsi', 'SCSI']);
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.ControllerSelector', {
- extend: 'Ext.form.FieldContainer',
- alias: 'widget.pveControllerSelector',
-
- statics: {
- maxIds: {
- ide: 3,
- sata: 5,
- virtio: 15,
- scsi: 13
- }
- },
-
- noVirtIO: false,
-
- vmconfig: {}, // used to check for existing devices
-
- sortByPreviousUsage: function(vmconfig, controllerList) {
-
- var usedControllers = Ext.clone(PVE.form.ControllerSelector.maxIds);
-
- var type;
- for (type in usedControllers) {
- if(usedControllers.hasOwnProperty(type)) {
- usedControllers[type] = 0;
- }
- }
-
- var property;
- for (property in vmconfig) {
- if (vmconfig.hasOwnProperty(property)) {
- if (property.match(PVE.Utils.bus_match) && !vmconfig[property].match(/media=cdrom/)) {
- var foundController = property.match(PVE.Utils.bus_match)[1];
- usedControllers[foundController]++;
- }
- }
- }
-
- var vmDefaults = PVE.qemu.OSDefaults[vmconfig.ostype];
-
- var sortPriority = vmDefaults && vmDefaults.busPriority
- ? vmDefaults.busPriority : PVE.qemu.OSDefaults.generic;
-
- var sortedList = Ext.clone(controllerList);
- sortedList.sort(function(a,b) {
- if (usedControllers[b] == usedControllers[a]) {
- return sortPriority[b] - sortPriority[a];
- }
- return usedControllers[b] - usedControllers[a];
- });
-
- return sortedList;
- },
-
- setVMConfig: function(vmconfig, autoSelect) {
- var me = this;
-
- me.vmconfig = Ext.apply({}, vmconfig);
-
- var clist = ['ide', 'virtio', 'scsi', 'sata'];
- var bussel = me.down('field[name=controller]');
- var deviceid = me.down('field[name=deviceid]');
-
- if (autoSelect === 'cdrom') {
- clist = ['ide', 'scsi', 'sata'];
- if (!Ext.isDefined(me.vmconfig.ide2)) {
- bussel.setValue('ide');
- deviceid.setValue(2);
- return;
- }
- } else {
- // in most cases we want to add a disk to the same controller
- // we previously used
- clist = me.sortByPreviousUsage(me.vmconfig, clist);
- }
-
- Ext.Array.each(clist, function(controller) {
- var confid, i;
- bussel.setValue(controller);
- for (i = 0; i <= PVE.form.ControllerSelector.maxIds[controller]; i++) {
- confid = controller + i.toString();
- if (!Ext.isDefined(me.vmconfig[confid])) {
- deviceid.setValue(i);
- return false; // break
- }
- }
- });
- deviceid.validate();
- },
-
- initComponent: function() {
- var me = this;
-
- Ext.apply(me, {
- fieldLabel: gettext('Bus/Device'),
- layout: 'hbox',
- defaults: {
- hideLabel: true
- },
- items: [
- {
- xtype: 'pveBusSelector',
- name: 'controller',
- value: PVE.qemu.OSDefaults.generic.busType,
- noVirtIO: me.noVirtIO,
- allowBlank: false,
- flex: 2,
- listeners: {
- change: function(t, value) {
- if (!value) {
- return;
- }
- var field = me.down('field[name=deviceid]');
- field.setMaxValue(PVE.form.ControllerSelector.maxIds[value]);
- field.validate();
- }
- }
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'deviceid',
- minValue: 0,
- maxValue: PVE.form.ControllerSelector.maxIds.ide,
- value: '0',
- flex: 1,
- allowBlank: false,
- validator: function(value) {
- /*jslint confusion: true */
- if (!me.rendered) {
- return;
- }
- var field = me.down('field[name=controller]');
- var controller = field.getValue();
- var confid = controller + value;
- if (Ext.isDefined(me.vmconfig[confid])) {
- return "This device is already in use.";
- }
- return true;
- }
- }
- ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.EmailNotificationSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveEmailNotificationSelector'],
- comboItems: [
- ['always', gettext('Always')],
- ['failure', gettext('On failure only')]
- ]
-});
-/*global Proxmox*/
-Ext.define('PVE.form.RealmComboBox', {
- extend: 'Ext.form.field.ComboBox',
- alias: ['widget.pveRealmComboBox'],
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.store.on('load', this.onLoad, view);
- },
-
- onLoad: function(store, records, success) {
- if (!success) {
- return;
- }
- var me = this;
- var val = me.getValue();
- if (!val || !me.store.findRecord('realm', val)) {
- var def = 'pam';
- Ext.each(records, function(rec) {
- if (rec.data && rec.data['default']) {
- def = rec.data.realm;
- }
- });
- me.setValue(def);
- }
- }
- },
-
- fieldLabel: gettext('Realm'),
- name: 'realm',
- queryMode: 'local',
- allowBlank: false,
- editable: false,
- forceSelection: true,
- autoSelect: false,
- triggerAction: 'all',
- valueField: 'realm',
- displayField: 'descr',
- getState: function() {
- return { value: this.getValue() };
- },
- applyState : function(state) {
- if (state && state.value) {
- this.setValue(state.value);
- }
- },
- stateEvents: [ 'select' ],
- stateful: true, // last chosen auth realm is saved between page reloads
- id: 'pveloginrealm', // We need stable ids when using stateful, not autogenerated
- stateID: 'pveloginrealm',
-
- needOTP: function(realm) {
- var me = this;
- // use exact match
- var rec = me.store.findRecord('realm', realm, 0, false, false, true);
- return rec && rec.data && rec.data.tfa ? rec.data.tfa : undefined;
- },
-
- store: {
- model: 'pve-domains',
- autoLoad: true
- }
-});
-/*
- * Top left combobox, used to select a view of the underneath RessourceTree
- */
-Ext.define('PVE.form.ViewSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: ['widget.pveViewSelector'],
-
- editable: false,
- allowBlank: false,
- forceSelection: true,
- autoSelect: false,
- valueField: 'key',
- displayField: 'value',
- hideLabel: true,
- queryMode: 'local',
-
- initComponent: function() {
- var me = this;
-
- var default_views = {
- server: {
- text: gettext('Server View'),
- groups: ['node']
- },
- folder: {
- text: gettext('Folder View'),
- groups: ['type']
- },
- storage: {
- text: gettext('Storage View'),
- groups: ['node'],
- filterfn: function(node) {
- return node.data.type === 'storage' || node.data.type === 'node';
- }
- },
- pool: {
- text: gettext('Pool View'),
- groups: ['pool'],
- // Pool View only lists VMs and Containers
- filterfn: function(node) {
- return node.data.type === 'qemu' || node.data.type === 'lxc' || node.data.type === 'openvz' ||
- node.data.type === 'pool';
- }
- }
- };
-
- var groupdef = [];
- Ext.Object.each(default_views, function(viewname, value) {
- groupdef.push([viewname, value.text]);
- });
-
- var store = Ext.create('Ext.data.Store', {
- model: 'KeyValue',
- proxy: {
- type: 'memory',
- reader: 'array'
- },
- data: groupdef,
- autoload: true
- });
-
- Ext.apply(me, {
- store: store,
- value: groupdef[0][0],
- getViewFilter: function() {
- var view = me.getValue();
- return Ext.apply({ id: view }, default_views[view] || default_views.server);
- },
-
- getState: function() {
- return { value: me.getValue() };
- },
-
- applyState : function(state, doSelect) {
- var view = me.getValue();
- if (state && state.value && (view != state.value)) {
- var record = store.findRecord('key', state.value);
- if (record) {
- me.setValue(state.value, true);
- if (doSelect) {
- me.fireEvent('select', me, [record]);
- }
- }
- }
- },
- stateEvents: [ 'select' ],
- stateful: true,
- stateId: 'pveview',
- id: 'view'
- });
-
- me.callParent();
-
- var statechange = function(sp, key, value) {
- if (key === me.id) {
- me.applyState(value, true);
- }
- };
-
- var sp = Ext.state.Manager.getProvider();
- me.mon(sp, 'statechange', statechange, me);
- }
-});
-Ext.define('PVE.form.NodeSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveNodeSelector'],
-
- // invalidate nodes which are offline
- onlineValidator: false,
-
- selectCurNode: false,
-
- // do not allow those nodes (array)
- disallowedNodes: undefined,
-
- // only allow those nodes (array)
- allowedNodes: undefined,
- // set default value to empty array, else it inits it with
- // null and after the store load it is an empty array,
- // triggering dirtychange
- value: [],
- valueField: 'node',
- displayField: 'node',
- store: {
- fields: [ 'node', 'cpu', 'maxcpu', 'mem', 'maxmem', 'uptime' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes'
- },
- sorters: [
- {
- property : 'node',
- direction: 'ASC'
- },
- {
- property : 'mem',
- direction: 'DESC'
- }
- ]
- },
-
- listConfig: {
- columns: [
- {
- header: gettext('Node'),
- dataIndex: 'node',
- sortable: true,
- hideable: false,
- flex: 1
- },
- {
- header: gettext('Memory usage') + " %",
- renderer: PVE.Utils.render_mem_usage_percent,
- sortable: true,
- width: 100,
- dataIndex: 'mem'
- },
- {
- header: gettext('CPU usage'),
- renderer: PVE.Utils.render_cpu,
- sortable: true,
- width: 100,
- dataIndex: 'cpu'
- }
- ]
- },
-
- validator: function(value) {
- /*jslint confusion: true */
- var me = this;
- if (!me.onlineValidator || (me.allowBlank && !value)) {
- return true;
- }
-
- var offline = [];
- var notAllowed = [];
-
- Ext.Array.each(value.split(/\s*,\s*/), function(node) {
- var rec = me.store.findRecord(me.valueField, node);
- if (!(rec && rec.data) || rec.data.status !== 'online') {
- offline.push(node);
- } else if (me.allowedNodes && !Ext.Array.contains(me.allowedNodes, node)) {
- notAllowed.push(node);
- }
- });
-
- if (value && notAllowed.length !== 0) {
- return "Node " + notAllowed.join(', ') + " is not allowed for this action!";
- }
-
- if (value && offline.length !== 0) {
- return "Node " + offline.join(', ') + " seems to be offline!";
- }
- return true;
- },
-
- initComponent: function() {
- var me = this;
-
- if (me.selectCurNode && PVE.curSelectedNode && PVE.curSelectedNode.data.node) {
- me.preferredValue = PVE.curSelectedNode.data.node;
- }
-
- me.callParent();
- me.getStore().load();
-
- // filter out disallowed nodes
- me.getStore().addFilter(new Ext.util.Filter({
- filterFn: function(item) {
- if (Ext.isArray(me.disallowedNodes)) {
- return !Ext.Array.contains(me.disallowedNodes, item.data.node);
- } else {
- return true;
- }
- }
- }));
-
- me.mon(me.getStore(), 'load', function(){
- me.isValid();
- });
- }
-});
-Ext.define('PVE.form.FileSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.pveFileSelector',
-
- editable: true,
- anyMatch: true,
- forceSelection: true,
-
- listeners: {
- afterrender: function() {
- var me = this;
- if (!me.disabled) {
- me.setStorage(me.storage, me.nodename);
- }
- }
- },
-
- setStorage: function(storage, nodename) {
- var me = this;
-
- var change = false;
- if (storage && (me.storage !== storage)) {
- me.storage = storage;
- change = true;
- }
-
- if (nodename && (me.nodename !== nodename)) {
- me.nodename = nodename;
- change = true;
- }
-
- if (!(me.storage && me.nodename && change)) {
- return;
- }
-
- var url = '/api2/json/nodes/' + me.nodename + '/storage/' + me.storage + '/content';
- if (me.storageContent) {
- url += '?content=' + me.storageContent;
- }
-
- me.store.setProxy({
- type: 'proxmox',
- url: url
- });
-
- me.store.removeAll();
- me.store.load();
- },
-
- setNodename: function(nodename) {
- this.setStorage(undefined, nodename);
- },
-
- store: {
- model: 'pve-storage-content'
- },
-
- allowBlank: false,
- autoSelect: false,
- valueField: 'volid',
- displayField: 'text',
-
- listConfig: {
- width: 600,
- columns: [
- {
- header: gettext('Name'),
- dataIndex: 'text',
- hideable: false,
- flex: 1
- },
- {
- header: gettext('Format'),
- width: 60,
- dataIndex: 'format'
- },
- {
- header: gettext('Size'),
- width: 100,
- dataIndex: 'size',
- renderer: Proxmox.Utils.format_size
- }
- ]
- }
-});
-Ext.define('PVE.form.StorageSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.pveStorageSelector',
-
- allowBlank: false,
- valueField: 'storage',
- displayField: 'storage',
- listConfig: {
- width: 450,
- columns: [
- {
- header: gettext('Name'),
- dataIndex: 'storage',
- hideable: false,
- flex: 1
- },
- {
- header: gettext('Type'),
- width: 75,
- dataIndex: 'type'
- },
- {
- header: gettext('Avail'),
- width: 90,
- dataIndex: 'avail',
- renderer: Proxmox.Utils.format_size
- },
- {
- header: gettext('Capacity'),
- width: 90,
- dataIndex: 'total',
- renderer: Proxmox.Utils.format_size
- }
- ]
- },
-
- reloadStorageList: function() {
- var me = this;
- if (!me.nodename) {
- return;
- }
-
- var params = {
- format: 1
- };
- var url = '/api2/json/nodes/' + me.nodename + '/storage';
- if (me.storageContent) {
- params.content = me.storageContent;
- }
- if (me.targetNode) {
- params.target = me.targetNode;
- params.enabled = 1; // skip disabled storages
- }
- me.store.setProxy({
- type: 'proxmox',
- url: url,
- extraParams: params
- });
-
- me.store.load();
-
- },
-
- setTargetNode: function(targetNode) {
- var me = this;
-
- if (!targetNode || (me.targetNode === targetNode)) {
- return;
- }
-
- me.targetNode = targetNode;
-
- me.reloadStorageList();
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
-
- me.reloadStorageList();
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- me.nodename = undefined;
-
- var store = Ext.create('Ext.data.Store', {
- model: 'pve-storage-status',
- sorters: {
- property: 'storage',
- order: 'DESC'
- }
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- if (nodename) {
- me.setNodename(nodename);
- }
- }
-}, function() {
-
- Ext.define('pve-storage-status', {
- extend: 'Ext.data.Model',
- fields: [ 'storage', 'active', 'type', 'avail', 'total' ],
- idProperty: 'storage'
- });
-
-});
-Ext.define('PVE.form.DiskStorageSelector', {
- extend: 'Ext.container.Container',
- alias: 'widget.pveDiskStorageSelector',
-
- layout: 'fit',
- defaults: {
- margin: '0 0 5 0'
- },
-
- // the fieldLabel for the storageselector
- storageLabel: gettext('Storage'),
-
- // the content to show (e.g., images or rootdir)
- storageContent: undefined,
-
- // if true, selects the first available storage
- autoSelect: false,
-
- allowBlank: false,
- emptyText: '',
-
- // hides the selection field
- // this is always hidden on creation,
- // and only shown when the storage needs a selection and
- // hideSelection is not true
- hideSelection: undefined,
-
- // hides the size field (e.g, for the efi disk dialog)
- hideSize: false,
-
- // sets the initial size value
- // string because else we get a type confusion
- defaultSize: '32',
-
- changeStorage: function(f, value) {
- var me = this;
- var formatsel = me.getComponent('diskformat');
- var hdfilesel = me.getComponent('hdimage');
- var hdsizesel = me.getComponent('disksize');
-
- // initial store load, and reset/deletion of the storage
- if (!value) {
- hdfilesel.setDisabled(true);
- hdfilesel.setVisible(false);
-
- formatsel.setDisabled(true);
- return;
- }
-
- var rec = f.store.getById(value);
- // if the storage is not defined, or valid,
- // we cannot know what to enable/disable
- if (!rec) {
- return;
- }
-
- var selectformat = false;
- if (rec.data.format) {
- var format = rec.data.format[0]; // 0 is the formats, 1 the default in the backend
- delete format.subvol; // we never need subvol in the gui
- selectformat = (Ext.Object.getSize(format) > 1);
- }
-
- var select = !!rec.data.select_existing && !me.hideSelection;
-
- formatsel.setDisabled(!selectformat);
- formatsel.setValue(selectformat ? 'qcow2' : 'raw');
-
- hdfilesel.setDisabled(!select);
- hdfilesel.setVisible(select);
- if (select) {
- hdfilesel.setStorage(value);
- }
-
- hdsizesel.setDisabled(select || me.hideSize);
- hdsizesel.setVisible(!select && !me.hideSize);
- },
-
- setNodename: function(nodename) {
- var me = this;
- var hdstorage = me.getComponent('hdstorage');
- var hdfilesel = me.getComponent('hdimage');
-
- hdstorage.setNodename(nodename);
- hdfilesel.setNodename(nodename);
- },
-
- setDisabled: function(value) {
- var me = this;
- var hdstorage = me.getComponent('hdstorage');
-
- // reset on disable
- if (value) {
- hdstorage.setValue();
- }
- hdstorage.setDisabled(value);
-
- // disabling does not always fire this event and we do not need
- // the value of the validity
- hdstorage.fireEvent('validitychange');
- },
-
- initComponent: function() {
- var me = this;
-
- me.items = [
- {
- xtype: 'pveStorageSelector',
- itemId: 'hdstorage',
- name: 'hdstorage',
- reference: 'hdstorage',
- fieldLabel: me.storageLabel,
- nodename: me.nodename,
- storageContent: me.storageContent,
- disabled: me.disabled,
- autoSelect: me.autoSelect,
- allowBlank: me.allowBlank,
- emptyText: me.emptyText,
- listeners: {
- change: {
- fn: me.changeStorage,
- scope: me
- }
- }
- },
- {
- xtype: 'pveFileSelector',
- name: 'hdimage',
- reference: 'hdimage',
- itemId: 'hdimage',
- fieldLabel: gettext('Disk image'),
- nodename: me.nodename,
- disabled: true,
- hidden: true
- },
- {
- xtype: 'numberfield',
- itemId: 'disksize',
- reference: 'disksize',
- name: 'disksize',
- fieldLabel: gettext('Disk size') + ' (GiB)',
- hidden: me.hideSize,
- disabled: me.hideSize,
- minValue: 0.001,
- maxValue: 128*1024,
- decimalPrecision: 3,
- value: me.defaultSize,
- allowBlank: false
- },
- {
- xtype: 'pveDiskFormatSelector',
- itemId: 'diskformat',
- reference: 'diskformat',
- name: 'diskformat',
- fieldLabel: gettext('Format'),
- nodename: me.nodename,
- disabled: true,
- hidden: me.storageContent === 'rootdir',
- value: 'qcow2',
- allowBlank: false
- }
- ];
-
- // use it to disable the children but not ourself
- me.disabled = false;
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.BridgeSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.PVE.form.BridgeSelector'],
-
- bridgeType: 'any_bridge', // bridge, OVSBridge or any_bridge
-
- store: {
- fields: [ 'iface', 'active', 'type' ],
- filterOnLoad: true,
- sorters: [
- {
- property : 'iface',
- direction: 'ASC'
- }
- ]
- },
- valueField: 'iface',
- displayField: 'iface',
- listConfig: {
- columns: [
- {
- header: gettext('Bridge'),
- dataIndex: 'iface',
- hideable: false,
- width: 100
- },
- {
- header: gettext('Active'),
- width: 60,
- dataIndex: 'active',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comments',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
-
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/network?type=' +
- me.bridgeType
- });
-
- me.store.load();
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- me.nodename = undefined;
-
- me.callParent();
-
- me.setNodename(nodename);
- }
-});
-
-Ext.define('PVE.form.PCISelector', {
- extend: 'Proxmox.form.ComboGrid',
- xtype: 'pvePCISelector',
-
- store: {
- fields: [ 'id','vendor_name', 'device_name', 'vendor', 'device', 'iommugroup', 'mdev' ],
- filterOnLoad: true,
- sorters: [
- {
- property : 'id',
- direction: 'ASC'
- }
- ]
- },
-
- autoSelect: false,
- valueField: 'id',
- displayField: 'id',
-
- // can contain a load callback for the store
- // useful to determine the state of the IOMMU
- onLoadCallBack: undefined,
-
- listConfig: {
- width: 800,
- columns: [
- {
- header: 'ID',
- dataIndex: 'id',
- width: 80
- },
- {
- header: gettext('IOMMU Group'),
- dataIndex: 'iommugroup',
- width: 50
- },
- {
- header: gettext('Vendor'),
- dataIndex: 'vendor_name',
- flex: 2
- },
- {
- header: gettext('Device'),
- dataIndex: 'device_name',
- flex: 6
- },
- {
- header: gettext('Mediated Devices'),
- dataIndex: 'mdev',
- flex: 1,
- renderer: function(val) {
- return Proxmox.Utils.format_boolean(!!val);
- }
- }
- ]
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
-
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/hardware/pci'
- });
-
- me.store.load();
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- me.nodename = undefined;
-
- me.callParent();
-
- if (me.onLoadCallBack !== undefined) {
- me.mon(me.getStore(), 'load', me.onLoadCallBack);
- }
-
- me.setNodename(nodename);
- }
-});
-
-Ext.define('PVE.form.MDevSelector', {
- extend: 'Proxmox.form.ComboGrid',
- xtype: 'pveMDevSelector',
-
- store: {
- fields: [ 'type','available', 'description' ],
- filterOnLoad: true,
- sorters: [
- {
- property : 'type',
- direction: 'ASC'
- }
- ]
- },
- autoSelect: false,
- valueField: 'type',
- displayField: 'type',
- listConfig: {
- columns: [
- {
- header: gettext('Type'),
- dataIndex: 'type',
- flex: 1
- },
- {
- header: gettext('Available'),
- dataIndex: 'available',
- width: 80
- },
- {
- header: gettext('Description'),
- dataIndex: 'description',
- flex: 1,
- renderer: function(value) {
- if (!value) {
- return '';
- }
-
- return value.split('\n').join(' ');
- }
- }
- ]
- },
-
- setPciID: function(pciid, force) {
- var me = this;
-
- if (!force && (!pciid || (me.pciid === pciid))) {
- return;
- }
-
- me.pciid = pciid;
- me.updateProxy();
- },
-
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
- me.updateProxy();
- },
-
- updateProxy: function() {
- var me = this;
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/hardware/pci/' + me.pciid + '/mdev'
- });
- me.store.load();
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw 'no node name specified';
- }
-
- me.callParent();
-
- if (me.pciid) {
- me.setPciID(me.pciid, true);
- }
- }
-});
-
-Ext.define('PVE.form.SecurityGroupsSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveSecurityGroupsSelector'],
-
- valueField: 'group',
- displayField: 'group',
- initComponent: function() {
- var me = this;
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: true,
- fields: [ 'group', 'comment' ],
- idProperty: 'group',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/firewall/groups"
- },
- sorters: {
- property: 'group',
- order: 'DESC'
- }
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: gettext('Security Group'),
- dataIndex: 'group',
- hideable: false,
- width: 100
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.form.IPRefSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveIPRefSelector'],
-
- base_url: undefined,
-
- preferredValue: '', // hack: else Form sets dirty flag?
-
- ref_type: undefined, // undefined = any [undefined, 'ipset' or 'alias']
-
- valueField: 'ref',
- displayField: 'ref',
-
- initComponent: function() {
- var me = this;
-
- if (!me.base_url) {
- throw "no base_url specified";
- }
-
- var url = "/api2/json" + me.base_url;
- if (me.ref_type) {
- url += "?type=" + me.ref_type;
- }
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: true,
- fields: [ 'type', 'name', 'ref', 'comment' ],
- idProperty: 'ref',
- proxy: {
- type: 'proxmox',
- url: url
- },
- sorters: {
- property: 'ref',
- order: 'DESC'
- }
- });
-
- var disable_query_for_ips = function(f, value) {
- if (value === null ||
- value.match(/^\d/)) { // IP address starts with \d
- f.queryDelay = 9999999999; // hack: disable with long delay
- } else {
- f.queryDelay = 10;
- }
- };
-
- var columns = [];
-
- if (!me.ref_type) {
- columns.push({
- header: gettext('Type'),
- dataIndex: 'type',
- hideable: false,
- width: 60
- });
- }
-
- columns.push(
- {
- header: gettext('Name'),
- dataIndex: 'ref',
- hideable: false,
- width: 140
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- );
-
- Ext.apply(me, {
- store: store,
- listConfig: { columns: columns }
- });
-
- me.on('change', disable_query_for_ips);
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.form.IPProtocolSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveIPProtocolSelector'],
- valueField: 'p',
- displayField: 'p',
- listConfig: {
- columns: [
- {
- header: gettext('Protocol'),
- dataIndex: 'p',
- hideable: false,
- sortable: false,
- width: 100
- },
- {
- header: gettext('Number'),
- dataIndex: 'n',
- hideable: false,
- sortable: false,
- width: 50
- },
- {
- header: gettext('Description'),
- dataIndex: 'd',
- hideable: false,
- sortable: false,
- flex: 1
- }
- ]
- },
- store: {
- fields: [ 'p', 'd', 'n'],
- data: [
- { p: 'tcp', n: 6, d: 'Transmission Control Protocol' },
- { p: 'udp', n: 17, d: 'User Datagram Protocol' },
- { p: 'icmp', n: 1, d: 'Internet Control Message Protocol' },
- { p: 'igmp', n: 2, d: 'Internet Group Management' },
- { p: 'ggp', n: 3, d: 'gateway-gateway protocol' },
- { p: 'ipencap', n: 4, d: 'IP encapsulated in IP' },
- { p: 'st', n: 5, d: 'ST datagram mode' },
- { p: 'egp', n: 8, d: 'exterior gateway protocol' },
- { p: 'igp', n: 9, d: 'any private interior gateway (Cisco)' },
- { p: 'pup', n: 12, d: 'PARC universal packet protocol' },
- { p: 'hmp', n: 20, d: 'host monitoring protocol' },
- { p: 'xns-idp', n: 22, d: 'Xerox NS IDP' },
- { p: 'rdp', n: 27, d: '"reliable datagram" protocol' },
- { p: 'iso-tp4', n: 29, d: 'ISO Transport Protocol class 4 [RFC905]' },
- { p: 'dccp', n: 33, d: 'Datagram Congestion Control Prot. [RFC4340]' },
- { p: 'xtp', n: 36, d: 'Xpress Transfer Protocol' },
- { p: 'ddp', n: 37, d: 'Datagram Delivery Protocol' },
- { p: 'idpr-cmtp', n: 38, d: 'IDPR Control Message Transport' },
- { p: 'ipv6', n: 41, d: 'Internet Protocol, version 6' },
- { p: 'ipv6-route', n: 43, d: 'Routing Header for IPv6' },
- { p: 'ipv6-frag', n: 44, d: 'Fragment Header for IPv6' },
- { p: 'idrp', n: 45, d: 'Inter-Domain Routing Protocol' },
- { p: 'rsvp', n: 46, d: 'Reservation Protocol' },
- { p: 'gre', n: 47, d: 'General Routing Encapsulation' },
- { p: 'esp', n: 50, d: 'Encap Security Payload [RFC2406]' },
- { p: 'ah', n: 51, d: 'Authentication Header [RFC2402]' },
- { p: 'skip', n: 57, d: 'SKIP' },
- { p: 'ipv6-icmp', n: 58, d: 'ICMP for IPv6' },
- { p: 'ipv6-nonxt', n: 59, d: 'No Next Header for IPv6' },
- { p: 'ipv6-opts', n: 60, d: 'Destination Options for IPv6' },
- { p: 'vmtp', n: 81, d: 'Versatile Message Transport' },
- { p: 'eigrp', n: 88, d: 'Enhanced Interior Routing Protocol (Cisco)' },
- { p: 'ospf', n: 89, d: 'Open Shortest Path First IGP' },
- { p: 'ax.25', n: 93, d: 'AX.25 frames' },
- { p: 'ipip', n: 94, d: 'IP-within-IP Encapsulation Protocol' },
- { p: 'etherip', n: 97, d: 'Ethernet-within-IP Encapsulation [RFC3378]' },
- { p: 'encap', n: 98, d: 'Yet Another IP encapsulation [RFC1241]' },
- { p: 'pim', n: 103, d: 'Protocol Independent Multicast' },
- { p: 'ipcomp', n: 108, d: 'IP Payload Compression Protocol' },
- { p: 'vrrp', n: 112, d: 'Virtual Router Redundancy Protocol [RFC5798]' },
- { p: 'l2tp', n: 115, d: 'Layer Two Tunneling Protocol [RFC2661]' },
- { p: 'isis', n: 124, d: 'IS-IS over IPv4' },
- { p: 'sctp', n: 132, d: 'Stream Control Transmission Protocol' },
- { p: 'fc', n: 133, d: 'Fibre Channel' },
- { p: 'mobility-header', n: 135, d: 'Mobility Support for IPv6 [RFC3775]' },
- { p: 'udplite', n: 136, d: 'UDP-Lite [RFC3828]' },
- { p: 'mpls-in-ip', n: 137, d: 'MPLS-in-IP [RFC4023]' },
- { p: 'hip', n: 139, d: 'Host Identity Protocol' },
- { p: 'shim6', n: 140, d: 'Shim6 Protocol [RFC5533]' },
- { p: 'wesp', n: 141, d: 'Wrapped Encapsulating Security Payload' },
- { p: 'rohc', n: 142, d: 'Robust Header Compression' }
- ]
- }
-});
-Ext.define('PVE.form.CPUModelSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.CPUModelSelector'],
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText + ' (kvm64)'],
- ['486', '486'],
- ['athlon', 'athlon'],
- ['core2duo', 'core2duo'],
- ['coreduo', 'coreduo'],
- ['kvm32', 'kvm32'],
- ['kvm64', 'kvm64'],
- ['pentium', 'pentium'],
- ['pentium2', 'pentium2'],
- ['pentium3', 'pentium3'],
- ['phenom', 'phenom'],
- ['qemu32', 'qemu32'],
- ['qemu64', 'qemu64'],
- ['Conroe', 'Conroe'],
- ['Penryn', 'Penryn'],
- ['Nehalem', 'Nehalem'],
- ['Westmere', 'Westmere'],
- ['SandyBridge', 'SandyBridge'],
- ['IvyBridge', 'IvyBridge'],
- ['Haswell', 'Haswell'],
- ['Haswell-noTSX','Haswell-noTSX'],
- ['Broadwell', 'Broadwell'],
- ['Broadwell-noTSX','Broadwell-noTSX'],
- ['Skylake-Client','Skylake-Client'],
- ['Opteron_G1', 'Opteron_G1'],
- ['Opteron_G2', 'Opteron_G2'],
- ['Opteron_G3', 'Opteron_G3'],
- ['Opteron_G4', 'Opteron_G4'],
- ['Opteron_G5', 'Opteron_G5'],
- ['EPYC', 'EPYC'],
- ['host', 'host']
-
- ]
-});
-Ext.define('PVE.form.VNCKeyboardSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.VNCKeyboardSelector'],
- comboItems: PVE.Utils.kvm_keymap_array()
-});
-Ext.define('PVE.form.CacheTypeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.CacheTypeSelector'],
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText + " (" + gettext('No cache') + ")"],
- ['directsync', 'Direct sync'],
- ['writethrough', 'Write through'],
- ['writeback', 'Write back'],
- ['unsafe', 'Write back (' + gettext('unsafe') + ')'],
- ['none', gettext('No cache')]
- ]
-});
-Ext.define('PVE.form.SnapshotSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.PVE.form.SnapshotSelector'],
-
- valueField: 'name',
- displayField: 'name',
-
- loadStore: function(nodename, vmid) {
- var me = this;
-
- if (!nodename) {
- return;
- }
-
- me.nodename = nodename;
-
- if (!vmid) {
- return;
- }
-
- me.vmid = vmid;
-
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/' + me.guestType + '/' + me.vmid +'/snapshot'
- });
-
- me.store.load();
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.guestType) {
- throw "no guest type specified";
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'name'],
- filterOnLoad: true
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: gettext('Snapshot'),
- dataIndex: 'name',
- hideable: false,
- flex: 1
- }
- ]
- }
- });
-
- me.callParent();
-
- me.loadStore(me.nodename, me.vmid);
- }
-});
-Ext.define('PVE.form.ContentTypeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveContentTypeSelector'],
-
- cts: undefined,
-
- initComponent: function() {
- var me = this;
-
- me.comboItems = [];
-
- if (me.cts === undefined) {
- me.cts = ['images', 'iso', 'vztmpl', 'backup', 'rootdir', 'snippets'];
- }
-
- Ext.Array.each(me.cts, function(ct) {
- me.comboItems.push([ct, PVE.Utils.format_content_types(ct)]);
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.HotplugFeatureSelector', {
- extend: 'Ext.form.CheckboxGroup',
- alias: 'widget.pveHotplugFeatureSelector',
-
- columns: 1,
- vertical: true,
-
- defaults: {
- name: 'hotplug',
- submitValue: false
- },
- items: [
- {
- boxLabel: gettext('Disk'),
- inputValue: 'disk',
- checked: true
- },
- {
- boxLabel: gettext('Network'),
- inputValue: 'network',
- checked: true
- },
- {
- boxLabel: 'USB',
- inputValue: 'usb',
- checked: true
- },
- {
- boxLabel: gettext('Memory'),
- inputValue: 'memory'
- },
- {
- boxLabel: gettext('CPU'),
- inputValue: 'cpu'
- }
- ],
-
- setValue: function(value) {
- var me = this;
- var newVal = [];
- if (value === '1') {
- newVal = ['disk', 'network', 'usb'];
- } else if (value !== '0') {
- newVal = value.split(',');
- }
- me.callParent([{ hotplug: newVal }]);
- },
-
- // override framework function to
- // assemble the hotplug value
- getSubmitData: function() {
- var me = this,
- boxes = me.getBoxes(),
- data = [];
- Ext.Array.forEach(boxes, function(box){
- if (box.getValue()) {
- data.push(box.inputValue);
- }
- });
-
- /* because above is hotplug an array */
- /*jslint confusion: true*/
- if (data.length === 0) {
- return { 'hotplug':'0' };
- } else {
- return { 'hotplug': data.join(',') };
- }
- }
-
-});
-Ext.define('PVE.form.AgentFeatureSelector', {
- extend: 'Proxmox.panel.InputPanel',
- alias: ['widget.pveAgentFeatureSelector'],
-
- initComponent: function() {
- var me = this;
- me.items= [
- {
- xtype: 'proxmoxcheckbox',
- boxLabel: gettext('Qemu Agent'),
- name: 'enabled',
- uncheckedValue: 0,
- listeners: {
- change: function(f, value, old) {
- var gtcb = me.down('proxmoxcheckbox[name=fstrim_cloned_disks]');
- if (value) {
- gtcb.setDisabled(false);
- } else {
- gtcb.setDisabled(true);
- }
- }
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- boxLabel: gettext('Run guest-trim after clone disk'),
- name: 'fstrim_cloned_disks',
- disabled: true
- }
- ];
- me.callParent();
- },
-
- onGetValues: function(values) {
- var agentstr = PVE.Parser.printPropertyString(values, 'enabled');
- return { agent: agentstr };
- },
-
- setValues: function(values) {
- var agent = values.agent || '';
- var res = PVE.Parser.parsePropertyString(agent, 'enabled');
- this.callParent([res]);
- }
-});
-Ext.define('PVE.form.iScsiProviderSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveiScsiProviderSelector'],
- comboItems: [
- ['comstar', 'Comstar'],
- [ 'istgt', 'istgt'],
- [ 'iet', 'IET'],
- [ 'LIO', 'LIO']
- ]
-});
-Ext.define('PVE.form.DayOfWeekSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveDayOfWeekSelector'],
- comboItems:[],
- initComponent: function(){
- var me = this;
- me.comboItems = [
- ['mon', Ext.util.Format.htmlDecode(Ext.Date.dayNames[1])],
- ['tue', Ext.util.Format.htmlDecode(Ext.Date.dayNames[2])],
- ['wed', Ext.util.Format.htmlDecode(Ext.Date.dayNames[3])],
- ['thu', Ext.util.Format.htmlDecode(Ext.Date.dayNames[4])],
- ['fri', Ext.util.Format.htmlDecode(Ext.Date.dayNames[5])],
- ['sat', Ext.util.Format.htmlDecode(Ext.Date.dayNames[6])],
- ['sun', Ext.util.Format.htmlDecode(Ext.Date.dayNames[0])]
- ];
- this.callParent();
- }
-});
-Ext.define('PVE.form.BackupModeSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveBackupModeSelector'],
- comboItems: [
- ['snapshot', gettext('Snapshot')],
- ['suspend', gettext('Suspend')],
- ['stop', gettext('Stop')]
- ]
-});
-Ext.define('PVE.form.ScsiHwSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveScsiHwSelector'],
- comboItems: [
- ['__default__', PVE.Utils.render_scsihw('')],
- ['lsi', PVE.Utils.render_scsihw('lsi')],
- ['lsi53c810', PVE.Utils.render_scsihw('lsi53c810')],
- ['megasas', PVE.Utils.render_scsihw('megasas')],
- ['virtio-scsi-pci', PVE.Utils.render_scsihw('virtio-scsi-pci')],
- ['virtio-scsi-single', PVE.Utils.render_scsihw('virtio-scsi-single')],
- ['pvscsi', PVE.Utils.render_scsihw('pvscsi')]
- ]
-});
-Ext.define('PVE.form.FirewallPolicySelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveFirewallPolicySelector'],
- comboItems: [
- ['ACCEPT', 'ACCEPT'],
- ['REJECT', 'REJECT'],
- [ 'DROP', 'DROP']
- ]
-});
-/*
- * This is a global search field
- * it loads the /cluster/resources on focus
- * and displays the result in a floating grid
- *
- * it filters and sorts the objects by the algorithm in
- * the customFilter function
- *
- * also it does accept key up/down and enter for input
- * and it opens to ctrl+shift+f and ctrl+space
- */
-Ext.define('PVE.form.GlobalSearchField', {
- extend: 'Ext.form.field.Text',
- alias: 'widget.pveGlobalSearchField',
-
- emptyText: gettext('Search'),
- enableKeyEvents: true,
- selectOnFocus: true,
- padding: '0 5 0 5',
-
- grid: {
- xtype: 'gridpanel',
- focusOnToFront: false,
- floating: true,
- emptyText: Proxmox.Utils.noneText,
- width: 600,
- height: 400,
- scrollable: {
- xtype: 'scroller',
- y: true,
- x:false
- },
- store: {
- model: 'PVEResources',
- proxy:{
- type: 'proxmox',
- url: '/api2/extjs/cluster/resources'
- }
- },
- plugins: {
- ptype: 'bufferedrenderer',
- trailingBufferZone: 20,
- leadingBufferZone: 20
- },
-
- hideMe: function() {
- var me = this;
- if (typeof me.ctxMenu !== 'undefined' && me.ctxMenu.isVisible()) {
- return;
- }
- me.hasFocus = false;
- if (!me.textfield.hasFocus) {
- me.hide();
- }
- },
-
- setFocus: function() {
- var me = this;
- me.hasFocus = true;
- },
-
- listeners: {
- rowclick: function(grid, record) {
- var me = this;
- me.textfield.selectAndHide(record.id);
- },
- itemcontextmenu: function(v, record, item, index, event) {
- var me = this;
- me.ctxMenu = PVE.Utils.createCmdMenu(v, record, item, index, event);
- },
- /* because of lint */
- focusleave: {
- fn: 'hideMe'
- },
- focusenter: 'setFocus'
- },
-
- columns: [
- {
- text: gettext('Type'),
- dataIndex: 'type',
- width: 100,
- renderer: PVE.Utils.render_resource_type
- },
- {
- text: gettext('Description'),
- flex: 1,
- dataIndex: 'text'
- },
- {
- text: gettext('Node'),
- dataIndex: 'node'
- },
- {
- text: gettext('Pool'),
- dataIndex: 'pool'
- }
- ]
- },
-
- customFilter: function(item) {
- var me = this;
- var match = 0;
- var fieldArr = [];
- var i,j, fields;
-
- // different types of objects have different fields to search
- // for example, a node will never have a pool and vice versa
- switch (item.data.type) {
- case 'pool': fieldArr = ['type', 'pool', 'text']; break;
- case 'node': fieldArr = ['type', 'node', 'text']; break;
- case 'storage': fieldArr = ['type', 'pool', 'node', 'storage']; break;
- default: fieldArr = ['name', 'type', 'node', 'pool', 'vmid'];
- }
- if (me.filterVal === '') {
- item.data.relevance = 0;
- return true;
- }
-
- // all text is case insensitive and each word is
- // searched alone
- // for every partial match, the row gets
- // 1 match point, for every exact match
- // it gets 2 points
- //
- // results gets sorted by points (descending)
- fields = me.filterVal.split(/\s+/);
- for(i = 0; i < fieldArr.length; i++) {
- var v = item.data[fieldArr[i]];
- if (v !== undefined) {
- v = v.toString().toLowerCase();
- for(j = 0; j < fields.length; j++) {
- if (v.indexOf(fields[j]) !== -1) {
- match++;
- if(v === fields[j]) {
- match++;
- }
- }
- }
- }
- }
- // give the row the 'relevance' value
- item.data.relevance = match;
- return (match > 0);
- },
-
- updateFilter: function(field, newValue, oldValue) {
- var me = this;
- // parse input and filter store,
- // show grid
- me.grid.store.filterVal = newValue.toLowerCase().trim();
- me.grid.store.clearFilter(true);
- me.grid.store.filterBy(me.customFilter);
- me.grid.getSelectionModel().select(0);
- },
-
- selectAndHide: function(id) {
- var me = this;
- me.tree.selectById(id);
- me.grid.hide();
- me.setValue('');
- me.blur();
- },
-
- onKey: function(field, e) {
- var me = this;
- var key = e.getKey();
-
- switch(key) {
- case Ext.event.Event.ENTER:
- // go to first entry if there is one
- if (me.grid.store.getCount() > 0) {
- me.selectAndHide(me.grid.getSelection()[0].data.id);
- }
- break;
- case Ext.event.Event.UP:
- me.grid.getSelectionModel().selectPrevious();
- break;
- case Ext.event.Event.DOWN:
- me.grid.getSelectionModel().selectNext();
- break;
- case Ext.event.Event.ESC:
- me.grid.hide();
- me.blur();
- break;
- }
- },
-
- loadValues: function(field) {
- var me = this;
- var records = [];
-
- me.hasFocus = true;
- me.grid.textfield = me;
- me.grid.store.load();
- me.grid.showBy(me, 'tl-bl');
- },
-
- hideGrid: function() {
- var me = this;
-
- me.hasFocus = false;
- if (!me.grid.hasFocus) {
- me.grid.hide();
- }
- },
-
- listeners: {
- change: {
- fn: 'updateFilter',
- buffer: 250
- },
- specialkey: 'onKey',
- focusenter: 'loadValues',
- focusleave: {
- fn: 'hideGrid',
- delay: 100
- }
- },
-
- toggleFocus: function() {
- var me = this;
- if (!me.hasFocus) {
- me.focus();
- } else {
- me.blur();
- }
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.tree) {
- throw "no tree given";
- }
-
- me.grid = Ext.create(me.grid);
-
- me.callParent();
-
- /*jslint confusion: true*/
- /*because shift is also a function*/
- // bind ctrl+shift+f and ctrl+space
- // to open/close the search
- me.keymap = new Ext.KeyMap({
- target: Ext.get(document),
- binding: [{
- key:'F',
- ctrl: true,
- shift: true,
- fn: me.toggleFocus,
- scope: me
- },{
- key:' ',
- ctrl: true,
- fn: me.toggleFocus,
- scope: me
- }]
- });
-
- // always select first item and
- // sort by relevance after load
- me.mon(me.grid.store, 'load', function() {
- me.grid.getSelectionModel().select(0);
- me.grid.store.sort({
- property: 'relevance',
- direction: 'DESC'
- });
- });
- }
-
-});
-Ext.define('PVE.form.QemuBiosSelector', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveQemuBiosSelector'],
-
- initComponent: function() {
- var me = this;
-
- me.comboItems = [
- ['__default__', PVE.Utils.render_qemu_bios('')],
- ['seabios', PVE.Utils.render_qemu_bios('seabios')],
- ['ovmf', PVE.Utils.render_qemu_bios('ovmf')]
- ];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-/* filter is a javascript builtin, but extjs calls it also filter */
-Ext.define('PVE.form.VMSelector', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.vmselector',
-
- mixins: {
- field: 'Ext.form.field.Field'
- },
-
- allowBlank: true,
- selectAll: false,
- isFormField: true,
-
- plugins: 'gridfilters',
-
- store: {
- model: 'PVEResources',
- autoLoad: true,
- sorters: 'vmid',
- filters: [{
- property: 'type',
- value: /lxc|qemu/
- }]
- },
- columns: [
- {
- header: 'ID',
- dataIndex: 'vmid',
- width: 80,
- filter: {
- type: 'number'
- }
- },
- {
- header: gettext('Node'),
- dataIndex: 'node'
- },
- {
- header: gettext('Status'),
- dataIndex: 'status',
- filter: {
- type: 'list'
- }
- },
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1,
- filter: {
- type: 'string'
- }
- },
- {
- header: gettext('Pool'),
- dataIndex: 'pool',
- filter: {
- type: 'list'
- }
- },
- {
- header: gettext('Type'),
- dataIndex: 'type',
- width: 120,
- renderer: function(value) {
- if (value === 'qemu') {
- return gettext('Virtual Machine');
- } else if (value === 'lxc') {
- return gettext('LXC Container');
- }
-
- return '';
- },
- filter: {
- type: 'list',
- store: {
- data: [
- {id: 'qemu', text: gettext('Virtual Machine')},
- {id: 'lxc', text: gettext('LXC Container')}
- ],
- // due to EXTJS-18711
- // we have to do a static list via a store
- // but to avoid creating an object,
- // we have to have a pseudo un function
- un: function(){}
- }
- }
- },
- {
- header: 'HA ' + gettext('Status'),
- dataIndex: 'hastate',
- flex: 1,
- filter: {
- type: 'list'
- }
- }
- ],
-
- selModel: {
- selType: 'checkboxmodel',
- mode: 'SIMPLE'
- },
-
- checkChangeEvents: [
- 'selectionchange',
- 'change'
- ],
-
- listeners: {
- selectionchange: function() {
- // to trigger validity and error checks
- this.checkChange();
- }
- },
-
- getValue: function() {
- var me = this;
- var sm = me.getSelectionModel();
- var selection = sm.getSelection();
- var values = [];
- var store = me.getStore();
- selection.forEach(function(item) {
- // only add if not filtered
- if (store.findExact('vmid', item.data.vmid) !== -1) {
- values.push(item.data.vmid);
- }
- });
- return values;
- },
-
- setValue: function(value) {
- console.log(value);
- var me = this;
- var sm = me.getSelectionModel();
- if (!Ext.isArray(value)) {
- value = value.split(',');
- }
- var selection = [];
- var store = me.getStore();
-
- value.forEach(function(item) {
- var rec = store.findRecord('vmid',item, 0, false, true, true);
- console.log(store);
-
- if (rec) {
- console.log(rec);
- selection.push(rec);
- }
- });
-
- sm.select(selection);
-
- return me.mixins.field.setValue.call(me, value);
- },
-
- getErrors: function(value) {
- var me = this;
- if (me.allowBlank === false &&
- me.getSelectionModel().getCount() === 0) {
- me.addBodyCls(['x-form-trigger-wrap-default','x-form-trigger-wrap-invalid']);
- return [gettext('No VM selected')];
- }
-
- me.removeBodyCls(['x-form-trigger-wrap-default','x-form-trigger-wrap-invalid']);
- return [];
- },
-
- initComponent: function() {
- var me = this;
-
- me.callParent();
-
- if (me.nodename) {
- me.store.filters.add({
- property: 'node',
- exactMatch: true,
- value: me.nodename
- });
- }
-
- // only show the relevant guests by default
- if (me.action) {
- var statusfilter = '';
- switch (me.action) {
- case 'startall':
- statusfilter = 'stopped';
- break;
- case 'stopall':
- statusfilter = 'running';
- break;
- }
- if (statusfilter !== '') {
- me.store.filters.add({
- property: 'template',
- value: 0
- },{
- id: 'x-gridfilter-status',
- operator: 'in',
- property: 'status',
- value: [statusfilter]
- });
- }
- }
-
- var store = me.getStore();
- var sm = me.getSelectionModel();
-
- if (me.selectAll) {
- me.mon(store,'load', function(){
- me.getSelectionModel().selectAll(false);
- });
- }
- }
-});
-
-
-Ext.define('PVE.form.VMComboSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.vmComboSelector',
-
- valueField: 'vmid',
- displayField: 'vmid',
-
- autoSelect: false,
- editable: true,
- anyMatch: true,
- forceSelection: true,
-
- store: {
- model: 'PVEResources',
- autoLoad: true,
- sorters: 'vmid',
- filters: [{
- property: 'type',
- value: /lxc|qemu/
- }]
- },
-
- listConfig: {
- width: 600,
- plugins: 'gridfilters',
- columns: [
- {
- header: 'ID',
- dataIndex: 'vmid',
- width: 80,
- filter: {
- type: 'number'
- }
- },
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1,
- filter: {
- type: 'string'
- }
- },
- {
- header: gettext('Node'),
- dataIndex: 'node'
- },
- {
- header: gettext('Status'),
- dataIndex: 'status',
- filter: {
- type: 'list'
- }
- },
- {
- header: gettext('Pool'),
- dataIndex: 'pool',
- hidden: true,
- filter: {
- type: 'list'
- }
- },
- {
- header: gettext('Type'),
- dataIndex: 'type',
- width: 120,
- renderer: function(value) {
- if (value === 'qemu') {
- return gettext('Virtual Machine');
- } else if (value === 'lxc') {
- return gettext('LXC Container');
- }
-
- return '';
- },
- filter: {
- type: 'list',
- store: {
- data: [
- {id: 'qemu', text: gettext('Virtual Machine')},
- {id: 'lxc', text: gettext('LXC Container')}
- ],
- un: function(){} // due to EXTJS-18711
- }
- }
- },
- {
- header: 'HA ' + gettext('Status'),
- dataIndex: 'hastate',
- hidden: true,
- flex: 1,
- filter: {
- type: 'list'
- }
- }
- ]
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.form.VMCPUFlagSelector', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.vmcpuflagselector',
-
- mixins: {
- field: 'Ext.form.field.Field'
- },
-
- disableSelection: true,
- columnLines: false,
- selectable: false,
- hideHeaders: true,
-
- scrollable: 'y',
- height: 200,
-
- unkownFlags: [],
-
- store: {
- type: 'store',
- fields: ['flag', { name: 'state', defaultValue: '=' }, 'desc'],
- data: [
- // FIXME: let qemu-server host this and autogenerate or get from API call??
- { flag: 'md-clear', desc: 'Required to let the guest OS know if MDS is mitigated correctly' },
- { flag: 'pcid', desc: 'Meltdown fix cost reduction on Westmere, Sandy-, and IvyBridge Intel CPUs' },
- { flag: 'spec-ctrl', desc: 'Allows improved Spectre mitigation with Intel CPUs' },
- { flag: 'ssbd', desc: 'Protection for "Speculative Store Bypass" for Intel models' },
- { flag: 'ibpb', desc: 'Allows improved Spectre mitigation with AMD CPUs' },
- { flag: 'virt-ssbd', desc: 'Basis for "Speculative Store Bypass" protection for AMD models' },
- { flag: 'amd-ssbd', desc: 'Improves Spectre mitigation performance with AMD CPUs, best used with "virt-ssbd"' },
- { flag: 'amd-no-ssb', desc: 'Notifies guest OS that host is not vulnerable for Spectre on AMD CPUs' },
- { flag: 'pdpe1gb', desc: 'Allow guest OS to use 1GB size pages, if host HW supports it' }
- ],
- listeners: {
- update: function() {
- this.commitChanges();
- }
- }
- },
-
- getValue: function() {
- var me = this;
- var store = me.getStore();
- var flags = '';
-
- // ExtJS does not has a nice getAllRecords interface for stores :/
- store.queryBy(Ext.returnTrue).each(function(rec) {
- var s = rec.get('state');
- if (s && s !== '=') {
- var f = rec.get('flag');
- if (flags === '') {
- flags = s + f;
- } else {
- flags += ';' + s + f;
- }
- }
- });
-
- flags += me.unkownFlags.join(';');
-
- return flags;
- },
-
- setValue: function(value) {
- var me = this;
- var store = me.getStore();
-
- me.value = value || '';
-
- me.unkownFlags = [];
-
- me.getStore().queryBy(Ext.returnTrue).each(function(rec) {
- rec.set('state', '=');
- });
-
- var flags = value ? value.split(';') : [];
- flags.forEach(function(flag) {
- var sign = flag.substr(0, 1);
- flag = flag.substr(1);
-
- var rec = store.findRecord('flag', flag);
- if (rec !== null) {
- rec.set('state', sign);
- } else {
- me.unkownFlags.push(flag);
- }
- });
- store.reload();
-
- var res = me.mixins.field.setValue.call(me, value);
-
- return res;
- },
- columns: [
- {
- dataIndex: 'state',
- renderer: function(v) {
- switch(v) {
- case '=': return 'Default';
- case '-': return 'Off';
- case '+': return 'On';
- default: return 'Unknown';
- }
- },
- width: 65
- },
- {
- xtype: 'widgetcolumn',
- dataIndex: 'state',
- width: 95,
- onWidgetAttach: function (column, widget, record) {
- var val = record.get('state') || '=';
- widget.down('[inputValue=' + val + ']').setValue(true);
- // TODO: disable if selected CPU model and flag are incompatible
- },
- widget: {
- xtype: 'radiogroup',
- hideLabel: true,
- layout: 'hbox',
- validateOnChange: false,
- value: '=',
- listeners: {
- change: function(f, value) {
- var v = Object.values(value)[0];
- f.getWidgetRecord().set('state', v);
-
- var view = this.up('grid');
- view.dirty = view.getValue() !== view.originalValue;
- view.checkDirty();
- //view.checkChange();
- }
- },
- items: [
- {
- boxLabel: '-',
- boxLabelAlign: 'before',
- inputValue: '-'
- },
- {
- checked: true,
- inputValue: '='
- },
- {
- boxLabel: '+',
- inputValue: '+'
- }
- ]
- }
- },
- {
- dataIndex: 'flag',
- width: 100
- },
- {
- dataIndex: 'desc',
- cellWrap: true,
- flex: 1
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- // static class store, thus gets not recreated, so ensure defaults are set!
- me.getStore().data.forEach(function(v) {
- v.state = '=';
- });
-
- me.value = me.originalValue = '';
-
- me.callParent(arguments);
- }
-});
-Ext.define('PVE.form.USBSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveUSBSelector'],
- allowBlank: false,
- autoSelect: false,
- displayField: 'usbid',
- valueField: 'usbid',
- editable: true,
-
- getUSBValue: function() {
- var me = this;
- var rec = me.store.findRecord('usbid', me.value);
- var val = 'host='+ me.value;
- if (rec && rec.data.speed === "5000") {
- val = 'host=' + me.value + ",usb3=1";
- }
- return val;
- },
-
- validator: function(value) {
- var me = this;
- if (me.type === 'device') {
- return (/^[a-f0-9]{4}\:[a-f0-9]{4}$/i).test(value);
- } else if (me.type === 'port') {
- return (/^[0-9]+\-[0-9]+(\.[0-9]+)*$/).test(value);
- }
- return false;
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
-
- if (!nodename) {
- throw "no nodename specified";
- }
-
- if (me.type !== 'device' && me.type !== 'port') {
- throw "no valid type specified";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-usb-' + me.type,
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/scan/usb"
- },
- filters: [
- function (item) {
- return !!item.data.usbpath && !!item.data.prodid && item.data['class'] != 9;
- }
- ]
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- columns: [
- {
- header: (me.type === 'device')?gettext('Device'):gettext('Port'),
- sortable: true,
- dataIndex: 'usbid',
- width: 80
- },
- {
- header: gettext('Manufacturer'),
- sortable: true,
- dataIndex: 'manufacturer',
- width: 100
- },
- {
- header: gettext('Product'),
- sortable: true,
- dataIndex: 'product',
- flex: 1
- },
- {
- header: gettext('Speed'),
- width: 70,
- sortable: true,
- dataIndex: 'speed',
- renderer: function(value) {
- if (value === "5000") {
- return "USB 3.0";
- } else if (value === "480") {
- return "USB 2.0";
- } else {
- return "USB 1.x";
- }
- }
- }
- ]
- }
- });
-
- me.callParent();
-
- store.load();
- }
-
-}, function() {
-
- Ext.define('pve-usb-device', {
- extend: 'Ext.data.Model',
- fields: [
- {
- name: 'usbid',
- convert: function(val, data) {
- if (val) {
- return val;
- }
- return data.get('vendid') + ':' + data.get('prodid');
- }
- },
- 'speed', 'product', 'manufacturer', 'vendid', 'prodid', 'usbpath',
- { name: 'port' , type: 'number' },
- { name: 'level' , type: 'number' },
- { name: 'class' , type: 'number' },
- { name: 'devnum' , type: 'number' },
- { name: 'busnum' , type: 'number' }
- ]
- });
-
- Ext.define('pve-usb-port', {
- extend: 'Ext.data.Model',
- fields: [
- {
- name: 'usbid',
- convert: function(val,data) {
- if (val) {
- return val;
- }
- return data.get('busnum') + '-' + data.get('usbpath');
- }
- },
- 'speed', 'product', 'manufacturer', 'vendid', 'prodid', 'usbpath',
- { name: 'port' , type: 'number' },
- { name: 'level' , type: 'number' },
- { name: 'class' , type: 'number' },
- { name: 'devnum' , type: 'number' },
- { name: 'busnum' , type: 'number' }
- ]
- });
-});
-Ext.define('PVE.form.CalendarEvent', {
- extend: 'Ext.form.field.ComboBox',
- xtype: 'pveCalendarEvent',
-
- editable: true,
-
- valueField: 'value',
- displayField: 'text',
- queryMode: 'local',
-
- store: {
- field: [ 'value', 'text'],
- data: [
- { value: '*/30', text: Ext.String.format(gettext("Every {0} minutes"), 30) },
- { value: '*/2:00', text: gettext("Every two hours")},
- { value: '2,22:30', text: gettext("Every day") + " 02:30, 22:30"},
- { value: 'mon..fri', text: gettext("Monday to Friday") + " 00:00"},
- { value: 'mon..fri */1:00', text: gettext("Monday to Friday") + ': ' + gettext("hourly")},
- { value: 'sun 01:00', text: gettext("Sunday") + " 01:00"}
- ]
- },
-
- tpl: [
- ''
- ],
-
- displayTpl: [
- '',
- '{value}',
- ' '
- ]
-
-});
-Ext.define('PVE.form.CephPoolSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveCephPoolSelector',
-
- allowBlank: false,
- valueField: 'pool_name',
- displayField: 'pool_name',
- editable: false,
- queryMode: 'local',
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: ['name'],
- sorters: 'name',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/ceph/pools'
- }
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- store.load({
- callback: function(rec, op, success){
- if (success && rec.length > 0) {
- me.select(rec[0]);
- }
- }
- });
- }
-
-});
-Ext.define('PVE.form.PermPathSelector', {
- extend: 'Ext.form.field.ComboBox',
- xtype: 'pvePermPathSelector',
-
- valueField: 'value',
- displayField: 'value',
- typeAhead: true,
- queryMode: 'local',
- store: {
- type: 'pvePermPath'
- }
-});
-/* This class defines the "Tasks" tab of the bottom status panel
- * Tasks are jobs with a start, end and log output
- */
-
-Ext.define('PVE.dc.Tasks', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveClusterTasks'],
-
- initComponent : function() {
- var me = this;
-
- var taskstore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'pve-cluster-tasks',
- model: 'proxmox-tasks',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/tasks'
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: taskstore,
- sortAfterUpdate: true,
- appendAtStart: true,
- sorters: [
- {
- property : 'pid',
- direction: 'DESC'
- },
- {
- property : 'starttime',
- direction: 'DESC'
- }
- ]
-
- });
-
- var run_task_viewer = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: rec.data.upid
- });
- win.show();
- };
-
- Ext.apply(me, {
- store: store,
- stateful: false,
-
- viewConfig: {
- trackOver: false,
- stripeRows: true, // does not work with getRowClass()
-
- getRowClass: function(record, index) {
- var status = record.get('status');
-
- if (status && status != 'OK') {
- return "proxmox-invalid-row";
- }
- }
- },
- sortableColumns: false,
- columns: [
- {
- header: gettext("Start Time"),
- dataIndex: 'starttime',
- width: 150,
- renderer: function(value) {
- return Ext.Date.format(value, "M d H:i:s");
- }
- },
- {
- header: gettext("End Time"),
- dataIndex: 'endtime',
- width: 150,
- renderer: function(value, metaData, record) {
- if (record.data.pid) {
- if (record.data.type == "vncproxy" ||
- record.data.type == "vncshell" ||
- record.data.type == "spiceproxy") {
- metaData.tdCls = "x-grid-row-console";
- } else {
- metaData.tdCls = "x-grid-row-loading";
- }
- return "";
- }
- return Ext.Date.format(value, "M d H:i:s");
- }
- },
- {
- header: gettext("Node"),
- dataIndex: 'node',
- width: 100
- },
- {
- header: gettext("User name"),
- dataIndex: 'user',
- width: 150
- },
- {
- header: gettext("Description"),
- dataIndex: 'upid',
- flex: 1,
- renderer: Proxmox.Utils.render_upid
- },
- {
- header: gettext("Status"),
- dataIndex: 'status',
- width: 200,
- renderer: function(value, metaData, record) {
- if (record.data.pid) {
- if (record.data.type != "vncproxy") {
- metaData.tdCls = "x-grid-row-loading";
- }
- return "";
- }
- if (value == 'OK') {
- return 'OK';
- }
- // metaData.attr = 'style="color:red;"';
- return Proxmox.Utils.errorText + ': ' + value;
- }
- }
- ],
- listeners: {
- itemdblclick: run_task_viewer,
- show: taskstore.startUpdate,
- destroy: taskstore.stopUpdate
- }
- });
-
- me.callParent();
- }
-});
-/* This class defines the "Cluster log" tab of the bottom status panel
- * A log entry is a timestamp associated with an action on a cluster
- */
-
-Ext.define('PVE.dc.Log', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveClusterLog'],
-
- initComponent : function() {
- var me = this;
-
- var logstore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'pve-cluster-log',
- model: 'proxmox-cluster-log',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/log'
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: logstore,
- appendAtStart: true
- });
-
- Ext.apply(me, {
- store: store,
- stateful: false,
-
- viewConfig: {
- trackOver: false,
- stripeRows: true,
-
- getRowClass: function(record, index) {
- var pri = record.get('pri');
-
- if (pri && pri <= 3) {
- return "proxmox-invalid-row";
- }
- }
- },
- sortableColumns: false,
- columns: [
- {
- header: gettext("Time"),
- dataIndex: 'time',
- width: 150,
- renderer: function(value) {
- return Ext.Date.format(value, "M d H:i:s");
- }
- },
- {
- header: gettext("Node"),
- dataIndex: 'node',
- width: 150
- },
- {
- header: gettext("Service"),
- dataIndex: 'tag',
- width: 100
- },
- {
- header: "PID",
- dataIndex: 'pid',
- width: 100
- },
- {
- header: gettext("User name"),
- dataIndex: 'user',
- width: 150
- },
- {
- header: gettext("Severity"),
- dataIndex: 'pri',
- renderer: PVE.Utils.render_serverity,
- width: 100
- },
- {
- header: gettext("Message"),
- dataIndex: 'msg',
- flex: 1
- }
- ],
- listeners: {
- activate: logstore.startUpdate,
- deactivate: logstore.stopUpdate,
- destroy: logstore.stopUpdate
- }
- });
-
- me.callParent();
- }
-});
-/*
- * This class describes the bottom panel
- */
-Ext.define('PVE.panel.StatusPanel', {
- extend: 'Ext.tab.Panel',
- alias: 'widget.pveStatusPanel',
-
-
- //title: "Logs",
- //tabPosition: 'bottom',
-
- initComponent: function() {
- var me = this;
-
- var stateid = 'ltab';
- var sp = Ext.state.Manager.getProvider();
-
- var state = sp.get(stateid);
- if (state && state.value) {
- me.activeTab = state.value;
- }
-
- Ext.apply(me, {
- listeners: {
- tabchange: function() {
- var atab = me.getActiveTab().itemId;
- var state = { value: atab };
- sp.set(stateid, state);
- }
- },
- items: [
- {
- itemId: 'tasks',
- title: gettext('Tasks'),
- xtype: 'pveClusterTasks'
- },
- {
- itemId: 'clog',
- title: gettext('Cluster log'),
- xtype: 'pveClusterLog'
- }
- ]
- });
-
- me.callParent();
-
- me.items.get(0).fireEvent('show', me.items.get(0));
-
- var statechange = function(sp, key, state) {
- if (key === stateid) {
- var atab = me.getActiveTab().itemId;
- var ntab = state.value;
- if (state && ntab && (atab != ntab)) {
- me.setActiveTab(ntab);
- }
- }
- };
-
- sp.on('statechange', statechange);
- me.on('destroy', function() {
- sp.un('statechange', statechange);
- });
-
- }
-});
-Ext.define('PVE.panel.StatusView', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveStatusView',
-
- layout: {
- type: 'column'
- },
-
- title: gettext('Status'),
-
- getRecordValue: function(key, store) {
- if (!key) {
- throw "no key given";
- }
- var me = this;
-
- if (store === undefined) {
- store = me.getStore();
- }
-
- var rec = store.getById(key);
- if (rec) {
- return rec.data.value;
- }
-
- return '';
- },
-
- fieldRenderer: function(val,max) {
- if (max === undefined) {
- return val;
- }
-
- if (!Ext.isNumeric(max) || max === 1) {
- return PVE.Utils.render_usage(val);
- }
- return PVE.Utils.render_size_usage(val,max);
- },
-
- fieldCalculator: function(used, max) {
- if (!Ext.isNumeric(max) && Ext.isNumeric(used)) {
- return used;
- } else if(!Ext.isNumeric(used)) {
- /* we come here if the field is from a node
- * where the records are not mem and maxmem
- * but mem.used and mem.total
- */
- if (used.used !== undefined &&
- used.total !== undefined) {
- return used.used/used.total;
- }
- }
-
- return used/max;
- },
-
- updateField: function(field) {
- var me = this;
- var text = '';
- var renderer = me.fieldRenderer;
- if (Ext.isFunction(field.renderer)) {
- renderer = field.renderer;
- }
- if (field.multiField === true) {
- field.updateValue(renderer.call(field, me.getStore().getRecord()));
- } else if (field.textField !== undefined) {
- field.updateValue(renderer.call(field, me.getRecordValue(field.textField)));
- } else if(field.valueField !== undefined) {
- var used = me.getRecordValue(field.valueField);
- /*jslint confusion: true*/
- /* string and int */
- var max = field.maxField !== undefined ? me.getRecordValue(field.maxField) : 1;
-
- var calculate = me.fieldCalculator;
-
- if (Ext.isFunction(field.calculate)) {
- calculate = field.calculate;
- }
- field.updateValue(renderer.call(field, used,max), calculate(used,max));
- }
- },
-
- getStore: function() {
- var me = this;
- if (!me.rstore) {
- throw "there is no rstore";
- }
-
- return me.rstore;
- },
-
- updateTitle: function() {
- var me = this;
- me.setTitle(me.getRecordValue('name'));
- },
-
- updateValues: function(store, records, success) {
- if (!success) {
- return; // do not update if store load was not successful
- }
- var me = this;
- var itemsToUpdate = me.query('pveInfoWidget');
-
- itemsToUpdate.forEach(me.updateField, me);
-
- me.updateTitle(store);
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.rstore) {
- throw "no rstore given";
- }
-
- if (!me.title) {
- throw "no title given";
- }
-
- Proxmox.Utils.monStoreErrors(me, me.rstore);
-
- me.callParent();
-
- me.mon(me.rstore, 'load', 'updateValues');
- }
-
-});
-Ext.define('PVE.panel.GuestStatusView', {
- extend: 'PVE.panel.StatusView',
- alias: 'widget.pveGuestStatusView',
- mixins: ['Proxmox.Mixin.CBind'],
-
- height: 300,
-
- cbindData: function (initialConfig) {
- var me = this;
- return {
- isQemu: me.pveSelNode.data.type === 'qemu',
- isLxc: me.pveSelNode.data.type === 'lxc'
- };
- },
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- defaults: {
- xtype: 'pveInfoWidget',
- padding: '2 25'
- },
- items: [
- {
- xtype: 'box',
- height: 20
- },
- {
- itemId: 'status',
- title: gettext('Status'),
- iconCls: 'fa fa-info fa-fw',
- printBar: false,
- multiField: true,
- renderer: function(record) {
- var me = this;
- var text = record.data.status;
- var qmpstatus = record.data.qmpstatus;
- if (qmpstatus && qmpstatus !== record.data.status) {
- text += ' (' + qmpstatus + ')';
- }
- return text;
- }
- },
- {
- itemId: 'hamanaged',
- iconCls: 'fa fa-heartbeat fa-fw',
- title: gettext('HA State'),
- printBar: false,
- textField: 'ha',
- renderer: PVE.Utils.format_ha
- },
- {
- xtype: 'pveInfoWidget',
- itemId: 'node',
- iconCls: 'fa fa-building fa-fw',
- title: gettext('Node'),
- cbind: {
- text: '{pveSelNode.data.node}'
- },
- printBar: false
- },
- {
- xtype: 'box',
- height: 15
- },
- {
- itemId: 'cpu',
- iconCls: 'fa fa-fw pve-itype-icon-processor pve-icon',
- title: gettext('CPU usage'),
- valueField: 'cpu',
- maxField: 'cpus',
- renderer: PVE.Utils.render_cpu_usage,
- // in this specific api call
- // we already have the correct value for the usage
- calculate: Ext.identityFn
- },
- {
- itemId: 'memory',
- iconCls: 'fa fa-fw pve-itype-icon-memory pve-icon',
- title: gettext('Memory usage'),
- valueField: 'mem',
- maxField: 'maxmem'
- },
- {
- itemId: 'swap',
- xtype: 'pveInfoWidget',
- iconCls: 'fa fa-refresh fa-fw',
- title: gettext('SWAP usage'),
- valueField: 'swap',
- maxField: 'maxswap',
- cbind: {
- hidden: '{isQemu}',
- disabled: '{isQemu}'
- }
- },
- {
- itemId: 'rootfs',
- iconCls: 'fa fa-hdd-o fa-fw',
- title: gettext('Bootdisk size'),
- valueField: 'disk',
- maxField: 'maxdisk',
- printBar: false,
- renderer: function(used, max) {
- var me = this;
- me.setPrintBar(used > 0);
- if (used === 0) {
- return PVE.Utils.render_size(max);
- } else {
- return PVE.Utils.render_size_usage(used,max);
- }
- }
- },
- {
- xtype: 'box',
- height: 15
- },
- {
- itemId: 'ips',
- xtype: 'pveAgentIPView',
- cbind: {
- rstore: '{rstore}',
- pveSelNode: '{pveSelNode}',
- hidden: '{isLxc}',
- disabled: '{isLxc}'
- }
- }
- ],
-
- updateTitle: function() {
- var me = this;
- var uptime = me.getRecordValue('uptime');
-
- var text = "";
- if (Number(uptime) > 0) {
- text = " (" + gettext('Uptime') + ': ' + Proxmox.Utils.format_duration_long(uptime)
- + ')';
- }
-
- me.setTitle(me.getRecordValue('name') + text);
- }
-});
-/*
- * This is a running chart widget
- * you add time datapoints to it,
- * and we only show the last x of it
- * used for ceph performance charts
- */
-Ext.define('PVE.widget.RunningChart', {
- extend: 'Ext.container.Container',
- alias: 'widget.pveRunningChart',
-
- layout: {
- type: 'hbox',
- align: 'center'
- },
- items: [
- {
- width: 80,
- xtype: 'box',
- itemId: 'title',
- data: {
- title: ''
- },
- tpl: '{title}: '
- },
- {
- flex: 1,
- xtype: 'cartesian',
- height: '100%',
- itemId: 'chart',
- border: false,
- axes: [
- {
- type: 'numeric',
- position: 'left',
- hidden: true,
- minimum: 0
- },
- {
- type: 'numeric',
- position: 'bottom',
- hidden: true
- }
- ],
-
- store: {
- data: {}
- },
-
- sprites: [{
- id: 'valueSprite',
- type: 'text',
- text: '0 B/s',
- textAlign: 'end',
- textBaseline: 'middle',
- fontSize: 14
- }],
-
- series: [{
- type: 'line',
- xField: 'time',
- yField: 'val',
- fill: 'true',
- colors: ['#cfcfcf'],
- tooltip: {
- trackMouse: true,
- renderer: function( tooltip, record, ctx) {
- var me = this.getChart();
- var date = new Date(record.data.time);
- var value = me.up().renderer(record.data.val);
- tooltip.setHtml(
- me.up().title + ': ' + value + ' ' +
- Ext.Date.format(date, 'H:i:s')
- );
- }
- },
- style: {
- lineWidth: 1.5,
- opacity: 0.60
- },
- marker: {
- opacity: 0,
- scaling: 0.01,
- fx: {
- duration: 200,
- easing: 'easeOut'
- }
- },
- highlightCfg: {
- opacity: 1,
- scaling: 1.5
- }
- }]
- }
- ],
-
- // the renderer for the tooltip and last value,
- // default just the value
- renderer: Ext.identityFn,
-
- // show the last x seconds
- // default is 5 minutes
- timeFrame: 5*60,
-
- addDataPoint: function(value, time) {
- var me = this.chart;
- var panel = me.up();
- var now = new Date();
- var begin = new Date(now.getTime() - (1000*panel.timeFrame));
-
- me.store.add({
- time: time || now.getTime(),
- val: value || 0
- });
-
- // delete all old records when we have 20 times more datapoints
- // than seconds in our timeframe (so even a subsecond graph does
- // not trigger this often)
- //
- // records in the store do not take much space, but like this,
- // we prevent a memory leak when someone has the site open for a long time
- // with minimal graphical glitches
- if (me.store.count() > panel.timeFrame * 20) {
- var oldData = me.store.getData().createFiltered(function(item) {
- return item.data.time < begin.getTime();
- });
-
- me.store.remove(oldData.getRange());
- }
-
- me.timeaxis.setMinimum(begin.getTime());
- me.timeaxis.setMaximum(now.getTime());
- me.valuesprite.setText(panel.renderer(value || 0).toString());
- me.valuesprite.setAttributes({
- x: me.getWidth() - 15,
- y: me.getHeight()/2
- }, true);
- me.redraw();
- },
-
- setTitle: function(title) {
- this.title = title;
- var me = this.getComponent('title');
- me.update({title: title});
- },
-
- initComponent: function(){
- var me = this;
- me.callParent();
-
- if (me.title) {
- me.getComponent('title').update({title: me.title});
- }
- me.chart = me.getComponent('chart');
- me.chart.timeaxis = me.chart.getAxes()[1];
- me.chart.valuesprite = me.chart.getSurface('chart').get('valueSprite');
- if (me.color) {
- me.chart.series[0].setStyle({
- fill: me.color,
- stroke: me.color
- });
- }
- }
-});
-Ext.define('PVE.widget.Info',{
- extend: 'Ext.container.Container',
- alias: 'widget.pveInfoWidget',
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- value: 0,
- maximum: 1,
- printBar: true,
- items: [
- {
- xtype: 'component',
- itemId: 'label',
- data: {
- title: '',
- usage: '',
- iconCls: undefined
- },
- tpl: [
- '',
- '',
- ' ',
- ' ',
- '{title}
{usage}
'
- ]
- },
- {
- height: 2,
- border: 0
- },
- {
- xtype: 'progressbar',
- itemId: 'progress',
- height: 5,
- value: 0,
- animate: true
- }
- ],
-
- warningThreshold: 0.6,
- criticalThreshold: 0.9,
-
- setPrintBar: function(enable) {
- var me = this;
- me.printBar = enable;
- me.getComponent('progress').setVisible(enable);
- },
-
- setIconCls: function(iconCls) {
- var me = this;
- me.getComponent('label').data.iconCls = iconCls;
- },
-
- updateValue: function(text, usage) {
- var me = this;
- var label = me.getComponent('label');
- label.update(Ext.apply(label.data, {title: me.title, usage:text}));
-
- if (usage !== undefined &&
- me.printBar &&
- Ext.isNumeric(usage) &&
- usage >= 0) {
- var progressBar = me.getComponent('progress');
- progressBar.updateProgress(usage, '');
- if (usage > me.criticalThreshold) {
- progressBar.removeCls('warning');
- progressBar.addCls('critical');
- } else if (usage > me.warningThreshold) {
- progressBar.removeCls('critical');
- progressBar.addCls('warning');
- } else {
- progressBar.removeCls('warning');
- progressBar.removeCls('critical');
- }
- }
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.title) {
- throw "no title defined";
- }
-
- me.callParent();
-
- me.getComponent('progress').setVisible(me.printBar);
-
- me.updateValue(me.text, me.value);
- me.setIconCls(me.iconCls);
- }
-
-});
-Ext.define('PVE.panel.TemplateStatusView',{
- extend: 'PVE.panel.StatusView',
- alias: 'widget.pveTemplateStatusView',
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- defaults: {
- xtype: 'pveInfoWidget',
- printBar: false,
- padding: '2 25'
- },
- items: [
- {
- xtype: 'box',
- height: 20
- },
- {
- itemId: 'hamanaged',
- iconCls: 'fa fa-heartbeat fa-fw',
- title: gettext('HA State'),
- printBar: false,
- textField: 'ha',
- renderer: PVE.Utils.format_ha
- },
- {
- itemId: 'node',
- iconCls: 'fa fa-fw fa-building',
- title: gettext('Node')
- },
- {
- xtype: 'box',
- height: 20
- },
- {
- itemId: 'cpus',
- iconCls: 'fa fa-fw pve-itype-icon-processor pve-icon',
- title: gettext('Processors'),
- textField: 'cpus'
- },
- {
- itemId: 'memory',
- iconCls: 'fa fa-fw pve-itype-icon-memory pve-icon',
- title: gettext('Memory'),
- textField: 'maxmem',
- renderer: PVE.Utils.render_size
- },
- {
- itemId: 'swap',
- iconCls: 'fa fa-refresh fa-fw',
- title: gettext('Swap'),
- textField: 'maxswap',
- renderer: PVE.Utils.render_size
- },
- {
- itemId: 'disk',
- iconCls: 'fa fa-hdd-o fa-fw',
- title: gettext('Bootdisk size'),
- textField: 'maxdisk',
- renderer: PVE.Utils.render_size
- },
- {
- xtype: 'box',
- height: 20
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- var name = me.pveSelNode.data.name;
- if (!name) {
- throw "no name specified";
- }
-
- me.title = name;
-
- me.callParent();
- if (me.pveSelNode.data.type !== 'lxc') {
- me.remove(me.getComponent('swap'));
- }
- me.getComponent('node').updateValue(me.pveSelNode.data.node);
- }
-});
-Ext.define('PVE.widget.HealthWidget', {
- extend: 'Ext.Component',
- alias: 'widget.pveHealthWidget',
-
- data: {
- iconCls: PVE.Utils.get_health_icon(undefined, true),
- text: '',
- title: ''
- },
-
- style: {
- 'text-align':'center'
- },
-
- tpl: [
- '{title} ',
- ' ',
- ' ',
- '{text}'
- ],
-
- updateHealth: function(data) {
- var me = this;
- me.update(Ext.apply(me.data, data));
- },
-
- initComponent: function(){
- var me = this;
-
- if (me.title) {
- me.config.data.title = me.title;
- }
-
- me.callParent();
- }
-
-});
-/*global u2f*/
-Ext.define('PVE.window.LoginWindow', {
- extend: 'Ext.window.Window',
-
- controller: {
-
- xclass: 'Ext.app.ViewController',
-
- onLogon: function() {
- var me = this;
-
- var form = this.lookupReference('loginForm');
- var unField = this.lookupReference('usernameField');
- var saveunField = this.lookupReference('saveunField');
- var view = this.getView();
-
- if (!form.isValid()) {
- return;
- }
-
- view.el.mask(gettext('Please wait...'), 'x-mask-loading');
-
- // set or clear username
- var sp = Ext.state.Manager.getProvider();
- if (saveunField.getValue() === true) {
- sp.set(unField.getStateId(), unField.getValue());
- } else {
- sp.clear(unField.getStateId());
- }
- sp.set(saveunField.getStateId(), saveunField.getValue());
-
- form.submit({
- failure: function(f, resp){
- me.failure(resp);
- },
- success: function(f, resp){
- view.el.unmask();
-
- var data = resp.result.data;
- if (Ext.isDefined(data.NeedTFA)) {
- // Store first factor login information first:
- data.LoggedOut = true;
- Proxmox.Utils.setAuthData(data);
-
- if (Ext.isDefined(data.U2FChallenge)) {
- me.perform_u2f(data);
- } else {
- me.perform_otp();
- }
- } else {
- me.success(data);
- }
- }
- });
-
- },
- failure: function(resp) {
- var me = this;
- var view = me.getView();
- view.el.unmask();
- var handler = function() {
- var uf = me.lookupReference('usernameField');
- uf.focus(true, true);
- };
-
- Ext.MessageBox.alert(gettext('Error'),
- gettext("Login failed. Please try again"),
- handler);
- },
- success: function(data) {
- var me = this;
- var view = me.getView();
- var handler = view.handler || Ext.emptyFn;
- handler.call(me, data);
- view.close();
- },
-
- perform_otp: function() {
- var me = this;
- var win = Ext.create('PVE.window.TFALoginWindow', {
- onLogin: function(value) {
- me.finish_tfa(value);
- },
- onCancel: function() {
- Proxmox.LoggedOut = false;
- Proxmox.Utils.authClear();
- me.getView().show();
- }
- });
- win.show();
- },
-
- perform_u2f: function(data) {
- var me = this;
- // Show the message:
- var msg = Ext.Msg.show({
- title: 'U2F: '+gettext('Verification'),
- message: gettext('Please press the button on your U2F Device'),
- buttons: []
- });
- var chlg = data.U2FChallenge;
- var key = {
- version: chlg.version,
- keyHandle: chlg.keyHandle
- };
- u2f.sign(chlg.appId, chlg.challenge, [key], function(res) {
- msg.close();
- if (res.errorCode) {
- Proxmox.Utils.authClear();
- Ext.Msg.alert(gettext('Error'), PVE.Utils.render_u2f_error(res.errorCode));
- return;
- }
- delete res.errorCode;
- me.finish_tfa(JSON.stringify(res));
- });
- },
- finish_tfa: function(res) {
- var me = this;
- var view = me.getView();
- view.el.mask(gettext('Please wait...'), 'x-mask-loading');
- var params = { response: res };
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'POST',
- timeout: 5000, // it'll delay both success & failure
- success: function(resp, opts) {
- view.el.unmask();
- // Fill in what we copy over from the 1st factor:
- var data = resp.result.data;
- data.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
- data.username = Proxmox.UserName;
- // Finish logging in:
- me.success(data);
- },
- failure: function(resp, opts) {
- Proxmox.Utils.authClear();
- me.failure(resp);
- }
- });
- },
-
- control: {
- 'field[name=username]': {
- specialkey: function(f, e) {
- if (e.getKey() === e.ENTER) {
- var pf = this.lookupReference('passwordField');
- if (!pf.getValue()) {
- pf.focus(false);
- }
- }
- }
- },
- 'field[name=lang]': {
- change: function(f, value) {
- var dt = Ext.Date.add(new Date(), Ext.Date.YEAR, 10);
- Ext.util.Cookies.set('PVELangCookie', value, dt);
- this.getView().mask(gettext('Please wait...'), 'x-mask-loading');
- window.location.reload();
- }
- },
- 'button[reference=loginButton]': {
- click: 'onLogon'
- },
- '#': {
- show: function() {
- var sp = Ext.state.Manager.getProvider();
- var checkboxField = this.lookupReference('saveunField');
- var unField = this.lookupReference('usernameField');
-
- var checked = sp.get(checkboxField.getStateId());
- checkboxField.setValue(checked);
-
- if(checked === true) {
- var username = sp.get(unField.getStateId());
- unField.setValue(username);
- var pwField = this.lookupReference('passwordField');
- pwField.focus();
- }
- }
- }
- }
- },
-
- width: 400,
-
- modal: true,
-
- border: false,
-
- draggable: true,
-
- closable: false,
-
- resizable: false,
-
- layout: 'auto',
-
- title: gettext('Proxmox VE Login'),
-
- defaultFocus: 'usernameField',
-
- defaultButton: 'loginButton',
-
- items: [{
- xtype: 'form',
- layout: 'form',
- url: '/api2/extjs/access/ticket',
- reference: 'loginForm',
-
- fieldDefaults: {
- labelAlign: 'right',
- allowBlank: false
- },
-
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('User name'),
- name: 'username',
- itemId: 'usernameField',
- reference: 'usernameField',
- stateId: 'login-username'
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- fieldLabel: gettext('Password'),
- name: 'password',
- reference: 'passwordField'
- },
- {
- xtype: 'pveRealmComboBox',
- name: 'realm'
- },
- {
- xtype: 'proxmoxLanguageSelector',
- fieldLabel: gettext('Language'),
- value: Ext.util.Cookies.get('PVELangCookie') || Proxmox.defaultLang || 'en',
- name: 'lang',
- reference: 'langField',
- submitValue: false
- }
- ],
- buttons: [
- {
- xtype: 'checkbox',
- fieldLabel: gettext('Save User name'),
- name: 'saveusername',
- reference: 'saveunField',
- stateId: 'login-saveusername',
- labelWidth: 'auto',
- labelAlign: 'right',
- submitValue: false
- },
- {
- text: gettext('Login'),
- reference: 'loginButton'
- }
- ]
- }]
- });
-Ext.define('PVE.window.TFALoginWindow', {
- extend: 'Ext.window.Window',
-
- modal: true,
- resizable: false,
- title: 'Two-Factor Authentication',
- layout: 'form',
- defaultButton: 'loginButton',
- defaultFocus: 'otpField',
-
- controller: {
- xclass: 'Ext.app.ViewController',
- login: function() {
- var me = this;
- var view = me.getView();
- view.onLogin(me.lookup('otpField').getValue());
- view.close();
- },
- cancel: function() {
- var me = this;
- var view = me.getView();
- view.onCancel();
- view.close();
- }
- },
-
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Please enter your OTP verification code:'),
- name: 'otp',
- itemId: 'otpField',
- reference: 'otpField',
- allowBlank: false
- }
- ],
-
- buttons: [
- {
- text: gettext('Login'),
- reference: 'loginButton',
- handler: 'login'
- },
- {
- text: gettext('Cancel'),
- handler: 'cancel'
- }
- ]
-});
-Ext.define('PVE.window.Wizard', {
- extend: 'Ext.window.Window',
-
- activeTitle: '', // used for automated testing
-
- width: 700,
- height: 510,
-
- modal: true,
- border: false,
-
- draggable: true,
- closable: true,
- resizable: false,
-
- layout: 'border',
-
- getValues: function(dirtyOnly) {
- var me = this;
-
- var values = {};
-
- var form = me.down('form').getForm();
-
- form.getFields().each(function(field) {
- if (!field.up('inputpanel') && (!dirtyOnly || field.isDirty())) {
- Proxmox.Utils.assemble_field_data(values, field.getSubmitData());
- }
- });
-
- Ext.Array.each(me.query('inputpanel'), function(panel) {
- Proxmox.Utils.assemble_field_data(values, panel.getValues(dirtyOnly));
- });
-
- return values;
- },
-
- initComponent: function() {
- var me = this;
-
- var tabs = me.items || [];
- delete me.items;
-
- /*
- * Items may have the following functions:
- * validator(): per tab custom validation
- * onSubmit(): submit handler
- * onGetValues(): overwrite getValues results
- */
-
- Ext.Array.each(tabs, function(tab) {
- tab.disabled = true;
- });
- tabs[0].disabled = false;
-
- var maxidx = 0;
- var curidx = 0;
-
- var check_card = function(card) {
- var valid = true;
- var fields = card.query('field, fieldcontainer');
- if (card.isXType('fieldcontainer')) {
- fields.unshift(card);
- }
- Ext.Array.each(fields, function(field) {
- // Note: not all fielcontainer have isValid()
- if (Ext.isFunction(field.isValid) && !field.isValid()) {
- valid = false;
- }
- });
-
- if (Ext.isFunction(card.validator)) {
- return card.validator();
- }
-
- return valid;
- };
-
- var disable_at = function(card) {
- var tp = me.down('#wizcontent');
- var idx = tp.items.indexOf(card);
- for(;idx < tp.items.getCount();idx++) {
- var nc = tp.items.getAt(idx);
- if (nc) {
- nc.disable();
- }
- }
- };
-
- var tabchange = function(tp, newcard, oldcard) {
- if (newcard.onSubmit) {
- me.down('#next').setVisible(false);
- me.down('#submit').setVisible(true);
- } else {
- me.down('#next').setVisible(true);
- me.down('#submit').setVisible(false);
- }
- var valid = check_card(newcard);
- me.down('#next').setDisabled(!valid);
- me.down('#submit').setDisabled(!valid);
- me.down('#back').setDisabled(tp.items.indexOf(newcard) == 0);
-
- var idx = tp.items.indexOf(newcard);
- if (idx > maxidx) {
- maxidx = idx;
- }
- curidx = idx;
-
- var next = idx + 1;
- var ntab = tp.items.getAt(next);
- if (valid && ntab && !newcard.onSubmit) {
- ntab.enable();
- }
- };
-
- if (me.subject && !me.title) {
- me.title = Proxmox.Utils.dialog_title(me.subject, true, false);
- }
-
- var sp = Ext.state.Manager.getProvider();
- var advchecked = sp.get('proxmox-advanced-cb');
-
- Ext.apply(me, {
- items: [
- {
- xtype: 'form',
- region: 'center',
- layout: 'fit',
- border: false,
- margins: '5 5 0 5',
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [{
- itemId: 'wizcontent',
- xtype: 'tabpanel',
- activeItem: 0,
- bodyPadding: 10,
- listeners: {
- afterrender: function(tp) {
- var atab = this.getActiveTab();
- tabchange(tp, atab);
- },
- tabchange: function(tp, newcard, oldcard) {
- tabchange(tp, newcard, oldcard);
- }
- },
- items: tabs
- }]
- }
- ],
- fbar: [
- {
- xtype: 'proxmoxHelpButton',
- itemId: 'help'
- },
- '->',
- {
- xtype: 'proxmoxcheckbox',
- boxLabelAlign: 'before',
- boxLabel: gettext('Advanced'),
- value: advchecked,
- listeners: {
- change: function(cb, val) {
- var tp = me.down('#wizcontent');
- tp.query('inputpanel').forEach(function(ip) {
- ip.setAdvancedVisible(val);
- });
-
- sp.set('proxmox-advanced-cb', val);
- }
- }
- },
- {
- text: gettext('Back'),
- disabled: true,
- itemId: 'back',
- minWidth: 60,
- handler: function() {
- var tp = me.down('#wizcontent');
- var atab = tp.getActiveTab();
- var prev = tp.items.indexOf(atab) - 1;
- if (prev < 0) {
- return;
- }
- var ntab = tp.items.getAt(prev);
- if (ntab) {
- tp.setActiveTab(ntab);
- }
- }
- },
- {
- text: gettext('Next'),
- disabled: true,
- itemId: 'next',
- minWidth: 60,
- handler: function() {
-
- var form = me.down('form').getForm();
-
- var tp = me.down('#wizcontent');
- var atab = tp.getActiveTab();
- if (!check_card(atab)) {
- return;
- }
-
- var next = tp.items.indexOf(atab) + 1;
- var ntab = tp.items.getAt(next);
- if (ntab) {
- ntab.enable();
- tp.setActiveTab(ntab);
- }
-
- }
- },
- {
- text: gettext('Finish'),
- minWidth: 60,
- hidden: true,
- itemId: 'submit',
- handler: function() {
- var tp = me.down('#wizcontent');
- var atab = tp.getActiveTab();
- atab.onSubmit();
- }
- }
- ]
- });
- me.callParent();
-
- Ext.Array.each(me.query('inputpanel'), function(panel) {
- panel.setAdvancedVisible(advchecked);
- });
-
- Ext.Array.each(me.query('field'), function(field) {
- var validcheck = function() {
- var tp = me.down('#wizcontent');
-
- // check tabs from current to the last enabled for validity
- // since we might have changed a validity on a later one
- var i;
- for (i = curidx; i <= maxidx && i < tp.items.getCount(); i++) {
- var tab = tp.items.getAt(i);
- var valid = check_card(tab);
-
- // only set the buttons on the current panel
- if (i === curidx) {
- me.down('#next').setDisabled(!valid);
- me.down('#submit').setDisabled(!valid);
- }
-
- // if a panel is invalid, then disable it and all following,
- // else enable it and go to the next
- var ntab = tp.items.getAt(i + 1);
- if (!valid) {
- disable_at(ntab);
- return;
- } else if (ntab && !tab.onSubmit) {
- ntab.enable();
- }
- }
- };
- field.on('change', validcheck);
- field.on('validitychange', validcheck);
- });
- }
-});
-Ext.define('PVE.window.NotesEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.apply(me, {
- title: gettext('Notes'),
- width: 600,
- height: '400px',
- resizable: true,
- layout: 'fit',
- defaultButton: undefined,
- items: {
- xtype: 'textarea',
- name: 'description',
- height: '100%',
- value: '',
- hideLabel: true
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('PVE.window.Backup', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.vmtype) {
- throw "no VM type specified";
- }
-
- var storagesel = Ext.create('PVE.form.StorageSelector', {
- nodename: me.nodename,
- name: 'storage',
- value: me.storage,
- fieldLabel: gettext('Storage'),
- storageContent: 'backup',
- allowBlank: false
- });
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [
- storagesel,
- {
- xtype: 'pveBackupModeSelector',
- fieldLabel: gettext('Mode'),
- value: 'snapshot',
- name: 'mode'
- },
- {
- xtype: 'pveCompressionSelector',
- name: 'compress',
- value: 'lzo',
- fieldLabel: gettext('Compression')
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Send email to'),
- name: 'mailto',
- emptyText: Proxmox.Utils.noneText
- }
- ]
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn = Ext.create('Ext.Button', {
- text: gettext('Backup'),
- handler: function(){
- var storage = storagesel.getValue();
- var values = form.getValues();
- var params = {
- storage: storage,
- vmid: me.vmid,
- mode: values.mode,
- remove: 0
- };
-
- if ( values.mailto ) {
- params.mailto = values.mailto;
- }
-
- if (values.compress) {
- params.compress = values.compress;
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/vzdump',
- params: params,
- method: 'POST',
- failure: function (response, opts) {
- Ext.Msg.alert('Error',response.htmlStatus);
- },
- success: function(response, options) {
- // close later so we reload the grid
- // after the task has completed
- me.hide();
-
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid,
- listeners: {
- close: function() {
- me.close();
- }
- }
- });
- win.show();
- }
- });
- }
- });
-
- var helpBtn = Ext.create('Proxmox.button.Help', {
- onlineHelp: 'chapter_vzdump',
- listenToGlobalEvent: false,
- hidden: false
- });
-
- var title = gettext('Backup') + " " +
- ((me.vmtype === 'lxc') ? "CT" : "VM") +
- " " + me.vmid;
-
- Ext.apply(me, {
- title: title,
- width: 350,
- modal: true,
- layout: 'auto',
- border: false,
- items: [ me.formPanel ],
- buttons: [ helpBtn, '->', submitBtn ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.window.Restore', {
- extend: 'Ext.window.Window', // fixme: Proxmox.window.Edit?
-
- resizable: false,
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.volid) {
- throw "no volume ID specified";
- }
-
- if (!me.vmtype) {
- throw "no vmtype specified";
- }
-
- var storagesel = Ext.create('PVE.form.StorageSelector', {
- nodename: me.nodename,
- name: 'storage',
- value: '',
- fieldLabel: gettext('Storage'),
- storageContent: (me.vmtype === 'lxc') ? 'rootdir' : 'images',
- allowBlank: true
- });
-
- var IDfield;
- if (me.vmid) {
- IDfield = Ext.create('Ext.form.field.Display', {
- name: 'vmid',
- value: me.vmid,
- fieldLabel: (me.vmtype === 'lxc') ? 'CT' : 'VM'
- });
- } else {
- IDfield = Ext.create('PVE.form.GuestIDSelector', {
- name: 'vmid',
- guestType: me.vmtype,
- loadNextFreeID: true,
- validateExists: false
- });
- }
-
- var items = [
- {
- xtype: 'displayfield',
- value: me.volidText || me.volid,
- fieldLabel: gettext('Source')
- },
- storagesel,
- IDfield,
- {
- xtype: 'proxmoxintegerfield',
- name: 'bwlimit',
- fieldLabel: gettext('Read Limit (MiB/s)'),
- minValue: 0,
- emptyText: gettext('Defaults to target storage restore limit'),
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext("Use '0' to disable all bandwidth limits.")
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'unique',
- fieldLabel: gettext('Unique'),
- hidden: !!me.vmid,
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext('Autogenerate unique properties, e.g., MAC addresses')
- },
- checked: false
- }
- ];
-
- /*jslint confusion: true*/
- if (me.vmtype === 'lxc') {
- items.push({
- xtype: 'proxmoxcheckbox',
- name: 'unprivileged',
- value: true,
- fieldLabel: gettext('Unprivileged container')
- });
- }
- /*jslint confusion: false*/
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var doRestore = function(url, params) {
- Proxmox.Utils.API2Request({
- url: url,
- params: params,
- method: 'POST',
- waitMsgTarget: me,
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- me.close();
- }
- });
- };
-
- var submitBtn = Ext.create('Ext.Button', {
- text: gettext('Restore'),
- handler: function(){
- var storage = storagesel.getValue();
- var values = form.getValues();
-
- var params = {
- storage: storage,
- vmid: me.vmid || values.vmid,
- force: me.vmid ? 1 : 0
- };
- if (values.unique) { params.unique = 1; }
-
- if (values.bwlimit !== undefined) {
- params.bwlimit = values.bwlimit * 1024;
- }
-
- var url;
- var msg;
- if (me.vmtype === 'lxc') {
- url = '/nodes/' + me.nodename + '/lxc';
- params.ostemplate = me.volid;
- params.restore = 1;
- if (values.unprivileged) { params.unprivileged = 1; }
- msg = Proxmox.Utils.format_task_description('vzrestore', params.vmid);
- } else if (me.vmtype === 'qemu') {
- url = '/nodes/' + me.nodename + '/qemu';
- params.archive = me.volid;
- msg = Proxmox.Utils.format_task_description('qmrestore', params.vmid);
- } else {
- throw 'unknown VM type';
- }
-
- if (me.vmid) {
- msg += '. ' + gettext('This will permanently erase current VM data.');
- Ext.Msg.confirm(gettext('Confirm'), msg, function(btn) {
- if (btn !== 'yes') {
- return;
- }
- doRestore(url, params);
- });
- } else {
- doRestore(url, params);
- }
- }
- });
-
- form.on('validitychange', function(f, valid) {
- submitBtn.setDisabled(!valid);
- });
-
- var title = gettext('Restore') + ": " + (
- (me.vmtype === 'lxc') ? 'CT' : 'VM');
-
- if (me.vmid) {
- title += " " + me.vmid;
- }
-
- Ext.apply(me, {
- title: title,
- width: 500,
- modal: true,
- layout: 'auto',
- border: false,
- items: [ me.formPanel ],
- buttons: [ submitBtn ]
- });
-
- me.callParent();
- }
-});
-/* Popup a message window
- * where the user has to manually enter the resource ID
- * to enable the destroy button
- */
-Ext.define('PVE.window.SafeDestroy', {
- extend: 'Ext.window.Window',
- alias: 'widget.pveSafeDestroy',
-
- title: gettext('Confirm'),
- modal: true,
- buttonAlign: 'center',
- bodyPadding: 10,
- width: 450,
- layout: { type:'hbox' },
- defaultFocus: 'confirmField',
- showProgress: false,
-
- config: {
- item: {
- id: undefined,
- type: undefined
- },
- url: undefined,
- params: {}
- },
-
- getParams: function() {
- var me = this;
- if (Ext.Object.isEmpty(me.params)) {
- return '';
- }
- return '?' + Ext.Object.toQueryString(me.params);
- },
-
- controller: {
-
- xclass: 'Ext.app.ViewController',
-
- control: {
- 'field[name=confirm]': {
- change: function(f, value) {
- var view = this.getView();
- var removeButton = this.lookupReference('removeButton');
- if (value === view.getItem().id.toString()) {
- removeButton.enable();
- } else {
- removeButton.disable();
- }
- },
- specialkey: function (field, event) {
- var removeButton = this.lookupReference('removeButton');
- if (!removeButton.isDisabled() && event.getKey() == event.ENTER) {
- removeButton.fireEvent('click', removeButton, event);
- }
- }
- },
- 'button[reference=removeButton]': {
- click: function() {
- var view = this.getView();
- Proxmox.Utils.API2Request({
- url: view.getUrl() + view.getParams(),
- method: 'DELETE',
- waitMsgTarget: view,
- failure: function(response, opts) {
- view.close();
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- var hasProgressBar = view.showProgress &&
- response.result.data ? true : false;
-
- if (hasProgressBar) {
- // stay around so we can trigger our close events
- // when background action is completed
- view.hide();
-
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid,
- listeners: {
- destroy: function () {
- view.close();
- }
- }
- });
- win.show();
- } else {
- view.close();
- }
- }
- });
- }
- }
- }
- },
-
- items: [
- {
- xtype: 'component',
- cls: [ Ext.baseCSSPrefix + 'message-box-icon',
- Ext.baseCSSPrefix + 'message-box-warning',
- Ext.baseCSSPrefix + 'dlg-icon']
- },
- {
- xtype: 'container',
- flex: 1,
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- items: [
- {
- xtype: 'component',
- reference: 'messageCmp'
- },
- {
- itemId: 'confirmField',
- reference: 'confirmField',
- xtype: 'textfield',
- name: 'confirm',
- labelWidth: 300,
- hideTrigger: true,
- allowBlank: false
- }
- ]
- }
- ],
- buttons: [
- {
- reference: 'removeButton',
- text: gettext('Remove'),
- disabled: true
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- var item = me.getItem();
-
- if (!Ext.isDefined(item.id)) {
- throw "no ID specified";
- }
-
- if (!Ext.isDefined(item.type)) {
- throw "no VM type specified";
- }
-
- var messageCmp = me.lookupReference('messageCmp');
- var msg;
-
- if (item.type === 'VM') {
- msg = Proxmox.Utils.format_task_description('qmdestroy', item.id);
- } else if (item.type === 'CT') {
- msg = Proxmox.Utils.format_task_description('vzdestroy', item.id);
- } else if (item.type === 'CephPool') {
- msg = Proxmox.Utils.format_task_description('cephdestroypool', item.id);
- } else if (item.type === 'Image') {
- msg = Proxmox.Utils.format_task_description('unknownimgdel', item.id);
- } else {
- throw "unknown item type specified";
- }
-
- messageCmp.setHtml(msg);
-
- var confirmField = me.lookupReference('confirmField');
- msg = gettext('Please enter the ID to confirm') +
- ' (' + item.id + ')';
- confirmField.setFieldLabel(msg);
- }
-});
-Ext.define('PVE.window.BackupConfig', {
- extend: 'Ext.window.Window',
- title: gettext('Configuration'),
- width: 600,
- height: 400,
- layout: 'fit',
- modal: true,
- items: {
- xtype: 'component',
- itemId: 'configtext',
- autoScroll: true,
- style: {
- 'background-color': 'white',
- 'white-space': 'pre',
- 'font-family': 'monospace',
- padding: '5px'
- }
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.volume) {
- throw "no volume specified";
- }
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.callParent();
-
- Proxmox.Utils.API2Request({
- url: "/nodes/" + nodename + "/vzdump/extractconfig",
- method: 'GET',
- params: {
- volume: me.volume
- },
- failure: function(response, opts) {
- me.close();
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response,options) {
- me.show();
- me.down('#configtext').update(Ext.htmlEncode(response.result.data));
- }
- });
- }
-});
-Ext.define('PVE.window.Settings', {
- extend: 'Ext.window.Window',
-
- width: '800px',
- title: gettext('My Settings'),
- iconCls: 'fa fa-gear',
- modal: true,
- bodyPadding: 10,
- resizable: false,
-
- buttons: [
- {
- xtype: 'proxmoxHelpButton',
- onlineHelp: 'gui_my_settings',
- hidden: false
- },
- '->',
- {
- text: gettext('Close'),
- handler: function() {
- this.up('window').close();
- }
- }
- ],
-
- layout: {
- type: 'hbox',
- align: 'top'
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- var me = this;
- var sp = Ext.state.Manager.getProvider();
-
- var username = sp.get('login-username') || Proxmox.Utils.noneText;
- me.lookupReference('savedUserName').setValue(username);
-
- var settings = ['fontSize', 'fontFamily', 'letterSpacing', 'lineHeight'];
- settings.forEach(function(setting) {
- var val = localStorage.getItem('pve-xterm-' + setting);
- if (val !== undefined && val !== null) {
- var field = me.lookup(setting);
- field.setValue(val);
- field.resetOriginalValue();
- }
- });
- },
-
- set_button_status: function() {
- var me = this;
-
- var form = me.lookup('xtermform');
- var valid = form.isValid();
- var dirty = form.isDirty();
-
- var hasvalues = false;
- var values = form.getValues();
- Ext.Object.eachValue(values, function(value) {
- if (value) {
- hasvalues = true;
- return false;
- }
- });
-
- me.lookup('xtermsave').setDisabled(!dirty || !valid);
- me.lookup('xtermreset').setDisabled(!hasvalues);
- },
-
- control: {
- '#xtermjs form': {
- dirtychange: 'set_button_status',
- validitychange: 'set_button_status'
- },
- '#xtermjs button': {
- click: function(button) {
- var me = this;
- var settings = ['fontSize', 'fontFamily', 'letterSpacing', 'lineHeight'];
- settings.forEach(function(setting) {
- var field = me.lookup(setting);
- if (button.reference === 'xtermsave') {
- var value = field.getValue();
- if (value) {
- localStorage.setItem('pve-xterm-' + setting, value);
- } else {
- localStorage.removeItem('pve-xterm-' + setting);
- }
- } else if (button.reference === 'xtermreset') {
- field.setValue(undefined);
- localStorage.removeItem('pve-xterm-' + setting);
- }
- field.resetOriginalValue();
- });
- me.set_button_status();
- }
- },
- 'button[name=reset]': {
- click: function () {
- var blacklist = ['GuiCap', 'login-username', 'dash-storages'];
- var sp = Ext.state.Manager.getProvider();
- var state;
- for (state in sp.state) {
- if (sp.state.hasOwnProperty(state)) {
- if (blacklist.indexOf(state) !== -1) {
- continue;
- }
-
- sp.clear(state);
- }
- }
-
- window.location.reload();
- }
- },
- 'button[name=clear-username]': {
- click: function () {
- var me = this;
- var usernamefield = me.lookupReference('savedUserName');
- var sp = Ext.state.Manager.getProvider();
-
- usernamefield.setValue(Proxmox.Utils.noneText);
- sp.clear('login-username');
- }
- },
- 'grid[reference=dashboard-storages]': {
- selectionchange: function(grid, selected) {
- var me = this;
- var sp = Ext.state.Manager.getProvider();
-
- // saves the selected storageids as
- // "id1,id2,id3,..."
- // or clears the variable
- if (selected.length > 0) {
- sp.set('dash-storages',
- Ext.Array.pluck(selected, 'id').join(','));
- } else {
- sp.clear('dash-storages');
- }
- },
- afterrender: function(grid) {
- var me = grid;
- var sp = Ext.state.Manager.getProvider();
- var store = me.getStore();
- var items = [];
- me.suspendEvent('selectionchange');
- var storages = sp.get('dash-storages') || '';
- storages.split(',').forEach(function(storage){
- // we have to get the records
- // to be able to select them
- if (storage !== '') {
- var item = store.getById(storage);
- if (item) {
- items.push(item);
- }
- }
- });
- me.getSelectionModel().select(items);
- me.resumeEvent('selectionchange');
- }
- }
- }
- },
-
- items: [{
- xtype: 'fieldset',
- width: '50%',
- title: gettext('Webinterface Settings'),
- margin: '5',
- layout: {
- type: 'vbox',
- align: 'left'
- },
- defaults: {
- width: '100%',
- margin: '0 0 10 0'
- },
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Dashboard Storages'),
- labelAlign: 'left',
- labelWidth: '50%'
- },
- {
- xtype: 'grid',
- maxHeight: 150,
- reference: 'dashboard-storages',
- selModel: {
- selType: 'checkboxmodel'
- },
- columns: [{
- header: gettext('Name'),
- dataIndex: 'storage',
- flex: 1
- },{
- header: gettext('Node'),
- dataIndex: 'node',
- flex: 1
- }],
- store: {
- type: 'diff',
- field: ['type', 'storage', 'id', 'node'],
- rstore: PVE.data.ResourceStore,
- filters: [{
- property: 'type',
- value: 'storage'
- }],
- sorters: [ 'node','storage']
- }
- },
- {
- xtype: 'box',
- autoEl: { tag: 'hr'}
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Saved User name'),
- labelAlign: 'left',
- labelWidth: '50%',
- stateId: 'login-username',
- reference: 'savedUserName',
- value: ''
- },
- {
- xtype: 'button',
- cls: 'x-btn-default-toolbar-small proxmox-inline-button',
- text: gettext('Clear User name'),
- width: 'auto',
- name: 'clear-username'
- },
- {
- xtype: 'box',
- autoEl: { tag: 'hr'}
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Layout'),
- labelAlign: 'left',
- labelWidth: '50%'
- },
- {
- xtype: 'button',
- cls: 'x-btn-default-toolbar-small proxmox-inline-button',
- text: gettext('Reset Layout'),
- width: 'auto',
- name: 'reset'
- }
- ]
- },{
- xtype: 'fieldset',
- itemId: 'xtermjs',
- width: '50%',
- margin: '5',
- title: gettext('xterm.js Settings'),
- items: [{
- xtype: 'form',
- reference: 'xtermform',
- border: false,
- layout: {
- type: 'vbox',
- algin: 'left'
- },
- defaults: {
- width: '100%',
- margin: '0 0 10 0'
- },
- items: [
- {
- xtype: 'textfield',
- name: 'fontFamily',
- reference: 'fontFamily',
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('Font-Family')
- },
- {
- xtype: 'proxmoxintegerfield',
- emptyText: Proxmox.Utils.defaultText,
- name: 'fontSize',
- reference: 'fontSize',
- minValue: 1,
- fieldLabel: gettext('Font-Size')
- },
- {
- xtype: 'numberfield',
- name: 'letterSpacing',
- reference: 'letterSpacing',
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('Letter Spacing')
- },
- {
- xtype: 'numberfield',
- name: 'lineHeight',
- minValue: 0.1,
- reference: 'lineHeight',
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('Line Height')
- },
- {
- xtype: 'container',
- layout: {
- type: 'hbox',
- pack: 'end'
- },
- items: [
- {
- xtype: 'button',
- reference: 'xtermreset',
- disabled: true,
- text: gettext('Reset')
- },
- {
- xtype: 'button',
- reference: 'xtermsave',
- disabled: true,
- text: gettext('Save')
- }
- ]
- }
- ]
- }]
- }],
-
- onShow: function() {
- var me = this;
- me.callParent();
- }
-});
-Ext.define('PVE.panel.StartupInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- onlineHelp: 'qm_startup_and_shutdown',
-
- onGetValues: function(values) {
- var me = this;
-
- var res = PVE.Parser.printStartup(values);
-
- if (res === undefined || res === '') {
- return { 'delete': 'startup' };
- }
-
- return { startup: res };
- },
-
- setStartup: function(value) {
- var me = this;
-
- var startup = PVE.Parser.parseStartup(value);
- if (startup) {
- me.setValues(startup);
- }
- },
-
- initComponent : function() {
- var me = this;
-
- me.items = [
- {
- xtype: 'textfield',
- name: 'order',
- defaultValue: '',
- emptyText: 'any',
- fieldLabel: gettext('Start/Shutdown order')
- },
- {
- xtype: 'textfield',
- name: 'up',
- defaultValue: '',
- emptyText: 'default',
- fieldLabel: gettext('Startup delay')
- },
- {
- xtype: 'textfield',
- name: 'down',
- defaultValue: '',
- emptyText: 'default',
- fieldLabel: gettext('Shutdown timeout')
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.window.StartupEdit', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveWindowStartupEdit',
- onlineHelp: undefined,
-
- initComponent : function() {
-
- var me = this;
- var ipanelConfig = me.onlineHelp ? {onlineHelp: me.onlineHelp} : {};
- var ipanel = Ext.create('PVE.panel.StartupInputPanel', ipanelConfig);
-
- Ext.applyIf(me, {
- subject: gettext('Start/Shutdown order'),
- fieldDefaults: {
- labelWidth: 120
- },
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var i, confid;
- me.vmconfig = response.result.data;
- ipanel.setStartup(me.vmconfig.startup);
- }
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.ceph.Install', {
- extend: 'Ext.window.Window',
- xtype: 'pveCephInstallWindow',
- mixins: ['Proxmox.Mixin.CBind'],
-
- width: 220,
- header: false,
- resizable: false,
- draggable: false,
- modal: true,
- nodename: undefined,
- shadow: false,
- border: false,
- bodyBorder: false,
- closable: false,
- cls: 'install-mask',
- bodyCls: 'install-mask',
- layout: {
- align: 'stretch',
- pack: 'center',
- type: 'vbox'
- },
- viewModel: {
- data: {
- cephVersion: 'nautilus',
- isInstalled: false
- },
- formulas: {
- buttonText: function (get){
- if (get('isInstalled')) {
- return gettext('Configure Ceph');
- } else {
- return gettext('Install Ceph-') + get('cephVersion');
- }
- },
- windowText: function (get) {
- if (get('isInstalled')) {
- return '' +
- Ext.String.format(gettext('{0} is not initialized.'), 'Ceph') + ' '+
- gettext('You need to create a initial config once.') + '
';
- } else {
- return '' +
- Ext.String.format(gettext('{0} is not installed on this node.'), 'Ceph') + ' ' +
- gettext('Would you like to install it now?') + '
';
- }
- }
- }
- },
- items: [
- {
- bind: {
- html: '{windowText}'
- },
- border: false,
- padding: 5,
- bodyCls: 'install-mask'
-
- },
- {
- xtype: 'button',
- bind: {
- text: '{buttonText}'
- },
- viewModel: {},
- cbind: {
- nodename: '{nodename}'
- },
- handler: function() {
- var me = this.up('pveCephInstallWindow');
- var win = Ext.create('PVE.ceph.CephInstallWizard',{
- nodename: me.nodename
- });
- win.getViewModel().set('isInstalled', this.getViewModel().get('isInstalled'));
- win.show();
- me.mon(win,'beforeClose', function(){
- me.fireEvent("cephInstallWindowClosed");
- me.close();
- });
-
- }
- }
- ]
-});
-/*jslint confusion: true*/
-Ext.define('PVE.FirewallEnableEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveFirewallEnableEdit'],
- mixins: ['Proxmox.Mixin.CBind'],
-
- subject: gettext('Firewall'),
- cbindData: {
- defaultValue: 0
- },
- width: 350,
-
- items: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- uncheckedValue: 0,
- cbind: {
- defaultValue: '{defaultValue}',
- checked: '{defaultValue}'
- },
- deleteDefaultValue: false,
- fieldLabel: gettext('Firewall')
- },
- {
- xtype: 'displayfield',
- name: 'warning',
- userCls: 'pve-hint',
- value: gettext('Warning: Firewall still disabled at datacenter level!'),
- hidden: true
- }
- ],
-
- beforeShow: function() {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/cluster/firewall/options',
- method: 'GET',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- if (!response.result.data.enable) {
- me.down('displayfield[name=warning]').setVisible(true);
- }
- }
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.FirewallLograteInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveFirewallLograteInputPanel',
-
- viewModel: {},
-
- items: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- reference: 'enable',
- fieldLabel: gettext('Enable'),
- value: true
- },
- {
- layout: 'hbox',
- border: false,
- items: [
- {
- xtype: 'numberfield',
- name: 'rate',
- fieldLabel: gettext('Log rate limit'),
- minValue: 1,
- maxValue: 99,
- allowBlank: false,
- flex: 2,
- value: 1
- },
- {
- xtype: 'box',
- html: '/
'
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'unit',
- comboItems: [['second', 'second'], ['minute', 'minute'],
- ['hour', 'hour'], ['day', 'day']],
- allowBlank: false,
- flex: 1,
- value: 'second'
- }
- ]
- },
- {
- xtype: 'numberfield',
- name: 'burst',
- fieldLabel: gettext('Log burst limit'),
- minValue: 1,
- maxValue: 99,
- value: 5
- }
- ],
-
- onGetValues: function(values) {
- var me = this;
-
- var vals = {};
- vals.enable = values.enable !== undefined ? 1 : 0;
- vals.rate = values.rate + '/' + values.unit;
- vals.burst = values.burst;
- var properties = PVE.Parser.printPropertyString(vals, undefined);
- if (properties == '') {
- return { 'delete': 'log_ratelimit' };
- }
- return { log_ratelimit: properties };
- },
-
- setValues: function(values) {
- var me = this;
-
- var properties = {};
- if (values.log_ratelimit !== undefined) {
- properties = PVE.Parser.parsePropertyString(values.log_ratelimit, 'enable');
- if (properties.rate) {
- var matches = properties.rate.match(/^(\d+)\/(second|minute|hour|day)$/);
- if (matches) {
- properties.rate = matches[1];
- properties.unit = matches[2];
- }
- }
- }
- me.callParent([properties]);
- }
-});
-
-Ext.define('PVE.FirewallLograteEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveFirewallLograteEdit',
-
- subject: gettext('Log rate limit'),
-
- items: [{
- xtype: 'pveFirewallLograteInputPanel'
- }],
- autoLoad: true
-});
-Ext.define('PVE.panel.NotesView', {
- extend: 'Ext.panel.Panel',
- xtype: 'pveNotesView',
-
- title: gettext("Notes"),
- bodyStyle: 'white-space:pre',
- bodyPadding: 10,
- scrollable: true,
-
- tbar: {
- itemId: 'tbar',
- hidden: true,
- items: [
- {
- text: gettext('Edit'),
- handler: function() {
- var me = this.up('panel');
- me.run_editor();
- }
- }
- ]
- },
-
- run_editor: function() {
- var me = this;
- var win = Ext.create('PVE.window.NotesEdit', {
- pveSelNode: me.pveSelNode,
- url: me.url
- });
- win.show();
- win.on('destroy', me.load, me);
- },
-
- load: function() {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: me.url,
- waitMsgTarget: me,
- failure: function(response, opts) {
- me.update(gettext('Error') + " " + response.htmlStatus);
- },
- success: function(response, opts) {
- var data = response.result.data.description || '';
- me.update(Ext.htmlEncode(data));
- }
- });
- },
-
- listeners: {
- render: function(c) {
- var me = this;
- me.getEl().on('dblclick', me.run_editor, me);
- }
- },
-
- tools: [{
- type: 'gear',
- handler: function() {
- var me = this.up('panel');
- me.run_editor();
- }
- }],
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var type = me.pveSelNode.data.type;
- if (!Ext.Array.contains(['node', 'qemu', 'lxc'], type)) {
- throw 'invalid type specified';
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid && type !== 'node') {
- throw "no VM ID specified";
- }
-
- me.url = '/api2/extjs/nodes/' + nodename + '/';
-
- // add the type specific path if qemu/lxc
- if (type === 'qemu' || type === 'lxc') {
- me.url += type + '/' + vmid + '/';
- }
-
- me.url += 'config';
-
- me.callParent();
- if (type === 'node') {
- me.down('#tbar').setVisible(true);
- }
- me.load();
- }
-});
-Ext.define('PVE.grid.ResourceGrid', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveResourceGrid'],
-
- border: false,
- defaultSorter: {
- property: 'type',
- direction: 'ASC'
- },
- initComponent : function() {
- var me = this;
-
- var rstore = PVE.data.ResourceStore;
- var sp = Ext.state.Manager.getProvider();
-
- var coldef = rstore.defaultColumns();
-
- var store = Ext.create('Ext.data.Store', {
- model: 'PVEResources',
- sorters: me.defaultSorter,
- proxy: { type: 'memory' }
- });
-
- var textfilter = '';
-
- var textfilter_match = function(item) {
- var match = false;
- Ext.each(['name', 'storage', 'node', 'type', 'text'], function(field) {
- var v = item.data[field];
- if (v !== undefined) {
- v = v.toLowerCase();
- if (v.indexOf(textfilter) >= 0) {
- match = true;
- return false;
- }
- }
- });
- return match;
- };
-
- var updateGrid = function() {
-
- var filterfn = me.viewFilter ? me.viewFilter.filterfn : null;
-
- //console.log("START GRID UPDATE " + me.viewFilter);
-
- store.suspendEvents();
-
- var nodeidx = {};
- var gather_child_nodes = function(cn) {
- if (!cn) {
- return;
- }
- var cs = cn.childNodes;
- if (!cs) {
- return;
- }
- var len = cs.length, i = 0, n, res;
-
- for (; i < len; i++) {
- var child = cs[i];
- var orgnode = rstore.data.get(child.data.id);
- if (orgnode) {
- if ((!filterfn || filterfn(child)) &&
- (!textfilter || textfilter_match(child))) {
- nodeidx[child.data.id] = orgnode;
- }
- }
- gather_child_nodes(child);
- }
- };
- gather_child_nodes(me.pveSelNode);
-
- // remove vanished items
- var rmlist = [];
- store.each(function(olditem) {
- var item = nodeidx[olditem.data.id];
- if (!item) {
- //console.log("GRID REM UID: " + olditem.data.id);
- rmlist.push(olditem);
- }
- });
-
- if (rmlist.length) {
- store.remove(rmlist);
- }
-
- // add new items
- var addlist = [];
- var key;
- for (key in nodeidx) {
- if (nodeidx.hasOwnProperty(key)) {
- var item = nodeidx[key];
-
- // getById() use find(), which is slow (ExtJS4 DP5)
- //var olditem = store.getById(item.data.id);
- var olditem = store.data.get(item.data.id);
-
- if (!olditem) {
- //console.log("GRID ADD UID: " + item.data.id);
- var info = Ext.apply({}, item.data);
- var child = Ext.create(store.model, info);
- addlist.push(item);
- continue;
- }
- // try to detect changes
- var changes = false;
- var fieldkeys = PVE.data.ResourceStore.fieldNames;
- var fieldcount = fieldkeys.length;
- var fieldind;
- for (fieldind = 0; fieldind < fieldcount; fieldind++) {
- var field = fieldkeys[fieldind];
- if (field != 'id' && item.data[field] != olditem.data[field]) {
- changes = true;
- //console.log("changed item " + item.id + " " + field + " " + item.data[field] + " != " + olditem.data[field]);
- olditem.beginEdit();
- olditem.set(field, item.data[field]);
- }
- }
- if (changes) {
- olditem.endEdit(true);
- olditem.commit(true);
- }
- }
- }
-
- if (addlist.length) {
- store.add(addlist);
- }
-
- store.sort();
-
- store.resumeEvents();
-
- store.fireEvent('refresh', store);
-
- //console.log("END GRID UPDATE");
- };
-
- var filter_task = new Ext.util.DelayedTask(function(){
- updateGrid();
- });
-
- var load_cb = function() {
- updateGrid();
- };
-
- Ext.apply(me, {
- store: store,
- stateful: true,
- stateId: 'grid-resource',
- tbar: [
- '->',
- gettext('Search') + ':', ' ',
- {
- xtype: 'textfield',
- width: 200,
- value: textfilter,
- enableKeyEvents: true,
- listeners: {
- keyup: function(field, e) {
- var v = field.getValue();
- textfilter = v.toLowerCase();
- filter_task.delay(500);
- }
- }
- }
- ],
- viewConfig: {
- stripeRows: true
- },
- listeners: {
- itemcontextmenu: PVE.Utils.createCmdMenu,
- itemdblclick: function(v, record) {
- var ws = me.up('pveStdWorkspace');
- ws.selectById(record.data.id);
- },
- destroy: function() {
- rstore.un("load", load_cb);
- }
- },
- columns: coldef
- });
- me.callParent();
- updateGrid();
- rstore.on("load", load_cb);
- }
-});
-Ext.define('PVE.pool.AddVM', {
- extend: 'Proxmox.window.Edit',
- width: 600,
- height: 400,
- isAdd: true,
- isCreate: true,
- initComponent : function() {
-
- var me = this;
-
- if (!me.pool) {
- throw "no pool specified";
- }
-
- me.url = "/pools/" + me.pool;
- me.method = 'PUT';
-
- var vmsField = Ext.create('Ext.form.field.Text', {
- name: 'vms',
- hidden: true,
- allowBlank: false
- });
-
- var vmStore = Ext.create('Ext.data.Store', {
- model: 'PVEResources',
- sorters: [
- {
- property: 'vmid',
- order: 'ASC'
- }
- ],
- filters: [
- function(item) {
- return ((item.data.type === 'lxc' || item.data.type === 'qemu') && item.data.pool === '');
- }
- ]
- });
-
- var vmGrid = Ext.create('widget.grid',{
- store: vmStore,
- border: true,
- height: 300,
- scrollable: true,
- selModel: {
- selType: 'checkboxmodel',
- mode: 'SIMPLE',
- listeners: {
- selectionchange: function(model, selected, opts) {
- var selectedVms = [];
- selected.forEach(function(vm) {
- selectedVms.push(vm.data.vmid);
- });
- vmsField.setValue(selectedVms);
- }
- }
- },
- columns: [
- {
- header: 'ID',
- dataIndex: 'vmid',
- width: 60
- },
- {
- header: gettext('Node'),
- dataIndex: 'node'
- },
- {
- header: gettext('Status'),
- dataIndex: 'uptime',
- renderer: function(value) {
- if (value) {
- return Proxmox.Utils.runningText;
- } else {
- return Proxmox.Utils.stoppedText;
- }
- }
- },
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- header: gettext('Type'),
- dataIndex: 'type'
- }
- ]
- });
- Ext.apply(me, {
- subject: gettext('Virtual Machine'),
- items: [ vmsField, vmGrid ]
- });
-
- me.callParent();
- vmStore.load();
- }
-});
-
-Ext.define('PVE.pool.AddStorage', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
-
- var me = this;
-
- if (!me.pool) {
- throw "no pool specified";
- }
-
- me.isCreate = true;
- me.isAdd = true;
- me.url = "/pools/" + me.pool;
- me.method = 'PUT';
-
- Ext.apply(me, {
- subject: gettext('Storage'),
- width: 350,
- items: [
- {
- xtype: 'pveStorageSelector',
- name: 'storage',
- nodename: 'localhost',
- autoSelect: false,
- value: '',
- fieldLabel: gettext("Storage")
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.grid.PoolMembers', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pvePoolMembers'],
-
- // fixme: dynamic status update ?
-
- stateful: true,
- stateId: 'grid-pool-members',
-
- initComponent : function() {
- var me = this;
-
- if (!me.pool) {
- throw "no pool specified";
- }
-
- var store = Ext.create('Ext.data.Store', {
- model: 'PVEResources',
- sorters: [
- {
- property : 'type',
- direction: 'ASC'
- }
- ],
- proxy: {
- type: 'proxmox',
- root: 'data.members',
- url: "/api2/json/pools/" + me.pool
- }
- });
-
- var coldef = PVE.data.ResourceStore.defaultColumns();
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- confirmMsg: function (rec) {
- return Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.id + "'");
- },
- handler: function(btn, event, rec) {
- var params = { 'delete': 1 };
- if (rec.data.type === 'storage') {
- params.storage = rec.data.storage;
- } else if (rec.data.type === 'qemu' || rec.data.type === 'lxc' || rec.data.type === 'openvz') {
- params.vms = rec.data.vmid;
- } else {
- throw "unknown resource type";
- }
-
- Proxmox.Utils.API2Request({
- url: '/pools/' + me.pool,
- method: 'PUT',
- params: params,
- waitMsgTarget: me,
- callback: function() {
- reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Virtual Machine'),
- iconCls: 'pve-itype-icon-qemu',
- handler: function() {
- var win = Ext.create('PVE.pool.AddVM', { pool: me.pool });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('Storage'),
- iconCls: 'pve-itype-icon-storage',
- handler: function() {
- var win = Ext.create('PVE.pool.AddStorage', { pool: me.pool });
- win.on('destroy', reload);
- win.show();
- }
- }
- ]
- })
- },
- remove_btn
- ],
- viewConfig: {
- stripeRows: true
- },
- columns: coldef,
- listeners: {
- itemcontextmenu: PVE.Utils.createCmdMenu,
- itemdblclick: function(v, record) {
- var ws = me.up('pveStdWorkspace');
- ws.selectById(record.data.id);
- },
- activate: reload
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.form.FWMacroSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: 'widget.pveFWMacroSelector',
- allowBlank: true,
- autoSelect: false,
- valueField: 'macro',
- displayField: 'macro',
- listConfig: {
- columns: [
- {
- header: gettext('Macro'),
- dataIndex: 'macro',
- hideable: false,
- width: 100
- },
- {
- header: gettext('Description'),
- renderer: Ext.String.htmlEncode,
- flex: 1,
- dataIndex: 'descr'
- }
- ]
- },
- initComponent: function() {
- var me = this;
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: true,
- fields: [ 'macro', 'descr' ],
- idProperty: 'macro',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/firewall/macros"
- },
- sorters: {
- property: 'macro',
- order: 'DESC'
- }
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.FirewallRulePanel', {
- extend: 'Proxmox.panel.InputPanel',
-
- allow_iface: false,
-
- list_refs_url: undefined,
-
- onGetValues: function(values) {
- var me = this;
-
- // hack: editable ComboGrid returns nothing when empty, so we need to set ''
- // Also, disabled text fields return nothing, so we need to set ''
-
- Ext.Array.each(['source', 'dest', 'macro', 'proto', 'sport', 'dport', 'log'], function(key) {
- if (values[key] === undefined) {
- values[key] = '';
- }
- });
-
- delete values.modified_marker;
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.list_refs_url) {
- throw "no list_refs_url specified";
- }
-
- me.column1 = [
- {
- // hack: we use this field to mark the form 'dirty' when the
- // record has errors- so that the user can safe the unmodified
- // form again.
- xtype: 'hiddenfield',
- name: 'modified_marker',
- value: ''
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'type',
- value: 'in',
- comboItems: [['in', 'in'], ['out', 'out']],
- fieldLabel: gettext('Direction'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'action',
- value: 'ACCEPT',
- comboItems: [['ACCEPT', 'ACCEPT'], ['DROP', 'DROP'], ['REJECT', 'REJECT']],
- fieldLabel: gettext('Action'),
- allowBlank: false
- }
- ];
-
- if (me.allow_iface) {
- me.column1.push({
- xtype: 'proxmoxtextfield',
- name: 'iface',
- deleteEmpty: !me.isCreate,
- value: '',
- fieldLabel: gettext('Interface')
- });
- } else {
- me.column1.push({
- xtype: 'displayfield',
- fieldLabel: '',
- value: ''
- });
- }
-
- me.column1.push(
- {
- xtype: 'displayfield',
- fieldLabel: '',
- height: 7,
- value: ''
- },
- {
- xtype: 'pveIPRefSelector',
- name: 'source',
- autoSelect: false,
- editable: true,
- base_url: me.list_refs_url,
- value: '',
- fieldLabel: gettext('Source')
-
- },
- {
- xtype: 'pveIPRefSelector',
- name: 'dest',
- autoSelect: false,
- editable: true,
- base_url: me.list_refs_url,
- value: '',
- fieldLabel: gettext('Destination')
- }
- );
-
-
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: gettext('Enable')
- },
- {
- xtype: 'pveFWMacroSelector',
- name: 'macro',
- fieldLabel: gettext('Macro'),
- editable: true,
- allowBlank: true,
- listeners: {
- change: function(f, value) {
- if (value === null) {
- me.down('field[name=proto]').setDisabled(false);
- me.down('field[name=sport]').setDisabled(false);
- me.down('field[name=dport]').setDisabled(false);
- } else {
- me.down('field[name=proto]').setDisabled(true);
- me.down('field[name=proto]').setValue('');
- me.down('field[name=sport]').setDisabled(true);
- me.down('field[name=sport]').setValue('');
- me.down('field[name=dport]').setDisabled(true);
- me.down('field[name=dport]').setValue('');
- }
- }
- }
- },
- {
- xtype: 'pveIPProtocolSelector',
- name: 'proto',
- autoSelect: false,
- editable: true,
- value: '',
- fieldLabel: gettext('Protocol')
- },
- {
- xtype: 'displayfield',
- fieldLabel: '',
- height: 7,
- value: ''
- },
- {
- xtype: 'textfield',
- name: 'sport',
- value: '',
- fieldLabel: gettext('Source port')
- },
- {
- xtype: 'textfield',
- name: 'dport',
- value: '',
- fieldLabel: gettext('Dest. port')
- }
- ];
-
- me.advancedColumn1 = [
- {
- xtype: 'pveFirewallLogLevels'
- }
- ];
-
- me.columnB = [
- {
- xtype: 'textfield',
- name: 'comment',
- value: '',
- fieldLabel: gettext('Comment')
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.FirewallRuleEdit', {
- extend: 'Proxmox.window.Edit',
-
- base_url: undefined,
- list_refs_url: undefined,
-
- allow_iface: false,
-
- initComponent : function() {
-
- var me = this;
-
- if (!me.base_url) {
- throw "no base_url specified";
- }
- if (!me.list_refs_url) {
- throw "no list_refs_url specified";
- }
-
- me.isCreate = (me.rule_pos === undefined);
-
- if (me.isCreate) {
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs' + me.base_url + '/' + me.rule_pos.toString();
- me.method = 'PUT';
- }
-
- var ipanel = Ext.create('PVE.FirewallRulePanel', {
- isCreate: me.isCreate,
- list_refs_url: me.list_refs_url,
- allow_iface: me.allow_iface,
- rule_pos: me.rule_pos
- });
-
- Ext.apply(me, {
- subject: gettext('Rule'),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- ipanel.setValues(values);
- if (values.errors) {
- var field = me.query('[isFormField][name=modified_marker]')[0];
- field.setValue(1);
- Ext.Function.defer(function() {
- var form = ipanel.up('form').getForm();
- form.markInvalid(values.errors);
- }, 100);
- }
- }
- });
- } else if (me.rec) {
- ipanel.setValues(me.rec.data);
- }
- }
-});
-
-Ext.define('PVE.FirewallGroupRuleEdit', {
- extend: 'Proxmox.window.Edit',
-
- base_url: undefined,
-
- allow_iface: false,
-
- initComponent : function() {
-
- var me = this;
-
- me.isCreate = (me.rule_pos === undefined);
-
- if (me.isCreate) {
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs' + me.base_url + '/' + me.rule_pos.toString();
- me.method = 'PUT';
- }
-
- var column1 = [
- {
- xtype: 'hiddenfield',
- name: 'type',
- value: 'group'
- },
- {
- xtype: 'pveSecurityGroupsSelector',
- name: 'action',
- value: '',
- fieldLabel: gettext('Security Group'),
- allowBlank: false
- }
- ];
-
- if (me.allow_iface) {
- column1.push({
- xtype: 'proxmoxtextfield',
- name: 'iface',
- deleteEmpty: !me.isCreate,
- value: '',
- fieldLabel: gettext('Interface')
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- isCreate: me.isCreate,
- column1: column1,
- column2: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: gettext('Enable')
- }
- ],
- columnB: [
- {
- xtype: 'textfield',
- name: 'comment',
- value: '',
- fieldLabel: gettext('Comment')
- }
- ]
- });
-
- Ext.apply(me, {
- subject: gettext('Rule'),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-
-Ext.define('PVE.FirewallRules', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveFirewallRules',
-
- onlineHelp: 'chapter_pve_firewall',
-
- stateful: true,
- stateId: 'grid-firewall-rules',
-
- base_url: undefined,
- list_refs_url: undefined,
-
- addBtn: undefined,
- removeBtn: undefined,
- editBtn: undefined,
- groupBtn: undefined,
-
- tbar_prefix: undefined,
-
- allow_groups: true,
- allow_iface: false,
-
- setBaseUrl: function(url) {
- var me = this;
-
- me.base_url = url;
-
- if (url === undefined) {
- me.addBtn.setDisabled(true);
- if (me.groupBtn) {
- me.groupBtn.setDisabled(true);
- }
- me.store.removeAll();
- } else {
- me.addBtn.setDisabled(false);
- me.removeBtn.baseurl = url + '/';
- if (me.groupBtn) {
- me.groupBtn.setDisabled(false);
- }
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json' + url
- });
-
- me.store.load();
- }
- },
-
- moveRule: function(from, to) {
- var me = this;
-
- if (!me.base_url) {
- return;
- }
-
- Proxmox.Utils.API2Request({
- url: me.base_url + "/" + from,
- method: 'PUT',
- params: { moveto: to },
- waitMsgTarget: me,
- failure: function(response, options) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- callback: function() {
- me.store.load();
- }
- });
- },
-
- updateRule: function(rule) {
- var me = this;
-
- if (!me.base_url) {
- return;
- }
-
- rule.enable = rule.enable ? 1 : 0;
-
- var pos = rule.pos;
- delete rule.pos;
- delete rule.errors;
-
- Proxmox.Utils.API2Request({
- url: me.base_url + '/' + pos.toString(),
- method: 'PUT',
- params: rule,
- waitMsgTarget: me,
- failure: function(response, options) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- callback: function() {
- me.store.load();
- }
- });
- },
-
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.list_refs_url) {
- throw "no list_refs_url specified";
- }
-
- var store = Ext.create('Ext.data.Store',{
- model: 'pve-fw-rule'
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var type = rec.data.type;
-
- var editor;
- if (type === 'in' || type === 'out') {
- editor = 'PVE.FirewallRuleEdit';
- } else if (type === 'group') {
- editor = 'PVE.FirewallGroupRuleEdit';
- } else {
- return;
- }
-
- var win = Ext.create(editor, {
- digest: rec.data.digest,
- allow_iface: me.allow_iface,
- base_url: me.base_url,
- list_refs_url: me.list_refs_url,
- rule_pos: rec.data.pos
- });
-
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = Ext.create('Proxmox.button.Button',{
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = Ext.create('Ext.Button', {
- text: gettext('Add'),
- disabled: true,
- handler: function() {
- var win = Ext.create('PVE.FirewallRuleEdit', {
- allow_iface: me.allow_iface,
- base_url: me.base_url,
- list_refs_url: me.list_refs_url
- });
- win.on('destroy', reload);
- win.show();
- }
- });
-
- var run_copy_editor = function() {
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- return;
- }
- var type = rec.data.type;
-
-
- if (!(type === 'in' || type === 'out')) {
- return;
- }
-
- var win = Ext.create('PVE.FirewallRuleEdit', {
- allow_iface: me.allow_iface,
- base_url: me.base_url,
- list_refs_url: me.list_refs_url,
- rec: rec
- });
-
- win.show();
- win.on('destroy', reload);
- };
-
- me.copyBtn = Ext.create('Proxmox.button.Button',{
- text: gettext('Copy'),
- selModel: sm,
- enableFn: function(rec) {
- return (rec.data.type === 'in' || rec.data.type === 'out');
- },
- disabled: true,
- handler: run_copy_editor
- });
-
- if (me.allow_groups) {
- me.groupBtn = Ext.create('Ext.Button', {
- text: gettext('Insert') + ': ' +
- gettext('Security Group'),
- disabled: true,
- handler: function() {
- var win = Ext.create('PVE.FirewallGroupRuleEdit', {
- allow_iface: me.allow_iface,
- base_url: me.base_url
- });
- win.on('destroy', reload);
- win.show();
- }
- });
- }
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton',{
- selModel: sm,
- baseurl: me.base_url + '/',
- confirmMsg: false,
- getRecordName: function(rec) {
- var rule = rec.data;
- return rule.pos.toString() +
- '?digest=' + encodeURIComponent(rule.digest);
- },
- callback: function() {
- me.store.load();
- }
- });
-
- var tbar = me.tbar_prefix ? [ me.tbar_prefix ] : [];
- tbar.push(me.addBtn, me.copyBtn);
- if (me.groupBtn) {
- tbar.push(me.groupBtn);
- }
- tbar.push(me.removeBtn, me.editBtn);
-
- var render_errors = function(name, value, metaData, record) {
- var errors = record.data.errors;
- if (errors && errors[name]) {
- metaData.tdCls = 'proxmox-invalid-row';
- var html = '' + Ext.htmlEncode(errors[name]) + '
';
- metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
- html.replace(/\"/g,'"') + '"';
- }
- return value;
- };
-
- var columns = [
- {
- // similar to xtype: 'rownumberer',
- dataIndex: 'pos',
- resizable: false,
- width: 23,
- sortable: false,
- align: 'right',
- hideable: false,
- menuDisabled: true,
- renderer: function(value, metaData, record, rowIdx, colIdx, store) {
- metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
- if (value >= 0) {
- return value;
- }
- return '';
- }
- },
- {
- xtype: 'checkcolumn',
- header: gettext('Enable'),
- dataIndex: 'enable',
- listeners: {
- checkchange: function(column, recordIndex, checked) {
- var record = me.getStore().getData().items[recordIndex];
- record.commit();
- var data = {};
- Ext.Array.forEach(record.getFields(), function(field) {
- data[field.name] = record.get(field.name);
- });
- if (!me.allow_iface || !data.iface) {
- delete data.iface;
- }
- me.updateRule(data);
- }
- },
- width: 50
- },
- {
- header: gettext('Type'),
- dataIndex: 'type',
- renderer: function(value, metaData, record) {
- return render_errors('type', value, metaData, record);
- },
- width: 50
- },
- {
- header: gettext('Action'),
- dataIndex: 'action',
- renderer: function(value, metaData, record) {
- return render_errors('action', value, metaData, record);
- },
- width: 80
- },
- {
- header: gettext('Macro'),
- dataIndex: 'macro',
- renderer: function(value, metaData, record) {
- return render_errors('macro', value, metaData, record);
- },
- width: 80
- }
- ];
-
- if (me.allow_iface) {
- columns.push({
- header: gettext('Interface'),
- dataIndex: 'iface',
- renderer: function(value, metaData, record) {
- return render_errors('iface', value, metaData, record);
- },
- width: 80
- });
- }
-
- columns.push(
- {
- header: gettext('Source'),
- dataIndex: 'source',
- renderer: function(value, metaData, record) {
- return render_errors('source', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Destination'),
- dataIndex: 'dest',
- renderer: function(value, metaData, record) {
- return render_errors('dest', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Protocol'),
- dataIndex: 'proto',
- renderer: function(value, metaData, record) {
- return render_errors('proto', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Dest. port'),
- dataIndex: 'dport',
- renderer: function(value, metaData, record) {
- return render_errors('dport', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Source port'),
- dataIndex: 'sport',
- renderer: function(value, metaData, record) {
- return render_errors('sport', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Log level'),
- dataIndex: 'log',
- renderer: function(value, metaData, record) {
- return render_errors('log', value, metaData, record);
- },
- width: 100
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comment',
- flex: 1,
- renderer: function(value, metaData, record) {
- return render_errors('comment', Ext.util.Format.htmlEncode(value), metaData, record);
- }
- }
- );
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- plugins: [
- {
- ptype: 'gridviewdragdrop',
- dragGroup: 'FWRuleDDGroup',
- dropGroup: 'FWRuleDDGroup'
- }
- ],
- listeners: {
- beforedrop: function(node, data, dropRec, dropPosition) {
- if (!dropRec) {
- return false; // empty view
- }
- var moveto = dropRec.get('pos');
- if (dropPosition === 'after') {
- moveto++;
- }
- var pos = data.records[0].get('pos');
- me.moveRule(pos, moveto);
- return 0;
- },
- itemdblclick: run_editor
- }
- },
- sortableColumns: false,
- columns: columns
- });
-
- me.callParent();
-
- if (me.base_url) {
- me.setBaseUrl(me.base_url); // load
- }
- }
-}, function() {
-
- Ext.define('pve-fw-rule', {
- extend: 'Ext.data.Model',
- fields: [ { name: 'enable', type: 'boolean' },
- 'type', 'action', 'macro', 'source', 'dest', 'proto', 'iface',
- 'dport', 'sport', 'comment', 'pos', 'digest', 'errors' ],
- idProperty: 'pos'
- });
-
-});
-Ext.define('PVE.FirewallAliasEdit', {
- extend: 'Proxmox.window.Edit',
-
- base_url: undefined,
-
- alias_name: undefined,
-
- initComponent : function() {
-
- var me = this;
-
- me.isCreate = (me.alias_name === undefined);
-
- if (me.isCreate) {
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs' + me.base_url + '/' + me.alias_name;
- me.method = 'PUT';
- }
-
- var items = [
- {
- xtype: 'textfield',
- name: me.isCreate ? 'name' : 'rename',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'cidr',
- fieldLabel: gettext('IP/CIDR'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- }
- ];
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- isCreate: me.isCreate,
- items: items
- });
-
- Ext.apply(me, {
- subject: gettext('Alias'),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- values.rename = values.name;
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-
-Ext.define('pve-fw-aliases', {
- extend: 'Ext.data.Model',
-
- fields: [ 'name', 'cidr', 'comment', 'digest' ],
- idProperty: 'name'
-});
-
-Ext.define('PVE.FirewallAliases', {
- extend: 'Ext.grid.Panel',
- alias: ['widget.pveFirewallAliases'],
-
- onlineHelp: 'pve_firewall_ip_aliases',
-
- stateful: true,
- stateId: 'grid-firewall-aliases',
-
- base_url: undefined,
-
- title: gettext('Alias'),
-
- initComponent : function() {
-
- var me = this;
-
- if (!me.base_url) {
- throw "missing base_url configuration";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-fw-aliases',
- proxy: {
- type: 'proxmox',
- url: "/api2/json" + me.base_url
- },
- sorters: {
- property: 'name',
- order: 'DESC'
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- var oldrec = sm.getSelection()[0];
- store.load(function(records, operation, success) {
- if (oldrec) {
- var rec = store.findRecord('name', oldrec.data.name);
- if (rec) {
- sm.select(rec);
- }
- }
- });
- };
-
- var run_editor = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.FirewallAliasEdit', {
- base_url: me.base_url,
- alias_name: rec.data.name
- });
-
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = Ext.create('Ext.Button', {
- text: gettext('Add'),
- handler: function() {
- var win = Ext.create('PVE.FirewallAliasEdit', {
- base_url: me.base_url
- });
- win.on('destroy', reload);
- win.show();
- }
- });
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: me.base_url + '/',
- callback: reload
- });
-
-
- Ext.apply(me, {
- store: store,
- tbar: [ me.addBtn, me.removeBtn, me.editBtn ],
- selModel: sm,
- columns: [
- { header: gettext('Name'), dataIndex: 'name', width: 100 },
- { header: gettext('IP/CIDR'), dataIndex: 'cidr', width: 100 },
- { header: gettext('Comment'), dataIndex: 'comment', renderer: Ext.String.htmlEncode, flex: 1 }
- ],
- listeners: {
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- me.on('activate', reload);
- }
-});
-Ext.define('PVE.FirewallOptions', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveFirewallOptions'],
-
- fwtype: undefined, // 'dc', 'node' or 'vm'
-
- base_url: undefined,
-
- initComponent : function() {
- /*jslint confusion: true */
-
- var me = this;
-
- if (!me.base_url) {
- throw "missing base_url configuration";
- }
-
- if (me.fwtype === 'dc' || me.fwtype === 'node' || me.fwtype === 'vm') {
- if (me.fwtype === 'node') {
- me.cwidth1 = 250;
- }
- } else {
- throw "unknown firewall option type";
- }
-
- me.rows = {};
-
- var add_boolean_row = function(name, text, defaultValue) {
- me.add_boolean_row(name, text, { defaultValue: defaultValue });
- };
- var add_integer_row = function(name, text, minValue, labelWidth) {
- me.add_integer_row(name, text, {
- minValue: minValue,
- deleteEmpty: true,
- labelWidth: labelWidth,
- renderer: function(value) {
- if (value === undefined) {
- return Proxmox.Utils.defaultText;
- }
-
- return value;
- }
- });
- };
-
- var add_log_row = function(name, labelWidth) {
- me.rows[name] = {
- header: name,
- required: true,
- defaultValue: 'nolog',
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: name,
- fieldDefaults: { labelWidth: labelWidth || 100 },
- items: {
- xtype: 'pveFirewallLogLevels',
- name: name,
- fieldLabel: name
- }
- }
- };
- };
-
- if (me.fwtype === 'node') {
- me.rows.enable = {
- required: true,
- defaultValue: 1,
- header: gettext('Firewall'),
- renderer: Proxmox.Utils.format_boolean,
- editor: {
- xtype: 'pveFirewallEnableEdit',
- defaultValue: 1
- }
- };
- add_boolean_row('nosmurfs', gettext('SMURFS filter'), 1);
- add_boolean_row('tcpflags', gettext('TCP flags filter'), 0);
- add_boolean_row('ndp', 'NDP', 1);
- add_integer_row('nf_conntrack_max', 'nf_conntrack_max', 32768, 120);
- add_integer_row('nf_conntrack_tcp_timeout_established',
- 'nf_conntrack_tcp_timeout_established', 7875, 250);
- add_log_row('log_level_in');
- add_log_row('log_level_out');
- add_log_row('tcp_flags_log_level', 120);
- add_log_row('smurf_log_level');
- } else if (me.fwtype === 'vm') {
- me.rows.enable = {
- required: true,
- defaultValue: 0,
- header: gettext('Firewall'),
- renderer: Proxmox.Utils.format_boolean,
- editor: {
- xtype: 'pveFirewallEnableEdit',
- defaultValue: 0
- }
- };
- add_boolean_row('dhcp', 'DHCP', 1);
- add_boolean_row('ndp', 'NDP', 1);
- add_boolean_row('radv', gettext('Router Advertisement'), 0);
- add_boolean_row('macfilter', gettext('MAC filter'), 1);
- add_boolean_row('ipfilter', gettext('IP filter'), 0);
- add_log_row('log_level_in');
- add_log_row('log_level_out');
- } else if (me.fwtype === 'dc') {
- add_boolean_row('enable', gettext('Firewall'), 0);
- add_boolean_row('ebtables', 'ebtables', 1);
- me.rows.log_ratelimit = {
- header: gettext('Log rate limit'),
- required: true,
- defaultValue: gettext('Default') + ' (enable=1,rate1/second,burst=5)',
- editor: {
- xtype: 'pveFirewallLograteEdit',
- defaultValue: 'enable=1'
- }
- };
- }
-
- if (me.fwtype === 'dc' || me.fwtype === 'vm') {
- me.rows.policy_in = {
- header: gettext('Input Policy'),
- required: true,
- defaultValue: 'DROP',
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Input Policy'),
- items: {
- xtype: 'pveFirewallPolicySelector',
- name: 'policy_in',
- value: 'DROP',
- fieldLabel: gettext('Input Policy')
- }
- }
- };
-
- me.rows.policy_out = {
- header: gettext('Output Policy'),
- required: true,
- defaultValue: 'ACCEPT',
- editor: {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Output Policy'),
- items: {
- xtype: 'pveFirewallPolicySelector',
- name: 'policy_out',
- value: 'ACCEPT',
- fieldLabel: gettext('Output Policy')
- }
- }
- };
- }
-
- var edit_btn = new Ext.Button({
- text: gettext('Edit'),
- disabled: true,
- handler: function() { me.run_editor(); }
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- edit_btn.disable();
- return;
- }
- var rowdef = me.rows[rec.data.key];
- edit_btn.setDisabled(!rowdef.editor);
- };
-
- Ext.apply(me, {
- url: "/api2/json" + me.base_url,
- tbar: [ edit_btn ],
- editorConfig: {
- url: '/api2/extjs/' + me.base_url
- },
- listeners: {
- itemdblclick: me.run_editor,
- selectionchange: set_button_status
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
- }
-});
-
-
-Ext.define('PVE.FirewallLogLevels', {
- extend: 'Proxmox.form.KVComboBox',
- alias: ['widget.pveFirewallLogLevels'],
-
- name: 'log',
- fieldLabel: gettext('Log level'),
- value: 'nolog',
- comboItems: [['nolog', 'nolog'], ['emerg', 'emerg'], ['alert', 'alert'],
- ['crit', 'crit'], ['err', 'err'], ['warning', 'warning'],
- ['notice', 'notice'], ['info', 'info'], ['debug', 'debug']]
-});
-/*
- * Left Treepanel, containing all the resources we manage in this datacenter: server nodes, server storages, VMs and Containers
- */
-Ext.define('PVE.tree.ResourceTree', {
- extend: 'Ext.tree.TreePanel',
- alias: ['widget.pveResourceTree'],
-
- statics: {
- typeDefaults: {
- node: {
- iconCls: 'fa fa-building',
- text: gettext('Nodes')
- },
- pool: {
- iconCls: 'fa fa-tags',
- text: gettext('Resource Pool')
- },
- storage: {
- iconCls: 'fa fa-database',
- text: gettext('Storage')
- },
- qemu: {
- iconCls: 'fa fa-desktop',
- text: gettext('Virtual Machine')
- },
- lxc: {
- //iconCls: 'x-tree-node-lxc',
- iconCls: 'fa fa-cube',
- text: gettext('LXC Container')
- },
- template: {
- iconCls: 'fa fa-file-o'
- }
- }
- },
-
- useArrows: true,
-
- // private
- nodeSortFn: function(node1, node2) {
- var n1 = node1.data;
- var n2 = node2.data;
-
- if ((n1.groupbyid && n2.groupbyid) ||
- !(n1.groupbyid || n2.groupbyid)) {
-
- var tcmp;
-
- var v1 = n1.type;
- var v2 = n2.type;
-
- if ((tcmp = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)) != 0) {
- return tcmp;
- }
-
- // numeric compare for VM IDs
- // sort templates after regular VMs
- if (v1 === 'qemu' || v1 === 'lxc') {
- if (n1.template && !n2.template) {
- return 1;
- } else if (n2.template && !n1.template) {
- return -1;
- }
- v1 = n1.vmid;
- v2 = n2.vmid;
- if ((tcmp = v1 > v2 ? 1 : (v1 < v2 ? -1 : 0)) != 0) {
- return tcmp;
- }
- }
-
- return n1.id > n2.id ? 1 : (n1.id < n2.id ? -1 : 0);
- } else if (n1.groupbyid) {
- return -1;
- } else if (n2.groupbyid) {
- return 1;
- }
- },
-
- // private: fast binary search
- findInsertIndex: function(node, child, start, end) {
- var me = this;
-
- var diff = end - start;
-
- var mid = start + (diff>>1);
-
- if (diff <= 0) {
- return start;
- }
-
- var res = me.nodeSortFn(child, node.childNodes[mid]);
- if (res <= 0) {
- return me.findInsertIndex(node, child, start, mid);
- } else {
- return me.findInsertIndex(node, child, mid + 1, end);
- }
- },
-
- setIconCls: function(info) {
- var me = this;
-
- var cls = PVE.Utils.get_object_icon_class(info.type, info);
-
- if (cls !== '') {
- info.iconCls = cls;
- }
- },
-
- // add additional elements to text
- // at the moment only the usage indicator for storages
- setText: function(info) {
- var me = this;
-
- var status = '';
- if (info.type === 'storage') {
- var maxdisk = info.maxdisk;
- var disk = info.disk;
- var usage = disk/maxdisk;
- var cls = '';
- if (usage <= 1.0 && usage >= 0.0) {
- var height = (usage*100).toFixed(0);
- var neg_height = (100-usage*100).toFixed(0);
- status = '';
- status += '
';
- status += '
';
- status += '
';
- }
- }
-
- info.text = status + info.text;
- },
-
- setToolTip: function(info) {
- if (info.type === 'pool' || info.groupbyid !== undefined) {
- return;
- }
-
- var qtips = [gettext('Status') + ': ' + (info.qmpstatus || info.status)];
- if (info.lock) {
- qtips.push('Config locked (' + info.lock + ')');
- }
- if (info.hastate != 'unmanaged') {
- qtips.push(gettext('HA State') + ": " + info.hastate);
- }
-
- info.qtip = qtips.join(', ');
- },
-
- // private
- addChildSorted: function(node, info) {
- var me = this;
-
- me.setIconCls(info);
- me.setText(info);
- me.setToolTip(info);
-
- var defaults;
- if (info.groupbyid) {
- info.text = info.groupbyid;
- if (info.type === 'type') {
- defaults = PVE.tree.ResourceTree.typeDefaults[info.groupbyid];
- if (defaults && defaults.text) {
- info.text = defaults.text;
- }
- }
- }
- var child = Ext.create('PVETree', info);
-
- var cs = node.childNodes;
- var pos;
- if (cs) {
- pos = cs[me.findInsertIndex(node, child, 0, cs.length)];
- }
-
- node.insertBefore(child, pos);
-
- return child;
- },
-
- // private
- groupChild: function(node, info, groups, level) {
- var me = this;
-
- var groupby = groups[level];
- var v = info[groupby];
-
- if (v) {
- var group = node.findChild('groupbyid', v);
- if (!group) {
- var groupinfo;
- if (info.type === groupby) {
- groupinfo = info;
- } else {
- groupinfo = {
- type: groupby,
- id : groupby + "/" + v
- };
- if (groupby !== 'type') {
- groupinfo[groupby] = v;
- }
- }
- groupinfo.leaf = false;
- groupinfo.groupbyid = v;
- group = me.addChildSorted(node, groupinfo);
- }
- if (info.type === groupby) {
- return group;
- }
- if (group) {
- return me.groupChild(group, info, groups, level + 1);
- }
- }
-
- return me.addChildSorted(node, info);
- },
-
- initComponent : function() {
- var me = this;
-
- var rstore = PVE.data.ResourceStore;
- var sp = Ext.state.Manager.getProvider();
-
- if (!me.viewFilter) {
- me.viewFilter = {};
- }
-
- var pdata = {
- dataIndex: {},
- updateCount: 0
- };
-
- var store = Ext.create('Ext.data.TreeStore', {
- model: 'PVETree',
- root: {
- expanded: true,
- id: 'root',
- text: gettext('Datacenter'),
- iconCls: 'fa fa-server'
- }
- });
-
- var stateid = 'rid';
-
- var updateTree = function() {
- var tmp;
-
- store.suspendEvents();
-
- var rootnode = me.store.getRootNode();
- // remember selected node (and all parents)
- var sm = me.getSelectionModel();
-
- var lastsel = sm.getSelection()[0];
- var reselect = false;
- var parents = [];
- var p = lastsel;
- while (p && !!(p = p.parentNode)) {
- parents.push(p);
- }
-
- var index = pdata.dataIndex;
-
- var groups = me.viewFilter.groups || [];
- var filterfn = me.viewFilter.filterfn;
-
- // remove vanished or moved items
- // update in place changed items
- var key;
- for (key in index) {
- if (index.hasOwnProperty(key)) {
- var olditem = index[key];
-
- // getById() use find(), which is slow (ExtJS4 DP5)
- //var item = rstore.getById(olditem.data.id);
- var item = rstore.data.get(olditem.data.id);
-
- var changed = false;
- var moved = false;
- if (item) {
- // test if any grouping attributes changed
- // this will also catch migrated nodes
- // in server view
- var i, len;
- for (i = 0, len = groups.length; i < len; i++) {
- var attr = groups[i];
- if (item.data[attr] != olditem.data[attr]) {
- //console.log("changed " + attr);
- moved = true;
- break;
- }
- }
-
- // explicitly check for node, since
- // in some views, node is not a grouping
- // attribute
- if (!moved && item.data.node !== olditem.data.node) {
- moved = true;
- }
-
- // tree item has been updated
- var fields = [
- 'text', 'running', 'template', 'status',
- 'qmpstatus', 'hastate', 'lock'
- ];
-
- var field;
- for (i = 0; i < fields.length; i++) {
- field = fields[i];
- if (item.data[field] !== olditem.data[field]) {
- changed = true;
- break;
- }
- }
-
- // fixme: also test filterfn()?
- }
-
- if (changed) {
- olditem.beginEdit();
- //console.log("REM UPDATE UID: " + key + " ITEM " + item.data.running);
- var info = olditem.data;
- Ext.apply(info, item.data);
- me.setIconCls(info);
- me.setText(info);
- me.setToolTip(info);
- olditem.commit();
- }
- if ((!item || moved) && olditem.isLeaf()) {
- //console.log("REM UID: " + key + " ITEM " + olditem.data.id);
- delete index[key];
- var parentNode = olditem.parentNode;
- // when the selected item disappears,
- // we have to deselect it here, and reselect it
- // later
- if (lastsel && olditem.data.id === lastsel.data.id) {
- reselect = true;
- sm.deselect(olditem);
- }
- // since the store events are suspended, we
- // manually remove the item from the store also
- store.remove(olditem);
- parentNode.removeChild(olditem, true);
- }
- }
- }
-
- // add new items
- rstore.each(function(item) {
- var olditem = index[item.data.id];
- if (olditem) {
- return;
- }
-
- if (filterfn && !filterfn(item)) {
- return;
- }
-
- //console.log("ADD UID: " + item.data.id);
-
- var info = Ext.apply({ leaf: true }, item.data);
-
- var child = me.groupChild(rootnode, info, groups, 0);
- if (child) {
- index[item.data.id] = child;
- }
- });
-
- store.resumeEvents();
- store.fireEvent('refresh', store);
-
- // select parent node is selection vanished
- if (lastsel && !rootnode.findChild('id', lastsel.data.id, true)) {
- lastsel = rootnode;
- while (!!(p = parents.shift())) {
- if (!!(tmp = rootnode.findChild('id', p.data.id, true))) {
- lastsel = tmp;
- break;
- }
- }
- me.selectById(lastsel.data.id);
- } else if (lastsel && reselect) {
- me.selectById(lastsel.data.id);
- }
-
- // on first tree load set the selection from the stateful provider
- if (!pdata.updateCount) {
- rootnode.expand();
- me.applyState(sp.get(stateid));
- }
-
- pdata.updateCount++;
- };
-
- var statechange = function(sp, key, value) {
- if (key === stateid) {
- me.applyState(value);
- }
- };
-
- sp.on('statechange', statechange);
-
- Ext.apply(me, {
- allowSelection: true,
- store: store,
- viewConfig: {
- // note: animate cause problems with applyState
- animate: false
- },
- //useArrows: true,
- //rootVisible: false,
- //title: 'Resource Tree',
- listeners: {
- itemcontextmenu: PVE.Utils.createCmdMenu,
- destroy: function() {
- rstore.un("load", updateTree);
- },
- beforecellmousedown: function (tree, td, cellIndex, record, tr, rowIndex, ev) {
- var sm = me.getSelectionModel();
- // disable selection when right clicking
- // except the record is already selected
- me.allowSelection = (ev.button !== 2) || sm.isSelected(record);
- },
- beforeselect: function (tree, record, index, eopts) {
- var allow = me.allowSelection;
- me.allowSelection = true;
- return allow;
- },
- itemdblclick: PVE.Utils.openTreeConsole
- },
- setViewFilter: function(view) {
- me.viewFilter = view;
- me.clearTree();
- updateTree();
- },
- setDatacenterText: function(clustername) {
- var rootnode = me.store.getRootNode();
-
- var rnodeText = gettext('Datacenter');
- if (clustername !== undefined) {
- rnodeText += ' (' + clustername + ')';
- }
-
- rootnode.beginEdit();
- rootnode.data.text = rnodeText;
- rootnode.commit();
- },
- clearTree: function() {
- pdata.updateCount = 0;
- var rootnode = me.store.getRootNode();
- rootnode.collapse();
- rootnode.removeAll();
- pdata.dataIndex = {};
- me.getSelectionModel().deselectAll();
- },
- selectExpand: function(node) {
- var sm = me.getSelectionModel();
- if (!sm.isSelected(node)) {
- sm.select(node);
- var cn = node;
- while (!!(cn = cn.parentNode)) {
- if (!cn.isExpanded()) {
- cn.expand();
- }
- }
- me.getView().focusRow(node);
- }
- },
- selectById: function(nodeid) {
- var rootnode = me.store.getRootNode();
- var sm = me.getSelectionModel();
- var node;
- if (nodeid === 'root') {
- node = rootnode;
- } else {
- node = rootnode.findChild('id', nodeid, true);
- }
- if (node) {
- me.selectExpand(node);
- }
- return node;
- },
- applyState : function(state) {
- var sm = me.getSelectionModel();
- if (state && state.value) {
- me.selectById(state.value);
- } else {
- sm.deselectAll();
- }
- }
- });
-
- me.callParent();
-
- var sm = me.getSelectionModel();
- sm.on('select', function(sm, n) {
- sp.set(stateid, { value: n.data.id});
- });
-
- rstore.on("load", updateTree);
- rstore.startUpdate();
- //rstore.stopUpdate();
- }
-
-});
-Ext.define('pve-fw-ipsets', {
- extend: 'Ext.data.Model',
- fields: [ 'name', 'comment', 'digest' ],
- idProperty: 'name'
-});
-
-Ext.define('PVE.IPSetList', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveIPSetList',
-
- stateful: true,
- stateId: 'grid-firewall-ipsetlist',
-
- ipset_panel: undefined,
-
- base_url: undefined,
-
- addBtn: undefined,
- removeBtn: undefined,
- editBtn: undefined,
-
- initComponent: function() {
-
- var me = this;
-
- if (me.ipset_panel == undefined) {
- throw "no rule panel specified";
- }
-
- if (me.base_url == undefined) {
- throw "no base_url specified";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-fw-ipsets',
- proxy: {
- type: 'proxmox',
- url: "/api2/json" + me.base_url
- },
- sorters: {
- property: 'name',
- order: 'DESC'
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- var oldrec = sm.getSelection()[0];
- store.load(function(records, operation, success) {
- if (oldrec) {
- var rec = store.findRecord('name', oldrec.data.name);
- if (rec) {
- sm.select(rec);
- }
- }
- });
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var win = Ext.create('Proxmox.window.Edit', {
- subject: "IPSet '" + rec.data.name + "'",
- url: me.base_url,
- method: 'POST',
- digest: rec.data.digest,
- items: [
- {
- xtype: 'hiddenfield',
- name: 'rename',
- value: rec.data.name
- },
- {
- xtype: 'textfield',
- name: 'name',
- value: rec.data.name,
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'comment',
- value: rec.data.comment,
- fieldLabel: gettext('Comment')
- }
- ]
- });
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = new Proxmox.button.Button({
- text: gettext('Create'),
- handler: function() {
- sm.deselectAll();
- var win = Ext.create('Proxmox.window.Edit', {
- subject: 'IPSet',
- url: me.base_url,
- method: 'POST',
- items: [
- {
- xtype: 'textfield',
- name: 'name',
- value: '',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'comment',
- value: '',
- fieldLabel: gettext('Comment')
- }
- ]
- });
- win.show();
- win.on('destroy', reload);
-
- }
- });
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: me.base_url + '/',
- callback: reload
- });
-
- Ext.apply(me, {
- store: store,
- tbar: [ 'IPSet: ', me.addBtn, me.removeBtn, me.editBtn ],
- selModel: sm,
- columns: [
- { header: 'IPSet', dataIndex: 'name', width: '100' },
- { header: gettext('Comment'), dataIndex: 'comment', renderer: Ext.String.htmlEncode, flex: 1 }
- ],
- listeners: {
- itemdblclick: run_editor,
- select: function(sm, rec) {
- var url = me.base_url + '/' + rec.data.name;
- me.ipset_panel.setBaseUrl(url);
- },
- deselect: function() {
- me.ipset_panel.setBaseUrl(undefined);
- },
- show: reload
- }
- });
-
- me.callParent();
-
- store.load();
- }
-});
-
-Ext.define('PVE.IPSetCidrEdit', {
- extend: 'Proxmox.window.Edit',
-
- cidr: undefined,
-
- initComponent : function() {
-
- var me = this;
-
- me.isCreate = (me.cidr === undefined);
-
-
- if (me.isCreate) {
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs' + me.base_url + '/' + me.cidr;
- me.method = 'PUT';
- }
-
- var column1 = [];
-
- if (me.isCreate) {
- if (!me.list_refs_url) {
- throw "no alias_base_url specified";
- }
-
- column1.push({
- xtype: 'pveIPRefSelector',
- name: 'cidr',
- ref_type: 'alias',
- autoSelect: false,
- editable: true,
- base_url: me.list_refs_url,
- value: '',
- fieldLabel: gettext('IP/CIDR')
- });
- } else {
- column1.push({
- xtype: 'displayfield',
- name: 'cidr',
- value: '',
- fieldLabel: gettext('IP/CIDR')
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- isCreate: me.isCreate,
- column1: column1,
- column2: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'nomatch',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: 'nomatch'
- }
- ],
- columnB: [
- {
- xtype: 'textfield',
- name: 'comment',
- value: '',
- fieldLabel: gettext('Comment')
- }
- ]
- });
-
- Ext.apply(me, {
- subject: gettext('IP/CIDR'),
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-
-Ext.define('PVE.IPSetGrid', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveIPSetGrid',
-
- stateful: true,
- stateId: 'grid-firewall-ipsets',
-
- base_url: undefined,
- list_refs_url: undefined,
-
- addBtn: undefined,
- removeBtn: undefined,
- editBtn: undefined,
-
- setBaseUrl: function(url) {
- var me = this;
-
- me.base_url = url;
-
- if (url === undefined) {
- me.addBtn.setDisabled(true);
- me.store.removeAll();
- } else {
- me.addBtn.setDisabled(false);
- me.removeBtn.baseurl = url + '/';
- me.store.setProxy({
- type: 'proxmox',
- url: '/api2/json' + url
- });
-
- me.store.load();
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.list_refs_url) {
- throw "no1 list_refs_url specified";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-ipset'
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var win = Ext.create('PVE.IPSetCidrEdit', {
- base_url: me.base_url,
- cidr: rec.data.cidr
- });
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = new Proxmox.button.Button({
- text: gettext('Add'),
- disabled: true,
- handler: function() {
- if (!me.base_url) {
- return;
- }
- var win = Ext.create('PVE.IPSetCidrEdit', {
- base_url: me.base_url,
- list_refs_url: me.list_refs_url
- });
- win.show();
- win.on('destroy', reload);
- }
- });
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: me.base_url + '/',
- callback: reload
- });
-
- var render_errors = function(value, metaData, record) {
- var errors = record.data.errors;
- if (errors) {
- var msg = errors.cidr || errors.nomatch;
- if (msg) {
- metaData.tdCls = 'proxmox-invalid-row';
- var html = '' + Ext.htmlEncode(msg) + '
';
- metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
- html.replace(/\"/g,'"') + '"';
- }
- }
- return value;
- };
-
- Ext.apply(me, {
- tbar: [ 'IP/CIDR: ', me.addBtn, me.removeBtn, me.editBtn ],
- store: store,
- selModel: sm,
- listeners: {
- itemdblclick: run_editor
- },
- columns: [
- {
- xtype: 'rownumberer'
- },
- {
- header: gettext('IP/CIDR'),
- dataIndex: 'cidr',
- width: 150,
- renderer: function(value, metaData, record) {
- value = render_errors(value, metaData, record);
- if (record.data.nomatch) {
- return '! ' + value;
- }
- return value;
- }
- },
- {
- header: gettext('Comment'),
- dataIndex: 'comment',
- flex: 1,
- renderer: function(value) {
- return Ext.util.Format.htmlEncode(value);
- }
- }
- ]
- });
-
- me.callParent();
-
- if (me.base_url) {
- me.setBaseUrl(me.base_url); // load
- }
- }
-}, function() {
-
- Ext.define('pve-ipset', {
- extend: 'Ext.data.Model',
- fields: [ { name: 'nomatch', type: 'boolean' },
- 'cidr', 'comment', 'errors' ],
- idProperty: 'cidr'
- });
-
-});
-
-Ext.define('PVE.IPSet', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveIPSet',
-
- title: 'IPSet',
-
- onlineHelp: 'pve_firewall_ip_sets',
-
- list_refs_url: undefined,
-
- initComponent: function() {
- var me = this;
-
- if (!me.list_refs_url) {
- throw "no list_refs_url specified";
- }
-
- var ipset_panel = Ext.createWidget('pveIPSetGrid', {
- region: 'center',
- list_refs_url: me.list_refs_url,
- border: false
- });
-
- var ipset_list = Ext.createWidget('pveIPSetList', {
- region: 'west',
- ipset_panel: ipset_panel,
- base_url: me.base_url,
- width: '50%',
- border: false,
- split: true
- });
-
- Ext.apply(me, {
- layout: 'border',
- items: [ ipset_list, ipset_panel ],
- listeners: {
- show: function() {
- ipset_list.fireEvent('show', ipset_list);
- }
- }
- });
-
- me.callParent();
- }
-});
-/*
- * Base class for all the multitab config panels
- *
- * How to use this:
- *
- * You create a subclass of this, and then define your wanted tabs
- * as items like this:
- *
- * items: [{
- * title: "myTitle",
- * xytpe: "somextype",
- * iconCls: 'fa fa-icon',
- * groups: ['somegroup'],
- * expandedOnInit: true,
- * itemId: 'someId'
- * }]
- *
- * this has to be in the declarative syntax, else we
- * cannot save them for later
- * (so no Ext.create or Ext.apply of an item in the subclass)
- *
- * the groups array expects the itemids of the items
- * which are the parents, which have to come before they
- * are used
- *
- * if you want following the tree:
- *
- * Option1
- * Option2
- * -> SubOption1
- * -> SubSubOption1
- *
- * the suboption1 group array has to look like this:
- * groups: ['itemid-of-option2']
- *
- * and of subsuboption1:
- * groups: ['itemid-of-option2', 'itemid-of-suboption1']
- *
- * setting the expandedOnInit determines if the item/group is expanded
- * initially (false by default)
- */
-Ext.define('PVE.panel.Config', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pvePanelConfig',
-
- showSearch: true, // add a resource grid with a search button as first tab
- viewFilter: undefined, // a filter to pass to that resource grid
-
- tbarSpacing: true, // if true, adds a spacer after the title in tbar
-
- dockedItems: [{
- // this is needed for the overflow handler
- xtype: 'toolbar',
- overflowHandler: 'scroller',
- dock: 'left',
- style: {
- backgroundColor: '#f5f5f5',
- padding: 0,
- margin: 0
- },
- items: {
- xtype: 'treelist',
- itemId: 'menu',
- ui: 'nav',
- expanderOnly: true,
- expanderFirst: false,
- animation: false,
- singleExpand: false,
- listeners: {
- selectionchange: function(treeList, selection) {
- var me = this.up('panel');
- me.suspendLayout = true;
- me.activateCard(selection.data.id);
- me.suspendLayout = false;
- me.updateLayout();
- },
- itemclick: function(treelist, info) {
- var olditem = treelist.getSelection();
- var newitem = info.node;
-
- // when clicking on the expand arrow,
- // we don't select items, but still want
- // the original behaviour
- if (info.select === false) {
- return;
- }
-
- // if you click on a different item which is open,
- // leave it open
- // else toggle the clicked item
- if (olditem.data.id !== newitem.data.id &&
- newitem.data.expanded === true) {
- info.toggle = false;
- } else {
- info.toggle = true;
- }
- }
- }
- }
- },
- {
- xtype: 'toolbar',
- itemId: 'toolbar',
- dock: 'top',
- height: 36,
- overflowHandler: 'scroller'
- }],
-
- firstItem: '',
- layout: 'card',
- border: 0,
-
- // used for automated test
- selectById: function(cardid) {
- var me = this;
-
- var root = me.store.getRoot();
- var selection = root.findChild('id', cardid, true);
-
- if (selection) {
- selection.expand();
- var menu = me.down('#menu');
- menu.setSelection(selection);
- return cardid;
- }
- },
-
- activateCard: function(cardid) {
- var me = this;
- if (me.savedItems[cardid]) {
- var curcard = me.getLayout().getActiveItem();
- var newcard = me.add(me.savedItems[cardid]);
- me.helpButton.setOnlineHelp(newcard.onlineHelp || me.onlineHelp);
- if (curcard) {
- me.setActiveItem(cardid);
- me.remove(curcard, true);
-
- // trigger state change
-
- var ncard = cardid;
- // Note: '' is alias for first tab.
- // First tab can be 'search' or something else
- if (cardid === me.firstItem) {
- ncard = '';
- }
- if (me.hstateid) {
- me.sp.set(me.hstateid, { value: ncard });
- }
- }
- }
- },
-
- initComponent: function() {
- var me = this;
-
- var stateid = me.hstateid;
-
- me.sp = Ext.state.Manager.getProvider();
-
- var activeTab; // leaving this undefined means items[0] will be the default tab
-
- if (stateid) {
- var state = me.sp.get(stateid);
- if (state && state.value) {
- // if this tab does not exists, it chooses the first
- activeTab = state.value;
- }
- }
-
- // get title
- var title = me.title || me.pveSelNode.data.text;
- me.title = undefined;
-
- // create toolbar
- var tbar = me.tbar || [];
- me.tbar = undefined;
-
- if (!me.onlineHelp) {
- switch(me.pveSelNode.data.id) {
- case 'type/storage':me.onlineHelp = 'chapter-pvesm.html'; break;
- case 'type/qemu':me.onlineHelp = 'chapter-qm.html'; break;
- case 'type/lxc':me.onlineHelp = 'chapter-pct.html'; break;
- case 'type/pool':me.onlineHelp = 'chapter-pveum.html#_pools'; break;
- case 'type/node':me.onlineHelp = 'chapter-sysadmin.html'; break;
- }
- }
-
- if (me.tbarSpacing) {
- tbar.unshift('->');
- }
- tbar.unshift({
- xtype: 'tbtext',
- text: title,
- baseCls: 'x-panel-header-text'
- });
-
- me.helpButton = Ext.create('Proxmox.button.Help', {
- hidden: false,
- listenToGlobalEvent: false,
- onlineHelp: me.onlineHelp || undefined
- });
-
- tbar.push(me.helpButton);
-
- me.dockedItems[1].items = tbar;
-
- // include search tab
- me.items = me.items || [];
- if (me.showSearch) {
- me.items.unshift({
- itemId: 'search',
- title: gettext('Search'),
- iconCls: 'fa fa-search',
- xtype: 'pveResourceGrid',
- pveSelNode: me.pveSelNode
- });
- }
-
- me.savedItems = {};
- /*jslint confusion:true*/
- if (me.items[0]) {
- me.firstItem = me.items[0].itemId;
- }
- /*jslint confusion:false*/
-
- me.store = Ext.create('Ext.data.TreeStore', {
- root: {
- expanded: true
- }
- });
- var root = me.store.getRoot();
- me.items.forEach(function(item){
- var treeitem = Ext.create('Ext.data.TreeModel',{
- id: item.itemId,
- text: item.title,
- iconCls: item.iconCls,
- leaf: true,
- expanded: item.expandedOnInit
- });
- item.header = false;
- if (me.savedItems[item.itemId] !== undefined) {
- throw "itemId already exists, please use another";
- }
- me.savedItems[item.itemId] = item;
-
- var group;
- var curnode = root;
-
- // get/create the group items
- while (Ext.isArray(item.groups) && item.groups.length > 0) {
- group = item.groups.shift();
-
- var child = curnode.findChild('id', group);
- if (child === null) {
- // did not find the group item
- // so add it where we are
- break;
- }
- curnode = child;
- }
-
- // insert the item
-
- // lets see if it already exists
- var node = curnode.findChild('id', item.itemId);
-
- if (node === null) {
- curnode.appendChild(treeitem);
- } else {
- // should not happen!
- throw "id already exists";
- }
- });
-
- delete me.items;
- me.defaults = me.defaults || {};
- Ext.apply(me.defaults, {
- pveSelNode: me.pveSelNode,
- viewFilter: me.viewFilter,
- workspace: me.workspace,
- border: 0
- });
-
- me.callParent();
-
- var menu = me.down('#menu');
- var selection = root.findChild('id', activeTab, true) || root.firstChild;
- var node = selection;
- while (node !== root) {
- node.expand();
- node = node.parentNode;
- }
- menu.setStore(me.store);
- menu.setSelection(selection);
-
- // on a state change,
- // select the new item
- var statechange = function(sp, key, state) {
- // it the state change is for this panel
- if (stateid && (key === stateid) && state) {
- // get active item
- var acard = me.getLayout().getActiveItem().itemId;
- // get the itemid of the new value
- var ncard = state.value || me.firstItem;
- if (ncard && (acard != ncard)) {
- // select the chosen item
- menu.setSelection(root.findChild('id', ncard, true) || root.firstChild);
- }
- }
- };
-
- if (stateid) {
- me.mon(me.sp, 'statechange', statechange);
- }
- }
-});
-Ext.define('PVE.grid.BackupView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveBackupView'],
-
- onlineHelp: 'chapter_vzdump',
-
- stateful: true,
- stateId: 'grid-guest-backup',
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var vmtype = me.pveSelNode.data.type;
- if (!vmtype) {
- throw "no VM type specified";
- }
-
- var vmtypeFilter;
- if (vmtype === 'openvz') {
- vmtypeFilter = function(item) {
- return item.data.volid.match(':backup/vzdump-openvz-');
- };
- } else if (vmtype === 'lxc') {
- vmtypeFilter = function(item) {
- return item.data.volid.match(':backup/vzdump-lxc-');
- };
- } else if (vmtype === 'qemu') {
- vmtypeFilter = function(item) {
- return item.data.volid.match(':backup/vzdump-qemu-');
- };
- } else {
- throw "unsupported VM type '" + vmtype + "'";
- }
-
- var searchFilter = {
- property: 'volid',
- // on initial store display only our vmid backups
- // surround with minus sign to prevent the 2016 VMID bug
- value: vmtype + '-' + vmid + '-',
- anyMatch: true,
- caseSensitive: false
- };
-
- me.store = Ext.create('Ext.data.Store', {
- model: 'pve-storage-content',
- sorters: {
- property: 'volid',
- order: 'DESC'
- },
- filters: [
- vmtypeFilter,
- searchFilter
- ]
- });
-
- var reload = Ext.Function.createBuffered(function() {
- if (me.store) {
- me.store.load();
- }
- }, 100);
-
- var setStorage = function(storage) {
- var url = '/api2/json/nodes/' + nodename + '/storage/' + storage + '/content';
- url += '?content=backup';
-
- me.store.setProxy({
- type: 'proxmox',
- url: url
- });
-
- reload();
- };
-
- var storagesel = Ext.create('PVE.form.StorageSelector', {
- nodename: nodename,
- fieldLabel: gettext('Storage'),
- labelAlign: 'right',
- storageContent: 'backup',
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- setStorage(value);
- }
- }
- });
-
- var storagefilter = Ext.create('Ext.form.field.Text', {
- fieldLabel: gettext('Search'),
- labelWidth: 50,
- labelAlign: 'right',
- enableKeyEvents: true,
- value: searchFilter.value,
- listeners: {
- buffer: 500,
- keyup: function(field) {
- me.store.clearFilter(true);
- searchFilter.value = field.getValue();
- me.store.filter([
- vmtypeFilter,
- searchFilter
- ]);
- }
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var backup_btn = Ext.create('Ext.button.Button', {
- text: gettext('Backup now'),
- handler: function() {
- var win = Ext.create('PVE.window.Backup', {
- nodename: nodename,
- vmid: vmid,
- vmtype: vmtype,
- storage: storagesel.getValue(),
- listeners : {
- close: function() {
- reload();
- }
- }
- });
- win.show();
- }
- });
-
- var restore_btn = Ext.create('Proxmox.button.Button', {
- text: gettext('Restore'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- return !!rec;
- },
- handler: function(b, e, rec) {
- var volid = rec.data.volid;
-
- var win = Ext.create('PVE.window.Restore', {
- nodename: nodename,
- vmid: vmid,
- volid: rec.data.volid,
- volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
- vmtype: vmtype
- });
- win.show();
- win.on('destroy', reload);
- }
- });
-
- var delete_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- dangerous: true,
- confirmMsg: function(rec) {
- var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.volid + "'");
- msg += " " + gettext('This will permanently erase all data.');
-
- return msg;
- },
- getUrl: function(rec) {
- var storage = storagesel.getValue();
- return '/nodes/' + nodename + '/storage/' + storage + '/content/' + rec.data.volid;
- },
- callback: function() {
- reload();
- }
- });
-
- var config_btn = Ext.create('Proxmox.button.Button', {
- text: gettext('Show Configuration'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- return !!rec;
- },
- handler: function(b, e, rec) {
- var storage = storagesel.getValue();
- if (!storage) {
- return;
- }
-
- var win = Ext.create('PVE.window.BackupConfig', {
- volume: rec.data.volid,
- pveSelNode: me.pveSelNode
- });
-
- win.show();
- }
- });
-
- Ext.apply(me, {
- selModel: sm,
- tbar: [ backup_btn, restore_btn, delete_btn,config_btn, '->', storagesel, storagefilter ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- renderer: PVE.Utils.render_storage_content,
- dataIndex: 'volid'
- },
- {
- header: gettext('Format'),
- width: 100,
- dataIndex: 'format'
- },
- {
- header: gettext('Size'),
- width: 100,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- }
- ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.CephCreateService', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCephCreateService',
-
- showProgress: true,
-
- setNode: function(nodename) {
- var me = this;
-
- me.nodename = nodename;
- me.url = "/nodes/" + nodename + "/ceph/" + me.type + "/" + nodename;
- },
-
- method: 'POST',
- isCreate: true,
-
- items: [
- {
- xtype: 'pveNodeSelector',
- submitValue: false,
- fieldLabel: gettext('Host'),
- selectCurNode: true,
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- var me = this.up('pveCephCreateService');
- me.setNode(value);
- }
- }
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.type) {
- throw "no type specified";
- }
-
- me.setNode(me.nodename);
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.CephServiceList', {
- extend: 'Ext.grid.GridPanel',
- xtype: 'pveNodeCephServiceList',
-
- onlineHelp: 'chapter_pveceph',
- emptyText: gettext('No such service configured.'),
-
- stateful: true,
-
- // will be called when the store loads
- storeLoadCallback: Ext.emptyFn,
-
- // if set to true, does shows the ceph install mask if needed
- showCephInstallMask: false,
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- if (view.pveSelNode) {
- view.nodename = view.pveSelNode.data.node;
- }
- if (!view.nodename) {
- throw "no node name specified";
- }
-
- if (!view.type) {
- throw "no type specified";
- }
-
- view.rstore = Ext.create('Proxmox.data.UpdateStore', {
- autoLoad: true,
- autoStart: true,
- interval: 3000,
- storeid: 'ceph-' + view.type + '-list' + view.nodename,
- model: 'ceph-service-list',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + view.nodename + "/ceph/" + view.type
- }
- });
-
- view.setStore(Ext.create('Proxmox.data.DiffStore', {
- rstore: view.rstore,
- sorters: [{ property: 'name' }]
- }));
-
- if (view.storeLoadCallback) {
- view.rstore.on('load', view.storeLoadCallback, this);
- }
- view.on('destroy', view.rstore.stopUpdate);
-
- if (view.showCephInstallMask) {
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error) {
- view.rstore.stopUpdate();
- PVE.Utils.showCephInstallOrMask(view.ownerCt, error.statusText, view.nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- view.rstore.startUpdate();
- });
- }
- );
- });
- }
- },
-
- service_cmd: function(rec, cmd) {
- var view = this.getView();
- if (!rec.data.host) {
- Ext.Msg.alert(gettext('Error'), "entry has no host");
- return;
- }
- Proxmox.Utils.API2Request({
- url: "/nodes/" + rec.data.host + "/ceph/" + cmd,
- method: 'POST',
- params: { service: view.type + '.' + rec.data.name },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid,
- taskDone: function() {
- view.rstore.load();
- }
- });
- win.show();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
- onChangeService: function(btn) {
- var me = this;
- var view = this.getView();
- var cmd = btn.action;
- var rec = view.getSelection()[0];
- me.service_cmd(rec, cmd);
- },
-
- showSyslog: function() {
- var view = this.getView();
- var rec = view.getSelection()[0];
- var servicename = 'ceph-' + view.type + '@' + rec.data.name;
- var url = "/api2/extjs/nodes/" + rec.data.host + "/syslog?service=" + encodeURIComponent(servicename);
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Syslog') + ': ' + servicename,
- modal: true,
- width: 800,
- height: 400,
- layout: 'fit',
- items: [{
- xtype: 'proxmoxLogView',
- url: url,
- log_select_timespan: 1
- }]
- });
- win.show();
- },
-
- onCreate: function() {
- var view = this.getView();
- var win = Ext.create('PVE.CephCreateService', {
- autoShow: true,
- nodename: view.nodename,
- subject: view.getTitle(),
- type: view.type,
- taskDone: function() {
- view.rstore.load();
- }
- });
- }
- },
-
- tbar: [
- {
- xtype: 'proxmoxButton',
- text: gettext('Start'),
- iconCls: 'fa fa-play',
- action: 'start',
- disabled: true,
- enableFn: function(rec) {
- return rec.data.state === 'stopped' ||
- rec.data.state === 'unknown';
- },
- handler: 'onChangeService'
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Stop'),
- iconCls: 'fa fa-stop',
- action: 'stop',
- enableFn: function(rec) {
- return rec.data.state !== 'stopped';
- },
- disabled: true,
- handler: 'onChangeService'
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Restart'),
- iconCls: 'fa fa-refresh',
- action: 'restart',
- disabled: true,
- enableFn: function(rec) {
- return rec.data.state !== 'stopped';
- },
- handler: 'onChangeService'
- },
- '-',
- {
- text: gettext('Create'),
- reference: 'createButton',
- handler: 'onCreate'
- },
- {
- text: gettext('Destroy'),
- xtype: 'proxmoxStdRemoveButton',
- getUrl: function(rec) {
- var view = this.up('grid');
- if (!rec.data.host) {
- Ext.Msg.alert(gettext('Error'), "entry has no host");
- return;
- }
- return "/nodes/" + rec.data.host + "/ceph/" + view.type + "/" + rec.data.name;
- },
- callback: function(options, success, response) {
- var view = this.up('grid');
- if (!success) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- return;
- }
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid,
- taskDone: function() {
- view.rstore.load();
- }
- });
- win.show();
- }
- },
- '-',
- {
- xtype: 'proxmoxButton',
- text: gettext('Syslog'),
- disabled: true,
- handler: 'showSyslog'
- }
- ],
-
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- renderer: function(v) {
- return this.type + '.' + v;
- },
- dataIndex: 'name'
- },
- {
- header: gettext('Host'),
- flex: 1,
- sortable: true,
- renderer: function(v) {
- return v || Proxmox.Utils.unknownText;
- },
- dataIndex: 'host'
- },
- {
- header: gettext('Status'),
- flex: 1,
- sortable: false,
- dataIndex: 'state'
- },
- {
- header: gettext('Address'),
- flex: 3,
- sortable: true,
- renderer: function(v) {
- return v || Proxmox.Utils.unknownText;
- },
- dataIndex: 'addr'
- },
- {
- header: gettext('Version'),
- flex: 3,
- sortable: true,
- dataIndex: 'version'
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (me.additionalColumns) {
- me.columns = me.columns.concat(me.additionalColumns);
- }
-
- me.callParent();
- }
-
-}, function() {
-
- Ext.define('ceph-service-list', {
- extend: 'Ext.data.Model',
- fields: [ 'addr', 'name', 'rank', 'host', 'quorum', 'state',
- 'ceph_version', 'ceph_version_short',
- { type: 'string', name: 'version', calculate: function(data) {
- return PVE.Utils.parse_ceph_version(data);
- } }
- ],
- idProperty: 'name'
- });
-});
-/*jslint confusion: true */
-Ext.define('PVE.CephCreateFS', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveCephCreateFS',
-
- showTaskViewer: true,
- onlineHelp: 'pveceph_fs_create',
-
- subject: 'Ceph FS',
- isCreate: true,
- method: 'POST',
-
- setFSName: function(fsName) {
- var me = this;
-
- if (fsName === '' || fsName === undefined) {
- fsName = 'cephfs';
- }
-
- me.url = "/nodes/" + me.nodename + "/ceph/fs/" + fsName;
- },
-
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Name'),
- name: 'name',
- value: 'cephfs',
- listeners: {
- change: function(f, value) {
- this.up('pveCephCreateFS').setFSName(value);
- }
- },
- submitValue: false, // already encoded in apicall URL
- emptyText: 'cephfs'
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: 'Placement Groups',
- name: 'pg_num',
- value: 128,
- emptyText: 128,
- minValue: 8,
- maxValue: 32768,
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Add as Storage'),
- value: true,
- name: 'add-storage',
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext('Add the new CephFS to the cluster storage configuration.'),
- },
- }
- ],
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
- me.setFSName();
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.NodeCephFSPanel', {
- extend: 'Ext.panel.Panel',
- xtype: 'pveNodeCephFSPanel',
- mixins: ['Proxmox.Mixin.CBind'],
-
- title: gettext('CephFS'),
- onlineHelp: 'pveceph_fs',
-
- border: false,
- defaults: {
- border: false,
- cbind: {
- nodename: '{nodename}'
- }
- },
-
- viewModel: {
- parent: null,
- data: {
- cephfsConfigured: false,
- mdsCount: 0
- },
- formulas: {
- canCreateFS: function(get) {
- return (!get('cephfsConfigured') && get('mdsCount') > 0);
- }
- }
- },
-
- items: [
- {
- xtype: 'grid',
- emptyText: Ext.String.format(gettext('No {0} configured.'), 'CephFS'),
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.rstore = Ext.create('Proxmox.data.UpdateStore', {
- autoLoad: true,
- xtype: 'update',
- interval: 5 * 1000,
- autoStart: true,
- storeid: 'pve-ceph-fs',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + view.nodename + '/ceph/fs'
- },
- model: 'pve-ceph-fs'
- });
- view.setStore(Ext.create('Proxmox.data.DiffStore', {
- rstore: view.rstore,
- sorters: {
- property: 'name',
- order: 'DESC'
- }
- }));
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error){
- me.rstore.stopUpdate();
- PVE.Utils.showCephInstallOrMask(me.ownerCt, error.statusText, view.nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.rstore.startUpdate();
- });
- }
- );
- });
- view.rstore.on('load', this.onLoad, this);
- view.on('destroy', view.rstore.stopUpdate);
- },
-
- onCreate: function() {
- var view = this.getView();
- view.rstore.stopUpdate();
- var win = Ext.create('PVE.CephCreateFS', {
- autoShow: true,
- nodename: view.nodename,
- listeners: {
- destroy: function() {
- view.rstore.startUpdate();
- }
- }
- });
- },
-
- onLoad: function(store, records, success) {
- var vm = this.getViewModel();
- if (!(success && records && records.length > 0)) {
- vm.set('cephfsConfigured', false);
- return;
- }
- vm.set('cephfsConfigured', true);
- }
- },
- tbar: [
- {
- text: gettext('Create CephFS'),
- reference: 'createButton',
- handler: 'onCreate',
- bind: {
- // only one CephFS per Ceph cluster makes sense for now
- disabled: '{!canCreateFS}'
- }
- }
- ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- dataIndex: 'name'
- },
- {
- header: 'Data Pool',
- flex: 1,
- dataIndex: 'data_pool'
- },
- {
- header: 'Metadata Pool',
- flex: 1,
- dataIndex: 'metadata_pool'
- }
- ],
- cbind: {
- nodename: '{nodename}'
- }
- },
- {
- xtype: 'pveNodeCephServiceList',
- title: gettext('Metadata Servers'),
- stateId: 'grid-ceph-mds',
- type: 'mds',
- storeLoadCallback: function(store, records, success) {
- var vm = this.getViewModel();
- if (!success || !records) {
- vm.set('mdsCount', 0);
- return;
- }
- vm.set('mdsCount', records.length);
- },
- cbind: {
- nodename: '{nodename}'
- }
- }
- ]
-}, function() {
- Ext.define('pve-ceph-fs', {
- extend: 'Ext.data.Model',
- fields: [ 'name', 'data_pool', 'metadata_pool' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/localhost/ceph/fs"
- },
- idProperty: 'name'
- });
-});
-Ext.define('PVE.CephCreatePool', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveCephCreatePool',
-
- showProgress: true,
- onlineHelp: 'pve_ceph_pools',
-
- subject: 'Ceph Pool',
- isCreate: true,
- method: 'POST',
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Name'),
- name: 'name',
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Size'),
- name: 'size',
- value: 3,
- minValue: 1,
- maxValue: 7,
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Min. Size'),
- name: 'min_size',
- value: 2,
- minValue: 1,
- maxValue: 7,
- allowBlank: false
- },
- {
- xtype: 'pveCephRuleSelector',
- fieldLabel: 'Crush Rule', // do not localize
- name: 'crush_rule',
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: 'pg_num',
- name: 'pg_num',
- value: 128,
- minValue: 8,
- maxValue: 32768,
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Add as Storage'),
- value: true,
- name: 'add_storages',
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext('Add the new pool to the cluster storage configuration.'),
- },
- }
- ],
- initComponent : function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- url: "/nodes/" + me.nodename + "/ceph/pools",
- defaults: {
- nodename: me.nodename
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.CephPoolList', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pveNodeCephPoolList',
-
- onlineHelp: 'chapter_pveceph',
-
- stateful: true,
- stateId: 'grid-ceph-pools',
- bufferedRenderer: false,
-
- features: [ { ftype: 'summary'} ],
-
- columns: [
- {
- header: gettext('Name'),
- width: 120,
- sortable: true,
- dataIndex: 'pool_name'
- },
- {
- header: gettext('Size') + '/min',
- width: 100,
- align: 'right',
- renderer: function(v, meta, rec) {
- return v + '/' + rec.data.min_size;
- },
- dataIndex: 'size'
- },
- {
- text: '# Placement Groups', // pg_num',
- width: 180,
- align: 'right',
- dataIndex: 'pg_num'
- },
- {
- text: 'CRUSH Rule',
- columns: [
- {
- text: 'ID',
- align: 'right',
- width: 50,
- dataIndex: 'crush_rule'
- },
- {
- text: gettext('Name'),
- width: 150,
- dataIndex: 'crush_rule_name',
- },
- ]
- },
- {
- text: gettext('Used'),
- columns: [
- {
- text: '%',
- width: 100,
- sortable: true,
- align: 'right',
- renderer: function(val) {
- return Ext.util.Format.percent(val, '0.00');
- },
- dataIndex: 'percent_used',
- summaryType: 'sum',
- summaryRenderer: function(val) {
- return Ext.util.Format.percent(val, '0.00');
- },
- },
- {
- text: gettext('Total'),
- width: 100,
- sortable: true,
- renderer: PVE.Utils.render_size,
- align: 'right',
- dataIndex: 'bytes_used',
- summaryType: 'sum',
- summaryRenderer: PVE.Utils.render_size
- }
- ]
- }
- ],
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var rstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 3000,
- storeid: 'ceph-pool-list' + nodename,
- model: 'ceph-pool-list',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/ceph/pools"
- }
- });
-
- var store = Ext.create('Proxmox.data.DiffStore', { rstore: rstore });
-
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(me, rstore, regex, function(me, error){
- me.store.rstore.stopUpdate();
- PVE.Utils.showCephInstallOrMask(me, error.statusText, nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.store.rstore.startUpdate();
- });
- }
- );
- });
-
- var create_btn = new Ext.Button({
- text: gettext('Create'),
- handler: function() {
- var win = Ext.create('PVE.CephCreatePool', {
- nodename: nodename
- });
- win.show();
- win.on('destroy', function() {
- rstore.load();
- });
- }
- });
-
- var destroy_btn = Ext.create('Proxmox.button.Button', {
- text: gettext('Destroy'),
- selModel: sm,
- disabled: true,
- handler: function() {
- var rec = sm.getSelection()[0];
-
- if (!rec.data.pool_name) {
- return;
- }
- var base_url = '/nodes/' + nodename + '/ceph/pools/' +
- rec.data.pool_name;
-
- var win = Ext.create('PVE.window.SafeDestroy', {
- showProgress: true,
- url: base_url,
- params: {
- remove_storages: 1
- },
- item: { type: 'CephPool', id: rec.data.pool_name }
- }).show();
- win.on('destroy', function() {
- rstore.load();
- });
- }
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [ create_btn, destroy_btn ],
- listeners: {
- activate: rstore.startUpdate,
- destroy: rstore.stopUpdate
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('ceph-pool-list', {
- extend: 'Ext.data.Model',
- fields: [ 'pool_name',
- { name: 'pool', type: 'integer'},
- { name: 'size', type: 'integer'},
- { name: 'min_size', type: 'integer'},
- { name: 'pg_num', type: 'integer'},
- { name: 'bytes_used', type: 'integer'},
- { name: 'percent_used', type: 'number'},
- { name: 'crush_rule', type: 'integer'},
- { name: 'crush_rule_name', type: 'string'}
- ],
- idProperty: 'pool_name'
- });
-});
-
-Ext.define('PVE.form.CephRuleSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveCephRuleSelector',
-
- allowBlank: false,
- valueField: 'name',
- displayField: 'name',
- editable: false,
- queryMode: 'local',
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: ['name'],
- sorters: 'name',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/ceph/rules'
- }
- });
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
-
- store.load({
- callback: function(rec, op, success){
- if (success && rec.length > 0) {
- me.select(rec[0]);
- }
- }
- });
- }
-
-});
-Ext.define('PVE.CephCreateOsd', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCephCreateOsd',
-
- subject: 'Ceph OSD',
-
- showProgress: true,
-
- onlineHelp: 'pve_ceph_osds',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/ceph/osd",
- method: 'POST',
- items: [
- {
- xtype: 'inputpanel',
- onGetValues: function(values) {
- Object.keys(values || {}).forEach(function(name) {
- if (values[name] === '') {
- delete values[name];
- }
- });
-
- return values;
- },
- column1: [
- {
- xtype: 'pveDiskSelector',
- name: 'dev',
- nodename: me.nodename,
- diskType: 'unused',
- fieldLabel: gettext('Disk'),
- allowBlank: false
- }
- ],
- column2: [
- {
- xtype: 'pveDiskSelector',
- name: 'db_dev',
- nodename: me.nodename,
- diskType: 'journal_disks',
- fieldLabel: gettext('DB Disk'),
- value: '',
- autoSelect: false,
- allowBlank: true,
- emptyText: 'use OSD disk',
- listeners: {
- change: function(field, val) {
- me.down('field[name=db_size]').setDisabled(!val);
- }
- }
- },
- {
- xtype: 'numberfield',
- name: 'db_size',
- fieldLabel: gettext('DB size') + ' (GiB)',
- minValue: 1,
- maxValue: 128*1024,
- decimalPrecision: 2,
- allowBlank: true,
- disabled: true,
- emptyText: gettext('Automatic')
- }
- ],
- advancedColumn1: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'encrypted',
- fieldLabel: gettext('Encrypt OSD')
- },
- ],
- advancedColumn2: [
- {
- xtype: 'pveDiskSelector',
- name: 'wal_dev',
- nodename: me.nodename,
- diskType: 'journal_disks',
- fieldLabel: gettext('WAL Disk'),
- value: '',
- autoSelect: false,
- allowBlank: true,
- emptyText: 'use OSD/DB disk',
- listeners: {
- change: function(field, val) {
- me.down('field[name=wal_size]').setDisabled(!val);
- }
- }
- },
- {
- xtype: 'numberfield',
- name: 'wal_size',
- fieldLabel: gettext('WAL size') + ' (GiB)',
- minValue: 0.5,
- maxValue: 128*1024,
- decimalPrecision: 2,
- allowBlank: true,
- disabled: true,
- emptyText: gettext('Automatic')
- }
- ]
- },
- {
- xtype: 'displayfield',
- padding: '5 0 0 0',
- userCls: 'pve-hint',
- value: 'Note: Ceph is not compatible with disks backed by a hardware ' +
- 'RAID controller. For details see ' +
- 'the reference documentation .',
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.CephRemoveOsd', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveCephRemoveOsd'],
-
- isRemove: true,
-
- showProgress: true,
- method: 'DELETE',
- items: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'cleanup',
- checked: true,
- labelWidth: 130,
- fieldLabel: gettext('Cleanup Disks')
- }
- ],
- initComponent : function() {
-
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
- if (me.osdid === undefined || me.osdid < 0) {
- throw "no osdid specified";
- }
-
- me.isCreate = true;
-
- me.title = gettext('Destroy') + ': Ceph OSD osd.' + me.osdid.toString();
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/ceph/osd/" + me.osdid.toString()
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.CephOsdTree', {
- extend: 'Ext.tree.Panel',
- alias: ['widget.pveNodeCephOsdTree'],
- onlineHelp: 'chapter_pveceph',
-
- viewModel: {
- data: {
- nodename: '',
- flags: [],
- maxversion: '0',
- versions: {},
- isOsd: false,
- downOsd: false,
- upOsd: false,
- inOsd: false,
- outOsd: false,
- osdid: '',
- osdhost: '',
- }
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- reload: function() {
- var me = this.getView();
- var vm = this.getViewModel();
- var nodename = vm.get('nodename');
- var sm = me.getSelectionModel();
- Proxmox.Utils.API2Request({
- url: "/nodes/" + nodename + "/ceph/osd",
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- var msg = response.htmlStatus;
- PVE.Utils.showCephInstallOrMask(me, msg, nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', this.reload);
- }
- );
- },
- success: function(response, opts) {
- var data = response.result.data;
- var selected = me.getSelection();
- var name;
- if (selected.length) {
- name = selected[0].data.name;
- }
- vm.set('versions', data.versions);
- // extract max version
- var maxversion = vm.get('maxversion');
- Object.values(data.versions || {}).forEach(function(version) {
- if (PVE.Utils.compare_ceph_versions(version, maxversion) > 0) {
- maxversion = version;
- }
- });
- vm.set('maxversion', maxversion);
- sm.deselectAll();
- me.setRootNode(data.root);
- me.expandAll();
- if (name) {
- var node = me.getRootNode().findChild('name', name, true);
- if (node) {
- me.setSelection([node]);
- }
- }
-
- var flags = data.flags.split(',');
- vm.set('flags', flags);
- var noout = flags.includes('noout');
- me.down('#nooutBtn').setText(noout ? gettext("Unset noout") : gettext("Set noout"));
- }
- });
- },
-
- osd_cmd: function(comp) {
- var me = this;
- var vm = this.getViewModel();
- var cmd = comp.cmd;
- var params = comp.params || {};
- var osdid = vm.get('osdid');
-
- var doRequest = function() {
- Proxmox.Utils.API2Request({
- url: "/nodes/" + vm.get('osdhost') + "/ceph/osd/" + osdid + '/' + cmd,
- waitMsgTarget: me.getView(),
- method: 'POST',
- params: params,
- success: () => { me.reload(); },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- if (cmd === 'scrub') {
- Ext.MessageBox.defaultButton = params.deep === 1 ? 2 : 1;
- Ext.Msg.show({
- title: gettext('Confirm'),
- icon: params.deep === 1 ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
- msg: params.deep !== 1 ?
- Ext.String.format(gettext("Scrub OSD.{0}"), osdid) :
- Ext.String.format(gettext("Deep Scrub OSD.{0}"), osdid) +
- " Caution: This can reduce performance while it is running.",
- buttons: Ext.Msg.YESNO,
- callback: function(btn) {
- if (btn !== 'yes') {
- return;
- }
- doRequest();
- }
- });
- } else {
- doRequest();
- }
- },
-
- create_osd: function() {
- var me = this;
- var vm = this.getViewModel();
- Ext.create('PVE.CephCreateOsd', {
- nodename: vm.get('nodename'),
- taskDone: () => { me.reload(); }
- }).show();
- },
-
- destroy_osd: function() {
- var me = this;
- var vm = this.getViewModel();
- Ext.create('PVE.CephRemoveOsd', {
- nodename: vm.get('osdhost'),
- osdid: vm.get('osdid'),
- taskDone: () => { me.reload(); }
- }).show();
- },
-
- set_flag: function() {
- var me = this;
- var vm = this.getViewModel();
- var flags = vm.get('flags');
- Proxmox.Utils.API2Request({
- url: "/nodes/" + vm.get('nodename') + "/ceph/flags/noout",
- waitMsgTarget: me.getView(),
- method: flags.includes('noout') ? 'DELETE' : 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: () => { me.reload(); }
- });
- },
-
- service_cmd: function(comp) {
- var me = this;
- var vm = this.getViewModel();
- var cmd = comp.cmd || comp;
- Proxmox.Utils.API2Request({
- url: "/nodes/" + vm.get('osdhost') + "/ceph/" + cmd,
- params: { service: "osd." + vm.get('osdid') },
- waitMsgTarget: me.getView(),
- method: 'POST',
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid,
- taskDone: () => { me.reload(); }
- });
- win.show();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- set_selection_status: function(tp, selection) {
- if (selection.length < 1) {
- return;
- }
- var rec = selection[0];
- var vm = this.getViewModel();
-
- var isOsd = (rec.data.host && (rec.data.type === 'osd') && (rec.data.id >= 0));
-
- vm.set('isOsd', isOsd);
- vm.set('downOsd', isOsd && rec.data.status === 'down');
- vm.set('upOsd', isOsd && rec.data.status !== 'down');
- vm.set('inOsd', isOsd && rec.data.in);
- vm.set('outOsd', isOsd && !rec.data.in);
- vm.set('osdid', isOsd ? rec.data.id : undefined);
- vm.set('osdhost', isOsd ? rec.data.host : undefined);
- },
-
- render_status: function(value, metaData, rec) {
- if (!value) {
- return value;
- }
- var inout = rec.data['in'] ? 'in' : 'out';
- var updownicon = value === 'up' ? 'good fa-arrow-circle-up' :
- 'critical fa-arrow-circle-down';
-
- var inouticon = rec.data['in'] ? 'good fa-circle' :
- 'warning fa-circle-o';
-
- var text = value + ' / ' +
- inout + ' ';
-
- return text;
- },
-
- render_wal: function(value, metaData, rec) {
- if (!value &&
- rec.data.osdtype === 'bluestore' &&
- rec.data.type === 'osd') {
- return 'N/A';
- }
- return value;
- },
-
- render_version: function(value, metadata, rec) {
- var vm = this.getViewModel();
- var versions = vm.get('versions');
- var icon = "";
- var version = value || "";
- if (value && value != vm.get('maxversion')) {
- icon = PVE.Utils.get_ceph_icon_html('HEALTH_OLD');
- }
-
- if (!value && rec.data.type == 'host') {
- version = versions[rec.data.name] || Proxmox.Utils.unknownText;
- }
-
- return icon + version;
- },
-
- render_osd_val: function(value, metaData, rec) {
- return (rec.data.type === 'osd') ? value : '';
- },
- render_osd_weight: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- return Ext.util.Format.number(value, '0.00###');
- },
-
- render_osd_latency: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- let commit_ms = rec.data.commit_latency_ms,
- apply_ms = rec.data.apply_latency_ms;
- return apply_ms + ' / ' + commit_ms;
- },
-
- render_osd_size: function(value, metaData, rec) {
- return this.render_osd_val(PVE.Utils.render_size(value), metaData, rec);
- },
-
- control: {
- '#': {
- selectionchange: 'set_selection_status'
- }
- },
-
- init: function(view) {
- var me = this;
- var vm = this.getViewModel();
-
- if (!view.pveSelNode.data.node) {
- throw "no node name specified";
- }
-
- vm.set('nodename', view.pveSelNode.data.node);
-
- me.callParent();
- me.reload();
- }
- },
-
- stateful: true,
- stateId: 'grid-ceph-osd',
- rootVisible: false,
- useArrows: true,
-
- columns: [
- {
- xtype: 'treecolumn',
- text: 'Name',
- dataIndex: 'name',
- width: 150
- },
- {
- text: 'Type',
- dataIndex: 'type',
- hidden: true,
- align: 'right',
- width: 75
- },
- {
- text: gettext("Class"),
- dataIndex: 'device_class',
- align: 'right',
- width: 75
- },
- {
- text: "OSD Type",
- dataIndex: 'osdtype',
- align: 'right',
- width: 100
- },
- {
- text: "Bluestore Device",
- dataIndex: 'blfsdev',
- align: 'right',
- width: 75,
- hidden: true
- },
- {
- text: "DB Device",
- dataIndex: 'dbdev',
- align: 'right',
- width: 75,
- hidden: true
- },
- {
- text: "WAL Device",
- dataIndex: 'waldev',
- align: 'right',
- renderer: 'render_wal',
- width: 75,
- hidden: true
- },
- {
- text: 'Status',
- dataIndex: 'status',
- align: 'right',
- renderer: 'render_status',
- width: 120
- },
- {
- text: gettext('Version'),
- dataIndex: 'version',
- align: 'right',
- renderer: 'render_version'
- },
- {
- text: 'weight',
- dataIndex: 'crush_weight',
- align: 'right',
- renderer: 'render_osd_weight',
- width: 90
- },
- {
- text: 'reweight',
- dataIndex: 'reweight',
- align: 'right',
- renderer: 'render_osd_weight',
- width: 90
- },
- {
- text: gettext('Used') + ' (%)',
- dataIndex: 'percent_used',
- align: 'right',
- renderer: function(value, metaData, rec) {
- if (rec.data.type !== 'osd') {
- return '';
- }
- return Ext.util.Format.number(value, '0.00');
- },
- width: 100
- },
- {
- text: gettext('Total'),
- dataIndex: 'total_space',
- align: 'right',
- renderer: 'render_osd_size',
- width: 100
- },
- {
- text: 'Apply/Commit Latency (ms)',
- dataIndex: 'apply_latency_ms',
- align: 'right',
- renderer: 'render_osd_latency',
- width: 120
- }
- ],
-
-
- tbar: {
- items: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: 'reload'
- },
- '-',
- {
- text: gettext('Create') + ': OSD',
- handler: 'create_osd',
- },
- {
- text: gettext('Set noout'),
- itemId: 'nooutBtn',
- handler: 'set_flag',
- },
- '->',
- {
- xtype: 'tbtext',
- data: {
- osd: undefined
- },
- bind: {
- data: {
- osd: "{osdid}"
- }
- },
- tpl: [
- '',
- 'osd.{osd}:',
- '',
- gettext('No OSD selected'),
- ' '
- ]
- },
- {
- text: gettext('Start'),
- iconCls: 'fa fa-play',
- disabled: true,
- bind: {
- disabled: '{!downOsd}'
- },
- cmd: 'start',
- handler: 'service_cmd'
- },
- {
- text: gettext('Stop'),
- iconCls: 'fa fa-stop',
- disabled: true,
- bind: {
- disabled: '{!upOsd}'
- },
- cmd: 'stop',
- handler: 'service_cmd'
- },
- {
- text: gettext('Restart'),
- iconCls: 'fa fa-refresh',
- disabled: true,
- bind: {
- disabled: '{!upOsd}'
- },
- cmd: 'restart',
- handler: 'service_cmd'
- },
- '-',
- {
- text: 'Out',
- iconCls: 'fa fa-circle-o',
- disabled: true,
- bind: {
- disabled: '{!inOsd}'
- },
- cmd: 'out',
- handler: 'osd_cmd'
- },
- {
- text: 'In',
- iconCls: 'fa fa-circle',
- disabled: true,
- bind: {
- disabled: '{!outOsd}'
- },
- cmd: 'in',
- handler: 'osd_cmd'
- },
- '-',
- {
- text: gettext('More'),
- iconCls: 'fa fa-bars',
- disabled: true,
- bind: {
- disabled: '{!isOsd}'
- },
- menu: [
- {
- text: gettext('Scrub'),
- iconCls: 'fa fa-shower',
- cmd: 'scrub',
- handler: 'osd_cmd'
- },
- {
- text: gettext('Deep Scrub'),
- iconCls: 'fa fa-bath',
- cmd: 'scrub',
- params: {
- deep: 1,
- },
- handler: 'osd_cmd'
- },
- {
- text: gettext('Destroy'),
- itemId: 'remove',
- iconCls: 'fa fa-fw fa-trash-o',
- bind: {
- disabled: '{!downOsd}'
- },
- handler: 'destroy_osd'
- }
- ],
- }
- ]
- },
-
- fields: [
- 'name', 'type', 'status', 'host', 'in', 'id' ,
- { type: 'number', name: 'reweight' },
- { type: 'number', name: 'percent_used' },
- { type: 'integer', name: 'bytes_used' },
- { type: 'integer', name: 'total_space' },
- { type: 'integer', name: 'apply_latency_ms' },
- { type: 'integer', name: 'commit_latency_ms' },
- { type: 'string', name: 'device_class' },
- { type: 'string', name: 'osdtype' },
- { type: 'string', name: 'blfsdev' },
- { type: 'string', name: 'dbdev' },
- { type: 'string', name: 'waldev' },
- { type: 'string', name: 'version', calculate: function(data) {
- return PVE.Utils.parse_ceph_version(data);
- } },
- { type: 'string', name: 'iconCls', calculate: function(data) {
- var iconMap = {
- host: 'fa-building',
- osd: 'fa-hdd-o',
- root: 'fa-server',
- };
- return 'fa x-fa-tree ' + iconMap[data.type];
- } },
- { type: 'number', name: 'crush_weight' }
- ],
-});
-Ext.define('PVE.node.CephMonMgrList', {
- extend: 'Ext.container.Container',
- xtype: 'pveNodeCephMonMgr',
-
- mixins: ['Proxmox.Mixin.CBind' ],
-
- onlineHelp: 'chapter_pveceph',
-
- defaults: {
- border: false,
- onlineHelp: 'chapter_pveceph',
- flex: 1
- },
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- items: [
- {
- xtype: 'pveNodeCephServiceList',
- cbind: { pveSelNode: '{pveSelNode}' },
- type: 'mon',
- additionalColumns: [
- {
- header: gettext('Quorum'),
- width: 70,
- sortable: true,
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'quorum'
- }
- ],
- stateId: 'grid-ceph-monitor',
- showCephInstallMask: true,
- title: gettext('Monitor')
- },
- {
- xtype: 'pveNodeCephServiceList',
- type: 'mgr',
- stateId: 'grid-ceph-manager',
- cbind: { pveSelNode: '{pveSelNode}' },
- title: gettext('Manager')
- }
- ]
-});
-Ext.define('PVE.node.CephCrushMap', {
- extend: 'Ext.panel.Panel',
- alias: ['widget.pveNodeCephCrushMap'],
- bodyStyle: 'white-space:pre',
- bodyPadding: 5,
- border: false,
- stateful: true,
- stateId: 'layout-ceph-crush',
- scrollable: true,
- load: function() {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: me.url,
- waitMsgTarget: me,
- failure: function(response, opts) {
- me.update(gettext('Error') + " " + response.htmlStatus);
- var msg = response.htmlStatus;
- PVE.Utils.showCephInstallOrMask(me.ownerCt, msg, me.pveSelNode.data.node,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.load();
- });
- }
- );
- },
- success: function(response, opts) {
- var data = response.result.data;
- me.update(Ext.htmlEncode(data));
- }
- });
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- url: '/nodes/' + nodename + '/ceph/crush',
-
- listeners: {
- activate: function() {
- me.load();
- }
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('PVE.node.CephStatus', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNodeCephStatus',
-
- onlineHelp: 'chapter_pveceph',
-
- scrollable: true,
-
- bodyPadding: 5,
-
- layout: {
- type: 'column'
- },
-
- defaults: {
- padding: 5
- },
-
- items: [
- {
- xtype: 'panel',
- title: gettext('Health'),
- bodyPadding: 10,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- minHeight: 230,
- columnWidth: 1
- },
- 'width >= 1900': {
- minHeight: 500,
- columnWidth: 0.5
- }
- },
- layout: {
- type: 'hbox',
- align: 'stretch'
- },
- items: [
- {
- flex: 1,
- itemId: 'overallhealth',
- xtype: 'pveHealthWidget',
- title: gettext('Status')
- },
- {
- flex: 2,
- itemId: 'warnings',
- stateful: true,
- stateId: 'ceph-status-warnings',
- xtype: 'grid',
- // since we load the store manually,
- // to show the emptytext, we have to
- // specify an empty store
- store: { data:[] },
- emptyText: gettext('No Warnings/Errors'),
- columns: [
- {
- dataIndex: 'severity',
- header: gettext('Severity'),
- align: 'center',
- width: 70,
- renderer: function(value) {
- var health = PVE.Utils.map_ceph_health[value];
- var classes = PVE.Utils.get_health_icon(health);
-
- return ' ';
- },
- sorter: {
- sorterFn: function(a,b) {
- var healthArr = ['HEALTH_ERR', 'HEALTH_WARN', 'HEALTH_OK'];
- return healthArr.indexOf(b.data.severity) - healthArr.indexOf(a.data.severity);
- }
- }
- },
- {
- dataIndex: 'summary',
- header: gettext('Summary'),
- flex: 1
- },
- {
- xtype: 'actioncolumn',
- width: 40,
- align: 'center',
- tooltip: gettext('Detail'),
- items: [
- {
- iconCls: 'x-fa fa-info-circle',
- handler: function(grid, rowindex, colindex, item, e, record) {
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Detail'),
- resizable: true,
- modal: true,
- width: 650,
- height: 400,
- layout: {
- type: 'fit'
- },
- items: [{
- scrollable: true,
- padding: 10,
- xtype: 'box',
- html: [
- '' + Ext.htmlEncode(record.data.summary) + ' ',
- '' + Ext.htmlEncode(record.data.detail) + ' '
- ]
- }]
- });
- win.show();
- }
- }
- ]
- }
- ]
- }
- ]
- },
- {
- xtype: 'pveCephStatusDetail',
- itemId: 'statusdetail',
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1,
- minHeight: 250
- },
- 'width >= 1900': {
- columnWidth: 0.5,
- minHeight: 300
- }
- },
- title: gettext('Status')
- },
- {
- title: gettext('Services'),
- xtype: 'pveCephServices',
- itemId: 'services',
- plugins: 'responsive',
- layout: {
- type: 'hbox',
- align: 'stretch'
- },
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1,
- minHeight: 200
- },
- 'width >= 1900': {
- columnWidth: 0.5,
- minHeight: 200
- }
- }
- },
- {
- xtype: 'panel',
- title: gettext('Performance'),
- columnWidth: 1,
- bodyPadding: 5,
- layout: {
- type: 'hbox',
- align: 'center'
- },
- items: [
- {
- flex: 1,
- xtype: 'proxmoxGauge',
- itemId: 'space',
- title: gettext('Usage')
- },
- {
- flex: 2,
- xtype: 'container',
- defaults: {
- padding: 0,
- height: 100
- },
- items: [
- {
- itemId: 'reads',
- xtype: 'pveRunningChart',
- title: gettext('Reads'),
- renderer: PVE.Utils.render_bandwidth
- },
- {
- itemId: 'writes',
- xtype: 'pveRunningChart',
- title: gettext('Writes'),
- renderer: PVE.Utils.render_bandwidth
- },
- {
- itemId: 'iops',
- xtype: 'pveRunningChart',
- hidden: true,
- title: 'IOPS', // do not localize
- renderer: Ext.util.Format.numberRenderer('0,000')
- },
- {
- itemId: 'readiops',
- xtype: 'pveRunningChart',
- hidden: true,
- title: 'IOPS: ' + gettext('Reads'),
- renderer: Ext.util.Format.numberRenderer('0,000')
- },
- {
- itemId: 'writeiops',
- xtype: 'pveRunningChart',
- hidden: true,
- title: 'IOPS: ' + gettext('Writes'),
- renderer: Ext.util.Format.numberRenderer('0,000')
- }
- ]
- }
- ]
- }
- ],
-
- generateCheckData: function(health) {
- var result = [];
- var checks = health.checks || {};
- var keys = Ext.Object.getKeys(checks).sort();
-
- Ext.Array.forEach(keys, function(key) {
- var details = checks[key].detail || [];
- result.push({
- id: key,
- summary: checks[key].summary.message,
- detail: Ext.Array.reduce(
- checks[key].detail,
- function(first, second) {
- return first + '\n' + second.message;
- },
- ''
- ),
- severity: checks[key].severity
- });
- });
-
- return result;
- },
-
- updateAll: function(store, records, success) {
- if (!success || records.length === 0) {
- return;
- }
-
- var me = this;
- var rec = records[0];
- me.status = rec.data;
-
- // add health panel
- me.down('#overallhealth').updateHealth(PVE.Utils.render_ceph_health(rec.data.health || {}));
- // add errors to gridstore
- me.down('#warnings').getStore().loadRawData(me.generateCheckData(rec.data.health || {}), false);
-
- // update services
- me.getComponent('services').updateAll(me.metadata || {}, rec.data);
-
- // update detailstatus panel
- me.getComponent('statusdetail').updateAll(me.metadata || {}, rec.data);
-
- // add performance data
- var used = rec.data.pgmap.bytes_used;
- var total = rec.data.pgmap.bytes_total;
-
- var text = Ext.String.format(gettext('{0} of {1}'),
- PVE.Utils.render_size(used),
- PVE.Utils.render_size(total)
- );
-
- // update the usage widget
- me.down('#space').updateValue(used/total, text);
-
- // TODO: logic for jewel (iops split in read/write)
-
- var iops = rec.data.pgmap.op_per_sec;
- var readiops = rec.data.pgmap.read_op_per_sec;
- var writeiops = rec.data.pgmap.write_op_per_sec;
- var reads = rec.data.pgmap.read_bytes_sec || 0;
- var writes = rec.data.pgmap.write_bytes_sec || 0;
-
- if (iops !== undefined && me.version !== 'hammer') {
- me.change_version('hammer');
- } else if((readiops !== undefined || writeiops !== undefined) && me.version !== 'jewel') {
- me.change_version('jewel');
- }
- // update the graphs
- me.reads.addDataPoint(reads);
- me.writes.addDataPoint(writes);
- me.iops.addDataPoint(iops);
- me.readiops.addDataPoint(readiops);
- me.writeiops.addDataPoint(writeiops);
- },
-
- change_version: function(version) {
- var me = this;
- me.version = version;
- me.sp.set('ceph-version', version);
- me.iops.setVisible(version === 'hammer');
- me.readiops.setVisible(version === 'jewel');
- me.writeiops.setVisible(version === 'jewel');
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
-
- me.callParent();
- var baseurl = '/api2/json' + (nodename ? '/nodes/' + nodename : '/cluster') + '/ceph';
- me.store = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'ceph-status-' + (nodename || 'cluster'),
- interval: 5000,
- proxy: {
- type: 'proxmox',
- url: baseurl + '/status'
- }
- });
-
- me.metadatastore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'ceph-metadata-' + (nodename || 'cluster'),
- interval: 15*1000,
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/ceph/metadata'
- }
- });
-
- // save references for the updatefunction
- me.iops = me.down('#iops');
- me.readiops = me.down('#readiops');
- me.writeiops = me.down('#writeiops');
- me.reads = me.down('#reads');
- me.writes = me.down('#writes');
-
- // get ceph version
- me.sp = Ext.state.Manager.getProvider();
- me.version = me.sp.get('ceph-version');
- me.change_version(me.version);
-
- var regex = new RegExp("not (installed|initialized)", "i");
- PVE.Utils.handleStoreErrorOrMask(me, me.store, regex, function(me, error){
- me.store.stopUpdate();
- PVE.Utils.showCephInstallOrMask(me, error.statusText, (nodename || 'localhost'),
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.store.startUpdate();
- });
- }
- );
- });
-
- me.mon(me.store, 'load', me.updateAll, me);
- me.mon(me.metadatastore, 'load', function(store, records, success) {
- if (!success || records.length < 1) {
- return;
- }
- var rec = records[0];
- me.metadata = rec.data;
-
- // update services
- me.getComponent('services').updateAll(rec.data, me.status || {});
-
- // update detailstatus panel
- me.getComponent('statusdetail').updateAll(rec.data, me.status || {});
-
- }, me);
-
- me.on('destroy', me.store.stopUpdate);
- me.on('destroy', me.metadatastore.stopUpdate);
- me.store.startUpdate();
- me.metadatastore.startUpdate();
- }
-
-});
-Ext.define('PVE.ceph.StatusDetail', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveCephStatusDetail',
-
- layout: {
- type: 'hbox',
- align: 'stretch'
- },
-
- bodyPadding: '0 5',
- defaults: {
- xtype: 'box',
- style: {
- 'text-align':'center'
- }
- },
-
- items: [{
- flex: 1,
- itemId: 'osds',
- maxHeight: 250,
- scrollable: true,
- padding: '0 10 5 10',
- data: {
- total: 0,
- upin: 0,
- upout: 0,
- downin: 0,
- downout: 0,
- oldosds: []
- },
- tpl: [
- '' + 'OSDs' + ' ',
- '',
- ' ',
- ' ',
- gettext('In'),
- ' ',
- ' ',
- gettext('Out'),
- ' ',
- ' ',
- '',
- ' ',
- gettext('Up'),
- ' ',
- '{upin} ',
- '{upout} ',
- ' ',
- '',
- ' ',
- gettext('Down'),
- ' ',
- '{downin} ',
- '{downout} ',
- ' ',
- '
',
- '',
- gettext('Total'),
- ': {total}',
- '
',
- '',
- ' ' + gettext('Outdated OSDs') + " ",
- '',
- '
',
- 'osd.{id}:
',
- '{version}
',
- '
',
- ' ',
- '
',
- ' '
- ]
- },
- {
- flex: 1,
- border: false,
- itemId: 'pgchart',
- xtype: 'polar',
- height: 184,
- innerPadding: 5,
- insetPadding: 5,
- colors: [
- '#CFCFCF',
- '#21BF4B',
- '#FFCC00',
- '#FF6C59'
- ],
- store: { },
- series: [
- {
- type: 'pie',
- donut: 60,
- angleField: 'count',
- tooltip: {
- trackMouse: true,
- renderer: function(tooltip, record, ctx) {
- var html = record.get('text');
- html += ' ';
- record.get('states').forEach(function(state) {
- html += ' ' +
- state.state_name + ': ' + state.count.toString();
- });
- tooltip.setHtml(html);
- }
- },
- subStyle: {
- strokeStyle: false
- }
- }
- ]
- },
- {
- flex: 1.6,
- itemId: 'pgs',
- padding: '0 10',
- maxHeight: 250,
- scrollable: true,
- data: {
- states: []
- },
- tpl: [
- '' + 'PGs' + ' ',
- '',
- ' {state_name}:
',
- '{count}
',
- '
',
- ' '
- ]
- }],
-
- // similar to mgr dashboard
- pgstates: {
- // clean
- clean: 1,
- active: 1,
-
- // working
- activating: 2,
- backfill_wait: 2,
- backfilling: 2,
- creating: 2,
- deep: 2,
- degraded: 2,
- forced_backfill: 2,
- forced_recovery: 2,
- peered: 2,
- peering: 2,
- recovering: 2,
- recovery_wait: 2,
- repair: 2,
- scrubbing: 2,
- snaptrim: 2,
- snaptrim_wait: 2,
-
- // error
- backfill_toofull: 3,
- backfill_unfound: 3,
- down: 3,
- incomplete: 3,
- inconsistent: 3,
- recovery_toofull: 3,
- recovery_unfound: 3,
- remapped: 3,
- snaptrim_error: 3,
- stale: 3,
- undersized: 3
- },
-
- statecategories: [
- {
- text: gettext('Unknown'),
- count: 0,
- states: [],
- cls: 'faded'
- },
- {
- text: gettext('Clean'),
- cls: 'good'
- },
- {
- text: gettext('Working'),
- cls: 'warning'
- },
- {
- text: gettext('Error'),
- cls: 'critical'
- }
- ],
-
- updateAll: function(metadata, status) {
- var me = this;
- me.suspendLayout = true;
-
- var maxversion = "0";
- Object.values(metadata.version || {}).forEach(function(version) {
- if (PVE.Utils.compare_ceph_versions(version, maxversion) > 0) {
- maxversion = version;
- }
- });
-
- var oldosds = [];
-
- if (metadata.osd) {
- metadata.osd.forEach(function(osd) {
- var version = PVE.Utils.parse_ceph_version(osd);
- if (version != maxversion) {
- oldosds.push({
- id: osd.id,
- version: version
- });
- }
- });
- }
-
- var pgmap = status.pgmap || {};
- var health = status.health || {};
- var osdmap = status.osdmap || { osdmap: {} };
-
-
- // update pgs sorted
- var pgs_by_state = pgmap.pgs_by_state || [];
- pgs_by_state.sort(function(a,b){
- return (a.state_name < b.state_name)?-1:(a.state_name === b.state_name)?0:1;
- });
-
- me.statecategories.forEach(function(cat) {
- cat.count = 0;
- cat.states = [];
- });
-
- pgs_by_state.forEach(function(state) {
- var i;
- var states = state.state_name.split(/[^a-z]+/);
- var result = 0;
- for (i = 0; i < states.length; i++) {
- if (me.pgstates[states[i]] > result) {
- result = me.pgstates[states[i]];
- }
- }
- // for the list
- state.cls = me.statecategories[result].cls;
-
- me.statecategories[result].count += state.count;
- me.statecategories[result].states.push(state);
- });
-
- me.getComponent('pgchart').getStore().setData(me.statecategories);
- me.getComponent('pgs').update({states: pgs_by_state});
-
- var downinregex = /(\d+) osds down/;
- var downin_osds = 0;
-
- // we collect monitor/osd information from the checks
- Ext.Object.each(health.checks, function(key, value, obj) {
- var found = null;
- if (key === 'OSD_DOWN') {
- found = value.summary.message.match(downinregex);
- if (found !== null) {
- downin_osds = parseInt(found[1],10);
- }
- }
- });
-
- // update osds counts
-
- var total_osds = osdmap.osdmap.num_osds || 0;
- var in_osds = osdmap.osdmap.num_in_osds || 0;
- var up_osds = osdmap.osdmap.num_up_osds || 0;
- var out_osds = total_osds - in_osds;
- var down_osds = total_osds - up_osds;
-
- var downout_osds = down_osds - downin_osds;
- var upin_osds = in_osds - downin_osds;
- var upout_osds = up_osds - upin_osds;
- var osds = {
- total: total_osds,
- upin: upin_osds,
- upout: upout_osds,
- downin: downin_osds,
- downout: downout_osds,
- oldosds: oldosds
- };
- var osdcomponent = me.getComponent('osds');
- osdcomponent.update(Ext.apply(osdcomponent.data, osds));
-
- me.suspendLayout = false;
- me.updateLayout();
- }
-});
-
-Ext.define('PVE.ceph.Services', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveCephServices',
-
- layout: {
- type: 'hbox',
- align: 'stretch'
- },
-
- bodyPadding: '0 5 20',
- defaults: {
- xtype: 'box',
- style: {
- 'text-align':'center'
- }
- },
-
- items: [
- {
- flex: 1,
- xtype: 'pveCephServiceList',
- itemId: 'mons',
- title: gettext('Monitors')
- },
- {
- flex: 1,
- xtype: 'pveCephServiceList',
- itemId: 'mgrs',
- title: gettext('Managers')
- },
- {
- flex: 1,
- xtype: 'pveCephServiceList',
- itemId: 'mdss',
- title: gettext('Meta Data Servers')
- }
- ],
-
- updateAll: function(metadata, status) {
- var me = this;
-
- var healthstates = {
- 'HEALTH_UNKNOWN': 0,
- 'HEALTH_ERR': 1,
- 'HEALTH_WARN': 2,
- 'HEALTH_OLD': 3,
- 'HEALTH_OK': 4
- };
- var healthmap = [
- 'HEALTH_UNKNOWN',
- 'HEALTH_ERR',
- 'HEALTH_WARN',
- 'HEALTH_OLD',
- 'HEALTH_OK'
- ];
- var reduceFn = function(first, second) {
- return first + '\n' + second.message;
- };
- var services = ['mon','mgr','mds'];
- var maxversion = "00.0.00";
- Object.values(metadata.version || {}).forEach(function(version) {
- if (PVE.Utils.compare_ceph_versions(version, maxversion) > 0) {
- maxversion = version;
- }
- });
- var i;
- var quorummap = (status && status.quorum_names) ? status.quorum_names : [];
- var monmessages = {};
- var mgrmessages = {};
- var mdsmessages = {};
- if (status) {
- if (status.health) {
- Ext.Object.each(status.health.checks, function(key, value, obj) {
- if (!Ext.String.startsWith(key, "MON_")) {
- return;
- }
-
- var i;
- for (i = 0; i < value.detail.length; i++) {
- var match = value.detail[i].message.match(/mon.([a-zA-Z0-9\-\.]+)/);
- if (!match) {
- continue;
- }
- var monid = match[1];
-
- if (!monmessages[monid]) {
- monmessages[monid] = {
- worstSeverity: healthstates.HEALTH_OK,
- messages: []
- };
- }
-
-
- monmessages[monid].messages.push(
- PVE.Utils.get_ceph_icon_html(value.severity, true) +
- Ext.Array.reduce(value.detail, reduceFn, '')
- );
- if (healthstates[value.severity] < monmessages[monid].worstSeverity) {
- monmessages[monid].worstSeverity = healthstates[value.severity];
- }
- }
- });
- }
-
- if (status.mgrmap) {
- mgrmessages[status.mgrmap.active_name] = "active";
- status.mgrmap.standbys.forEach(function(mgr) {
- mgrmessages[mgr.name] = "standby";
- });
- }
-
- if (status.fsmap) {
- status.fsmap.by_rank.forEach(function(mds) {
- mdsmessages[mds.name] = 'rank: ' + mds.rank + "; " + mds.status;
- });
- }
- }
-
- var checks = {
- mon: function(mon) {
- if (quorummap.indexOf(mon.name) !== -1) {
- mon.health = healthstates.HEALTH_OK;
- } else {
- mon.health = healthstates.HEALTH_ERR;
- }
- if (monmessages[mon.name]) {
- if (monmessages[mon.name].worstSeverity < mon.health) {
- mon.health = monmessages[mon.name].worstSeverity;
- }
- Array.prototype.push.apply(mon.messages, monmessages[mon.name].messages);
- }
- return mon;
- },
- mgr: function(mgr) {
- if (mgrmessages[mgr.name] === 'active') {
- mgr.title = '' + mgr.title + ' ';
- mgr.statuses.push(gettext('Status') + ': active ');
- } else if (mgrmessages[mgr.name] === 'standby') {
- mgr.statuses.push(gettext('Status') + ': standby');
- } else if (mgr.health > healthstates.HEALTH_WARN) {
- mgr.health = healthstates.HEALTH_WARN;
- }
-
- return mgr;
- },
- mds: function(mds) {
- if (mdsmessages[mds.name]) {
- mds.title = '' + mds.title + ' ';
- mds.statuses.push(gettext('Status') + ': ' + mdsmessages[mds.name]+" ");
- } else if (mds.addr !== Proxmox.Utils.unknownText) {
- mds.statuses.push(gettext('Status') + ': standby');
- }
-
- return mds;
- }
- };
-
- for (i = 0; i < services.length; i++) {
- var type = services[i];
- var ids = Object.keys(metadata[type] || {});
- me[type] = {};
-
- var j;
- for (j = 0; j < ids.length; j++) {
- var id = ids[j];
- var tmp = id.split('@');
- var name = tmp[0];
- var host = tmp[1];
- var result = {
- id: id,
- health: healthstates.HEALTH_OK,
- statuses: [],
- messages: [],
- name: name,
- title: metadata[type][id].name || name,
- host: host,
- version: PVE.Utils.parse_ceph_version(metadata[type][id]),
- service: metadata[type][id].service,
- addr: metadata[type][id].addr || metadata[type][id].addrs || Proxmox.Utils.unknownText
- };
-
- result.statuses = [
- gettext('Host') + ": " + result.host,
- gettext('Address') + ": " + result.addr
- ];
-
- if (checks[type]) {
- result = checks[type](result);
- }
-
- if (result.service && !result.version) {
- result.messages.push(
- PVE.Utils.get_ceph_icon_html('HEALTH_UNKNOWN', true) +
- gettext('Stopped')
- );
- result.health = healthstates.HEALTH_UNKNOWN;
- }
-
- if (!result.version && result.addr === Proxmox.Utils.unknownText) {
- result.health = healthstates.HEALTH_UNKNOWN;
- }
-
- if (result.version) {
- result.statuses.push(gettext('Version') + ": " + result.version);
-
- if (result.version != maxversion) {
- if (result.health > healthstates.HEALTH_OLD) {
- result.health = healthstates.HEALTH_OLD;
- }
- result.messages.push(
- PVE.Utils.get_ceph_icon_html('HEALTH_OLD', true) +
- gettext('Not Current Version, please upgrade')
- );
- }
- }
-
- result.statuses.push(''); // empty line
- result.text = result.statuses.concat(result.messages).join(' ');
-
- result.health = healthmap[result.health];
-
- me[type][id] = result;
- }
- }
-
- me.getComponent('mons').updateAll(Object.values(me.mon));
- me.getComponent('mgrs').updateAll(Object.values(me.mgr));
- me.getComponent('mdss').updateAll(Object.values(me.mds));
- }
-});
-
-Ext.define('PVE.ceph.ServiceList', {
- extend: 'Ext.container.Container',
- xtype: 'pveCephServiceList',
-
- style: {
- 'text-align':'center'
- },
- defaults: {
- xtype: 'box',
- style: {
- 'text-align':'center'
- }
- },
-
- items: [
- {
- itemId: 'title',
- data: {
- title: ''
- },
- tpl: '{title} '
- }
- ],
-
- updateAll: function(list) {
- var me = this;
- me.suspendLayout = true;
-
- var i;
- list.sort(function(a,b) {
- return a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
- });
- var ids = {};
- if (me.ids) {
- me.ids.forEach(function(id) {
- ids[id] = true;
- });
- }
- for (i = 0; i < list.length; i++) {
- var service = me.getComponent(list[i].id);
- if (!service) {
- // since services are already sorted, and
- // we always have a sorted list
- // we can add it at the service+1 position (because of the title)
- service = me.insert(i+1, {
- xtype: 'pveCephServiceWidget',
- itemId: list[i].id
- });
- if (!me.ids) {
- me.ids = [];
- }
- me.ids.push(list[i].id);
- } else {
- delete ids[list[i].id];
- }
- service.updateService(list[i].title, list[i].text, list[i].health);
- }
-
- Object.keys(ids).forEach(function(id) {
- me.remove(id);
- });
- me.suspendLayout = false;
- me.updateLayout();
- },
-
- initComponent: function() {
- var me = this;
- me.callParent();
- me.getComponent('title').update({
- title: me.title
- });
- }
-});
-
-/*jslint confusion: true*/
-Ext.define('PVE.ceph.ServiceWidget', {
- extend: 'Ext.Component',
- alias: 'widget.pveCephServiceWidget',
-
- userCls: 'monitor inline-block',
- data: {
- title: '0',
- health: 'HEALTH_ERR',
- text: '',
- iconCls: PVE.Utils.get_health_icon()
- },
-
- tpl: [
- '{title}: ',
- ' '
- ],
-
- updateService: function(title, text, health) {
- var me = this;
-
- me.update(Ext.apply(me.data, {
- health: health,
- text: text,
- title: title,
- iconCls: PVE.Utils.get_health_icon(PVE.Utils.map_ceph_health[health])
- }));
-
- if (me.tooltip) {
- me.tooltip.setHtml(text);
- }
- },
-
- listeners: {
- destroy: function() {
- var me = this;
- if (me.tooltip) {
- me.tooltip.destroy();
- delete me.tooltip;
- }
- },
- mouseenter: {
- element: 'el',
- fn: function(events, element) {
- var me = this.component;
- if (!me) {
- return;
- }
- if (!me.tooltip) {
- me.tooltip = Ext.create('Ext.tip.ToolTip', {
- target: me.el,
- trackMouse: true,
- dismissDelay: 0,
- renderTo: Ext.getBody(),
- html: me.data.text
- });
- }
- me.tooltip.show();
- }
- },
- mouseleave: {
- element: 'el',
- fn: function(events, element) {
- var me = this.component;
- if (me.tooltip) {
- me.tooltip.destroy();
- delete me.tooltip;
- }
- }
- }
- }
-});
-Ext.define('PVE.node.CephConfigDb', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveNodeCephConfigDb',
-
- border: false,
- store: {
- proxy: {
- type: 'proxmox'
- }
- },
-
- columns: [
- {
- dataIndex: 'section',
- text: 'WHO',
- width: 100,
- },
- {
- dataIndex: 'mask',
- text: 'MASK',
- hidden: true,
- width: 80,
- },
- {
- dataIndex: 'level',
- hidden: true,
- text: 'LEVEL',
- },
- {
- dataIndex: 'name',
- flex: 1,
- text: 'OPTION',
- },
- {
- dataIndex: 'value',
- flex: 1,
- text: 'VALUE',
- },
- {
- dataIndex: 'can_update_at_runtime',
- text: 'Runtime Updatable',
- hidden: true,
- width: 80,
- renderer: Proxmox.Utils.format_boolean
- },
- ],
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.store.proxy.url = '/api2/json/nodes/' + nodename + '/ceph/configdb';
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.getStore());
- me.getStore().load();
- }
-});
-Ext.define('PVE.node.CephConfig', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNodeCephConfig',
-
- bodyStyle: 'white-space:pre',
- bodyPadding: 5,
- border: false,
- scrollable: true,
- load: function() {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: me.url,
- waitMsgTarget: me,
- failure: function(response, opts) {
- me.update(gettext('Error') + " " + response.htmlStatus);
- var msg = response.htmlStatus;
- PVE.Utils.showCephInstallOrMask(me.ownerCt, msg, me.pveSelNode.data.node,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.load();
- });
- }
- );
-
- },
- success: function(response, opts) {
- var data = response.result.data;
- me.update(Ext.htmlEncode(data));
- }
- });
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- url: '/nodes/' + nodename + '/ceph/config',
- listeners: {
- activate: function() {
- me.load();
- }
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-
-Ext.define('PVE.node.CephConfigCrush', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNodeCephConfigCrush',
-
- onlineHelp: 'chapter_pveceph',
-
- layout: 'border',
- items: [{
- title: gettext('Configuration'),
- xtype: 'pveNodeCephConfig',
- region: 'center'
- },
- {
- title: 'Crush Map', // do not localize
- xtype: 'pveNodeCephCrushMap',
- region: 'east',
- split: true,
- width: '50%'
- },
- {
- title: gettext('Configuration Database'),
- xtype: 'pveNodeCephConfigDb',
- region: 'south',
- split: true,
- weight: -30,
- height: '50%'
- }],
-
- initComponent: function() {
- var me = this;
- me.defaults = {
- pveSelNode: me.pveSelNode
- };
- me.callParent();
- }
-});
-Ext.define('PVE.ceph.Log', {
- extend: 'Proxmox.panel.LogView',
- xtype: 'cephLogView',
- nodename: undefined,
- failCallback: function(response) {
- var me = this;
- var msg = response.htmlStatus;
- var windowShow = PVE.Utils.showCephInstallOrMask(me, msg, me.nodename,
- function(win){
- me.mon(win, 'cephInstallWindowClosed', function(){
- me.loadTask.delay(200);
- });
- }
- );
- if (!windowShow) {
- Proxmox.Utils.setErrorMask(me, msg);
- }
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.ceph.CephInstallWizard', {
- extend: 'PVE.window.Wizard',
- alias: 'widget.pveCephInstallWizard',
- mixins: ['Proxmox.Mixin.CBind'],
- resizable: false,
- nodename: undefined,
- viewModel: {
- data: {
- nodename: '',
- configuration: true,
- isInstalled: false
- }
- },
- cbindData: {
- nodename: undefined
- },
- title: gettext('Setup'),
- navigateNext: function() {
- var tp = this.down('#wizcontent');
- var atab = tp.getActiveTab();
-
- var next = tp.items.indexOf(atab) + 1;
- var ntab = tp.items.getAt(next);
- if (ntab) {
- ntab.enable();
- tp.setActiveTab(ntab);
- }
- },
- setInitialTab: function (index) {
- var tp = this.down('#wizcontent');
- var initialTab = tp.items.getAt(index);
- initialTab.enable();
- tp.setActiveTab(initialTab);
- },
- onShow: function() {
- this.callParent(arguments);
- var isInstalled = this.getViewModel().get('isInstalled');
- if (isInstalled) {
- this.getViewModel().set('configuration', false);
- this.setInitialTab(2);
- }
- },
- items: [
- {
- title: gettext('Info'),
- xtype: 'panel',
- border: false,
- bodyBorder: false,
- onlineHelp: 'chapter_pveceph',
- html: 'Ceph? '+
- '"Ceph is a unified, distributed storage system designed for excellent performance, reliability and scalability."
'+
- 'Ceph is currently not installed on this node, click on the next button below to start the installation.'+
- ' This wizard will guide you through the necessary steps, after the initial installation you will be offered to create an initial configuration.'+
- ' The configuration step is only needed once per cluster and will be skipped if a config is already present.
'+
- 'Please take a look at our documentation, by clicking the help button below, before starting the installation, '+
- 'if you want to gain deeper knowledge about Ceph visit ceph.com .
',
- listeners: {
- activate: function() {
- // notify owning container that it should display a help button
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
- }
- this.up('pveCephInstallWizard').down('#back').hide(true);
- this.up('pveCephInstallWizard').down('#next').setText(gettext('Start installation'));
- },
- deactivate: function() {
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
- }
- this.up('pveCephInstallWizard').down('#next').setText(gettext('Next'));
- }
- }
- },
- {
- title: gettext('Installation'),
- xtype: 'panel',
- layout: 'fit',
- cbind:{
- nodename: '{nodename}'
- },
- viewModel: {}, // needed to inherit parent viewModel data
- listeners: {
- afterrender: function() {
- var me = this;
- if (this.getViewModel().get('isInstalled')) {
- this.mask("Ceph is already installed, click next to create your configuration.",['pve-static-mask']);
- } else {
- me.down('pveNoVncConsole').fireEvent('activate');
- }
- },
- activate: function() {
- var me = this;
- var nodename = me.nodename;
- me.updateStore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'ceph-status-' + nodename,
- interval: 1000,
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + nodename + '/ceph/status'
- },
- listeners: {
- load: function(rec, response, success, operation) {
-
- if (success) {
- me.updateStore.stopUpdate();
- me.down('textfield').setValue('success');
- } else if (operation.error.statusText.match("not initialized", "i")) {
- me.updateStore.stopUpdate();
- me.up('pveCephInstallWizard').getViewModel().set('configuration',false);
- me.down('textfield').setValue('success');
- } else if (operation.error.statusText.match("rados_connect failed", "i")) {
- me.updateStore.stopUpdate();
- me.up('pveCephInstallWizard').getViewModel().set('configuration',true);
- me.down('textfield').setValue('success');
- } else if (!operation.error.statusText.match("not installed", "i")) {
- Proxmox.Utils.setErrorMask(me, operation.error.statusText);
- }
- }
- }
- });
- me.updateStore.startUpdate();
- },
- destroy: function() {
- var me = this;
- if (me.updateStore) {
- me.updateStore.stopUpdate();
- }
- }
- },
- items: [
- {
- itemId: 'jsconsole',
- consoleType: 'cmd',
- xtermjs: true,
- xtype: 'pveNoVncConsole',
- cbind:{
- nodename: '{nodename}'
- },
- cmd: 'ceph_install'
- },
- {
- xtype: 'textfield',
- name: 'installSuccess',
- value: '',
- allowBlank: false,
- submitValue: false,
- hidden: true
- }
- ]
- },
- {
- xtype: 'inputpanel',
- title: gettext('Configuration'),
- onlineHelp: 'chapter_pveceph',
- cbind: {
- nodename: '{nodename}'
- },
- viewModel: {
- data: {
- replicas: undefined,
- minreplicas: undefined
- }
- },
- listeners: {
- activate: function() {
- this.up('pveCephInstallWizard').down('#submit').setText(gettext('Next'));
- },
- beforeshow: function() {
- if (this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
- this.mask("Coniguration already initialized",['pve-static-mask']);
- } else {
- this.unmask();
- }
- },
- deactivate: function() {
- this.up('pveCephInstallWizard').down('#submit').setText(gettext('Finish'));
- }
- },
- column1: [
- {
- xtype: 'displayfield',
- value: gettext('Ceph cluster configuration') + ':'
- },
- {
- xtype: 'proxmoxNetworkSelector',
- name: 'network',
- value: '',
- fieldLabel: 'Public Network IP/CIDR',
- bind: {
- allowBlank: '{configuration}'
- }
- },
- {
- xtype: 'proxmoxNetworkSelector',
- name: 'cluster-network',
- fieldLabel: 'Cluster Network IP/CIDR',
- allowBlank: true,
- autoSelect: false,
- emptyText: gettext('Same as Public Network')
- }
- // FIXME: add hint about cluster network and/or reference user to docs??
- ],
- column2: [
- {
- xtype: 'displayfield',
- value: gettext('First Ceph monitor') + ':'
- },
- {
- xtype: 'pveNodeSelector',
- fieldLabel: gettext('Monitor node'),
- name: 'mon-node',
- selectCurNode: true,
- allowBlank: false
- },
- {
- xtype: 'displayfield',
- value: gettext('Additional monitors are recommended. They can be created at any time in the Monitor tab.'),
- userCls: 'pve-hint'
- }
- ],
- advancedColumn1: [
- {
- xtype: 'numberfield',
- name: 'size',
- fieldLabel: 'Number of replicas',
- bind: {
- value: '{replicas}'
- },
- maxValue: 7,
- minValue: 2,
- emptyText: '3'
- },
- {
- xtype: 'numberfield',
- name: 'min_size',
- fieldLabel: 'Minimum replicas',
- bind: {
- maxValue: '{replicas}',
- value: '{minreplicas}'
- },
- minValue: 2,
- maxValue: 3,
- setMaxValue: function(value) {
- this.maxValue = Ext.Number.from(value, 2);
- // allow enough to avoid split brains with max 'size', but more makes simply no sense
- if (this.maxValue > 4) {
- this.maxValue = 4;
- }
- this.toggleSpinners();
- this.validate();
- },
- emptyText: '2'
- }
- ],
- onGetValues: function(values) {
- ['cluster-network', 'size', 'min_size'].forEach(function(field) {
- if (!values[field]) {
- delete values[field];
- }
- });
- return values;
- },
- onSubmit: function() {
- var me = this;
- if (!this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
- var wizard = me.up('window');
- var kv = wizard.getValues();
- delete kv['delete'];
- var monNode = kv['mon-node'];
- delete kv['mon-node'];
- var nodename = me.nodename;
- delete kv.nodename;
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/ceph/init',
- waitMsgTarget: wizard,
- method: 'POST',
- params: kv,
- success: function() {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + monNode + '/ceph/mon/' + monNode,
- waitMsgTarget: wizard,
- method: 'POST',
- success: function() {
- me.up('pveCephInstallWizard').navigateNext();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
-
- } else {
- me.up('pveCephInstallWizard').navigateNext();
- }
- }
- },
- {
- title: gettext('Success'),
- xtype: 'panel',
- border: false,
- bodyBorder: false,
- onlineHelp: 'pve_ceph_install',
- html: 'Installation successful! '+
- 'The basic installation and configuration is completed, depending on your setup some of the following steps are required to start using Ceph:
'+
- 'Install Ceph on other nodes '+
- 'Create additional Ceph Monitors '+
- 'Create Ceph OSDs '+
- 'Create Ceph Pools '+
- 'To learn more click on the help button below.
',
- listeners: {
- activate: function() {
- // notify owning container that it should display a help button
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
- }
-
- var tp = this.up('#wizcontent');
- var idx = tp.items.indexOf(this)-1;
- for(;idx >= 0;idx--) {
- var nc = tp.items.getAt(idx);
- if (nc) {
- nc.disable();
- }
- }
- },
- deactivate: function() {
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
- }
- }
- },
- onSubmit: function() {
- var wizard = this.up('pveCephInstallWizard');
- wizard.close();
- }
- }
- ]
- });
-Ext.define('PVE.node.DiskList', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pveNodeDiskList',
-
- emptyText: gettext('No Disks found'),
-
- stateful: true,
- stateId: 'grid-node-disks',
-
- columns: [
- {
- header: gettext('Device'),
- width: 150,
- sortable: true,
- dataIndex: 'devpath'
- },
- {
- header: gettext('Type'),
- width: 80,
- sortable: true,
- dataIndex: 'type',
- renderer: function(v) {
- if (v === 'ssd') {
- return 'SSD';
- } else if (v === 'hdd') {
- return 'Hard Disk';
- } else if (v === 'usb'){
- return 'USB';
- } else {
- return gettext('Unknown');
- }
- }
- },
- {
- header: gettext('Usage'),
- width: 150,
- sortable: false,
- renderer: function(v, metaData, rec) {
- if (rec) {
- if (rec.data.osdid >= 0) {
- var bluestore = '';
- if (rec.data.bluestore === 1) {
- bluestore = ' (Bluestore)';
- }
- return "Ceph osd." + rec.data.osdid.toString() + bluestore;
- }
-
- var types = [];
- if (rec.data.journals > 0) {
- types.push('Journal');
- }
-
- if (rec.data.db > 0) {
- types.push('DB');
- }
-
- if (rec.data.wal > 0) {
- types.push('WAL');
- }
-
- if (types.length > 0) {
- return 'Ceph (' + types.join(', ') + ')';
- }
- }
-
- return v || Proxmox.Utils.noText;
- },
- dataIndex: 'used'
- },
- {
- header: gettext('Size'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- },
- {
- header: 'GPT',
- width: 60,
- align: 'right',
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'gpt'
- },
- {
- header: gettext('Vendor'),
- width: 100,
- sortable: true,
- hidden: true,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'vendor'
- },
- {
- header: gettext('Model'),
- width: 200,
- sortable: true,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'model'
- },
- {
- header: gettext('Serial'),
- width: 200,
- sortable: true,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'serial'
- },
- {
- header: 'S.M.A.R.T.',
- width: 100,
- sortable: true,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'health'
- },
- {
- header: 'Wearout',
- width: 90,
- sortable: true,
- align: 'right',
- dataIndex: 'wearout',
- renderer: function(value) {
- if (Ext.isNumeric(value)) {
- return (100 - value).toString() + '%';
- }
- return 'N/A';
- }
- }
- ],
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var store = Ext.create('Ext.data.Store', {
- storeid: 'node-disk-list' + nodename,
- model: 'node-disk-list',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/disks/list"
- },
- sorters: [
- {
- property : 'dev',
- direction: 'ASC'
- }
- ]
- });
-
- var reloadButton = Ext.create('Proxmox.button.Button', {
- text: gettext('Reload'),
- handler: function() {
- me.store.load();
- }
- });
-
- var smartButton = Ext.create('Proxmox.button.Button', {
- text: gettext('Show S.M.A.R.T. values'),
- selModel: sm,
- enableFn: function() {
- return !!sm.getSelection().length;
- },
- disabled: true,
- handler: function() {
- var rec = sm.getSelection()[0];
-
- var win = Ext.create('PVE.DiskSmartWindow', {
- nodename: nodename,
- dev: rec.data.devpath
- });
- win.show();
- }
- });
-
- var initButton = Ext.create('Proxmox.button.Button', {
- text: gettext('Initialize Disk with GPT'),
- selModel: sm,
- enableFn: function() {
- var selection = sm.getSelection();
-
- if (!selection.length || selection[0].data.used) {
- return false;
- } else {
- return true;
- }
- },
- disabled: true,
-
- handler: function() {
- var rec = sm.getSelection()[0];
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/nodes/' + nodename + '/disks/initgpt',
- waitMsgTarget: me,
- method: 'POST',
- params: { disk: rec.data.devpath},
- failure: function(response, options) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid
- });
- win.show();
- }
- });
- }
- });
-
- me.loadCount = 1; // avoid duplicate loadmask
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [ reloadButton, smartButton, initButton ],
- listeners: {
- itemdblclick: function() {
- var rec = sm.getSelection()[0];
-
- var win = Ext.create('PVE.DiskSmartWindow', {
- nodename: nodename,
- dev: rec.data.devpath
- });
- win.show();
- }
- }
- });
-
-
- me.callParent();
- me.store.load();
- }
-}, function() {
-
- Ext.define('node-disk-list', {
- extend: 'Ext.data.Model',
- fields: [ 'devpath', 'used', { name: 'size', type: 'number'},
- {name: 'osdid', type: 'number'},
- 'vendor', 'model', 'serial', 'rpm', 'type', 'health', 'wearout' ],
- idProperty: 'devpath'
- });
-});
-
-Ext.define('PVE.DiskSmartWindow', {
- extend: 'Ext.window.Window',
- alias: 'widget.pveSmartWindow',
-
- modal: true,
-
- items: [
- {
- xtype: 'gridpanel',
- layout: {
- type: 'fit'
- },
- emptyText: gettext('No S.M.A.R.T. Values'),
- scrollable: true,
- flex: 1,
- itemId: 'smarts',
- reserveScrollbar: true,
- columns: [
- { text: 'ID', dataIndex: 'id', width: 50 },
- { text: gettext('Attribute'), flex: 1, dataIndex: 'name', renderer: Ext.String.htmlEncode },
- { text: gettext('Value'), dataIndex: 'raw', renderer: Ext.String.htmlEncode },
- { text: gettext('Normalized'), dataIndex: 'value', width: 60},
- { text: gettext('Threshold'), dataIndex: 'threshold', width: 60},
- { text: gettext('Worst'), dataIndex: 'worst', width: 60},
- { text: gettext('Flags'), dataIndex: 'flags'},
- { text: gettext('Failing'), dataIndex: 'fail', renderer: Ext.String.htmlEncode }
- ]
- },
- {
- xtype: 'component',
- itemId: 'text',
- layout: {
- type: 'fit'
- },
- hidden: true,
- style: {
- 'background-color': '#23272a',
- 'white-space': 'pre',
- 'font-family': 'monospace'
- }
- }
- ],
-
- buttons: [
- {
- text: gettext('Reload'),
- name: 'reload',
- handler: function() {
- var me = this;
- me.up('window').store.reload();
- }
- },
- {
- text: gettext('Close'),
- name: 'close',
- handler: function() {
- var me = this;
- me.up('window').close();
- }
- }
- ],
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- width: 800,
- height: 500,
- minWidth: 600,
- minHeight: 400,
- bodyPadding: 5,
- title: gettext('S.M.A.R.T. Values'),
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.nodename;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var dev = me.dev;
- if (!dev) {
- throw "no device specified";
- }
-
- me.store = Ext.create('Ext.data.Store', {
- model: 'disk-smart',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + nodename + "/disks/smart?disk=" + dev
- }
- });
-
- me.callParent();
- var grid = me.down('#smarts');
- var text = me.down('#text');
-
- Proxmox.Utils.monStoreErrors(grid, me.store);
- me.mon(me.store, 'load', function(s, records, success) {
- if (success && records.length > 0) {
- var rec = records[0];
- switch (rec.data.type) {
- case 'text':
- grid.setVisible(false);
- text.setVisible(true);
- text.setHtml(Ext.String.htmlEncode(rec.data.text));
- break;
- default:
- // includes 'ata'
- // cannot use empty case because
- // of jslint
- grid.setVisible(true);
- text.setVisible(false);
- grid.setStore(rec.attributes());
- break;
- }
- }
- });
-
- me.store.load();
- }
-}, function() {
-
- Ext.define('disk-smart', {
- extend: 'Ext.data.Model',
- fields: [
- { name:'health'},
- { name:'type'},
- { name:'text'}
- ],
- hasMany: {model: 'smart-attribute', name: 'attributes'}
- });
- Ext.define('smart-attribute', {
- extend: 'Ext.data.Model',
- fields: [
- { name:'id', type:'number' }, 'name', 'value', 'worst', 'threshold', 'flags', 'fail', 'raw'
- ]
- });
-});
-Ext.define('PVE.node.CreateLVM', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCreateLVM',
-
- subject: 'LVM Volume Group',
-
- showProgress: true,
-
- onlineHelp: 'chapter_lvm',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/disks/lvm",
- method: 'POST',
- items: [
- {
- xtype: 'pveDiskSelector',
- name: 'device',
- nodename: me.nodename,
- diskType: 'unused',
- fieldLabel: gettext('Disk'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'add_storage',
- fieldLabel: gettext('Add Storage'),
- value: '1'
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.LVMList', {
- extend: 'Ext.tree.Panel',
- xtype: 'pveLVMList',
- emptyText: gettext('No Volume Groups found'),
- stateful: true,
- stateId: 'grid-node-lvm',
- columns: [
- {
- xtype: 'treecolumn',
- text: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- text: gettext('Number of LVs'),
- dataIndex: 'lvcount',
- width: 150,
- align: 'right'
- },
- {
- header: gettext('Usage'),
- width: 110,
- dataIndex: 'usage',
- tdCls: 'x-progressbar-default-cell',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Size'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- },
- {
- header: gettext('Free'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'free'
- }
- ],
-
- rootVisible: false,
- useArrows: true,
-
- tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
- var me = this.up('panel');
- me.reload();
- }
- },
- {
- text: gettext('Create') + ': Volume Group',
- handler: function() {
- var me = this.up('panel');
- var win = Ext.create('PVE.node.CreateLVM', {
- nodename: me.nodename,
- taskDone: function() {
- me.reload();
- }
- }).show();
- }
- }
- ],
-
- reload: function() {
- var me = this;
- var sm = me.getSelectionModel();
- Proxmox.Utils.API2Request({
- url: "/nodes/" + me.nodename + "/disks/lvm",
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- },
- success: function(response, opts) {
- sm.deselectAll();
- me.setRootNode(response.result.data);
- me.expandAll();
- }
- });
- },
-
- listeners: {
- activate: function() {
- var me = this;
- me.reload();
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var sm = Ext.create('Ext.selection.TreeModel', {});
-
- Ext.apply(me, {
- selModel: sm,
- fields: ['name', 'size', 'free',
- {
- type: 'string',
- name: 'iconCls',
- calculate: function(data) {
- var txt = 'fa x-fa-tree fa-';
- txt += (data.leaf) ? 'hdd-o' : 'object-group';
- return txt;
- }
- },
- {
- type: 'number',
- name: 'usage',
- calculate: function(data) {
- return ((data.size-data.free)/data.size);
- }
- }
- ],
- sorters: 'name'
- });
-
- me.callParent();
-
- me.reload();
- }
-});
-
-Ext.define('PVE.node.CreateLVMThin', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCreateLVMThin',
-
- subject: 'LVM Thinpool',
-
- showProgress: true,
-
- onlineHelp: 'chapter_lvm',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/disks/lvmthin",
- method: 'POST',
- items: [
- {
- xtype: 'pveDiskSelector',
- name: 'device',
- nodename: me.nodename,
- diskType: 'unused',
- fieldLabel: gettext('Disk'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'add_storage',
- fieldLabel: gettext('Add Storage'),
- value: '1'
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.LVMThinList', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveLVMThinList',
-
- emptyText: gettext('No thinpools found'),
- stateful: true,
- stateId: 'grid-node-lvmthin',
- columns: [
- {
- text: gettext('Name'),
- dataIndex: 'lv',
- flex: 1
- },
- {
- header: gettext('Usage'),
- width: 110,
- dataIndex: 'usage',
- tdCls: 'x-progressbar-default-cell',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Size'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'lv_size'
- },
- {
- header: gettext('Used'),
- width: 100,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'used'
- },
- {
- header: gettext('Metadata Usage'),
- width: 120,
- dataIndex: 'metadata_usage',
- tdCls: 'x-progressbar-default-cell',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Metadata Size'),
- width: 120,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'metadata_size'
- },
- {
- header: gettext('Metadata Used'),
- width: 125,
- align: 'right',
- sortable: true,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'metadata_used'
- }
- ],
-
- rootVisible: false,
- useArrows: true,
-
- tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
- var me = this.up('panel');
- me.reload();
- }
- },
- {
- text: gettext('Create') + ': Thinpool',
- handler: function() {
- var me = this.up('panel');
- var win = Ext.create('PVE.node.CreateLVMThin', {
- nodename: me.nodename,
- taskDone: function() {
- me.reload();
- }
- }).show();
- }
- }
- ],
-
- reload: function() {
- var me = this;
- me.store.load();
- me.store.sort();
- },
-
- listeners: {
- activate: function() {
- var me = this;
- me.reload();
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- store: {
- fields: ['lv', 'lv_size', 'used', 'metadata_size', 'metadata_used',
- {
- type: 'number',
- name: 'usage',
- calculate: function(data) {
- return data.used/data.lv_size;
- }
- },
- {
- type: 'number',
- name: 'metadata_usage',
- calculate: function(data) {
- return data.metadata_used/data.metadata_size;
- }
- }
- ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + '/disks/lvmthin'
- },
- sorters: 'lv'
- }
- });
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.getStore(), true);
- me.reload();
- }
-});
-
-Ext.define('PVE.node.CreateDirectory', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCreateDirectory',
-
- subject: Proxmox.Utils.directoryText,
-
- showProgress: true,
-
- onlineHelp: 'chapter_storage',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- Ext.applyIf(me, {
- url: "/nodes/" + me.nodename + "/disks/directory",
- method: 'POST',
- items: [
- {
- xtype: 'pveDiskSelector',
- name: 'device',
- nodename: me.nodename,
- diskType: 'unused',
- fieldLabel: gettext('Disk'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxKVComboBox',
- comboItems: [
- ['ext4', 'ext4'],
- ['xfs', 'xfs']
- ],
- fieldLabel: gettext('Filesystem'),
- name: 'filesystem',
- value: '',
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'add_storage',
- fieldLabel: gettext('Add Storage'),
- value: '1'
- }
- ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.node.Directorylist', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveDirectoryList',
-
- stateful: true,
- stateId: 'grid-node-directory',
- columns: [
- {
- text: gettext('Path'),
- dataIndex: 'path',
- flex: 1
- },
- {
- header: gettext('Device'),
- flex: 1,
- dataIndex: 'device'
- },
- {
- header: gettext('Type'),
- width: 100,
- dataIndex: 'type'
- },
- {
- header: gettext('Options'),
- width: 100,
- dataIndex: 'options'
- },
- {
- header: gettext('Unit File'),
- hidden: true,
- dataIndex: 'unitfile'
- }
- ],
-
- rootVisible: false,
- useArrows: true,
-
- tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
- var me = this.up('panel');
- me.reload();
- }
- },
- {
- text: gettext('Create') + ': Directory',
- handler: function() {
- var me = this.up('panel');
- var win = Ext.create('PVE.node.CreateDirectory', {
- nodename: me.nodename
- }).show();
- win.on('destroy', function() { me.reload(); });
- }
- }
- ],
-
- reload: function() {
- var me = this;
- me.store.load();
- me.store.sort();
- },
-
- listeners: {
- activate: function() {
- var me = this;
- me.reload();
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- store: {
- fields: ['path', 'device', 'type', 'options', 'unitfile' ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + '/disks/directory'
- },
- sorters: 'path'
- }
- });
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.getStore(), true);
- me.reload();
- }
-});
-
-/*jslint confusion: true*/
-Ext.define('PVE.node.CreateZFS', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCreateZFS',
-
- subject: 'ZFS',
-
- showProgress: true,
-
- onlineHelp: 'chapter_zfs',
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = true;
-
- var update_disklist = function() {
- var grid = me.down('#disklist');
- var disks = grid.getSelection();
-
- var val = [];
- disks.sort(function(a,b) {
- var aorder = a.get('order') || 0;
- var border = b.get('order') || 0;
- return (aorder - border);
- });
-
- disks.forEach(function(disk) {
- val.push(disk.get('devpath'));
- });
-
- me.down('field[name=devices]').setValue(val.join(','));
- };
-
- Ext.apply(me, {
- url: '/nodes/' + me.nodename + '/disks/zfs',
- method: 'POST',
- items: [
- {
- xtype: 'inputpanel',
- onGetValues: function(values) {
- return values;
- },
- column1: [
- {
- xtype: 'textfield',
- hidden: true,
- name: 'devices',
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'add_storage',
- fieldLabel: gettext('Add Storage'),
- value: '1'
- }
- ],
- column2: [
- {
- xtype: 'proxmoxKVComboBox',
- fieldLabel: gettext('RAID Level'),
- name: 'raidlevel',
- value: 'single',
- comboItems: [
- ['single', gettext('Single Disk')],
- ['mirror', 'Mirror'],
- ['raid10', 'RAID10'],
- ['raidz', 'RAIDZ'],
- ['raidz2', 'RAIDZ2'],
- ['raidz3', 'RAIDZ3']
- ]
- },
- {
- xtype: 'proxmoxKVComboBox',
- fieldLabel: gettext('Compression'),
- name: 'compression',
- value: 'on',
- comboItems: [
- ['on', 'on'],
- ['off', 'off'],
- ['gzip', 'gzip'],
- ['lz4', 'lz4'],
- ['lzjb', 'lzjb'],
- ['zle', 'zle']
- ]
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('ashift'),
- minValue: 9,
- maxValue: 16,
- value: '12',
- name: 'ashift'
- }
- ],
- columnB: [
- {
- xtype: 'grid',
- height: 200,
- emptyText: gettext('No Disks unused'),
- itemId: 'disklist',
- selModel: 'checkboxmodel',
- listeners: {
- selectionchange: update_disklist
- },
- store: {
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/disks/list?type=unused'
- }
- },
- columns: [
- {
- text: gettext('Device'),
- dataIndex: 'devpath',
- flex: 1
- },
- {
- text: gettext('Serial'),
- dataIndex: 'serial'
- },
- {
- text: gettext('Size'),
- dataIndex: 'size',
- renderer: PVE.Utils.render_size
- },
- {
- header: gettext('Order'),
- xtype: 'widgetcolumn',
- dataIndex: 'order',
- sortable: true,
- widget: {
- xtype: 'proxmoxintegerfield',
- minValue: 1,
- isFormField: false,
- listeners: {
- change: function(numberfield, value, old_value) {
- var record = numberfield.getWidgetRecord();
- record.set('order', value);
- update_disklist(record);
- }
- }
- }
- }
- ]
- }
- ]
- },
- {
- xtype: 'displayfield',
- padding: '5 0 0 0',
- userCls: 'pve-hint',
- value: 'Note: ZFS is not compatible with disks backed by a hardware ' +
- 'RAID controller. For details see ' +
- 'the reference documentation .',
- }
- ]
- });
-
- me.callParent();
- me.down('#disklist').getStore().load();
- }
-});
-
-Ext.define('PVE.node.ZFSDevices', {
- extend: 'Ext.tree.Panel',
- xtype: 'pveZFSDevices',
- stateful: true,
- stateId: 'grid-node-zfsstatus',
- columns: [
- {
- xtype: 'treecolumn',
- text: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- text: gettext('Health'),
- renderer: PVE.Utils.render_zfs_health,
- dataIndex: 'state'
- },
- {
- text: 'READ',
- dataIndex: 'read'
- },
- {
- text: 'WRITE',
- dataIndex: 'write'
- },
- {
- text: 'CKSUM',
- dataIndex: 'cksum'
- },
- {
- text: gettext('Message'),
- dataIndex: 'msg'
- }
- ],
-
- rootVisible: true,
-
- reload: function() {
- var me = this;
- var sm = me.getSelectionModel();
- Proxmox.Utils.API2Request({
- url: "/nodes/" + me.nodename + "/disks/zfs/" + me.zpool,
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- },
- success: function(response, opts) {
- sm.deselectAll();
- me.setRootNode(response.result.data);
- me.expandAll();
- }
- });
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.zpool) {
- throw "no zpool specified";
- }
-
- var sm = Ext.create('Ext.selection.TreeModel', {});
-
- Ext.apply(me, {
- selModel: sm,
- fields: ['name', 'status',
- {
- type: 'string',
- name: 'iconCls',
- calculate: function(data) {
- var txt = 'fa x-fa-tree fa-';
- if (data.leaf) {
- return txt + 'hdd-o';
- }
- }
- }
- ],
- sorters: 'name'
- });
-
- me.callParent();
-
- me.reload();
- }
-});
-
-Ext.define('PVE.node.ZFSStatus', {
- extend: 'Proxmox.grid.ObjectGrid',
- xtype: 'pveZFSStatus',
- layout: 'fit',
- border: false,
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.zpool) {
- throw "no zpool specified";
- }
-
- me.url = "/api2/extjs/nodes/" + me.nodename + "/disks/zfs/" + me.zpool;
-
- me.rows = {
- scan: {
- header: gettext('Scan')
- },
- status: {
- header: gettext('Status')
- },
- action: {
- header: gettext('Action')
- },
- errors: {
- header: gettext('Errors')
- }
- };
-
- me.callParent();
- me.reload();
- }
-});
-
-Ext.define('PVE.node.ZFSList', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveZFSList',
-
- stateful: true,
- stateId: 'grid-node-zfs',
- columns: [
- {
- text: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- header: gettext('Size'),
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- },
- {
- header: gettext('Free'),
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'free'
- },
- {
- header: gettext('Allocated'),
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'alloc'
- },
- {
- header: gettext('Fragmentation'),
- renderer: function(value) {
- return value.toString() + '%';
- },
- dataIndex: 'frag'
- },
- {
- header: gettext('Health'),
- renderer: PVE.Utils.render_zfs_health,
- dataIndex: 'health'
- },
- {
- header: gettext('Deduplication'),
- hidden: true,
- renderer: function(value) {
- return value.toFixed(2).toString() + 'x';
- },
- dataIndex: 'dedup'
- }
- ],
-
- rootVisible: false,
- useArrows: true,
-
- tbar: [
- {
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
- var me = this.up('panel');
- me.reload();
- }
- },
- {
- text: gettext('Create') + ': ZFS',
- handler: function() {
- var me = this.up('panel');
- var win = Ext.create('PVE.node.CreateZFS', {
- nodename: me.nodename
- }).show();
- win.on('destroy', function() { me.reload(); });
- }
- },
- {
- text: gettext('Detail'),
- itemId: 'detailbtn',
- disabled: true,
- handler: function() {
- var me = this.up('panel');
- var selection = me.getSelection();
- if (selection.length < 1) {
- return;
- }
- me.show_detail(selection[0].get('name'));
- }
- }
- ],
-
- show_detail: function(zpool) {
- var me = this;
-
- var detailsgrid = Ext.create('PVE.node.ZFSStatus', {
- layout: 'fit',
- nodename: me.nodename,
- flex: 0,
- zpool: zpool
- });
-
- var devicetree = Ext.create('PVE.node.ZFSDevices', {
- title: gettext('Devices'),
- nodename: me.nodename,
- flex: 1,
- zpool: zpool
- });
-
-
- var win = Ext.create('Ext.window.Window', {
- modal: true,
- width: 800,
- height: 400,
- resizable: true,
- layout: 'fit',
- title: gettext('Status') + ': ' + zpool,
- items:[{
- xtype: 'panel',
- region: 'center',
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- items: [detailsgrid, devicetree],
- tbar: [{
- text: gettext('Reload'),
- iconCls: 'fa fa-refresh',
- handler: function() {
-
- devicetree.reload();
- detailsgrid.reload();
- }
- }]
- }]
- }).show();
- },
-
- set_button_status: function() {
- var me = this;
- var selection = me.getSelection();
- me.down('#detailbtn').setDisabled(selection.length === 0);
- },
-
- reload: function() {
- var me = this;
- me.store.load();
- me.store.sort();
- },
-
- listeners: {
- activate: function() {
- var me = this;
- me.reload();
- },
- selectionchange: function() {
- this.set_button_status();
- },
- itemdblclick: function(grid, record) {
- var me = this;
- me.show_detail(record.get('name'));
- }
- },
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- Ext.apply(me, {
- store: {
- fields: ['name', 'size', 'free', 'alloc', 'dedup', 'frag', 'health'],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/nodes/" + me.nodename + '/disks/zfs'
- },
- sorters: 'name'
- }
- });
-
- me.callParent();
-
- Proxmox.Utils.monStoreErrors(me, me.getStore(), true);
- me.reload();
- }
-});
-
-Ext.define('PVE.node.StatusView', {
- extend: 'PVE.panel.StatusView',
- alias: 'widget.pveNodeStatus',
-
- height: 300,
- bodyPadding: '20 15 20 15',
-
- layout: {
- type: 'table',
- columns: 2,
- tableAttrs: {
- style: {
- width: '100%'
- }
- }
- },
-
- defaults: {
- xtype: 'pveInfoWidget',
- padding: '0 15 5 15'
- },
-
- items: [
- {
- itemId: 'cpu',
- iconCls: 'fa fa-fw pve-itype-icon-processor pve-icon',
- title: gettext('CPU usage'),
- valueField: 'cpu',
- maxField: 'cpuinfo',
- renderer: PVE.Utils.render_node_cpu_usage
- },
- {
- itemId: 'wait',
- iconCls: 'fa fa-fw fa-clock-o',
- title: gettext('IO delay'),
- valueField: 'wait',
- rowspan: 2
- },
- {
- itemId: 'load',
- iconCls: 'fa fa-fw fa-tasks',
- title: gettext('Load average'),
- printBar: false,
- textField: 'loadavg'
- },
- {
- xtype: 'box',
- colspan: 2,
- padding: '0 0 20 0'
- },
- {
- iconCls: 'fa fa-fw pve-itype-icon-memory pve-icon',
- itemId: 'memory',
- title: gettext('RAM usage'),
- valueField: 'memory',
- maxField: 'memory',
- renderer: PVE.Utils.render_node_size_usage
- },
- {
- itemId: 'ksm',
- printBar: false,
- title: gettext('KSM sharing'),
- textField: 'ksm',
- renderer: function(record) {
- return PVE.Utils.render_size(record.shared);
- },
- padding: '0 15 10 15'
- },
- {
- iconCls: 'fa fa-fw fa-hdd-o',
- itemId: 'rootfs',
- title: gettext('HD space') + '(root)',
- valueField: 'rootfs',
- maxField: 'rootfs',
- renderer: PVE.Utils.render_node_size_usage
- },
- {
- iconCls: 'fa fa-fw fa-refresh',
- itemId: 'swap',
- printSize: true,
- title: gettext('SWAP usage'),
- valueField: 'swap',
- maxField: 'swap',
- renderer: PVE.Utils.render_node_size_usage
- },
- {
- xtype: 'box',
- colspan: 2,
- padding: '0 0 20 0'
- },
- {
- itemId: 'cpus',
- colspan: 2,
- printBar: false,
- title: gettext('CPU(s)'),
- textField: 'cpuinfo',
- renderer: function(cpuinfo) {
- return cpuinfo.cpus + " x " + cpuinfo.model + " (" +
- cpuinfo.sockets.toString() + " " +
- (cpuinfo.sockets > 1 ?
- gettext('Sockets') :
- gettext('Socket')
- ) + ")";
- },
- value: ''
- },
- {
- itemId: 'kversion',
- colspan: 2,
- title: gettext('Kernel Version'),
- printBar: false,
- textField: 'kversion',
- value: ''
- },
- {
- itemId: 'version',
- colspan: 2,
- printBar: false,
- title: gettext('PVE Manager Version'),
- textField: 'pveversion',
- value: ''
- }
- ],
-
- updateTitle: function() {
- var me = this;
- var uptime = Proxmox.Utils.render_uptime(me.getRecordValue('uptime'));
- me.setTitle(me.pveSelNode.data.node + ' (' + gettext('Uptime') + ': ' + uptime + ')');
- }
-
-});
-Ext.define('PVE.node.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveNodeSummary',
-
- scrollable: true,
- bodyPadding: 5,
-
- showVersions: function() {
- var me = this;
-
- // Note: we use simply text/html here, because ExtJS grid has problems
- // with cut&paste
-
- var nodename = me.pveSelNode.data.node;
-
- var view = Ext.createWidget('component', {
- autoScroll: true,
- padding: 5,
- style: {
- 'background-color': '#23272a',
- 'white-space': 'pre',
- 'font-family': 'monospace'
- }
- });
-
- var win = Ext.create('Ext.window.Window', {
- title: gettext('Package versions'),
- width: 600,
- height: 400,
- layout: 'fit',
- modal: true,
- items: [ view ]
- });
-
- Proxmox.Utils.API2Request({
- waitMsgTarget: me,
- url: "/nodes/" + nodename + "/apt/versions",
- method: 'GET',
- failure: function(response, opts) {
- win.close();
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- win.show();
- var text = '';
-
- Ext.Array.each(response.result.data, function(rec) {
- var version = "not correctly installed";
- var pkg = rec.Package;
- if (rec.OldVersion && rec.CurrentState === 'Installed') {
- version = rec.OldVersion;
- }
- if (rec.RunningKernel) {
- text += pkg + ': ' + version + ' (running kernel: ' +
- rec.RunningKernel + ')\n';
- } else if (rec.ManagerVersion) {
- text += pkg + ': ' + version + ' (running version: ' +
- rec.ManagerVersion + ')\n';
- } else {
- text += pkg + ': ' + version + '\n';
- }
- });
-
- view.update(Ext.htmlEncode(text));
- }
- });
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- if (!me.statusStore) {
- throw "no status storage specified";
- }
-
- var rstore = me.statusStore;
-
- var version_btn = new Ext.Button({
- text: gettext('Package versions'),
- handler: function(){
- Proxmox.Utils.checked_command(function() { me.showVersions(); });
- }
- });
-
- var rrdstore = Ext.create('Proxmox.data.RRDStore', {
- rrdurl: "/api2/json/nodes/" + nodename + "/rrddata",
- model: 'pve-rrd-node'
- });
-
- Ext.apply(me, {
- tbar: [version_btn, '->', { xtype: 'proxmoxRRDTypeSelector' } ],
- items: [
- {
- xtype: 'container',
- layout: 'column',
- defaults: {
- minHeight: 320,
- padding: 5,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- }
- },
- items: [
- {
- xtype: 'pveNodeStatus',
- rstore: rstore,
- width: 770,
- pveSelNode: me.pveSelNode
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('CPU usage'),
- fields: ['cpu','iowait'],
- fieldTitles: [gettext('CPU usage'), gettext('IO delay')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Server load'),
- fields: ['loadavg'],
- fieldTitles: [gettext('Load average')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Memory usage'),
- fields: ['memtotal','memused'],
- fieldTitles: [gettext('Total'), gettext('RAM usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Network traffic'),
- fields: ['netin','netout'],
- store: rrdstore
- }
- ]
- }
- ],
- listeners: {
- activate: function() { rstore.startUpdate(); rrdstore.startUpdate(); },
- destroy: function() { rstore.stopUpdate(); rrdstore.stopUpdate(); }
- }
- });
-
- me.callParent();
- }
-});
-/*global Blob*/
-Ext.define('PVE.node.SubscriptionKeyEdit', {
- extend: 'Proxmox.window.Edit',
- title: gettext('Upload Subscription Key'),
- width: 300,
- items: {
- xtype: 'textfield',
- name: 'key',
- value: '',
- fieldLabel: gettext('Subscription Key')
- },
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- me.load();
- }
-});
-
-Ext.define('PVE.node.Subscription', {
- extend: 'Proxmox.grid.ObjectGrid',
-
- alias: ['widget.pveNodeSubscription'],
-
- onlineHelp: 'getting_help',
-
- viewConfig: {
- enableTextSelection: true
- },
-
- showReport: function() {
- var me = this;
- var nodename = me.pveSelNode.data.node;
-
- var getReportFileName = function() {
- var now = Ext.Date.format(new Date(), 'D-d-F-Y-G-i');
- return me.nodename + '-report-' + now + '.txt';
- };
-
- var view = Ext.createWidget('component', {
- itemId: 'system-report-view',
- scrollable: true,
- style: {
- 'background-color': '#23272a',
- 'white-space': 'pre',
- 'font-family': 'monospace',
- padding: '5px'
- }
- });
-
- var reportWindow = Ext.create('Ext.window.Window', {
- title: gettext('System Report'),
- width: 1024,
- height: 600,
- layout: 'fit',
- modal: true,
- buttons: [
- '->',
- {
- text: gettext('Download'),
- handler: function() {
- var fileContent = reportWindow.getComponent('system-report-view').html;
- var fileName = getReportFileName();
-
- // Internet Explorer
- if (window.navigator.msSaveOrOpenBlob) {
- navigator.msSaveOrOpenBlob(new Blob([fileContent]), fileName);
- } else {
- var element = document.createElement('a');
- element.setAttribute('href', 'data:text/plain;charset=utf-8,'
- + encodeURIComponent(fileContent));
- element.setAttribute('download', fileName);
- element.style.display = 'none';
- document.body.appendChild(element);
- element.click();
- document.body.removeChild(element);
- }
- }
- }
- ],
- items: view
- });
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/nodes/' + me.nodename + '/report',
- method: 'GET',
- waitMsgTarget: me,
- failure: function(response) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response) {
- var report = Ext.htmlEncode(response.result.data);
- reportWindow.show();
- view.update(report);
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var reload = function() {
- me.rstore.load();
- };
-
- var baseurl = '/nodes/' + me.nodename + '/subscription';
-
- var render_status = function(value) {
-
- var message = me.getObjectValue('message');
-
- if (message) {
- return value + ": " + message;
- }
- return value;
- };
-
- var rows = {
- productname: {
- header: gettext('Type')
- },
- key: {
- header: gettext('Subscription Key')
- },
- status: {
- header: gettext('Status'),
- renderer: render_status
- },
- message: {
- visible: false
- },
- serverid: {
- header: gettext('Server ID')
- },
- sockets: {
- header: gettext('Sockets')
- },
- checktime: {
- header: gettext('Last checked'),
- renderer: Proxmox.Utils.render_timestamp
- },
- nextduedate: {
- header: gettext('Next due date')
- }
- };
-
- Ext.apply(me, {
- url: '/api2/json' + baseurl,
- cwidth1: 170,
- tbar: [
- {
- text: gettext('Upload Subscription Key'),
- handler: function() {
- var win = Ext.create('PVE.node.SubscriptionKeyEdit', {
- url: '/api2/extjs/' + baseurl
- });
- win.show();
- win.on('destroy', reload);
- }
- },
- {
- text: gettext('Check'),
- handler: function() {
- Proxmox.Utils.API2Request({
- params: { force: 1 },
- url: baseurl,
- method: 'POST',
- waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- callback: reload
- });
- }
- },
- {
- text: gettext('System Report'),
- handler: function() {
- Proxmox.Utils.checked_command(function (){ me.showReport(); });
- }
- }
- ],
- rows: rows,
- listeners: {
- activate: reload
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.node.CertificateView', {
- extend: 'Ext.container.Container',
- xtype: 'pveCertificatesView',
-
- onlineHelp: 'sysadmin_certificate_management',
-
- mixins: ['Proxmox.Mixin.CBind' ],
-
- items: [
- {
- xtype: 'pveCertView',
- border: 0,
- cbind: {
- nodename: '{nodename}'
- }
- },
- {
- xtype: 'pveACMEView',
- border: 0,
- cbind: {
- nodename: '{nodename}'
- }
- }
- ]
-
-});
-
-Ext.define('PVE.node.CertificateViewer', {
- extend: 'Proxmox.window.Edit',
-
- title: gettext('Certificate'),
-
- fieldDefaults: {
- labelWidth: 120
- },
- width: 800,
- resizable: true,
-
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Name'),
- name: 'filename'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Fingerprint'),
- name: 'fingerprint'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Issuer'),
- name: 'issuer'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Subject'),
- name: 'subject'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Valid Since'),
- renderer: Proxmox.Utils.render_timestamp,
- name: 'notbefore'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Expires'),
- renderer: Proxmox.Utils.render_timestamp,
- name: 'notafter'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Subject Alternative Names'),
- name: 'san',
- renderer: PVE.Utils.render_san
- },
- {
- xtype: 'textarea',
- editable: false,
- grow: true,
- growMax: 200,
- fieldLabel: gettext('Certificate'),
- name: 'pem'
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.cert) {
- throw "no cert given";
- }
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- me.url = '/nodes/' + me.nodename + '/certificates/info';
- me.callParent();
-
- // hide OK/Reset button, because we just want to show data
- me.down('toolbar[dock=bottom]').setVisible(false);
-
- me.load({
- success: function(response) {
- if (Ext.isArray(response.result.data)) {
- Ext.Array.each(response.result.data, function(item) {
- if (item.filename === me.cert) {
- me.setValues(item);
- return false;
- }
- });
- }
- }
- });
- }
-});
-
-Ext.define('PVE.node.CertUpload', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCertUpload',
-
- title: gettext('Upload Custom Certificate'),
- resizable: false,
- isCreate: true,
- submitText: gettext('Upload'),
- method: 'POST',
- width: 600,
-
- apiCallDone: function(success, response, options) {
- if (!success) {
- return;
- }
-
- var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
- Ext.getBody().mask(txt, ['pve-static-mask']);
- // reload after 10 seconds automatically
- Ext.defer(function() {
- window.location.reload(true);
- }, 10000);
- },
-
- items: [
- {
- fieldLabel: gettext('Private Key (Optional)'),
- labelAlign: 'top',
- emptyText: gettext('No change'),
- name: 'key',
- xtype: 'textarea'
- },
- {
- xtype: 'filebutton',
- text: gettext('From File'),
- listeners: {
- change: function(btn, e, value) {
- var me = this.up('form');
- e = e.event;
- Ext.Array.each(e.target.files, function(file) {
- PVE.Utils.loadSSHKeyFromFile(file, function(res) {
- me.down('field[name=key]').setValue(res);
- });
- });
- btn.reset();
- }
- }
- },
- {
- xtype: 'box',
- autoEl: 'hr'
- },
- {
- fieldLabel: gettext('Certificate Chain'),
- labelAlign: 'top',
- allowBlank: false,
- name: 'certificates',
- xtype: 'textarea'
- },
- {
- xtype: 'filebutton',
- text: gettext('From File'),
- listeners: {
- change: function(btn, e, value) {
- var me = this.up('form');
- e = e.event;
- Ext.Array.each(e.target.files, function(file) {
- PVE.Utils.loadSSHKeyFromFile(file, function(res) {
- me.down('field[name=certificates]').setValue(res);
- });
- });
- btn.reset();
- }
- }
- },
- {
- xtype: 'hidden',
- name: 'restart',
- value: '1'
- },
- {
- xtype: 'hidden',
- name: 'force',
- value: '1'
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- me.url = '/nodes/' + me.nodename + '/certificates/custom';
-
- me.callParent();
- }
-});
-
-Ext.define('pve-certificate', {
- extend: 'Ext.data.Model',
-
- fields: [ 'filename', 'fingerprint', 'issuer', 'notafter', 'notbefore', 'subject', 'san' ],
- idProperty: 'filename'
-});
-
-Ext.define('PVE.node.Certificates', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveCertView',
-
- tbar: [
- {
- xtype: 'button',
- text: gettext('Upload Custom Certificate'),
- handler: function() {
- var me = this.up('grid');
- var win = Ext.create('PVE.node.CertUpload', {
- nodename: me.nodename
- });
- win.show();
- win.on('destroy', me.reload, me);
- }
- },
- {
- xtype: 'button',
- itemId: 'deletebtn',
- text: gettext('Delete Custom Certificate'),
- handler: function() {
- var me = this.up('grid');
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/certificates/custom?restart=1',
- method: 'DELETE',
- success: function(response, opt) {
- var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
- Ext.getBody().mask(txt, ['pve-static-mask']);
- // reload after 10 seconds automatically
- Ext.defer(function() {
- window.location.reload(true);
- }, 10000);
- },
- failure: function(response, opt) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- },
- '-',
- {
- xtype: 'proxmoxButton',
- itemId: 'viewbtn',
- disabled: true,
- text: gettext('View Certificate'),
- handler: function() {
- var me = this.up('grid');
- me.view_certificate();
- }
- }
- ],
-
- columns: [
- {
- header: gettext('File'),
- width: 150,
- dataIndex: 'filename'
- },
- {
- header: gettext('Issuer'),
- flex: 1,
- dataIndex: 'issuer'
- },
- {
- header: gettext('Subject'),
- flex: 1,
- dataIndex: 'subject'
- },
- {
- header: gettext('Valid Since'),
- width: 150,
- dataIndex: 'notbefore',
- renderer: Proxmox.Utils.render_timestamp
- },
- {
- header: gettext('Expires'),
- width: 150,
- dataIndex: 'notafter',
- renderer: Proxmox.Utils.render_timestamp
- },
- {
- header: gettext('Subject Alternative Names'),
- flex: 1,
- dataIndex: 'san',
- renderer: PVE.Utils.render_san
- },
- {
- header: gettext('Fingerprint'),
- dataIndex: 'fingerprint',
- hidden: true
- },
- {
- header: gettext('PEM'),
- dataIndex: 'pem',
- hidden: true
- }
- ],
-
- reload: function() {
- var me = this;
- me.rstore.load();
- },
-
- set_button_status: function() {
- var me = this;
- var rec = me.rstore.getById('pveproxy-ssl.pem');
-
- me.down('#deletebtn').setDisabled(!rec);
- },
-
- view_certificate: function() {
- var me = this;
- var selection = me.getSelection();
- if (!selection || selection.length < 1) {
- return;
- }
- var win = Ext.create('PVE.node.CertificateViewer', {
- cert: selection[0].data.filename,
- nodename : me.nodename
- });
- win.show();
- },
-
- listeners: {
- itemdblclick: 'view_certificate'
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- me.rstore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'certs-' + me.nodename,
- model: 'pve-certificate',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/certificates/info'
- }
- });
-
- me.store = {
- type: 'diff',
- rstore: me.rstore
- };
-
- me.callParent();
-
- me.mon(me.rstore, 'load', me.set_button_status, me);
- me.rstore.startUpdate();
- }
-});
-Ext.define('PVE.node.ACMEEditor', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveACMEEditor',
-
- subject: gettext('Domains'),
- items: [
- {
- xtype: 'inputpanel',
- items: [
- {
- xtype: 'textarea',
- fieldLabel: gettext('Domains'),
- emptyText: "domain1.example.com\ndomain2.example.com",
- name: 'domains'
- }
- ],
- onGetValues: function(values) {
- if (!values.domains) {
- return {
- 'delete': 'acme'
- };
- }
- var domains = values.domains.split(/\n/).join(';');
- return {
- 'acme': 'domains=' + domains
- };
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
- me.callParent();
-
- me.load({
- success: function(response, opts) {
- var res = PVE.Parser.parseACME(response.result.data.acme);
- if (res) {
- res.domains = res.domains.join(' ');
- me.setValues(res);
- }
- }
- });
- }
-});
-
-Ext.define('PVE.node.ACMEAccountCreate', {
- extend: 'Proxmox.window.Edit',
-
- width: 400,
- title: gettext('Register Account'),
- isCreate: true,
- method: 'POST',
- submitText: gettext('Register'),
- url: '/cluster/acme/account',
- showTaskViewer: true,
-
- items: [
- {
- xtype: 'proxmoxComboGrid',
- name: 'directory',
- allowBlank: false,
- valueField: 'url',
- displayField: 'name',
- fieldLabel: gettext('ACME Directory'),
- store: {
- autoLoad: true,
- fields: ['name', 'url'],
- idProperty: ['name'],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/acme/directories'
- },
- sorters: {
- property: 'name',
- order: 'ASC'
- }
- },
- listConfig: {
- columns: [
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- header: gettext('URL'),
- dataIndex: 'url',
- flex: 1
- }
- ]
- },
- listeners: {
- change: function(combogrid, value) {
- var me = this;
- if (!value) {
- return;
- }
-
- var disp = me.up('window').down('#tos_url_display');
- var field = me.up('window').down('#tos_url');
- var checkbox = me.up('window').down('#tos_checkbox');
-
- disp.setValue(gettext('Loading'));
- field.setValue(undefined);
- checkbox.setValue(undefined);
-
- Proxmox.Utils.API2Request({
- url: '/cluster/acme/tos',
- method: 'GET',
- params: {
- directory: value
- },
- success: function(response, opt) {
- me.up('window').down('#tos_url').setValue(response.result.data);
- me.up('window').down('#tos_url_display').setValue(response.result.data);
- },
- failure: function(response, opt) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- }
- },
- {
- xtype: 'displayfield',
- itemId: 'tos_url_display',
- fieldLabel: gettext('Terms of Service'),
- renderer: PVE.Utils.render_optional_url,
- name: 'tos_url_display'
- },
- {
- xtype: 'hidden',
- itemId: 'tos_url',
- name: 'tos_url'
- },
- {
- xtype: 'proxmoxcheckbox',
- itemId: 'tos_checkbox',
- fieldLabel: gettext('Accept TOS'),
- submitValue: false,
- validateValue: function(value) {
- if (value && this.checked) {
- return true;
- }
- return false;
- }
- },
- {
- xtype: 'textfield',
- name: 'contact',
- vtype: 'email',
- allowBlank: false,
- fieldLabel: gettext('E-Mail')
- }
- ]
-
-});
-
-Ext.define('PVE.node.ACMEAccountView', {
- extend: 'Proxmox.window.Edit',
-
- width: 600,
- fieldDefaults: {
- labelWidth: 140
- },
-
- title: gettext('Account'),
-
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('E-Mail'),
- name: 'email'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Created'),
- name: 'createdAt'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Status'),
- name: 'status'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Directory'),
- renderer: PVE.Utils.render_optional_url,
- name: 'directory'
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Terms of Services'),
- renderer: PVE.Utils.render_optional_url,
- name: 'tos'
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.accountname) {
- throw "no account name defined";
- }
-
- me.url = '/cluster/acme/account/' + me.accountname;
-
- me.callParent();
-
- // hide OK/Reset button, because we just want to show data
- me.down('toolbar[dock=bottom]').setVisible(false);
-
- me.load({
- success: function(response) {
- var data = response.result.data;
- data.email = data.account.contact[0];
- data.createdAt = data.account.createdAt;
- data.status = data.account.status;
- me.setValues(data);
- }
- });
- }
-});
-
-Ext.define('PVE.node.ACME', {
- extend: 'Proxmox.grid.ObjectGrid',
- xtype: 'pveACMEView',
-
- margin: '10 0 0 0',
- title: 'ACME',
-
- tbar: [
- {
- xtype: 'button',
- itemId: 'edit',
- text: gettext('Edit Domains'),
- handler: function() {
- this.up('grid').run_editor();
- }
- },
- {
- xtype: 'button',
- itemId: 'createaccount',
- text: gettext('Register Account'),
- handler: function() {
- var me = this.up('grid');
- var win = Ext.create('PVE.node.ACMEAccountCreate', {
- taskDone: function() {
- me.load_account();
- me.reload();
- }
- });
- win.show();
- }
- },
- {
- xtype: 'button',
- itemId: 'viewaccount',
- text: gettext('View Account'),
- handler: function() {
- var me = this.up('grid');
- var win = Ext.create('PVE.node.ACMEAccountView', {
- accountname: 'default'
- });
- win.show();
- }
- },
- {
- xtype: 'button',
- itemId: 'order',
- text: gettext('Order Certificate'),
- handler: function() {
- var me = this.up('grid');
-
- Proxmox.Utils.API2Request({
- method: 'POST',
- params: {
- force: 1
- },
- url: '/nodes/' + me.nodename + '/certificates/acme/certificate',
- success: function(response, opt) {
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: response.result.data,
- taskDone: function(success) {
- me.certificate_order_finished(success);
- }
- });
- win.show();
- },
- failure: function(response, opt) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- }
- ],
-
- certificate_order_finished: function(success) {
- if (!success) {
- return;
- }
- var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
- Ext.getBody().mask(txt, ['pve-static-mask']);
- // reload after 10 seconds automatically
- Ext.defer(function() {
- window.location.reload(true);
- }, 10000);
- },
-
- set_button_status: function() {
- var me = this;
-
- var account = !!me.account;
- var acmeObj = PVE.Parser.parseACME(me.getObjectValue('acme'));
- var domains = acmeObj ? acmeObj.domains.length : 0;
-
- var order = me.down('#order');
- order.setVisible(account);
- order.setDisabled(!account || !domains);
-
- me.down('#createaccount').setVisible(!account);
- me.down('#viewaccount').setVisible(account);
- },
-
- load_account: function() {
- var me = this;
-
- // for now we only use the 'default' account
- Proxmox.Utils.API2Request({
- url: '/cluster/acme/account/default',
- success: function(response, opt) {
- me.account = response.result.data;
- me.set_button_status();
- },
- failure: function(response, opt) {
- me.account = undefined;
- me.set_button_status();
- }
- });
- },
-
- run_editor: function() {
- var me = this;
- var win = Ext.create(me.rows.acme.editor, me.editorConfig);
- win.show();
- win.on('destroy', me.reload, me);
- },
-
- listeners: {
- itemdblclick: 'run_editor'
- },
-
- // account data gets loaded here
- account: undefined,
-
- disableSelection: true,
-
- initComponent: function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no nodename given";
- }
-
- me.url = '/api2/json/nodes/' + me.nodename + '/config';
-
- me.editorConfig = {
- url: '/api2/extjs/nodes/' + me.nodename + '/config'
- };
- /*jslint confusion: true*/
- /*acme is a string above*/
- me.rows = {
- acme: {
- defaultValue: '',
- header: gettext('Domains'),
- editor: 'PVE.node.ACMEEditor',
- renderer: function(value) {
- var acmeObj = PVE.Parser.parseACME(value);
- if (acmeObj) {
- return acmeObj.domains.join(' ');
- }
- return Proxmox.Utils.noneText;
- }
- }
- };
- /*jslint confusion: false*/
-
- me.callParent();
- me.mon(me.rstore, 'load', me.set_button_status, me);
- me.rstore.startUpdate();
- me.load_account();
- }
-});
-Ext.define('PVE.node.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.node.Config',
-
- onlineHelp: 'chapter_system_administration',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: "/api2/json/nodes/" + nodename + "/status",
- interval: 1000
- });
-
- var node_command = function(cmd) {
- Proxmox.Utils.API2Request({
- params: { command: cmd },
- url: '/nodes/' + nodename + '/status',
- method: 'POST',
- waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- };
-
- var actionBtn = Ext.create('Ext.Button', {
- text: gettext('Bulk Actions'),
- iconCls: 'fa fa-fw fa-ellipsis-v',
- disabled: !caps.nodes['Sys.PowerMgmt'],
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Bulk Start'),
- iconCls: 'fa fa-fw fa-play',
- handler: function() {
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: nodename,
- title: gettext('Bulk Start'),
- btnText: gettext('Start'),
- action: 'startall'
- });
- win.show();
- }
- },
- {
- text: gettext('Bulk Stop'),
- iconCls: 'fa fa-fw fa-stop',
- handler: function() {
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: nodename,
- title: gettext('Bulk Stop'),
- btnText: gettext('Stop'),
- action: 'stopall'
- });
- win.show();
- }
- },
- {
- text: gettext('Bulk Migrate'),
- iconCls: 'fa fa-fw fa-send-o',
- handler: function() {
- var win = Ext.create('PVE.window.BulkAction', {
- nodename: nodename,
- title: gettext('Bulk Migrate'),
- btnText: gettext('Migrate'),
- action: 'migrateall'
- });
- win.show();
- }
- }
- ]
- })
- });
-
- var restartBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('Reboot'),
- disabled: !caps.nodes['Sys.PowerMgmt'],
- dangerous: true,
- confirmMsg: Ext.String.format(gettext("Reboot node '{0}'?"), nodename),
- handler: function() {
- node_command('reboot');
- },
- iconCls: 'fa fa-undo'
- });
-
- var shutdownBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('Shutdown'),
- disabled: !caps.nodes['Sys.PowerMgmt'],
- dangerous: true,
- confirmMsg: Ext.String.format(gettext("Shutdown node '{0}'?"), nodename),
- handler: function() {
- node_command('shutdown');
- },
- iconCls: 'fa fa-power-off'
- });
-
- var shellBtn = Ext.create('PVE.button.ConsoleButton', {
- disabled: !caps.nodes['Sys.Console'],
- text: gettext('Shell'),
- consoleType: 'shell',
- nodename: nodename
- });
-
- me.items = [];
-
- Ext.apply(me, {
- title: gettext('Node') + " '" + nodename + "'",
- hstateid: 'nodetab',
- defaults: { statusStore: me.statusStore },
- tbar: [ restartBtn, shutdownBtn, shellBtn, actionBtn]
- });
-
- if (caps.nodes['Sys.Audit']) {
- me.items.push(
- {
- title: gettext('Summary'),
- iconCls: 'fa fa-book',
- itemId: 'summary',
- xtype: 'pveNodeSummary'
- },
- {
- title: gettext('Notes'),
- iconCls: 'fa fa-sticky-note-o',
- itemId: 'notes',
- xtype: 'pveNotesView'
- }
- );
- }
-
- if (caps.nodes['Sys.Console']) {
- me.items.push(
- {
- title: gettext('Shell'),
- iconCls: 'fa fa-terminal',
- itemId: 'jsconsole',
- xtype: 'pveNoVncConsole',
- consoleType: 'shell',
- xtermjs: true,
- nodename: nodename
- }
- );
- }
-
- if (caps.nodes['Sys.Audit']) {
- me.items.push(
- {
- title: gettext('System'),
- iconCls: 'fa fa-cogs',
- itemId: 'services',
- expandedOnInit: true,
- startOnlyServices: {
- 'pveproxy': true,
- 'pvedaemon': true,
- 'pve-cluster': true
- },
- nodename: nodename,
- onlineHelp: 'pve_service_daemons',
- xtype: 'proxmoxNodeServiceView'
- },
- {
- title: gettext('Network'),
- iconCls: 'fa fa-exchange',
- itemId: 'network',
- groups: ['services'],
- nodename: nodename,
- onlineHelp: 'sysadmin_network_configuration',
- xtype: 'proxmoxNodeNetworkView'
- },
- {
- title: gettext('Certificates'),
- iconCls: 'fa fa-certificate',
- itemId: 'certificates',
- groups: ['services'],
- nodename: nodename,
- xtype: 'pveCertificatesView'
- },
- {
- title: gettext('DNS'),
- iconCls: 'fa fa-globe',
- groups: ['services'],
- itemId: 'dns',
- nodename: nodename,
- onlineHelp: 'sysadmin_network_configuration',
- xtype: 'proxmoxNodeDNSView'
- },
- {
- title: gettext('Hosts'),
- iconCls: 'fa fa-globe',
- groups: ['services'],
- itemId: 'hosts',
- nodename: nodename,
- onlineHelp: 'sysadmin_network_configuration',
- xtype: 'proxmoxNodeHostsView'
- },
- {
- title: gettext('Time'),
- itemId: 'time',
- groups: ['services'],
- nodename: nodename,
- xtype: 'proxmoxNodeTimeView',
- iconCls: 'fa fa-clock-o'
- });
- }
-
- if (caps.nodes['Sys.Syslog']) {
- me.items.push({
- title: 'Syslog',
- iconCls: 'fa fa-list',
- groups: ['services'],
- disabled: !caps.nodes['Sys.Syslog'],
- itemId: 'syslog',
- xtype: 'proxmoxJournalView',
- url: "/api2/extjs/nodes/" + nodename + "/journal"
- });
-
- if (caps.nodes['Sys.Modify']) {
- me.items.push({
- title: gettext('Updates'),
- iconCls: 'fa fa-refresh',
- disabled: !caps.nodes['Sys.Console'],
- // do we want to link to system updates instead?
- itemId: 'apt',
- xtype: 'proxmoxNodeAPT',
- upgradeBtn: {
- xtype: 'pveConsoleButton',
- disabled: Proxmox.UserName !== 'root@pam',
- text: gettext('Upgrade'),
- consoleType: 'upgrade',
- nodename: nodename
- },
- nodename: nodename
- });
- }
- }
-
- if (caps.nodes['Sys.Audit']) {
- me.items.push(
- {
- xtype: 'pveFirewallRules',
- iconCls: 'fa fa-shield',
- title: gettext('Firewall'),
- allow_iface: true,
- base_url: '/nodes/' + nodename + '/firewall/rules',
- list_refs_url: '/cluster/firewall/refs',
- itemId: 'firewall'
- },
- {
- xtype: 'pveFirewallOptions',
- title: gettext('Options'),
- iconCls: 'fa fa-gear',
- onlineHelp: 'pve_firewall_host_specific_configuration',
- groups: ['firewall'],
- base_url: '/nodes/' + nodename + '/firewall/options',
- fwtype: 'node',
- itemId: 'firewall-options'
- });
- }
-
-
- if (caps.nodes['Sys.Audit']) {
- me.items.push(
- {
- title: gettext('Disks'),
- itemId: 'storage',
- expandedOnInit: true,
- iconCls: 'fa fa-hdd-o',
- xtype: 'pveNodeDiskList'
- },
- {
- title: 'LVM',
- itemId: 'lvm',
- onlineHelp: 'chapter_lvm',
- iconCls: 'fa fa-square',
- groups: ['storage'],
- xtype: 'pveLVMList'
- },
- {
- title: 'LVM-Thin',
- itemId: 'lvmthin',
- onlineHelp: 'chapter_lvm',
- iconCls: 'fa fa-square-o',
- groups: ['storage'],
- xtype: 'pveLVMThinList'
- },
- {
- title: Proxmox.Utils.directoryText,
- itemId: 'directory',
- onlineHelp: 'chapter_storage',
- iconCls: 'fa fa-folder',
- groups: ['storage'],
- xtype: 'pveDirectoryList'
- },
- {
- title: 'ZFS',
- itemId: 'zfs',
- onlineHelp: 'chapter_zfs',
- iconCls: 'fa fa-th-large',
- groups: ['storage'],
- xtype: 'pveZFSList'
- },
- {
- title: 'Ceph',
- itemId: 'ceph',
- iconCls: 'fa fa-ceph',
- xtype: 'pveNodeCephStatus'
- },
- {
- xtype: 'pveReplicaView',
- iconCls: 'fa fa-retweet',
- title: gettext('Replication'),
- itemId: 'replication'
- },
- {
- xtype: 'pveNodeCephConfigCrush',
- title: gettext('Configuration'),
- iconCls: 'fa fa-gear',
- groups: ['ceph'],
- itemId: 'ceph-config'
- },
- {
- xtype: 'pveNodeCephMonMgr',
- title: gettext('Monitor'),
- iconCls: 'fa fa-tv',
- groups: ['ceph'],
- itemId: 'ceph-monlist'
- },
- {
- xtype: 'pveNodeCephOsdTree',
- title: 'OSD',
- iconCls: 'fa fa-hdd-o',
- groups: ['ceph'],
- itemId: 'ceph-osdtree'
- },
- {
- xtype: 'pveNodeCephFSPanel',
- title: 'CephFS',
- iconCls: 'fa fa-folder',
- groups: ['ceph'],
- nodename: nodename,
- itemId: 'ceph-cephfspanel'
- },
- {
- xtype: 'pveNodeCephPoolList',
- title: 'Pools',
- iconCls: 'fa fa-sitemap',
- groups: ['ceph'],
- itemId: 'ceph-pools'
- }
- );
- }
-
- if (caps.nodes['Sys.Syslog']) {
- me.items.push(
- {
- xtype: 'proxmoxLogView',
- title: gettext('Log'),
- iconCls: 'fa fa-list',
- groups: ['firewall'],
- onlineHelp: 'chapter_pve_firewall',
- url: '/api2/extjs/nodes/' + nodename + '/firewall/log',
- itemId: 'firewall-fwlog'
- },
- {
- title: gettext('Log'),
- itemId: 'ceph-log',
- iconCls: 'fa fa-list',
- groups: ['ceph'],
- onlineHelp: 'chapter_pveceph',
- xtype: 'cephLogView',
- url: "/api2/extjs/nodes/" + nodename + "/ceph/log",
- nodename: nodename
- });
- }
-
- me.items.push(
- {
- title: gettext('Task History'),
- iconCls: 'fa fa-list',
- itemId: 'tasks',
- nodename: nodename,
- xtype: 'proxmoxNodeTasks'
- },
- {
- title: gettext('Subscription'),
- iconCls: 'fa fa-support',
- itemId: 'support',
- xtype: 'pveNodeSubscription',
- nodename: nodename
- }
- );
-
- me.callParent();
-
- me.mon(me.statusStore, 'load', function(s, records, success) {
- var uptimerec = s.data.get('uptime');
- var powermgmt = uptimerec ? uptimerec.data.value : false;
- if (!caps.nodes['Sys.PowerMgmt']) {
- powermgmt = false;
- }
- restartBtn.setDisabled(!powermgmt);
- shutdownBtn.setDisabled(!powermgmt);
- shellBtn.setDisabled(!powermgmt);
- });
-
- me.on('afterrender', function() {
- me.statusStore.startUpdate();
- });
-
- me.on('destroy', function() {
- me.statusStore.stopUpdate();
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.window.Migrate', {
- extend: 'Ext.window.Window',
-
- vmtype: undefined,
- nodename: undefined,
- vmid: undefined,
-
- viewModel: {
- data: {
- vmid: undefined,
- nodename: undefined,
- vmtype: undefined,
- running: false,
- qemu: {
- onlineHelp: 'qm_migration',
- commonName: 'VM'
- },
- lxc: {
- onlineHelp: 'pct_migration',
- commonName: 'CT'
- },
- migration: {
- possible: true,
- preconditions: [],
- 'with-local-disks': 0,
- mode: undefined,
- allowedNodes: undefined
- }
-
- },
-
- formulas: {
- setMigrationMode: function(get) {
- if (get('running')){
- if (get('vmtype') === 'qemu') {
- return gettext('Online');
- } else {
- return gettext('Restart Mode');
- }
- } else {
- return gettext('Offline');
- }
- },
- setStorageselectorHidden: function(get) {
- if (get('migration.with-local-disks') && get('running')) {
- return false;
- } else {
- return true;
- }
- }
- }
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'panel[reference=formPanel]': {
- validityChange: function(panel, isValid) {
- this.getViewModel().set('migration.possible', isValid);
- this.checkMigratePreconditions();
- }
- }
- },
-
- init: function(view) {
- var me = this,
- vm = view.getViewModel();
-
- if (!view.nodename) {
- throw "missing custom view config: nodename";
- }
- vm.set('nodename', view.nodename);
-
- if (!view.vmid) {
- throw "missing custom view config: vmid";
- }
- vm.set('vmid', view.vmid);
-
- if (!view.vmtype) {
- throw "missing custom view config: vmtype";
- }
- vm.set('vmtype', view.vmtype);
-
-
- view.setTitle(
- Ext.String.format('{0} {1}{2}', gettext('Migrate'), vm.get(view.vmtype).commonName, view.vmid)
- );
- me.lookup('proxmoxHelpButton').setHelpConfig({
- onlineHelp: vm.get(view.vmtype).onlineHelp
- });
- me.checkMigratePreconditions();
- me.lookup('formPanel').isValid();
-
- },
-
- onTargetChange: function (nodeSelector) {
- //Always display the storages of the currently seleceted migration target
- this.lookup('pveDiskStorageSelector').setNodename(nodeSelector.value);
- this.checkMigratePreconditions();
- },
-
- startMigration: function() {
- var me = this,
- view = me.getView(),
- vm = me.getViewModel();
-
- var values = me.lookup('formPanel').getValues();
- var params = {
- target: values.target
- };
-
- if (vm.get('migration.mode')) {
- params[vm.get('migration.mode')] = 1;
- }
- if (vm.get('migration.with-local-disks')) {
- params['with-local-disks'] = 1;
- }
- //only submit targetstorage if vm is running, storage migration to different storage is only possible online
- if (vm.get('migration.with-local-disks') && vm.get('running')) {
- params.targetstorage = values.targetstorage;
- }
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + vm.get('nodename') + '/' + vm.get('vmtype') + '/' + vm.get('vmid') + '/migrate',
- waitMsgTarget: view,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var extraTitle = Ext.String.format(' ({0} ---> {1})', vm.get('nodename'), params.target);
-
- Ext.create('Proxmox.window.TaskViewer', {
- upid: upid,
- extraTitle: extraTitle
- }).show();
-
- view.close();
- }
- });
-
- },
-
- checkMigratePreconditions: function() {
- var me = this,
- vm = me.getViewModel();
-
-
- var vmrec = PVE.data.ResourceStore.findRecord('vmid', vm.get('vmid'),
- 0, false, false, true);
- if (vmrec && vmrec.data && vmrec.data.running) {
- vm.set('running', true);
- }
-
- if (vm.get('vmtype') === 'qemu') {
- me.checkQemuPreconditions();
- } else {
- me.checkLxcPreconditions();
- }
- me.lookup('pveNodeSelector').disallowedNodes = [vm.get('nodename')];
-
- // Only allow nodes where the local storage is available in case of offline migration
- // where storage migration is not possible
- me.lookup('pveNodeSelector').allowedNodes = vm.get('migration.allowedNodes');
-
- me.lookup('formPanel').isValid();
-
- },
-
- checkQemuPreconditions: function() {
- var me = this,
- vm = me.getViewModel(),
- migrateStats;
-
- if (vm.get('running')) {
- vm.set('migration.mode', 'online');
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + vm.get('nodename') + '/' + vm.get('vmtype') + '/' + vm.get('vmid') + '/migrate',
- method: 'GET',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- migrateStats = response.result.data;
- if (migrateStats.running) {
- vm.set('running', true);
- }
- // Get migration object from viewmodel to prevent
- // to many bind callbacks
- var migration = vm.get('migration');
- migration.preconditions = [];
-
- if (migrateStats.allowed_nodes) {
- migration.allowedNodes = migrateStats.allowed_nodes;
- var target = me.lookup('pveNodeSelector').value;
- if (target.length && !migrateStats.allowed_nodes.includes(target)) {
- let disallowed = migrateStats.not_allowed_nodes[target];
- let missing_storages = disallowed.unavailable_storages.join(', ');
-
- migration.possible = false;
- migration.preconditions.push({
- text: 'Storage (' + missing_storages + ') not available on selected target. ' +
- 'Start VM to use live storage migration or select other target node',
- severity: 'error'
- });
- }
- }
-
- if (migrateStats.local_resources.length) {
- migration.possible = false;
- migration.preconditions.push({
- text: 'Can\'t migrate VM with local resources: '+ migrateStats.local_resources.join(', '),
- severity: 'error'
- });
- }
-
- if (migrateStats.local_disks.length) {
-
- migrateStats.local_disks.forEach(function (disk) {
- if (disk.cdrom && disk.cdrom === 1) {
- migration.possible = false;
- migration.preconditions.push({
- text: "Can't migrate VM with local CD/DVD",
- severity: 'error'
- });
-
- } else if (!disk.referenced_in_config) {
- migration.possible = false;
- migration.preconditions.push({
- text: 'Found not referenced/unused disk via storage: '+ disk.volid,
- severity: 'error'
- });
- } else {
- migration['with-local-disks'] = 1;
- migration.preconditions.push({
- text:'Migration with local disk might take long: ' + disk.volid
- +' (' + PVE.Utils.render_size(disk.size) + ')',
- severity: 'warning'
- });
- }
- });
-
- }
-
- vm.set('migration', migration);
-
- }
- });
- },
- checkLxcPreconditions: function() {
- var me = this,
- vm = me.getViewModel();
- if (vm.get('running')) {
- vm.set('migration.mode', 'restart');
- }
- }
-
-
- },
-
- width: 600,
- modal: true,
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- border: false,
- items: [
- {
- xtype: 'form',
- reference: 'formPanel',
- bodyPadding: 10,
- border: false,
- layout: {
- type: 'column'
- },
- items: [
- {
- xtype: 'container',
- columnWidth: 0.5,
- items: [{
- xtype: 'displayfield',
- name: 'source',
- fieldLabel: gettext('Source node'),
- bind: {
- value: '{nodename}'
- }
- },
- {
- xtype: 'displayfield',
- reference: 'migrationMode',
- fieldLabel: gettext('Mode'),
- bind: {
- value: '{setMigrationMode}'
- }
- }]
- },
- {
- xtype: 'container',
- columnWidth: 0.5,
- items: [{
- xtype: 'pveNodeSelector',
- reference: 'pveNodeSelector',
- name: 'target',
- fieldLabel: gettext('Target node'),
- allowBlank: false,
- disallowedNodes: undefined,
- onlineValidator: true,
- listeners: {
- change: 'onTargetChange'
- }
- },
- {
- xtype: 'pveStorageSelector',
- reference: 'pveDiskStorageSelector',
- name: 'targetstorage',
- fieldLabel: gettext('Target storage'),
- storageContent: 'images',
- bind: {
- hidden: '{setStorageselectorHidden}'
- }
- }]
- }
- ]
- },
- {
- xtype: 'gridpanel',
- reference: 'preconditionGrid',
- selectable: false,
- flex: 1,
- columns: [{
- text: '',
- dataIndex: 'severity',
- renderer: function(v) {
- switch (v) {
- case 'warning':
- return ' ';
- case 'error':
- return ' ';
- default:
- return v;
- }
- },
- width: 35
- },
- {
- text: 'Info',
- dataIndex: 'text',
- cellWrap: true,
- flex: 1
- }],
- bind: {
- hidden: '{!migration.preconditions.length}',
- store: {
- fields: ['severity','text'],
- data: '{migration.preconditions}'
- }
- }
- }
-
- ],
- buttons: [
- {
- xtype: 'proxmoxHelpButton',
- reference: 'proxmoxHelpButton',
- onlineHelp: 'pct_migration',
- listenToGlobalEvent: false,
- hidden: false
- },
- '->',
- {
- xtype: 'button',
- reference: 'submitButton',
- text: gettext('Migrate'),
- handler: 'startMigration',
- bind: {
- disabled: '{!migration.possible}'
- }
- }
- ]
-});
-Ext.define('PVE.window.BulkAction', {
- extend: 'Ext.window.Window',
-
- resizable: true,
- width: 800,
- modal: true,
- layout: {
- type: 'fit'
- },
- border: false,
-
- // the action to be set
- // currently there are
- // startall
- // migrateall
- // stopall
- action: undefined,
-
- submit: function(params) {
- var me = this;
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/' + me.action,
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- me.hide();
- win.on('destroy', function() {
- me.close();
- });
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.action) {
- throw "no action specified";
- }
-
- if (!me.btnText) {
- throw "no button text specified";
- }
-
- if (!me.title) {
- throw "no title specified";
- }
-
- var items = [];
-
- if (me.action === 'migrateall') {
- /*jslint confusion: true*/
- /*value is string and number*/
- items.push(
- {
- xtype: 'pveNodeSelector',
- name: 'target',
- disallowedNodes: [me.nodename],
- fieldLabel: gettext('Target node'),
- allowBlank: false,
- onlineValidator: true
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'maxworkers',
- minValue: 1,
- maxValue: 100,
- value: 1,
- fieldLabel: gettext('Parallel jobs'),
- allowBlank: false
- },
- {
- itemId: 'lxcwarning',
- xtype: 'displayfield',
- userCls: 'pve-hint',
- value: 'Warning: Running CTs will be migrated in Restart Mode.',
- hidden: true // only visible if running container chosen
- }
- );
- /*jslint confusion: false*/
- } else if (me.action === 'startall') {
- items.push({
- xtype: 'hiddenfield',
- name: 'force',
- value: 1
- });
- }
-
- items.push({
- xtype: 'vmselector',
- itemId: 'vms',
- name: 'vms',
- flex: 1,
- height: 300,
- selectAll: true,
- allowBlank: false,
- nodename: me.nodename,
- action: me.action,
- listeners: {
- selectionchange: function(vmselector, records) {
- if (me.action == 'migrateall') {
- var showWarning = records.some(function(item) {
- return (item.data.type == 'lxc' &&
- item.data.status == 'running');
- });
- me.down('#lxcwarning').setVisible(showWarning);
- }
- }
- }
- });
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- fieldDefaults: {
- labelWidth: 300,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn = Ext.create('Ext.Button', {
- text: me.btnText,
- handler: function() {
- form.isValid();
- me.submit(form.getValues());
- }
- });
-
- Ext.apply(me, {
- items: [ me.formPanel ],
- buttons: [ submitBtn ]
- });
-
- me.callParent();
-
- form.on('validitychange', function() {
- var valid = form.isValid();
- submitBtn.setDisabled(!valid);
- });
- form.isValid();
- }
-});
-Ext.define('PVE.window.Clone', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- isTemplate: false,
-
- onlineHelp: 'qm_copy_and_clone',
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'panel[reference=cloneform]': {
- validitychange: 'disableSubmit'
- }
- },
- disableSubmit: function(form) {
- this.lookupReference('submitBtn').setDisabled(!form.isValid());
- }
- },
-
- statics: {
- // display a snapshot selector only if needed
- wrap: function(nodename, vmid, isTemplate, guestType) {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/' + guestType + '/' + vmid +'/snapshot',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, opts) {
- var snapshotList = response.result.data;
- var hasSnapshots = snapshotList.length === 1 &&
- snapshotList[0].name === 'current' ? false : true;
-
- Ext.create('PVE.window.Clone', {
- nodename: nodename,
- guestType: guestType,
- vmid: vmid,
- isTemplate: isTemplate,
- hasSnapshots: hasSnapshots
- }).show();
- }
- });
- }
- },
-
- create_clone: function(values) {
- var me = this;
-
- var params = { newid: values.newvmid };
-
- if (values.snapname && values.snapname !== 'current') {
- params.snapname = values.snapname;
- }
-
- if (values.pool) {
- params.pool = values.pool;
- }
-
- if (values.name) {
- if (me.guestType === 'lxc') {
- params.hostname = values.name;
- } else {
- params.name = values.name;
- }
- }
-
- if (values.target) {
- params.target = values.target;
- }
-
- if (values.clonemode === 'copy') {
- params.full = 1;
- if (values.hdstorage) {
- params.storage = values.hdstorage;
- if (values.diskformat && me.guestType !== 'lxc') {
- params.format = values.diskformat;
- }
- }
- }
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/' + me.guestType + '/' + me.vmid + '/clone',
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- me.close();
- }
- });
-
- },
-
- // disable the Storage selector when clone mode is linked clone
- updateVisibility: function() {
- var me = this;
- var clonemode = me.lookupReference('clonemodesel').getValue();
- var disksel = me.lookup('diskselector');
- disksel.setDisabled(clonemode === 'clone');
- },
-
- // add to the list of valid nodes each node where
- // all the VM disks are available
- verifyFeature: function() {
- var me = this;
-
- var snapname = me.lookupReference('snapshotsel').getValue();
- var clonemode = me.lookupReference('clonemodesel').getValue();
-
- var params = { feature: clonemode };
- if (snapname !== 'current') {
- params.snapname = snapname;
- }
-
- Proxmox.Utils.API2Request({
- waitMsgTarget: me,
- url: '/nodes/' + me.nodename + '/' + me.guestType + '/' + me.vmid + '/feature',
- params: params,
- method: 'GET',
- failure: function(response, opts) {
- me.lookupReference('submitBtn').setDisabled(true);
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- var res = response.result.data;
-
- me.lookupReference('targetsel').allowedNodes = res.nodes;
- me.lookupReference('targetsel').validate();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.snapname) {
- me.snapname = 'current';
- }
-
- if (!me.guestType) {
- throw "no Guest Type specified";
- }
-
- var titletext = me.guestType === 'lxc' ? 'CT' : 'VM';
- if (me.isTemplate) {
- titletext += ' Template';
- }
- me.title = "Clone " + titletext + " " + me.vmid;
-
- var col1 = [];
- var col2 = [];
-
- col1.push({
- xtype: 'pveNodeSelector',
- name: 'target',
- reference: 'targetsel',
- fieldLabel: gettext('Target node'),
- selectCurNode: true,
- allowBlank: false,
- onlineValidator: true,
- listeners: {
- change: function(f, value) {
- me.lookupReference('hdstorage').setTargetNode(value);
- }
- }
- });
-
- var modelist = [['copy', gettext('Full Clone')]];
- if (me.isTemplate) {
- modelist.push(['clone', gettext('Linked Clone')]);
- }
-
- col1.push({
- xtype: 'pveGuestIDSelector',
- name: 'newvmid',
- guestType: me.guestType,
- value: '',
- loadNextFreeID: true,
- validateExists: false
- },
- {
- xtype: 'textfield',
- name: 'name',
- allowBlank: true,
- fieldLabel: me.guestType === 'lxc' ? gettext('Hostname') : gettext('Name')
- },
- {
- xtype: 'pvePoolSelector',
- fieldLabel: gettext('Resource Pool'),
- name: 'pool',
- value: '',
- allowBlank: true
- }
- );
-
- col2.push({
- xtype: 'proxmoxKVComboBox',
- fieldLabel: gettext('Mode'),
- name: 'clonemode',
- reference: 'clonemodesel',
- allowBlank: false,
- hidden: !me.isTemplate,
- value: me.isTemplate ? 'clone' : 'copy',
- comboItems: modelist,
- listeners: {
- change: function(t, value) {
- me.updateVisibility();
- me.verifyFeature();
- }
- }
- },
- {
- xtype: 'PVE.form.SnapshotSelector',
- name: 'snapname',
- reference: 'snapshotsel',
- fieldLabel: gettext('Snapshot'),
- nodename: me.nodename,
- guestType: me.guestType,
- vmid: me.vmid,
- hidden: me.isTemplate || !me.hasSnapshots ? true : false,
- disabled: false,
- allowBlank: false,
- value : me.snapname,
- listeners: {
- change: function(f, value) {
- me.verifyFeature();
- }
- }
- },
- {
- xtype: 'pveDiskStorageSelector',
- reference: 'diskselector',
- nodename: me.nodename,
- autoSelect: false,
- hideSize: true,
- hideSelection: true,
- storageLabel: gettext('Target Storage'),
- allowBlank: true,
- storageContent: me.guestType === 'qemu' ? 'images' : 'rootdir',
- emptyText: gettext('Same as source'),
- disabled: me.isTemplate ? true : false // because default mode is clone for templates
- });
-
- var formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- reference: 'cloneform',
- border: false,
- layout: 'column',
- defaultType: 'container',
- columns: 2,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [
- {
- columnWidth: 0.5,
- padding: '0 10 0 0',
- layout: 'anchor',
- items: col1
- },
- {
- columnWidth: 0.5,
- padding: '0 0 0 10',
- layout: 'anchor',
- items: col2
- }
- ]
- });
-
- Ext.apply(me, {
- modal: true,
- width: 600,
- height: 250,
- border: false,
- layout: 'fit',
- buttons: [ {
- xtype: 'proxmoxHelpButton',
- listenToGlobalEvent: false,
- hidden: false,
- onlineHelp: me.onlineHelp
- },
- '->',
- {
- reference: 'submitBtn',
- text: gettext('Clone'),
- disabled: true,
- handler: function() {
- var cloneForm = me.lookupReference('cloneform');
- if (cloneForm.isValid()) {
- me.create_clone(cloneForm.getValues());
- }
- }
- } ],
- items: [ formPanel ]
- });
-
- me.callParent();
-
- me.verifyFeature();
- }
-});
-Ext.define('PVE.qemu.Monitor', {
- extend: 'Ext.panel.Panel',
-
- alias: 'widget.pveQemuMonitor',
-
- maxLines: 500,
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var history = [];
- var histNum = -1;
- var lines = [];
-
- var textbox = Ext.createWidget('panel', {
- region: 'center',
- xtype: 'panel',
- autoScroll: true,
- border: true,
- margins: '5 5 5 5',
- bodyStyle: 'font-family: monospace;'
- });
-
- var scrollToEnd = function() {
- var el = textbox.getTargetEl();
- var dom = Ext.getDom(el);
-
- var clientHeight = dom.clientHeight;
- // BrowserBug: clientHeight reports 0 in IE9 StrictMode
- // Instead we are using offsetHeight and hardcoding borders
- if (Ext.isIE9 && Ext.isStrict) {
- clientHeight = dom.offsetHeight + 2;
- }
- dom.scrollTop = dom.scrollHeight - clientHeight;
- };
-
- var refresh = function() {
- textbox.update('' + lines.join('\n') + ' ');
- scrollToEnd();
- };
-
- var addLine = function(line) {
- lines.push(line);
- if (lines.length > me.maxLines) {
- lines.shift();
- }
- };
-
- var executeCmd = function(cmd) {
- addLine("# " + Ext.htmlEncode(cmd));
- if (cmd) {
- history.unshift(cmd);
- if (history.length > 20) {
- history.splice(20);
- }
- }
- histNum = -1;
-
- refresh();
- Proxmox.Utils.API2Request({
- params: { command: cmd },
- url: '/nodes/' + nodename + '/qemu/' + vmid + "/monitor",
- method: 'POST',
- waitMsgTarget: me,
- success: function(response, opts) {
- var res = response.result.data;
- Ext.Array.each(res.split('\n'), function(line) {
- addLine(Ext.htmlEncode(line));
- });
- refresh();
- },
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- Ext.apply(me, {
- layout: { type: 'border' },
- border: false,
- items: [
- textbox,
- {
- region: 'south',
- margins:'0 5 5 5',
- border: false,
- xtype: 'textfield',
- name: 'cmd',
- value: '',
- fieldStyle: 'font-family: monospace;',
- allowBlank: true,
- listeners: {
- afterrender: function(f) {
- f.focus(false);
- addLine("Type 'help' for help.");
- refresh();
- },
- specialkey: function(f, e) {
- var key = e.getKey();
- switch (key) {
- case e.ENTER:
- var cmd = f.getValue();
- f.setValue('');
- executeCmd(cmd);
- break;
- case e.PAGE_UP:
- textbox.scrollBy(0, -0.9*textbox.getHeight(), false);
- break;
- case e.PAGE_DOWN:
- textbox.scrollBy(0, 0.9*textbox.getHeight(), false);
- break;
- case e.UP:
- if (histNum + 1 < history.length) {
- f.setValue(history[++histNum]);
- }
- e.preventDefault();
- break;
- case e.DOWN:
- if (histNum > 0) {
- f.setValue(history[--histNum]);
- }
- e.preventDefault();
- break;
- default:
- break;
- }
- }
- }
- }
- ],
- listeners: {
- show: function() {
- var field = me.query('textfield[name="cmd"]')[0];
- field.focus(false, true);
- }
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.qemu.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveQemuSummary',
-
- scrollable: true,
- bodyPadding: 5,
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.workspace) {
- throw "no workspace specified";
- }
-
- if (!me.statusStore) {
- throw "no status storage specified";
- }
-
- var template = !!me.pveSelNode.data.template;
- var rstore = me.statusStore;
-
- var width = template ? 1 : 0.5;
- var items = [
- {
- xtype: template ? 'pveTemplateStatusView' : 'pveGuestStatusView',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: width
- },
- 'width >= 1900': {
- columnWidth: width / 2
- }
- },
- itemId: 'gueststatus',
- pveSelNode: me.pveSelNode,
- rstore: rstore
- },
- {
- xtype: 'pveNotesView',
- maxHeight: 330,
- itemId: 'notesview',
- pveSelNode: me.pveSelNode,
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: width
- },
- 'width >= 1900': {
- columnWidth: width / 2
- }
- }
- }
- ];
-
- var rrdstore;
- if (!template) {
-
- rrdstore = Ext.create('Proxmox.data.RRDStore', {
- rrdurl: "/api2/json/nodes/" + nodename + "/qemu/" + vmid + "/rrddata",
- model: 'pve-rrd-guest'
- });
-
- items.push(
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('CPU usage'),
- pveSelNode: me.pveSelNode,
- fields: ['cpu'],
- fieldTitles: [gettext('CPU usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Memory usage'),
- pveSelNode: me.pveSelNode,
- fields: ['maxmem', 'mem'],
- fieldTitles: [gettext('Total'), gettext('RAM usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Network traffic'),
- pveSelNode: me.pveSelNode,
- fields: ['netin','netout'],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Disk IO'),
- pveSelNode: me.pveSelNode,
- fields: ['diskread','diskwrite'],
- store: rrdstore
- }
- );
-
- }
-
- Ext.apply(me, {
- tbar: [ '->', { xtype: 'proxmoxRRDTypeSelector' } ],
- items: [
- {
- xtype: 'container',
- layout: {
- type: 'column'
- },
- defaults: {
- minHeight: 330,
- padding: 5,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- }
- },
- items: items
- }
- ]
- });
-
- me.callParent();
- if (!template) {
- rrdstore.startUpdate();
- me.on('destroy', rrdstore.stopUpdate);
- }
- }
-});
-Ext.define('PVE.qemu.OSTypeInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuOSTypePanel',
- onlineHelp: 'qm_os_settings',
- insideWizard: false,
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'combobox[name=osbase]': {
- change: 'onOSBaseChange'
- },
- 'combobox[name=ostype]': {
- afterrender: 'onOSTypeChange',
- change: 'onOSTypeChange'
- }
- },
- onOSBaseChange: function(field, value) {
- this.lookup('ostype').getStore().setData(PVE.Utils.kvm_ostypes[value]);
- },
- onOSTypeChange: function(field) {
- var me = this, ostype = field.getValue();
- if (!me.getView().insideWizard) {
- return;
- }
- var targetValues = PVE.qemu.OSDefaults.getDefaults(ostype);
-
- me.setWidget('pveBusSelector', targetValues.busType);
- me.setWidget('pveNetworkCardSelector', targetValues.networkCard);
- var scsihw = targetValues.scsihw || '__default__';
- this.getViewModel().set('current.scsihw', scsihw);
- },
- setWidget: function(widget, newValue) {
- // changing a widget is safe only if ComponentQuery.query returns us
- // a single value array
- var widgets = Ext.ComponentQuery.query('pveQemuCreateWizard ' + widget);
- if (widgets.length === 1) {
- widgets[0].setValue(newValue);
- } else {
- throw 'non unique widget :' + widget + ' in Wizard';
- }
- }
- },
-
- initComponent : function() {
- var me = this;
-
- /*jslint confusion: true */
- me.items = [
- {
- xtype: 'displayfield',
- value: gettext('Guest OS') + ':',
- hidden: !me.insideWizard
- },
- {
- xtype: 'combobox',
- submitValue: false,
- name: 'osbase',
- fieldLabel: gettext('Type'),
- editable: false,
- queryMode: 'local',
- value: 'Linux',
- store: Object.keys(PVE.Utils.kvm_ostypes)
- },
- {
- xtype: 'combobox',
- name: 'ostype',
- reference: 'ostype',
- fieldLabel: gettext('Version'),
- value: 'l26',
- allowBlank : false,
- editable: false,
- queryMode: 'local',
- valueField: 'val',
- displayField: 'desc',
- store: {
- fields: ['desc', 'val'],
- data: PVE.Utils.kvm_ostypes.Linux,
- listeners: {
- datachanged: function (store) {
- var ostype = me.lookup('ostype');
- var old_val = ostype.getValue();
- if (!me.insideWizard && old_val && store.find('val', old_val) != -1) {
- ostype.setValue(old_val);
- } else {
- ostype.setValue(store.getAt(0));
- }
- }
- }
- }
- }
- ];
- /*jslint confusion: false */
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.OSTypeEdit', {
- extend: 'Proxmox.window.Edit',
-
- subject: 'OS Type',
-
- items: [{ xtype: 'pveQemuOSTypePanel' }],
-
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var value = response.result.data.ostype || 'other';
- var osinfo = PVE.Utils.get_kvm_osinfo(value);
- me.setValues({ ostype: value, osbase: osinfo.base });
- }
- });
- }
-});
-/*
- * This class holds performance *recommended* settings for the PVE Qemu wizards
- * the *mandatory* settings are set in the PVE::QemuServer
- * config_to_command sub
- * We store this here until we get the data from the API server
-*/
-
-// this is how you would add an hypothetic FreeBSD > 10 entry
-//
-//virtio-blk is stable but virtIO net still
-// problematic as of 10.3
-// see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=165059
-// addOS({
-// parent: 'generic', // inherits defaults
-// pveOS: 'freebsd10', // must match a radiofield in OSTypeEdit.js
-// busType: 'virtio' // must match a pveBusController value
-// // networkCard muss match a pveNetworkCardSelector
-
-
-Ext.define('PVE.qemu.OSDefaults', {
- singleton: true, // will also force creation when loaded
-
- constructor: function() {
- var me = this;
-
- var addOS = function(settings) {
- if (me.hasOwnProperty(settings.parent)) {
- var child = Ext.clone(me[settings.parent]);
- me[settings.pveOS] = Ext.apply(child, settings);
-
- } else {
- throw("Could not find your genitor");
- }
- };
-
- // default values
- me.generic = {
- busType: 'ide',
- networkCard: 'e1000',
- busPriority: {
- ide: 4,
- sata: 3,
- scsi: 2,
- virtio: 1
- },
- scsihw: 'virtio-scsi-pci'
- };
-
- // virtio-net is in kernel since 2.6.25
- // virtio-scsi since 3.2 but backported in RHEL with 2.6 kernel
- addOS({
- pveOS: 'l26',
- parent : 'generic',
- busType: 'scsi',
- busPriority: {
- scsi: 4,
- virtio: 3,
- sata: 2,
- ide: 1
- },
- networkCard: 'virtio'
- });
-
- // recommandation from http://wiki.qemu.org/Windows2000
- addOS({
- pveOS: 'w2k',
- parent : 'generic',
- networkCard: 'rtl8139',
- scsihw: ''
- });
- // https://pve.proxmox.com/wiki/Windows_XP_Guest_Notes
- addOS({
- pveOS: 'wxp',
- parent : 'w2k'
- });
-
- me.getDefaults = function(ostype) {
- if (PVE.qemu.OSDefaults[ostype]) {
- return PVE.qemu.OSDefaults[ostype];
- } else {
- return PVE.qemu.OSDefaults.generic;
- }
- };
- }
-});
-Ext.define('PVE.qemu.ProcessorInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuProcessorPanel',
- onlineHelp: 'qm_cpu',
-
- insideWizard: false,
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- updateCores: function() {
- var me = this.getView();
- var sockets = me.down('field[name=sockets]').getValue();
- var cores = me.down('field[name=cores]').getValue();
- me.down('field[name=totalcores]').setValue(sockets*cores);
- var vcpus = me.down('field[name=vcpus]');
- vcpus.setMaxValue(sockets*cores);
- vcpus.setEmptyText(sockets*cores);
- vcpus.validate();
- },
-
- control: {
- 'field[name=sockets]': {
- change: 'updateCores'
- },
- 'field[name=cores]': {
- change: 'updateCores'
- }
- }
- },
-
- onGetValues: function(values) {
- var me = this;
-
- if (Array.isArray(values['delete'])) {
- values['delete'] = values['delete'].join(',');
- }
-
- PVE.Utils.delete_if_default(values, 'cpulimit', '0', 0);
- PVE.Utils.delete_if_default(values, 'cpuunits', '1024', 0);
-
- // build the cpu options:
- me.cpu.cputype = values.cputype;
-
- if (values.flags) {
- me.cpu.flags = values.flags;
- } else {
- delete me.cpu.flags;
- }
-
- delete values.cputype;
- delete values.flags;
- var cpustring = PVE.Parser.printQemuCpu(me.cpu);
-
- // remove cputype delete request:
- var del = values['delete'];
- delete values['delete'];
- if (del) {
- del = del.split(',');
- Ext.Array.remove(del, 'cputype');
- } else {
- del = [];
- }
-
- if (cpustring) {
- values.cpu = cpustring;
- } else {
- del.push('cpu');
- }
-
- var delarr = del.join(',');
- if (delarr) {
- values['delete'] = delarr;
- }
-
- return values;
- },
-
- cpu: {},
-
- column1: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'sockets',
- minValue: 1,
- maxValue: 4,
- value: '1',
- fieldLabel: gettext('Sockets'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'cores',
- minValue: 1,
- maxValue: 128,
- value: '1',
- fieldLabel: gettext('Cores'),
- allowBlank: false
- }
- ],
-
- column2: [
- {
- xtype: 'CPUModelSelector',
- name: 'cputype',
- value: '__default__',
- fieldLabel: gettext('Type')
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Total cores'),
- name: 'totalcores',
- value: '1'
- }
- ],
-
- advancedColumn1: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'vcpus',
- minValue: 1,
- maxValue: 1,
- value: '',
- fieldLabel: gettext('VCPUs'),
- deleteEmpty: true,
- allowBlank: true,
- emptyText: '1'
- },
- {
- xtype: 'numberfield',
- name: 'cpulimit',
- minValue: 0,
- maxValue: 128, // api maximum
- value: '',
- step: 1,
- fieldLabel: gettext('CPU limit'),
- allowBlank: true,
- emptyText: gettext('unlimited')
- }
- ],
-
- advancedColumn2: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'cpuunits',
- fieldLabel: gettext('CPU units'),
- minValue: 8,
- maxValue: 500000,
- value: '1024',
- deleteEmpty: true,
- allowBlank: true
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Enable NUMA'),
- name: 'numa',
- uncheckedValue: 0
- }
- ],
- advancedColumnB: [
- {
- xtype: 'label',
- text: 'Extra CPU Flags:'
- },
- {
- xtype: 'vmcpuflagselector',
- name: 'flags'
- }
- ]
-});
-
-Ext.define('PVE.qemu.ProcessorEdit', {
- extend: 'Proxmox.window.Edit',
-
- width: 700,
-
- initComponent : function() {
- var me = this;
-
- var ipanel = Ext.create('PVE.qemu.ProcessorInputPanel');
-
- Ext.apply(me, {
- subject: gettext('Processors'),
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var data = response.result.data;
- var value = data.cpu;
- if (value) {
- var cpu = PVE.Parser.parseQemuCpu(value);
- ipanel.cpu = cpu;
- data.cputype = cpu.cputype;
- if (cpu.flags) {
- data.flags = cpu.flags;
- }
- }
- me.setValues(data);
- }
- });
- }
-});
-Ext.define('PVE.qemu.BootOrderPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuBootOrderPanel',
- vmconfig: {}, // store loaded vm config
-
- bootdisk: undefined,
- selection: [],
- list: [],
- comboboxes: [],
-
- isBootDisk: function(value) {
- return PVE.Utils.bus_match.test(value);
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
- me.vmconfig = vmconfig;
- var order = me.vmconfig.boot || 'cdn';
- me.bootdisk = me.vmconfig.bootdisk || undefined;
-
- // get the first 3 characters
- // ignore the rest (there should never be more than 3)
- me.selection = order.split('').slice(0,3);
-
- // build bootdev list
- me.list = [];
- Ext.Object.each(me.vmconfig, function(key, value) {
- if (me.isBootDisk(key) &&
- !(/media=cdrom/).test(value)) {
- me.list.push([key, "Disk '" + key + "'"]);
- }
- });
-
- me.list.push(['d', 'CD-ROM']);
- me.list.push(['n', gettext('Network')]);
- me.list.push(['__none__', Proxmox.Utils.noneText]);
-
- me.recomputeList();
-
- me.comboboxes.forEach(function(box) {
- box.resetOriginalValue();
- });
- },
-
- onGetValues: function(values) {
- var me = this;
- var order = me.selection.join('');
- var res = { boot: order };
-
- if (me.bootdisk && order.indexOf('c') !== -1) {
- res.bootdisk = me.bootdisk;
- } else {
- res['delete'] = 'bootdisk';
- }
-
- return res;
- },
-
- recomputeSelection: function(combobox, newVal, oldVal) {
- var me = this.up('#inputpanel');
- me.selection = [];
- me.comboboxes.forEach(function(item) {
- var val = item.getValue();
-
- // when selecting an already selected item,
- // switch it around
- if ((val === newVal || (me.isBootDisk(val) && me.isBootDisk(newVal))) &&
- item.name !== combobox.name &&
- newVal !== '__none__') {
- // swap items
- val = oldVal;
- }
-
- // push 'c','d' or 'n' in the array
- if (me.isBootDisk(val)) {
- me.selection.push('c');
- me.bootdisk = val;
- } else if (val === 'd' ||
- val === 'n') {
- me.selection.push(val);
- }
- });
-
- me.recomputeList();
- },
-
- recomputeList: function(){
- var me = this;
- // set the correct values in the kvcomboboxes
- var cnt = 0;
- me.comboboxes.forEach(function(item) {
- if (cnt === 0) {
- // never show 'none' on first combobox
- item.store.loadData(me.list.slice(0, me.list.length-1));
- } else {
- item.store.loadData(me.list);
- }
- item.suspendEvent('change');
- if (cnt < me.selection.length) {
- item.setValue((me.selection[cnt] !== 'c')?me.selection[cnt]:me.bootdisk);
- } else if (cnt === 0){
- item.setValue('');
- } else {
- item.setValue('__none__');
- }
- cnt++;
- item.resumeEvent('change');
- item.validate();
- });
- },
-
- initComponent : function() {
- var me = this;
-
- // this has to be done here, because of
- // the way our inputPanel class handles items
- me.comboboxes = [
- Ext.createWidget('proxmoxKVComboBox', {
- fieldLabel: gettext('Boot device') + " 1",
- labelWidth: 120,
- name: 'bd1',
- allowBlank: false,
- listeners: {
- change: me.recomputeSelection
- }
- }),
- Ext.createWidget('proxmoxKVComboBox', {
- fieldLabel: gettext('Boot device') + " 2",
- labelWidth: 120,
- name: 'bd2',
- allowBlank: false,
- listeners: {
- change: me.recomputeSelection
- }
- }),
- Ext.createWidget('proxmoxKVComboBox', {
- fieldLabel: gettext('Boot device') + " 3",
- labelWidth: 120,
- name: 'bd3',
- allowBlank: false,
- listeners: {
- change: me.recomputeSelection
- }
- })
- ];
- Ext.apply(me, { items: me.comboboxes });
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.BootOrderEdit', {
- extend: 'Proxmox.window.Edit',
-
- items: [{
- xtype: 'pveQemuBootOrderPanel',
- itemId: 'inputpanel'
- }],
-
- subject: gettext('Boot Order'),
-
- initComponent : function() {
- var me = this;
- me.callParent();
- me.load({
- success: function(response, options) {
- me.down('#inputpanel').setVMConfig(response.result.data);
- }
- });
- }
-});
-Ext.define('PVE.qemu.MemoryInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuMemoryPanel',
- onlineHelp: 'qm_memory',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- var res = {};
-
- res.memory = values.memory;
- res.balloon = values.balloon;
-
- if (!values.ballooning) {
- res.balloon = 0;
- res['delete'] = 'shares';
- } else if (values.memory === values.balloon) {
- delete res.balloon;
- res['delete'] = 'balloon,shares';
- } else if (Ext.isDefined(values.shares) && (values.shares !== "")) {
- res.shares = values.shares;
- } else {
- res['delete'] = "shares";
- }
-
- return res;
- },
-
- initComponent: function() {
- var me = this;
- var labelWidth = 160;
-
- me.items= [
- {
- xtype: 'pveMemoryField',
- labelWidth: labelWidth,
- fieldLabel: gettext('Memory') + ' (MiB)',
- name: 'memory',
- minValue: 1,
- step: 32,
- hotplug: me.hotplug,
- listeners: {
- change: function(f, value, old) {
- var bf = me.down('field[name=balloon]');
- var balloon = bf.getValue();
- bf.setMaxValue(value);
- if (balloon === old) {
- bf.setValue(value);
- }
- bf.validate();
- }
- }
- }
- ];
-
- me.advancedItems= [
- {
- xtype: 'pveMemoryField',
- name: 'balloon',
- minValue: 1,
- step: 32,
- fieldLabel: gettext('Minimum memory') + ' (MiB)',
- hotplug: me.hotplug,
- labelWidth: labelWidth,
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- var memory = me.down('field[name=memory]').getValue();
- var shares = me.down('field[name=shares]');
- shares.setDisabled(value === memory);
- }
- }
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'shares',
- disabled: true,
- minValue: 0,
- maxValue: 50000,
- value: '',
- step: 10,
- fieldLabel: gettext('Shares'),
- labelWidth: labelWidth,
- allowBlank: true,
- emptyText: Proxmox.Utils.defaultText + ' (1000)',
- submitEmptyText: false
- },
- {
- xtype: 'proxmoxcheckbox',
- labelWidth: labelWidth,
- value: '1',
- name: 'ballooning',
- fieldLabel: gettext('Ballooning Device'),
- listeners: {
- change: function(f, value) {
- var bf = me.down('field[name=balloon]');
- var shares = me.down('field[name=shares]');
- var memory = me.down('field[name=memory]');
- bf.setDisabled(!value);
- shares.setDisabled(!value || (bf.getValue() === memory.getValue()));
- }
- }
- }
- ];
-
- if (me.insideWizard) {
- me.column1 = me.items;
- me.items = undefined;
- me.advancedColumn1 = me.advancedItems;
- me.advancedItems = undefined;
- }
- me.callParent();
- }
-
-});
-
-Ext.define('PVE.qemu.MemoryEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent: function() {
- var me = this;
-
- var memoryhotplug;
- if(me.hotplug) {
- Ext.each(me.hotplug.split(','), function(el) {
- if (el === 'memory') {
- memoryhotplug = 1;
- }
- });
- }
-
- var ipanel = Ext.create('PVE.qemu.MemoryInputPanel', {
- hotplug: memoryhotplug
- });
-
- Ext.apply(me, {
- subject: gettext('Memory'),
- items: [ ipanel ],
- // uncomment the following to use the async configiguration API
- // backgroundDelay: 5,
- width: 400
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var data = response.result.data;
-
- var values = {
- ballooning: data.balloon === 0 ? '0' : '1',
- shares: data.shares,
- memory: data.memory || '512',
- balloon: data.balloon > 0 ? data.balloon : (data.memory || '512')
- };
-
- ipanel.setValues(values);
- }
- });
- }
-});
-Ext.define('PVE.qemu.NetworkInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuNetworkInputPanel',
- onlineHelp: 'qm_network_device',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- me.network.model = values.model;
- if (values.nonetwork) {
- return {};
- } else {
- me.network.bridge = values.bridge;
- me.network.tag = values.tag;
- me.network.firewall = values.firewall;
- }
- me.network.macaddr = values.macaddr;
- me.network.disconnect = values.disconnect;
- me.network.queues = values.queues;
-
- if (values.rate) {
- me.network.rate = values.rate;
- } else {
- delete me.network.rate;
- }
-
- var params = {};
-
- params[me.confid] = PVE.Parser.printQemuNetwork(me.network);
-
- return params;
- },
-
- setNetwork: function(confid, data) {
- var me = this;
-
- me.confid = confid;
-
- if (data) {
- data.networkmode = data.bridge ? 'bridge' : 'nat';
- } else {
- data = {};
- data.networkmode = 'bridge';
- }
- me.network = data;
-
- me.setValues(me.network);
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- me.bridgesel.setNodename(nodename);
- },
-
- initComponent : function() {
- var me = this;
-
- me.network = {};
- me.confid = 'net0';
-
- me.column1 = [];
- me.column2 = [];
-
- me.bridgesel = Ext.create('PVE.form.BridgeSelector', {
- name: 'bridge',
- fieldLabel: gettext('Bridge'),
- nodename: me.nodename,
- autoSelect: true,
- allowBlank: false
- });
-
- me.column1 = [
- me.bridgesel,
- {
- xtype: 'pveVlanField',
- name: 'tag',
- value: ''
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Firewall'),
- name: 'firewall',
- checked: (me.insideWizard || me.isCreate)
- }
- ];
-
- me.advancedColumn1 = [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Disconnect'),
- name: 'disconnect'
- }
- ];
-
- if (me.insideWizard) {
- me.column1.unshift({
- xtype: 'checkbox',
- name: 'nonetwork',
- inputValue: 'none',
- boxLabel: gettext('No network device'),
- listeners: {
- change: function(cb, value) {
- var fields = [
- 'disconnect',
- 'bridge',
- 'tag',
- 'firewall',
- 'model',
- 'macaddr',
- 'rate',
- 'queues'
- ];
- fields.forEach(function(fieldname) {
- me.down('field[name='+fieldname+']').setDisabled(value);
- });
- me.down('field[name=bridge]').validate();
- }
- }
- });
- me.column2.unshift({
- xtype: 'displayfield'
- });
- }
-
- me.column2.push(
- {
- xtype: 'pveNetworkCardSelector',
- name: 'model',
- fieldLabel: gettext('Model'),
- value: PVE.qemu.OSDefaults.generic.networkCard,
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'macaddr',
- fieldLabel: gettext('MAC address'),
- vtype: 'MacAddress',
- allowBlank: true,
- emptyText: 'auto'
- });
- me.advancedColumn2 = [
- {
- xtype: 'numberfield',
- name: 'rate',
- fieldLabel: gettext('Rate limit') + ' (MB/s)',
- minValue: 0,
- maxValue: 10*1024,
- value: '',
- emptyText: 'unlimited',
- allowBlank: true
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'queues',
- fieldLabel: 'Multiqueue',
- minValue: 1,
- maxValue: 8,
- value: '',
- allowBlank: true
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.NetworkEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
-
- initComponent : function() {
- /*jslint confusion: true */
-
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = me.confid ? false : true;
-
- var ipanel = Ext.create('PVE.qemu.NetworkInputPanel', {
- confid: me.confid,
- nodename: nodename,
- isCreate: me.isCreate
- });
-
- Ext.applyIf(me, {
- subject: gettext('Network Device'),
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var i, confid;
- me.vmconfig = response.result.data;
- if (!me.isCreate) {
- var value = me.vmconfig[me.confid];
- var network = PVE.Parser.parseQemuNetwork(me.confid, value);
- if (!network) {
- Ext.Msg.alert(gettext('Error'), 'Unable to parse network options');
- me.close();
- return;
- }
- ipanel.setNetwork(me.confid, network);
- } else {
- for (i = 0; i < 100; i++) {
- confid = 'net' + i.toString();
- if (!Ext.isDefined(me.vmconfig[confid])) {
- me.confid = confid;
- break;
- }
- }
- ipanel.setNetwork(me.confid);
- }
- }
- });
- }
-});
-Ext.define('PVE.qemu.Smbios1InputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.PVE.qemu.Smbios1InputPanel',
-
- insideWizard: false,
-
- smbios1: {},
-
- onGetValues: function(values) {
- var me = this;
-
- var params = {
- smbios1: PVE.Parser.printQemuSmbios1(values)
- };
-
- return params;
- },
-
- setSmbios1: function(data) {
- var me = this;
-
- me.smbios1 = data;
-
- me.setValues(me.smbios1);
- },
-
- items: [
- {
- xtype: 'textfield',
- fieldLabel: 'UUID',
- regex: /^[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$/,
- name: 'uuid'
- },
- {
- xtype: 'textareafield',
- fieldLabel: gettext('Manufacturer'),
- fieldStyle: {
- height: '2em',
- minHeight: '2em'
- },
- name: 'manufacturer'
- },
- {
- xtype: 'textareafield',
- fieldLabel: gettext('Product'),
- fieldStyle: {
- height: '2em',
- minHeight: '2em'
- },
- name: 'product'
- },
- {
- xtype: 'textareafield',
- fieldLabel: gettext('Version'),
- fieldStyle: {
- height: '2em',
- minHeight: '2em'
- },
- name: 'version'
- },
- {
- xtype: 'textareafield',
- fieldLabel: gettext('Serial'),
- fieldStyle: {
- height: '2em',
- minHeight: '2em'
- },
- name: 'serial'
- },
- {
- xtype: 'textareafield',
- fieldLabel: 'SKU',
- fieldStyle: {
- height: '2em',
- minHeight: '2em'
- },
- name: 'sku'
- },
- {
- xtype: 'textareafield',
- fieldLabel: gettext('Family'),
- fieldStyle: {
- height: '2em',
- minHeight: '2em'
- },
- name: 'family'
- }
- ]
-});
-
-Ext.define('PVE.qemu.Smbios1Edit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- /*jslint confusion: true */
-
- var me = this;
-
- var ipanel = Ext.create('PVE.qemu.Smbios1InputPanel', {});
-
- Ext.applyIf(me, {
- subject: gettext('SMBIOS settings (type1)'),
- width: 450,
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- var i, confid;
- me.vmconfig = response.result.data;
- var value = me.vmconfig.smbios1;
- if (value) {
- var data = PVE.Parser.parseQemuSmbios1(value);
- if (!data) {
- Ext.Msg.alert(gettext('Error'), 'Unable to parse smbios options');
- me.close();
- return;
- }
- ipanel.setSmbios1(data);
- }
- }
- });
- }
-});
-Ext.define('PVE.qemu.CDInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuCDInputPanel',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- var confid = me.confid || (values.controller + values.deviceid);
-
- me.drive.media = 'cdrom';
- if (values.mediaType === 'iso') {
- me.drive.file = values.cdimage;
- } else if (values.mediaType === 'cdrom') {
- me.drive.file = 'cdrom';
- } else {
- me.drive.file = 'none';
- }
-
- var params = {};
-
- params[confid] = PVE.Parser.printQemuDrive(me.drive);
-
- return params;
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
-
- if (me.bussel) {
- me.bussel.setVMConfig(vmconfig, 'cdrom');
- }
- },
-
- setDrive: function(drive) {
- var me = this;
-
- var values = {};
- if (drive.file === 'cdrom') {
- values.mediaType = 'cdrom';
- } else if (drive.file === 'none') {
- values.mediaType = 'none';
- } else {
- values.mediaType = 'iso';
- var match = drive.file.match(/^([^:]+):/);
- if (match) {
- values.cdstorage = match[1];
- values.cdimage = drive.file;
- }
- }
-
- me.drive = drive;
-
- me.setValues(values);
- },
-
- setNodename: function(nodename) {
- var me = this;
-
- me.cdstoragesel.setNodename(nodename);
- me.cdfilesel.setStorage(undefined, nodename);
- },
-
- initComponent : function() {
- var me = this;
-
- me.drive = {};
-
- var items = [];
-
- if (!me.confid) {
- me.bussel = Ext.create('PVE.form.ControllerSelector', {
- noVirtIO: true
- });
- items.push(me.bussel);
- }
-
- items.push({
- xtype: 'radiofield',
- name: 'mediaType',
- inputValue: 'iso',
- boxLabel: gettext('Use CD/DVD disc image file (iso)'),
- checked: true,
- listeners: {
- change: function(f, value) {
- if (!me.rendered) {
- return;
- }
- me.down('field[name=cdstorage]').setDisabled(!value);
- me.down('field[name=cdimage]').setDisabled(!value);
- me.down('field[name=cdimage]').validate();
- }
- }
- });
-
- me.cdfilesel = Ext.create('PVE.form.FileSelector', {
- name: 'cdimage',
- nodename: me.nodename,
- storageContent: 'iso',
- fieldLabel: gettext('ISO image'),
- labelAlign: 'right',
- allowBlank: false
- });
-
- me.cdstoragesel = Ext.create('PVE.form.StorageSelector', {
- name: 'cdstorage',
- nodename: me.nodename,
- fieldLabel: gettext('Storage'),
- labelAlign: 'right',
- storageContent: 'iso',
- allowBlank: false,
- autoSelect: me.insideWizard,
- listeners: {
- change: function(f, value) {
- me.cdfilesel.setStorage(value);
- }
- }
- });
-
- items.push(me.cdstoragesel);
- items.push(me.cdfilesel);
-
- items.push({
- xtype: 'radiofield',
- name: 'mediaType',
- inputValue: 'cdrom',
- boxLabel: gettext('Use physical CD/DVD Drive')
- });
-
- items.push({
- xtype: 'radiofield',
- name: 'mediaType',
- inputValue: 'none',
- boxLabel: gettext('Do not use any media')
- });
-
- me.items = items;
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.CDEdit', {
- extend: 'Proxmox.window.Edit',
-
- width: 400,
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = me.confid ? false : true;
-
- var ipanel = Ext.create('PVE.qemu.CDInputPanel', {
- confid: me.confid,
- nodename: nodename
- });
-
- Ext.applyIf(me, {
- subject: 'CD/DVD Drive',
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- if (me.confid) {
- var value = response.result.data[me.confid];
- var drive = PVE.Parser.parseQemuDrive(me.confid, value);
- if (!drive) {
- Ext.Msg.alert('Error', 'Unable to parse drive options');
- me.close();
- return;
- }
- ipanel.setDrive(drive);
- }
- }
- });
- }
-});
-/*jslint confusion: true */
-/* 'change' property is assigned a string and then a function */
-Ext.define('PVE.qemu.HDInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveQemuHDInputPanel',
- onlineHelp: 'qm_hard_disk',
-
- insideWizard: false,
-
- unused: false, // ADD usused disk imaged
-
- vmconfig: {}, // used to select usused disks
-
- controller: {
-
- xclass: 'Ext.app.ViewController',
-
- onControllerChange: function(field) {
- var value = field.getValue();
-
- var allowIOthread = value.match(/^(virtio|scsi)/);
- this.lookup('iothread').setDisabled(!allowIOthread);
- if (!allowIOthread) {
- this.lookup('iothread').setValue(false);
- }
-
- var virtio = value.match(/^virtio/);
- this.lookup('discard').setDisabled(virtio);
- this.lookup('ssd').setDisabled(virtio);
- if (virtio) {
- this.lookup('discard').setValue(false);
- this.lookup('ssd').setValue(false);
- }
-
- this.lookup('scsiController').setVisible(value.match(/^scsi/));
- },
-
- control: {
- 'field[name=controller]': {
- change: 'onControllerChange',
- afterrender: 'onControllerChange'
- },
- 'field[name=iothread]' : {
- change: function(f, value) {
- if (!this.getView().insideWizard) {
- return;
- }
- var vmScsiType = value ? 'virtio-scsi-single': 'virtio-scsi-pci';
- this.lookupReference('scsiController').setValue(vmScsiType);
- }
- }
- }
- },
-
- onGetValues: function(values) {
- var me = this;
-
- var params = {};
- var confid = me.confid || (values.controller + values.deviceid);
-
- if (me.unused) {
- me.drive.file = me.vmconfig[values.unusedId];
- confid = values.controller + values.deviceid;
- } else if (me.isCreate) {
- if (values.hdimage) {
- me.drive.file = values.hdimage;
- } else {
- me.drive.file = values.hdstorage + ":" + values.disksize;
- }
- me.drive.format = values.diskformat;
- }
-
- if (values.nobackup) {
- me.drive.backup = 'no';
- } else {
- delete me.drive.backup;
- }
-
- if (values.noreplicate) {
- me.drive.replicate = 'no';
- } else {
- delete me.drive.replicate;
- }
-
- if (values.discard) {
- me.drive.discard = 'on';
- } else {
- delete me.drive.discard;
- }
-
- if (values.ssd) {
- me.drive.ssd = 'on';
- } else {
- delete me.drive.ssd;
- }
-
- if (values.iothread) {
- me.drive.iothread = 'on';
- } else {
- delete me.drive.iothread;
- }
-
- if (values.cache) {
- me.drive.cache = values.cache;
- } else {
- delete me.drive.cache;
- }
-
- var names = ['mbps_rd', 'mbps_wr', 'iops_rd', 'iops_wr'];
- Ext.Array.each(names, function(name) {
- if (values[name]) {
- me.drive[name] = values[name];
- } else {
- delete me.drive[name];
- }
- var burst_name = name + '_max';
- if (values[burst_name] && values[name]) {
- me.drive[burst_name] = values[burst_name];
- } else {
- delete me.drive[burst_name];
- }
- });
-
-
- params[confid] = PVE.Parser.printQemuDrive(me.drive);
-
- return params;
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
-
- me.vmconfig = vmconfig;
-
- if (me.bussel) {
- me.bussel.setVMConfig(vmconfig);
- me.scsiController.setValue(vmconfig.scsihw);
- }
- if (me.unusedDisks) {
- var disklist = [];
- Ext.Object.each(vmconfig, function(key, value) {
- if (key.match(/^unused\d+$/)) {
- disklist.push([key, value]);
- }
- });
- me.unusedDisks.store.loadData(disklist);
- me.unusedDisks.setValue(me.confid);
- }
- },
-
- setDrive: function(drive) {
- var me = this;
-
- me.drive = drive;
-
- var values = {};
- var match = drive.file.match(/^([^:]+):/);
- if (match) {
- values.hdstorage = match[1];
- }
-
- values.hdimage = drive.file;
- values.nobackup = !PVE.Parser.parseBoolean(drive.backup, 1);
- values.noreplicate = !PVE.Parser.parseBoolean(drive.replicate, 1);
- values.diskformat = drive.format || 'raw';
- values.cache = drive.cache || '__default__';
- values.discard = (drive.discard === 'on');
- values.ssd = PVE.Parser.parseBoolean(drive.ssd);
- values.iothread = PVE.Parser.parseBoolean(drive.iothread);
-
- values.mbps_rd = drive.mbps_rd;
- values.mbps_wr = drive.mbps_wr;
- values.iops_rd = drive.iops_rd;
- values.iops_wr = drive.iops_wr;
- values.mbps_rd_max = drive.mbps_rd_max;
- values.mbps_wr_max = drive.mbps_wr_max;
- values.iops_rd_max = drive.iops_rd_max;
- values.iops_wr_max = drive.iops_wr_max;
-
- me.setValues(values);
- },
-
- setNodename: function(nodename) {
- var me = this;
- me.down('#hdstorage').setNodename(nodename);
- me.down('#hdimage').setStorage(undefined, nodename);
- },
-
- initComponent : function() {
- var me = this;
-
- var labelWidth = 140;
-
- me.drive = {};
-
- me.column1 = [];
- me.column2 = [];
-
- me.advancedColumn1 = [];
- me.advancedColumn2 = [];
-
- if (!me.confid || me.unused) {
- me.bussel = Ext.create('PVE.form.ControllerSelector', {
- vmconfig: me.insideWizard ? {ide2: 'cdrom'} : {}
- });
- me.column1.push(me.bussel);
-
- me.scsiController = Ext.create('Ext.form.field.Display', {
- fieldLabel: gettext('SCSI Controller'),
- reference: 'scsiController',
- bind: me.insideWizard ? {
- value: '{current.scsihw}'
- } : undefined,
- renderer: PVE.Utils.render_scsihw,
- submitValue: false,
- hidden: true
- });
- me.column1.push(me.scsiController);
- }
-
- if (me.unused) {
- me.unusedDisks = Ext.create('Proxmox.form.KVComboBox', {
- name: 'unusedId',
- fieldLabel: gettext('Disk image'),
- matchFieldWidth: false,
- listConfig: {
- width: 350
- },
- data: [],
- allowBlank: false
- });
- me.column1.push(me.unusedDisks);
- } else if (me.isCreate) {
- me.column1.push({
- xtype: 'pveDiskStorageSelector',
- storageContent: 'images',
- name: 'disk',
- nodename: me.nodename,
- autoSelect: me.insideWizard
- });
- } else {
- me.column1.push({
- xtype: 'textfield',
- disabled: true,
- submitValue: false,
- fieldLabel: gettext('Disk image'),
- name: 'hdimage'
- });
- }
-
- me.column2.push(
- {
- xtype: 'CacheTypeSelector',
- name: 'cache',
- value: '__default__',
- fieldLabel: gettext('Cache')
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Discard'),
- disabled: me.confid && me.confid.match(/^virtio/),
- reference: 'discard',
- name: 'discard'
- }
- );
-
- me.advancedColumn1.push(
- {
- xtype: 'proxmoxcheckbox',
- disabled: me.confid && me.confid.match(/^virtio/),
- fieldLabel: gettext('SSD emulation'),
- labelWidth: labelWidth,
- name: 'ssd',
- reference: 'ssd'
- },
- {
- xtype: 'proxmoxcheckbox',
- disabled: me.confid && !me.confid.match(/^(virtio|scsi)/),
- fieldLabel: 'IO thread',
- labelWidth: labelWidth,
- reference: 'iothread',
- name: 'iothread'
- },
- {
- xtype: 'numberfield',
- name: 'mbps_rd',
- minValue: 1,
- step: 1,
- fieldLabel: gettext('Read limit') + ' (MB/s)',
- labelWidth: labelWidth,
- emptyText: gettext('unlimited')
- },
- {
- xtype: 'numberfield',
- name: 'mbps_wr',
- minValue: 1,
- step: 1,
- fieldLabel: gettext('Write limit') + ' (MB/s)',
- labelWidth: labelWidth,
- emptyText: gettext('unlimited')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'iops_rd',
- minValue: 10,
- step: 10,
- fieldLabel: gettext('Read limit') + ' (ops/s)',
- labelWidth: labelWidth,
- emptyText: gettext('unlimited')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'iops_wr',
- minValue: 10,
- step: 10,
- fieldLabel: gettext('Write limit') + ' (ops/s)',
- labelWidth: labelWidth,
- emptyText: gettext('unlimited')
- }
- );
-
- me.advancedColumn2.push(
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('No backup'),
- labelWidth: labelWidth,
- name: 'nobackup'
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Skip replication'),
- labelWidth: labelWidth,
- name: 'noreplicate'
- },
- {
- xtype: 'numberfield',
- name: 'mbps_rd_max',
- minValue: 1,
- step: 1,
- fieldLabel: gettext('Read max burst') + ' (MB)',
- labelWidth: labelWidth,
- emptyText: gettext('default')
- },
- {
- xtype: 'numberfield',
- name: 'mbps_wr_max',
- minValue: 1,
- step: 1,
- fieldLabel: gettext('Write max burst') + ' (MB)',
- labelWidth: labelWidth,
- emptyText: gettext('default')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'iops_rd_max',
- minValue: 10,
- step: 10,
- fieldLabel: gettext('Read max burst') + ' (ops)',
- labelWidth: labelWidth,
- emptyText: gettext('default')
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'iops_wr_max',
- minValue: 10,
- step: 10,
- fieldLabel: gettext('Write max burst') + ' (ops)',
- labelWidth: labelWidth,
- emptyText: gettext('default')
- }
- );
-
- me.callParent();
- }
-});
-/*jslint confusion: false */
-
-Ext.define('PVE.qemu.HDEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
-
- backgroundDelay: 5,
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var unused = me.confid && me.confid.match(/^unused\d+$/);
-
- me.isCreate = me.confid ? unused : true;
-
- var ipanel = Ext.create('PVE.qemu.HDInputPanel', {
- confid: me.confid,
- nodename: nodename,
- unused: unused,
- isCreate: me.isCreate
- });
-
- var subject;
- if (unused) {
- me.subject = gettext('Unused Disk');
- } else if (me.isCreate) {
- me.subject = gettext('Hard Disk');
- } else {
- me.subject = gettext('Hard Disk') + ' (' + me.confid + ')';
- }
-
- me.items = [ ipanel ];
-
- me.callParent();
- /*jslint confusion: true*/
- /* 'data' is assigned an empty array in same file, and here we
- * use it like an object
- */
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- if (me.confid) {
- var value = response.result.data[me.confid];
- var drive = PVE.Parser.parseQemuDrive(me.confid, value);
- if (!drive) {
- Ext.Msg.alert(gettext('Error'), 'Unable to parse drive options');
- me.close();
- return;
- }
- ipanel.setDrive(drive);
- me.isValid(); // trigger validation
- }
- }
- });
- /*jslint confusion: false*/
- }
-});
-Ext.define('PVE.window.HDResize', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- resize_disk: function(disk, size) {
- var me = this;
- var params = { disk: disk, size: '+' + size + 'G' };
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/resize',
- waitMsgTarget: me,
- method: 'PUT',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- me.close();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- var items = [
- {
- xtype: 'displayfield',
- name: 'disk',
- value: me.disk,
- fieldLabel: gettext('Disk'),
- vtype: 'StorageId',
- allowBlank: false
- }
- ];
-
- me.hdsizesel = Ext.createWidget('numberfield', {
- name: 'size',
- minValue: 0,
- maxValue: 128*1024,
- decimalPrecision: 3,
- value: '0',
- fieldLabel: gettext('Size Increment') + ' (GiB)',
- allowBlank: false
- });
-
- items.push(me.hdsizesel);
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 140,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- me.title = gettext('Resize disk');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Resize disk'),
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.resize_disk(me.disk, values.size);
- }
- }
- });
-
- Ext.apply(me, {
- modal: true,
- width: 250,
- height: 150,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
-
- me.callParent();
-
- if (!me.disk) {
- return;
- }
-
- }
-});
-Ext.define('PVE.window.HDMove', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
-
- move_disk: function(disk, storage, format, delete_disk) {
- var me = this;
- var qemu = (me.type === 'qemu');
- var params = {};
- params.storage = storage;
- params[qemu ? 'disk':'volume'] = disk;
-
- if (format && qemu) {
- params.format = format;
- }
-
- if (delete_disk) {
- params['delete'] = 1;
- }
-
- var url = '/nodes/' + me.nodename + '/' + me.type + '/' + me.vmid + '/';
- url += qemu ? 'move_disk' : 'move_volume';
-
- Proxmox.Utils.API2Request({
- params: params,
- url: url,
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- win.on('destroy', function() { me.close(); });
- }
- });
-
- },
-
- initComponent : function() {
- var me = this;
-
- var diskarray = [];
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.type) {
- me.type = 'qemu';
- }
-
- var qemu = (me.type === 'qemu');
-
- var items = [
- {
- xtype: 'displayfield',
- name: qemu ? 'disk' : 'volume',
- value: me.disk,
- fieldLabel: qemu ? gettext('Disk') : gettext('Mount Point'),
- vtype: 'StorageId',
- allowBlank: false
- }
- ];
-
- items.push({
- xtype: 'pveDiskStorageSelector',
- storageLabel: gettext('Target Storage'),
- nodename: me.nodename,
- storageContent: qemu ? 'images' : 'rootdir',
- hideSize: true
- });
-
- items.push({
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Delete source'),
- name: 'deleteDisk',
- uncheckedValue: 0,
- checked: false
- });
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- me.title = qemu ? gettext("Move disk") : gettext('Move Volume');
- submitBtn = Ext.create('Ext.Button', {
- text: me.title,
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.move_disk(me.disk, values.hdstorage, values.diskformat,
- values.deleteDisk);
- }
- }
- });
-
- Ext.apply(me, {
- modal: true,
- width: 350,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
-
- me.callParent();
-
- me.mon(me.formPanel, 'validitychange', function(fp, isValid) {
- submitBtn.setDisabled(!isValid);
- });
-
- me.formPanel.isValid();
- }
-});
-Ext.define('PVE.qemu.EFIDiskInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveEFIDiskInputPanel',
-
- insideWizard: false,
-
- unused: false, // ADD usused disk imaged
-
- vmconfig: {}, // used to select usused disks
-
- onGetValues: function(values) {
- var me = this;
-
- var confid = 'efidisk0';
-
- if (values.hdimage) {
- me.drive.file = values.hdimage;
- } else {
- // we use 1 here, because for efi the size gets overridden from the backend
- me.drive.file = values.hdstorage + ":1";
- }
-
- me.drive.format = values.diskformat;
- var params = {};
- params[confid] = PVE.Parser.printQemuDrive(me.drive);
- return params;
- },
-
- setNodename: function(nodename) {
- var me = this;
- me.down('#hdstorage').setNodename(nodename);
- me.down('#hdimage').setStorage(undefined, nodename);
- },
-
- initComponent : function() {
- var me = this;
-
- me.drive = {};
-
- me.items= [];
-
- me.items.push({
- xtype: 'pveDiskStorageSelector',
- name: 'efidisk0',
- storageContent: 'images',
- nodename: me.nodename,
- hideSize: true
- });
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.EFIDiskEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
- subject: gettext('EFI Disk'),
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.items = [{
- xtype: 'pveEFIDiskInputPanel',
- onlineHelp: 'qm_bios_and_uefi',
- confid: me.confid,
- nodename: nodename,
- isCreate: true
- }];
-
- me.callParent();
- }
-});
-Ext.define('PVE.qemu.DisplayInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveDisplayInputPanel',
-
- onGetValues: function(values) {
- var ret = PVE.Parser.printPropertyString(values, 'type');
- if (ret === '') {
- return {
- 'delete': 'vga'
- };
- }
- return {
- vga: ret
- };
- },
-
- items: [{
- name: 'type',
- xtype: 'proxmoxKVComboBox',
- value: '__default__',
- deleteEmpty: false,
- fieldLabel: gettext('Graphic card'),
- comboItems: PVE.Utils.kvm_vga_driver_array(),
- validator: function() {
- var v = this.getValue();
- var cfg = this.up('proxmoxWindowEdit').vmconfig || {};
-
- if (v.match(/^serial\d+$/) && (!cfg[v] || cfg[v] !== 'socket')) {
- var fmt = gettext("Serial interface '{0}' is not correctly configured.");
- return Ext.String.format(fmt, v);
- }
- return true;
- },
- listeners: {
- change: function(cb, val) {
- var me = this.up('panel');
- if (!val) {
- return;
- }
- var disable = false;
- var emptyText = Proxmox.Utils.defaultText;
- switch (val) {
- case "cirrus":
- emptyText = "4";
- break;
- case "std":
- emptyText = "16";
- break;
- case "qxl":
- case "qxl2":
- case "qxl3":
- case "qxl4":
- emptyText = "16";
- break;
- case "vmware":
- emptyText = "16";
- break;
- case "none":
- case "serial0":
- case "serial1":
- case "serial2":
- case "serial3":
- emptyText = 'N/A';
- disable = true;
- break;
- case "virtio":
- emptyText = "256";
- break;
- default:
- break;
- }
- var memoryfield = me.down('field[name=memory]');
- memoryfield.setEmptyText(emptyText);
- memoryfield.setDisabled(disable);
- }
- }
- },{
- xtype: 'proxmoxintegerfield',
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('Memory') + ' (MiB)',
- minValue: 4,
- maxValue: 512,
- step: 4,
- name: 'memory'
- }]
-});
-
-Ext.define('PVE.qemu.DisplayEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmconfig: undefined,
-
- subject: gettext('Display'),
- width: 350,
-
- items: [{
- xtype: 'pveDisplayInputPanel'
- }],
-
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- me.load({
- success: function(response) {
- me.vmconfig = response.result.data;
- var vga = me.vmconfig.vga || '__default__';
- me.setValues(PVE.Parser.parsePropertyString(vga, 'type'));
- }
- });
- }
-});
-Ext.define('PVE.qemu.KeyboardEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.applyIf(me, {
- subject: gettext('Keyboard Layout'),
- items: {
- xtype: 'VNCKeyboardSelector',
- name: 'keyboard',
- value: '__default__',
- fieldLabel: gettext('Keyboard Layout')
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('PVE.qemu.HardwareView', {
- extend: 'Proxmox.grid.PendingObjectGrid',
- alias: ['widget.PVE.qemu.HardwareView'],
-
- onlineHelp: 'qm_virtual_machines_settings',
-
- renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var rowdef = rows[key] || {};
- var iconCls = rowdef.iconCls;
- var icon = '';
- var txt = (rowdef.header || key);
-
- metaData.tdAttr = "valign=middle";
-
- if (rowdef.tdCls) {
- metaData.tdCls = rowdef.tdCls;
- if (rowdef.tdCls == 'pve-itype-icon-storage') {
- var value = me.getObjectValue(key, '', false);
- if (value === '') {
- value = me.getObjectValue(key, '', true);
- }
- if (value.match(/vm-.*-cloudinit/)) {
- metaData.tdCls = 'pve-itype-icon-cloud';
- return rowdef.cloudheader;
- } else if (value.match(/media=cdrom/)) {
- metaData.tdCls = 'pve-itype-icon-cdrom';
- return rowdef.cdheader;
- }
- }
- } else if (iconCls) {
- icon = " ";
- metaData.tdCls += " pve-itype-fa";
- }
- return icon + txt;
- },
-
- initComponent : function() {
- var me = this;
- var i, confid;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
- var diskCap = caps.vms['VM.Config.Disk'];
-
- /*jslint confusion: true */
- var rows = {
- memory: {
- header: gettext('Memory'),
- editor: caps.vms['VM.Config.Memory'] ? 'PVE.qemu.MemoryEdit' : undefined,
- never_delete: true,
- defaultValue: '512',
- tdCls: 'pve-itype-icon-memory',
- group: 2,
- multiKey: ['memory', 'balloon', 'shares'],
- renderer: function(value, metaData, record, ri, ci, store, pending) {
- var res = '';
-
- var max = me.getObjectValue('memory', 512, pending);
- var balloon = me.getObjectValue('balloon', undefined, pending);
- var shares = me.getObjectValue('shares', undefined, pending);
-
- res = Proxmox.Utils.format_size(max*1024*1024);
-
- if (balloon !== undefined && balloon > 0) {
- res = Proxmox.Utils.format_size(balloon*1024*1024) + "/" + res;
-
- if (shares) {
- res += ' [shares=' + shares +']';
- }
- } else if (balloon === 0) {
- res += ' [balloon=0]';
- }
- return res;
- }
- },
- sockets: {
- header: gettext('Processors'),
- never_delete: true,
- editor: (caps.vms['VM.Config.CPU'] || caps.vms['VM.Config.HWType']) ?
- 'PVE.qemu.ProcessorEdit' : undefined,
- tdCls: 'pve-itype-icon-processor',
- group: 3,
- defaultValue: '1',
- multiKey: ['sockets', 'cpu', 'cores', 'numa', 'vcpus', 'cpulimit', 'cpuunits'],
- renderer: function(value, metaData, record, rowIndex, colIndex, store, pending) {
-
- var sockets = me.getObjectValue('sockets', 1, pending);
- var model = me.getObjectValue('cpu', undefined, pending);
- var cores = me.getObjectValue('cores', 1, pending);
- var numa = me.getObjectValue('numa', undefined, pending);
- var vcpus = me.getObjectValue('vcpus', undefined, pending);
- var cpulimit = me.getObjectValue('cpulimit', undefined, pending);
- var cpuunits = me.getObjectValue('cpuunits', undefined, pending);
-
- var res = Ext.String.format('{0} ({1} sockets, {2} cores)',
- sockets*cores, sockets, cores);
-
- if (model) {
- res += ' [' + model + ']';
- }
-
- if (numa) {
- res += ' [numa=' + numa +']';
- }
-
- if (vcpus) {
- res += ' [vcpus=' + vcpus +']';
- }
-
- if (cpulimit) {
- res += ' [cpulimit=' + cpulimit +']';
- }
-
- if (cpuunits) {
- res += ' [cpuunits=' + cpuunits +']';
- }
-
- return res;
- }
- },
- bios: {
- header: 'BIOS',
- group: 4,
- never_delete: true,
- editor: caps.vms['VM.Config.Options'] ? 'PVE.qemu.BiosEdit' : undefined,
- defaultValue: '',
- iconCls: 'microchip',
- renderer: PVE.Utils.render_qemu_bios
- },
- vga: {
- header: gettext('Display'),
- editor: caps.vms['VM.Config.HWType'] ? 'PVE.qemu.DisplayEdit' : undefined,
- never_delete: true,
- tdCls: 'pve-itype-icon-display',
- group:5,
- defaultValue: '',
- renderer: PVE.Utils.render_kvm_vga_driver
- },
- machine: {
- header: gettext('Machine'),
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Machine'),
- width: 350,
- items: [{
- xtype: 'proxmoxKVComboBox',
- name: 'machine',
- value: '__default__',
- fieldLabel: gettext('Machine'),
- comboItems: [
- ['__default__', PVE.Utils.render_qemu_machine('')],
- ['q35', 'q35']
- ]
- }]} : undefined,
- iconCls: 'cogs',
- never_delete: true,
- group: 6,
- defaultValue: '',
- renderer: PVE.Utils.render_qemu_machine
- },
- scsihw: {
- header: gettext('SCSI Controller'),
- iconCls: 'database',
- editor: caps.vms['VM.Config.Options'] ? 'PVE.qemu.ScsiHwEdit' : undefined,
- renderer: PVE.Utils.render_scsihw,
- group: 7,
- never_delete: true,
- defaultValue: ''
- },
- cores: {
- visible: false
- },
- cpu: {
- visible: false
- },
- numa: {
- visible: false
- },
- balloon: {
- visible: false
- },
- hotplug: {
- visible: false
- },
- vcpus: {
- visible: false
- },
- cpuunits: {
- visible: false
- },
- cpulimit: {
- visible: false
- },
- shares: {
- visible: false
- }
- };
- /*jslint confusion: false */
-
- PVE.Utils.forEachBus(undefined, function(type, id) {
- var confid = type + id;
- rows[confid] = {
- group: 10,
- tdCls: 'pve-itype-icon-storage',
- editor: 'PVE.qemu.HDEdit',
- never_delete: caps.vms['VM.Config.Disk'] ? false : true,
- header: gettext('Hard Disk') + ' (' + confid +')',
- cdheader: gettext('CD/DVD Drive') + ' (' + confid +')',
- cloudheader: gettext('CloudInit Drive') + ' (' + confid + ')'
- };
- });
- for (i = 0; i < 32; i++) {
- confid = "net" + i.toString();
- rows[confid] = {
- group: 15,
- order: i,
- tdCls: 'pve-itype-icon-network',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.qemu.NetworkEdit' : undefined,
- never_delete: caps.vms['VM.Config.Network'] ? false : true,
- header: gettext('Network Device') + ' (' + confid +')'
- };
- }
- rows.efidisk0 = {
- group: 20,
- tdCls: 'pve-itype-icon-storage',
- editor: null,
- never_delete: caps.vms['VM.Config.Disk'] ? false : true,
- header: gettext('EFI Disk')
- };
- for (i = 0; i < 5; i++) {
- confid = "usb" + i.toString();
- rows[confid] = {
- group: 25,
- order: i,
- tdCls: 'pve-itype-icon-usb',
- editor: caps.nodes['Sys.Console'] ? 'PVE.qemu.USBEdit' : undefined,
- never_delete: caps.nodes['Sys.Console'] ? false : true,
- header: gettext('USB Device') + ' (' + confid + ')'
- };
- }
- for (i = 0; i < 4; i++) {
- confid = "hostpci" + i.toString();
- rows[confid] = {
- group: 30,
- order: i,
- tdCls: 'pve-itype-icon-pci',
- never_delete: caps.nodes['Sys.Console'] ? false : true,
- editor: caps.nodes['Sys.Console'] ? 'PVE.qemu.PCIEdit' : undefined,
- header: gettext('PCI Device') + ' (' + confid + ')'
- };
- }
- for (i = 0; i < 4; i++) {
- confid = "serial" + i.toString();
- rows[confid] = {
- group: 35,
- order: i,
- tdCls: 'pve-itype-icon-serial',
- never_delete: caps.nodes['Sys.Console'] ? false : true,
- header: gettext('Serial Port') + ' (' + confid + ')'
- };
- }
- for (i = 0; i < 256; i++) {
- rows["unused" + i.toString()] = {
- group: 99,
- order: i,
- tdCls: 'pve-itype-icon-storage',
- editor: caps.vms['VM.Config.Disk'] ? 'PVE.qemu.HDEdit' : undefined,
- header: gettext('Unused Disk') + ' ' + i.toString()
- };
- }
-
- var sorterFn = function(rec1, rec2) {
- var v1 = rec1.data.key;
- var v2 = rec2.data.key;
- var g1 = rows[v1].group || 0;
- var g2 = rows[v2].group || 0;
- var order1 = rows[v1].order || 0;
- var order2 = rows[v2].order || 0;
-
- if ((g1 - g2) !== 0) {
- return g1 - g2;
- }
-
- if ((order1 - order2) !== 0) {
- return order1 - order2;
- }
-
- if (v1 > v2) {
- return 1;
- } else if (v1 < v2) {
- return -1;
- } else {
- return 0;
- }
- };
-
- var reload = function() {
- me.rstore.load();
- };
-
- var baseurl = 'nodes/' + nodename + '/qemu/' + vmid + '/config';
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var rowdef = rows[rec.data.key];
- if (!rowdef.editor) {
- return;
- }
-
- var editor = rowdef.editor;
- if (rowdef.tdCls == 'pve-itype-icon-storage') {
- var value = me.getObjectValue(rec.data.key, '', true);
- if (value.match(/vm-.*-cloudinit/)) {
- return;
- } else if (value.match(/media=cdrom/)) {
- editor = 'PVE.qemu.CDEdit';
- } else if (!diskCap) {
- return;
- }
- }
-
- var win;
-
- if (Ext.isString(editor)) {
- win = Ext.create(editor, {
- pveSelNode: me.pveSelNode,
- confid: rec.data.key,
- url: '/api2/extjs/' + baseurl
- });
- } else {
- var config = Ext.apply({
- pveSelNode: me.pveSelNode,
- confid: rec.data.key,
- url: '/api2/extjs/' + baseurl
- }, rowdef.editor);
- win = Ext.createWidget(rowdef.editor.xtype, config);
- win.load();
- }
-
- win.show();
- win.on('destroy', reload);
- };
-
- var run_resize = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.window.HDResize', {
- disk: rec.data.key,
- nodename: nodename,
- vmid: vmid
- });
-
- win.show();
-
- win.on('destroy', reload);
- };
-
- var run_move = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.window.HDMove', {
- disk: rec.data.key,
- nodename: nodename,
- vmid: vmid
- });
-
- win.show();
-
- win.on('destroy', reload);
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- selModel: sm,
- disabled: true,
- handler: run_editor
- });
-
- var resize_btn = new Proxmox.button.Button({
- text: gettext('Resize disk'),
- selModel: sm,
- disabled: true,
- handler: run_resize
- });
-
- var move_btn = new Proxmox.button.Button({
- text: gettext('Move disk'),
- selModel: sm,
- disabled: true,
- handler: run_move
- });
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- defaultText: gettext('Remove'),
- altText: gettext('Detach'),
- selModel: sm,
- disabled: true,
- dangerous: true,
- RESTMethod: 'PUT',
- confirmMsg: function(rec) {
- var warn = gettext('Are you sure you want to remove entry {0}');
- if (this.text === this.altText) {
- warn = gettext('Are you sure you want to detach entry {0}');
- }
-
- var entry = rec.data.key;
- var msg = Ext.String.format(warn, "'"
- + me.renderKey(entry, {}, rec) + "'");
-
- if (entry.match(/^unused\d+$/)) {
- msg += " " + gettext('This will permanently erase all data.');
- }
-
- return msg;
- },
- handler: function(b, e, rec) {
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/' + baseurl,
- waitMsgTarget: me,
- method: b.RESTMethod,
- params: {
- 'delete': rec.data.key
- },
- callback: function() {
- reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- success: function(response, options) {
- if (b.RESTMethod === 'POST') {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', {
- upid: upid,
- listeners: {
- destroy: function () {
- me.reload();
- }
- }
- });
- win.show();
- }
- }
- });
- },
- listeners: {
- render: function(btn) {
- // hack: calculate an optimal button width on first display
- // to prevent the whole toolbar to move when we switch
- // between the "Remove" and "Detach" labels
- var def = btn.getSize().width;
-
- btn.setText(btn.altText);
- var alt = btn.getSize().width;
-
- btn.setText(btn.defaultText);
-
- var optimal = alt > def ? alt : def;
- btn.setSize({ width: optimal });
- }
- }
- });
-
- var revert_btn = new Proxmox.button.Button({
- text: gettext('Revert'),
- selModel: sm,
- disabled: true,
- handler: function(b, e, rec) {
- var rowdef = me.rows[rec.data.key] || {};
- var keys = rowdef.multiKey || [ rec.data.key ];
- var revert = keys.join(',');
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/' + baseurl,
- waitMsgTarget: me,
- method: 'PUT',
- params: {
- 'revert': revert
- },
- callback: function() {
- reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert('Error',response.htmlStatus);
- }
- });
- }
- });
-
- var efidisk_menuitem = Ext.create('Ext.menu.Item',{
- text: gettext('EFI Disk'),
- iconCls: 'pve-itype-icon-storage',
- disabled: !caps.vms['VM.Config.Disk'],
- handler: function() {
-
- var rstoredata = me.rstore.getData().map;
- // check if ovmf is configured
- if (rstoredata.bios && rstoredata.bios.data.value === 'ovmf') {
- var win = Ext.create('PVE.qemu.EFIDiskEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- } else {
- Ext.Msg.alert('Error',gettext('Please select OVMF(UEFI) as BIOS first.'));
- }
-
- }
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- // disable button when we have an efidisk already
- // disable is ok in this case, because you can instantly
- // see that there is already one
- efidisk_menuitem.setDisabled(me.rstore.getData().map.efidisk0 !== undefined);
- // en/disable usb add button
- var usbcount = 0;
- var pcicount = 0;
- var hasCloudInit = false;
- me.rstore.getData().items.forEach(function(item){
- if (/^usb\d+/.test(item.id)) {
- usbcount++;
- } else if (/^hostpci\d+/.test(item.id)) {
- pcicount++;
- }
- if (!hasCloudInit && /vm-.*-cloudinit/.test(item.data.value)) {
- hasCloudInit = true;
- }
- });
-
- // heuristic only for disabling some stuff, the backend has the final word.
- var noSysConsolePerm = !caps.nodes['Sys.Console'];
-
- me.down('#addusb').setDisabled(noSysConsolePerm || (usbcount >= 5));
- me.down('#addpci').setDisabled(noSysConsolePerm || (pcicount >= 4));
- me.down('#addci').setDisabled(noSysConsolePerm || hasCloudInit);
-
- if (!rec) {
- remove_btn.disable();
- edit_btn.disable();
- resize_btn.disable();
- move_btn.disable();
- revert_btn.disable();
- return;
- }
- var key = rec.data.key;
- var value = rec.data.value;
- var rowdef = rows[key];
-
- var pending = rec.data['delete'] || me.hasPendingChanges(key);
- var isCDRom = (value && !!value.toString().match(/media=cdrom/));
- var isUnusedDisk = key.match(/^unused\d+/);
- var isUsedDisk = !isUnusedDisk &&
- rowdef.tdCls == 'pve-itype-icon-storage' &&
- !isCDRom;
-
- var isCloudInit = (value && value.toString().match(/vm-.*-cloudinit/));
-
- var isEfi = (key === 'efidisk0');
-
- remove_btn.setDisabled(rec.data['delete'] || (rowdef.never_delete === true) || (isUnusedDisk && !diskCap));
- remove_btn.setText((isUsedDisk && !isCloudInit) ? remove_btn.altText : remove_btn.defaultText);
- remove_btn.RESTMethod = isUnusedDisk ? 'POST':'PUT';
-
- edit_btn.setDisabled(rec.data['delete'] || !rowdef.editor || isCloudInit || (!isCDRom && !diskCap));
-
- resize_btn.setDisabled(pending || !isUsedDisk || !diskCap);
-
- move_btn.setDisabled(pending || !isUsedDisk || !diskCap);
-
- revert_btn.setDisabled(!pending);
-
- };
-
- Ext.apply(me, {
- url: '/api2/json/' + 'nodes/' + nodename + '/qemu/' + vmid + '/pending',
- interval: 5000,
- selModel: sm,
- run_editor: run_editor,
- tbar: [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Hard Disk'),
- iconCls: 'pve-itype-icon-storage',
- disabled: !caps.vms['VM.Config.Disk'],
- handler: function() {
- var win = Ext.create('PVE.qemu.HDEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('CD/DVD Drive'),
- iconCls: 'pve-itype-icon-cdrom',
- disabled: !caps.vms['VM.Config.Disk'],
- handler: function() {
- var win = Ext.create('PVE.qemu.CDEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('Network Device'),
- iconCls: 'pve-itype-icon-network',
- disabled: !caps.vms['VM.Config.Network'],
- handler: function() {
- var win = Ext.create('PVE.qemu.NetworkEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode,
- isCreate: true
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- efidisk_menuitem,
- {
- text: gettext('USB Device'),
- itemId: 'addusb',
- iconCls: 'pve-itype-icon-usb',
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.qemu.USBEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('PCI Device'),
- itemId: 'addpci',
- iconCls: 'pve-itype-icon-pci',
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.qemu.PCIEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('Serial Port'),
- itemId: 'addserial',
- iconCls: 'pve-itype-icon-serial',
- disabled: !caps.vms['VM.Config.Options'],
- handler: function() {
- var win = Ext.create('PVE.qemu.SerialEdit', {
- url: '/api2/extjs/' + baseurl
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('CloudInit Drive'),
- itemId: 'addci',
- iconCls: 'pve-itype-icon-cloud',
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.qemu.CIDriveEdit', {
- url: '/api2/extjs/' + baseurl,
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', reload);
- win.show();
- }
- }
- ]
- })
- },
- remove_btn,
- edit_btn,
- resize_btn,
- move_btn,
- revert_btn
- ],
- rows: rows,
- sorterFn: sorterFn,
- listeners: {
- itemdblclick: run_editor,
- selectionchange: set_button_status
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
-
- me.mon(me.rstore, 'refresh', function() {
- set_button_status();
- });
- }
-});
-Ext.define('PVE.qemu.ScsiHwEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.applyIf(me, {
- subject: gettext('SCSI Controller Type'),
- items: {
- xtype: 'pveScsiHwSelector',
- name: 'scsihw',
- value: '__default__',
- fieldLabel: gettext('Type')
- }
- });
-
- me.callParent();
-
- me.load();
- }
-});
-Ext.define('PVE.qemu.BiosEdit', {
- extend: 'Proxmox.window.Edit',
- alias: 'widget.pveQemuBiosEdit',
-
- initComponent : function() {
- var me = this;
-
- var EFIHint = Ext.createWidget({
- xtype: 'displayfield', //submitValue is false, so we don't get submitted
- userCls: 'pve-hint',
- value: 'You need to add an EFI disk for storing the ' +
- 'EFI settings. See the online help for details.',
- hidden: true
- });
-
- Ext.applyIf(me, {
- subject: 'BIOS',
- items: [ {
- xtype: 'pveQemuBiosSelector',
- onlineHelp: 'qm_bios_and_uefi',
- name: 'bios',
- value: '__default__',
- fieldLabel: 'BIOS',
- listeners: {
- 'change' : function(field, newValue) {
- if (newValue == 'ovmf') {
- Proxmox.Utils.API2Request({
- url : me.url,
- method : 'GET',
- failure : function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success : function(response, opts) {
- var vmConfig = response.result.data;
- // there can be only one
- if (!vmConfig.efidisk0) {
- EFIHint.setVisible(true);
- }
- }
- });
- } else {
- if (EFIHint.isVisible()) {
- EFIHint.setVisible(false);
- }
- }
- }
- }
- },
- EFIHint
- ] });
-
- me.callParent();
-
- me.load();
-
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.qemu.Options', {
- extend: 'Proxmox.grid.PendingObjectGrid',
- alias: ['widget.PVE.qemu.Options'],
-
- onlineHelp: 'qm_options',
-
- initComponent : function() {
- var me = this;
- var i;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var rows = {
- name: {
- required: true,
- defaultValue: me.pveSelNode.data.name,
- header: gettext('Name'),
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Name'),
- items: {
- xtype: 'inputpanel',
- items:{
- xtype: 'textfield',
- name: 'name',
- vtype: 'DnsName',
- value: '',
- fieldLabel: gettext('Name'),
- allowBlank: true
- },
- onGetValues: function(values) {
- var params = values;
- if (values.name === undefined ||
- values.name === null ||
- values.name === '') {
- params = { 'delete':'name'};
- }
- return params;
- }
- }
- } : undefined
- },
- onboot: {
- header: gettext('Start at boot'),
- defaultValue: '',
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Start at boot'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'onboot',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Start at boot')
- }
- } : undefined
- },
- startup: {
- header: gettext('Start/Shutdown order'),
- defaultValue: '',
- renderer: PVE.Utils.render_kvm_startup,
- editor: caps.vms['VM.Config.Options'] && caps.nodes['Sys.Modify'] ?
- {
- xtype: 'pveWindowStartupEdit',
- onlineHelp: 'qm_startup_and_shutdown'
- } : undefined
- },
- ostype: {
- header: gettext('OS Type'),
- editor: caps.vms['VM.Config.Options'] ? 'PVE.qemu.OSTypeEdit' : undefined,
- renderer: PVE.Utils.render_kvm_ostype,
- defaultValue: 'other'
- },
- bootdisk: {
- visible: false
- },
- boot: {
- header: gettext('Boot Order'),
- defaultValue: 'cdn',
- editor: caps.vms['VM.Config.Disk'] ? 'PVE.qemu.BootOrderEdit' : undefined,
- multiKey: ['boot', 'bootdisk'],
- renderer: function(order, metaData, record, rowIndex, colIndex, store, pending) {
- var i;
- var text = '';
- var bootdisk = me.getObjectValue('bootdisk', undefined, pending);
- order = order || 'cdn';
- for (i = 0; i < order.length; i++) {
- var sel = order.substring(i, i + 1);
- if (text) {
- text += ', ';
- }
- if (sel === 'c') {
- if (bootdisk) {
- text += "Disk '" + bootdisk + "'";
- } else {
- text += "Disk";
- }
- } else if (sel === 'n') {
- text += 'Network';
- } else if (sel === 'a') {
- text += 'Floppy';
- } else if (sel === 'd') {
- text += 'CD-ROM';
- } else {
- text += sel;
- }
- }
- return text;
- }
- },
- tablet: {
- header: gettext('Use tablet for pointer'),
- defaultValue: true,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Use tablet for pointer'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'tablet',
- checked: true,
- uncheckedValue: 0,
- defaultValue: 1,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- hotplug: {
- header: gettext('Hotplug'),
- defaultValue: 'disk,network,usb',
- renderer: PVE.Utils.render_hotplug_features,
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Hotplug'),
- items: {
- xtype: 'pveHotplugFeatureSelector',
- name: 'hotplug',
- value: '',
- multiSelect: true,
- fieldLabel: gettext('Hotplug'),
- allowBlank: true
- }
- } : undefined
- },
- acpi: {
- header: gettext('ACPI support'),
- defaultValue: true,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('ACPI support'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'acpi',
- checked: true,
- uncheckedValue: 0,
- defaultValue: 1,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- kvm: {
- header: gettext('KVM hardware virtualization'),
- defaultValue: true,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.HWType'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('KVM hardware virtualization'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'kvm',
- checked: true,
- uncheckedValue: 0,
- defaultValue: 1,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- freeze: {
- header: gettext('Freeze CPU at startup'),
- defaultValue: false,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.PowerMgmt'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Freeze CPU at startup'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'freeze',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- labelWidth: 140,
- fieldLabel: gettext('Freeze CPU at startup')
- }
- } : undefined
- },
- localtime: {
- header: gettext('Use local time for RTC'),
- defaultValue: false,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Use local time for RTC'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'localtime',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- labelWidth: 140,
- fieldLabel: gettext('Use local time for RTC')
- }
- } : undefined
- },
- startdate: {
- header: gettext('RTC start date'),
- defaultValue: 'now',
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('RTC start date'),
- items: {
- xtype: 'proxmoxtextfield',
- name: 'startdate',
- deleteEmpty: true,
- value: 'now',
- fieldLabel: gettext('RTC start date'),
- vtype: 'QemuStartDate',
- allowBlank: true
- }
- } : undefined
- },
- smbios1: {
- header: gettext('SMBIOS settings (type1)'),
- defaultValue: '',
- renderer: Ext.String.htmlEncode,
- editor: caps.vms['VM.Config.HWType'] ? 'PVE.qemu.Smbios1Edit' : undefined
- },
- agent: {
- header: gettext('Qemu Agent'),
- defaultValue: false,
- renderer: PVE.Utils.render_qga_features,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Qemu Agent'),
- items: {
- xtype: 'pveAgentFeatureSelector',
- name: 'agent'
- }
- } : undefined
- },
- protection: {
- header: gettext('Protection'),
- defaultValue: false,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Protection'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'protection',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- hookscript: {
- header: gettext('Hookscript')
- }
- };
-
- var baseurl = 'nodes/' + nodename + '/qemu/' + vmid + '/config';
-
- var edit_btn = new Ext.Button({
- text: gettext('Edit'),
- disabled: true,
- handler: function() { me.run_editor(); }
- });
-
- var revert_btn = new Proxmox.button.Button({
- text: gettext('Revert'),
- disabled: true,
- handler: function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var rowdef = me.rows[rec.data.key] || {};
- var keys = rowdef.multiKey || [ rec.data.key ];
- var revert = keys.join(',');
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/' + baseurl,
- waitMsgTarget: me,
- method: 'PUT',
- params: {
- 'revert': revert
- },
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert('Error',response.htmlStatus);
- }
- });
- }
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- edit_btn.disable();
- return;
- }
-
- var key = rec.data.key;
- var pending = rec.data['delete'] || me.hasPendingChanges(key);
- var rowdef = rows[key];
-
- edit_btn.setDisabled(!rowdef.editor);
- revert_btn.setDisabled(!pending);
- };
-
- Ext.apply(me, {
- url: "/api2/json/nodes/" + nodename + "/qemu/" + vmid + "/pending",
- interval: 5000,
- cwidth1: 250,
- tbar: [ edit_btn, revert_btn ],
- rows: rows,
- editorConfig: {
- url: "/api2/extjs/" + baseurl
- },
- listeners: {
- itemdblclick: me.run_editor,
- selectionchange: set_button_status
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
-
- me.rstore.on('datachanged', function() {
- set_button_status();
- });
- }
-});
-
-Ext.define('PVE.window.Snapshot', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- // needed for finding the reference to submitbutton
- // because we do not have a controller
- referenceHolder: true,
- defaultButton: 'submitbutton',
- defaultFocus: 'field',
-
- take_snapshot: function(snapname, descr, vmstate) {
- var me = this;
- var params = { snapname: snapname, vmstate: vmstate ? 1 : 0 };
- if (descr) {
- params.description = descr;
- }
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot",
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- me.close();
- }
- });
- },
-
- update_snapshot: function(snapname, descr) {
- var me = this;
- Proxmox.Utils.API2Request({
- params: { description: descr },
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot/" +
- snapname + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- me.close();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- var summarystore = Ext.create('Ext.data.Store', {
- model: 'KeyValue',
- sorters: [
- {
- property : 'key',
- direction: 'ASC'
- }
- ]
- });
-
- var items = [
- {
- xtype: me.snapname ? 'displayfield' : 'textfield',
- name: 'snapname',
- value: me.snapname,
- fieldLabel: gettext('Name'),
- vtype: 'ConfigId',
- allowBlank: false
- }
- ];
-
- if (me.snapname) {
- items.push({
- xtype: 'displayfield',
- name: 'snaptime',
- renderer: PVE.Utils.render_timestamp_human_readable,
- fieldLabel: gettext('Timestamp')
- });
- } else {
- items.push({
- xtype: 'proxmoxcheckbox',
- name: 'vmstate',
- uncheckedValue: 0,
- defaultValue: 0,
- checked: 1,
- fieldLabel: gettext('Include RAM')
- });
- }
-
- items.push({
- xtype: 'textareafield',
- grow: true,
- name: 'description',
- fieldLabel: gettext('Description')
- });
-
- if (me.snapname) {
- items.push({
- title: gettext('Settings'),
- xtype: 'grid',
- height: 200,
- store: summarystore,
- columns: [
- {header: gettext('Key'), width: 150, dataIndex: 'key'},
- {header: gettext('Value'), flex: 1, dataIndex: 'value'}
- ]
- });
- }
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- if (me.snapname) {
- me.title = gettext('Edit') + ': ' + gettext('Snapshot');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Update'),
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.update_snapshot(me.snapname, values.description);
- }
- }
- });
- } else {
- me.title ="VM " + me.vmid + ': ' + gettext('Take Snapshot');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Take Snapshot'),
- reference: 'submitbutton',
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.take_snapshot(values.snapname, values.description, values.vmstate);
- }
- }
- });
- }
-
- Ext.apply(me, {
- modal: true,
- width: 450,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
- if (me.snapname) {
- Ext.apply(me, {
- width: 620,
- height: 420
- });
- }
-
- me.callParent();
-
- if (!me.snapname) {
- return;
- }
-
- // else load data
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + "/snapshot/" +
- me.snapname + '/config',
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- me.close();
- },
- success: function(response, options) {
- var data = response.result.data;
- var kvarray = [];
- Ext.Object.each(data, function(key, value) {
- if (key === 'description' || key === 'snaptime') {
- return;
- }
- kvarray.push({ key: key, value: value });
- });
-
- summarystore.suspendEvents();
- summarystore.add(kvarray);
- summarystore.sort();
- summarystore.resumeEvents();
- summarystore.fireEvent('refresh', summarystore);
-
- form.findField('snaptime').setValue(data.snaptime);
- form.findField('description').setValue(data.description);
- }
- });
- }
-});
-Ext.define('PVE.qemu.SnapshotTree', {
- extend: 'Ext.tree.Panel',
- alias: ['widget.pveQemuSnapshotTree'],
-
- load_delay: 3000,
-
- old_digest: 'invalid',
-
- stateful: true,
- stateId: 'grid-qemu-snapshots',
-
- sorterFn: function(rec1, rec2) {
- var v1 = rec1.data.snaptime;
- var v2 = rec2.data.snaptime;
-
- if (rec1.data.name === 'current') {
- return 1;
- }
- if (rec2.data.name === 'current') {
- return -1;
- }
-
- return (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
- },
-
- reload: function(repeat) {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/snapshot',
- method: 'GET',
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- me.load_task.delay(me.load_delay);
- },
- success: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, false);
- var digest = 'invalid';
- var idhash = {};
- var root = { name: '__root', expanded: true, children: [] };
- Ext.Array.each(response.result.data, function(item) {
- item.leaf = true;
- item.children = [];
- if (item.name === 'current') {
- digest = item.digest + item.running;
- if (item.running) {
- item.iconCls = 'fa fa-fw fa-desktop x-fa-tree-running';
- } else {
- item.iconCls = 'fa fa-fw fa-desktop x-fa-tree';
- }
- } else {
- item.iconCls = 'fa fa-fw fa-history x-fa-tree';
- }
- idhash[item.name] = item;
- });
-
- if (digest !== me.old_digest) {
- me.old_digest = digest;
-
- Ext.Array.each(response.result.data, function(item) {
- if (item.parent && idhash[item.parent]) {
- var parent_item = idhash[item.parent];
- parent_item.children.push(item);
- parent_item.leaf = false;
- parent_item.expanded = true;
- parent_item.expandable = false;
- } else {
- root.children.push(item);
- }
- });
-
- me.setRootNode(root);
- }
-
- me.load_task.delay(me.load_delay);
- }
- });
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/feature',
- params: { feature: 'snapshot' },
- method: 'GET',
- success: function(response, options) {
- var res = response.result.data;
- if (res.hasFeature) {
- var snpBtns = Ext.ComponentQuery.query('#snapshotBtn');
- snpBtns.forEach(function(item){
- item.enable();
- });
- }
- }
- });
-
-
- },
-
- listeners: {
- beforestatesave: function(grid, state, eopts) {
- // extjs cannot serialize functions,
- // so a the sorter with only the sorterFn will
- // not be a valid sorter when restoring the state
- delete state.storeState.sorters;
- }
- },
-
- initComponent: function() {
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.vmid = me.pveSelNode.data.vmid;
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- me.load_task = new Ext.util.DelayedTask(me.reload, me);
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var valid_snapshot = function(record) {
- return record && record.data && record.data.name &&
- record.data.name !== 'current';
- };
-
- var valid_snapshot_rollback = function(record) {
- return record && record.data && record.data.name &&
- record.data.name !== 'current' && !record.data.snapstate;
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (valid_snapshot(rec)) {
- var win = Ext.create('PVE.window.Snapshot', {
- snapname: rec.data.name,
- nodename: me.nodename,
- vmid: me.vmid
- });
- win.show();
- me.mon(win, 'close', me.reload, me);
- }
- };
-
- var editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- enableFn: valid_snapshot,
- handler: run_editor
- });
-
- var rollbackBtn = new Proxmox.button.Button({
- text: gettext('Rollback'),
- disabled: true,
- selModel: sm,
- enableFn: valid_snapshot_rollback,
- confirmMsg: function(rec) {
- return Proxmox.Utils.format_task_description('qmrollback', me.vmid) +
- " '" + rec.data.name + "'";
- },
- handler: function(btn, event) {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var snapname = rec.data.name;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/snapshot/' + snapname + '/rollback',
- method: 'POST',
- waitMsgTarget: me,
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- });
- }
- });
-
- var removeBtn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- confirmMsg: function(rec) {
- var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.name + "'");
- return msg;
- },
- enableFn: valid_snapshot,
- handler: function(btn, event) {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var snapname = rec.data.name;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/qemu/' + me.vmid + '/snapshot/' + snapname,
- method: 'DELETE',
- waitMsgTarget: me,
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- });
- }
- });
-
- var snapshotBtn = Ext.create('Ext.Button', {
- itemId: 'snapshotBtn',
- text: gettext('Take Snapshot'),
- disabled: true,
- handler: function() {
- var win = Ext.create('PVE.window.Snapshot', {
- nodename: me.nodename,
- vmid: me.vmid
- });
- win.show();
- }
- });
-
- Ext.apply(me, {
- layout: 'fit',
- rootVisible: false,
- animate: false,
- sortableColumns: false,
- selModel: sm,
- tbar: [ snapshotBtn, rollbackBtn, removeBtn, editBtn ],
- fields: [
- 'name', 'description', 'snapstate', 'vmstate', 'running',
- { name: 'snaptime', type: 'date', dateFormat: 'timestamp' }
- ],
- columns: [
- {
- xtype: 'treecolumn',
- text: gettext('Name'),
- dataIndex: 'name',
- width: 200,
- renderer: function(value, metaData, record) {
- if (value === 'current') {
- return "NOW";
- } else {
- return value;
- }
- }
- },
- {
- text: gettext('RAM'),
- align: 'center',
- resizable: false,
- dataIndex: 'vmstate',
- width: 50,
- renderer: function(value, metaData, record) {
- if (record.data.name !== 'current') {
- return Proxmox.Utils.format_boolean(value);
- }
- }
- },
- {
- text: gettext('Date') + "/" + gettext("Status"),
- dataIndex: 'snaptime',
- width: 150,
- renderer: function(value, metaData, record) {
- if (record.data.snapstate) {
- return record.data.snapstate;
- }
- if (value) {
- return Ext.Date.format(value,'Y-m-d H:i:s');
- }
- }
- },
- {
- text: gettext('Description'),
- dataIndex: 'description',
- flex: 1,
- renderer: function(value, metaData, record) {
- if (record.data.name === 'current') {
- return gettext("You are here!");
- } else {
- return Ext.String.htmlEncode(value);
- }
- }
- }
- ],
- columnLines: true, // will work in 4.1?
- listeners: {
- activate: me.reload,
- destroy: me.load_task.cancel,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
-
- me.store.sorters.add(new Ext.util.Sorter({
- sorterFn: me.sorterFn
- }));
- }
-});
-
-Ext.define('PVE.qemu.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.qemu.Config',
-
- onlineHelp: 'chapter_virtual_machines',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var template = !!me.pveSelNode.data.template;
-
- var running = !!me.pveSelNode.data.uptime;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var base_url = '/nodes/' + nodename + "/qemu/" + vmid;
-
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: '/api2/json' + base_url + '/status/current',
- interval: 1000
- });
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: base_url + '/status/' + cmd,
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- var resumeBtn = Ext.create('Ext.Button', {
- text: gettext('Resume'),
- disabled: !caps.vms['VM.PowerMgmt'],
- hidden: true,
- handler: function() {
- vm_command('resume');
- },
- iconCls: 'fa fa-play'
- });
-
- var startBtn = Ext.create('Ext.Button', {
- text: gettext('Start'),
- disabled: !caps.vms['VM.PowerMgmt'] || running,
- hidden: template,
- handler: function() {
- vm_command('start');
- },
- iconCls: 'fa fa-play'
- });
-
- var migrateBtn = Ext.create('Ext.Button', {
- text: gettext('Migrate'),
- disabled: !caps.vms['VM.Migrate'],
- hidden: PVE.data.ResourceStore.getNodes().length < 2,
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: 'qemu',
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- },
- iconCls: 'fa fa-send-o'
- });
-
- var moreBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('More'),
- menu: { items: [
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- hidden: caps.vms['VM.Clone'] ? false : true,
- handler: function() {
- PVE.window.Clone.wrap(nodename, vmid, template, 'qemu');
- }
- },
- {
- text: gettext('Convert to template'),
- disabled: template,
- xtype: 'pveMenuItem',
- iconCls: 'fa fa-fw fa-file-o',
- hidden: caps.vms['VM.Allocate'] ? false : true,
- confirmMsg: Proxmox.Utils.format_task_description('qmtemplate', vmid),
- handler: function() {
- Proxmox.Utils.API2Request({
- url: base_url + '/template',
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- }
- },
- {
- iconCls: 'fa fa-heartbeat ',
- hidden: !caps.nodes['Sys.Console'],
- text: gettext('Manage HA'),
- handler: function() {
- var ha = me.pveSelNode.data.hastate;
- Ext.create('PVE.ha.VMResourceEdit', {
- vmid: vmid,
- isCreate: (!ha || ha === 'unmanaged')
- }).show();
- }
- },
- {
- text: gettext('Remove'),
- itemId: 'removeBtn',
- disabled: !caps.vms['VM.Allocate'],
- handler: function() {
- Ext.create('PVE.window.SafeDestroy', {
- url: base_url,
- item: { type: 'VM', id: vmid }
- }).show();
- },
- iconCls: 'fa fa-trash-o'
- }
- ]}
- });
-
- var shutdownBtn = Ext.create('PVE.button.Split', {
- text: gettext('Shutdown'),
- disabled: !caps.vms['VM.PowerMgmt'] || !running,
- hidden: template,
- confirmMsg: Proxmox.Utils.format_task_description('qmshutdown', vmid),
- handler: function() {
- vm_command('shutdown');
- },
- menu: {
- items: [{
- text: gettext('Pause'),
- disabled: !caps.vms['VM.PowerMgmt'],
- confirmMsg: Proxmox.Utils.format_task_description('qmpause', vmid),
- handler: function() {
- vm_command("suspend");
- },
- iconCls: 'fa fa-pause'
- },{
- text: gettext('Hibernate'),
- disabled: !caps.vms['VM.PowerMgmt'],
- confirmMsg: Proxmox.Utils.format_task_description('qmsuspend', vmid),
- tooltip: gettext('Suspend to disk'),
- handler: function() {
- vm_command("suspend", { todisk: 1 });
- },
- iconCls: 'fa fa-download'
- },{
- text: gettext('Stop'),
- disabled: !caps.vms['VM.PowerMgmt'],
- dangerous: true,
- tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'VM'),
- confirmMsg: Proxmox.Utils.format_task_description('qmstop', vmid),
- handler: function() {
- vm_command("stop", { timeout: 30 });
- },
- iconCls: 'fa fa-stop'
- },{
- text: gettext('Reset'),
- disabled: !caps.vms['VM.PowerMgmt'],
- confirmMsg: Proxmox.Utils.format_task_description('qmreset', vmid),
- handler: function() {
- vm_command("reset");
- },
- iconCls: 'fa fa-bolt'
- }]
- },
- iconCls: 'fa fa-power-off'
- });
-
- var vm = me.pveSelNode.data;
-
- var consoleBtn = Ext.create('PVE.button.ConsoleButton', {
- disabled: !caps.vms['VM.Console'],
- hidden: template,
- consoleType: 'kvm',
- consoleName: vm.name,
- nodename: nodename,
- vmid: vmid
- });
-
- var statusTxt = Ext.create('Ext.toolbar.TextItem', {
- data: {
- lock: undefined
- },
- tpl: [
- '',
- ' ({lock})',
- ' '
- ]
- });
-
- Ext.apply(me, {
- title: Ext.String.format(gettext("Virtual Machine {0} on node '{1}'"), vm.text, nodename),
- hstateid: 'kvmtab',
- tbarSpacing: false,
- tbar: [ statusTxt, '->', resumeBtn, startBtn, shutdownBtn, migrateBtn, consoleBtn, moreBtn ],
- defaults: { statusStore: me.statusStore },
- items: [
- {
- title: gettext('Summary'),
- xtype: 'pveQemuSummary',
- iconCls: 'fa fa-book',
- itemId: 'summary'
- }
- ]
- });
-
- if (caps.vms['VM.Console'] && !template) {
- me.items.push({
- title: gettext('Console'),
- itemId: 'console',
- iconCls: 'fa fa-terminal',
- xtype: 'pveNoVncConsole',
- vmid: vmid,
- consoleType: 'kvm',
- nodename: nodename
- });
- }
-
- me.items.push(
- {
- title: gettext('Hardware'),
- itemId: 'hardware',
- iconCls: 'fa fa-desktop',
- xtype: 'PVE.qemu.HardwareView'
- },
- {
- title: 'Cloud-Init',
- itemId: 'cloudinit',
- iconCls: 'fa fa-cloud',
- xtype: 'pveCiPanel'
- },
- {
- title: gettext('Options'),
- iconCls: 'fa fa-gear',
- itemId: 'options',
- xtype: 'PVE.qemu.Options'
- },
- {
- title: gettext('Task History'),
- itemId: 'tasks',
- xtype: 'proxmoxNodeTasks',
- iconCls: 'fa fa-list',
- nodename: nodename,
- vmidFilter: vmid
- }
- );
-
- if (caps.vms['VM.Monitor'] && !template) {
- me.items.push({
- title: gettext('Monitor'),
- iconCls: 'fa fa-eye',
- itemId: 'monitor',
- xtype: 'pveQemuMonitor'
- });
- }
-
- if (caps.vms['VM.Backup']) {
- me.items.push({
- title: gettext('Backup'),
- iconCls: 'fa fa-floppy-o',
- xtype: 'pveBackupView',
- itemId: 'backup'
- },
- {
- title: gettext('Replication'),
- iconCls: 'fa fa-retweet',
- xtype: 'pveReplicaView',
- itemId: 'replication'
- });
- }
-
- if ((caps.vms['VM.Snapshot'] || caps.vms['VM.Snapshot.Rollback']) && !template) {
- me.items.push({
- title: gettext('Snapshots'),
- iconCls: 'fa fa-history',
- xtype: 'pveQemuSnapshotTree',
- itemId: 'snapshot'
- });
- }
-
- if (caps.vms['VM.Console']) {
- me.items.push(
- {
- xtype: 'pveFirewallRules',
- title: gettext('Firewall'),
- iconCls: 'fa fa-shield',
- allow_iface: true,
- base_url: base_url + '/firewall/rules',
- list_refs_url: base_url + '/firewall/refs',
- itemId: 'firewall'
- },
- {
- xtype: 'pveFirewallOptions',
- groups: ['firewall'],
- iconCls: 'fa fa-gear',
- onlineHelp: 'pve_firewall_vm_container_configuration',
- title: gettext('Options'),
- base_url: base_url + '/firewall/options',
- fwtype: 'vm',
- itemId: 'firewall-options'
- },
- {
- xtype: 'pveFirewallAliases',
- title: gettext('Alias'),
- groups: ['firewall'],
- iconCls: 'fa fa-external-link',
- base_url: base_url + '/firewall/aliases',
- itemId: 'firewall-aliases'
- },
- {
- xtype: 'pveIPSet',
- title: gettext('IPSet'),
- groups: ['firewall'],
- iconCls: 'fa fa-list-ol',
- base_url: base_url + '/firewall/ipset',
- list_refs_url: base_url + '/firewall/refs',
- itemId: 'firewall-ipset'
- },
- {
- title: gettext('Log'),
- groups: ['firewall'],
- iconCls: 'fa fa-list',
- onlineHelp: 'chapter_pve_firewall',
- itemId: 'firewall-fwlog',
- xtype: 'proxmoxLogView',
- url: '/api2/extjs' + base_url + '/firewall/log'
- }
- );
- }
-
- if (caps.vms['Permissions.Modify']) {
- me.items.push({
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- iconCls: 'fa fa-unlock',
- itemId: 'permissions',
- path: '/vms/' + vmid
- });
- }
-
- me.callParent();
-
- me.mon(me.statusStore, 'load', function(s, records, success) {
- var status;
- var qmpstatus;
- var spice = false;
- var xtermjs = false;
- var lock;
-
- if (!success) {
- status = qmpstatus = 'unknown';
- } else {
- var rec = s.data.get('status');
- status = rec ? rec.data.value : 'unknown';
- rec = s.data.get('qmpstatus');
- qmpstatus = rec ? rec.data.value : 'unknown';
- rec = s.data.get('template');
- template = rec.data.value || false;
- rec = s.data.get('lock');
- lock = rec ? rec.data.value : undefined;
-
- spice = s.data.get('spice') ? true : false;
- xtermjs = s.data.get('serial') ? true : false;
-
- }
-
- if (template) {
- return;
- }
-
- var resume = (['prelaunch', 'paused', 'suspended'].indexOf(qmpstatus) !== -1);
-
- if (resume || lock === 'suspended') {
- startBtn.setVisible(false);
- resumeBtn.setVisible(true);
- } else {
- startBtn.setVisible(true);
- resumeBtn.setVisible(false);
- }
-
- consoleBtn.setEnableSpice(spice);
- consoleBtn.setEnableXtermJS(xtermjs);
-
- statusTxt.update({ lock: lock });
-
- startBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 'running' || template);
- shutdownBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status !== 'running');
- me.down('#removeBtn').setDisabled(!caps.vms['VM.Allocate'] || status !== 'stopped');
- consoleBtn.setDisabled(template);
- });
-
- me.on('afterrender', function() {
- me.statusStore.startUpdate();
- });
-
- me.on('destroy', function() {
- me.statusStore.stopUpdate();
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.qemu.CreateWizard', {
- extend: 'PVE.window.Wizard',
- alias: 'widget.pveQemuCreateWizard',
- mixins: ['Proxmox.Mixin.CBind'],
-
- viewModel: {
- data: {
- nodename: '',
- current: {
- scsihw: ''
- }
- }
- },
-
- cbindData: {
- nodename: undefined
- },
-
- subject: gettext('Virtual Machine'),
-
- items: [
- {
- xtype: 'inputpanel',
- title: gettext('General'),
- onlineHelp: 'qm_general_settings',
- column1: [
- {
- xtype: 'pveNodeSelector',
- name: 'nodename',
- cbind: {
- selectCurNode: '{!nodename}',
- preferredValue: '{nodename}'
- },
- bind: {
- value: '{nodename}'
- },
- fieldLabel: gettext('Node'),
- allowBlank: false,
- onlineValidator: true
- },
- {
- xtype: 'pveGuestIDSelector',
- name: 'vmid',
- guestType: 'qemu',
- value: '',
- loadNextFreeID: true,
- validateExists: false
- },
- {
- xtype: 'textfield',
- name: 'name',
- vtype: 'DnsName',
- value: '',
- fieldLabel: gettext('Name'),
- allowBlank: true
- }
- ],
- column2: [
- {
- xtype: 'pvePoolSelector',
- fieldLabel: gettext('Resource Pool'),
- name: 'pool',
- value: '',
- allowBlank: true
- }
- ],
- advancedColumn1: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'onboot',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Start at boot')
- }
- ],
- advancedColumn2: [
- {
- xtype: 'textfield',
- name: 'order',
- defaultValue: '',
- emptyText: 'any',
- labelWidth: 120,
- fieldLabel: gettext('Start/Shutdown order')
- },
- {
- xtype: 'textfield',
- name: 'up',
- defaultValue: '',
- emptyText: 'default',
- labelWidth: 120,
- fieldLabel: gettext('Startup delay')
- },
- {
- xtype: 'textfield',
- name: 'down',
- defaultValue: '',
- emptyText: 'default',
- labelWidth: 120,
- fieldLabel: gettext('Shutdown timeout')
- }
- ],
- onGetValues: function(values) {
-
- ['name', 'pool', 'onboot', 'agent'].forEach(function(field) {
- if (!values[field]) {
- delete values[field];
- }
- });
-
- var res = PVE.Parser.printStartup({
- order: values.order,
- up: values.up,
- down: values.down
- });
-
- if (res) {
- values.startup = res;
- }
-
- delete values.order;
- delete values.up;
- delete values.down;
-
- return values;
- }
- },
- {
- xtype: 'container',
- layout: 'hbox',
- defaults: {
- flex: 1,
- padding: '0 10'
- },
- title: gettext('OS'),
- items: [
- {
- xtype: 'pveQemuCDInputPanel',
- bind: {
- nodename: '{nodename}'
- },
- confid: 'ide2',
- insideWizard: true
- },
- {
- xtype: 'pveQemuOSTypePanel',
- insideWizard: true
- }
- ]
- },
- {
- xtype: 'pveQemuSystemPanel',
- title: gettext('System'),
- isCreate: true,
- insideWizard: true
- },
- {
- xtype: 'pveQemuHDInputPanel',
- bind: {
- nodename: '{nodename}'
- },
- title: gettext('Hard Disk'),
- isCreate: true,
- insideWizard: true
- },
- {
- xtype: 'pveQemuProcessorPanel',
- insideWizard: true,
- title: gettext('CPU')
- },
- {
- xtype: 'pveQemuMemoryPanel',
- insideWizard: true,
- title: gettext('Memory')
- },
- {
- xtype: 'pveQemuNetworkInputPanel',
- bind: {
- nodename: '{nodename}'
- },
- title: gettext('Network'),
- insideWizard: true
- },
- {
- title: gettext('Confirm'),
- layout: 'fit',
- items: [
- {
- xtype: 'grid',
- store: {
- model: 'KeyValue',
- sorters: [{
- property : 'key',
- direction: 'ASC'
- }]
- },
- columns: [
- {header: 'Key', width: 150, dataIndex: 'key'},
- {header: 'Value', flex: 1, dataIndex: 'value'}
- ]
- }
- ],
- dockedItems: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'start',
- dock: 'bottom',
- margin: '5 0 0 0',
- boxLabel: gettext('Start after created')
- }
- ],
- listeners: {
- show: function(panel) {
- var kv = this.up('window').getValues();
- var data = [];
- Ext.Object.each(kv, function(key, value) {
- if (key === 'delete') { // ignore
- return;
- }
- data.push({ key: key, value: value });
- });
-
- var summarystore = panel.down('grid').getStore();
- summarystore.suspendEvents();
- summarystore.removeAll();
- summarystore.add(data);
- summarystore.sort();
- summarystore.resumeEvents();
- summarystore.fireEvent('refresh');
-
- }
- },
- onSubmit: function() {
- var wizard = this.up('window');
- var kv = wizard.getValues();
- delete kv['delete'];
-
- var nodename = kv.nodename;
- delete kv.nodename;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/qemu',
- waitMsgTarget: wizard,
- method: 'POST',
- params: kv,
- success: function(response){
- wizard.close();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- }
- ]
-});
-
-
-
-
-Ext.define('PVE.qemu.USBInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- mixins: ['Proxmox.Mixin.CBind' ],
-
- autoComplete: false,
- onlineHelp: 'qm_usb_passthrough',
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- control: {
- 'field[name=usb]': {
- change: function(field, newValue, oldValue) {
- var hwidfield = this.lookupReference('hwid');
- var portfield = this.lookupReference('port');
- var usb3field = this.lookupReference('usb3');
- if (field.inputValue === 'hostdevice') {
- hwidfield.setDisabled(!newValue);
- } else if(field.inputValue === 'port') {
- portfield.setDisabled(!newValue);
- } else if(field.inputValue === 'spice') {
- usb3field.setDisabled(newValue);
- }
- }
- },
- 'pveUSBSelector': {
- change: function(field, newValue, oldValue) {
- var usbval = field.getUSBValue();
- var usb3field = this.lookupReference('usb3');
- var usb3 = /usb3/.test(usbval);
- if(usb3 && !usb3field.isDisabled()) {
- usb3field.savedVal = usb3field.getValue();
- usb3field.setValue(true);
- usb3field.setDisabled(true);
- } else if(!usb3 && usb3field.isDisabled()){
- var val = (usb3field.savedVal === undefined)?usb3field.originalValue:usb3field.savedVal;
- usb3field.setValue(val);
- usb3field.setDisabled(false);
- }
- }
- }
- }
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
- me.vmconfig = vmconfig;
- },
-
- onGetValues: function(values) {
- var me = this;
- if(!me.confid) {
- var i;
- for (i = 0; i < 6; i++) {
- if (!me.vmconfig['usb' + i.toString()]) {
- me.confid = 'usb' + i.toString();
- break;
- }
- }
- }
- var val = "";
- var type = me.down('radiofield').getGroupValue();
- switch (type) {
- case 'spice':
- val = 'spice'; break;
- case 'hostdevice':
- case 'port':
- val = me.down('pveUSBSelector[name=' + type + ']').getUSBValue();
- if (!/usb3/.test(val) && me.down('field[name=usb3]').getValue() === true) {
- val += ',usb3=1';
- }
- break;
- default:
- throw "invalid type selected";
- }
-
- values[me.confid] = val;
- return values;
- },
-
- items: [
- {
- xtype: 'fieldcontainer',
- defaultType: 'radiofield',
- items:[
- {
- name: 'usb',
- inputValue: 'spice',
- boxLabel: gettext('Spice Port'),
- submitValue: false,
- checked: true
- },
- {
- name: 'usb',
- inputValue: 'hostdevice',
- boxLabel: gettext('Use USB Vendor/Device ID'),
- submitValue: false
- },
- {
- xtype: 'pveUSBSelector',
- disabled: true,
- type: 'device',
- name: 'hostdevice',
- cbind: { pveSelNode: '{pveSelNode}' },
- editable: true,
- reference: 'hwid',
- allowBlank: false,
- fieldLabel: 'Choose Device',
- labelAlign: 'right',
- submitValue: false
- },
- {
- name: 'usb',
- inputValue: 'port',
- boxLabel: gettext('Use USB Port'),
- submitValue: false
- },
- {
- xtype: 'pveUSBSelector',
- disabled: true,
- name: 'port',
- cbind: { pveSelNode: '{pveSelNode}' },
- editable: true,
- type: 'port',
- reference: 'port',
- allowBlank: false,
- fieldLabel: gettext('Choose Port'),
- labelAlign: 'right',
- submitValue: false
- },
- {
- xtype: 'checkbox',
- name: 'usb3',
- submitValue: false,
- reference: 'usb3',
- fieldLabel: gettext('Use USB3')
- }
- ]
- }
- ]
-});
-
-Ext.define('PVE.qemu.USBEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmconfig: undefined,
-
- isAdd: true,
-
- subject: gettext('USB Device'),
-
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.confid;
-
- var ipanel = Ext.create('PVE.qemu.USBInputPanel', {
- confid: me.confid,
- pveSelNode: me.pveSelNode
- });
-
- Ext.apply(me, {
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- if (me.confid) {
- var data = response.result.data[me.confid].split(',');
- var port, hostdevice, usb3 = false;
- var type = 'spice';
- var i;
- for (i = 0; i < data.length; i++) {
- if (/^(host=)?(0x)?[a-zA-Z0-9]{4}\:(0x)?[a-zA-Z0-9]{4}$/.test(data[i])) {
- hostdevice = data[i];
- hostdevice = hostdevice.replace('host=', '').replace('0x','');
- type = 'hostdevice';
- } else if (/^(host=)?(\d+)\-(\d+(\.\d+)*)$/.test(data[i])) {
- port = data[i];
- port = port.replace('host=','');
- type = 'port';
- }
-
- if (/^usb3=(1|on|true)$/.test(data[i])) {
- usb3 = true;
- }
- }
- var values = {
- usb : type,
- hostdevice: hostdevice,
- port: port,
- usb3: usb3
- };
-
- ipanel.setValues(values);
- }
- }
- });
- }
-});
-Ext.define('PVE.qemu.PCIInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
-
- onlineHelp: 'qm_pci_passthrough',
-
- setVMConfig: function(vmconfig) {
- var me = this;
- me.vmconfig = vmconfig;
-
- var hostpci = me.vmconfig[me.confid] || '';
-
- var values = PVE.Parser.parsePropertyString(hostpci, 'host');
- if (values.host && values.host.length < 6) { // 00:00 format not 00:00.0
- values.host += ".0";
- values.multifunction = true;
- }
- values['x-vga'] = PVE.Parser.parseBoolean(values['x-vga'], 0);
- values.pcie = PVE.Parser.parseBoolean(values.pcie, 0);
- values.rombar = PVE.Parser.parseBoolean(values.rombar, 1);
-
- me.setValues(values);
- if (!me.vmconfig.machine || me.vmconfig.machine.indexOf('q35') === -1) {
- // machine is not set to some variant of q35, so we disable pcie
- var pcie = me.down('field[name=pcie]');
- pcie.setDisabled(true);
- pcie.setBoxLabel(gettext('Q35 only'));
- }
-
- if (values.romfile) {
- me.down('field[name=romfile]').setVisible(true);
- }
- },
-
- onGetValues: function(values) {
- var me = this;
- var ret = {};
- if(!me.confid) {
- var i;
- for (i = 0; i < 5; i++) {
- if (!me.vmconfig['hostpci' + i.toString()]) {
- me.confid = 'hostpci' + i.toString();
- break;
- }
- }
- }
- if (values.multifunction) {
- // modify host to skip the '.X'
- values.host = values.host.substring(0,5);
- delete values.multifunction;
- }
-
- if (values.rombar) {
- delete values.rombar;
- } else {
- values.rombar = 0;
- }
-
- if (!values.romfile) {
- delete values.romfile;
- }
-
- ret[me.confid] = PVE.Parser.printPropertyString(values, 'host');
- return ret;
- },
-
- initComponent: function() {
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.column1 = [
- {
- xtype: 'pvePCISelector',
- fieldLabel: gettext('Device'),
- name: 'host',
- nodename: me.nodename,
- allowBlank: false,
- onLoadCallBack: function(store, records, success) {
- if (!success || !records.length) {
- return;
- }
-
- var first = records[0];
- if (first.data.iommugroup === -1) {
- // no iommu groups
- var warning = Ext.create('Ext.form.field.Display', {
- columnWidth: 1,
- padding: '0 0 10 0',
- value: 'No IOMMU detected, please activate it.' +
- 'See Documentation for further information.',
- userCls: 'pve-hint'
- });
- me.items.insert(0, warning);
- me.updateLayout(); // insert does not trigger that
- }
- },
- listeners: {
- change: function(pcisel, value) {
- if (!value) {
- return;
- }
- var pcidev = pcisel.getStore().getById(value);
- var mdevfield = me.down('field[name=mdev]');
- mdevfield.setDisabled(!pcidev || !pcidev.data.mdev);
- if (!pcidev) {
- return;
- }
- var id = pcidev.data.id.substring(0,5); // 00:00
- var iommu = pcidev.data.iommugroup;
- // try to find out if there are more devices
- // in that iommu group
- if (iommu !== -1) {
- var count = 0;
- pcisel.getStore().each(function(record) {
- if (record.data.iommugroup === iommu &&
- record.data.id.substring(0,5) !== id)
- {
- count++;
- return false;
- }
- });
- var warning = me.down('#iommuwarning');
- if (count && !warning) {
- warning = Ext.create('Ext.form.field.Display', {
- columnWidth: 1,
- padding: '0 0 10 0',
- itemId: 'iommuwarning',
- value: 'The selected Device is not in a seperate' +
- 'IOMMU group, make sure this is intended.',
- userCls: 'pve-hint'
- });
- me.items.insert(0, warning);
- me.updateLayout(); // insert does not trigger that
- } else if (!count && warning) {
- me.remove(warning);
- }
- }
- if (pcidev.data.mdev) {
- mdevfield.setPciID(value);
- }
- }
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('All Functions'),
- name: 'multifunction'
- }
- ];
-
- me.column2 = [
- {
- xtype: 'pveMDevSelector',
- name: 'mdev',
- disabled: true,
- fieldLabel: gettext('MDev Type'),
- nodename: me.nodename,
- listeners: {
- change: function(field, value) {
- var mf = me.down('field[name=multifunction]');
- if (!!value) {
- mf.setValue(false);
- }
- mf.setDisabled(!!value);
- }
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Primary GPU'),
- name: 'x-vga'
- }
- ];
-
- me.advancedColumn1 = [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: 'ROM-Bar',
- name: 'rombar'
- },
- {
- xtype: 'displayfield',
- submitValue: true,
- hidden: true,
- fieldLabel: 'ROM-File',
- name: 'romfile'
- }
- ];
-
- me.advancedColumn2 = [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: 'PCI-Express',
- name: 'pcie'
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.PCIEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmconfig: undefined,
-
- isAdd: true,
-
- subject: gettext('PCI Device'),
-
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.confid;
-
- var ipanel = Ext.create('PVE.qemu.PCIInputPanel', {
- confid: me.confid,
- pveSelNode: me.pveSelNode
- });
-
- Ext.apply(me, {
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response) {
- ipanel.setVMConfig(response.result.data);
- }
- });
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.qemu.SerialnputPanel', {
- extend: 'Proxmox.panel.InputPanel',
-
- autoComplete: false,
-
- setVMConfig: function(vmconfig) {
- var me = this, i;
- me.vmconfig = vmconfig;
-
- for (i = 0; i < 4; i++) {
- var port = 'serial' + i.toString();
- if (!me.vmconfig[port]) {
- me.down('field[name=serialid]').setValue(i);
- break;
- }
- }
-
- },
-
- onGetValues: function(values) {
- var me = this;
-
- var id = 'serial' + values.serialid;
- delete values.serialid;
- values[id] = 'socket';
- return values;
- },
-
- items: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'serialid',
- fieldLabel: gettext('Serial Port'),
- minValue: 0,
- maxValue: 3,
- allowBlank: false,
- validator: function(id) {
- if (!this.rendered) {
- return true;
- }
- var me = this.up('panel');
- if (me.vmconfig !== undefined && Ext.isDefined(me.vmconfig['serial' + id])) {
- return "This device is already in use.";
- }
- return true;
- }
- }
- ]
-});
-
-Ext.define('PVE.qemu.SerialEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmconfig: undefined,
-
- isAdd: true,
-
- subject: gettext('Serial Port'),
-
- initComponent : function() {
- var me = this;
-
- // for now create of (socket) serial port only
- me.isCreate = true;
-
- var ipanel = Ext.create('PVE.qemu.SerialnputPanel', {});
-
- Ext.apply(me, {
- items: [ ipanel ]
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- }
- });
- }
-});
-Ext.define('PVE.window.IPInfo', {
- extend: 'Ext.window.Window',
- width: 600,
- title: gettext('Guest Agent Network Information'),
- height: 300,
- layout: {
- type: 'fit'
- },
- modal: true,
- items: [
- {
- xtype: 'grid',
- emptyText: gettext('No network information'),
- columns: [
- {
- dataIndex: 'name',
- text: gettext('Name'),
- flex: 3
- },
- {
- dataIndex: 'hardware-address',
- text: gettext('MAC address'),
- width: 140
- },
- {
- dataIndex: 'ip-addresses',
- text: gettext('IP address'),
- align: 'right',
- flex: 4,
- renderer: function(val) {
- if (!Ext.isArray(val)) {
- return '';
- }
- var ips = [];
- val.forEach(function(ip) {
- var addr = ip['ip-address'];
- var pref = ip.prefix;
- if (addr && pref) {
- ips.push(addr + '/' + pref);
- }
- });
- return ips.join(' ');
- }
- }
- ]
- }
- ]
-});
-
-Ext.define('PVE.qemu.AgentIPView', {
- extend: 'Ext.container.Container',
- xtype: 'pveAgentIPView',
-
- layout: {
- type: 'hbox',
- align: 'top'
- },
-
- nics: [],
-
- items: [
- {
- xtype: 'box',
- html: ' IPs'
- },
- {
- xtype: 'container',
- flex: 1,
- layout: {
- type: 'vbox',
- align: 'right',
- pack: 'end'
- },
- items: [
- {
- xtype: 'label',
- flex: 1,
- itemId: 'ipBox',
- style: {
- 'text-align': 'right'
- }
- },
- {
- xtype: 'button',
- itemId: 'moreBtn',
- hidden: true,
- ui: 'default-toolbar',
- handler: function(btn) {
- var me = this.up('pveAgentIPView');
-
- var win = Ext.create('PVE.window.IPInfo');
- win.down('grid').getStore().setData(me.nics);
- win.show();
- },
- text: gettext('More')
- }
- ]
- }
- ],
-
- getDefaultIps: function(nics) {
- var me = this;
- var ips = [];
- nics.forEach(function(nic) {
- if (nic['hardware-address'] &&
- nic['hardware-address'] != '00:00:00:00:00:00') {
-
- var nic_ips = nic['ip-addresses'] || [];
- nic_ips.forEach(function(ip) {
- var p = ip['ip-address'];
- // show 2 ips at maximum
- if (ips.length < 2) {
- ips.push(p);
- }
- });
- }
- });
-
- return ips;
- },
-
- startIPStore: function(store, records, success) {
- var me = this;
- var agentRec = store.getById('agent');
- /*jslint confusion: true*/
- /* value is number and string */
- me.agent = (agentRec && agentRec.data.value === 1);
- me.running = (store.getById('status').data.value === 'running');
- /*jslint confusion: false*/
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- if (!caps.vms['VM.Monitor']) {
- var errorText = gettext("Requires '{0}' Privileges");
- me.updateStatus(false, Ext.String.format(errorText, 'VM.Monitor'));
- return;
- }
-
- if (me.agent && me.running && me.ipStore.isStopped) {
- me.ipStore.startUpdate();
- } else if (me.ipStore.isStopped) {
- me.updateStatus();
- }
- },
-
- updateStatus: function(unsuccessful, defaulttext) {
- var me = this;
- var text = defaulttext || gettext('No network information');
- var more = false;
- if (unsuccessful) {
- text = gettext('Guest Agent not running');
- } else if (me.agent && me.running) {
- if (Ext.isArray(me.nics) && me.nics.length) {
- more = true;
- var ips = me.getDefaultIps(me.nics);
- if (ips.length !== 0) {
- text = ips.join(' ');
- }
- } else if (me.nics && me.nics.error) {
- var msg = gettext('Cannot get info from Guest Agent Error: {0}');
- text = Ext.String.format(text, me.nics.error.desc);
- }
- } else if (me.agent) {
- text = gettext('Guest Agent not running');
- } else {
- text = gettext('No Guest Agent configured');
- }
-
- var ipBox = me.down('#ipBox');
- ipBox.update(text);
-
- var moreBtn = me.down('#moreBtn');
- moreBtn.setVisible(more);
- },
-
- initComponent: function() {
- var me = this;
-
- if (!me.rstore) {
- throw 'rstore not given';
- }
-
- if (!me.pveSelNode) {
- throw 'pveSelNode not given';
- }
-
- var nodename = me.pveSelNode.data.node;
- var vmid = me.pveSelNode.data.vmid;
-
- me.ipStore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 10000,
- storeid: 'pve-qemu-agent-' + vmid,
- method: 'POST',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + nodename + '/qemu/' + vmid + '/agent/network-get-interfaces'
- }
- });
-
- me.callParent();
-
- me.mon(me.ipStore, 'load', function(store, records, success) {
- if (records && records.length) {
- me.nics = records[0].data.result;
- } else {
- me.nics = undefined;
- }
- me.updateStatus(!success);
- });
-
- me.on('destroy', me.ipStore.stopUpdate);
-
- // if we already have info about the vm, use it immediately
- if (me.rstore.getCount()) {
- me.startIPStore(me.rstore, me.rstore.getData(), false);
- }
-
- // check if the guest agent is there on every statusstore load
- me.mon(me.rstore, 'load', me.startIPStore, me);
- }
-});
-Ext.define('PVE.qemu.CloudInit', {
- extend: 'Proxmox.grid.PendingObjectGrid',
- xtype: 'pveCiPanel',
-
- onlineHelp: 'qm_cloud_init',
-
- tbar: [
- {
- xtype: 'proxmoxButton',
- disabled: true,
- dangerous: true,
- confirmMsg: function(rec) {
- var me = this.up('grid');
- var warn = gettext('Are you sure you want to remove entry {0}');
-
- var entry = rec.data.key;
- var msg = Ext.String.format(warn, "'"
- + me.renderKey(entry, {}, rec) + "'");
-
- return msg;
- },
- enableFn: function(record) {
- var me = this.up('grid');
- var caps = Ext.state.Manager.get('GuiCap');
- if (me.rows[record.data.key].never_delete ||
- !caps.vms['VM.Config.Network']) {
- return false;
- }
-
- if (record.data.key === 'cipassword' && !record.data.value) {
- return false;
- }
- return true;
- },
- handler: function() {
- var me = this.up('grid');
- var records = me.getSelection();
- if (!records || !records.length) {
- return;
- }
-
- var id = records[0].data.key;
- var match = id.match(/^net(\d+)$/);
- if (match) {
- id = 'ipconfig' + match[1];
- }
-
- var params = {};
- params['delete'] = id;
- Proxmox.Utils.API2Request({
- url: me.baseurl + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- params: params,
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- },
- callback: function() {
- me.reload();
- }
- });
- },
- text: gettext('Remove')
- },
- {
- xtype: 'proxmoxButton',
- disabled: true,
- handler: function() {
- var me = this.up('grid');
- me.run_editor();
- },
- text: gettext('Edit')
- },
- '-',
- {
- xtype: 'button',
- itemId: 'savebtn',
- text: gettext('Regenerate Image'),
- handler: function() {
- var me = this.up('grid');
- var eject_params = {};
- var insert_params = {};
- var disk = PVE.Parser.parseQemuDrive(me.ciDriveId, me.ciDrive);
- var storage = '';
- var stormatch = disk.file.match(/^([^\:]+)\:/);
- if (stormatch) {
- storage = stormatch[1];
- }
- eject_params[me.ciDriveId] = 'none,media=cdrom';
- insert_params[me.ciDriveId] = storage + ':cloudinit';
-
- var failure = function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- };
-
- Proxmox.Utils.API2Request({
- url: me.baseurl + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- params: eject_params,
- failure: failure,
- callback: function() {
- Proxmox.Utils.API2Request({
- url: me.baseurl + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- params: insert_params,
- failure: failure,
- callback: function() {
- me.reload();
- }
- });
- }
- });
- }
- }
- ],
-
- border: false,
-
- set_button_status: function(rstore, records, success) {
- if (!success || records.length < 1) {
- return;
- }
- var me = this;
- var found;
- records.forEach(function(record) {
- if (found) {
- return;
- }
- var id = record.data.key;
- var value = record.data.value;
- var ciregex = new RegExp("vm-" + me.pveSelNode.data.vmid + "-cloudinit");
- if (id.match(/^(ide|scsi|sata)\d+$/) && ciregex.test(value)) {
- found = id;
- me.ciDriveId = found;
- me.ciDrive = value;
- }
- });
-
- me.down('#savebtn').setDisabled(!found);
- me.setDisabled(!found);
- if (!found) {
- me.getView().mask(gettext('No CloudInit Drive found'), ['pve-static-mask']);
- } else {
- me.getView().unmask();
- }
- },
-
- renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
- var me = this;
- var rows = me.rows;
- var rowdef = rows[key] || {};
-
- var icon = "";
- if (rowdef.iconCls) {
- icon = ' ';
- }
- return icon + (rowdef.header || key);
- },
-
- listeners: {
- activate: function () {
- var me = this;
- me.rstore.startUpdate();
- },
- itemdblclick: function() {
- var me = this;
- me.run_editor();
- }
- },
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
- var caps = Ext.state.Manager.get('GuiCap');
- me.baseurl = '/api2/extjs/nodes/' + nodename + '/qemu/' + vmid;
- me.url = me.baseurl + '/pending';
- me.editorConfig.url = me.baseurl + '/config';
- me.editorConfig.pveSelNode = me.pveSelNode;
-
- /*jslint confusion: true*/
- /* editor is string and object */
- me.rows = {
- ciuser: {
- header: gettext('User'),
- iconCls: 'fa fa-user',
- never_delete: true,
- defaultValue: '',
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('User'),
- items: [
- {
- xtype: 'proxmoxtextfield',
- deleteEmpty: true,
- emptyText: Proxmox.Utils.defaultText,
- fieldLabel: gettext('User'),
- name: 'ciuser'
- }
- ]
- } : undefined,
- renderer: function(value) {
- return value || Proxmox.Utils.defaultText;
- }
- },
- cipassword: {
- header: gettext('Password'),
- iconCls: 'fa fa-unlock',
- defaultValue: '',
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Password'),
- items: [
- {
- xtype: 'proxmoxtextfield',
- inputType: 'password',
- deleteEmpty: true,
- emptyText: Proxmox.Utils.noneText,
- fieldLabel: gettext('Password'),
- name: 'cipassword'
- }
- ]
- } : undefined,
- renderer: function(value) {
- return value || Proxmox.Utils.noneText;
- }
- },
- searchdomain: {
- header: gettext('DNS domain'),
- iconCls: 'fa fa-globe',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
- never_delete: true,
- defaultValue: gettext('use host settings')
- },
- nameserver: {
- header: gettext('DNS servers'),
- iconCls: 'fa fa-globe',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
- never_delete: true,
- defaultValue: gettext('use host settings')
- },
- sshkeys: {
- header: gettext('SSH public key'),
- iconCls: 'fa fa-key',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.qemu.SSHKeyEdit' : undefined,
- never_delete: true,
- renderer: function(value) {
- value = decodeURIComponent(value);
- var keys = value.split('\n');
- var text = [];
- keys.forEach(function(key) {
- if (key.length) {
- // First erase all quoted strings (eg. command="foo"
- var v = key.replace(/"(?:\\.|[^"\\])*"/g, '');
- // Now try to detect the comment:
- var res = v.match(/^\s*(\S+\s+)?(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)\s+\S+\s+(.*?)\s*$/, '');
- if (res) {
- key = Ext.String.htmlEncode(res[2]);
- if (res[1]) {
- key += ' (' + gettext('with options') + ') ';
- }
- text.push(key);
- return;
- }
- // Most likely invalid at this point, so just stick to
- // the old value.
- text.push(Ext.String.htmlEncode(key));
- }
- });
- if (text.length) {
- return text.join(' ');
- } else {
- return Proxmox.Utils.noneText;
- }
- },
- defaultValue: ''
- }
- };
- var i;
- var ipconfig_renderer = function(value, md, record, ri, ci, store, pending) {
- var id = record.data.key;
- var match = id.match(/^net(\d+)$/);
- var val = '';
- if (match) {
- val = me.getObjectValue('ipconfig'+match[1], '', pending);
- }
- return val;
- };
- for (i = 0; i < 32; i++) {
- // we want to show an entry for every network device
- // even if it is empty
- me.rows['net' + i.toString()] = {
- multiKey: ['ipconfig' + i.toString(), 'net' + i.toString()],
- header: gettext('IP Config') + ' (net' + i.toString() +')',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.qemu.IPConfigEdit' : undefined,
- iconCls: 'fa fa-exchange',
- renderer: ipconfig_renderer
- };
- me.rows['ipconfig' + i.toString()] = {
- visible: false
- };
- }
- /*jslint confusion: false*/
-
- PVE.Utils.forEachBus(['ide', 'scsi', 'sata'], function(type, id) {
- me.rows[type+id] = {
- visible: false
- };
- });
- me.callParent();
- me.mon(me.rstore, 'load', me.set_button_status, me);
- }
-});
-Ext.define('PVE.qemu.CIDriveInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveCIDriveInputPanel',
-
- insideWizard: false,
-
- vmconfig: {}, // used to select usused disks
-
- onGetValues: function(values) {
- var me = this;
-
- var drive = {};
- var params = {};
- drive.file = values.hdstorage + ":cloudinit";
- drive.format = values.diskformat;
- params[values.controller + values.deviceid] = PVE.Parser.printQemuDrive(drive);
- return params;
- },
-
- setNodename: function(nodename) {
- var me = this;
- me.down('#hdstorage').setNodename(nodename);
- me.down('#hdimage').setStorage(undefined, nodename);
- },
-
- setVMConfig: function(config) {
- var me = this;
- me.down('#drive').setVMConfig(config, 'cdrom');
- },
-
- initComponent : function() {
- var me = this;
-
- me.drive = {};
-
- me.items = [
- {
- xtype: 'pveControllerSelector',
- noVirtIO: true,
- itemId: 'drive',
- fieldLabel: gettext('CloudInit Drive'),
- name: 'drive'
- },
- {
- xtype: 'pveDiskStorageSelector',
- itemId: 'storselector',
- storageContent: 'images',
- nodename: me.nodename,
- hideSize: true
- }
- ];
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.CIDriveEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveCIDriveEdit',
-
- isCreate: true,
- subject: gettext('CloudInit Drive'),
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.items = [{
- xtype: 'pveCIDriveInputPanel',
- itemId: 'cipanel',
- nodename: nodename
- }];
-
- me.callParent();
-
- me.load({
- success: function(response, opts) {
- me.down('#cipanel').setVMConfig(response.result.data);
- }
- });
- }
-});
-Ext.define('PVE.qemu.SSHKeyInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveQemuSSHKeyInputPanel',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
- if (values.sshkeys) {
- values.sshkeys.trim();
- }
- if (!values.sshkeys.length) {
- values = {};
- values['delete'] = 'sshkeys';
- return values;
- } else {
- values.sshkeys = encodeURIComponent(values.sshkeys);
- }
- return values;
- },
-
- items: [
- {
- xtype: 'textarea',
- itemId: 'sshkeys',
- name: 'sshkeys',
- height: 250
- },
- {
- xtype: 'filebutton',
- itemId: 'filebutton',
- name: 'file',
- text: gettext('Load SSH Key File'),
- fieldLabel: 'test',
- listeners: {
- change: function(btn, e, value) {
- var me = this.up('inputpanel');
- e = e.event;
- Ext.Array.each(e.target.files, function(file) {
- PVE.Utils.loadSSHKeyFromFile(file, function(res) {
- var keysField = me.down('#sshkeys');
- var old = keysField.getValue();
- keysField.setValue(old + res);
- });
- });
- btn.reset();
- }
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- me.callParent();
- if (!window.FileReader) {
- me.down('#filebutton').setVisible(false);
- }
-
- }
-});
-
-Ext.define('PVE.qemu.SSHKeyEdit', {
- extend: 'Proxmox.window.Edit',
-
- width: 800,
-
- initComponent : function() {
- var me = this;
-
- var ipanel = Ext.create('PVE.qemu.SSHKeyInputPanel');
-
- Ext.apply(me, {
- subject: gettext('SSH Keys'),
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.create) {
- me.load({
- success: function(response, options) {
- var data = response.result.data;
- if (data.sshkeys) {
- data.sshkeys = decodeURIComponent(data.sshkeys);
- ipanel.setValues(data);
- }
- }
- });
- }
- }
-});
-Ext.define('PVE.qemu.IPConfigPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveIPConfigPanel',
-
- insideWizard: false,
-
- vmconfig: {},
-
- onGetValues: function(values) {
- var me = this;
-
- if (values.ipv4mode !== 'static') {
- values.ip = values.ipv4mode;
- }
-
- if (values.ipv6mode !== 'static') {
- values.ip6 = values.ipv6mode;
- }
-
- var params = {};
-
- var cfg = PVE.Parser.printIPConfig(values);
- if (cfg === '') {
- params['delete'] = [me.confid];
- } else {
- params[me.confid] = cfg;
- }
- return params;
- },
-
- setVMConfig: function(config) {
- var me = this;
- me.vmconfig = config;
- },
-
- setIPConfig: function(confid, data) {
- var me = this;
-
- me.confid = confid;
-
- if (data.ip === 'dhcp') {
- data.ipv4mode = data.ip;
- data.ip = '';
- } else {
- data.ipv4mode = 'static';
- }
- if (data.ip6 === 'dhcp' || data.ip6 === 'auto') {
- data.ipv6mode = data.ip6;
- data.ip6 = '';
- } else {
- data.ipv6mode = 'static';
- }
-
- me.ipconfig = data;
- me.setValues(me.ipconfig);
- },
-
- initComponent : function() {
- var me = this;
-
- me.ipconfig = {};
-
- me.column1 = [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Network Device'),
- value: me.netid
- },
- {
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- border: false,
- margin: '0 0 5 0',
- items: [
- {
- xtype: 'label',
- text: gettext('IPv4') + ':'
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('Static'),
- name: 'ipv4mode',
- inputValue: 'static',
- checked: false,
- margin: '0 0 0 10',
- listeners: {
- change: function(cb, value) {
- me.down('field[name=ip]').setDisabled(!value);
- me.down('field[name=gw]').setDisabled(!value);
- }
- }
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('DHCP'),
- name: 'ipv4mode',
- inputValue: 'dhcp',
- checked: false,
- margin: '0 0 0 10'
- }
- ]
- },
- {
- xtype: 'textfield',
- name: 'ip',
- vtype: 'IPCIDRAddress',
- value: '',
- disabled: true,
- fieldLabel: gettext('IPv4/CIDR')
- },
- {
- xtype: 'textfield',
- name: 'gw',
- value: '',
- vtype: 'IPAddress',
- disabled: true,
- fieldLabel: gettext('Gateway') + ' (' + gettext('IPv4') +')'
- }
- ];
-
- me.column2 = [
- {
- xtype: 'displayfield'
- },
- {
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- border: false,
- margin: '0 0 5 0',
- items: [
- {
- xtype: 'label',
- text: gettext('IPv6') + ':'
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('Static'),
- name: 'ipv6mode',
- inputValue: 'static',
- checked: false,
- margin: '0 0 0 10',
- listeners: {
- change: function(cb, value) {
- me.down('field[name=ip6]').setDisabled(!value);
- me.down('field[name=gw6]').setDisabled(!value);
- }
- }
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('DHCP'),
- name: 'ipv6mode',
- inputValue: 'dhcp',
- checked: false,
- margin: '0 0 0 10'
- }
- ]
- },
- {
- xtype: 'textfield',
- name: 'ip6',
- value: '',
- vtype: 'IP6CIDRAddress',
- disabled: true,
- fieldLabel: gettext('IPv6/CIDR')
- },
- {
- xtype: 'textfield',
- name: 'gw6',
- vtype: 'IP6Address',
- value: '',
- disabled: true,
- fieldLabel: gettext('Gateway') + ' (' + gettext('IPv6') +')'
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.qemu.IPConfigEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
-
- initComponent : function() {
- /*jslint confusion: true */
-
- var me = this;
-
- // convert confid from netX to ipconfigX
- var match = me.confid.match(/^net(\d+)$/);
- if (match) {
- me.netid = me.confid;
- me.confid = 'ipconfig' + match[1];
- }
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- me.isCreate = me.confid ? false : true;
-
- var ipanel = Ext.create('PVE.qemu.IPConfigPanel', {
- confid: me.confid,
- netid: me.netid,
- nodename: nodename
- });
-
- Ext.applyIf(me, {
- subject: gettext('Network Config'),
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- me.vmconfig = response.result.data;
- var ipconfig = {};
- var value = me.vmconfig[me.confid];
- if (value) {
- ipconfig = PVE.Parser.parseIPConfig(me.confid, value);
- if (!ipconfig) {
- Ext.Msg.alert(gettext('Error'), gettext('Unable to parse network configuration'));
- me.close();
- return;
- }
- }
- ipanel.setIPConfig(me.confid, ipconfig);
- ipanel.setVMConfig(me.vmconfig);
- }
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.qemu.SystemInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveQemuSystemPanel',
-
- onlineHelp: 'qm_system_settings',
-
- viewModel: {
- data: {
- efi: false,
- addefi: true
- },
-
- formulas: {
- efidisk: function(get) {
- return get('efi') && get('addefi');
- }
- }
- },
-
- onGetValues: function(values) {
- if (values.vga && values.vga.substr(0,6) === 'serial') {
- values['serial' + values.vga.substr(6,1)] = 'socket';
- }
-
- var efidrive = {};
- if (values.hdimage) {
- efidrive.file = values.hdimage;
- } else if (values.hdstorage) {
- efidrive.file = values.hdstorage + ":1";
- }
-
- if (values.diskformat) {
- efidrive.format = values.diskformat;
- }
-
- delete values.hdimage;
- delete values.hdstorage;
- delete values.diskformat;
-
- if (efidrive.file) {
- values.efidisk0 = PVE.Parser.printQemuDrive(efidrive);
- }
-
- return values;
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- scsihwChange: function(field, value) {
- var me = this;
- if (me.getView().insideWizard) {
- me.getViewModel().set('current.scsihw', value);
- }
- },
-
- biosChange: function(field, value) {
- var me = this;
- if (me.getView().insideWizard) {
- me.getViewModel().set('efi', value === 'ovmf');
- }
- },
-
- control: {
- 'pveScsiHwSelector': {
- change: 'scsihwChange'
- },
- 'pveQemuBiosSelector': {
- change: 'biosChange'
- }
- }
- },
-
- column1: [
- {
- xtype: 'proxmoxKVComboBox',
- value: '__default__',
- deleteEmpty: false,
- fieldLabel: gettext('Graphic card'),
- name: 'vga',
- comboItems: PVE.Utils.kvm_vga_driver_array()
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'agent',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Qemu Agent')
- }
- ],
-
- column2: [
- {
- xtype: 'pveScsiHwSelector',
- name: 'scsihw',
- value: '__default__',
- bind: {
- value: '{current.scsihw}'
- },
- fieldLabel: gettext('SCSI Controller')
- }
- ],
-
- advancedColumn1: [
- {
- xtype: 'pveQemuBiosSelector',
- name: 'bios',
- value: '__default__',
- fieldLabel: 'BIOS'
- },
- {
- xtype: 'proxmoxcheckbox',
- bind: {
- value: '{addefi}',
- hidden: '{!efi}',
- disabled: '{!efi}'
- },
- hidden: true,
- submitValue: false,
- disabled: true,
- fieldLabel: gettext('Add EFI Disk')
- },
- {
- xtype: 'pveDiskStorageSelector',
- name: 'efidisk0',
- storageContent: 'images',
- bind: {
- nodename: '{nodename}',
- hidden: '{!efi}',
- disabled: '{!efidisk}'
- },
- autoSelect: false,
- disabled: true,
- hidden: true,
- hideSize: true
- }
- ],
-
- advancedColumn2: [
- {
- xtype: 'proxmoxKVComboBox',
- name: 'machine',
- value: '__default__',
- fieldLabel: gettext('Machine'),
- comboItems: [
- ['__default__', PVE.Utils.render_qemu_machine('')],
- ['q35', 'q35']
- ]
- }
- ]
-
-});
-Ext.define('PVE.lxc.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveLxcSummary',
-
- scrollable: true,
- bodyPadding: 5,
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- if (!me.workspace) {
- throw "no workspace specified";
- }
-
- if (!me.statusStore) {
- throw "no status storage specified";
- }
-
- var template = !!me.pveSelNode.data.template;
- var rstore = me.statusStore;
-
- var width = template ? 1 : 0.5;
- var items = [
- {
- xtype: template ? 'pveTemplateStatusView' : 'pveGuestStatusView',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: width
- },
- 'width >= 1900': {
- columnWidth: width / 2
- }
- },
- itemId: 'gueststatus',
- pveSelNode: me.pveSelNode,
- rstore: rstore
- },
- {
- xtype: 'pveNotesView',
- maxHeight: 320,
- itemId: 'notesview',
- pveSelNode: me.pveSelNode,
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: width
- },
- 'width >= 1900': {
- columnWidth: width / 2
- }
- }
- }
- ];
-
- var rrdstore;
- if (!template) {
-
- rrdstore = Ext.create('Proxmox.data.RRDStore', {
- rrdurl: "/api2/json/nodes/" + nodename + "/lxc/" + vmid + "/rrddata",
- model: 'pve-rrd-guest'
- });
-
- items.push(
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('CPU usage'),
- pveSelNode: me.pveSelNode,
- fields: ['cpu'],
- fieldTitles: [gettext('CPU usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Memory usage'),
- pveSelNode: me.pveSelNode,
- fields: ['maxmem', 'mem'],
- fieldTitles: [gettext('Total'), gettext('RAM usage')],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Network traffic'),
- pveSelNode: me.pveSelNode,
- fields: ['netin','netout'],
- store: rrdstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Disk IO'),
- pveSelNode: me.pveSelNode,
- fields: ['diskread','diskwrite'],
- store: rrdstore
- }
- );
-
- }
-
- Ext.apply(me, {
- tbar: [ '->', { xtype: 'proxmoxRRDTypeSelector' } ],
- items: [
- {
- xtype: 'container',
- layout: {
- type: 'column'
- },
- defaults: {
- minHeight: 320,
- padding: 5,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- }
- },
- items: items
- }
- ]
- });
-
- me.callParent();
- if (!template) {
- rrdstore.startUpdate();
- me.on('destroy', rrdstore.stopUpdate);
- }
- }
-});
-Ext.define('PVE.lxc.NetworkInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveLxcNetworkInputPanel',
-
- insideWizard: false,
-
- onlineHelp: 'pct_container_network',
-
- setNodename: function(nodename) {
- var me = this;
-
- if (!nodename || (me.nodename === nodename)) {
- return;
- }
-
- me.nodename = nodename;
-
- var bridgesel = me.query("[isFormField][name=bridge]")[0];
- bridgesel.setNodename(nodename);
- },
-
- onGetValues: function(values) {
- var me = this;
-
- var id;
- if (me.isCreate) {
- id = values.id;
- delete values.id;
- } else {
- id = me.ifname;
- }
-
- if (!id) {
- return {};
- }
-
- var newdata = {};
-
- if (values.ipv6mode !== 'static') {
- values.ip6 = values.ipv6mode;
- }
- if (values.ipv4mode !== 'static') {
- values.ip = values.ipv4mode;
- }
- newdata[id] = PVE.Parser.printLxcNetwork(values);
- return newdata;
- },
-
- initComponent : function() {
- var me = this;
-
- var cdata = {};
-
- if (me.insideWizard) {
- me.ifname = 'net0';
- cdata.name = 'eth0';
- me.dataCache = {};
- }
- cdata.firewall = (me.insideWizard || me.isCreate);
-
- if (!me.dataCache) {
- throw "no dataCache specified";
- }
-
- if (!me.isCreate) {
- if (!me.ifname) {
- throw "no interface name specified";
- }
- if (!me.dataCache[me.ifname]) {
- throw "no such interface '" + me.ifname + "'";
- }
-
- cdata = PVE.Parser.parseLxcNetwork(me.dataCache[me.ifname]);
- }
-
- var i;
- for (i = 0; i < 10; i++) {
- if (me.isCreate && !me.dataCache['net'+i.toString()]) {
- me.ifname = 'net' + i.toString();
- break;
- }
- }
-
- var idselector = {
- xtype: 'hidden',
- name: 'id',
- value: me.ifname
- };
-
- me.column1 = [
- idselector,
- {
- xtype: 'textfield',
- name: 'name',
- fieldLabel: gettext('Name'),
- emptyText: '(e.g., eth0)',
- allowBlank: false,
- value: cdata.name,
- validator: function(value) {
- var result = '';
- Ext.Object.each(me.dataCache, function(key, netstr) {
- if (!key.match(/^net\d+/) || key === me.ifname) {
- return; // continue
- }
- var net = PVE.Parser.parseLxcNetwork(netstr);
- if (net.name === value) {
- result = "interface name already in use";
- return false;
- }
- });
- if (result !== '') {
- return result;
- }
- // validator can return bool/string
- /*jslint confusion:true*/
- return true;
- }
- },
- {
- xtype: 'textfield',
- name: 'hwaddr',
- fieldLabel: gettext('MAC address'),
- vtype: 'MacAddress',
- value: cdata.hwaddr,
- allowBlank: true,
- emptyText: 'auto'
- },
- {
- xtype: 'PVE.form.BridgeSelector',
- name: 'bridge',
- nodename: me.nodename,
- fieldLabel: gettext('Bridge'),
- value: cdata.bridge,
- allowBlank: false
- },
- {
- xtype: 'pveVlanField',
- name: 'tag',
- value: cdata.tag
- },
- {
- xtype: 'numberfield',
- name: 'rate',
- fieldLabel: gettext('Rate limit') + ' (MB/s)',
- minValue: 0,
- maxValue: 10*1024,
- value: cdata.rate,
- emptyText: 'unlimited',
- allowBlank: true
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Firewall'),
- name: 'firewall',
- value: cdata.firewall
- }
- ];
-
- var dhcp4 = (cdata.ip === 'dhcp');
- if (dhcp4) {
- cdata.ip = '';
- cdata.gw = '';
- }
-
- var auto6 = (cdata.ip6 === 'auto');
- var dhcp6 = (cdata.ip6 === 'dhcp');
- if (auto6 || dhcp6) {
- cdata.ip6 = '';
- cdata.gw6 = '';
- }
-
- me.column2 = [
- {
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- border: false,
- margin: '0 0 5 0',
- items: [
- {
- xtype: 'label',
- text: 'IPv4:' // do not localize
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('Static'),
- name: 'ipv4mode',
- inputValue: 'static',
- checked: !dhcp4,
- margin: '0 0 0 10',
- listeners: {
- change: function(cb, value) {
- me.down('field[name=ip]').setDisabled(!value);
- me.down('field[name=gw]').setDisabled(!value);
- }
- }
- },
- {
- xtype: 'radiofield',
- boxLabel: 'DHCP', // do not localize
- name: 'ipv4mode',
- inputValue: 'dhcp',
- checked: dhcp4,
- margin: '0 0 0 10'
- }
- ]
- },
- {
- xtype: 'textfield',
- name: 'ip',
- vtype: 'IPCIDRAddress',
- value: cdata.ip,
- disabled: dhcp4,
- fieldLabel: 'IPv4/CIDR' // do not localize
- },
- {
- xtype: 'textfield',
- name: 'gw',
- value: cdata.gw,
- vtype: 'IPAddress',
- disabled: dhcp4,
- fieldLabel: gettext('Gateway') + ' (IPv4)',
- margin: '0 0 3 0' // override bottom margin to account for the menuseparator
- },
- {
- xtype: 'menuseparator',
- height: '3',
- margin: '0'
- },
- {
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- border: false,
- margin: '0 0 5 0',
- items: [
- {
- xtype: 'label',
- text: 'IPv6:' // do not localize
- },
- {
- xtype: 'radiofield',
- boxLabel: gettext('Static'),
- name: 'ipv6mode',
- inputValue: 'static',
- checked: !(auto6 || dhcp6),
- margin: '0 0 0 10',
- listeners: {
- change: function(cb, value) {
- me.down('field[name=ip6]').setDisabled(!value);
- me.down('field[name=gw6]').setDisabled(!value);
- }
- }
- },
- {
- xtype: 'radiofield',
- boxLabel: 'DHCP', // do not localize
- name: 'ipv6mode',
- inputValue: 'dhcp',
- checked: dhcp6,
- margin: '0 0 0 10'
- },
- {
- xtype: 'radiofield',
- boxLabel: 'SLAAC', // do not localize
- name: 'ipv6mode',
- inputValue: 'auto',
- checked: auto6,
- margin: '0 0 0 10'
- }
- ]
- },
- {
- xtype: 'textfield',
- name: 'ip6',
- value: cdata.ip6,
- vtype: 'IP6CIDRAddress',
- disabled: (dhcp6 || auto6),
- fieldLabel: 'IPv6/CIDR' // do not localize
- },
- {
- xtype: 'textfield',
- name: 'gw6',
- vtype: 'IP6Address',
- value: cdata.gw6,
- disabled: (dhcp6 || auto6),
- fieldLabel: gettext('Gateway') + ' (IPv6)'
- }
- ];
-
- me.callParent();
- }
-});
-
-
-Ext.define('PVE.lxc.NetworkEdit', {
- extend: 'Proxmox.window.Edit',
-
- isAdd: true,
-
- initComponent : function() {
- var me = this;
-
- if (!me.dataCache) {
- throw "no dataCache specified";
- }
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var ipanel = Ext.create('PVE.lxc.NetworkInputPanel', {
- ifname: me.ifname,
- nodename: me.nodename,
- dataCache: me.dataCache,
- isCreate: me.isCreate
- });
-
- Ext.apply(me, {
- subject: gettext('Network Device') + ' (veth)',
- digest: me.dataCache.digest,
- items: [ ipanel ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.lxc.NetworkView', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pveLxcNetworkView',
-
- onlineHelp: 'pct_container_network',
-
- dataCache: {}, // used to store result of last load
-
- stateful: true,
- stateId: 'grid-lxc-network',
-
- load: function() {
- var me = this;
-
- Proxmox.Utils.setErrorMask(me, true);
-
- Proxmox.Utils.API2Request({
- url: me.url,
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, gettext('Error') + ': ' + response.htmlStatus);
- },
- success: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, false);
- var result = Ext.decode(response.responseText);
- var data = result.data || {};
- me.dataCache = data;
- var records = [];
- Ext.Object.each(data, function(key, value) {
- if (!key.match(/^net\d+/)) {
- return; // continue
- }
- var net = PVE.Parser.parseLxcNetwork(value);
- net.id = key;
- records.push(net);
- });
- me.store.loadData(records);
- me.down('button[name=addButton]').setDisabled((records.length >= 10));
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- me.url = '/nodes/' + nodename + '/lxc/' + vmid + '/config';
-
- var store = new Ext.data.Store({
- model: 'pve-lxc-network',
- sorters: [
- {
- property : 'id',
- direction: 'ASC'
- }
- ]
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- return !!caps.vms['VM.Config.Network'];
- },
- confirmMsg: function (rec) {
- return Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.id + "'");
- },
- handler: function(btn, event, rec) {
- Proxmox.Utils.API2Request({
- url: me.url,
- waitMsgTarget: me,
- method: 'PUT',
- params: { 'delete': rec.data.id, digest: me.dataCache.digest },
- callback: function() {
- me.load();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- if (!caps.vms['VM.Config.Network']) {
- return false;
- }
-
- var win = Ext.create('PVE.lxc.NetworkEdit', {
- url: me.url,
- nodename: nodename,
- dataCache: me.dataCache,
- ifname: rec.data.id
- });
- win.on('destroy', me.load, me);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- selModel: sm,
- disabled: true,
- enableFn: function(rec) {
- if (!caps.vms['VM.Config.Network']) {
- return false;
- }
- return true;
- },
- handler: run_editor
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- {
- text: gettext('Add'),
- name: 'addButton',
- disabled: !caps.vms['VM.Config.Network'],
- handler: function() {
- var win = Ext.create('PVE.lxc.NetworkEdit', {
- url: me.url,
- nodename: nodename,
- isCreate: true,
- dataCache: me.dataCache
- });
- win.on('destroy', me.load, me);
- win.show();
- }
- },
- remove_btn,
- edit_btn
- ],
- columns: [
- {
- header: 'ID',
- width: 50,
- dataIndex: 'id'
- },
- {
- header: gettext('Name'),
- width: 80,
- dataIndex: 'name'
- },
- {
- header: gettext('Bridge'),
- width: 80,
- dataIndex: 'bridge'
- },
- {
- header: gettext('Firewall'),
- width: 80,
- dataIndex: 'firewall',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- header: gettext('VLAN Tag'),
- width: 80,
- dataIndex: 'tag'
- },
- {
- header: gettext('MAC address'),
- width: 110,
- dataIndex: 'hwaddr'
- },
- {
- header: gettext('IP address'),
- width: 150,
- dataIndex: 'ip',
- renderer: function(value, metaData, rec) {
- if (rec.data.ip && rec.data.ip6) {
- return rec.data.ip + " " + rec.data.ip6;
- } else if (rec.data.ip6) {
- return rec.data.ip6;
- } else {
- return rec.data.ip;
- }
- }
- },
- {
- header: gettext('Gateway'),
- width: 150,
- dataIndex: 'gw',
- renderer: function(value, metaData, rec) {
- if (rec.data.gw && rec.data.gw6) {
- return rec.data.gw + " " + rec.data.gw6;
- } else if (rec.data.gw6) {
- return rec.data.gw6;
- } else {
- return rec.data.gw;
- }
- }
- }
- ],
- listeners: {
- activate: me.load,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-lxc-network', {
- extend: "Ext.data.Model",
- proxy: { type: 'memory' },
- fields: [ 'id', 'name', 'hwaddr', 'bridge',
- 'ip', 'gw', 'ip6', 'gw6', 'tag', 'firewall' ]
- });
-
-});
-
-/*jslint confusion: true */
-Ext.define('PVE.lxc.RessourceView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveLxcRessourceView'],
-
- onlineHelp: 'pct_configuration',
-
- renderKey: function(key, metaData, rec, rowIndex, colIndex, store) {
- var me = this;
- var rowdef = me.rows[key] || {};
-
- metaData.tdAttr = "valign=middle";
- if (rowdef.tdCls) {
- metaData.tdCls = rowdef.tdCls;
- }
- return rowdef.header || key;
- },
-
- initComponent : function() {
- var me = this;
- var i, confid;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
- var diskCap = caps.vms['VM.Config.Disk'];
-
- var mpeditor = caps.vms['VM.Config.Disk'] ? 'PVE.lxc.MountPointEdit' : undefined;
-
- var rows = {
- memory: {
- header: gettext('Memory'),
- editor: caps.vms['VM.Config.Memory'] ? 'PVE.lxc.MemoryEdit' : undefined,
- defaultValue: 512,
- tdCls: 'pve-itype-icon-memory',
- group: 1,
- renderer: function(value) {
- return Proxmox.Utils.format_size(value*1024*1024);
- }
- },
- swap: {
- header: gettext('Swap'),
- editor: caps.vms['VM.Config.Memory'] ? 'PVE.lxc.MemoryEdit' : undefined,
- defaultValue: 512,
- tdCls: 'pve-itype-icon-swap',
- group: 2,
- renderer: function(value) {
- return Proxmox.Utils.format_size(value*1024*1024);
- }
- },
- cores: {
- header: gettext('Cores'),
- editor: caps.vms['VM.Config.CPU'] ? 'PVE.lxc.CPUEdit' : undefined,
- defaultValue: '',
- tdCls: 'pve-itype-icon-processor',
- group: 3,
- renderer: function(value) {
- var cpulimit = me.getObjectValue('cpulimit');
- var cpuunits = me.getObjectValue('cpuunits');
- var res;
- if (value) {
- res = value;
- } else {
- res = gettext('unlimited');
- }
-
- if (cpulimit) {
- res += ' [cpulimit=' + cpulimit + ']';
- }
-
- if (cpuunits) {
- res += ' [cpuunits=' + cpuunits + ']';
- }
- return res;
- }
- },
- rootfs: {
- header: gettext('Root Disk'),
- defaultValue: Proxmox.Utils.noneText,
- editor: mpeditor,
- tdCls: 'pve-itype-icon-storage',
- group: 4
- },
- cpulimit: {
- visible: false
- },
- cpuunits: {
- visible: false
- },
- unprivileged: {
- visible: false
- }
- };
-
- PVE.Utils.forEachMP(function(bus, i) {
- confid = bus + i;
- var group = 5;
- var header;
- if (bus === 'mp') {
- header = gettext('Mount Point') + ' (' + confid + ')';
- } else {
- header = gettext('Unused Disk') + ' ' + i;
- group += 1;
- }
- rows[confid] = {
- group: group,
- order: i,
- tdCls: 'pve-itype-icon-storage',
- editor: mpeditor,
- header: header
- };
- }, true);
-
- var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
-
- me.selModel = Ext.create('Ext.selection.RowModel', {});
-
- var run_resize = function() {
- var rec = me.selModel.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.window.MPResize', {
- disk: rec.data.key,
- nodename: nodename,
- vmid: vmid
- });
-
- win.show();
- };
-
- var run_remove = function(b, e, rec) {
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/' + baseurl,
- waitMsgTarget: me,
- method: 'PUT',
- params: {
- 'delete': rec.data.key
- },
- failure: function (response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- var run_move = function(b, e, rec) {
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.window.HDMove', {
- disk: rec.data.key,
- nodename: nodename,
- vmid: vmid,
- type: 'lxc'
- });
-
- win.show();
-
- win.on('destroy', me.reload, me);
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- selModel: me.selModel,
- disabled: true,
- enableFn: function(rec) {
- if (!rec) {
- return false;
- }
- var rowdef = rows[rec.data.key];
- return !!rowdef.editor;
- },
- handler: function() { me.run_editor(); }
- });
-
- var resize_btn = new Proxmox.button.Button({
- text: gettext('Resize disk'),
- selModel: me.selModel,
- disabled: true,
- handler: run_resize
- });
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- selModel: me.selModel,
- disabled: true,
- dangerous: true,
- confirmMsg: function(rec) {
- var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + me.renderKey(rec.data.key, {}, rec) + "'");
- if (rec.data.key.match(/^unused\d+$/)) {
- msg += " " + gettext('This will permanently erase all data.');
- }
-
- return msg;
- },
- handler: run_remove
- });
-
- var move_btn = new Proxmox.button.Button({
- text: gettext('Move Volume'),
- selModel: me.selModel,
- disabled: true,
- dangerous: true,
- handler: run_move
- });
-
- var set_button_status = function() {
- var rec = me.selModel.getSelection()[0];
-
- if (!rec) {
- edit_btn.disable();
- remove_btn.disable();
- resize_btn.disable();
- return;
- }
- var key = rec.data.key;
- var value = rec.data.value;
- var rowdef = rows[key];
-
- var isDisk = (rowdef.tdCls == 'pve-itype-icon-storage');
-
- var noedit = rec.data['delete'] || !rowdef.editor;
- if (!noedit && Proxmox.UserName !== 'root@pam' && key.match(/^mp\d+$/)) {
- var mp = PVE.Parser.parseLxcMountPoint(value);
- if (mp.type !== 'volume') {
- noedit = true;
- }
- }
- edit_btn.setDisabled(noedit);
-
- remove_btn.setDisabled(!isDisk || rec.data.key === 'rootfs' || !diskCap);
- resize_btn.setDisabled(!isDisk || !diskCap);
- move_btn.setDisabled(!isDisk || !diskCap);
-
- };
-
- var sorterFn = function(rec1, rec2) {
- var v1 = rec1.data.key;
- var v2 = rec2.data.key;
- var g1 = rows[v1].group || 0;
- var g2 = rows[v2].group || 0;
- var order1 = rows[v1].order || 0;
- var order2 = rows[v2].order || 0;
-
- if ((g1 - g2) !== 0) {
- return g1 - g2;
- }
-
- if ((order1 - order2) !== 0) {
- return order1 - order2;
- }
-
- if (v1 > v2) {
- return 1;
- } else if (v1 < v2) {
- return -1;
- } else {
- return 0;
- }
- };
-
- Ext.apply(me, {
- url: '/api2/json/' + baseurl,
- selModel: me.selModel,
- interval: 2000,
- cwidth1: 170,
- tbar: [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Mount Point'),
- iconCls: 'pve-itype-icon-storage',
- disabled: !caps.vms['VM.Config.Disk'],
- handler: function() {
- var win = Ext.create('PVE.lxc.MountPointEdit', {
- url: '/api2/extjs/' + baseurl,
- unprivileged: me.getObjectValue('unprivileged'),
- pveSelNode: me.pveSelNode
- });
- win.show();
- }
- }
- ]
- })
- },
- edit_btn,
- remove_btn,
- resize_btn,
- move_btn
- ],
- rows: rows,
- sorterFn: sorterFn,
- editorConfig: {
- pveSelNode: me.pveSelNode,
- url: '/api2/extjs/' + baseurl
- },
- listeners: {
- itemdblclick: me.run_editor,
- selectionchange: set_button_status
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
-
- Ext.apply(me.editorConfig, { unprivileged: me.getObjectValue('unprivileged') });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.lxc.FeaturesInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveLxcFeaturesInputPanel',
-
- // used to save the mounts fstypes until sending
- mounts: [],
-
- fstypes: ['nfs', 'cifs'],
-
- viewModel: {
- parent: null,
- data: {
- unprivileged: false
- },
- formulas: {
- privilegedOnly: function(get) {
- return (get('unprivileged') ? gettext('privileged only') : '');
- },
- unprivilegedOnly: function(get) {
- return (!get('unprivileged') ? gettext('unprivileged only') : '');
- }
- }
- },
-
- items: [
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('keyctl'),
- name: 'keyctl',
- bind: {
- disabled: '{!unprivileged}',
- boxLabel: '{unprivilegedOnly}'
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Nesting'),
- name: 'nesting'
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'nfs',
- fieldLabel: 'NFS',
- bind: {
- disabled: '{unprivileged}',
- boxLabel: '{privilegedOnly}'
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'cifs',
- fieldLabel: 'CIFS',
- bind: {
- disabled: '{unprivileged}',
- boxLabel: '{privilegedOnly}'
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'fuse',
- fieldLabel: 'FUSE'
- }
- ],
-
- onGetValues: function(values) {
- var me = this;
- var mounts = me.mounts;
- me.fstypes.forEach(function(fs) {
- if (values[fs]) {
- mounts.push(fs);
- }
- delete values[fs];
- });
-
- if (mounts.length) {
- values.mount = mounts.join(';');
- }
-
- var featuresstring = PVE.Parser.printPropertyString(values, undefined);
- if (featuresstring == '') {
- return { 'delete': 'features' };
- }
- return { features: featuresstring };
- },
-
- setValues: function(values) {
- var me = this;
-
- me.viewModel.set({ unprivileged: values.unprivileged });
-
- if (values.features) {
- var res = PVE.Parser.parsePropertyString(values.features);
- me.mounts = [];
- if (res.mount) {
- res.mount.split(/[; ]/).forEach(function(item) {
- if (me.fstypes.indexOf(item) === -1) {
- me.mounts.push(item);
- } else {
- res[item] = 1;
- }
- });
- }
- this.callParent([res]);
- }
- }
-});
-
-Ext.define('PVE.lxc.FeaturesEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveLxcFeaturesEdit',
-
- subject: gettext('Features'),
-
- items: [{
- xtype: 'pveLxcFeaturesInputPanel'
- }],
-
- initComponent : function() {
- var me = this;
-
- me.callParent();
-
- me.load();
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.lxc.Options', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveLxcOptions'],
-
- onlineHelp: 'pct_options',
-
- initComponent : function() {
- var me = this;
- var i;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var rows = {
- onboot: {
- header: gettext('Start at boot'),
- defaultValue: '',
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Start at boot'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'onboot',
- uncheckedValue: 0,
- defaultValue: 0,
- fieldLabel: gettext('Start at boot')
- }
- } : undefined
- },
- startup: {
- header: gettext('Start/Shutdown order'),
- defaultValue: '',
- renderer: PVE.Utils.render_kvm_startup,
- editor: caps.vms['VM.Config.Options'] && caps.nodes['Sys.Modify'] ?
- {
- xtype: 'pveWindowStartupEdit',
- onlineHelp: 'pct_startup_and_shutdown'
- } : undefined
- },
- ostype: {
- header: gettext('OS Type'),
- defaultValue: Proxmox.Utils.unknownText
- },
- arch: {
- header: gettext('Architecture'),
- defaultValue: Proxmox.Utils.unknownText
- },
- console: {
- header: '/dev/console',
- defaultValue: 1,
- renderer: Proxmox.Utils.format_enabled_toggle,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: '/dev/console',
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'console',
- uncheckedValue: 0,
- defaultValue: 1,
- deleteDefaultValue: true,
- checked: true,
- fieldLabel: '/dev/console'
- }
- } : undefined
- },
- tty: {
- header: gettext('TTY count'),
- defaultValue: 2,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('TTY count'),
- items: {
- xtype: 'proxmoxintegerfield',
- name: 'tty',
- minValue: 0,
- maxValue: 6,
- value: 2,
- fieldLabel: gettext('TTY count'),
- emptyText: gettext('Default'),
- deleteEmpty: true
- }
- } : undefined
- },
- cmode: {
- header: gettext('Console mode'),
- defaultValue: 'tty',
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Console mode'),
- items: {
- xtype: 'proxmoxKVComboBox',
- name: 'cmode',
- deleteEmpty: true,
- value: '__default__',
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText + " (tty)"],
- ['tty', "/dev/tty[X]"],
- ['console', "/dev/console"],
- ['shell', "shell"]
- ],
- fieldLabel: gettext('Console mode')
- }
- } : undefined
- },
- protection: {
- header: gettext('Protection'),
- defaultValue: false,
- renderer: Proxmox.Utils.format_boolean,
- editor: caps.vms['VM.Config.Options'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Protection'),
- items: {
- xtype: 'proxmoxcheckbox',
- name: 'protection',
- uncheckedValue: 0,
- defaultValue: 0,
- deleteDefaultValue: true,
- fieldLabel: gettext('Enabled')
- }
- } : undefined
- },
- unprivileged: {
- header: gettext('Unprivileged container'),
- renderer: Proxmox.Utils.format_boolean,
- defaultValue: 0
- },
- features: {
- header: gettext('Features'),
- defaultValue: Proxmox.Utils.noneText,
- editor: Proxmox.UserName === 'root@pam' ?
- 'PVE.lxc.FeaturesEdit' : undefined
- },
- hookscript: {
- header: gettext('Hookscript')
- }
- };
-
- var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- var rowdef = rows[rec.data.key];
- return !!rowdef.editor;
- },
- handler: function() { me.run_editor(); }
- });
-
- Ext.apply(me, {
- url: "/api2/json/" + baseurl,
- selModel: sm,
- interval: 5000,
- tbar: [ edit_btn ],
- rows: rows,
- editorConfig: {
- url: '/api2/extjs/' + baseurl
- },
- listeners: {
- itemdblclick: me.run_editor
- }
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
-
- }
-});
-
-Ext.define('PVE.lxc.DNSInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveLxcDNSInputPanel',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- var deletes = [];
- if (!values.searchdomain && !me.insideWizard) {
- deletes.push('searchdomain');
- }
-
- if (values.nameserver) {
- var list = values.nameserver.split(/[\ \,\;]+/);
- values.nameserver = list.join(' ');
- } else if(!me.insideWizard) {
- deletes.push('nameserver');
- }
-
- if (deletes.length) {
- values['delete'] = deletes.join(',');
- }
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
-
- var items = [
- {
- xtype: 'proxmoxtextfield',
- name: 'searchdomain',
- skipEmptyText: true,
- fieldLabel: gettext('DNS domain'),
- emptyText: gettext('use host settings'),
- allowBlank: true
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('DNS servers'),
- vtype: 'IP64AddressList',
- allowBlank: true,
- emptyText: gettext('use host settings'),
- name: 'nameserver',
- itemId: 'nameserver'
- }
- ];
-
- if (me.insideWizard) {
- me.column1 = items;
- } else {
- me.items = items;
- }
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.lxc.DNSEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- var ipanel = Ext.create('PVE.lxc.DNSInputPanel');
-
- Ext.apply(me, {
- subject: gettext('Resources'),
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
-
- if (values.nameserver) {
- values.nameserver.replace(/[,;]/, ' ');
- values.nameserver.replace(/^\s+/, '');
- }
-
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-
-/*jslint confusion: true */
-Ext.define('PVE.lxc.DNS', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveLxcDNS'],
-
- onlineHelp: 'pct_container_network',
-
- initComponent : function() {
- var me = this;
- var i;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var rows = {
- hostname: {
- required: true,
- defaultValue: me.pveSelNode.data.name,
- header: gettext('Hostname'),
- editor: caps.vms['VM.Config.Network'] ? {
- xtype: 'proxmoxWindowEdit',
- subject: gettext('Hostname'),
- items: {
- xtype: 'inputpanel',
- items:{
- fieldLabel: gettext('Hostname'),
- xtype: 'textfield',
- name: 'hostname',
- vtype: 'DnsName',
- allowBlank: true,
- emptyText: 'CT' + vmid.toString()
- },
- onGetValues: function(values) {
- var params = values;
- if (values.hostname === undefined ||
- values.hostname === null ||
- values.hostname === '') {
- params = { hostname: 'CT'+vmid.toString()};
- }
- return params;
- }
- }
- } : undefined
- },
- searchdomain: {
- header: gettext('DNS domain'),
- defaultValue: '',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
- renderer: function(value) {
- return value || gettext('use host settings');
- }
- },
- nameserver: {
- header: gettext('DNS server'),
- defaultValue: '',
- editor: caps.vms['VM.Config.Network'] ? 'PVE.lxc.DNSEdit' : undefined,
- renderer: function(value) {
- return value || gettext('use host settings');
- }
- }
- };
-
- var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
-
- var reload = function() {
- me.rstore.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var rowdef = rows[rec.data.key];
- if (!rowdef.editor) {
- return;
- }
-
- var win;
- if (Ext.isString(rowdef.editor)) {
- win = Ext.create(rowdef.editor, {
- pveSelNode: me.pveSelNode,
- confid: rec.data.key,
- url: '/api2/extjs/' + baseurl
- });
- } else {
- var config = Ext.apply({
- pveSelNode: me.pveSelNode,
- confid: rec.data.key,
- url: '/api2/extjs/' + baseurl
- }, rowdef.editor);
- win = Ext.createWidget(rowdef.editor.xtype, config);
- win.load();
- }
- //win.load();
- win.show();
- win.on('destroy', reload);
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- var rowdef = rows[rec.data.key];
- return !!rowdef.editor;
- },
- handler: run_editor
- });
-
- var set_button_status = function() {
- var sm = me.getSelectionModel();
- var rec = sm.getSelection()[0];
-
- if (!rec) {
- edit_btn.disable();
- return;
- }
- var rowdef = rows[rec.data.key];
- edit_btn.setDisabled(!rowdef.editor);
- };
-
- Ext.apply(me, {
- url: "/api2/json/nodes/" + nodename + "/lxc/" + vmid + "/config",
- selModel: sm,
- cwidth1: 150,
- run_editor: run_editor,
- tbar: [ edit_btn ],
- rows: rows,
- listeners: {
- itemdblclick: run_editor,
- selectionchange: set_button_status,
- activate: reload
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.lxc.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.lxc.Config',
-
- onlineHelp: 'chapter_pct',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var vmid = me.pveSelNode.data.vmid;
- if (!vmid) {
- throw "no VM ID specified";
- }
-
- var template = !!me.pveSelNode.data.template;
-
- var running = !!me.pveSelNode.data.uptime;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var base_url = '/nodes/' + nodename + '/lxc/' + vmid;
-
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: '/api2/json' + base_url + '/status/current',
- interval: 1000
- });
-
- var vm_command = function(cmd, params) {
- Proxmox.Utils.API2Request({
- params: params,
- url: base_url + "/status/" + cmd,
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- };
-
- var startBtn = Ext.create('Ext.Button', {
- text: gettext('Start'),
- disabled: !caps.vms['VM.PowerMgmt'] || running,
- hidden: template,
- handler: function() {
- vm_command('start');
- },
- iconCls: 'fa fa-play'
- });
-
- var stopBtn = Ext.create('Ext.menu.Item',{
- text: gettext('Stop'),
- disabled: !caps.vms['VM.PowerMgmt'],
- confirmMsg: Proxmox.Utils.format_task_description('vzstop', vmid),
- tooltip: Ext.String.format(gettext('Stop {0} immediately'), 'CT'),
- dangerous: true,
- handler: function() {
- vm_command("stop");
- },
- iconCls: 'fa fa-stop'
- });
-
- var shutdownBtn = Ext.create('PVE.button.Split', {
- text: gettext('Shutdown'),
- disabled: !caps.vms['VM.PowerMgmt'] || !running,
- hidden: template,
- confirmMsg: Proxmox.Utils.format_task_description('vzshutdown', vmid),
- handler: function() {
- vm_command('shutdown');
- },
- menu: {
- items:[stopBtn]
- },
- iconCls: 'fa fa-power-off'
- });
-
- var migrateBtn = Ext.create('Ext.Button', {
- text: gettext('Migrate'),
- disabled: !caps.vms['VM.Migrate'],
- hidden: PVE.data.ResourceStore.getNodes().length < 2,
- handler: function() {
- var win = Ext.create('PVE.window.Migrate', {
- vmtype: 'lxc',
- nodename: nodename,
- vmid: vmid
- });
- win.show();
- },
- iconCls: 'fa fa-send-o'
- });
-
- var moreBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('More'),
- menu: { items: [
- {
- text: gettext('Clone'),
- iconCls: 'fa fa-fw fa-clone',
- hidden: caps.vms['VM.Clone'] ? false : true,
- handler: function() {
- PVE.window.Clone.wrap(nodename, vmid, template, 'lxc');
- }
- },
- {
- text: gettext('Convert to template'),
- disabled: template,
- xtype: 'pveMenuItem',
- iconCls: 'fa fa-fw fa-file-o',
- hidden: caps.vms['VM.Allocate'] ? false : true,
- confirmMsg: Proxmox.Utils.format_task_description('vztemplate', vmid),
- handler: function() {
- Proxmox.Utils.API2Request({
- url: base_url + '/template',
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert('Error', response.htmlStatus);
- }
- });
- }
- },
- {
- iconCls: 'fa fa-heartbeat ',
- hidden: !caps.nodes['Sys.Console'],
- text: gettext('Manage HA'),
- handler: function() {
- var ha = me.pveSelNode.data.hastate;
- Ext.create('PVE.ha.VMResourceEdit', {
- vmid: vmid,
- guestType: 'ct',
- isCreate: (!ha || ha === 'unmanaged')
- }).show();
- }
- },
- {
- text: gettext('Remove'),
- disabled: !caps.vms['VM.Allocate'],
- itemId: 'removeBtn',
- handler: function() {
- Ext.create('PVE.window.SafeDestroy', {
- url: base_url,
- item: { type: 'CT', id: vmid }
- }).show();
- },
- iconCls: 'fa fa-trash-o'
- }
- ]}
- });
-
- var vm = me.pveSelNode.data;
-
- var consoleBtn = Ext.create('PVE.button.ConsoleButton', {
- disabled: !caps.vms['VM.Console'],
- consoleType: 'lxc',
- consoleName: vm.name,
- hidden: template,
- nodename: nodename,
- vmid: vmid
- });
-
- var statusTxt = Ext.create('Ext.toolbar.TextItem', {
- data: {
- lock: undefined
- },
- tpl: [
- '',
- ' ({lock})',
- ' '
- ]
- });
-
-
- Ext.apply(me, {
- title: Ext.String.format(gettext("Container {0} on node '{1}'"), vm.text, nodename),
- hstateid: 'lxctab',
- tbarSpacing: false,
- tbar: [ statusTxt, '->', startBtn, shutdownBtn, migrateBtn, consoleBtn, moreBtn ],
- defaults: { statusStore: me.statusStore },
- items: [
- {
- title: gettext('Summary'),
- xtype: 'pveLxcSummary',
- iconCls: 'fa fa-book',
- itemId: 'summary'
- }
- ]
- });
-
- if (caps.vms['VM.Console'] && !template) {
- me.items.push(
- {
- title: gettext('Console'),
- itemId: 'consolejs',
- iconCls: 'fa fa-terminal',
- xtype: 'pveNoVncConsole',
- vmid: vmid,
- consoleType: 'lxc',
- xtermjs: true,
- nodename: nodename
- }
- );
- }
-
- me.items.push(
- {
- title: gettext('Resources'),
- itemId: 'resources',
- expandedOnInit: true,
- iconCls: 'fa fa-cube',
- xtype: 'pveLxcRessourceView'
- },
- {
- title: gettext('Network'),
- iconCls: 'fa fa-exchange',
- itemId: 'network',
- xtype: 'pveLxcNetworkView'
- },
- {
- title: gettext('DNS'),
- iconCls: 'fa fa-globe',
- itemId: 'dns',
- xtype: 'pveLxcDNS'
- },
- {
- title: gettext('Options'),
- itemId: 'options',
- iconCls: 'fa fa-gear',
- xtype: 'pveLxcOptions'
- },
- {
- title: gettext('Task History'),
- itemId: 'tasks',
- iconCls: 'fa fa-list',
- xtype: 'proxmoxNodeTasks',
- nodename: nodename,
- vmidFilter: vmid
- }
- );
-
- if (caps.vms['VM.Backup']) {
- me.items.push({
- title: gettext('Backup'),
- iconCls: 'fa fa-floppy-o',
- xtype: 'pveBackupView',
- itemId: 'backup'
- },
- {
- title: gettext('Replication'),
- iconCls: 'fa fa-retweet',
- xtype: 'pveReplicaView',
- itemId: 'replication'
- });
- }
-
- if ((caps.vms['VM.Snapshot'] || caps.vms['VM.Snapshot.Rollback']) && !template) {
- me.items.push({
- title: gettext('Snapshots'),
- iconCls: 'fa fa-history',
- xtype: 'pveLxcSnapshotTree',
- itemId: 'snapshot'
- });
- }
-
- if (caps.vms['VM.Console']) {
- me.items.push(
- {
- xtype: 'pveFirewallRules',
- title: gettext('Firewall'),
- iconCls: 'fa fa-shield',
- allow_iface: true,
- base_url: base_url + '/firewall/rules',
- list_refs_url: base_url + '/firewall/refs',
- itemId: 'firewall'
- },
- {
- xtype: 'pveFirewallOptions',
- groups: ['firewall'],
- iconCls: 'fa fa-gear',
- onlineHelp: 'pve_firewall_vm_container_configuration',
- title: gettext('Options'),
- base_url: base_url + '/firewall/options',
- fwtype: 'vm',
- itemId: 'firewall-options'
- },
- {
- xtype: 'pveFirewallAliases',
- title: gettext('Alias'),
- groups: ['firewall'],
- iconCls: 'fa fa-external-link',
- base_url: base_url + '/firewall/aliases',
- itemId: 'firewall-aliases'
- },
- {
- xtype: 'pveIPSet',
- title: gettext('IPSet'),
- groups: ['firewall'],
- iconCls: 'fa fa-list-ol',
- base_url: base_url + '/firewall/ipset',
- list_refs_url: base_url + '/firewall/refs',
- itemId: 'firewall-ipset'
- },
- {
- title: gettext('Log'),
- groups: ['firewall'],
- iconCls: 'fa fa-list',
- onlineHelp: 'chapter_pve_firewall',
- itemId: 'firewall-fwlog',
- xtype: 'proxmoxLogView',
- url: '/api2/extjs' + base_url + '/firewall/log'
- }
- );
- }
-
- if (caps.vms['Permissions.Modify']) {
- me.items.push({
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- itemId: 'permissions',
- iconCls: 'fa fa-unlock',
- path: '/vms/' + vmid
- });
- }
-
- me.callParent();
-
- me.mon(me.statusStore, 'load', function(s, records, success) {
- var status;
- var lock;
- if (!success) {
- status = 'unknown';
- } else {
- var rec = s.data.get('status');
- status = rec ? rec.data.value : 'unknown';
- rec = s.data.get('template');
- template = rec.data.value || false;
- rec = s.data.get('lock');
- lock = rec ? rec.data.value : undefined;
- }
-
- statusTxt.update({ lock: lock });
-
- startBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 'running' || template);
- shutdownBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status !== 'running');
- stopBtn.setDisabled(!caps.vms['VM.PowerMgmt'] || status === 'stopped');
- me.down('#removeBtn').setDisabled(!caps.vms['VM.Allocate'] || status !== 'stopped');
- consoleBtn.setDisabled(template);
- });
-
- me.on('afterrender', function() {
- me.statusStore.startUpdate();
- });
-
- me.on('destroy', function() {
- me.statusStore.stopUpdate();
- });
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.lxc.CreateWizard', {
- extend: 'PVE.window.Wizard',
- mixins: ['Proxmox.Mixin.CBind'],
-
- viewModel: {
- data: {
- nodename: '',
- storage: '',
- unprivileged: true
- }
- },
-
- cbindData: {
- nodename: undefined
- },
-
- subject: gettext('LXC Container'),
-
- items: [
- {
- xtype: 'inputpanel',
- title: gettext('General'),
- onlineHelp: 'pct_general',
- column1: [
- {
- xtype: 'pveNodeSelector',
- name: 'nodename',
- cbind: {
- selectCurNode: '{!nodename}',
- preferredValue: '{nodename}'
- },
- bind: {
- value: '{nodename}'
- },
- fieldLabel: gettext('Node'),
- allowBlank: false,
- onlineValidator: true
- },
- {
- xtype: 'pveGuestIDSelector',
- name: 'vmid', // backend only knows vmid
- guestType: 'lxc',
- value: '',
- loadNextFreeID: true,
- validateExists: false
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'hostname',
- vtype: 'DnsName',
- value: '',
- fieldLabel: gettext('Hostname'),
- skipEmptyText: true,
- allowBlank: true
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'unprivileged',
- value: true,
- bind: {
- value: '{unprivileged}'
- },
- fieldLabel: gettext('Unprivileged container')
- }
- ],
- column2: [
- {
- xtype: 'pvePoolSelector',
- fieldLabel: gettext('Resource Pool'),
- name: 'pool',
- value: '',
- allowBlank: true
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- name: 'password',
- value: '',
- fieldLabel: gettext('Password'),
- allowBlank: false,
- minLength: 5,
- change: function(f, value) {
- if (f.rendered) {
- f.up().down('field[name=confirmpw]').validate();
- }
- }
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- name: 'confirmpw',
- value: '',
- fieldLabel: gettext('Confirm password'),
- allowBlank: true,
- submitValue: false,
- validator: function(value) {
- var pw = this.up().down('field[name=password]').getValue();
- if (pw !== value) {
- return "Passwords do not match!";
- }
- return true;
- }
- },
- {
- xtype: 'proxmoxtextfield',
- name: 'ssh-public-keys',
- value: '',
- fieldLabel: gettext('SSH public key'),
- allowBlank: true,
- validator: function(value) {
- var pwfield = this.up().down('field[name=password]');
- if (value.length) {
- var key = PVE.Parser.parseSSHKey(value);
- if (!key) {
- return "Failed to recognize ssh key";
- }
- pwfield.allowBlank = true;
- } else {
- pwfield.allowBlank = false;
- }
- pwfield.validate();
- return true;
- },
- afterRender: function() {
- if (!window.FileReader) {
- // No FileReader support in this browser
- return;
- }
- var cancel = function(ev) {
- ev = ev.event;
- if (ev.preventDefault) {
- ev.preventDefault();
- }
- };
- var field = this;
- field.inputEl.on('dragover', cancel);
- field.inputEl.on('dragenter', cancel);
- field.inputEl.on('drop', function(ev) {
- ev = ev.event;
- if (ev.preventDefault) {
- ev.preventDefault();
- }
- var files = ev.dataTransfer.files;
- PVE.Utils.loadSSHKeyFromFile(files[0], function(v) {
- field.setValue(v);
- });
- });
- }
- },
- {
- xtype: 'filebutton',
- name: 'file',
- hidden: !window.FileReader,
- text: gettext('Load SSH Key File'),
- listeners: {
- change: function(btn, e, value) {
- e = e.event;
- var field = this.up().down('proxmoxtextfield[name=ssh-public-keys]');
- PVE.Utils.loadSSHKeyFromFile(e.target.files[0], function(v) {
- field.setValue(v);
- });
- btn.reset();
- }
- }
- }
- ]
- },
- {
- xtype: 'inputpanel',
- title: gettext('Template'),
- onlineHelp: 'pct_container_images',
- column1: [
- {
- xtype: 'pveStorageSelector',
- name: 'tmplstorage',
- fieldLabel: gettext('Storage'),
- storageContent: 'vztmpl',
- autoSelect: true,
- allowBlank: false,
- bind: {
- value: '{storage}',
- nodename: '{nodename}'
- }
- },
- {
- xtype: 'pveFileSelector',
- name: 'ostemplate',
- storageContent: 'vztmpl',
- fieldLabel: gettext('Template'),
- bind: {
- storage: '{storage}',
- nodename: '{nodename}'
- },
- allowBlank: false
- }
- ]
- },
- {
- xtype: 'pveLxcMountPointInputPanel',
- title: gettext('Root Disk'),
- insideWizard: true,
- isCreate: true,
- unused: false,
- bind: {
- nodename: '{nodename}',
- unprivileged: '{unprivileged}'
- },
- confid: 'rootfs'
- },
- {
- xtype: 'pveLxcCPUInputPanel',
- title: gettext('CPU'),
- insideWizard: true
- },
- {
- xtype: 'pveLxcMemoryInputPanel',
- title: gettext('Memory'),
- insideWizard: true
- },
- {
- xtype: 'pveLxcNetworkInputPanel',
- title: gettext('Network'),
- insideWizard: true,
- bind: {
- nodename: '{nodename}'
- },
- isCreate: true
- },
- {
- xtype: 'pveLxcDNSInputPanel',
- title: gettext('DNS'),
- insideWizard: true
- },
- {
- title: gettext('Confirm'),
- layout: 'fit',
- items: [
- {
- xtype: 'grid',
- store: {
- model: 'KeyValue',
- sorters: [{
- property : 'key',
- direction: 'ASC'
- }]
- },
- columns: [
- {header: 'Key', width: 150, dataIndex: 'key'},
- {header: 'Value', flex: 1, dataIndex: 'value'}
- ]
- }
- ],
- dockedItems: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'start',
- dock: 'bottom',
- margin: '5 0 0 0',
- boxLabel: gettext('Start after created')
- }
- ],
- listeners: {
- show: function(panel) {
- var wizard = this.up('window');
- var kv = wizard.getValues();
- var data = [];
- Ext.Object.each(kv, function(key, value) {
- if (key === 'delete' || key === 'tmplstorage') { // ignore
- return;
- }
- if (key === 'password') { // don't show pw
- return;
- }
- var html = Ext.htmlEncode(Ext.JSON.encode(value));
- data.push({ key: key, value: value });
- });
-
- var summarystore = panel.down('grid').getStore();
- summarystore.suspendEvents();
- summarystore.removeAll();
- summarystore.add(data);
- summarystore.sort();
- summarystore.resumeEvents();
- summarystore.fireEvent('refresh');
- }
- },
- onSubmit: function() {
- var wizard = this.up('window');
- var kv = wizard.getValues();
- delete kv['delete'];
-
- var nodename = kv.nodename;
- delete kv.nodename;
- delete kv.tmplstorage;
-
- if (!kv.pool.length) {
- delete kv.pool;
- }
-
- if (!kv.password.length && kv['ssh-public-keys']) {
- delete kv.password;
- }
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/lxc',
- waitMsgTarget: wizard,
- method: 'POST',
- params: kv,
- success: function(response, opts){
- var upid = response.result.data;
-
- var win = Ext.create('Proxmox.window.TaskViewer', {
- upid: upid
- });
- win.show();
- wizard.close();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- }
- ]
-});
-
-
-
-Ext.define('PVE.lxc.SnapshotTree', {
- extend: 'Ext.tree.Panel',
- alias: ['widget.pveLxcSnapshotTree'],
-
- onlineHelp: 'pct_snapshots',
-
- load_delay: 3000,
-
- old_digest: 'invalid',
-
- stateful: true,
- stateId: 'grid-lxc-snapshots',
-
- sorterFn: function(rec1, rec2) {
- var v1 = rec1.data.snaptime;
- var v2 = rec2.data.snaptime;
-
- if (rec1.data.name === 'current') {
- return 1;
- }
- if (rec2.data.name === 'current') {
- return -1;
- }
-
- return (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
- },
-
- reload: function(repeat) {
- var me = this;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/snapshot',
- method: 'GET',
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, response.htmlStatus);
- me.load_task.delay(me.load_delay);
- },
- success: function(response, opts) {
- Proxmox.Utils.setErrorMask(me, false);
- var digest = 'invalid';
- var idhash = {};
- var root = { name: '__root', expanded: true, children: [] };
- Ext.Array.each(response.result.data, function(item) {
- item.leaf = true;
- item.children = [];
- if (item.name === 'current') {
- digest = item.digest + item.running;
- if (item.running) {
- item.iconCls = 'fa fa-fw fa-desktop x-fa-tree-running';
- } else {
- item.iconCls = 'fa fa-fw fa-desktop x-fa-tree';
- }
- } else {
- item.iconCls = 'fa fa-fw fa-history x-fa-tree';
- }
- idhash[item.name] = item;
- });
-
- if (digest !== me.old_digest) {
- me.old_digest = digest;
-
- Ext.Array.each(response.result.data, function(item) {
- if (item.parent && idhash[item.parent]) {
- var parent_item = idhash[item.parent];
- parent_item.children.push(item);
- parent_item.leaf = false;
- parent_item.expanded = true;
- parent_item.expandable = false;
- } else {
- root.children.push(item);
- }
- });
-
- me.setRootNode(root);
- }
-
- me.load_task.delay(me.load_delay);
- }
- });
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/feature',
- params: { feature: 'snapshot' },
- method: 'GET',
- success: function(response, options) {
- var res = response.result.data;
- if (res.hasFeature) {
- var snpBtns = Ext.ComponentQuery.query('#snapshotBtn');
- snpBtns.forEach(function(item){
- item.enable();
- });
- }
- }
- });
-
-
- },
-
- listeners: {
- beforestatesave: function(grid, state, eopts) {
- // extjs cannot serialize functions,
- // so a the sorter with only the sorterFn will
- // not be a valid sorter when restoring the state
- delete state.storeState.sorters;
- }
- },
-
- initComponent: function() {
- var me = this;
-
- me.nodename = me.pveSelNode.data.node;
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- me.vmid = me.pveSelNode.data.vmid;
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- me.load_task = new Ext.util.DelayedTask(me.reload, me);
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var valid_snapshot = function(record) {
- return record && record.data && record.data.name &&
- record.data.name !== 'current';
- };
-
- var valid_snapshot_rollback = function(record) {
- return record && record.data && record.data.name &&
- record.data.name !== 'current' && !record.data.snapstate;
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (valid_snapshot(rec)) {
- var win = Ext.create('PVE.window.LxcSnapshot', {
- snapname: rec.data.name,
- nodename: me.nodename,
- vmid: me.vmid
- });
- win.show();
- me.mon(win, 'close', me.reload, me);
- }
- };
-
- var editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- enableFn: valid_snapshot,
- handler: run_editor
- });
-
- var rollbackBtn = new Proxmox.button.Button({
- text: gettext('Rollback'),
- disabled: true,
- dangerous: true,
- selModel: sm,
- enableFn: valid_snapshot_rollback,
- confirmMsg: function(rec) {
- var taskdescription = Proxmox.Utils.format_task_description('vzrollback', me.vmid);
- var snaptime = Ext.Date.format(rec.data.snaptime,'Y-m-d H:i:s');
- var snapname = rec.data.name;
-
- var msg = Ext.String.format(gettext('{0} to {1} ({2})'),
- taskdescription, snapname, snaptime);
- msg += '' + gettext('Note: Rollback stops CT') + '
';
-
- return msg;
- },
- handler: function(btn, event) {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var snapname = rec.data.name;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/snapshot/' + snapname + '/rollback',
- method: 'POST',
- waitMsgTarget: me,
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- });
- }
- });
-
- var removeBtn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- confirmMsg: function(rec) {
- var msg = Ext.String.format(gettext('Are you sure you want to remove entry {0}'),
- "'" + rec.data.name + "'");
- return msg;
- },
- enableFn: valid_snapshot,
- handler: function(btn, event) {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var snapname = rec.data.name;
-
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/snapshot/' + snapname,
- method: 'DELETE',
- waitMsgTarget: me,
- callback: function() {
- me.reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- }
- });
- }
- });
-
- var snapshotBtn = Ext.create('Ext.Button', {
- itemId: 'snapshotBtn',
- text: gettext('Take Snapshot'),
- disabled: true,
- handler: function() {
- var win = Ext.create('PVE.window.LxcSnapshot', {
- nodename: me.nodename,
- vmid: me.vmid
- });
- win.show();
- }
- });
-
- Ext.apply(me, {
- layout: 'fit',
- rootVisible: false,
- animate: false,
- sortableColumns: false,
- selModel: sm,
- tbar: [ snapshotBtn, rollbackBtn, removeBtn, editBtn ],
- fields: [
- 'name', 'description', 'snapstate', 'vmstate', 'running',
- { name: 'snaptime', type: 'date', dateFormat: 'timestamp' }
- ],
- columns: [
- {
- xtype: 'treecolumn',
- text: gettext('Name'),
- dataIndex: 'name',
- width: 200,
- renderer: function(value, metaData, record) {
- if (value === 'current') {
- return "NOW";
- } else {
- return value;
- }
- }
- },
-// {
-// text: gettext('RAM'),
-// align: 'center',
-// resizable: false,
-// dataIndex: 'vmstate',
-// width: 50,
-// renderer: function(value, metaData, record) {
-// if (record.data.name !== 'current') {
-// return Proxmox.Utils.format_boolean(value);
-// }
-// }
-// },
- {
- text: gettext('Date') + "/" + gettext("Status"),
- dataIndex: 'snaptime',
- resizable: false,
- width: 150,
- renderer: function(value, metaData, record) {
- if (record.data.snapstate) {
- return record.data.snapstate;
- }
- if (value) {
- return Ext.Date.format(value,'Y-m-d H:i:s');
- }
- }
- },
- {
- text: gettext('Description'),
- dataIndex: 'description',
- flex: 1,
- renderer: function(value, metaData, record) {
- if (record.data.name === 'current') {
- return gettext("You are here!");
- } else {
- return Ext.String.htmlEncode(value);
- }
- }
- }
- ],
- columnLines: true,
- listeners: {
- activate: me.reload,
- destroy: me.load_task.cancel,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
-
- me.store.sorters.add(new Ext.util.Sorter({
- sorterFn: me.sorterFn
- }));
- }
-});
-Ext.define('PVE.window.LxcSnapshot', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- // needed for finding the reference to submitbutton
- // because we do not have a controller
- referenceHolder: true,
- defaultButton: 'submitbutton',
- defaultFocus: 'field',
-
- take_snapshot: function(snapname, descr, vmstate) {
- var me = this;
- var params = { snapname: snapname };
- if (descr) {
- params.description = descr;
- }
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot",
- waitMsgTarget: me,
- method: 'POST',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskProgress', { upid: upid });
- win.show();
- me.close();
- }
- });
- },
-
- update_snapshot: function(snapname, descr) {
- var me = this;
- Proxmox.Utils.API2Request({
- params: { description: descr },
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot/" +
- snapname + '/config',
- waitMsgTarget: me,
- method: 'PUT',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- me.close();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- var summarystore = Ext.create('Ext.data.Store', {
- model: 'KeyValue',
- sorters: [
- {
- property : 'key',
- direction: 'ASC'
- }
- ]
- });
-
- var items = [
- {
- xtype: me.snapname ? 'displayfield' : 'textfield',
- name: 'snapname',
- value: me.snapname,
- fieldLabel: gettext('Name'),
- vtype: 'ConfigId',
- allowBlank: false
- }
- ];
-
- if (me.snapname) {
- items.push({
- xtype: 'displayfield',
- name: 'snaptime',
- renderer: PVE.Utils.render_timestamp_human_readable,
- fieldLabel: gettext('Timestamp')
- });
- }
-
- items.push({
- xtype: 'textareafield',
- grow: true,
- name: 'description',
- fieldLabel: gettext('Description')
- });
-
- if (me.snapname) {
- items.push({
- title: gettext('Settings'),
- xtype: 'grid',
- height: 200,
- store: summarystore,
- columns: [
- {header: gettext('Key'), width: 150, dataIndex: 'key'},
- {header: gettext('Value'), flex: 1, dataIndex: 'value'}
- ]
- });
- }
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- if (me.snapname) {
- me.title = gettext('Edit') + ': ' + gettext('Snapshot');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Update'),
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.update_snapshot(me.snapname, values.description);
- }
- }
- });
- } else {
- me.title ="VM " + me.vmid + ': ' + gettext('Take Snapshot');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Take Snapshot'),
- reference: 'submitbutton',
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.take_snapshot(values.snapname, values.description);
- }
- }
- });
- }
-
- Ext.apply(me, {
- modal: true,
- width: 450,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
- if (me.snapname) {
- Ext.apply(me, {
- width: 620,
- height: 420
- });
- }
-
- me.callParent();
-
- if (!me.snapname) {
- return;
- }
-
- // else load data
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + "/snapshot/" +
- me.snapname + '/config',
- waitMsgTarget: me,
- method: 'GET',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- me.close();
- },
- success: function(response, options) {
- var data = response.result.data;
- var kvarray = [];
- Ext.Object.each(data, function(key, value) {
- if (key === 'description' || key === 'snaptime') {
- return;
- }
- kvarray.push({ key: key, value: value });
- });
-
- summarystore.suspendEvents();
- summarystore.add(kvarray);
- summarystore.sort();
- summarystore.resumeEvents();
- summarystore.fireEvent('refresh', summarystore);
-
- form.findField('snaptime').setValue(data.snaptime);
- form.findField('description').setValue(data.description);
- }
- });
- }
-});
-/*jslint confusion: true */
-var labelWidth = 120;
-
-Ext.define('PVE.lxc.MemoryEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.apply(me, {
- subject: gettext('Memory'),
- items: Ext.create('PVE.lxc.MemoryInputPanel')
- });
-
- me.callParent();
-
- me.load();
- }
-});
-
-
-Ext.define('PVE.lxc.CPUEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- Ext.apply(me, {
- subject: gettext('CPU'),
- items: Ext.create('PVE.lxc.CPUInputPanel')
- });
-
- me.callParent();
-
- me.load();
- }
-});
-
-Ext.define('PVE.lxc.CPUInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveLxcCPUInputPanel',
-
- onlineHelp: 'pct_cpu',
-
- insideWizard: false,
-
- onGetValues: function(values) {
- var me = this;
-
- PVE.Utils.delete_if_default(values, 'cores', '', me.insideWizard);
- // cpu{limit,unit} aren't in the wizard so create is always false
- PVE.Utils.delete_if_default(values, 'cpulimit', '0', 0);
- PVE.Utils.delete_if_default(values, 'cpuunits', '1024', 0);
-
- return values;
- },
-
- advancedColumn1: [
- {
- xtype: 'numberfield',
- name: 'cpulimit',
- minValue: 0,
- value: '',
- step: 1,
- fieldLabel: gettext('CPU limit'),
- allowBlank: true,
- emptyText: gettext('unlimited')
- }
- ],
-
- advancedColumn2: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'cpuunits',
- fieldLabel: gettext('CPU units'),
- value: 1024,
- minValue: 8,
- maxValue: 500000,
- labelWidth: labelWidth,
- allowBlank: false
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: 'proxmoxintegerfield',
- name: 'cores',
- minValue: 1,
- maxValue: 128,
- value: me.insideWizard ? 1 : '',
- fieldLabel: gettext('Cores'),
- allowBlank: true,
- deleteEmpty: true,
- emptyText: gettext('unlimited')
- }
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.lxc.MemoryInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- alias: 'widget.pveLxcMemoryInputPanel',
-
- onlineHelp: 'pct_memory',
-
- insideWizard: false,
-
- initComponent : function() {
- var me = this;
-
- var items = [
- {
- xtype: 'proxmoxintegerfield',
- name: 'memory',
- minValue: 16,
- value: '512',
- step: 32,
- fieldLabel: gettext('Memory') + ' (MiB)',
- labelWidth: labelWidth,
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'swap',
- minValue: 0,
- value: '512',
- step: 32,
- fieldLabel: gettext('Swap') + ' (MiB)',
- labelWidth: labelWidth,
- allowBlank: false
- }
- ];
-
- if (me.insideWizard) {
- me.column1 = items;
- } else {
- me.items = items;
- }
-
- me.callParent();
- }
-});
-Ext.define('PVE.window.MPResize', {
- extend: 'Ext.window.Window',
-
- resizable: false,
-
- resize_disk: function(disk, size) {
- var me = this;
- var params = { disk: disk, size: '+' + size + 'G' };
-
- Proxmox.Utils.API2Request({
- params: params,
- url: '/nodes/' + me.nodename + '/lxc/' + me.vmid + '/resize',
- waitMsgTarget: me,
- method: 'PUT',
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, opts) {
- var upid = response.result.data;
- var win = Ext.create('Proxmox.window.TaskViewer', { upid: upid });
- win.show();
- me.close();
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.vmid) {
- throw "no VM ID specified";
- }
-
- var items = [
- {
- xtype: 'displayfield',
- name: 'disk',
- value: me.disk,
- fieldLabel: gettext('Disk'),
- vtype: 'StorageId',
- allowBlank: false
- }
- ];
-
- me.hdsizesel = Ext.createWidget('numberfield', {
- name: 'size',
- minValue: 0,
- maxValue: 128*1024,
- decimalPrecision: 3,
- value: '0',
- fieldLabel: gettext('Size Increment') + ' (GiB)',
- allowBlank: false
- });
-
- items.push(me.hdsizesel);
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- bodyPadding: 10,
- border: false,
- fieldDefaults: {
- labelWidth: 120,
- anchor: '100%'
- },
- items: items
- });
-
- var form = me.formPanel.getForm();
-
- var submitBtn;
-
- me.title = gettext('Resize disk');
- submitBtn = Ext.create('Ext.Button', {
- text: gettext('Resize disk'),
- handler: function() {
- if (form.isValid()) {
- var values = form.getValues();
- me.resize_disk(me.disk, values.size);
- }
- }
- });
-
- Ext.apply(me, {
- modal: true,
- border: false,
- layout: 'fit',
- buttons: [ submitBtn ],
- items: [ me.formPanel ]
- });
-
-
- me.callParent();
-
- if (!me.disk) {
- return;
- }
-
- }
-});
-/*jslint confusion: true*/
-/* hidden: boolean and string
- * bind: function and object
- * disabled: boolean and string
- */
-Ext.define('PVE.lxc.MountPointInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- xtype: 'pveLxcMountPointInputPanel',
-
- insideWizard: false,
-
- onlineHelp: 'pct_container_storage',
-
- unused: false, // add unused disk imaged
-
- unprivileged: false,
-
- vmconfig: {}, // used to select unused disks
-
- setUnprivileged: function(unprivileged) {
- var me = this;
- var vm = me.getViewModel();
- me.unprivileged = unprivileged;
- vm.set('unpriv', unprivileged);
- },
-
- onGetValues: function(values) {
- var me = this;
-
- var confid = me.confid || "mp"+values.mpid;
- values.file = me.down('field[name=file]').getValue();
- if (values.mountoptions) {
- values.mountoptions = values.mountoptions.join(';');
- }
-
- if (me.unused) {
- confid = "mp"+values.mpid;
- } else if (me.isCreate) {
- values.file = values.hdstorage + ':' + values.disksize;
- }
-
- // delete unnecessary fields
- delete values.mpid;
- delete values.hdstorage;
- delete values.disksize;
- delete values.diskformat;
-
- var res = {};
- res[confid] = PVE.Parser.printLxcMountPoint(values);
- return res;
- },
-
-
- setMountPoint: function(mp) {
- var me = this;
- var vm = this.getViewModel();
- vm.set('mptype', mp.type);
- if (mp.mountoptions) {
- mp.mountoptions = mp.mountoptions.split(';');
- }
-
- if (this.confid === 'rootfs') {
- var field = me.down('field[name=mountoptions]');
- var forbidden = ['nodev', 'noexec'];
- var filtered = field.comboItems.filter(e => !forbidden.includes(e[0]));
- field.setComboItems(filtered);
- }
-
- me.setValues(mp);
- },
-
- setVMConfig: function(vmconfig) {
- var me = this;
- var vm = me.getViewModel();
- me.vmconfig = vmconfig;
- vm.set('unpriv', vmconfig.unprivileged);
-
- PVE.Utils.forEachMP(function(bus, i) {
- var name = "mp" + i.toString();
- if (!Ext.isDefined(vmconfig[name])) {
- me.down('field[name=mpid]').setValue(i);
- return false;
- }
- });
- },
-
- setNodename: function(nodename) {
- var me = this;
- var vm = me.getViewModel();
- vm.set('node', nodename);
- me.down('#diskstorage').setNodename(nodename);
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- control: {
- 'field[name=mpid]': {
- change: function(field, value) {
- field.validate();
- }
- },
- '#hdstorage': {
- change: function(field, newValue) {
- var me = this;
- if (!newValue) {
- return;
- }
-
- var rec = field.store.getById(newValue);
- if (!rec) {
- return;
- }
-
- var vm = me.getViewModel();
- vm.set('type', rec.data.type);
- }
- }
- },
-
- init: function(view) {
- var me = this;
- var vm = this.getViewModel();
- vm.set('confid', view.confid);
- vm.set('unused', view.unused);
- vm.set('node', view.nodename);
- vm.set('unpriv', view.unprivileged);
- vm.set('hideStorSelector', view.unused || !view.isCreate);
- }
- },
-
- viewModel: {
- data: {
- unpriv: false,
- unused: false,
- showStorageSelector: false,
- mptype: '',
- type: '',
- confid: '',
- node: ''
- },
-
- formulas: {
- quota: function(get) {
- return !(get('type') === 'zfs' ||
- get('type') === 'zfspool' ||
- get('unpriv') ||
- get('isBind'));
- },
- hasMP: function(get) {
- return !!get('confid') && !get('unused');
- },
- isRoot: function(get) {
- return get('confid') === 'rootfs';
- },
- isBind: function(get) {
- return get('mptype') === 'bind';
- },
- isBindOrRoot: function(get) {
- return get('isBind') || get('isRoot');
- }
- }
- },
-
- column1: [
- {
- xtype: 'proxmoxintegerfield',
- name: 'mpid',
- fieldLabel: gettext('Mount Point ID'),
- minValue: 0,
- maxValue: PVE.Utils.mp_counts.mps - 1,
- hidden: true,
- allowBlank: false,
- disabled: true,
- bind: {
- hidden: '{hasMP}',
- disabled: '{hasMP}'
- },
- validator: function(value) {
- var me = this.up('inputpanel');
- if (!me.rendered) {
- return;
- }
- if (Ext.isDefined(me.vmconfig["mp"+value])) {
- return "Mount point is already in use.";
- }
- /*jslint confusion: true*/
- /* returns a string above */
- return true;
- }
- },
- {
- xtype: 'pveDiskStorageSelector',
- itemId: 'diskstorage',
- storageContent: 'rootdir',
- hidden: true,
- autoSelect: true,
- selectformat: false,
- defaultSize: 8,
- bind: {
- hidden: '{hideStorSelector}',
- disabled: '{hideStorSelector}',
- nodename: '{node}'
- }
- },
- {
- xtype: 'textfield',
- disabled: true,
- submitValue: false,
- fieldLabel: gettext('Disk image'),
- name: 'file',
- bind: {
- hidden: '{!hideStorSelector}'
- }
- }
- ],
-
- column2: [
- {
- xtype: 'textfield',
- name: 'mp',
- value: '',
- emptyText: gettext('/some/path'),
- allowBlank: false,
- disabled: true,
- fieldLabel: gettext('Path'),
- bind: {
- hidden: '{isRoot}',
- disabled: '{isRoot}'
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'backup',
- fieldLabel: gettext('Backup'),
- bind: {
- hidden: '{isRoot}',
- disabled: '{isBindOrRoot}'
- }
- }
- ],
-
- advancedColumn1: [
- {
- xtype: 'proxmoxcheckbox',
- name: 'quota',
- defaultValue: 0,
- bind: {
- disabled: '{!quota}'
- },
- fieldLabel: gettext('Enable quota'),
- listeners: {
- disable: function() {
- this.reset();
- }
- }
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'ro',
- defaultValue: 0,
- bind: {
- hidden: '{isRoot}',
- disabled: '{isRoot}'
- },
- fieldLabel: gettext('Read-only')
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'mountoptions',
- fieldLabel: gettext('Mount options'),
- deleteEmpty: false,
- comboItems: [
- ['noatime', 'noatime'],
- ['nodev', 'nodev'],
- ['noexec', 'noexec'],
- ['nosuid', 'nosuid']
- ],
- multiSelect: true,
- value: [],
- allowBlank: true
- },
- ],
-
- advancedColumn2: [
- {
- xtype: 'proxmoxKVComboBox',
- name: 'acl',
- fieldLabel: 'ACLs',
- deleteEmpty: false,
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText],
- ['1', Proxmox.Utils.enabledText],
- ['0', Proxmox.Utils.disabledText]
- ],
- value: '__default__',
- bind: {
- disabled: '{isBind}'
- },
- allowBlank: true
- },
- {
- xtype: 'proxmoxcheckbox',
- inputValue: '0', // reverses the logic
- name: 'replicate',
- fieldLabel: gettext('Skip replication')
- }
- ]
-});
-
-Ext.define('PVE.lxc.MountPointEdit', {
- extend: 'Proxmox.window.Edit',
-
- unprivileged: false,
-
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var unused = me.confid && me.confid.match(/^unused\d+$/);
-
- me.isCreate = me.confid ? unused : true;
-
- var ipanel = Ext.create('PVE.lxc.MountPointInputPanel', {
- confid: me.confid,
- nodename: nodename,
- unused: unused,
- unprivileged: me.unprivileged,
- isCreate: me.isCreate
- });
-
- var subject;
- if (unused) {
- subject = gettext('Unused Disk');
- } else if (me.isCreate) {
- subject = gettext('Mount Point');
- } else {
- subject = gettext('Mount Point') + ' (' + me.confid + ')';
- }
-
- Ext.apply(me, {
- subject: subject,
- defaultFocus: me.confid !== 'rootfs' ? 'textfield[name=mp]' : 'tool',
- items: ipanel
- });
-
- me.callParent();
-
- me.load({
- success: function(response, options) {
- ipanel.setVMConfig(response.result.data);
- if (me.confid) {
- /*jslint confusion: true*/
- /*data is defined as array above*/
- var value = response.result.data[me.confid];
- /*jslint confusion: false*/
- var mp = PVE.Parser.parseLxcMountPoint(value);
-
- if (!mp) {
- Ext.Msg.alert(gettext('Error'), 'Unable to parse mount point options');
- me.close();
- return;
- }
-
- ipanel.setMountPoint(mp);
- me.isValid(); // trigger validation
- }
- }
- });
- }
-});
-Ext.define('PVE.pool.StatusView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pvePoolStatusView'],
- disabled: true,
-
- title: gettext('Status'),
- cwidth1: 150,
- interval: 30000,
- //height: 195,
- initComponent : function() {
- var me = this;
-
- var pool = me.pveSelNode.data.pool;
- if (!pool) {
- throw "no pool specified";
- }
-
- var rows = {
- comment: {
- header: gettext('Comment'),
- renderer: Ext.String.htmlEncode,
- required: true
- }
- };
-
- Ext.apply(me, {
- url: "/api2/json/pools/" + pool,
- rows: rows
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.pool.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pvePoolSummary',
-
- initComponent: function() {
- var me = this;
-
- var pool = me.pveSelNode.data.pool;
- if (!pool) {
- throw "no pool specified";
- }
-
- var statusview = Ext.create('PVE.pool.StatusView', {
- pveSelNode: me.pveSelNode,
- style: 'padding-top:0px'
- });
-
- var rstore = statusview.rstore;
-
- Ext.apply(me, {
- autoScroll: true,
- bodyStyle: 'padding:10px',
- defaults: {
- style: 'padding-top:10px',
- width: 800
- },
- items: [ statusview ]
- });
-
- me.on('activate', rstore.startUpdate);
- me.on('destroy', rstore.stopUpdate);
-
- me.callParent();
- }
-});
-Ext.define('PVE.pool.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.pvePoolConfig',
-
- onlineHelp: 'pveum_pools',
-
- initComponent: function() {
- var me = this;
-
- var pool = me.pveSelNode.data.pool;
- if (!pool) {
- throw "no pool specified";
- }
-
- Ext.apply(me, {
- title: Ext.String.format(gettext("Resource Pool") + ': ' + pool),
- hstateid: 'pooltab',
- items: [
- {
- title: gettext('Summary'),
- iconCls: 'fa fa-book',
- xtype: 'pvePoolSummary',
- itemId: 'summary'
- },
- {
- title: gettext('Members'),
- xtype: 'pvePoolMembers',
- iconCls: 'fa fa-th',
- pool: pool,
- itemId: 'members'
- },
- {
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- iconCls: 'fa fa-unlock',
- itemId: 'permissions',
- path: '/pool/' + pool
- }
- ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.panel.StorageBase', {
- extend: 'Proxmox.panel.InputPanel',
- controller: 'storageEdit',
-
- type: '',
-
- onGetValues: function(values) {
- var me = this;
-
- if (me.isCreate) {
- values.type = me.type;
- } else {
- delete values.storage;
- }
-
- values.disable = values.enable ? 0 : 1;
- delete values.enable;
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
-
- me.column1.unshift({
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'storage',
- value: me.storageId || '',
- fieldLabel: 'ID',
- vtype: 'StorageId',
- allowBlank: false
- });
-
- me.column2.unshift(
- {
- xtype: 'pveNodeSelector',
- name: 'nodes',
- disabled: me.storageId === 'local',
- fieldLabel: gettext('Nodes'),
- emptyText: gettext('All') + ' (' + gettext('No restrictions') +')',
- multiSelect: true,
- autoSelect: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'enable',
- checked: true,
- uncheckedValue: 0,
- fieldLabel: gettext('Enable')
- }
- );
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.BaseEdit', {
- extend: 'Proxmox.window.Edit',
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.storageId;
-
- if (me.isCreate) {
- me.url = '/api2/extjs/storage';
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs/storage/' + me.storageId;
- me.method = 'PUT';
- }
-
- var ipanel = Ext.create(me.paneltype, {
- type: me.type,
- isCreate: me.isCreate,
- storageId: me.storageId
- });
-
- Ext.apply(me, {
- subject: PVE.Utils.format_storage_type(me.type),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
- var ctypes = values.content || '';
-
- values.content = ctypes.split(',');
-
- if (values.nodes) {
- values.nodes = values.nodes.split(',');
- }
- values.enable = values.disable ? 0 : 1;
-
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-Ext.define('PVE.grid.TemplateSelector', {
- extend: 'Ext.grid.GridPanel',
-
- alias: 'widget.pveTemplateSelector',
-
- stateful: true,
- stateId: 'grid-template-selector',
- viewConfig: {
- trackOver: false
- },
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- var baseurl = "/nodes/" + me.nodename + "/aplinfo";
- var store = new Ext.data.Store({
- model: 'pve-aplinfo',
- groupField: 'section',
- proxy: {
- type: 'proxmox',
- url: '/api2/json' + baseurl
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
- groupHeaderTpl: '{[ "Section: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
- });
-
- var reload = function() {
- store.load();
- };
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- '->',
- gettext('Search'),
- {
- xtype: 'textfield',
- width: 200,
- enableKeyEvents: true,
- listeners: {
- buffer: 500,
- keyup: function(field) {
- var value = field.getValue().toLowerCase();
- store.clearFilter(true);
- store.filterBy(function(rec) {
- return (rec.data['package'].toLowerCase().indexOf(value) !== -1)
- || (rec.data.headline.toLowerCase().indexOf(value) !== -1);
- });
- }
- }
- }
- ],
- features: [ groupingFeature ],
- columns: [
- {
- header: gettext('Type'),
- width: 80,
- dataIndex: 'type'
- },
- {
- header: gettext('Package'),
- flex: 1,
- dataIndex: 'package'
- },
- {
- header: gettext('Version'),
- width: 80,
- dataIndex: 'version'
- },
- {
- header: gettext('Description'),
- flex: 1.5,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'headline'
- }
- ],
- listeners: {
- afterRender: reload
- }
- });
-
- me.callParent();
- }
-
-}, function() {
-
- Ext.define('pve-aplinfo', {
- extend: 'Ext.data.Model',
- fields: [
- 'template', 'type', 'package', 'version', 'headline', 'infopage',
- 'description', 'os', 'section'
- ],
- idProperty: 'template'
- });
-
-});
-
-Ext.define('PVE.storage.TemplateDownload', {
- extend: 'Ext.window.Window',
- alias: 'widget.pveTemplateDownload',
-
- modal: true,
- title: gettext('Templates'),
- layout: 'fit',
- width: 900,
- height: 600,
- initComponent : function() {
- /*jslint confusion: true */
- var me = this;
-
- var grid = Ext.create('PVE.grid.TemplateSelector', {
- border: false,
- scrollable: true,
- nodename: me.nodename
- });
-
- var sm = grid.getSelectionModel();
-
- var submitBtn = Ext.create('Proxmox.button.Button', {
- text: gettext('Download'),
- disabled: true,
- selModel: sm,
- handler: function(button, event, rec) {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + me.nodename + '/aplinfo',
- params: {
- storage: me.storage,
- template: rec.data.template
- },
- method: 'POST',
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response, options) {
- var upid = response.result.data;
-
- Ext.create('Proxmox.window.TaskViewer', {
- upid: upid,
- listeners: {
- destroy: me.reloadGrid
- }
- }).show();
-
- me.close();
- }
- });
- }
- });
-
- Ext.apply(me, {
- items: grid,
- buttons: [ submitBtn ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.Upload', {
- extend: 'Ext.window.Window',
- alias: 'widget.pveStorageUpload',
-
- resizable: false,
-
- modal: true,
-
- initComponent : function() {
- /*jslint confusion: true */
- var me = this;
-
- var xhr;
-
- if (!me.nodename) {
- throw "no node name specified";
- }
-
- if (!me.storage) {
- throw "no storage ID specified";
- }
-
- var baseurl = "/nodes/" + me.nodename + "/storage/" + me.storage + "/upload";
-
- var pbar = Ext.create('Ext.ProgressBar', {
- text: 'Ready',
- hidden: true
- });
-
- me.formPanel = Ext.create('Ext.form.Panel', {
- method: 'POST',
- waitMsgTarget: true,
- bodyPadding: 10,
- border: false,
- width: 300,
- fieldDefaults: {
- labelWidth: 100,
- anchor: '100%'
- },
- items: [
- {
- xtype: 'pveContentTypeSelector',
- cts: me.contents,
- fieldLabel: gettext('Content'),
- name: 'content',
- value: me.contents[0] || '',
- allowBlank: false
- },
- {
- xtype: 'filefield',
- name: 'filename',
- buttonText: gettext('Select File...'),
- allowBlank: false
- },
- pbar
- ]
- });
-
- var form = me.formPanel.getForm();
-
- var doStandardSubmit = function() {
- form.submit({
- url: "/api2/htmljs" + baseurl,
- waitMsg: gettext('Uploading file...'),
- success: function(f, action) {
- me.close();
- },
- failure: function(f, action) {
- var msg = PVE.Utils.extractFormActionError(action);
- Ext.Msg.alert(gettext('Error'), msg);
- }
- });
- };
-
- var updateProgress = function(per, bytes) {
- var text = (per * 100).toFixed(2) + '%';
- if (bytes) {
- text += " (" + Proxmox.Utils.format_size(bytes) + ')';
- }
- pbar.updateProgress(per, text);
- };
-
- var abortBtn = Ext.create('Ext.Button', {
- text: gettext('Abort'),
- disabled: true,
- handler: function() {
- me.close();
- }
- });
-
- var submitBtn = Ext.create('Ext.Button', {
- text: gettext('Upload'),
- disabled: true,
- handler: function(button) {
- var fd;
- try {
- fd = new FormData();
- } catch (err) {
- doStandardSubmit();
- return;
- }
-
- button.setDisabled(true);
- abortBtn.setDisabled(false);
-
- var field = form.findField('content');
- fd.append("content", field.getValue());
- field.setDisabled(true);
-
- field = form.findField('filename');
- var file = field.fileInputEl.dom;
- fd.append("filename", file.files[0]);
- field.setDisabled(true);
-
- pbar.setVisible(true);
- updateProgress(0);
-
- xhr = new XMLHttpRequest();
-
- xhr.addEventListener("load", function(e) {
- if (xhr.status == 200) {
- me.close();
- } else {
- var msg = gettext('Error') + " " + xhr.status.toString() + ": " + Ext.htmlEncode(xhr.statusText);
- if (xhr.responseText !== "") {
- var result = Ext.decode(xhr.responseText);
- result.message = msg;
- msg = Proxmox.Utils.extractRequestError(result, true);
- }
- Ext.Msg.alert(gettext('Error'), msg, function(btn) {
- me.close();
- });
- }
- }, false);
-
- xhr.addEventListener("error", function(e) {
- var msg = "Error " + e.target.status.toString() + " occurred while receiving the document.";
- Ext.Msg.alert(gettext('Error'), msg, function(btn) {
- me.close();
- });
- });
-
- xhr.upload.addEventListener("progress", function(evt) {
- if (evt.lengthComputable) {
- var percentComplete = evt.loaded / evt.total;
- updateProgress(percentComplete, evt.loaded);
- }
- }, false);
-
- xhr.open("POST", "/api2/json" + baseurl, true);
- xhr.send(fd);
- }
- });
-
- form.on('validitychange', function(f, valid) {
- submitBtn.setDisabled(!valid);
- });
-
- Ext.apply(me, {
- title: gettext('Upload'),
- items: me.formPanel,
- buttons: [ abortBtn, submitBtn ],
- listeners: {
- close: function() {
- if (xhr) {
- xhr.abort();
- }
- }
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.ContentView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: 'widget.pveStorageContentView',
-
- stateful: true,
- stateId: 'grid-storage-content',
- viewConfig: {
- trackOver: false,
- loadMask: false
- },
- features: [
- {
- ftype: 'grouping',
- groupHeaderTpl: '{name} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
- }
- ],
- initComponent : function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var storage = me.pveSelNode.data.storage;
- if (!storage) {
- throw "no storage ID specified";
- }
-
- var baseurl = "/nodes/" + nodename + "/storage/" + storage + "/content";
- var store = Ext.create('Ext.data.Store',{
- model: 'pve-storage-content',
- groupField: 'content',
- proxy: {
- type: 'proxmox',
- url: '/api2/json' + baseurl
- },
- sorters: {
- property: 'volid',
- order: 'DESC'
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- store.load();
- me.statusStore.load();
- };
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- var templateButton = Ext.create('Proxmox.button.Button',{
- itemId: 'tmpl-btn',
- text: gettext('Templates'),
- handler: function() {
- var win = Ext.create('PVE.storage.TemplateDownload', {
- nodename: nodename,
- storage: storage,
- reloadGrid: reload
- });
- win.show();
- }
- });
-
- var uploadButton = Ext.create('Proxmox.button.Button', {
- contents : ['iso','vztmpl'],
- text: gettext('Upload'),
- handler: function() {
- var me = this;
- var win = Ext.create('PVE.storage.Upload', {
- nodename: nodename,
- storage: storage,
- contents: me.contents
- });
- win.show();
- win.on('destroy', reload);
- }
- });
-
- var imageRemoveButton;
- var removeButton = Ext.create('Proxmox.button.StdRemoveButton',{
- selModel: sm,
- enableFn: function(rec) {
- if (rec && rec.data.content !== 'images') {
- imageRemoveButton.setVisible(false);
- removeButton.setVisible(true);
- return true;
- }
- return false;
- },
- callback: function() {
- reload();
- },
- baseurl: baseurl + '/'
- });
-
- imageRemoveButton = Ext.create('Proxmox.button.Button',{
- selModel: sm,
- hidden: true,
- text: gettext('Remove'),
- enableFn: function(rec) {
- if (rec && rec.data.content === 'images') {
- removeButton.setVisible(false);
- imageRemoveButton.setVisible(true);
- return true;
- }
- return false;
- },
- handler: function(btn, event, rec) {
- me = this;
-
- var url = baseurl + '/' + rec.data.volid;
- var vmid = rec.data.vmid;
-
- var store = PVE.data.ResourceStore;
-
- if (vmid && store.findVMID(vmid)) {
- var guest_node = store.guestNode(vmid);
- var storage_path = 'storage/' + nodename + '/' + storage;
-
- // allow to delete local backed images if a VMID exists on another node.
- if (store.storageIsShared(storage_path) || guest_node == nodename) {
- var msg = Ext.String.format(
- gettext("Cannot remove image, a guest with VMID '{0}' exists!"), vmid);
- msg += ' ' + gettext("You can delete the image from the guest's hardware pane");
-
- Ext.Msg.show({
- title: gettext('Cannot remove disk image.'),
- icon: Ext.Msg.ERROR,
- msg: msg
- });
- return;
- }
- }
- var win = Ext.create('PVE.window.SafeDestroy', {
- title: Ext.String.format(gettext("Destroy '{0}'"), rec.data.volid),
- showProgress: true,
- url: url,
- item: { type: 'Image', id: vmid }
- }).show();
- win.on('destroy', function() {
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: '/api2/json/nodes/' + nodename + '/storage/' + storage + '/status'
- });
- reload();
-
- });
- }
- });
-
- me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
- url: '/api2/json/nodes/' + nodename + '/storage/' + storage + '/status'
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- {
- xtype: 'proxmoxButton',
- text: gettext('Restore'),
- selModel: sm,
- disabled: true,
- enableFn: function(rec) {
- return rec && rec.data.content === 'backup';
- },
- handler: function(b, e, rec) {
- var vmtype;
- if (rec.data.volid.match(/vzdump-qemu-/)) {
- vmtype = 'qemu';
- } else if (rec.data.volid.match(/vzdump-openvz-/) || rec.data.volid.match(/vzdump-lxc-/)) {
- vmtype = 'lxc';
- } else {
- return;
- }
-
- var win = Ext.create('PVE.window.Restore', {
- nodename: nodename,
- volid: rec.data.volid,
- volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
- vmtype: vmtype
- });
- win.show();
- win.on('destroy', reload);
- }
- },
- removeButton,
- imageRemoveButton,
- templateButton,
- uploadButton,
- {
- xtype: 'proxmoxButton',
- text: gettext('Show Configuration'),
- disabled: true,
- selModel: sm,
- enableFn: function(rec) {
- return rec && rec.data.content === 'backup';
- },
- handler: function(b,e,rec) {
- var win = Ext.create('PVE.window.BackupConfig', {
- volume: rec.data.volid,
- pveSelNode: me.pveSelNode
- });
-
- win.show();
- }
- },
- '->',
- gettext('Search') + ':', ' ',
- {
- xtype: 'textfield',
- width: 200,
- enableKeyEvents: true,
- listeners: {
- buffer: 500,
- keyup: function(field) {
- store.clearFilter(true);
- store.filter([
- {
- property: 'text',
- value: field.getValue(),
- anyMatch: true,
- caseSensitive: false
- }
- ]);
- }
- }
- }
- ],
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- renderer: PVE.Utils.render_storage_content,
- dataIndex: 'text'
- },
- {
- header: gettext('Format'),
- width: 100,
- dataIndex: 'format'
- },
- {
- header: gettext('Type'),
- width: 100,
- dataIndex: 'content',
- renderer: PVE.Utils.format_content_types
- },
- {
- header: gettext('Size'),
- width: 100,
- renderer: Proxmox.Utils.format_size,
- dataIndex: 'size'
- }
- ],
- listeners: {
- activate: reload
- }
- });
-
- me.callParent();
-
- // disable the buttons/restrict the upload window
- // if templates or uploads are not allowed
- me.mon(me.statusStore, 'load', function(s, records, success) {
- var availcontent = [];
- Ext.Array.each(records, function(item){
- if (item.id === 'content') {
- availcontent = item.data.value.split(',');
- }
- });
- var templ = false;
- var upload = false;
- var cts = [];
-
- Ext.Array.each(availcontent, function(content) {
- if (content === 'vztmpl') {
- templ = true;
- cts.push('vztmpl');
- } else if (content === 'iso') {
- upload = true;
- cts.push('iso');
- }
- });
-
- if (templ !== upload) {
- uploadButton.contents = cts;
- }
-
- templateButton.setDisabled(!templ);
- uploadButton.setDisabled(!upload && !templ);
- });
- }
-}, function() {
-
- Ext.define('pve-storage-content', {
- extend: 'Ext.data.Model',
- fields: [
- 'volid', 'content', 'format', 'size', 'used', 'vmid',
- 'channel', 'id', 'lun',
- {
- name: 'text',
- convert: function(value, record) {
- // check for volid, because if you click on a grouping header,
- // it calls convert (but with an empty volid)
- if (value || record.data.volid === null) {
- return value;
- }
- return PVE.Utils.render_storage_content(value, {}, record);
- }
- }
- ],
- idProperty: 'volid'
- });
-
-});
-Ext.define('PVE.storage.StatusView', {
- extend: 'PVE.panel.StatusView',
- alias: 'widget.pveStorageStatusView',
-
- height: 230,
- title: gettext('Status'),
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- defaults: {
- xtype: 'pveInfoWidget',
- padding: '0 30 5 30'
- },
- items: [
- {
- xtype: 'box',
- height: 30
- },
- {
- itemId: 'enabled',
- title: gettext('Enabled'),
- printBar: false,
- textField: 'disabled',
- renderer: Proxmox.Utils.format_neg_boolean
- },
- {
- itemId: 'active',
- title: gettext('Active'),
- printBar: false,
- textField: 'active',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- itemId: 'content',
- title: gettext('Content'),
- printBar: false,
- textField: 'content',
- renderer: PVE.Utils.format_content_types
- },
- {
- itemId: 'type',
- title: gettext('Type'),
- printBar: false,
- textField: 'type',
- renderer: PVE.Utils.format_storage_type
- },
- {
- xtype: 'box',
- height: 10
- },
- {
- itemId: 'usage',
- title: gettext('Usage'),
- valueField: 'used',
- maxField: 'total'
- }
- ],
-
- updateTitle: function() {
- return;
- }
-});
-Ext.define('PVE.storage.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveStorageSummary',
- scrollable: true,
- bodyPadding: 5,
- tbar: [
- '->',
- {
- xtype: 'proxmoxRRDTypeSelector'
- }
- ],
- layout: {
- type: 'column'
- },
- defaults: {
- padding: 5,
- columnWidth: 1
- },
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var storage = me.pveSelNode.data.storage;
- if (!storage) {
- throw "no storage ID specified";
- }
-
- var rstore = Ext.create('Proxmox.data.ObjectStore', {
- url: "/api2/json/nodes/" + nodename + "/storage/" + storage + "/status",
- interval: 1000
- });
-
- var rrdstore = Ext.create('Proxmox.data.RRDStore', {
- rrdurl: "/api2/json/nodes/" + nodename + "/storage/" + storage + "/rrddata",
- model: 'pve-rrd-storage'
- });
-
- Ext.apply(me, {
- items: [
- {
- xtype: 'pveStorageStatusView',
- pveSelNode: me.pveSelNode,
- rstore: rstore
- },
- {
- xtype: 'proxmoxRRDChart',
- title: gettext('Usage'),
- fields: ['total','used'],
- fieldTitles: ['Total Size', 'Used Size'],
- store: rrdstore
- }
- ],
- listeners: {
- activate: function() { rstore.startUpdate(); rrdstore.startUpdate(); },
- destroy: function() { rstore.stopUpdate(); rrdstore.stopUpdate(); }
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.Browser', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.storage.Browser',
-
- onlineHelp: 'chapter_storage',
-
- initComponent: function() {
- var me = this;
-
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
- throw "no node name specified";
- }
-
- var storeid = me.pveSelNode.data.storage;
- if (!storeid) {
- throw "no storage ID specified";
- }
-
-
- me.items = [
- {
- title: gettext('Summary'),
- xtype: 'pveStorageSummary',
- iconCls: 'fa fa-book',
- itemId: 'summary'
- }
- ];
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- Ext.apply(me, {
- title: Ext.String.format(gettext("Storage {0} on node {1}"),
- "'" + storeid + "'", "'" + nodename + "'"),
- hstateid: 'storagetab'
- });
-
- if (caps.storage['Datastore.Allocate'] ||
- caps.storage['Datastore.AllocateSpace'] ||
- caps.storage['Datastore.Audit']) {
- me.items.push({
- xtype: 'pveStorageContentView',
- title: gettext('Content'),
- iconCls: 'fa fa-th',
- itemId: 'content'
- });
- }
-
- if (caps.storage['Permissions.Modify']) {
- me.items.push({
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- iconCls: 'fa fa-unlock',
- itemId: 'permissions',
- path: '/storage/' + storeid
- });
- }
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.DirInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_directory',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'path',
- value: '',
- fieldLabel: gettext('Directory'),
- allowBlank: false
- },
- {
- xtype: 'pveContentTypeSelector',
- name: 'content',
- value: 'images',
- multiSelect: true,
- fieldLabel: gettext('Content'),
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'shared',
- uncheckedValue: 0,
- fieldLabel: gettext('Shared')
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- disabled: true,
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- }
- ];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.storage.NFSScan', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveNFSScan',
-
- queryParam: 'server',
-
- valueField: 'path',
- displayField: 'path',
- matchFieldWidth: false,
- listConfig: {
- loadingText: gettext('Scanning...'),
- width: 350
- },
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.nfsServer) {
- me.store.removeAll();
- }
-
- me.allQuery = me.nfsServer;
-
- me.callParent();
- },
-
- setServer: function(server) {
- var me = this;
-
- me.nfsServer = server;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'path', 'options' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/nfs'
- }
- });
-
- store.sort('path', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.NFSInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_nfs',
-
- options : [],
-
- onGetValues: function(values) {
- var me = this;
-
- var i;
- var res = [];
- for (i = 0; i < me.options.length; i++) {
- var item = me.options[i];
- if (!item.match(/^vers=(.*)$/)) {
- res.push(item);
- }
- }
- if (values.nfsversion && values.nfsversion !== '__default__') {
- res.push('vers=' + values.nfsversion);
- }
- delete values.nfsversion;
- values.options = res.join(',');
- if (values.options === '') {
- delete values.options;
- if (!me.isCreate) {
- values["delete"] = "options";
- }
- }
-
- return me.callParent([values]);
- },
-
- setValues: function(values) {
- var me = this;
- if (values.options) {
- var res = values.options;
- me.options = values.options.split(',');
- me.options.forEach(function(item) {
- var match = item.match(/^vers=(.*)$/);
- if (match) {
- values.nfsversion = match[1];
- }
- });
- }
- return me.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'server',
- value: '',
- fieldLabel: gettext('Server'),
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- var exportField = me.down('field[name=export]');
- exportField.setServer(value);
- exportField.setValue('');
- }
- }
- }
- },
- {
- xtype: me.isCreate ? 'pveNFSScan' : 'displayfield',
- name: 'export',
- value: '',
- fieldLabel: 'Export',
- allowBlank: false
- },
- {
- xtype: 'pveContentTypeSelector',
- name: 'content',
- value: 'images',
- multiSelect: true,
- fieldLabel: gettext('Content'),
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- disabled: true,
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- }
- ];
-
- me.advancedColumn1 = [
- {
- xtype: 'proxmoxKVComboBox',
- fieldLabel: gettext('NFS Version'),
- name: 'nfsversion',
- value: '__default__',
- deleteEmpty: false,
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText],
- ['3', '3'],
- ['4', '4'],
- ['4.1', '4.1'],
- ['4.2', '4.2']
- ]
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.CIFSScan', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveCIFSScan',
-
- queryParam: 'server',
-
- valueField: 'share',
- displayField: 'share',
- matchFieldWidth: false,
- listConfig: {
- loadingText: gettext('Scanning...'),
- width: 350
- },
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.cifsServer) {
- me.store.removeAll();
- }
-
- var params = {};
- if (me.cifsUsername && me.cifsPassword) {
- params.username = me.cifsUsername;
- params.password = me.cifsPassword;
- }
-
- if (me.cifsDomain) {
- params.domain = me.cifsDomain;
- }
-
- me.store.getProxy().setExtraParams(params);
- me.allQuery = me.cifsServer;
-
- me.callParent();
- },
-
- setServer: function(server) {
- this.cifsServer = server;
- },
-
- setUsername: function(username) {
- this.cifsUsername = username;
- },
-
- setPassword: function(password) {
- this.cifsPassword = password;
- },
-
- setDomain: function(domain) {
- this.cifsDomain = domain;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: ['description', 'share'],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/cifs'
- }
- });
- store.sort('share', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.CIFSInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_cifs',
-
- initComponent : function() {
- var me = this;
-
- var passwordfield = Ext.createWidget(me.isCreate ? 'textfield' : 'displayfield', {
- inputType: 'password',
- name: 'password',
- value: me.isCreate ? '' : '********',
- fieldLabel: gettext('Password'),
- allowBlank: false,
- disabled: me.isCreate,
- minLength: 1,
- listeners: {
- change: function(f, value) {
-
- if (me.isCreate) {
- var exportField = me.down('field[name=share]');
- exportField.setPassword(value);
- }
- }
- }
- });
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'server',
- value: '',
- fieldLabel: gettext('Server'),
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- var exportField = me.down('field[name=share]');
- exportField.setServer(value);
- }
- }
- }
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'username',
- value: '',
- fieldLabel: gettext('Username'),
- emptyText: gettext('Guest user'),
- allowBlank: true,
- listeners: {
- change: function(f, value) {
- if (!me.isCreate) {
- return;
- }
- var exportField = me.down('field[name=share]');
- exportField.setUsername(value);
-
- if (value == "") {
- passwordfield.disable();
- } else {
- passwordfield.enable();
- }
- passwordfield.validate();
- }
- }
- },
- passwordfield,
- {
- xtype: me.isCreate ? 'pveCIFSScan' : 'displayfield',
- name: 'share',
- value: '',
- fieldLabel: 'Share',
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- },
- {
- xtype: 'pveContentTypeSelector',
- name: 'content',
- value: 'images',
- multiSelect: true,
- fieldLabel: gettext('Content'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'domain',
- value: me.isCreate ? '' : undefined,
- fieldLabel: gettext('Domain'),
- allowBlank: true,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
-
- var exportField = me.down('field[name=share]');
- exportField.setDomain(value);
- }
- }
- }
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.GlusterFsScan', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveGlusterFsScan',
-
- queryParam: 'server',
-
- valueField: 'volname',
- displayField: 'volname',
- matchFieldWidth: false,
- listConfig: {
- loadingText: 'Scanning...',
- width: 350
- },
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.glusterServer) {
- me.store.removeAll();
- }
-
- me.allQuery = me.glusterServer;
-
- me.callParent();
- },
-
- setServer: function(server) {
- var me = this;
-
- me.glusterServer = server;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'volname' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/glusterfs'
- }
- });
-
- store.sort('volname', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.GlusterFsInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_glusterfs',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'server',
- value: '',
- fieldLabel: gettext('Server'),
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- var volumeField = me.down('field[name=volume]');
- volumeField.setServer(value);
- volumeField.setValue('');
- }
- }
- }
- },
- {
- xtype: me.isCreate ? 'proxmoxtextfield' : 'displayfield',
- name: 'server2',
- value: '',
- fieldLabel: gettext('Second Server'),
- allowBlank: true
- },
- {
- xtype: me.isCreate ? 'pveGlusterFsScan' : 'displayfield',
- name: 'volume',
- value: '',
- fieldLabel: 'Volume name',
- allowBlank: false
- },
- {
- xtype: 'pveContentTypeSelector',
- cts: ['images', 'iso', 'backup', 'vztmpl', 'snippets'],
- name: 'content',
- value: 'images',
- multiSelect: true,
- fieldLabel: gettext('Content'),
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- disabled: true,
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.IScsiScan', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveIScsiScan',
-
- queryParam: 'portal',
- valueField: 'target',
- displayField: 'target',
- matchFieldWidth: false,
- listConfig: {
- loadingText: gettext('Scanning...'),
- width: 350
- },
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.portal) {
- me.store.removeAll();
- }
-
- me.allQuery = me.portal;
-
- me.callParent();
- },
-
- setPortal: function(portal) {
- var me = this;
-
- me.portal = portal;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'target', 'portal' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/iscsi'
- }
- });
-
- store.sort('target', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.IScsiInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_open_iscsi',
-
- onGetValues: function(values) {
- var me = this;
-
- values.content = values.luns ? 'images' : 'none';
- delete values.luns;
-
- return me.callParent([values]);
- },
-
- setValues: function(values) {
- values.luns = (values.content.indexOf('images') !== -1) ? true : false;
- this.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'portal',
- value: '',
- fieldLabel: 'Portal',
- allowBlank: false,
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- var exportField = me.down('field[name=target]');
- exportField.setPortal(value);
- exportField.setValue('');
- }
- }
- }
- },
- {
- readOnly: !me.isCreate,
- xtype: me.isCreate ? 'pveIScsiScan' : 'displayfield',
- name: 'target',
- value: '',
- fieldLabel: 'Target',
- allowBlank: false
- }
- ];
-
- me.column2 = [
- {
- xtype: 'checkbox',
- name: 'luns',
- checked: true,
- fieldLabel: gettext('Use LUNs directly')
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.VgSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveVgSelector',
- valueField: 'vg',
- displayField: 'vg',
- queryMode: 'local',
- editable: false,
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: {}, // true,
- fields: [ 'vg', 'size', 'free' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/lvm'
- }
- });
-
- store.sort('vg', 'ASC');
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- loadingText: gettext('Scanning...')
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.BaseStorageSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveBaseStorageSelector',
-
- existingGroupsText: gettext("Existing volume groups"),
- queryMode: 'local',
- editable: false,
- value: '',
- valueField: 'storage',
- displayField: 'text',
- initComponent : function() {
- var me = this;
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: {
- addRecords: true,
- params: {
- type: 'iscsi'
- }
- },
- fields: [ 'storage', 'type', 'content',
- {
- name: 'text',
- convert: function(value, record) {
- if (record.data.storage) {
- return record.data.storage + " (iSCSI)";
- } else {
- return me.existingGroupsText;
- }
- }
- }],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/storage/'
- }
- });
-
- store.loadData([{ storage: '' }], true);
-
- store.sort('storage', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.LVMInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_lvm',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [];
-
- var vgnameField = Ext.createWidget(me.isCreate ? 'textfield' : 'displayfield', {
- name: 'vgname',
- hidden: !!me.isCreate,
- disabled: !!me.isCreate,
- value: '',
- fieldLabel: gettext('Volume group'),
- allowBlank: false
- });
-
- if (me.isCreate) {
- var vgField = Ext.create('PVE.storage.VgSelector', {
- name: 'vgname',
- fieldLabel: gettext('Volume group'),
- allowBlank: false
- });
-
- var baseField = Ext.createWidget('pveFileSelector', {
- name: 'base',
- hidden: true,
- disabled: true,
- nodename: 'localhost',
- storageContent: 'images',
- fieldLabel: gettext('Base volume'),
- allowBlank: false
- });
-
- me.column1.push({
- xtype: 'pveBaseStorageSelector',
- name: 'basesel',
- fieldLabel: gettext('Base storage'),
- submitValue: false,
- listeners: {
- change: function(f, value) {
- if (value) {
- vgnameField.setVisible(true);
- vgnameField.setDisabled(false);
- vgField.setVisible(false);
- vgField.setDisabled(true);
- baseField.setVisible(true);
- baseField.setDisabled(false);
- } else {
- vgnameField.setVisible(false);
- vgnameField.setDisabled(true);
- vgField.setVisible(true);
- vgField.setDisabled(false);
- baseField.setVisible(false);
- baseField.setDisabled(true);
- }
- baseField.setStorage(value);
- }
- }
- });
-
- me.column1.push(baseField);
-
- me.column1.push(vgField);
- }
-
- me.column1.push(vgnameField);
-
- // here value is an array,
- // while before it was a string
- /*jslint confusion: true*/
- me.column1.push({
- xtype: 'pveContentTypeSelector',
- cts: ['images', 'rootdir'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: ['images', 'rootdir'],
- multiSelect: true,
- allowBlank: false
- });
- /*jslint confusion: false*/
-
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'shared',
- uncheckedValue: 0,
- fieldLabel: gettext('Shared')
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.TPoolSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveTPSelector',
-
- queryParam: 'vg',
- valueField: 'lv',
- displayField: 'lv',
- editable: false,
-
- doRawQuery: function() {
- },
-
- onTriggerClick: function() {
- var me = this;
-
- if (!me.queryCaching || me.lastQuery !== me.vg) {
- me.store.removeAll();
- }
-
- me.allQuery = me.vg;
-
- me.callParent();
- },
-
- setVG: function(myvg) {
- var me = this;
-
- me.vg = myvg;
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'lv' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/lvmthin'
- }
- });
-
- store.sort('lv', 'ASC');
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- loadingText: gettext('Scanning...')
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.BaseVGSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveBaseVGSelector',
-
- valueField: 'vg',
- displayField: 'vg',
- queryMode: 'local',
- editable: false,
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: {},
- fields: [ 'vg', 'size', 'free'],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/lvm'
- }
- });
-
- Ext.apply(me, {
- store: store,
- listConfig: {
- loadingText: gettext('Scanning...')
- }
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.LvmThinInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_lvmthin',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [];
-
- var vgnameField = Ext.createWidget(me.isCreate ? 'textfield' : 'displayfield', {
- name: 'vgname',
- hidden: !!me.isCreate,
- disabled: !!me.isCreate,
- value: '',
- fieldLabel: gettext('Volume group'),
- allowBlank: false
- });
-
- var thinpoolField = Ext.createWidget(me.isCreate ? 'textfield' : 'displayfield', {
- name: 'thinpool',
- hidden: !!me.isCreate,
- disabled: !!me.isCreate,
- value: '',
- fieldLabel: gettext('Thin Pool'),
- allowBlank: false
- });
-
- if (me.isCreate) {
- var vgField = Ext.create('PVE.storage.TPoolSelector', {
- name: 'thinpool',
- fieldLabel: gettext('Thin Pool'),
- allowBlank: false
- });
-
- me.column1.push({
- xtype: 'pveBaseVGSelector',
- name: 'vgname',
- fieldLabel: gettext('Volume group'),
- listeners: {
- change: function(f, value) {
- if (me.isCreate) {
- vgField.setVG(value);
- vgField.setValue('');
- }
- }
- }
- });
-
- me.column1.push(vgField);
- }
-
- me.column1.push(vgnameField);
-
- me.column1.push(thinpoolField);
-
- // here value is an array,
- // while before it was a string
- /*jslint confusion: true*/
- me.column1.push({
- xtype: 'pveContentTypeSelector',
- cts: ['images', 'rootdir'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: ['images', 'rootdir'],
- multiSelect: true,
- allowBlank: false
- });
- /*jslint confusion: false*/
-
- me.column2 = [];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.storage.CephFSInputPanel', {
- extend: 'PVE.panel.StorageBase',
- controller: 'cephstorage',
-
- onlineHelp: 'storage_cephfs',
-
- viewModel: {
- type: 'cephstorage'
- },
-
- setValues: function(values) {
- if (values.monhost) {
- this.viewModel.set('pveceph', false);
- this.lookupReference('pvecephRef').setValue(false);
- this.lookupReference('pvecephRef').resetOriginalValue();
- }
- this.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
- me.type = 'cephfs';
-
- me.column1 = [];
-
- me.column1.push(
- {
- xtype: 'textfield',
- name: 'monhost',
- vtype: 'HostList',
- value: '',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}',
- hidden: '{pveceph}'
- },
- fieldLabel: 'Monitor(s)',
- allowBlank: false
- },
- {
- xtype: 'displayfield',
- reference: 'monhost',
- bind: {
- disabled: '{!pveceph}',
- hidden: '{!pveceph}'
- },
- value: '',
- fieldLabel: 'Monitor(s)'
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'username',
- value: 'admin',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}'
- },
- fieldLabel: gettext('User name'),
- allowBlank: true
- }
- );
-
- me.column2 = [
- {
- xtype: 'pveContentTypeSelector',
- cts: ['backup', 'iso', 'vztmpl', 'snippets'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: 'backup',
- multiSelect: true,
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- fieldLabel: gettext('Max Backups'),
- name: 'maxfiles',
- reference: 'maxfiles',
- minValue: 0,
- maxValue: 365,
- value: me.isCreate ? '1' : undefined,
- allowBlank: false
- }
- ];
-
- me.columnB = [{
- xtype: 'proxmoxcheckbox',
- name: 'pveceph',
- reference: 'pvecephRef',
- bind : {
- disabled: '{!pvecephPossible}',
- value: '{pveceph}'
- },
- checked: true,
- uncheckedValue: 0,
- submitValue: false,
- hidden: !me.isCreate,
- boxLabel: gettext('Use Proxmox VE managed hyper-converged cephFS')
- }];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.storage.Ceph.Model', {
- extend: 'Ext.app.ViewModel',
- alias: 'viewmodel.cephstorage',
-
- data: {
- pveceph: true,
- pvecephPossible: true
- }
-});
-
-Ext.define('PVE.storage.Ceph.Controller', {
- extend: 'PVE.controller.StorageEdit',
- alias: 'controller.cephstorage',
-
- control: {
- '#': {
- afterrender: 'queryMonitors'
- },
- 'textfield[name=username]': {
- disable: 'resetField'
- },
- 'displayfield[name=monhost]': {
- enable: 'queryMonitors'
- },
- 'textfield[name=monhost]': {
- disable: 'resetField',
- enable: 'resetField'
- }
- },
- resetField: function(field) {
- field.reset();
- },
- queryMonitors: function(field, newVal, oldVal) {
- // we get called with two signatures, the above one for a field
- // change event and the afterrender from the view, this check only
- // can be true for the field change one and omit the API request if
- // pveceph got unchecked - as it's not needed there.
- if (field && !newVal && oldVal) {
- return;
- }
- var view = this.getView();
- var vm = this.getViewModel();
- if (!(view.isCreate || vm.get('pveceph'))) {
- return; // only query on create or if editing a pveceph store
- }
-
- var monhostField = this.lookupReference('monhost');
-
- Proxmox.Utils.API2Request({
- url: '/api2/json/nodes/localhost/ceph/mon',
- method: 'GET',
- scope: this,
- callback: function(options, success, response) {
- var data = response.result.data;
- if (response.status === 200) {
- if (data.length > 0) {
- var monhost = Ext.Array.pluck(data, 'name').sort().join(',');
- monhostField.setValue(monhost);
- monhostField.resetOriginalValue();
- if (view.isCreate) {
- vm.set('pvecephPossible', true);
- }
- } else {
- vm.set('pveceph', false);
- }
- } else {
- vm.set('pveceph', false);
- vm.set('pvecephPossible', false);
- }
- }
- });
- }
-});
-
-Ext.define('PVE.storage.RBDInputPanel', {
- extend: 'PVE.panel.StorageBase',
- controller: 'cephstorage',
-
- onlineHelp: 'ceph_rados_block_devices',
-
- viewModel: {
- type: 'cephstorage'
- },
-
- setValues: function(values) {
- if (values.monhost) {
- this.viewModel.set('pveceph', false);
- this.lookupReference('pvecephRef').setValue(false);
- this.lookupReference('pvecephRef').resetOriginalValue();
- }
- this.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
- me.type = 'rbd';
-
- me.column1 = [];
-
- if (me.isCreate) {
- me.column1.push({
- xtype: 'pveCephPoolSelector',
- nodename: me.nodename,
- name: 'pool',
- bind: {
- disabled: '{!pveceph}',
- submitValue: '{pveceph}',
- hidden: '{!pveceph}'
- },
- fieldLabel: gettext('Pool'),
- allowBlank: false
- },{
- xtype: 'textfield',
- name: 'pool',
- value: 'rbd',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}',
- hidden: '{pveceph}'
- },
- fieldLabel: gettext('Pool'),
- allowBlank: false
- });
- } else {
- me.column1.push({
- xtype: 'displayfield',
- nodename: me.nodename,
- name: 'pool',
- fieldLabel: gettext('Pool'),
- allowBlank: false
- });
- }
-
- me.column1.push(
- {
- xtype: 'textfield',
- name: 'monhost',
- vtype: 'HostList',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}',
- hidden: '{pveceph}'
- },
- value: '',
- fieldLabel: 'Monitor(s)',
- allowBlank: false
- },
- {
- xtype: 'displayfield',
- reference: 'monhost',
- bind: {
- disabled: '{!pveceph}',
- hidden: '{!pveceph}'
- },
- value: '',
- fieldLabel: 'Monitor(s)'
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'username',
- bind: {
- disabled: '{pveceph}',
- submitValue: '{!pveceph}'
- },
- value: 'admin',
- fieldLabel: gettext('User name'),
- allowBlank: true
- }
- );
-
- me.column2 = [
- {
- xtype: 'pveContentTypeSelector',
- cts: ['images', 'rootdir'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: ['images'],
- multiSelect: true,
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'krbd',
- uncheckedValue: 0,
- fieldLabel: 'KRBD'
- }
- ];
-
- me.columnB = [{
- xtype: 'proxmoxcheckbox',
- name: 'pveceph',
- reference: 'pvecephRef',
- bind : {
- disabled: '{!pvecephPossible}',
- value: '{pveceph}'
- },
- checked: true,
- uncheckedValue: 0,
- submitValue: false,
- hidden: !me.isCreate,
- boxLabel: gettext('Use Proxmox VE managed hyper-converged ceph pool')
- }];
-
- me.callParent();
- }
-});
-/*jslint confusion: true*/
-Ext.define('PVE.storage.ZFSInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- viewModel: {
- parent: null,
- data: {
- isLIO: false,
- isComstar: true,
- hasWriteCacheOption: true
- }
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'field[name=iscsiprovider]': {
- change: 'changeISCSIProvider'
- }
- },
- changeISCSIProvider: function(f, newVal, oldVal) {
- var vm = this.getViewModel();
- vm.set('isLIO', newVal === 'LIO');
- vm.set('isComstar', newVal === 'comstar');
- vm.set('hasWriteCacheOption', newVal === 'comstar' || newVal === 'istgt');
- }
- },
-
- onGetValues: function(values) {
- var me = this;
-
- if (me.isCreate) {
- values.content = 'images';
- }
-
- values.nowritecache = values.writecache ? 0 : 1;
- delete values.writecache;
-
- return me.callParent([values]);
- },
-
- setValues: function diff(values) {
- values.writecache = values.nowritecache ? 0 : 1;
- this.callParent([values]);
- },
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'portal',
- value: '',
- fieldLabel: gettext('Portal'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'pool',
- value: '',
- fieldLabel: gettext('Pool'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'blocksize',
- value: '4k',
- fieldLabel: gettext('Block Size'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'target',
- value: '',
- fieldLabel: gettext('Target'),
- allowBlank: false
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'comstar_tg',
- value: '',
- fieldLabel: gettext('Target group'),
- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' },
- allowBlank: true
- }
- ];
-
- me.column2 = [
- {
- xtype: me.isCreate ? 'pveiScsiProviderSelector' : 'displayfield',
- name: 'iscsiprovider',
- value: 'comstar',
- fieldLabel: gettext('iSCSI Provider'),
- allowBlank: false
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'sparse',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: gettext('Thin provision')
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'writecache',
- checked: true,
- bind: me.isCreate ? { disabled: '{!hasWriteCacheOption}' } : { hidden: '{!hasWriteCacheOption}' },
- uncheckedValue: 0,
- fieldLabel: gettext('Write cache')
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'comstar_hg',
- value: '',
- bind: me.isCreate ? { disabled: '{!isComstar}' } : { hidden: '{!isComstar}' },
- fieldLabel: gettext('Host group'),
- allowBlank: true
- },
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'lio_tpg',
- value: '',
- bind: me.isCreate ? { disabled: '{!isLIO}' } : { hidden: '{!isLIO}' },
- allowBlank: false,
- fieldLabel: gettext('Target portal group')
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.storage.ZFSPoolSelector', {
- extend: 'Ext.form.field.ComboBox',
- alias: 'widget.pveZFSPoolSelector',
- valueField: 'pool',
- displayField: 'pool',
- queryMode: 'local',
- editable: false,
- listConfig: {
- loadingText: gettext('Scanning...')
- },
- initComponent : function() {
- var me = this;
-
- if (!me.nodename) {
- me.nodename = 'localhost';
- }
-
- var store = Ext.create('Ext.data.Store', {
- autoLoad: {}, // true,
- fields: [ 'pool', 'size', 'free' ],
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodename + '/scan/zfs'
- }
- });
-
- store.sort('pool', 'ASC');
-
- Ext.apply(me, {
- store: store
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.storage.ZFSPoolInputPanel', {
- extend: 'PVE.panel.StorageBase',
-
- onlineHelp: 'storage_zfspool',
-
- initComponent : function() {
- var me = this;
-
- me.column1 = [];
-
- if (me.isCreate) {
- me.column1.push(Ext.create('PVE.storage.ZFSPoolSelector', {
- name: 'pool',
- fieldLabel: gettext('ZFS Pool'),
- allowBlank: false
- }));
- } else {
- me.column1.push(Ext.createWidget('displayfield', {
- name: 'pool',
- value: '',
- fieldLabel: gettext('ZFS Pool'),
- allowBlank: false
- }));
- }
-
- // value is an array,
- // while before it was a string
- /*jslint confusion: true*/
- me.column1.push(
- {xtype: 'pveContentTypeSelector',
- cts: ['images', 'rootdir'],
- fieldLabel: gettext('Content'),
- name: 'content',
- value: ['images', 'rootdir'],
- multiSelect: true,
- allowBlank: false
- });
- /*jslint confusion: false*/
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'sparse',
- checked: false,
- uncheckedValue: 0,
- fieldLabel: gettext('Thin provision')
- },
- {
- xtype: 'textfield',
- name: 'blocksize',
- emptyText: '8k',
- fieldLabel: gettext('Block Size'),
- allowBlank: true
- }
- ];
-
- me.callParent();
- }
-});
-Ext.define('PVE.ha.StatusView', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveHAStatusView'],
-
- onlineHelp: 'chapter_ha_manager',
-
- sortPriority: {
- quorum: 1,
- master: 2,
- lrm: 3,
- service: 4
- },
-
- initComponent : function() {
- var me = this;
-
- if (!me.rstore) {
- throw "no rstore given";
- }
-
- Proxmox.Utils.monStoreErrors(me, me.rstore);
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: me.rstore,
- sortAfterUpdate: true,
- sorters: [{
- sorterFn: function(rec1, rec2) {
- var p1 = me.sortPriority[rec1.data.type];
- var p2 = me.sortPriority[rec2.data.type];
- return (p1 !== p2) ? ((p1 > p2) ? 1 : -1) : 0;
- }
- }],
- filters: {
- property: 'type',
- value: 'service',
- operator: '!='
- }
- });
-
- Ext.apply(me, {
- store: store,
- stateful: false,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Type'),
- width: 80,
- dataIndex: 'type'
- },
- {
- header: gettext('Status'),
- width: 80,
- flex: 1,
- dataIndex: 'status'
- }
- ]
- });
-
- me.callParent();
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
-
- }
-}, function() {
-
- Ext.define('pve-ha-status', {
- extend: 'Ext.data.Model',
- fields: [
- 'id', 'type', 'node', 'status', 'sid',
- 'state', 'group', 'comment',
- 'max_restart', 'max_relocate', 'type',
- 'crm_state', 'request_state'
- ],
- idProperty: 'id'
- });
-
-});
-Ext.define('PVE.ha.Status', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveHAStatus',
-
- onlineHelp: 'chapter_ha_manager',
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- initComponent: function() {
- var me = this;
-
- me.rstore = Ext.create('Proxmox.data.ObjectStore', {
- interval: me.interval,
- model: 'pve-ha-status',
- storeid: 'pve-store-' + (++Ext.idSeed),
- groupField: 'type',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/cluster/ha/status/current'
- }
- });
-
- me.items = [{
- xtype: 'pveHAStatusView',
- title: gettext('Status'),
- rstore: me.rstore,
- border: 0,
- collapsible: true,
- padding: '0 0 20 0'
- },{
- xtype: 'pveHAResourcesView',
- flex: 1,
- collapsible: true,
- title: gettext('Resources'),
- border: 0,
- rstore: me.rstore
- }];
-
- me.callParent();
- me.on('activate', me.rstore.startUpdate);
- }
-});
-Ext.define('PVE.ha.GroupSelector', {
- extend: 'Proxmox.form.ComboGrid',
- alias: ['widget.pveHAGroupSelector'],
-
- value: [],
- autoSelect: false,
- valueField: 'group',
- displayField: 'group',
- listConfig: {
- columns: [
- {
- header: gettext('Group'),
- width: 100,
- sortable: true,
- dataIndex: 'group'
- },
- {
- header: gettext('Nodes'),
- width: 100,
- sortable: false,
- dataIndex: 'nodes'
- },
- {
- header: gettext('Comment'),
- flex: 1,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode
- }
- ]
- },
- store: {
- model: 'pve-ha-groups',
- sorters: {
- property: 'group',
- order: 'DESC'
- }
- },
-
- initComponent: function() {
- var me = this;
- me.callParent();
- me.getStore().load();
- }
-
-}, function() {
-
- Ext.define('pve-ha-groups', {
- extend: 'Ext.data.Model',
- fields: [
- 'group', 'type', 'digest', 'nodes', 'comment',
- {
- name : 'restricted',
- type: 'boolean'
- },
- {
- name : 'nofailback',
- type: 'boolean'
- }
- ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/ha/groups"
- },
- idProperty: 'group'
- });
-});
-Ext.define('PVE.ha.VMResourceInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- onlineHelp: 'ha_manager_resource_config',
- vmid: undefined,
-
- onGetValues: function(values) {
- var me = this;
-
- if (values.vmid) {
- values.sid = values.vmid;
- }
- delete values.vmid;
-
- PVE.Utils.delete_if_default(values, 'group', '', me.isCreate);
- PVE.Utils.delete_if_default(values, 'max_restart', '1', me.isCreate);
- PVE.Utils.delete_if_default(values, 'max_relocate', '1', me.isCreate);
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
- var MIN_QUORUM_VOTES = 3;
-
- var disabledHint = Ext.createWidget({
- xtype: 'displayfield', // won't get submitted by default
- userCls: 'pve-hint',
- value: 'Disabling the resource will stop the guest system. ' +
- 'See the online help for details.',
- hidden: true
- });
-
- var fewVotesHint = Ext.createWidget({
- itemId: 'fewVotesHint',
- xtype: 'displayfield',
- userCls: 'pve-hint',
- value: 'At least three quorum votes are recommended for reliable HA.',
- hidden: true
- });
-
- Proxmox.Utils.API2Request({
- url: '/cluster/config/nodes',
- method: 'GET',
- failure: function(response) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- },
- success: function(response) {
- var nodes = response.result.data;
- var votes = 0;
- Ext.Array.forEach(nodes, function(node) {
- var vote = parseInt(node.quorum_votes, 10); // parse as base 10
- votes += vote || 0; // parseInt might return NaN, which is false
- });
-
- if (votes < MIN_QUORUM_VOTES) {
- fewVotesHint.setVisible(true);
- }
- }
- });
-
- /*jslint confusion: true */
- var vmidStore = (me.vmid) ? {} : {
- model: 'PVEResources',
- autoLoad: true,
- sorters: 'vmid',
- filters: [
- {
- property: 'type',
- value: /lxc|qemu/
- },
- {
- property: 'hastate',
- value: /unmanaged/
- }
- ]
- };
-
- // value is a string above, but a number below
- me.column1 = [
- {
- xtype: me.vmid ? 'displayfield' : 'vmComboSelector',
- submitValue: me.isCreate,
- name: 'vmid',
- fieldLabel: (me.vmid && me.guestType === 'ct') ? 'CT' : 'VM',
- value: me.vmid,
- store: vmidStore,
- validateExists: true
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'max_restart',
- fieldLabel: gettext('Max. Restart'),
- value: 1,
- minValue: 0,
- maxValue: 10,
- allowBlank: false
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'max_relocate',
- fieldLabel: gettext('Max. Relocate'),
- value: 1,
- minValue: 0,
- maxValue: 10,
- allowBlank: false
- }
- ];
- /*jslint confusion: false */
-
- me.column2 = [
- {
- xtype: 'pveHAGroupSelector',
- name: 'group',
- fieldLabel: gettext('Group')
- },
- {
- xtype: 'proxmoxKVComboBox',
- name: 'state',
- value: 'started',
- fieldLabel: gettext('Request State'),
- comboItems: [
- ['started', 'started'],
- ['stopped', 'stopped'],
- ['ignored', 'ignored'],
- ['disabled', 'disabled']
- ],
- listeners: {
- 'change': function(field, newValue) {
- if (newValue === 'disabled') {
- disabledHint.setVisible(true);
- }
- else {
- if (disabledHint.isVisible()) {
- disabledHint.setVisible(false);
- }
- }
- }
- }
- },
- disabledHint
- ];
-
- me.columnB = [
- {
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- },
- fewVotesHint
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.ha.VMResourceEdit', {
- extend: 'Proxmox.window.Edit',
-
- vmid: undefined,
- guestType: undefined,
- isCreate: undefined,
-
- initComponent : function() {
- var me = this;
-
- if (me.isCreate === undefined) {
- me.isCreate = !me.vmid;
- }
-
- if (me.isCreate) {
- me.url = '/api2/extjs/cluster/ha/resources';
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs/cluster/ha/resources/' + me.vmid;
- me.method = 'PUT';
- }
-
- var ipanel = Ext.create('PVE.ha.VMResourceInputPanel', {
- isCreate: me.isCreate,
- vmid: me.vmid,
- guestType: me.guestType
- });
-
- Ext.apply(me, {
- subject: gettext('Resource') + ': ' + gettext('Container') +
- '/' + gettext('Virtual Machine'),
- isAdd: true,
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
-
- var regex = /^(\S+):(\S+)$/;
- var res = regex.exec(values.sid);
-
- if (res[1] !== 'vm' && res[1] !== 'ct') {
- throw "got unexpected resource type";
- }
-
- values.vmid = res[2];
-
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-Ext.define('PVE.ha.ResourcesView', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveHAResourcesView'],
-
- onlineHelp: 'ha_manager_resources',
-
- stateful: true,
- stateId: 'grid-ha-resources',
-
- initComponent : function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- if (!me.rstore) {
- throw "no store given";
- }
-
- Proxmox.Utils.monStoreErrors(me, me.rstore);
-
- var store = Ext.create('Proxmox.data.DiffStore', {
- rstore: me.rstore,
- filters: {
- property: 'type',
- value: 'service'
- }
- });
-
- var reload = function() {
- me.rstore.load();
- };
-
- var render_error = function(dataIndex, value, metaData, record) {
- var errors = record.data.errors;
- if (errors) {
- var msg = errors[dataIndex];
- if (msg) {
- metaData.tdCls = 'proxmox-invalid-row';
- var html = '' + Ext.htmlEncode(msg) + '
';
- metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
- html.replace(/\"/g,'"') + '"';
- }
- }
- return value;
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- var sid = rec.data.sid;
-
- var regex = /^(\S+):(\S+)$/;
- var res = regex.exec(sid);
-
- if (res[1] !== 'vm' && res[1] !== 'ct') {
- return;
- }
- var guestType = res[1];
- var vmid = res[2];
-
- var win = Ext.create('PVE.ha.VMResourceEdit',{
- guestType: guestType,
- vmid: vmid
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/cluster/ha/resources/',
- getUrl: function(rec) {
- var me = this;
- return me.baseurl + '/' + rec.get('sid');
- },
- callback: function() {
- reload();
- }
- });
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- viewConfig: {
- trackOver: false
- },
- tbar: [
- {
- text: gettext('Add'),
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.ha.VMResourceEdit',{});
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn
- ],
-
- columns: [
- {
- header: 'ID',
- width: 100,
- sortable: true,
- dataIndex: 'sid'
- },
- {
- header: gettext('State'),
- width: 100,
- sortable: true,
- dataIndex: 'state'
- },
- {
- header: gettext('Node'),
- width: 100,
- sortable: true,
- dataIndex: 'node'
- },
- {
- header: gettext('Request State'),
- width: 100,
- hidden: true,
- sortable: true,
- renderer: function(v) {
- return v || 'started';
- },
- dataIndex: 'request_state'
- },
- {
- header: gettext('CRM State'),
- width: 100,
- hidden: true,
- sortable: true,
- dataIndex: 'crm_state'
- },
- {
- header: gettext('Max. Restart'),
- width: 100,
- sortable: true,
- renderer: (v) => v === undefined ? '1' : v,
- dataIndex: 'max_restart'
- },
- {
- header: gettext('Max. Relocate'),
- width: 100,
- sortable: true,
- renderer: (v) => v === undefined ? '1' : v,
- dataIndex: 'max_relocate'
- },
- {
- header: gettext('Group'),
- width: 200,
- sortable: true,
- renderer: function(value, metaData, record) {
- return render_error('group', value, metaData, record);
- },
- dataIndex: 'group'
- },
- {
- header: gettext('Description'),
- flex: 1,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment'
- }
- ],
- listeners: {
- beforeselect: function(grid, record, index, eOpts) {
- if (!caps.nodes['Sys.Console']) {
- return false;
- }
- },
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-ha-resources', {
- extend: 'Ext.data.Model',
- fields: [
- 'sid', 'state', 'digest', 'errors', 'group', 'comment',
- 'max_restart', 'max_relocate', 'type', 'status', 'node',
- 'crm_state', 'request_state'
- ],
- idProperty: 'sid'
- });
-
-});
-Ext.define('PVE.ha.GroupInputPanel', {
- extend: 'Proxmox.panel.InputPanel',
- onlineHelp: 'ha_manager_groups',
-
- groupId: undefined,
-
- onGetValues: function(values) {
- var me = this;
-
- if (me.isCreate) {
- values.type = 'group';
- }
-
- return values;
- },
-
- initComponent : function() {
- var me = this;
-
- var update_nodefield, update_node_selection;
-
- var sm = Ext.create('Ext.selection.CheckboxModel', {
- mode: 'SIMPLE',
- listeners: {
- selectionchange: function(model, selected) {
- update_nodefield(selected);
- }
- }
- });
-
- // use already cached data to avoid an API call
- var data = PVE.data.ResourceStore.getNodes();
-
- var store = Ext.create('Ext.data.Store', {
- fields: [ 'node', 'mem', 'cpu', 'priority' ],
- data: data,
- proxy: {
- type: 'memory',
- reader: {type: 'json'}
- },
- sorters: [
- {
- property : 'node',
- direction: 'ASC'
- }
- ]
- });
-
- var nodegrid = Ext.createWidget('grid', {
- store: store,
- border: true,
- height: 300,
- selModel: sm,
- columns: [
- {
- header: gettext('Node'),
- flex: 1,
- dataIndex: 'node'
- },
- {
- header: gettext('Memory usage') + " %",
- renderer: PVE.Utils.render_mem_usage_percent,
- sortable: true,
- width: 150,
- dataIndex: 'mem'
- },
- {
- header: gettext('CPU usage'),
- renderer: PVE.Utils.render_cpu,
- sortable: true,
- width: 150,
- dataIndex: 'cpu'
- },
- {
- header: 'Priority',
- xtype: 'widgetcolumn',
- dataIndex: 'priority',
- sortable: true,
- stopSelection: true,
- widget: {
- xtype: 'proxmoxintegerfield',
- minValue: 0,
- maxValue: 1000,
- isFormField: false,
- listeners: {
- change: function(numberfield, value, old_value) {
- var record = numberfield.getWidgetRecord();
- record.set('priority', value);
- update_nodefield(sm.getSelection());
- }
- }
- }
- }
- ]
- });
-
- var nodefield = Ext.create('Ext.form.field.Hidden', {
- name: 'nodes',
- value: '',
- listeners: {
- change: function (nodefield, value) {
- update_node_selection(value);
- }
- },
- isValid: function () {
- var value = nodefield.getValue();
- return (value && 0 !== value.length);
- }
- });
-
- update_node_selection = function(string) {
- sm.deselectAll(true);
-
- string.split(',').forEach(function (e, idx, array) {
- var res = e.split(':');
-
- store.each(function(record) {
- var node = record.get('node');
-
- if (node == res[0]) {
- sm.select(record, true);
- record.set('priority', res[1]);
- record.commit();
- }
- });
- });
- nodegrid.reconfigure(store);
-
- };
-
- update_nodefield = function(selected) {
- var nodes = '';
- var first_iteration = true;
- Ext.Array.each(selected, function(record) {
- if (!first_iteration) {
- nodes += ',';
- }
- first_iteration = false;
-
- nodes += record.data.node;
- if (record.data.priority) {
- nodes += ':' + record.data.priority;
- }
- });
-
- // nodefield change listener calls us again, which results in a
- // endless recursion, suspend the event temporary to avoid this
- nodefield.suspendEvent('change');
- nodefield.setValue(nodes);
- nodefield.resumeEvent('change');
- };
-
- me.column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'group',
- value: me.groupId || '',
- fieldLabel: 'ID',
- vtype: 'StorageId',
- allowBlank: false
- },
- nodefield
- ];
-
- me.column2 = [
- {
- xtype: 'proxmoxcheckbox',
- name: 'restricted',
- uncheckedValue: 0,
- fieldLabel: 'restricted'
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'nofailback',
- uncheckedValue: 0,
- fieldLabel: 'nofailback'
- }
- ];
-
- me.columnB = [
- {
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- },
- nodegrid
- ];
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.ha.GroupEdit', {
- extend: 'Proxmox.window.Edit',
-
- groupId: undefined,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.groupId;
-
- if (me.isCreate) {
- me.url = '/api2/extjs/cluster/ha/groups';
- me.method = 'POST';
- } else {
- me.url = '/api2/extjs/cluster/ha/groups/' + me.groupId;
- me.method = 'PUT';
- }
-
- var ipanel = Ext.create('PVE.ha.GroupInputPanel', {
- isCreate: me.isCreate,
- groupId: me.groupId
- });
-
- Ext.apply(me, {
- subject: gettext('HA Group'),
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var values = response.result.data;
-
- ipanel.setValues(values);
- }
- });
- }
- }
-});
-Ext.define('PVE.ha.GroupsView', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveHAGroupsView'],
-
- onlineHelp: 'ha_manager_groups',
-
- stateful: true,
- stateId: 'grid-ha-groups',
-
- initComponent : function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var store = new Ext.data.Store({
- model: 'pve-ha-groups',
- sorters: {
- property: 'group',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
-
- var win = Ext.create('PVE.ha.GroupEdit',{
- groupId: rec.data.group
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/cluster/ha/groups/',
- callback: function() {
- reload();
- }
- });
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- viewConfig: {
- trackOver: false
- },
- tbar: [
- {
- text: gettext('Create'),
- disabled: !caps.nodes['Sys.Console'],
- handler: function() {
- var win = Ext.create('PVE.ha.GroupEdit',{});
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn
- ],
- columns: [
- {
- header: gettext('Group'),
- width: 150,
- sortable: true,
- dataIndex: 'group'
- },
- {
- header: 'restricted',
- width: 100,
- sortable: true,
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'restricted'
- },
- {
- header: 'nofailback',
- width: 100,
- sortable: true,
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'nofailback'
- },
- {
- header: gettext('Nodes'),
- flex: 1,
- sortable: false,
- dataIndex: 'nodes'
- },
- {
- header: gettext('Comment'),
- flex: 1,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment'
- }
- ],
- listeners: {
- activate: reload,
- beforeselect: function(grid, record, index, eOpts) {
- if (!caps.nodes['Sys.Console']) {
- return false;
- }
- },
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.ha.FencingView', {
- extend: 'Ext.grid.GridPanel',
- alias: ['widget.pveFencingView'],
-
- onlineHelp: 'ha_manager_fencing',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-ha-fencing',
- data: []
- });
-
- Ext.apply(me, {
- store: store,
- stateful: false,
- viewConfig: {
- trackOver: false,
- deferEmptyText: false,
- emptyText: 'Use watchdog based fencing.'
- },
- columns: [
- {
- header: 'Node',
- width: 100,
- sortable: true,
- dataIndex: 'node'
- },
- {
- header: gettext('Command'),
- flex: 1,
- dataIndex: 'command'
- }
- ]
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-ha-fencing', {
- extend: 'Ext.data.Model',
- fields: [
- 'node', 'command', 'digest'
- ]
- });
-
-});
-Ext.define('PVE.dc.Summary', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveDcSummary',
-
- scrollable: true,
-
- bodyPadding: 5,
-
- layout: 'column',
-
- defaults: {
- padding: 5,
- plugins: 'responsive',
- responsiveConfig: {
- 'width < 1900': {
- columnWidth: 1
- },
- 'width >= 1900': {
- columnWidth: 0.5
- }
- }
- },
-
- items: [
- {
- itemId: 'dcHealth',
- xtype: 'pveDcHealth'
- },
- {
- itemId: 'dcGuests',
- xtype: 'pveDcGuests'
- },
- {
- title: gettext('Resources'),
- xtype: 'panel',
- minHeight: 250,
- bodyPadding: 5,
- layout: 'hbox',
- defaults: {
- xtype: 'proxmoxGauge',
- flex: 1
- },
- items:[
- {
- title: gettext('CPU'),
- itemId: 'cpu'
- },
- {
- title: gettext('Memory'),
- itemId: 'memory'
- },
- {
- title: gettext('Storage'),
- itemId: 'storage'
- }
- ]
- },
- {
- itemId: 'nodeview',
- xtype: 'pveDcNodeView',
- height: 250
- },
- {
- title: gettext('Subscriptions'),
- height: 220,
- items: [
- {
- itemId: 'subscriptions',
- xtype: 'pveHealthWidget',
- userCls: 'pointer',
- listeners: {
- element: 'el',
- click: function() {
- if (this.component.userCls === 'pointer') {
- window.open('https://www.proxmox.com/en/proxmox-ve/pricing', '_blank');
- }
- }
- }
- }
- ]
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- var rstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 3000,
- storeid: 'pve-cluster-status',
- model: 'pve-dc-nodes',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/status"
- }
- });
-
- var gridstore = Ext.create('Proxmox.data.DiffStore', {
- rstore: rstore,
- filters: {
- property: 'type',
- value: 'node'
- },
- sorters: {
- property: 'id',
- direction: 'ASC'
- }
- });
-
- me.callParent();
-
- me.getComponent('nodeview').setStore(gridstore);
-
- var gueststatus = me.getComponent('dcGuests');
-
- var cpustat = me.down('#cpu');
- var memorystat = me.down('#memory');
- var storagestat = me.down('#storage');
- var sp = Ext.state.Manager.getProvider();
-
- me.mon(PVE.data.ResourceStore, 'load', function(curstore, results) {
- me.suspendLayout = true;
-
- var cpu = 0;
- var maxcpu = 0;
-
- var nodes = 0;
-
- var memory = 0;
- var maxmem = 0;
-
- var countedStorages = {};
- var used = 0;
- var total = 0;
- var usableStorages = {};
- var storages = sp.get('dash-storages') || '';
- storages.split(',').forEach(function(storage){
- if (storage !== '') {
- usableStorages[storage] = true;
- }
- });
-
- var qemu = {
- running: 0,
- paused: 0,
- stopped: 0,
- template: 0
- };
- var lxc = {
- running: 0,
- paused: 0,
- stopped: 0,
- template: 0
- };
- var error = 0;
-
- var i;
-
- for (i = 0; i < results.length; i++) {
- var item = results[i];
- switch(item.data.type) {
- case 'node':
- cpu += (item.data.cpu * item.data.maxcpu);
- maxcpu += item.data.maxcpu || 0;
- memory += item.data.mem || 0;
- maxmem += item.data.maxmem || 0;
- nodes++;
-
- // update grid also
- var griditem = gridstore.getById(item.data.id);
- if (griditem) {
- griditem.set('cpuusage', item.data.cpu);
- var max = item.data.maxmem || 1;
- var val = item.data.mem || 0;
- griditem.set('memoryusage', val/max);
- griditem.set('uptime', item.data.uptime);
- griditem.commit(); //else it marks the fields as dirty
- }
- break;
- case 'storage':
- if (!Ext.Object.isEmpty(usableStorages)) {
- if (usableStorages[item.data.id] === true) {
- used += item.data.disk;
- total += item.data.maxdisk;
- }
- break;
- }
- if (!countedStorages[item.data.storage] ||
- (item.data.storage === 'local' &&
- !countedStorages[item.data.id])) {
- used += item.data.disk;
- total += item.data.maxdisk;
-
- countedStorages[item.data.storage === 'local'?item.data.id:item.data.storage] = true;
- }
- break;
- case 'qemu':
- qemu[item.data.template ? 'template' : item.data.status]++;
- if (item.data.hastate === 'error') {
- error++;
- }
- break;
- case 'lxc':
- lxc[item.data.template ? 'template' : item.data.status]++;
- if (item.data.hastate === 'error') {
- error++;
- }
- break;
- default: break;
- }
- }
-
- var text = Ext.String.format(gettext('of {0} CPU(s)'), maxcpu);
- cpustat.updateValue((cpu/maxcpu), text);
-
- text = Ext.String.format(gettext('{0} of {1}'), PVE.Utils.render_size(memory), PVE.Utils.render_size(maxmem));
- memorystat.updateValue((memory/maxmem), text);
-
- text = Ext.String.format(gettext('{0} of {1}'), PVE.Utils.render_size(used), PVE.Utils.render_size(total));
- storagestat.updateValue((used/total), text);
-
- gueststatus.updateValues(qemu,lxc,error);
-
- me.suspendLayout = false;
- me.updateLayout(true);
- });
-
- var dcHealth = me.getComponent('dcHealth');
- me.mon(rstore, 'load', dcHealth.updateStatus, dcHealth);
-
- var subs = me.down('#subscriptions');
- me.mon(rstore, 'load', function(store, records, success) {
- var i;
- var level;
- var mixed = false;
- for (i = 0; i < records.length; i++) {
- if (records[i].get('type') !== 'node') {
- continue;
- }
- var node = records[i];
- if (node.get('status') === 'offline') {
- continue;
- }
-
- var curlevel = node.get('level');
-
- if (curlevel === '') { // no subscription trumps all, set and break
- level = '';
- break;
- }
-
- if (level === undefined) { // save level
- level = curlevel;
- } else if (level !== curlevel) { // detect different levels
- mixed = true;
- }
- }
-
- var data = {
- title: Proxmox.Utils.unknownText,
- text: Proxmox.Utils.unknownText,
- iconCls: PVE.Utils.get_health_icon(undefined, true)
- };
- if (level === '') {
- data = {
- title: gettext('No Subscription'),
- iconCls: PVE.Utils.get_health_icon('critical', true),
- text: gettext('You have at least one node without subscription.')
- };
- subs.setUserCls('pointer');
- } else if (mixed) {
- data = {
- title: gettext('Mixed Subscriptions'),
- iconCls: PVE.Utils.get_health_icon('warning', true),
- text: gettext('Warning: Your subscription levels are not the same.')
- };
- subs.setUserCls('pointer');
- } else if (level) {
- data = {
- title: PVE.Utils.render_support_level(level),
- iconCls: PVE.Utils.get_health_icon('good', true),
- text: gettext('Your subscription status is valid.')
- };
- subs.setUserCls('');
- }
-
- subs.setData(data);
- });
-
- me.on('destroy', function(){
- rstore.stopUpdate();
- });
-
- rstore.startUpdate();
- }
-
-});
-Ext.define('PVE.window.ReplicaEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveReplicaEdit',
-
- subject: gettext('Replication Job'),
-
-
- url: '/cluster/replication',
- method: 'POST',
-
- initComponent: function() {
- var me = this;
-
- var vmid = me.pveSelNode.data.vmid;
- var nodename = me.pveSelNode.data.node;
-
- var items = [];
-
- items.push({
- xtype: (me.isCreate && !vmid)?'pveGuestIDSelector':'displayfield',
- name: 'guest',
- fieldLabel: 'CT/VM ID',
- value: vmid || ''
- });
-
- items.push(
- {
- xtype: me.isCreate ? 'pveNodeSelector':'displayfield',
- name: 'target',
- disallowedNodes: [nodename],
- allowBlank: false,
- onlineValidator: true,
- fieldLabel: gettext("Target")
- },
- {
- xtype: 'pveCalendarEvent',
- fieldLabel: gettext('Schedule'),
- emptyText: '*/15 - ' + Ext.String.format(gettext('Every {0} minutes'), 15),
- name: 'schedule'
- },
- {
- xtype: 'numberfield',
- fieldLabel: gettext('Rate limit') + ' (MB/s)',
- step: 1,
- minValue: 1,
- emptyText: gettext('unlimited'),
- name: 'rate'
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Comment'),
- name: 'comment'
- },
- {
- xtype: 'proxmoxcheckbox',
- name: 'enabled',
- defaultValue: 'on',
- checked: true,
- fieldLabel: gettext('Enabled')
- }
- );
-
- me.items = [
- {
- xtype: 'inputpanel',
- itemId: 'ipanel',
- onlineHelp: 'pvesr_schedule_time_format',
-
- onGetValues: function(values) {
- var me = this.up('window');
-
- values.disable = values.enabled ? 0 : 1;
- delete values.enabled;
-
- PVE.Utils.delete_if_default(values, 'rate', '', me.isCreate);
- PVE.Utils.delete_if_default(values, 'disable', 0, me.isCreate);
- PVE.Utils.delete_if_default(values, 'schedule', '*/15', me.isCreate);
- PVE.Utils.delete_if_default(values, 'comment', '', me.isCreate);
-
- if (me.isCreate) {
- values.type = 'local';
- var vm = vmid || values.guest;
- var id = -1;
- if (me.highestids[vm] !== undefined) {
- id = me.highestids[vm];
- }
- id++;
- values.id = vm + '-' + id.toString();
- delete values.guest;
- }
- return values;
- },
- items: items
- }
- ];
-
- me.callParent();
-
- if (me.isCreate) {
- me.load({
- success: function(response) {
- var jobs = response.result.data;
- var highestids = {};
- Ext.Array.forEach(jobs, function(job) {
- var match = /^([0-9]+)\-([0-9]+)$/.exec(job.id);
- if (match) {
- var vmid = parseInt(match[1],10);
- var id = parseInt(match[2],10);
- if (highestids[vmid] < id ||
- highestids[vmid] === undefined) {
- highestids[vmid] = id;
- }
- }
- });
-
- me.highestids = highestids;
- }
- });
-
- } else {
- me.load({
- success: function(response, options) {
- response.result.data.enabled = !response.result.data.disable;
- me.setValues(response.result.data);
- me.digest = response.result.data.digest;
- }
- });
- }
- }
-});
-
-/*jslint confusion: true */
-/* callback is a function and string */
-Ext.define('PVE.grid.ReplicaView', {
- extend: 'Ext.grid.Panel',
- xtype: 'pveReplicaView',
-
- onlineHelp: 'chapter_pvesr',
-
- stateful: true,
- stateId: 'grid-pve-replication-status',
-
- controller: {
- xclass: 'Ext.app.ViewController',
-
- addJob: function(button,event,rec) {
- var me = this.getView();
- var controller = this;
- var win = Ext.create('PVE.window.ReplicaEdit', {
- isCreate: true,
- method: 'POST',
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', function() { controller.reload(); });
- win.show();
- },
-
- editJob: function(button,event,rec) {
- var me = this.getView();
- var controller = this;
- var data = rec.data;
- var win = Ext.create('PVE.window.ReplicaEdit', {
- url: '/cluster/replication/' + data.id,
- method: 'PUT',
- pveSelNode: me.pveSelNode
- });
- win.on('destroy', function() { controller.reload(); });
- win.show();
- },
-
- scheduleJobNow: function(button,event,rec) {
- var me = this.getView();
- var controller = this;
-
- Proxmox.Utils.API2Request({
- url: "/api2/extjs/nodes/" + me.nodename + "/replication/" + rec.data.id + "/schedule_now",
- method: 'POST',
- waitMsgTarget: me,
- callback: function() { controller.reload(); },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- showLog: function(button, event, rec) {
- var me = this.getView();
- var controller = this;
- var logView = Ext.create('Proxmox.panel.LogView', {
- border: false,
- url: "/api2/extjs/nodes/" + me.nodename + "/replication/" + rec.data.id + "/log"
- });
- var win = Ext.create('Ext.window.Window', {
- items: [ logView ],
- layout: 'fit',
- width: 800,
- height: 400,
- modal: true,
- title: gettext("Replication Log")
- });
- var task = {
- run: function() {
- logView.requestUpdate();
- },
- interval: 1000
- };
- Ext.TaskManager.start(task);
- win.on('destroy', function() {
- Ext.TaskManager.stop(task);
- controller.reload();
- });
- win.show();
- },
-
- reload: function() {
- var me = this.getView();
- me.rstore.load();
- },
-
- dblClick: function(grid, record, item) {
- var me = this;
- me.editJob(undefined, undefined, record);
- },
-
- // check for cluster
- // currently replication is for cluster only, so we disable the whole
- // component
- checkPrerequisites: function() {
- var me = this.getView();
- if (PVE.data.ResourceStore.getNodes().length < 2) {
- me.mask(gettext("Replication needs at least two nodes"), ['pve-static-mask']);
- }
- },
-
- control: {
- '#': {
- itemdblclick: 'dblClick',
- afterlayout: 'checkPrerequisites'
- }
- }
- },
-
- tbar: [
- {
- text: gettext('Add'),
- itemId: 'addButton',
- handler: 'addJob'
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Edit'),
- itemId: 'editButton',
- handler: 'editJob',
- disabled: true
- },
- {
- xtype: 'proxmoxStdRemoveButton',
- itemId: 'removeButton',
- baseurl: '/api2/extjs/cluster/replication/',
- dangerous: true,
- callback: 'reload'
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Log'),
- itemId: 'logButton',
- handler: 'showLog',
- disabled: true
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Schedule now'),
- itemId: 'scheduleNowButton',
- handler: 'scheduleJobNow',
- disabled: true
- }
- ],
-
- initComponent: function() {
- var me = this;
- var mode = '';
- var url = '/cluster/replication';
-
- me.nodename = me.pveSelNode.data.node;
- me.vmid = me.pveSelNode.data.vmid;
-
- me.columns = [
- {
- text: gettext('Enabled'),
- dataIndex: 'enabled',
- xtype: 'checkcolumn',
- sortable: true,
- disabled: true
- },
- {
- text: 'ID',
- dataIndex: 'id',
- width: 60,
- hidden: true
- },
- {
- text: gettext('Guest'),
- dataIndex: 'guest',
- width: 75
- },
- {
- text: gettext('Job'),
- dataIndex: 'jobnum',
- width: 60
- },
- {
- text: gettext('Target'),
- dataIndex: 'target'
- }
- ];
-
- if (!me.nodename) {
- mode = 'dc';
- me.stateId = 'grid-pve-replication-dc';
- } else if (!me.vmid) {
- mode = 'node';
- url = '/nodes/' + me.nodename + '/replication';
- } else {
- mode = 'vm';
- url = '/nodes/' + me.nodename + '/replication' + '?guest=' + me.vmid;
- }
-
- if (mode !== 'dc') {
- me.columns.push(
- {
- text: gettext('Status'),
- dataIndex: 'state',
- minWidth: 160,
- flex: 1,
- renderer: function(value, metadata, record) {
-
- if (record.data.pid) {
- metadata.tdCls = 'x-grid-row-loading';
- return '';
- }
-
- var icons = [];
- var states = [];
-
- if (record.data.remove_job) {
- icons.push(' ');
- states.push(gettext("Removal Scheduled"));
- }
-
- if (record.data.error) {
- icons.push(' ');
- states.push(record.data.error);
- }
-
- if (icons.length == 0) {
- icons.push(' ');
- states.push(gettext('OK'));
- }
-
- return icons.join(',') + ' ' + states.join(',');
- }
- },
- {
- text: gettext('Last Sync'),
- dataIndex: 'last_sync',
- width: 150,
- renderer: function(value, metadata, record) {
- if (!value) {
- return '-';
- }
-
- if (record.data.pid) {
- return gettext('syncing');
- }
-
- return Proxmox.Utils.render_timestamp(value);
- }
- },
- {
- text: gettext('Duration'),
- dataIndex: 'duration',
- width: 60,
- renderer: PVE.Utils.render_duration
- },
- {
- text: gettext('Next Sync'),
- dataIndex: 'next_sync',
- width: 150,
- renderer: function(value) {
- if (!value) {
- return '-';
- }
-
- var now = new Date();
- var next = new Date(value*1000);
-
- if (next < now) {
- return gettext('pending');
- }
-
- return Proxmox.Utils.render_timestamp(value);
- }
- }
- );
- }
-
- me.columns.push(
- {
- text: gettext('Schedule'),
- width: 75,
- dataIndex: 'schedule'
- },
- {
- text: gettext('Rate limit'),
- dataIndex: 'rate',
- renderer: function(value) {
- if (!value) {
- return gettext('unlimited');
- }
-
- return value.toString() + ' MB/s';
- },
- hidden: true
- },
- {
- text: gettext('Comment'),
- dataIndex: 'comment',
- renderer: Ext.htmlEncode
- }
- );
-
- me.rstore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'pve-replica-' + me.nodename + me.vmid,
- model: (mode === 'dc')? 'pve-replication' : 'pve-replication-state',
- interval: 3000,
- proxy: {
- type: 'proxmox',
- url: "/api2/json" + url
- }
- });
-
- me.store = Ext.create('Proxmox.data.DiffStore', {
- rstore: me.rstore,
- sorters: [
- {
- property: 'guest'
- },
- {
- property: 'jobnum'
- }
- ]
- });
-
- me.callParent();
-
- // we cannot access the log and scheduleNow button
- // in the datacenter, because
- // we do not know where/if the jobs runs
- if (mode === 'dc') {
- me.down('#logButton').setHidden(true);
- me.down('#scheduleNowButton').setHidden(true);
- }
-
- // if we set the warning mask, we do not want to load
- // or set the mask on store errors
- if (PVE.data.ResourceStore.getNodes().length < 2) {
- return;
- }
-
- Proxmox.Utils.monStoreErrors(me, me.rstore);
-
- me.on('destroy', me.rstore.stopUpdate);
- me.rstore.startUpdate();
- }
-}, function() {
-
- Ext.define('pve-replication', {
- extend: 'Ext.data.Model',
- fields: [
- 'id', 'target', 'comment', 'rate', 'type',
- { name: 'guest', type: 'integer' },
- { name: 'jobnum', type: 'integer' },
- { name: 'schedule', defaultValue: '*/15' },
- { name: 'disable', defaultValue: '' },
- { name: 'enabled', calculate: function(data) { return !data.disable; } }
- ]
- });
-
- Ext.define('pve-replication-state', {
- extend: 'pve-replication',
- fields: [
- 'last_sync', 'next_sync', 'error', 'duration', 'state',
- 'fail_count', 'remove_job', 'pid'
- ]
- });
-
-});
-Ext.define('PVE.dc.Health', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveDcHealth',
-
- title: gettext('Health'),
-
- bodyPadding: 10,
- height: 220,
- layout: {
- type: 'hbox',
- align: 'stretch'
- },
-
- defaults: {
- flex: 1,
- xtype: 'box',
- style: {
- 'text-align':'center'
- }
- },
-
- nodeList: [],
- nodeIndex: 0,
-
- updateStatus: function(store, records, success) {
- var me = this;
- if (!success) {
- return;
- }
-
- var cluster = {
- iconCls: PVE.Utils.get_health_icon('good', true),
- text: gettext("Standalone node - no cluster defined")
- };
-
- var nodes = {
- online: 0,
- offline: 0
- };
-
- // by default we have one node
- var numNodes = 1;
- var i;
-
- for (i = 0; i < records.length; i++) {
- var item = records[i];
- if (item.data.type === 'node') {
- nodes[item.data.online === 1 ? 'online':'offline']++;
- } else if(item.data.type === 'cluster') {
- cluster.text = gettext("Cluster") + ": ";
- cluster.text += item.data.name + ", ";
- cluster.text += gettext("Quorate") + ": ";
- cluster.text += Proxmox.Utils.format_boolean(item.data.quorate);
- if (item.data.quorate != 1) {
- cluster.iconCls = PVE.Utils.get_health_icon('critical', true);
- }
-
- numNodes = item.data.nodes;
- }
- }
-
- if (numNodes !== (nodes.online + nodes.offline)) {
- nodes.offline = numNodes - nodes.online;
- }
-
- me.getComponent('clusterstatus').updateHealth(cluster);
- me.getComponent('nodestatus').update(nodes);
- },
-
- updateCeph: function(store, records, success) {
- var me = this;
- var cephstatus = me.getComponent('ceph');
- if (!success || records.length < 1) {
-
- // if ceph status is already visible
- // don't stop to update
- if (cephstatus.isVisible()) {
- return;
- }
-
- // try all nodes until we either get a successful api call,
- // or we tried all nodes
- if (++me.nodeIndex >= me.nodeList.length) {
- me.cephstore.stopUpdate();
- } else {
- store.getProxy().setUrl('/api2/json/nodes/' + me.nodeList[me.nodeIndex].node + '/ceph/status');
- }
-
- return;
- }
-
- var state = PVE.Utils.render_ceph_health(records[0].data.health || {});
- cephstatus.updateHealth(state);
- cephstatus.setVisible(true);
- },
-
- listeners: {
- destroy: function() {
- var me = this;
- me.cephstore.stopUpdate();
- }
- },
-
- items: [
- {
- itemId: 'clusterstatus',
- xtype: 'pveHealthWidget',
- title: gettext('Status')
- },
- {
- itemId: 'nodestatus',
- data: {
- online: 0,
- offline: 0
- },
- tpl: [
- '' + gettext('Nodes') + ' ',
- '',
- '
',
- ' ',
- gettext('Online'),
- '
',
- '
{online}
',
- '
',
- '
',
- ' ',
- gettext('Offline'),
- '
',
- '
{offline}
',
- '
'
- ]
- },
- {
- itemId: 'ceph',
- width: 250,
- columnWidth: undefined,
- userCls: 'pointer',
- title: 'Ceph',
- xtype: 'pveHealthWidget',
- hidden: true,
- listeners: {
- element: 'el',
- click: function() {
- var sp = Ext.state.Manager.getProvider();
- sp.set('dctab', {value:'ceph'}, true);
- }
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- me.nodeList = PVE.data.ResourceStore.getNodes();
- me.nodeIndex = 0;
- me.cephstore = Ext.create('Proxmox.data.UpdateStore', {
- interval: 3000,
- storeid: 'pve-cluster-ceph',
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + me.nodeList[me.nodeIndex].node + '/ceph/status'
- }
- });
- me.callParent();
- me.mon(me.cephstore, 'load', me.updateCeph, me);
- me.cephstore.startUpdate();
- }
-});
-Ext.define('PVE.dc.Guests', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveDcGuests',
-
-
- title: gettext('Guests'),
- height: 220,
- layout: {
- type: 'table',
- columns: 2,
- tableAttrs: {
- style: {
- width: '100%'
- }
- }
- },
- bodyPadding: '0 20 20 20',
-
- defaults: {
- xtype: 'box',
- padding: '0 50 0 50',
- style: {
- 'text-align':'center',
- 'line-height':'1.2'
- }
- },
- items: [{
- itemId: 'qemu',
- data: {
- running: 0,
- paused: 0,
- stopped: 0,
- template: 0
- },
- tpl: [
- '' + gettext("Virtual Machines") + ' ',
- '',
- ' ',
- gettext('Running'),
- '
',
- '{running}
' + ' ',
- '',
- '',
- ' ',
- gettext('Paused'),
- '
',
- '{paused}
' + ' ',
- ' ',
- '',
- ' ',
- gettext('Stopped'),
- '
',
- '{stopped}
' + ' ',
- '',
- '',
- ' ',
- gettext('Templates'),
- '
',
- '{template}
',
- ' '
- ]
- },{
- itemId: 'lxc',
- data: {
- running: 0,
- paused: 0,
- stopped: 0,
- template: 0
- },
- tpl: [
- '' + gettext("LXC Container") + ' ',
- '',
- ' ',
- gettext('Running'),
- '
',
- '{running}
' + ' ',
- '',
- '',
- ' ',
- gettext('Paused'),
- '
',
- '{paused}
' + ' ',
- ' ',
- '',
- ' ',
- gettext('Stopped'),
- '
',
- '{stopped}
' + ' ',
- '',
- '',
- ' ',
- gettext('Templates'),
- '
',
- '{template}
',
- ' '
- ]
- },{
- itemId: 'error',
- colspan: 2,
- data: {
- num: 0
- },
- columnWidth: 1,
- padding: '10 250 0 250',
- tpl: [
- '',
- '',
- ' ',
- gettext('Error'),
- '
',
- '{num}
',
- ' '
- ]
- }],
-
- updateValues: function(qemu, lxc, error) {
- var me = this;
- me.getComponent('qemu').update(qemu);
- me.getComponent('lxc').update(lxc);
- me.getComponent('error').update({num: error});
- }
-});
- /*jslint confusion: true*/
-Ext.define('PVE.dc.OptionView', {
- extend: 'Proxmox.grid.ObjectGrid',
- alias: ['widget.pveDcOptionView'],
-
- onlineHelp: 'datacenter_configuration_file',
-
- monStoreErrors: true,
-
- add_inputpanel_row: function(name, text, opts) {
- var me = this;
-
- opts = opts || {};
- me.rows = me.rows || {};
-
- var canEdit = (opts.caps === undefined || opts.caps);
- me.rows[name] = {
- required: true,
- defaultValue: opts.defaultValue,
- header: text,
- renderer: opts.renderer,
- editor: canEdit ? {
- xtype: 'proxmoxWindowEdit',
- width: 350,
- subject: text,
- fieldDefaults: {
- labelWidth: opts.labelWidth || 100
- },
- setValues: function(values) {
- // FIXME: run through parsePropertyString if not an object?
- var edit_value = values[name];
- Ext.Array.each(this.query('inputpanel'), function(panel) {
- panel.setValues(edit_value);
- });
- },
- url: opts.url,
- items: [{
- xtype: 'inputpanel',
- onGetValues: function(values) {
- if (values === undefined || Object.keys(values).length === 0) {
- return { 'delete': name };
- }
- var ret_val = {};
- ret_val[name] = PVE.Parser.printPropertyString(values);
- return ret_val;
- },
- items: opts.items
- }]
- } : undefined
- };
- },
-
- initComponent : function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- me.add_combobox_row('keyboard', gettext('Keyboard Layout'), {
- renderer: PVE.Utils.render_kvm_language,
- comboItems: PVE.Utils.kvm_keymap_array(),
- defaultValue: '__default__',
- deleteEmpty: true
- });
- me.add_text_row('http_proxy', gettext('HTTP proxy'), {
- defaultValue: Proxmox.Utils.noneText,
- vtype: 'HttpProxy',
- deleteEmpty: true
- });
- me.add_combobox_row('console', gettext('Console Viewer'), {
- renderer: PVE.Utils.render_console_viewer,
- comboItems: PVE.Utils.console_viewer_array(),
- defaultValue: '__default__',
- deleteEmpty: true
- });
- me.add_text_row('email_from', gettext('Email from address'), {
- deleteEmpty: true,
- vtype: 'proxmoxMail',
- defaultValue: 'root@$hostname'
- });
- me.add_text_row('mac_prefix', gettext('MAC address prefix'), {
- deleteEmpty: true,
- vtype: 'MacPrefix',
- defaultValue: Proxmox.Utils.noneText
- });
- me.add_inputpanel_row('migration', gettext('Migration Settings'), {
- renderer: PVE.Utils.render_dc_ha_opts,
- caps: caps.vms['Sys.Modify'],
- labelWidth: 120,
- url: "/api2/extjs/cluster/options",
- defaultKey: 'type',
- items: [{
- xtype: 'displayfield',
- name: 'type',
- fieldLabel: gettext('Type'),
- value: 'secure',
- submitValue: true,
- }, {
- xtype: 'proxmoxNetworkSelector',
- name: 'network',
- fieldLabel: gettext('Network'),
- value: null,
- emptyText: Proxmox.Utils.defaultText,
- autoSelect: false,
- skipEmptyText: true
- }]
- });
- me.add_inputpanel_row('ha', gettext('HA Settings'), {
- renderer: PVE.Utils.render_dc_ha_opts,
- caps: caps.vms['Sys.Modify'],
- labelWidth: 120,
- url: "/api2/extjs/cluster/options",
- items: [{
- xtype: 'proxmoxKVComboBox',
- name: 'shutdown_policy',
- fieldLabel: gettext('Shutdown Policy'),
- deleteEmpty: false,
- value: '__default__',
- comboItems: [
- ['__default__', Proxmox.Utils.defaultText + ' (conditional)' ],
- ['freeze', 'freeze'],
- ['failover', 'failover'],
- ['conditional', 'conditional']
- ],
- defaultValue: '__default__'
- }]
- });
-
- // TODO: bwlimits, u2f?
-
- me.selModel = Ext.create('Ext.selection.RowModel', {});
-
- Ext.apply(me, {
- tbar: [{
- text: gettext('Edit'),
- xtype: 'proxmoxButton',
- disabled: true,
- handler: function() { me.run_editor(); },
- selModel: me.selModel
- }],
- url: "/api2/json/cluster/options",
- editorConfig: {
- url: "/api2/extjs/cluster/options"
- },
- interval: 5000,
- cwidth1: 200,
- listeners: {
- itemdblclick: me.run_editor
- }
- });
-
- me.callParent();
-
- // set the new value for the default console
- me.mon(me.rstore, 'load', function(store, records, success) {
- if (!success) {
- return;
- }
-
- var rec = store.getById('console');
- PVE.VersionInfo.console = rec.data.value;
- if (rec.data.value === '__default__') {
- delete PVE.VersionInfo.console;
- }
- });
-
- me.on('activate', me.rstore.startUpdate);
- me.on('destroy', me.rstore.stopUpdate);
- me.on('deactivate', me.rstore.stopUpdate);
- }
-});
-Ext.define('PVE.dc.StorageView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveStorageView'],
-
- onlineHelp: 'chapter_storage',
-
- stateful: true,
- stateId: 'grid-dc-storage',
-
- createStorageEditWindow: function(type, sid) {
- var schema = PVE.Utils.storageSchema[type];
- if (!schema || !schema.ipanel) {
- throw "no editor registered for storage type: " + type;
- }
-
- Ext.create('PVE.storage.BaseEdit', {
- paneltype: 'PVE.storage.' + schema.ipanel,
- type: type,
- storageId: sid,
- autoShow: true,
- listeners: {
- destroy: this.reloadStore
- }
- });
- },
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-storage',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/storage"
- },
- sorters: {
- property: 'storage',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var type = rec.data.type,
- sid = rec.data.storage;
-
- me.createStorageEditWindow(type, sid);
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/storage/',
- callback: reload
- });
-
- // else we cannot dynamically generate the add menu handlers
- var addHandleGenerator = function(type) {
- return function() { me.createStorageEditWindow(type); };
- };
- var addMenuItems = [], type;
- /*jslint forin: true */
- for (type in PVE.Utils.storageSchema) {
- var storage = PVE.Utils.storageSchema[type];
- if (storage.hideAdd) {
- continue;
- }
- addMenuItems.push({
- text: PVE.Utils.format_storage_type(type),
- iconCls: 'fa fa-fw fa-' + storage.faIcon,
- handler: addHandleGenerator(type)
- });
- }
-
- Ext.apply(me, {
- store: store,
- reloadStore: reload,
- selModel: sm,
- viewConfig: {
- trackOver: false
- },
- tbar: [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: addMenuItems
- })
- },
- remove_btn,
- edit_btn
- ],
- columns: [
- {
- header: 'ID',
- flex: 2,
- sortable: true,
- dataIndex: 'storage'
- },
- {
- header: gettext('Type'),
- flex: 1,
- sortable: true,
- dataIndex: 'type',
- renderer: PVE.Utils.format_storage_type
- },
- {
- header: gettext('Content'),
- flex: 3,
- sortable: true,
- dataIndex: 'content',
- renderer: PVE.Utils.format_content_types
- },
- {
- header: gettext('Path') + '/' + gettext('Target'),
- flex: 2,
- sortable: true,
- dataIndex: 'path',
- renderer: function(value, metaData, record) {
- if (record.data.target) {
- return record.data.target;
- }
- return value;
- }
- },
- {
- header: gettext('Shared'),
- flex: 1,
- sortable: true,
- dataIndex: 'shared',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- header: gettext('Enabled'),
- flex: 1,
- sortable: true,
- dataIndex: 'disable',
- renderer: Proxmox.Utils.format_neg_boolean
- },
- {
- header: gettext('Bandwidth Limit'),
- flex: 2,
- sortable: true,
- dataIndex: 'bwlimit'
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-storage', {
- extend: 'Ext.data.Model',
- fields: [
- 'path', 'type', 'content', 'server', 'portal', 'target', 'export', 'storage',
- { name: 'shared', type: 'boolean'},
- { name: 'disable', type: 'boolean'}
- ],
- idProperty: 'storage'
- });
-
-});
-/*global u2f,QRCode,Uint8Array*/
-/*jslint confusion: true*/
-Ext.define('PVE.window.TFAEdit', {
- extend: 'Ext.window.Window',
- mixins: ['Proxmox.Mixin.CBind'],
-
- onlineHelp: 'pveum_tfa_auth', // fake to ensure this gets a link target
-
- modal: true,
- resizable: false,
- title: gettext('Two Factor Authentication'),
- subject: 'TFA',
- url: '/api2/extjs/access/tfa',
- width: 512,
-
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
-
- updateQrCode: function() {
- var me = this;
- var values = me.lookup('totp_form').getValues();
- var algorithm = values.algorithm;
- if (!algorithm) {
- algorithm = 'SHA1';
- }
-
- me.qrcode.makeCode(
- 'otpauth://totp/' + encodeURIComponent(me.userid) +
- '?secret=' + values.secret +
- '&period=' + values.step +
- '&digits=' + values.digits +
- '&algorithm=' + algorithm +
- '&issuer=' + encodeURIComponent(values.issuer)
- );
-
- me.lookup('challenge').setVisible(true);
- me.down('#qrbox').setVisible(true);
- },
-
- showError: function(error) {
- Ext.Msg.alert(
- gettext('Error'),
- PVE.Utils.render_u2f_error(error)
- );
- },
-
- doU2FChallenge: function(response) {
- var me = this;
-
- var data = response.result.data;
- me.lookup('password').setDisabled(true);
- var msg = Ext.Msg.show({
- title: 'U2F: '+gettext('Setup'),
- message: gettext('Please press the button on your U2F Device'),
- buttons: []
- });
- Ext.Function.defer(function() {
- u2f.register(data.appId, [data], [], function(data) {
- msg.close();
- if (data.errorCode) {
- me.showError(data.errorCode);
- } else {
- me.respondToU2FChallenge(data);
- }
- });
- }, 500, me);
- },
-
- respondToU2FChallenge: function(data) {
- var me = this;
- var params = {
- userid: me.userid,
- action: 'confirm',
- response: JSON.stringify(data)
- };
- if (Proxmox.UserName !== 'root@pam') {
- params.password = me.lookup('password').value;
- }
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'PUT',
- success: function() {
- me.close();
- Ext.Msg.show({
- title: gettext('Success'),
- message: gettext('U2F Device successfully connected.'),
- buttons: Ext.Msg.OK
- });
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- viewModel: {
- data: {
- in_totp_tab: true,
- tfa_required: false,
- tfa_type: null, // dependencies of formulas should not be undefined
- valid: false,
- u2f_available: true
- },
- formulas: {
- canDeleteTFA: function(get) {
- return (get('tfa_type') !== null && !get('tfa_required'));
- },
- canSetupTOTP: function(get) {
- var tfa = get('tfa_type');
- return (tfa === null || tfa === 'totp' || tfa === 1);
- },
- canSetupU2F: function(get) {
- var tfa = get('tfa_type');
- return (get('u2f_available') && (tfa === null || tfa === 'u2f' || tfa === 1));
- }
- }
- },
-
- afterLoading: function(realm_tfa_type, user_tfa_type) {
- var me = this;
- var viewmodel = me.getViewModel();
- if (user_tfa_type === 'oath') {
- user_tfa_type = 'totp';
- }
- viewmodel.set('tfa_type', user_tfa_type || null);
- if (!realm_tfa_type) {
- // There's no TFA enforced by the realm, everything works.
- viewmodel.set('u2f_available', true);
- viewmodel.set('tfa_required', false);
- } else if (realm_tfa_type === 'oath') {
- // The realm explicitly requires TOTP
- if (user_tfa_type !== 'totp' && user_tfa_type !== null) {
- // user had a different tfa method, so
- // we have to change back to the totp tab and
- // generate a secret
- viewmodel.set('tfa_type', null);
- me.lookup('tfatabs').setActiveTab(me.lookup('totp_panel'));
- me.getController().randomizeSecret();
- }
- viewmodel.set('tfa_required', true);
- viewmodel.set('u2f_available', false);
- } else {
- // The realm enforces some other TFA type (yubico)
- me.close();
- Ext.Msg.alert(
- gettext('Error'),
- Ext.String.format(
- gettext("Custom 2nd factor configuration is not supported on realms with '{0}' TFA."),
- realm_tfa_type
- )
- );
- }
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- 'field[qrupdate=true]': {
- change: function() {
- var me = this.getView();
- me.updateQrCode();
- }
- },
- 'field': {
- validitychange: function(field, valid) {
- var me = this;
- var viewModel = me.getViewModel();
- var form = me.lookup('totp_form');
- var challenge = me.lookup('challenge');
- var password = me.lookup('password');
- viewModel.set('valid', form.isValid() && challenge.isValid() && password.isValid());
- }
- },
- '#': {
- show: function() {
- var me = this.getView();
- var viewmodel = this.getViewModel();
-
- var loadMaskContainer = me.down('#tfatabs');
- Proxmox.Utils.API2Request({
- url: '/access/users/' + encodeURIComponent(me.userid) + '/tfa',
- waitMsgTarget: loadMaskContainer,
- method: 'GET',
- success: function(response, opts) {
- var data = response.result.data;
- me.afterLoading(data.realm, data.user);
- },
- failure: function(response, opts) {
- Proxmox.Utils.setErrorMask(loadMaskContainer, response.htmlStatus);
- }
- });
-
- me.qrdiv = document.createElement('center');
- me.qrcode = new QRCode(me.qrdiv, {
- width: 256,
- height: 256,
- correctLevel: QRCode.CorrectLevel.M
- });
- me.down('#qrbox').getEl().appendChild(me.qrdiv);
-
- viewmodel.set('tfa_type', me.tfa_type || null);
- if (!me.tfa_type) {
- this.randomizeSecret();
- } else {
- me.down('#qrbox').setVisible(false);
- me.lookup('challenge').setVisible(false);
- if (me.tfa_type === 'u2f') {
- var u2f_panel = me.lookup('u2f_panel');
- me.lookup('tfatabs').setActiveTab(u2f_panel);
- }
- }
-
- if (Proxmox.UserName === 'root@pam') {
- me.lookup('password').setVisible(false);
- me.lookup('password').setDisabled(true);
- }
- }
- },
- '#tfatabs': {
- tabchange: function(panel, newcard) {
- var viewmodel = this.getViewModel();
- viewmodel.set('in_totp_tab', newcard.itemId === 'totp-panel');
- }
- }
- },
-
- applySettings: function() {
- var me = this;
- var values = me.lookup('totp_form').getValues();
- var params = {
- userid: me.getView().userid,
- action: 'new',
- key: values.secret,
- config: PVE.Parser.printPropertyString({
- type: 'oath',
- digits: values.digits,
- step: values.step
- }),
- // this is used to verify that the client generates the correct codes:
- response: me.lookup('challenge').value
- };
-
- if (Proxmox.UserName !== 'root@pam') {
- params.password = me.lookup('password').value;
- }
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'PUT',
- waitMsgTarget: me.getView(),
- success: function(response, opts) {
- me.getView().close();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- deleteTFA: function() {
- var me = this;
- var values = me.lookup('totp_form').getValues();
- var params = {
- userid: me.getView().userid,
- action: 'delete'
- };
-
- if (Proxmox.UserName !== 'root@pam') {
- params.password = me.lookup('password').value;
- }
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'PUT',
- waitMsgTarget: me.getView(),
- success: function(response, opts) {
- me.getView().close();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
-
- randomizeSecret: function() {
- var me = this;
- var rnd = new Uint8Array(16);
- window.crypto.getRandomValues(rnd);
- var data = '';
- rnd.forEach(function(b) {
- // secret must be base32, so just use the first 5 bits
- b = b & 0x1f;
- if (b < 26) {
- // A..Z
- data += String.fromCharCode(b + 0x41);
- } else {
- // 2..7
- data += String.fromCharCode(b-26 + 0x32);
- }
- });
- me.lookup('tfa_secret').setValue(data);
- },
-
- startU2FRegistration: function() {
- var me = this;
-
- var params = {
- userid: me.getView().userid,
- action: 'new'
- };
-
- if (Proxmox.UserName !== 'root@pam') {
- params.password = me.lookup('password').value;
- }
-
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'PUT',
- waitMsgTarget: me.getView(),
- success: function(response) {
- me.getView().doU2FChallenge(response);
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- },
-
- items: [
- {
- xtype: 'tabpanel',
- itemId: 'tfatabs',
- reference: 'tfatabs',
- border: false,
- items: [
- {
- xtype: 'panel',
- title: 'TOTP',
- itemId: 'totp-panel',
- reference: 'totp_panel',
- tfa_type: 'totp',
- border: false,
- bind: {
- disabled: '{!canSetupTOTP}'
- },
- layout: {
- type: 'vbox',
- align: 'stretch'
- },
- items: [
- {
- xtype: 'form',
- layout: 'anchor',
- border: false,
- reference: 'totp_form',
- fieldDefaults: {
- anchor: '100%',
- padding: '0 5'
- },
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('User name'),
- cbind: {
- value: '{userid}'
- }
- },
- {
- layout: 'hbox',
- border: false,
- padding: '0 0 5 0',
- items: [{
- xtype: 'textfield',
- fieldLabel: gettext('Secret'),
- emptyText: gettext('Unchanged'),
- name: 'secret',
- reference: 'tfa_secret',
- regex: /^[A-Z2-7=]+$/,
- regexText: 'Must be base32 [A-Z2-7=]',
- maskRe: /[A-Z2-7=]/,
- qrupdate: true,
- flex: 4
- },
- {
- xtype: 'button',
- text: gettext('Randomize'),
- reference: 'randomize_button',
- handler: 'randomizeSecret',
- flex: 1
- }]
- },
- {
- xtype: 'numberfield',
- fieldLabel: gettext('Time period'),
- name: 'step',
- // Google Authenticator ignores this and generates bogus data
- hidden: true,
- value: 30,
- minValue: 10,
- qrupdate: true
- },
- {
- xtype: 'numberfield',
- fieldLabel: gettext('Digits'),
- name: 'digits',
- value: 6,
- // Google Authenticator ignores this and generates bogus data
- hidden: true,
- minValue: 6,
- maxValue: 8,
- qrupdate: true
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Issuer Name'),
- name: 'issuer',
- value: 'Proxmox Web UI',
- qrupdate: true
- }
- ]
- },
- {
- xtype: 'box',
- itemId: 'qrbox',
- visible: false, // will be enabled when generating a qr code
- style: {
- 'background-color': '#23272a',
- padding: '5px',
- width: '266px',
- height: '266px'
- }
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Verification Code'),
- allowBlank: false,
- reference: 'challenge',
- padding: '0 5',
- emptyText: gettext('Scan QR code and enter TOTP auth. code to verify')
- }
- ]
- },
- {
- title: 'U2F',
- itemId: 'u2f-panel',
- reference: 'u2f_panel',
- tfa_type: 'u2f',
- border: false,
- padding: '5 5',
- layout: {
- type: 'vbox',
- align: 'middle'
- },
- bind: {
- disabled: '{!canSetupU2F}'
- },
- items: [
- {
- xtype: 'label',
- width: 500,
- text: gettext('To register a U2F device, connect the device, then click the button and follow the instructions.')
- }
- ]
- }
- ]
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- fieldLabel: gettext('Password'),
- minLength: 5,
- reference: 'password',
- allowBlank: false,
- validateBlank: true,
- padding: '0 0 5 5',
- emptyText: gettext('verify current password')
- }
- ],
-
- buttons: [
- {
- xtype: 'proxmoxHelpButton'
- },
- '->',
- {
- text: gettext('Apply'),
- handler: 'applySettings',
- bind: {
- hidden: '{!in_totp_tab}',
- disabled: '{!valid}'
- }
- },
- {
- xtype: 'button',
- text: gettext('Register U2F Device'),
- handler: 'startU2FRegistration',
- bind: {
- hidden: '{in_totp_tab}',
- disabled: '{tfa_type}'
- }
- },
- {
- text: gettext('Delete'),
- reference: 'delete_button',
- disabled: true,
- handler: 'deleteTFA',
- bind: {
- disabled: '{!canDeleteTFA}'
- }
- }
- ],
-
- initComponent: function() {
- var me = this;
-
- if (!me.userid) {
- throw "no userid given";
- }
-
- me.callParent();
-
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', 'pveum_tfa_auth');
- }
-});
-Ext.define('PVE.dc.UserEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcUserEdit'],
-
- isAdd: true,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.userid;
-
- var url;
- var method;
- var realm;
-
- if (me.isCreate) {
- url = '/api2/extjs/access/users';
- method = 'POST';
- } else {
- url = '/api2/extjs/access/users/' + encodeURIComponent(me.userid);
- method = 'PUT';
- }
-
- var verifypw;
- var pwfield;
-
- var validate_pw = function() {
- if (verifypw.getValue() !== pwfield.getValue()) {
- return gettext("Passwords do not match");
- }
- return true;
- };
-
- verifypw = Ext.createWidget('textfield', {
- inputType: 'password',
- fieldLabel: gettext('Confirm password'),
- name: 'verifypassword',
- submitValue: false,
- disabled: true,
- hidden: true,
- validator: validate_pw
- });
-
- pwfield = Ext.createWidget('textfield', {
- inputType: 'password',
- fieldLabel: gettext('Password'),
- minLength: 5,
- name: 'password',
- disabled: true,
- hidden: true,
- validator: validate_pw
- });
-
- var update_passwd_field = function(realm) {
- if (realm === 'pve') {
- pwfield.setVisible(true);
- pwfield.setDisabled(false);
- verifypw.setVisible(true);
- verifypw.setDisabled(false);
- } else {
- pwfield.setVisible(false);
- pwfield.setDisabled(true);
- verifypw.setVisible(false);
- verifypw.setDisabled(true);
- }
-
- };
-
- var column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'userid',
- fieldLabel: gettext('User name'),
- value: me.userid,
- allowBlank: false,
- submitValue: me.isCreate ? true : false
- },
- pwfield, verifypw,
- {
- xtype: 'pveGroupSelector',
- name: 'groups',
- multiSelect: true,
- allowBlank: true,
- fieldLabel: gettext('Group')
- },
- {
- xtype: 'datefield',
- name: 'expire',
- emptyText: 'never',
- format: 'Y-m-d',
- submitFormat: 'U',
- fieldLabel: gettext('Expire')
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Enabled'),
- name: 'enable',
- uncheckedValue: 0,
- defaultValue: 1,
- checked: true
- }
- ];
-
- var column2 = [
- {
- xtype: 'textfield',
- name: 'firstname',
- fieldLabel: gettext('First Name')
- },
- {
- xtype: 'textfield',
- name: 'lastname',
- fieldLabel: gettext('Last Name')
- },
- {
- xtype: 'textfield',
- name: 'email',
- fieldLabel: gettext('E-Mail'),
- vtype: 'proxmoxMail'
- }
- ];
-
- if (me.isCreate) {
- column1.splice(1,0,{
- xtype: 'pveRealmComboBox',
- name: 'realm',
- fieldLabel: gettext('Realm'),
- allowBlank: false,
- matchFieldWidth: false,
- listConfig: { width: 300 },
- listeners: {
- change: function(combo, newValue){
- realm = newValue;
- update_passwd_field(realm);
- }
- },
- submitValue: false
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- column1: column1,
- column2: column2,
- columnB: [
- {
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- }
- ],
- advancedItems: [
- {
- xtype: 'textfield',
- name: 'keys',
- fieldLabel: gettext('Key IDs')
- }
- ],
- onGetValues: function(values) {
- // hack: ExtJS datefield does not submit 0, so we need to set that
- if (!values.expire) {
- values.expire = 0;
- }
-
- if (realm) {
- values.userid = values.userid + '@' + realm;
- }
-
- if (!values.password) {
- delete values.password;
- }
-
- return values;
- }
- });
-
- Ext.applyIf(me, {
- subject: gettext('User'),
- url: url,
- method: method,
- fieldDefaults: {
- labelWidth: 110 // for spanish translation
- },
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var data = response.result.data;
- if (Ext.isDefined(data.expire)) {
- if (data.expire) {
- data.expire = new Date(data.expire * 1000);
- } else {
- // display 'never' instead of '1970-01-01'
- data.expire = null;
- }
- }
- me.setValues(data);
- }
- });
- }
- }
-});
-/*jslint confusion: true */
-Ext.define('PVE.dc.UserView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveUserView'],
-
- onlineHelp: 'pveum_users',
-
- stateful: true,
- stateId: 'grid-users',
-
- initComponent : function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- var store = new Ext.data.Store({
- id: "users",
- model: 'pve-users',
- sorters: {
- property: 'userid',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/access/users/',
- enableFn: function(rec) {
- if (!caps.access['User.Modify']) {
- return false;
- }
- return rec.data.userid !== 'root@pam';
- },
- callback: function() {
- reload();
- }
- });
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec || !caps.access['User.Modify']) {
- return;
- }
-
- var win = Ext.create('PVE.dc.UserEdit',{
- userid: rec.data.userid
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- enableFn: function(rec) {
- return !!caps.access['User.Modify'];
- },
- selModel: sm,
- handler: run_editor
- });
-
- var pwchange_btn = new Proxmox.button.Button({
- text: gettext('Password'),
- disabled: true,
- selModel: sm,
- handler: function(btn, event, rec) {
- var win = Ext.create('Proxmox.window.PasswordEdit', {
- userid: rec.data.userid
- });
- win.on('destroy', reload);
- win.show();
- }
- });
-
- var tfachange_btn = new Proxmox.button.Button({
- text: 'TFA',
- disabled: true,
- selModel: sm,
- handler: function(btn, event, rec) {
- var d = rec.data;
- var tfa_type = PVE.Parser.parseTfaType(d.keys);
- var win = Ext.create('PVE.window.TFAEdit',{
- tfa_type: tfa_type,
- userid: d.userid
- });
- win.on('destroy', reload);
- win.show();
- }
- });
-
- var tbar = [
- {
- text: gettext('Add'),
- disabled: !caps.access['User.Modify'],
- handler: function() {
- var win = Ext.create('PVE.dc.UserEdit',{
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn, pwchange_btn, tfachange_btn
- ];
-
- var render_username = function(userid) {
- return userid.match(/^(.+)(@[^@]+)$/)[1];
- };
-
- var render_realm = function(userid) {
- return userid.match(/@([^@]+)$/)[1];
- };
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('User name'),
- width: 200,
- sortable: true,
- renderer: render_username,
- dataIndex: 'userid'
- },
- {
- header: gettext('Realm'),
- width: 100,
- sortable: true,
- renderer: render_realm,
- dataIndex: 'userid'
- },
- {
- header: gettext('Enabled'),
- width: 80,
- sortable: true,
- renderer: Proxmox.Utils.format_boolean,
- dataIndex: 'enable'
- },
- {
- header: gettext('Expire'),
- width: 80,
- sortable: true,
- renderer: Proxmox.Utils.format_expire,
- dataIndex: 'expire'
- },
- {
- header: gettext('Name'),
- width: 150,
- sortable: true,
- renderer: PVE.Utils.render_full_name,
- dataIndex: 'firstname'
- },
- {
- header: 'TFA',
- width: 50,
- sortable: true,
- renderer: function(v) {
- var tfa_type = PVE.Parser.parseTfaType(v);
- if (tfa_type === undefined) {
- return Proxmox.Utils.noText;
- } else if (tfa_type === 1) {
- return Proxmox.Utils.yesText;
- } else {
- return tfa_type;
- }
- },
- dataIndex: 'keys'
- },
- {
- header: gettext('Comment'),
- sortable: false,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment',
- flex: 1
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.PoolView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pvePoolView'],
-
- onlineHelp: 'pveum_pools',
-
- stateful: true,
- stateId: 'grid-pools',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-pools',
- sorters: {
- property: 'poolid',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/pools/',
- callback: function () {
- reload();
- }
- });
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.dc.PoolEdit',{
- poolid: rec.data.poolid
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var tbar = [
- {
- text: gettext('Create'),
- handler: function() {
- var win = Ext.create('PVE.dc.PoolEdit', {});
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn
- ];
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Name'),
- width: 200,
- sortable: true,
- dataIndex: 'poolid'
- },
- {
- header: gettext('Comment'),
- sortable: false,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment',
- flex: 1
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.PoolEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcPoolEdit'],
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.poolid;
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = '/api2/extjs/pools';
- method = 'POST';
- } else {
- url = '/api2/extjs/pools/' + me.poolid;
- method = 'PUT';
- }
-
- Ext.applyIf(me, {
- subject: gettext('Pool'),
- url: url,
- method: method,
- items: [
- {
- xtype: me.isCreate ? 'proxmoxtextfield' : 'displayfield',
- fieldLabel: gettext('Name'),
- name: 'poolid',
- value: me.poolid,
- allowBlank: false
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Comment'),
- name: 'comment',
- allowBlank: true
- }
- ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load();
- }
- }
-});
-Ext.define('PVE.dc.GroupView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveGroupView'],
-
- onlineHelp: 'pveum_groups',
-
- stateful: true,
- stateId: 'grid-groups',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-groups',
- sorters: {
- property: 'groupid',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- callback: function() {
- reload();
- },
- baseurl: '/access/groups/'
- });
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.dc.GroupEdit',{
- groupid: rec.data.groupid
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var tbar = [
- {
- text: gettext('Create'),
- handler: function() {
- var win = Ext.create('PVE.dc.GroupEdit', {});
- win.on('destroy', reload);
- win.show();
- }
- },
- edit_btn, remove_btn
- ];
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Name'),
- width: 200,
- sortable: true,
- dataIndex: 'groupid'
- },
- {
- header: gettext('Comment'),
- sortable: false,
- renderer: Ext.String.htmlEncode,
- dataIndex: 'comment',
- flex: 1
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.GroupEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcGroupEdit'],
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.groupid;
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = '/api2/extjs/access/groups';
- method = 'POST';
- } else {
- url = '/api2/extjs/access/groups/' + me.groupid;
- method = 'PUT';
- }
-
- Ext.applyIf(me, {
- subject: gettext('Group'),
- url: url,
- method: method,
- items: [
- {
- xtype: me.isCreate ? 'proxmoxtextfield' : 'displayfield',
- fieldLabel: gettext('Name'),
- name: 'groupid',
- value: me.groupid,
- allowBlank: false
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Comment'),
- name: 'comment',
- allowBlank: true
- }
- ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load();
- }
- }
-});
-Ext.define('PVE.dc.RoleView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveRoleView'],
-
- onlineHelp: 'pveum_roles',
-
- stateful: true,
- stateId: 'grid-roles',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-roles',
- sorters: {
- property: 'roleid',
- order: 'DESC'
- }
- });
-
- var render_privs = function(value, metaData) {
-
- if (!value) {
- return '-';
- }
-
- // allow word wrap
- metaData.style = 'white-space:normal;';
-
- return value.replace(/\,/g, ' ');
- };
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- store.load();
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- if (rec.data.special === "1") {
- return;
- }
-
- var win = Ext.create('PVE.dc.RoleEdit',{
- roleid: rec.data.roleid,
- privs: rec.data.privs
- });
- win.on('destroy', reload);
- win.show();
- };
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
-
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Built-In'),
- width: 65,
- sortable: true,
- dataIndex: 'special',
- renderer: Proxmox.Utils.format_boolean
- },
- {
- header: gettext('Name'),
- width: 150,
- sortable: true,
- dataIndex: 'roleid'
- },
- {
- itemid: 'privs',
- header: gettext('Privileges'),
- sortable: false,
- renderer: render_privs,
- dataIndex: 'privs',
- flex: 1
- }
- ],
- listeners: {
- activate: function() {
- store.load();
- },
- itemdblclick: run_editor
- },
- tbar: [
- {
- text: gettext('Create'),
- handler: function() {
- var win = Ext.create('PVE.dc.RoleEdit', {});
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- xtype: 'proxmoxButton',
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor,
- enableFn: function(record) {
- return record.data.special !== '1';
- }
- },
- {
- xtype: 'proxmoxStdRemoveButton',
- selModel: sm,
- callback: function() {
- reload();
- },
- baseurl: '/access/roles/',
- enableFn: function(record) {
- return record.data.special !== '1';
- }
- }
- ]
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.RoleEdit', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveDcRoleEdit',
-
- width: 400,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.roleid;
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = '/api2/extjs/access/roles';
- method = 'POST';
- } else {
- url = '/api2/extjs/access/roles/' + me.roleid;
- method = 'PUT';
- }
-
- Ext.applyIf(me, {
- subject: gettext('Role'),
- url: url,
- method: method,
- items: [
- {
- xtype: me.isCreate ? 'proxmoxtextfield' : 'displayfield',
- name: 'roleid',
- value: me.roleid,
- allowBlank: false,
- fieldLabel: gettext('Name')
- },
- {
- xtype: 'pvePrivilegesSelector',
- name: 'privs',
- value: me.privs,
- allowBlank: false,
- fieldLabel: gettext('Privileges')
- }
- ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response) {
- var data = response.result.data;
- var keys = Ext.Object.getKeys(data);
-
- me.setValues({
- privs: keys,
- roleid: me.roleid
- });
- }
- });
- }
- }
-});
-Ext.define('PVE.dc.ACLAdd', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveACLAdd'],
- url: '/access/acl',
- method: 'PUT',
- isAdd: true,
- initComponent : function() {
-
- var me = this;
-
- me.isCreate = true;
-
- var items = [
- {
- xtype: me.path ? 'hiddenfield' : 'pvePermPathSelector',
- name: 'path',
- value: me.path,
- allowBlank: false,
- fieldLabel: gettext('Path')
- }
- ];
-
- if (me.aclType === 'group') {
- me.subject = gettext("Group Permission");
- items.push({
- xtype: 'pveGroupSelector',
- name: 'groups',
- fieldLabel: gettext('Group')
- });
- } else if (me.aclType === 'user') {
- me.subject = gettext("User Permission");
- items.push({
- xtype: 'pveUserSelector',
- name: 'users',
- fieldLabel: gettext('User')
- });
- } else {
- throw "unknown ACL type";
- }
-
- items.push({
- xtype: 'pveRoleSelector',
- name: 'roles',
- value: 'NoAccess',
- fieldLabel: gettext('Role')
- });
-
- if (!me.path) {
- items.push({
- xtype: 'proxmoxcheckbox',
- name: 'propagate',
- checked: true,
- uncheckedValue: 0,
- fieldLabel: gettext('Propagate')
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- items: items,
- onlineHelp: 'pveum_permission_management'
- });
-
- Ext.apply(me, {
- items: [ ipanel ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.dc.ACLView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveACLView'],
-
- onlineHelp: 'chapter_user_management',
-
- stateful: true,
- stateId: 'grid-acls',
-
- // use fixed path
- path: undefined,
-
- initComponent : function() {
- var me = this;
-
- var store = Ext.create('Ext.data.Store',{
- model: 'pve-acl',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/access/acl"
- },
- sorters: {
- property: 'path',
- order: 'DESC'
- }
- });
-
- if (me.path) {
- store.addFilter(Ext.create('Ext.util.Filter',{
- filterFn: function(item) {
- if (item.data.path === me.path) {
- return true;
- }
- }
- }));
- }
-
- var render_ugid = function(ugid, metaData, record) {
- if (record.data.type == 'group') {
- return '@' + ugid;
- }
-
- return ugid;
- };
-
- var columns = [
- {
- header: gettext('User') + '/' + gettext('Group'),
- flex: 1,
- sortable: true,
- renderer: render_ugid,
- dataIndex: 'ugid'
- },
- {
- header: gettext('Role'),
- flex: 1,
- sortable: true,
- dataIndex: 'roleid'
- }
- ];
-
- if (!me.path) {
- columns.unshift({
- header: gettext('Path'),
- flex: 1,
- sortable: true,
- dataIndex: 'path'
- });
- columns.push({
- header: gettext('Propagate'),
- width: 80,
- sortable: true,
- dataIndex: 'propagate'
- });
- }
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- store.load();
- };
-
- var remove_btn = new Proxmox.button.Button({
- text: gettext('Remove'),
- disabled: true,
- selModel: sm,
- confirmMsg: gettext('Are you sure you want to remove this entry'),
- handler: function(btn, event, rec) {
- var params = {
- 'delete': 1,
- path: rec.data.path,
- roles: rec.data.roleid
- };
- if (rec.data.type === 'group') {
- params.groups = rec.data.ugid;
- } else if (rec.data.type === 'user') {
- params.users = rec.data.ugid;
- } else {
- throw 'unknown data type';
- }
-
- Proxmox.Utils.API2Request({
- url: '/access/acl',
- params: params,
- method: 'PUT',
- waitMsgTarget: me,
- callback: function() {
- reload();
- },
- failure: function (response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- }
- });
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: [
- {
- text: gettext('Add'),
- menu: {
- xtype: 'menu',
- items: [
- {
- text: gettext('Group Permission'),
- iconCls: 'fa fa-fw fa-group',
- handler: function() {
- var win = Ext.create('PVE.dc.ACLAdd',{
- aclType: 'group',
- path: me.path
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('User Permission'),
- iconCls: 'fa fa-fw fa-user',
- handler: function() {
- var win = Ext.create('PVE.dc.ACLAdd',{
- aclType: 'user',
- path: me.path
- });
- win.on('destroy', reload);
- win.show();
- }
- }
- ]
- }
- },
- remove_btn
- ],
- viewConfig: {
- trackOver: false
- },
- columns: columns,
- listeners: {
- activate: reload
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-acl', {
- extend: 'Ext.data.Model',
- fields: [
- 'path', 'type', 'ugid', 'roleid',
- {
- name: 'propagate',
- type: 'boolean'
- }
- ]
- });
-
-});
-Ext.define('PVE.dc.AuthView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveAuthView'],
-
- onlineHelp: 'pveum_authentication_realms',
-
- stateful: true,
- stateId: 'grid-authrealms',
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-domains',
- sorters: {
- property: 'realm',
- order: 'DESC'
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.dc.AuthEdit',{
- realm: rec.data.realm,
- authType: rec.data.type
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- baseurl: '/access/domains/',
- selModel: sm,
- enableFn: function(rec) {
- return !(rec.data.type === 'pve' || rec.data.type === 'pam');
- },
- callback: function() {
- reload();
- }
- });
-
- var tbar = [
- {
- text: gettext('Add'),
- menu: new Ext.menu.Menu({
- items: [
- {
- text: gettext('Active Directory Server'),
- handler: function() {
- var win = Ext.create('PVE.dc.AuthEdit', {
- authType: 'ad'
- });
- win.on('destroy', reload);
- win.show();
- }
- },
- {
- text: gettext('LDAP Server'),
- handler: function() {
- var win = Ext.create('PVE.dc.AuthEdit',{
- authType: 'ldap'
- });
- win.on('destroy', reload);
- win.show();
- }
- }
- ]
- })
- },
- edit_btn, remove_btn
- ];
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- tbar: tbar,
- viewConfig: {
- trackOver: false
- },
- columns: [
- {
- header: gettext('Realm'),
- width: 100,
- sortable: true,
- dataIndex: 'realm'
- },
- {
- header: gettext('Type'),
- width: 100,
- sortable: true,
- dataIndex: 'type'
- },
- {
- header: gettext('TFA'),
- width: 100,
- sortable: true,
- dataIndex: 'tfa'
- },
- {
- header: gettext('Comment'),
- sortable: false,
- dataIndex: 'comment',
- renderer: Ext.String.htmlEncode,
- flex: 1
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.AuthEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcAuthEdit'],
-
- isAdd: true,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.realm;
-
- var url;
- var method;
- var serverlist;
-
- if (me.isCreate) {
- url = '/api2/extjs/access/domains';
- method = 'POST';
- } else {
- url = '/api2/extjs/access/domains/' + me.realm;
- method = 'PUT';
- }
-
- var column1 = [
- {
- xtype: me.isCreate ? 'textfield' : 'displayfield',
- name: 'realm',
- fieldLabel: gettext('Realm'),
- value: me.realm,
- allowBlank: false
- }
- ];
-
- if (me.authType === 'ad') {
-
- me.subject = gettext('Active Directory Server');
-
- column1.push({
- xtype: 'textfield',
- name: 'domain',
- fieldLabel: gettext('Domain'),
- emptyText: 'company.net',
- allowBlank: false
- });
-
- } else if (me.authType === 'ldap') {
-
- me.subject = gettext('LDAP Server');
-
- column1.push({
- xtype: 'textfield',
- name: 'base_dn',
- fieldLabel: gettext('Base Domain Name'),
- emptyText: 'CN=Users,DC=Company,DC=net',
- allowBlank: false
- });
-
- column1.push({
- xtype: 'textfield',
- name: 'user_attr',
- emptyText: 'uid / sAMAccountName',
- fieldLabel: gettext('User Attribute Name'),
- allowBlank: false
- });
- } else if (me.authType === 'pve') {
-
- if (me.isCreate) {
- throw 'unknown auth type';
- }
-
- me.subject = 'Proxmox VE authentication server';
-
- } else if (me.authType === 'pam') {
-
- if (me.isCreate) {
- throw 'unknown auth type';
- }
-
- me.subject = 'linux PAM';
-
- } else {
- throw 'unknown auth type ';
- }
-
- column1.push({
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Default'),
- name: 'default',
- uncheckedValue: 0
- });
-
- var column2 = [];
-
- if (me.authType === 'ldap' || me.authType === 'ad') {
- column2.push(
- {
- xtype: 'textfield',
- fieldLabel: gettext('Server'),
- name: 'server1',
- allowBlank: false
- },
- {
- xtype: 'proxmoxtextfield',
- fieldLabel: gettext('Fallback Server'),
- deleteEmpty: !me.isCreate,
- name: 'server2'
- },
- {
- xtype: 'proxmoxintegerfield',
- name: 'port',
- fieldLabel: gettext('Port'),
- minValue: 1,
- maxValue: 65535,
- emptyText: gettext('Default'),
- submitEmptyText: false
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: 'SSL',
- name: 'secure',
- uncheckedValue: 0
- }
- );
- }
-
- // Two Factor Auth settings
-
- column2.push({
- xtype: 'proxmoxKVComboBox',
- name: 'tfa',
- deleteEmpty: !me.isCreate,
- value: '',
- fieldLabel: gettext('TFA'),
- comboItems: [ ['__default__', Proxmox.Utils.noneText], ['oath', 'OATH'], ['yubico', 'Yubico']],
- listeners: {
- change: function(f, value) {
- if (!me.rendered) {
- return;
- }
- me.down('field[name=oath_step]').setVisible(value === 'oath');
- me.down('field[name=oath_digits]').setVisible(value === 'oath');
- me.down('field[name=yubico_api_id]').setVisible(value === 'yubico');
- me.down('field[name=yubico_api_key]').setVisible(value === 'yubico');
- me.down('field[name=yubico_url]').setVisible(value === 'yubico');
- }
- }
- });
-
- column2.push({
- xtype: 'proxmoxintegerfield',
- name: 'oath_step',
- value: '',
- minValue: 10,
- emptyText: Proxmox.Utils.defaultText + ' (30)',
- submitEmptyText: false,
- hidden: true,
- fieldLabel: 'OATH time step'
- });
-
- column2.push({
- xtype: 'proxmoxintegerfield',
- name: 'oath_digits',
- value: '',
- minValue: 6,
- maxValue: 8,
- emptyText: Proxmox.Utils.defaultText + ' (6)',
- submitEmptyText: false,
- hidden: true,
- fieldLabel: 'OATH password length'
- });
-
- column2.push({
- xtype: 'textfield',
- name: 'yubico_api_id',
- hidden: true,
- fieldLabel: 'Yubico API Id'
- });
-
- column2.push({
- xtype: 'textfield',
- name: 'yubico_api_key',
- hidden: true,
- fieldLabel: 'Yubico API Key'
- });
-
- column2.push({
- xtype: 'textfield',
- name: 'yubico_url',
- hidden: true,
- fieldLabel: 'Yubico URL'
- });
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- column1: column1,
- column2: column2,
- columnB: [{
- xtype: 'textfield',
- name: 'comment',
- fieldLabel: gettext('Comment')
- }],
- onGetValues: function(values) {
- if (!values.port) {
- if (!me.isCreate) {
- Proxmox.Utils.assemble_field_data(values, { 'delete': 'port' });
- }
- delete values.port;
- }
-
- if (me.isCreate) {
- values.type = me.authType;
- }
-
- if (values.tfa === 'oath') {
- values.tfa = "type=oath";
- if (values.oath_step) {
- values.tfa += ",step=" + values.oath_step;
- }
- if (values.oath_digits) {
- values.tfa += ",digits=" + values.oath_digits;
- }
- } else if (values.tfa === 'yubico') {
- values.tfa = "type=yubico";
- values.tfa += ",id=" + values.yubico_api_id;
- values.tfa += ",key=" + values.yubico_api_key;
- if (values.yubico_url) {
- values.tfa += ",url=" + values.yubico_url;
- }
- } else {
- delete values.tfa;
- }
-
- delete values.oath_step;
- delete values.oath_digits;
- delete values.yubico_api_id;
- delete values.yubico_api_key;
- delete values.yubico_url;
-
- return values;
- }
- });
-
- Ext.applyIf(me, {
- url: url,
- method: method,
- fieldDefaults: {
- labelWidth: 120
- },
- items: [ ipanel ]
- });
-
- me.callParent();
-
- if (!me.isCreate) {
- me.load({
- success: function(response, options) {
- var data = response.result.data || {};
- // just to be sure (should not happen)
- if (data.type !== me.authType) {
- me.close();
- throw "got wrong auth type";
- }
-
- if (data.tfa) {
- var tfacfg = PVE.Parser.parseTfaConfig(data.tfa);
- data.tfa = tfacfg.type;
- if (tfacfg.type === 'yubico') {
- data.yubico_api_key = tfacfg.key;
- data.yubico_api_id = tfacfg.id;
- data.yubico_url = tfacfg.url;
- } else if (tfacfg.type === 'oath') {
- // step is a number before
- /*jslint confusion: true*/
- data.oath_step = tfacfg.step;
- data.oath_digits = tfacfg.digits;
- /*jslint confusion: false*/
- }
- }
-
- me.setValues(data);
- }
- });
- }
- }
-});
-Ext.define('PVE.dc.BackupEdit', {
- extend: 'Proxmox.window.Edit',
- alias: ['widget.pveDcBackupEdit'],
-
- defaultFocus: undefined,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = !me.jobid;
-
- var url;
- var method;
-
- if (me.isCreate) {
- url = '/api2/extjs/cluster/backup';
- method = 'POST';
- } else {
- url = '/api2/extjs/cluster/backup/' + me.jobid;
- method = 'PUT';
- }
-
- var vmidField = Ext.create('Ext.form.field.Hidden', {
- name: 'vmid'
- });
-
- /*jslint confusion: true*/
- // 'value' can be assigned a string or an array
- var selModeField = Ext.create('Proxmox.form.KVComboBox', {
- xtype: 'proxmoxKVComboBox',
- comboItems: [
- ['include', gettext('Include selected VMs')],
- ['all', gettext('All')],
- ['exclude', gettext('Exclude selected VMs')],
- ['pool', gettext('Pool based')]
- ],
- fieldLabel: gettext('Selection mode'),
- name: 'selMode',
- value: ''
- });
-
- var sm = Ext.create('Ext.selection.CheckboxModel', {
- mode: 'SIMPLE',
- listeners: {
- selectionchange: function(model, selected) {
- var sel = [];
- Ext.Array.each(selected, function(record) {
- sel.push(record.data.vmid);
- });
-
- // to avoid endless recursion suspend the vmidField change
- // event temporary as it calls us again
- vmidField.suspendEvent('change');
- vmidField.setValue(sel);
- vmidField.resumeEvent('change');
- }
- }
- });
-
- var storagesel = Ext.create('PVE.form.StorageSelector', {
- fieldLabel: gettext('Storage'),
- nodename: 'localhost',
- storageContent: 'backup',
- allowBlank: false,
- name: 'storage'
- });
-
- var store = new Ext.data.Store({
- model: 'PVEResources',
- sorters: {
- property: 'vmid',
- order: 'ASC'
- }
- });
-
- var vmgrid = Ext.createWidget('grid', {
- store: store,
- border: true,
- height: 300,
- selModel: sm,
- disabled: true,
- columns: [
- {
- header: 'ID',
- dataIndex: 'vmid',
- width: 60
- },
- {
- header: gettext('Node'),
- dataIndex: 'node'
- },
- {
- header: gettext('Status'),
- dataIndex: 'uptime',
- renderer: function(value) {
- if (value) {
- return Proxmox.Utils.runningText;
- } else {
- return Proxmox.Utils.stoppedText;
- }
- }
- },
- {
- header: gettext('Name'),
- dataIndex: 'name',
- flex: 1
- },
- {
- header: gettext('Type'),
- dataIndex: 'type'
- }
- ]
- });
-
- var selectPoolMembers = function(poolid) {
- if (!poolid) {
- return;
- }
- sm.deselectAll(true);
- store.filter([
- {
- id: 'poolFilter',
- property: 'pool',
- value: poolid
- }
- ]);
- sm.selectAll(true);
- };
-
- var selPool = Ext.create('PVE.form.PoolSelector', {
- fieldLabel: gettext('Pool to backup'),
- hidden: true,
- allowBlank: true,
- name: 'pool',
- listeners: {
- change: function( selpool, newValue, oldValue) {
- selectPoolMembers(newValue);
- }
- }
- });
-
- var nodesel = Ext.create('PVE.form.NodeSelector', {
- name: 'node',
- fieldLabel: gettext('Node'),
- allowBlank: true,
- editable: true,
- autoSelect: false,
- emptyText: '-- ' + gettext('All') + ' --',
- listeners: {
- change: function(f, value) {
- storagesel.setNodename(value || 'localhost');
- var mode = selModeField.getValue();
- store.clearFilter();
- store.filterBy(function(rec) {
- return (!value || rec.get('node') === value);
- });
- if (mode === 'all') {
- sm.selectAll(true);
- }
-
- if (mode === 'pool') {
- selectPoolMembers(selPool.value);
- }
- }
- }
- });
-
- var column1 = [
- nodesel,
- storagesel,
- {
- xtype: 'pveDayOfWeekSelector',
- name: 'dow',
- fieldLabel: gettext('Day of week'),
- multiSelect: true,
- value: ['sat'],
- allowBlank: false
- },
- {
- xtype: 'timefield',
- fieldLabel: gettext('Start Time'),
- name: 'starttime',
- format: 'H:i',
- formatText: 'HH:MM',
- value: '00:00',
- allowBlank: false
- },
- selModeField,
- selPool
- ];
-
- var column2 = [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Send email to'),
- name: 'mailto'
- },
- {
- xtype: 'pveEmailNotificationSelector',
- fieldLabel: gettext('Email notification'),
- name: 'mailnotification',
- deleteEmpty: me.isCreate ? false : true,
- value: me.isCreate ? 'always' : ''
- },
- {
- xtype: 'pveCompressionSelector',
- fieldLabel: gettext('Compression'),
- name: 'compress',
- deleteEmpty: me.isCreate ? false : true,
- value: 'lzo'
- },
- {
- xtype: 'pveBackupModeSelector',
- fieldLabel: gettext('Mode'),
- value: 'snapshot',
- name: 'mode'
- },
- {
- xtype: 'proxmoxcheckbox',
- fieldLabel: gettext('Enable'),
- name: 'enabled',
- uncheckedValue: 0,
- defaultValue: 1,
- checked: true
- },
- vmidField
- ];
- /*jslint confusion: false*/
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- onlineHelp: 'chapter_vzdump',
- column1: column1,
- column2: column2,
- onGetValues: function(values) {
- if (!values.node) {
- if (!me.isCreate) {
- Proxmox.Utils.assemble_field_data(values, { 'delete': 'node' });
- }
- delete values.node;
- }
-
- var selMode = values.selMode;
- delete values.selMode;
-
- if (selMode === 'all') {
- values.all = 1;
- values.exclude = '';
- delete values.vmid;
- } else if (selMode === 'exclude') {
- values.all = 1;
- values.exclude = values.vmid;
- delete values.vmid;
- } else if (selMode === 'pool') {
- delete values.vmid;
- }
-
- if (selMode !== 'pool') {
- delete values.pool;
- }
- return values;
- }
- });
-
- var update_vmid_selection = function(list, mode) {
- if (mode !== 'all' && mode !== 'pool') {
- sm.deselectAll(true);
- if (list) {
- Ext.Array.each(list.split(','), function(vmid) {
- var rec = store.findRecord('vmid', vmid);
- if (rec) {
- sm.select(rec, true);
- }
- });
- }
- }
- };
-
- vmidField.on('change', function(f, value) {
- var mode = selModeField.getValue();
- update_vmid_selection(value, mode);
- });
-
- selModeField.on('change', function(f, value, oldValue) {
- if (oldValue === 'pool') {
- store.removeFilter('poolFilter');
- }
-
- if (oldValue === 'all') {
- sm.deselectAll(true);
- vmidField.setValue('');
- }
-
- if (value === 'all') {
- sm.selectAll(true);
- vmgrid.setDisabled(true);
- } else {
- vmgrid.setDisabled(false);
- }
-
- if (value === 'pool') {
- vmgrid.setDisabled(true);
- vmidField.setValue('');
- selPool.setVisible(true);
- selPool.allowBlank = false;
- selectPoolMembers(selPool.value);
-
- } else {
- selPool.setVisible(false);
- selPool.allowBlank = true;
- }
- var list = vmidField.getValue();
- update_vmid_selection(list, value);
- });
-
- var reload = function() {
- store.load({
- params: { type: 'vm' },
- callback: function() {
- var node = nodesel.getValue();
- store.clearFilter();
- store.filterBy(function(rec) {
- return (!node || node.length === 0 || rec.get('node') === node);
- });
- var list = vmidField.getValue();
- var mode = selModeField.getValue();
- if (mode === 'all') {
- sm.selectAll(true);
- } else if (mode === 'pool'){
- selectPoolMembers(selPool.value);
- } else {
- update_vmid_selection(list, mode);
- }
- }
- });
- };
-
- Ext.applyIf(me, {
- subject: gettext("Backup Job"),
- url: url,
- method: method,
- items: [ ipanel, vmgrid ]
- });
-
- me.callParent();
-
- if (me.isCreate) {
- selModeField.setValue('include');
- } else {
- me.load({
- success: function(response, options) {
- var data = response.result.data;
-
- data.dow = data.dow.split(',');
-
- if (data.all || data.exclude) {
- if (data.exclude) {
- data.vmid = data.exclude;
- data.selMode = 'exclude';
- } else {
- data.vmid = '';
- data.selMode = 'all';
- }
- } else if (data.pool) {
- data.selMode = 'pool';
- data.selPool = data.pool;
- } else {
- data.selMode = 'include';
- }
-
- me.setValues(data);
- }
- });
- }
-
- reload();
- }
-});
-
-
-Ext.define('PVE.dc.BackupView', {
- extend: 'Ext.grid.GridPanel',
-
- alias: ['widget.pveDcBackupView'],
-
- onlineHelp: 'chapter_vzdump',
-
- allText: '-- ' + gettext('All') + ' --',
- allExceptText: gettext('All except {0}'),
-
- initComponent : function() {
- var me = this;
-
- var store = new Ext.data.Store({
- model: 'pve-cluster-backup',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/backup"
- }
- });
-
- var reload = function() {
- store.load();
- };
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
-
- var win = Ext.create('PVE.dc.BackupEdit',{
- jobid: rec.data.id
- });
- win.on('destroy', reload);
- win.show();
- };
-
- var edit_btn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: '/cluster/backup',
- callback: function() {
- reload();
- }
- });
-
- Proxmox.Utils.monStoreErrors(me, store);
-
- Ext.apply(me, {
- store: store,
- selModel: sm,
- stateful: true,
- stateId: 'grid-dc-backup',
- viewConfig: {
- trackOver: false
- },
- tbar: [
- {
- text: gettext('Add'),
- handler: function() {
- var win = Ext.create('PVE.dc.BackupEdit',{});
- win.on('destroy', reload);
- win.show();
- }
- },
- remove_btn,
- edit_btn
- ],
- columns: [
- {
- header: gettext('Enabled'),
- width: 80,
- dataIndex: 'enabled',
- xtype: 'checkcolumn',
- sortable: true,
- disabled: true,
- disabledCls: 'x-item-enabled',
- stopSelection: false
- },
- {
- header: gettext('Node'),
- width: 100,
- sortable: true,
- dataIndex: 'node',
- renderer: function(value) {
- if (value) {
- return value;
- }
- return me.allText;
- }
- },
- {
- header: gettext('Day of week'),
- width: 200,
- sortable: false,
- dataIndex: 'dow',
- renderer: function(val) {
- var dows = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
- var selected = [];
- var cur = -1;
- val.split(',').forEach(function(day){
- cur++;
- var dow = (dows.indexOf(day)+6)%7;
- if (cur === dow) {
- if (selected.length === 0 || selected[selected.length-1] === 0) {
- selected.push(1);
- } else {
- selected[selected.length-1]++;
- }
- } else {
- while (cur < dow) {
- cur++;
- selected.push(0);
- }
- selected.push(1);
- }
- });
-
- cur = -1;
- var days = [];
- selected.forEach(function(item) {
- cur++;
- if (item > 2) {
- days.push(Ext.Date.dayNames[(cur+1)] + '-' + Ext.Date.dayNames[(cur+item)%7]);
- cur += item-1;
- } else if (item == 2) {
- days.push(Ext.Date.dayNames[cur+1]);
- days.push(Ext.Date.dayNames[(cur+2)%7]);
- cur++;
- } else if (item == 1) {
- days.push(Ext.Date.dayNames[(cur+1)%7]);
- }
- });
- return days.join(', ');
- }
- },
- {
- header: gettext('Start Time'),
- width: 60,
- sortable: true,
- dataIndex: 'starttime'
- },
- {
- header: gettext('Storage'),
- width: 100,
- sortable: true,
- dataIndex: 'storage'
- },
- {
- header: gettext('Selection'),
- flex: 1,
- sortable: false,
- dataIndex: 'vmid',
- renderer: function(value, metaData, record) {
- /*jslint confusion: true */
- if (record.data.all) {
- if (record.data.exclude) {
- return Ext.String.format(me.allExceptText, record.data.exclude);
- }
- return me.allText;
- }
- if (record.data.vmid) {
- return record.data.vmid;
- }
-
- if (record.data.pool) {
- return "Pool '"+ record.data.pool + "'";
- }
-
- return "-";
- }
- }
- ],
- listeners: {
- activate: reload,
- itemdblclick: run_editor
- }
- });
-
- me.callParent();
- }
-}, function() {
-
- Ext.define('pve-cluster-backup', {
- extend: 'Ext.data.Model',
- fields: [
- 'id', 'starttime', 'dow',
- 'storage', 'node', 'vmid', 'exclude',
- 'mailto', 'pool',
- { name: 'enabled', type: 'boolean' },
- { name: 'all', type: 'boolean' },
- { name: 'snapshot', type: 'boolean' },
- { name: 'stop', type: 'boolean' },
- { name: 'suspend', type: 'boolean' },
- { name: 'compress', type: 'boolean' }
- ]
- });
-});
-Ext.define('PVE.dc.Support', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveDcSupport',
- pveGuidePath: '/pve-docs/index.html',
- onlineHelp: 'getting_help',
-
- invalidHtml: 'No valid subscription ' + PVE.Utils.noSubKeyHtml,
-
- communityHtml: 'Please use the public community forum for any questions.',
-
- activeHtml: 'Please use our support portal for any questions. You can also use the public community forum to get additional information.',
-
- bugzillaHtml: 'Bug Tracking Our bug tracking system is available here .',
-
- docuHtml: function() {
- var me = this;
- var guideUrl = window.location.origin + me.pveGuidePath;
- var text = Ext.String.format('Documentation '
- + 'The official Proxmox VE Administration Guide'
- + ' is included with this installation and can be browsed at '
- + '{0} ', guideUrl);
- return text;
- },
-
- updateActive: function(data) {
- var me = this;
-
- var html = '' + data.productname + ' ' + me.activeHtml;
- html += ' ' + me.docuHtml();
- html += ' ' + me.bugzillaHtml;
-
- me.update(html);
- },
-
- updateCommunity: function(data) {
- var me = this;
-
- var html = '' + data.productname + ' ' + me.communityHtml;
- html += ' ' + me.docuHtml();
- html += ' ' + me.bugzillaHtml;
-
- me.update(html);
- },
-
- updateInactive: function(data) {
- var me = this;
- me.update(me.invalidHtml);
- },
-
- initComponent: function() {
- var me = this;
-
- var reload = function() {
- Proxmox.Utils.API2Request({
- url: '/nodes/localhost/subscription',
- method: 'GET',
- waitMsgTarget: me,
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- me.update('Unable to load subscription status' + ": " + response.htmlStatus);
- },
- success: function(response, opts) {
- var data = response.result.data;
-
- if (data.status === 'Active') {
- if (data.level === 'c') {
- me.updateCommunity(data);
- } else {
- me.updateActive(data);
- }
- } else {
- me.updateInactive(data);
- }
- }
- });
- };
-
- Ext.apply(me, {
- autoScroll: true,
- bodyStyle: 'padding:10px',
- listeners: {
- activate: reload
- }
- });
-
- me.callParent();
- }
-});
-Ext.define('pve-security-groups', {
- extend: 'Ext.data.Model',
-
- fields: [ 'group', 'comment', 'digest' ],
- idProperty: 'group'
-});
-
-Ext.define('PVE.SecurityGroupEdit', {
- extend: 'Proxmox.window.Edit',
-
- base_url: "/cluster/firewall/groups",
-
- allow_iface: false,
-
- initComponent : function() {
- var me = this;
-
- me.isCreate = (me.group_name === undefined);
-
- var subject;
-
- me.url = '/api2/extjs' + me.base_url;
- me.method = 'POST';
-
- var items = [
- {
- xtype: 'textfield',
- name: 'group',
- value: me.group_name || '',
- fieldLabel: gettext('Name'),
- allowBlank: false
- },
- {
- xtype: 'textfield',
- name: 'comment',
- value: me.group_comment || '',
- fieldLabel: gettext('Comment')
- }
- ];
-
- if (me.isCreate) {
- subject = gettext('Security Group');
- } else {
- subject = gettext('Security Group') + " '" + me.group_name + "'";
- items.push({
- xtype: 'hiddenfield',
- name: 'rename',
- value: me.group_name
- });
- }
-
- var ipanel = Ext.create('Proxmox.panel.InputPanel', {
- // InputPanel does not have a 'create' property, does it need a 'isCreate'
- isCreate: me.isCreate,
- items: items
- });
-
-
- Ext.apply(me, {
- subject: subject,
- items: [ ipanel ]
- });
-
- me.callParent();
- }
-});
-
-Ext.define('PVE.SecurityGroupList', {
- extend: 'Ext.grid.Panel',
- alias: 'widget.pveSecurityGroupList',
-
- stateful: true,
- stateId: 'grid-securitygroups',
-
- rule_panel: undefined,
-
- addBtn: undefined,
- removeBtn: undefined,
- editBtn: undefined,
-
- base_url: "/cluster/firewall/groups",
-
- initComponent: function() {
- /*jslint confusion: true */
- var me = this;
-
- if (me.rule_panel == undefined) {
- throw "no rule panel specified";
- }
-
- if (me.base_url == undefined) {
- throw "no base_url specified";
- }
-
- var store = new Ext.data.Store({
- model: 'pve-security-groups',
- proxy: {
- type: 'proxmox',
- url: '/api2/json' + me.base_url
- },
- sorters: {
- property: 'group',
- order: 'DESC'
- }
- });
-
- var sm = Ext.create('Ext.selection.RowModel', {});
-
- var reload = function() {
- var oldrec = sm.getSelection()[0];
- store.load(function(records, operation, success) {
- if (oldrec) {
- var rec = store.findRecord('group', oldrec.data.group);
- if (rec) {
- sm.select(rec);
- }
- }
- });
- };
-
- var run_editor = function() {
- var rec = sm.getSelection()[0];
- if (!rec) {
- return;
- }
- var win = Ext.create('PVE.SecurityGroupEdit', {
- digest: rec.data.digest,
- group_name: rec.data.group,
- group_comment: rec.data.comment
- });
- win.show();
- win.on('destroy', reload);
- };
-
- me.editBtn = new Proxmox.button.Button({
- text: gettext('Edit'),
- disabled: true,
- selModel: sm,
- handler: run_editor
- });
-
- me.addBtn = new Proxmox.button.Button({
- text: gettext('Create'),
- handler: function() {
- sm.deselectAll();
- var win = Ext.create('PVE.SecurityGroupEdit', {});
- win.show();
- win.on('destroy', reload);
- }
- });
-
- me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
- selModel: sm,
- baseurl: me.base_url + '/',
- enableFn: function(rec) {
- return (rec && me.base_url);
- },
- callback: function() {
- reload();
- }
- });
-
- Ext.apply(me, {
- store: store,
- tbar: [ '' + gettext('Group') + ': ', me.addBtn, me.removeBtn, me.editBtn ],
- selModel: sm,
- columns: [
- { header: gettext('Group'), dataIndex: 'group', width: '100' },
- { header: gettext('Comment'), dataIndex: 'comment', renderer: Ext.String.htmlEncode, flex: 1 }
- ],
- listeners: {
- itemdblclick: run_editor,
- select: function(sm, rec) {
- var url = '/cluster/firewall/groups/' + rec.data.group;
- me.rule_panel.setBaseUrl(url);
- },
- deselect: function() {
- me.rule_panel.setBaseUrl(undefined);
- },
- show: reload
- }
- });
-
- me.callParent();
-
- store.load();
- }
-});
-
-Ext.define('PVE.SecurityGroups', {
- extend: 'Ext.panel.Panel',
- alias: 'widget.pveSecurityGroups',
-
- title: 'Security Groups',
-
- initComponent: function() {
- var me = this;
-
- var rule_panel = Ext.createWidget('pveFirewallRules', {
- region: 'center',
- allow_groups: false,
- list_refs_url: '/cluster/firewall/refs',
- tbar_prefix: '' + gettext('Rules') + ': ',
- border: false
- });
-
- var sglist = Ext.createWidget('pveSecurityGroupList', {
- region: 'west',
- rule_panel: rule_panel,
- width: '25%',
- border: false,
- split: true
- });
-
-
- Ext.apply(me, {
- layout: 'border',
- items: [ sglist, rule_panel ],
- listeners: {
- show: function() {
- sglist.fireEvent('show', sglist);
- }
- }
- });
-
- me.callParent();
- }
-});
-/*
- * Datacenter config panel, located in the center of the ViewPort after the Datacenter view is selected
- */
-
-Ext.define('PVE.dc.Config', {
- extend: 'PVE.panel.Config',
- alias: 'widget.PVE.dc.Config',
-
- onlineHelp: 'pve_admin_guide',
-
- initComponent: function() {
- var me = this;
-
- var caps = Ext.state.Manager.get('GuiCap');
-
- me.items = [];
-
- Ext.apply(me, {
- title: gettext("Datacenter"),
- hstateid: 'dctab'
- });
-
- if (caps.dc['Sys.Audit']) {
- me.items.push({
- title: gettext('Summary'),
- xtype: 'pveDcSummary',
- iconCls: 'fa fa-book',
- itemId: 'summary'
- },
- {
- title: gettext('Cluster'),
- xtype: 'pveClusterAdministration',
- iconCls: 'fa fa-server',
- itemId: 'cluster'
- },
- {
- title: 'Ceph',
- itemId: 'ceph',
- iconCls: 'fa fa-ceph',
- xtype: 'pveNodeCephStatus'
- },
- {
- xtype: 'pveDcOptionView',
- title: gettext('Options'),
- iconCls: 'fa fa-gear',
- itemId: 'options'
- });
- }
-
- if (caps.storage['Datastore.Allocate'] || caps.dc['Sys.Audit']) {
- me.items.push({
- xtype: 'pveStorageView',
- title: gettext('Storage'),
- iconCls: 'fa fa-database',
- itemId: 'storage'
- });
- }
-
- if (caps.dc['Sys.Audit']) {
- me.items.push({
- xtype: 'pveDcBackupView',
- iconCls: 'fa fa-floppy-o',
- title: gettext('Backup'),
- itemId: 'backup'
- },
- {
- xtype: 'pveReplicaView',
- iconCls: 'fa fa-retweet',
- title: gettext('Replication'),
- itemId: 'replication'
- },
- {
- xtype: 'pveACLView',
- title: gettext('Permissions'),
- iconCls: 'fa fa-unlock',
- itemId: 'permissions',
- expandedOnInit: true
- });
- }
-
- me.items.push({
- xtype: 'pveUserView',
- groups: ['permissions'],
- iconCls: 'fa fa-user',
- title: gettext('Users'),
- itemId: 'users'
- });
-
- if (caps.dc['Sys.Audit']) {
- me.items.push({
- xtype: 'pveGroupView',
- title: gettext('Groups'),
- iconCls: 'fa fa-users',
- groups: ['permissions'],
- itemId: 'groups'
- },
- {
- xtype: 'pvePoolView',
- title: gettext('Pools'),
- iconCls: 'fa fa-tags',
- groups: ['permissions'],
- itemId: 'pools'
- },
- {
- xtype: 'pveRoleView',
- title: gettext('Roles'),
- iconCls: 'fa fa-male',
- groups: ['permissions'],
- itemId: 'roles'
- },
- {
- xtype: 'pveAuthView',
- title: gettext('Authentication'),
- groups: ['permissions'],
- iconCls: 'fa fa-key',
- itemId: 'domains'
- },
- {
- xtype: 'pveHAStatus',
- title: 'HA',
- iconCls: 'fa fa-heartbeat',
- itemId: 'ha'
- },
- {
- title: gettext('Groups'),
- groups: ['ha'],
- xtype: 'pveHAGroupsView',
- iconCls: 'fa fa-object-group',
- itemId: 'ha-groups'
- },
- {
- title: gettext('Fencing'),
- groups: ['ha'],
- iconCls: 'fa fa-bolt',
- xtype: 'pveFencingView',
- itemId: 'ha-fencing'
- },
- {
- xtype: 'pveFirewallRules',
- title: gettext('Firewall'),
- allow_iface: true,
- base_url: '/cluster/firewall/rules',
- list_refs_url: '/cluster/firewall/refs',
- iconCls: 'fa fa-shield',
- itemId: 'firewall'
- },
- {
- xtype: 'pveFirewallOptions',
- title: gettext('Options'),
- groups: ['firewall'],
- iconCls: 'fa fa-gear',
- base_url: '/cluster/firewall/options',
- onlineHelp: 'pve_firewall_cluster_wide_setup',
- fwtype: 'dc',
- itemId: 'firewall-options'
- },
- {
- xtype: 'pveSecurityGroups',
- title: gettext('Security Group'),
- groups: ['firewall'],
- iconCls: 'fa fa-group',
- itemId: 'firewall-sg'
- },
- {
- xtype: 'pveFirewallAliases',
- title: gettext('Alias'),
- groups: ['firewall'],
- iconCls: 'fa fa-external-link',
- base_url: '/cluster/firewall/aliases',
- itemId: 'firewall-aliases'
- },
- {
- xtype: 'pveIPSet',
- title: 'IPSet',
- groups: ['firewall'],
- iconCls: 'fa fa-list-ol',
- base_url: '/cluster/firewall/ipset',
- list_refs_url: '/cluster/firewall/refs',
- itemId: 'firewall-ipset'
- },
- {
- xtype: 'pveDcSupport',
- title: gettext('Support'),
- itemId: 'support',
- iconCls: 'fa fa-comments-o'
- });
- }
-
- me.callParent();
- }
-});
-Ext.define('PVE.dc.NodeView', {
- extend: 'Ext.grid.GridPanel',
- alias: 'widget.pveDcNodeView',
-
- title: gettext('Nodes'),
- disableSelection: true,
- scrollable: true,
-
- columns: [
- {
- header: gettext('Name'),
- flex: 1,
- sortable: true,
- dataIndex: 'name'
- },
- {
- header: 'ID',
- width: 40,
- sortable: true,
- dataIndex: 'nodeid'
- },
- {
- header: gettext('Online'),
- width: 60,
- sortable: true,
- dataIndex: 'online',
- renderer: function(value) {
- var cls = (value)?'good':'critical';
- return ' ';
- }
- },
- {
- header: gettext('Support'),
- width: 100,
- sortable: true,
- dataIndex: 'level',
- renderer: PVE.Utils.render_support_level
- },
- {
- header: gettext('Server Address'),
- width: 115,
- sortable: true,
- dataIndex: 'ip'
- },
- {
- header: gettext('CPU usage'),
- sortable: true,
- width: 110,
- dataIndex: 'cpuusage',
- tdCls: 'x-progressbar-default-cell',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Memory usage'),
- width: 110,
- sortable: true,
- tdCls: 'x-progressbar-default-cell',
- dataIndex: 'memoryusage',
- xtype: 'widgetcolumn',
- widget: {
- xtype: 'pveProgressBar'
- }
- },
- {
- header: gettext('Uptime'),
- sortable: true,
- dataIndex: 'uptime',
- align: 'right',
- renderer: Proxmox.Utils.render_uptime
- }
- ],
-
- stateful: true,
- stateId: 'grid-cluster-nodes',
- tools: [
- {
- type: 'up',
- handler: function(){
- var me = this.up('grid');
- var height = Math.max(me.getHeight()-50, 250);
- me.setHeight(height);
- }
- },
- {
- type: 'down',
- handler: function(){
- var me = this.up('grid');
- var height = me.getHeight()+50;
- me.setHeight(height);
- }
- }
- ]
-}, function() {
-
- Ext.define('pve-dc-nodes', {
- extend: 'Ext.data.Model',
- fields: [ 'id', 'type', 'name', 'nodeid', 'ip', 'level', 'local', 'online'],
- idProperty: 'id'
- });
-
-});
-
-Ext.define('PVE.widget.ProgressBar',{
- extend: 'Ext.Progress',
- alias: 'widget.pveProgressBar',
-
- animate: true,
- textTpl: [
- '{percent}%'
- ],
-
- setValue: function(value){
- var me = this;
- me.callParent([value]);
-
- me.removeCls(['warning', 'critical']);
-
- if (value > 0.89) {
- me.addCls('critical');
- } else if (value > 0.59) {
- me.addCls('warning');
- }
- }
-});
-/*jslint confusion: true*/
-Ext.define('pve-cluster-nodes', {
- extend: 'Ext.data.Model',
- fields: [
- 'node', { type: 'integer', name: 'nodeid' }, 'ring0_addr', 'ring1_addr',
- { type: 'integer', name: 'quorum_votes' }
- ],
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/config/nodes"
- },
- idProperty: 'nodeid'
-});
-
-Ext.define('pve-cluster-info', {
- extend: 'Ext.data.Model',
- proxy: {
- type: 'proxmox',
- url: "/api2/json/cluster/config/join"
- }
-});
-
-Ext.define('PVE.ClusterAdministration', {
- extend: 'Ext.panel.Panel',
- xtype: 'pveClusterAdministration',
-
- title: gettext('Cluster Administration'),
- onlineHelp: 'chapter_pvecm',
-
- border: false,
- defaults: { border: false },
-
- viewModel: {
- parent: null,
- data: {
- totem: {},
- nodelist: [],
- preferred_node: {
- name: '',
- fp: '',
- addr: ''
- },
- isInCluster: false,
- nodecount: 0
- }
- },
-
- items: [
- {
- xtype: 'panel',
- title: gettext('Cluster Information'),
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.store = Ext.create('Proxmox.data.UpdateStore', {
- autoStart: true,
- interval: 15 * 1000,
- storeid: 'pve-cluster-info',
- model: 'pve-cluster-info'
- });
- view.store.on('load', this.onLoad, this);
- view.on('destroy', view.store.stopUpdate);
- },
-
- onLoad: function(store, records, success) {
- var vm = this.getViewModel();
- if (!success || !records || !records[0].data) {
- vm.set('totem', {});
- vm.set('isInCluster', false);
- vm.set('nodelist', []);
- vm.set('preferred_node', {
- name: '',
- addr: '',
- fp: ''
- });
- return;
- }
- var data = records[0].data;
- vm.set('totem', data.totem);
- vm.set('isInCluster', !!data.totem.cluster_name);
- vm.set('nodelist', data.nodelist);
-
- var nodeinfo = Ext.Array.findBy(data.nodelist, function (el) {
- return el.name === data.preferred_node;
- });
-
- vm.set('preferred_node', {
- name: data.preferred_node,
- addr: nodeinfo.pve_addr,
- ring_addr: [ nodeinfo.ring0_addr, nodeinfo.ring1_addr ],
- fp: nodeinfo.pve_fp
- });
- },
-
- onCreate: function() {
- var view = this.getView();
- view.store.stopUpdate();
- var win = Ext.create('PVE.ClusterCreateWindow', {
- autoShow: true,
- listeners: {
- destroy: function() {
- view.store.startUpdate();
- }
- }
- });
- },
-
- onClusterInfo: function() {
- var vm = this.getViewModel();
- var win = Ext.create('PVE.ClusterInfoWindow', {
- joinInfo: {
- ipAddress: vm.get('preferred_node.addr'),
- fingerprint: vm.get('preferred_node.fp'),
- ring_addr: vm.get('preferred_node.ring_addr'),
- totem: vm.get('totem')
- }
- });
- win.show();
- },
-
- onJoin: function() {
- var view = this.getView();
- view.store.stopUpdate();
- var win = Ext.create('PVE.ClusterJoinNodeWindow', {
- autoShow: true,
- listeners: {
- destroy: function() {
- view.store.startUpdate();
- }
- }
- });
- }
- },
- tbar: [
- {
- text: gettext('Create Cluster'),
- reference: 'createButton',
- handler: 'onCreate',
- bind: {
- disabled: '{isInCluster}'
- }
- },
- {
- text: gettext('Join Information'),
- reference: 'addButton',
- handler: 'onClusterInfo',
- bind: {
- disabled: '{!isInCluster}'
- }
- },
- {
- text: gettext('Join Cluster'),
- reference: 'joinButton',
- handler: 'onJoin',
- bind: {
- disabled: '{isInCluster}'
- }
- }
- ],
- layout: 'hbox',
- bodyPadding: 5,
- items: [
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Cluster Name'),
- bind: {
- value: '{totem.cluster_name}',
- hidden: '{!isInCluster}'
- },
- flex: 1
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Config Version'),
- bind: {
- value: '{totem.config_version}',
- hidden: '{!isInCluster}'
- },
- flex: 1
- },
- {
- xtype: 'displayfield',
- fieldLabel: gettext('Number of Nodes'),
- labelWidth: 120,
- bind: {
- value: '{nodecount}',
- hidden: '{!isInCluster}'
- },
- flex: 1
- },
- {
- xtype: 'displayfield',
- value: gettext('Standalone node - no cluster defined'),
- bind: {
- hidden: '{isInCluster}'
- },
- flex: 1
- }
- ]
- },
- {
- xtype: 'grid',
- title: gettext('Cluster Nodes'),
- controller: {
- xclass: 'Ext.app.ViewController',
-
- init: function(view) {
- view.rstore = Ext.create('Proxmox.data.UpdateStore', {
- autoLoad: true,
- xtype: 'update',
- interval: 5 * 1000,
- autoStart: true,
- storeid: 'pve-cluster-nodes',
- model: 'pve-cluster-nodes'
- });
- view.setStore(Ext.create('Proxmox.data.DiffStore', {
- rstore: view.rstore,
- sorters: {
- property: 'nodeid',
- order: 'DESC'
- }
- }));
- Proxmox.Utils.monStoreErrors(view, view.rstore);
- view.rstore.on('load', this.onLoad, this);
- view.on('destroy', view.rstore.stopUpdate);
- },
-
- onLoad: function(store, records, success) {
- var vm = this.getViewModel();
- if (!success || !records) {
- vm.set('nodecount', 0);
- return;
- }
- vm.set('nodecount', records.length);
- }
- },
- columns: [
- {
- header: gettext('Nodename'),
- flex: 2,
- dataIndex: 'name'
- },
- {
- header: gettext('ID'),
- flex: 1,
- dataIndex: 'nodeid'
- },
- {
- header: gettext('Votes'),
- flex: 1,
- dataIndex: 'quorum_votes'
- },
- {
- header: Ext.String.format(gettext('Link {0}'), 0),
- flex: 2,
- dataIndex: 'ring0_addr'
- },
- {
- header: Ext.String.format(gettext('Link {0}'), 1),
- flex: 2,
- dataIndex: 'ring1_addr'
- }
- ]
- }
- ]
-});
-/*jslint confusion: true*/
-Ext.define('PVE.ClusterCreateWindow', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveClusterCreateWindow',
-
- title: gettext('Create Cluster'),
- width: 600,
-
- method: 'POST',
- url: '/cluster/config',
-
- isCreate: true,
- subject: gettext('Cluster'),
- showTaskViewer: true,
-
- onlineHelp: 'pvecm_create_cluster',
-
- items: {
- xtype: 'inputpanel',
- items: [{
- xtype: 'textfield',
- fieldLabel: gettext('Cluster Name'),
- allowBlank: false,
- name: 'clustername'
- },
- {
- xtype: 'proxmoxNetworkSelector',
- fieldLabel: Ext.String.format(gettext('Link {0}'), 0),
- emptyText: gettext("Optional, defaults to IP resolved by node's hostname"),
- name: 'link0',
- autoSelect: false,
- valueField: 'address',
- displayField: 'address',
- skipEmptyText: true
- }],
- advancedItems: [{
- xtype: 'proxmoxNetworkSelector',
- fieldLabel: Ext.String.format(gettext('Link {0}'), 1),
- emptyText: gettext("Optional second link for redundancy"),
- name: 'link1',
- autoSelect: false,
- valueField: 'address',
- displayField: 'address',
- skipEmptyText: true
- }]
- }
-});
-
-Ext.define('PVE.ClusterInfoWindow', {
- extend: 'Ext.window.Window',
- xtype: 'pveClusterInfoWindow',
- mixins: ['Proxmox.Mixin.CBind'],
-
- width: 800,
- modal: true,
- resizable: false,
- title: gettext('Cluster Join Information'),
-
- joinInfo: {
- ipAddress: undefined,
- fingerprint: undefined,
- totem: {}
- },
-
- items: [
- {
- xtype: 'component',
- border: false,
- padding: '10 10 10 10',
- html: gettext("Copy the Join Information here and use it on the node you want to add.")
- },
- {
- xtype: 'container',
- layout: 'form',
- border: false,
- padding: '0 10 10 10',
- items: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('IP Address'),
- cbind: { value: '{joinInfo.ipAddress}' },
- editable: false
- },
- {
- xtype: 'textfield',
- fieldLabel: gettext('Fingerprint'),
- cbind: { value: '{joinInfo.fingerprint}' },
- editable: false
- },
- {
- xtype: 'textarea',
- inputId: 'pveSerializedClusterInfo',
- fieldLabel: gettext('Join Information'),
- grow: true,
- cbind: { joinInfo: '{joinInfo}' },
- editable: false,
- listeners: {
- afterrender: function(field) {
- if (!field.joinInfo) {
- return;
- }
- var jsons = Ext.JSON.encode(field.joinInfo);
- var base64s = Ext.util.Base64.encode(jsons);
- field.setValue(base64s);
- }
- }
- }
- ]
- }
- ],
- dockedItems: [{
- dock: 'bottom',
- xtype: 'toolbar',
- items: [{
- xtype: 'button',
- handler: function(b) {
- var el = document.getElementById('pveSerializedClusterInfo');
- el.select();
- document.execCommand("copy");
- },
- text: gettext('Copy Information')
- }]
- }]
-});
-
-Ext.define('PVE.ClusterJoinNodeWindow', {
- extend: 'Proxmox.window.Edit',
- xtype: 'pveClusterJoinNodeWindow',
-
- title: gettext('Cluster Join'),
- width: 800,
-
- method: 'POST',
- url: '/cluster/config/join',
-
- defaultFocus: 'textarea[name=serializedinfo]',
- isCreate: true,
- submitText: gettext('Join'),
- showTaskViewer: true,
-
- onlineHelp: 'chapter_pvecm',
-
- viewModel: {
- parent: null,
- data: {
- info: {
- fp: '',
- ip: '',
- ring0Needed: false,
- ring1Possible: false,
- ring1Needed: false
- }
- },
- formulas: {
- ring0EmptyText: function(get) {
- if (get('info.ring0Needed')) {
- return gettext("Cannot use default address safely");
- } else {
- return gettext("Default: IP resolved by node's hostname");
- }
- }
- }
- },
-
- controller: {
- xclass: 'Ext.app.ViewController',
- control: {
- '#': {
- close: function() {
- delete PVE.Utils.silenceAuthFailures;
- }
- },
- 'proxmoxcheckbox[name=assistedEntry]': {
- change: 'onInputTypeChange'
- },
- 'textarea[name=serializedinfo]': {
- change: 'recomputeSerializedInfo',
- enable: 'resetField'
- },
- 'proxmoxtextfield[name=ring1_addr]': {
- enable: 'ring1Needed'
- },
- 'textfield': {
- disable: 'resetField'
- }
- },
- resetField: function(field) {
- field.reset();
- },
- ring1Needed: function(f) {
- var vm = this.getViewModel();
- f.allowBlank = !vm.get('info.ring1Needed');
- },
- onInputTypeChange: function(field, assistedInput) {
- var vm = this.getViewModel();
- if (!assistedInput) {
- vm.set('info.ring1Possible', true);
- }
- },
- recomputeSerializedInfo: function(field, value) {
- var vm = this.getViewModel();
- var jsons = Ext.util.Base64.decode(value);
- var joinInfo = Ext.JSON.decode(jsons, true);
-
- var info = {
- fp: '',
- ring1Needed: false,
- ring1Possible: false,
- ip: ''
- };
-
- var totem = {};
- if (!(joinInfo && joinInfo.totem)) {
- field.valid = false;
- } else {
- var ring0Needed = false;
- if (joinInfo.ring_addr !== undefined) {
- ring0Needed = joinInfo.ring_addr[0] !== joinInfo.ipAddress;
- }
-
- info = {
- ip: joinInfo.ipAddress,
- fp: joinInfo.fingerprint,
- ring0Needed: ring0Needed,
- ring1Possible: !!joinInfo.totem['interface']['1'],
- ring1Needed: !!joinInfo.totem['interface']['1']
- };
- totem = joinInfo.totem;
- field.valid = true;
- }
-
- vm.set('info', info);
- }
- },
-
- submit: function() {
- // joining may produce temporarily auth failures, ignore as long the task runs
- PVE.Utils.silenceAuthFailures = true;
- this.callParent();
- },
-
- taskDone: function(success) {
- delete PVE.Utils.silenceAuthFailures;
- if (success) {
- var txt = gettext('Cluster join task finished, node certificate may have changed, reload GUI!');
- // ensure user cannot do harm
- Ext.getBody().mask(txt, ['pve-static-mask']);
- // TaskView may hide above mask, so tell him directly
- Ext.Msg.show({
- title: gettext('Join Task Finished'),
- icon: Ext.Msg.INFO,
- msg: txt
- });
- // reload always (if user wasn't faster), but wait a bit for pveproxy
- Ext.defer(function() {
- window.location.reload(true);
- }, 5000);
- }
- },
-
- items: [{
- xtype: 'proxmoxcheckbox',
- reference: 'assistedEntry',
- name: 'assistedEntry',
- submitValue: false,
- value: true,
- autoEl: {
- tag: 'div',
- 'data-qtip': gettext('Select if join information should be extracted from pasted cluster information, deselect for manual entering')
- },
- boxLabel: gettext('Assisted join: Paste encoded cluster join information and enter password.')
- },
- {
- xtype: 'textarea',
- name: 'serializedinfo',
- submitValue: false,
- allowBlank: false,
- fieldLabel: gettext('Information'),
- emptyText: gettext('Paste encoded Cluster Information here'),
- validator: function(val) {
- return val === '' || this.valid ||
- gettext('Does not seem like a valid encoded Cluster Information!');
- },
- bind: {
- disabled: '{!assistedEntry.checked}',
- hidden: '{!assistedEntry.checked}'
- },
- value: ''
- },
- {
- xtype: 'inputpanel',
- column1: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Peer Address'),
- allowBlank: false,
- bind: {
- value: '{info.ip}',
- readOnly: '{assistedEntry.checked}'
- },
- name: 'hostname'
- },
- {
- xtype: 'textfield',
- inputType: 'password',
- emptyText: gettext("Peer's root password"),
- fieldLabel: gettext('Password'),
- allowBlank: false,
- name: 'password'
- }
- ],
- column2: [
- {
- xtype: 'proxmoxNetworkSelector',
- fieldLabel: Ext.String.format(gettext('Link {0}'), 0),
- bind: {
- emptyText: '{ring0EmptyText}',
- allowBlank: '{!info.ring0Needed}'
- },
- skipEmptyText: true,
- autoSelect: false,
- valueField: 'address',
- displayField: 'address',
- name: 'link0'
- },
- {
- xtype: 'proxmoxNetworkSelector',
- fieldLabel: Ext.String.format(gettext('Link {0}'), 1),
- skipEmptyText: true,
- autoSelect: false,
- valueField: 'address',
- displayField: 'address',
- bind: {
- disabled: '{!info.ring1Possible}',
- allowBlank: '{!info.ring1Needed}',
- },
- name: 'link1'
- }
- ],
- columnB: [
- {
- xtype: 'textfield',
- fieldLabel: gettext('Fingerprint'),
- allowBlank: false,
- bind: {
- value: '{info.fp}',
- readOnly: '{assistedEntry.checked}'
- },
- name: 'fingerprint'
- }
- ]
- }]
-});
-/*
- * Workspace base class
- *
- * popup login window when auth fails (call onLogin handler)
- * update (re-login) ticket every 15 minutes
- *
- */
-
-Ext.define('PVE.Workspace', {
- extend: 'Ext.container.Viewport',
-
- title: 'Proxmox Virtual Environment',
-
- loginData: null, // Data from last login call
-
- onLogin: function(loginData) {},
-
- // private
- updateLoginData: function(loginData) {
- var me = this;
- me.loginData = loginData;
- Proxmox.Utils.setAuthData(loginData);
-
- var rt = me.down('pveResourceTree');
- rt.setDatacenterText(loginData.clustername);
-
- if (loginData.cap) {
- Ext.state.Manager.set('GuiCap', loginData.cap);
- }
- me.response401count = 0;
-
- me.onLogin(loginData);
- },
-
- // private
- showLogin: function() {
- var me = this;
-
- Proxmox.Utils.authClear();
- Proxmox.UserName = null;
- me.loginData = null;
-
- if (!me.login) {
- me.login = Ext.create('PVE.window.LoginWindow', {
- handler: function(data) {
- me.login = null;
- me.updateLoginData(data);
- Proxmox.Utils.checked_command(function() {}); // display subscription status
- }
- });
- }
- me.onLogin(null);
- me.login.show();
- },
-
- initComponent : function() {
- var me = this;
-
- Ext.tip.QuickTipManager.init();
-
- // fixme: what about other errors
- Ext.Ajax.on('requestexception', function(conn, response, options) {
- if (response.status == 401 && !PVE.Utils.silenceAuthFailures) { // auth failure
- // don't immediately show as logged out to cope better with some big
- // upgrades, which may temporarily produce a false positive 401 err
- me.response401count++;
- if (me.response401count > 5) {
- me.showLogin();
- }
- }
- });
-
- me.callParent();
-
- if (!Proxmox.Utils.authOK()) {
- me.showLogin();
- } else {
- if (me.loginData) {
- me.onLogin(me.loginData);
- }
- }
-
- Ext.TaskManager.start({
- run: function() {
- var ticket = Proxmox.Utils.authOK();
- if (!ticket || !Proxmox.UserName) {
- return;
- }
-
- Ext.Ajax.request({
- params: {
- username: Proxmox.UserName,
- password: ticket
- },
- url: '/api2/json/access/ticket',
- method: 'POST',
- success: function(response, opts) {
- var obj = Ext.decode(response.responseText);
- me.updateLoginData(obj.data);
- }
- });
- },
- interval: 15*60*1000
- });
-
- }
-});
-
-Ext.define('PVE.StdWorkspace', {
- extend: 'PVE.Workspace',
-
- alias: ['widget.pveStdWorkspace'],
-
- // private
- setContent: function(comp) {
- var me = this;
-
- var cont = me.child('#content');
-
- var lay = cont.getLayout();
-
- var cur = lay.getActiveItem();
-
- if (comp) {
- Proxmox.Utils.setErrorMask(cont, false);
- comp.border = false;
- cont.add(comp);
- if (cur !== null && lay.getNext()) {
- lay.next();
- var task = Ext.create('Ext.util.DelayedTask', function(){
- cont.remove(cur);
- });
- task.delay(10);
- }
- }
- else {
- // helper for cleaning the content when logging out
- cont.removeAll();
- }
- },
-
- selectById: function(nodeid) {
- var me = this;
- var tree = me.down('pveResourceTree');
- tree.selectById(nodeid);
- },
-
- onLogin: function(loginData) {
- var me = this;
-
- me.updateUserInfo();
-
- if (loginData) {
- PVE.data.ResourceStore.startUpdate();
-
- Proxmox.Utils.API2Request({
- url: '/version',
- method: 'GET',
- success: function(response) {
- PVE.VersionInfo = response.result.data;
- me.updateVersionInfo();
- }
- });
- }
- },
-
- updateUserInfo: function() {
- var me = this;
- var ui = me.query('#userinfo')[0];
- ui.setText(Proxmox.UserName || '');
- ui.updateLayout();
- },
-
- updateVersionInfo: function() {
- var me = this;
-
- var ui = me.query('#versioninfo')[0];
-
- if (PVE.VersionInfo) {
- var version = PVE.VersionInfo.version;
- ui.update('Virtual Environment ' + version);
- } else {
- ui.update('Virtual Environment');
- }
- ui.updateLayout();
- },
-
- initComponent : function() {
- var me = this;
-
- Ext.History.init();
-
- var sprovider = Ext.create('PVE.StateProvider');
- Ext.state.Manager.setProvider(sprovider);
-
- var selview = Ext.create('PVE.form.ViewSelector');
-
- var rtree = Ext.createWidget('pveResourceTree', {
- viewFilter: selview.getViewFilter(),
- flex: 1,
- selModel: {
- selType: 'treemodel',
- listeners: {
- selectionchange: function(sm, selected) {
- if (selected.length > 0) {
- var n = selected[0];
- var tlckup = {
- root: 'PVE.dc.Config',
- node: 'PVE.node.Config',
- qemu: 'PVE.qemu.Config',
- lxc: 'PVE.lxc.Config',
- storage: 'PVE.storage.Browser',
- pool: 'pvePoolConfig'
- };
- var comp = {
- xtype: tlckup[n.data.type || 'root'] ||
- 'pvePanelConfig',
- showSearch: (n.data.id === 'root') ||
- Ext.isDefined(n.data.groupbyid),
- pveSelNode: n,
- workspace: me,
- viewFilter: selview.getViewFilter()
- };
- PVE.curSelectedNode = n;
- me.setContent(comp);
- }
- }
- }
- }
- });
-
- selview.on('select', function(combo, records) {
- if (records) {
- var view = combo.getViewFilter();
- rtree.setViewFilter(view);
- }
- });
-
- var caps = sprovider.get('GuiCap');
-
- var createVM = Ext.createWidget('button', {
- pack: 'end',
- margin: '3 5 0 0',
- baseCls: 'x-btn',
- iconCls: 'fa fa-desktop',
- text: gettext("Create VM"),
- disabled: !caps.vms['VM.Allocate'],
- handler: function() {
- var wiz = Ext.create('PVE.qemu.CreateWizard', {});
- wiz.show();
- }
- });
-
- var createCT = Ext.createWidget('button', {
- pack: 'end',
- margin: '3 5 0 0',
- baseCls: 'x-btn',
- iconCls: 'fa fa-cube',
- text: gettext("Create CT"),
- disabled: !caps.vms['VM.Allocate'],
- handler: function() {
- var wiz = Ext.create('PVE.lxc.CreateWizard', {});
- wiz.show();
- }
- });
-
- sprovider.on('statechange', function(sp, key, value) {
- if (key === 'GuiCap' && value) {
- caps = value;
- createVM.setDisabled(!caps.vms['VM.Allocate']);
- createCT.setDisabled(!caps.vms['VM.Allocate']);
- }
- });
-
- Ext.apply(me, {
- layout: { type: 'border' },
- border: false,
- items: [
- {
- region: 'north',
- layout: {
- type: 'hbox',
- align: 'middle'
- },
- baseCls: 'x-plain',
- defaults: {
- baseCls: 'x-plain'
- },
- border: false,
- margin: '2 0 2 5',
- items: [
- {
- html: '' +
- ' '
- },
- {
- minWidth: 150,
- id: 'versioninfo',
- html: 'Virtual Environment'
- },
- {
- xtype: 'pveGlobalSearchField',
- tree: rtree
- },
- {
- flex: 1
- },
- {
- xtype: 'proxmoxHelpButton',
- hidden: false,
- baseCls: 'x-btn',
- iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ',
- listenToGlobalEvent: false,
- onlineHelp: 'pve_documentation_index',
- text: gettext('Documentation'),
- margin: '0 5 0 0'
- },
- createVM,
- createCT,
- {
- pack: 'end',
- margin: '0 5 0 0',
- id: 'userinfo',
- xtype: 'button',
- baseCls: 'x-btn',
- style: {
- // proxmox dark grey p light grey as border
- backgroundColor: '#464d4d',
- borderColor: '#ABBABA'
- },
- iconCls: 'fa fa-user',
- menu: [
- {
- iconCls: 'fa fa-gear',
- text: gettext('My Settings'),
- handler: function() {
- var win = Ext.create('PVE.window.Settings');
- win.show();
- }
- },
- {
- text: gettext('Password'),
- iconCls: 'fa fa-fw fa-key',
- handler: function() {
- var win = Ext.create('Proxmox.window.PasswordEdit', {
- userid: Proxmox.UserName
- });
- win.show();
- }
- },
- {
- text: 'TFA',
- iconCls: 'fa fa-fw fa-lock',
- handler: function(btn, event, rec) {
- var win = Ext.create('PVE.window.TFAEdit',{
- userid: Proxmox.UserName
- });
- win.show();
- }
- },
- '-',
- {
- iconCls: 'fa fa-fw fa-sign-out',
- text: gettext("Logout"),
- handler: function() {
- PVE.data.ResourceStore.loadData([], false);
- me.showLogin();
- me.setContent(null);
- var rt = me.down('pveResourceTree');
- rt.setDatacenterText(undefined);
- rt.clearTree();
-
- // empty the stores of the StatusPanel child items
- var statusPanels = Ext.ComponentQuery.query('pveStatusPanel grid');
- Ext.Array.forEach(statusPanels, function(comp) {
- if (comp.getStore()) {
- comp.getStore().loadData([], false);
- }
- });
- }
- }
- ]
- }
- ]
- },
- {
- region: 'center',
- stateful: true,
- stateId: 'pvecenter',
- minWidth: 100,
- minHeight: 100,
- id: 'content',
- xtype: 'container',
- layout: { type: 'card' },
- border: false,
- margin: '0 5 0 0',
- items: []
- },
- {
- region: 'west',
- stateful: true,
- stateId: 'pvewest',
- itemId: 'west',
- xtype: 'container',
- border: false,
- layout: { type: 'vbox', align: 'stretch' },
- margin: '0 0 0 5',
- split: true,
- width: 200,
- items: [ selview, rtree ],
- listeners: {
- resize: function(panel, width, height) {
- var viewWidth = me.getSize().width;
- if (width > viewWidth - 100) {
- panel.setWidth(viewWidth - 100);
- }
- }
- }
- },
- {
- xtype: 'pveStatusPanel',
- stateful: true,
- stateId: 'pvesouth',
- itemId: 'south',
- region: 'south',
- margin:'0 5 5 5',
- title: gettext('Logs'),
- collapsible: true,
- header: false,
- height: 200,
- split:true,
- listeners: {
- resize: function(panel, width, height) {
- var viewHeight = me.getSize().height;
- if (height > (viewHeight - 150)) {
- panel.setHeight(viewHeight - 150);
- }
- }
- }
- }
- ]
- });
-
- me.callParent();
-
- me.updateUserInfo();
-
- // on resize, center all modal windows
- Ext.on('resize', function(){
- var wins = Ext.ComponentQuery.query('window[modal]');
- if (wins.length > 0) {
- wins.forEach(function(win){
- win.alignTo(me, 'c-c');
- });
- }
- });
- }
-});
-
diff --git a/serverside/jsmod/6.1-3.sh b/serverside/jsmod/6.1-3.sh
deleted file mode 100644
index b0575a8..0000000
--- a/serverside/jsmod/6.1-3.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-
-Say () {
- printf "\e[1;34m $1 \e[0m \n";
-}
-
-DotSay () {
- printf "[\e[1;34m*\e[0m] \e[1;34m $1 \e[0m \n";
-}
-
-
-Say '[PVE Discord Dark UI Theme JSMOD Installer]'
-Say 'Internet connection REQUIRED.'
-Say '!!ONLY FOR PVE 6.0-4 - 6.1-x!!'
-Say '>Press any key to begin installation'
-read -p ""
-Say ' '
-DotSay 'Backing up files'
-cp /usr/share/pve-manager/js/pvemanagerlib.js /usr/share/pve-manager/js/pvemanagerlib.js.bak
-cp /usr/share/javascript/extjs/charts.js /usr/share/javascript/extjs/charts.js.bak
-cp /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.bak
-DotSay 'Modding files'
-#replace white with #23272a
-sed -i -e "s/'white'/'#23272a'/g" /usr/share/pve-manager/js/pvemanagerlib.js
-
-#Proxmox changed nothing here to last version, so we can use it without modifications
-rm /usr/share/javascript/extjs/charts.js
-wget https://raw.githubusercontent.com/Weilbyte/PVEDiscordDark/master/serverside/jsmod/6.0-4/charts.js -P /usr/share/javascript/extjs/ &> /dev/null
-
-sed -i -e "s/#c2ddf2/#7289DA/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
-sed -i -e "s/#f5f5f5/#2C2F33/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
-
-DotSay 'Applied patch successfully.'
-Say ''
-Say 'Installation finished!'
-Say 'o7'
diff --git a/serverside/jsmod/6.1-3/charts.js b/serverside/jsmod/6.1-3/charts.js
deleted file mode 100644
index 713bec3..0000000
--- a/serverside/jsmod/6.1-3/charts.js
+++ /dev/null
@@ -1,22013 +0,0 @@
-Ext.define("Ext.draw.ContainerBase", {
- extend: "Ext.panel.Panel",
- requires: ["Ext.window.Window"],
- previewTitleText: "Chart Preview",
- previewAltText: "Chart preview",
- layout: "container",
- addElementListener: function() {
- var b = this,
- a = arguments;
- if (b.rendered) {
- b.el.on.apply(b.el, a)
- } else {
- b.on("render", function() {
- b.el.on.apply(b.el, a)
- })
- }
- },
- removeElementListener: function() {
- var b = this,
- a = arguments;
- if (b.rendered) {
- b.el.un.apply(b.el, a)
- }
- },
- afterRender: function() {
- this.callParent(arguments);
- this.initAnimator()
- },
- getItems: function() {
- var b = this,
- a = b.items;
- if (!a || !a.isMixedCollection) {
- b.initItems()
- }
- return b.items
- },
- onRender: function() {
- this.callParent(arguments);
- this.element = this.el;
- this.innerElement = this.body
- },
- setItems: function(a) {
- this.items = a;
- return a
- },
- setSurfaceSize: function(b, a) {
- this.resizeHandler({
- width: b,
- height: a
- });
- this.renderFrame()
- },
- onResize: function(c, a, b, e) {
- var d = this;
- d.callParent([c, a, b, e]);
- d.setBodySize({
- width: c,
- height: a
- })
- },
- preview: function() {
- var a = this.getImage();
- new Ext.window.Window({
- title: this.previewTitleText,
- closeable: true,
- renderTo: Ext.getBody(),
- autoShow: true,
- maximizeable: true,
- maximized: true,
- border: true,
- layout: {
- type: "hbox",
- pack: "center",
- align: "middle"
- },
- items: {
- xtype: "container",
- items: {
- xtype: "image",
- mode: "img",
- cls: Ext.baseCSSPrefix + "chart-image",
- alt: this.previewAltText,
- src: a.data,
- listeners: {
- afterrender: function() {
- var e = this,
- b = e.imgEl.dom,
- d = a.type === "svg" ? 1 : (window.devicePixelRatio || 1),
- c;
- if (!b.naturalWidth || !b.naturalHeight) {
- b.onload = function() {
- var g = b.naturalWidth,
- f = b.naturalHeight;
- e.setWidth(Math.floor(g / d));
- e.setHeight(Math.floor(f / d))
- }
- } else {
- c = e.getSize();
- e.setWidth(Math.floor(c.width / d));
- e.setHeight(Math.floor(c.height / d))
- }
- }
- }
- }
- }
- })
- },
- privates: {
- getTargetEl: function() {
- return this.innerElement
- },
- reattachToBody: function() {
- var a = this;
- if (a.pendingDetachSize) {
- a.onBodyResize()
- }
- a.pendingDetachSize = false;
- a.callParent()
- }
- }
-});
-Ext.define("Ext.draw.SurfaceBase", {
- extend: "Ext.Widget",
- getOwnerBody: function() {
- return this.ownerCt.body
- },
- destroy: function() {
- var a = this;
- if (a.hasListeners.destroy) {
- a.fireEvent("destroy", a)
- }
- a.callParent()
- }
-});
-Ext.define("Ext.draw.Color", {
- statics: {
- colorToHexRe: /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
- rgbToHexRe: /\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
- rgbaToHexRe: /\s*rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\.\d]+)\)/,
- hexRe: /\s*#([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)\s*/,
- NONE: "none",
- RGBA_NONE: "rgba(0, 0, 0, 0)"
- },
- isColor: true,
- lightnessFactor: 0.2,
- constructor: function(d, b, a, c) {
- this.setRGB(d, b, a, c)
- },
- setRGB: function(e, c, a, d) {
- var b = this;
- b.r = Math.min(255, Math.max(0, e));
- b.g = Math.min(255, Math.max(0, c));
- b.b = Math.min(255, Math.max(0, a));
- if (d === undefined) {
- b.a = 1
- } else {
- b.a = Math.min(1, Math.max(0, d))
- }
- },
- getGrayscale: function() {
- return this.r * 0.3 + this.g * 0.59 + this.b * 0.11
- },
- getHSL: function() {
- var i = this,
- a = i.r / 255,
- f = i.g / 255,
- j = i.b / 255,
- k = Math.max(a, f, j),
- d = Math.min(a, f, j),
- m = k - d,
- e, n = 0,
- c = 0.5 * (k + d);
- if (d !== k) {
- n = (c <= 0.5) ? m / (k + d) : m / (2 - k - d);
- if (a === k) {
- e = 60 * (f - j) / m
- } else {
- if (f === k) {
- e = 120 + 60 * (j - a) / m
- } else {
- e = 240 + 60 * (a - f) / m
- }
- }
- if (e < 0) {
- e += 360
- }
- if (e >= 360) {
- e -= 360
- }
- }
- return [e, n, c]
- },
- getHSV: function() {
- var i = this,
- a = i.r / 255,
- f = i.g / 255,
- j = i.b / 255,
- k = Math.max(a, f, j),
- d = Math.min(a, f, j),
- c = k - d,
- e, m = 0,
- l = k;
- if (d != k) {
- m = l ? c / l : 0;
- if (a === k) {
- e = 60 * (f - j) / c
- } else {
- if (f === k) {
- e = 60 * (j - a) / c + 120
- } else {
- e = 60 * (a - f) / c + 240
- }
- }
- if (e < 0) {
- e += 360
- }
- if (e >= 360) {
- e -= 360
- }
- }
- return [e, m, l]
- },
- setHSL: function(g, f, e) {
- var i = this,
- d = Math.abs,
- j, b, a;
- g = (g % 360 + 360) % 360;
- f = f > 1 ? 1 : f < 0 ? 0 : f;
- e = e > 1 ? 1 : e < 0 ? 0 : e;
- if (f === 0 || g === null) {
- e *= 255;
- i.setRGB(e, e, e)
- } else {
- g /= 60;
- j = f * (1 - d(2 * e - 1));
- b = j * (1 - d(g % 2 - 1));
- a = e - j / 2;
- a *= 255;
- j *= 255;
- b *= 255;
- switch (Math.floor(g)) {
- case 0:
- i.setRGB(j + a, b + a, a);
- break;
- case 1:
- i.setRGB(b + a, j + a, a);
- break;
- case 2:
- i.setRGB(a, j + a, b + a);
- break;
- case 3:
- i.setRGB(a, b + a, j + a);
- break;
- case 4:
- i.setRGB(b + a, a, j + a);
- break;
- case 5:
- i.setRGB(j + a, a, b + a);
- break
- }
- }
- return i
- },
- setHSV: function(f, e, d) {
- var g = this,
- i, b, a;
- f = (f % 360 + 360) % 360;
- e = e > 1 ? 1 : e < 0 ? 0 : e;
- d = d > 1 ? 1 : d < 0 ? 0 : d;
- if (e === 0 || f === null) {
- d *= 255;
- g.setRGB(d, d, d)
- } else {
- f /= 60;
- i = d * e;
- b = i * (1 - Math.abs(f % 2 - 1));
- a = d - i;
- a *= 255;
- i *= 255;
- b *= 255;
- switch (Math.floor(f)) {
- case 0:
- g.setRGB(i + a, b + a, a);
- break;
- case 1:
- g.setRGB(b + a, i + a, a);
- break;
- case 2:
- g.setRGB(a, i + a, b + a);
- break;
- case 3:
- g.setRGB(a, b + a, i + a);
- break;
- case 4:
- g.setRGB(b + a, a, i + a);
- break;
- case 5:
- g.setRGB(i + a, a, b + a);
- break
- }
- }
- return g
- },
- createLighter: function(b) {
- if (!b && b !== 0) {
- b = this.lightnessFactor
- }
- var a = this.getHSL();
- a[2] = Ext.Number.constrain(a[2] + b, 0, 1);
- return Ext.draw.Color.fromHSL(a[0], a[1], a[2])
- },
- createDarker: function(a) {
- if (!a && a !== 0) {
- a = this.lightnessFactor
- }
- return this.createLighter(-a)
- },
- toString: function() {
- var f = this,
- c = Math.round;
- if (f.a === 1) {
- var e = c(f.r).toString(16),
- d = c(f.g).toString(16),
- a = c(f.b).toString(16);
- e = (e.length === 1) ? "0" + e : e;
- d = (d.length === 1) ? "0" + d : d;
- a = (a.length === 1) ? "0" + a : a;
- return ["#", e, d, a].join("")
- } else {
- return "rgba(" + [c(f.r), c(f.g), c(f.b), f.a === 0 ? 0 : f.a.toFixed(15)].join(", ") + ")"
- }
- },
- toHex: function(b) {
- if (Ext.isArray(b)) {
- b = b[0]
- }
- if (!Ext.isString(b)) {
- return ""
- }
- if (b.substr(0, 1) === "#") {
- return b
- }
- var e = Ext.draw.Color.colorToHexRe.exec(b);
- if (Ext.isArray(e)) {
- var f = parseInt(e[2], 10),
- d = parseInt(e[3], 10),
- a = parseInt(e[4], 10),
- c = a | (d << 8) | (f << 16);
- return e[1] + "#" + ("000000" + c.toString(16)).slice(-6)
- } else {
- return ""
- }
- },
- setFromString: function(j) {
- var e, h, f, c, d = 1,
- i = parseInt;
- if (j === Ext.draw.Color.NONE) {
- this.r = this.g = this.b = this.a = 0;
- return this
- }
- if ((j.length === 4 || j.length === 7) && j.substr(0, 1) === "#") {
- e = j.match(Ext.draw.Color.hexRe);
- if (e) {
- h = i(e[1], 16) >> 0;
- f = i(e[2], 16) >> 0;
- c = i(e[3], 16) >> 0;
- if (j.length === 4) {
- h += (h * 16);
- f += (f * 16);
- c += (c * 16)
- }
- }
- } else {
- if ((e = j.match(Ext.draw.Color.rgbToHexRe))) {
- h = +e[1];
- f = +e[2];
- c = +e[3]
- } else {
- if ((e = j.match(Ext.draw.Color.rgbaToHexRe))) {
- h = +e[1];
- f = +e[2];
- c = +e[3];
- d = +e[4]
- } else {
- if (Ext.draw.Color.ColorList.hasOwnProperty(j.toLowerCase())) {
- return this.setFromString(Ext.draw.Color.ColorList[j.toLowerCase()])
- }
- }
- }
- }
- if (typeof h === "undefined") {
- return this
- }
- this.r = h;
- this.g = f;
- this.b = c;
- this.a = d;
- return this
- }
-}, function() {
- var a = new this();
- this.addStatics({
- fly: function(f, e, c, d) {
- switch (arguments.length) {
- case 1:
- a.setFromString(f);
- break;
- case 3:
- case 4:
- a.setRGB(f, e, c, d);
- break;
- default:
- return null
- }
- return a
- },
- ColorList: {
- aliceblue: "#f0f8ff",
- antiquewhite: "#faebd7",
- aqua: "#00ffff",
- aquamarine: "#7fffd4",
- azure: "#f0ffff",
- beige: "#f5f5dc",
- bisque: "#ffe4c4",
- black: "#000000",
- blanchedalmond: "#ffebcd",
- blue: "#0000ff",
- blueviolet: "#8a2be2",
- brown: "#a52a2a",
- burlywood: "#deb887",
- cadetblue: "#5f9ea0",
- chartreuse: "#7fff00",
- chocolate: "#d2691e",
- coral: "#ff7f50",
- cornflowerblue: "#6495ed",
- cornsilk: "#fff8dc",
- crimson: "#dc143c",
- cyan: "#00ffff",
- darkblue: "#00008b",
- darkcyan: "#008b8b",
- darkgoldenrod: "#b8860b",
- darkgray: "#a9a9a9",
- darkgreen: "#006400",
- darkkhaki: "#bdb76b",
- darkmagenta: "#8b008b",
- darkolivegreen: "#556b2f",
- darkorange: "#ff8c00",
- darkorchid: "#9932cc",
- darkred: "#8b0000",
- darksalmon: "#e9967a",
- darkseagreen: "#8fbc8f",
- darkslateblue: "#483d8b",
- darkslategray: "#2f4f4f",
- darkturquoise: "#00ced1",
- darkviolet: "#9400d3",
- deeppink: "#ff1493",
- deepskyblue: "#00bfff",
- dimgray: "#696969",
- dodgerblue: "#1e90ff",
- firebrick: "#b22222",
- floralwhite: "#fffaf0",
- forestgreen: "#228b22",
- fuchsia: "#ff00ff",
- gainsboro: "#dcdcdc",
- ghostwhite: "#f8f8ff",
- gold: "#ffd700",
- goldenrod: "#daa520",
- gray: "#808080",
- green: "#008000",
- greenyellow: "#adff2f",
- honeydew: "#f0fff0",
- hotpink: "#ff69b4",
- indianred: "#cd5c5c",
- indigo: "#4b0082",
- ivory: "#fffff0",
- khaki: "#f0e68c",
- lavender: "#e6e6fa",
- lavenderblush: "#fff0f5",
- lawngreen: "#7cfc00",
- lemonchiffon: "#fffacd",
- lightblue: "#add8e6",
- lightcoral: "#f08080",
- lightcyan: "#e0ffff",
- lightgoldenrodyellow: "#fafad2",
- lightgray: "#d3d3d3",
- lightgrey: "#d3d3d3",
- lightgreen: "#90ee90",
- lightpink: "#ffb6c1",
- lightsalmon: "#ffa07a",
- lightseagreen: "#20b2aa",
- lightskyblue: "#87cefa",
- lightslategray: "#778899",
- lightsteelblue: "#b0c4de",
- lightyellow: "#ffffe0",
- lime: "#00ff00",
- limegreen: "#32cd32",
- linen: "#faf0e6",
- magenta: "#ff00ff",
- maroon: "#800000",
- mediumaquamarine: "#66cdaa",
- mediumblue: "#0000cd",
- mediumorchid: "#ba55d3",
- mediumpurple: "#9370d8",
- mediumseagreen: "#3cb371",
- mediumslateblue: "#7b68ee",
- mediumspringgreen: "#00fa9a",
- mediumturquoise: "#48d1cc",
- mediumvioletred: "#c71585",
- midnightblue: "#191970",
- mintcream: "#f5fffa",
- mistyrose: "#ffe4e1",
- moccasin: "#ffe4b5",
- navajowhite: "#ffdead",
- navy: "#000080",
- oldlace: "#fdf5e6",
- olive: "#808000",
- olivedrab: "#6b8e23",
- orange: "#ffa500",
- orangered: "#ff4500",
- orchid: "#da70d6",
- palegoldenrod: "#eee8aa",
- palegreen: "#98fb98",
- paleturquoise: "#afeeee",
- palevioletred: "#d87093",
- papayawhip: "#ffefd5",
- peachpuff: "#ffdab9",
- peru: "#cd853f",
- pink: "#ffc0cb",
- plum: "#dda0dd",
- powderblue: "#b0e0e6",
- purple: "#800080",
- red: "#ff0000",
- rosybrown: "#bc8f8f",
- royalblue: "#4169e1",
- saddlebrown: "#8b4513",
- salmon: "#fa8072",
- sandybrown: "#f4a460",
- seagreen: "#2e8b57",
- seashell: "#fff5ee",
- sienna: "#a0522d",
- silver: "#c0c0c0",
- skyblue: "#87ceeb",
- slateblue: "#6a5acd",
- slategray: "#708090",
- snow: "#fffafa",
- springgreen: "#00ff7f",
- steelblue: "#4682b4",
- tan: "#d2b48c",
- teal: "#008080",
- thistle: "#d8bfd8",
- tomato: "#ff6347",
- turquoise: "#40e0d0",
- violet: "#ee82ee",
- wheat: "#f5deb3",
- white: "#ffffff",
- whitesmoke: "#f5f5f5",
- yellow: "#ffff00",
- yellowgreen: "#9acd32"
- },
- fromHSL: function(d, c, b) {
- return (new this(0, 0, 0, 0)).setHSL(d, c, b)
- },
- fromHSV: function(d, c, b) {
- return (new this(0, 0, 0, 0)).setHSL(d, c, b)
- },
- fromString: function(b) {
- return (new this(0, 0, 0, 0)).setFromString(b)
- },
- create: function(b) {
- if (b instanceof this) {
- return b
- } else {
- if (Ext.isArray(b)) {
- return new Ext.draw.Color(b[0], b[1], b[2], b[3])
- } else {
- if (Ext.isString(b)) {
- return Ext.draw.Color.fromString(b)
- } else {
- if (arguments.length > 2) {
- return new Ext.draw.Color(arguments[0], arguments[1], arguments[2], arguments[3])
- } else {
- return new Ext.draw.Color(0, 0, 0, 0)
- }
- }
- }
- }
- }
- })
-});
-Ext.define("Ext.draw.sprite.AnimationParser", function() {
- function a(d, c, b) {
- return d + (c - d) * b
- }
- return {
- singleton: true,
- attributeRe: /^url\(#([a-zA-Z\-]+)\)$/,
- requires: ["Ext.draw.Color"],
- color: {
- parseInitial: function(c, b) {
- if (Ext.isString(c)) {
- c = Ext.draw.Color.create(c)
- }
- if (Ext.isString(b)) {
- b = Ext.draw.Color.create(b)
- }
- if ((c instanceof Ext.draw.Color) && (b instanceof Ext.draw.Color)) {
- return [
- [c.r, c.g, c.b, c.a],
- [b.r, b.g, b.b, b.a]
- ]
- } else {
- return [c || b, b || c]
- }
- },
- compute: function(d, c, b) {
- if (!Ext.isArray(d) || !Ext.isArray(c)) {
- return c || d
- } else {
- return [a(d[0], c[0], b), a(d[1], c[1], b), a(d[2], c[2], b), a(d[3], c[3], b)]
- }
- },
- serve: function(c) {
- var b = Ext.draw.Color.fly(c[0], c[1], c[2], c[3]);
- return b.toString()
- }
- },
- number: {
- parse: function(b) {
- return b === null ? null : +b
- },
- compute: function(d, c, b) {
- if (!Ext.isNumber(d) || !Ext.isNumber(c)) {
- return c || d
- } else {
- return a(d, c, b)
- }
- }
- },
- angle: {
- parseInitial: function(c, b) {
- if (b - c > Math.PI) {
- b -= Math.PI * 2
- } else {
- if (b - c < -Math.PI) {
- b += Math.PI * 2
- }
- }
- return [c, b]
- },
- compute: function(d, c, b) {
- if (!Ext.isNumber(d) || !Ext.isNumber(c)) {
- return c || d
- } else {
- return a(d, c, b)
- }
- }
- },
- path: {
- parseInitial: function(m, n) {
- var c = m.toStripes(),
- o = n.toStripes(),
- e, d, k = c.length,
- p = o.length,
- h, f, b, g = o[p - 1],
- l = [g[g.length - 2], g[g.length - 1]];
- for (e = k; e < p; e++) {
- c.push(c[k - 1].slice(0))
- }
- for (e = p; e < k; e++) {
- o.push(l.slice(0))
- }
- b = c.length;
- o.path = n;
- o.temp = new Ext.draw.Path();
- for (e = 0; e < b; e++) {
- h = c[e];
- f = o[e];
- k = h.length;
- p = f.length;
- o.temp.commands.push("M");
- for (d = p; d < k; d += 6) {
- f.push(l[0], l[1], l[0], l[1], l[0], l[1])
- }
- g = o[o.length - 1];
- l = [g[g.length - 2], g[g.length - 1]];
- for (d = k; d < p; d += 6) {
- h.push(l[0], l[1], l[0], l[1], l[0], l[1])
- }
- for (e = 0; e < f.length; e++) {
- f[e] -= h[e]
- }
- for (e = 2; e < f.length; e += 6) {
- o.temp.commands.push("C")
- }
- }
- return [c, o]
- },
- compute: function(c, l, m) {
- if (m >= 1) {
- return l.path
- }
- var e = 0,
- f = c.length,
- d = 0,
- b, k, h, n = l.temp.params,
- g = 0;
- for (; e < f; e++) {
- k = c[e];
- h = l[e];
- b = k.length;
- for (d = 0; d < b; d++) {
- n[g++] = h[d] * m + k[d]
- }
- }
- return l.temp
- }
- },
- data: {
- compute: function(h, j, k, g) {
- var m = h.length - 1,
- b = j.length - 1,
- e = Math.max(m, b),
- d, l, c;
- if (!g || g === h) {
- g = []
- }
- g.length = e + 1;
- for (c = 0; c <= e; c++) {
- d = h[Math.min(c, m)];
- l = j[Math.min(c, b)];
- if (Ext.isNumber(d)) {
- if (!Ext.isNumber(l)) {
- l = 0
- }
- g[c] = (l - d) * k + d
- } else {
- g[c] = l
- }
- }
- return g
- }
- },
- text: {
- compute: function(d, c, b) {
- return d.substr(0, Math.round(d.length * (1 - b))) + c.substr(Math.round(c.length * (1 - b)))
- }
- },
- limited: "number",
- limited01: "number"
- }
-});
-(function() {
- if (!Ext.global.Float32Array) {
- var a = function(d) {
- if (typeof d === "number") {
- this.length = d
- } else {
- if ("length" in d) {
- this.length = d.length;
- for (var c = 0, b = d.length; c < b; c++) {
- this[c] = +d[c]
- }
- }
- }
- };
- a.prototype = [];
- Ext.global.Float32Array = a
- }
-})();
-Ext.define("Ext.draw.Draw", {
- singleton: true,
- radian: Math.PI / 180,
- pi2: Math.PI * 2,
- reflectFn: function(b) {
- return b
- },
- rad: function(a) {
- return (a % 360) * this.radian
- },
- degrees: function(a) {
- return (a / this.radian) % 360
- },
- isBBoxIntersect: function(b, a, c) {
- c = c || 0;
- return (Math.max(b.x, a.x) - c > Math.min(b.x + b.width, a.x + a.width)) || (Math.max(b.y, a.y) - c > Math.min(b.y + b.height, a.y + a.height))
- },
- isPointInBBox: function(a, c, b) {
- return !!b && a >= b.x && a <= (b.x + b.width) && c >= b.y && c <= (b.y + b.height)
- },
- spline: function(m) {
- var e, c, k = m.length,
- b, h, l, f, a = 0,
- g = new Float32Array(m.length),
- n = new Float32Array(m.length * 3 - 2);
- g[0] = 0;
- g[k - 1] = 0;
- for (e = 1; e < k - 1; e++) {
- g[e] = (m[e + 1] + m[e - 1] - 2 * m[e]) - g[e - 1];
- a = 1 / (4 - a);
- g[e] *= a
- }
- for (e = k - 2; e > 0; e--) {
- a = 3.732050807568877 + 48.248711305964385 / (-13.928203230275537 + Math.pow(0.07179676972449123, e));
- g[e] -= g[e + 1] * a
- }
- f = m[0];
- b = f - g[0];
- for (e = 0, c = 0; e < k - 1; c += 3) {
- l = f;
- h = b;
- e++;
- f = m[e];
- b = f - g[e];
- n[c] = l;
- n[c + 1] = (b + 2 * h) / 3;
- n[c + 2] = (b * 2 + h) / 3
- }
- n[c] = f;
- return n
- },
- getAnchors: function(e, d, i, h, t, s, o) {
- o = o || 4;
- var n = Math.PI,
- p = n / 2,
- k = Math.abs,
- a = Math.sin,
- b = Math.cos,
- f = Math.atan,
- r, q, g, j, m, l, v, u, c;
- r = (i - e) / o;
- q = (t - i) / o;
- if ((h >= d && h >= s) || (h <= d && h <= s)) {
- g = j = p
- } else {
- g = f((i - e) / k(h - d));
- if (d < h) {
- g = n - g
- }
- j = f((t - i) / k(h - s));
- if (s < h) {
- j = n - j
- }
- }
- c = p - ((g + j) % (n * 2)) / 2;
- if (c > p) {
- c -= n
- }
- g += c;
- j += c;
- m = i - r * a(g);
- l = h + r * b(g);
- v = i + q * a(j);
- u = h + q * b(j);
- if ((h > d && l < d) || (h < d && l > d)) {
- m += k(d - l) * (m - i) / (l - h);
- l = d
- }
- if ((h > s && u < s) || (h < s && u > s)) {
- v -= k(s - u) * (v - i) / (u - h);
- u = s
- }
- return {
- x1: m,
- y1: l,
- x2: v,
- y2: u
- }
- },
- smooth: function(l, j, o) {
- var k = l.length,
- h, g, c, b, q, p, n, m, f = [],
- e = [],
- d, a;
- for (d = 0; d < k - 1; d++) {
- h = l[d];
- g = j[d];
- if (d === 0) {
- n = h;
- m = g;
- f.push(n);
- e.push(m);
- if (k === 1) {
- break
- }
- }
- c = l[d + 1];
- b = j[d + 1];
- q = l[d + 2];
- p = j[d + 2];
- if (!Ext.isNumber(q + p)) {
- f.push(n, c, c);
- e.push(m, b, b);
- break
- }
- a = this.getAnchors(h, g, c, b, q, p, o);
- f.push(n, a.x1, c);
- e.push(m, a.y1, b);
- n = a.x2;
- m = a.y2
- }
- return {
- smoothX: f,
- smoothY: e
- }
- },
- beginUpdateIOS: Ext.os.is.iOS ? function() {
- this.iosUpdateEl = Ext.getBody().createChild({
- style: "position: absolute; top: 0px; bottom: 0px; left: 0px; right: 0px; background: rgba(0,0,0,0.001); z-index: 100000"
- })
- } : Ext.emptyFn,
- endUpdateIOS: function() {
- this.iosUpdateEl = Ext.destroy(this.iosUpdateEl)
- }
-});
-Ext.define("Ext.draw.gradient.Gradient", {
- requires: ["Ext.draw.Color"],
- isGradient: true,
- config: {
- stops: []
- },
- applyStops: function(f) {
- var e = [],
- d = f.length,
- c, b, a;
- for (c = 0; c < d; c++) {
- b = f[c];
- a = b.color;
- if (!(a && a.isColor)) {
- a = Ext.draw.Color.fly(a || Ext.draw.Color.NONE)
- }
- e.push({
- offset: Math.min(1, Math.max(0, "offset" in b ? b.offset : b.position || 0)),
- color: a.toString()
- })
- }
- e.sort(function(h, g) {
- return h.offset - g.offset
- });
- return e
- },
- onClassExtended: function(a, b) {
- if (!b.alias && b.type) {
- b.alias = "gradient." + b.type
- }
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- generateGradient: Ext.emptyFn
-});
-Ext.define("Ext.draw.gradient.GradientDefinition", {
- singleton: true,
- urlStringRe: /^url\(#([\w\-]+)\)$/,
- gradients: {},
- add: function(a) {
- var b = this.gradients,
- c, e, d;
- for (c = 0, e = a.length; c < e; c++) {
- d = a[c];
- if (Ext.isString(d.id)) {
- b[d.id] = d
- }
- }
- },
- get: function(d) {
- var a = this.gradients,
- b = d.match(this.urlStringRe),
- c;
- if (b && b[1] && (c = a[b[1]])) {
- return c || d
- }
- return d
- }
-});
-Ext.define("Ext.draw.sprite.AttributeParser", {
- singleton: true,
- attributeRe: /^url\(#([a-zA-Z\-]+)\)$/,
- requires: ["Ext.draw.Color", "Ext.draw.gradient.GradientDefinition"],
- "default": Ext.identityFn,
- string: function(a) {
- return String(a)
- },
- number: function(a) {
- if (Ext.isNumber(+a)) {
- return a
- }
- },
- angle: function(a) {
- if (Ext.isNumber(a)) {
- a %= Math.PI * 2;
- if (a < -Math.PI) {
- a += Math.PI * 2
- } else {
- if (a >= Math.PI) {
- a -= Math.PI * 2
- }
- }
- return a
- }
- },
- data: function(a) {
- if (Ext.isArray(a)) {
- return a.slice()
- } else {
- if (a instanceof Float32Array) {
- return new Float32Array(a)
- }
- }
- },
- bool: function(a) {
- return !!a
- },
- color: function(a) {
- if (a instanceof Ext.draw.Color) {
- return a.toString()
- } else {
- if (a instanceof Ext.draw.gradient.Gradient) {
- return a
- } else {
- if (!a) {
- return Ext.draw.Color.NONE
- } else {
- if (Ext.isString(a)) {
- if (a.substr(0, 3) === "url") {
- a = Ext.draw.gradient.GradientDefinition.get(a);
- if (Ext.isString(a)) {
- return a
- }
- } else {
- return Ext.draw.Color.fly(a).toString()
- }
- }
- }
- }
- }
- if (a.type === "linear") {
- return Ext.create("Ext.draw.gradient.Linear", a)
- } else {
- if (a.type === "radial") {
- return Ext.create("Ext.draw.gradient.Radial", a)
- } else {
- if (a.type === "pattern") {
- return Ext.create("Ext.draw.gradient.Pattern", a)
- } else {
- return Ext.draw.Color.NONE
- }
- }
- }
- },
- limited: function(a, b) {
- return function(c) {
- c = +c;
- return Ext.isNumber(c) ? Math.min(Math.max(c, a), b) : undefined
- }
- },
- limited01: function(a) {
- a = +a;
- return Ext.isNumber(a) ? Math.min(Math.max(a, 0), 1) : undefined
- },
- enums: function() {
- var d = {},
- a = Array.prototype.slice.call(arguments, 0),
- b, c;
- for (b = 0, c = a.length; b < c; b++) {
- d[a[b]] = true
- }
- return function(e) {
- return e in d ? e : undefined
- }
- }
-});
-Ext.define("Ext.draw.sprite.AttributeDefinition", {
- requires: ["Ext.draw.sprite.AttributeParser", "Ext.draw.sprite.AnimationParser"],
- config: {
- defaults: {
- $value: {},
- lazy: true
- },
- aliases: {},
- animationProcessors: {},
- processors: {
- $value: {},
- lazy: true
- },
- dirtyTriggers: {},
- triggers: {},
- updaters: {}
- },
- inheritableStatics: {
- processorFactoryRe: /^(\w+)\(([\w\-,]*)\)$/
- },
- spriteClass: null,
- constructor: function(a) {
- var b = this;
- b.initConfig(a)
- },
- applyDefaults: function(b, a) {
- a = Ext.apply(a || {}, this.normalize(b));
- return a
- },
- applyAliases: function(b, a) {
- return Ext.apply(a || {}, b)
- },
- applyProcessors: function(e, i) {
- this.getAnimationProcessors();
- var j = i || {},
- h = Ext.draw.sprite.AttributeParser,
- a = this.self.processorFactoryRe,
- g = {},
- d, b, c, f;
- for (b in e) {
- f = e[b];
- if (typeof f === "string") {
- c = f.match(a);
- if (c) {
- f = h[c[1]].apply(h, c[2].split(","))
- } else {
- if (h[f]) {
- g[b] = f;
- d = true;
- f = h[f]
- }
- }
- }
- j[b] = f
- }
- if (d) {
- this.setAnimationProcessors(g)
- }
- return j
- },
- applyAnimationProcessors: function(c, a) {
- var e = Ext.draw.sprite.AnimationParser,
- b, d;
- if (!a) {
- a = {}
- }
- for (b in c) {
- d = c[b];
- if (d === "none") {
- a[b] = null
- } else {
- if (Ext.isString(d) && !(b in a)) {
- if (d in e) {
- while (Ext.isString(e[d])) {
- d = e[d]
- }
- a[b] = e[d]
- }
- } else {
- if (Ext.isObject(d)) {
- a[b] = d
- }
- }
- }
- }
- return a
- },
- updateDirtyTriggers: function(a) {
- this.setTriggers(a)
- },
- applyTriggers: function(b, c) {
- if (!c) {
- c = {}
- }
- for (var a in b) {
- c[a] = b[a].split(",")
- }
- return c
- },
- applyUpdaters: function(b, a) {
- return Ext.apply(a || {}, b)
- },
- batchedNormalize: function(f, n) {
- if (!f) {
- return {}
- }
- var j = this.getProcessors(),
- d = this.getAliases(),
- a = f.translation || f.translate,
- o = {},
- g, h, b, e, p, c, m, l, k;
- if ("rotation" in f) {
- p = f.rotation
- } else {
- p = ("rotate" in f) ? f.rotate : undefined
- }
- if ("scaling" in f) {
- c = f.scaling
- } else {
- c = ("scale" in f) ? f.scale : undefined
- }
- if (typeof c !== "undefined") {
- if (Ext.isNumber(c)) {
- o.scalingX = c;
- o.scalingY = c
- } else {
- if ("x" in c) {
- o.scalingX = c.x
- }
- if ("y" in c) {
- o.scalingY = c.y
- }
- if ("centerX" in c) {
- o.scalingCenterX = c.centerX
- }
- if ("centerY" in c) {
- o.scalingCenterY = c.centerY
- }
- }
- }
- if (typeof p !== "undefined") {
- if (Ext.isNumber(p)) {
- p = Ext.draw.Draw.rad(p);
- o.rotationRads = p
- } else {
- if ("rads" in p) {
- o.rotationRads = p.rads
- } else {
- if ("degrees" in p) {
- if (Ext.isArray(p.degrees)) {
- o.rotationRads = Ext.Array.map(p.degrees, function(i) {
- return Ext.draw.Draw.rad(i)
- })
- } else {
- o.rotationRads = Ext.draw.Draw.rad(p.degrees)
- }
- }
- }
- if ("centerX" in p) {
- o.rotationCenterX = p.centerX
- }
- if ("centerY" in p) {
- o.rotationCenterY = p.centerY
- }
- }
- }
- if (typeof a !== "undefined") {
- if ("x" in a) {
- o.translationX = a.x
- }
- if ("y" in a) {
- o.translationY = a.y
- }
- }
- if ("matrix" in f) {
- m = Ext.draw.Matrix.create(f.matrix);
- k = m.split();
- o.matrix = m;
- o.rotationRads = k.rotation;
- o.rotationCenterX = 0;
- o.rotationCenterY = 0;
- o.scalingX = k.scaleX;
- o.scalingY = k.scaleY;
- o.scalingCenterX = 0;
- o.scalingCenterY = 0;
- o.translationX = k.translateX;
- o.translationY = k.translateY
- }
- for (b in f) {
- e = f[b];
- if (typeof e === "undefined") {
- continue
- } else {
- if (Ext.isArray(e)) {
- if (b in d) {
- b = d[b]
- }
- if (b in j) {
- o[b] = [];
- for (g = 0, h = e.length; g < h; g++) {
- l = j[b].call(this, e[g]);
- if (typeof l !== "undefined") {
- o[b][g] = l
- }
- }
- } else {
- if (n) {
- o[b] = e
- }
- }
- } else {
- if (b in d) {
- b = d[b]
- }
- if (b in j) {
- e = j[b].call(this, e);
- if (typeof e !== "undefined") {
- o[b] = e
- }
- } else {
- if (n) {
- o[b] = e
- }
- }
- }
- }
- }
- return o
- },
- normalize: function(i, j) {
- if (!i) {
- return {}
- }
- var f = this.getProcessors(),
- d = this.getAliases(),
- a = i.translation || i.translate,
- k = {},
- b, e, l, c, h, g;
- if ("rotation" in i) {
- l = i.rotation
- } else {
- l = ("rotate" in i) ? i.rotate : undefined
- }
- if ("scaling" in i) {
- c = i.scaling
- } else {
- c = ("scale" in i) ? i.scale : undefined
- }
- if (a) {
- if ("x" in a) {
- k.translationX = a.x
- }
- if ("y" in a) {
- k.translationY = a.y
- }
- }
- if (typeof c !== "undefined") {
- if (Ext.isNumber(c)) {
- k.scalingX = c;
- k.scalingY = c
- } else {
- if ("x" in c) {
- k.scalingX = c.x
- }
- if ("y" in c) {
- k.scalingY = c.y
- }
- if ("centerX" in c) {
- k.scalingCenterX = c.centerX
- }
- if ("centerY" in c) {
- k.scalingCenterY = c.centerY
- }
- }
- }
- if (typeof l !== "undefined") {
- if (Ext.isNumber(l)) {
- l = Ext.draw.Draw.rad(l);
- k.rotationRads = l
- } else {
- if ("rads" in l) {
- k.rotationRads = l.rads
- } else {
- if ("degrees" in l) {
- k.rotationRads = Ext.draw.Draw.rad(l.degrees)
- }
- }
- if ("centerX" in l) {
- k.rotationCenterX = l.centerX
- }
- if ("centerY" in l) {
- k.rotationCenterY = l.centerY
- }
- }
- }
- if ("matrix" in i) {
- h = Ext.draw.Matrix.create(i.matrix);
- g = h.split();
- k.matrix = h;
- k.rotationRads = g.rotation;
- k.rotationCenterX = 0;
- k.rotationCenterY = 0;
- k.scalingX = g.scaleX;
- k.scalingY = g.scaleY;
- k.scalingCenterX = 0;
- k.scalingCenterY = 0;
- k.translationX = g.translateX;
- k.translationY = g.translateY
- }
- for (b in i) {
- e = i[b];
- if (typeof e === "undefined") {
- continue
- }
- if (b in d) {
- b = d[b]
- }
- if (b in f) {
- e = f[b].call(this, e);
- if (typeof e !== "undefined") {
- k[b] = e
- }
- } else {
- if (j) {
- k[b] = e
- }
- }
- }
- return k
- },
- setBypassingNormalization: function(a, c, b) {
- return c.pushDown(a, b)
- },
- set: function(a, c, b) {
- b = this.normalize(b);
- return this.setBypassingNormalization(a, c, b)
- }
-});
-Ext.define("Ext.draw.Matrix", {
- isMatrix: true,
- statics: {
- createAffineMatrixFromTwoPair: function(h, t, g, s, k, o, i, j) {
- var v = g - h,
- u = s - t,
- e = i - k,
- q = j - o,
- d = 1 / (v * v + u * u),
- p = v * e + u * q,
- n = e * u - v * q,
- m = -p * h - n * t,
- l = n * h - p * t;
- return new this(p * d, -n * d, n * d, p * d, m * d + k, l * d + o)
- },
- createPanZoomFromTwoPair: function(q, e, p, c, h, s, n, g) {
- if (arguments.length === 2) {
- return this.createPanZoomFromTwoPair.apply(this, q.concat(e))
- }
- var k = p - q,
- j = c - e,
- d = (q + p) * 0.5,
- b = (e + c) * 0.5,
- o = n - h,
- a = g - s,
- f = (h + n) * 0.5,
- l = (s + g) * 0.5,
- m = k * k + j * j,
- i = o * o + a * a,
- t = Math.sqrt(i / m);
- return new this(t, 0, 0, t, f - t * d, l - t * b)
- },
- fly: (function() {
- var a = null,
- b = function(c) {
- a.elements = c;
- return a
- };
- return function(c) {
- if (!a) {
- a = new Ext.draw.Matrix()
- }
- a.elements = c;
- Ext.draw.Matrix.fly = b;
- return a
- }
- })(),
- create: function(a) {
- if (a instanceof this) {
- return a
- }
- return new this(a)
- }
- },
- constructor: function(e, d, a, f, c, b) {
- if (e && e.length === 6) {
- this.elements = e.slice()
- } else {
- if (e !== undefined) {
- this.elements = [e, d, a, f, c, b]
- } else {
- this.elements = [1, 0, 0, 1, 0, 0]
- }
- }
- },
- prepend: function(a, l, h, g, m, k) {
- var b = this.elements,
- d = b[0],
- j = b[1],
- e = b[2],
- c = b[3],
- i = b[4],
- f = b[5];
- b[0] = a * d + h * j;
- b[1] = l * d + g * j;
- b[2] = a * e + h * c;
- b[3] = l * e + g * c;
- b[4] = a * i + h * f + m;
- b[5] = l * i + g * f + k;
- return this
- },
- prependMatrix: function(a) {
- return this.prepend.apply(this, a.elements)
- },
- append: function(a, l, h, g, m, k) {
- var b = this.elements,
- d = b[0],
- j = b[1],
- e = b[2],
- c = b[3],
- i = b[4],
- f = b[5];
- b[0] = a * d + l * e;
- b[1] = a * j + l * c;
- b[2] = h * d + g * e;
- b[3] = h * j + g * c;
- b[4] = m * d + k * e + i;
- b[5] = m * j + k * c + f;
- return this
- },
- appendMatrix: function(a) {
- return this.append.apply(this, a.elements)
- },
- set: function(f, e, a, g, c, b) {
- var d = this.elements;
- d[0] = f;
- d[1] = e;
- d[2] = a;
- d[3] = g;
- d[4] = c;
- d[5] = b;
- return this
- },
- inverse: function(i) {
- var g = this.elements,
- o = g[0],
- m = g[1],
- l = g[2],
- k = g[3],
- j = g[4],
- h = g[5],
- n = 1 / (o * k - m * l);
- o *= n;
- m *= n;
- l *= n;
- k *= n;
- if (i) {
- i.set(k, -m, -l, o, l * h - k * j, m * j - o * h);
- return i
- } else {
- return new Ext.draw.Matrix(k, -m, -l, o, l * h - k * j, m * j - o * h)
- }
- },
- translate: function(a, c, b) {
- if (b) {
- return this.prepend(1, 0, 0, 1, a, c)
- } else {
- return this.append(1, 0, 0, 1, a, c)
- }
- },
- scale: function(f, e, c, a, b) {
- var d = this;
- if (e == null) {
- e = f
- }
- if (c === undefined) {
- c = 0
- }
- if (a === undefined) {
- a = 0
- }
- if (b) {
- return d.prepend(f, 0, 0, e, c - c * f, a - a * e)
- } else {
- return d.append(f, 0, 0, e, c - c * f, a - a * e)
- }
- },
- rotate: function(g, e, c, b) {
- var d = this,
- f = Math.cos(g),
- a = Math.sin(g);
- e = e || 0;
- c = c || 0;
- if (b) {
- return d.prepend(f, a, -a, f, e - f * e + c * a, c - f * c - e * a)
- } else {
- return d.append(f, a, -a, f, e - f * e + c * a, c - f * c - e * a)
- }
- },
- rotateFromVector: function(a, h, c) {
- var e = this,
- g = Math.sqrt(a * a + h * h),
- f = a / g,
- b = h / g;
- if (c) {
- return e.prepend(f, b, -b, f, 0, 0)
- } else {
- return e.append(f, b, -b, f, 0, 0)
- }
- },
- clone: function() {
- return new Ext.draw.Matrix(this.elements)
- },
- flipX: function() {
- return this.append(-1, 0, 0, 1, 0, 0)
- },
- flipY: function() {
- return this.append(1, 0, 0, -1, 0, 0)
- },
- skewX: function(a) {
- return this.append(1, 0, Math.tan(a), 1, 0, 0)
- },
- skewY: function(a) {
- return this.append(1, Math.tan(a), 0, 1, 0, 0)
- },
- shearX: function(a) {
- return this.append(1, 0, a, 1, 0, 0)
- },
- shearY: function(a) {
- return this.append(1, a, 0, 1, 0, 0)
- },
- reset: function() {
- return this.set(1, 0, 0, 1, 0, 0)
- },
- precisionCompensate: function(j, g) {
- var c = this.elements,
- f = c[0],
- e = c[1],
- i = c[2],
- h = c[3],
- d = c[4],
- b = c[5],
- a = e * i - f * h;
- g.b = j * e / f;
- g.c = j * i / h;
- g.d = j;
- g.xx = f / j;
- g.yy = h / j;
- g.dx = (b * f * i - d * f * h) / a / j;
- g.dy = (d * e * h - b * f * h) / a / j
- },
- precisionCompensateRect: function(j, g) {
- var b = this.elements,
- f = b[0],
- e = b[1],
- i = b[2],
- h = b[3],
- c = b[4],
- a = b[5],
- d = i / f;
- g.b = j * e / f;
- g.c = j * d;
- g.d = j * h / f;
- g.xx = f / j;
- g.yy = f / j;
- g.dx = (a * i - c * h) / (e * d - h) / j;
- g.dy = -(a * f - c * e) / (e * d - h) / j
- },
- x: function(a, c) {
- var b = this.elements;
- return a * b[0] + c * b[2] + b[4]
- },
- y: function(a, c) {
- var b = this.elements;
- return a * b[1] + c * b[3] + b[5]
- },
- get: function(b, a) {
- return +this.elements[b + a * 2].toFixed(4)
- },
- transformPoint: function(b) {
- var c = this.elements,
- a, d;
- if (b.isPoint) {
- a = b.x;
- d = b.y
- } else {
- a = b[0];
- d = b[1]
- }
- return [a * c[0] + d * c[2] + c[4], a * c[1] + d * c[3] + c[5]]
- },
- transformBBox: function(q, i, j) {
- var b = this.elements,
- d = q.x,
- r = q.y,
- g = q.width * 0.5,
- o = q.height * 0.5,
- a = b[0],
- s = b[1],
- n = b[2],
- k = b[3],
- e = d + g,
- c = r + o,
- p, f, m;
- if (i) {
- g -= i;
- o -= i;
- m = [Math.sqrt(b[0] * b[0] + b[2] * b[2]), Math.sqrt(b[1] * b[1] + b[3] * b[3])];
- p = Math.abs(g * a) + Math.abs(o * n) + Math.abs(m[0] * i);
- f = Math.abs(g * s) + Math.abs(o * k) + Math.abs(m[1] * i)
- } else {
- p = Math.abs(g * a) + Math.abs(o * n);
- f = Math.abs(g * s) + Math.abs(o * k)
- }
- if (!j) {
- j = {}
- }
- j.x = e * a + c * n + b[4] - p;
- j.y = e * s + c * k + b[5] - f;
- j.width = p + p;
- j.height = f + f;
- return j
- },
- transformList: function(e) {
- var b = this.elements,
- a = b[0],
- h = b[2],
- l = b[4],
- k = b[1],
- g = b[3],
- j = b[5],
- f = e.length,
- c, d;
- for (d = 0; d < f; d++) {
- c = e[d];
- e[d] = [c[0] * a + c[1] * h + l, c[0] * k + c[1] * g + j]
- }
- return e
- },
- isIdentity: function() {
- var a = this.elements;
- return a[0] === 1 && a[1] === 0 && a[2] === 0 && a[3] === 1 && a[4] === 0 && a[5] === 0
- },
- isEqual: function(a) {
- var c = a && a.isMatrix ? a.elements : a,
- b = this.elements;
- return b[0] === c[0] && b[1] === c[1] && b[2] === c[2] && b[3] === c[3] && b[4] === c[4] && b[5] === c[5]
- },
- equals: function(a) {
- return this.isEqual(a)
- },
- toArray: function() {
- var a = this.elements;
- return [a[0], a[2], a[4], a[1], a[3], a[5]]
- },
- toVerticalArray: function() {
- return this.elements.slice()
- },
- toString: function() {
- var a = this;
- return [a.get(0, 0), a.get(0, 1), a.get(1, 0), a.get(1, 1), a.get(2, 0), a.get(2, 1)].join(",")
- },
- toContext: function(a) {
- a.transform.apply(a, this.elements);
- return this
- },
- toSvg: function() {
- var a = this.elements;
- return "matrix(" + a[0].toFixed(9) + "," + a[1].toFixed(9) + "," + a[2].toFixed(9) + "," + a[3].toFixed(9) + "," + a[4].toFixed(9) + "," + a[5].toFixed(9) + ")"
- },
- getScaleX: function() {
- var a = this.elements;
- return Math.sqrt(a[0] * a[0] + a[2] * a[2])
- },
- getScaleY: function() {
- var a = this.elements;
- return Math.sqrt(a[1] * a[1] + a[3] * a[3])
- },
- getXX: function() {
- return this.elements[0]
- },
- getXY: function() {
- return this.elements[1]
- },
- getYX: function() {
- return this.elements[2]
- },
- getYY: function() {
- return this.elements[3]
- },
- getDX: function() {
- return this.elements[4]
- },
- getDY: function() {
- return this.elements[5]
- },
- split: function() {
- var b = this.elements,
- d = b[0],
- c = b[1],
- e = b[3],
- a = {
- translateX: b[4],
- translateY: b[5]
- };
- a.rotate = a.rotation = Math.atan2(c, d);
- a.scaleX = d / Math.cos(a.rotate);
- a.scaleY = e / d * a.scaleX;
- return a
- }
-}, function() {
- function b(e, c, d) {
- e[c] = {
- get: function() {
- return this.elements[d]
- },
- set: function(f) {
- this.elements[d] = f
- }
- }
- }
- if (Object.defineProperties) {
- var a = {};
- b(a, "a", 0);
- b(a, "b", 1);
- b(a, "c", 2);
- b(a, "d", 3);
- b(a, "e", 4);
- b(a, "f", 5);
- Object.defineProperties(this.prototype, a)
- }
- this.prototype.multiply = this.prototype.appendMatrix
-});
-Ext.define("Ext.draw.modifier.Modifier", {
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- previous: null,
- next: null,
- sprite: null
- },
- constructor: function(a) {
- this.mixins.observable.constructor.call(this, a)
- },
- updateNext: function(a) {
- if (a) {
- a.setPrevious(this)
- }
- },
- updatePrevious: function(a) {
- if (a) {
- a.setNext(this)
- }
- },
- prepareAttributes: function(a) {
- if (this._previous) {
- this._previous.prepareAttributes(a)
- }
- },
- popUp: function(a, b) {
- if (this._next) {
- this._next.popUp(a, b)
- } else {
- Ext.apply(a, b)
- }
- },
- pushDown: function(a, c) {
- if (this._previous) {
- return this._previous.pushDown(a, c)
- } else {
- for (var b in c) {
- if (c[b] === a[b]) {
- delete c[b]
- }
- }
- return c
- }
- }
-});
-Ext.define("Ext.draw.modifier.Target", {
- requires: ["Ext.draw.Matrix"],
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.target",
- statics: {
- uniqueId: 0
- },
- prepareAttributes: function(a) {
- var b = this.getPrevious();
- if (b) {
- b.prepareAttributes(a)
- }
- a.attributeId = "attribute-" + Ext.draw.modifier.Target.uniqueId++;
- if (!a.hasOwnProperty("canvasAttributes")) {
- a.bbox = {
- plain: {
- dirty: true
- },
- transform: {
- dirty: true
- }
- };
- a.dirty = true;
- a.pendingUpdaters = {};
- a.canvasAttributes = {};
- a.matrix = new Ext.draw.Matrix();
- a.inverseMatrix = new Ext.draw.Matrix()
- }
- },
- applyChanges: function(f, k) {
- Ext.apply(f, k);
- var l = this.getSprite(),
- o = f.pendingUpdaters,
- h = l.self.def.getTriggers(),
- p, a, m, b, e, n, d, c, g;
- for (b in k) {
- e = true;
- if ((p = h[b])) {
- l.scheduleUpdaters(f, p, [b])
- }
- if (f.template && k.removeFromInstance && k.removeFromInstance[b]) {
- delete f[b]
- }
- }
- if (!e) {
- return
- }
- if (o.canvas) {
- n = o.canvas;
- delete o.canvas;
- for (d = 0, g = n.length; d < g; d++) {
- b = n[d];
- f.canvasAttributes[b] = f[b]
- }
- }
- if (f.hasOwnProperty("children")) {
- a = f.children;
- for (d = 0, g = a.length; d < g; d++) {
- m = a[d];
- Ext.apply(m.pendingUpdaters, o);
- if (n) {
- for (c = 0; c < n.length; c++) {
- b = n[c];
- m.canvasAttributes[b] = m[b]
- }
- }
- l.callUpdaters(m)
- }
- }
- l.setDirty(true);
- l.callUpdaters(f)
- },
- popUp: function(a, b) {
- this.applyChanges(a, b)
- },
- pushDown: function(a, b) {
- var c = this.getPrevious();
- if (c) {
- b = c.pushDown(a, b)
- }
- this.applyChanges(a, b);
- return b
- }
-});
-Ext.define("Ext.draw.TimingFunctions", function() {
- var g = Math.pow,
- j = Math.sin,
- m = Math.cos,
- l = Math.sqrt,
- e = Math.PI,
- b = ["quad", "cube", "quart", "quint"],
- c = {
- pow: function(o, i) {
- return g(o, i || 6)
- },
- expo: function(i) {
- return g(2, 8 * (i - 1))
- },
- circ: function(i) {
- return 1 - l(1 - i * i)
- },
- sine: function(i) {
- return 1 - j((1 - i) * e / 2)
- },
- back: function(i, o) {
- o = o || 1.616;
- return i * i * ((o + 1) * i - o)
- },
- bounce: function(q) {
- for (var o = 0, i = 1; 1; o += i, i /= 2) {
- if (q >= (7 - 4 * o) / 11) {
- return i * i - g((11 - 6 * o - 11 * q) / 4, 2)
- }
- }
- },
- elastic: function(o, i) {
- return g(2, 10 * --o) * m(20 * o * e * (i || 1) / 3)
- }
- },
- k = {},
- a, f, d;
-
- function h(i) {
- return function(o) {
- return g(o, i)
- }
- }
-
- function n(i, o) {
- k[i + "In"] = function(p) {
- return o(p)
- };
- k[i + "Out"] = function(p) {
- return 1 - o(1 - p)
- };
- k[i + "InOut"] = function(p) {
- return (p <= 0.5) ? o(2 * p) / 2 : (2 - o(2 * (1 - p))) / 2
- }
- }
- for (d = 0, f = b.length; d < f; ++d) {
- c[b[d]] = h(d + 2)
- }
- for (a in c) {
- n(a, c[a])
- }
- k.linear = Ext.identityFn;
- k.easeIn = k.quadIn;
- k.easeOut = k.quadOut;
- k.easeInOut = k.quadInOut;
- return {
- singleton: true,
- easingMap: k
- }
-}, function(a) {
- Ext.apply(a, a.easingMap)
-});
-Ext.define("Ext.draw.Animator", {
- uses: ["Ext.draw.Draw"],
- singleton: true,
- frameCallbacks: {},
- frameCallbackId: 0,
- scheduled: 0,
- frameStartTimeOffset: Ext.now(),
- animations: [],
- running: false,
- animationTime: function() {
- return Ext.AnimationQueue.frameStartTime - this.frameStartTimeOffset
- },
- add: function(b) {
- var a = this;
- if (!a.contains(b)) {
- a.animations.push(b);
- a.ignite();
- if ("fireEvent" in b) {
- b.fireEvent("animationstart", b)
- }
- }
- },
- remove: function(d) {
- var c = this,
- e = c.animations,
- b = 0,
- a = e.length;
- for (; b < a; ++b) {
- if (e[b] === d) {
- e.splice(b, 1);
- if ("fireEvent" in d) {
- d.fireEvent("animationend", d)
- }
- return
- }
- }
- },
- contains: function(a) {
- return Ext.Array.indexOf(this.animations, a) > -1
- },
- empty: function() {
- return this.animations.length === 0
- },
- step: function(d) {
- var c = this,
- f = c.animations,
- e, a = 0,
- b = f.length;
- for (; a < b; a++) {
- e = f[a];
- e.step(d);
- if (!e.animating) {
- f.splice(a, 1);
- a--;
- b--;
- if (e.fireEvent) {
- e.fireEvent("animationend", e)
- }
- }
- }
- },
- schedule: function(c, a) {
- a = a || this;
- var b = "frameCallback" + (this.frameCallbackId++);
- if (Ext.isString(c)) {
- c = a[c]
- }
- Ext.draw.Animator.frameCallbacks[b] = {
- fn: c,
- scope: a,
- once: true
- };
- this.scheduled++;
- Ext.draw.Animator.ignite();
- return b
- },
- scheduleIf: function(e, b) {
- b = b || this;
- var c = Ext.draw.Animator.frameCallbacks,
- a, d;
- if (Ext.isString(e)) {
- e = b[e]
- }
- for (d in c) {
- a = c[d];
- if (a.once && a.fn === e && a.scope === b) {
- return null
- }
- }
- return this.schedule(e, b)
- },
- cancel: function(a) {
- if (Ext.draw.Animator.frameCallbacks[a] && Ext.draw.Animator.frameCallbacks[a].once) {
- this.scheduled--;
- delete Ext.draw.Animator.frameCallbacks[a]
- }
- },
- addFrameCallback: function(c, a) {
- a = a || this;
- if (Ext.isString(c)) {
- c = a[c]
- }
- var b = "frameCallback" + (this.frameCallbackId++);
- Ext.draw.Animator.frameCallbacks[b] = {
- fn: c,
- scope: a
- };
- return b
- },
- removeFrameCallback: function(a) {
- delete Ext.draw.Animator.frameCallbacks[a]
- },
- fireFrameCallbacks: function() {
- var c = this.frameCallbacks,
- d, b, a;
- for (d in c) {
- a = c[d];
- b = a.fn;
- if (Ext.isString(b)) {
- b = a.scope[b]
- }
- b.call(a.scope);
- if (c[d] && a.once) {
- this.scheduled--;
- delete c[d]
- }
- }
- },
- handleFrame: function() {
- this.step(this.animationTime());
- this.fireFrameCallbacks();
- if (!this.scheduled && this.empty()) {
- Ext.AnimationQueue.stop(this.handleFrame, this);
- this.running = false;
- Ext.draw.Draw.endUpdateIOS()
- }
- },
- ignite: function() {
- if (!this.running) {
- this.running = true;
- Ext.AnimationQueue.start(this.handleFrame, this);
- Ext.draw.Draw.beginUpdateIOS()
- }
- }
-});
-Ext.define("Ext.draw.modifier.Animation", {
- requires: ["Ext.draw.TimingFunctions", "Ext.draw.Animator"],
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.animation",
- config: {
- easing: Ext.identityFn,
- duration: 0,
- customEasings: {},
- customDurations: {},
- customDuration: null
- },
- constructor: function(a) {
- var b = this;
- b.anyAnimation = b.anySpecialAnimations = false;
- b.animating = 0;
- b.animatingPool = [];
- b.callParent([a])
- },
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("timers")) {
- a.animating = false;
- a.timers = {};
- a.animationOriginal = Ext.Object.chain(a);
- a.animationOriginal.prototype = a
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.animationOriginal)
- }
- },
- updateSprite: function(a) {
- this.setConfig(a.config.fx)
- },
- updateDuration: function(a) {
- this.anyAnimation = a > 0
- },
- applyEasing: function(a) {
- if (typeof a === "string") {
- a = Ext.draw.TimingFunctions.easingMap[a]
- }
- return a
- },
- applyCustomEasings: function(a, e) {
- e = e || {};
- var g, d, b, h, c, f;
- for (d in a) {
- g = true;
- h = a[d];
- b = d.split(",");
- if (typeof h === "string") {
- h = Ext.draw.TimingFunctions.easingMap[h]
- }
- for (c = 0, f = b.length; c < f; c++) {
- e[b[c]] = h
- }
- }
- if (g) {
- this.anySpecialAnimations = g
- }
- return e
- },
- setEasingOn: function(a, e) {
- a = Ext.Array.from(a).slice();
- var c = {},
- d = a.length,
- b = 0;
- for (; b < d; b++) {
- c[a[b]] = e
- }
- this.setCustomEasings(c)
- },
- clearEasingOn: function(a) {
- a = Ext.Array.from(a, true);
- var b = 0,
- c = a.length;
- for (; b < c; b++) {
- delete this._customEasings[a[b]]
- }
- },
- applyCustomDurations: function(g, h) {
- h = h || {};
- var e, c, f, a, b, d;
- for (c in g) {
- e = true;
- f = g[c];
- a = c.split(",");
- for (b = 0, d = a.length; b < d; b++) {
- h[a[b]] = f
- }
- }
- if (e) {
- this.anySpecialAnimations = e
- }
- return h
- },
- applyCustomDuration: function(a, b) {
- if (a) {
- this.getCustomDurations();
- this.setCustomDurations(a)
- }
- },
- setDurationOn: function(b, e) {
- b = Ext.Array.from(b).slice();
- var a = {},
- c = 0,
- d = b.length;
- for (; c < d; c++) {
- a[b[c]] = e
- }
- this.setCustomDurations(a)
- },
- clearDurationOn: function(a) {
- a = Ext.Array.from(a, true);
- var b = 0,
- c = a.length;
- for (; b < c; b++) {
- delete this._customDurations[a[b]]
- }
- },
- setAnimating: function(a, b) {
- var e = this,
- d = e.animatingPool;
- if (a.animating !== b) {
- a.animating = b;
- if (b) {
- d.push(a);
- if (e.animating === 0) {
- Ext.draw.Animator.add(e)
- }
- e.animating++
- } else {
- for (var c = d.length; c--;) {
- if (d[c] === a) {
- d.splice(c, 1)
- }
- }
- e.animating = d.length
- }
- }
- },
- setAttrs: function(r, t) {
- var s = this,
- m = r.timers,
- h = s._sprite.self.def._animationProcessors,
- f = s._easing,
- e = s._duration,
- j = s._customDurations,
- i = s._customEasings,
- g = s.anySpecialAnimations,
- n = s.anyAnimation || g,
- o = r.animationOriginal,
- d = false,
- k, u, l, p, c, q, a;
- if (!n) {
- for (u in t) {
- if (r[u] === t[u]) {
- delete t[u]
- } else {
- r[u] = t[u]
- }
- delete o[u];
- delete m[u]
- }
- return t
- } else {
- for (u in t) {
- l = t[u];
- p = r[u];
- if (l !== p && p !== undefined && p !== null && (c = h[u])) {
- q = f;
- a = e;
- if (g) {
- if (u in i) {
- q = i[u]
- }
- if (u in j) {
- a = j[u]
- }
- }
- if (p && p.isGradient || l && l.isGradient) {
- a = 0
- }
- if (a) {
- if (!m[u]) {
- m[u] = {}
- }
- k = m[u];
- k.start = 0;
- k.easing = q;
- k.duration = a;
- k.compute = c.compute;
- k.serve = c.serve || Ext.identityFn;
- k.remove = t.removeFromInstance && t.removeFromInstance[u];
- if (c.parseInitial) {
- var b = c.parseInitial(p, l);
- k.source = b[0];
- k.target = b[1]
- } else {
- if (c.parse) {
- k.source = c.parse(p);
- k.target = c.parse(l)
- } else {
- k.source = p;
- k.target = l
- }
- }
- o[u] = l;
- delete t[u];
- d = true;
- continue
- } else {
- delete o[u]
- }
- } else {
- delete o[u]
- }
- delete m[u]
- }
- }
- if (d && !r.animating) {
- s.setAnimating(r, true)
- }
- return t
- },
- updateAttributes: function(g) {
- if (!g.animating) {
- return {}
- }
- var h = {},
- e = false,
- d = g.timers,
- f = g.animationOriginal,
- c = Ext.draw.Animator.animationTime(),
- a, b, i;
- if (g.lastUpdate === c) {
- return null
- }
- for (a in d) {
- b = d[a];
- if (!b.start) {
- b.start = c;
- i = 0
- } else {
- i = (c - b.start) / b.duration
- }
- if (i >= 1) {
- h[a] = f[a];
- delete f[a];
- if (d[a].remove) {
- h.removeFromInstance = h.removeFromInstance || {};
- h.removeFromInstance[a] = true
- }
- delete d[a]
- } else {
- h[a] = b.serve(b.compute(b.source, b.target, b.easing(i), g[a]));
- e = true
- }
- }
- g.lastUpdate = c;
- this.setAnimating(g, e);
- return h
- },
- pushDown: function(a, b) {
- b = this.callParent([a.animationOriginal, b]);
- return this.setAttrs(a, b)
- },
- popUp: function(a, b) {
- a = a.prototype;
- b = this.setAttrs(a, b);
- if (this._next) {
- return this._next.popUp(a, b)
- } else {
- return Ext.apply(a, b)
- }
- },
- step: function(g) {
- var f = this,
- c = f.animatingPool.slice(),
- e = c.length,
- b = 0,
- a, d;
- for (; b < e; b++) {
- a = c[b];
- d = f.updateAttributes(a);
- if (d && f._next) {
- f._next.popUp(a, d)
- }
- }
- },
- stop: function() {
- this.step();
- var d = this,
- b = d.animatingPool,
- a, c;
- for (a = 0, c = b.length; a < c; a++) {
- b[a].animating = false
- }
- d.animatingPool.length = 0;
- d.animating = 0;
- Ext.draw.Animator.remove(d)
- },
- destroy: function() {
- this.animatingPool.length = 0;
- this.animating = 0;
- this.callParent()
- }
-});
-Ext.define("Ext.draw.modifier.Highlight", {
- extend: "Ext.draw.modifier.Modifier",
- alias: "modifier.highlight",
- config: {
- enabled: false,
- highlightStyle: null
- },
- preFx: true,
- applyHighlightStyle: function(b, a) {
- a = a || {};
- if (this.getSprite()) {
- Ext.apply(a, this.getSprite().self.def.normalize(b))
- } else {
- Ext.apply(a, b)
- }
- return a
- },
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("highlightOriginal")) {
- a.highlighted = false;
- a.highlightOriginal = Ext.Object.chain(a);
- a.highlightOriginal.prototype = a;
- a.highlightOriginal.removeFromInstance = {}
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.highlightOriginal)
- }
- },
- updateSprite: function(b, a) {
- if (b) {
- if (this.getHighlightStyle()) {
- this._highlightStyle = b.self.def.normalize(this.getHighlightStyle())
- }
- this.setHighlightStyle(b.config.highlight)
- }
- b.self.def.setConfig({
- defaults: {
- highlighted: false
- },
- processors: {
- highlighted: "bool"
- }
- });
- this.setSprite(b)
- },
- filterChanges: function(a, d) {
- var e = this,
- f = a.highlightOriginal,
- c = e.getHighlightStyle(),
- b;
- if (a.highlighted) {
- for (b in d) {
- if (c.hasOwnProperty(b)) {
- f[b] = d[b];
- delete d[b]
- }
- }
- }
- for (b in d) {
- if (b !== "highlighted" && f[b] === d[b]) {
- delete d[b]
- }
- }
- return d
- },
- pushDown: function(e, g) {
- var f = this.getHighlightStyle(),
- c = e.highlightOriginal,
- i = c.removeFromInstance,
- d, a, h, b;
- if (g.hasOwnProperty("highlighted")) {
- d = g.highlighted;
- delete g.highlighted;
- if (this._previous) {
- g = this._previous.pushDown(c, g)
- }
- g = this.filterChanges(e, g);
- if (d !== e.highlighted) {
- if (d) {
- for (a in f) {
- if (a in g) {
- c[a] = g[a]
- } else {
- h = e.template && e.template.ownAttr;
- if (h && !e.prototype.hasOwnProperty(a)) {
- i[a] = true;
- c[a] = h.animationOriginal[a]
- } else {
- b = c.timers[a];
- if (b && b.remove) {
- i[a] = true
- }
- c[a] = e[a]
- }
- }
- if (c[a] !== f[a]) {
- g[a] = f[a]
- }
- }
- } else {
- for (a in f) {
- if (!(a in g)) {
- g[a] = c[a]
- }
- delete c[a]
- }
- g.removeFromInstance = g.removeFromInstance || {};
- Ext.apply(g.removeFromInstance, i);
- c.removeFromInstance = {}
- }
- g.highlighted = d
- }
- } else {
- if (this._previous) {
- g = this._previous.pushDown(c, g)
- }
- g = this.filterChanges(e, g)
- }
- return g
- },
- popUp: function(a, b) {
- b = this.filterChanges(a, b);
- Ext.draw.modifier.Modifier.prototype.popUp.call(this, a, b)
- }
-});
-Ext.define("Ext.draw.sprite.Sprite", {
- alias: "sprite.sprite",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- requires: ["Ext.draw.Draw", "Ext.draw.gradient.Gradient", "Ext.draw.sprite.AttributeDefinition", "Ext.draw.modifier.Target", "Ext.draw.modifier.Animation", "Ext.draw.modifier.Highlight"],
- isSprite: true,
- statics: {
- defaultHitTestOptions: {
- fill: true,
- stroke: true
- }
- },
- inheritableStatics: {
- def: {
- processors: {
- strokeStyle: "color",
- fillStyle: "color",
- strokeOpacity: "limited01",
- fillOpacity: "limited01",
- lineWidth: "number",
- lineCap: "enums(butt,round,square)",
- lineJoin: "enums(round,bevel,miter)",
- lineDash: "data",
- lineDashOffset: "number",
- miterLimit: "number",
- shadowColor: "color",
- shadowOffsetX: "number",
- shadowOffsetY: "number",
- shadowBlur: "number",
- globalAlpha: "limited01",
- globalCompositeOperation: "enums(source-over,destination-over,source-in,destination-in,source-out,destination-out,source-atop,destination-atop,lighter,xor,copy)",
- hidden: "bool",
- transformFillStroke: "bool",
- zIndex: "number",
- translationX: "number",
- translationY: "number",
- rotationRads: "number",
- rotationCenterX: "number",
- rotationCenterY: "number",
- scalingX: "number",
- scalingY: "number",
- scalingCenterX: "number",
- scalingCenterY: "number",
- constrainGradients: "bool"
- },
- aliases: {
- stroke: "strokeStyle",
- fill: "fillStyle",
- color: "fillStyle",
- "stroke-width": "lineWidth",
- "stroke-linecap": "lineCap",
- "stroke-linejoin": "lineJoin",
- "stroke-miterlimit": "miterLimit",
- "text-anchor": "textAlign",
- opacity: "globalAlpha",
- translateX: "translationX",
- translateY: "translationY",
- rotateRads: "rotationRads",
- rotateCenterX: "rotationCenterX",
- rotateCenterY: "rotationCenterY",
- scaleX: "scalingX",
- scaleY: "scalingY",
- scaleCenterX: "scalingCenterX",
- scaleCenterY: "scalingCenterY"
- },
- defaults: {
- hidden: false,
- zIndex: 0,
- strokeStyle: "none",
- fillStyle: "none",
- lineWidth: 1,
- lineDash: [],
- lineDashOffset: 0,
- lineCap: "butt",
- lineJoin: "miter",
- miterLimit: 10,
- shadowColor: "none",
- shadowOffsetX: 0,
- shadowOffsetY: 0,
- shadowBlur: 0,
- globalAlpha: 1,
- strokeOpacity: 1,
- fillOpacity: 1,
- transformFillStroke: false,
- translationX: 0,
- translationY: 0,
- rotationRads: 0,
- rotationCenterX: null,
- rotationCenterY: null,
- scalingX: 1,
- scalingY: 1,
- scalingCenterX: null,
- scalingCenterY: null,
- constrainGradients: false
- },
- triggers: {
- zIndex: "zIndex",
- globalAlpha: "canvas",
- globalCompositeOperation: "canvas",
- transformFillStroke: "canvas",
- strokeStyle: "canvas",
- fillStyle: "canvas",
- strokeOpacity: "canvas",
- fillOpacity: "canvas",
- lineWidth: "canvas",
- lineCap: "canvas",
- lineJoin: "canvas",
- lineDash: "canvas",
- lineDashOffset: "canvas",
- miterLimit: "canvas",
- shadowColor: "canvas",
- shadowOffsetX: "canvas",
- shadowOffsetY: "canvas",
- shadowBlur: "canvas",
- translationX: "transform",
- translationY: "transform",
- rotationRads: "transform",
- rotationCenterX: "transform",
- rotationCenterY: "transform",
- scalingX: "transform",
- scalingY: "transform",
- scalingCenterX: "transform",
- scalingCenterY: "transform",
- constrainGradients: "canvas"
- },
- updaters: {
- bbox: "bboxUpdater",
- zIndex: function(a) {
- a.dirtyZIndex = true
- },
- transform: function(a) {
- a.dirtyTransform = true;
- a.bbox.transform.dirty = true
- }
- }
- }
- },
- config: {
- parent: null,
- surface: null
- },
- onClassExtended: function(d, c) {
- var b = d.superclass.self.def.initialConfig,
- e = c.inheritableStatics && c.inheritableStatics.def,
- a;
- if (e) {
- a = Ext.Object.merge({}, b, e);
- d.def = new Ext.draw.sprite.AttributeDefinition(a);
- delete c.inheritableStatics.def
- } else {
- d.def = new Ext.draw.sprite.AttributeDefinition(b)
- }
- d.def.spriteClass = d
- },
- constructor: function(b) {
- var d = this,
- c = d.self.def,
- e = c.getDefaults(),
- a;
- b = Ext.isObject(b) ? b : {};
- d.id = b.id || Ext.id(null, "ext-sprite-");
- d.attr = {};
- d.mixins.observable.constructor.apply(d, arguments);
- a = Ext.Array.from(b.modifiers, true);
- d.prepareModifiers(a);
- d.initializeAttributes();
- d.setAttributes(e, true);
- d.setAttributes(b)
- },
- getDirty: function() {
- return this.attr.dirty
- },
- setDirty: function(b) {
- this.attr.dirty = b;
- if (b) {
- var a = this.getParent();
- if (a) {
- a.setDirty(true)
- }
- }
- },
- addModifier: function(a, b) {
- var c = this;
- if (!(a instanceof Ext.draw.modifier.Modifier)) {
- a = Ext.factory(a, null, null, "modifier")
- }
- a.setSprite(c);
- if (a.preFx || a.config && a.config.preFx) {
- if (c.fx.getPrevious()) {
- c.fx.getPrevious().setNext(a)
- }
- a.setNext(c.fx)
- } else {
- c.topModifier.getPrevious().setNext(a);
- a.setNext(c.topModifier)
- }
- if (b) {
- c.initializeAttributes()
- }
- return a
- },
- prepareModifiers: function(d) {
- var c = this,
- a, b;
- c.topModifier = new Ext.draw.modifier.Target({
- sprite: c
- });
- c.fx = new Ext.draw.modifier.Animation({
- sprite: c
- });
- c.fx.setNext(c.topModifier);
- for (a = 0, b = d.length; a < b; a++) {
- c.addModifier(d[a], false)
- }
- },
- getAnimation: function() {
- return this.fx
- },
- setAnimation: function(a) {
- this.fx.setConfig(a)
- },
- initializeAttributes: function() {
- this.topModifier.prepareAttributes(this.attr)
- },
- callUpdaters: function(d) {
- var e = this,
- h = d.pendingUpdaters,
- i = e.self.def.getUpdaters(),
- c = false,
- a = false,
- b, g, f;
- e.callUpdaters = Ext.emptyFn;
- do {
- c = false;
- for (g in h) {
- c = true;
- b = h[g];
- delete h[g];
- f = i[g];
- if (typeof f === "string") {
- f = e[f]
- }
- if (f) {
- f.call(e, d, b)
- }
- }
- a = a || c
- } while (c);
- delete e.callUpdaters;
- if (a) {
- e.setDirty(true)
- }
- },
- scheduleUpdaters: function(a, e, c) {
- var f;
- if (c) {
- for (var b = 0, d = e.length; b < d; b++) {
- f = e[b];
- this.scheduleUpdater(a, f, c)
- }
- } else {
- for (f in e) {
- c = e[f];
- this.scheduleUpdater(a, f, c)
- }
- }
- },
- scheduleUpdater: function(a, c, b) {
- b = b || [];
- var d = a.pendingUpdaters;
- if (c in d) {
- if (b.length) {
- d[c] = Ext.Array.merge(d[c], b)
- }
- } else {
- d[c] = b
- }
- },
- setAttributes: function(d, g, c) {
- var a = this.attr,
- b, e, f;
- if (g) {
- if (c) {
- this.topModifier.pushDown(a, d)
- } else {
- f = {};
- for (b in d) {
- e = d[b];
- if (e !== a[b]) {
- f[b] = e
- }
- }
- this.topModifier.pushDown(a, f)
- }
- } else {
- this.topModifier.pushDown(a, this.self.def.normalize(d))
- }
- },
- setAttributesBypassingNormalization: function(b, a) {
- return this.setAttributes(b, true, a)
- },
- bboxUpdater: function(b) {
- var c = b.rotationRads !== 0,
- a = b.scalingX !== 1 || b.scalingY !== 1,
- d = b.rotationCenterX === null || b.rotationCenterY === null,
- e = b.scalingCenterX === null || b.scalingCenterY === null;
- b.bbox.plain.dirty = true;
- b.bbox.transform.dirty = true;
- if (c && d || a && e) {
- this.scheduleUpdater(b, "transform")
- }
- },
- getBBox: function(d) {
- var e = this,
- a = e.attr,
- f = a.bbox,
- c = f.plain,
- b = f.transform;
- if (c.dirty) {
- e.updatePlainBBox(c);
- c.dirty = false
- }
- if (!d) {
- e.applyTransformations();
- if (b.dirty) {
- e.updateTransformedBBox(b, c);
- b.dirty = false
- }
- return b
- }
- return c
- },
- updatePlainBBox: Ext.emptyFn,
- updateTransformedBBox: function(a, b) {
- this.attr.matrix.transformBBox(b, 0, a)
- },
- getBBoxCenter: function(a) {
- var b = this.getBBox(a);
- if (b) {
- return [b.x + b.width * 0.5, b.y + b.height * 0.5]
- } else {
- return [0, 0]
- }
- },
- hide: function() {
- this.attr.hidden = true;
- this.setDirty(true);
- return this
- },
- show: function() {
- this.attr.hidden = false;
- this.setDirty(true);
- return this
- },
- useAttributes: function(i, f) {
- this.applyTransformations();
- var d = this.attr,
- h = d.canvasAttributes,
- e = h.strokeStyle,
- g = h.fillStyle,
- b = h.lineDash,
- c = h.lineDashOffset,
- a;
- if (e) {
- if (e.isGradient) {
- i.strokeStyle = "black";
- i.strokeGradient = e
- } else {
- i.strokeGradient = false
- }
- }
- if (g) {
- if (g.isGradient) {
- i.fillStyle = "black";
- i.fillGradient = g
- } else {
- i.fillGradient = false
- }
- }
- if (b) {
- i.setLineDash(b)
- }
- if (Ext.isNumber(c + i.lineDashOffset)) {
- i.lineDashOffset = c
- }
- for (a in h) {
- if (h[a] !== undefined && h[a] !== i[a]) {
- i[a] = h[a]
- }
- }
- this.setGradientBBox(i, f)
- },
- setGradientBBox: function(b, c) {
- var a = this.attr;
- if (a.constrainGradients) {
- b.setGradientBBox({
- x: c[0],
- y: c[1],
- width: c[2],
- height: c[3]
- })
- } else {
- b.setGradientBBox(this.getBBox(a.transformFillStroke))
- }
- },
- applyTransformations: function(b) {
- if (!b && !this.attr.dirtyTransform) {
- return
- }
- var r = this,
- k = r.attr,
- p = r.getBBoxCenter(true),
- g = p[0],
- f = p[1],
- q = k.translationX,
- o = k.translationY,
- j = k.scalingX,
- i = k.scalingY === null ? k.scalingX : k.scalingY,
- m = k.scalingCenterX === null ? g : k.scalingCenterX,
- l = k.scalingCenterY === null ? f : k.scalingCenterY,
- s = k.rotationRads,
- e = k.rotationCenterX === null ? g : k.rotationCenterX,
- d = k.rotationCenterY === null ? f : k.rotationCenterY,
- c = Math.cos(s),
- a = Math.sin(s),
- n, h;
- if (j === 1 && i === 1) {
- m = 0;
- l = 0
- }
- if (s === 0) {
- e = 0;
- d = 0
- }
- n = m * (1 - j) - e;
- h = l * (1 - i) - d;
- k.matrix.elements = [c * j, a * j, -a * i, c * i, c * n - a * h + e + q, a * n + c * h + d + o];
- k.matrix.inverse(k.inverseMatrix);
- k.dirtyTransform = false;
- k.bbox.transform.dirty = true
- },
- transform: function(b, c) {
- var a = this.attr,
- e = a.matrix,
- d;
- if (b && b.isMatrix) {
- d = b.elements
- } else {
- d = b
- }
- e.prepend.apply(e, d.slice());
- e.inverse(a.inverseMatrix);
- if (c) {
- this.updateTransformAttributes()
- }
- a.dirtyTransform = false;
- a.bbox.transform.dirty = true;
- this.setDirty(true);
- return this
- },
- updateTransformAttributes: function() {
- var a = this.attr,
- b = a.matrix.split();
- a.rotationRads = b.rotate;
- a.rotationCenterX = 0;
- a.rotationCenterY = 0;
- a.scalingX = b.scaleX;
- a.scalingY = b.scaleY;
- a.scalingCenterX = 0;
- a.scalingCenterY = 0;
- a.translationX = b.translateX;
- a.translationY = b.translateY
- },
- resetTransform: function(b) {
- var a = this.attr;
- a.matrix.reset();
- a.inverseMatrix.reset();
- if (!b) {
- this.updateTransformAttributes()
- }
- a.dirtyTransform = false;
- a.bbox.transform.dirty = true;
- this.setDirty(true);
- return this
- },
- setTransform: function(a, b) {
- this.resetTransform(true);
- this.transform.call(this, a, b);
- return this
- },
- preRender: Ext.emptyFn,
- render: Ext.emptyFn,
- hitTest: function(b, c) {
- if (this.isVisible()) {
- var a = b[0],
- f = b[1],
- e = this.getBBox(),
- d = e && a >= e.x && a <= (e.x + e.width) && f >= e.y && f <= (e.y + e.height);
- if (d) {
- return {
- sprite: this
- }
- }
- }
- return null
- },
- isVisible: function() {
- var e = this.attr,
- f = this.getParent(),
- g = f && (f.isSurface || f.isVisible()),
- d = g && !e.hidden && e.globalAlpha,
- b = Ext.draw.Color.NONE,
- a = Ext.draw.Color.RGBA_NONE,
- c = e.fillOpacity && e.fillStyle !== b && e.fillStyle !== a,
- i = e.strokeOpacity && e.strokeStyle !== b && e.strokeStyle !== a,
- h = d && (c || i);
- return !!h
- },
- repaint: function() {
- var a = this.getSurface();
- if (a) {
- a.renderFrame()
- }
- },
- remove: function() {
- var a = this.getSurface();
- if (a && a.isSurface) {
- return a.remove(this)
- }
- return null
- },
- destroy: function() {
- var b = this,
- a = b.topModifier,
- c;
- while (a) {
- c = a;
- a = a.getPrevious();
- c.destroy()
- }
- delete b.attr;
- b.remove();
- if (b.fireEvent("beforedestroy", b) !== false) {
- b.fireEvent("destroy", b)
- }
- b.callParent()
- }
-}, function() {
- this.def = new Ext.draw.sprite.AttributeDefinition(this.def);
- this.def.spriteClass = this
-});
-Ext.define("Ext.draw.Path", {
- requires: ["Ext.draw.Draw"],
- statics: {
- pathRe: /,?([achlmqrstvxz]),?/gi,
- pathRe2: /-/gi,
- pathSplitRe: /\s|,/g
- },
- svgString: "",
- constructor: function(a) {
- var b = this;
- b.commands = [];
- b.params = [];
- b.cursor = null;
- b.startX = 0;
- b.startY = 0;
- if (a) {
- b.fromSvgString(a)
- }
- },
- clear: function() {
- var a = this;
- a.params.length = 0;
- a.commands.length = 0;
- a.cursor = null;
- a.startX = 0;
- a.startY = 0;
- a.dirt()
- },
- dirt: function() {
- this.svgString = ""
- },
- moveTo: function(a, c) {
- var b = this;
- if (!b.cursor) {
- b.cursor = [a, c]
- }
- b.params.push(a, c);
- b.commands.push("M");
- b.startX = a;
- b.startY = c;
- b.cursor[0] = a;
- b.cursor[1] = c;
- b.dirt()
- },
- lineTo: function(a, c) {
- var b = this;
- if (!b.cursor) {
- b.cursor = [a, c];
- b.params.push(a, c);
- b.commands.push("M")
- } else {
- b.params.push(a, c);
- b.commands.push("L")
- }
- b.cursor[0] = a;
- b.cursor[1] = c;
- b.dirt()
- },
- bezierCurveTo: function(c, e, b, d, a, g) {
- var f = this;
- if (!f.cursor) {
- f.moveTo(c, e)
- }
- f.params.push(c, e, b, d, a, g);
- f.commands.push("C");
- f.cursor[0] = a;
- f.cursor[1] = g;
- f.dirt()
- },
- quadraticCurveTo: function(b, e, a, d) {
- var c = this;
- if (!c.cursor) {
- c.moveTo(b, e)
- }
- c.bezierCurveTo((2 * b + c.cursor[0]) / 3, (2 * e + c.cursor[1]) / 3, (2 * b + a) / 3, (2 * e + d) / 3, a, d)
- },
- closePath: function() {
- var a = this;
- if (a.cursor) {
- a.cursor = null;
- a.commands.push("Z");
- a.dirt()
- }
- },
- arcTo: function(A, f, z, d, j, i, v) {
- var E = this;
- if (i === undefined) {
- i = j
- }
- if (v === undefined) {
- v = 0
- }
- if (!E.cursor) {
- E.moveTo(A, f);
- return
- }
- if (j === 0 || i === 0) {
- E.lineTo(A, f);
- return
- }
- z -= A;
- d -= f;
- var B = E.cursor[0] - A,
- g = E.cursor[1] - f,
- C = z * g - d * B,
- b, a, l, r, k, q, x = Math.sqrt(B * B + g * g),
- u = Math.sqrt(z * z + d * d),
- t, e, c;
- if (C === 0) {
- E.lineTo(A, f);
- return
- }
- if (i !== j) {
- b = Math.cos(v);
- a = Math.sin(v);
- l = b / j;
- r = a / i;
- k = -a / j;
- q = b / i;
- var D = l * B + r * g;
- g = k * B + q * g;
- B = D;
- D = l * z + r * d;
- d = k * z + q * d;
- z = D
- } else {
- B /= j;
- g /= i;
- z /= j;
- d /= i
- }
- e = B * u + z * x;
- c = g * u + d * x;
- t = 1 / (Math.sin(Math.asin(Math.abs(C) / (x * u)) * 0.5) * Math.sqrt(e * e + c * c));
- e *= t;
- c *= t;
- var o = (e * B + c * g) / (B * B + g * g),
- m = (e * z + c * d) / (z * z + d * d);
- var n = B * o - e,
- p = g * o - c,
- h = z * m - e,
- y = d * m - c,
- w = Math.atan2(p, n),
- s = Math.atan2(y, h);
- if (C > 0) {
- if (s < w) {
- s += Math.PI * 2
- }
- } else {
- if (w < s) {
- w += Math.PI * 2
- }
- }
- if (i !== j) {
- e = b * e * j - a * c * i + A;
- c = a * c * i + b * c * i + f;
- E.lineTo(b * j * n - a * i * p + e, a * j * n + b * i * p + c);
- E.ellipse(e, c, j, i, v, w, s, C < 0)
- } else {
- e = e * j + A;
- c = c * i + f;
- E.lineTo(j * n + e, i * p + c);
- E.ellipse(e, c, j, i, v, w, s, C < 0)
- }
- },
- ellipse: function(h, f, c, a, q, n, d, e) {
- var o = this,
- g = o.params,
- b = g.length,
- m, l, k;
- if (d - n >= Math.PI * 2) {
- o.ellipse(h, f, c, a, q, n, n + Math.PI, e);
- o.ellipse(h, f, c, a, q, n + Math.PI, d, e);
- return
- }
- if (!e) {
- if (d < n) {
- d += Math.PI * 2
- }
- m = o.approximateArc(g, h, f, c, a, q, n, d)
- } else {
- if (n < d) {
- n += Math.PI * 2
- }
- m = o.approximateArc(g, h, f, c, a, q, d, n);
- for (l = b, k = g.length - 2; l < k; l += 2, k -= 2) {
- var p = g[l];
- g[l] = g[k];
- g[k] = p;
- p = g[l + 1];
- g[l + 1] = g[k + 1];
- g[k + 1] = p
- }
- }
- if (!o.cursor) {
- o.cursor = [g[g.length - 2], g[g.length - 1]];
- o.commands.push("M")
- } else {
- o.cursor[0] = g[g.length - 2];
- o.cursor[1] = g[g.length - 1];
- o.commands.push("L")
- }
- for (l = 2; l < m; l += 6) {
- o.commands.push("C")
- }
- o.dirt()
- },
- arc: function(b, f, a, d, c, e) {
- this.ellipse(b, f, a, a, 0, d, c, e)
- },
- rect: function(b, e, c, a) {
- if (c == 0 || a == 0) {
- return
- }
- var d = this;
- d.moveTo(b, e);
- d.lineTo(b + c, e);
- d.lineTo(b + c, e + a);
- d.lineTo(b, e + a);
- d.closePath()
- },
- approximateArc: function(s, i, f, o, n, d, x, v) {
- var e = Math.cos(d),
- z = Math.sin(d),
- k = Math.cos(x),
- l = Math.sin(x),
- q = e * k * o - z * l * n,
- y = -e * l * o - z * k * n,
- p = z * k * o + e * l * n,
- w = -z * l * o + e * k * n,
- m = Math.PI / 2,
- r = 2,
- j = q,
- u = y,
- h = p,
- t = w,
- b = 0.547443256150549,
- C, g, A, a, B, c;
- v -= x;
- if (v < 0) {
- v += Math.PI * 2
- }
- s.push(q + i, p + f);
- while (v >= m) {
- s.push(j + u * b + i, h + t * b + f, j * b + u + i, h * b + t + f, u + i, t + f);
- r += 6;
- v -= m;
- C = j;
- j = u;
- u = -C;
- C = h;
- h = t;
- t = -C
- }
- if (v) {
- g = (0.3294738052815987 + 0.012120855841304373 * v) * v;
- A = Math.cos(v);
- a = Math.sin(v);
- B = A + g * a;
- c = a - g * A;
- s.push(j + u * g + i, h + t * g + f, j * B + u * c + i, h * B + t * c + f, j * A + u * a + i, h * A + t * a + f);
- r += 6
- }
- return r
- },
- arcSvg: function(j, h, r, m, w, t, c) {
- if (j < 0) {
- j = -j
- }
- if (h < 0) {
- h = -h
- }
- var x = this,
- u = x.cursor[0],
- f = x.cursor[1],
- a = (u - t) / 2,
- y = (f - c) / 2,
- d = Math.cos(r),
- s = Math.sin(r),
- o = a * d + y * s,
- v = -a * s + y * d,
- i = o / j,
- g = v / h,
- p = i * i + g * g,
- e = (u + t) * 0.5,
- b = (f + c) * 0.5,
- l = 0,
- k = 0;
- if (p >= 1) {
- p = Math.sqrt(p);
- j *= p;
- h *= p
- } else {
- p = Math.sqrt(1 / p - 1);
- if (m === w) {
- p = -p
- }
- l = p * j * g;
- k = -p * h * i;
- e += d * l - s * k;
- b += s * l + d * k
- }
- var q = Math.atan2((v - k) / h, (o - l) / j),
- n = Math.atan2((-v - k) / h, (-o - l) / j) - q;
- if (w) {
- if (n <= 0) {
- n += Math.PI * 2
- }
- } else {
- if (n >= 0) {
- n -= Math.PI * 2
- }
- }
- x.ellipse(e, b, j, h, r, q, q + n, 1 - w)
- },
- fromSvgString: function(e) {
- if (!e) {
- return
- }
- var m = this,
- h, l = {
- a: 7,
- c: 6,
- h: 1,
- l: 2,
- m: 2,
- q: 4,
- s: 4,
- t: 2,
- v: 1,
- z: 0,
- A: 7,
- C: 6,
- H: 1,
- L: 2,
- M: 2,
- Q: 4,
- S: 4,
- T: 2,
- V: 1,
- Z: 0
- },
- k = "",
- g, f, c = 0,
- b = 0,
- d = false,
- j, n, a;
- if (Ext.isString(e)) {
- h = e.replace(Ext.draw.Path.pathRe, " $1 ").replace(Ext.draw.Path.pathRe2, " -").split(Ext.draw.Path.pathSplitRe)
- } else {
- if (Ext.isArray(e)) {
- h = e.join(",").split(Ext.draw.Path.pathSplitRe)
- }
- }
- for (j = 0, n = 0; j < h.length; j++) {
- if (h[j] !== "") {
- h[n++] = h[j]
- }
- }
- h.length = n;
- m.clear();
- for (j = 0; j < h.length;) {
- k = d;
- d = h[j];
- a = (d.toUpperCase() !== d);
- j++;
- switch (d) {
- case "M":
- m.moveTo(c = +h[j], b = +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2
- }
- break;
- case "L":
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b = +h[j + 1]);
- j += 2
- }
- break;
- case "A":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.arcSvg(+h[j], +h[j + 1], +h[j + 2] * Math.PI / 180, +h[j + 3], +h[j + 4], c = +h[j + 5], b = +h[j + 6]);
- j += 7
- }
- break;
- case "C":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(+h[j], +h[j + 1], g = +h[j + 2], f = +h[j + 3], c = +h[j + 4], b = +h[j + 5]);
- j += 6
- }
- break;
- case "Z":
- m.closePath();
- break;
- case "m":
- m.moveTo(c += +h[j], b += +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2
- }
- break;
- case "l":
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2;
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b += +h[j + 1]);
- j += 2
- }
- break;
- case "a":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.arcSvg(+h[j], +h[j + 1], +h[j + 2] * Math.PI / 180, +h[j + 3], +h[j + 4], c += +h[j + 5], b += +h[j + 6]);
- j += 7
- }
- break;
- case "c":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + (+h[j]), b + (+h[j + 1]), g = c + (+h[j + 2]), f = b + (+h[j + 3]), c += +h[j + 4], b += +h[j + 5]);
- j += 6
- }
- break;
- case "z":
- m.closePath();
- break;
- case "s":
- if (!(k === "c" || k === "C" || k === "s" || k === "S")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + c - g, b + b - f, g = c + (+h[j]), f = b + (+h[j + 1]), c += +h[j + 2], b += +h[j + 3]);
- j += 4
- }
- break;
- case "S":
- if (!(k === "c" || k === "C" || k === "s" || k === "S")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.bezierCurveTo(c + c - g, b + b - f, g = +h[j], f = +h[j + 1], c = (+h[j + 2]), b = (+h[j + 3]));
- j += 4
- }
- break;
- case "q":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + (+h[j]), f = b + (+h[j + 1]), c += +h[j + 2], b += +h[j + 3]);
- j += 4
- }
- break;
- case "Q":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = +h[j], f = +h[j + 1], c = +h[j + 2], b = +h[j + 3]);
- j += 4
- }
- break;
- case "t":
- if (!(k === "q" || k === "Q" || k === "t" || k === "T")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + c - g, f = b + b - f, c += +h[j + 1], b += +h[j + 2]);
- j += 2
- }
- break;
- case "T":
- if (!(k === "q" || k === "Q" || k === "t" || k === "T")) {
- g = c;
- f = b
- }
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.quadraticCurveTo(g = c + c - g, f = b + b - f, c = (+h[j + 1]), b = (+h[j + 2]));
- j += 2
- }
- break;
- case "h":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c += +h[j], b);
- j++
- }
- break;
- case "H":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c = +h[j], b);
- j++
- }
- break;
- case "v":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c, b += +h[j]);
- j++
- }
- break;
- case "V":
- while (j < n && !l.hasOwnProperty(h[j])) {
- m.lineTo(c, b = +h[j]);
- j++
- }
- break
- }
- }
- },
- clone: function() {
- var a = this,
- b = new Ext.draw.Path();
- b.params = a.params.slice(0);
- b.commands = a.commands.slice(0);
- b.cursor = a.cursor ? a.cursor.slice(0) : null;
- b.startX = a.startX;
- b.startY = a.startY;
- b.svgString = a.svgString;
- return b
- },
- transform: function(j) {
- if (j.isIdentity()) {
- return
- }
- var a = j.getXX(),
- f = j.getYX(),
- m = j.getDX(),
- l = j.getXY(),
- e = j.getYY(),
- k = j.getDY(),
- b = this.params,
- c = 0,
- d = b.length,
- h, g;
- for (; c < d; c += 2) {
- h = b[c];
- g = b[c + 1];
- b[c] = h * a + g * f + m;
- b[c + 1] = h * l + g * e + k
- }
- this.dirt()
- },
- getDimension: function(f) {
- if (!f) {
- f = {}
- }
- if (!this.commands || !this.commands.length) {
- f.x = 0;
- f.y = 0;
- f.width = 0;
- f.height = 0;
- return f
- }
- f.left = Infinity;
- f.top = Infinity;
- f.right = -Infinity;
- f.bottom = -Infinity;
- var d = 0,
- c = 0,
- b = this.commands,
- g = this.params,
- e = b.length,
- a, h;
- for (; d < e; d++) {
- switch (b[d]) {
- case "M":
- case "L":
- a = g[c];
- h = g[c + 1];
- f.left = Math.min(a, f.left);
- f.top = Math.min(h, f.top);
- f.right = Math.max(a, f.right);
- f.bottom = Math.max(h, f.bottom);
- c += 2;
- break;
- case "C":
- this.expandDimension(f, a, h, g[c], g[c + 1], g[c + 2], g[c + 3], a = g[c + 4], h = g[c + 5]);
- c += 6;
- break
- }
- }
- f.x = f.left;
- f.y = f.top;
- f.width = f.right - f.left;
- f.height = f.bottom - f.top;
- return f
- },
- getDimensionWithTransform: function(n, f) {
- if (!this.commands || !this.commands.length) {
- if (!f) {
- f = {}
- }
- f.x = 0;
- f.y = 0;
- f.width = 0;
- f.height = 0;
- return f
- }
- f.left = Infinity;
- f.top = Infinity;
- f.right = -Infinity;
- f.bottom = -Infinity;
- var a = n.getXX(),
- k = n.getYX(),
- q = n.getDX(),
- p = n.getXY(),
- h = n.getYY(),
- o = n.getDY(),
- e = 0,
- d = 0,
- b = this.commands,
- c = this.params,
- g = b.length,
- m, l;
- for (; e < g; e++) {
- switch (b[e]) {
- case "M":
- case "L":
- m = c[d] * a + c[d + 1] * k + q;
- l = c[d] * p + c[d + 1] * h + o;
- f.left = Math.min(m, f.left);
- f.top = Math.min(l, f.top);
- f.right = Math.max(m, f.right);
- f.bottom = Math.max(l, f.bottom);
- d += 2;
- break;
- case "C":
- this.expandDimension(f, m, l, c[d] * a + c[d + 1] * k + q, c[d] * p + c[d + 1] * h + o, c[d + 2] * a + c[d + 3] * k + q, c[d + 2] * p + c[d + 3] * h + o, m = c[d + 4] * a + c[d + 5] * k + q, l = c[d + 4] * p + c[d + 5] * h + o);
- d += 6;
- break
- }
- }
- if (!f) {
- f = {}
- }
- f.x = f.left;
- f.y = f.top;
- f.width = f.right - f.left;
- f.height = f.bottom - f.top;
- return f
- },
- expandDimension: function(i, d, p, k, g, j, e, c, o) {
- var m = this,
- f = i.left,
- a = i.right,
- q = i.top,
- n = i.bottom,
- h = m.dim || (m.dim = []);
- m.curveDimension(d, k, j, c, h);
- f = Math.min(f, h[0]);
- a = Math.max(a, h[1]);
- m.curveDimension(p, g, e, o, h);
- q = Math.min(q, h[0]);
- n = Math.max(n, h[1]);
- i.left = f;
- i.right = a;
- i.top = q;
- i.bottom = n
- },
- curveDimension: function(p, n, k, j, h) {
- var i = 3 * (-p + 3 * (n - k) + j),
- g = 6 * (p - 2 * n + k),
- f = -3 * (p - n),
- o, m, e = Math.min(p, j),
- l = Math.max(p, j),
- q;
- if (i === 0) {
- if (g === 0) {
- h[0] = e;
- h[1] = l;
- return
- } else {
- o = -f / g;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- }
- } else {
- q = g * g - 4 * i * f;
- if (q >= 0) {
- q = Math.sqrt(q);
- o = (q - g) / 2 / i;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- if (q > 0) {
- o -= q / i;
- if (0 < o && o < 1) {
- m = this.interpolate(p, n, k, j, o);
- e = Math.min(e, m);
- l = Math.max(l, m)
- }
- }
- }
- }
- h[0] = e;
- h[1] = l
- },
- interpolate: function(f, e, j, i, g) {
- if (g === 0) {
- return f
- }
- if (g === 1) {
- return i
- }
- var h = (1 - g) / g;
- return g * g * g * (i + h * (3 * j + h * (3 * e + h * f)))
- },
- fromStripes: function(g) {
- var e = this,
- c = 0,
- d = g.length,
- b, a, f;
- e.clear();
- for (; c < d; c++) {
- f = g[c];
- e.params.push.apply(e.params, f);
- e.commands.push("M");
- for (b = 2, a = f.length; b < a; b += 6) {
- e.commands.push("C")
- }
- }
- if (!e.cursor) {
- e.cursor = []
- }
- e.cursor[0] = e.params[e.params.length - 2];
- e.cursor[1] = e.params[e.params.length - 1];
- e.dirt()
- },
- toStripes: function(k) {
- var o = k || [],
- p, n, m, b, a, h, g, f, e, c = this.commands,
- d = this.params,
- l = c.length;
- for (f = 0, e = 0; f < l; f++) {
- switch (c[f]) {
- case "M":
- p = [h = b = d[e++], g = a = d[e++]];
- o.push(p);
- break;
- case "L":
- n = d[e++];
- m = d[e++];
- p.push((b + b + n) / 3, (a + a + m) / 3, (b + n + n) / 3, (a + m + m) / 3, b = n, a = m);
- break;
- case "C":
- p.push(d[e++], d[e++], d[e++], d[e++], b = d[e++], a = d[e++]);
- break;
- case "Z":
- n = h;
- m = g;
- p.push((b + b + n) / 3, (a + a + m) / 3, (b + n + n) / 3, (a + m + m) / 3, b = n, a = m);
- break
- }
- }
- return o
- },
- updateSvgString: function() {
- var b = [],
- a = this.commands,
- f = this.params,
- e = a.length,
- d = 0,
- c = 0;
- for (; d < e; d++) {
- switch (a[d]) {
- case "M":
- b.push("M" + f[c] + "," + f[c + 1]);
- c += 2;
- break;
- case "L":
- b.push("L" + f[c] + "," + f[c + 1]);
- c += 2;
- break;
- case "C":
- b.push("C" + f[c] + "," + f[c + 1] + " " + f[c + 2] + "," + f[c + 3] + " " + f[c + 4] + "," + f[c + 5]);
- c += 6;
- break;
- case "Z":
- b.push("Z");
- break
- }
- }
- this.svgString = b.join("")
- },
- toString: function() {
- if (!this.svgString) {
- this.updateSvgString()
- }
- return this.svgString
- }
-});
-Ext.define("Ext.draw.overrides.Path", {
- override: "Ext.draw.Path",
- rayOrigin: {
- x: -10000,
- y: -10000
- },
- isPointInPath: function(o, n) {
- var m = this,
- c = m.commands,
- q = Ext.draw.PathUtil,
- p = m.rayOrigin,
- f = m.params,
- l = c.length,
- e = null,
- d = null,
- b = 0,
- a = 0,
- k = 0,
- h, g;
- for (h = 0, g = 0; h < l; h++) {
- switch (c[h]) {
- case "M":
- if (e !== null) {
- if (q.linesIntersection(e, d, b, a, p.x, p.y, o, n)) {
- k += 1
- }
- }
- e = b = f[g];
- d = a = f[g + 1];
- g += 2;
- break;
- case "L":
- if (q.linesIntersection(b, a, f[g], f[g + 1], p.x, p.y, o, n)) {
- k += 1
- }
- b = f[g];
- a = f[g + 1];
- g += 2;
- break;
- case "C":
- k += q.cubicLineIntersections(b, f[g], f[g + 2], f[g + 4], a, f[g + 1], f[g + 3], f[g + 5], p.x, p.y, o, n).length;
- b = f[g + 4];
- a = f[g + 5];
- g += 6;
- break;
- case "Z":
- if (e !== null) {
- if (q.linesIntersection(e, d, b, a, p.x, p.y, o, n)) {
- k += 1
- }
- }
- break
- }
- }
- return k % 2 === 1
- },
- isPointOnPath: function(n, m) {
- var l = this,
- c = l.commands,
- o = Ext.draw.PathUtil,
- f = l.params,
- k = c.length,
- e = null,
- d = null,
- b = 0,
- a = 0,
- h, g;
- for (h = 0, g = 0; h < k; h++) {
- switch (c[h]) {
- case "M":
- if (e !== null) {
- if (o.pointOnLine(e, d, b, a, n, m)) {
- return true
- }
- }
- e = b = f[g];
- d = a = f[g + 1];
- g += 2;
- break;
- case "L":
- if (o.pointOnLine(b, a, f[g], f[g + 1], n, m)) {
- return true
- }
- b = f[g];
- a = f[g + 1];
- g += 2;
- break;
- case "C":
- if (o.pointOnCubic(b, f[g], f[g + 2], f[g + 4], a, f[g + 1], f[g + 3], f[g + 5], n, m)) {
- return true
- }
- b = f[g + 4];
- a = f[g + 5];
- g += 6;
- break;
- case "Z":
- if (e !== null) {
- if (o.pointOnLine(e, d, b, a, n, m)) {
- return true
- }
- }
- break
- }
- }
- return false
- },
- getSegmentIntersections: function(t, d, s, c, r, b, o, a) {
- var w = this,
- g = arguments.length,
- v = Ext.draw.PathUtil,
- f = w.commands,
- u = w.params,
- k = f.length,
- m = null,
- l = null,
- h = 0,
- e = 0,
- x = [],
- q, n, p;
- for (q = 0, n = 0; q < k; q++) {
- switch (f[q]) {
- case "M":
- if (m !== null) {
- switch (g) {
- case 4:
- p = v.linesIntersection(m, l, h, e, t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, m, l, h, e);
- x.push.apply(x, p);
- break
- }
- }
- m = h = u[n];
- l = e = u[n + 1];
- n += 2;
- break;
- case "L":
- switch (g) {
- case 4:
- p = v.linesIntersection(h, e, u[n], u[n + 1], t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, h, e, u[n], u[n + 1]);
- x.push.apply(x, p);
- break
- }
- h = u[n];
- e = u[n + 1];
- n += 2;
- break;
- case "C":
- switch (g) {
- case 4:
- p = v.cubicLineIntersections(h, u[n], u[n + 2], u[n + 4], e, u[n + 1], u[n + 3], u[n + 5], t, d, s, c);
- x.push.apply(x, p);
- break;
- case 8:
- p = v.cubicsIntersections(h, u[n], u[n + 2], u[n + 4], e, u[n + 1], u[n + 3], u[n + 5], t, s, r, o, d, c, b, a);
- x.push.apply(x, p);
- break
- }
- h = u[n + 4];
- e = u[n + 5];
- n += 6;
- break;
- case "Z":
- if (m !== null) {
- switch (g) {
- case 4:
- p = v.linesIntersection(m, l, h, e, t, d, s, c);
- if (p) {
- x.push(p)
- }
- break;
- case 8:
- p = v.cubicLineIntersections(t, s, r, o, d, c, b, a, m, l, h, e);
- x.push.apply(x, p);
- break
- }
- }
- break
- }
- }
- return x
- },
- getIntersections: function(o) {
- var m = this,
- c = m.commands,
- g = m.params,
- l = c.length,
- f = null,
- e = null,
- b = 0,
- a = 0,
- d = [],
- k, h, n;
- for (k = 0, h = 0; k < l; k++) {
- switch (c[k]) {
- case "M":
- if (f !== null) {
- n = o.getSegmentIntersections.call(o, f, e, b, a);
- d.push.apply(d, n)
- }
- f = b = g[h];
- e = a = g[h + 1];
- h += 2;
- break;
- case "L":
- n = o.getSegmentIntersections.call(o, b, a, g[h], g[h + 1]);
- d.push.apply(d, n);
- b = g[h];
- a = g[h + 1];
- h += 2;
- break;
- case "C":
- n = o.getSegmentIntersections.call(o, b, a, g[h], g[h + 1], g[h + 2], g[h + 3], g[h + 4], g[h + 5]);
- d.push.apply(d, n);
- b = g[h + 4];
- a = g[h + 5];
- h += 6;
- break;
- case "Z":
- if (f !== null) {
- n = o.getSegmentIntersections.call(o, f, e, b, a);
- d.push.apply(d, n)
- }
- break
- }
- }
- return d
- }
-});
-Ext.define("Ext.draw.sprite.Path", {
- extend: "Ext.draw.sprite.Sprite",
- requires: ["Ext.draw.Draw", "Ext.draw.Path"],
- alias: ["sprite.path", "Ext.draw.Sprite"],
- type: "path",
- isPath: true,
- inheritableStatics: {
- def: {
- processors: {
- path: function(b, a) {
- if (!(b instanceof Ext.draw.Path)) {
- b = new Ext.draw.Path(b)
- }
- return b
- }
- },
- aliases: {
- d: "path"
- },
- triggers: {
- path: "bbox"
- },
- updaters: {
- path: function(a) {
- var b = a.path;
- if (!b || b.bindAttr !== a) {
- b = new Ext.draw.Path();
- b.bindAttr = a;
- a.path = b
- }
- b.clear();
- this.updatePath(b, a);
- this.scheduleUpdater(a, "bbox", ["path"])
- }
- }
- }
- },
- updatePlainBBox: function(a) {
- if (this.attr.path) {
- this.attr.path.getDimension(a)
- }
- },
- updateTransformedBBox: function(a) {
- if (this.attr.path) {
- this.attr.path.getDimensionWithTransform(this.attr.matrix, a)
- }
- },
- render: function(b, c) {
- var d = this.attr.matrix,
- a = this.attr;
- if (!a.path || a.path.params.length === 0) {
- return
- }
- d.toContext(c);
- c.appendPath(a.path);
- c.fillStroke(a)
- },
- updatePath: function(b, a) {}
-});
-Ext.define("Ext.draw.overrides.sprite.Path", {
- override: "Ext.draw.sprite.Path",
- requires: ["Ext.draw.Color"],
- isPointInPath: function(c, g) {
- var b = this.attr;
- if (b.fillStyle === Ext.draw.Color.RGBA_NONE) {
- return this.isPointOnPath(c, g)
- }
- var e = b.path,
- d = b.matrix,
- f, a;
- if (!d.isIdentity()) {
- f = e.params.slice(0);
- e.transform(b.matrix)
- }
- a = e.isPointInPath(c, g);
- if (f) {
- e.params = f
- }
- return a
- },
- isPointOnPath: function(c, g) {
- var b = this.attr,
- e = b.path,
- d = b.matrix,
- f, a;
- if (!d.isIdentity()) {
- f = e.params.slice(0);
- e.transform(b.matrix)
- }
- a = e.isPointOnPath(c, g);
- if (f) {
- e.params = f
- }
- return a
- },
- hitTest: function(i, l) {
- var e = this,
- c = e.attr,
- k = c.path,
- g = c.matrix,
- h = i[0],
- f = i[1],
- d = e.callParent([i, l]),
- j = null,
- a, b;
- if (!d) {
- return j
- }
- l = l || Ext.draw.sprite.Sprite.defaultHitTestOptions;
- if (!g.isIdentity()) {
- a = k.params.slice(0);
- k.transform(c.matrix)
- }
- if (l.fill && l.stroke) {
- b = c.fillStyle !== Ext.draw.Color.NONE && c.fillStyle !== Ext.draw.Color.RGBA_NONE;
- if (b) {
- if (k.isPointInPath(h, f)) {
- j = {
- sprite: e
- }
- }
- } else {
- if (k.isPointInPath(h, f) || k.isPointOnPath(h, f)) {
- j = {
- sprite: e
- }
- }
- }
- } else {
- if (l.stroke && !l.fill) {
- if (k.isPointOnPath(h, f)) {
- j = {
- sprite: e
- }
- }
- } else {
- if (l.fill && !l.stroke) {
- if (k.isPointInPath(h, f)) {
- j = {
- sprite: e
- }
- }
- }
- }
- }
- if (a) {
- k.params = a
- }
- return j
- },
- getIntersections: function(j) {
- if (!(j.isSprite && j.isPath)) {
- return []
- }
- var e = this.attr,
- d = j.attr,
- i = e.path,
- h = d.path,
- g = e.matrix,
- a = d.matrix,
- c, f, b;
- if (!g.isIdentity()) {
- c = i.params.slice(0);
- i.transform(e.matrix)
- }
- if (!a.isIdentity()) {
- f = h.params.slice(0);
- h.transform(d.matrix)
- }
- b = i.getIntersections(h);
- if (c) {
- i.params = c
- }
- if (f) {
- h.params = f
- }
- return b
- }
-});
-Ext.define("Ext.draw.sprite.Circle", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.circle",
- type: "circle",
- inheritableStatics: {
- def: {
- processors: {
- cx: "number",
- cy: "number",
- r: "number"
- },
- aliases: {
- radius: "r",
- x: "cx",
- y: "cy",
- centerX: "cx",
- centerY: "cy"
- },
- defaults: {
- cx: 0,
- cy: 0,
- r: 4
- },
- triggers: {
- cx: "path",
- cy: "path",
- r: "path"
- }
- }
- },
- updatePlainBBox: function(c) {
- var b = this.attr,
- a = b.cx,
- e = b.cy,
- d = b.r;
- c.x = a - d;
- c.y = e - d;
- c.width = d + d;
- c.height = d + d
- },
- updateTransformedBBox: function(d) {
- var g = this.attr,
- f = g.cx,
- e = g.cy,
- a = g.r,
- h = g.matrix,
- j = h.getScaleX(),
- i = h.getScaleY(),
- c, b;
- c = j * a;
- b = i * a;
- d.x = h.x(f, e) - c;
- d.y = h.y(f, e) - b;
- d.width = c + c;
- d.height = b + b
- },
- updatePath: function(b, a) {
- b.arc(a.cx, a.cy, a.r, 0, Math.PI * 2, false)
- }
-});
-Ext.define("Ext.draw.sprite.Arc", {
- extend: "Ext.draw.sprite.Circle",
- alias: "sprite.arc",
- type: "arc",
- inheritableStatics: {
- def: {
- processors: {
- startAngle: "number",
- endAngle: "number",
- anticlockwise: "bool"
- },
- aliases: {
- from: "startAngle",
- to: "endAngle",
- start: "startAngle",
- end: "endAngle"
- },
- defaults: {
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false
- },
- triggers: {
- startAngle: "path",
- endAngle: "path",
- anticlockwise: "path"
- }
- }
- },
- updatePath: function(b, a) {
- b.arc(a.cx, a.cy, a.r, a.startAngle, a.endAngle, a.anticlockwise)
- }
-});
-Ext.define("Ext.draw.sprite.Arrow", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.arrow",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 1.5,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c * 0.7, ",", e - c * 0.4, "l", [c * 0.6, 0, 0, -c * 0.4, c, c * 0.8, -c, c * 0.8, 0, -c * 0.4, -c * 0.6, 0], "z"))
- }
-});
-Ext.define("Ext.draw.sprite.Composite", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.composite",
- type: "composite",
- isComposite: true,
- config: {
- sprites: []
- },
- constructor: function() {
- this.sprites = [];
- this.sprites.map = {};
- this.callParent(arguments)
- },
- add: function(c) {
- if (!c) {
- return null
- }
- if (!c.isSprite) {
- c = Ext.create("sprite." + c.type, c);
- c.setParent(this);
- c.setSurface(this.getSurface())
- }
- var d = this,
- a = d.attr,
- b = c.applyTransformations;
- c.applyTransformations = function() {
- if (c.attr.dirtyTransform) {
- a.dirtyTransform = true;
- a.bbox.plain.dirty = true;
- a.bbox.transform.dirty = true
- }
- b.call(c)
- };
- d.sprites.push(c);
- d.sprites.map[c.id] = c.getId();
- a.bbox.plain.dirty = true;
- a.bbox.transform.dirty = true;
- return c
- },
- updateSurface: function(a) {
- for (var b = 0, c = this.sprites.length; b < c; b++) {
- this.sprites[b].setSurface(a)
- }
- },
- addAll: function(b) {
- if (b.isSprite || b.type) {
- this.add(b)
- } else {
- if (Ext.isArray(b)) {
- var a = 0;
- while (a < b.length) {
- this.add(b[a++])
- }
- }
- }
- },
- updatePlainBBox: function(g) {
- var e = this,
- b = Infinity,
- h = -Infinity,
- f = Infinity,
- a = -Infinity,
- j, k, c, d;
- for (c = 0, d = e.sprites.length; c < d; c++) {
- j = e.sprites[c];
- j.applyTransformations();
- k = j.getBBox();
- if (b > k.x) {
- b = k.x
- }
- if (h < k.x + k.width) {
- h = k.x + k.width
- }
- if (f > k.y) {
- f = k.y
- }
- if (a < k.y + k.height) {
- a = k.y + k.height
- }
- }
- g.x = b;
- g.y = f;
- g.width = h - b;
- g.height = a - f
- },
- render: function(a, b, f) {
- var d = this.attr.matrix,
- c, e;
- d.toContext(b);
- for (c = 0, e = this.sprites.length; c < e; c++) {
- a.renderSprite(this.sprites[c], f)
- }
- },
- destroy: function() {
- var c = this,
- d = c.sprites,
- b = d.length,
- a;
- c.callParent();
- for (a = 0; a < b; a++) {
- d[a].destroy()
- }
- d.length = 0
- }
-});
-Ext.define("Ext.draw.sprite.Cross", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.cross",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size / 1.7,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c, ",", e, "l", [-c, -c, c, -c, c, c, c, -c, c, c, -c, c, c, c, -c, c, -c, -c, -c, c, -c, -c, "z"]))
- }
-});
-Ext.define("Ext.draw.sprite.Diamond", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.diamond",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 1.25,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString(["M", a, e - c, "l", c, c, -c, c, -c, -c, c, -c, "z"])
- }
-});
-Ext.define("Ext.draw.sprite.Ellipse", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.ellipse",
- type: "ellipse",
- inheritableStatics: {
- def: {
- processors: {
- cx: "number",
- cy: "number",
- rx: "number",
- ry: "number",
- axisRotation: "number"
- },
- aliases: {
- radius: "r",
- x: "cx",
- y: "cy",
- centerX: "cx",
- centerY: "cy",
- radiusX: "rx",
- radiusY: "ry"
- },
- defaults: {
- cx: 0,
- cy: 0,
- rx: 1,
- ry: 1,
- axisRotation: 0
- },
- triggers: {
- cx: "path",
- cy: "path",
- rx: "path",
- ry: "path",
- axisRotation: "path"
- }
- }
- },
- updatePlainBBox: function(c) {
- var b = this.attr,
- a = b.cx,
- f = b.cy,
- e = b.rx,
- d = b.ry;
- c.x = a - e;
- c.y = f - d;
- c.width = e + e;
- c.height = d + d
- },
- updateTransformedBBox: function(d) {
- var i = this.attr,
- f = i.cx,
- e = i.cy,
- c = i.rx,
- b = i.ry,
- l = b / c,
- m = i.matrix.clone(),
- a, q, k, j, p, o, n, g;
- m.append(1, 0, 0, l, 0, e * (1 - l));
- a = m.getXX();
- k = m.getYX();
- p = m.getDX();
- q = m.getXY();
- j = m.getYY();
- o = m.getDY();
- n = Math.sqrt(a * a + k * k) * c;
- g = Math.sqrt(q * q + j * j) * c;
- d.x = f * a + e * k + p - n;
- d.y = f * q + e * j + o - g;
- d.width = n + n;
- d.height = g + g
- },
- updatePath: function(b, a) {
- b.ellipse(a.cx, a.cy, a.rx, a.ry, a.axisRotation, 0, Math.PI * 2, false)
- }
-});
-Ext.define("Ext.draw.sprite.EllipticalArc", {
- extend: "Ext.draw.sprite.Ellipse",
- alias: "sprite.ellipticalArc",
- type: "ellipticalArc",
- inheritableStatics: {
- def: {
- processors: {
- startAngle: "number",
- endAngle: "number",
- anticlockwise: "bool"
- },
- aliases: {
- from: "startAngle",
- to: "endAngle",
- start: "startAngle",
- end: "endAngle"
- },
- defaults: {
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false
- },
- triggers: {
- startAngle: "path",
- endAngle: "path",
- anticlockwise: "path"
- }
- }
- },
- updatePath: function(b, a) {
- b.ellipse(a.cx, a.cy, a.rx, a.ry, a.axisRotation, a.startAngle, a.endAngle, a.anticlockwise)
- }
-});
-Ext.define("Ext.draw.sprite.Rect", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.rect",
- type: "rect",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number",
- radius: "number"
- },
- aliases: {},
- triggers: {
- x: "path",
- y: "path",
- width: "path",
- height: "path",
- radius: "path"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 8,
- height: 8,
- radius: 0
- }
- }
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.x;
- b.y = a.y;
- b.width = a.width;
- b.height = a.height
- },
- updateTransformedBBox: function(a, b) {
- this.attr.matrix.transformBBox(b, this.attr.radius, a)
- },
- updatePath: function(f, d) {
- var c = d.x,
- g = d.y,
- e = d.width,
- b = d.height,
- a = Math.min(d.radius, Math.abs(d.height) * 0.5, Math.abs(d.width) * 0.5);
- if (a === 0) {
- f.rect(c, g, e, b)
- } else {
- f.moveTo(c + a, g);
- f.arcTo(c + e, g, c + e, g + b, a);
- f.arcTo(c + e, g + b, c, g + b, a);
- f.arcTo(c, g + b, c, g, a);
- f.arcTo(c, g, c + a, g, a)
- }
- }
-});
-Ext.define("Ext.draw.sprite.Image", {
- extend: "Ext.draw.sprite.Rect",
- alias: "sprite.image",
- type: "image",
- statics: {
- imageLoaders: {}
- },
- inheritableStatics: {
- def: {
- processors: {
- src: "string"
- },
- defaults: {
- src: "",
- width: null,
- height: null
- }
- }
- },
- render: function(c, o) {
- var j = this,
- h = j.attr,
- n = h.matrix,
- a = h.src,
- l = h.x,
- k = h.y,
- b = h.width,
- m = h.height,
- g = Ext.draw.sprite.Image.imageLoaders[a],
- f, d, e;
- if (g && g.done) {
- n.toContext(o);
- d = g.image;
- o.drawImage(d, l, k, b || (d.naturalWidth || d.width) / c.devicePixelRatio, m || (d.naturalHeight || d.height) / c.devicePixelRatio)
- } else {
- if (!g) {
- f = new Image();
- g = Ext.draw.sprite.Image.imageLoaders[a] = {
- image: f,
- done: false,
- pendingSprites: [j],
- pendingSurfaces: [c]
- };
- f.width = b;
- f.height = m;
- f.onload = function() {
- if (!g.done) {
- g.done = true;
- for (e = 0; e < g.pendingSprites.length; e++) {
- g.pendingSprites[e].setDirty(true)
- }
- for (e in g.pendingSurfaces) {
- g.pendingSurfaces[e].renderFrame()
- }
- }
- };
- f.src = a
- } else {
- Ext.Array.include(g.pendingSprites, j);
- Ext.Array.include(g.pendingSurfaces, c)
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Instancing", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.instancing",
- type: "instancing",
- isInstancing: true,
- config: {
- template: null
- },
- instances: null,
- applyTemplate: function(a) {
- if (!a.isSprite) {
- if (!a.xclass && !a.type) {
- a.type = "circle"
- }
- a = Ext.create(a.xclass || "sprite." + a.type, a)
- }
- a.setParent(this);
- return a
- },
- updateTemplate: function(a, b) {
- if (b) {
- delete b.ownAttr
- }
- a.setSurface(this.getSurface());
- a.ownAttr = a.attr;
- this.clearAll()
- },
- updateSurface: function(a) {
- var b = this.getTemplate();
- if (b) {
- b.setSurface(a)
- }
- },
- get: function(a) {
- return this.instances[a]
- },
- getCount: function() {
- return this.instances.length
- },
- clearAll: function() {
- var a = this.getTemplate();
- a.attr.children = this.instances = [];
- this.position = 0
- },
- createInstance: function(d, f, c) {
- var e = this.getTemplate(),
- b = e.attr,
- a = Ext.Object.chain(b);
- e.topModifier.prepareAttributes(a);
- e.attr = a;
- e.setAttributes(d, f, c);
- a.template = e;
- this.instances.push(a);
- e.attr = b;
- this.position++;
- return a
- },
- getBBox: function() {
- return null
- },
- getBBoxFor: function(b, d) {
- var c = this.getTemplate(),
- a = c.attr,
- e;
- c.attr = this.instances[b];
- e = c.getBBox(d);
- c.attr = a;
- return e
- },
- isVisible: function() {
- var b = this.attr,
- c = this.getParent(),
- a;
- a = c && c.isSurface && !b.hidden && b.globalAlpha;
- return !!a
- },
- isInstanceVisible: function(c) {
- var e = this,
- d = e.getTemplate(),
- b = d.attr,
- f = e.instances,
- a = false;
- if (!Ext.isNumber(c) || c < 0 || c >= f.length || !e.isVisible()) {
- return a
- }
- d.attr = f[c];
- a = d.isVisible(point, options);
- d.attr = b;
- return a
- },
- render: function(b, l, d, h) {
- var g = this,
- j = g.getTemplate(),
- k = g.attr.matrix,
- c = j.attr,
- a = g.instances,
- e, f = g.position;
- k.toContext(l);
- j.preRender(b, l, d, h);
- j.useAttributes(l, h);
- for (e = 0; e < f; e++) {
- if (a[e].dirtyZIndex) {
- break
- }
- }
- for (e = 0; e < f; e++) {
- if (a[e].hidden) {
- continue
- }
- l.save();
- j.attr = a[e];
- j.useAttributes(l, h);
- j.render(b, l, d, h);
- l.restore()
- }
- j.attr = c
- },
- setAttributesFor: function(c, e, f) {
- var d = this.getTemplate(),
- b = d.attr,
- a = this.instances[c];
- if (!a) {
- return
- }
- d.attr = a;
- if (f) {
- e = Ext.apply({}, e)
- } else {
- e = d.self.def.normalize(e)
- }
- d.topModifier.pushDown(a, e);
- d.attr = b
- },
- destroy: function() {
- var b = this,
- a = b.getTemplate();
- b.instances = null;
- if (a) {
- a.destroy()
- }
- b.callParent()
- }
-});
-Ext.define("Ext.draw.overrides.sprite.Instancing", {
- override: "Ext.draw.sprite.Instancing",
- hitTest: function(f, j) {
- var e = this,
- g = e.getTemplate(),
- b = g.attr,
- a = e.instances,
- d = a.length,
- c = 0,
- h = null;
- if (!e.isVisible()) {
- return h
- }
- for (; c < d; c++) {
- g.attr = a[c];
- h = g.hitTest(f, j);
- if (h) {
- h.isInstance = true;
- h.template = h.sprite;
- h.sprite = this;
- h.instance = a[c];
- h.index = c;
- return h
- }
- }
- g.attr = b;
- return h
- }
-});
-Ext.define("Ext.draw.sprite.Line", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.line",
- type: "line",
- inheritableStatics: {
- def: {
- processors: {
- fromX: "number",
- fromY: "number",
- toX: "number",
- toY: "number"
- },
- defaults: {
- fromX: 0,
- fromY: 0,
- toX: 1,
- toY: 1,
- strokeStyle: "black"
- },
- aliases: {
- x1: "fromX",
- y1: "fromY",
- x2: "toX",
- y2: "toY"
- }
- }
- },
- updateLineBBox: function(b, i, s, g, r, f) {
- var o = this.attr,
- q = o.matrix,
- h = o.lineWidth / 2,
- m, l, d, c, k, j, n;
- if (i) {
- n = q.transformPoint([s, g]);
- s = n[0];
- g = n[1];
- n = q.transformPoint([r, f]);
- r = n[0];
- f = n[1]
- }
- m = Math.min(s, r);
- d = Math.max(s, r);
- l = Math.min(g, f);
- c = Math.max(g, f);
- var t = Math.atan2(d - m, c - l),
- a = Math.sin(t),
- e = Math.cos(t),
- k = h * e,
- j = h * a;
- m -= k;
- l -= j;
- d += k;
- c += j;
- b.x = m;
- b.y = l;
- b.width = d - m;
- b.height = c - l
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- this.updateLineBBox(b, false, a.fromX, a.fromY, a.toX, a.toY)
- },
- updateTransformedBBox: function(b, c) {
- var a = this.attr;
- this.updateLineBBox(b, true, a.fromX, a.fromY, a.toX, a.toY)
- },
- render: function(b, c) {
- var a = this.attr,
- d = this.attr.matrix;
- d.toContext(c);
- c.beginPath();
- c.moveTo(a.fromX, a.fromY);
- c.lineTo(a.toX, a.toY);
- c.stroke()
- }
-});
-Ext.define("Ext.draw.sprite.Plus", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.plus",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size / 1.3,
- a = b.x - b.lineWidth / 2,
- e = b.y;
- d.fromSvgString("M".concat(a - c / 2, ",", e - c / 2, "l", [0, -c, c, 0, 0, c, c, 0, 0, c, -c, 0, 0, c, -c, 0, 0, -c, -c, 0, 0, -c, "z"]))
- }
-});
-Ext.define("Ext.draw.sprite.Sector", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.sector",
- type: "sector",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- margin: "number"
- },
- aliases: {
- rho: "endRho"
- },
- triggers: {
- centerX: "path,bbox",
- centerY: "path,bbox",
- startAngle: "path,bbox",
- endAngle: "path,bbox",
- startRho: "path,bbox",
- endRho: "path,bbox",
- margin: "path,bbox"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: 0,
- endAngle: 0,
- startRho: 0,
- endRho: 150,
- margin: 0,
- path: "M 0,0"
- }
- }
- },
- getMidAngle: function() {
- return this.midAngle || 0
- },
- updatePath: function(j, h) {
- var g = Math.min(h.startAngle, h.endAngle),
- c = Math.max(h.startAngle, h.endAngle),
- b = this.midAngle = (g + c) * 0.5,
- d = h.margin,
- f = h.centerX,
- e = h.centerY,
- i = Math.min(h.startRho, h.endRho),
- a = Math.max(h.startRho, h.endRho);
- if (d) {
- f += d * Math.cos(b);
- e += d * Math.sin(b)
- }
- j.moveTo(f + i * Math.cos(g), e + i * Math.sin(g));
- j.lineTo(f + a * Math.cos(g), e + a * Math.sin(g));
- j.arc(f, e, a, g, c, false);
- j.lineTo(f + i * Math.cos(c), e + i * Math.sin(c));
- j.arc(f, e, i, c, g, true)
- }
-});
-Ext.define("Ext.draw.sprite.Square", {
- extend: "Ext.draw.sprite.Rect",
- alias: "sprite.square",
- inheritableStatics: {
- def: {
- processors: {
- size: "number"
- },
- defaults: {
- size: 4
- },
- triggers: {
- size: "size"
- },
- updaters: {
- size: function(a) {
- var c = a.size,
- b = a.lineWidth / 2;
- this.setAttributes({
- x: a.x - c - b,
- y: a.y - c,
- height: 2 * c,
- width: 2 * c
- })
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.TextMeasurer", {
- singleton: true,
- requires: ["Ext.util.TextMetrics"],
- measureDiv: null,
- measureCache: {},
- precise: Ext.isIE8,
- measureDivTpl: {
- tag: "div",
- style: {
- overflow: "hidden",
- position: "relative",
- "float": "left",
- width: 0,
- height: 0
- },
- children: {
- tag: "div",
- style: {
- display: "block",
- position: "absolute",
- x: -100000,
- y: -100000,
- padding: 0,
- margin: 0,
- "z-index": -100000,
- "white-space": "nowrap"
- }
- }
- },
- actualMeasureText: function(g, b) {
- var e = Ext.draw.TextMeasurer,
- f = e.measureDiv,
- a = 100000,
- c;
- if (!f) {
- var d = Ext.Element.create({
- style: {
- overflow: "hidden",
- position: "relative",
- "float": "left",
- width: 0,
- height: 0
- }
- });
- e.measureDiv = f = Ext.Element.create({
- style: {
- position: "absolute",
- x: a,
- y: a,
- "z-index": -a,
- "white-space": "nowrap",
- display: "block",
- padding: 0,
- margin: 0
- }
- });
- Ext.getBody().appendChild(d);
- d.appendChild(f)
- }
- if (b) {
- f.setStyle({
- font: b,
- lineHeight: "normal"
- })
- }
- f.setText("(" + g + ")");
- c = f.getSize();
- f.setText("()");
- c.width -= f.getSize().width;
- return c
- },
- measureTextSingleLine: function(h, d) {
- if (this.precise) {
- return this.preciseMeasureTextSingleLine(h, d)
- }
- h = h.toString();
- var a = this.measureCache,
- g = h.split(""),
- c = 0,
- j = 0,
- l, b, e, f, k;
- if (!a[d]) {
- a[d] = {}
- }
- a = a[d];
- if (a[h]) {
- return a[h]
- }
- for (e = 0, f = g.length; e < f; e++) {
- b = g[e];
- if (!(l = a[b])) {
- k = this.actualMeasureText(b, d);
- l = a[b] = k
- }
- c += l.width;
- j = Math.max(j, l.height)
- }
- return a[h] = {
- width: c,
- height: j
- }
- },
- preciseMeasureTextSingleLine: function(c, a) {
- c = c.toString();
- var b = this.measureDiv || (this.measureDiv = Ext.getBody().createChild(this.measureDivTpl).down("div"));
- b.setStyle({
- font: a || ""
- });
- return Ext.util.TextMetrics.measure(b, c)
- },
- measureText: function(e, b) {
- var h = e.split("\n"),
- d = h.length,
- f = 0,
- a = 0,
- j, c, g;
- if (d === 1) {
- return this.measureTextSingleLine(e, b)
- }
- g = [];
- for (c = 0; c < d; c++) {
- j = this.measureTextSingleLine(h[c], b);
- g.push(j);
- f += j.height;
- a = Math.max(a, j.width)
- }
- return {
- width: a,
- height: f,
- sizes: g
- }
- }
-});
-Ext.define("Ext.draw.sprite.Text", function() {
- var d = {
- "xx-small": true,
- "x-small": true,
- small: true,
- medium: true,
- large: true,
- "x-large": true,
- "xx-large": true
- };
- var b = {
- normal: true,
- bold: true,
- bolder: true,
- lighter: true,
- 100: true,
- 200: true,
- 300: true,
- 400: true,
- 500: true,
- 600: true,
- 700: true,
- 800: true,
- 900: true
- };
- var a = {
- start: "start",
- left: "start",
- center: "center",
- middle: "center",
- end: "end",
- right: "end"
- };
- var c = {
- top: "top",
- hanging: "hanging",
- middle: "middle",
- center: "middle",
- alphabetic: "alphabetic",
- ideographic: "ideographic",
- bottom: "bottom"
- };
- return {
- extend: "Ext.draw.sprite.Sprite",
- requires: ["Ext.draw.TextMeasurer", "Ext.draw.Color"],
- alias: "sprite.text",
- type: "text",
- lineBreakRe: /\r?\n/g,
- inheritableStatics: {
- def: {
- animationProcessors: {
- text: "text"
- },
- processors: {
- x: "number",
- y: "number",
- text: "string",
- fontSize: function(e) {
- if (Ext.isNumber(+e)) {
- return e + "px"
- } else {
- if (e.match(Ext.dom.Element.unitRe)) {
- return e
- } else {
- if (e in d) {
- return e
- }
- }
- }
- },
- fontStyle: "enums(,italic,oblique)",
- fontVariant: "enums(,small-caps)",
- fontWeight: function(e) {
- if (e in b) {
- return String(e)
- } else {
- return ""
- }
- },
- fontFamily: "string",
- textAlign: function(e) {
- return a[e] || "center"
- },
- textBaseline: function(e) {
- return c[e] || "alphabetic"
- },
- font: "string"
- },
- aliases: {
- "font-size": "fontSize",
- "font-family": "fontFamily",
- "font-weight": "fontWeight",
- "font-variant": "fontVariant",
- "text-anchor": "textAlign"
- },
- defaults: {
- fontStyle: "",
- fontVariant: "",
- fontWeight: "",
- fontSize: "10px",
- fontFamily: "sans-serif",
- font: "10px sans-serif",
- textBaseline: "alphabetic",
- textAlign: "start",
- strokeStyle: "rgba(0, 0, 0, 0)",
- fillStyle: "#000",
- x: 0,
- y: 0,
- text: ""
- },
- triggers: {
- fontStyle: "fontX,bbox",
- fontVariant: "fontX,bbox",
- fontWeight: "fontX,bbox",
- fontSize: "fontX,bbox",
- fontFamily: "fontX,bbox",
- font: "font,bbox,canvas",
- textBaseline: "bbox",
- textAlign: "bbox",
- x: "bbox",
- y: "bbox",
- text: "bbox"
- },
- updaters: {
- fontX: "makeFontShorthand",
- font: "parseFontShorthand"
- }
- }
- },
- constructor: function(e) {
- if (e && e.font) {
- e = Ext.clone(e);
- for (var f in e) {
- if (f !== "font" && f.indexOf("font") === 0) {
- delete e[f]
- }
- }
- }
- Ext.draw.sprite.Sprite.prototype.constructor.call(this, e)
- },
- fontValuesMap: {
- italic: "fontStyle",
- oblique: "fontStyle",
- "small-caps": "fontVariant",
- bold: "fontWeight",
- bolder: "fontWeight",
- lighter: "fontWeight",
- "100": "fontWeight",
- "200": "fontWeight",
- "300": "fontWeight",
- "400": "fontWeight",
- "500": "fontWeight",
- "600": "fontWeight",
- "700": "fontWeight",
- "800": "fontWeight",
- "900": "fontWeight",
- "xx-small": "fontSize",
- "x-small": "fontSize",
- small: "fontSize",
- medium: "fontSize",
- large: "fontSize",
- "x-large": "fontSize",
- "xx-large": "fontSize"
- },
- makeFontShorthand: function(e) {
- var f = [];
- if (e.fontStyle) {
- f.push(e.fontStyle)
- }
- if (e.fontVariant) {
- f.push(e.fontVariant)
- }
- if (e.fontWeight) {
- f.push(e.fontWeight)
- }
- if (e.fontSize) {
- f.push(e.fontSize)
- }
- if (e.fontFamily) {
- f.push(e.fontFamily)
- }
- this.setAttributes({
- font: f.join(" ")
- }, true)
- },
- parseFontShorthand: function(j) {
- var m = j.font,
- k = m.length,
- l = {},
- n = this.fontValuesMap,
- e = 0,
- i, g, f, h;
- while (e < k && i !== -1) {
- i = m.indexOf(" ", e);
- if (i < 0) {
- f = m.substr(e)
- } else {
- if (i > e) {
- f = m.substr(e, i - e)
- } else {
- continue
- }
- }
- g = f.indexOf("/");
- if (g > 0) {
- f = f.substr(0, g)
- } else {
- if (g === 0) {
- continue
- }
- }
- if (f !== "normal" && f !== "inherit") {
- h = n[f];
- if (h) {
- l[h] = f
- } else {
- if (f.match(Ext.dom.Element.unitRe)) {
- l.fontSize = f
- } else {
- l.fontFamily = m.substr(e);
- break
- }
- }
- }
- e = i + 1
- }
- if (!l.fontStyle) {
- l.fontStyle = ""
- }
- if (!l.fontVariant) {
- l.fontVariant = ""
- }
- if (!l.fontWeight) {
- l.fontWeight = ""
- }
- this.setAttributes(l, true)
- },
- fontProperties: {
- fontStyle: true,
- fontVariant: true,
- fontWeight: true,
- fontSize: true,
- fontFamily: true
- },
- setAttributes: function(g, i, e) {
- var f, h;
- if (g && g.font) {
- h = {};
- for (f in g) {
- if (!(f in this.fontProperties)) {
- h[f] = g[f]
- }
- }
- g = h
- }
- this.callParent([g, i, e])
- },
- getBBox: function(g) {
- var h = this,
- f = h.attr.bbox.plain,
- e = h.getSurface();
- if (f.dirty) {
- h.updatePlainBBox(f);
- f.dirty = false
- }
- if (e.getInherited().rtl && e.getFlipRtlText()) {
- h.updatePlainBBox(f, true)
- }
- return h.callParent([g])
- },
- rtlAlignments: {
- start: "end",
- center: "center",
- end: "start"
- },
- updatePlainBBox: function(k, B) {
- var C = this,
- w = C.attr,
- o = w.x,
- n = w.y,
- q = [],
- t = w.font,
- r = w.text,
- s = w.textBaseline,
- l = w.textAlign,
- u = (B && C.oldSize) ? C.oldSize : (C.oldSize = Ext.draw.TextMeasurer.measureText(r, t)),
- z = C.getSurface(),
- p = z.getInherited().rtl,
- v = p && z.getFlipRtlText(),
- h = z.getRect(),
- f = u.sizes,
- g = u.height,
- j = u.width,
- m = f ? f.length : 0,
- e, A = 0;
- switch (s) {
- case "hanging":
- case "top":
- break;
- case "ideographic":
- case "bottom":
- n -= g;
- break;
- case "alphabetic":
- n -= g * 0.8;
- break;
- case "middle":
- n -= g * 0.5;
- break
- }
- if (v) {
- o = h[2] - h[0] - o;
- l = C.rtlAlignments[l]
- }
- switch (l) {
- case "start":
- if (p) {
- for (; A < m; A++) {
- e = f[A].width;
- q.push(-(j - e))
- }
- }
- break;
- case "end":
- o -= j;
- if (p) {
- break
- }
- for (; A < m; A++) {
- e = f[A].width;
- q.push(j - e)
- }
- break;
- case "center":
- o -= j * 0.5;
- for (; A < m; A++) {
- e = f[A].width;
- q.push((p ? -1 : 1) * (j - e) * 0.5)
- }
- break
- }
- w.textAlignOffsets = q;
- k.x = o;
- k.y = n;
- k.width = j;
- k.height = g
- },
- setText: function(e) {
- this.setAttributes({
- text: e
- }, true)
- },
- render: function(e, q, k) {
- var h = this,
- g = h.attr,
- p = Ext.draw.Matrix.fly(g.matrix.elements.slice(0)),
- o = h.getBBox(true),
- s = g.textAlignOffsets,
- m = Ext.draw.Color.RGBA_NONE,
- l, j, f, r, n;
- if (g.text.length === 0) {
- return
- }
- r = g.text.split(h.lineBreakRe);
- n = o.height / r.length;
- l = g.bbox.plain.x;
- j = g.bbox.plain.y + n * 0.78;
- p.toContext(q);
- if (e.getInherited().rtl) {
- l += g.bbox.plain.width
- }
- for (f = 0; f < r.length; f++) {
- if (q.fillStyle !== m) {
- q.fillText(r[f], l + (s[f] || 0), j + n * f)
- }
- if (q.strokeStyle !== m) {
- q.strokeText(r[f], l + (s[f] || 0), j + n * f)
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Tick", {
- extend: "Ext.draw.sprite.Line",
- alias: "sprite.tick",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "tick",
- y: "tick",
- size: "tick"
- },
- updaters: {
- tick: function(b) {
- var d = b.size * 1.5,
- c = b.lineWidth / 2,
- a = b.x,
- e = b.y;
- this.setAttributes({
- fromX: a - c,
- fromY: e - d,
- toX: a - c,
- toY: e + d
- })
- }
- }
- }
- }
-});
-Ext.define("Ext.draw.sprite.Triangle", {
- extend: "Ext.draw.sprite.Path",
- alias: "sprite.triangle",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- size: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- size: 4
- },
- triggers: {
- x: "path",
- y: "path",
- size: "path"
- }
- }
- },
- updatePath: function(d, b) {
- var c = b.size * 2.2,
- a = b.x,
- e = b.y;
- d.fromSvgString("M".concat(a, ",", e, "m0-", c * 0.58, "l", c * 0.5, ",", c * 0.87, "-", c, ",0z"))
- }
-});
-Ext.define("Ext.draw.gradient.Linear", {
- extend: "Ext.draw.gradient.Gradient",
- requires: ["Ext.draw.Color"],
- type: "linear",
- config: {
- degrees: 0,
- radians: 0
- },
- applyRadians: function(b, a) {
- if (Ext.isNumber(b)) {
- return b
- }
- return a
- },
- applyDegrees: function(b, a) {
- if (Ext.isNumber(b)) {
- return b
- }
- return a
- },
- updateRadians: function(a) {
- this.setDegrees(Ext.draw.Draw.degrees(a))
- },
- updateDegrees: function(a) {
- this.setRadians(Ext.draw.Draw.rad(a))
- },
- generateGradient: function(q, o) {
- var c = this.getRadians(),
- p = Math.cos(c),
- j = Math.sin(c),
- m = o.width,
- f = o.height,
- d = o.x + m * 0.5,
- b = o.y + f * 0.5,
- n = this.getStops(),
- g = n.length,
- k, a, e;
- if (Ext.isNumber(d + b) && f > 0 && m > 0) {
- a = (Math.sqrt(f * f + m * m) * Math.abs(Math.cos(c - Math.atan(f / m)))) / 2;
- k = q.createLinearGradient(d + p * a, b + j * a, d - p * a, b - j * a);
- for (e = 0; e < g; e++) {
- k.addColorStop(n[e].offset, n[e].color)
- }
- return k
- }
- return Ext.draw.Color.NONE
- }
-});
-Ext.define("Ext.draw.gradient.Radial", {
- extend: "Ext.draw.gradient.Gradient",
- type: "radial",
- config: {
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- }
- },
- applyStart: function(a, b) {
- if (!b) {
- return a
- }
- var c = {
- x: b.x,
- y: b.y,
- r: b.r
- };
- if ("x" in a) {
- c.x = a.x
- } else {
- if ("centerX" in a) {
- c.x = a.centerX
- }
- }
- if ("y" in a) {
- c.y = a.y
- } else {
- if ("centerY" in a) {
- c.y = a.centerY
- }
- }
- if ("r" in a) {
- c.r = a.r
- } else {
- if ("radius" in a) {
- c.r = a.radius
- }
- }
- return c
- },
- applyEnd: function(b, a) {
- if (!a) {
- return b
- }
- var c = {
- x: a.x,
- y: a.y,
- r: a.r
- };
- if ("x" in b) {
- c.x = b.x
- } else {
- if ("centerX" in b) {
- c.x = b.centerX
- }
- }
- if ("y" in b) {
- c.y = b.y
- } else {
- if ("centerY" in b) {
- c.y = b.centerY
- }
- }
- if ("r" in b) {
- c.r = b.r
- } else {
- if ("radius" in b) {
- c.r = b.radius
- }
- }
- return c
- },
- generateGradient: function(n, m) {
- var a = this.getStart(),
- b = this.getEnd(),
- k = m.width * 0.5,
- d = m.height * 0.5,
- j = m.x + k,
- f = m.y + d,
- g = n.createRadialGradient(j + a.x * k, f + a.y * d, a.r * Math.max(k, d), j + b.x * k, f + b.y * d, b.r * Math.max(k, d)),
- l = this.getStops(),
- e = l.length,
- c;
- for (c = 0; c < e; c++) {
- g.addColorStop(l[c].offset, l[c].color)
- }
- return g
- }
-});
-Ext.define("Ext.draw.Surface", {
- extend: "Ext.draw.SurfaceBase",
- xtype: "surface",
- requires: ["Ext.draw.sprite.*", "Ext.draw.gradient.*", "Ext.draw.sprite.AttributeDefinition", "Ext.draw.Matrix", "Ext.draw.Draw"],
- uses: ["Ext.draw.engine.Canvas"],
- devicePixelRatio: window.devicePixelRatio || window.screen.deviceXDPI / window.screen.logicalXDPI,
- deprecated: {
- "5.1.0": {
- statics: {
- methods: {
- stableSort: function(a) {
- return Ext.Array.sort(a, function(d, c) {
- return d.attr.zIndex - c.attr.zIndex
- })
- }
- }
- }
- }
- },
- config: {
- cls: Ext.baseCSSPrefix + "surface",
- rect: null,
- background: null,
- items: [],
- dirty: false,
- flipRtlText: false
- },
- isSurface: true,
- isPendingRenderFrame: false,
- dirtyPredecessorCount: 0,
- constructor: function(a) {
- var b = this;
- b.predecessors = [];
- b.successors = [];
- b.map = {};
- b.callParent([a]);
- b.matrix = new Ext.draw.Matrix();
- b.inverseMatrix = b.matrix.inverse()
- },
- roundPixel: function(a) {
- return Math.round(this.devicePixelRatio * a) / this.devicePixelRatio
- },
- waitFor: function(a) {
- var b = this,
- c = b.predecessors;
- if (!Ext.Array.contains(c, a)) {
- c.push(a);
- a.successors.push(b);
- if (a.getDirty()) {
- b.dirtyPredecessorCount++
- }
- }
- },
- updateDirty: function(d) {
- var c = this.successors,
- e = c.length,
- b = 0,
- a;
- for (; b < e; b++) {
- a = c[b];
- if (d) {
- a.dirtyPredecessorCount++;
- a.setDirty(true)
- } else {
- a.dirtyPredecessorCount--;
- if (a.dirtyPredecessorCount === 0 && a.isPendingRenderFrame) {
- a.renderFrame()
- }
- }
- }
- },
- applyBackground: function(a, b) {
- this.setDirty(true);
- if (Ext.isString(a)) {
- a = {
- fillStyle: a
- }
- }
- return Ext.factory(a, Ext.draw.sprite.Rect, b)
- },
- applyRect: function(a, b) {
- if (b && a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]) {
- return
- }
- if (Ext.isArray(a)) {
- return [a[0], a[1], a[2], a[3]]
- } else {
- if (Ext.isObject(a)) {
- return [a.x || a.left, a.y || a.top, a.width || (a.right - a.left), a.height || (a.bottom - a.top)]
- }
- }
- },
- updateRect: function(i) {
- var h = this,
- c = i[0],
- f = i[1],
- g = c + i[2],
- a = f + i[3],
- e = h.getBackground(),
- d = h.element;
- d.setLocalXY(Math.floor(c), Math.floor(f));
- d.setSize(Math.ceil(g - Math.floor(c)), Math.ceil(a - Math.floor(f)));
- if (e) {
- e.setAttributes({
- x: 0,
- y: 0,
- width: Math.ceil(g - Math.floor(c)),
- height: Math.ceil(a - Math.floor(f))
- })
- }
- h.setDirty(true)
- },
- resetTransform: function() {
- this.matrix.set(1, 0, 0, 1, 0, 0);
- this.inverseMatrix.set(1, 0, 0, 1, 0, 0);
- this.setDirty(true)
- },
- get: function(a) {
- return this.map[a] || this.getItems()[a]
- },
- add: function() {
- var g = this,
- e = Array.prototype.slice.call(arguments),
- j = Ext.isArray(e[0]),
- a = g.map,
- c = [],
- f, k, h, b, d;
- f = Ext.Array.clean(j ? e[0] : e);
- if (!f.length) {
- return c
- }
- for (b = 0, d = f.length; b < d; b++) {
- k = f[b];
- h = null;
- if (k.isSprite && !a[k.getId()]) {
- h = k
- } else {
- if (!a[k.id]) {
- h = this.createItem(k)
- }
- }
- if (h) {
- a[h.getId()] = h;
- c.push(h);
- h.setParent(g);
- h.setSurface(g);
- g.onAdd(h)
- }
- }
- f = g.getItems();
- if (f) {
- f.push.apply(f, c)
- }
- g.dirtyZIndex = true;
- g.setDirty(true);
- if (!j && c.length === 1) {
- return c[0]
- } else {
- return c
- }
- },
- onAdd: Ext.emptyFn,
- remove: function(a, c) {
- var b = this,
- e, d;
- if (a) {
- if (a.charAt) {
- a = b.map[a]
- }
- if (!a || !a.isSprite) {
- return null
- }
- if (a.isDestroyed || a.isDestroying) {
- return a
- }
- e = a.getId();
- d = b.map[e];
- delete b.map[e];
- if (c) {
- a.destroy()
- }
- if (!d) {
- return a
- }
- a.setParent(null);
- a.setSurface(null);
- Ext.Array.remove(b.getItems(), a);
- b.dirtyZIndex = true;
- b.setDirty(true)
- }
- return a || null
- },
- removeAll: function(d) {
- var a = this.getItems(),
- b = a.length - 1,
- c;
- if (d) {
- for (; b >= 0; b--) {
- a[b].destroy()
- }
- } else {
- for (; b >= 0; b--) {
- c = a[b];
- c.setParent(null);
- c.setSurface(null)
- }
- }
- a.length = 0;
- this.map = {};
- this.dirtyZIndex = true
- },
- applyItems: function(a) {
- if (this.getItems()) {
- this.removeAll(true)
- }
- return Ext.Array.from(this.add(a))
- },
- createItem: function(a) {
- return Ext.create(a.xclass || "sprite." + a.type, a)
- },
- getBBox: function(f, b) {
- var f = Ext.Array.from(f),
- c = Infinity,
- h = -Infinity,
- g = Infinity,
- a = -Infinity,
- j, k, d, e;
- for (d = 0, e = f.length; d < e; d++) {
- j = f[d];
- k = j.getBBox(b);
- if (c > k.x) {
- c = k.x
- }
- if (h < k.x + k.width) {
- h = k.x + k.width
- }
- if (g > k.y) {
- g = k.y
- }
- if (a < k.y + k.height) {
- a = k.y + k.height
- }
- }
- return {
- x: c,
- y: g,
- width: h - c,
- height: a - g
- }
- },
- emptyRect: [0, 0, 0, 0],
- getEventXY: function(d) {
- var g = this,
- f = g.getInherited().rtl,
- c = d.getXY(),
- a = g.getOwnerBody(),
- i = a.getXY(),
- h = g.getRect() || g.emptyRect,
- j = [],
- b;
- if (f) {
- b = a.getWidth();
- j[0] = i[0] - c[0] - h[0] + b
- } else {
- j[0] = c[0] - i[0] - h[0]
- }
- j[1] = c[1] - i[1] - h[1];
- return j
- },
- clear: Ext.emptyFn,
- orderByZIndex: function() {
- var d = this,
- a = d.getItems(),
- e = false,
- b, c;
- if (d.getDirty()) {
- for (b = 0, c = a.length; b < c; b++) {
- if (a[b].attr.dirtyZIndex) {
- e = true;
- break
- }
- }
- if (e) {
- Ext.Array.sort(a, function(g, f) {
- return g.attr.zIndex - f.attr.zIndex
- });
- this.setDirty(true)
- }
- for (b = 0, c = a.length; b < c; b++) {
- a[b].attr.dirtyZIndex = false
- }
- }
- },
- repaint: function() {
- var a = this;
- a.repaint = Ext.emptyFn;
- Ext.defer(function() {
- delete a.repaint;
- a.element.repaint()
- }, 1)
- },
- renderFrame: function() {
- var g = this;
- if (!g.element) {
- return
- }
- if (g.dirtyPredecessorCount > 0) {
- g.isPendingRenderFrame = true;
- return
- }
- var f = g.getRect(),
- c = g.getBackground(),
- a = g.getItems(),
- e, b, d;
- if (!f) {
- return
- }
- g.orderByZIndex();
- if (g.getDirty()) {
- g.clear();
- g.clearTransform();
- if (c) {
- g.renderSprite(c)
- }
- for (b = 0, d = a.length; b < d; b++) {
- e = a[b];
- if (g.renderSprite(e) === false) {
- return
- }
- e.attr.textPositionCount = g.textPosition
- }
- g.setDirty(false)
- }
- },
- renderSprite: Ext.emptyFn,
- clearTransform: Ext.emptyFn,
- destroy: function() {
- var a = this;
- a.removeAll(true);
- a.predecessors = null;
- a.successors = null;
- a.callParent()
- }
-});
-Ext.define("Ext.draw.overrides.Surface", {
- override: "Ext.draw.Surface",
- hitTest: function(b, c) {
- var f = this,
- g = f.getItems(),
- e, d, a;
- c = c || Ext.draw.sprite.Sprite.defaultHitTestOptions;
- for (e = g.length - 1; e >= 0; e--) {
- d = g[e];
- if (d.hitTest) {
- a = d.hitTest(b, c);
- if (a) {
- return a
- }
- }
- }
- return null
- },
- hitTestEvent: function(b, a) {
- var c = this.getEventXY(b);
- return this.hitTest(c, a)
- }
-});
-Ext.define("Ext.draw.engine.SvgContext", {
- requires: ["Ext.draw.Color"],
- toSave: ["strokeOpacity", "strokeStyle", "fillOpacity", "fillStyle", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "lineDash", "lineDashOffset", "miterLimit", "shadowOffsetX", "shadowOffsetY", "shadowBlur", "shadowColor", "globalCompositeOperation", "position", "fillGradient", "strokeGradient"],
- strokeOpacity: 1,
- strokeStyle: "none",
- fillOpacity: 1,
- fillStyle: "none",
- lineDash: [],
- lineDashOffset: 0,
- globalAlpha: 1,
- lineWidth: 1,
- lineCap: "butt",
- lineJoin: "miter",
- miterLimit: 10,
- shadowOffsetX: 0,
- shadowOffsetY: 0,
- shadowBlur: 0,
- shadowColor: "none",
- globalCompositeOperation: "src",
- urlStringRe: /^url\(#([\w\-]+)\)$/,
- constructor: function(a) {
- this.surface = a;
- this.state = [];
- this.matrix = new Ext.draw.Matrix();
- this.path = null;
- this.clear()
- },
- clear: function() {
- this.group = this.surface.mainGroup;
- this.position = 0;
- this.path = null
- },
- getElement: function(a) {
- return this.surface.getSvgElement(this.group, a, this.position++)
- },
- removeElement: function(d) {
- var d = Ext.fly(d),
- h, g, b, f, a, e, c;
- if (!d) {
- return
- }
- if (d.dom.tagName === "g") {
- a = d.dom.gradients;
- for (c in a) {
- a[c].destroy()
- }
- } else {
- h = d.getAttribute("fill");
- g = d.getAttribute("stroke");
- b = h && h.match(this.urlStringRe);
- f = g && g.match(this.urlStringRe);
- if (b && b[1]) {
- e = Ext.fly(b[1]);
- if (e) {
- e.destroy()
- }
- }
- if (f && f[1]) {
- e = Ext.fly(f[1]);
- if (e) {
- e.destroy()
- }
- }
- }
- d.destroy()
- },
- save: function() {
- var c = this.toSave,
- e = {},
- d = this.getElement("g"),
- b, a;
- for (a = 0; a < c.length; a++) {
- b = c[a];
- if (b in this) {
- e[b] = this[b]
- }
- }
- this.position = 0;
- e.matrix = this.matrix.clone();
- this.state.push(e);
- this.group = d;
- return d
- },
- restore: function() {
- var d = this.toSave,
- e = this.state.pop(),
- c = this.group.dom.childNodes,
- b, a;
- while (c.length > this.position) {
- this.removeElement(c[c.length - 1])
- }
- for (a = 0; a < d.length; a++) {
- b = d[a];
- if (b in e) {
- this[b] = e[b]
- } else {
- delete this[b]
- }
- }
- this.setTransform.apply(this, e.matrix.elements);
- this.group = this.group.getParent()
- },
- transform: function(f, b, e, g, d, c) {
- if (this.path) {
- var a = Ext.draw.Matrix.fly([f, b, e, g, d, c]).inverse();
- this.path.transform(a)
- }
- this.matrix.append(f, b, e, g, d, c)
- },
- setTransform: function(e, a, d, f, c, b) {
- if (this.path) {
- this.path.transform(this.matrix)
- }
- this.matrix.reset();
- this.transform(e, a, d, f, c, b)
- },
- scale: function(a, b) {
- this.transform(a, 0, 0, b, 0, 0)
- },
- rotate: function(d) {
- var c = Math.cos(d),
- a = Math.sin(d),
- b = -Math.sin(d),
- e = Math.cos(d);
- this.transform(c, a, b, e, 0, 0)
- },
- translate: function(a, b) {
- this.transform(1, 0, 0, 1, a, b)
- },
- setGradientBBox: function(a) {
- this.bbox = a
- },
- beginPath: function() {
- this.path = new Ext.draw.Path()
- },
- moveTo: function(a, b) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.moveTo(a, b);
- this.path.element = null
- },
- lineTo: function(a, b) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.lineTo(a, b);
- this.path.element = null
- },
- rect: function(b, d, c, a) {
- this.moveTo(b, d);
- this.lineTo(b + c, d);
- this.lineTo(b + c, d + a);
- this.lineTo(b, d + a);
- this.closePath()
- },
- strokeRect: function(b, d, c, a) {
- this.beginPath();
- this.rect(b, d, c, a);
- this.stroke()
- },
- fillRect: function(b, d, c, a) {
- this.beginPath();
- this.rect(b, d, c, a);
- this.fill()
- },
- closePath: function() {
- if (!this.path) {
- this.beginPath()
- }
- this.path.closePath();
- this.path.element = null
- },
- arcSvg: function(d, a, f, g, c, b, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arcSvg(d, a, f, g, c, b, e);
- this.path.element = null
- },
- arc: function(b, f, a, d, c, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arc(b, f, a, d, c, e);
- this.path.element = null
- },
- ellipse: function(a, h, g, f, d, c, b, e) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.ellipse(a, h, g, f, d, c, b, e);
- this.path.element = null
- },
- arcTo: function(b, e, a, d, g, f, c) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.arcTo(b, e, a, d, g, f, c);
- this.path.element = null
- },
- bezierCurveTo: function(d, f, b, e, a, c) {
- if (!this.path) {
- this.beginPath()
- }
- this.path.bezierCurveTo(d, f, b, e, a, c);
- this.path.element = null
- },
- strokeText: function(d, a, e) {
- d = String(d);
- if (this.strokeStyle) {
- var b = this.getElement("text"),
- c = this.surface.getSvgElement(b, "tspan", 0);
- this.surface.setElementAttributes(b, {
- x: a,
- y: e,
- transform: this.matrix.toSvg(),
- stroke: this.strokeStyle,
- fill: "none",
- opacity: this.globalAlpha,
- "stroke-opacity": this.strokeOpacity,
- style: "font: " + this.font,
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- });
- if (this.lineDash.length) {
- this.surface.setElementAttributes(b, {
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- })
- }
- if (c.dom.firstChild) {
- c.dom.removeChild(c.dom.firstChild)
- }
- this.surface.setElementAttributes(c, {
- "alignment-baseline": "alphabetic"
- });
- c.dom.appendChild(document.createTextNode(Ext.String.htmlDecode(d)))
- }
- },
- fillText: function(d, a, e) {
- d = String(d);
- if (this.fillStyle) {
- var b = this.getElement("text"),
- c = this.surface.getSvgElement(b, "tspan", 0);
- this.surface.setElementAttributes(b, {
- x: a,
- y: e,
- transform: this.matrix.toSvg(),
- fill: this.fillStyle,
- opacity: this.globalAlpha,
- "fill-opacity": this.fillOpacity,
- style: "font: " + this.font
- });
- if (c.dom.firstChild) {
- c.dom.removeChild(c.dom.firstChild)
- }
- this.surface.setElementAttributes(c, {
- "alignment-baseline": "alphabetic"
- });
- c.dom.appendChild(document.createTextNode(Ext.String.htmlDecode(d)))
- }
- },
- drawImage: function(c, k, i, l, e, p, n, a, g) {
- var f = this,
- d = f.getElement("image"),
- j = k,
- h = i,
- b = typeof l === "undefined" ? c.width : l,
- m = typeof e === "undefined" ? c.height : e,
- o = null;
- if (typeof g !== "undefined") {
- o = k + " " + i + " " + l + " " + e;
- j = p;
- h = n;
- b = a;
- m = g
- }
- d.dom.setAttributeNS("http://www.w3.org/1999/xlink", "href", c.src);
- f.surface.setElementAttributes(d, {
- viewBox: o,
- x: j,
- y: h,
- width: b,
- height: m,
- opacity: f.globalAlpha,
- transform: f.matrix.toSvg()
- })
- },
- fill: function() {
- if (!this.path) {
- return
- }
- if (this.fillStyle) {
- var c, a = this.fillGradient,
- d = this.bbox,
- b = this.path.element;
- if (!b) {
- c = this.path.toString();
- b = this.path.element = this.getElement("path");
- this.surface.setElementAttributes(b, {
- d: c,
- transform: this.matrix.toSvg()
- })
- }
- this.surface.setElementAttributes(b, {
- fill: a && d ? a.generateGradient(this, d) : this.fillStyle,
- "fill-opacity": this.fillOpacity * this.globalAlpha
- })
- }
- },
- stroke: function() {
- if (!this.path) {
- return
- }
- if (this.strokeStyle) {
- var c, b = this.strokeGradient,
- d = this.bbox,
- a = this.path.element;
- if (!a || !this.path.svgString) {
- c = this.path.toString();
- if (!c) {
- return
- }
- a = this.path.element = this.getElement("path");
- this.surface.setElementAttributes(a, {
- fill: "none",
- d: c,
- transform: this.matrix.toSvg()
- })
- }
- this.surface.setElementAttributes(a, {
- stroke: b && d ? b.generateGradient(this, d) : this.strokeStyle,
- "stroke-linecap": this.lineCap,
- "stroke-linejoin": this.lineJoin,
- "stroke-width": this.lineWidth,
- "stroke-opacity": this.strokeOpacity * this.globalAlpha,
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- });
- if (this.lineDash.length) {
- this.surface.setElementAttributes(a, {
- "stroke-dasharray": this.lineDash.join(","),
- "stroke-dashoffset": this.lineDashOffset
- })
- }
- }
- },
- fillStroke: function(a, e) {
- var b = this,
- d = b.fillStyle,
- g = b.strokeStyle,
- c = b.fillOpacity,
- f = b.strokeOpacity;
- if (e === undefined) {
- e = a.transformFillStroke
- }
- if (!e) {
- a.inverseMatrix.toContext(b)
- }
- if (d && c !== 0) {
- b.fill()
- }
- if (g && f !== 0) {
- b.stroke()
- }
- },
- appendPath: function(a) {
- this.path = a.clone()
- },
- setLineDash: function(a) {
- this.lineDash = a
- },
- getLineDash: function() {
- return this.lineDash
- },
- createLinearGradient: function(d, g, b, e) {
- var f = this,
- c = f.surface.getNextDef("linearGradient"),
- a = f.group.dom.gradients || (f.group.dom.gradients = {}),
- h;
- f.surface.setElementAttributes(c, {
- x1: d,
- y1: g,
- x2: b,
- y2: e,
- gradientUnits: "userSpaceOnUse"
- });
- h = new Ext.draw.engine.SvgContext.Gradient(f, f.surface, c);
- a[c.dom.id] = h;
- return h
- },
- createRadialGradient: function(b, j, d, a, i, c) {
- var g = this,
- e = g.surface.getNextDef("radialGradient"),
- f = g.group.dom.gradients || (g.group.dom.gradients = {}),
- h;
- g.surface.setElementAttributes(e, {
- fx: b,
- fy: j,
- cx: a,
- cy: i,
- r: c,
- gradientUnits: "userSpaceOnUse"
- });
- h = new Ext.draw.engine.SvgContext.Gradient(g, g.surface, e, d / c);
- f[e.dom.id] = h;
- return h
- }
-});
-Ext.define("Ext.draw.engine.SvgContext.Gradient", {
- statics: {
- map: {}
- },
- constructor: function(c, a, d, b) {
- var f = this.statics().map,
- e;
- e = f[d.dom.id];
- if (e) {
- e.element = null
- }
- f[d.dom.id] = this;
- this.ctx = c;
- this.surface = a;
- this.element = d;
- this.position = 0;
- this.compression = b || 0
- },
- addColorStop: function(d, b) {
- var c = this.surface.getSvgElement(this.element, "stop", this.position++),
- a = this.compression;
- this.surface.setElementAttributes(c, {
- offset: (((1 - a) * d + a) * 100).toFixed(2) + "%",
- "stop-color": b,
- "stop-opacity": Ext.draw.Color.fly(b).a.toFixed(15)
- })
- },
- toString: function() {
- var a = this.element.dom.childNodes;
- while (a.length > this.position) {
- Ext.fly(a[a.length - 1]).destroy()
- }
- return "url(#" + this.element.getId() + ")"
- },
- destroy: function() {
- var b = this.statics().map,
- a = this.element;
- if (a && a.dom) {
- delete b[a.dom.id];
- a.destroy()
- }
- this.callParent()
- }
-});
-Ext.define("Ext.draw.engine.Svg", {
- extend: "Ext.draw.Surface",
- requires: ["Ext.draw.engine.SvgContext"],
- statics: {
- BBoxTextCache: {}
- },
- config: {
- highPrecision: false
- },
- getElementConfig: function() {
- return {
- reference: "element",
- style: {
- position: "absolute"
- },
- children: [{
- reference: "innerElement",
- style: {
- width: "100%",
- height: "100%",
- position: "relative"
- },
- children: [{
- tag: "svg",
- reference: "svgElement",
- namespace: "http://www.w3.org/2000/svg",
- width: "100%",
- height: "100%",
- version: 1.1
- }]
- }]
- }
- },
- constructor: function(a) {
- var b = this;
- b.callParent([a]);
- b.mainGroup = b.createSvgNode("g");
- b.defElement = b.createSvgNode("defs");
- b.svgElement.appendChild(b.mainGroup);
- b.svgElement.appendChild(b.defElement);
- b.ctx = new Ext.draw.engine.SvgContext(b)
- },
- createSvgNode: function(a) {
- var b = document.createElementNS("http://www.w3.org/2000/svg", a);
- return Ext.get(b)
- },
- getSvgElement: function(d, b, a) {
- var c;
- if (d.dom.childNodes.length > a) {
- c = d.dom.childNodes[a];
- if (c.tagName === b) {
- return Ext.get(c)
- } else {
- Ext.destroy(c)
- }
- }
- c = Ext.get(this.createSvgNode(b));
- if (a === 0) {
- d.insertFirst(c)
- } else {
- c.insertAfter(Ext.fly(d.dom.childNodes[a - 1]))
- }
- c.cache = {};
- return c
- },
- setElementAttributes: function(d, b) {
- var f = d.dom,
- a = d.cache,
- c, e;
- for (c in b) {
- e = b[c];
- if (a[c] !== e) {
- a[c] = e;
- f.setAttribute(c, e)
- }
- }
- },
- getNextDef: function(a) {
- return this.getSvgElement(this.defElement, a, this.defPosition++)
- },
- clearTransform: function() {
- var a = this;
- a.mainGroup.set({
- transform: a.matrix.toSvg()
- })
- },
- clear: function() {
- this.ctx.clear();
- this.defPosition = 0
- },
- renderSprite: function(b) {
- var d = this,
- c = d.getRect(),
- a = d.ctx;
- if (b.attr.hidden || b.attr.globalAlpha === 0) {
- a.save();
- a.restore();
- return
- }
- b.element = a.save();
- b.preRender(this);
- b.useAttributes(a, c);
- if (false === b.render(this, a, [0, 0, c[2], c[3]])) {
- return false
- }
- b.setDirty(false);
- a.restore()
- },
- flatten: function(e, b) {
- var c = '',
- f = Ext.getClassName(this),
- a, g, d;
- c += '';
- for (d = 0; d < b.length; d++) {
- a = b[d];
- if (Ext.getClassName(a) !== f) {
- continue
- }
- g = a.getRect();
- c += '';
- c += this.serializeNode(a.svgElement.dom);
- c += " "
- }
- c += " ";
- return {
- data: "data:image/svg+xml;utf8," + encodeURIComponent(c),
- type: "svg"
- }
- },
- serializeNode: function(d) {
- var b = "",
- c, f, a, e;
- if (d.nodeType === document.TEXT_NODE) {
- return d.nodeValue
- }
- b += "<" + d.nodeName;
- if (d.attributes.length) {
- for (c = 0, f = d.attributes.length; c < f; c++) {
- a = d.attributes[c];
- b += " " + a.name + '="' + a.value + '"'
- }
- }
- b += ">";
- if (d.childNodes && d.childNodes.length) {
- for (c = 0, f = d.childNodes.length; c < f; c++) {
- e = d.childNodes[c];
- b += this.serializeNode(e)
- }
- }
- b += "" + d.nodeName + ">";
- return b
- },
- destroy: function() {
- var a = this;
- a.ctx.destroy();
- a.mainGroup.destroy();
- delete a.mainGroup;
- delete a.ctx;
- a.callParent()
- },
- remove: function(a, b) {
- if (a && a.element) {
- if (this.ctx) {
- this.ctx.removeElement(a.element)
- } else {
- a.element.destroy()
- }
- a.element = null
- }
- this.callParent(arguments)
- }
-});
-Ext.draw || (Ext.draw = {});
-Ext.draw.engine || (Ext.draw.engine = {});
-Ext.draw.engine.excanvas = true;
-if (!document.createElement("canvas").getContext) {
- (function() {
- var ab = Math;
- var n = ab.round;
- var l = ab.sin;
- var A = ab.cos;
- var H = ab.abs;
- var N = ab.sqrt;
- var d = 10;
- var f = d / 2;
- var z = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];
-
- function y() {
- return this.context_ || (this.context_ = new D(this))
- }
- var t = Array.prototype.slice;
-
- function g(j, m, p) {
- var i = t.call(arguments, 2);
- return function() {
- return j.apply(m, i.concat(t.call(arguments)))
- }
- }
-
- function af(i) {
- return String(i).replace(/&/g, "&").replace(/"/g, """)
- }
-
- function Y(m, j, i) {
- Ext.onReady(function() {
- if (!m.namespaces[j]) {
- m.namespaces.add(j, i, "#default#VML")
- }
- })
- }
-
- function R(j) {
- Y(j, "g_vml_", "urn:schemas-microsoft-com:vml");
- Y(j, "g_o_", "urn:schemas-microsoft-com:office:office");
- if (!j.styleSheets.ex_canvas_) {
- var i = j.createStyleSheet();
- i.owningElement.id = "ex_canvas_";
- i.cssText = "canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"
- }
- }
- R(document);
- var e = {
- init: function(i) {
- var j = i || document;
- j.createElement("canvas");
- j.attachEvent("onreadystatechange", g(this.init_, this, j))
- },
- init_: function(p) {
- var m = p.getElementsByTagName("canvas");
- for (var j = 0; j < m.length; j++) {
- this.initElement(m[j])
- }
- },
- initElement: function(j) {
- if (!j.getContext) {
- j.getContext = y;
- R(j.ownerDocument);
- j.innerHTML = "";
- j.attachEvent("onpropertychange", x);
- j.attachEvent("onresize", W);
- var i = j.attributes;
- if (i.width && i.width.specified) {
- j.style.width = i.width.nodeValue + "px"
- } else {
- j.width = j.clientWidth
- }
- if (i.height && i.height.specified) {
- j.style.height = i.height.nodeValue + "px"
- } else {
- j.height = j.clientHeight
- }
- }
- return j
- }
- };
-
- function x(j) {
- var i = j.srcElement;
- switch (j.propertyName) {
- case "width":
- i.getContext().clearRect();
- i.style.width = i.attributes.width.nodeValue + "px";
- i.firstChild.style.width = i.clientWidth + "px";
- break;
- case "height":
- i.getContext().clearRect();
- i.style.height = i.attributes.height.nodeValue + "px";
- i.firstChild.style.height = i.clientHeight + "px";
- break
- }
- }
-
- function W(j) {
- var i = j.srcElement;
- if (i.firstChild) {
- i.firstChild.style.width = i.clientWidth + "px";
- i.firstChild.style.height = i.clientHeight + "px"
- }
- }
- e.init();
- var k = [];
- for (var ae = 0; ae < 16; ae++) {
- for (var ad = 0; ad < 16; ad++) {
- k[ae * 16 + ad] = ae.toString(16) + ad.toString(16)
- }
- }
-
- function B() {
- return [
- [1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]
- ]
- }
-
- function J(p, m) {
- var j = B();
- for (var i = 0; i < 3; i++) {
- for (var ah = 0; ah < 3; ah++) {
- var Z = 0;
- for (var ag = 0; ag < 3; ag++) {
- Z += p[i][ag] * m[ag][ah]
- }
- j[i][ah] = Z
- }
- }
- return j
- }
-
- function v(j, i) {
- i.fillStyle = j.fillStyle;
- i.lineCap = j.lineCap;
- i.lineJoin = j.lineJoin;
- i.lineDash = j.lineDash;
- i.lineWidth = j.lineWidth;
- i.miterLimit = j.miterLimit;
- i.shadowBlur = j.shadowBlur;
- i.shadowColor = j.shadowColor;
- i.shadowOffsetX = j.shadowOffsetX;
- i.shadowOffsetY = j.shadowOffsetY;
- i.strokeStyle = j.strokeStyle;
- i.globalAlpha = j.globalAlpha;
- i.font = j.font;
- i.textAlign = j.textAlign;
- i.textBaseline = j.textBaseline;
- i.arcScaleX_ = j.arcScaleX_;
- i.arcScaleY_ = j.arcScaleY_;
- i.lineScale_ = j.lineScale_
- }
- var b = {
- aliceblue: "#F0F8FF",
- antiquewhite: "#FAEBD7",
- aquamarine: "#7FFFD4",
- azure: "#F0FFFF",
- beige: "#F5F5DC",
- bisque: "#FFE4C4",
- black: "#000000",
- blanchedalmond: "#FFEBCD",
- blueviolet: "#8A2BE2",
- brown: "#A52A2A",
- burlywood: "#DEB887",
- cadetblue: "#5F9EA0",
- chartreuse: "#7FFF00",
- chocolate: "#D2691E",
- coral: "#FF7F50",
- cornflowerblue: "#6495ED",
- cornsilk: "#FFF8DC",
- crimson: "#DC143C",
- cyan: "#00FFFF",
- darkblue: "#00008B",
- darkcyan: "#008B8B",
- darkgoldenrod: "#B8860B",
- darkgray: "#A9A9A9",
- darkgreen: "#006400",
- darkgrey: "#A9A9A9",
- darkkhaki: "#BDB76B",
- darkmagenta: "#8B008B",
- darkolivegreen: "#556B2F",
- darkorange: "#FF8C00",
- darkorchid: "#9932CC",
- darkred: "#8B0000",
- darksalmon: "#E9967A",
- darkseagreen: "#8FBC8F",
- darkslateblue: "#483D8B",
- darkslategray: "#2F4F4F",
- darkslategrey: "#2F4F4F",
- darkturquoise: "#00CED1",
- darkviolet: "#9400D3",
- deeppink: "#FF1493",
- deepskyblue: "#00BFFF",
- dimgray: "#696969",
- dimgrey: "#696969",
- dodgerblue: "#1E90FF",
- firebrick: "#B22222",
- floralwhite: "#FFFAF0",
- forestgreen: "#228B22",
- gainsboro: "#DCDCDC",
- ghostwhite: "#F8F8FF",
- gold: "#FFD700",
- goldenrod: "#DAA520",
- grey: "#808080",
- greenyellow: "#ADFF2F",
- honeydew: "#F0FFF0",
- hotpink: "#FF69B4",
- indianred: "#CD5C5C",
- indigo: "#4B0082",
- ivory: "#FFFFF0",
- khaki: "#F0E68C",
- lavender: "#E6E6FA",
- lavenderblush: "#FFF0F5",
- lawngreen: "#7CFC00",
- lemonchiffon: "#FFFACD",
- lightblue: "#ADD8E6",
- lightcoral: "#F08080",
- lightcyan: "#E0FFFF",
- lightgoldenrodyellow: "#FAFAD2",
- lightgreen: "#90EE90",
- lightgrey: "#D3D3D3",
- lightpink: "#FFB6C1",
- lightsalmon: "#FFA07A",
- lightseagreen: "#20B2AA",
- lightskyblue: "#87CEFA",
- lightslategray: "#778899",
- lightslategrey: "#778899",
- lightsteelblue: "#B0C4DE",
- lightyellow: "#FFFFE0",
- limegreen: "#32CD32",
- linen: "#FAF0E6",
- magenta: "#FF00FF",
- mediumaquamarine: "#66CDAA",
- mediumblue: "#0000CD",
- mediumorchid: "#BA55D3",
- mediumpurple: "#9370DB",
- mediumseagreen: "#3CB371",
- mediumslateblue: "#7B68EE",
- mediumspringgreen: "#00FA9A",
- mediumturquoise: "#48D1CC",
- mediumvioletred: "#C71585",
- midnightblue: "#191970",
- mintcream: "#F5FFFA",
- mistyrose: "#FFE4E1",
- moccasin: "#FFE4B5",
- navajowhite: "#FFDEAD",
- oldlace: "#FDF5E6",
- olivedrab: "#6B8E23",
- orange: "#FFA500",
- orangered: "#FF4500",
- orchid: "#DA70D6",
- palegoldenrod: "#EEE8AA",
- palegreen: "#98FB98",
- paleturquoise: "#AFEEEE",
- palevioletred: "#DB7093",
- papayawhip: "#FFEFD5",
- peachpuff: "#FFDAB9",
- peru: "#CD853F",
- pink: "#FFC0CB",
- plum: "#DDA0DD",
- powderblue: "#B0E0E6",
- rosybrown: "#BC8F8F",
- royalblue: "#4169E1",
- saddlebrown: "#8B4513",
- salmon: "#FA8072",
- sandybrown: "#F4A460",
- seagreen: "#2E8B57",
- seashell: "#FFF5EE",
- sienna: "#A0522D",
- skyblue: "#87CEEB",
- slateblue: "#6A5ACD",
- slategray: "#708090",
- slategrey: "#708090",
- snow: "#FFFAFA",
- springgreen: "#00FF7F",
- steelblue: "#4682B4",
- tan: "#D2B48C",
- thistle: "#D8BFD8",
- tomato: "#FF6347",
- turquoise: "#40E0D0",
- violet: "#EE82EE",
- wheat: "#F5DEB3",
- whitesmoke: "#F5F5F5",
- yellowgreen: "#9ACD32"
- };
-
- function M(j) {
- var p = j.indexOf("(", 3);
- var i = j.indexOf(")", p + 1);
- var m = j.substring(p + 1, i).split(",");
- if (m.length != 4 || j.charAt(3) != "a") {
- m[3] = 1
- }
- return m
- }
-
- function c(i) {
- return parseFloat(i) / 100
- }
-
- function r(j, m, i) {
- return Math.min(i, Math.max(m, j))
- }
-
- function I(ag) {
- var i, ai, aj, ah, ak, Z;
- ah = parseFloat(ag[0]) / 360 % 360;
- if (ah < 0) {
- ah++
- }
- ak = r(c(ag[1]), 0, 1);
- Z = r(c(ag[2]), 0, 1);
- if (ak == 0) {
- i = ai = aj = Z
- } else {
- var j = Z < 0.5 ? Z * (1 + ak) : Z + ak - Z * ak;
- var m = 2 * Z - j;
- i = a(m, j, ah + 1 / 3);
- ai = a(m, j, ah);
- aj = a(m, j, ah - 1 / 3)
- }
- return "#" + k[Math.floor(i * 255)] + k[Math.floor(ai * 255)] + k[Math.floor(aj * 255)]
- }
-
- function a(j, i, m) {
- if (m < 0) {
- m++
- }
- if (m > 1) {
- m--
- }
- if (6 * m < 1) {
- return j + (i - j) * 6 * m
- } else {
- if (2 * m < 1) {
- return i
- } else {
- if (3 * m < 2) {
- return j + (i - j) * (2 / 3 - m) * 6
- } else {
- return j
- }
- }
- }
- }
- var C = {};
-
- function F(j) {
- if (j in C) {
- return C[j]
- }
- var ag, Z = 1;
- j = String(j);
- if (j.charAt(0) == "#") {
- ag = j
- } else {
- if (/^rgb/.test(j)) {
- var p = M(j);
- var ag = "#",
- ah;
- for (var m = 0; m < 3; m++) {
- if (p[m].indexOf("%") != -1) {
- ah = Math.floor(c(p[m]) * 255)
- } else {
- ah = +p[m]
- }
- ag += k[r(ah, 0, 255)]
- }
- Z = +p[3]
- } else {
- if (/^hsl/.test(j)) {
- var p = M(j);
- ag = I(p);
- Z = p[3]
- } else {
- ag = b[j] || j
- }
- }
- }
- return C[j] = {
- color: ag,
- alpha: Z
- }
- }
- var o = {
- style: "normal",
- variant: "normal",
- weight: "normal",
- size: 10,
- family: "sans-serif"
- };
- var L = {};
-
- function E(i) {
- if (L[i]) {
- return L[i]
- }
- var p = document.createElement("div");
- var m = p.style;
- try {
- m.font = i
- } catch (j) {}
- return L[i] = {
- style: m.fontStyle || o.style,
- variant: m.fontVariant || o.variant,
- weight: m.fontWeight || o.weight,
- size: m.fontSize || o.size,
- family: m.fontFamily || o.family
- }
- }
-
- function u(m, j) {
- var i = {};
- for (var ah in m) {
- i[ah] = m[ah]
- }
- var ag = parseFloat(j.currentStyle.fontSize),
- Z = parseFloat(m.size);
- if (typeof m.size == "number") {
- i.size = m.size
- } else {
- if (m.size.indexOf("px") != -1) {
- i.size = Z
- } else {
- if (m.size.indexOf("em") != -1) {
- i.size = ag * Z
- } else {
- if (m.size.indexOf("%") != -1) {
- i.size = (ag / 100) * Z
- } else {
- if (m.size.indexOf("pt") != -1) {
- i.size = Z / 0.75
- } else {
- i.size = ag
- }
- }
- }
- }
- }
- i.size *= 0.981;
- return i
- }
-
- function ac(i) {
- return i.style + " " + i.variant + " " + i.weight + " " + i.size + "px " + i.family
- }
- var s = {
- butt: "flat",
- round: "round"
- };
-
- function S(i) {
- return s[i] || "square"
- }
-
- function D(i) {
- this.m_ = B();
- this.mStack_ = [];
- this.aStack_ = [];
- this.currentPath_ = [];
- this.strokeStyle = "#000";
- this.fillStyle = "#000";
- this.lineWidth = 1;
- this.lineJoin = "miter";
- this.lineDash = [];
- this.lineCap = "butt";
- this.miterLimit = d * 1;
- this.globalAlpha = 1;
- this.font = "10px sans-serif";
- this.textAlign = "left";
- this.textBaseline = "alphabetic";
- this.canvas = i;
- var m = "width:" + i.clientWidth + "px;height:" + i.clientHeight + "px;overflow:hidden;position:absolute";
- var j = i.ownerDocument.createElement("div");
- j.style.cssText = m;
- i.appendChild(j);
- var p = j.cloneNode(false);
- p.style.backgroundColor = "red";
- p.style.filter = "alpha(opacity=0)";
- i.appendChild(p);
- this.element_ = j;
- this.arcScaleX_ = 1;
- this.arcScaleY_ = 1;
- this.lineScale_ = 1
- }
- var q = D.prototype;
- q.clearRect = function() {
- if (this.textMeasureEl_) {
- this.textMeasureEl_.removeNode(true);
- this.textMeasureEl_ = null
- }
- this.element_.innerHTML = ""
- };
- q.beginPath = function() {
- this.currentPath_ = []
- };
- q.moveTo = function(j, i) {
- var m = V(this, j, i);
- this.currentPath_.push({
- type: "moveTo",
- x: m.x,
- y: m.y
- });
- this.currentX_ = m.x;
- this.currentY_ = m.y
- };
- q.lineTo = function(j, i) {
- var m = V(this, j, i);
- this.currentPath_.push({
- type: "lineTo",
- x: m.x,
- y: m.y
- });
- this.currentX_ = m.x;
- this.currentY_ = m.y
- };
- q.bezierCurveTo = function(m, j, ak, aj, ai, ag) {
- var i = V(this, ai, ag);
- var ah = V(this, m, j);
- var Z = V(this, ak, aj);
- K(this, ah, Z, i)
- };
-
- function K(i, Z, m, j) {
- i.currentPath_.push({
- type: "bezierCurveTo",
- cp1x: Z.x,
- cp1y: Z.y,
- cp2x: m.x,
- cp2y: m.y,
- x: j.x,
- y: j.y
- });
- i.currentX_ = j.x;
- i.currentY_ = j.y
- }
- q.quadraticCurveTo = function(ai, m, j, i) {
- var ah = V(this, ai, m);
- var ag = V(this, j, i);
- var aj = {
- x: this.currentX_ + 2 / 3 * (ah.x - this.currentX_),
- y: this.currentY_ + 2 / 3 * (ah.y - this.currentY_)
- };
- var Z = {
- x: aj.x + (ag.x - this.currentX_) / 3,
- y: aj.y + (ag.y - this.currentY_) / 3
- };
- K(this, aj, Z, ag)
- };
- q.arc = function(al, aj, ak, ag, j, m) {
- ak *= d;
- var ap = m ? "at" : "wa";
- var am = al + A(ag) * ak - f;
- var ao = aj + l(ag) * ak - f;
- var i = al + A(j) * ak - f;
- var an = aj + l(j) * ak - f;
- if (am == i && !m) {
- am += 0.125
- }
- var Z = V(this, al, aj);
- var ai = V(this, am, ao);
- var ah = V(this, i, an);
- this.currentPath_.push({
- type: ap,
- x: Z.x,
- y: Z.y,
- radius: ak,
- xStart: ai.x,
- yStart: ai.y,
- xEnd: ah.x,
- yEnd: ah.y
- })
- };
- q.rect = function(m, j, i, p) {
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath()
- };
- q.strokeRect = function(m, j, i, p) {
- var Z = this.currentPath_;
- this.beginPath();
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath();
- this.stroke();
- this.currentPath_ = Z
- };
- q.fillRect = function(m, j, i, p) {
- var Z = this.currentPath_;
- this.beginPath();
- this.moveTo(m, j);
- this.lineTo(m + i, j);
- this.lineTo(m + i, j + p);
- this.lineTo(m, j + p);
- this.closePath();
- this.fill();
- this.currentPath_ = Z
- };
- q.createLinearGradient = function(j, p, i, m) {
- var Z = new U("gradient");
- Z.x0_ = j;
- Z.y0_ = p;
- Z.x1_ = i;
- Z.y1_ = m;
- return Z
- };
- q.createRadialGradient = function(p, ag, m, j, Z, i) {
- var ah = new U("gradientradial");
- ah.x0_ = p;
- ah.y0_ = ag;
- ah.r0_ = m;
- ah.x1_ = j;
- ah.y1_ = Z;
- ah.r1_ = i;
- return ah
- };
- q.drawImage = function(an, j) {
- var ah, Z, aj, ar, al, ak, ao, av;
- var ai = an.runtimeStyle.width;
- var am = an.runtimeStyle.height;
- an.runtimeStyle.width = "auto";
- an.runtimeStyle.height = "auto";
- var ag = an.width;
- var aq = an.height;
- an.runtimeStyle.width = ai;
- an.runtimeStyle.height = am;
- if (arguments.length == 3) {
- ah = arguments[1];
- Z = arguments[2];
- al = ak = 0;
- ao = aj = ag;
- av = ar = aq
- } else {
- if (arguments.length == 5) {
- ah = arguments[1];
- Z = arguments[2];
- aj = arguments[3];
- ar = arguments[4];
- al = ak = 0;
- ao = ag;
- av = aq
- } else {
- if (arguments.length == 9) {
- al = arguments[1];
- ak = arguments[2];
- ao = arguments[3];
- av = arguments[4];
- ah = arguments[5];
- Z = arguments[6];
- aj = arguments[7];
- ar = arguments[8]
- } else {
- throw Error("Invalid number of arguments")
- }
- }
- }
- var au = V(this, ah, Z);
- var at = [];
- var i = 10;
- var p = 10;
- var ap = this.m_;
- at.push(" ', ' ", " ");
- this.element_.insertAdjacentHTML("BeforeEnd", at.join(""))
- };
- q.setLineDash = function(i) {
- if (i.length === 1) {
- i = i.slice();
- i[1] = i[0]
- }
- this.lineDash = i
- };
- q.getLineDash = function() {
- return this.lineDash
- };
- q.stroke = function(ak) {
- var ai = [];
- var m = 10;
- var al = 10;
- ai.push(" aj.x) {
- aj.x = j.x
- }
- if (Z.y == null || j.y < Z.y) {
- Z.y = j.y
- }
- if (aj.y == null || j.y > aj.y) {
- aj.y = j.y
- }
- }
- }
- ai.push(' ">');
- if (!ak) {
- w(this, ai)
- } else {
- G(this, ai, Z, aj)
- }
- ai.push(" ");
- this.element_.insertAdjacentHTML("beforeEnd", ai.join(""))
- };
-
- function w(m, ag) {
- var j = F(m.strokeStyle);
- var p = j.color;
- var Z = j.alpha * m.globalAlpha;
- var i = m.lineScale_ * m.lineWidth;
- if (i < 1) {
- Z *= i
- }
- ag.push(" ')
- }
-
- function G(aq, ai, aK, ar) {
- var aj = aq.fillStyle;
- var aB = aq.arcScaleX_;
- var aA = aq.arcScaleY_;
- var j = ar.x - aK.x;
- var p = ar.y - aK.y;
- if (aj instanceof U) {
- var an = 0;
- var aF = {
- x: 0,
- y: 0
- };
- var ax = 0;
- var am = 1;
- if (aj.type_ == "gradient") {
- var al = aj.x0_ / aB;
- var m = aj.y0_ / aA;
- var ak = aj.x1_ / aB;
- var aM = aj.y1_ / aA;
- var aJ = V(aq, al, m);
- var aI = V(aq, ak, aM);
- var ag = aI.x - aJ.x;
- var Z = aI.y - aJ.y;
- an = Math.atan2(ag, Z) * 180 / Math.PI;
- if (an < 0) {
- an += 360
- }
- if (an < 0.000001) {
- an = 0
- }
- } else {
- var aJ = V(aq, aj.x0_, aj.y0_);
- aF = {
- x: (aJ.x - aK.x) / j,
- y: (aJ.y - aK.y) / p
- };
- j /= aB * d;
- p /= aA * d;
- var aD = ab.max(j, p);
- ax = 2 * aj.r0_ / aD;
- am = 2 * aj.r1_ / aD - ax
- }
- var av = aj.colors_;
- av.sort(function(aN, i) {
- return aN.offset - i.offset
- });
- var ap = av.length;
- var au = av[0].color;
- var at = av[ap - 1].color;
- var az = av[0].alpha * aq.globalAlpha;
- var ay = av[ap - 1].alpha * aq.globalAlpha;
- var aE = [];
- for (var aH = 0; aH < ap; aH++) {
- var ao = av[aH];
- aE.push(ao.offset * am + ax + " " + ao.color)
- }
- ai.push(' ')
- } else {
- if (aj instanceof T) {
- if (j && p) {
- var ah = -aK.x;
- var aC = -aK.y;
- ai.push(" ')
- }
- } else {
- var aL = F(aq.fillStyle);
- var aw = aL.color;
- var aG = aL.alpha * aq.globalAlpha;
- ai.push(' ')
- }
- }
- }
- q.fill = function() {
- this.$stroke(true)
- };
- q.closePath = function() {
- this.currentPath_.push({
- type: "close"
- })
- };
-
- function V(j, Z, p) {
- var i = j.m_;
- return {
- x: d * (Z * i[0][0] + p * i[1][0] + i[2][0]) - f,
- y: d * (Z * i[0][1] + p * i[1][1] + i[2][1]) - f
- }
- }
- q.save = function() {
- var i = {};
- v(this, i);
- this.aStack_.push(i);
- this.mStack_.push(this.m_);
- this.m_ = J(B(), this.m_)
- };
- q.restore = function() {
- if (this.aStack_.length) {
- v(this.aStack_.pop(), this);
- this.m_ = this.mStack_.pop()
- }
- };
-
- function h(i) {
- return isFinite(i[0][0]) && isFinite(i[0][1]) && isFinite(i[1][0]) && isFinite(i[1][1]) && isFinite(i[2][0]) && isFinite(i[2][1])
- }
-
- function aa(j, i, p) {
- if (!h(i)) {
- return
- }
- j.m_ = i;
- if (p) {
- var Z = i[0][0] * i[1][1] - i[0][1] * i[1][0];
- j.lineScale_ = N(H(Z))
- }
- }
- q.translate = function(m, j) {
- var i = [
- [1, 0, 0],
- [0, 1, 0],
- [m, j, 1]
- ];
- aa(this, J(i, this.m_), false)
- };
- q.rotate = function(j) {
- var p = A(j);
- var m = l(j);
- var i = [
- [p, m, 0],
- [-m, p, 0],
- [0, 0, 1]
- ];
- aa(this, J(i, this.m_), false)
- };
- q.scale = function(m, j) {
- this.arcScaleX_ *= m;
- this.arcScaleY_ *= j;
- var i = [
- [m, 0, 0],
- [0, j, 0],
- [0, 0, 1]
- ];
- aa(this, J(i, this.m_), true)
- };
- q.transform = function(Z, p, ah, ag, j, i) {
- var m = [
- [Z, p, 0],
- [ah, ag, 0],
- [j, i, 1]
- ];
- aa(this, J(m, this.m_), true)
- };
- q.setTransform = function(ag, Z, ai, ah, p, j) {
- var i = [
- [ag, Z, 0],
- [ai, ah, 0],
- [p, j, 1]
- ];
- aa(this, i, true)
- };
- q.drawText_ = function(am, ak, aj, ap, ai) {
- var ao = this.m_,
- at = 1000,
- j = 0,
- ar = at,
- ah = {
- x: 0,
- y: 0
- },
- ag = [];
- var i = u(E(this.font), this.element_);
- var p = ac(i);
- var au = this.element_.currentStyle;
- var Z = this.textAlign.toLowerCase();
- switch (Z) {
- case "left":
- case "center":
- case "right":
- break;
- case "end":
- Z = au.direction == "ltr" ? "right" : "left";
- break;
- case "start":
- Z = au.direction == "rtl" ? "right" : "left";
- break;
- default:
- Z = "left"
- }
- switch (this.textBaseline) {
- case "hanging":
- case "top":
- ah.y = i.size / 1.75;
- break;
- case "middle":
- break;
- default:
- case null:
- case "alphabetic":
- case "ideographic":
- case "bottom":
- ah.y = -i.size / 3;
- break
- }
- switch (Z) {
- case "right":
- j = at;
- ar = 0.05;
- break;
- case "center":
- j = ar = at / 2;
- break
- }
- var aq = V(this, ak + ah.x, aj + ah.y);
- ag.push('');
- if (ai) {
- w(this, ag)
- } else {
- G(this, ag, {
- x: -j,
- y: 0
- }, {
- x: ar,
- y: i.size
- })
- }
- var an = ao[0][0].toFixed(3) + "," + ao[1][0].toFixed(3) + "," + ao[0][1].toFixed(3) + "," + ao[1][1].toFixed(3) + ",0,0";
- var al = n(aq.x / d) + "," + n(aq.y / d);
- ag.push(' ', ' ', ' ');
- this.element_.insertAdjacentHTML("beforeEnd", ag.join(""))
- };
- q.fillText = function(m, i, p, j) {
- this.drawText_(m, i, p, j, false)
- };
- q.strokeText = function(m, i, p, j) {
- this.drawText_(m, i, p, j, true)
- };
- q.measureText = function(m) {
- if (!this.textMeasureEl_) {
- var i = ' ';
- this.element_.insertAdjacentHTML("beforeEnd", i);
- this.textMeasureEl_ = this.element_.lastChild
- }
- var j = this.element_.ownerDocument;
- this.textMeasureEl_.innerHTML = "";
- this.textMeasureEl_.style.font = this.font;
- this.textMeasureEl_.appendChild(j.createTextNode(m));
- return {
- width: this.textMeasureEl_.offsetWidth
- }
- };
- q.clip = function() {};
- q.arcTo = function() {};
- q.createPattern = function(j, i) {
- return new T(j, i)
- };
-
- function U(i) {
- this.type_ = i;
- this.x0_ = 0;
- this.y0_ = 0;
- this.r0_ = 0;
- this.x1_ = 0;
- this.y1_ = 0;
- this.r1_ = 0;
- this.colors_ = []
- }
- U.prototype.addColorStop = function(j, i) {
- i = F(i);
- this.colors_.push({
- offset: j,
- color: i.color,
- alpha: i.alpha
- })
- };
-
- function T(j, i) {
- Q(j);
- switch (i) {
- case "repeat":
- case null:
- case "":
- this.repetition_ = "repeat";
- break;
- case "repeat-x":
- case "repeat-y":
- case "no-repeat":
- this.repetition_ = i;
- break;
- default:
- O("SYNTAX_ERR")
- }
- this.src_ = j.src;
- this.width_ = j.width;
- this.height_ = j.height
- }
-
- function O(i) {
- throw new P(i)
- }
-
- function Q(i) {
- if (!i || i.nodeType != 1 || i.tagName != "IMG") {
- O("TYPE_MISMATCH_ERR")
- }
- if (i.readyState != "complete") {
- O("INVALID_STATE_ERR")
- }
- }
-
- function P(i) {
- this.code = this[i];
- this.message = i + ": DOM Exception " + this.code
- }
- var X = P.prototype = new Error();
- X.INDEX_SIZE_ERR = 1;
- X.DOMSTRING_SIZE_ERR = 2;
- X.HIERARCHY_REQUEST_ERR = 3;
- X.WRONG_DOCUMENT_ERR = 4;
- X.INVALID_CHARACTER_ERR = 5;
- X.NO_DATA_ALLOWED_ERR = 6;
- X.NO_MODIFICATION_ALLOWED_ERR = 7;
- X.NOT_FOUND_ERR = 8;
- X.NOT_SUPPORTED_ERR = 9;
- X.INUSE_ATTRIBUTE_ERR = 10;
- X.INVALID_STATE_ERR = 11;
- X.SYNTAX_ERR = 12;
- X.INVALID_MODIFICATION_ERR = 13;
- X.NAMESPACE_ERR = 14;
- X.INVALID_ACCESS_ERR = 15;
- X.VALIDATION_ERR = 16;
- X.TYPE_MISMATCH_ERR = 17;
- G_vmlCanvasManager = e;
- CanvasRenderingContext2D = D;
- CanvasGradient = U;
- CanvasPattern = T;
- DOMException = P
- })()
-}
-Ext.define("Ext.draw.engine.Canvas", {
- extend: "Ext.draw.Surface",
- requires: ["Ext.draw.engine.excanvas", "Ext.draw.Animator", "Ext.draw.Color"],
- config: {
- highPrecision: false
- },
- statics: {
- contextOverrides: {
- setGradientBBox: function(a) {
- this.bbox = a
- },
- fill: function() {
- var c = this.fillStyle,
- a = this.fillGradient,
- b = this.fillOpacity,
- d = this.globalAlpha,
- e = this.bbox;
- if (c !== Ext.draw.Color.RGBA_NONE && b !== 0) {
- if (a && e) {
- this.fillStyle = a.generateGradient(this, e)
- }
- if (b !== 1) {
- this.globalAlpha = d * b
- }
- this.$fill();
- if (b !== 1) {
- this.globalAlpha = d
- }
- if (a && e) {
- this.fillStyle = c
- }
- }
- },
- stroke: function() {
- var e = this.strokeStyle,
- c = this.strokeGradient,
- a = this.strokeOpacity,
- b = this.globalAlpha,
- d = this.bbox;
- if (e !== Ext.draw.Color.RGBA_NONE && a !== 0) {
- if (c && d) {
- this.strokeStyle = c.generateGradient(this, d)
- }
- if (a !== 1) {
- this.globalAlpha = b * a
- }
- this.$stroke();
- if (a !== 1) {
- this.globalAlpha = b
- }
- if (c && d) {
- this.strokeStyle = e
- }
- }
- },
- fillStroke: function(d, e) {
- var j = this,
- i = this.fillStyle,
- h = this.fillOpacity,
- f = this.strokeStyle,
- c = this.strokeOpacity,
- b = j.shadowColor,
- a = j.shadowBlur,
- g = Ext.draw.Color.RGBA_NONE;
- if (e === undefined) {
- e = d.transformFillStroke
- }
- if (!e) {
- d.inverseMatrix.toContext(j)
- }
- if (i !== g && h !== 0) {
- j.fill();
- j.shadowColor = g;
- j.shadowBlur = 0
- }
- if (f !== g && c !== 0) {
- j.stroke()
- }
- j.shadowColor = b;
- j.shadowBlur = a
- },
- setLineDash: function(a) {
- if (this.$setLineDash) {
- this.$setLineDash(a)
- }
- },
- getLineDash: function() {
- if (this.$getLineDash) {
- return this.$getLineDash()
- }
- },
- ellipse: function(g, e, c, a, j, b, f, d) {
- var i = Math.cos(j),
- h = Math.sin(j);
- this.transform(i * c, h * c, -h * a, i * a, g, e);
- this.arc(0, 0, 1, b, f, d);
- this.transform(i / c, -h / a, h / c, i / a, -(i * g + h * e) / c, (h * g - i * e) / a)
- },
- appendPath: function(f) {
- var e = this,
- c = 0,
- b = 0,
- a = f.commands,
- g = f.params,
- d = a.length;
- e.beginPath();
- for (; c < d; c++) {
- switch (a[c]) {
- case "M":
- e.moveTo(g[b], g[b + 1]);
- b += 2;
- break;
- case "L":
- e.lineTo(g[b], g[b + 1]);
- b += 2;
- break;
- case "C":
- e.bezierCurveTo(g[b], g[b + 1], g[b + 2], g[b + 3], g[b + 4], g[b + 5]);
- b += 6;
- break;
- case "Z":
- e.closePath();
- break
- }
- }
- },
- save: function() {
- var c = this.toSave,
- d = c.length,
- e = d && {},
- b = 0,
- a;
- for (; b < d; b++) {
- a = c[b];
- if (a in this) {
- e[a] = this[a]
- }
- }
- this.state.push(e);
- this.$save()
- },
- restore: function() {
- var b = this.state.pop(),
- a;
- if (b) {
- for (a in b) {
- this[a] = b[a]
- }
- }
- this.$restore()
- }
- }
- },
- splitThreshold: 3000,
- toSave: ["fillGradient", "strokeGradient"],
- element: {
- reference: "element",
- style: {
- position: "absolute"
- },
- children: [{
- reference: "innerElement",
- style: {
- width: "100%",
- height: "100%",
- position: "relative"
- }
- }]
- },
- createCanvas: function() {
- var c = Ext.Element.create({
- tag: "canvas",
- cls: Ext.baseCSSPrefix + "surface-canvas"
- });
- window.G_vmlCanvasManager && G_vmlCanvasManager.initElement(c.dom);
- var d = Ext.draw.engine.Canvas.contextOverrides,
- a = c.dom.getContext("2d"),
- b;
- if (a.ellipse) {
- delete d.ellipse
- }
- a.state = [];
- a.toSave = this.toSave;
- for (b in d) {
- a["$" + b] = a[b]
- }
- Ext.apply(a, d);
- if (this.getHighPrecision()) {
- this.enablePrecisionCompensation(a)
- } else {
- this.disablePrecisionCompensation(a)
- }
- this.innerElement.appendChild(c);
- this.canvases.push(c);
- this.contexts.push(a)
- },
- updateHighPrecision: function(d) {
- var e = this.contexts,
- c = e.length,
- b, a;
- for (b = 0; b < c; b++) {
- a = e[b];
- if (d) {
- this.enablePrecisionCompensation(a)
- } else {
- this.disablePrecisionCompensation(a)
- }
- }
- },
- precisionNames: ["rect", "fillRect", "strokeRect", "clearRect", "moveTo", "lineTo", "arc", "arcTo", "save", "restore", "updatePrecisionCompensate", "setTransform", "transform", "scale", "translate", "rotate", "quadraticCurveTo", "bezierCurveTo", "createLinearGradient", "createRadialGradient", "fillText", "strokeText", "drawImage"],
- disablePrecisionCompensation: function(b) {
- var a = Ext.draw.engine.Canvas.contextOverrides,
- f = this.precisionNames,
- e = f.length,
- d, c;
- for (d = 0; d < e; d++) {
- c = f[d];
- if (!(c in a)) {
- delete b[c]
- }
- }
- this.setDirty(true)
- },
- enablePrecisionCompensation: function(j) {
- var c = this,
- a = 1,
- g = 1,
- l = 0,
- k = 0,
- i = new Ext.draw.Matrix(),
- b = [],
- e = {},
- d = Ext.draw.engine.Canvas.contextOverrides,
- h = j.constructor.prototype;
- var f = {
- toSave: c.toSave,
- rect: function(m, p, n, o) {
- return h.rect.call(this, m * a + l, p * g + k, n * a, o * g)
- },
- fillRect: function(m, p, n, o) {
- this.updatePrecisionCompensateRect();
- h.fillRect.call(this, m * a + l, p * g + k, n * a, o * g);
- this.updatePrecisionCompensate()
- },
- strokeRect: function(m, p, n, o) {
- this.updatePrecisionCompensateRect();
- h.strokeRect.call(this, m * a + l, p * g + k, n * a, o * g);
- this.updatePrecisionCompensate()
- },
- clearRect: function(m, p, n, o) {
- return h.clearRect.call(this, m * a + l, p * g + k, n * a, o * g)
- },
- moveTo: function(m, n) {
- return h.moveTo.call(this, m * a + l, n * g + k)
- },
- lineTo: function(m, n) {
- return h.lineTo.call(this, m * a + l, n * g + k)
- },
- arc: function(n, r, m, p, o, q) {
- this.updatePrecisionCompensateRect();
- h.arc.call(this, n * a + l, r * a + k, m * a, p, o, q);
- this.updatePrecisionCompensate()
- },
- arcTo: function(o, q, n, p, m) {
- this.updatePrecisionCompensateRect();
- h.arcTo.call(this, o * a + l, q * g + k, n * a + l, p * g + k, m * a);
- this.updatePrecisionCompensate()
- },
- save: function() {
- b.push(i);
- i = i.clone();
- d.save.call(this);
- h.save.call(this)
- },
- restore: function() {
- i = b.pop();
- d.restore.call(this);
- h.restore.call(this);
- this.updatePrecisionCompensate()
- },
- updatePrecisionCompensate: function() {
- i.precisionCompensate(c.devicePixelRatio, e);
- a = e.xx;
- g = e.yy;
- l = e.dx;
- k = e.dy;
- h.setTransform.call(this, c.devicePixelRatio, e.b, e.c, e.d, 0, 0)
- },
- updatePrecisionCompensateRect: function() {
- i.precisionCompensateRect(c.devicePixelRatio, e);
- a = e.xx;
- g = e.yy;
- l = e.dx;
- k = e.dy;
- h.setTransform.call(this, c.devicePixelRatio, e.b, e.c, e.d, 0, 0)
- },
- setTransform: function(q, o, n, m, r, p) {
- i.set(q, o, n, m, r, p);
- this.updatePrecisionCompensate()
- },
- transform: function(q, o, n, m, r, p) {
- i.append(q, o, n, m, r, p);
- this.updatePrecisionCompensate()
- },
- scale: function(n, m) {
- this.transform(n, 0, 0, m, 0, 0)
- },
- translate: function(n, m) {
- this.transform(1, 0, 0, 1, n, m)
- },
- rotate: function(o) {
- var n = Math.cos(o),
- m = Math.sin(o);
- this.transform(n, m, -m, n, 0, 0)
- },
- quadraticCurveTo: function(n, p, m, o) {
- h.quadraticCurveTo.call(this, n * a + l, p * g + k, m * a + l, o * g + k)
- },
- bezierCurveTo: function(r, p, o, n, m, q) {
- h.bezierCurveTo.call(this, r * a + l, p * g + k, o * a + l, n * g + k, m * a + l, q * g + k)
- },
- createLinearGradient: function(n, p, m, o) {
- this.updatePrecisionCompensateRect();
- var q = h.createLinearGradient.call(this, n * a + l, p * g + k, m * a + l, o * g + k);
- this.updatePrecisionCompensate();
- return q
- },
- createRadialGradient: function(p, r, o, n, q, m) {
- this.updatePrecisionCompensateRect();
- var s = h.createLinearGradient.call(this, p * a + l, r * a + k, o * a, n * a + l, q * a + k, m * a);
- this.updatePrecisionCompensate();
- return s
- },
- fillText: function(o, m, p, n) {
- h.setTransform.apply(this, i.elements);
- if (typeof n === "undefined") {
- h.fillText.call(this, o, m, p)
- } else {
- h.fillText.call(this, o, m, p, n)
- }
- this.updatePrecisionCompensate()
- },
- strokeText: function(o, m, p, n) {
- h.setTransform.apply(this, i.elements);
- if (typeof n === "undefined") {
- h.strokeText.call(this, o, m, p)
- } else {
- h.strokeText.call(this, o, m, p, n)
- }
- this.updatePrecisionCompensate()
- },
- fill: function() {
- var m = this.fillGradient,
- n = this.bbox;
- this.updatePrecisionCompensateRect();
- if (m && n) {
- this.fillStyle = m.generateGradient(this, n)
- }
- h.fill.call(this);
- this.updatePrecisionCompensate()
- },
- stroke: function() {
- var m = this.strokeGradient,
- n = this.bbox;
- this.updatePrecisionCompensateRect();
- if (m && n) {
- this.strokeStyle = m.generateGradient(this, n)
- }
- h.stroke.call(this);
- this.updatePrecisionCompensate()
- },
- drawImage: function(u, s, r, q, p, o, n, m, t) {
- switch (arguments.length) {
- case 3:
- return h.drawImage.call(this, u, s * a + l, r * g + k);
- case 5:
- return h.drawImage.call(this, u, s * a + l, r * g + k, q * a, p * g);
- case 9:
- return h.drawImage.call(this, u, s, r, q, p, o * a + l, n * g * k, m * a, t * g)
- }
- }
- };
- Ext.apply(j, f);
- this.setDirty(true)
- },
- updateRect: function(a) {
- this.callParent([a]);
- var C = this,
- p = Math.floor(a[0]),
- e = Math.floor(a[1]),
- g = Math.ceil(a[0] + a[2]),
- B = Math.ceil(a[1] + a[3]),
- u = C.devicePixelRatio,
- D = C.canvases,
- d = g - p,
- y = B - e,
- n = Math.round(C.splitThreshold / u),
- c = C.xSplits = Math.ceil(d / n),
- f = C.ySplits = Math.ceil(y / n),
- v, s, q, A, z, x, o, m;
- for (s = 0, z = 0; s < f; s++, z += n) {
- for (v = 0, A = 0; v < c; v++, A += n) {
- q = s * c + v;
- if (q >= D.length) {
- C.createCanvas()
- }
- x = D[q].dom;
- x.style.left = A + "px";
- x.style.top = z + "px";
- m = Math.min(n, y - z);
- if (m * u !== x.height) {
- x.height = m * u;
- x.style.height = m + "px"
- }
- o = Math.min(n, d - A);
- if (o * u !== x.width) {
- x.width = o * u;
- x.style.width = o + "px"
- }
- C.applyDefaults(C.contexts[q])
- }
- }
- for (q += 1; q < D.length; q++) {
- D[q].destroy()
- }
- C.activeCanvases = c * f;
- D.length = C.activeCanvases;
- C.clear()
- },
- clearTransform: function() {
- var f = this,
- a = f.xSplits,
- g = f.ySplits,
- d = f.contexts,
- h = f.splitThreshold,
- l = f.devicePixelRatio,
- e, c, b, m;
- for (e = 0; e < a; e++) {
- for (c = 0; c < g; c++) {
- b = c * a + e;
- m = d[b];
- m.translate(-h * e, -h * c);
- m.scale(l, l);
- f.matrix.toContext(m)
- }
- }
- },
- renderSprite: function(q) {
- var C = this,
- b = C.getRect(),
- e = C.matrix,
- g = q.getParent(),
- v = Ext.draw.Matrix.fly([1, 0, 0, 1, 0, 0]),
- p = C.splitThreshold / C.devicePixelRatio,
- c = C.xSplits,
- m = C.ySplits,
- A, z, s, a, r, o, d = 0,
- B, n = 0,
- f, l = b[2],
- y = b[3],
- x, u, t;
- while (g && (g !== C)) {
- v.prependMatrix(g.matrix || g.attr && g.attr.matrix);
- g = g.getParent()
- }
- v.prependMatrix(e);
- a = q.getBBox();
- if (a) {
- a = v.transformBBox(a)
- }
- q.preRender(C);
- if (q.attr.hidden || q.attr.globalAlpha === 0) {
- q.setDirty(false);
- return
- }
- for (u = 0, z = 0; u < m; u++, z += p) {
- for (x = 0, A = 0; x < c; x++, A += p) {
- t = u * c + x;
- s = C.contexts[t];
- r = Math.min(p, l - A);
- o = Math.min(p, y - z);
- d = A;
- B = d + r;
- n = z;
- f = n + o;
- if (a) {
- if (a.x > B || a.x + a.width < d || a.y > f || a.y + a.height < n) {
- continue
- }
- }
- s.save();
- q.useAttributes(s, b);
- if (false === q.render(C, s, [d, n, r, o], b)) {
- return false
- }
- s.restore()
- }
- }
- q.setDirty(false)
- },
- flatten: function(n, a) {
- var k = document.createElement("canvas"),
- f = Ext.getClassName(this),
- g = this.devicePixelRatio,
- l = k.getContext("2d"),
- b, c, h, e, d, m;
- k.width = Math.ceil(n.width * g);
- k.height = Math.ceil(n.height * g);
- for (e = 0; e < a.length; e++) {
- b = a[e];
- if (Ext.getClassName(b) !== f) {
- continue
- }
- h = b.getRect();
- for (d = 0; d < b.canvases.length; d++) {
- c = b.canvases[d];
- m = c.getOffsetsTo(c.getParent());
- l.drawImage(c.dom, (h[0] + m[0]) * g, (h[1] + m[1]) * g)
- }
- }
- return {
- data: k.toDataURL(),
- type: "png"
- }
- },
- applyDefaults: function(a) {
- var b = Ext.draw.Color.RGBA_NONE;
- a.strokeStyle = b;
- a.fillStyle = b;
- a.textAlign = "start";
- a.textBaseline = "alphabetic";
- a.miterLimit = 1
- },
- clear: function() {
- var d = this,
- e = d.activeCanvases,
- c, b, a;
- for (c = 0; c < e; c++) {
- b = d.canvases[c].dom;
- a = d.contexts[c];
- a.setTransform(1, 0, 0, 1, 0, 0);
- a.clearRect(0, 0, b.width, b.height)
- }
- d.setDirty(true)
- },
- destroy: function() {
- var c = this,
- a, b = c.canvases.length;
- for (a = 0; a < b; a++) {
- c.contexts[a] = null;
- c.canvases[a].destroy();
- c.canvases[a] = null
- }
- delete c.contexts;
- delete c.canvases;
- c.callParent()
- },
- privates: {
- initElement: function() {
- var a = this;
- a.callParent();
- a.canvases = [];
- a.contexts = [];
- a.activeCanvases = (a.xSplits = 0) * (a.ySplits = 0)
- }
- }
-}, function() {
- var c = this,
- b = c.prototype,
- a = 10000000000;
- if (Ext.os.is.Android4 && Ext.browser.is.Chrome) {
- a = 3000
- } else {
- if (Ext.is.iOS) {
- a = 2200
- }
- }
- b.splitThreshold = a
-});
-Ext.define("Ext.draw.Container", {
- extend: "Ext.draw.ContainerBase",
- alternateClassName: "Ext.draw.Component",
- xtype: "draw",
- defaultType: "surface",
- isDrawContainer: true,
- requires: ["Ext.draw.Surface", "Ext.draw.engine.Svg", "Ext.draw.engine.Canvas", "Ext.draw.gradient.GradientDefinition"],
- engine: "Ext.draw.engine.Canvas",
- config: {
- cls: Ext.baseCSSPrefix + "draw-container",
- resizeHandler: null,
- sprites: null,
- gradients: []
- },
- defaultDownloadServerUrl: "http://svg.sencha.io",
- supportedFormats: ["png", "pdf", "jpeg", "gif"],
- supportedOptions: {
- version: Ext.isNumber,
- data: Ext.isString,
- format: function(a) {
- return Ext.Array.indexOf(this.supportedFormats, a) >= 0
- },
- filename: Ext.isString,
- width: Ext.isNumber,
- height: Ext.isNumber,
- scale: Ext.isNumber,
- pdf: Ext.isObject,
- jpeg: Ext.isObject
- },
- initAnimator: function() {
- this.frameCallbackId = Ext.draw.Animator.addFrameCallback("renderFrame", this)
- },
- applyGradients: function(b) {
- var a = [],
- c, f, d, e;
- if (!Ext.isArray(b)) {
- return a
- }
- for (c = 0, f = b.length; c < f; c++) {
- d = b[c];
- if (!Ext.isObject(d)) {
- continue
- }
- if (typeof d.type !== "string") {
- d.type = "linear"
- }
- if (d.angle) {
- d.degrees = d.angle;
- delete d.angle
- }
- if (Ext.isObject(d.stops)) {
- d.stops = (function(i) {
- var g = [],
- h;
- for (e in i) {
- h = i[e];
- h.offset = e / 100;
- g.push(h)
- }
- return g
- })(d.stops)
- }
- a.push(d)
- }
- Ext.draw.gradient.GradientDefinition.add(a);
- return a
- },
- applySprites: function(f) {
- if (!f) {
- return
- }
- f = Ext.Array.from(f);
- var e = f.length,
- b = [],
- d, a, c;
- for (d = 0; d < e; d++) {
- c = f[d];
- a = c.surface;
- if (!(a && a.isSurface)) {
- if (Ext.isString(a)) {
- a = this.getSurface(a)
- } else {
- a = this.getSurface("main")
- }
- }
- c = a.add(c);
- b.push(c)
- }
- return b
- },
- onBodyResize: function() {
- var b = this.element,
- a;
- if (!b) {
- return
- }
- a = b.getSize();
- if (a.width && a.height) {
- this.setBodySize(a)
- }
- },
- setBodySize: function(c) {
- var d = this,
- b = d.getResizeHandler() || d.defaultResizeHandler,
- a;
- d.fireEvent("bodyresize", d, c);
- a = b.call(d, c);
- if (a !== false) {
- d.renderFrame()
- }
- },
- defaultResizeHandler: function(a) {
- this.getItems().each(function(b) {
- b.setRect([0, 0, a.width, a.height])
- })
- },
- getSurface: function(d) {
- d = this.getId() + "-" + (d || "main");
- var c = this,
- b = c.getItems(),
- a = b.get(d);
- if (!a) {
- a = c.add({
- xclass: c.engine,
- id: d
- });
- c.onBodyResize()
- }
- return a
- },
- renderFrame: function() {
- var e = this,
- a = e.getItems(),
- b, d, c;
- for (b = 0, d = a.length; b < d; b++) {
- c = a.items[b];
- if (c.isSurface) {
- c.renderFrame()
- }
- }
- },
- getImage: function(k) {
- var l = this.innerElement.getSize(),
- a = Array.prototype.slice.call(this.items.items),
- d, g, c = this.surfaceZIndexes,
- f, e, b, h;
- for (e = 1; e < a.length; e++) {
- b = a[e];
- h = c[b.type];
- f = e - 1;
- while (f >= 0 && c[a[f].type] > h) {
- a[f + 1] = a[f];
- f--
- }
- a[f + 1] = b
- }
- d = a[0].flatten(l, a);
- if (k === "image") {
- g = new Image();
- g.src = d.data;
- d.data = g;
- return d
- }
- if (k === "stream") {
- d.data = d.data.replace(/^data:image\/[^;]+/, "data:application/octet-stream");
- return d
- }
- return d
- },
- download: function(d) {
- var e = this,
- a = [],
- b, c, f;
- d = Ext.apply({
- version: 2,
- data: e.getImage().data
- }, d);
- for (c in d) {
- if (d.hasOwnProperty(c)) {
- f = d[c];
- if (c in e.supportedOptions) {
- if (e.supportedOptions[c].call(e, f)) {
- a.push({
- tag: "input",
- type: "hidden",
- name: c,
- value: Ext.String.htmlEncode(Ext.isObject(f) ? Ext.JSON.encode(f) : f)
- })
- }
- }
- }
- }
- b = Ext.dom.Helper.markup({
- tag: "html",
- children: [{
- tag: "head"
- }, {
- tag: "body",
- children: [{
- tag: "form",
- method: "POST",
- action: d.url || e.defaultDownloadServerUrl,
- children: a
- }, {
- tag: "script",
- type: "text/javascript",
- children: 'document.getElementsByTagName("form")[0].submit();'
- }]
- }]
- });
- window.open("", "ImageDownload_" + Date.now()).document.write(b)
- },
- destroy: function() {
- var a = this.frameCallbackId;
- if (a) {
- Ext.draw.Animator.removeFrameCallback(a)
- }
- this.callParent()
- }
-}, function() {
- if (location.search.match("svg")) {
- Ext.draw.Container.prototype.engine = "Ext.draw.engine.Svg"
- } else {
- if ((Ext.os.is.BlackBerry && Ext.os.version.getMajor() === 10) || (Ext.browser.is.AndroidStock4 && (Ext.os.version.getMinor() === 1 || Ext.os.version.getMinor() === 2 || Ext.os.version.getMinor() === 3))) {
- Ext.draw.Container.prototype.engine = "Ext.draw.engine.Svg"
- }
- }
-});
-Ext.define("Ext.chart.theme.Base", {
- mixins: {
- factoryable: "Ext.mixin.Factoryable"
- },
- requires: ["Ext.draw.Color"],
- factoryConfig: {
- type: "chart.theme"
- },
- isTheme: true,
- config: {
- baseColor: null,
- colors: undefined,
- gradients: null,
- chart: {
- defaults: {
- background: "#23272a"
- }
- },
- axis: {
- defaults: {
- label: {
- x: 0,
- y: 0,
- textBaseline: "middle",
- textAlign: "center",
- fontSize: "default",
- fontFamily: "default",
- fontWeight: "default",
- fillStyle: "black",
- color: "white"
- },
- title: {
- fillStyle: "black",
- fontSize: "default*1.23",
- fontFamily: "default",
- fontWeight: "default",
- color: "white"
- },
- style: {
- strokeStyle: "black"
- },
- grid: {
- strokeStyle: "rgba(44, 47, 51, 1)"
- }
- },
- top: {
- style: {
- textPadding: 5
- }
- },
- bottom: {
- style: {
- textPadding: 5
- }
- }
- },
- series: {
- defaults: {
- label: {
- fillStyle: "black",
- strokeStyle: "none",
- fontFamily: "default",
- fontWeight: "default",
- fontSize: "default*1.077",
- textBaseline: "middle",
- textAlign: "center"
- },
- labelOverflowPadding: 5
- }
- },
- sprites: {
- text: {
- fontSize: "default",
- fontWeight: "default",
- fontFamily: "default",
- fillStyle: "black",
- color: "white"
- }
- },
- seriesThemes: undefined,
- markerThemes: {
- type: ["circle", "cross", "plus", "square", "triangle", "diamond"]
- },
- useGradients: false,
- background: null
- },
- colorDefaults: ["#94ae0a", "#115fa6", "#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
- constructor: function(a) {
- this.initConfig(a);
- this.resolveDefaults()
- },
- defaultRegEx: /^default([+\-/\*]\d+(?:\.\d+)?)?$/,
- defaultOperators: {
- "*": function(b, a) {
- return b * a
- },
- "+": function(b, a) {
- return b + a
- },
- "-": function(b, a) {
- return b - a
- }
- },
- resolveDefaults: function() {
- var a = this;
- Ext.onReady(function() {
- var f = Ext.clone(a.getSprites()),
- e = Ext.clone(a.getAxis()),
- d = Ext.clone(a.getSeries()),
- g, c, b;
- if (!a.superclass.defaults) {
- g = Ext.getBody().createChild({
- tag: "div",
- cls: "x-component"
- });
- a.superclass.defaults = {
- fontFamily: g.getStyle("fontFamily"),
- fontWeight: g.getStyle("fontWeight"),
- fontSize: parseFloat(g.getStyle("fontSize")),
- fontVariant: g.getStyle("fontVariant"),
- fontStyle: g.getStyle("fontStyle")
- };
- g.destroy()
- }
- a.replaceDefaults(f.text);
- a.setSprites(f);
- for (c in e) {
- b = e[c];
- a.replaceDefaults(b.label);
- a.replaceDefaults(b.title)
- }
- a.setAxis(e);
- for (c in d) {
- b = d[c];
- a.replaceDefaults(b.label)
- }
- a.setSeries(d)
- })
- },
- replaceDefaults: function(h) {
- var e = this,
- g = e.superclass.defaults,
- a = e.defaultRegEx,
- d, f, c, b;
- if (Ext.isObject(h)) {
- for (d in g) {
- c = a.exec(h[d]);
- if (c) {
- f = g[d];
- c = c[1];
- if (c) {
- b = e.defaultOperators[c.charAt(0)];
- f = Math.round(b(f, parseFloat(c.substr(1))))
- }
- h[d] = f
- }
- }
- }
- },
- applyBaseColor: function(c) {
- var a, b;
- if (c) {
- a = c.isColor ? c : Ext.draw.Color.fromString(c);
- b = a.getHSL()[2];
- if (b < 0.15) {
- a = a.createLighter(0.3)
- } else {
- if (b < 0.3) {
- a = a.createLighter(0.15)
- } else {
- if (b > 0.85) {
- a = a.createDarker(0.3)
- } else {
- if (b > 0.7) {
- a = a.createDarker(0.15)
- }
- }
- }
- }
- this.setColors([a.createDarker(0.3).toString(), a.createDarker(0.15).toString(), a.toString(), a.createLighter(0.12).toString(), a.createLighter(0.24).toString(), a.createLighter(0.31).toString()])
- }
- return c
- },
- applyColors: function(a) {
- return a || this.colorDefaults
- },
- updateUseGradients: function(a) {
- if (a) {
- this.updateGradients({
- type: "linear",
- degrees: 90
- })
- }
- },
- updateBackground: function(a) {
- if (a) {
- var b = this.getChart();
- b.defaults.background = a;
- this.setChart(b)
- }
- },
- updateGradients: function(a) {
- var c = this.getColors(),
- e = [],
- h, b, d, f, g;
- if (Ext.isObject(a)) {
- for (f = 0, g = c && c.length || 0; f < g; f++) {
- b = Ext.draw.Color.fromString(c[f]);
- if (b) {
- d = b.createLighter(0.15).toString();
- h = Ext.apply(Ext.Object.chain(a), {
- stops: [{
- offset: 1,
- color: b.toString()
- }, {
- offset: 0,
- color: d.toString()
- }]
- });
- e.push(h)
- }
- }
- this.setColors(e)
- }
- },
- applySeriesThemes: function(a) {
- this.getBaseColor();
- this.getUseGradients();
- this.getGradients();
- var b = this.getColors();
- if (!a) {
- a = {
- fillStyle: Ext.Array.clone(b),
- strokeStyle: Ext.Array.map(b, function(d) {
- var c = Ext.draw.Color.fromString(d.stops ? d.stops[0].color : d);
- return c.createDarker(0.15).toString()
- })
- }
- }
- return a
- }
-});
-Ext.define("Ext.chart.theme.Default", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.default", "chart.theme.Base"]
-});
-Ext.define("Ext.chart.Markers", {
- extend: "Ext.draw.sprite.Instancing",
- isMarkers: true,
- defaultCategory: "default",
- constructor: function() {
- this.callParent(arguments);
- this.categories = {};
- this.revisions = {}
- },
- destroy: function() {
- this.categories = null;
- this.revisions = null;
- this.callParent()
- },
- getMarkerFor: function(b, a) {
- if (b in this.categories) {
- var c = this.categories[b];
- if (a in c) {
- return this.get(c[a])
- }
- }
- },
- clear: function(a) {
- a = a || this.defaultCategory;
- if (!(a in this.revisions)) {
- this.revisions[a] = 1
- } else {
- this.revisions[a]++
- }
- },
- putMarkerFor: function(e, b, c, h, f) {
- e = e || this.defaultCategory;
- var d = this,
- g = d.categories[e] || (d.categories[e] = {}),
- a;
- if (c in g) {
- d.setAttributesFor(g[c], b, h)
- } else {
- g[c] = d.getCount();
- d.createInstance(b, h)
- }
- a = d.get(g[c]);
- if (a) {
- a.category = e;
- if (!f) {
- a.revision = d.revisions[e] || (d.revisions[e] = 1)
- }
- }
- },
- getMarkerBBoxFor: function(c, a, b) {
- if (c in this.categories) {
- var d = this.categories[c];
- if (a in d) {
- return this.getBBoxFor(d[a], b)
- }
- }
- },
- getBBox: function() {
- return null
- },
- render: function(a, l, b) {
- var f = this,
- k = f.revisions,
- j = f.attr.matrix,
- h = f.getTemplate(),
- d = h.attr,
- g, c, e;
- j.toContext(l);
- h.preRender(a, l, b);
- h.useAttributes(l, b);
- for (c = 0, e = f.instances.length; c < e; c++) {
- g = f.get(c);
- if (g.hidden || g.revision !== k[g.category]) {
- continue
- }
- l.save();
- h.attr = g;
- h.useAttributes(l, b);
- h.render(a, l, b);
- l.restore()
- }
- h.attr = d
- }
-});
-Ext.define("Ext.chart.label.Callout", {
- extend: "Ext.draw.modifier.Modifier",
- prepareAttributes: function(a) {
- if (!a.hasOwnProperty("calloutOriginal")) {
- a.calloutOriginal = Ext.Object.chain(a);
- a.calloutOriginal.prototype = a
- }
- if (this._previous) {
- this._previous.prepareAttributes(a.calloutOriginal)
- }
- },
- setAttrs: function(e, h) {
- var d = e.callout,
- i = e.calloutOriginal,
- l = e.bbox.plain,
- c = (l.width || 0) + e.labelOverflowPadding,
- m = (l.height || 0) + e.labelOverflowPadding,
- p, o;
- if ("callout" in h) {
- d = h.callout
- }
- if ("callout" in h || "calloutPlaceX" in h || "calloutPlaceY" in h || "x" in h || "y" in h) {
- var n = "rotationRads" in h ? i.rotationRads = h.rotationRads : i.rotationRads,
- g = "x" in h ? (i.x = h.x) : i.x,
- f = "y" in h ? (i.y = h.y) : i.y,
- b = "calloutPlaceX" in h ? h.calloutPlaceX : e.calloutPlaceX,
- a = "calloutPlaceY" in h ? h.calloutPlaceY : e.calloutPlaceY,
- k = "calloutVertical" in h ? h.calloutVertical : e.calloutVertical,
- j;
- n %= Math.PI * 2;
- if (Math.cos(n) < 0) {
- n = (n + Math.PI) % (Math.PI * 2)
- }
- if (n > Math.PI) {
- n -= Math.PI * 2
- }
- if (k) {
- n = n * (1 - d) - Math.PI / 2 * d;
- j = c;
- c = m;
- m = j
- } else {
- n = n * (1 - d)
- }
- h.rotationRads = n;
- h.x = g * (1 - d) + b * d;
- h.y = f * (1 - d) + a * d;
- p = b - g;
- o = a - f;
- if (Math.abs(o * c) > Math.abs(p * m)) {
- if (o > 0) {
- h.calloutEndX = h.x - (m / 2) * (p / o) * d;
- h.calloutEndY = h.y - (m / 2) * d
- } else {
- h.calloutEndX = h.x + (m / 2) * (p / o) * d;
- h.calloutEndY = h.y + (m / 2) * d
- }
- } else {
- if (p > 0) {
- h.calloutEndX = h.x - c / 2;
- h.calloutEndY = h.y - (c / 2) * (o / p) * d
- } else {
- h.calloutEndX = h.x + c / 2;
- h.calloutEndY = h.y + (c / 2) * (o / p) * d
- }
- }
- if (h.calloutStartX && h.calloutStartY) {
- h.calloutHasLine = (p > 0 && h.calloutStartX < h.calloutEndX) || (p <= 0 && h.calloutStartX > h.calloutEndX) || (o > 0 && h.calloutStartY < h.calloutEndY) || (o <= 0 && h.calloutStartY > h.calloutEndY)
- } else {
- h.calloutHasLine = true
- }
- }
- return h
- },
- pushDown: function(a, b) {
- b = this.callParent([a.calloutOriginal, b]);
- return this.setAttrs(a, b)
- },
- popUp: function(a, b) {
- a = a.prototype;
- b = this.setAttrs(a, b);
- if (this._next) {
- return this._next.popUp(a, b)
- } else {
- return Ext.apply(a, b)
- }
- }
-});
-Ext.define("Ext.chart.label.Label", {
- extend: "Ext.draw.sprite.Text",
- requires: ["Ext.chart.label.Callout"],
- inheritableStatics: {
- def: {
- processors: {
- callout: "limited01",
- calloutHasLine: "bool",
- calloutPlaceX: "number",
- calloutPlaceY: "number",
- calloutStartX: "number",
- calloutStartY: "number",
- calloutEndX: "number",
- calloutEndY: "number",
- calloutColor: "color",
- calloutWidth: "number",
- calloutVertical: "bool",
- labelOverflowPadding: "number",
- display: "enums(none,under,over,rotate,insideStart,insideEnd,inside,outside)",
- orientation: "enums(horizontal,vertical)",
- renderer: "default"
- },
- defaults: {
- callout: 0,
- calloutHasLine: true,
- calloutPlaceX: 0,
- calloutPlaceY: 0,
- calloutStartX: 0,
- calloutStartY: 0,
- calloutEndX: 0,
- calloutEndY: 0,
- calloutWidth: 1,
- calloutVertical: false,
- calloutColor: "black",
- labelOverflowPadding: 5,
- display: "none",
- orientation: "",
- renderer: null
- },
- triggers: {
- callout: "transform",
- calloutPlaceX: "transform",
- calloutPlaceY: "transform",
- labelOverflowPadding: "transform",
- calloutRotation: "transform",
- display: "hidden"
- },
- updaters: {
- hidden: function(a) {
- a.hidden = a.display === "none"
- }
- }
- }
- },
- config: {
- fx: {
- customDurations: {
- callout: 200
- }
- },
- field: null,
- calloutLine: true
- },
- applyCalloutLine: function(a) {
- if (a) {
- return Ext.apply({}, a)
- }
- },
- prepareModifiers: function() {
- this.callParent(arguments);
- this.calloutModifier = new Ext.chart.label.Callout({
- sprite: this
- });
- this.fx.setNext(this.calloutModifier);
- this.calloutModifier.setNext(this.topModifier)
- },
- render: function(b, c) {
- var e = this,
- a = e.attr,
- d = a.calloutColor;
- c.save();
- c.globalAlpha *= a.callout;
- if (c.globalAlpha > 0 && a.calloutHasLine) {
- if (d && d.isGradient) {
- d = d.getStops()[0].color
- }
- c.strokeStyle = d;
- c.fillStyle = d;
- c.lineWidth = a.calloutWidth;
- c.beginPath();
- c.moveTo(e.attr.calloutStartX, e.attr.calloutStartY);
- c.lineTo(e.attr.calloutEndX, e.attr.calloutEndY);
- c.stroke();
- c.beginPath();
- c.arc(e.attr.calloutStartX, e.attr.calloutStartY, 1 * a.calloutWidth, 0, 2 * Math.PI, true);
- c.fill();
- c.beginPath();
- c.arc(e.attr.calloutEndX, e.attr.calloutEndY, 1 * a.calloutWidth, 0, 2 * Math.PI, true);
- c.fill()
- }
- c.restore();
- Ext.draw.sprite.Text.prototype.render.apply(e, arguments)
- }
-});
-Ext.define("Ext.chart.series.Series", {
- requires: ["Ext.chart.Markers", "Ext.chart.label.Label", "Ext.tip.ToolTip"],
- mixins: ["Ext.mixin.Observable", "Ext.mixin.Bindable"],
- isSeries: true,
- defaultBindProperty: "store",
- type: null,
- seriesType: "sprite",
- identifiablePrefix: "ext-line-",
- observableType: "series",
- darkerStrokeRatio: 0.15,
- config: {
- chart: null,
- title: null,
- renderer: null,
- showInLegend: true,
- triggerAfterDraw: false,
- style: {},
- subStyle: {},
- themeStyle: {},
- colors: null,
- useDarkerStrokeColor: true,
- store: null,
- label: {},
- labelOverflowPadding: null,
- showMarkers: true,
- marker: null,
- markerSubStyle: null,
- itemInstancing: null,
- background: null,
- highlightItem: null,
- surface: null,
- overlaySurface: null,
- hidden: false,
- highlight: false,
- highlightCfg: {
- merge: function(a) {
- return a
- },
- $value: {
- fillStyle: "yellow",
- strokeStyle: "red"
- }
- },
- animation: null,
- tooltip: null
- },
- directions: [],
- sprites: null,
- themeColorCount: function() {
- return 1
- },
- isStoreDependantColorCount: false,
- themeMarkerCount: function() {
- return 0
- },
- getFields: function(f) {
- var e = this,
- a = [],
- c, b, d;
- for (b = 0, d = f.length; b < d; b++) {
- c = e["get" + f[b] + "Field"]();
- if (Ext.isArray(c)) {
- a.push.apply(a, c)
- } else {
- a.push(c)
- }
- }
- return a
- },
- applyAnimation: function(a, b) {
- if (!a) {
- a = {
- duration: 0
- }
- } else {
- if (a === true) {
- a = {
- easing: "easeInOut",
- duration: 500
- }
- }
- }
- return b ? Ext.apply({}, a, b) : a
- },
- getAnimation: function() {
- var a = this.getChart();
- if (a && a.animationSuspendCount) {
- return {
- duration: 0
- }
- } else {
- return this.callParent()
- }
- },
- updateTitle: function(a) {
- var j = this,
- g = j.getChart();
- if (!g || g.isInitializing) {
- return
- }
- a = Ext.Array.from(a);
- var c = g.getSeries(),
- b = Ext.Array.indexOf(c, j),
- e = g.getLegendStore(),
- h = j.getYField(),
- d, l, k, f;
- if (e.getCount() && b !== -1) {
- f = h ? Math.min(a.length, h.length) : a.length;
- for (d = 0; d < f; d++) {
- k = a[d];
- l = e.getAt(b + d);
- if (k && l) {
- l.set("name", k)
- }
- }
- }
- },
- applyHighlight: function(a, b) {
- if (Ext.isObject(a)) {
- a = Ext.merge({}, this.config.highlightCfg, a)
- } else {
- if (a === true) {
- a = this.config.highlightCfg
- }
- }
- return Ext.apply(b || {}, a)
- },
- updateHighlight: function(a) {
- this.getStyle();
- if (!Ext.Object.isEmpty(a)) {
- this.addItemHighlight()
- }
- },
- updateHighlightCfg: function(a) {
- if (!Ext.Object.equals(a, this.defaultConfig.highlightCfg)) {
- this.addItemHighlight()
- }
- },
- applyItemInstancing: function(a, b) {
- return Ext.merge(b || {}, a)
- },
- setAttributesForItem: function(c, d) {
- var b = c && c.sprite,
- a;
- if (b) {
- if (b.itemsMarker && c.category === "items") {
- b.putMarker(c.category, d, c.index, false, true)
- }
- if (b.isMarkerHolder && c.category === "markers") {
- b.putMarker(c.category, d, c.index, false, true)
- } else {
- if (b.isInstancing) {
- b.setAttributesFor(c.index, d)
- } else {
- if (Ext.isArray(b)) {
- for (a = 0; a < b.length; a++) {
- b[a].setAttributes(d)
- }
- } else {
- b.setAttributes(d)
- }
- }
- }
- }
- },
- getBBoxForItem: function(a) {
- if (a && a.sprite) {
- if (a.sprite.itemsMarker && a.category === "items") {
- return a.sprite.getMarkerBBox(a.category, a.index)
- } else {
- if (a.sprite instanceof Ext.draw.sprite.Instancing) {
- return a.sprite.getBBoxFor(a.index)
- } else {
- return a.sprite.getBBox()
- }
- }
- }
- return null
- },
- applyHighlightItem: function(d, a) {
- if (d === a) {
- return
- }
- if (Ext.isObject(d) && Ext.isObject(a)) {
- var c = d.sprite === a.sprite,
- b = d.index === a.index;
- if (c && b) {
- return
- }
- }
- return d
- },
- updateHighlightItem: function(b, a) {
- this.setAttributesForItem(a, {
- highlighted: false
- });
- this.setAttributesForItem(b, {
- highlighted: true
- })
- },
- constructor: function(a) {
- var b = this,
- c;
- a = a || {};
- if (a.tips) {
- a = Ext.apply({
- tooltip: a.tips
- }, a)
- }
- if (a.highlightCfg) {
- a = Ext.apply({
- highlight: a.highlightCfg
- }, a)
- }
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.sprites = [];
- b.dataRange = [];
- b.mixins.observable.constructor.call(b, a);
- b.initBindable()
- },
- lookupViewModel: function(a) {
- var b = this.getChart();
- return b ? b.lookupViewModel(a) : null
- },
- applyTooltip: function(c, b) {
- var a = Ext.apply({
- xtype: "tooltip",
- renderer: Ext.emptyFn,
- constrainPosition: true,
- shrinkWrapDock: true,
- autoHide: true,
- offsetX: 10,
- offsetY: 10
- }, c);
- return Ext.create(a)
- },
- updateTooltip: function() {
- this.addItemHighlight()
- },
- addItemHighlight: function() {
- var d = this.getChart();
- if (!d) {
- return
- }
- var e = d.getInteractions(),
- c, a, b;
- for (c = 0; c < e.length; c++) {
- a = e[c];
- if (a.isItemHighlight || a.isItemEdit) {
- b = true;
- break
- }
- }
- if (!b) {
- e.push("itemhighlight");
- d.setInteractions(e)
- }
- },
- showTooltip: function(l, m) {
- var d = this,
- n = d.getTooltip(),
- j, a, i, f, h, k, g, e, b, c;
- if (!n) {
- return
- }
- clearTimeout(d.tooltipTimeout);
- b = n.config;
- if (n.trackMouse) {
- m[0] += b.offsetX;
- m[1] += b.offsetY
- } else {
- j = l.sprite;
- a = j.getSurface();
- i = Ext.get(a.getId());
- if (i) {
- k = l.series.getBBoxForItem(l);
- g = k.x + k.width / 2;
- e = k.y + k.height / 2;
- h = a.matrix.transformPoint([g, e]);
- f = i.getXY();
- c = a.getInherited().rtl;
- g = c ? f[0] + i.getWidth() - h[0] : f[0] + h[0];
- e = f[1] + h[1];
- m = [g, e]
- }
- }
- Ext.callback(n.renderer, n.scope, [n, l.record, l], 0, d);
- n.show(m)
- },
- hideTooltip: function(b) {
- var a = this,
- c = a.getTooltip();
- if (!c) {
- return
- }
- clearTimeout(a.tooltipTimeout);
- a.tooltipTimeout = Ext.defer(function() {
- c.hide()
- }, 1)
- },
- applyStore: function(a) {
- return a && Ext.StoreManager.lookup(a)
- },
- getStore: function() {
- return this._store || this.getChart() && this.getChart().getStore()
- },
- updateStore: function(b, a) {
- var h = this,
- g = h.getChart(),
- c = g && g.getStore(),
- f, j, e, d;
- a = a || c;
- if (a && a !== b) {
- a.un({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: h
- })
- }
- if (b) {
- b.on({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: h
- });
- f = h.getSprites();
- for (d = 0, e = f.length; d < e; d++) {
- j = f[d];
- if (j.setStore) {
- j.setStore(b)
- }
- }
- h.onDataChanged()
- }
- h.fireEvent("storechange", h, b, a)
- },
- onStoreChange: function(b, a, c) {
- if (!this._store) {
- this.updateStore(a, c)
- }
- },
- coordinate: function(o, m, e) {
- var l = this,
- p = l.getStore(),
- h = l.getHidden(),
- k = p.getData().items,
- b = l["get" + o + "Axis"](),
- f = {
- min: Infinity,
- max: -Infinity
- },
- q = l["fieldCategory" + o] || [o],
- g = l.getFields(q),
- d, n, c, a = {},
- j = l.getSprites();
- if (j.length > 0) {
- if (!Ext.isBoolean(h) || !h) {
- for (d = 0; d < q.length; d++) {
- n = g[d];
- c = l.coordinateData(k, n, b);
- l.getRangeOfData(c, f);
- a["data" + q[d]] = c
- }
- }
- l.dataRange[m] = f.min;
- l.dataRange[m + e] = f.max;
- a["dataMin" + o] = f.min;
- a["dataMax" + o] = f.max;
- if (b) {
- b.range = null;
- a["range" + o] = b.getRange()
- }
- for (d = 0; d < j.length; d++) {
- j[d].setAttributes(a)
- }
- }
- },
- coordinateData: function(b, h, d) {
- var g = [],
- f = b.length,
- e = d && d.getLayout(),
- c, a;
- for (c = 0; c < f; c++) {
- a = b[c].data[h];
- if (!Ext.isEmpty(a, true)) {
- if (e) {
- g[c] = e.getCoordFor(a, h, c, b)
- } else {
- g[c] = +a
- }
- } else {
- g[c] = a
- }
- }
- return g
- },
- getRangeOfData: function(g, b) {
- var e = g.length,
- d = b.min,
- a = b.max,
- c, f;
- for (c = 0; c < e; c++) {
- f = g[c];
- if (f < d) {
- d = f
- }
- if (f > a) {
- a = f
- }
- }
- b.min = d;
- b.max = a
- },
- updateLabelData: function() {
- var h = this,
- l = h.getStore(),
- g = l.getData().items,
- f = h.getSprites(),
- a = h.getLabel().getTemplate(),
- n = Ext.Array.from(a.getField()),
- c, b, e, d, m, k;
- if (!f.length || !n.length) {
- return
- }
- for (c = 0; c < f.length; c++) {
- d = [];
- m = f[c];
- k = m.getField();
- if (Ext.Array.indexOf(n, k) < 0) {
- k = n[c]
- }
- for (b = 0, e = g.length; b < e; b++) {
- d.push(g[b].get(k))
- }
- m.setAttributes({
- labels: d
- })
- }
- },
- processData: function() {
- if (!this.getStore()) {
- return
- }
- var d = this,
- f = this.directions,
- a, c = f.length,
- e, b;
- for (a = 0; a < c; a++) {
- e = f[a];
- b = d["get" + e + "Axis"]();
- if (b) {
- b.processData(d);
- continue
- }
- if (d["coordinate" + e]) {
- d["coordinate" + e]()
- }
- }
- d.updateLabelData()
- },
- applyBackground: function(a) {
- if (this.getChart()) {
- this.getSurface().setBackground(a);
- return this.getSurface().getBackground()
- } else {
- return a
- }
- },
- updateChart: function(d, a) {
- var c = this,
- b = c._store;
- if (a) {
- a.un("axeschange", "onAxesChange", c);
- c.clearSprites();
- c.setSurface(null);
- c.setOverlaySurface(null);
- a.unregister(c);
- c.onChartDetached(a);
- if (!b) {
- c.updateStore(null)
- }
- }
- if (d) {
- c.setSurface(d.getSurface("series"));
- c.setOverlaySurface(d.getSurface("overlay"));
- d.on("axeschange", "onAxesChange", c);
- if (d.getAxes()) {
- c.onAxesChange(d)
- }
- c.onChartAttached(d);
- d.register(c);
- if (!b) {
- c.updateStore(d.getStore())
- }
- }
- },
- onAxesChange: function(h) {
- var k = this,
- g = h.getAxes(),
- c, a = {},
- b = {},
- e = false,
- j = this.directions,
- l, d, f;
- for (d = 0, f = j.length; d < f; d++) {
- l = j[d];
- b[l] = k.getFields(k["fieldCategory" + l])
- }
- for (d = 0, f = g.length; d < f; d++) {
- c = g[d];
- if (!a[c.getDirection()]) {
- a[c.getDirection()] = [c]
- } else {
- a[c.getDirection()].push(c)
- }
- }
- for (d = 0, f = j.length; d < f; d++) {
- l = j[d];
- if (k["get" + l + "Axis"]()) {
- continue
- }
- if (a[l]) {
- c = k.findMatchingAxis(a[l], b[l]);
- if (c) {
- k["set" + l + "Axis"](c);
- if (c.getNeedHighPrecision()) {
- e = true
- }
- }
- }
- }
- this.getSurface().setHighPrecision(e)
- },
- findMatchingAxis: function(f, e) {
- var d, c, b, a;
- for (b = 0; b < f.length; b++) {
- d = f[b];
- c = d.getFields();
- if (!c.length) {
- return d
- } else {
- if (e) {
- for (a = 0; a < e.length; a++) {
- if (Ext.Array.indexOf(c, e[a]) >= 0) {
- return d
- }
- }
- }
- }
- }
- },
- onChartDetached: function(a) {
- var b = this;
- b.fireEvent("chartdetached", a, b);
- a.un("storechange", "onStoreChange", b)
- },
- onChartAttached: function(a) {
- var b = this;
- b.setBackground(b.getBackground());
- b.fireEvent("chartattached", a, b);
- a.on("storechange", "onStoreChange", b);
- b.processData()
- },
- updateOverlaySurface: function(a) {
- var b = this;
- if (a) {
- if (b.getLabel()) {
- b.getOverlaySurface().add(b.getLabel())
- }
- }
- },
- applyLabel: function(a, b) {
- if (!b) {
- b = new Ext.chart.Markers({
- zIndex: 10
- });
- b.setTemplate(new Ext.chart.label.Label(a))
- } else {
- b.getTemplate().setAttributes(a)
- }
- return b
- },
- createItemInstancingSprite: function(c, b) {
- var e = this,
- f = new Ext.chart.Markers(),
- a, d;
- f.setAttributes({
- zIndex: Number.MAX_VALUE
- });
- a = Ext.apply({}, b);
- if (e.getHighlight()) {
- a.highlight = e.getHighlight();
- a.modifiers = ["highlight"]
- }
- f.setTemplate(a);
- d = f.getTemplate();
- d.setAttributes(e.getStyle());
- d.fx.on("animationstart", "onSpriteAnimationStart", this);
- d.fx.on("animationend", "onSpriteAnimationEnd", this);
- c.bindMarker("items", f);
- e.getSurface().add(f);
- return f
- },
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer()
- }
- },
- updateRenderer: function(c) {
- var b = this,
- a = b.getChart(),
- d;
- if (a && a.isInitializing) {
- return
- }
- d = b.getSprites();
- if (d.length) {
- d[0].setAttributes({
- renderer: c || null
- });
- if (a && !a.isInitializing) {
- a.redraw()
- }
- }
- },
- updateShowMarkers: function(a) {
- var d = this.getSprites(),
- b = d && d[0],
- c = b && b.getMarker("markers");
- if (c) {
- c.getTemplate().setAttributes({
- hidden: !a
- })
- }
- },
- createSprite: function() {
- var f = this,
- a = f.getSurface(),
- e = f.getItemInstancing(),
- d = a.add(f.getDefaultSpriteConfig()),
- b = f.getMarker(),
- g, c;
- d.setAttributes(f.getStyle());
- d.setSeries(f);
- if (e) {
- d.itemsMarker = f.createItemInstancingSprite(d, e)
- }
- if (d.bindMarker) {
- if (b) {
- g = new Ext.chart.Markers();
- c = Ext.Object.merge({}, b);
- if (f.getHighlight()) {
- c.highlight = f.getHighlight();
- c.modifiers = ["highlight"]
- }
- g.setTemplate(c);
- g.getTemplate().fx.setCustomDurations({
- translationX: 0,
- translationY: 0
- });
- d.dataMarker = g;
- d.bindMarker("markers", g);
- f.getOverlaySurface().add(g)
- }
- if (f.getLabel().getTemplate().getField()) {
- d.bindMarker("labels", f.getLabel())
- }
- }
- if (d.setStore) {
- d.setStore(f.getStore())
- }
- d.fx.on("animationstart", "onSpriteAnimationStart", f);
- d.fx.on("animationend", "onSpriteAnimationEnd", f);
- f.sprites.push(d);
- return d
- },
- getSprites: Ext.emptyFn,
- onDataChanged: function() {
- var d = this,
- c = d.getChart(),
- b = c && c.getStore(),
- a = d.getStore();
- if (a !== b) {
- d.processData()
- }
- },
- isXType: function(a) {
- return a === "series"
- },
- getItemId: function() {
- return this.getId()
- },
- applyThemeStyle: function(e, a) {
- var b = this,
- d, c;
- d = e && e.subStyle && e.subStyle.fillStyle;
- c = d && e.subStyle.strokeStyle;
- if (d && !c) {
- e.subStyle.strokeStyle = b.getStrokeColorsFromFillColors(d)
- }
- d = e && e.markerSubStyle && e.markerSubStyle.fillStyle;
- c = d && e.markerSubStyle.strokeStyle;
- if (d && !c) {
- e.markerSubStyle.strokeStyle = b.getStrokeColorsFromFillColors(d)
- }
- return Ext.apply(a || {}, e)
- },
- applyStyle: function(c, b) {
- var a = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + this.seriesType));
- if (a && a.def) {
- c = a.def.normalize(c)
- }
- return Ext.apply({}, c, b)
- },
- applySubStyle: function(b, c) {
- var a = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + this.seriesType));
- if (a && a.def) {
- b = a.def.batchedNormalize(b, true)
- }
- return Ext.merge({}, c, b)
- },
- applyMarker: function(c, a) {
- var d = (c && c.type) || (a && a.type) || "circle",
- b = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + d));
- if (b && b.def) {
- c = b.def.normalize(Ext.isObject(c) ? c : {}, true);
- c.type = d
- }
- return Ext.merge(a || {}, c)
- },
- applyMarkerSubStyle: function(c, a) {
- var d = (c && c.type) || (a && a.type) || "circle",
- b = Ext.ClassManager.get(Ext.ClassManager.getNameByAlias("sprite." + d));
- if (b && b.def) {
- c = b.def.batchedNormalize(c, true)
- }
- return Ext.merge(a || {}, c)
- },
- updateHidden: function(b) {
- var a = this;
- a.getColors();
- a.getSubStyle();
- a.setSubStyle({
- hidden: b
- });
- a.processData();
- a.doUpdateStyles();
- if (!Ext.isArray(b)) {
- a.updateLegendStore(b)
- }
- },
- updateLegendStore: function(f, b) {
- var e = this,
- d = e.getChart(),
- c = d.getLegendStore(),
- g = e.getId(),
- a;
- if (c) {
- if (arguments.length > 1) {
- a = c.findBy(function(h) {
- return h.get("series") === g && h.get("index") === b
- });
- if (a !== -1) {
- a = c.getAt(a)
- }
- } else {
- a = c.findRecord("series", g)
- }
- if (a && a.get("disabled") !== f) {
- a.set("disabled", f)
- }
- }
- },
- setHiddenByIndex: function(a, c) {
- var b = this;
- if (Ext.isArray(b.getHidden())) {
- b.getHidden()[a] = c;
- b.updateHidden(b.getHidden());
- b.updateLegendStore(c, a)
- } else {
- b.setHidden(c)
- }
- },
- getStrokeColorsFromFillColors: function(a) {
- var c = this,
- e = c.getUseDarkerStrokeColor(),
- b = (Ext.isNumber(e) ? e : c.darkerStrokeRatio),
- d;
- if (e) {
- d = Ext.Array.map(a, function(f) {
- f = Ext.isString(f) ? f : f.stops[0].color;
- f = Ext.draw.Color.fromString(f);
- return f.createDarker(b).toString()
- })
- } else {
- d = Ext.Array.clone(a)
- }
- return d
- },
- updateThemeColors: function(b) {
- var c = this,
- d = c.getThemeStyle(),
- a = Ext.Array.clone(b),
- f = c.getStrokeColorsFromFillColors(b),
- e = {
- fillStyle: a,
- strokeStyle: f
- };
- d.subStyle = Ext.apply(d.subStyle || {}, e);
- d.markerSubStyle = Ext.apply(d.markerSubStyle || {}, e);
- c.doUpdateStyles()
- },
- themeOnlyIfConfigured: {},
- updateTheme: function(d) {
- var h = this,
- a = d.getSeries(),
- n = h.getInitialConfig(),
- c = h.defaultConfig,
- f = h.getConfigurator().configs,
- j = a.defaults,
- k = a[h.type],
- g = h.themeOnlyIfConfigured,
- l, i, o, b, m, e;
- a = Ext.merge({}, j, k);
- for (l in a) {
- i = a[l];
- e = f[l];
- if (i !== null && i !== undefined && e) {
- m = n[l];
- o = Ext.isObject(i);
- b = m === c[l];
- if (o) {
- if (b && g[l]) {
- continue
- }
- i = Ext.merge({}, i, m)
- }
- if (b || o) {
- h[e.names.set](i)
- }
- }
- }
- },
- updateChartColors: function(a) {
- var b = this;
- if (!b.getColors()) {
- b.updateThemeColors(a)
- }
- },
- updateColors: function(a) {
- this.updateThemeColors(a)
- },
- updateStyle: function() {
- this.doUpdateStyles()
- },
- updateSubStyle: function() {
- this.doUpdateStyles()
- },
- updateThemeStyle: function() {
- this.doUpdateStyles()
- },
- doUpdateStyles: function() {
- var g = this,
- h = g.sprites,
- d = g.getItemInstancing(),
- c = 0,
- f = h && h.length,
- a = g.getConfig("showMarkers", true),
- b = g.getMarker(),
- e;
- for (; c < f; c++) {
- e = g.getStyleByIndex(c);
- if (d) {
- h[c].itemsMarker.getTemplate().setAttributes(e)
- }
- h[c].setAttributes(e);
- if (b && h[c].dataMarker) {
- h[c].dataMarker.getTemplate().setAttributes(g.getMarkerStyleByIndex(c))
- }
- }
- },
- getStyleWithTheme: function() {
- var b = this,
- c = b.getThemeStyle(),
- d = (c && c.style) || {},
- a = Ext.applyIf(Ext.apply({}, b.getStyle()), d);
- return a
- },
- getSubStyleWithTheme: function() {
- var c = this,
- d = c.getThemeStyle(),
- a = (d && d.subStyle) || {},
- b = Ext.applyIf(Ext.apply({}, c.getSubStyle()), a);
- return b
- },
- getStyleByIndex: function(b) {
- var e = this,
- h = e.getThemeStyle(),
- d, g, c, f, a = {};
- d = e.getStyle();
- g = (h && h.style) || {};
- c = e.styleDataForIndex(e.getSubStyle(), b);
- f = e.styleDataForIndex((h && h.subStyle), b);
- Ext.apply(a, g);
- Ext.apply(a, f);
- Ext.apply(a, d);
- Ext.apply(a, c);
- return a
- },
- getMarkerStyleByIndex: function(d) {
- var g = this,
- c = g.getThemeStyle(),
- a, e, k, j, b, l, h, f, m = {};
- a = g.getStyle();
- e = (c && c.style) || {};
- k = g.styleDataForIndex(g.getSubStyle(), d);
- if (k.hasOwnProperty("hidden")) {
- k.hidden = k.hidden || !this.getConfig("showMarkers", true)
- }
- j = g.styleDataForIndex((c && c.subStyle), d);
- b = g.getMarker();
- l = (c && c.marker) || {};
- h = g.getMarkerSubStyle();
- f = g.styleDataForIndex((c && c.markerSubStyle), d);
- Ext.apply(m, e);
- Ext.apply(m, j);
- Ext.apply(m, l);
- Ext.apply(m, f);
- Ext.apply(m, a);
- Ext.apply(m, k);
- Ext.apply(m, b);
- Ext.apply(m, h);
- return m
- },
- styleDataForIndex: function(d, c) {
- var e, b, a = {};
- if (d) {
- for (b in d) {
- e = d[b];
- if (Ext.isArray(e)) {
- a[b] = e[c % e.length]
- } else {
- a[b] = e
- }
- }
- }
- return a
- },
- getItemForPoint: Ext.emptyFn,
- getItemByIndex: function(a, e) {
- var d = this,
- f = d.getSprites(),
- b = f && f[0],
- c;
- if (!b) {
- return
- }
- if (e === undefined && b.isMarkerHolder) {
- e = d.getItemInstancing() ? "items" : "markers"
- } else {
- if (!e || e === "" || e === "sprites") {
- b = f[a]
- }
- }
- if (b) {
- c = {
- series: d,
- category: e,
- index: a,
- record: d.getStore().getData().items[a],
- field: d.getYField(),
- sprite: b
- };
- return c
- }
- },
- onSpriteAnimationStart: function(a) {
- this.fireEvent("animationstart", this, a)
- },
- onSpriteAnimationEnd: function(a) {
- this.fireEvent("animationend", this, a)
- },
- resolveListenerScope: function(e) {
- var d = this,
- a = Ext._namedScopes[e],
- c = d.getChart(),
- b;
- if (!a) {
- b = c ? c.resolveListenerScope(e, false) : (e || d)
- } else {
- if (a.isThis) {
- b = d
- } else {
- if (a.isController) {
- b = c ? c.resolveListenerScope(e, false) : d
- } else {
- if (a.isSelf) {
- b = c ? c.resolveListenerScope(e, false) : d;
- if (b === c && !c.getInheritedConfig("defaultListenerScope")) {
- b = d
- }
- }
- }
- }
- }
- return b
- },
- provideLegendInfo: function(a) {
- a.push({
- name: this.getTitle() || this.getId(),
- mark: "black",
- disabled: this.getHidden(),
- series: this.getId(),
- index: 0
- })
- },
- clearSprites: function() {
- var d = this.sprites,
- b, a, c;
- for (a = 0, c = d.length; a < c; a++) {
- b = d[a];
- if (b && b.isSprite) {
- b.destroy()
- }
- }
- this.sprites = []
- },
- destroy: function() {
- var b = this,
- a = b._store,
- c = b.getConfig("tooltip", true);
- if (a && a.getAutoDestroy()) {
- Ext.destroy(a)
- }
- b.setChart(null);
- b.clearListeners();
- if (c) {
- Ext.destroy(c);
- clearTimeout(b.tooltipTimeout)
- }
- b.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.Abstract", {
- xtype: "interaction",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- gestures: {
- tap: "onGesture"
- },
- chart: null,
- enabled: true
- },
- throttleGap: 0,
- stopAnimationBeforeSync: false,
- constructor: function(a) {
- var b = this,
- c;
- a = a || {};
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.mixins.observable.constructor.call(b, a)
- },
- initialize: Ext.emptyFn,
- updateChart: function(c, a) {
- var b = this;
- if (a === c) {
- return
- }
- if (a) {
- a.unregister(b);
- b.removeChartListener(a)
- }
- if (c) {
- c.register(b);
- b.addChartListener()
- }
- },
- updateEnabled: function(a) {
- var c = this,
- b = c.getChart();
- if (b) {
- if (a) {
- c.addChartListener()
- } else {
- c.removeChartListener(b)
- }
- }
- },
- onGesture: Ext.emptyFn,
- getItemForEvent: function(d) {
- var b = this,
- a = b.getChart(),
- c = a.getEventXY(d);
- return a.getItemForPoint(c[0], c[1])
- },
- getItemsForEvent: function(d) {
- var b = this,
- a = b.getChart(),
- c = a.getEventXY(d);
- return a.getItemsForPoint(c[0], c[1])
- },
- addChartListener: function() {
- var c = this,
- b = c.getChart(),
- e = c.getGestures(),
- a;
- if (!c.getEnabled()) {
- return
- }
-
- function d(f, g) {
- b.addElementListener(f, c.listeners[f] = function(j) {
- var i = c.getLocks(),
- h;
- if (c.getEnabled() && (!(f in i) || i[f] === c)) {
- h = (Ext.isFunction(g) ? g : c[g]).apply(this, arguments);
- if (h === false && j && j.stopPropagation) {
- j.stopPropagation()
- }
- return h
- }
- }, c)
- }
- c.listeners = c.listeners || {};
- for (a in e) {
- d(a, e[a])
- }
- },
- removeChartListener: function(c) {
- var d = this,
- e = d.getGestures(),
- b;
-
- function a(f) {
- var g = d.listeners[f];
- if (g) {
- c.removeElementListener(f, g);
- delete d.listeners[f]
- }
- }
- if (d.listeners) {
- for (b in e) {
- a(b)
- }
- }
- },
- lockEvents: function() {
- var d = this,
- c = d.getLocks(),
- a = Array.prototype.slice.call(arguments),
- b = a.length;
- while (b--) {
- c[a[b]] = d
- }
- },
- unlockEvents: function() {
- var c = this.getLocks(),
- a = Array.prototype.slice.call(arguments),
- b = a.length;
- while (b--) {
- delete c[a[b]]
- }
- },
- getLocks: function() {
- var a = this.getChart();
- return a.lockedEvents || (a.lockedEvents = {})
- },
- isMultiTouch: function() {
- if (Ext.browser.is.IE10) {
- return true
- }
- return !Ext.os.is.Desktop
- },
- initializeDefaults: Ext.emptyFn,
- doSync: function() {
- var b = this,
- a = b.getChart();
- if (b.syncTimer) {
- clearTimeout(b.syncTimer);
- b.syncTimer = null
- }
- if (b.stopAnimationBeforeSync) {
- a.animationSuspendCount++
- }
- a.redraw();
- if (b.stopAnimationBeforeSync) {
- a.animationSuspendCount--
- }
- b.syncThrottle = Date.now() + b.throttleGap
- },
- sync: function() {
- var a = this;
- if (a.throttleGap && Ext.frameStartTime < a.syncThrottle) {
- if (a.syncTimer) {
- return
- }
- a.syncTimer = Ext.defer(function() {
- a.doSync()
- }, a.throttleGap)
- } else {
- a.doSync()
- }
- },
- getItemId: function() {
- return this.getId()
- },
- isXType: function(a) {
- return a === "interaction"
- },
- destroy: function() {
- var a = this;
- a.setChart(null);
- delete a.listeners;
- a.callParent()
- }
-}, function() {
- if (Ext.os.is.Android4) {
- this.prototype.throttleGap = 40
- }
-});
-Ext.define("Ext.chart.MarkerHolder", {
- extend: "Ext.Mixin",
- mixinConfig: {
- id: "markerHolder",
- after: {
- constructor: "constructor",
- preRender: "preRender"
- },
- before: {
- destroy: "destroy"
- }
- },
- isMarkerHolder: true,
- surfaceMatrix: null,
- inverseSurfaceMatrix: null,
- deprecated: {
- 6: {
- methods: {
- getBoundMarker: {
- message: "Please use the 'getMarker' method instead.",
- fn: function(b) {
- var a = this.boundMarkers[b];
- return a ? [a] : a
- }
- }
- }
- }
- },
- constructor: function() {
- this.boundMarkers = {};
- this.cleanRedraw = false
- },
- bindMarker: function(b, a) {
- var c = this,
- d = c.boundMarkers;
- if (a && a.isMarkers) {
- c.releaseMarker(b);
- d[b] = a;
- a.on("destroy", c.onMarkerDestroy, c)
- }
- },
- onMarkerDestroy: function(a) {
- this.releaseMarker(a)
- },
- releaseMarker: function(a) {
- var c = this.boundMarkers,
- b;
- if (a && a.isMarkers) {
- for (b in c) {
- if (c[b] === a) {
- delete c[b];
- break
- }
- }
- } else {
- b = a;
- a = c[b];
- delete c[b]
- }
- return a || null
- },
- getMarker: function(a) {
- return this.boundMarkers[a] || null
- },
- preRender: function() {
- var f = this,
- g = f.getId(),
- d = f.boundMarkers,
- e = f.getParent(),
- c, a, b;
- if (f.surfaceMatrix) {
- b = f.surfaceMatrix.set(1, 0, 0, 1, 0, 0)
- } else {
- b = f.surfaceMatrix = new Ext.draw.Matrix()
- }
- f.cleanRedraw = !f.attr.dirty;
- if (!f.cleanRedraw) {
- for (c in d) {
- a = d[c];
- if (a) {
- a.clear(g)
- }
- }
- }
- while (e && e.attr && e.attr.matrix) {
- b.prependMatrix(e.attr.matrix);
- e = e.getParent()
- }
- b.prependMatrix(e.matrix);
- f.surfaceMatrix = b;
- f.inverseSurfaceMatrix = b.inverse(f.inverseSurfaceMatrix)
- },
- putMarker: function(d, a, c, g, e) {
- var b = this.boundMarkers[d],
- f = this.getId();
- if (b) {
- b.putMarkerFor(f, a, c, g, e)
- }
- },
- getMarkerBBox: function(c, b, d) {
- var a = this.boundMarkers[c],
- e = this.getId();
- if (a) {
- return a.getMarkerBBoxFor(e, b, d)
- }
- },
- destroy: function() {
- var c = this.boundMarkers,
- b, a;
- for (b in c) {
- a = c[b];
- a.destroy()
- }
- }
-});
-Ext.define("Ext.chart.axis.sprite.Axis", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.axis",
- type: "axis",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- requires: ["Ext.draw.sprite.Text"],
- inheritableStatics: {
- def: {
- processors: {
- grid: "bool",
- axisLine: "bool",
- minorTicks: "bool",
- minorTickSize: "number",
- majorTicks: "bool",
- majorTickSize: "number",
- length: "number",
- startGap: "number",
- endGap: "number",
- dataMin: "number",
- dataMax: "number",
- visibleMin: "number",
- visibleMax: "number",
- position: "enums(left,right,top,bottom,angular,radial,gauge)",
- minStepSize: "number",
- estStepSize: "number",
- titleOffset: "number",
- textPadding: "number",
- min: "number",
- max: "number",
- centerX: "number",
- centerY: "number",
- radius: "number",
- totalAngle: "number",
- baseRotation: "number",
- data: "default",
- enlargeEstStepSizeByText: "bool"
- },
- defaults: {
- grid: false,
- axisLine: true,
- minorTicks: false,
- minorTickSize: 3,
- majorTicks: true,
- majorTickSize: 5,
- length: 0,
- startGap: 0,
- endGap: 0,
- visibleMin: 0,
- visibleMax: 1,
- dataMin: 0,
- dataMax: 1,
- position: "",
- minStepSize: 0,
- estStepSize: 20,
- min: 0,
- max: 1,
- centerX: 0,
- centerY: 0,
- radius: 1,
- baseRotation: 0,
- data: null,
- titleOffset: 0,
- textPadding: 0,
- scalingCenterY: 0,
- scalingCenterX: 0,
- strokeStyle: "black",
- enlargeEstStepSizeByText: false
- },
- triggers: {
- minorTickSize: "bbox",
- majorTickSize: "bbox",
- position: "bbox,layout",
- axisLine: "bbox,layout",
- min: "layout",
- max: "layout",
- length: "layout",
- minStepSize: "layout",
- estStepSize: "layout",
- data: "layout",
- dataMin: "layout",
- dataMax: "layout",
- visibleMin: "layout",
- visibleMax: "layout",
- enlargeEstStepSizeByText: "layout"
- },
- updaters: {
- layout: "layoutUpdater"
- }
- }
- },
- config: {
- label: null,
- layout: null,
- segmenter: null,
- renderer: null,
- layoutContext: null,
- axis: null
- },
- thickness: 0,
- stepSize: 0,
- getBBox: function() {
- return null
- },
- defaultRenderer: function(a) {
- return this.segmenter.renderer(a, this)
- },
- layoutUpdater: function() {
- var h = this,
- f = h.getAxis().getChart();
- if (f.isInitializing) {
- return
- }
- var e = h.attr,
- d = h.getLayout(),
- g = f.getInherited().rtl,
- b = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMin,
- i = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMax,
- c = e.position,
- a = {
- attr: e,
- segmenter: h.getSegmenter(),
- renderer: h.defaultRenderer
- };
- if (c === "left" || c === "right") {
- e.translationX = 0;
- e.translationY = i * e.length / (i - b);
- e.scalingX = 1;
- e.scalingY = -e.length / (i - b);
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- } else {
- if (c === "top" || c === "bottom") {
- if (g) {
- e.translationX = e.length + b * e.length / (i - b) + 1
- } else {
- e.translationX = -b * e.length / (i - b)
- }
- e.translationY = 0;
- e.scalingX = (g ? -1 : 1) * e.length / (i - b);
- e.scalingY = 1;
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- }
- }
- if (d) {
- d.calculateLayout(a);
- h.setLayoutContext(a)
- }
- },
- iterate: function(e, j) {
- var c, g, a, b, h, d, k = Ext.Array.some,
- m = Math.abs,
- f;
- if (e.getLabel) {
- if (e.min < e.from) {
- j.call(this, e.min, e.getLabel(e.min), -1, e)
- }
- for (c = 0; c <= e.steps; c++) {
- j.call(this, e.get(c), e.getLabel(c), c, e)
- }
- if (e.max > e.to) {
- j.call(this, e.max, e.getLabel(e.max), e.steps + 1, e)
- }
- } else {
- b = this.getAxis();
- h = b.floatingAxes;
- d = [];
- f = (e.to - e.from) / (e.steps + 1);
- if (b.getFloating()) {
- for (a in h) {
- d.push(h[a])
- }
- }
-
- function l(i) {
- return !d.length || k(d, function(n) {
- return m(n - i) > f
- })
- }
- if (e.min < e.from && l(e.min)) {
- j.call(this, e.min, e.min, -1, e)
- }
- for (c = 0; c <= e.steps; c++) {
- g = e.get(c);
- if (l(g)) {
- j.call(this, g, g, c, e)
- }
- }
- if (e.max > e.to && l(e.max)) {
- j.call(this, e.max, e.max, e.steps + 1, e)
- }
- }
- },
- renderTicks: function(l, m, s, p) {
- var v = this,
- k = v.attr,
- u = k.position,
- n = k.matrix,
- e = 0.5 * k.lineWidth,
- f = n.getXX(),
- i = n.getDX(),
- j = n.getYY(),
- h = n.getDY(),
- o = s.majorTicks,
- d = k.majorTickSize,
- a = s.minorTicks,
- r = k.minorTickSize;
- if (o) {
- switch (u) {
- case "right":
- function q(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * j + h) + e;
- m.moveTo(0, x);
- m.lineTo(w, x)
- }
- }
- v.iterate(o, q(d));
- a && v.iterate(a, q(r));
- break;
- case "left":
- function t(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * j + h) + e;
- m.moveTo(p[2] - w, x);
- m.lineTo(p[2], x)
- }
- }
- v.iterate(o, t(d));
- a && v.iterate(a, t(r));
- break;
- case "bottom":
- function c(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * f + i) - e;
- m.moveTo(x, 0);
- m.lineTo(x, w)
- }
- }
- v.iterate(o, c(d));
- a && v.iterate(a, c(r));
- break;
- case "top":
- function b(w) {
- return function(x, z, y) {
- x = l.roundPixel(x * f + i) - e;
- m.moveTo(x, p[3]);
- m.lineTo(x, p[3] - w)
- }
- }
- v.iterate(o, b(d));
- a && v.iterate(a, b(r));
- break;
- case "angular":
- v.iterate(o, function(w, y, x) {
- w = w / (k.max + 1) * Math.PI * 2 + k.baseRotation;
- m.moveTo(k.centerX + (k.length) * Math.cos(w), k.centerY + (k.length) * Math.sin(w));
- m.lineTo(k.centerX + (k.length + d) * Math.cos(w), k.centerY + (k.length + d) * Math.sin(w))
- });
- break;
- case "gauge":
- var g = v.getGaugeAngles();
- v.iterate(o, function(w, y, x) {
- w = (w - k.min) / (k.max - k.min + 1) * k.totalAngle - k.totalAngle + g.start;
- m.moveTo(k.centerX + (k.length) * Math.cos(w), k.centerY + (k.length) * Math.sin(w));
- m.lineTo(k.centerX + (k.length + d) * Math.cos(w), k.centerY + (k.length + d) * Math.sin(w))
- });
- break
- }
- }
- },
- renderLabels: function(E, q, D, K) {
- var o = this,
- k = o.attr,
- i = 0.5 * k.lineWidth,
- u = k.position,
- y = k.matrix,
- A = k.textPadding,
- x = y.getXX(),
- d = y.getDX(),
- g = y.getYY(),
- c = y.getDY(),
- n = 0,
- I = D.majorTicks,
- G = Math.max(k.majorTickSize, k.minorTickSize) + k.lineWidth,
- f = Ext.draw.Draw.isBBoxIntersect,
- F = o.getLabel(),
- J, s, r = null,
- w = 0,
- b = 0,
- m = D.segmenter,
- B = o.getRenderer(),
- t = o.getAxis(),
- z = t.getTitle(),
- a = z && z.attr.text !== "" && z.getBBox(),
- l, h = null,
- p, C, v, e, H;
- if (I && F && !F.attr.hidden) {
- J = F.attr.font;
- if (q.font !== J) {
- q.font = J
- }
- F.setAttributes({
- translationX: 0,
- translationY: 0
- }, true);
- F.applyTransformations();
- l = F.attr.inverseMatrix.elements.slice(0);
- switch (u) {
- case "left":
- e = a ? a.x + a.width : 0;
- switch (F.attr.textAlign) {
- case "start":
- H = E.roundPixel(e + d) - i;
- break;
- case "end":
- H = E.roundPixel(K[2] - G + d) - i;
- break;
- default:
- H = E.roundPixel(e + (K[2] - e - G) / 2 + d) - i
- }
- F.setAttributes({
- translationX: H
- }, true);
- break;
- case "right":
- e = a ? K[2] - a.x : 0;
- switch (F.attr.textAlign) {
- case "start":
- H = E.roundPixel(G + d) + i;
- break;
- case "end":
- H = E.roundPixel(K[2] - e + d) + i;
- break;
- default:
- H = E.roundPixel(G + (K[2] - G - e) / 2 + d) + i
- }
- F.setAttributes({
- translationX: H
- }, true);
- break;
- case "top":
- e = a ? a.y + a.height : 0;
- F.setAttributes({
- translationY: E.roundPixel(e + (K[3] - e - G) / 2) - i
- }, true);
- break;
- case "bottom":
- e = a ? K[3] - a.y : 0;
- F.setAttributes({
- translationY: E.roundPixel(G + (K[3] - G - e) / 2) + i
- }, true);
- break;
- case "radial":
- F.setAttributes({
- translationX: k.centerX
- }, true);
- break;
- case "angular":
- F.setAttributes({
- translationY: k.centerY
- }, true);
- break;
- case "gauge":
- F.setAttributes({
- translationY: k.centerY
- }, true);
- break
- }
- if (u === "left" || u === "right") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- F.setAttributes({
- text: String(v),
- translationY: E.roundPixel(L * g + c)
- }, true);
- F.applyTransformations();
- n = Math.max(n, F.getBBox().width + G);
- if (n <= o.thickness) {
- C = Ext.draw.Matrix.fly(F.attr.matrix.elements.slice(0));
- p = C.prepend.apply(C, l).transformBBox(F.getBBox(true));
- if (h && !f(p, h, A)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.height;
- b++
- }
- })
- } else {
- if (u === "top" || u === "bottom") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- F.setAttributes({
- text: String(v),
- translationX: E.roundPixel(L * x + d)
- }, true);
- F.applyTransformations();
- n = Math.max(n, F.getBBox().height + G);
- if (n <= o.thickness) {
- C = Ext.draw.Matrix.fly(F.attr.matrix.elements.slice(0));
- p = C.prepend.apply(C, l).transformBBox(F.getBBox(true));
- if (h && !f(p, h, A)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "radial") {
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- if (typeof v !== "undefined") {
- F.setAttributes({
- text: String(v),
- translationX: k.centerX - E.roundPixel(L) / k.max * k.length * Math.cos(k.baseRotation + Math.PI / 2),
- translationY: k.centerY - E.roundPixel(L) / k.max * k.length * Math.sin(k.baseRotation + Math.PI / 2)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "angular") {
- s = k.majorTickSize + k.lineWidth * 0.5 + (parseInt(F.attr.fontSize, 10) || 10) / 2;
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- n = Math.max(n, Math.max(k.majorTickSize, k.minorTickSize) + (k.lineCap !== "butt" ? k.lineWidth * 0.5 : 0));
- if (typeof v !== "undefined") {
- var O = L / (k.max + 1) * Math.PI * 2 + k.baseRotation;
- F.setAttributes({
- text: String(v),
- translationX: k.centerX + (k.length + s) * Math.cos(O),
- translationY: k.centerY + (k.length + s) * Math.sin(O)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- } else {
- if (u === "gauge") {
- var j = o.getGaugeAngles();
- o.iterate(I, function(L, N, M) {
- if (N === undefined) {
- return
- }
- if (B) {
- v = Ext.callback(B, null, [t, N, D, r], 0, t)
- } else {
- v = m.renderer(N, D, r)
- }
- r = N;
- if (typeof v !== "undefined") {
- var O = (L - k.min) / (k.max - k.min + 1) * k.totalAngle - k.totalAngle + j.start;
- F.setAttributes({
- text: String(v),
- translationX: k.centerX + (k.length + 10) * Math.cos(O),
- translationY: k.centerY + (k.length + 10) * Math.sin(O)
- }, true);
- F.applyTransformations();
- p = F.attr.matrix.transformBBox(F.getBBox(true));
- if (h && !f(p, h)) {
- return
- }
- E.renderSprite(F);
- h = p;
- w += p.width;
- b++
- }
- })
- }
- }
- }
- }
- }
- if (k.enlargeEstStepSizeByText && b) {
- w /= b;
- w += G;
- w *= 2;
- if (k.estStepSize < w) {
- k.estStepSize = w
- }
- }
- if (Math.abs(o.thickness - (n)) > 1) {
- o.thickness = n;
- k.bbox.plain.dirty = true;
- k.bbox.transform.dirty = true;
- o.doThicknessChanged();
- return false
- }
- }
- },
- renderAxisLine: function(a, i, e, c) {
- var h = this,
- g = h.attr,
- b = g.lineWidth * 0.5,
- j = g.position,
- d, f;
- if (g.axisLine && g.length) {
- switch (j) {
- case "left":
- d = a.roundPixel(c[2]) - b;
- i.moveTo(d, -g.endGap);
- i.lineTo(d, g.length + g.startGap + 1);
- break;
- case "right":
- i.moveTo(b, -g.endGap);
- i.lineTo(b, g.length + g.startGap + 1);
- break;
- case "bottom":
- i.moveTo(-g.startGap, b);
- i.lineTo(g.length + g.endGap, b);
- break;
- case "top":
- d = a.roundPixel(c[3]) - b;
- i.moveTo(-g.startGap, d);
- i.lineTo(g.length + g.endGap, d);
- break;
- case "angular":
- i.moveTo(g.centerX + g.length, g.centerY);
- i.arc(g.centerX, g.centerY, g.length, 0, Math.PI * 2, true);
- break;
- case "gauge":
- f = h.getGaugeAngles();
- i.moveTo(g.centerX + Math.cos(f.start) * g.length, g.centerY + Math.sin(f.start) * g.length);
- i.arc(g.centerX, g.centerY, g.length, f.start, f.end, true);
- break
- }
- }
- },
- getGaugeAngles: function() {
- var a = this,
- c = a.attr.totalAngle,
- b;
- if (c <= Math.PI) {
- b = (Math.PI - c) * 0.5
- } else {
- b = -(Math.PI * 2 - c) * 0.5
- }
- b = Math.PI * 2 - b;
- return {
- start: b,
- end: b - c
- }
- },
- renderGridLines: function(m, n, s, r) {
- var t = this,
- b = t.getAxis(),
- l = t.attr,
- p = l.matrix,
- d = l.startGap,
- a = l.endGap,
- c = p.getXX(),
- k = p.getYY(),
- h = p.getDX(),
- g = p.getDY(),
- u = l.position,
- f = b.getGridAlignment(),
- q = s.majorTicks,
- e, o, i;
- if (l.grid) {
- if (q) {
- if (u === "left" || u === "right") {
- i = l.min * k + g + a + d;
- t.iterate(q, function(j, w, v) {
- e = j * k + g + a;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- y: e,
- height: i - e
- }, o = v, true);
- i = e
- });
- o++;
- e = 0;
- t.putMarker(f + "-" + (o % 2 ? "odd" : "even"), {
- y: e,
- height: i - e
- }, o, true)
- } else {
- if (u === "top" || u === "bottom") {
- i = l.min * c + h + d;
- if (d) {
- t.putMarker(f + "-even", {
- x: 0,
- width: i
- }, -1, true)
- }
- t.iterate(q, function(j, w, v) {
- e = j * c + h + d;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- x: e,
- width: i - e
- }, o = v, true);
- i = e
- });
- o++;
- e = l.length + l.startGap + l.endGap;
- t.putMarker(f + "-" + (o % 2 ? "odd" : "even"), {
- x: e,
- width: i - e
- }, o, true)
- } else {
- if (u === "radial") {
- t.iterate(q, function(j, w, v) {
- if (!j) {
- return
- }
- e = j / l.max * l.length;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- scalingX: e,
- scalingY: e
- }, v, true);
- i = e
- })
- } else {
- if (u === "angular") {
- t.iterate(q, function(j, w, v) {
- if (!l.length) {
- return
- }
- e = j / (l.max + 1) * Math.PI * 2 + l.baseRotation;
- t.putMarker(f + "-" + (v % 2 ? "odd" : "even"), {
- rotationRads: e,
- rotationCenterX: 0,
- rotationCenterY: 0,
- scalingX: l.length,
- scalingY: l.length
- }, v, true);
- i = e
- })
- }
- }
- }
- }
- }
- }
- },
- renderLimits: function(o) {
- var t = this,
- a = t.getAxis(),
- h = a.getChart(),
- p = h.getInnerPadding(),
- d = Ext.Array.from(a.getLimits());
- if (!d.length) {
- return
- }
- var r = a.limits.surface.getRect(),
- m = t.attr,
- n = m.matrix,
- u = m.position,
- k = Ext.Object.chain,
- v = a.limits.titles,
- c, j, b, s, l, q, f, g, e;
- v.instances = [];
- v.position = 0;
- if (u === "left" || u === "right") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l * n.getYY() + n.getDY();
- s.line.y = l + p.top;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("horizontal-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- j = s.line.title.position || (u === "left" ? "start" : "end");
- switch (j) {
- case "start":
- g = 10;
- break;
- case "end":
- g = r[2] - 10;
- break;
- case "middle":
- g = r[2] / 2;
- break
- }
- v.setAttributesFor(v.position - 1, {
- x: g,
- y: s.line.y - c.height / 2,
- textAlign: j,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "top" || u === "bottom") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l * n.getXX() + n.getDX();
- s.line.x = l + p.left;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("vertical-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- j = s.line.title.position || (u === "top" ? "end" : "start");
- switch (j) {
- case "start":
- e = r[3] - c.width / 2 - 10;
- break;
- case "end":
- e = c.width / 2 + 10;
- break;
- case "middle":
- e = r[3] / 2;
- break
- }
- v.setAttributesFor(v.position - 1, {
- x: s.line.x + c.height / 2,
- y: e,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle,
- rotationRads: Math.PI / 2
- })
- }
- }
- } else {
- if (u === "radial") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- if (l > m.max) {
- continue
- }
- l = l / m.max * m.length;
- s.line.cx = m.centerX;
- s.line.cy = m.centerY;
- s.line.scalingX = l;
- s.line.scalingY = l;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("circular-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- v.setAttributesFor(v.position - 1, {
- x: m.centerX,
- y: m.centerY - l - c.height / 2,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "angular") {
- for (q = 0, f = d.length; q < f; q++) {
- s = k(d[q]);
- !s.line && (s.line = {});
- l = Ext.isString(s.value) ? a.getCoordFor(s.value) : s.value;
- l = l / (m.max + 1) * Math.PI * 2 + m.baseRotation;
- s.line.translationX = m.centerX;
- s.line.translationY = m.centerY;
- s.line.rotationRads = l;
- s.line.rotationCenterX = 0;
- s.line.rotationCenterY = 0;
- s.line.scalingX = m.length;
- s.line.scalingY = m.length;
- s.line.strokeStyle = s.line.strokeStyle || m.strokeStyle;
- t.putMarker("radial-limit-lines", s.line, q, true);
- if (s.line.title) {
- v.createInstance(s.line.title);
- c = v.getBBoxFor(v.position - 1);
- b = ((l > -0.5 * Math.PI && l < 0.5 * Math.PI) || (l > 1.5 * Math.PI && l < 2 * Math.PI)) ? 1 : -1;
- v.setAttributesFor(v.position - 1, {
- x: m.centerX + 0.5 * m.length * Math.cos(l) + b * c.height / 2 * Math.sin(l),
- y: m.centerY + 0.5 * m.length * Math.sin(l) - b * c.height / 2 * Math.cos(l),
- rotationRads: b === 1 ? l : l - Math.PI,
- fillStyle: s.line.title.fillStyle || s.line.strokeStyle
- })
- }
- }
- } else {
- if (u === "gauge") {}
- }
- }
- }
- }
- },
- doThicknessChanged: function() {
- var a = this.getAxis();
- if (a) {
- a.onThicknessChanged()
- }
- },
- render: function(a, c, d) {
- var e = this,
- b = e.getLayoutContext();
- if (b) {
- if (false === e.renderLabels(a, c, b, d)) {
- return false
- }
- c.beginPath();
- e.renderTicks(a, c, b, d);
- e.renderAxisLine(a, c, b, d);
- e.renderGridLines(a, c, b, d);
- e.renderLimits(d);
- c.stroke()
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Segmenter", {
- config: {
- axis: null
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- renderer: function(b, a) {
- return String(b)
- },
- from: function(a) {
- return a
- },
- diff: Ext.emptyFn,
- align: Ext.emptyFn,
- add: Ext.emptyFn,
- preferredStep: Ext.emptyFn
-});
-Ext.define("Ext.chart.axis.segmenter.Names", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.names",
- renderer: function(b, a) {
- return b
- },
- diff: function(b, a, c) {
- return Math.floor(a - b)
- },
- align: function(c, b, a) {
- return Math.floor(c)
- },
- add: function(c, b, a) {
- return c + b
- },
- preferredStep: function(c, a, b, d) {
- return {
- unit: 1,
- step: 1
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Numeric", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.numeric",
- isNumeric: true,
- renderer: function(b, a) {
- return b.toFixed(Math.max(0, a.majorTicks.unit.fixes))
- },
- diff: function(b, a, c) {
- return Math.floor((a - b) / c.scale)
- },
- align: function(c, b, a) {
- return Math.floor(c / (a.scale * b)) * a.scale * b
- },
- add: function(c, b, a) {
- return c + b * a.scale
- },
- preferredStep: function(c, b) {
- var a = Math.floor(Math.log(b) * Math.LOG10E),
- d = Math.pow(10, a);
- b /= d;
- if (b < 2) {
- b = 2
- } else {
- if (b < 5) {
- b = 5
- } else {
- if (b < 10) {
- b = 10;
- a++
- }
- }
- }
- return {
- unit: {
- fixes: -a,
- scale: d
- },
- step: b
- }
- },
- exactStep: function(c, b) {
- var a = Math.floor(Math.log(b) * Math.LOG10E),
- d = Math.pow(10, a);
- return {
- unit: {
- fixes: -a + (b % d === 0 ? 0 : 1),
- scale: 1
- },
- step: b
- }
- },
- adjustByMajorUnit: function(e, g, c) {
- var d = c[0],
- b = c[1],
- a = e * g,
- f = d % a;
- if (f !== 0) {
- c[0] = d - f + (d < 0 ? -a : 0)
- }
- f = b % a;
- if (f !== 0) {
- c[1] = b - f + (b > 0 ? a : 0)
- }
- }
-});
-Ext.define("Ext.chart.axis.segmenter.Time", {
- extend: "Ext.chart.axis.segmenter.Segmenter",
- alias: "segmenter.time",
- config: {
- step: null
- },
- renderer: function(c, b) {
- var a = Ext.Date;
- switch (b.majorTicks.unit) {
- case "y":
- return a.format(c, "Y");
- case "mo":
- return a.format(c, "Y-m");
- case "d":
- return a.format(c, "Y-m-d")
- }
- return a.format(c, "Y-m-d\nH:i:s")
- },
- from: function(a) {
- return new Date(a)
- },
- diff: function(b, a, c) {
- if (isFinite(b)) {
- b = new Date(b)
- }
- if (isFinite(a)) {
- a = new Date(a)
- }
- return Ext.Date.diff(b, a, c)
- },
- align: function(a, c, b) {
- if (b === "d" && c >= 7) {
- a = Ext.Date.align(a, "d", c);
- a.setDate(a.getDate() - a.getDay() + 1);
- return a
- } else {
- return Ext.Date.align(a, b, c)
- }
- },
- add: function(c, b, a) {
- return Ext.Date.add(new Date(c), a, b)
- },
- stepUnits: [
- [Ext.Date.YEAR, 1, 2, 5, 10, 20, 50, 100, 200, 500],
- [Ext.Date.MONTH, 1, 3, 6],
- [Ext.Date.DAY, 1, 7, 14],
- [Ext.Date.HOUR, 1, 6, 12],
- [Ext.Date.MINUTE, 1, 5, 15, 30],
- [Ext.Date.SECOND, 1, 5, 15, 30],
- [Ext.Date.MILLI, 1, 2, 5, 10, 20, 50, 100, 200, 500]
- ],
- preferredStep: function(b, e) {
- if (this.getStep()) {
- return this.getStep()
- }
- var f = new Date(+b),
- g = new Date(+b + Math.ceil(e)),
- d = this.stepUnits,
- l, k, h, c, a;
- for (c = 0; c < d.length; c++) {
- k = d[c][0];
- h = this.diff(f, g, k);
- if (h > 0) {
- for (a = 1; a < d[c].length; a++) {
- if (h <= d[c][a]) {
- l = {
- unit: k,
- step: d[c][a]
- };
- break
- }
- }
- if (!l) {
- c--;
- l = {
- unit: d[c][0],
- step: 1
- }
- }
- break
- }
- }
- if (!l) {
- l = {
- unit: Ext.Date.DAY,
- step: 1
- }
- }
- return l
- }
-});
-Ext.define("Ext.chart.axis.layout.Layout", {
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- config: {
- axis: null
- },
- constructor: function(a) {
- this.mixins.observable.constructor.call(this, a)
- },
- processData: function(b) {
- var e = this,
- c = e.getAxis(),
- f = c.getDirection(),
- g = c.boundSeries,
- a, d;
- if (b) {
- b["coordinate" + f]()
- } else {
- for (a = 0, d = g.length; a < d; a++) {
- g[a]["coordinate" + f]()
- }
- }
- },
- calculateMajorTicks: function(a) {
- var f = this,
- e = a.attr,
- d = e.max - e.min,
- i = d / Math.max(1, e.length) * (e.visibleMax - e.visibleMin),
- h = e.min + d * e.visibleMin,
- b = e.min + d * e.visibleMax,
- g = e.estStepSize * i,
- c = f.snapEnds(a, e.min, e.max, g);
- if (c) {
- f.trimByRange(a, c, h, b);
- a.majorTicks = c
- }
- },
- calculateMinorTicks: function(a) {
- if (this.snapMinorEnds) {
- a.minorTicks = this.snapMinorEnds(a)
- }
- },
- calculateLayout: function(b) {
- var c = this,
- a = b.attr;
- if (a.length === 0) {
- return null
- }
- if (a.majorTicks) {
- c.calculateMajorTicks(b);
- if (a.minorTicks) {
- c.calculateMinorTicks(b)
- }
- }
- },
- snapEnds: Ext.emptyFn,
- trimByRange: function(b, f, i, a) {
- var g = b.segmenter,
- j = f.unit,
- h = g.diff(f.from, i, j),
- d = g.diff(f.from, a, j),
- c = Math.max(0, Math.ceil(h / f.step)),
- e = Math.min(f.steps, Math.floor(d / f.step));
- if (e < f.steps) {
- f.to = g.add(f.from, e * f.step, j)
- }
- if (f.max > a) {
- f.max = f.to
- }
- if (f.from < i) {
- f.from = g.add(f.from, c * f.step, j);
- while (f.from < i) {
- c++;
- f.from = g.add(f.from, f.step, j)
- }
- }
- if (f.min < i) {
- f.min = f.from
- }
- f.steps = e - c
- }
-});
-Ext.define("Ext.chart.axis.layout.Discrete", {
- extend: "Ext.chart.axis.layout.Layout",
- alias: "axisLayout.discrete",
- isDiscrete: true,
- processData: function() {
- var f = this,
- d = f.getAxis(),
- c = d.boundSeries,
- g = d.getDirection(),
- b, e, a;
- f.labels = [];
- f.labelMap = {};
- for (b = 0, e = c.length; b < e; b++) {
- a = c[b];
- if (a["get" + g + "Axis"]() === d) {
- a["coordinate" + g]()
- }
- }
- d.getSprites()[0].setAttributes({
- data: f.labels
- });
- f.fireEvent("datachange", f.labels)
- },
- calculateLayout: function(a) {
- a.data = this.labels;
- this.callParent([a])
- },
- calculateMajorTicks: function(a) {
- var g = this,
- f = a.attr,
- d = a.data,
- e = f.max - f.min,
- j = e / Math.max(1, f.length) * (f.visibleMax - f.visibleMin),
- i = f.min + e * f.visibleMin,
- b = f.min + e * f.visibleMax,
- h = f.estStepSize * j;
- var c = g.snapEnds(a, Math.max(0, f.min), Math.min(f.max, d.length - 1), h);
- if (c) {
- g.trimByRange(a, c, i, b);
- a.majorTicks = c
- }
- },
- snapEnds: function(e, d, a, b) {
- b = Math.ceil(b);
- var c = Math.floor((a - d) / b),
- f = e.data;
- return {
- min: d,
- max: a,
- from: d,
- to: c * b + d,
- step: b,
- steps: c,
- unit: 1,
- getLabel: function(g) {
- return f[this.from + this.step * g]
- },
- get: function(g) {
- return this.from + this.step * g
- }
- }
- },
- trimByRange: function(b, f, h, a) {
- var i = f.unit,
- g = Math.ceil((h - f.from) / i) * i,
- d = Math.floor((a - f.from) / i) * i,
- c = Math.max(0, Math.ceil(g / f.step)),
- e = Math.min(f.steps, Math.floor(d / f.step));
- if (e < f.steps) {
- f.to = e
- }
- if (f.max > a) {
- f.max = f.to
- }
- if (f.from < h && f.step > 0) {
- f.from = f.from + c * f.step * i;
- while (f.from < h) {
- c++;
- f.from += f.step * i
- }
- }
- if (f.min < h) {
- f.min = f.from
- }
- f.steps = e - c
- },
- getCoordFor: function(c, d, a, b) {
- this.labels.push(c);
- return this.labels.length - 1
- }
-});
-Ext.define("Ext.chart.axis.layout.CombineDuplicate", {
- extend: "Ext.chart.axis.layout.Discrete",
- alias: "axisLayout.combineDuplicate",
- getCoordFor: function(d, e, b, c) {
- if (!(d in this.labelMap)) {
- var a = this.labelMap[d] = this.labels.length;
- this.labels.push(d);
- return a
- }
- return this.labelMap[d]
- }
-});
-Ext.define("Ext.chart.axis.layout.Continuous", {
- extend: "Ext.chart.axis.layout.Layout",
- alias: "axisLayout.continuous",
- isContinuous: true,
- config: {
- adjustMinimumByMajorUnit: false,
- adjustMaximumByMajorUnit: false
- },
- getCoordFor: function(c, d, a, b) {
- return +c
- },
- snapEnds: function(a, d, i, h) {
- var f = a.segmenter,
- c = this.getAxis(),
- l = c.getMajorTickSteps(),
- e = l && f.exactStep ? f.exactStep(d, (i - d) / l) : f.preferredStep(d, h),
- k = e.unit,
- b = e.step,
- j = f.align(d, b, k),
- g = (l || f.diff(d, i, k)) + 1;
- return {
- min: f.from(d),
- max: f.from(i),
- from: j,
- to: f.add(j, g * b, k),
- step: b,
- steps: g,
- unit: k,
- get: function(m) {
- return f.add(this.from, this.step * m, k)
- }
- }
- },
- snapMinorEnds: function(a) {
- var e = a.majorTicks,
- m = this.getAxis().getMinorTickSteps(),
- f = a.segmenter,
- d = e.min,
- i = e.max,
- k = e.from,
- l = e.unit,
- b = e.step / m,
- n = b * l.scale,
- j = k - d,
- c = Math.floor(j / n),
- h = c + Math.floor((i - e.to) / n) + 1,
- g = e.steps * m + h;
- return {
- min: d,
- max: i,
- from: d + j % n,
- to: f.add(k, g * b, l),
- step: b,
- steps: g,
- unit: l,
- get: function(o) {
- return (o % m + c + 1 !== 0) ? f.add(this.from, this.step * o, l) : null
- }
- }
- }
-});
-Ext.define("Ext.chart.axis.Axis", {
- xtype: "axis",
- mixins: {
- observable: "Ext.mixin.Observable"
- },
- requires: ["Ext.chart.axis.sprite.Axis", "Ext.chart.axis.segmenter.*", "Ext.chart.axis.layout.*"],
- isAxis: true,
- config: {
- position: "bottom",
- fields: [],
- label: undefined,
- grid: false,
- limits: null,
- renderer: null,
- chart: null,
- style: null,
- margin: 0,
- titleMargin: 4,
- background: null,
- minimum: NaN,
- maximum: NaN,
- reconcileRange: false,
- minZoom: 1,
- maxZoom: 10000,
- layout: "continuous",
- segmenter: "numeric",
- hidden: false,
- majorTickSteps: 0,
- minorTickSteps: 0,
- adjustByMajorUnit: true,
- title: null,
- increment: 0.5,
- length: 0,
- center: null,
- radius: null,
- totalAngle: Math.PI,
- rotation: null,
- labelInSpan: null,
- visibleRange: [0, 1],
- needHighPrecision: false,
- linkedTo: null,
- floating: null
- },
- titleOffset: 0,
- spriteAnimationCount: 0,
- prevMin: 0,
- prevMax: 1,
- boundSeries: [],
- sprites: null,
- surface: null,
- range: null,
- xValues: [],
- yValues: [],
- masterAxis: null,
- applyRotation: function(b) {
- var a = Math.PI * 2;
- return (b % a + Math.PI) % a - Math.PI
- },
- updateRotation: function(b) {
- var c = this.getSprites(),
- a = this.getPosition();
- if (!this.getHidden() && a === "angular" && c[0]) {
- c[0].setAttributes({
- baseRotation: b
- })
- }
- },
- applyTitle: function(c, b) {
- var a;
- if (Ext.isString(c)) {
- c = {
- text: c
- }
- }
- if (!b) {
- b = Ext.create("sprite.text", c);
- if ((a = this.getSurface())) {
- a.add(b)
- }
- } else {
- b.setAttributes(c)
- }
- return b
- },
- applyFloating: function(b, a) {
- if (b === null) {
- b = {
- value: null,
- alongAxis: null
- }
- } else {
- if (Ext.isNumber(b)) {
- b = {
- value: b,
- alongAxis: null
- }
- }
- }
- if (Ext.isObject(b)) {
- if (a && a.alongAxis) {
- delete this.getChart().getAxis(a.alongAxis).floatingAxes[this.getId()]
- }
- return b
- }
- return a
- },
- constructor: function(a) {
- var b = this,
- c;
- b.sprites = [];
- b.labels = [];
- b.floatingAxes = {};
- a = a || {};
- if (a.position === "angular") {
- a.style = a.style || {};
- a.style.estStepSize = 1
- }
- if ("id" in a) {
- c = a.id
- } else {
- if ("id" in b.config) {
- c = b.config.id
- } else {
- c = b.getId()
- }
- }
- b.setId(c);
- b.mixins.observable.constructor.apply(b, arguments)
- },
- getAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "vertical";
- case "top":
- case "bottom":
- return "horizontal";
- case "radial":
- return "radial";
- case "angular":
- return "angular"
- }
- },
- getGridAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "horizontal";
- case "top":
- case "bottom":
- return "vertical";
- case "radial":
- return "circular";
- case "angular":
- return "radial"
- }
- },
- getSurface: function() {
- var e = this,
- d = e.getChart();
- if (d && !e.surface) {
- var b = e.surface = d.getSurface(e.getId(), "axis"),
- c = e.gridSurface = d.getSurface("main"),
- a = e.getSprites()[0],
- f = e.getGridAlignment();
- c.waitFor(b);
- e.getGrid();
- if (e.getLimits() && f) {
- f = f.replace("3d", "");
- e.limits = {
- surface: d.getSurface("overlay"),
- lines: new Ext.chart.Markers(),
- titles: new Ext.draw.sprite.Instancing()
- };
- e.limits.lines.setTemplate({
- xclass: "grid." + f
- });
- e.limits.lines.getTemplate().setAttributes({
- strokeStyle: "black"
- }, true);
- e.limits.surface.add(e.limits.lines);
- a.bindMarker(f + "-limit-lines", e.limits.lines);
- e.limitTitleTpl = new Ext.draw.sprite.Text();
- e.limits.titles.setTemplate(e.limitTitleTpl);
- e.limits.surface.add(e.limits.titles);
- d.on("redraw", e.renderLimits, e)
- }
- }
- return e.surface
- },
- applyGrid: function(a) {
- if (a === true) {
- return {}
- }
- return a
- },
- updateGrid: function(b) {
- var e = this,
- d = e.getChart();
- if (!d) {
- e.on({
- chartattached: Ext.bind(e.updateGrid, e, [b]),
- single: true
- });
- return
- }
- var c = e.gridSurface,
- a = e.getSprites()[0],
- f = e.getGridAlignment(),
- g;
- if (b) {
- g = e.gridSpriteEven;
- if (!g) {
- g = e.gridSpriteEven = new Ext.chart.Markers();
- g.setTemplate({
- xclass: "grid." + f
- });
- c.add(g);
- a.bindMarker(f + "-even", g)
- }
- if (Ext.isObject(b)) {
- g.getTemplate().setAttributes(b);
- if (Ext.isObject(b.even)) {
- g.getTemplate().setAttributes(b.even)
- }
- }
- g = e.gridSpriteOdd;
- if (!g) {
- g = e.gridSpriteOdd = new Ext.chart.Markers();
- g.setTemplate({
- xclass: "grid." + f
- });
- c.add(g);
- a.bindMarker(f + "-odd", g)
- }
- if (Ext.isObject(b)) {
- g.getTemplate().setAttributes(b);
- if (Ext.isObject(b.odd)) {
- g.getTemplate().setAttributes(b.odd)
- }
- }
- }
- },
- renderLimits: function() {
- this.getSprites()[0].renderLimits()
- },
- getCoordFor: function(c, d, a, b) {
- return this.getLayout().getCoordFor(c, d, a, b)
- },
- applyPosition: function(a) {
- return a.toLowerCase()
- },
- applyLength: function(b, a) {
- return b > 0 ? b : a
- },
- applyLabel: function(b, a) {
- if (!a) {
- a = new Ext.draw.sprite.Text({})
- }
- if (this.limitTitleTpl) {
- this.limitTitleTpl.setAttributes(b)
- }
- a.setAttributes(b);
- return a
- },
- applyLayout: function(b, a) {
- b = Ext.factory(b, null, a, "axisLayout");
- b.setAxis(this);
- return b
- },
- applySegmenter: function(a, b) {
- a = Ext.factory(a, null, b, "segmenter");
- a.setAxis(this);
- return a
- },
- updateMinimum: function() {
- this.range = null
- },
- updateMaximum: function() {
- this.range = null
- },
- hideLabels: function() {
- this.getSprites()[0].setDirty(true);
- this.setLabel({
- hidden: true
- })
- },
- showLabels: function() {
- this.getSprites()[0].setDirty(true);
- this.setLabel({
- hidden: false
- })
- },
- renderFrame: function() {
- this.getSurface().renderFrame()
- },
- updateChart: function(d, b) {
- var c = this,
- a;
- if (b) {
- b.unregister(c);
- b.un("serieschange", c.onSeriesChange, c);
- b.un("redraw", c.renderLimits, c);
- c.linkAxis();
- c.fireEvent("chartdetached", b, c)
- }
- if (d) {
- d.on("serieschange", c.onSeriesChange, c);
- c.surface = null;
- a = c.getSurface();
- c.getLabel().setSurface(a);
- a.add(c.getSprites());
- a.add(c.getTitle());
- d.register(c);
- c.fireEvent("chartattached", d, c)
- }
- },
- applyBackground: function(a) {
- var b = Ext.ClassManager.getByAlias("sprite.rect");
- return b.def.normalize(a)
- },
- processData: function() {
- this.getLayout().processData();
- this.range = null
- },
- getDirection: function() {
- return this.getChart().getDirectionForAxis(this.getPosition())
- },
- isSide: function() {
- var a = this.getPosition();
- return a === "left" || a === "right"
- },
- applyFields: function(a) {
- return Ext.Array.from(a)
- },
- applyVisibleRange: function(a, c) {
- this.getChart();
- if (a[0] > a[1]) {
- var b = a[0];
- a[0] = a[1];
- a[0] = b
- }
- if (a[1] === a[0]) {
- a[1] += 1 / this.getMaxZoom()
- }
- if (a[1] > a[0] + 1) {
- a[0] = 0;
- a[1] = 1
- } else {
- if (a[0] < 0) {
- a[1] -= a[0];
- a[0] = 0
- } else {
- if (a[1] > 1) {
- a[0] -= a[1] - 1;
- a[1] = 1
- }
- }
- }
- if (c && a[0] === c[0] && a[1] === c[1]) {
- return undefined
- }
- return a
- },
- updateVisibleRange: function(a) {
- this.fireEvent("visiblerangechange", this, a)
- },
- onSeriesChange: function(e) {
- var f = this,
- b = e.getSeries(),
- j = "get" + f.getDirection() + "Axis",
- g = [],
- c, d = b.length,
- a, h;
- for (c = 0; c < d; c++) {
- if (this === b[c][j]()) {
- g.push(b[c])
- }
- }
- f.boundSeries = g;
- a = f.getLinkedTo();
- h = !Ext.isEmpty(a) && e.getAxis(a);
- if (h) {
- f.linkAxis(h)
- } else {
- f.getLayout().processData()
- }
- },
- linkAxis: function(a) {
- var c = this;
-
- function b(f, d, e) {
- e.getLayout()[f]("datachange", "onDataChange", d);
- e[f]("rangechange", "onMasterAxisRangeChange", d)
- }
- if (c.masterAxis) {
- b("un", c, c.masterAxis);
- c.masterAxis = null
- }
- if (a) {
- if (a.type !== this.type) {
- Ext.Error.raise("Linked axes must be of the same type.")
- }
- b("on", c, a);
- c.onDataChange(a.getLayout().labels);
- c.onMasterAxisRangeChange(a, a.range);
- c.setStyle(Ext.apply({}, c.config.style, a.config.style));
- c.setTitle(Ext.apply({}, c.config.title, a.config.title));
- c.setLabel(Ext.apply({}, c.config.label, a.config.label));
- c.masterAxis = a
- }
- },
- onDataChange: function(a) {
- this.getLayout().labels = a
- },
- onMasterAxisRangeChange: function(b, a) {
- this.range = a
- },
- applyRange: function(a) {
- if (!a) {
- return this.dataRange.slice(0)
- } else {
- return [a[0] === null ? this.dataRange[0] : a[0], a[1] === null ? this.dataRange[1] : a[1]]
- }
- },
- getRange: function() {
- var m = this;
- if (m.range) {
- return m.range
- } else {
- if (m.masterAxis) {
- return m.masterAxis.range
- }
- }
- if (Ext.isNumber(m.getMinimum() + m.getMaximum())) {
- return m.range = [m.getMinimum(), m.getMaximum()]
- }
- var d = Infinity,
- n = -Infinity,
- o = m.boundSeries,
- h = m.getLayout(),
- l = m.getSegmenter(),
- p = m.getVisibleRange(),
- b = "get" + m.getDirection() + "Range",
- a, j, g, f, e, k;
- for (e = 0, k = o.length; e < k; e++) {
- f = o[e];
- var c = f[b]();
- if (c) {
- if (c[0] < d) {
- d = c[0]
- }
- if (c[1] > n) {
- n = c[1]
- }
- }
- }
- if (!isFinite(n)) {
- n = m.prevMax
- }
- if (!isFinite(d)) {
- d = m.prevMin
- }
- if (m.getLabelInSpan() || d === n) {
- n += m.getIncrement();
- d -= m.getIncrement()
- }
- if (Ext.isNumber(m.getMinimum())) {
- d = m.getMinimum()
- } else {
- m.prevMin = d
- }
- if (Ext.isNumber(m.getMaximum())) {
- n = m.getMaximum()
- } else {
- m.prevMax = n
- }
- m.range = [Ext.Number.correctFloat(d), Ext.Number.correctFloat(n)];
- if (m.getReconcileRange()) {
- m.reconcileRange()
- }
- if (m.getAdjustByMajorUnit() && l.adjustByMajorUnit && !m.getMajorTickSteps()) {
- j = Ext.Object.chain(m.getSprites()[0].attr);
- j.min = m.range[0];
- j.max = m.range[1];
- j.visibleMin = p[0];
- j.visibleMax = p[1];
- a = {
- attr: j,
- segmenter: l
- };
- h.calculateLayout(a);
- g = a.majorTicks;
- if (g) {
- l.adjustByMajorUnit(g.step, g.unit.scale, m.range);
- j.min = m.range[0];
- j.max = m.range[1];
- delete a.majorTicks;
- h.calculateLayout(a);
- g = a.majorTicks;
- l.adjustByMajorUnit(g.step, g.unit.scale, m.range)
- } else {
- if (!m.hasClearRangePending) {
- m.hasClearRangePending = true;
- m.getChart().on("layout", "clearRange", m)
- }
- }
- }
- if (!Ext.Array.equals(m.range, m.oldRange || [])) {
- m.fireEvent("rangechange", m, m.range);
- m.oldRange = m.range
- }
- return m.range
- },
- clearRange: function() {
- delete this.hasClearRangePending;
- this.range = null
- },
- reconcileRange: function() {
- var e = this,
- g = e.getChart().getAxes(),
- f = e.getDirection(),
- b, d, c, a;
- if (!g) {
- return
- }
- for (b = 0, d = g.length; b < d; b++) {
- c = g[b];
- a = c.getRange();
- if (c === e || c.getDirection() !== f || !a || !c.getReconcileRange()) {
- continue
- }
- if (a[0] < e.range[0]) {
- e.range[0] = a[0]
- }
- if (a[1] > e.range[1]) {
- e.range[1] = a[1]
- }
- }
- },
- applyStyle: function(c, b) {
- var a = Ext.ClassManager.getByAlias("sprite." + this.seriesType);
- if (a && a.def) {
- c = a.def.normalize(c)
- }
- b = Ext.apply(b || {}, c);
- return b
- },
- themeOnlyIfConfigured: {
- grid: true
- },
- updateTheme: function(d) {
- var i = this,
- k = d.getAxis(),
- e = i.getPosition(),
- o = i.getInitialConfig(),
- c = i.defaultConfig,
- g = i.getConfigurator().configs,
- a = k.defaults,
- n = k[e],
- h = i.themeOnlyIfConfigured,
- l, j, p, b, m, f;
- k = Ext.merge({}, a, n);
- for (l in k) {
- j = k[l];
- f = g[l];
- if (j !== null && j !== undefined && f) {
- m = o[l];
- p = Ext.isObject(j);
- b = m === c[l];
- if (p) {
- if (b && h[l]) {
- continue
- }
- j = Ext.merge({}, j, m)
- }
- if (b || p) {
- i[f.names.set](j)
- }
- }
- }
- },
- updateCenter: function(b) {
- var e = this.getSprites(),
- a = e[0],
- d = b[0],
- c = b[1];
- if (a) {
- a.setAttributes({
- centerX: d,
- centerY: c
- })
- }
- if (this.gridSpriteEven) {
- this.gridSpriteEven.getTemplate().setAttributes({
- translationX: d,
- translationY: c,
- rotationCenterX: d,
- rotationCenterY: c
- })
- }
- if (this.gridSpriteOdd) {
- this.gridSpriteOdd.getTemplate().setAttributes({
- translationX: d,
- translationY: c,
- rotationCenterX: d,
- rotationCenterY: c
- })
- }
- },
- getSprites: function() {
- if (!this.getChart()) {
- return
- }
- var i = this,
- e = i.getRange(),
- f = i.getPosition(),
- g = i.getChart(),
- c = g.getAnimation(),
- d, a, b = i.getLength(),
- h = i.superclass;
- if (c === false) {
- c = {
- duration: 0
- }
- }
- if (e) {
- a = Ext.applyIf({
- position: f,
- axis: i,
- min: e[0],
- max: e[1],
- length: b,
- grid: i.getGrid(),
- hidden: i.getHidden(),
- titleOffset: i.titleOffset,
- layout: i.getLayout(),
- segmenter: i.getSegmenter(),
- totalAngle: i.getTotalAngle(),
- label: i.getLabel()
- }, i.getStyle());
- if (!i.sprites.length) {
- while (!h.xtype) {
- h = h.superclass
- }
- d = Ext.create("sprite." + h.xtype, a);
- d.fx.setCustomDurations({
- baseRotation: 0
- });
- d.fx.on("animationstart", "onAnimationStart", i);
- d.fx.on("animationend", "onAnimationEnd", i);
- d.setLayout(i.getLayout());
- d.setSegmenter(i.getSegmenter());
- d.setLabel(i.getLabel());
- i.sprites.push(d);
- i.updateTitleSprite()
- } else {
- d = i.sprites[0];
- d.setAnimation(c);
- d.setAttributes(a)
- }
- if (i.getRenderer()) {
- d.setRenderer(i.getRenderer())
- }
- }
- return i.sprites
- },
- updateTitleSprite: function() {
- var f = this,
- b = f.getLength();
- if (!f.sprites[0] || !Ext.isNumber(b)) {
- return
- }
- var h = this.sprites[0].thickness,
- a = f.getSurface(),
- g = f.getTitle(),
- e = f.getPosition(),
- c = f.getMargin(),
- i = f.getTitleMargin(),
- d = a.roundPixel(b / 2);
- if (g) {
- switch (e) {
- case "top":
- g.setAttributes({
- x: d,
- y: c + i / 2,
- textBaseline: "top",
- textAlign: "center"
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().height + i;
- break;
- case "bottom":
- g.setAttributes({
- x: d,
- y: h + i / 2,
- textBaseline: "top",
- textAlign: "center"
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().height + i;
- break;
- case "left":
- g.setAttributes({
- x: c + i / 2,
- y: d,
- textBaseline: "top",
- textAlign: "center",
- rotationCenterX: c + i / 2,
- rotationCenterY: d,
- rotationRads: -Math.PI / 2
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().width + i;
- break;
- case "right":
- g.setAttributes({
- x: h - c + i / 2,
- y: d,
- textBaseline: "bottom",
- textAlign: "center",
- rotationCenterX: h + i / 2,
- rotationCenterY: d,
- rotationRads: Math.PI / 2
- }, true);
- g.applyTransformations();
- f.titleOffset = g.getBBox().width + i;
- break
- }
- }
- },
- onThicknessChanged: function() {
- this.getChart().onThicknessChanged()
- },
- getThickness: function() {
- if (this.getHidden()) {
- return 0
- }
- return (this.sprites[0] && this.sprites[0].thickness || 1) + this.titleOffset + this.getMargin()
- },
- onAnimationStart: function() {
- this.spriteAnimationCount++;
- if (this.spriteAnimationCount === 1) {
- this.fireEvent("animationstart", this)
- }
- },
- onAnimationEnd: function() {
- this.spriteAnimationCount--;
- if (this.spriteAnimationCount === 0) {
- this.fireEvent("animationend", this)
- }
- },
- getItemId: function() {
- return this.getId()
- },
- getAncestorIds: function() {
- return [this.getChart().getId()]
- },
- isXType: function(a) {
- return a === "axis"
- },
- resolveListenerScope: function(e) {
- var d = this,
- a = Ext._namedScopes[e],
- c = d.getChart(),
- b;
- if (!a) {
- b = c ? c.resolveListenerScope(e, false) : (e || d)
- } else {
- if (a.isThis) {
- b = d
- } else {
- if (a.isController) {
- b = c ? c.resolveListenerScope(e, false) : d
- } else {
- if (a.isSelf) {
- b = c ? c.resolveListenerScope(e, false) : d;
- if (b === c && !c.getInheritedConfig("defaultListenerScope")) {
- b = d
- }
- }
- }
- }
- }
- return b
- },
- destroy: function() {
- var a = this;
- a.setChart(null);
- a.surface.destroy();
- a.surface = null;
- a.callParent()
- }
-});
-Ext.define("Ext.chart.LegendBase", {
- extend: "Ext.view.View",
- config: {
- tpl: ['', '
', '', "', " {name}", "
", " ", "
"],
- nodeContainerSelector: "div." + Ext.baseCSSPrefix + "legend-container",
- itemSelector: "div." + Ext.baseCSSPrefix + "legend-item",
- docked: "bottom"
- },
- setDocked: function(d) {
- var c = this,
- a = c.ownerCt,
- b;
- c.docked = d;
- switch (d) {
- case "top":
- case "bottom":
- c.addCls(Ext.baseCSSPrefix + "horizontal");
- b = "hbox";
- break;
- case "left":
- case "right":
- c.removeCls(Ext.baseCSSPrefix + "horizontal");
- b = "vbox";
- break
- }
- if (a) {
- a.setDocked(d)
- }
- },
- setStore: function(a) {
- this.bindStore(a)
- },
- clearViewEl: function() {
- this.callParent(arguments);
- Ext.removeNode(this.getNodeContainer())
- },
- onItemClick: function(a, c, b, d) {
- this.callParent(arguments);
- this.toggleItem(b)
- }
-});
-Ext.define("Ext.chart.Legend", {
- xtype: "legend",
- extend: "Ext.chart.LegendBase",
- config: {
- baseCls: Ext.baseCSSPrefix + "legend",
- padding: 5,
- rect: null,
- disableSelection: true,
- toggleable: true
- },
- toggleItem: function(c) {
- if (!this.getToggleable()) {
- return
- }
- var b = this.getStore(),
- h = 0,
- e, g = true,
- d, f, a;
- if (b) {
- f = b.getCount();
- for (d = 0; d < f; d++) {
- a = b.getAt(d);
- if (a.get("disabled")) {
- h++
- }
- }
- g = f - h > 1;
- a = b.getAt(c);
- if (a) {
- e = a.get("disabled");
- if (e || g) {
- a.set("disabled", !e)
- }
- }
- }
- }
-});
-Ext.define("Ext.chart.AbstractChart", {
- extend: "Ext.draw.Container",
- requires: ["Ext.chart.theme.Default", "Ext.chart.series.Series", "Ext.chart.interactions.Abstract", "Ext.chart.axis.Axis", "Ext.data.StoreManager", "Ext.chart.Legend", "Ext.data.Store"],
- isChart: true,
- defaultBindProperty: "store",
- config: {
- store: "ext-empty-store",
- theme: "default",
- style: null,
- animation: !Ext.isIE8,
- series: [],
- axes: [],
- legend: null,
- colors: null,
- insetPadding: {
- top: 10,
- left: 10,
- right: 10,
- bottom: 10
- },
- background: null,
- interactions: [],
- mainRect: null,
- resizeHandler: null,
- highlightItem: null
- },
- animationSuspendCount: 0,
- chartLayoutSuspendCount: 0,
- axisThicknessSuspendCount: 0,
- isThicknessChanged: false,
- surfaceZIndexes: {
- background: 0,
- main: 1,
- grid: 2,
- series: 3,
- axis: 4,
- chart: 5,
- overlay: 6,
- events: 7
- },
- constructor: function(a) {
- var b = this;
- b.itemListeners = {};
- b.surfaceMap = {};
- b.chartComponents = {};
- b.isInitializing = true;
- b.suspendChartLayout();
- b.animationSuspendCount++;
- b.callParent(arguments);
- delete b.isInitializing;
- b.getSurface("main");
- b.getSurface("chart").setFlipRtlText(b.getInherited().rtl);
- b.getSurface("overlay").waitFor(b.getSurface("series"));
- b.animationSuspendCount--;
- b.resumeChartLayout()
- },
- applyAnimation: function(a, b) {
- if (!a) {
- a = {
- duration: 0
- }
- } else {
- if (a === true) {
- a = {
- easing: "easeInOut",
- duration: 500
- }
- }
- }
- return b ? Ext.apply({}, a, b) : a
- },
- getAnimation: function() {
- if (this.animationSuspendCount) {
- return {
- duration: 0
- }
- } else {
- return this.callParent()
- }
- },
- applyInsetPadding: function(b, a) {
- if (!Ext.isObject(b)) {
- return Ext.util.Format.parseBox(b)
- } else {
- if (!a) {
- return b
- } else {
- return Ext.apply(a, b)
- }
- }
- },
- suspendAnimation: function() {
- var d = this,
- c = d.getSeries(),
- e = c.length,
- b = -1,
- a;
- d.animationSuspendCount++;
- if (d.animationSuspendCount === 1) {
- while (++b < e) {
- a = c[b];
- a.setAnimation(a.getAnimation())
- }
- }
- },
- resumeAnimation: function() {
- var d = this,
- c = d.getSeries(),
- f = c.length,
- b = -1,
- a, e;
- d.animationSuspendCount--;
- if (d.animationSuspendCount === 0) {
- while (++b < f) {
- a = c[b];
- e = a.getAnimation();
- a.setAnimation(e.duration && e || d.getAnimation())
- }
- }
- },
- suspendChartLayout: function() {
- this.chartLayoutSuspendCount++;
- if (this.chartLayoutSuspendCount === 1) {
- if (this.scheduledLayoutId) {
- this.layoutInSuspension = true;
- this.cancelChartLayout()
- } else {
- this.layoutInSuspension = false
- }
- }
- },
- resumeChartLayout: function() {
- this.chartLayoutSuspendCount--;
- if (this.chartLayoutSuspendCount === 0) {
- if (this.layoutInSuspension) {
- this.scheduleLayout()
- }
- }
- },
- cancelChartLayout: function() {
- if (this.scheduledLayoutId) {
- Ext.draw.Animator.cancel(this.scheduledLayoutId);
- this.scheduledLayoutId = null
- }
- },
- scheduleLayout: function() {
- var a = this;
- if (a.allowSchedule() && !a.scheduledLayoutId) {
- a.scheduledLayoutId = Ext.draw.Animator.schedule("doScheduleLayout", a)
- }
- },
- allowSchedule: function() {
- return true
- },
- doScheduleLayout: function() {
- if (this.chartLayoutSuspendCount) {
- this.layoutInSuspension = true
- } else {
- this.performLayout()
- }
- },
- suspendThicknessChanged: function() {
- this.axisThicknessSuspendCount++
- },
- resumeThicknessChanged: function() {
- if (this.axisThicknessSuspendCount > 0) {
- this.axisThicknessSuspendCount--;
- if (this.axisThicknessSuspendCount === 0 && this.isThicknessChanged) {
- this.onThicknessChanged()
- }
- }
- },
- onThicknessChanged: function() {
- if (this.axisThicknessSuspendCount === 0) {
- this.isThicknessChanged = false;
- this.performLayout()
- } else {
- this.isThicknessChanged = true
- }
- },
- applySprites: function(b) {
- var a = this.getSurface("chart");
- b = Ext.Array.from(b);
- a.removeAll(true);
- a.add(b);
- return b
- },
- initItems: function() {
- var a = this.items,
- b, d, c;
- if (a && !a.isMixedCollection) {
- this.items = [];
- a = Ext.Array.from(a);
- for (b = 0, d = a.length; b < d; b++) {
- c = a[b];
- if (c.type) {
- Ext.raise("To add custom sprites to the chart use the 'sprites' config.")
- } else {
- this.items.push(c)
- }
- }
- }
- this.callParent()
- },
- applyBackground: function(c, e) {
- var b = this.getSurface("background"),
- d, a, f;
- if (c) {
- if (e) {
- d = e.attr.width;
- a = e.attr.height;
- f = e.type === (c.type || "rect")
- }
- if (c.isSprite) {
- e = c
- } else {
- if (c.type === "image" && Ext.isString(c.src)) {
- if (f) {
- e.setAttributes({
- src: c.src
- })
- } else {
- b.remove(e, true);
- e = b.add(c)
- }
- } else {
- if (f) {
- e.setAttributes({
- fillStyle: c
- })
- } else {
- b.remove(e, true);
- e = b.add({
- type: "rect",
- fillStyle: c,
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0
- }
- }
- })
- }
- }
- }
- }
- if (d && a) {
- e.setAttributes({
- width: d,
- height: a
- })
- }
- e.setAnimation(this.getAnimation());
- return e
- },
- getLegendStore: function() {
- return this.legendStore
- },
- refreshLegendStore: function() {
- if (this.getLegendStore()) {
- var d, e, c = this.getSeries(),
- b, a = [];
- if (c) {
- for (d = 0, e = c.length; d < e; d++) {
- b = c[d];
- if (b.getShowInLegend()) {
- b.provideLegendInfo(a)
- }
- }
- }
- this.getLegendStore().setData(a)
- }
- },
- resetLegendStore: function() {
- var c = this.getLegendStore(),
- e, d, a, b;
- if (c) {
- e = this.getLegendStore().getData().items;
- for (d = 0, a = e.length; d < a; d++) {
- b = e[d];
- b.beginEdit();
- b.set("disabled", false);
- b.commit()
- }
- }
- },
- onUpdateLegendStore: function(b, a) {
- var d = this.getSeries(),
- c;
- if (a && d) {
- c = d.map[a.get("series")];
- if (c) {
- c.setHiddenByIndex(a.get("index"), a.get("disabled"));
- this.redraw()
- }
- }
- },
- defaultResizeHandler: function(a) {
- this.scheduleLayout();
- return false
- },
- applyMainRect: function(a, b) {
- if (!b) {
- return a
- }
- this.getSeries();
- this.getAxes();
- if (a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]) {
- return b
- } else {
- return a
- }
- },
- register: function(a) {
- var b = this.chartComponents,
- c = a.getId();
- b[c] = a
- },
- unregister: function(a) {
- var b = this.chartComponents,
- c = a.getId();
- delete b[c]
- },
- get: function(a) {
- return this.chartComponents[a]
- },
- getAxis: function(a) {
- if (a instanceof Ext.chart.axis.Axis) {
- return a
- } else {
- if (Ext.isNumber(a)) {
- return this.getAxes()[a]
- } else {
- if (Ext.isString(a)) {
- return this.get(a)
- }
- }
- }
- },
- getSurface: function(b, c) {
- b = b || "main";
- c = c || b;
- var d = this,
- a = this.callParent([b]),
- f = d.surfaceZIndexes,
- e = d.surfaceMap;
- if (c in f) {
- a.element.setStyle("zIndex", f[c])
- }
- if (!e[c]) {
- e[c] = []
- }
- if (Ext.Array.indexOf(e[c], a) < 0) {
- a.type = c;
- e[c].push(a);
- a.on("destroy", d.forgetSurface, d)
- }
- return a
- },
- forgetSurface: function(a) {
- var d = this.surfaceMap;
- if (!d || this.isDestroying) {
- return
- }
- var c = d[a.type],
- b = c ? Ext.Array.indexOf(c, a) : -1;
- if (b >= 0) {
- c.splice(b, 1)
- }
- },
- applyAxes: function(b, k) {
- var l = this,
- g = {
- left: "right",
- right: "left"
- },
- m = [],
- c, d, e, a, f, h, j;
- l.animationSuspendCount++;
- l.getStore();
- if (!k) {
- k = [];
- k.map = {}
- }
- j = k.map;
- m.map = {};
- b = Ext.Array.from(b, true);
- for (f = 0, h = b.length; f < h; f++) {
- c = b[f];
- if (!c) {
- continue
- }
- if (c instanceof Ext.chart.axis.Axis) {
- d = j[c.getId()];
- c.setChart(l)
- } else {
- c = Ext.Object.chain(c);
- e = c.linkedTo;
- a = c.id;
- if (Ext.isNumber(e)) {
- c = Ext.merge({}, b[e], c)
- } else {
- if (Ext.isString(e)) {
- Ext.Array.each(b, function(i) {
- if (i.id === c.linkedTo) {
- c = Ext.merge({}, i, c);
- return false
- }
- })
- }
- }
- c.id = a;
- c.chart = l;
- if (l.getInherited().rtl) {
- c.position = g[c.position] || c.position
- }
- a = c.getId && c.getId() || c.id;
- c = Ext.factory(c, null, d = j[a], "axis")
- }
- if (c) {
- m.push(c);
- m.map[c.getId()] = c;
- if (!d) {
- c.on("animationstart", "onAnimationStart", l);
- c.on("animationend", "onAnimationEnd", l)
- }
- }
- }
- for (f in j) {
- if (!m.map[f]) {
- j[f].destroy()
- }
- }
- l.animationSuspendCount--;
- return m
- },
- updateAxes: function() {
- if (!this.isDestroying) {
- this.scheduleLayout()
- }
- },
- circularCopyArray: function(e, f, d) {
- var c = [],
- b, a = e && e.length;
- if (a) {
- for (b = 0; b < d; b++) {
- c.push(e[(f + b) % a])
- }
- }
- return c
- },
- circularCopyObject: function(f, g, d) {
- var c = this,
- b, e, a = {};
- if (d) {
- for (b in f) {
- if (f.hasOwnProperty(b)) {
- e = f[b];
- if (Ext.isArray(e)) {
- a[b] = c.circularCopyArray(e, g, d)
- } else {
- a[b] = e
- }
- }
- }
- }
- return a
- },
- getColors: function() {
- var b = this,
- a = b.config.colors,
- c = b.getTheme();
- if (Ext.isArray(a) && a.length > 0) {
- a = b.applyColors(a)
- }
- return a || (c && c.getColors())
- },
- applyColors: function(a) {
- a = Ext.Array.map(a, function(b) {
- if (Ext.isString(b)) {
- return b
- } else {
- return b.toString()
- }
- });
- return a
- },
- updateColors: function(c) {
- var k = this,
- e = k.getTheme(),
- a = c || (e && e.getColors()),
- l = 0,
- f = k.getSeries(),
- d = f && f.length,
- g, j, b, h;
- if (a.length) {
- for (g = 0; g < d; g++) {
- j = f[g];
- h = j.themeColorCount();
- b = k.circularCopyArray(a, l, h);
- l += h;
- j.updateChartColors(b)
- }
- }
- k.refreshLegendStore()
- },
- applyTheme: function(a) {
- if (a && a.isTheme) {
- return a
- }
- return Ext.Factory.chartTheme(a)
- },
- updateTheme: function(g) {
- var e = this,
- f = e.getAxes(),
- d = e.getSeries(),
- a = e.getColors(),
- c, b;
- e.updateChartTheme(g);
- for (b = 0; b < f.length; b++) {
- f[b].updateTheme(g)
- }
- for (b = 0; b < d.length; b++) {
- c = d[b];
- c.updateTheme(g)
- }
- e.updateSpriteTheme(g);
- e.updateColors(a);
- e.redraw()
- },
- themeOnlyIfConfigured: {},
- updateChartTheme: function(c) {
- var i = this,
- k = c.getChart(),
- n = i.getInitialConfig(),
- b = i.defaultConfig,
- e = i.getConfigurator().configs,
- f = k.defaults,
- g = k[i.xtype],
- h = i.themeOnlyIfConfigured,
- l, j, o, a, m, d;
- k = Ext.merge({}, f, g);
- for (l in k) {
- j = k[l];
- d = e[l];
- if (j !== null && j !== undefined && d) {
- m = n[l];
- o = Ext.isObject(j);
- a = m === b[l];
- if (o) {
- if (a && h[l]) {
- continue
- }
- j = Ext.merge({}, j, m)
- }
- if (a || o) {
- i[d.names.set](j)
- }
- }
- }
- },
- updateSpriteTheme: function(c) {
- this.getSprites();
- var j = this,
- e = j.getSurface("chart"),
- h = e.getItems(),
- m = c.getSprites(),
- k, a, l, f, d, b, g;
- for (b = 0, g = h.length; b < g; b++) {
- k = h[b];
- a = m[k.type];
- if (a) {
- f = {};
- d = k.type === "text";
- for (l in a) {
- if (!(l in k.config)) {
- if (!(d && l.indexOf("font") === 0 && k.config.font)) {
- f[l] = a[l]
- }
- }
- }
- k.setAttributes(f)
- }
- }
- },
- addSeries: function(b) {
- var a = this.getSeries();
- Ext.Array.push(a, b);
- this.setSeries(a)
- },
- removeSeries: function(d) {
- d = Ext.Array.from(d);
- var b = this.getSeries(),
- f = [],
- a = d.length,
- g = {},
- c, e;
- for (c = 0; c < a; c++) {
- e = d[c];
- if (typeof e !== "string") {
- e = e.getId()
- }
- g[e] = true
- }
- for (c = 0, a = b.length; c < a; c++) {
- if (!g[b[c].getId()]) {
- f.push(b[c])
- }
- }
- this.setSeries(f)
- },
- applySeries: function(e, d) {
- var g = this,
- j = [],
- h, a, c, f, b;
- g.animationSuspendCount++;
- g.getAxes();
- if (d) {
- h = d.map
- } else {
- d = [];
- h = d.map = {}
- }
- j.map = {};
- e = Ext.Array.from(e, true);
- for (c = 0, f = e.length; c < f; c++) {
- b = e[c];
- if (!b) {
- continue
- }
- a = h[b.getId && b.getId() || b.id];
- if (b instanceof Ext.chart.series.Series) {
- if (a && a !== b) {
- a.destroy()
- }
- b.setChart(g)
- } else {
- if (Ext.isObject(b)) {
- if (a) {
- a.setConfig(b);
- b = a
- } else {
- if (Ext.isString(b)) {
- b = {
- type: b
- }
- }
- b.chart = g;
- b = Ext.create(b.xclass || ("series." + b.type), b);
- b.on("animationstart", "onAnimationStart", g);
- b.on("animationend", "onAnimationEnd", g)
- }
- }
- }
- j.push(b);
- j.map[b.getId()] = b
- }
- for (c in h) {
- if (!j.map[h[c].getId()]) {
- h[c].destroy()
- }
- }
- g.animationSuspendCount--;
- return j
- },
- applyLegend: function(b, a) {
- return Ext.factory(b, Ext.chart.Legend, a)
- },
- updateLegend: function(b, a) {
- if (a) {
- a.destroy()
- }
- if (b) {
- this.getItems();
- this.legendStore = new Ext.data.Store({
- autoDestroy: true,
- fields: ["id", "name", "mark", "disabled", "series", "index"]
- });
- b.setStore(this.legendStore);
- this.refreshLegendStore();
- this.legendStore.on("update", "onUpdateLegendStore", this)
- }
- },
- updateSeries: function(b, a) {
- var c = this;
- if (c.isDestroying) {
- return
- }
- c.animationSuspendCount++;
- c.fireEvent("serieschange", c, b, a);
- c.refreshLegendStore();
- if (!Ext.isEmpty(b)) {
- c.updateTheme(c.getTheme())
- }
- c.scheduleLayout();
- c.animationSuspendCount--
- },
- applyInteractions: function(h, d) {
- if (!d) {
- d = [];
- d.map = {}
- }
- var g = this,
- a = [],
- c = d.map,
- e, f, b;
- a.map = {};
- h = Ext.Array.from(h, true);
- for (e = 0, f = h.length; e < f; e++) {
- b = h[e];
- if (!b) {
- continue
- }
- b = Ext.factory(b, null, c[b.getId && b.getId() || b.id], "interaction");
- if (b) {
- b.setChart(g);
- a.push(b);
- a.map[b.getId()] = b
- }
- }
- for (e in c) {
- if (!a.map[e]) {
- c[e].destroy()
- }
- }
- return a
- },
- getInteraction: function(e) {
- var f = this.getInteractions(),
- a = f && f.length,
- c = null,
- b, d;
- if (a) {
- for (d = 0; d < a; ++d) {
- b = f[d];
- if (b.type === e) {
- c = b;
- break
- }
- }
- }
- return c
- },
- applyStore: function(a) {
- return a && Ext.StoreManager.lookup(a)
- },
- updateStore: function(a, c) {
- var b = this;
- if (c) {
- c.un({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: b,
- order: "after"
- });
- if (c.autoDestroy) {
- c.destroy()
- }
- }
- if (a) {
- a.on({
- datachanged: "onDataChanged",
- update: "onDataChanged",
- scope: b,
- order: "after"
- })
- }
- b.fireEvent("storechange", b, a, c);
- b.onDataChanged()
- },
- redraw: function() {
- this.fireEvent("redraw", this)
- },
- performLayout: function() {
- var d = this,
- b = d.getChartSize(true),
- c = [0, 0, b.width, b.height],
- a = d.getBackground();
- d.hasFirstLayout = true;
- d.fireEvent("layout", d);
- d.cancelChartLayout();
- d.getSurface("background").setRect(c);
- d.getSurface("chart").setRect(c);
- a.setAttributes({
- width: b.width,
- height: b.height
- })
- },
- getChartSize: function(b) {
- var a = this;
- if (b) {
- a.chartSize = null
- }
- return a.chartSize || (a.chartSize = a.innerElement.getSize())
- },
- getEventXY: function(a) {
- return this.getSurface().getEventXY(a)
- },
- getItemForPoint: function(h, g) {
- var f = this,
- a = f.getSeries(),
- e = f.getMainRect(),
- d = a.length,
- b = f.hasFirstLayout ? d - 1 : -1,
- c, j;
- if (!(e && h >= 0 && h <= e[2] && g >= 0 && g <= e[3])) {
- return null
- }
- for (; b >= 0; b--) {
- c = a[b];
- j = c.getItemForPoint(h, g);
- if (j) {
- return j
- }
- }
- return null
- },
- getItemsForPoint: function(h, g) {
- var f = this,
- a = f.getSeries(),
- d = a.length,
- b = f.hasFirstLayout ? d - 1 : -1,
- e = [],
- c, j;
- for (; b >= 0; b--) {
- c = a[b];
- j = c.getItemForPoint(h, g);
- if (j) {
- e.push(j)
- }
- }
- return e
- },
- onAnimationStart: function() {
- this.fireEvent("animationstart", this)
- },
- onAnimationEnd: function() {
- this.fireEvent("animationend", this)
- },
- onDataChanged: function() {
- var d = this;
- if (d.isInitializing) {
- return
- }
- var c = d.getMainRect(),
- a = d.getStore(),
- b = d.getSeries(),
- e = d.getAxes();
- if (!a || !e || !b) {
- return
- }
- if (!c) {
- d.on({
- redraw: d.onDataChanged,
- scope: d,
- single: true
- });
- return
- }
- d.processData();
- d.redraw()
- },
- recordCount: 0,
- processData: function() {
- var g = this,
- e = g.getStore().getCount(),
- c = g.getSeries(),
- f = c.length,
- d = false,
- b = 0,
- a;
- for (; b < f; b++) {
- a = c[b];
- a.processData();
- if (!d && a.isStoreDependantColorCount) {
- d = true
- }
- }
- if (d && e > g.recordCount) {
- g.updateColors(g.getColors());
- g.recordCount = e
- }
- },
- bindStore: function(a) {
- this.setStore(a)
- },
- applyHighlightItem: function(f, a) {
- if (f === a) {
- return
- }
- if (Ext.isObject(f) && Ext.isObject(a)) {
- var e = f,
- d = a,
- c = e.sprite && (e.sprite[0] || e.sprite),
- b = d.sprite && (d.sprite[0] || d.sprite);
- if (c === b && e.index === d.index) {
- return
- }
- }
- return f
- },
- updateHighlightItem: function(b, a) {
- if (a) {
- a.series.setAttributesForItem(a, {
- highlighted: false
- })
- }
- if (b) {
- b.series.setAttributesForItem(b, {
- highlighted: true
- });
- this.fireEvent("itemhighlight", this, b, a)
- }
- this.fireEvent("itemhighlightchange", this, b, a)
- },
- destroyChart: function() {
- var f = this,
- d = f.getLegend(),
- g = f.getAxes(),
- c = f.getSeries(),
- h = f.getInteractions(),
- b = [],
- a, e;
- f.surfaceMap = null;
- for (a = 0, e = h.length; a < e; a++) {
- h[a].destroy()
- }
- for (a = 0, e = g.length; a < e; a++) {
- g[a].destroy()
- }
- for (a = 0, e = c.length; a < e; a++) {
- c[a].destroy()
- }
- f.setInteractions(b);
- f.setAxes(b);
- f.setSeries(b);
- if (d) {
- d.destroy();
- f.setLegend(null)
- }
- f.legendStore = null;
- f.setStore(null);
- f.cancelChartLayout()
- },
- getRefItems: function(b) {
- var g = this,
- e = g.getSeries(),
- h = g.getAxes(),
- a = g.getInteractions(),
- c = [],
- d, f;
- for (d = 0, f = e.length; d < f; d++) {
- c.push(e[d]);
- if (e[d].getRefItems) {
- c.push.apply(c, e[d].getRefItems(b))
- }
- }
- for (d = 0, f = h.length; d < f; d++) {
- c.push(h[d]);
- if (h[d].getRefItems) {
- c.push.apply(c, h[d].getRefItems(b))
- }
- }
- for (d = 0, f = a.length; d < f; d++) {
- c.push(a[d]);
- if (a[d].getRefItems) {
- c.push.apply(c, a[d].getRefItems(b))
- }
- }
- return c
- }
-});
-Ext.define("Ext.chart.overrides.AbstractChart", {
- override: "Ext.chart.AbstractChart",
- updateLegend: function(b, a) {
- var c;
- this.callParent([b, a]);
- if (b) {
- c = b.docked;
- this.addDocked({
- dock: c,
- xtype: "panel",
- shrinkWrap: true,
- scrollable: true,
- layout: {
- type: c === "top" || c === "bottom" ? "hbox" : "vbox",
- pack: "center"
- },
- items: b,
- cls: Ext.baseCSSPrefix + "legend-panel"
- })
- }
- },
- performLayout: function() {
- if (this.isVisible(true)) {
- return this.callParent()
- }
- this.cancelChartLayout();
- return false
- },
- afterComponentLayout: function(c, a, b, d) {
- this.callParent([c, a, b, d]);
- this.scheduleLayout()
- },
- allowSchedule: function() {
- return this.rendered
- },
- onDestroy: function() {
- this.destroyChart();
- this.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.grid.HorizontalGrid", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "grid.horizontal",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 1,
- height: 1,
- strokeStyle: "#DDD"
- }
- }
- },
- render: function(b, c, e) {
- var a = this.attr,
- f = b.roundPixel(a.y),
- d = c.lineWidth * 0.5;
- c.beginPath();
- c.rect(e[0] - b.matrix.getDX(), f + d, +e[2], a.height);
- c.fill();
- c.beginPath();
- c.moveTo(e[0] - b.matrix.getDX(), f + d);
- c.lineTo(e[0] + e[2] - b.matrix.getDX(), f + d);
- c.stroke()
- }
-});
-Ext.define("Ext.chart.grid.VerticalGrid", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "grid.vertical",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 1,
- height: 1,
- strokeStyle: "#DDD"
- }
- }
- },
- render: function(c, d, f) {
- var b = this.attr,
- a = c.roundPixel(b.x),
- e = d.lineWidth * 0.5;
- d.beginPath();
- d.rect(a - e, f[1] - c.matrix.getDY(), b.width, f[3]);
- d.fill();
- d.beginPath();
- d.moveTo(a - e, f[1] - c.matrix.getDY());
- d.lineTo(a - e, f[1] + f[3] - c.matrix.getDY());
- d.stroke()
- }
-});
-Ext.define("Ext.chart.CartesianChart", {
- extend: "Ext.chart.AbstractChart",
- alternateClassName: "Ext.chart.Chart",
- requires: ["Ext.chart.grid.HorizontalGrid", "Ext.chart.grid.VerticalGrid"],
- xtype: ["cartesian", "chart"],
- isCartesian: true,
- config: {
- flipXY: false,
- innerRect: [0, 0, 1, 1],
- innerPadding: {
- top: 0,
- left: 0,
- right: 0,
- bottom: 0
- }
- },
- applyInnerPadding: function(b, a) {
- if (!Ext.isObject(b)) {
- return Ext.util.Format.parseBox(b)
- } else {
- if (!a) {
- return b
- } else {
- return Ext.apply(a, b)
- }
- }
- },
- getDirectionForAxis: function(a) {
- var b = this.getFlipXY();
- if (a === "left" || a === "right") {
- if (b) {
- return "X"
- } else {
- return "Y"
- }
- } else {
- if (b) {
- return "Y"
- } else {
- return "X"
- }
- }
- },
- performLayout: function() {
- var A = this;
- A.animationSuspendCount++;
- if (A.callParent() === false) {
- --A.animationSuspendCount;
- return
- }
- A.suspendThicknessChanged();
- var d = A.getSurface("chart").getRect(),
- o = d[2],
- n = d[3],
- z = A.getAxes(),
- b, q = A.getSeries(),
- h, l, a, f = A.getInsetPadding(),
- v = A.getInnerPadding(),
- r, c, e = Ext.apply({}, f),
- u, p, s, k, m, y, t, x, g, j = A.getInherited().rtl,
- w = A.getFlipXY();
- if (o <= 0 || n <= 0) {
- return
- }
- for (x = 0; x < z.length; x++) {
- b = z[x];
- l = b.getSurface();
- m = b.getFloating();
- y = m ? m.value : null;
- a = b.getThickness();
- switch (b.getPosition()) {
- case "top":
- l.setRect([0, e.top + 1, o, a]);
- break;
- case "bottom":
- l.setRect([0, n - (e.bottom + a), o, a]);
- break;
- case "left":
- l.setRect([e.left, 0, a, n]);
- break;
- case "right":
- l.setRect([o - (e.right + a), 0, a, n]);
- break
- }
- if (y === null) {
- e[b.getPosition()] += a
- }
- }
- o -= e.left + e.right;
- n -= e.top + e.bottom;
- u = [e.left, e.top, o, n];
- e.left += v.left;
- e.top += v.top;
- e.right += v.right;
- e.bottom += v.bottom;
- p = o - v.left - v.right;
- s = n - v.top - v.bottom;
- A.setInnerRect([e.left, e.top, p, s]);
- if (p <= 0 || s <= 0) {
- return
- }
- A.setMainRect(u);
- A.getSurface().setRect(u);
- for (x = 0, g = A.surfaceMap.grid && A.surfaceMap.grid.length; x < g; x++) {
- c = A.surfaceMap.grid[x];
- c.setRect(u);
- c.matrix.set(1, 0, 0, 1, v.left, v.top);
- c.matrix.inverse(c.inverseMatrix)
- }
- for (x = 0; x < z.length; x++) {
- b = z[x];
- l = b.getSurface();
- t = l.matrix;
- k = t.elements;
- switch (b.getPosition()) {
- case "top":
- case "bottom":
- k[4] = e.left;
- b.setLength(p);
- break;
- case "left":
- case "right":
- k[5] = e.top;
- b.setLength(s);
- break
- }
- b.updateTitleSprite();
- t.inverse(l.inverseMatrix)
- }
- for (x = 0, g = q.length; x < g; x++) {
- h = q[x];
- r = h.getSurface();
- r.setRect(u);
- if (w) {
- if (j) {
- r.matrix.set(0, -1, -1, 0, v.left + p, v.top + s)
- } else {
- r.matrix.set(0, -1, 1, 0, v.left, v.top + s)
- }
- } else {
- r.matrix.set(1, 0, 0, -1, v.left, v.top + s)
- }
- r.matrix.inverse(r.inverseMatrix);
- h.getOverlaySurface().setRect(u)
- }
- A.redraw();
- A.animationSuspendCount--;
- A.resumeThicknessChanged()
- },
- refloatAxes: function() {
- var h = this,
- g = h.getAxes(),
- o = (g && g.length) || 0,
- c, d, n, f, l, b, k, r = h.getChartSize(),
- q = h.getInsetPadding(),
- p = h.getInnerPadding(),
- a = r.width - q.left - q.right,
- m = r.height - q.top - q.bottom,
- j, e;
- for (e = 0; e < o; e++) {
- c = g[e];
- f = c.getFloating();
- l = f ? f.value : null;
- if (l === null) {
- delete c.floatingAtCoord;
- continue
- }
- d = c.getSurface();
- n = d.getRect();
- if (!n) {
- continue
- }
- n = n.slice();
- b = h.getAxis(f.alongAxis);
- if (b) {
- j = b.getAlignment() === "horizontal";
- if (Ext.isString(l)) {
- l = b.getCoordFor(l)
- }
- b.floatingAxes[c.getId()] = l;
- k = b.getSprites()[0].attr.matrix;
- if (j) {
- l = l * k.getXX() + k.getDX();
- c.floatingAtCoord = l + p.left + p.right
- } else {
- l = l * k.getYY() + k.getDY();
- c.floatingAtCoord = l + p.top + p.bottom
- }
- } else {
- j = c.getAlignment() === "horizontal";
- if (j) {
- c.floatingAtCoord = l + p.top + p.bottom
- } else {
- c.floatingAtCoord = l + p.left + p.right
- }
- l = d.roundPixel(0.01 * l * (j ? m : a))
- }
- switch (c.getPosition()) {
- case "top":
- n[1] = q.top + p.top + l - n[3] + 1;
- break;
- case "bottom":
- n[1] = q.top + p.top + (b ? l : m - l);
- break;
- case "left":
- n[0] = q.left + p.left + l - n[2];
- break;
- case "right":
- n[0] = q.left + p.left + (b ? l : a - l) - 1;
- break
- }
- d.setRect(n)
- }
- },
- redraw: function() {
- var C = this,
- r = C.getSeries(),
- z = C.getAxes(),
- b = C.getMainRect(),
- p, t, w = C.getInnerPadding(),
- f, l, s, e, q, A, v, g, d, c, a, k, n, y = C.getFlipXY(),
- x = 1000,
- m, u, h, o, B;
- if (!b) {
- return
- }
- p = b[2] - w.left - w.right;
- t = b[3] - w.top - w.bottom;
- for (A = 0; A < r.length; A++) {
- h = r[A];
- if ((c = h.getXAxis())) {
- n = c.getVisibleRange();
- l = c.getRange();
- l = [l[0] + (l[1] - l[0]) * n[0], l[0] + (l[1] - l[0]) * n[1]]
- } else {
- l = h.getXRange()
- }
- if ((a = h.getYAxis())) {
- n = a.getVisibleRange();
- s = a.getRange();
- s = [s[0] + (s[1] - s[0]) * n[0], s[0] + (s[1] - s[0]) * n[1]]
- } else {
- s = h.getYRange()
- }
- q = {
- visibleMinX: l[0],
- visibleMaxX: l[1],
- visibleMinY: s[0],
- visibleMaxY: s[1],
- innerWidth: p,
- innerHeight: t,
- flipXY: y
- };
- f = h.getSprites();
- for (v = 0, g = f.length; v < g; v++) {
- o = f[v];
- m = o.attr.zIndex;
- if (m < x) {
- m += (A + 1) * 100 + x;
- o.attr.zIndex = m;
- B = o.getMarker("items");
- if (B) {
- u = B.attr.zIndex;
- if (u === Number.MAX_VALUE) {
- B.attr.zIndex = m
- } else {
- if (u < x) {
- B.attr.zIndex = m + u
- }
- }
- }
- }
- o.setAttributes(q, true)
- }
- }
- for (A = 0; A < z.length; A++) {
- d = z[A];
- e = d.isSide();
- f = d.getSprites();
- k = d.getRange();
- n = d.getVisibleRange();
- q = {
- dataMin: k[0],
- dataMax: k[1],
- visibleMin: n[0],
- visibleMax: n[1]
- };
- if (e) {
- q.length = t;
- q.startGap = w.bottom;
- q.endGap = w.top
- } else {
- q.length = p;
- q.startGap = w.left;
- q.endGap = w.right
- }
- for (v = 0, g = f.length; v < g; v++) {
- f[v].setAttributes(q, true)
- }
- }
- C.renderFrame();
- C.callParent(arguments)
- },
- renderFrame: function() {
- this.refloatAxes();
- this.callParent()
- }
-});
-Ext.define("Ext.chart.grid.CircularGrid", {
- extend: "Ext.draw.sprite.Circle",
- alias: "grid.circular",
- inheritableStatics: {
- def: {
- defaults: {
- r: 1,
- strokeStyle: "#DDD"
- }
- }
- }
-});
-Ext.define("Ext.chart.grid.RadialGrid", {
- extend: "Ext.draw.sprite.Path",
- alias: "grid.radial",
- inheritableStatics: {
- def: {
- processors: {
- startRadius: "number",
- endRadius: "number"
- },
- defaults: {
- startRadius: 0,
- endRadius: 1,
- scalingCenterX: 0,
- scalingCenterY: 0,
- strokeStyle: "#DDD"
- },
- triggers: {
- startRadius: "path,bbox",
- endRadius: "path,bbox"
- }
- }
- },
- render: function() {
- this.callParent(arguments)
- },
- updatePath: function(d, a) {
- var b = a.startRadius,
- c = a.endRadius;
- d.moveTo(b, 0);
- d.lineTo(c, 0)
- }
-});
-Ext.define("Ext.chart.PolarChart", {
- extend: "Ext.chart.AbstractChart",
- requires: ["Ext.chart.grid.CircularGrid", "Ext.chart.grid.RadialGrid"],
- xtype: "polar",
- isPolar: true,
- config: {
- center: [0, 0],
- radius: 0,
- innerPadding: 0
- },
- getDirectionForAxis: function(a) {
- return a === "radial" ? "Y" : "X"
- },
- applyCenter: function(a, b) {
- if (b && a[0] === b[0] && a[1] === b[1]) {
- return
- }
- return [+a[0], +a[1]]
- },
- updateCenter: function(a) {
- var g = this,
- h = g.getAxes(),
- d = g.getSeries(),
- c, f, e, b;
- for (c = 0, f = h.length; c < f; c++) {
- e = h[c];
- e.setCenter(a)
- }
- for (c = 0, f = d.length; c < f; c++) {
- b = d[c];
- b.setCenter(a)
- }
- },
- applyInnerPadding: function(b, a) {
- return Ext.isNumber(b) ? b : a
- },
- doSetSurfaceRect: function(b, c) {
- var a = this.getMainRect();
- b.setRect(c);
- b.matrix.set(1, 0, 0, 1, a[0] - c[0], a[1] - c[1]);
- b.inverseMatrix.set(1, 0, 0, 1, c[0] - a[0], c[1] - a[1])
- },
- applyAxes: function(f, h) {
- var e = this,
- g = Ext.Array.from(e.config.series)[0],
- b, d, c, a;
- if (g.type === "radar" && f && f.length) {
- for (b = 0, d = f.length; b < d; b++) {
- c = f[b];
- if (c.position === "angular") {
- a = true;
- break
- }
- }
- if (!a) {
- f.push({
- type: "category",
- position: "angular",
- fields: g.xField || g.angleField,
- style: {
- estStepSize: 1
- },
- grid: true
- })
- }
- }
- return this.callParent(arguments)
- },
- performLayout: function() {
- var F = this,
- g = true;
- try {
- F.animationSuspendCount++;
- if (this.callParent() === false) {
- g = false;
- return
- }
- F.suspendThicknessChanged();
- var h = F.getSurface("chart").getRect(),
- v = F.getInsetPadding(),
- G = F.getInnerPadding(),
- l = Ext.apply({}, v),
- d, s = h[2] - v.left - v.right,
- r = h[3] - v.top - v.bottom,
- x = [v.left, v.top, s, r],
- u = F.getSeries(),
- p, t = s - G * 2,
- w = r - G * 2,
- D = [t * 0.5 + G, w * 0.5 + G],
- j = Math.min(t, w) * 0.5,
- A = F.getAxes(),
- f, a, k, m = [],
- o = [],
- E = j - G,
- z, n, b, q, y, c, C;
- F.setMainRect(x);
- F.doSetSurfaceRect(F.getSurface(), x);
- for (z = 0, n = F.surfaceMap.grid && F.surfaceMap.grid.length; z < n; z++) {
- F.doSetSurfaceRect(F.surfaceMap.grid[z], h)
- }
- for (z = 0, n = A.length; z < n; z++) {
- f = A[z];
- switch (f.getPosition()) {
- case "angular":
- m.push(f);
- break;
- case "radial":
- o.push(f);
- break
- }
- }
- for (z = 0, n = m.length; z < n; z++) {
- f = m[z];
- q = f.getFloating();
- y = q ? q.value : null;
- F.doSetSurfaceRect(f.getSurface(), h);
- a = f.getThickness();
- for (d in l) {
- l[d] += a
- }
- s = h[2] - l.left - l.right;
- r = h[3] - l.top - l.bottom;
- b = Math.min(s, r) * 0.5;
- if (z === 0) {
- E = b - G
- }
- f.setMinimum(0);
- f.setLength(b);
- f.getSprites();
- k = f.sprites[0].attr.lineWidth * 0.5;
- for (d in l) {
- l[d] += k
- }
- }
- for (z = 0, n = o.length; z < n; z++) {
- f = o[z];
- F.doSetSurfaceRect(f.getSurface(), h);
- f.setMinimum(0);
- f.setLength(E);
- f.getSprites()
- }
- for (z = 0, n = u.length; z < n; z++) {
- p = u[z];
- if (p.type === "gauge" && !c) {
- c = p
- } else {
- p.setRadius(E)
- }
- F.doSetSurfaceRect(p.getSurface(), x)
- }
- F.doSetSurfaceRect(F.getSurface("overlay"), h);
- if (c) {
- c.setRect(x);
- C = c.getRadius() - G;
- F.setRadius(C);
- F.setCenter(c.getCenter());
- c.setRadius(C);
- if (A.length && A[0].getPosition() === "gauge") {
- f = A[0];
- F.doSetSurfaceRect(f.getSurface(), h);
- f.setTotalAngle(c.getTotalAngle());
- f.setLength(C)
- }
- } else {
- F.setRadius(j);
- F.setCenter(D)
- }
- F.redraw()
- } catch (B) {
- throw B
- } finally {
- F.animationSuspendCount--;
- if (g) {
- F.resumeThicknessChanged()
- }
- }
- },
- refloatAxes: function() {
- var j = this,
- g = j.getAxes(),
- h = j.getMainRect(),
- f, k, b, d, a, c, e;
- if (!h) {
- return
- }
- e = 0.5 * Math.min(h[2], h[3]);
- for (d = 0, a = g.length; d < a; d++) {
- c = g[d];
- f = c.getFloating();
- k = f ? f.value : null;
- if (k !== null) {
- b = j.getAxis(f.alongAxis);
- if (c.getPosition() === "angular") {
- if (b) {
- k = b.getLength() * k / b.getRange()[1]
- } else {
- k = 0.01 * k * e
- }
- c.sprites[0].setAttributes({
- length: k
- }, true)
- } else {
- if (b) {
- if (Ext.isString(k)) {
- k = b.getCoordFor(k)
- }
- k = k / (b.getRange()[1] + 1) * Math.PI * 2 - Math.PI * 1.5 + c.getRotation()
- } else {
- k = Ext.draw.Draw.rad(k)
- }
- c.sprites[0].setAttributes({
- baseRotation: k
- }, true)
- }
- }
- }
- },
- redraw: function() {
- var f = this,
- g = f.getAxes(),
- d, c = f.getSeries(),
- b, a, e;
- for (a = 0, e = g.length; a < e; a++) {
- d = g[a];
- d.getSprites()
- }
- for (a = 0, e = c.length; a < e; a++) {
- b = c[a];
- b.getSprites()
- }
- f.renderFrame();
- f.callParent(arguments)
- },
- renderFrame: function() {
- this.refloatAxes();
- this.callParent()
- }
-});
-Ext.define("Ext.chart.SpaceFillingChart", {
- extend: "Ext.chart.AbstractChart",
- xtype: "spacefilling",
- config: {},
- performLayout: function() {
- var j = this;
- try {
- j.animationSuspendCount++;
- if (j.callParent() === false) {
- return
- }
- var k = j.getSurface("chart").getRect(),
- l = j.getInsetPadding(),
- a = k[2] - l.left - l.right,
- m = k[3] - l.top - l.bottom,
- h = [l.left, l.top, a, m],
- b = j.getSeries(),
- d, c, g;
- j.getSurface().setRect(h);
- j.setMainRect(h);
- for (c = 0, g = b.length; c < g; c++) {
- d = b[c];
- d.getSurface().setRect(h);
- if (d.setRect) {
- d.setRect(h)
- }
- d.getOverlaySurface().setRect(k)
- }
- j.redraw()
- } catch (f) {
- throw f
- } finally {
- j.animationSuspendCount--
- }
- },
- redraw: function() {
- var e = this,
- c = e.getSeries(),
- b, a, d;
- for (a = 0, d = c.length; a < d; a++) {
- b = c[a];
- b.getSprites()
- }
- e.renderFrame();
- e.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.axis.sprite.Axis3D", {
- extend: "Ext.chart.axis.sprite.Axis",
- alias: "sprite.axis3d",
- type: "axis3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- },
- triggers: {
- depth: "layout"
- }
- }
- },
- config: {
- fx: {
- customDurations: {
- depth: 0
- }
- }
- },
- layoutUpdater: function() {
- var h = this,
- f = h.getAxis().getChart();
- if (f.isInitializing) {
- return
- }
- var e = h.attr,
- d = h.getLayout(),
- c = d.isDiscrete ? 0 : e.depth,
- g = f.getInherited().rtl,
- b = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMin,
- i = e.dataMin + (e.dataMax - e.dataMin) * e.visibleMax,
- a = {
- attr: e,
- segmenter: h.getSegmenter(),
- renderer: h.defaultRenderer
- };
- if (e.position === "left" || e.position === "right") {
- e.translationX = 0;
- e.translationY = i * (e.length - c) / (i - b) + c;
- e.scalingX = 1;
- e.scalingY = (-e.length + c) / (i - b);
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- } else {
- if (e.position === "top" || e.position === "bottom") {
- if (g) {
- e.translationX = e.length + b * e.length / (i - b) + 1
- } else {
- e.translationX = -b * e.length / (i - b)
- }
- e.translationY = 0;
- e.scalingX = (g ? -1 : 1) * (e.length - c) / (i - b);
- e.scalingY = 1;
- e.scalingCenterY = 0;
- e.scalingCenterX = 0;
- h.applyTransformations(true)
- }
- }
- if (d) {
- d.calculateLayout(a);
- h.setLayoutContext(a)
- }
- },
- renderAxisLine: function(a, j, f, c) {
- var i = this,
- h = i.attr,
- b = h.lineWidth * 0.5,
- f = i.getLayout(),
- d = f.isDiscrete ? 0 : h.depth,
- k = h.position,
- e, g;
- if (h.axisLine && h.length) {
- switch (k) {
- case "left":
- e = a.roundPixel(c[2]) - b;
- j.moveTo(e, -h.endGap + d);
- j.lineTo(e, h.length + h.startGap);
- break;
- case "right":
- j.moveTo(b, -h.endGap);
- j.lineTo(b, h.length + h.startGap);
- break;
- case "bottom":
- j.moveTo(-h.startGap, b);
- j.lineTo(h.length - d + h.endGap, b);
- break;
- case "top":
- e = a.roundPixel(c[3]) - b;
- j.moveTo(-h.startGap, e);
- j.lineTo(h.length + h.endGap, e);
- break;
- case "angular":
- j.moveTo(h.centerX + h.length, h.centerY);
- j.arc(h.centerX, h.centerY, h.length, 0, Math.PI * 2, true);
- break;
- case "gauge":
- g = i.getGaugeAngles();
- j.moveTo(h.centerX + Math.cos(g.start) * h.length, h.centerY + Math.sin(g.start) * h.length);
- j.arc(h.centerX, h.centerY, h.length, g.start, g.end, true);
- break
- }
- }
- }
-});
-Ext.define("Ext.chart.axis.Axis3D", {
- extend: "Ext.chart.axis.Axis",
- xtype: "axis3d",
- requires: ["Ext.chart.axis.sprite.Axis3D"],
- config: {
- depth: 0
- },
- onSeriesChange: function(e) {
- var g = this,
- b = "depthchange",
- f = "onSeriesDepthChange",
- d, c;
-
- function a(h) {
- var i = g.boundSeries;
- for (d = 0; d < i.length; d++) {
- c = i[d];
- c[h](b, f, g)
- }
- }
- a("un");
- g.callParent(arguments);
- a("on")
- },
- onSeriesDepthChange: function(b, f) {
- var d = this,
- g = f,
- e = d.boundSeries,
- a, c;
- if (f > d.getDepth()) {
- g = f
- } else {
- for (a = 0; a < e.length; a++) {
- c = e[a];
- if (c !== b && c.getDepth) {
- f = c.getDepth();
- if (f > g) {
- g = f
- }
- }
- }
- }
- d.setDepth(g)
- },
- updateDepth: function(d) {
- var b = this,
- c = b.getSprites(),
- a = {
- depth: d
- };
- if (c && c.length) {
- c[0].setAttributes(a)
- }
- if (b.gridSpriteEven && b.gridSpriteOdd) {
- b.gridSpriteEven.getTemplate().setAttributes(a);
- b.gridSpriteOdd.getTemplate().setAttributes(a)
- }
- },
- getGridAlignment: function() {
- switch (this.getPosition()) {
- case "left":
- case "right":
- return "horizontal3d";
- case "top":
- case "bottom":
- return "vertical3d"
- }
- }
-});
-Ext.define("Ext.chart.axis.Category", {
- requires: ["Ext.chart.axis.layout.CombineDuplicate", "Ext.chart.axis.segmenter.Names"],
- extend: "Ext.chart.axis.Axis",
- alias: "axis.category",
- type: "category",
- config: {
- layout: "combineDuplicate",
- segmenter: "names"
- }
-});
-Ext.define("Ext.chart.axis.Category3D", {
- requires: ["Ext.chart.axis.layout.CombineDuplicate", "Ext.chart.axis.segmenter.Names"],
- extend: "Ext.chart.axis.Axis3D",
- alias: "axis.category3d",
- type: "category3d",
- config: {
- layout: "combineDuplicate",
- segmenter: "names"
- }
-});
-Ext.define("Ext.chart.axis.Numeric", {
- extend: "Ext.chart.axis.Axis",
- type: "numeric",
- alias: ["axis.numeric", "axis.radial"],
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Numeric"],
- config: {
- layout: "continuous",
- segmenter: "numeric",
- aggregator: "double"
- }
-});
-Ext.define("Ext.chart.axis.Numeric3D", {
- extend: "Ext.chart.axis.Axis3D",
- alias: ["axis.numeric3d"],
- type: "numeric3d",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Numeric"],
- config: {
- layout: "continuous",
- segmenter: "numeric",
- aggregator: "double"
- }
-});
-Ext.define("Ext.chart.axis.Time", {
- extend: "Ext.chart.axis.Numeric",
- alias: "axis.time",
- type: "time",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Time"],
- config: {
- calculateByLabelSize: true,
- dateFormat: null,
- fromDate: null,
- toDate: null,
- step: [Ext.Date.DAY, 1],
- layout: "continuous",
- segmenter: "time",
- aggregator: "time"
- },
- updateDateFormat: function(a) {
- this.setRenderer(function(c, b) {
- return Ext.Date.format(new Date(b), a)
- })
- },
- updateFromDate: function(a) {
- this.setMinimum(+a)
- },
- updateToDate: function(a) {
- this.setMaximum(+a)
- },
- getCoordFor: function(a) {
- if (Ext.isString(a)) {
- a = new Date(a)
- }
- return +a
- }
-});
-Ext.define("Ext.chart.axis.Time3D", {
- extend: "Ext.chart.axis.Numeric3D",
- alias: "axis.time3d",
- type: "time3d",
- requires: ["Ext.chart.axis.layout.Continuous", "Ext.chart.axis.segmenter.Time"],
- config: {
- calculateByLabelSize: true,
- dateFormat: null,
- fromDate: null,
- toDate: null,
- step: [Ext.Date.DAY, 1],
- layout: "continuous",
- segmenter: "time",
- aggregator: "time"
- },
- updateDateFormat: function(a) {
- this.setRenderer(function(c, b) {
- return Ext.Date.format(new Date(b), a)
- })
- },
- updateFromDate: function(a) {
- this.setMinimum(+a)
- },
- updateToDate: function(a) {
- this.setMaximum(+a)
- },
- getCoordFor: function(a) {
- if (Ext.isString(a)) {
- a = new Date(a)
- }
- return +a
- }
-});
-Ext.define("Ext.chart.grid.HorizontalGrid3D", {
- extend: "Ext.chart.grid.HorizontalGrid",
- alias: "grid.horizontal3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- }
- }
- },
- render: function(a, k, d) {
- var f = this.attr,
- i = a.roundPixel(f.x),
- h = a.roundPixel(f.y),
- l = a.matrix.getDX(),
- c = k.lineWidth * 0.5,
- j = f.height,
- e = f.depth,
- b, g;
- if (h <= d[1]) {
- return
- }
- b = d[0] + e - l;
- g = h + c - e;
- k.beginPath();
- k.rect(b, g, d[2], j);
- k.fill();
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + d[2], g);
- k.stroke();
- b = d[0] + i - l;
- g = h + c;
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + e, g - e);
- k.lineTo(b + e, g - e + j);
- k.lineTo(b, g + j);
- k.closePath();
- k.fill();
- k.beginPath();
- k.moveTo(b, g);
- k.lineTo(b + e, g - e);
- k.stroke()
- }
-});
-Ext.define("Ext.chart.grid.VerticalGrid3D", {
- extend: "Ext.chart.grid.VerticalGrid",
- alias: "grid.vertical3d",
- inheritableStatics: {
- def: {
- processors: {
- depth: "number"
- },
- defaults: {
- depth: 0
- }
- }
- },
- render_: function(c, d, f) {
- var b = this.attr,
- a = c.roundPixel(b.x),
- e = d.lineWidth * 0.5;
- d.beginPath();
- d.rect(a - e, f[1] - c.matrix.getDY(), b.width, f[3]);
- d.fill();
- d.beginPath();
- d.moveTo(a - e, f[1] - c.matrix.getDY());
- d.lineTo(a - e, f[1] + f[3] - c.matrix.getDY());
- d.stroke()
- },
- render: function(b, j, e) {
- var g = this.attr,
- i = b.roundPixel(g.x),
- k = b.matrix.getDY(),
- d = j.lineWidth * 0.5,
- a = g.width,
- f = g.depth,
- c, h;
- if (i >= e[2]) {
- return
- }
- c = i - d + f;
- h = e[1] - f - k;
- j.beginPath();
- j.rect(c, h, a, e[3]);
- j.fill();
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c, h + e[3]);
- j.stroke();
- c = i - d;
- h = e[3];
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c + f, h - f);
- j.lineTo(c + f + a, h - f);
- j.lineTo(c + a, h);
- j.closePath();
- j.fill();
- c = i - d;
- h = e[3];
- j.beginPath();
- j.moveTo(c, h);
- j.lineTo(c + f, h - f);
- j.stroke()
- }
-});
-Ext.define("Ext.chart.interactions.CrossZoom", {
- extend: "Ext.chart.interactions.Abstract",
- type: "crosszoom",
- alias: "interaction.crosszoom",
- isCrossZoom: true,
- config: {
- axes: true,
- gestures: {
- dragstart: "onGestureStart",
- drag: "onGesture",
- dragend: "onGestureEnd",
- dblclick: "onDoubleTap"
- },
- undoButton: {}
- },
- stopAnimationBeforeSync: false,
- zoomAnimationInProgress: false,
- constructor: function() {
- this.callParent(arguments);
- this.zoomHistory = []
- },
- applyAxes: function(b) {
- var a = {};
- if (b === true) {
- return {
- top: {},
- right: {},
- bottom: {},
- left: {}
- }
- } else {
- if (Ext.isArray(b)) {
- a = {};
- Ext.each(b, function(c) {
- a[c] = {}
- })
- } else {
- if (Ext.isObject(b)) {
- Ext.iterate(b, function(c, d) {
- if (d === true) {
- a[c] = {}
- } else {
- if (d !== false) {
- a[c] = d
- }
- }
- })
- }
- }
- }
- return a
- },
- applyUndoButton: function(b, a) {
- var c = this;
- if (a) {
- a.destroy()
- }
- if (b) {
- return Ext.create("Ext.Button", Ext.apply({
- cls: [],
- text: "Undo Zoom",
- disabled: true,
- handler: function() {
- c.undoZoom()
- }
- }, b))
- }
- },
- getSurface: function() {
- return this.getChart() && this.getChart().getSurface("main")
- },
- setSeriesOpacity: function(b) {
- var a = this.getChart() && this.getChart().getSurface("series");
- if (a) {
- a.element.setStyle("opacity", b)
- }
- },
- onGestureStart: function(h) {
- var j = this,
- i = j.getChart(),
- d = j.getSurface(),
- l = i.getInnerRect(),
- c = i.getInnerPadding(),
- g = c.left,
- b = g + l[2],
- f = c.top,
- a = f + l[3],
- n = i.getEventXY(h),
- m = n[0],
- k = n[1];
- if (j.zoomAnimationInProgress) {
- return
- }
- if (m > g && m < b && k > f && k < a) {
- j.gestureEvent = "drag";
- j.lockEvents(j.gestureEvent);
- j.startX = m;
- j.startY = k;
- j.selectionRect = d.add({
- type: "rect",
- globalAlpha: 0.5,
- fillStyle: "rgba(80,80,140,0.5)",
- strokeStyle: "rgba(80,80,140,1)",
- lineWidth: 2,
- x: m,
- y: k,
- width: 0,
- height: 0,
- zIndex: 10000
- });
- j.setSeriesOpacity(0.8);
- return false
- }
- },
- onGesture: function(h) {
- var j = this;
- if (j.zoomAnimationInProgress) {
- return
- }
- if (j.getLocks()[j.gestureEvent] === j) {
- var i = j.getChart(),
- d = j.getSurface(),
- l = i.getInnerRect(),
- c = i.getInnerPadding(),
- g = c.left,
- b = g + l[2],
- f = c.top,
- a = f + l[3],
- n = i.getEventXY(h),
- m = n[0],
- k = n[1];
- if (m < g) {
- m = g
- } else {
- if (m > b) {
- m = b
- }
- }
- if (k < f) {
- k = f
- } else {
- if (k > a) {
- k = a
- }
- }
- j.selectionRect.setAttributes({
- width: m - j.startX,
- height: k - j.startY
- });
- if (Math.abs(j.startX - m) < 11 || Math.abs(j.startY - k) < 11) {
- j.selectionRect.setAttributes({
- globalAlpha: 0.5
- })
- } else {
- j.selectionRect.setAttributes({
- globalAlpha: 1
- })
- }
- d.renderFrame();
- return false
- }
- },
- onGestureEnd: function(i) {
- var l = this;
- if (l.zoomAnimationInProgress) {
- return
- }
- if (l.getLocks()[l.gestureEvent] === l) {
- var k = l.getChart(),
- d = l.getSurface(),
- n = k.getInnerRect(),
- c = k.getInnerPadding(),
- g = c.left,
- b = g + n[2],
- f = c.top,
- a = f + n[3],
- h = n[2],
- j = n[3],
- p = k.getEventXY(i),
- o = p[0],
- m = p[1];
- if (o < g) {
- o = g
- } else {
- if (o > b) {
- o = b
- }
- }
- if (m < f) {
- m = f
- } else {
- if (m > a) {
- m = a
- }
- }
- if (Math.abs(l.startX - o) < 11 || Math.abs(l.startY - m) < 11) {
- d.remove(l.selectionRect)
- } else {
- l.zoomBy([Math.min(l.startX, o) / h, 1 - Math.max(l.startY, m) / j, Math.max(l.startX, o) / h, 1 - Math.min(l.startY, m) / j]);
- l.selectionRect.setAttributes({
- x: Math.min(l.startX, o),
- y: Math.min(l.startY, m),
- width: Math.abs(l.startX - o),
- height: Math.abs(l.startY - m)
- });
- l.selectionRect.setAnimation(k.getAnimation() || {
- duration: 0
- });
- l.selectionRect.setAttributes({
- globalAlpha: 0,
- x: 0,
- y: 0,
- width: h,
- height: j
- });
- l.zoomAnimationInProgress = true;
- k.suspendThicknessChanged();
- l.selectionRect.fx.on("animationend", function() {
- k.resumeThicknessChanged();
- d.remove(l.selectionRect);
- l.selectionRect = null;
- l.zoomAnimationInProgress = false
- })
- }
- d.renderFrame();
- l.sync();
- l.unlockEvents(l.gestureEvent);
- l.setSeriesOpacity(1);
- if (!l.zoomAnimationInProgress) {
- d.remove(l.selectionRect);
- l.selectionRect = null
- }
- }
- },
- zoomBy: function(o) {
- var n = this,
- a = n.getAxes(),
- k = n.getChart(),
- j = k.getAxes(),
- l = k.getInherited().rtl,
- f, d = {},
- c, b;
- if (l) {
- o = o.slice();
- c = 1 - o[0];
- b = 1 - o[2];
- o[0] = Math.min(c, b);
- o[2] = Math.max(c, b)
- }
- for (var h = 0; h < j.length; h++) {
- var g = j[h];
- f = a[g.getPosition()];
- if (f && f.allowZoom !== false) {
- var e = g.isSide(),
- m = g.getVisibleRange();
- d[g.getId()] = m.slice(0);
- if (!e) {
- g.setVisibleRange([(m[1] - m[0]) * o[0] + m[0], (m[1] - m[0]) * o[2] + m[0]])
- } else {
- g.setVisibleRange([(m[1] - m[0]) * o[1] + m[0], (m[1] - m[0]) * o[3] + m[0]])
- }
- }
- }
- n.zoomHistory.push(d);
- n.getUndoButton().setDisabled(false)
- },
- undoZoom: function() {
- var c = this.zoomHistory.pop(),
- d = this.getChart().getAxes();
- if (c) {
- for (var a = 0; a < d.length; a++) {
- var b = d[a];
- if (c[b.getId()]) {
- b.setVisibleRange(c[b.getId()])
- }
- }
- }
- this.getUndoButton().setDisabled(this.zoomHistory.length === 0);
- this.sync()
- },
- onDoubleTap: function(a) {
- this.undoZoom()
- },
- destroy: function() {
- this.setUndoButton(null);
- this.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.interactions.Crosshair", {
- extend: "Ext.chart.interactions.Abstract",
- requires: ["Ext.chart.grid.HorizontalGrid", "Ext.chart.grid.VerticalGrid", "Ext.chart.CartesianChart", "Ext.chart.axis.layout.Discrete"],
- type: "crosshair",
- alias: "interaction.crosshair",
- config: {
- axes: {
- top: {
- label: {},
- rect: {}
- },
- right: {
- label: {},
- rect: {}
- },
- bottom: {
- label: {},
- rect: {}
- },
- left: {
- label: {},
- rect: {}
- }
- },
- lines: {
- horizontal: {
- strokeStyle: "black",
- lineDash: [5, 5]
- },
- vertical: {
- strokeStyle: "black",
- lineDash: [5, 5]
- }
- },
- gesture: "drag"
- },
- applyAxes: function(b, a) {
- return Ext.merge(a || {}, b)
- },
- applyLines: function(a, b) {
- return Ext.merge(b || {}, a)
- },
- updateChart: function(a) {
- if (a && !a.isCartesian) {
- Ext.raise("Crosshair interaction can only be used on cartesian charts.")
- }
- this.callParent(arguments)
- },
- getGestures: function() {
- var a = this,
- b = {};
- b[a.getGesture()] = "onGesture";
- b[a.getGesture() + "start"] = "onGestureStart";
- b[a.getGesture() + "end"] = "onGestureEnd";
- return b
- },
- onGestureStart: function(N) {
- var m = this,
- O = m.getChart(),
- B = O.getTheme().getAxis(),
- A, F = O.getSurface("overlay"),
- s = O.getInnerRect(),
- n = s[2],
- M = s[3],
- r = O.getEventXY(N),
- D = r[0],
- C = r[1],
- E = O.getAxes(),
- u = m.getAxes(),
- h = m.getLines(),
- q, v, b, d, k, z, G, L, J, o, I, w, l, f, p, j, t, a, g, H, c, K;
- if (D > 0 && D < n && C > 0 && C < M) {
- m.lockEvents(m.getGesture());
- H = Ext.apply({
- xclass: "Ext.chart.grid.HorizontalGrid",
- x: 0,
- y: C,
- width: n
- }, h.horizontal);
- c = Ext.apply({
- xclass: "Ext.chart.grid.VerticalGrid",
- x: D,
- y: 0,
- height: M
- }, h.vertical);
- m.axesLabels = m.axesLabels || {};
- for (K = 0; K < E.length; K++) {
- q = E[K];
- v = q.getSurface();
- b = v.getRect();
- w = q.getSprites()[0];
- d = b[2];
- k = b[3];
- z = q.getPosition();
- G = q.getAlignment();
- t = q.getTitle();
- a = t && t.attr.text !== "" && t.getBBox();
- l = w.attr;
- f = w.thickness;
- p = l.axisLine ? l.lineWidth : 0;
- j = p / 2;
- I = Math.max(l.majorTickSize, l.minorTickSize) + p;
- L = m.axesLabels[z] = v.add({
- type: "composite"
- });
- L.labelRect = L.add(Ext.apply({
- type: "rect",
- fillStyle: "white",
- x: z === "right" ? p : 0,
- y: z === "bottom" ? p : 0,
- width: d - p - (G === "vertical" && a ? a.width : 0),
- height: k - p - (G === "horizontal" && a ? a.height : 0),
- translationX: z === "left" && a ? a.width : 0,
- translationY: z === "top" && a ? a.height : 0
- }, u.rect || u[z].rect));
- if (G === "vertical" && !c.strokeStyle) {
- c.strokeStyle = l.strokeStyle
- }
- if (G === "horizontal" && !H.strokeStyle) {
- H.strokeStyle = l.strokeStyle
- }
- A = Ext.merge({}, B.defaults, B[z]);
- J = Ext.apply({}, q.config.label, A.label);
- o = u.label || u[z].label;
- L.labelText = L.add(Ext.apply(J, o, {
- type: "text",
- x: (function() {
- switch (z) {
- case "left":
- g = a ? a.x + a.width : 0;
- return g + (d - g - I) / 2 - j;
- case "right":
- g = a ? d - a.x : 0;
- return I + (d - I - g) / 2 + j;
- default:
- return 0
- }
- })(),
- y: (function() {
- switch (z) {
- case "top":
- g = a ? a.y + a.height : 0;
- return g + (k - g - I) / 2 - j;
- case "bottom":
- g = a ? k - a.y : 0;
- return I + (k - I - g) / 2 + j;
- default:
- return 0
- }
- })()
- }))
- }
- m.horizontalLine = F.add(H);
- m.verticalLine = F.add(c);
- return false
- }
- },
- onGesture: function(G) {
- var K = this;
- if (K.getLocks()[K.getGesture()] !== K) {
- return
- }
- var u = K.getChart(),
- z = u.getSurface("overlay"),
- a = Ext.Array.slice(u.getInnerRect()),
- r = u.getInnerPadding(),
- t = r.left,
- q = r.top,
- E = a[2],
- f = a[3],
- d = u.getEventXY(G),
- k = d[0],
- j = d[1],
- D = u.getAxes(),
- c, h, m, p, J, w, I, H, s, b, C, g, v, n, l, A, F, o, B;
- if (k < 0) {
- k = 0
- } else {
- if (k > E) {
- k = E
- }
- }
- if (j < 0) {
- j = 0
- } else {
- if (j > f) {
- j = f
- }
- }
- k += t;
- j += q;
- for (B = 0; B < D.length; B++) {
- c = D[B];
- h = c.getPosition();
- m = c.getAlignment();
- p = c.getSurface();
- J = c.getSprites()[0];
- w = J.attr.matrix;
- C = J.attr.textPadding * 2;
- s = K.axesLabels[h];
- I = J.getLayoutContext();
- H = c.getSegmenter();
- if (s) {
- if (m === "vertical") {
- v = w.getYY();
- l = w.getDY();
- F = (j - l - q) / v;
- if (c.getLayout() instanceof Ext.chart.axis.layout.Discrete) {
- j = Math.round(F) * v + l + q;
- F = H.from(Math.round(F));
- F = J.attr.data[F]
- } else {
- F = H.from(F)
- }
- o = H.renderer(F, I);
- s.setAttributes({
- translationY: j - q
- });
- s.labelText.setAttributes({
- text: o
- });
- b = s.labelText.getBBox();
- s.labelRect.setAttributes({
- height: b.height + C,
- y: -(b.height + C) / 2
- });
- p.renderFrame()
- } else {
- g = w.getXX();
- n = w.getDX();
- A = (k - n - t) / g;
- if (c.getLayout() instanceof Ext.chart.axis.layout.Discrete) {
- k = Math.round(A) * g + n + t;
- A = H.from(Math.round(A));
- A = J.attr.data[A]
- } else {
- A = H.from(A)
- }
- o = H.renderer(A, I);
- s.setAttributes({
- translationX: k - t
- });
- s.labelText.setAttributes({
- text: o
- });
- b = s.labelText.getBBox();
- s.labelRect.setAttributes({
- width: b.width + C,
- x: -(b.width + C) / 2
- });
- p.renderFrame()
- }
- }
- }
- K.horizontalLine.setAttributes({
- y: j,
- strokeStyle: J.attr.strokeStyle
- });
- K.verticalLine.setAttributes({
- x: k,
- strokeStyle: J.attr.strokeStyle
- });
- z.renderFrame();
- return false
- },
- onGestureEnd: function(h) {
- var l = this,
- k = l.getChart(),
- a = k.getSurface("overlay"),
- j = k.getAxes(),
- c, g, d, b, f;
- a.remove(l.verticalLine);
- a.remove(l.horizontalLine);
- for (f = 0; f < j.length; f++) {
- c = j[f];
- g = c.getPosition();
- d = c.getSurface();
- b = l.axesLabels[g];
- if (b) {
- delete l.axesLabels[g];
- d.remove(b)
- }
- d.renderFrame()
- }
- a.renderFrame();
- l.unlockEvents(l.getGesture())
- }
-});
-Ext.define("Ext.chart.interactions.ItemHighlight", {
- extend: "Ext.chart.interactions.Abstract",
- type: "itemhighlight",
- alias: "interaction.itemhighlight",
- isItemHighlight: true,
- config: {
- gestures: {
- tap: "onTapGesture",
- mousemove: "onMouseMoveGesture",
- mousedown: "onMouseDownGesture",
- mouseup: "onMouseUpGesture",
- mouseleave: "onMouseUpGesture"
- },
- sticky: false
- },
- stickyHighlightItem: null,
- onMouseMoveGesture: function(g) {
- var d = this,
- h = d.tipItem,
- a = g.pointerType === "mouse",
- c, f, b;
- if (d.getSticky()) {
- return true
- }
- if (d.isDragging) {
- if (h && a) {
- h.series.hideTooltip(h);
- d.tipItem = null
- }
- } else {
- if (!d.stickyHighlightItem) {
- c = d.getItemForEvent(g);
- b = d.getChart();
- if (c !== b.getHighlightItem()) {
- d.highlight(c);
- d.sync()
- }
- if (a) {
- if (h && (!c || h.field !== c.field || h.record !== c.record)) {
- h.series.hideTooltip(h);
- d.tipItem = h = null
- }
- if (c && (f = c.series.getTooltip())) {
- if (f.trackMouse || !h) {
- c.series.showTooltip(c, g.getXY())
- }
- d.tipItem = c
- }
- }
- return false
- }
- }
- },
- highlight: function(a) {
- this.getChart().setHighlightItem(a)
- },
- showTooltip: function(b, a) {
- a.series.showTooltip(a, b.getXY());
- this.tipItem = a
- },
- onMouseDownGesture: function() {
- this.isDragging = true
- },
- onMouseUpGesture: function() {
- this.isDragging = false
- },
- onTapGesture: function(c) {
- var b = this;
- if (c.pointerType === "mouse" && !b.getSticky()) {
- return
- }
- var a = b.getItemForEvent(c);
- if (b.stickyHighlightItem && a && (b.stickyHighlightItem.index === a.index)) {
- a = null
- }
- b.stickyHighlightItem = a;
- b.highlight(a)
- }
-});
-Ext.define("Ext.chart.interactions.ItemEdit", {
- extend: "Ext.chart.interactions.ItemHighlight",
- requires: ["Ext.tip.ToolTip"],
- type: "itemedit",
- alias: "interaction.itemedit",
- isItemEdit: true,
- config: {
- style: null,
- renderer: null,
- tooltip: true,
- gestures: {
- dragstart: "onDragStart",
- drag: "onDrag",
- dragend: "onDragEnd"
- },
- cursors: {
- ewResize: "ew-resize",
- nsResize: "ns-resize",
- move: "move"
- }
- },
- item: null,
- applyTooltip: function(b) {
- if (b) {
- var a = Ext.apply({}, b, {
- renderer: this.defaultTooltipRenderer,
- constrainPosition: true,
- shrinkWrapDock: true,
- autoHide: true,
- offsetX: 10,
- offsetY: 10
- });
- b = new Ext.tip.ToolTip(a)
- }
- return b
- },
- defaultTooltipRenderer: function(b, a, f, d) {
- var c = [];
- if (f.xField) {
- c.push(f.xField + ": " + f.xValue)
- }
- if (f.yField) {
- c.push(f.yField + ": " + f.yValue)
- }
- b.setHtml(c.join(" "))
- },
- onDragStart: function(d) {
- var c = this,
- a = c.getChart(),
- b = a.getHighlightItem();
- if (b) {
- a.fireEvent("beginitemedit", a, c, c.item = b);
- return false
- }
- },
- onDrag: function(f) {
- var d = this,
- b = d.getChart(),
- c = b.getHighlightItem(),
- a = c && c.sprite.type;
- if (c) {
- switch (a) {
- case "barSeries":
- return d.onDragBar(f);
- break;
- case "scatterSeries":
- return d.onDragScatter(f);
- break
- }
- }
- },
- highlight: function(f) {
- var e = this,
- d = e.getChart(),
- a = d.getFlipXY(),
- g = e.getCursors(),
- c = f && f.sprite.type,
- b = d.el.dom.style;
- e.callParent([f]);
- if (f) {
- switch (c) {
- case "barSeries":
- if (a) {
- b.cursor = g.ewResize
- } else {
- b.cursor = g.nsResize
- }
- break;
- case "scatterSeries":
- b.cursor = g.move;
- break
- }
- } else {
- d.el.dom.style.cursor = "default"
- }
- },
- onDragBar: function(i) {
- var m = this,
- k = m.getChart(),
- l = k.getInherited().rtl,
- f = k.isCartesian && k.getFlipXY(),
- q = k.getHighlightItem(),
- g = q.sprite.getMarker("items"),
- p = g.getMarkerFor(q.sprite.getId(), q.index),
- b = q.sprite.getSurface(),
- c = b.getRect(),
- r = b.getEventXY(i),
- o = q.sprite.attr.matrix,
- j = m.getRenderer(),
- a, n, d, h;
- if (f) {
- h = l ? c[2] - r[0] : r[0]
- } else {
- h = c[3] - r[1]
- }
- a = {
- x: p.x,
- y: h,
- width: p.width,
- height: p.height + (p.y - h),
- radius: p.radius,
- fillStyle: "none",
- lineDash: [4, 4],
- zIndex: 100
- };
- Ext.apply(a, m.getStyle());
- if (Ext.isArray(q.series.getYField())) {
- h = h - p.y - p.height
- }
- m.target = {
- index: q.index,
- yField: q.field,
- yValue: (h - o.getDY()) / o.getYY()
- };
- d = [k, {
- target: m.target,
- style: a,
- item: q
- }];
- n = Ext.callback(j, null, d, 0, k);
- if (n) {
- Ext.apply(a, n)
- }
- q.sprite.putMarker("items", a, "itemedit");
- m.showTooltip(i, m.target, q);
- b.renderFrame()
- },
- onDragScatter: function(n) {
- var t = this,
- g = t.getChart(),
- d = g.getInherited().rtl,
- l = g.isCartesian && g.getFlipXY(),
- o = g.getHighlightItem(),
- b = o.sprite.getMarker("items"),
- p = b.getMarkerFor(o.sprite.getId(), o.index),
- j = o.sprite.getSurface(),
- h = j.getRect(),
- a = j.getEventXY(n),
- k = o.sprite.attr.matrix,
- c = o.series.getXAxis(),
- f = c && c.getLayout().isContinuous,
- i = t.getRenderer(),
- m, u, q, s, r;
- if (l) {
- r = d ? h[2] - a[0] : a[0]
- } else {
- r = h[3] - a[1]
- }
- if (f) {
- if (l) {
- s = h[3] - a[1]
- } else {
- s = a[0]
- }
- } else {
- s = p.translationX
- }
- m = {
- translationX: s,
- translationY: r,
- scalingX: p.scalingX,
- scalingY: p.scalingY,
- r: p.r,
- fillStyle: "none",
- lineDash: [4, 4],
- zIndex: 100
- };
- Ext.apply(m, t.getStyle());
- t.target = {
- index: o.index,
- yField: o.field,
- yValue: (r - k.getDY()) / k.getYY()
- };
- if (f) {
- Ext.apply(t.target, {
- xField: o.series.getXField(),
- xValue: (s - k.getDX()) / k.getXX()
- })
- }
- q = [g, {
- target: t.target,
- style: m,
- item: o
- }];
- u = Ext.callback(i, null, q, 0, g);
- if (u) {
- Ext.apply(m, u)
- }
- o.sprite.putMarker("items", m, "itemedit");
- t.showTooltip(n, t.target, o);
- j.renderFrame()
- },
- showTooltip: function(g, f, c) {
- var d = this.getTooltip(),
- a, b;
- if (d && Ext.toolkit !== "modern") {
- a = d.config;
- b = this.getChart();
- Ext.callback(a.renderer, null, [d, c, f, g], 0, b);
- d.show([g.x + a.offsetX, g.y + a.offsetY])
- }
- },
- hideTooltip: function() {
- var a = this.getTooltip();
- if (a && Ext.toolkit !== "modern") {
- a.hide()
- }
- },
- onDragEnd: function(g) {
- var d = this,
- f = d.target,
- c = d.getChart(),
- b = c.getStore(),
- a;
- if (f) {
- a = b.getAt(f.index);
- if (f.yField) {
- a.set(f.yField, f.yValue, {
- convert: false
- })
- }
- if (f.xField) {
- a.set(f.xField, f.xValue, {
- convert: false
- })
- }
- if (f.yField || f.xField) {
- d.getChart().onDataChanged()
- }
- d.target = null
- }
- d.hideTooltip();
- if (d.item) {
- c.fireEvent("enditemedit", c, d, d.item, f)
- }
- d.highlight(d.item = null)
- },
- destroy: function() {
- var a = this.getConfig("tooltip", true);
- Ext.destroy(a);
- this.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.PanZoom", {
- extend: "Ext.chart.interactions.Abstract",
- type: "panzoom",
- alias: "interaction.panzoom",
- requires: ["Ext.draw.Animator"],
- config: {
- axes: {
- top: {},
- right: {},
- bottom: {},
- left: {}
- },
- minZoom: null,
- maxZoom: null,
- showOverflowArrows: true,
- panGesture: "drag",
- zoomGesture: "pinch",
- zoomOnPanGesture: false,
- modeToggleButton: {
- xtype: "segmentedbutton",
- width: 200,
- defaults: {
- ui: "default-toolbar"
- },
- cls: Ext.baseCSSPrefix + "panzoom-toggle",
- items: [{
- text: "Pan"
- }, {
- text: "Zoom"
- }]
- },
- hideLabelInGesture: false
- },
- stopAnimationBeforeSync: true,
- applyAxes: function(b, a) {
- return Ext.merge(a || {}, b)
- },
- applyZoomOnPanGesture: function(a) {
- this.getChart();
- if (this.isMultiTouch()) {
- return false
- }
- return a
- },
- updateZoomOnPanGesture: function(b) {
- var a = this.getModeToggleButton();
- if (!this.isMultiTouch()) {
- a.show();
- a.setValue(b ? 1 : 0)
- } else {
- a.hide()
- }
- },
- toggleMode: function() {
- var a = this;
- if (!a.isMultiTouch()) {
- a.setZoomOnPanGesture(!a.getZoomOnPanGesture())
- }
- },
- applyModeToggleButton: function(c, b) {
- var d = this,
- a = Ext.factory(c, "Ext.button.Segmented", b);
- if (!a && b) {
- b.destroy()
- }
- if (a && !b) {
- a.addListener("toggle", function(e) {
- d.setZoomOnPanGesture(e.getValue() === 1)
- })
- }
- return a
- },
- getGestures: function() {
- var c = this,
- e = {},
- d = c.getPanGesture(),
- b = c.getZoomGesture(),
- a = Ext.supports.Touch;
- e[b] = "onZoomGestureMove";
- e[b + "start"] = "onZoomGestureStart";
- e[b + "end"] = "onZoomGestureEnd";
- e[d] = "onPanGestureMove";
- e[d + "start"] = "onPanGestureStart";
- e[d + "end"] = "onPanGestureEnd";
- e.doubletap = "onDoubleTap";
- return e
- },
- onDoubleTap: function(h) {
- var f = this,
- c = f.getChart(),
- g = c.getAxes(),
- b, a, d;
- for (a = 0, d = g.length; a < d; a++) {
- b = g[a];
- b.setVisibleRange([0, 1])
- }
- c.redraw()
- },
- onPanGestureStart: function(d) {
- if (!d || !d.touches || d.touches.length < 2) {
- var b = this,
- a = b.getChart().getInnerRect(),
- c = b.getChart().element.getXY();
- b.startX = d.getX() - c[0] - a[0];
- b.startY = d.getY() - c[1] - a[1];
- b.oldVisibleRanges = null;
- b.hideLabels();
- b.getChart().suspendThicknessChanged();
- b.lockEvents(b.getPanGesture());
- return false
- }
- },
- onPanGestureMove: function(d) {
- var b = this;
- if (b.getLocks()[b.getPanGesture()] === b) {
- var a = b.getChart().getInnerRect(),
- c = b.getChart().element.getXY();
- if (b.getZoomOnPanGesture()) {
- b.transformAxesBy(b.getZoomableAxes(d), 0, 0, (d.getX() - c[0] - a[0]) / b.startX, b.startY / (d.getY() - c[1] - a[1]))
- } else {
- b.transformAxesBy(b.getPannableAxes(d), d.getX() - c[0] - a[0] - b.startX, d.getY() - c[1] - a[1] - b.startY, 1, 1)
- }
- b.sync();
- return false
- }
- },
- onPanGestureEnd: function(b) {
- var a = this,
- c = a.getPanGesture();
- if (a.getLocks()[c] === a) {
- a.getChart().resumeThicknessChanged();
- a.showLabels();
- a.sync();
- a.unlockEvents(c);
- return false
- }
- },
- onZoomGestureStart: function(b) {
- if (b.touches && b.touches.length === 2) {
- var c = this,
- i = c.getChart().element.getXY(),
- f = c.getChart().getInnerRect(),
- h = i[0] + f[0],
- d = i[1] + f[1],
- j = [b.touches[0].point.x - h, b.touches[0].point.y - d, b.touches[1].point.x - h, b.touches[1].point.y - d],
- g = Math.max(44, Math.abs(j[2] - j[0])),
- a = Math.max(44, Math.abs(j[3] - j[1]));
- c.getChart().suspendThicknessChanged();
- c.lastZoomDistances = [g, a];
- c.lastPoints = j;
- c.oldVisibleRanges = null;
- c.hideLabels();
- c.lockEvents(c.getZoomGesture());
- return false
- }
- },
- onZoomGestureMove: function(d) {
- var f = this;
- if (f.getLocks()[f.getZoomGesture()] === f) {
- var i = f.getChart().getInnerRect(),
- n = f.getChart().element.getXY(),
- k = n[0] + i[0],
- h = n[1] + i[1],
- o = Math.abs,
- c = f.lastPoints,
- m = [d.touches[0].point.x - k, d.touches[0].point.y - h, d.touches[1].point.x - k, d.touches[1].point.y - h],
- g = Math.max(44, o(m[2] - m[0])),
- b = Math.max(44, o(m[3] - m[1])),
- a = this.lastZoomDistances || [g, b],
- l = g / a[0],
- j = b / a[1];
- f.transformAxesBy(f.getZoomableAxes(d), i[2] * (l - 1) / 2 + m[2] - c[2] * l, i[3] * (j - 1) / 2 + m[3] - c[3] * j, l, j);
- f.sync();
- return false
- }
- },
- onZoomGestureEnd: function(c) {
- var b = this,
- a = b.getZoomGesture();
- if (b.getLocks()[a] === b) {
- b.getChart().resumeThicknessChanged();
- b.showLabels();
- b.sync();
- b.unlockEvents(a);
- return false
- }
- },
- hideLabels: function() {
- if (this.getHideLabelInGesture()) {
- this.eachInteractiveAxes(function(a) {
- a.hideLabels()
- })
- }
- },
- showLabels: function() {
- if (this.getHideLabelInGesture()) {
- this.eachInteractiveAxes(function(a) {
- a.showLabels()
- })
- }
- },
- isEventOnAxis: function(c, a) {
- var b = a.getSurface().getRect();
- return b[0] <= c.getX() && c.getX() <= b[0] + b[2] && b[1] <= c.getY() && c.getY() <= b[1] + b[3]
- },
- getPannableAxes: function(d) {
- var h = this,
- a = h.getAxes(),
- f = h.getChart().getAxes(),
- c, g = f.length,
- k = [],
- j = false,
- b;
- if (d) {
- for (c = 0; c < g; c++) {
- if (this.isEventOnAxis(d, f[c])) {
- j = true;
- break
- }
- }
- }
- for (c = 0; c < g; c++) {
- b = a[f[c].getPosition()];
- if (b && b.allowPan !== false && (!j || this.isEventOnAxis(d, f[c]))) {
- k.push(f[c])
- }
- }
- return k
- },
- getZoomableAxes: function(f) {
- var j = this,
- a = j.getAxes(),
- g = j.getChart().getAxes(),
- l = [],
- d, h = g.length,
- c, k = false,
- b;
- if (f) {
- for (d = 0; d < h; d++) {
- if (this.isEventOnAxis(f, g[d])) {
- k = true;
- break
- }
- }
- }
- for (d = 0; d < h; d++) {
- c = g[d];
- b = a[c.getPosition()];
- if (b && b.allowZoom !== false && (!k || this.isEventOnAxis(f, c))) {
- l.push(c)
- }
- }
- return l
- },
- eachInteractiveAxes: function(c) {
- var d = this,
- b = d.getAxes(),
- e = d.getChart().getAxes();
- for (var a = 0; a < e.length; a++) {
- if (b[e[a].getPosition()]) {
- if (false === c.call(this, e[a])) {
- return
- }
- }
- }
- },
- transformAxesBy: function(d, j, g, h, e) {
- var f = this.getChart().getInnerRect(),
- a = this.getAxes(),
- k, b = this.oldVisibleRanges,
- l = false;
- if (!b) {
- this.oldVisibleRanges = b = {};
- this.eachInteractiveAxes(function(i) {
- b[i.getId()] = i.getVisibleRange()
- })
- }
- if (!f) {
- return
- }
- for (var c = 0; c < d.length; c++) {
- k = a[d[c].getPosition()];
- l = this.transformAxisBy(d[c], b[d[c].getId()], j, g, h, e, this.minZoom || k.minZoom, this.maxZoom || k.maxZoom) || l
- }
- return l
- },
- transformAxisBy: function(c, o, r, q, k, i, h, m) {
- var s = this,
- b = o[1] - o[0],
- l = c.getVisibleRange(),
- g = h || s.getMinZoom() || c.config.minZoom,
- j = m || s.getMaxZoom() || c.config.maxZoom,
- a = s.getChart().getInnerRect(),
- f, p;
- if (!a) {
- return
- }
- var d = c.isSide(),
- e = d ? a[3] : a[2],
- n = d ? -q : r;
- b /= d ? i : k;
- if (b < 0) {
- b = -b
- }
- if (b * g > 1) {
- b = 1
- }
- if (b * j < 1) {
- b = 1 / j
- }
- f = o[0];
- p = o[1];
- l = l[1] - l[0];
- if (b === l && l === 1) {
- return
- }
- c.setVisibleRange([(o[0] + o[1] - b) * 0.5 - n / e * b, (o[0] + o[1] + b) * 0.5 - n / e * b]);
- return (Math.abs(f - c.getVisibleRange()[0]) > 1e-10 || Math.abs(p - c.getVisibleRange()[1]) > 1e-10)
- },
- destroy: function() {
- this.setModeToggleButton(null);
- this.callParent()
- }
-});
-Ext.define("Ext.chart.interactions.Rotate", {
- extend: "Ext.chart.interactions.Abstract",
- type: "rotate",
- alias: "interaction.rotate",
- config: {
- gesture: "rotate",
- gestures: {
- rotate: "onRotate",
- rotateend: "onRotate",
- dragstart: "onGestureStart",
- drag: "onGesture",
- dragend: "onGestureEnd"
- },
- rotation: 0
- },
- oldRotations: null,
- getAngle: function(f) {
- var c = this,
- b = c.getChart(),
- d = b.getEventXY(f),
- a = b.getCenter();
- return Math.atan2(d[1] - a[1], d[0] - a[0])
- },
- getRadius: function(a) {
- return this.getChart().getRadius()
- },
- getEventRadius: function(h) {
- var f = this,
- d = f.getChart(),
- g = d.getEventXY(h),
- a = d.getCenter(),
- c = g[0] - a[0],
- b = g[1] - a[1];
- return Math.sqrt(c * c + b * b)
- },
- onGestureStart: function(d) {
- var c = this,
- b = c.getRadius(d),
- a = c.getEventRadius(d);
- if (b >= a) {
- c.lockEvents("drag");
- c.angle = c.getAngle(d);
- c.oldRotations = {};
- return false
- }
- },
- onGesture: function(b) {
- var a = this,
- c = a.getAngle(b) - a.angle;
- if (a.getLocks().drag === a) {
- a.doRotateTo(c, true);
- return false
- }
- },
- doRotateTo: function(d, a, b) {
- var n = this,
- l = n.getChart(),
- k = l.getAxes(),
- f = l.getSeries(),
- m = n.oldRotations,
- c, j, g, e, h;
- if (!b) {
- l.suspendAnimation()
- }
- for (e = 0, h = k.length; e < h; e++) {
- c = k[e];
- g = m[c.getId()] || (m[c.getId()] = c.getRotation());
- c.setRotation(d + (a ? g : 0))
- }
- for (e = 0, h = f.length; e < h; e++) {
- j = f[e];
- g = m[j.getId()] || (m[j.getId()] = j.getRotation());
- j.setRotation(d + (a ? g : 0))
- }
- n.setRotation(d + (a ? g : 0));
- n.fireEvent("rotate", n, n.getRotation());
- n.sync();
- if (!b) {
- l.resumeAnimation()
- }
- },
- rotateTo: function(c, b, a) {
- this.doRotateTo(c, b, a);
- this.oldRotations = {}
- },
- onGestureEnd: function(b) {
- var a = this;
- if (a.getLocks().drag === a) {
- a.onGesture(b);
- a.unlockEvents("drag");
- a.fireEvent("rotationEnd", a, a.getRotation());
- return false
- }
- },
- onRotate: function(a) {}
-});
-Ext.define("Ext.chart.interactions.RotatePie3D", {
- extend: "Ext.chart.interactions.Rotate",
- type: "rotatePie3d",
- alias: "interaction.rotatePie3d",
- getAngle: function(g) {
- var a = this.getChart(),
- f = a.getInherited().rtl,
- d = f ? -1 : 1,
- h = g.getXY(),
- c = a.element.getXY(),
- b = a.getMainRect();
- return d * Math.atan2(h[1] - c[1] - b[3] * 0.5, h[0] - c[0] - b[2] * 0.5)
- },
- getRadius: function(j) {
- var f = this.getChart(),
- a = f.getRadius(),
- d = f.getSeries(),
- h = d.length,
- c = 0,
- b, g;
- for (; c < h; c++) {
- b = d[c];
- if (b.isPie3D) {
- g = b.getRadius();
- if (g > a) {
- a = g
- }
- }
- }
- return a
- }
-});
-Ext.define("Ext.chart.plugin.ItemEvents", {
- extend: "Ext.plugin.Abstract",
- alias: "plugin.chartitemevents",
- moveEvents: false,
- mouseMoveEvents: {
- mousemove: true,
- mouseover: true,
- mouseout: true
- },
- itemMouseMoveEvents: {
- itemmousemove: true,
- itemmouseover: true,
- itemmouseout: true
- },
- init: function(b) {
- var a = "handleEvent";
- this.chart = b;
- b.addElementListener({
- click: a,
- dblclick: a,
- mousedown: a,
- mousemove: a,
- mouseup: a,
- mouseover: a,
- mouseout: a,
- priority: 1001,
- scope: this
- })
- },
- hasItemMouseMoveListeners: function() {
- var b = this.chart.hasListeners,
- a;
- for (a in this.itemMouseMoveEvents) {
- if (a in b) {
- return true
- }
- }
- return false
- },
- handleEvent: function(g) {
- var d = this,
- a = d.chart,
- h = g.type in d.mouseMoveEvents,
- c = d.lastItem,
- f, b;
- if (h && !d.hasItemMouseMoveListeners() && !d.moveEvents) {
- return
- }
- f = a.getEventXY(g);
- b = a.getItemForPoint(f[0], f[1]);
- if (h && !Ext.Object.equals(b, c)) {
- if (c) {
- a.fireEvent("itemmouseout", a, c, g);
- c.series.fireEvent("itemmouseout", c.series, c, g)
- }
- if (b) {
- a.fireEvent("itemmouseover", a, b, g);
- b.series.fireEvent("itemmouseover", b.series, b, g)
- }
- }
- if (b) {
- a.fireEvent("item" + g.type, a, b, g);
- b.series.fireEvent("item" + g.type, b.series, b, g)
- }
- d.lastItem = b
- }
-});
-Ext.define("Ext.chart.series.Cartesian", {
- extend: "Ext.chart.series.Series",
- config: {
- xField: null,
- yField: null,
- xAxis: null,
- yAxis: null
- },
- directions: ["X", "Y"],
- fieldCategoryX: ["X"],
- fieldCategoryY: ["Y"],
- applyXAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- applyYAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- updateXAxis: function(a) {
- a.processData(this)
- },
- updateYAxis: function(a) {
- a.processData(this)
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- getItemForPoint: function(a, g) {
- if (this.getSprites()) {
- var f = this,
- d = f.getSprites()[0],
- b = f.getStore(),
- e, c;
- if (f.getHidden()) {
- return null
- }
- if (d) {
- c = d.getIndexNearPoint(a, g);
- if (c !== -1) {
- e = {
- series: f,
- category: f.getItemInstancing() ? "items" : "markers",
- index: c,
- record: b.getData().items[c],
- field: f.getYField(),
- sprite: d
- };
- return e
- }
- }
- }
- },
- createSprite: function() {
- var c = this,
- a = c.callParent(),
- b = c.getChart(),
- d = c.getXAxis();
- a.setAttributes({
- flipXY: b.getFlipXY(),
- xAxis: d
- });
- if (a.setAggregator && d && d.getAggregator) {
- if (d.getAggregator) {
- a.setAggregator({
- strategy: d.getAggregator()
- })
- } else {
- a.setAggregator({})
- }
- }
- return a
- },
- getSprites: function() {
- var d = this,
- c = this.getChart(),
- e = d.getAnimation() || c && c.getAnimation(),
- b = d.getItemInstancing(),
- f = d.sprites,
- a;
- if (!c) {
- return []
- }
- if (!f.length) {
- a = d.createSprite()
- } else {
- a = f[0]
- }
- if (e) {
- if (b) {
- a.itemsMarker.getTemplate().setAnimation(e)
- }
- a.setAnimation(e)
- }
- return f
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getSubStyleWithTheme(),
- c = a.fillStyle;
- if (Ext.isArray(c)) {
- c = c[0]
- }
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- },
- getXRange: function() {
- return [this.dataRange[0], this.dataRange[2]]
- },
- getYRange: function() {
- return [this.dataRange[1], this.dataRange[3]]
- }
-});
-Ext.define("Ext.chart.series.StackedCartesian", {
- extend: "Ext.chart.series.Cartesian",
- config: {
- stacked: true,
- splitStacks: true,
- fullStack: false,
- fullStackTotal: 100,
- hidden: []
- },
- spriteAnimationCount: 0,
- themeColorCount: function() {
- var b = this,
- a = b.getYField();
- return Ext.isArray(a) ? a.length : 1
- },
- updateStacked: function() {
- this.processData()
- },
- updateSplitStacks: function() {
- this.processData()
- },
- coordinateY: function() {
- return this.coordinateStacked("Y", 1, 2)
- },
- coordinateStacked: function(D, e, m) {
- var F = this,
- f = F.getStore(),
- r = f.getData().items,
- B = r.length,
- c = F["get" + D + "Axis"](),
- x = F.getHidden(),
- a = F.getSplitStacks(),
- z = F.getFullStack(),
- l = F.getFullStackTotal(),
- p = {
- min: 0,
- max: 0
- },
- n = F["fieldCategory" + D],
- C = [],
- o = [],
- E = [],
- h, A = F.getStacked(),
- g = F.getSprites(),
- q = [],
- w, v, u, s, H, y, b, d, G, t;
- if (!g.length) {
- return
- }
- for (w = 0; w < n.length; w++) {
- d = n[w];
- s = F.getFields([d]);
- H = s.length;
- for (v = 0; v < B; v++) {
- C[v] = 0;
- o[v] = 0;
- E[v] = 0
- }
- for (v = 0; v < H; v++) {
- if (!x[v]) {
- q[v] = F.coordinateData(r, s[v], c)
- }
- }
- if (A && z) {
- y = [];
- if (a) {
- b = []
- }
- for (v = 0; v < B; v++) {
- y[v] = 0;
- if (a) {
- b[v] = 0
- }
- for (u = 0; u < H; u++) {
- G = q[u];
- if (!G) {
- continue
- }
- G = G[v];
- if (G >= 0 || !a) {
- y[v] += G
- } else {
- if (G < 0) {
- b[v] += G
- }
- }
- }
- }
- }
- for (v = 0; v < H; v++) {
- t = {};
- if (x[v]) {
- t["dataStart" + d] = C;
- t["data" + d] = C;
- g[v].setAttributes(t);
- continue
- }
- G = q[v];
- if (A) {
- h = [];
- for (u = 0; u < B; u++) {
- if (!G[u]) {
- G[u] = 0
- }
- if (G[u] >= 0 || !a) {
- if (z && y[u]) {
- G[u] *= l / y[u]
- }
- C[u] = o[u];
- o[u] += G[u];
- h[u] = o[u]
- } else {
- if (z && b[u]) {
- G[u] *= l / b[u]
- }
- C[u] = E[u];
- E[u] += G[u];
- h[u] = E[u]
- }
- }
- t["dataStart" + d] = C;
- t["data" + d] = h;
- F.getRangeOfData(C, p);
- F.getRangeOfData(h, p)
- } else {
- t["dataStart" + d] = C;
- t["data" + d] = G;
- F.getRangeOfData(G, p)
- }
- g[v].setAttributes(t)
- }
- }
- F.dataRange[e] = p.min;
- F.dataRange[e + m] = p.max;
- t = {};
- t["dataMin" + D] = p.min;
- t["dataMax" + D] = p.max;
- for (w = 0; w < g.length; w++) {
- g[w].setAttributes(t)
- }
- },
- getFields: function(f) {
- var e = this,
- a = [],
- c, b, d;
- for (b = 0, d = f.length; b < d; b++) {
- c = e["get" + f[b] + "Field"]();
- if (Ext.isArray(c)) {
- a.push.apply(a, c)
- } else {
- a.push(c)
- }
- }
- return a
- },
- updateLabelOverflowPadding: function(a) {
- this.getLabel().setAttributes({
- labelOverflowPadding: a
- })
- },
- getSprites: function() {
- var k = this,
- j = k.getChart(),
- c = k.getAnimation() || j && j.getAnimation(),
- f = k.getFields(k.fieldCategoryY),
- b = k.getItemInstancing(),
- h = k.sprites,
- l, e = k.getHidden(),
- g = false,
- d, a = f.length;
- if (!j) {
- return []
- }
- for (d = 0; d < a; d++) {
- l = h[d];
- if (!l) {
- l = k.createSprite();
- l.setAttributes({
- zIndex: -d
- });
- l.setField(f[d]);
- g = true;
- e.push(false);
- if (b) {
- l.itemsMarker.getTemplate().setAttributes(k.getStyleByIndex(d))
- } else {
- l.setAttributes(k.getStyleByIndex(d))
- }
- }
- if (c) {
- if (b) {
- l.itemsMarker.getTemplate().setAnimation(c)
- }
- l.setAnimation(c)
- }
- }
- if (g) {
- k.updateHidden(e)
- }
- return h
- },
- getItemForPoint: function(k, j) {
- if (this.getSprites()) {
- var h = this,
- b, g, m, a = h.getItemInstancing(),
- f = h.getSprites(),
- l = h.getStore(),
- c = h.getHidden(),
- n, d, e;
- for (b = 0, g = f.length; b < g; b++) {
- if (!c[b]) {
- m = f[b];
- d = m.getIndexNearPoint(k, j);
- if (d !== -1) {
- e = h.getYField();
- n = {
- series: h,
- index: d,
- category: a ? "items" : "markers",
- record: l.getData().items[d],
- field: typeof e === "string" ? e : e[b],
- sprite: m
- };
- return n
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(e) {
- var g = this,
- f = g.getSprites(),
- h = g.getTitle(),
- j = g.getYField(),
- d = g.getHidden(),
- k = f.length === 1,
- b, l, c, a;
- for (c = 0; c < f.length; c++) {
- b = g.getStyleByIndex(c);
- l = b.fillStyle;
- if (h) {
- if (Ext.isArray(h)) {
- a = h[c]
- } else {
- if (k) {
- a = h
- }
- }
- } else {
- if (Ext.isArray(j)) {
- a = j[c]
- } else {
- a = g.getId()
- }
- }
- e.push({
- name: a,
- mark: (Ext.isObject(l) ? l.stops && l.stops[0].color : l) || b.strokeStyle || "black",
- disabled: d[c],
- series: g.getId(),
- index: c
- })
- }
- },
- onSpriteAnimationStart: function(a) {
- this.spriteAnimationCount++;
- if (this.spriteAnimationCount === 1) {
- this.fireEvent("animationstart")
- }
- },
- onSpriteAnimationEnd: function(a) {
- this.spriteAnimationCount--;
- if (this.spriteAnimationCount === 0) {
- this.fireEvent("animationend")
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Series", {
- extend: "Ext.draw.sprite.Sprite",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- inheritableStatics: {
- def: {
- processors: {
- dataMinX: "number",
- dataMaxX: "number",
- dataMinY: "number",
- dataMaxY: "number",
- rangeX: "data",
- rangeY: "data",
- dataX: "data",
- dataY: "data"
- },
- defaults: {
- dataMinX: 0,
- dataMaxX: 1,
- dataMinY: 0,
- dataMaxY: 1,
- rangeX: null,
- rangeY: null,
- dataX: null,
- dataY: null
- },
- triggers: {
- dataX: "bbox",
- dataY: "bbox",
- dataMinX: "bbox",
- dataMaxX: "bbox",
- dataMinY: "bbox",
- dataMaxY: "bbox"
- }
- }
- },
- config: {
- store: null,
- series: null,
- field: null
- }
-});
-Ext.define("Ext.chart.series.sprite.Cartesian", {
- extend: "Ext.chart.series.sprite.Series",
- inheritableStatics: {
- def: {
- processors: {
- labels: "default",
- labelOverflowPadding: "number",
- selectionTolerance: "number",
- flipXY: "bool",
- renderer: "default",
- visibleMinX: "number",
- visibleMinY: "number",
- visibleMaxX: "number",
- visibleMaxY: "number",
- innerWidth: "number",
- innerHeight: "number"
- },
- defaults: {
- labels: null,
- labelOverflowPadding: 10,
- selectionTolerance: 20,
- flipXY: false,
- renderer: null,
- transformFillStroke: false,
- visibleMinX: 0,
- visibleMinY: 0,
- visibleMaxX: 1,
- visibleMaxY: 1,
- innerWidth: 1,
- innerHeight: 1
- },
- triggers: {
- dataX: "dataX,bbox",
- dataY: "dataY,bbox",
- visibleMinX: "panzoom",
- visibleMinY: "panzoom",
- visibleMaxX: "panzoom",
- visibleMaxY: "panzoom",
- innerWidth: "panzoom",
- innerHeight: "panzoom"
- },
- updaters: {
- dataX: function(a) {
- this.processDataX();
- this.scheduleUpdater(a, "dataY", ["dataY"])
- },
- dataY: function() {
- this.processDataY()
- },
- panzoom: function(c) {
- var e = c.visibleMaxX - c.visibleMinX,
- d = c.visibleMaxY - c.visibleMinY,
- b = c.flipXY ? c.innerHeight : c.innerWidth,
- g = !c.flipXY ? c.innerHeight : c.innerWidth,
- a = this.getSurface(),
- f = a ? a.getInherited().rtl : false;
- if (f && !c.flipXY) {
- c.translationX = b + c.visibleMinX * b / e
- } else {
- c.translationX = -c.visibleMinX * b / e
- }
- c.translationY = -c.visibleMinY * g / d;
- c.scalingX = (f && !c.flipXY ? -1 : 1) * b / e;
- c.scalingY = g / d;
- c.scalingCenterX = 0;
- c.scalingCenterY = 0;
- this.applyTransformations(true)
- }
- }
- }
- },
- processDataY: Ext.emptyFn,
- processDataX: Ext.emptyFn,
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.dataMinX;
- b.y = a.dataMinY;
- b.width = a.dataMaxX - a.dataMinX;
- b.height = a.dataMaxY - a.dataMinY
- },
- binarySearch: function(d) {
- var b = this.attr.dataX,
- f = 0,
- a = b.length;
- if (d <= b[0]) {
- return f
- }
- if (d >= b[a - 1]) {
- return a - 1
- }
- while (f + 1 < a) {
- var c = (f + a) >> 1,
- e = b[c];
- if (e === d) {
- return c
- } else {
- if (e < d) {
- f = c
- } else {
- a = c
- }
- }
- }
- return f
- },
- render: function(b, c, g) {
- var f = this,
- a = f.attr,
- e = a.inverseMatrix.clone();
- e.appendMatrix(b.inverseMatrix);
- if (a.dataX === null || a.dataX === undefined) {
- return
- }
- if (a.dataY === null || a.dataY === undefined) {
- return
- }
- if (e.getXX() * e.getYX() || e.getXY() * e.getYY()) {
- console.log("Cartesian Series sprite does not support rotation/sheering");
- return
- }
- var d = e.transformList([
- [g[0] - 1, g[3] + 1],
- [g[0] + g[2] + 1, -1]
- ]);
- d = d[0].concat(d[1]);
- f.renderClipped(b, c, d, g)
- },
- renderClipped: Ext.emptyFn,
- getIndexNearPoint: function(f, e) {
- var w = this,
- q = w.attr.matrix,
- h = w.attr.dataX,
- g = w.attr.dataY,
- k = w.attr.selectionTolerance,
- t, r, c = -1,
- j = q.clone().prependMatrix(w.surfaceMatrix).inverse(),
- u = j.transformPoint([f, e]),
- b = j.transformPoint([f - k, e - k]),
- n = j.transformPoint([f + k, e + k]),
- a = Math.min(b[0], n[0]),
- s = Math.max(b[0], n[0]),
- l = Math.min(b[1], n[1]),
- d = Math.max(b[1], n[1]),
- m, v, o, p;
- for (o = 0, p = h.length; o < p; o++) {
- m = h[o];
- v = g[o];
- if (m > a && m < s && v > l && v < d) {
- if (c === -1 || (Math.abs(m - u[0]) < t) && (Math.abs(v - u[1]) < r)) {
- t = Math.abs(m - u[0]);
- r = Math.abs(v - u[1]);
- c = o
- }
- }
- }
- return c
- }
-});
-Ext.define("Ext.chart.series.sprite.StackedCartesian", {
- extend: "Ext.chart.series.sprite.Cartesian",
- inheritableStatics: {
- def: {
- processors: {
- groupCount: "number",
- groupOffset: "number",
- dataStartY: "data"
- },
- defaults: {
- selectionTolerance: 20,
- groupCount: 1,
- groupOffset: 0,
- dataStartY: null
- },
- triggers: {
- dataStartY: "dataY,bbox"
- }
- }
- },
- getIndexNearPoint: function(e, d) {
- var o = this,
- q = o.attr.matrix,
- h = o.attr.dataX,
- f = o.attr.dataY,
- u = o.attr.dataStartY,
- l = o.attr.selectionTolerance,
- s = 0.5,
- r = Infinity,
- b = -1,
- k = q.clone().prependMatrix(this.surfaceMatrix).inverse(),
- t = k.transformPoint([e, d]),
- a = k.transformPoint([e - l, d - l]),
- n = k.transformPoint([e + l, d + l]),
- m = Math.min(a[1], n[1]),
- c = Math.max(a[1], n[1]),
- j, g;
- for (var p = 0; p < h.length; p++) {
- if (Math.min(u[p], f[p]) <= c && m <= Math.max(u[p], f[p])) {
- j = Math.abs(h[p] - t[0]);
- g = Math.max(-Math.min(f[p] - t[1], t[1] - u[p]), 0);
- if (j < s && g <= r) {
- s = j;
- r = g;
- b = p
- }
- }
- }
- return b
- }
-});
-Ext.define("Ext.chart.series.sprite.Area", {
- alias: "sprite.areaSeries",
- extend: "Ext.chart.series.sprite.StackedCartesian",
- inheritableStatics: {
- def: {
- processors: {
- step: "bool"
- },
- defaults: {
- step: false
- }
- }
- },
- renderClipped: function(q, s, A) {
- var B = this,
- p = B.attr,
- l = p.dataX,
- j = p.dataY,
- C = p.dataStartY,
- t = p.matrix,
- h, g, v, f, d, z, w, e = t.elements[0],
- m = t.elements[4],
- o = t.elements[3],
- k = t.elements[5],
- c = B.surfaceMatrix,
- n = {},
- r = Math.min(A[0], A[2]),
- u = Math.max(A[0], A[2]),
- b = Math.max(0, this.binarySearch(r)),
- a = Math.min(l.length - 1, this.binarySearch(u) + 1);
- s.beginPath();
- z = l[b] * e + m;
- w = j[b] * o + k;
- s.moveTo(z, w);
- if (p.step) {
- d = w;
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, d);
- s.lineTo(h, d = g)
- }
- } else {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, g)
- }
- }
- if (C) {
- if (p.step) {
- f = l[a] * e + m;
- for (v = a; v >= b; v--) {
- h = l[v] * e + m;
- g = C[v] * o + k;
- s.lineTo(f, g);
- s.lineTo(f = h, g)
- }
- } else {
- for (v = a; v >= b; v--) {
- h = l[v] * e + m;
- g = C[v] * o + k;
- s.lineTo(h, g)
- }
- }
- } else {
- s.lineTo(l[a] * e + m, g);
- s.lineTo(l[a] * e + m, k);
- s.lineTo(z, k);
- s.lineTo(z, j[v] * o + k)
- }
- if (p.transformFillStroke) {
- p.matrix.toContext(s)
- }
- s.fill();
- if (p.transformFillStroke) {
- p.inverseMatrix.toContext(s)
- }
- s.beginPath();
- s.moveTo(z, w);
- if (p.step) {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, d);
- s.lineTo(h, d = g);
- n.translationX = c.x(h, g);
- n.translationY = c.y(h, g);
- B.putMarker("markers", n, v, !p.renderer)
- }
- } else {
- for (v = b; v <= a; v++) {
- h = l[v] * e + m;
- g = j[v] * o + k;
- s.lineTo(h, g);
- n.translationX = c.x(h, g);
- n.translationY = c.y(h, g);
- B.putMarker("markers", n, v, !p.renderer)
- }
- }
- if (p.transformFillStroke) {
- p.matrix.toContext(s)
- }
- s.stroke()
- }
-});
-Ext.define("Ext.chart.series.Area", {
- extend: "Ext.chart.series.StackedCartesian",
- alias: "series.area",
- type: "area",
- seriesType: "areaSeries",
- requires: ["Ext.chart.series.sprite.Area"],
- config: {
- splitStacks: false
- }
-});
-Ext.define("Ext.chart.series.sprite.Bar", {
- alias: "sprite.barSeries",
- extend: "Ext.chart.series.sprite.StackedCartesian",
- inheritableStatics: {
- def: {
- processors: {
- minBarWidth: "number",
- maxBarWidth: "number",
- minGapWidth: "number",
- radius: "number",
- inGroupGapWidth: "number"
- },
- defaults: {
- minBarWidth: 2,
- maxBarWidth: 100,
- minGapWidth: 5,
- inGroupGapWidth: 3,
- radius: 0
- }
- }
- },
- drawLabel: function(k, i, s, h, o) {
- var q = this,
- n = q.attr,
- f = q.getMarker("labels"),
- d = f.getTemplate(),
- l = q.labelCfg || (q.labelCfg = {}),
- c = q.surfaceMatrix,
- j = n.labelOverflowPadding,
- b = d.attr.display,
- m = d.attr.orientation,
- g, e, a, r, t, p;
- l.x = c.x(i, h);
- l.y = c.y(i, h);
- if (!n.flipXY) {
- l.rotationRads = -Math.PI * 0.5
- } else {
- l.rotationRads = 0
- }
- l.calloutVertical = !n.flipXY;
- switch (m) {
- case "horizontal":
- l.rotationRads = 0;
- l.calloutVertical = false;
- break;
- case "vertical":
- l.rotationRads = -Math.PI * 0.5;
- l.calloutVertical = true;
- break
- }
- l.text = k;
- if (d.attr.renderer) {
- p = [k, f, l, {
- store: q.getStore()
- }, o];
- r = Ext.callback(d.attr.renderer, null, p, 0, q.getSeries());
- if (typeof r === "string") {
- l.text = r
- } else {
- if (typeof r === "object") {
- if ("text" in r) {
- l.text = r.text
- }
- t = true
- }
- }
- }
- a = q.getMarkerBBox("labels", o, true);
- if (!a) {
- q.putMarker("labels", l, o);
- a = q.getMarkerBBox("labels", o, true)
- }
- e = (a.width / 2 + j);
- if (s > h) {
- e = -e
- }
- if ((m === "horizontal" && n.flipXY) || (m === "vertical" && !n.flipXY) || !m) {
- g = (b === "insideStart") ? s + e : h - e
- } else {
- g = (b === "insideStart") ? s + j * 2 : h - j * 2
- }
- l.x = c.x(i, g);
- l.y = c.y(i, g);
- g = (b === "insideStart") ? s - e : h + e;
- l.calloutPlaceX = c.x(i, g);
- l.calloutPlaceY = c.y(i, g);
- g = (b === "insideStart") ? s : h;
- l.calloutStartX = c.x(i, g);
- l.calloutStartY = c.y(i, g);
- if (s > h) {
- e = -e
- }
- if (Math.abs(h - s) <= e * 2 || b === "outside") {
- l.callout = 1
- } else {
- l.callout = 0
- }
- if (t) {
- Ext.apply(l, r)
- }
- q.putMarker("labels", l, o)
- },
- drawBar: function(l, b, d, c, h, k, a, e) {
- var g = this,
- j = {},
- f = g.attr.renderer,
- i;
- j.x = c;
- j.y = h;
- j.width = k - c;
- j.height = a - h;
- j.radius = g.attr.radius;
- if (f) {
- i = Ext.callback(f, null, [g, j, {
- store: g.getStore()
- }, e], 0, g.getSeries());
- Ext.apply(j, i)
- }
- g.putMarker("items", j, e, !f)
- },
- renderClipped: function(G, u, F, C) {
- if (this.cleanRedraw) {
- return
- }
- var q = this,
- o = q.attr,
- w = o.dataX,
- v = o.dataY,
- H = o.labels,
- n = o.dataStartY,
- m = o.groupCount,
- E = o.groupOffset - (m - 1) * 0.5,
- z = o.inGroupGapWidth,
- t = u.lineWidth,
- D = o.matrix,
- B = D.elements[0],
- j = D.elements[3],
- e = D.elements[4],
- d = G.roundPixel(D.elements[5]) - 1,
- J = (B < 0 ? -1 : 1) * B - o.minGapWidth,
- k = (Math.min(J, o.maxBarWidth) - z * (m - 1)) / m,
- A = G.roundPixel(Math.max(o.minBarWidth, k)),
- c = q.surfaceMatrix,
- g, I, b, h, K, a, l = 0.5 * o.lineWidth,
- L = Math.min(F[0], F[2]),
- x = Math.max(F[0], F[2]),
- y = Math.max(0, Math.floor(L)),
- p = Math.min(w.length - 1, Math.ceil(x)),
- f = H && q.getMarker("labels"),
- s, r;
- for (K = y; K <= p; K++) {
- s = n ? n[K] : 0;
- r = v[K];
- a = w[K] * B + e + E * (A + z);
- g = G.roundPixel(a - A / 2) + l;
- h = G.roundPixel(r * j + d + t);
- I = G.roundPixel(a + A / 2) - l;
- b = G.roundPixel(s * j + d + t);
- q.drawBar(u, G, F, g, h - l, I, b - l, K);
- if (f && H[K] != null) {
- q.drawLabel(H[K], a, b, h, K)
- }
- q.putMarker("markers", {
- translationX: c.x(a, h),
- translationY: c.y(a, h)
- }, K, true)
- }
- },
- getIndexNearPoint: function(l, k) {
- var m = this,
- g = m.attr,
- h = g.dataX,
- a = m.getSurface(),
- b = a.getRect() || [0, 0, 0, 0],
- j = b[3],
- e, d, c, n, f = -1;
- if (g.flipXY) {
- e = j - k;
- if (a.getInherited().rtl) {
- d = b[2] - l
- } else {
- d = l
- }
- } else {
- e = l;
- d = j - k
- }
- for (c = 0; c < h.length; c++) {
- n = m.getMarkerBBox("items", c);
- if (Ext.draw.Draw.isPointInBBox(e, d, n)) {
- f = c;
- break
- }
- }
- return f
- }
-});
-Ext.define("Ext.chart.series.Bar", {
- extend: "Ext.chart.series.StackedCartesian",
- alias: "series.bar",
- type: "bar",
- seriesType: "barSeries",
- requires: ["Ext.chart.series.sprite.Bar", "Ext.draw.sprite.Rect"],
- config: {
- itemInstancing: {
- type: "rect",
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- radius: 0
- }
- }
- }
- },
- getItemForPoint: function(a, f) {
- if (this.getSprites()) {
- var d = this,
- c = d.getChart(),
- e = c.getInnerPadding(),
- b = c.getInherited().rtl;
- arguments[0] = a + (b ? e.right : -e.left);
- arguments[1] = f + e.bottom;
- return d.callParent(arguments)
- }
- },
- updateXAxis: function(a) {
- a.setLabelInSpan(true);
- this.callParent(arguments)
- },
- updateHidden: function(a) {
- this.callParent(arguments);
- this.updateStacked()
- },
- updateStacked: function(c) {
- var e = this,
- g = e.getSprites(),
- d = g.length,
- f = [],
- a = {},
- b;
- for (b = 0; b < d; b++) {
- if (!g[b].attr.hidden) {
- f.push(g[b])
- }
- }
- d = f.length;
- if (e.getStacked()) {
- a.groupCount = 1;
- a.groupOffset = 0;
- for (b = 0; b < d; b++) {
- f[b].setAttributes(a)
- }
- } else {
- a.groupCount = f.length;
- for (b = 0; b < d; b++) {
- a.groupOffset = b;
- f[b].setAttributes(a)
- }
- }
- e.callParent(arguments)
- }
-});
-Ext.define("Ext.chart.series.sprite.Bar3D", {
- extend: "Ext.chart.series.sprite.Bar",
- alias: "sprite.bar3dSeries",
- requires: ["Ext.draw.gradient.Linear"],
- inheritableStatics: {
- def: {
- processors: {
- depthWidthRatio: "number",
- saturationFactor: "number",
- brightnessFactor: "number",
- colorSpread: "number"
- },
- defaults: {
- depthWidthRatio: 1 / 3,
- saturationFactor: 1,
- brightnessFactor: 1,
- colorSpread: 1,
- transformFillStroke: true
- },
- triggers: {
- groupCount: "panzoom"
- },
- updaters: {
- panzoom: function(c) {
- var g = this,
- e = c.visibleMaxX - c.visibleMinX,
- d = c.visibleMaxY - c.visibleMinY,
- b = c.flipXY ? c.innerHeight : c.innerWidth,
- h = !c.flipXY ? c.innerHeight : c.innerWidth,
- a = g.getSurface(),
- f = a ? a.getInherited().rtl : false;
- if (f && !c.flipXY) {
- c.translationX = b + c.visibleMinX * b / e
- } else {
- c.translationX = -c.visibleMinX * b / e
- }
- c.translationY = -c.visibleMinY * (h - g.depth) / d;
- c.scalingX = (f && !c.flipXY ? -1 : 1) * b / e;
- c.scalingY = (h - g.depth) / d;
- c.scalingCenterX = 0;
- c.scalingCenterY = 0;
- g.applyTransformations(true)
- }
- }
- }
- },
- config: {
- showStroke: false
- },
- depth: 0,
- drawBar: function(p, b, d, c, l, o, a, h) {
- var k = this,
- i = k.attr,
- n = {},
- j = i.renderer,
- m, g, f, e;
- n.x = (c + o) * 0.5;
- n.y = l;
- n.width = (o - c) * 0.75;
- n.height = a - l;
- n.depth = g = n.width * i.depthWidthRatio;
- n.orientation = i.flipXY ? "horizontal" : "vertical";
- n.saturationFactor = i.saturationFactor;
- n.brightnessFactor = i.brightnessFactor;
- n.colorSpread = i.colorSpread;
- if (g !== k.depth) {
- k.depth = g;
- f = k.getSeries();
- f.fireEvent("depthchange", f, g)
- }
- if (j) {
- e = [k, n, {
- store: k.getStore()
- }, h];
- m = Ext.callback(j, null, e, 0, k.getSeries());
- Ext.apply(n, m)
- }
- k.putMarker("items", n, h, !j)
- }
-});
-Ext.define("Ext.chart.series.sprite.Box", {
- extend: "Ext.draw.sprite.Sprite",
- alias: "sprite.box",
- type: "box",
- inheritableStatics: {
- def: {
- processors: {
- x: "number",
- y: "number",
- width: "number",
- height: "number",
- depth: "number",
- orientation: "enums(vertical,horizontal)",
- showStroke: "bool",
- saturationFactor: "number",
- brightnessFactor: "number",
- colorSpread: "number"
- },
- triggers: {
- x: "bbox",
- y: "bbox",
- width: "bbox",
- height: "bbox",
- depth: "bbox",
- orientation: "bbox"
- },
- defaults: {
- x: 0,
- y: 0,
- width: 8,
- height: 8,
- depth: 8,
- orientation: "vertical",
- showStroke: false,
- saturationFactor: 1,
- brightnessFactor: 1,
- colorSpread: 1,
- lineJoin: "bevel"
- }
- }
- },
- constructor: function(a) {
- this.callParent([a]);
- this.topGradient = new Ext.draw.gradient.Linear({});
- this.rightGradient = new Ext.draw.gradient.Linear({});
- this.frontGradient = new Ext.draw.gradient.Linear({})
- },
- updatePlainBBox: function(d) {
- var c = this.attr,
- b = c.x,
- g = c.y,
- e = c.width,
- a = c.height,
- f = c.depth;
- d.x = b - e * 0.5;
- d.width = e + f;
- if (a > 0) {
- d.y = g;
- d.height = a + f
- } else {
- d.y = g + f;
- d.height = a - f
- }
- },
- render: function(l, m) {
- var u = this,
- k = u.attr,
- r = k.x,
- j = k.y,
- f = j + k.height,
- i = j < f,
- e = k.width * 0.5,
- v = k.depth,
- d = k.orientation === "horizontal",
- g = k.globalAlpha < 1,
- c = k.fillStyle,
- n = Ext.draw.Color.create(c.isGradient ? c.getStops()[0].color : c),
- h = k.saturationFactor,
- o = k.brightnessFactor,
- t = k.colorSpread,
- b = n.getHSV(),
- a = {},
- s, q, p;
- if (!k.showStroke) {
- m.strokeStyle = Ext.draw.Color.RGBA_NONE
- }
- if (i) {
- p = j;
- j = f;
- f = p
- }
- u.topGradient.setDegrees(d ? 0 : 80);
- u.topGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 + t * 0.1) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.11) * o, 0, 1))
- }]);
- u.rightGradient.setDegrees(d ? 45 : 90);
- u.rightGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.14) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 + t * 0.4) * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.32) * o, 0, 1))
- }]);
- if (d) {
- u.frontGradient.setDegrees(0)
- } else {
- u.frontGradient.setRadians(Math.atan2(j - f, e * 2))
- }
- u.frontGradient.setStops([{
- offset: 0,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 - t * 0.1) * h, 0, 1), Ext.Number.constrain((0.5 + t * 0.1) * o, 0, 1))
- }, {
- offset: 1,
- color: Ext.draw.Color.fromHSV(b[0], Ext.Number.constrain(b[1] * (1 + t * 0.1) * h, 0, 1), Ext.Number.constrain((0.5 - t * 0.23) * o, 0, 1))
- }]);
- if (g || i) {
- m.beginPath();
- m.moveTo(r - e, f);
- m.lineTo(r - e + v, f + v);
- m.lineTo(r + e + v, f + v);
- m.lineTo(r + e, f);
- m.closePath();
- a.x = r - e;
- a.y = j;
- a.width = e + v;
- a.height = v;
- m.fillStyle = (d ? u.rightGradient : u.topGradient).generateGradient(m, a);
- m.fillStroke(k)
- }
- if (g) {
- m.beginPath();
- m.moveTo(r - e, j);
- m.lineTo(r - e + v, j + v);
- m.lineTo(r - e + v, f + v);
- m.lineTo(r - e, f);
- m.closePath();
- a.x = r + e;
- a.y = f;
- a.width = v;
- a.height = j + v - f;
- m.fillStyle = (d ? u.topGradient : u.rightGradient).generateGradient(m, a);
- m.fillStroke(k)
- }
- q = l.roundPixel(j);
- m.beginPath();
- m.moveTo(r - e, q);
- m.lineTo(r - e + v, j + v);
- m.lineTo(r + e + v, j + v);
- m.lineTo(r + e, q);
- m.closePath();
- a.x = r - e;
- a.y = j;
- a.width = e + v;
- a.height = v;
- m.fillStyle = (d ? u.rightGradient : u.topGradient).generateGradient(m, a);
- m.fillStroke(k);
- s = l.roundPixel(r + e);
- m.beginPath();
- m.moveTo(s, l.roundPixel(j));
- m.lineTo(r + e + v, j + v);
- m.lineTo(r + e + v, f + v);
- m.lineTo(s, f);
- m.closePath();
- a.x = r + e;
- a.y = f;
- a.width = v;
- a.height = j + v - f;
- m.fillStyle = (d ? u.topGradient : u.rightGradient).generateGradient(m, a);
- m.fillStroke(k);
- s = l.roundPixel(r + e);
- q = l.roundPixel(j);
- m.beginPath();
- m.moveTo(r - e, f);
- m.lineTo(r - e, q);
- m.lineTo(s, q);
- m.lineTo(s, f);
- m.closePath();
- a.x = r - e;
- a.y = f;
- a.width = e * 2;
- a.height = j - f;
- m.fillStyle = u.frontGradient.generateGradient(m, a);
- m.fillStroke(k)
- }
-});
-Ext.define("Ext.chart.series.Bar3D", {
- extend: "Ext.chart.series.Bar",
- requires: ["Ext.chart.series.sprite.Bar3D", "Ext.chart.series.sprite.Box"],
- alias: "series.bar3d",
- type: "bar3d",
- seriesType: "bar3dSeries",
- config: {
- itemInstancing: {
- type: "box",
- fx: {
- customDurations: {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- depth: 0
- }
- }
- },
- highlightCfg: {
- opacity: 0.8
- }
- },
- getSprites: function() {
- var c = this.callParent(arguments),
- b, d, a;
- for (a = 0; a < c.length; a++) {
- b = c[a];
- d = b.attr.zIndex;
- if (d < 0) {
- b.setAttributes({
- zIndex: -d
- })
- }
- if (b.setSeries) {
- b.setSeries(this)
- }
- }
- return c
- },
- getDepth: function() {
- var a = this.getSprites()[0];
- return a ? (a.depth || 0) : 0
- },
- getItemForPoint: function(m, k) {
- if (this.getSprites()) {
- var j = this,
- b, o, a = j.getItemInstancing(),
- h = j.getSprites(),
- n = j.getStore(),
- c = j.getHidden(),
- g = j.getChart(),
- l = g.getInnerPadding(),
- f = g.getInherited().rtl,
- p, d, e;
- m = m + (f ? l.right : -l.left);
- k = k + l.bottom;
- for (b = h.length - 1; b >= 0; b--) {
- if (!c[b]) {
- o = h[b];
- d = o.getIndexNearPoint(m, k);
- if (d !== -1) {
- e = j.getYField();
- p = {
- series: j,
- index: d,
- category: a ? "items" : "markers",
- record: n.getData().items[d],
- field: typeof e === "string" ? e : e[b],
- sprite: o
- };
- return p
- }
- }
- }
- return null
- }
- }
-});
-Ext.define("Ext.draw.LimitedCache", {
- config: {
- limit: 40,
- feeder: function() {
- return 0
- },
- scope: null
- },
- cache: null,
- constructor: function(a) {
- this.cache = {};
- this.cache.list = [];
- this.cache.tail = 0;
- this.initConfig(a)
- },
- get: function(e) {
- var c = this.cache,
- b = this.getLimit(),
- a = this.getFeeder(),
- d = this.getScope() || this;
- if (c[e]) {
- return c[e].value
- }
- if (c.list[c.tail]) {
- delete c[c.list[c.tail].cacheId]
- }
- c[e] = c.list[c.tail] = {
- value: a.apply(d, Array.prototype.slice.call(arguments, 1)),
- cacheId: e
- };
- c.tail++;
- if (c.tail === b) {
- c.tail = 0
- }
- return c[e].value
- },
- clear: function() {
- this.cache = {};
- this.cache.list = [];
- this.cache.tail = 0
- }
-});
-Ext.define("Ext.draw.SegmentTree", {
- config: {
- strategy: "double"
- },
- time: function(m, l, n, c, E, d, e) {
- var f = 0,
- o, A, s = new Date(n[m.startIdx[0]]),
- x = new Date(n[m.endIdx[l - 1]]),
- D = Ext.Date,
- u = [
- [D.MILLI, 1, "ms1", null],
- [D.MILLI, 2, "ms2", "ms1"],
- [D.MILLI, 5, "ms5", "ms1"],
- [D.MILLI, 10, "ms10", "ms5"],
- [D.MILLI, 50, "ms50", "ms10"],
- [D.MILLI, 100, "ms100", "ms50"],
- [D.MILLI, 500, "ms500", "ms100"],
- [D.SECOND, 1, "s1", "ms500"],
- [D.SECOND, 10, "s10", "s1"],
- [D.SECOND, 30, "s30", "s10"],
- [D.MINUTE, 1, "mi1", "s10"],
- [D.MINUTE, 5, "mi5", "mi1"],
- [D.MINUTE, 10, "mi10", "mi5"],
- [D.MINUTE, 30, "mi30", "mi10"],
- [D.HOUR, 1, "h1", "mi30"],
- [D.HOUR, 6, "h6", "h1"],
- [D.HOUR, 12, "h12", "h6"],
- [D.DAY, 1, "d1", "h12"],
- [D.DAY, 7, "d7", "d1"],
- [D.MONTH, 1, "mo1", "d1"],
- [D.MONTH, 3, "mo3", "mo1"],
- [D.MONTH, 6, "mo6", "mo3"],
- [D.YEAR, 1, "y1", "mo3"],
- [D.YEAR, 5, "y5", "y1"],
- [D.YEAR, 10, "y10", "y5"],
- [D.YEAR, 100, "y100", "y10"]
- ],
- z, b, k = f,
- F = l,
- j = false,
- r = m.startIdx,
- h = m.endIdx,
- w = m.minIdx,
- C = m.maxIdx,
- a = m.open,
- y = m.close,
- g = m.minX,
- q = m.minY,
- p = m.maxX,
- B = m.maxY,
- v, t;
- for (z = 0; l > f + 1 && z < u.length; z++) {
- s = new Date(n[r[0]]);
- b = u[z];
- s = D.align(s, b[0], b[1]);
- if (D.diff(s, x, b[0]) > n.length * 2 * b[1]) {
- continue
- }
- if (b[3] && m.map["time_" + b[3]]) {
- o = m.map["time_" + b[3]][0];
- A = m.map["time_" + b[3]][1]
- } else {
- o = k;
- A = F
- }
- f = l;
- t = s;
- j = true;
- r[l] = r[o];
- h[l] = h[o];
- w[l] = w[o];
- C[l] = C[o];
- a[l] = a[o];
- y[l] = y[o];
- g[l] = g[o];
- q[l] = q[o];
- p[l] = p[o];
- B[l] = B[o];
- t = Ext.Date.add(t, b[0], b[1]);
- for (v = o + 1; v < A; v++) {
- if (n[h[v]] < +t) {
- h[l] = h[v];
- y[l] = y[v];
- if (B[v] > B[l]) {
- B[l] = B[v];
- p[l] = p[v];
- C[l] = C[v]
- }
- if (q[v] < q[l]) {
- q[l] = q[v];
- g[l] = g[v];
- w[l] = w[v]
- }
- } else {
- l++;
- r[l] = r[v];
- h[l] = h[v];
- w[l] = w[v];
- C[l] = C[v];
- a[l] = a[v];
- y[l] = y[v];
- g[l] = g[v];
- q[l] = q[v];
- p[l] = p[v];
- B[l] = B[v];
- t = Ext.Date.add(t, b[0], b[1])
- }
- }
- if (l > f) {
- m.map["time_" + b[2]] = [f, l]
- }
- }
- },
- "double": function(h, u, j, a, t, b, c) {
- var e = 0,
- k, f = 1,
- n, d, v, g, s, l, m, r, q, p, o;
- while (u > e + 1) {
- k = e;
- e = u;
- f += f;
- for (n = k; n < e; n += 2) {
- if (n === e - 1) {
- d = h.startIdx[n];
- v = h.endIdx[n];
- g = h.minIdx[n];
- s = h.maxIdx[n];
- l = h.open[n];
- m = h.close[n];
- r = h.minX[n];
- q = h.minY[n];
- p = h.maxX[n];
- o = h.maxY[n]
- } else {
- d = h.startIdx[n];
- v = h.endIdx[n + 1];
- l = h.open[n];
- m = h.close[n];
- if (h.minY[n] <= h.minY[n + 1]) {
- g = h.minIdx[n];
- r = h.minX[n];
- q = h.minY[n]
- } else {
- g = h.minIdx[n + 1];
- r = h.minX[n + 1];
- q = h.minY[n + 1]
- }
- if (h.maxY[n] >= h.maxY[n + 1]) {
- s = h.maxIdx[n];
- p = h.maxX[n];
- o = h.maxY[n]
- } else {
- s = h.maxIdx[n + 1];
- p = h.maxX[n + 1];
- o = h.maxY[n + 1]
- }
- }
- h.startIdx[u] = d;
- h.endIdx[u] = v;
- h.minIdx[u] = g;
- h.maxIdx[u] = s;
- h.open[u] = l;
- h.close[u] = m;
- h.minX[u] = r;
- h.minY[u] = q;
- h.maxX[u] = p;
- h.maxY[u] = o;
- u++
- }
- h.map["double_" + f] = [e, u]
- }
- },
- none: Ext.emptyFn,
- aggregateData: function(h, a, r, c, d) {
- var b = h.length,
- e = [],
- s = [],
- f = [],
- q = [],
- j = [],
- p = [],
- n = [],
- o = [],
- m = [],
- k = [],
- g = {
- startIdx: e,
- endIdx: s,
- minIdx: f,
- maxIdx: q,
- open: j,
- minX: p,
- minY: n,
- maxX: o,
- maxY: m,
- close: k
- },
- l;
- for (l = 0; l < b; l++) {
- e[l] = l;
- s[l] = l;
- f[l] = l;
- q[l] = l;
- j[l] = a[l];
- p[l] = h[l];
- n[l] = c[l];
- o[l] = h[l];
- m[l] = r[l];
- k[l] = d[l]
- }
- g.map = {
- original: [0, b]
- };
- if (b) {
- this[this.getStrategy()](g, b, h, a, r, c, d)
- }
- return g
- },
- binarySearchMin: function(c, g, a, e) {
- var b = this.dataX;
- if (e <= b[c.startIdx[0]]) {
- return g
- }
- if (e >= b[c.startIdx[a - 1]]) {
- return a - 1
- }
- while (g + 1 < a) {
- var d = (g + a) >> 1,
- f = b[c.startIdx[d]];
- if (f === e) {
- return d
- } else {
- if (f < e) {
- g = d
- } else {
- a = d
- }
- }
- }
- return g
- },
- binarySearchMax: function(c, g, a, e) {
- var b = this.dataX;
- if (e <= b[c.endIdx[0]]) {
- return g
- }
- if (e >= b[c.endIdx[a - 1]]) {
- return a - 1
- }
- while (g + 1 < a) {
- var d = (g + a) >> 1,
- f = b[c.endIdx[d]];
- if (f === e) {
- return d
- } else {
- if (f < e) {
- g = d
- } else {
- a = d
- }
- }
- }
- return a
- },
- constructor: function(a) {
- this.initConfig(a)
- },
- setData: function(d, a, b, c, e) {
- if (!b) {
- e = c = b = a
- }
- this.dataX = d;
- this.dataOpen = a;
- this.dataHigh = b;
- this.dataLow = c;
- this.dataClose = e;
- if (d.length === b.length && d.length === c.length) {
- this.cache = this.aggregateData(d, a, b, c, e)
- }
- },
- getAggregation: function(d, k, i) {
- if (!this.cache) {
- return null
- }
- var c = Infinity,
- g = this.dataX[this.dataX.length - 1] - this.dataX[0],
- l = this.cache.map,
- m = l.original,
- a, e, j, b, f, h;
- for (a in l) {
- e = l[a];
- j = e[1] - e[0] - 1;
- b = g / j;
- if (i <= b && b < c) {
- m = e;
- c = b
- }
- }
- f = Math.max(this.binarySearchMin(this.cache, m[0], m[1], d), m[0]);
- h = Math.min(this.binarySearchMax(this.cache, m[0], m[1], k) + 1, m[1]);
- return {
- data: this.cache,
- start: f,
- end: h
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Aggregative", {
- extend: "Ext.chart.series.sprite.Cartesian",
- requires: ["Ext.draw.LimitedCache", "Ext.draw.SegmentTree"],
- inheritableStatics: {
- def: {
- processors: {
- dataHigh: "data",
- dataLow: "data",
- dataClose: "data"
- },
- aliases: {
- dataOpen: "dataY"
- },
- defaults: {
- dataHigh: null,
- dataLow: null,
- dataClose: null
- }
- }
- },
- config: {
- aggregator: {}
- },
- applyAggregator: function(b, a) {
- return Ext.factory(b, Ext.draw.SegmentTree, a)
- },
- constructor: function() {
- this.callParent(arguments)
- },
- processDataY: function() {
- var d = this,
- b = d.attr,
- e = b.dataHigh,
- a = b.dataLow,
- f = b.dataClose,
- c = b.dataY;
- d.callParent(arguments);
- if (b.dataX && c && c.length > 0) {
- if (e) {
- d.getAggregator().setData(b.dataX, b.dataY, e, a, f)
- } else {
- d.getAggregator().setData(b.dataX, b.dataY)
- }
- }
- },
- getGapWidth: function() {
- return 1
- },
- renderClipped: function(b, c, g, f) {
- var e = this,
- d = Math.min(g[0], g[2]),
- a = Math.max(g[0], g[2]),
- h = e.getAggregator() && e.getAggregator().getAggregation(d, a, (a - d) / f[2] * e.getGapWidth());
- if (h) {
- e.dataStart = h.data.startIdx[h.start];
- e.dataEnd = h.data.endIdx[h.end - 1];
- e.renderAggregates(h.data, h.start, h.end, b, c, g, f)
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.CandleStick", {
- alias: "sprite.candlestickSeries",
- extend: "Ext.chart.series.sprite.Aggregative",
- inheritableStatics: {
- def: {
- processors: {
- raiseStyle: function(b, a) {
- return Ext.merge({}, a || {}, b)
- },
- dropStyle: function(b, a) {
- return Ext.merge({}, a || {}, b)
- },
- barWidth: "number",
- padding: "number",
- ohlcType: "enums(candlestick,ohlc)"
- },
- defaults: {
- raiseStyle: {
- strokeStyle: "green",
- fillStyle: "green"
- },
- dropStyle: {
- strokeStyle: "red",
- fillStyle: "red"
- },
- planar: false,
- barWidth: 15,
- padding: 3,
- lineJoin: "miter",
- miterLimit: 5,
- ohlcType: "candlestick"
- },
- triggers: {
- raiseStyle: "raiseStyle",
- dropStyle: "dropStyle"
- },
- updaters: {
- raiseStyle: function() {
- this.raiseTemplate && this.raiseTemplate.setAttributes(this.attr.raiseStyle)
- },
- dropStyle: function() {
- this.dropTemplate && this.dropTemplate.setAttributes(this.attr.dropStyle)
- }
- }
- }
- },
- candlestick: function(i, c, a, e, h, f, b) {
- var d = Math.min(c, h),
- g = Math.max(c, h);
- i.moveTo(f, e);
- i.lineTo(f, g);
- i.moveTo(f + b, g);
- i.lineTo(f + b, d);
- i.lineTo(f - b, d);
- i.lineTo(f - b, g);
- i.closePath();
- i.moveTo(f, a);
- i.lineTo(f, d)
- },
- ohlc: function(b, d, e, a, f, c, g) {
- b.moveTo(c, e);
- b.lineTo(c, a);
- b.moveTo(c, d);
- b.lineTo(c - g, d);
- b.moveTo(c, f);
- b.lineTo(c + g, f)
- },
- constructor: function() {
- this.callParent(arguments);
- this.raiseTemplate = new Ext.draw.sprite.Rect({
- parent: this
- });
- this.dropTemplate = new Ext.draw.sprite.Rect({
- parent: this
- })
- },
- getGapWidth: function() {
- var a = this.attr,
- b = a.barWidth,
- c = a.padding;
- return b + c
- },
- renderAggregates: function(d, c, b, t, u, z) {
- var D = this,
- s = this.attr,
- j = s.dataX,
- v = s.matrix,
- e = v.getXX(),
- r = v.getYY(),
- l = v.getDX(),
- h = v.getDY(),
- o = s.barWidth / e,
- C, k = s.ohlcType,
- f = Math.round(o * 0.5 * e),
- a = d.open,
- y = d.close,
- B = d.maxY,
- p = d.minY,
- q = d.startIdx,
- m, g, E, n, A, x, w = s.lineWidth * t.devicePixelRatio / 2;
- w -= Math.floor(w);
- u.save();
- C = this.raiseTemplate;
- C.useAttributes(u, z);
- u.beginPath();
- for (x = c; x < b; x++) {
- if (a[x] <= y[x]) {
- m = Math.round(a[x] * r + h) + w;
- g = Math.round(B[x] * r + h) + w;
- E = Math.round(p[x] * r + h) + w;
- n = Math.round(y[x] * r + h) + w;
- A = Math.round(j[q[x]] * e + l) + w;
- D[k](u, m, g, E, n, A, f)
- }
- }
- u.fillStroke(C.attr);
- u.restore();
- u.save();
- C = this.dropTemplate;
- C.useAttributes(u, z);
- u.beginPath();
- for (x = c; x < b; x++) {
- if (a[x] > y[x]) {
- m = Math.round(a[x] * r + h) + w;
- g = Math.round(B[x] * r + h) + w;
- E = Math.round(p[x] * r + h) + w;
- n = Math.round(y[x] * r + h) + w;
- A = Math.round(j[q[x]] * e + l) + w;
- D[k](u, m, g, E, n, A, f)
- }
- }
- u.fillStroke(C.attr);
- u.restore()
- }
-});
-Ext.define("Ext.chart.series.CandleStick", {
- extend: "Ext.chart.series.Cartesian",
- requires: ["Ext.chart.series.sprite.CandleStick"],
- alias: "series.candlestick",
- type: "candlestick",
- seriesType: "candlestickSeries",
- config: {
- openField: null,
- highField: null,
- lowField: null,
- closeField: null
- },
- fieldCategoryY: ["Open", "High", "Low", "Close"],
- themeColorCount: function() {
- return 2
- }
-});
-Ext.define("Ext.chart.series.Polar", {
- extend: "Ext.chart.series.Series",
- config: {
- rotation: 0,
- radius: null,
- center: [0, 0],
- offsetX: 0,
- offsetY: 0,
- showInLegend: true,
- xField: null,
- yField: null,
- angleField: null,
- radiusField: null,
- xAxis: null,
- yAxis: null
- },
- directions: ["X", "Y"],
- fieldCategoryX: ["X"],
- fieldCategoryY: ["Y"],
- deprecatedConfigs: {
- field: "angleField",
- lengthField: "radiusField"
- },
- constructor: function(b) {
- var c = this,
- a = c.getConfigurator(),
- e = a.configs,
- d;
- if (b) {
- for (d in c.deprecatedConfigs) {
- if (d in b && !(b in e)) {
- Ext.raise("'" + d + "' config has been deprecated. Please use the '" + c.deprecatedConfigs[d] + "' config instead.")
- }
- }
- }
- c.callParent([b])
- },
- getXField: function() {
- return this.getAngleField()
- },
- updateXField: function(a) {
- this.setAngleField(a)
- },
- getYField: function() {
- return this.getRadiusField()
- },
- updateYField: function(a) {
- this.setRadiusField(a)
- },
- applyXAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- applyYAxis: function(a, b) {
- return this.getChart().getAxis(a) || b
- },
- getXRange: function() {
- return [this.dataRange[0], this.dataRange[2]]
- },
- getYRange: function() {
- return [this.dataRange[1], this.dataRange[3]]
- },
- themeColorCount: function() {
- var c = this,
- a = c.getStore(),
- b = a && a.getCount() || 0;
- return b
- },
- isStoreDependantColorCount: true,
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer(),
- centerX: 0,
- centerY: 0,
- rotationCenterX: 0,
- rotationCenterY: 0
- }
- },
- applyRotation: function(a) {
- return Ext.draw.sprite.AttributeParser.angle(a)
- },
- updateRotation: function(a) {
- var b = this.getSprites();
- if (b && b[0]) {
- b[0].setAttributes({
- baseRotation: a
- })
- }
- }
-});
-Ext.define("Ext.chart.series.Gauge", {
- alias: "series.gauge",
- extend: "Ext.chart.series.Polar",
- type: "gauge",
- seriesType: "pieslice",
- requires: ["Ext.draw.sprite.Sector"],
- config: {
- needle: false,
- needleLength: 90,
- needleWidth: 4,
- donut: 30,
- showInLegend: false,
- value: null,
- colors: null,
- sectors: null,
- minimum: 0,
- maximum: 100,
- rotation: 0,
- totalAngle: Math.PI / 2,
- rect: [0, 0, 1, 1],
- center: [0.5, 0.75],
- radius: 0.5,
- wholeDisk: false
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- updateNeedle: function(b) {
- var a = this,
- d = a.getSprites(),
- c = a.valueToAngle(a.getValue());
- if (d && d.length) {
- d[0].setAttributes({
- startAngle: (b ? c : 0),
- endAngle: c,
- strokeOpacity: (b ? 1 : 0),
- lineWidth: (b ? a.getNeedleWidth() : 0)
- });
- a.doUpdateStyles()
- }
- },
- themeColorCount: function() {
- var c = this,
- a = c.getStore(),
- b = a && a.getCount() || 0;
- return b + (c.getNeedle() ? 0 : 1)
- },
- updateColors: function(a, b) {
- var f = this,
- h = f.getSectors(),
- j = h && h.length,
- e = f.getSprites(),
- c = Ext.Array.clone(a),
- g = a && a.length,
- d;
- if (!g || !a[0]) {
- return
- }
- for (d = 0; d < j; d++) {
- c[d + 1] = h[d].color || c[d + 1] || a[d % g]
- }
- if (e.length) {
- e[0].setAttributes({
- strokeStyle: c[0]
- })
- }
- this.setSubStyle({
- fillStyle: c,
- strokeStyle: c
- });
- this.doUpdateStyles()
- },
- updateRect: function(f) {
- var d = this.getWholeDisk(),
- c = d ? Math.PI : this.getTotalAngle() / 2,
- g = this.getDonut() / 100,
- e, b, a;
- if (c <= Math.PI / 2) {
- e = 2 * Math.sin(c);
- b = 1 - g * Math.cos(c)
- } else {
- e = 2;
- b = 1 - Math.cos(c)
- }
- a = Math.min(f[2] / e, f[3] / b);
- this.setRadius(a);
- this.setCenter([f[2] / 2, a + (f[3] - b * a) / 2])
- },
- updateCenter: function(a) {
- this.setStyle({
- centerX: a[0],
- centerY: a[1],
- rotationCenterX: a[0],
- rotationCenterY: a[1]
- });
- this.doUpdateStyles()
- },
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a - (this.getTotalAngle() + Math.PI) / 2
- });
- this.doUpdateStyles()
- },
- doUpdateShape: function(b, f) {
- var a, d = this.getSectors(),
- c = (d && d.length) || 0,
- e = this.getNeedleLength() / 100;
- a = [b * e, b];
- while (c--) {
- a.push(b)
- }
- this.setSubStyle({
- endRho: a,
- startRho: b / 100 * f
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- var b = this.getDonut();
- this.doUpdateShape(a, b)
- },
- updateDonut: function(b) {
- var a = this.getRadius();
- this.doUpdateShape(a, b)
- },
- valueToAngle: function(a) {
- a = this.applyValue(a);
- return this.getTotalAngle() * (a - this.getMinimum()) / (this.getMaximum() - this.getMinimum())
- },
- applyValue: function(a) {
- return Math.min(this.getMaximum(), Math.max(a, this.getMinimum()))
- },
- updateValue: function(b) {
- var a = this,
- c = a.getNeedle(),
- e = a.valueToAngle(b),
- d = a.getSprites();
- d[0].rendererData.value = b;
- d[0].setAttributes({
- startAngle: (c ? e : 0),
- endAngle: e
- });
- a.doUpdateStyles()
- },
- processData: function() {
- var f = this,
- j = f.getStore(),
- a, d, h, b, g, e = j && j.first(),
- c, i;
- if (e) {
- c = f.getXField();
- if (c) {
- i = e.get(c)
- }
- }
- if (a = f.getXAxis()) {
- d = a.getMinimum();
- h = a.getMaximum();
- b = a.getSprites()[0].fx;
- g = b.getDuration();
- b.setDuration(0);
- if (Ext.isNumber(d)) {
- f.setMinimum(d)
- } else {
- a.setMinimum(f.getMinimum())
- }
- if (Ext.isNumber(h)) {
- f.setMaximum(h)
- } else {
- a.setMaximum(f.getMaximum())
- }
- b.setDuration(g)
- }
- if (!Ext.isNumber(i)) {
- i = f.getMinimum()
- }
- f.setValue(i)
- },
- getDefaultSpriteConfig: function() {
- return {
- type: this.seriesType,
- renderer: this.getRenderer(),
- fx: {
- customDurations: {
- translationX: 0,
- translationY: 0,
- rotationCenterX: 0,
- rotationCenterY: 0,
- centerX: 0,
- centerY: 0,
- startRho: 0,
- endRho: 0,
- baseRotation: 0
- }
- }
- }
- },
- normalizeSectors: function(f) {
- var d = this,
- c = (f && f.length) || 0,
- b, e, g, a;
- if (c) {
- for (b = 0; b < c; b++) {
- e = f[b];
- if (typeof e === "number") {
- f[b] = {
- start: (b > 0 ? f[b - 1].end : d.getMinimum()),
- end: Math.min(e, d.getMaximum())
- };
- if (b == (c - 1) && f[b].end < d.getMaximum()) {
- f[b + 1] = {
- start: f[b].end,
- end: d.getMaximum()
- }
- }
- } else {
- if (typeof e.start === "number") {
- g = Math.max(e.start, d.getMinimum())
- } else {
- g = (b > 0 ? f[b - 1].end : d.getMinimum())
- }
- if (typeof e.end === "number") {
- a = Math.min(e.end, d.getMaximum())
- } else {
- a = d.getMaximum()
- }
- f[b].start = g;
- f[b].end = a
- }
- }
- } else {
- f = [{
- start: d.getMinimum(),
- end: d.getMaximum()
- }]
- }
- return f
- },
- getSprites: function() {
- var j = this,
- m = j.getStore(),
- l = j.getValue(),
- c, g;
- if (!m && !Ext.isNumber(l)) {
- return []
- }
- var h = j.getChart(),
- b = j.getAnimation() || h && h.getAnimation(),
- f = j.sprites,
- k = 0,
- o, n, e, d, a = [];
- if (f && f.length) {
- f[0].setAnimation(b);
- return f
- }
- d = {
- store: m,
- field: j.getXField(),
- angleField: j.getXField(),
- value: l,
- series: j
- };
- o = j.createSprite();
- o.setAttributes({
- zIndex: 10
- }, true);
- o.rendererData = d;
- o.rendererIndex = k++;
- a.push(j.getNeedleWidth());
- j.getLabel().getTemplate().setField(true);
- n = j.normalizeSectors(j.getSectors());
- for (c = 0, g = n.length; c < g; c++) {
- e = {
- startAngle: j.valueToAngle(n[c].start),
- endAngle: j.valueToAngle(n[c].end),
- label: n[c].label,
- fillStyle: n[c].color,
- strokeOpacity: 0,
- doCallout: false,
- labelOverflowPadding: -1
- };
- Ext.apply(e, n[c].style);
- o = j.createSprite();
- o.rendererData = d;
- o.rendererIndex = k++;
- o.setAttributes(e, true);
- a.push(e.lineWidth)
- }
- j.setSubStyle({
- lineWidth: a
- });
- j.doUpdateStyles();
- return f
- }
-});
-Ext.define("Ext.chart.series.sprite.Line", {
- alias: "sprite.lineSeries",
- extend: "Ext.chart.series.sprite.Aggregative",
- inheritableStatics: {
- def: {
- processors: {
- smooth: "bool",
- fillArea: "bool",
- step: "bool",
- preciseStroke: "bool",
- xAxis: "default",
- yCap: "default"
- },
- defaults: {
- smooth: false,
- fillArea: false,
- step: false,
- preciseStroke: true,
- xAxis: null,
- yCap: Math.pow(2, 20),
- yJump: 50
- },
- triggers: {
- dataX: "dataX,bbox,smooth",
- dataY: "dataY,bbox,smooth",
- smooth: "smooth"
- },
- updaters: {
- smooth: function(a) {
- var c = a.dataX,
- b = a.dataY;
- if (a.smooth && c && b && c.length > 2 && b.length > 2) {
- this.smoothX = Ext.draw.Draw.spline(c);
- this.smoothY = Ext.draw.Draw.spline(b)
- } else {
- delete this.smoothX;
- delete this.smoothY
- }
- }
- }
- }
- },
- list: null,
- updatePlainBBox: function(d) {
- var b = this.attr,
- c = Math.min(0, b.dataMinY),
- a = Math.max(0, b.dataMaxY);
- d.x = b.dataMinX;
- d.y = c;
- d.width = b.dataMaxX - b.dataMinX;
- d.height = a - c
- },
- drawStrip: function(a, c) {
- a.moveTo(c[0], c[1]);
- for (var b = 2, d = c.length; b < d; b += 2) {
- a.lineTo(c[b], c[b + 1])
- }
- },
- drawStraightStroke: function(p, q, e, d, u, h) {
- var w = this,
- o = w.attr,
- n = o.renderer,
- g = o.step,
- a = true,
- l = {
- type: "line",
- smooth: false,
- step: g
- },
- m = [],
- l, z, v, f, k, j, t, c, s, b, r;
- for (r = 3; r < u.length; r += 3) {
- t = u[r - 3];
- c = u[r - 2];
- k = u[r];
- j = u[r + 1];
- s = u[r + 3];
- b = u[r + 4];
- if (n) {
- l.x = k;
- l.y = j;
- l.x0 = t;
- l.y0 = c;
- v = [w, l, w.rendererData, e + r / 3];
- z = Ext.callback(n, null, v, 0, w.getSeries())
- }
- if (Ext.isNumber(k + j + t + c)) {
- if (a) {
- q.beginPath();
- q.moveTo(t, c);
- m.push(t, c);
- f = t;
- a = false
- }
- } else {
- continue
- }
- if (g) {
- q.lineTo(k, c);
- m.push(k, c)
- }
- q.lineTo(k, j);
- m.push(k, j);
- if (z || !(Ext.isNumber(s + b))) {
- q.save();
- Ext.apply(q, z);
- if (o.fillArea) {
- q.lineTo(k, h);
- q.lineTo(f, h);
- q.closePath();
- q.fill()
- }
- q.beginPath();
- w.drawStrip(q, m);
- m = [];
- q.stroke();
- q.restore();
- q.beginPath();
- a = true
- }
- }
- },
- calculateScale: function(c, a) {
- var b = 0,
- d = c;
- while (d < a && c > 0) {
- b++;
- d += c >> b
- }
- return Math.pow(2, b > 0 ? b - 1 : b)
- },
- drawSmoothStroke: function(u, v, c, b, C, f) {
- var G = this,
- t = G.attr,
- d = t.step,
- z = t.matrix,
- s = t.renderer,
- e = z.getXX(),
- p = z.getYY(),
- m = z.getDX(),
- k = z.getDY(),
- r = G.smoothX,
- q = G.smoothY,
- I = G.calculateScale(t.dataX.length, b),
- o, F, n, E, h, g, B, a, A, w, H, D, l = {
- type: "line",
- smooth: true,
- step: d
- };
- v.beginPath();
- v.moveTo(r[c * 3] * e + m, q[c * 3] * p + k);
- for (A = 0, w = c * 3 + 1; A < C.length - 3; A += 3, w += 3 * I) {
- o = r[w] * e + m;
- F = q[w] * p + k;
- n = r[w + 1] * e + m;
- E = q[w + 1] * p + k;
- h = u.roundPixel(C[A + 3]);
- g = C[A + 4];
- B = u.roundPixel(C[A]);
- a = C[A + 1];
- if (s) {
- l.x0 = B;
- l.y0 = a;
- l.cx1 = o;
- l.cy1 = F;
- l.cx2 = n;
- l.cy2 = E;
- l.x = h;
- l.y = g;
- D = [G, l, G.rendererData, c + A / 3 + 1];
- H = Ext.callback(s, null, D, 0, G.getSeries());
- v.save();
- Ext.apply(v, H)
- }
- if (t.fillArea) {
- v.moveTo(B, a);
- v.bezierCurveTo(o, F, n, E, h, g);
- v.lineTo(h, f);
- v.lineTo(B, f);
- v.lineTo(B, a);
- v.closePath();
- v.fill();
- v.beginPath()
- }
- v.moveTo(B, a);
- v.bezierCurveTo(o, F, n, E, h, g);
- v.stroke();
- v.moveTo(B, a);
- v.closePath();
- if (s) {
- v.restore()
- }
- v.beginPath();
- v.moveTo(h, g)
- }
- v.beginPath()
- },
- drawLabel: function(k, i, h, o, a) {
- var q = this,
- n = q.attr,
- e = q.getMarker("labels"),
- d = e.getTemplate(),
- m = q.labelCfg || (q.labelCfg = {}),
- c = q.surfaceMatrix,
- g, f, j = n.labelOverflowPadding,
- l, b, r, p, s;
- m.x = c.x(i, h);
- m.y = c.y(i, h);
- if (n.flipXY) {
- m.rotationRads = Math.PI * 0.5
- } else {
- m.rotationRads = 0
- }
- m.text = k;
- if (d.attr.renderer) {
- p = [k, e, m, q.rendererData, o];
- r = Ext.callback(d.attr.renderer, null, p, 0, q.getSeries());
- if (typeof r === "string") {
- m.text = r
- } else {
- if (typeof r === "object") {
- if ("text" in r) {
- m.text = r.text
- }
- s = true
- }
- }
- }
- b = q.getMarkerBBox("labels", o, true);
- if (!b) {
- q.putMarker("labels", m, o);
- b = q.getMarkerBBox("labels", o, true)
- }
- l = b.height / 2;
- g = i;
- switch (d.attr.display) {
- case "under":
- f = h - l - j;
- break;
- case "rotate":
- g += j;
- f = h - j;
- m.rotationRads = -Math.PI / 4;
- break;
- default:
- f = h + l + j
- }
- m.x = c.x(g, f);
- m.y = c.y(g, f);
- if (s) {
- Ext.apply(m, r)
- }
- q.putMarker("labels", m, o)
- },
- drawMarker: function(j, h, d) {
- var g = this,
- e = g.attr,
- f = e.renderer,
- c = g.surfaceMatrix,
- b = {},
- i, a;
- if (f && g.getMarker("markers")) {
- b.type = "marker";
- b.x = j;
- b.y = h;
- a = [g, b, g.rendererData, d];
- i = Ext.callback(f, null, a, 0, g.getSeries());
- if (i) {
- Ext.apply(b, i)
- }
- }
- b.translationX = c.x(j, h);
- b.translationY = c.y(j, h);
- delete b.x;
- delete b.y;
- g.putMarker("markers", b, d, !f)
- },
- drawStroke: function(a, c, h, b, f, e) {
- var d = this,
- g = d.attr.smooth && d.smoothX && d.smoothY;
- if (g) {
- d.drawSmoothStroke(a, c, h, b, f, e)
- } else {
- d.drawStraightStroke(a, c, h, b, f, e)
- }
- },
- renderAggregates: function(B, w, l, N, o, I, D) {
- var m = this,
- k = m.attr,
- s = k.dataX,
- r = k.dataY,
- h = k.labels,
- v = k.xAxis,
- a = k.yCap,
- g = k.smooth && m.smoothX && m.smoothY,
- d = h && m.getMarker("labels"),
- t = m.getMarker("markers"),
- E = k.matrix,
- u = N.devicePixelRatio,
- C = E.getXX(),
- f = E.getYY(),
- c = E.getDX(),
- b = E.getDY(),
- q = m.list || (m.list = []),
- F = B.minX,
- e = B.maxX,
- j = B.minY,
- P = B.maxY,
- U = B.startIdx,
- S = true,
- Q, T, L, K, R, G;
- m.rendererData = {
- store: m.getStore()
- };
- q.length = 0;
- for (R = w; R < l; R++) {
- var O = F[R],
- p = e[R],
- M = j[R],
- n = P[R];
- if (O < p) {
- q.push(O * C + c, M * f + b, U[R]);
- q.push(p * C + c, n * f + b, U[R])
- } else {
- if (O > p) {
- q.push(p * C + c, n * f + b, U[R]);
- q.push(O * C + c, M * f + b, U[R])
- } else {
- q.push(p * C + c, n * f + b, U[R])
- }
- }
- }
- if (q.length) {
- for (R = 0; R < q.length; R += 3) {
- L = q[R];
- K = q[R + 1];
- if (Ext.isNumber(L + K)) {
- if (K > a) {
- K = a
- } else {
- if (K < -a) {
- K = -a
- }
- }
- q[R + 1] = K
- } else {
- S = false;
- continue
- }
- G = q[R + 2];
- if (t) {
- m.drawMarker(L, K, G)
- }
- if (d && h[G]) {
- m.drawLabel(h[G], L, K, G, D)
- }
- }
- m.isContinuousLine = S;
- if (g && !S) {
- Ext.raise("Line smoothing in only supported for gapless data, where all data points are finite numbers.")
- }
- if (v) {
- T = v.getAlignment() === "vertical";
- if (Ext.isNumber(v.floatingAtCoord)) {
- Q = (T ? D[2] : D[3]) - v.floatingAtCoord
- } else {
- Q = T ? D[0] : D[1]
- }
- } else {
- Q = k.flipXY ? D[0] : D[1]
- }
- if (k.preciseStroke) {
- if (k.fillArea) {
- o.fill()
- }
- if (k.transformFillStroke) {
- k.inverseMatrix.toContext(o)
- }
- m.drawStroke(N, o, w, l, q, Q);
- if (k.transformFillStroke) {
- k.matrix.toContext(o)
- }
- o.stroke()
- } else {
- m.drawStroke(N, o, w, l, q, Q);
- if (S && g && k.fillArea && !k.renderer) {
- var A = s[s.length - 1] * C + c + u,
- z = r[r.length - 1] * f + b,
- J = s[0] * C + c - u,
- H = r[0] * f + b;
- o.lineTo(A, z);
- o.lineTo(A, Q - k.lineWidth);
- o.lineTo(J, Q - k.lineWidth);
- o.lineTo(J, H)
- }
- if (k.transformFillStroke) {
- k.matrix.toContext(o)
- }
- if (k.fillArea) {
- o.fillStroke(k, true)
- } else {
- o.stroke(true)
- }
- }
- }
- }
-});
-Ext.define("Ext.chart.series.Line", {
- extend: "Ext.chart.series.Cartesian",
- alias: "series.line",
- type: "line",
- seriesType: "lineSeries",
- requires: ["Ext.chart.series.sprite.Line"],
- config: {
- selectionTolerance: 20,
- smooth: false,
- step: false,
- fill: undefined,
- aggregator: {
- strategy: "double"
- }
- },
- defaultSmoothness: 3,
- overflowBuffer: 1,
- themeMarkerCount: function() {
- return 1
- },
- getDefaultSpriteConfig: function() {
- var d = this,
- e = d.callParent(arguments),
- c = Ext.apply({}, d.getStyle()),
- b, a = false;
- if (typeof d.config.fill != "undefined") {
- if (d.config.fill) {
- a = true;
- if (typeof c.fillStyle == "undefined") {
- if (typeof c.strokeStyle == "undefined") {
- b = d.getStyleWithTheme();
- c.fillStyle = b.fillStyle;
- c.strokeStyle = b.strokeStyle
- } else {
- c.fillStyle = c.strokeStyle
- }
- }
- }
- } else {
- if (c.fillStyle) {
- a = true
- }
- }
- if (!a) {
- delete c.fillStyle
- }
- c = Ext.apply(e || {}, c);
- return Ext.apply(c, {
- fillArea: a,
- step: d.config.step,
- smooth: d.config.smooth,
- selectionTolerance: d.config.selectionTolerance
- })
- },
- updateStep: function(b) {
- var a = this.getSprites()[0];
- if (a && a.attr.step !== b) {
- a.setAttributes({
- step: b
- })
- }
- },
- updateFill: function(b) {
- var a = this.getSprites()[0];
- if (a && a.attr.fillArea !== b) {
- a.setAttributes({
- fillArea: b
- })
- }
- },
- updateSmooth: function(a) {
- var b = this.getSprites()[0];
- if (b && b.attr.smooth !== a) {
- b.setAttributes({
- smooth: a
- })
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.PieSlice", {
- extend: "Ext.draw.sprite.Sector",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- alias: "sprite.pieslice",
- inheritableStatics: {
- def: {
- processors: {
- doCallout: "bool",
- label: "string",
- rotateLabels: "bool",
- labelOverflowPadding: "number",
- renderer: "default"
- },
- defaults: {
- doCallout: true,
- rotateLabels: true,
- label: "",
- labelOverflowPadding: 10,
- renderer: null
- }
- }
- },
- config: {
- rendererData: null,
- rendererIndex: 0,
- series: null
- },
- setGradientBBox: function(q, k) {
- var j = this,
- i = j.attr,
- g = (i.fillStyle && i.fillStyle.isGradient) || (i.strokeStyle && i.strokeStyle.isGradient);
- if (g && !i.constrainGradients) {
- var b = j.getMidAngle(),
- d = i.margin,
- e = i.centerX,
- c = i.centerY,
- a = i.endRho,
- l = i.matrix,
- o = l.getScaleX(),
- n = l.getScaleY(),
- m = o * a,
- f = n * a,
- p = {
- width: m + m,
- height: f + f
- };
- if (d) {
- e += d * Math.cos(b);
- c += d * Math.sin(b)
- }
- p.x = l.x(e, c) - m;
- p.y = l.y(e, c) - f;
- q.setGradientBBox(p)
- } else {
- j.callParent([q, k])
- }
- },
- render: function(b, c, g, f) {
- var e = this,
- a = e.attr,
- h = {},
- d;
- if (a.renderer) {
- h = {
- type: "sector",
- text: a.text,
- centerX: a.centerX,
- centerY: a.centerY,
- margin: a.margin,
- startAngle: Math.min(a.startAngle, a.endAngle),
- endAngle: Math.max(a.startAngle, a.endAngle),
- startRho: Math.min(a.startRho, a.endRho),
- endRho: Math.max(a.startRho, a.endRho)
- };
- d = Ext.callback(a.renderer, null, [e, h, e.rendererData, e.rendererIndex], 0, e.getSeries());
- e.setAttributes(d);
- e.useAttributes(c, g)
- }
- e.callParent([b, c, g, f]);
- if (a.label && e.getMarker("labels")) {
- e.placeLabel()
- }
- },
- placeLabel: function() {
- var z = this,
- s = z.attr,
- r = s.attributeId,
- t = Math.min(s.startAngle, s.endAngle),
- p = Math.max(s.startAngle, s.endAngle),
- k = (t + p) * 0.5,
- n = s.margin,
- h = s.centerX,
- g = s.centerY,
- f = Math.sin(k),
- c = Math.cos(k),
- v = Math.min(s.startRho, s.endRho) + n,
- m = Math.max(s.startRho, s.endRho) + n,
- l = (v + m) * 0.5,
- b = z.surfaceMatrix,
- o = z.labelCfg || (z.labelCfg = {}),
- e = z.getMarker("labels"),
- d = e.getTemplate(),
- a = d.getCalloutLine(),
- q = a && a.length || 40,
- u, j, i, A, w;
- b.appendMatrix(s.matrix);
- o.text = s.label;
- j = h + c * l;
- i = g + f * l;
- o.x = b.x(j, i);
- o.y = b.y(j, i);
- j = h + c * m;
- i = g + f * m;
- o.calloutStartX = b.x(j, i);
- o.calloutStartY = b.y(j, i);
- j = h + c * (m + q);
- i = g + f * (m + q);
- o.calloutPlaceX = b.x(j, i);
- o.calloutPlaceY = b.y(j, i);
- if (!s.rotateLabels) {
- o.rotationRads = 0
- } else {
- switch (d.attr.orientation) {
- case "horizontal":
- o.rotationRads = k + Math.atan2(b.y(1, 0) - b.y(0, 0), b.x(1, 0) - b.x(0, 0)) + Math.PI / 2;
- break;
- case "vertical":
- o.rotationRads = k + Math.atan2(b.y(1, 0) - b.y(0, 0), b.x(1, 0) - b.x(0, 0));
- break
- }
- }
- o.calloutColor = (a && a.color) || z.attr.fillStyle;
- if (a) {
- if (a.width) {
- o.calloutWidth = a.width
- }
- } else {
- o.calloutHasLine = false
- }
- o.globalAlpha = s.globalAlpha * s.fillOpacity;
- o.hidden = (s.startAngle == s.endAngle);
- if (d.attr.renderer) {
- w = [z.attr.label, e, o, z.rendererData, z.rendererIndex];
- A = Ext.callback(d.attr.renderer, null, w, 0, z.getSeries());
- if (typeof A === "string") {
- o.text = A
- } else {
- Ext.apply(o, A)
- }
- }
- z.putMarker("labels", o, r);
- u = z.getMarkerBBox("labels", r, true);
- if (u) {
- if (s.doCallout) {
- if (d.attr.display === "outside") {
- z.putMarker("labels", {
- callout: 1
- }, r)
- } else {
- if (d.attr.display === "inside") {
- z.putMarker("labels", {
- callout: 0
- }, r)
- } else {
- z.putMarker("labels", {
- callout: 1 - z.sliceContainsLabel(s, u)
- }, r)
- }
- }
- } else {
- z.putMarker("labels", {
- globalAlpha: z.sliceContainsLabel(s, u)
- }, r)
- }
- }
- },
- sliceContainsLabel: function(d, f) {
- var e = d.labelOverflowPadding,
- h = (d.endRho + d.startRho) / 2,
- g = h + (f.width + e) / 2,
- i = h - (f.width + e) / 2,
- j, c, b, a;
- if (e < 0) {
- return 1
- }
- if (f.width + e * 2 > (d.endRho - d.startRho)) {
- return 0
- }
- c = Math.sqrt(d.endRho * d.endRho - g * g);
- b = Math.sqrt(d.endRho * d.endRho - i * i);
- j = Math.abs(d.endAngle - d.startAngle);
- a = (j > Math.PI / 2 ? i : Math.abs(Math.tan(j / 2)) * i);
- if (f.height + e * 2 > Math.min(c, b, a) * 2) {
- return 0
- }
- return 1
- }
-});
-Ext.define("Ext.chart.series.Pie", {
- extend: "Ext.chart.series.Polar",
- requires: ["Ext.chart.series.sprite.PieSlice"],
- type: "pie",
- alias: "series.pie",
- seriesType: "pieslice",
- config: {
- donut: 0,
- rotation: 0,
- clockwise: true,
- totalAngle: 2 * Math.PI,
- hidden: [],
- radiusFactor: 100,
- highlightCfg: {
- margin: 20
- },
- style: {}
- },
- directions: ["X"],
- applyLabel: function(a, b) {
- if (Ext.isObject(a) && !Ext.isString(a.orientation)) {
- Ext.apply(a = Ext.Object.chain(a), {
- orientation: "vertical"
- })
- }
- return this.callParent([a, b])
- },
- updateLabelData: function() {
- var h = this,
- j = h.getStore(),
- g = j.getData().items,
- e = h.getSprites(),
- a = h.getLabel().getTemplate().getField(),
- d = h.getHidden(),
- b, f, c, k;
- if (e.length && a) {
- c = [];
- for (b = 0, f = g.length; b < f; b++) {
- c.push(g[b].get(a))
- }
- for (b = 0, f = e.length; b < f; b++) {
- k = e[b];
- k.setAttributes({
- label: c[b]
- });
- k.putMarker("labels", {
- hidden: d[b]
- }, k.attr.attributeId)
- }
- }
- },
- coordinateX: function() {
- var t = this,
- f = t.getStore(),
- q = f.getData().items,
- c = q.length,
- b = t.getXField(),
- e = t.getYField(),
- l, a = 0,
- m, k, s = 0,
- o = t.getHidden(),
- d = [],
- p, g = 0,
- h = t.getTotalAngle(),
- r = t.getClockwise() ? 1 : -1,
- j = t.getSprites(),
- n;
- if (!j) {
- return
- }
- for (p = 0; p < c; p++) {
- l = Math.abs(Number(q[p].get(b))) || 0;
- k = e && Math.abs(Number(q[p].get(e))) || 0;
- if (!o[p]) {
- a += l;
- if (k > s) {
- s = k
- }
- }
- d[p] = a;
- if (p >= o.length) {
- o[p] = false
- }
- }
- o.length = c;
- t.maxY = s;
- if (a !== 0) {
- m = h / a
- }
- for (p = 0; p < c; p++) {
- j[p].setAttributes({
- startAngle: g,
- endAngle: g = (m ? r * d[p] * m : 0),
- globalAlpha: 1
- })
- }
- if (c < t.sprites.length) {
- for (p = c; p < t.sprites.length; p++) {
- n = t.sprites[p];
- n.getMarker("labels").clear(n.getId());
- n.releaseMarker("labels");
- n.destroy()
- }
- t.sprites.length = c
- }
- for (p = c; p < t.sprites.length; p++) {
- j[p].setAttributes({
- startAngle: h,
- endAngle: h,
- globalAlpha: 0
- })
- }
- t.getChart().refreshLegendStore()
- },
- updateCenter: function(a) {
- this.setStyle({
- translationX: a[0] + this.getOffsetX(),
- translationY: a[1] + this.getOffsetY()
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- this.setStyle({
- startRho: a * this.getDonut() * 0.01,
- endRho: a * this.getRadiusFactor() * 0.01
- });
- this.doUpdateStyles()
- },
- getStyleByIndex: function(c) {
- var g = this,
- j = g.getStore(),
- k = j.getAt(c),
- f = g.getYField(),
- d = g.getRadius(),
- a = {},
- e, b, h;
- if (k) {
- h = f && Math.abs(Number(k.get(f))) || 0;
- e = d * g.getDonut() * 0.01;
- b = d * g.getRadiusFactor() * 0.01;
- a = g.callParent([c]);
- a.startRho = e;
- a.endRho = g.maxY ? (e + (b - e) * h / g.maxY) : b
- }
- return a
- },
- updateDonut: function(b) {
- var a = this.getRadius();
- this.setStyle({
- startRho: a * b * 0.01,
- endRho: a * this.getRadiusFactor() * 0.01
- });
- this.doUpdateStyles()
- },
- rotationOffset: -Math.PI / 2,
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a + this.rotationOffset
- });
- this.doUpdateStyles()
- },
- updateTotalAngle: function(a) {
- this.processData()
- },
- getSprites: function() {
- var k = this,
- h = k.getChart(),
- n = k.getStore();
- if (!h || !n) {
- return []
- }
- k.getColors();
- k.getSubStyle();
- var j = n.getData().items,
- b = j.length,
- d = k.getAnimation() || h && h.getAnimation(),
- g = k.sprites,
- o, l = 0,
- f, e, c = false,
- m = k.getLabel(),
- a = m.getTemplate();
- f = {
- store: n,
- field: k.getXField(),
- angleField: k.getXField(),
- radiusField: k.getYField(),
- series: k
- };
- for (e = 0; e < b; e++) {
- o = g[e];
- if (!o) {
- o = k.createSprite();
- if (k.getHighlight()) {
- o.config.highlight = k.getHighlight();
- o.addModifier("highlight", true)
- }
- if (a.getField()) {
- a.setAttributes({
- labelOverflowPadding: k.getLabelOverflowPadding()
- });
- a.fx.setCustomDurations({
- callout: 200
- })
- }
- o.setAttributes(k.getStyleByIndex(e));
- o.rendererData = f;
- o.rendererIndex = l++;
- c = true
- }
- o.setAnimation(d)
- }
- if (c) {
- k.doUpdateStyles()
- }
- return k.sprites
- },
- betweenAngle: function(d, f, c) {
- var e = Math.PI * 2,
- g = this.rotationOffset;
- if (!this.getClockwise()) {
- d *= -1;
- f *= -1;
- c *= -1;
- f -= g;
- c -= g
- } else {
- f += g;
- c += g
- }
- d -= f;
- c -= f;
- d %= e;
- c %= e;
- d += e;
- c += e;
- d %= e;
- c %= e;
- return d < c || c === 0
- },
- getItemForAngle: function(a) {
- var h = this,
- f = h.getSprites(),
- d;
- a %= Math.PI * 2;
- while (a < 0) {
- a += Math.PI * 2
- }
- if (f) {
- var j = h.getStore(),
- g = j.getData().items,
- c = h.getHidden(),
- b = 0,
- e = j.getCount();
- for (; b < e; b++) {
- if (!c[b]) {
- d = f[b].attr;
- if (d.startAngle <= a && d.endAngle >= a) {
- return {
- series: h,
- sprite: f[b],
- index: b,
- record: g[b],
- field: h.getXField()
- }
- }
- }
- }
- }
- return null
- },
- getItemForPoint: function(f, e) {
- var t = this,
- c = t.getSprites();
- if (c) {
- var s = t.getCenter(),
- q = t.getOffsetX(),
- p = t.getOffsetY(),
- j = f - s[0] + q,
- h = e - s[1] + p,
- b = t.getStore(),
- g = t.getDonut(),
- o = b.getData().items,
- r = Math.atan2(h, j) - t.getRotation(),
- a = Math.sqrt(j * j + h * h),
- l = t.getRadius() * g * 0.01,
- m = t.getHidden(),
- n, d, k;
- for (n = 0, d = o.length; n < d; n++) {
- if (!m[n]) {
- k = c[n].attr;
- if (a >= l + k.margin && a <= k.endRho + k.margin) {
- if (t.betweenAngle(r, k.startAngle, k.endAngle)) {
- return {
- series: t,
- sprite: c[n],
- index: n,
- record: o[n],
- field: t.getXField()
- }
- }
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(f) {
- var h = this,
- j = h.getStore();
- if (j) {
- var g = j.getData().items,
- b = h.getLabel().getTemplate().getField(),
- c = h.getXField(),
- e = h.getHidden(),
- d, a, k;
- for (d = 0; d < g.length; d++) {
- a = h.getStyleByIndex(d);
- k = a.fillStyle;
- if (Ext.isObject(k)) {
- k = k.stops && k.stops[0].color
- }
- f.push({
- name: b ? String(g[d].get(b)) : c + " " + d,
- mark: k || a.strokeStyle || "black",
- disabled: e[d],
- series: h.getId(),
- index: d
- })
- }
- }
- }
-});
-Ext.define("Ext.chart.series.sprite.Pie3DPart", {
- extend: "Ext.draw.sprite.Path",
- mixins: {
- markerHolder: "Ext.chart.MarkerHolder"
- },
- alias: "sprite.pie3dPart",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- margin: "number",
- thickness: "number",
- bevelWidth: "number",
- distortion: "number",
- baseColor: "color",
- colorSpread: "number",
- baseRotation: "number",
- part: "enums(top,bottom,start,end,innerFront,innerBack,outerFront,outerBack)",
- label: "string"
- },
- aliases: {
- rho: "endRho"
- },
- triggers: {
- centerX: "path,bbox",
- centerY: "path,bbox",
- startAngle: "path,partZIndex",
- endAngle: "path,partZIndex",
- startRho: "path",
- endRho: "path,bbox",
- margin: "path,bbox",
- thickness: "path",
- distortion: "path",
- baseRotation: "path,partZIndex",
- baseColor: "partZIndex,partColor",
- colorSpread: "partColor",
- part: "path,partZIndex",
- globalAlpha: "canvas,alpha"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: Math.PI * 2,
- endAngle: Math.PI * 2,
- startRho: 0,
- endRho: 150,
- margin: 0,
- thickness: 35,
- distortion: 0.5,
- baseRotation: 0,
- baseColor: "white",
- colorSpread: 1,
- miterLimit: 1,
- bevelWidth: 5,
- strokeOpacity: 0,
- part: "top",
- label: ""
- },
- updaters: {
- alpha: "alphaUpdater",
- partColor: "partColorUpdater",
- partZIndex: "partZIndexUpdater"
- }
- }
- },
- bevelParams: [],
- constructor: function(a) {
- this.callParent([a]);
- this.bevelGradient = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: "rgba(255,255,255,0)"
- }, {
- offset: 0.7,
- color: "rgba(255,255,255,0.6)"
- }, {
- offset: 1,
- color: "rgba(255,255,255,0)"
- }]
- })
- },
- alphaUpdater: function(a) {
- var d = this,
- c = a.globalAlpha,
- b = d.oldOpacity;
- if (c !== b && (c === 1 || b === 1)) {
- d.scheduleUpdater(a, "path", ["globalAlpha"]);
- d.oldOpacity = c
- }
- },
- partColorUpdater: function(a) {
- var d = Ext.draw.Color.fly(a.baseColor),
- b = d.toString(),
- e = a.colorSpread,
- c;
- switch (a.part) {
- case "top":
- c = new Ext.draw.gradient.Radial({
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- },
- stops: [{
- offset: 0,
- color: d.createLighter(0.1 * e)
- }, {
- offset: 1,
- color: d.createDarker(0.1 * e)
- }]
- });
- break;
- case "bottom":
- c = new Ext.draw.gradient.Radial({
- start: {
- x: 0,
- y: 0,
- r: 0
- },
- end: {
- x: 0,
- y: 0,
- r: 1
- },
- stops: [{
- offset: 0,
- color: d.createDarker(0.2 * e)
- }, {
- offset: 1,
- color: d.toString()
- }]
- });
- break;
- case "outerFront":
- case "outerBack":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.15 * e).toString()
- }, {
- offset: 0.3,
- color: b
- }, {
- offset: 0.8,
- color: d.createLighter(0.2 * e).toString()
- }, {
- offset: 1,
- color: d.createDarker(0.25 * e).toString()
- }]
- });
- break;
- case "start":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 1,
- color: d.createLighter(0.2 * e).toString()
- }]
- });
- break;
- case "end":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 1,
- color: d.createLighter(0.2 * e).toString()
- }]
- });
- break;
- case "innerFront":
- case "innerBack":
- c = new Ext.draw.gradient.Linear({
- stops: [{
- offset: 0,
- color: d.createDarker(0.1 * e).toString()
- }, {
- offset: 0.2,
- color: d.createLighter(0.2 * e).toString()
- }, {
- offset: 0.7,
- color: b
- }, {
- offset: 1,
- color: d.createDarker(0.1 * e).toString()
- }]
- });
- break
- }
- a.fillStyle = c;
- a.canvasAttributes.fillStyle = c
- },
- partZIndexUpdater: function(a) {
- var c = Ext.draw.sprite.AttributeParser.angle,
- e = a.baseRotation,
- d = a.startAngle,
- b = a.endAngle,
- f;
- switch (a.part) {
- case "top":
- a.zIndex = 5;
- break;
- case "outerFront":
- d = c(d + e);
- b = c(b + e);
- if (d >= 0 && b < 0) {
- f = Math.sin(d)
- } else {
- if (d <= 0 && b > 0) {
- f = Math.sin(b)
- } else {
- if (d >= 0 && b > 0) {
- if (d > b) {
- f = 0
- } else {
- f = Math.max(Math.sin(d), Math.sin(b))
- }
- } else {
- f = 1
- }
- }
- }
- a.zIndex = 4 + f;
- break;
- case "outerBack":
- a.zIndex = 1;
- break;
- case "start":
- a.zIndex = 4 + Math.sin(c(d + e));
- break;
- case "end":
- a.zIndex = 4 + Math.sin(c(b + e));
- break;
- case "innerFront":
- a.zIndex = 2;
- break;
- case "innerBack":
- a.zIndex = 4 + Math.sin(c((d + b) / 2 + e));
- break;
- case "bottom":
- a.zIndex = 0;
- break
- }
- a.dirtyZIndex = true
- },
- updatePlainBBox: function(k) {
- var f = this.attr,
- a = f.part,
- b = f.baseRotation,
- e = f.centerX,
- d = f.centerY,
- j, c, i, h, g, l;
- if (a === "start") {
- c = f.startAngle + b
- } else {
- if (a === "end") {
- c = f.endAngle + b
- }
- }
- if (Ext.isNumber(c)) {
- g = Math.sin(c);
- l = Math.cos(c);
- i = Math.min(e + l * f.startRho, e + l * f.endRho);
- h = d + g * f.startRho * f.distortion;
- k.x = i;
- k.y = h;
- k.width = l * (f.endRho - f.startRho);
- k.height = f.thickness + g * (f.endRho - f.startRho) * 2;
- return
- }
- if (a === "innerFront" || a === "innerBack") {
- j = f.startRho
- } else {
- j = f.endRho
- }
- k.width = j * 2;
- k.height = j * f.distortion * 2 + f.thickness;
- k.x = f.centerX - j;
- k.y = f.centerY - j * f.distortion
- },
- updateTransformedBBox: function(a) {
- if (this.attr.part === "start" || this.attr.part === "end") {
- return this.callParent(arguments)
- }
- return this.updatePlainBBox(a)
- },
- updatePath: function(a) {
- if (!this.attr.globalAlpha) {
- return
- }
- if (this.attr.endAngle < this.attr.startAngle) {
- return
- }
- this[this.attr.part + "Renderer"](a)
- },
- render: function(b, c) {
- var d = this,
- a = d.attr;
- if (!a.globalAlpha) {
- return
- }
- d.callParent([b, c]);
- d.bevelRenderer(b, c);
- if (a.label && d.getMarker("labels")) {
- d.placeLabel()
- }
- },
- placeLabel: function() {
- var z = this,
- u = z.attr,
- t = u.attributeId,
- p = u.margin,
- c = u.distortion,
- i = u.centerX,
- h = u.centerY,
- j = u.baseRotation,
- v = u.startAngle + j,
- r = u.endAngle + j,
- m = (v + r) / 2,
- w = u.startRho + p,
- o = u.endRho + p,
- n = (w + o) / 2,
- a = Math.sin(m),
- b = Math.cos(m),
- e = z.surfaceMatrix,
- g = z.getMarker("labels"),
- f = g.getTemplate(),
- d = f.getCalloutLine(),
- s = d && d.length || 40,
- q = {},
- l, k;
- e.appendMatrix(u.matrix);
- q.text = u.label;
- l = i + b * n;
- k = h + a * n * c;
- q.x = e.x(l, k);
- q.y = e.y(l, k);
- l = i + b * o;
- k = h + a * o * c;
- q.calloutStartX = e.x(l, k);
- q.calloutStartY = e.y(l, k);
- l = i + b * (o + s);
- k = h + a * (o + s) * c;
- q.calloutPlaceX = e.x(l, k);
- q.calloutPlaceY = e.y(l, k);
- q.calloutWidth = 2;
- z.putMarker("labels", q, t);
- z.putMarker("labels", {
- callout: 1
- }, t)
- },
- bevelRenderer: function(b, c) {
- var f = this,
- a = f.attr,
- e = a.bevelWidth,
- g = f.bevelParams,
- d;
- for (d = 0; d < g.length; d++) {
- c.beginPath();
- c.ellipse.apply(c, g[d]);
- c.save();
- c.lineWidth = e;
- c.strokeOpacity = e ? 1 : 0;
- c.strokeGradient = f.bevelGradient;
- c.stroke(a);
- c.restore()
- }
- },
- lidRenderer: function(o, m) {
- var k = this.attr,
- g = k.margin,
- c = k.distortion,
- i = k.centerX,
- h = k.centerY,
- f = k.baseRotation,
- j = k.startAngle + f,
- e = k.endAngle + f,
- d = (j + e) / 2,
- l = k.startRho,
- b = k.endRho,
- n = Math.sin(e),
- a = Math.cos(e);
- i += Math.cos(d) * g;
- h += Math.sin(d) * g * c;
- o.ellipse(i, h + m, l, l * c, 0, j, e, false);
- o.lineTo(i + a * b, h + m + n * b * c);
- o.ellipse(i, h + m, b, b * c, 0, e, j, true);
- o.closePath()
- },
- topRenderer: function(a) {
- this.lidRenderer(a, 0)
- },
- bottomRenderer: function(b) {
- var a = this.attr;
- if (a.globalAlpha < 1 || a.shadowColor !== Ext.draw.Color.RGBA_NONE) {
- this.lidRenderer(b, a.thickness)
- }
- },
- sideRenderer: function(l, s) {
- var o = this.attr,
- k = o.margin,
- g = o.centerX,
- f = o.centerY,
- e = o.distortion,
- h = o.baseRotation,
- p = o.startAngle + h,
- m = o.endAngle + h,
- a = o.thickness,
- q = o.startRho,
- j = o.endRho,
- r = (s === "start" && p) || (s === "end" && m),
- b = Math.sin(r),
- d = Math.cos(r),
- c = o.globalAlpha < 1,
- n = s === "start" && d < 0 || s === "end" && d > 0 || c,
- i;
- if (n) {
- i = (p + m) / 2;
- g += Math.cos(i) * k;
- f += Math.sin(i) * k * e;
- l.moveTo(g + d * q, f + b * q * e);
- l.lineTo(g + d * j, f + b * j * e);
- l.lineTo(g + d * j, f + b * j * e + a);
- l.lineTo(g + d * q, f + b * q * e + a);
- l.closePath()
- }
- },
- startRenderer: function(a) {
- this.sideRenderer(a, "start")
- },
- endRenderer: function(a) {
- this.sideRenderer(a, "end")
- },
- rimRenderer: function(q, e, o, j) {
- var w = this,
- s = w.attr,
- p = s.margin,
- h = s.centerX,
- g = s.centerY,
- d = s.distortion,
- i = s.baseRotation,
- t = Ext.draw.sprite.AttributeParser.angle,
- u = s.startAngle + i,
- r = s.endAngle + i,
- k = t((u + r) / 2),
- a = s.thickness,
- b = s.globalAlpha < 1,
- c, n, v;
- w.bevelParams = [];
- u = t(u);
- r = t(r);
- h += Math.cos(k) * p;
- g += Math.sin(k) * p * d;
- c = u >= 0 && r >= 0;
- n = u <= 0 && r <= 0;
-
- function l() {
- q.ellipse(h, g + a, e, e * d, 0, Math.PI, u, true);
- q.lineTo(h + Math.cos(u) * e, g + Math.sin(u) * e * d);
- v = [h, g, e, e * d, 0, u, Math.PI, false];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function f() {
- q.ellipse(h, g + a, e, e * d, 0, 0, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, 0, true];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function x() {
- q.ellipse(h, g + a, e, e * d, 0, Math.PI, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, Math.PI, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
-
- function m() {
- q.ellipse(h, g + a, e, e * d, 0, u, 0, false);
- q.lineTo(h + e, g);
- v = [h, g, e, e * d, 0, 0, u, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- if (j) {
- if (!o || b) {
- if (u >= 0 && r < 0) {
- l()
- } else {
- if (u <= 0 && r > 0) {
- f()
- } else {
- if (u <= 0 && r < 0) {
- if (u > r) {
- q.ellipse(h, g + a, e, e * d, 0, 0, Math.PI, false);
- q.lineTo(h - e, g);
- v = [h, g, e, e * d, 0, Math.PI, 0, true];
- if (!o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- } else {
- if (u > r) {
- l();
- f()
- } else {
- v = [h, g, e, e * d, 0, u, r, false];
- if (c && !o || n && o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d + a);
- q.ellipse(h, g + a, e, e * d, 0, r, u, true);
- q.closePath()
- }
- }
- }
- }
- }
- } else {
- if (o || b) {
- if (u >= 0 && r < 0) {
- x()
- } else {
- if (u <= 0 && r > 0) {
- m()
- } else {
- if (u <= 0 && r < 0) {
- if (u > r) {
- x();
- m()
- } else {
- q.ellipse(h, g + a, e, e * d, 0, u, r, false);
- q.lineTo(h + Math.cos(r) * e, g + Math.sin(r) * e * d);
- v = [h, g, e, e * d, 0, r, u, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- } else {
- if (u > r) {
- q.ellipse(h, g + a, e, e * d, 0, -Math.PI, 0, false);
- q.lineTo(h + e, g);
- v = [h, g, e, e * d, 0, 0, -Math.PI, true];
- if (o) {
- w.bevelParams.push(v)
- }
- q.ellipse.apply(q, v);
- q.closePath()
- }
- }
- }
- }
- }
- }
- },
- innerFrontRenderer: function(a) {
- this.rimRenderer(a, this.attr.startRho, true, true)
- },
- innerBackRenderer: function(a) {
- this.rimRenderer(a, this.attr.startRho, true, false)
- },
- outerFrontRenderer: function(a) {
- this.rimRenderer(a, this.attr.endRho, false, true)
- },
- outerBackRenderer: function(a) {
- this.rimRenderer(a, this.attr.endRho, false, false)
- }
-});
-Ext.define("Ext.draw.PathUtil", function() {
- var a = Math.abs,
- c = Math.pow,
- e = Math.cos,
- b = Math.acos,
- d = Math.sqrt,
- f = Math.PI;
- return {
- singleton: true,
- requires: ["Ext.draw.overrides.Path", "Ext.draw.overrides.sprite.Path", "Ext.draw.overrides.sprite.Instancing", "Ext.draw.overrides.Surface"],
- cubicRoots: function(m) {
- var z = m[0],
- x = m[1],
- w = m[2],
- v = m[3];
- if (z === 0) {
- return this.quadraticRoots(x, w, v)
- }
- var s = x / z,
- r = w / z,
- q = v / z,
- k = (3 * r - c(s, 2)) / 9,
- j = (9 * s * r - 27 * q - 2 * c(s, 3)) / 54,
- p = c(k, 3) + c(j, 2),
- n = [],
- h, g, o, l, u, y = Ext.Number.sign;
- if (p >= 0) {
- h = y(j + d(p)) * c(a(j + d(p)), 1 / 3);
- g = y(j - d(p)) * c(a(j - d(p)), 1 / 3);
- n[0] = -s / 3 + (h + g);
- n[1] = -s / 3 - (h + g) / 2;
- n[2] = n[1];
- o = a(d(3) * (h - g) / 2);
- if (o !== 0) {
- n[1] = -1;
- n[2] = -1
- }
- } else {
- l = b(j / d(-c(k, 3)));
- n[0] = 2 * d(-k) * e(l / 3) - s / 3;
- n[1] = 2 * d(-k) * e((l + 2 * f) / 3) - s / 3;
- n[2] = 2 * d(-k) * e((l + 4 * f) / 3) - s / 3
- }
- for (u = 0; u < 3; u++) {
- if (n[u] < 0 || n[u] > 1) {
- n[u] = -1
- }
- }
- return n
- },
- quadraticRoots: function(h, g, n) {
- var m, l, k, j;
- if (h === 0) {
- return this.linearRoot(g, n)
- }
- m = g * g - 4 * h * n;
- if (m === 0) {
- k = [-g / (2 * h)]
- } else {
- if (m > 0) {
- l = d(m);
- k = [(-g - l) / (2 * h), (-g + l) / (2 * h)]
- } else {
- return []
- }
- }
- for (j = 0; j < k.length; j++) {
- if (k[j] < 0 || k[j] > 1) {
- k[j] = -1
- }
- }
- return k
- },
- linearRoot: function(h, g) {
- var i = -g / h;
- if (h === 0 || i < 0 || i > 1) {
- return []
- }
- return [i]
- },
- bezierCoeffs: function(h, g, k, j) {
- var i = [];
- i[0] = -h + 3 * g - 3 * k + j;
- i[1] = 3 * h - 6 * g + 3 * k;
- i[2] = -3 * h + 3 * g;
- i[3] = h;
- return i
- },
- cubicLineIntersections: function(I, G, F, E, l, k, j, h, M, p, K, n) {
- var u = [],
- N = [],
- D = p - n,
- z = K - M,
- y = M * (n - p) - p * (K - M),
- L = this.bezierCoeffs(I, G, F, E),
- J = this.bezierCoeffs(l, k, j, h),
- H, x, w, v, g, q, o, m;
- u[0] = D * L[0] + z * J[0];
- u[1] = D * L[1] + z * J[1];
- u[2] = D * L[2] + z * J[2];
- u[3] = D * L[3] + z * J[3] + y;
- x = this.cubicRoots(u);
- for (H = 0; H < x.length; H++) {
- v = x[H];
- if (v < 0 || v > 1) {
- continue
- }
- g = v * v;
- q = g * v;
- o = L[0] * q + L[1] * g + L[2] * v + L[3];
- m = J[0] * q + J[1] * g + J[2] * v + J[3];
- if ((K - M) !== 0) {
- w = (o - M) / (K - M)
- } else {
- w = (m - p) / (n - p)
- }
- if (!(w < 0 || w > 1)) {
- N.push([o, m])
- }
- }
- return N
- },
- splitCubic: function(g, q, p, o, m) {
- var j = m * m,
- n = m * j,
- i = m - 1,
- h = i * i,
- k = i * h,
- l = n * o - 3 * j * i * p + 3 * m * h * q - k * g;
- return [
- [g, m * q - i * g, j * p - 2 * m * i * q + h * g, l],
- [l, j * o - 2 * m * i * p + h * q, m * o - i * p, o]
- ]
- },
- cubicDimension: function(p, o, l, k) {
- var j = 3 * (-p + 3 * (o - l) + k),
- i = 6 * (p - 2 * o + l),
- h = -3 * (p - o),
- q, n, g = Math.min(p, k),
- m = Math.max(p, k),
- r;
- if (j === 0) {
- if (i === 0) {
- return [g, m]
- } else {
- q = -h / i;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- }
- } else {
- r = i * i - 4 * j * h;
- if (r >= 0) {
- r = d(r);
- q = (r - i) / 2 / j;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- if (r > 0) {
- q -= r / j;
- if (0 < q && q < 1) {
- n = this.interpolateCubic(p, o, l, k, q);
- g = Math.min(g, n);
- m = Math.max(m, n)
- }
- }
- }
- }
- return [g, m]
- },
- interpolateCubic: function(h, g, l, k, i) {
- if (i === 0) {
- return h
- }
- if (i === 1) {
- return k
- }
- var j = (1 - i) / i;
- return i * i * i * (k + j * (3 * l + j * (3 * g + j * h)))
- },
- cubicsIntersections: function(r, q, p, o, A, z, y, v, g, F, E, D, m, l, k, i) {
- var C = this,
- x = C.cubicDimension(r, q, p, o),
- B = C.cubicDimension(A, z, y, v),
- n = C.cubicDimension(g, F, E, D),
- s = C.cubicDimension(m, l, k, i),
- j, h, u, t, w = [];
- if (x[0] > n[1] || x[1] < n[0] || B[0] > s[1] || B[1] < s[0]) {
- return []
- }
- if (a(A - z) < 1 && a(y - v) < 1 && a(r - o) < 1 && a(q - p) < 1 && a(m - l) < 1 && a(k - i) < 1 && a(g - D) < 1 && a(F - E) < 1) {
- return [
- [(r + o) * 0.5, (A + z) * 0.5]
- ]
- }
- j = C.splitCubic(r, q, p, o, 0.5);
- h = C.splitCubic(A, z, y, v, 0.5);
- u = C.splitCubic(g, F, E, D, 0.5);
- t = C.splitCubic(m, l, k, i, 0.5);
- w.push.apply(w, C.cubicsIntersections.apply(C, j[0].concat(h[0], u[0], t[0])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[0].concat(h[0], u[1], t[1])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[1].concat(h[1], u[0], t[0])));
- w.push.apply(w, C.cubicsIntersections.apply(C, j[1].concat(h[1], u[1], t[1])));
- return w
- },
- linesIntersection: function(k, p, j, o, h, n, q, m) {
- var l = (j - k) * (m - n) - (o - p) * (q - h),
- i, g;
- if (l === 0) {
- return null
- }
- i = ((q - h) * (p - n) - (k - h) * (m - n)) / l;
- g = ((j - k) * (p - n) - (o - p) * (k - h)) / l;
- if (i >= 0 && i <= 1 && g >= 0 && g <= 1) {
- return [k + i * (j - k), p + i * (o - p)]
- }
- return null
- },
- pointOnLine: function(j, m, h, l, g, n) {
- var k, i;
- if (a(h - j) < a(l - m)) {
- i = j;
- j = m;
- m = i;
- i = h;
- h = l;
- l = i;
- i = g;
- g = n;
- n = i
- }
- k = (g - j) / (h - j);
- if (k < 0 || k > 1) {
- return false
- }
- return a(m + k * (l - m) - n) < 4
- },
- pointOnCubic: function(w, u, s, r, l, k, h, g, p, o) {
- var C = this,
- B = C.bezierCoeffs(w, u, s, r),
- A = C.bezierCoeffs(l, k, h, g),
- z, v, n, m, q;
- B[3] -= p;
- A[3] -= o;
- n = C.cubicRoots(B);
- m = C.cubicRoots(A);
- for (z = 0; z < n.length; z++) {
- q = n[z];
- for (v = 0; v < m.length; v++) {
- if (q >= 0 && q <= 1 && a(q - m[v]) < 0.05) {
- return true
- }
- }
- }
- return false
- }
- }
-});
-Ext.define("Ext.chart.series.Pie3D", {
- extend: "Ext.chart.series.Polar",
- requires: ["Ext.chart.series.sprite.Pie3DPart", "Ext.draw.PathUtil"],
- type: "pie3d",
- seriesType: "pie3d",
- alias: "series.pie3d",
- isPie3D: true,
- config: {
- rect: [0, 0, 0, 0],
- thickness: 35,
- distortion: 0.5,
- donut: false,
- hidden: [],
- highlightCfg: {
- margin: 20
- },
- shadow: false
- },
- rotationOffset: -Math.PI / 2,
- setField: function(a) {
- return this.setXField(a)
- },
- getField: function() {
- return this.getXField()
- },
- updateRotation: function(a) {
- this.setStyle({
- baseRotation: a + this.rotationOffset
- });
- this.doUpdateStyles()
- },
- updateDistortion: function() {
- this.setRadius()
- },
- updateThickness: function() {
- this.setRadius()
- },
- updateColors: function(a) {
- this.setSubStyle({
- baseColor: a
- })
- },
- applyShadow: function(a) {
- if (a === true) {
- a = {
- shadowColor: "rgba(0,0,0,0.8)",
- shadowBlur: 30
- }
- } else {
- if (!Ext.isObject(a)) {
- a = {
- shadowColor: Ext.draw.Color.RGBA_NONE
- }
- }
- }
- return a
- },
- updateShadow: function(g) {
- var e = this,
- f = e.getSprites(),
- d = e.spritesPerSlice,
- c = f && f.length,
- b, a;
- for (b = 1; b < c; b += d) {
- a = f[b];
- if (a.attr.part = "bottom") {
- a.setAttributes(g)
- }
- }
- },
- getStyleByIndex: function(b) {
- var d = this.callParent([b]),
- c = this.getStyle(),
- a = d.fillStyle || d.fill || d.color,
- e = c.strokeStyle || c.stroke;
- if (a) {
- d.baseColor = a;
- delete d.fillStyle;
- delete d.fill;
- delete d.color
- }
- if (e) {
- d.strokeStyle = e
- }
- return d
- },
- doUpdateStyles: function() {
- var g = this,
- h = g.getSprites(),
- f = g.spritesPerSlice,
- e = h && h.length,
- c = 0,
- b = 0,
- a, d;
- for (; c < e; c += f, b++) {
- d = g.getStyleByIndex(b);
- for (a = 0; a < f; a++) {
- h[c + a].setAttributes(d)
- }
- }
- },
- coordinateX: function() {
- var w = this,
- m = w.getChart(),
- u = m && m.getAnimation(),
- f = w.getStore(),
- t = f.getData().items,
- d = t.length,
- b = w.getXField(),
- p = w.getRotation(),
- s = w.getHidden(),
- n, c = 0,
- h, e = [],
- k = w.getSprites(),
- a = k.length,
- l = w.spritesPerSlice,
- g = 0,
- o = Math.PI * 2,
- v = 1e-10,
- r, q;
- for (r = 0; r < d; r++) {
- n = Math.abs(Number(t[r].get(b))) || 0;
- if (!s[r]) {
- c += n
- }
- e[r] = c;
- if (r >= s.length) {
- s[r] = false
- }
- }
- s.length = d;
- if (c === 0) {
- return
- }
- h = 2 * Math.PI / c;
- for (r = 0; r < d; r++) {
- e[r] *= h
- }
- for (r = 0; r < a; r++) {
- k[r].setAnimation(u)
- }
- for (r = 0; r < d; r++) {
- for (q = 0; q < l; q++) {
- k[r * l + q].setAttributes({
- startAngle: g,
- endAngle: e[r] - v,
- globalAlpha: 1,
- baseRotation: p
- })
- }
- g = e[r]
- }
- for (r *= l; r < a; r++) {
- k[r].setAnimation(u);
- k[r].setAttributes({
- startAngle: o,
- endAngle: o,
- globalAlpha: 0,
- baseRotation: p
- })
- }
- },
- updateLabelData: function() {
- var l = this,
- m = l.getStore(),
- k = m.getData().items,
- h = l.getSprites(),
- b = l.getLabel().getTemplate().getField(),
- f = l.getHidden(),
- a = l.spritesPerSlice,
- d, c, g, e, n;
- if (h.length && b) {
- e = [];
- for (d = 0, g = k.length; d < g; d++) {
- e.push(k[d].get(b))
- }
- for (d = 0, c = 0, g = h.length; d < g; d += a, c++) {
- n = h[d];
- n.setAttributes({
- label: e[c]
- });
- n.putMarker("labels", {
- hidden: f[c]
- }, n.attr.attributeId)
- }
- }
- },
- applyRadius: function() {
- var f = this,
- d = f.getChart(),
- h = d.getInnerPadding(),
- e = d.getMainRect() || [0, 0, 1, 1],
- c = e[2] - h * 2,
- a = e[3] - h * 2 - f.getThickness(),
- g = c / 2,
- b = g * f.getDistortion();
- if (b > a / 2) {
- return a / (f.getDistortion() * 2)
- } else {
- return g
- }
- },
- getSprites: function() {
- var y = this,
- e = y.getStore();
- if (!e) {
- return []
- }
- var n = y.getChart(),
- p = y.getSurface(),
- t = e.getData().items,
- l = y.spritesPerSlice,
- a = t.length,
- v = y.getAnimation() || n && n.getAnimation(),
- x = y.getCenter(),
- w = y.getOffsetX(),
- u = y.getOffsetY(),
- b = y.getRadius(),
- q = y.getRotation(),
- d = y.getHighlight(),
- c = {
- centerX: x[0] + w,
- centerY: x[1] + u - y.getThickness() / 2,
- endRho: b,
- startRho: b * y.getDonut() / 100,
- thickness: y.getThickness(),
- distortion: y.getDistortion()
- },
- k = y.sprites,
- h = y.getLabel(),
- f = h.getTemplate(),
- m, g, o, s, r;
- for (s = 0; s < a; s++) {
- g = Ext.apply({}, this.getStyleByIndex(s), c);
- if (!k[s * l]) {
- for (r = 0; r < y.partNames.length; r++) {
- o = p.add({
- type: "pie3dPart",
- part: y.partNames[r]
- });
- if (r === 0 && f.getField()) {
- o.bindMarker("labels", h)
- }
- o.fx.setDurationOn("baseRotation", q);
- if (d) {
- o.config.highlight = d;
- o.addModifier("highlight", true)
- }
- o.setAttributes(g);
- k.push(o)
- }
- } else {
- m = k.slice(s * l, (s + 1) * l);
- for (r = 0; r < m.length; r++) {
- o = m[r];
- if (v) {
- o.setAnimation(v)
- }
- o.setAttributes(g)
- }
- }
- }
- return k
- },
- betweenAngle: function(d, f, c) {
- var e = Math.PI * 2,
- g = this.rotationOffset;
- f += g;
- c += g;
- d -= f;
- c -= f;
- d %= e;
- c %= e;
- d += e;
- c += e;
- d %= e;
- c %= e;
- return d < c || c === 0
- },
- getItemForPoint: function(k, j) {
- var h = this,
- g = h.getSprites();
- if (g) {
- var l = h.getStore(),
- b = l.getData().items,
- a = h.spritesPerSlice,
- e = h.getHidden(),
- c, f, m, d;
- for (c = 0, f = b.length; c < f; c++) {
- if (!e[c]) {
- d = c * a;
- m = g[d];
- if (m.hitTest([k, j])) {
- return {
- series: h,
- sprite: g.slice(d, d + a),
- index: c,
- record: b[c],
- category: "sprites",
- field: h.getXField()
- }
- }
- }
- }
- return null
- }
- },
- provideLegendInfo: function(f) {
- var h = this,
- k = h.getStore();
- if (k) {
- var g = k.getData().items,
- b = h.getLabel().getTemplate().getField(),
- j = h.getField(),
- e = h.getHidden(),
- d, a, c;
- for (d = 0; d < g.length; d++) {
- a = h.getStyleByIndex(d);
- c = a.baseColor;
- f.push({
- name: b ? String(g[d].get(b)) : j + " " + d,
- mark: c || "black",
- disabled: e[d],
- series: h.getId(),
- index: d
- })
- }
- }
- }
-}, function() {
- var b = this.prototype,
- a = Ext.chart.series.sprite.Pie3DPart.def.getInitialConfig().processors.part;
- b.partNames = a.replace(/^enums\(|\)/g, "").split(",");
- b.spritesPerSlice = b.partNames.length
-});
-Ext.define("Ext.chart.series.sprite.Polar", {
- extend: "Ext.chart.series.sprite.Series",
- inheritableStatics: {
- def: {
- processors: {
- centerX: "number",
- centerY: "number",
- startAngle: "number",
- endAngle: "number",
- startRho: "number",
- endRho: "number",
- baseRotation: "number",
- labels: "default",
- labelOverflowPadding: "number"
- },
- defaults: {
- centerX: 0,
- centerY: 0,
- startAngle: 0,
- endAngle: Math.PI,
- startRho: 0,
- endRho: 150,
- baseRotation: 0,
- labels: null,
- labelOverflowPadding: 10
- },
- triggers: {
- centerX: "bbox",
- centerY: "bbox",
- startAngle: "bbox",
- endAngle: "bbox",
- startRho: "bbox",
- endRho: "bbox",
- baseRotation: "bbox"
- }
- }
- },
- updatePlainBBox: function(b) {
- var a = this.attr;
- b.x = a.centerX - a.endRho;
- b.y = a.centerY + a.endRho;
- b.width = a.endRho * 2;
- b.height = a.endRho * 2
- }
-});
-Ext.define("Ext.chart.series.sprite.Radar", {
- alias: "sprite.radar",
- extend: "Ext.chart.series.sprite.Polar",
- getDataPointXY: function(d) {
- var u = this,
- n = u.attr,
- f = n.centerX,
- e = n.centerY,
- o = n.matrix,
- t = n.dataMinX,
- s = n.dataMaxX,
- k = n.dataX,
- j = n.dataY,
- l = n.endRho,
- p = n.startRho,
- g = n.baseRotation,
- i, h, m, c, b, a, q;
- if (n.rangeY) {
- q = n.rangeY[1]
- } else {
- q = n.dataMaxY
- }
- c = (k[d] - t) / (s - t + 1) * 2 * Math.PI + g;
- m = j[d] / q * (l - p) + p;
- b = f + Math.cos(c) * m;
- a = e + Math.sin(c) * m;
- i = o.x(b, a);
- h = o.y(b, a);
- return [i, h]
- },
- render: function(a, l) {
- var h = this,
- f = h.attr,
- g = f.dataX,
- b = g.length,
- e = h.surfaceMatrix,
- d = {},
- c, k, j, m;
- l.beginPath();
- for (c = 0; c < b; c++) {
- m = h.getDataPointXY(c);
- k = m[0];
- j = m[1];
- if (c === 0) {
- l.moveTo(k, j)
- }
- l.lineTo(k, j);
- d.translationX = e.x(k, j);
- d.translationY = e.y(k, j);
- h.putMarker("markers", d, c, true)
- }
- l.closePath();
- l.fillStroke(f)
- }
-});
-Ext.define("Ext.chart.series.Radar", {
- extend: "Ext.chart.series.Polar",
- type: "radar",
- seriesType: "radar",
- alias: "series.radar",
- requires: ["Ext.chart.series.sprite.Radar"],
- themeColorCount: function() {
- return 1
- },
- isStoreDependantColorCount: false,
- themeMarkerCount: function() {
- return 1
- },
- updateAngularAxis: function(a) {
- a.processData(this)
- },
- updateRadialAxis: function(a) {
- a.processData(this)
- },
- coordinateX: function() {
- return this.coordinate("X", 0, 2)
- },
- coordinateY: function() {
- return this.coordinate("Y", 1, 2)
- },
- updateCenter: function(a) {
- this.setStyle({
- translationX: a[0] + this.getOffsetX(),
- translationY: a[1] + this.getOffsetY()
- });
- this.doUpdateStyles()
- },
- updateRadius: function(a) {
- this.setStyle({
- endRho: a
- });
- this.doUpdateStyles()
- },
- updateRotation: function(a) {
- this.setStyle({
- rotationRads: a
- });
- this.doUpdateStyles()
- },
- updateTotalAngle: function(a) {
- this.processData()
- },
- getItemForPoint: function(k, j) {
- var h = this,
- m = h.sprites && h.sprites[0],
- f = m.attr,
- g = f.dataX,
- a = g.length,
- l = h.getStore(),
- e = h.getMarker(),
- b, o, p, d, n, c;
- if (h.getHidden()) {
- return null
- }
- if (m && e) {
- c = m.getMarker("markers");
- for (d = 0; d < a; d++) {
- n = c.getBBoxFor(d);
- b = (n.width + n.height) * 0.25;
- p = m.getDataPointXY(d);
- if (Math.abs(p[0] - k) < b && Math.abs(p[1] - j) < b) {
- o = {
- series: h,
- sprite: m,
- index: d,
- category: "markers",
- record: l.getData().items[d],
- field: h.getYField()
- };
- return o
- }
- }
- }
- return h.callParent(arguments)
- },
- getDefaultSpriteConfig: function() {
- var a = this.callParent(),
- b = {
- customDurations: {
- translationX: 0,
- translationY: 0,
- rotationRads: 0,
- dataMinX: 0,
- dataMaxX: 0
- }
- };
- if (a.fx) {
- Ext.apply(a.fx, b)
- } else {
- a.fx = b
- }
- return a
- },
- getSprites: function() {
- var d = this,
- c = d.getChart(),
- e = d.getAnimation() || c && c.getAnimation(),
- b = d.sprites[0],
- a;
- if (!c) {
- return []
- }
- if (!b) {
- b = d.createSprite()
- }
- if (e) {
- a = b.getMarker("markers");
- if (a) {
- a.getTemplate().setAnimation(e)
- }
- b.setAnimation(e)
- }
- return d.sprites
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getSubStyleWithTheme(),
- c = a.fillStyle;
- if (Ext.isArray(c)) {
- c = c[0]
- }
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- }
-});
-Ext.define("Ext.chart.series.sprite.Scatter", {
- alias: "sprite.scatterSeries",
- extend: "Ext.chart.series.sprite.Cartesian",
- renderClipped: function(r, s, w, u) {
- if (this.cleanRedraw) {
- return
- }
- var C = this,
- q = C.attr,
- l = q.dataX,
- h = q.dataY,
- z = q.labels,
- j = C.getSeries(),
- b = z && C.getMarker("labels"),
- t = C.attr.matrix,
- c = t.getXX(),
- p = t.getYY(),
- m = t.getDX(),
- k = t.getDY(),
- n = {},
- D, B, d = r.getInherited().rtl && !q.flipXY ? -1 : 1,
- a, A, o, e, g, f, v;
- if (q.flipXY) {
- a = u[1] - c * d;
- A = u[1] + u[3] + c * d;
- o = u[0] - p;
- e = u[0] + u[2] + p
- } else {
- a = u[0] - c * d;
- A = u[0] + u[2] + c * d;
- o = u[1] - p;
- e = u[1] + u[3] + p
- }
- for (v = 0; v < l.length; v++) {
- g = l[v];
- f = h[v];
- g = g * c + m;
- f = f * p + k;
- if (a <= g && g <= A && o <= f && f <= e) {
- if (q.renderer) {
- n = {
- type: "items",
- translationX: g,
- translationY: f
- };
- B = [C, n, {
- store: C.getStore()
- }, v];
- D = Ext.callback(q.renderer, null, B, 0, j);
- n = Ext.apply(n, D)
- } else {
- n.translationX = g;
- n.translationY = f
- }
- C.putMarker("items", n, v, !q.renderer);
- if (b && z[v]) {
- C.drawLabel(z[v], g, f, v, u)
- }
- }
- }
- },
- drawLabel: function(j, h, g, p, a) {
- var r = this,
- m = r.attr,
- d = r.getMarker("labels"),
- c = d.getTemplate(),
- l = r.labelCfg || (r.labelCfg = {}),
- b = r.surfaceMatrix,
- f, e, i = m.labelOverflowPadding,
- o = m.flipXY,
- k, n, s, q;
- l.text = j;
- n = r.getMarkerBBox("labels", p, true);
- if (!n) {
- r.putMarker("labels", l, p);
- n = r.getMarkerBBox("labels", p, true)
- }
- if (o) {
- l.rotationRads = Math.PI * 0.5
- } else {
- l.rotationRads = 0
- }
- k = n.height / 2;
- f = h;
- switch (c.attr.display) {
- case "under":
- e = g - k - i;
- break;
- case "rotate":
- f += i;
- e = g - i;
- l.rotationRads = -Math.PI / 4;
- break;
- default:
- e = g + k + i
- }
- l.x = b.x(f, e);
- l.y = b.y(f, e);
- if (c.attr.renderer) {
- q = [j, d, l, {
- store: r.getStore()
- }, p];
- s = Ext.callback(c.attr.renderer, null, q, 0, r.getSeries());
- if (typeof s === "string") {
- l.text = s
- } else {
- Ext.apply(l, s)
- }
- }
- r.putMarker("labels", l, p)
- }
-});
-Ext.define("Ext.chart.series.Scatter", {
- extend: "Ext.chart.series.Cartesian",
- alias: "series.scatter",
- type: "scatter",
- seriesType: "scatterSeries",
- requires: ["Ext.chart.series.sprite.Scatter"],
- config: {
- itemInstancing: {
- fx: {
- customDurations: {
- translationX: 0,
- translationY: 0
- }
- }
- }
- },
- themeMarkerCount: function() {
- return 1
- },
- applyMarker: function(b, a) {
- this.getItemInstancing();
- this.setItemInstancing(b);
- return this.callParent(arguments)
- },
- provideLegendInfo: function(d) {
- var b = this,
- a = b.getMarkerStyleByIndex(0),
- c = a.fillStyle;
- d.push({
- name: b.getTitle() || b.getYField() || b.getId(),
- mark: (Ext.isObject(c) ? c.stops && c.stops[0].color : c) || a.strokeStyle || "black",
- disabled: b.getHidden(),
- series: b.getId(),
- index: 0
- })
- }
-});
-Ext.define("Ext.chart.theme.Blue", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.blue", "chart.theme.Blue"],
- config: {
- baseColor: "#4d7fe6"
- }
-});
-Ext.define("Ext.chart.theme.BlueGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.blue-gradients", "chart.theme.Blue:gradients"],
- config: {
- baseColor: "#4d7fe6",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category1", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category1", "chart.theme.Category1"],
- config: {
- colors: ["#f0a50a", "#c20024", "#2044ba", "#810065", "#7eae29"]
- }
-});
-Ext.define("Ext.chart.theme.Category1Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category1-gradients", "chart.theme.Category1:gradients"],
- config: {
- colors: ["#f0a50a", "#c20024", "#2044ba", "#810065", "#7eae29"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category2", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category2", "chart.theme.Category2"],
- config: {
- colors: ["#6d9824", "#87146e", "#2a9196", "#d39006", "#1e40ac"]
- }
-});
-Ext.define("Ext.chart.theme.Category2Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category2-gradients", "chart.theme.Category2:gradients"],
- config: {
- colors: ["#6d9824", "#87146e", "#2a9196", "#d39006", "#1e40ac"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category3", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category3", "chart.theme.Category3"],
- config: {
- colors: ["#fbbc29", "#ce2e4e", "#7e0062", "#158b90", "#57880e"]
- }
-});
-Ext.define("Ext.chart.theme.Category3Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category3-gradients", "chart.theme.Category3:gradients"],
- config: {
- colors: ["#fbbc29", "#ce2e4e", "#7e0062", "#158b90", "#57880e"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category4", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category4", "chart.theme.Category4"],
- config: {
- colors: ["#ef5773", "#fcbd2a", "#4f770d", "#1d3eaa", "#9b001f"]
- }
-});
-Ext.define("Ext.chart.theme.Category4Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category4-gradients", "chart.theme.Category4:gradients"],
- config: {
- colors: ["#ef5773", "#fcbd2a", "#4f770d", "#1d3eaa", "#9b001f"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category5", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category5", "chart.theme.Category5"],
- config: {
- colors: ["#7eae29", "#fdbe2a", "#910019", "#27b4bc", "#d74dbc"]
- }
-});
-Ext.define("Ext.chart.theme.Category5Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category5-gradients", "chart.theme.Category5:gradients"],
- config: {
- colors: ["#7eae29", "#fdbe2a", "#910019", "#27b4bc", "#d74dbc"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Category6", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category6", "chart.theme.Category6"],
- config: {
- colors: ["#44dce1", "#0b2592", "#996e05", "#7fb325", "#b821a1"]
- }
-});
-Ext.define("Ext.chart.theme.Category6Gradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.category6-gradients", "chart.theme.Category6:gradients"],
- config: {
- colors: ["#44dce1", "#0b2592", "#996e05", "#7fb325", "#b821a1"],
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.DefaultGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.default-gradients", "chart.theme.Base:gradients"],
- config: {
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Green", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.green", "chart.theme.Green"],
- config: {
- baseColor: "#b1da5a"
- }
-});
-Ext.define("Ext.chart.theme.GreenGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.green-gradients", "chart.theme.Green:gradients"],
- config: {
- baseColor: "#b1da5a",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Midnight", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.midnight", "chart.theme.Midnight"],
- config: {
- colors: ["#A837FF", "#4AC0F2", "#FF4D35", "#FF8809", "#61C102", "#FF37EA"],
- chart: {
- defaults: {
- background: "rgb(52, 52, 53)"
- }
- },
- axis: {
- defaults: {
- style: {
- strokeStyle: "rgb(224, 224, 227)"
- },
- label: {
- fillStyle: "rgb(224, 224, 227)"
- },
- title: {
- fillStyle: "rgb(224, 224, 227)"
- },
- grid: {
- strokeStyle: "rgb(112, 112, 115)"
- }
- }
- },
- series: {
- defaults: {
- label: {
- fillStyle: "rgb(224, 224, 227)"
- }
- }
- },
- sprites: {
- text: {
- fillStyle: "rgb(224, 224, 227)"
- }
- }
- }
-});
-Ext.define("Ext.chart.theme.Muted", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.muted", "chart.theme.Muted"],
- config: {
- colors: ["#8ca640", "#974144", "#4091ba", "#8e658e", "#3b8d8b", "#b86465", "#d2af69", "#6e8852", "#3dcc7e", "#a6bed1", "#cbaa4b", "#998baa"]
- }
-});
-Ext.define("Ext.chart.theme.Purple", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.purple", "chart.theme.Purple"],
- config: {
- baseColor: "#da5abd"
- }
-});
-Ext.define("Ext.chart.theme.PurpleGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.purple-gradients", "chart.theme.Purple:gradients"],
- config: {
- baseColor: "#da5abd",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Red", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.red", "chart.theme.Red"],
- config: {
- baseColor: "#e84b67"
- }
-});
-Ext.define("Ext.chart.theme.RedGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.red-gradients", "chart.theme.Red:gradients"],
- config: {
- baseColor: "#e84b67",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Sky", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.sky", "chart.theme.Sky"],
- config: {
- baseColor: "#4ce0e7"
- }
-});
-Ext.define("Ext.chart.theme.SkyGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.sky-gradients", "chart.theme.Sky:gradients"],
- config: {
- baseColor: "#4ce0e7",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.chart.theme.Yellow", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.yellow", "chart.theme.Yellow"],
- config: {
- baseColor: "#fec935"
- }
-});
-Ext.define("Ext.chart.theme.YellowGradients", {
- extend: "Ext.chart.theme.Base",
- singleton: true,
- alias: ["chart.theme.yellow-gradients", "chart.theme.Yellow:gradients"],
- config: {
- baseColor: "#fec935",
- gradients: {
- type: "linear",
- degrees: 90
- }
- }
-});
-Ext.define("Ext.draw.Point", {
- requires: ["Ext.draw.Draw", "Ext.draw.Matrix"],
- isPoint: true,
- x: 0,
- y: 0,
- length: 0,
- angle: 0,
- angleUnits: "degrees",
- statics: {
- fly: (function() {
- var a = null;
- return function(b, c) {
- if (!a) {
- a = new Ext.draw.Point()
- }
- a.constructor(b, c);
- return a
- }
- })()
- },
- constructor: function(a, c) {
- var b = this;
- if (typeof a === "number") {
- b.x = a;
- if (typeof c === "number") {
- b.y = c
- } else {
- b.y = a
- }
- } else {
- if (Ext.isArray(a)) {
- b.x = a[0];
- b.y = a[1]
- } else {
- if (a) {
- b.x = a.x;
- b.y = a.y
- }
- }
- }
- b.calculatePolar()
- },
- calculateCartesian: function() {
- var b = this,
- a = b.length,
- c = b.angle;
- if (b.angleUnits === "degrees") {
- c = Ext.draw.Draw.rad(c)
- }
- b.x = Math.cos(c) * a;
- b.y = Math.sin(c) * a
- },
- calculatePolar: function() {
- var b = this,
- a = b.x,
- c = b.y;
- b.length = Math.sqrt(a * a + c * c);
- b.angle = Math.atan2(c, a);
- if (b.angleUnits === "degrees") {
- b.angle = Ext.draw.Draw.degrees(b.angle)
- }
- },
- setX: function(a) {
- this.x = a;
- this.calculatePolar()
- },
- setY: function(a) {
- this.y = a;
- this.calculatePolar()
- },
- set: function(a, b) {
- this.constructor(a, b)
- },
- setAngle: function(a) {
- this.angle = a;
- this.calculateCartesian()
- },
- setLength: function(a) {
- this.length = a;
- this.calculateCartesian()
- },
- setPolar: function(b, a) {
- this.angle = b;
- this.length = a;
- this.calculateCartesian()
- },
- clone: function() {
- return new Ext.draw.Point(this.x, this.y)
- },
- add: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return new Ext.draw.Point(this.x + b.x, this.y + b.y)
- },
- sub: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return new Ext.draw.Point(this.x - b.x, this.y - b.y)
- },
- mul: function(a) {
- return new Ext.draw.Point(this.x * a, this.y * a)
- },
- div: function(a) {
- return new Ext.draw.Point(this.x / a, this.y / a)
- },
- dot: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return this.x * b.x + this.y * b.y
- },
- equals: function(a, c) {
- var b = Ext.draw.Point.fly(a, c);
- return this.x === b.x && this.y === b.y
- },
- rotate: function(f, c) {
- var d, e, b, g, a;
- if (this.angleUnits === "degrees") {
- f = Ext.draw.Draw.rad(f);
- d = Math.sin(f);
- e = Math.cos(f)
- }
- if (c) {
- b = c.x;
- g = c.y
- } else {
- b = 0;
- g = 0
- }
- a = Ext.draw.Matrix.fly([e, d, -d, e, b - e * b + g * d, g - e * g + b * -d]).transformPoint(this);
- return new Ext.draw.Point(a)
- },
- transform: function(a) {
- if (a && a.isMatrix) {
- return new Ext.draw.Point(a.transformPoint(this))
- } else {
- if (arguments.length === 6) {
- return new Ext.draw.Point(Ext.draw.Matrix.fly(arguments).transformPoint(this))
- } else {
- Ext.raise("Invalid parameters.")
- }
- }
- },
- round: function() {
- return new Ext.draw.Point(Math.round(this.x), Math.round(this.y))
- },
- ceil: function() {
- return new Ext.draw.Point(Math.ceil(this.x), Math.ceil(this.y))
- },
- floor: function() {
- return new Ext.draw.Point(Math.floor(this.x), Math.floor(this.y))
- },
- abs: function(a, b) {
- return new Ext.draw.Point(Math.abs(this.x), Math.abs(this.y))
- },
- normalize: function(c) {
- var b = this.x,
- f = this.y,
- a, e, d;
- c = c || 1;
- if (b === 0) {
- a = 0;
- e = c * Ext.Number.sign(f)
- } else {
- d = f / b;
- a = c / Math.sqrt(1 + d * d);
- e = a * d
- }
- return new Ext.draw.Point(a, e)
- },
- getDistanceToLine: function(c, b) {
- if (arguments.length === 4) {
- c = new Ext.draw.Point(arguments[0], arguments[1]);
- b = new Ext.draw.Point(arguments[2], arguments[3])
- }
- var d = b.sub(c).normalize(),
- a = c.sub(this);
- return a.sub(d.mul(a.dot(d)))
- },
- isZero: function() {
- return this.x === 0 && this.y === 0
- },
- isNumber: function() {
- return Ext.isNumber(this.x + this.y)
- }
-});
-Ext.define("Ext.draw.plugin.SpriteEvents", {
- extend: "Ext.plugin.Abstract",
- alias: "plugin.spriteevents",
- requires: ["Ext.draw.PathUtil"],
- mouseMoveEvents: {
- mousemove: true,
- mouseover: true,
- mouseout: true
- },
- spriteMouseMoveEvents: {
- spritemousemove: true,
- spritemouseover: true,
- spritemouseout: true
- },
- init: function(a) {
- var b = "handleEvent";
- this.drawContainer = a;
- a.addElementListener({
- click: b,
- dblclick: b,
- mousedown: b,
- mousemove: b,
- mouseup: b,
- mouseover: b,
- mouseout: b,
- priority: 1001,
- scope: this
- })
- },
- hasSpriteMouseMoveListeners: function() {
- var b = this.drawContainer.hasListeners,
- a;
- for (a in this.spriteMouseMoveEvents) {
- if (a in b) {
- return true
- }
- }
- return false
- },
- hitTestEvent: function(f) {
- var b = this.drawContainer.getItems(),
- a, d, c;
- for (c = b.length - 1; c >= 0; c--) {
- a = b.get(c);
- d = a.hitTestEvent(f);
- if (d) {
- return d
- }
- }
- return null
- },
- handleEvent: function(f) {
- var d = this,
- b = d.drawContainer,
- g = f.type in d.mouseMoveEvents,
- a = d.lastSprite,
- c;
- if (g && !d.hasSpriteMouseMoveListeners()) {
- return
- }
- c = d.hitTestEvent(f);
- if (g && !Ext.Object.equals(c, a)) {
- if (a) {
- b.fireEvent("spritemouseout", a, f)
- }
- if (c) {
- b.fireEvent("spritemouseover", c, f)
- }
- }
- if (c) {
- b.fireEvent("sprite" + f.type, c, f)
- }
- d.lastSprite = c
- }
-});
-Ext.define("Ext.chart.TipSurface", {
- extend: "Ext.draw.Container",
- spriteArray: false,
- renderFirst: true,
- constructor: function(a) {
- this.callParent([a]);
- if (a.sprites) {
- this.spriteArray = [].concat(a.sprites);
- delete a.sprites
- }
- },
- onRender: function() {
- var c = this,
- b = 0,
- a = 0,
- d, e;
- this.callParent(arguments);
- e = c.spriteArray;
- if (c.renderFirst && e) {
- c.renderFirst = false;
- for (a = e.length; b < a; b++) {
- d = c.surface.add(e[b]);
- d.setAttributes({
- hidden: false
- }, true)
- }
- }
- }
-});
-Ext.define("Ext.chart.interactions.ItemInfo", {
- extend: "Ext.chart.interactions.Abstract",
- type: "iteminfo",
- alias: "interaction.iteminfo",
- config: {
- extjsGestures: {
- start: {
- event: "click",
- handler: "onInfoGesture"
- },
- move: {
- event: "mousemove",
- handler: "onInfoGesture"
- },
- end: {
- event: "mouseleave",
- handler: "onInfoGesture"
- }
- }
- },
- item: null,
- onInfoGesture: function(f, a) {
- var c = this,
- b = c.getItemForEvent(f),
- d = b && b.series.tooltip;
- if (d) {
- d.onMouseMove.call(d, f)
- }
- if (b !== c.item) {
- if (b) {
- b.series.showTip(b)
- } else {
- c.item.series.hideTip(c.item)
- }
- c.item = b
- }
- return false
- }
-});
\ No newline at end of file