ExceptionWindow.js (8947B)
1 /** 2 * Represents an exception window. 3 */ 4 Ext.define('PartKeepr.ExceptionWindow', { 5 extend: 'Ext.window.Window', 6 resizable: true, 7 closeAction: 'hide', 8 layout: 'fit', 9 width: 500, 10 autoHeight: true, 11 maxHeight: 800, 12 constrain: true, 13 cls: Ext.baseCSSPrefix + 'message-box', 14 15 keyMap: { 16 scope: 'this', 17 ESC: 'onEsc', 18 ENTER: 'onEsc' 19 }, 20 21 initComponent: function () 22 { 23 this.iconComponent = Ext.create('Ext.Component', { 24 baseCls: Ext.baseCSSPrefix + 'message-box-icon' + " " + Ext.baseCSSPrefix + 'message-box-error' 25 }); 26 27 this.messageDiv = Ext.create('Ext.Component', { 28 autoEl: {tag: 'div'}, 29 cls: 'ext-mb-text', 30 height: 20 31 }); 32 33 this.detailDiv = Ext.create('Ext.Component', { 34 flex: 1, 35 autoEl: {tag: 'div'}, 36 cls: 'ext-mb-text', 37 style: 'margin-top: 20px;overflow: auto;' 38 }); 39 40 this.backtraceDetails = Ext.create('Ext.tree.Panel', { 41 rootVisible: false 42 }); 43 44 this.requestDetails = Ext.create('Ext.form.field.TextArea', { 45 fieldLabel: i18n("Request"), 46 height: 65, 47 minHeight: 65, 48 readOnly: true 49 }); 50 51 this.responseDetails = Ext.create('Ext.form.field.TextArea', { 52 fieldLabel: i18n("Response"), 53 height: 65, 54 minHeight: 65, 55 readOnly: true 56 }); 57 58 this.basicTab = Ext.create("Ext.panel.Panel", { 59 style: 'padding: 10px;', 60 layout: { 61 type: 'hbox', 62 align: 'stretch' 63 }, 64 title: i18n("Basic"), 65 items: [ 66 this.iconComponent, 67 { 68 border: false, 69 flex: 1, 70 layout: { 71 type: 'vbox', 72 align: 'stretch' 73 }, 74 75 items: [this.messageDiv, this.detailDiv] 76 } 77 ] 78 }); 79 80 this.detailTab = Ext.create("Ext.form.Panel", { 81 style: 'padding: 10px;', 82 height: 300, 83 width: 500, 84 layout: { 85 type: 'vbox', 86 align: 'stretch' 87 }, 88 title: i18n("Detail"), 89 items: [ 90 this.requestDetails, 91 this.responseDetails, 92 { 93 xtype: 'fieldcontainer', 94 layout: "fit", 95 fieldLabel: i18n("Backtrace"), 96 flex: 1, 97 minHeight: 65, 98 readOnly: true, 99 items: this.backtraceDetails 100 } 101 ] 102 103 }); 104 105 this.fullReport = Ext.create("Ext.form.field.TextArea", { 106 readOnly: true, 107 height: 300 108 }); 109 110 this.backtraceTab = Ext.create("Ext.panel.Panel", { 111 style: 'padding: 10px', 112 layout: 'fit', 113 anchor: '100% 100%', 114 title: i18n("Full Report"), 115 items: [this.fullReport] 116 }); 117 118 this.topContainer = Ext.create("Ext.tab.Panel", { 119 layout: "fit", 120 items: [this.basicTab, this.detailTab, this.backtraceTab] 121 }); 122 123 this.items = this.topContainer; 124 125 this.dockedItems = [ 126 { 127 xtype: 'toolbar', 128 dock: 'bottom', 129 ui: 'footer', 130 defaults: {minWidth: 80}, 131 layout: { 132 pack: 'center' 133 }, 134 items: [ 135 { 136 xtype: 'button', text: 'OK', handler: Ext.bind(function () 137 { 138 this.hide(); 139 }, this) 140 } 141 ] 142 } 143 ]; 144 145 this.callParent(); 146 147 }, 148 /** 149 * Private. Updates the exception dialog with the exception data. 150 * 151 * @see showException 152 * 153 * @param {PartKeepr.data.HydraException} exception The exception data 154 * @param {Object} response The response data 155 */ 156 _showException: function (exception, response) 157 { 158 var separator = "=================================="; 159 160 this.messageDiv.update('<strong>' + exception.getTitle() + '</strong>'); 161 this.setTitle(exception.getTitle()); 162 163 var fullDetails = exception.getTitle(); 164 165 if (exception.getDescription()) { 166 fullDetails += "\n\n" + i18n("Details") + "\n" + separator + "\n"; 167 fullDetails += exception.getDescription(); 168 169 this.detailDiv.update(exception.getDescription()); 170 } else { 171 this.detailDiv.update(""); 172 } 173 174 175 if (exception.getTrace()) { 176 var traceData = this.convertTraceToTree(exception.getTrace()); 177 178 var store = Ext.create("Ext.data.TreeStore", { 179 root: traceData 180 }); 181 182 this.backtraceDetails.setStore(store); 183 } 184 185 if (!response.request) { 186 response.request = {}; 187 } 188 189 var requestData; 190 191 if (response.request && response.request.options && response.request.options.method && response.request.options.url) { 192 requestData = response.request.options.method + " " + response.request.options.url; 193 } else { 194 requestData = ""; 195 } 196 197 if (response.request.jsonData) { 198 requestData += "\n\n" + response.request.jsonData; 199 } 200 201 fullDetails += "\n\n" + i18n("Request") + "\n" + separator + "\n"; 202 fullDetails += requestData; 203 204 this.requestDetails.setValue(nl2br(requestData)); 205 206 fullDetails += "\n\n" + i18n("Response Status Code") + "\n" + separator + "\n"; 207 fullDetails += response.status; 208 209 fullDetails += "\n\n" + i18n("Response") + "\n" + separator + "\n"; 210 fullDetails += response.responseText; 211 212 this.responseDetails.setValue(nl2br(response.responseText)); 213 214 fullDetails += "\n\n" + i18n("Server Configuration") + "\n" + separator + "\n"; 215 216 for (var j in window.parameters) { 217 fullDetails += j + ": " + window.parameters[j] + "\n"; 218 } 219 220 this.fullReport.setValue(fullDetails); 221 222 this.show(); 223 this.topContainer.layout.setActiveItem(0); 224 }, 225 /** 226 * Recursively converts a trace to an ExtJS tree 227 * 228 * @param {Object} node The current node to process 229 * @param {String} prefixText A text to prefix the data with. If undefined, uses the type of the given node 230 * @return {Object} An object comptable with {Ext.data.NodeInterface} 231 */ 232 convertTraceToTree: function (node, prefixText) 233 { 234 if (!Ext.isDefined(prefixText)) { 235 prefixText = typeof node; 236 } 237 238 var treeNode = { 239 text: prefixText 240 }; 241 242 243 if (Ext.isArray(node)) { 244 treeNode.children = []; 245 for (var j = 0; j < node.length; j++) { 246 treeNode.children.push(this.convertTraceToTree(node[j], j)); 247 } 248 249 if (treeNode.children.length === 0) { 250 treeNode.leaf = true; 251 } 252 return treeNode; 253 } 254 255 if (Ext.isObject(node)) { 256 treeNode.children = []; 257 258 for (var property in node) { 259 treeNode.children.push(this.convertTraceToTree(node[property], property)); 260 } 261 262 if (treeNode.children.length === 0) { 263 treeNode.leaf = true; 264 } 265 266 return treeNode; 267 } 268 269 treeNode.text += ": " + node; 270 treeNode.leaf = true; 271 272 return treeNode; 273 }, 274 statics: { 275 /** 276 * Displays the exception window. 277 * 278 * @param {PartKeepr.data.HydraException} exception The exception object 279 * @param {Object} response The response object 280 */ 281 showException: function (response) 282 { 283 if (!PartKeepr.ExceptionWindow.activeInstance) { 284 PartKeepr.ExceptionWindow.activeInstance = new PartKeepr.ExceptionWindow(); 285 } 286 287 try { 288 var data = Ext.decode(response.responseText); 289 290 var exception = Ext.create("PartKeepr.data.HydraException", data); 291 292 PartKeepr.ExceptionWindow.activeInstance._showException(exception, response); 293 } catch (ex) { 294 var exception = Ext.create("PartKeepr.data.HydraException", { 295 title: i18n("Critical Error"), 296 description: i18n("The server returned a response which we were not able to interpret.") 297 }); 298 299 PartKeepr.ExceptionWindow.activeInstance._showException(exception, response); 300 } 301 } 302 } 303 });