/* * JavaScript file created by Rockstarapps Concatenation */ /* * START OF FILE - /testopia/extensions/Testopia/js/strings.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * */ ATTACHMENT_DELETE_WARNING = 'You are about to remove the selected attachments. This cannot be undone. Continue?'; CASE_CATEGORY_DELETE_WARNING = 'You are about to delete the selected test case category. Are you sure you want to continue?'; CASE_DELETE_WARNING = 'You are about to delete the selected test cases including all children and history. This action cannot be undone. Are you sure you want to continue?'; PLAN_DELETE_WARNING = 'You are about to delete the selected test plans including all children and history. This action cannot be undone. Are you sure you want to continue?'; RUN_DELETE_WARNING = 'You are about to delete the selected test runs including all children and history. This action cannot be undone. Are you sure you want to continue?'; CASERUN_DELETE_WARNING = 'You are about to remove the selected test cases from this run including all history. This action cannot be undone. Are you sure you want to continue?'; ENVIRONMENT_DELETE_WARNING = 'You are about to delete the selected test environment including associated test run data. This action cannot be undone. Are you sure you want to continue?'; PRODUCT_PLAN_IMPORT = 'Accepts XML files under 2 MB in size.
See testopia.xsd for proper format.'; PLAN_CASES_IMPORT = 'Accepts CSV and XML files under 2 MB in size.
See import_example.csv and testopia.xsd for proper format.'; /* * END OF FILE - /testopia/extensions/Testopia/js/strings.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/vars.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks */ // Set up the Testopia Namespace var Testopia = {}; Testopia.Attachment = {}; Testopia.Build = {}; Testopia.TestCase = {}; Testopia.TestCase.Bugs = {}; Testopia.TestCaseRun = {}; Testopia.Category = {}; Testopia.Environment = {}; Testopia.TestPlan = {}; Testopia.TestRun = {}; Testopia.Search = {}; Testopia.Tags = {}; Testopia.Util = {}; Testopia.Product = {}; Testopia.User = {}; Testopia.Search.dashboard_urls = []; // There are a number of Ext defaults that we want to override. // This sets cookies to never expire. Ext.state.Manager.setProvider(new Ext.state.CookieProvider({ expires: new Date(new Date().getTime() + (1000 * 60 * 60 * 24 * 30)) })); // 2 minute limit on data retrievals Ext.data.Connection.timeout = 120000; Ext.Updater.defaults.timeout = 120000; Ext.Ajax.timeout = 120000; Ext.BLANK_IMAGE_URL = 'extensions/Testopia/extjs/resources/images/default/s.gif'; // Customized handler for the search field in the paging toolbar. // From JeffHowden at http://extjs.com/forum/showthread.php?t=17532 Ext.override(Ext.form.Field, { fireKey: function(e){ if (((Ext.isIE && e.type == 'keydown') || e.type == 'keypress') && e.isSpecialKey()) { this.fireEvent('specialkey', this, e); } else { this.fireEvent(e.type, this, e); } }, initEvents: function(){ // this.el.on(Ext.isIE ? "keydown" : "keypress", this.fireKey, this); this.el.on("focus", this.onFocus, this); this.el.on("blur", this.onBlur, this); this.el.on("keydown", this.fireKey, this); this.el.on("keypress", this.fireKey, this); this.el.on("keyup", this.fireKey, this); // reference to original value for reset this.originalValue = this.getValue(); } });// End Override Ext.override(Ext.menu.Menu, { ignoreParentClicks: true, enableScrolling: false }); //check column widget Ext.grid.CheckColumn = function(config){ Ext.apply(this, config); if (!this.id) { this.id = Ext.id(); } this.renderer = this.renderer.createDelegate(this); }; Ext.grid.CheckColumn.prototype = { init: function(grid){ this.grid = grid; this.grid.on('render', function(){ var view = this.grid.getView(); view.mainBody.on('mousedown', this.onMouseDown, this); }, this); }, onMouseDown: function(e, t){ if (t.className && t.className.indexOf('x-grid3-cc-' + this.id) != -1) { e.stopEvent(); var index = this.grid.getView().findRowIndex(t); var record = this.grid.store.getAt(index); record.set(this.dataIndex, !record.data[this.dataIndex]); } }, renderer: function(v, p, record){ p.css += ' x-grid3-check-col-td'; return '
 
'; } }; Testopia.StatusButton = function(cfg){ Ext.apply(this, cfg); } Ext.extend(Testopia.StatusButton, Ext.Button, { getTemplateArgs : function(){ return [this.icon]; } }); var imgButtonTpl = new Ext.Template( '' + '' + '
'); /* * END OF FILE - /testopia/extensions/Testopia/js/vars.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/util.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.Util.displayStatusIcon = function(name){ return '' + name + ''; }; Testopia.Util.makeLink = function(id, m, r, ri, ci, s, type){ if (type == 'bug') { if (s.isTreport === true) return '' + id + ''; return '' + id + ''; } if (s.isTreport === true) return '' + id + ''; return '' + id + ''; }; Testopia.Util.CascadeProductSelection = function(){ addOption = function(selectElement, newOption){ try { selectElement.add(newOption, null); } catch (e) { selectElement.add(newOption, selectElement.length); } }; lsearch = function(val, arr){ if (typeof arr != 'object') { if (arr == val) return true; return false; } for (var i in arr) { if (arr[i] == val) return true; } return false; }; this.addOption = addOption; var fillSelects = function(data, prods){ var s = Testopia.Util.urlQueryToJSON(window.location.search); if (prods) { s.product = prods; } for (var i in data.selectTypes) { if (typeof data.selectTypes[i] != 'function') { try { document.getElementById(data.selectTypes[i]).options.length = 0; for (var j in data[data.selectTypes[i]]) { if (typeof data[data.selectTypes[i]][j] != 'function') { var newOption = new Option(data[data.selectTypes[i]][j], data[data.selectTypes[i]][j], false, lsearch(data[data.selectTypes[i]][j], s[data.selectTypes[i]])); addOption(document.getElementById(data.selectTypes[i]), newOption); } } document.getElementById(data.selectTypes[i]).disabled = false; document.getElementById(data.selectTypes[i]) } catch (err) { } } } }; this.fillSelects = fillSelects; this.onProductSelection = function(prod){ var ids = []; for (var i = 0; i < prod.options.length; i++) { if (prod.options[i].selected === true) { ids.push(prod.options[i].value); } } var form = new Ext.form.BasicForm('testopia_helper_frm', {}); var type = prod.id == 'classification' ? 'classification' : 'product'; form.submit({ url: "tr_query.cgi", params: { value: ids.join(","), action: "getversions", type: type }, success: function(f, a){ fillSelects(a.result.objects); }, failure: Testopia.Util.error }); }; return this; }; /* * Testopia.User.Lookup - This generates a typeahead lookup for usernames. * It can be used anywhere in Testopia. Extends Ext ComboBox */ Testopia.User.Lookup = function(cfg){ Testopia.User.Lookup.superclass.constructor.call(this, { id: cfg.id || 'user_lookup', store: new Ext.data.JsonStore({ url: 'tr_quicksearch.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getuser' }, root: 'users', totalProperty: 'total', id: 'login', fields: [{ name: 'login', mapping: 'id' }, { name: 'name', mapping: 'name' }] }), listeners: { 'valid': function(f){ f.value = f.getRawValue(); }, 'beforequery': function(o){ if (cfg.multistring) { var term = o.query.match(/(^.*),(.*)/); if (term) { o.combo.multivalue = term[1]; o.query = term[2]; } } }, 'select': function(c, r, i){ if (cfg.multistring) { var v = c.multivalue || ''; v = v ? v + ', ' + r.get('login') : r.get('login'); c.setValue(v); } } }, queryParam: 'search', loadingText: 'Looking up users...', displayField: 'login', valueField: 'login', typeAhead: true, hideTrigger: true, minListWidth: 300, forceSelection: false, emptyText: 'Type a username...', pageSize: 20, tpl: '
{name}
{login}
' }); Ext.apply(this, cfg); }; Ext.extend(Testopia.User.Lookup, Ext.form.ComboBox); //TODO: Implement this (see bug 340461) DocCompareToolbar = function(object, id){ var store = new Ext.data.JsonStore({ url: 'tr_history.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getdocversions', object: object, object_id: id }, root: 'list', fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }] }); this.toolbar = new Ext.Toolbar({ id: 'doc_compare_tbar', items: [ // new Ext.form.ComboBox({ // id: 'doc_compare_v1', // store: store, // displayField: 'name', // valueField: 'id', // width: 50, // mode: 'local', // triggerAction: 'all' // }), // new Ext.form.ComboBox({ // id: 'doc_compare_v2', // store: store, // displayField: 'name', // valueField: 'id', // width: 50, // mode: 'local', // triggerAction: 'all' // }),{ // xtype: 'button', // id: 'doc_compare_btn', // text: 'Compare', // handler: function(){ // // } // }, // new Ext.Toolbar.Spacer(), // new Ext.Toolbar.Separator(), new Ext.Toolbar.Fill(), new Ext.form.ComboBox({ id: 'doc_view', store: store, displayField: 'name', valueField: 'id', width: 50, triggerAction: 'all' }), { xtype: 'button', id: 'doc_view_btn', text: 'View Version', handler: function(){ var tab = Ext.getCmp('object_panel').add({ title: 'Version ' + Ext.getCmp('doc_view').getValue(), closable: true, autoScroll: true }); tab.show(); tab.load({ url: 'tr_history.cgi', params: { action: 'showdoc', object: object, object_id: id, version: Ext.getCmp('doc_view').getValue() }, failure: Testopia.Util.error }); } }] }); return this.toolbar; }; /* * Testopia.Util.HistoryList - */ Testopia.Util.HistoryList = function(object, id){ this.store = new Ext.data.JsonStore({ url: 'tr_history.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'show', object: object, object_id: id }, root: 'list', fields: [{ name: "what", mapping: "what" }, { name: "who", mapping: "who" }, { name: "oldvalue", mapping: "oldvalue" }, { name: "newvalue", mapping: "newvalue" }, { name: "when", mapping: "changed" }] }); this.columns = [{ header: "What", width: 150, dataIndex: 'what', sortable: true }, { header: "Who", width: 180, sortable: true, dataIndex: 'who' }, { header: "When", width: 150, sortable: true, dataIndex: 'when' }, { header: "Old", width: 180, sortable: true, dataIndex: 'oldvalue' }, { id: 'new', header: "New", width: 180, sortable: true, dataIndex: 'newvalue' }]; Testopia.Util.HistoryList.superclass.constructor.call(this, { title: 'Change History', id: 'history-grid', layout: 'fit', loadMask: { msg: 'Loading History...' }, autoExpandColumn: "new", autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: false }) }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Util.HistoryList, Ext.grid.GridPanel, { onActivate: function(){ if (!this.store.getCount()) { this.store.load(); } }, onContextClick: function(grid, index, e){ if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'history-ctx-menu', enableScrolling: false, items: [{ text: 'Refresh', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }] }); } e.stopEvent(); this.menu.showAt(e.getXY()); } }); Testopia.Util.PagingBar = function(type, store){ this.type = type; var baseParams = clone(store.baseParams); function doUpdate(){ this.updateInfo(); } function clone(orig){ var clone = new Object(); for (var i in orig) { clone[i] = orig[i]; } return clone; } function viewallUpdate(){ this.cursor = 0; this.afterTextEl.el.innerHTML = String.format(this.afterPageText, 1); this.field.dom.value = 1; this.updateInfo(); } var sizer = new Ext.form.ComboBox({ store: new Ext.data.SimpleStore({ fields: ['value', 'name'], id: 0, data: [[25, 25], [50, 50], [100, 100], [500, 500]], autoLoad: true }), id: type + '_page_sizer', mode: 'local', displayField: 'name', valueField: 'value', triggerAction: 'all', editable: false, width: 50 }); sizer.on('select', function(c, r, i){ this.pageSize = r.get('value'); Ext.state.Manager.set('TESTOPIA_DEFAULT_PAGE_SIZE', r.get('value')); store.baseParams.limit = r.get('value'); store.load({ params: { start: 0 }, callback: doUpdate.createDelegate(this) }); }, this); this.sizer = sizer; var viewall = new Ext.Button({ text: 'View All', enableToggle: true }); viewall.on('toggle', function(b, p){ if (p) { this.pageSize = 0; store.load({ params: { viewall: 1 }, callback: viewallUpdate.createDelegate(this) }); } else { this.pageSize = sizer.getValue(); store.load({ params: { start: 0, limit: sizer.getValue() } }); } }, this); var filter = new Ext.form.TextField({ allowBlank: true, id: type + '_paging_filter', selectOnFocus: true }); filter.on('specialkey', function(f, e){ var key = e.getKey(); if (key == e.ENTER) { var params = { start: 0, limit: sizer.getValue() }; if (this.getValue().length === 0) { store.baseParams = clone(baseParams); store.load({ params: params }); Ext.getCmp(type + '_filtered_txt').hide(); return; } var params = { start: 0, limit: sizer.getValue() }; var s = this.getValue(); var term = s.match(/(^.*?):/); if (term) { term = term[1]; var q = Testopia.Util.trim(s.substr(s.indexOf(':') + 1, s.length)); if (term.match(/^start/i)) { term = 'start_date'; } if (term.match(/^stop/i)) { term = 'stop_date'; } if (term.match(/^manager/i)) { term = 'manager'; } switch (term) { case 'status': if (type == 'case') { term = 'case_status'; } else if (type == 'caserun') { term = 'case_run_status'; } else { term = 'run_status'; if (q.match(/running/i)) { q = 0; } else { q = 1; } } break; case 'tester': term = 'default_tester'; break; case 'plan': term = 'plan_id'; break; case 'case': term = 'case_id'; break; case 'run': term = 'run_id'; break; case 'product_version': term = 'default_product_version'; break; } store.baseParams[term] = q; store.baseParams[term + '_type'] = 'substring'; } else { if (type == 'case' || type == 'run') { store.baseParams.summary = this.getValue(); store.baseParams.summary_type = 'allwordssubst'; } else if (type == 'caserun') { store.baseParams.case_summary = this.getValue(); store.baseParams.case_summary_type = 'allwordssubst'; } else { store.baseParams.name = this.getValue(); store.baseParams.name_type = 'allwordssubst'; } } store.load({ params: params }); Ext.getCmp(type + '_filtered_txt').show(); } if ((key == e.BACKSPACE || key == e.DELETE) && this.getValue().length === 0) { store.baseParams = baseParams; store.load({ params: { start: 0, limit: sizer.getValue() } }); Ext.getCmp(type + '_filtered_txt').hide(); } }); sizer.on('render', function(){ var tt = new Ext.ToolTip({ target: type + '_paging_filter', title: 'Quick Search Filter', hideDelay: '500', html: "Enter column and search term separated by ':'
Example: priority: P3
Blank field and ENTER to clear" }); }); Testopia.Util.PagingBar.superclass.constructor.call(this, { id: type + '_pager', pageSize: Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25), displayInfo: true, displayMsg: 'Displaying test ' + type + 's {0} - {1} of {2}', emptyMsg: 'No test ' + type + 's were found', store: store, items: ['Filter: ', filter, ' ', '-', 'View ', ' ', sizer, ' ', viewall, ' ', { type: 'tbtext', text: '(FILTERED)', hidden: true, id: type + '_filtered_txt', style: 'font-weight:bold;color:red' }] }); this.on('render', this.setPager, this); this.cursor = 0; }; Ext.extend(Testopia.Util.PagingBar, Ext.PagingToolbar, { setPager: function(){ Ext.getCmp(this.type + '_page_sizer').setValue(Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25)); } }); Testopia.Util.updateFromList = function(type, params, grid){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); params.ctype = 'json'; params.action = 'update'; form.submit({ url: 'tr_list_' + type + 's.cgi', params: params, success: function(f, a){ if (type == 'caserun') { Ext.getCmp('run_progress').updateProgress(a.result.passed, a.result.failed, a.result.blocked, a.result.complete); } Testopia.Util.notify.msg('Test ' + type + 's updated', 'The selected {0}s were updated successfully', type); if (grid.selectedRows) { grid.store.baseParams.addcases = grid.selectedRows.join(','); Ext.getCmp(type + '_filtered_txt').show(); } try { Ext.getCmp('case_details_panel').store.reload(); } catch (err) { } grid.store.reload({ callback: function(){ if (grid.selectedRows) { var sm = grid.getSelectionModel(); var sel = []; for (var i = 0; i < grid.selectedRows.length; i++) { var index = grid.store.find('case_id', grid.selectedRows[i]); if (index >= 0) sel.push(index); } sm.selectRows(sel); if (sm.getCount() < 1) { Ext.getCmp('case_details_panel').disable(); } } } }); }, failure: function(f, a){ Testopia.Util.error(f, a); grid.store.reload({ callback: function(){ if (grid.selectedRows) { grid.getSelectionModel().selectRows(grid.selectedRows); } } }); } }); }; Testopia.Util.ComboRenderer = function(v, md, r, ri, ci, s){ f = this.getColumnModel().getCellEditor(ci, ri).field; record = f.store.getById(v); if (record) { return record.data[f.displayField]; } else { return v; } }; /* * Testopia.Util.error - global public function for displaying Bugzilla error messages * when ERROR_MODE_AJAX is set. All failure branches of Ext.basicForm submit calls * should point here. */ Testopia.Util.error = function(f, a){ f.el.unmask(); var message; if (a.response.status && a.response.status != 200) { message = { title: 'System Error!', msg: a.response.responseText, buttons: Ext.Msg.OK, icon: Ext.MessageBox.ERROR, minWidth: 450 }; } else { message = { title: 'An Error Has Occurred', msg: a.result.message, buttons: Ext.Msg.OK, icon: Ext.MessageBox.ERROR, prompt: true, value: a.result.message, multiline: true, minWidth: 450 }; } Ext.Msg.show(message); }; Testopia.Util.loadError = function(dp, errtype, a,o,r,ar,args){ var message = 'There was an error loading the data: '; if (errtype == 'response'){ message += r.responseText; } Ext.Msg.show({ title: 'An Error Has Occurred', width: 450, msg: message, prompt: true, multiline: true, value: message, buttons: Ext.Msg.OK, icon: Ext.MessageBox.ERROR }); }; Testopia.Util.getSelectedObjects = function(grid, field){ var selections = grid.getSelectionModel().getSelections(); var arIDs = []; var ids; for (var i = 0; i < selections.length; i++) { arIDs.push(selections[i].get(field)); } ids = arIDs.join(','); return ids; }; Testopia.Util.editFirstSelection = function(grid){ if (grid.store.getCount() === 0) { return; } var row = grid.store.indexOf(grid.getSelectionModel().getSelected()); if (row == -1){ row = 0; } grid.plugins[0].startEditing(row); }; Testopia.Util.urlQueryToJSON = function(url){ url = url.replace(/.*\//, ''); var params = {}; var loc = url.split('?', 2); var file = loc[0]; var search = loc[1] ? loc[1] : file; var pairs = search.split('&'); for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].split('='); if (params[pair[0]]) { if (typeof params[pair[0]] == 'object') { params[pair[0]].push(unescape(pair[1])); } else { params[pair[0]] = new Array(params[pair[0]]); params[pair[0]].push(unescape(pair[1])); } } else { params[pair[0]] = unescape(pair[1]); } } return params; }; Testopia.Util.JSONToURLQuery = function(params, searchStr, drops){ searchStr = searchStr || ''; for (var key in params) { if (drops.indexOf(key) != -1) { continue; } if (typeof params[key] == 'object') { for (i = 0; i < params[key].length; i++) { searchStr = searchStr + key + '=' + encodeURIComponent(params[key][i]) + '&'; } } else { searchStr = searchStr + key + '=' + encodeURIComponent(params[key]) + '&'; } } if (searchStr.lastIndexOf('&') == searchStr.length - 1) { searchStr = searchStr.substr(0, searchStr.length - 1); } return searchStr; }; /* * Testopia.notify - Displays a floating notification area. * Taken from ext/examples/examples.js */ Testopia.Util.notify = function(){ var msgCt; function createBox(t, s){ return ['
', '
', '

', t, '

', s, '
', '
', '
'].join(''); } return { msg: function(title, format){ if (!msgCt) { msgCt = Ext.DomHelper.insertFirst(document.getElementById('bugzilla-body'), { id: 'msg-div' }, true); } msgCt.alignTo(document, 't-t'); var s = String.format.apply(String, Array.prototype.slice.call(arguments, 1)); var m = Ext.DomHelper.append(msgCt, { html: createBox(title, s) }, true); m.slideIn('t').pause(1).ghost("t", { remove: true }); }, init: function(){ return; } }; }(); Testopia.Util.trim = function(input){ input = input.replace(/^\s+/g, ''); input = input.replace(/\s+$/g, ''); return input; }; Testopia.Util.PlanSelector = function(product_id, cfg){ var single = cfg.action.match('case') ? false : true; var pg = new Testopia.TestPlan.Grid({ product_id: product_id }, { id: 'plan_selector_grid', height: 300, single: single }); var pchooser = new Testopia.Product.Combo({ mode: 'local', value: product_id }); pchooser.on('select', function(c, r, i){ pg.store.baseParams = { ctype: 'json', product_id: r.get('id') }; pg.store.load(); }); Testopia.Util.PlanSelector.superclass.constructor.call(this, { items: [pg], buttons: [{ text: 'Use Selected', handler: function(){ var loc = cfg.action + '?plan_id=' + Testopia.Util.getSelectedObjects(pg, 'plan_id'); if (cfg.bug_id) { loc = loc + '&bug=' + cfg.bug_id; } window.location = loc; } }] }); pg.on('render', function(){ var items = pg.getTopToolbar().items.items; for (var i = 0; i < items.length; i++) { items[i].destroy(); } pg.getTopToolbar().add('Product: ', pchooser); pg.getSelectionModel().un('rowselect', pg.getSelectionModel().events['rowselect'].listeners[0].fn); pg.getSelectionModel().un('rowdeselect', pg.getSelectionModel().events['rowdeselect'].listeners[0].fn); pg.store.load(); }); } Ext.extend(Testopia.Util.PlanSelector, Ext.Panel); Testopia.Util.DisableTools = function(tbar, ex){ if (typeof ex != 'object'){ ex = []; } for (var i in tbar.items.items) { if (ex.indexOf(tbar.items.items[i].id) != -1) { continue; } try { tbar.items.items[i].disable(); } catch (e) { } } } /* * END OF FILE - /testopia/extensions/Testopia/js/util.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/attachments.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.Attachment.Grid = function(object){ function attachlink(id){ return '' + id + ''; } this.object = object; this.store = new Ext.data.JsonStore({ url: 'tr_attachment.cgi', root: 'attachment', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { ctype: 'json', action: 'list', object: this.object.type, object_id: this.object.id }, id: 'attach_id', fields: [{ name: "attach_id", mapping: "attachment_id" }, { name: "submitter", mapping: "submitter" }, { name: "caserun_id", mapping: "caserun_id" }, { name: "filename", mapping: "filename" }, //editable { name: "timestamp", mapping: "creation_ts" }, { name: "mimetype", mapping: "mime_type" }, //editable { name: "description", mapping: "description" }, //editable { name: "isviewable", mapping: "isviewable" }, { name: "canedit", mapping: "canedit" }, { name: "candelete", mapping: "candelete" }, { name: "size", mapping: "datasize" }] }); var ds = this.store; this.columns = [{ id: 'attach_id', header: "ID", width: 20, sortable: true, dataIndex: 'attach_id', renderer: attachlink }, { header: "Created", width: 50, sortable: true, dataIndex: 'timestamp', renderer: function(v, md, r){ if (r.get('caserun_id') && Ext.getCmp('caserun_grid') && Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('caserun_id') == r.get('caserun_id')) { return '* ' + v + ''; } else { return v; } } }, { header: "Name", width: 50, editor: { xtype: 'textfield' }, sortable: true, dataIndex: 'name' }, { header: "Submitted by", width: 50, sortable: true, dataIndex: 'submitter' }, { header: "Type", width: 30, editor: { xtype: 'textfield' }, sortable: true, dataIndex: 'mimetype' }, { header: "Description", width: 120, editor: { xtype: 'textfield', value: 'description' }, sortable: true, dataIndex: 'description' }, { header: "Size", width: 50, sortable: true, dataIndex: 'size', renderer: function(v){ if (v) return v + ' Bytes'; } }]; this.form = new Ext.form.BasicForm('testopia_helper_frm', {}); Testopia.Attachment.Grid.superclass.constructor.call(this, { title: 'Attachments', id: 'attachments_panel', loadMask: { msg: 'Loading attachments...' }, autoExpandColumn: "Name", autoScroll: true, plugins: [new Ext.ux.grid.RowEditor({ id:'attachment_row_editor', saveText: 'Update' })], enableColumnHide: true, tbar: ['->', { xtype: 'button', id: 'edit_attachment_btn', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', disabled: true, tooltip: 'Edit Attachments', handler: function(){ Testopia.Util.editFirstSelection(Ext.getCmp('attachments_panel')); } }, { xtype: 'button', id: 'add_attachment_btn', icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', tooltip: 'Attach a new file', handler: this.newAttachment.createDelegate(this) }, { xtype: 'button', id: 'delete_attachment_btn', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', disabled: true, tooltip: 'Remove selected attachments', handler: this.deleteAttachment.createDelegate(this) }], sm: new Ext.grid.RowSelectionModel({ singleSelect: false, listeners: { 'rowselect': function(sm, i, r){ if (r.get('candelete')) { Ext.getCmp('delete_attachment_btn').enable(); } if (r.get('canedit')) { Ext.getCmp('edit_attachment_btn').enable(); } }, 'rowdeselect': function(sm, i, r){ if (sm.getCount() < 1) { Ext.getCmp('delete_attachment_btn').disable(); Ext.getCmp('edit_attachment_btn').disable(); } } } }), viewConfig: { forceFit: true } }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); Ext.getCmp('attachment_row_editor').on('afteredit', this.onGridEdit, this); }; Ext.extend(Testopia.Attachment.Grid, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ var sm = this.selectionModel; var object = this.object; if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'AttachGrid-ctx-menu', enableScrolling: false, items: [{ text: "Delete Selected Attachments", id: 'attach_delete_mnu', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', disabled: true, handler: this.deleteAttachment.createDelegate(this) }, { text: 'Reload List', handler: function(){ grid.store.reload(); } }] }); } e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } if (grid.getSelectionModel().getSelected().get('candelete')) { Ext.getCmp('attach_delete_mnu').enable(); } else { Ext.getCmp('attach_delete_mnu').enable(); } this.menu.showAt(e.getXY()); }, onGridEdit: function(e){ var myparams = e.record.data; var ds = this.store; myparams.ctype = 'json'; myparams.action = 'edit'; this.form.submit({ url: "tr_attachment.cgi", params: myparams, success: function(f, a){ ds.commitChanges(); }, failure: function(f, a){ Testopia.Util.error(f, a); ds.rejectChanges(); } }); }, newAttachment: function(){ var form = new Testopia.Attachment.NewAttachmentPopup(this.object); form.window.show(); }, deleteAttachment: function(){ object = this.object; Ext.Msg.show({ title: 'Confirm Delete?', msg: ATTACHMENT_DELETE_WARNING, buttons: Ext.Msg.YESNO, fn: function(btn){ if (btn == 'yes') { var testopia_form = new Ext.form.BasicForm('testopia_helper_frm'); testopia_form.submit({ url: 'tr_attachment.cgi', params: { attach_ids: Testopia.Util.getSelectedObjects(Ext.getCmp('attachments_panel'), 'attach_id'), action: 'remove', ctype: 'json', object: object.type, object_id: object.id }, success: function(){ Ext.getCmp('attachments_panel').store.load(); }, failure: Testopia.Util.error }); } }, animEl: 'delete_attachment_btn', icon: Ext.MessageBox.QUESTION }); }, onActivate: function(event){ if (this.object.type == 'caserun') { this.store.baseParams = { ctype: 'json', action: 'list', object: 'caserun', object_id: Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('caserun_id') }; this.store.load(); } if (!this.store.getCount()) { this.store.load(); } } }); Testopia.Attachment.Form = function(){ var filecount = 1; Testopia.Attachment.Form.superclass.constructor.call(this, { title: "Attachments", id: 'attachments_form', autoScroll: true, items: [{ layout: 'column', items: [{ columnWidth: 0.5, layout: 'form', bodyStyle: 'padding: 5px 5px 10px 10px', id: 'attach_file_col', items: [{ xtype: 'field', fieldLabel: 'Attachment', inputType: 'file', name: 'file1', width: 300 }] }, { columnWidth: 0.5, id: 'attach_desc_col', bodyStyle: 'padding: 5px 5px 10px 10px', layout: 'form', items: [{ xtype: 'textfield', fieldLabel: 'Description', name: 'file_desc1', width: 300 }] }] }], buttons: [{ text: 'Attach Another', handler: function(){ filecount++; if (filecount > 4) { Ext.Msg.show({ msg: 'You may only attach 4 files at a time', title: 'Limit Exceeded', buttons: Ext.Msg.OK, icon: Ext.MessageBox.WARNING }); return; } Ext.getCmp('attach_file_col').add(new Ext.form.Field({ fieldLabel: 'Attachment', inputType: 'file', name: 'file' + filecount, width: 300 })); Ext.getCmp('attach_desc_col').add(new Ext.form.Field({ fieldLabel: 'Description', name: 'file_desc' + filecount, width: 300 })); Ext.getCmp('attachments_form').doLayout(); } }] }); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Attachment.Form, Ext.Panel, { onActivate: function(){ Ext.getCmp('attachments_form').doLayout(); } }); Testopia.Attachment.NewAttachmentPopup = function(object){ if (!this.window) { var win = new Ext.Window({ id: 'new_attachment_win', title: 'Attach a file', closable: true, width: 400, height: 180, plain: true, shadow: false, closable: false, layout: 'fit', items: [{ xtype: 'form', id: 'new_attach_frm', fileUpload: true, bodyStyle: 'padding: 10px', items: [{ xtype: 'textfield', id: 'attach_desc', fieldLabel: 'Description', name: 'description', allowBlank: false }, { xtype: 'field', id: 'attach_file', inputType: 'file', fieldLabel: 'File', name: 'data', allowBlank: false }] }], buttons: [{ text: 'Submit', handler: function(){ Ext.getCmp('new_attach_frm').getForm().submit({ url: 'tr_attachment.cgi', params: { action: 'add', object: object.type, object_id: object.id, ctype: 'json' }, success: function(){ Ext.getCmp('attachments_panel').store.load(); Ext.getCmp('new_attachment_win').close(); }, failure: Testopia.Util.error }); } }, { text: 'Cancel', handler: function(){ Ext.getCmp('new_attachment_win').close(); } }] }); this.window = win; } return this; }; /* * END OF FILE - /testopia/extensions/Testopia/js/attachments.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/plan.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.TestPlan.Store = function(params, auto){ params.ctype = 'json'; Testopia.TestPlan.Store.superclass.constructor.call(this, { url: 'tr_list_plans.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: params, totalProperty: 'totalResultsAvailable', root: 'Result', autoLoad: auto, id: 'plan_id', fields: [{ name: "plan_id", mapping: "plan_id" }, { name: "name", mapping: "name" }, { name: "author", mapping: "author_name" }, { name: "creation_date", mapping: "creation_date" }, { name: "product", mapping: "product_name" }, { name: "product_id", mapping: "product_id" }, { name: "prod_version", mapping: "default_product_version" }, { name: "type", mapping: "plan_type" }, { name: "case_count", mapping: "case_count" }, { name: "run_count", mapping: "run_count" }], remoteSort: true }); this.paramNames.sort = "order"; }; Ext.extend(Testopia.TestPlan.Store, Ext.data.JsonStore); Testopia.TestPlan.TypesStore = function(auto){ Testopia.TestPlan.TypesStore.superclass.constructor.call(this, { url: 'tr_quicksearch.cgi', root: 'types', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getplantypes' }, autoLoad: auto, id: 'id', fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }] }); }; Ext.extend(Testopia.TestPlan.TypesStore, Ext.data.JsonStore); /* * Testopia.TestPlan.TypesCombo */ Testopia.TestPlan.TypesCombo = function(cfg){ Testopia.TestPlan.TypesCombo.superclass.constructor.call(this, { id: cfg.id || 'plan_type_combo', store: cfg.transform ? false : new Testopia.TestPlan.TypesStore(cfg.mode == 'local' ? true : false), loadingText: 'Looking up types...', displayField: 'name', valueField: 'id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.TestPlan.TypesCombo, Ext.form.ComboBox); Testopia.TestPlan.Import = function(params){ var win = new Ext.Window({ id: 'plan_import_win', closable: true, width: 450, height: 150, plain: true, shadow: false, layout: 'fit', items: [{ xtype: 'form', height: 250, url: 'tr_importer.cgi', id: 'importform', baseParams: { action: 'upload', ctype: 'json', plan_id: params.plan_id, product_id: params.product_id }, fileUpload: true, items: [{ height: 50, style: "padding: 5px", border: false, html: params.product_id ? PRODUCT_PLAN_IMPORT : PLAN_CASES_IMPORT }, { xtype: 'field', fieldLabel: 'Upload File', labelStyle: "padding: 5px", inputType: 'file', name: 'data', width: 300 }], buttons: [{ text: 'Submit', handler: function(){ Ext.getCmp('importform').getForm().submit({ success: function(){ if (params.product_id) { Ext.getCmp('object_panel').activate('product_plan_grid'); Ext.getCmp('product_plan_grid').store.load(); } else { Ext.getCmp('object_panel').activate('plan_case_grid'); Ext.getCmp('plan_case_grid').store.load(); } Ext.getCmp('plan_import_win').close(); }, failure: Testopia.Util.error }); } }] }] }); win.show(this); } Testopia.TestPlan.Grid = function(params, cfg){ params.limit = Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25); params.current_tab = 'plan'; this.params = params; var versionbox = new Testopia.Product.VersionCombo({ id: 'plan_grid_version_chooser', hiddenName: 'prod_version', mode: 'remote', params: { product_id: params.product_id }, listeners: { 'startedit': function(){ var pid = Ext.getCmp(cfg.id || 'plan_grid').getSelectionModel().getSelected().get('product_id'); if (versionbox.store.baseParams.product_id != pid) { versionbox.store.baseParams.product_id = pid; versionbox.store.load(); } } } }); this.store = new Testopia.TestPlan.Store(params); var ds = this.store; this.columns = [{ header: "ID", width: 30, dataIndex: 'plan_id', sortable: true, renderer: Testopia.Util.makeLink.createDelegate(this,['plan'],true), hideable: false }, { header: "Name", width: 220, dataIndex: 'name', id: "plan_name", sortable: true, editor: { xtype: 'textfield', allowBlank: false } }, { header: "Author", width: 150, sortable: true, dataIndex: 'author' }, { header: "Created", width: 110, sortable: true, dataIndex: 'creation_date', hidden: true }, { header: "Product", width: 180, sortable: true, dataIndex: 'product', hidden: true }, { header: "Product Version", width: 60, sortable: true, dataIndex: 'prod_version', editor: versionbox, renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Type", width: 60, sortable: true, dataIndex: 'type', editor: new Testopia.TestPlan.TypesCombo({ id: 'plan_grid_ types_chooser', hiddenName: 'type', mode: 'remote' }), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Cases", width: 20, sortable: false, dataIndex: 'case_count' }, { header: "Runs", width: 20, sortable: false, dataIndex: 'run_count' }]; this.form = new Ext.form.BasicForm('testopia_helper_frm', {}); this.bbar = new Testopia.Util.PagingBar('plan', this.store); Testopia.TestPlan.Grid.superclass.constructor.call(this, { title: 'Test Plans', id: cfg.id || 'plan_grid', layout: 'fit', region: 'center', stripeRows: true, loadMask: { msg: 'Loading Test Plans...' }, autoExpandColumn: "plan_name", autoScroll: true, plugins: [new Ext.ux.grid.RowEditor({ id:'plan_row_editor', saveText: 'Update' })], sm: new Ext.grid.RowSelectionModel({ singleSelect: cfg.single || false, listeners: { 'rowselect': function(sm, i, r){ if (Ext.getCmp('plan_add_run_mnu')) { Ext.getCmp('plan_add_run_mnu').enable(); } if (Ext.getCmp('plan_add_case_mnu')) { Ext.getCmp('plan_add_case_mnu').enable(); } if (Ext.getCmp('plan_grid_edit_mnu')) { Ext.getCmp('plan_grid_edit_mnu').enable(); } Ext.getCmp('new_run_button').enable(); Ext.getCmp('new_case_button').enable(); Ext.getCmp('edit_plan_list_btn').enable(); if (sm.getCount() > 1) { if (Ext.getCmp('plan_add_run_mnu')) { Ext.getCmp('plan_add_run_mnu').disable(); } Ext.getCmp('new_run_button').disable(); } }, 'rowdeselect': function(sm, i, r){ if (sm.getCount() < 1) { Ext.getCmp('new_run_button').disable(); Ext.getCmp('new_case_button').disable(); Ext.getCmp('edit_plan_list_btn').disable(); } } } }), enableColumnHide: true, tbar: [{ xtype: 'button', text: 'New Run', id: 'new_run_button', disabled: true, handler: this.newRun.createDelegate(this) }, { xtype: 'button', text: 'New Case', id: 'new_case_button', disabled: true, handler: this.newCase.createDelegate(this) }, new Ext.Toolbar.Fill(), { xtype: 'button', id: 'save_plan_list_btn', icon: 'extensions/Testopia/img/save.png', iconCls: 'img_button_16x', tooltip: 'Save this search', handler: function(b, e){ Testopia.Search.save('plan', Ext.getCmp(cfg.id || 'plan_grid').store.baseParams); } }, { xtype: 'button', id: 'link_plan_list_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this list', handler: function(b, e){ Testopia.Search.LinkPopup(Ext.getCmp(cfg.id || 'plan_grid').store.baseParams); } }, { xtype: 'button', id: 'edit_plan_list_btn', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', disabled: true, tooltip: 'Edit Selected Test Plan', handler: function(){ Testopia.Util.editFirstSelection(Ext.getCmp(cfg.id || 'plan_grid')); } }, { xtype: 'button', id: 'new_plan_list_btn', icon: 'extensions/Testopia/img/new.png', iconCls: 'img_button_16x', tooltip: 'Create a New Test Plan', handler: function(){ Testopia.TestPlan.NewPlanPopup(params.product_id); } }], viewConfig: { forceFit: true } }); Ext.apply(this, cfg); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); Ext.getCmp('plan_row_editor').on('afteredit', this.onGridEdit, this); }; Ext.extend(Testopia.TestPlan.Grid, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ grid.selindex = index; if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'plan-ctx-menu', enableScrolling: false, items: [{ text: 'Create a New Test Plan', id: 'plan_menu_new_plan', icon: 'extensions/Testopia/img/new.png', iconCls: 'img_button_16x', handler: this.newPlan.createDelegate(this) }, { text: 'Add a New Test Run to Selected Plan', id: 'plan_add_run_mnu', handler: this.newRun.createDelegate(this) }, { text: 'Add a New Test Case to Selected Plans', id: 'plan_add_case_mnu', handler: this.newCase.createDelegate(this) }, { text: 'Edit', id: 'plan_grid_edit_mnu', menu: { enableScrolling: false, items: [{ text: 'Type', handler: function(){ var win = new Ext.Window({ title: 'Change Plan Type', id: 'plan_type_win', layout: 'fit', split: true, plain: true, shadow: false, listeners: {'afterlayout':function(){Ext.getCmp('plan_type_win_types_combo').focus('',10)}}, width: 350, height: 150, items: [new Ext.FormPanel({ labelWidth: '40', bodyStyle: 'padding: 5px', items: [new Testopia.TestPlan.TypesCombo({ id: 'plan_type_win_types_combo', fieldLabel: 'Plan Type' })] })], buttons: [{ text: 'Update Type', handler: function(){ var params = { plan_type: Ext.getCmp('plan_type_win_types_combo').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'plan_id') }; Testopia.Util.updateFromList('plan', params, grid); win.close(); } }, { text: 'Cancel', handler: function(){ win.close(); } }] }); win.show(); } }, { text: 'Tags', handler: function(){ Testopia.Tags.update('plan', grid); } }] } }, { text: "Reports", menu: { enableScrolling: false, items: [{ text: 'New Status Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Status Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=status&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id'); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); } }, { text: 'New Completion Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Completion Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=completion&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id'); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); } }, { text: 'New Run Execution Report', handler: function(){ var win = new Ext.Window({ title: 'Select a date range', id: 'plan_execution_win', layout: 'fit', split: true, plain: true, shadow: false, width: 350, height: 150, items: [new Ext.FormPanel({ labelWidth: '40', bodyStyle: 'padding: 5px', items: [{ xtype: 'datefield', id: 'execution_start_date', fieldLabel: 'Start Date', name: 'chfieldfrom' }, { xtype: 'datefield', fieldLabel: 'Stop Date', id: 'execution_stop_date', emptyText: 'Now', name: 'chfieldto' }] })], buttons: [{ text: 'Submit', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Execution Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=execution&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id') + '&chfieldfrom=' + Ext.getCmp('execution_start_date').getValue() + '&chfieldto=' + Ext.getCmp('execution_stop_date').getValue(); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); win.close(); } }, { text: 'Cancel', handler: function(){ win.close(); } }] }); win.show(); } }, { text: 'New Priority Breakdown Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Status Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=priority&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id'); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); } }, { text: 'New Bug Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Bug Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=bug_grid&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id') + '&noheader=1'; Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ scripts: true, url: newPortlet.url }); } }, { text: 'Worst Offender Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Worst Offender Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=worst&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id') + '&noheader=1'; Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ scripts: true, url: newPortlet.url }); } }, { text: 'Missing Cases Report', handler: function(){ window.open('tr_list_cases.cgi?report_type=missing&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id')); } }, { text: 'Case Roll-up Report', handler: function(){ window.open('tr_list_caseruns.cgi?report_type=rollup&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id')); } }] } }, { text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }, { text: 'View Test Plan(s) in a New Tab', handler: function(){ var plan_ids = Testopia.Util.getSelectedObjects(grid, 'plan_id').split(','); var i; for (i = 0; i < plan_ids.length; i += 1) { window.open('tr_show_plan.cgi?plan_id=' + plan_ids[i]); } } },{ text: 'Export', menu: [{ text: 'Test Results as CSV', handler: function(){ window.location = 'tr_list_caseruns.cgi?ctype=csv&viewall=1&plan_id=' + Testopia.Util.getSelectedObjects(grid, 'plan_id'); } },{ text: 'Cases as CSV', handler: function(){ window.location='tr_list_cases.cgi?ctype=csv&viewall=1&plan_id=' + Testopia.Util.getSelectedObjects(grid, 'plan_id'); } },{ text: 'Plans as XML', handler: function(){ window.location='tr_list_plans.cgi?ctype=xml&viewall=1&plan_id=' + Testopia.Util.getSelectedObjects(grid, 'plan_id'); } }] }] }); } e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } this.menu.showAt(e.getXY()); }, newPlan: function(){ Testopia.TestPlan.NewPlanPopup(this.params.product_id); }, newRun: function(a,b,c,d){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); var p = {plan_id: Testopia.Util.getSelectedObjects(this, 'plan_id'), action: 'check_plan_rights'}; var records = this.getSelectionModel().getSelected(); form.submit({ url: 'tr_quicksearch.cgi', params: p, success: function(f,a){ Testopia.TestRun.NewRunPopup(records); }, failure: function(f, a){ Testopia.Util.error(f, a); } }); }, newCase: function(){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); var p = {plan_id: Testopia.Util.getSelectedObjects(this, 'plan_id'), action: 'check_plan_rights'}; var records = Testopia.Util.getSelectedObjects(this, 'plan_id') var prod = this.getSelectionModel().getSelected().get('product_id'); form.submit({ url: 'tr_quicksearch.cgi', params: p, success: function(f,a){ Testopia.TestCase.NewCasePopup(records, prod); }, failure: function(f, a){ Testopia.Util.error(f, a); } }); }, onGridEdit: function(e){ var ds = this.store; var myparams = e.record.data; myparams.action = 'edit'; this.form.submit({ url: "tr_process_plan.cgi", params: myparams, success: function(f, a){ ds.commitChanges(); }, failure: function(f, a){ Testopia.Util.error(f, a); ds.rejectChanges(); } }); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load(); } } }); Testopia.TestPlan.NewPlanForm = function(product_id){ var versionsBox = new Testopia.Product.VersionCombo({ id: 'new_plan_form_version_chooser', hiddenName: 'prod_version', fieldLabel: "Product Version", mode: 'local', params: { product_id: product_id } }); var productsBox = new Testopia.Product.Combo({ id: 'new_plan_form_product_chooser', hiddenName: 'product_id', fieldLabel: "Product", mode: 'local', value: product_id }); productsBox.on('select', function(c, r, i){ versionsBox.reset(); versionsBox.store.baseParams.product_id = r.get('id'); versionsBox.store.load(); versionsBox.enable(); }); Testopia.TestPlan.NewPlanForm.superclass.constructor.call(this, { url: 'tr_new_plan.cgi', id: 'new_plan_form', baseParams: { action: 'add' }, fileUpload: true, labelAlign: 'top', frame: true, title: 'New Plan', bodyStyle: 'padding:5px 5px 0', width: 800, height: 500, items: [{ layout: 'column', items: [{ columnWidth: 0.5, layout: 'form', items: [{ xtype: 'textfield', fieldLabel: 'Plan Name', id: 'new_plan_name', name: 'plan_name', anchor: '95%', allowBlank: false }, new Testopia.TestPlan.TypesCombo({ id: 'new_plan_form_types_chooser', mode: 'local', hiddenName: 'type', fieldLabel: 'Plan Type' })] }, { columnWidth: 0.5, layout: 'form', items: [productsBox, versionsBox] }] }, { xtype: 'tabpanel', height: 280, activeItem: 0, items: [{ layout: 'fit', title: 'Plan Document', items: [{ id: 'plan_doc', xtype: 'htmleditor', name: 'plandoc' }] }, new Testopia.Attachment.Form()] }], buttons: [{ text: 'Submit', handler: function(){ if (!Ext.getCmp('new_plan_form').getForm().isValid()) { return; } Ext.getCmp('new_plan_form').getForm().submit({ success: function(form, data){ if (data.result.err) { alert('One or more attachments were either too large or were empty. These have been ignored.'); } Ext.Msg.show({ title: 'Plan Created', msg: 'Plan ' + data.result.plan + ' Created. Would you like to go there now?', buttons: Ext.Msg.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { window.location = 'tr_show_plan.cgi?plan_id=' + data.result.plan; } } }); try { Ext.getCmp('newplan-win').close(); } catch (err) { } }, failure: Testopia.Util.error }); } }, { text: 'Cancel', handler: function(){ if (Ext.getCmp('newplan-win')) { Ext.getCmp('newplan-win').close(); } else { window.location = 'tr_show_product.cgi'; } } }] }); }; Ext.extend(Testopia.TestPlan.NewPlanForm, Ext.form.FormPanel); Testopia.TestPlan.NewPlanPopup = function(product_id){ var win = new Ext.Window({ id: 'newplan-win', closable: true, width: 800, height: 550, plain: true, shadow: false, layout: 'fit', items: [new Testopia.TestPlan.NewPlanForm(product_id)] }); win.show(this); }; Testopia.TestPlan.ClonePanel = function(plan){ var pbox = new Testopia.Product.Combo({ id: 'plan_clone_product_chooser', hiddenName: 'product_id', fieldLabel: 'Copy To Product', mode: 'local', width: 550, value: plan.product_id }); var vbox = new Testopia.Product.VersionCombo({ id: 'plan_clone_version_chooser', hiddenName: 'prod_version', fieldLabel: 'Product Version', params: { product_id: plan.product_id }, allowBlank: false }); var bbox = new Testopia.Build.Combo({ fieldLabel: 'Select a Build', id: 'plan_clone_build_chooser', mode: 'local', hiddenName: 'new_run_build', width: 200, params: { product_id: plan.product_id, activeonly: 1 } }); var ebox = new Testopia.Environment.Combo({ fieldLabel: 'Select an Environment', id: 'plan_clone_environment_chooser', mode: 'local', width: 200, hiddenName: 'new_run_env', params: { product_id: plan.product_id, isactive: 1 } }); pbox.on('select', function(c, r, i){ vbox.reset(); vbox.store.baseParams.product_id = r.id; Ext.getCmp('plan_clone_build_chooser').store.baseParams.product_id = r.id; Ext.getCmp('plan_clone_environment_chooser').store.baseParams.product_id = r.id; Ext.getCmp('plan_clone_build_chooser').store.load(); Ext.getCmp('plan_clone_environment_chooser').store.load(); if (r.id == plan.product_id) { Ext.getCmp('copy_categories').disable(); } else { Ext.getCmp('copy_categories').enable(); } vbox.store.load(); vbox.enable(); }); function doSubmit(){ var form = this.getForm(); var p = form.getValues(); if (form.isValid()) { form.submit({ success: function(f, a){ Ext.Msg.show({ title: 'Plan Copied', msg: 'Plan ' + a.result.plan_id + ' Created. Would you like to go there now?', buttons: Ext.Msg.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { window.location = 'tr_show_plan.cgi?plan_id=' + a.result.plan_id; } } }); }, failure: Testopia.Util.error }) } } Testopia.TestPlan.ClonePanel.superclass.constructor.call(this, { id: 'plan_clone_panel', url: 'tr_process_plan.cgi', baseParams: { action: 'clone' }, bodyStyle: 'padding: 10px', border: false, autoScroll: true, width: 600, items: [{ layout: 'table', border: false, layoutConfig: { columns: 2, width: '100%' }, items: [{ colspan: 2, layout: 'form', border: false, items: [{ id: 'plan_clone_name', xtype: 'textfield', fieldLabel: 'New Plan Name', name: 'plan_name', allowBlank: false, width: 550 }, pbox, vbox] }, { layout: 'form', border: false, items: [{ xtype: 'checkbox', name: 'copy_attachments', checked: false, boxLabel: 'Copy Plan Attachments', hideLabel: true }, { xtype: 'checkbox', name: 'copy_doc', checked: true, boxLabel: 'Copy Plan Document', hideLabel: true }, { xtype: 'hidden', name: 'plan_id', value: plan.plan_id }] }, { layout: 'form', border: false, items: [{ xtype: 'checkbox', name: 'copy_tags', checked: true, boxLabel: 'Copy Plan Tags', hideLabel: true }, { xtype: 'checkbox', name: 'copy_perms', checked: true, boxLabel: 'Copy Plan Permissions', hideLabel: true }] }, { layout: 'form', border: false, colspan: 2, items: [{ xtype: 'checkbox', name: 'keep_plan_author', checked: false, boxLabel: 'Maintain original author (unchecking will make me the author of the new plan)', hideLabel: true }, { xtype: 'fieldset', autoHeight: true, checkboxToggle: true, checkboxName: 'copy_cases', id: 'copy_cases', title: 'Copy Test Cases', collapsed: true, items: [{ xtype: 'checkbox', id: 'case_copy_plan_ids', name: 'make_copy', boxLabel: 'Create a copy (Unchecking will create a link to selected plans)', hideLabel: true, listeners: { 'check': function(box, checked){ if (checked === true) { Ext.getCmp('copy_cases_keep_author').enable(); Ext.getCmp('copy_cases_keep_tester').enable(); } else { Ext.getCmp('copy_cases_keep_author').disable(); Ext.getCmp('copy_cases_keep_tester').disable(); } } } }, { xtype: 'checkbox', name: 'keep_case_authors', id: 'copy_cases_keep_author', checked: false, disabled: true, boxLabel: 'Maintain original authors (unchecking will make me the author of the copied cases)', hideLabel: true }, { xtype: 'checkbox', id: 'copy_cases_keep_tester', boxLabel: 'Keep Default Tester (unchecking will make you the default tester of copied cases)', hideLabel: true, name: 'keep_tester', checked: true }, { xtype: 'checkbox', name: 'copy_categories', id: 'copy_categories', checked: false, disabled: true, boxLabel: 'Copy Categories to new product (unchecking will place copied cases in the default category for the selected product)', hideLabel: true }] }, { xtype: 'fieldset', autoHeight: true, checkboxToggle: true, checkboxName: 'copy_runs', id: 'copy_runs', title: 'Copy Test Runs', collapsed: true, listeners: { 'expand': function(){ Ext.getCmp('plan_clone_build_chooser').allowBlank = false; Ext.getCmp('plan_clone_environment_chooser').allowBlank = false; }, 'collapse':function(){ Ext.getCmp('plan_clone_build_chooser').allowBlank = true; Ext.getCmp('plan_clone_environment_chooser').allowBlank = true; }}, items: [{ xtype: 'checkbox', name: 'keep_run_managers', checked: false, boxLabel: 'Maintain managers (unchecking will make me the manager of the new runs)', hideLabel: true }, { xtype: 'checkbox', name: 'copy_run_tags', checked: true, boxLabel: 'Copy tags from the old run to the new run', hideLabel: true }, { xtype: 'checkbox', name: 'copy_run_cases', id: 'copy_run_cases_cbox', checked: true, boxLabel: 'Include test cases (unchecking will produce an empty test run)', hideLabel: true }, bbox, ebox] }] }] }], buttons: [{ text: 'Submit', handler: doSubmit.createDelegate(this) }, { text: 'Cancel', handler: function(){ Ext.getCmp('plan-clone-win').close(); } }] }); }; Ext.extend(Testopia.TestPlan.ClonePanel, Ext.form.FormPanel); Testopia.TestPlan.ClonePopup = function(plan){ var win = new Ext.Window({ id: 'plan-clone-win', closable: true, width: 750, title: 'Create a Copy of Plan ' + plan.plan_id, height: 500, plain: true, shadow: false, closable: true, layout: 'fit', items: [new Testopia.TestPlan.ClonePanel(plan)] }); win.show(); }; /* * END OF FILE - /testopia/extensions/Testopia/js/plan.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/case.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker * M-A Parent */ Testopia.TestCase.Store = function(params, auto){ Testopia.TestCase.Store.superclass.constructor.call(this, { url: 'tr_list_cases.cgi', baseParams: params, listeners: { 'exception': Testopia.Util.loadError }, totalProperty: 'totalResultsAvailable', root: 'Result', autoLoad: auto, id: 'case_id', fields: [{ name: "case_id", mapping: "case_id" }, { name: "plan_id", mapping: "plan_id" }, { name: "alias", mapping: "alias" }, { name: "case_summary", mapping: "summary" }, { name: "author", mapping: "author_name" }, { name: "tester", mapping: "default_tester" }, { name: "creation_date", mapping: "creation_date" }, { name: "category", mapping: "category_name" }, { name: "priority", mapping: "priority" }, { name: "status", mapping: "status" }, { name: "run_count", mapping: "run_count" }, { name: "requirement", mapping: "requirement" }, { name: "isautomated", mapping: "isautomated" }], remoteSort: true }); }; Ext.extend(Testopia.TestCase.Store, Ext.data.JsonStore); Testopia.TestCase.StatusListStore = function(auto){ Testopia.TestCase.StatusListStore.superclass.constructor.call(this, { url: 'tr_quicksearch.cgi', root: 'statuses', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getcasestatus' }, autoLoad: auto, id: 'id', fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }] }); }; Ext.extend(Testopia.TestCase.StatusListStore, Ext.data.JsonStore); Testopia.TestCase.ComponentStore = function(params, auto){ params.action = 'getcomponents'; Testopia.TestCase.ComponentStore.superclass.constructor.call(this, { url: 'tr_quicksearch.cgi', root: 'components', baseParams: params, listeners: { 'exception': Testopia.Util.loadError }, autoLoad: auto, id: 'id', fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }, { name: 'qa', mapping: 'qa_contact' }, { name: 'product', mapping: 'product' }] }); }; Ext.extend(Testopia.TestCase.ComponentStore, Ext.data.JsonStore); Testopia.TestCase.PriorityStore = function(auto){ Testopia.TestCase.PriorityStore.superclass.constructor.call(this, { url: 'tr_quicksearch.cgi', root: 'priorities', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getpriorities' }, autoLoad: auto, id: 'id', fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }] }); }; Ext.extend(Testopia.TestCase.PriorityStore, Ext.data.JsonStore); /* * Testopia.TestCase.StatusListCombo */ Testopia.TestCase.StatusListCombo = function(cfg){ Testopia.TestCase.StatusListCombo.superclass.constructor.call(this, { id: cfg.id || 'case_status_combo', store: cfg.transform ? false : new Testopia.TestCase.StatusListStore(cfg.mode == 'local' ? true : false), loadingText: 'Looking up statuses...', displayField: 'name', valueField: 'id', typeAhead: true, triggerAction: 'all', minListWidth: 100, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.TestCase.StatusListCombo, Ext.form.ComboBox); /* * Testopia.TestCase.ComponentCombo */ Testopia.TestCase.ComponentCombo = function(cfg){ Testopia.TestCase.ComponentCombo.superclass.constructor.call(this, { id: cfg.id || 'component_combo', store: cfg.transform ? false : new Testopia.TestCase.ComponentStore(cfg.params, cfg.mode == 'local' ? true : false), loadingText: 'Looking up Components...', displayField: 'name', valueField: 'id', editable: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.TestCase.ComponentCombo, Ext.form.ComboBox); /* * Testopia.TestCase.PriorityCombo */ Testopia.TestCase.PriorityCombo = function(cfg){ Testopia.TestCase.PriorityCombo.superclass.constructor.call(this, { id: cfg.id || 'priority_combo', store: cfg.transform ? false : new Testopia.TestCase.PriorityStore(cfg.mode == 'local' ? true : false), loadingText: 'Looking up priorities...', displayField: 'name', valueField: 'id', typeAhead: true, triggerAction: 'all', minListWidth: 100, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.TestCase.PriorityCombo, Ext.form.ComboBox); Testopia.TestCase.Panel = function(params, cfg){ var cgrid = new Testopia.TestCase.Grid(params, cfg); var filter = new Testopia.TestCase.Filter(); this.cgrid = cgrid; this.store = cgrid.store; this.params = params; Testopia.TestCase.Panel.superclass.constructor.call(this, { title: 'Test Cases', layout: 'border', id: 'case-panel', items: [filter, cgrid] }); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestCase.Panel, Ext.Panel, { onActivate: function(event){ if (!this.store.getCount()) { this.store.load({ params: this.params }); } } }); Testopia.TestCase.Filter = function(){ this.form = new Ext.form.BasicForm('testopia_helper_frm', {}); Testopia.TestCase.Filter.superclass.constructor.call(this, { title: 'Search for Test Cases', region: 'north', layout: 'fit', frame: true, collapsible: true, height: 120, items: [{ buttons: [{ text: 'Search', handler: function(){ Ext.getCmp('case_search').getForm().submit(); } }] }] }); }; Ext.extend(Testopia.TestCase.Filter, Ext.Panel); Testopia.TestCase.Grid = function(params, cfg){ params.limit = Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25); params.current_tab = 'case'; this.params = params; var categoryCombo = new Testopia.Category.Combo({ id: 'case_grid_cateogy_chooser', hiddenName: 'category', mode: 'remote', params: { product_id: params.product_id }, listeners: { 'startedit': function(){ var pid = Ext.getCmp(cfg.id || 'case_grid').getSelectionModel().getSelected().get('product_id'); if (categoryCombo.store.baseParams.product_id != pid) { categoryCombo.store.baseParams.product_id = pid; categoryCombo.store.load(); } } } }); this.store = new Ext.data.GroupingStore({ url: 'tr_list_cases.cgi', baseParams: params, reader: new Ext.data.JsonReader({ totalProperty: 'totalResultsAvailable', root: 'Result', id: 'case_id', fields: [{ name: "case_id", mapping: "case_id" }, { name: "sortkey", mapping: "sortkey" }, { name: "plan_id", mapping: "plan_id" }, { name: "alias", mapping: "alias" }, { name: "summary", mapping: "summary" }, { name: "author", mapping: "author_name" }, { name: "tester", mapping: "default_tester" }, { name: "creation_date", mapping: "creation_date" }, { name: "category", mapping: "category_name" }, { name: "priority", mapping: "priority" }, { name: "status", mapping: "status" }, { name: "run_count", mapping: "run_count" }, { name: "requirement", mapping: "requirement" }, { name: "product_id", mapping: "product_id" }, { name: "component", mapping: "component" }, { name: "modified", mapping: "modified" }, { name: "isautomated", mapping: "isautomated" }, { name: "plan_name", mapping: "plan_name" }, { name: "average_time", mapping: "average_time" }, { name: "estimated_time", mapping: "estimated_time" }] }), listeners: { 'exception': Testopia.Util.loadError }, remoteSort: true, sortInfo: { field: 'case_id', direction: "ASC" }, groupField: params.plan_id ? '' : 'plan_id' }); var ds = this.store; ds.paramNames.sort = "order"; ds.on('beforeload', function(store, o){ store.baseParams.ctype = 'json'; }); this.columns = [{ header: "ID", width: 50, dataIndex: 'case_id', sortable: true, groupRenderer: function(v){ return v; }, renderer: Testopia.Util.makeLink.createDelegate(this,['case'],true), hideable: false }, { header: "Sort Key", width: 50, sortable: true, dataIndex: 'sortkey', editor: { xtype: 'numberfield', allowBlank: true, allowDecimals: false, allowNegative: false }, id: "sortkey" }, { header: "Summary", width: 220, dataIndex: 'summary', id: "case_summary", sortable: true, editor: { xtype: 'textfield', allowBlank: false } }, { header: "Author", width: 150, sortable: true, dataIndex: 'author', hidden: true }, { header: "Default Tester", width: 150, sortable: true, dataIndex: 'tester', editor: new Testopia.User.Lookup({ hiddenName: 'tester' }), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Created", width: 110, sortable: true, dataIndex: 'creation_date', hidden: true }, { header: "Last Modified", width: 110, sortable: true, dataIndex: 'modified', hidden: true }, { header: "Priority", width: 100, sortable: true, dataIndex: 'priority', editor: new Testopia.TestCase.PriorityCombo({ hiddenName: 'priority', mode: 'remote' }), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Category", width: 100, sortable: true, dataIndex: 'category', editor: categoryCombo, renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Component", width: 110, sortable: true, dataIndex: 'component' }, { header: "Status", width: 100, sortable: true, dataIndex: 'status', editor: new Testopia.TestCase.StatusListCombo('status'), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Requirement", width: 40, sortable: true, dataIndex: 'requirement', hidden: true, editor: { xtype: 'textfield', name: 'requirement' } }, { header: "Estimated Time", width: 60, sortable: true, dataIndex: 'estimated_time', editor: { xtype: 'textfield' }, hidden: true }, { header: "Average Time", width: 60, sortable: false, dataIndex: 'average_time', hidden: true }, { header: "Plan", width: 40, sortable: true, dataIndex: 'plan_id', hidden: true, renderer: Testopia.Util.makeLink.createDelegate(this,['plan'],true), groupRenderer: function(v, u, r){ return v + ': "' + r.get('plan_name') + '"'; } }, { header: "Run Count", width: 40, sortable: false, dataIndex: 'run_count', hidden: true }]; this.view = new Ext.grid.GroupingView({ forceFit: true, groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})' }); this.form = new Ext.form.BasicForm('testopia_helper_frm', {}); this.bbar = new Testopia.Util.PagingBar('case', this.store); Testopia.TestCase.Grid.superclass.constructor.call(this, { title: 'Test Cases', id: cfg.id || 'case_grid', loadMask: { msg: 'Loading Test Cases...' }, layout: 'fit', stripeRows: true, region: 'center', autoExpandColumn: "case_summary", autoScroll: true, plugins: [new Ext.ux.grid.RowEditor({ id:'case_row_editor', saveText: 'Update' })], sm: new Ext.grid.RowSelectionModel({ singleSelect: false, listeners: { 'rowselect': function(sm, i, r){ if (Ext.getCmp('delete_case_list_btn')) { Ext.getCmp('delete_case_list_btn').enable(); Ext.getCmp('edit_case_list_btn').enable(); } }, 'rowdeselect': function(sm, i, r){ if (sm.getCount() < 1) { if (Ext.getCmp('delete_case_list_btn')) { Ext.getCmp('delete_case_list_btn').disable(); Ext.getCmp('edit_case_list_btn').disable(); } } } } }), viewConfig: { forceFit: true }, tbar: [new Ext.Toolbar.Fill(), { xtype: 'button', id: 'case_grid_tocsv', icon: 'extensions/Testopia/img/csv.png', iconCls: 'img_button_16x', tooltip: 'Export Test Cases to CSV', handler: function(){ window.location = 'tr_list_cases.cgi?ctype=csv&viewall=1&' + Testopia.Util.JSONToURLQuery(Ext.getCmp(cfg.id || 'case_grid').store.baseParams, '', ['viewall', 'ctype']); } },{ xtype: 'button', id: 'case_grid_toxml', icon: 'extensions/Testopia/img/xml.png', iconCls: 'img_button_16x', tooltip: 'Export Test Cases to XML', handler: function(){ window.location = 'tr_list_cases.cgi?ctype=xml&viewall=1&' + Testopia.Util.JSONToURLQuery(Ext.getCmp(cfg.id || 'case_grid').store.baseParams, '', ['viewall', 'ctype']); } },{ xtype: 'button', id: 'save_case_list_btn', icon: 'extensions/Testopia/img/save.png', iconCls: 'img_button_16x', tooltip: 'Save this search', handler: function(b, e){ Testopia.Search.save('case', Ext.getCmp(cfg.id || 'case_grid').store.baseParams); } }, { xtype: 'button', id: 'link_case_list_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this list', handler: function(b, e){ Testopia.Search.LinkPopup(Ext.getCmp(cfg.id || 'case_grid').store.baseParams); } }, { xtype: 'button', id: 'edit_case_list_btn', icon: 'extensions/Testopia/img/edit.png', disabled: true, iconCls: 'img_button_16x', tooltip: 'Edit Selected Test Case', handler: function(){ Testopia.Util.editFirstSelection(Ext.getCmp(cfg.id || 'case_grid')); } }, { xtype: 'button', id: 'add_case_list_btn', icon: 'extensions/Testopia/img/new.png', iconCls: 'img_button_16x', tooltip: 'Create a New Test Case', handler: function(){ try { if (plan) { Testopia.TestCase.NewCasePopup(plan.plan_id, plan.product_id); } } catch (err) { window.location = 'tr_new_case.cgi'; } } }, { xtype: 'button', id: 'delete_case_list_btn', disabled: true, icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', tooltip: 'Delete Selected Test Cases', handler: this.deleteList.createDelegate(this) }] }); Ext.apply(this, cfg); this.on('activate', this.onActivate, this); this.on('rowcontextmenu', this.onContextClick, this); Ext.getCmp('case_row_editor').on('afteredit', this.onGridEdit, this); }; Ext.extend(Testopia.TestCase.Grid, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ grid.selindex = index; if (!this.menu) { // create context menu on first right click var hasplan; try { hasplan = plan ? false : true; } catch (err) { hasplan = true; } this.menu = new Ext.menu.Menu({ id: 'case_list_ctx_menu', enableScrolling: false, items: [{ text: 'Modify Selected Test Cases', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', menu: { enableScrolling: false, items: [{ text: 'Requirements', handler: function(){ Ext.Msg.prompt('Edit Requirements', '', function(btn, text){ if (btn == 'ok') { Testopia.Util.updateFromList('case', { requirement: text, ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, grid); } }); } }, { text: 'Category', disabled: hasplan, handler: function(){ var win = new Ext.Window({ title: 'Edit Category', id: 'status-win', plain: true, shadow: false, width: 300, height: 150, items: [new Testopia.Category.Combo({ fieldLabel: 'Category', params: { product_id: plan.product_id } })], buttons: [{ text: 'Submit', handler: function(){ Testopia.Util.updateFromList('case', { category: Ext.getCmp('case_category_combo').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }, { text: 'Status', handler: function(){ var win = new Ext.Window({ title: 'Edit Status', id: 'status-win', plain: true, shadow: false, listeners: {'afterlayout':function(){Ext.getCmp('case_status_update').focus('',10)}}, width: 300, height: 150, items: [new Testopia.TestCase.StatusListCombo({ id:'case_status_update', fieldLabel: 'Status' })], buttons: [{ text: 'Submit', handler: function(){ Testopia.Util.updateFromList('case', { status: Ext.getCmp('case_status_update').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }, { text: 'Priority', handler: function(){ var win = new Ext.Window({ title: 'Edit Priority', id: 'priority-win', layout: 'form', plain: true, shadow: false, listeners: {'afterlayout':function(){Ext.getCmp('case_priority_update').focus('',10)}}, width: 300, height: 150, labelWidth: 30, items: [new Testopia.TestCase.PriorityCombo({ id: 'case_priority_update', fieldLabel: 'Priority' })], buttons: [{ text: 'Submit', handler: function(){ Testopia.Util.updateFromList('case', { priority: Ext.getCmp('case_priority_update').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }, { text: 'Tester', handler: function(){ var win = new Ext.Window({ title: 'Change Default Tester', id: 'def_tester_win', layout: 'fit', plain: true, shadow: false, split: true, listeners: {'afterlayout':function(){Ext.getCmp('tester_update').focus('',10)}}, width: 350, height: 150, items: [new Ext.FormPanel({ labelWidth: '40', bodyStyle: 'padding: 5px', items: [new Testopia.User.Lookup({ id: 'tester_update', fieldLabel: 'Default Tester' })] })], buttons: [{ text: 'Update Tester', handler: function(){ Testopia.Util.updateFromList('case', { tester: Ext.getCmp('tester_update').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, grid); win.close(); } }, { text: 'Cancel', handler: function(){ win.close(); } }] }); win.show(); } }, { text: 'Automation', handler: function(){ var chbx = new Ext.form.Checkbox({ checked: false, name: 'isautomated', id: 'isautomated_update', fieldLabel: 'Enable Automation' }); var scripttext = new Ext.form.TextField({ xtype: 'textfield', disabled: true, name: 'script', fieldLabel: 'Script ' }); var argumenttext = new Ext.form.TextField({ xtype: 'textfield', name: 'arguments', disabled: true, fieldLabel: 'Arguments ' }); chbx.on('check', function(){ if (scripttext.disabled) { scripttext.enable(); argumenttext.enable(); } else { scripttext.disable(); argumenttext.disable(); } }, chbx); var win = new Ext.Window({ title: 'Edit Automation Settings', id: 'auto-win', layout: 'form', plain: true, shadow: false, listeners: {'afterlayout':function(){Ext.getCmp('isautomated_update').focus('',10)}}, width: 350, height: 250, items: [{ id: 'automation_form', bodyStyle: 'padding: 5px', xtype: 'form', items: [chbx, argumenttext, scripttext] }], buttons: [{ text: 'Submit', handler: function(){ params = Ext.getCmp('automation_form').getForm().getValues(); params.ids = Testopia.Util.getSelectedObjects(grid, 'case_id'); Testopia.Util.updateFromList('case', params, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }] } }, { text: 'Delete Selected Test Cases', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', handler: this.deleteList.createDelegate(this) }, { text: 'Add Selected Test Cases to Run... ', handler: function(){ Ext.Msg.prompt('Add to runs', '', function(btn, text){ if (btn == 'ok') { Testopia.Util.updateFromList('case', { addruns: text, ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, grid); } }); } }, { text: 'Copy or Link Selected Test Cases to Plan(s)... ', handler: function(){ var r = grid.getSelectionModel().getSelected(); Testopia.TestCase.clonePopup(r.get('product_id'), Testopia.Util.getSelectedObjects(grid, 'case_id')); } }, { text: 'Unlink from Plan', disabled: hasplan, handler: function(){ Ext.Msg.show({ title: 'Unlink Selected Test Cases', msg: 'You are about to unlink the selected test cases from this plan. If a test case is not linked to any other plans, it will be deleted. Do you want to continue?', buttons: Ext.Msg.YESNO, icon: Ext.Msg.WARNING, fn: function(btn){ if (btn == 'yes') { var testopia_form = new Ext.form.BasicForm('testopia_helper_frm'); testopia_form.submit({ url: 'tr_list_cases.cgi', params: { case_ids: Testopia.Util.getSelectedObjects(grid, 'case_id'), action: 'unlink', plan_id: plan.plan_id }, success: function(data){ Ext.Msg.show({ msg: "Test cases removed", buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); grid.store.reload(); }, failure: function(f, a){ Testopia.Util.error(f, a); grid.store.reload(); } }); } } }) } }, { text: 'Add or Remove Tags from Selected Cases...', handler: function(){ Testopia.Tags.update('case', grid); } }, { text: 'Add or Remove Bugs from Selected Cases...', handler: function(){ Testopia.TestCase.Bugs.update(grid); } }, { text: 'Add or Remove Components from Selected Cases...', handler: function(){ var win = new Ext.Window({ title: 'Add or Remove Components', id: 'component_update_win', layout: 'fit', split: true, plain: true, shadow: false, width: 550, height: 85, items: [new Testopia.TestCase.Components(grid)] }); win.show(); } }, { text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }, { text: 'View Test Case(s) in a New Tab', handler: function(){ var case_ids = Testopia.Util.getSelectedObjects(grid, 'case_id').split(','); var i; for (i = 0; i < case_ids.length; i += 1) { window.open('tr_show_case.cgi?case_id=' + case_ids[i]); } } }] }); } e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } this.menu.showAt(e.getXY()); }, onGridEdit: function(e){ var ds = this.store; var myparams = e.record.data; myparams.action = 'edit'; var tester; if (!myparams.tester.match('@')){ tester = myparams.tester; delete myparams.tester; } this.form.submit({ url: "tr_process_case.cgi", params: myparams, success: function(f, a){ if (tester) myparams.tester = tester; ds.commitChanges(); }, failure: function(f, a){ Testopia.Util.error(f, a); if (tester) myparams.tester = tester; ds.rejectChanges(); } }); }, deleteList: function(){ var grid = this; Ext.Msg.show({ title: 'Confirm Delete?', msg: CASE_DELETE_WARNING, buttons: Ext.Msg.YESNO, animEl: 'case-delete-btn', icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { var testopia_form = new Ext.form.BasicForm('testopia_helper_frm'); testopia_form.submit({ url: 'tr_list_cases.cgi', params: { case_ids: Testopia.Util.getSelectedObjects(grid, 'case_id'), action: 'delete' }, success: function(data){ Ext.Msg.show({ msg: "Test cases deleted", buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); grid.store.reload(); }, failure: function(f, a){ Testopia.Util.error(f, a); grid.store.reload(); } }); } } }); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load(); } } }); Testopia.TestCase.NewCaseForm = function(plan_ids, product_id, run_id){ Testopia.TestCase.NewCaseForm.superclass.constructor.call(this, { id: 'newcaseform', url: 'tr_new_case.cgi', baseParams: { action: 'add' }, fileUpload: true, labelAlign: 'left', frame: true, title: 'Create a New Test Case', bodyStyle: 'padding:5px 5px 0', width: 1050, height: 670, items: [{ layout: 'table', layoutConfig: { columns: 2, width: '100%' }, items: [{ colspan: 2, layout: 'form', items: [{ id: 'ncf-summary', xtype: 'textfield', fieldLabel: 'Summary', name: 'summary', allowBlank: false, width: 800 }, { xtype: 'hidden', name: 'components', id: 'compfield' }, { xtype: 'hidden', name: 'plan_id', id: 'planfield', value: plan_ids }] }, { layout: 'form', items: [new Testopia.User.Lookup({ id: 'default_tester', hiddenName: 'tester', fieldLabel: 'Default Tester' }), { xtype: 'textfield', fieldLabel: 'Alias', id: 'case_alias', name: 'alias' }, new Testopia.TestCase.PriorityCombo({ fieldLabel: 'Priority  ', hiddenName: 'priority', mode: 'local', allowBlank: false }), new Testopia.Category.Combo({ fieldLabel: 'Category', hiddenName: 'category', mode: 'local', allowBlank: false, params: { product_id: product_id } }), { xtype: 'textfield', fieldLabel: 'Estimated Time (HH:MM:SS)', id: 'estimated_time', name: 'estimated_time' }, { xtype: 'textfield', fieldLabel: 'Bugs', id: 'ncf-bugs', name: 'bugs' }, { xtype: 'textfield', fieldLabel: 'Blocks', id: 'ncf-blocks', name: 'tcblocks' }] }, { layout: 'form', items: [new Testopia.TestCase.StatusListCombo({ fieldLabel: 'Status', hiddenName: 'status', mode: 'local', value: DEFAULT_CASE_STATUS, allowBlank: false, id: 'ncf-casestatus' }), { xtype: 'textfield', fieldLabel: 'Add Tags', id: 'ncf-addtags', name: 'addtags' }, { xtype: 'textfield', fieldLabel: 'Requirements', id: 'ncf-reqs', name: 'requirement' }, { xtype: 'checkbox', fieldLabel: 'Automated', id: 'ncf-automated', name: 'isautomated', value: '1' }, { xtype: 'textfield', fieldLabel: 'Scripts', id: 'ncf-scripts', name: 'script' }, { xtype: 'textfield', fieldLabel: 'Arguments', id: 'ncf-arguments', name: 'arguments' }, { xtype: 'textfield', fieldLabel: 'Add to Run', id: 'ncf-addtorun', name: 'addruns', value: run_id }, { xtype: 'textfield', fieldLabel: 'Depends On', id: 'ncf-dependson', name: 'tcdependson' }] }] }, { xtype: 'tabpanel', id: 'ncf_tabs', height: 356, activeItem: 1, items: [{ layout: 'column', title: 'Setup Procedures', items: [{ columnWidth: 0.5, items: [{ title: 'Setup', layout: 'fit', items: [{ id: 'ncf-setup_doc', name: 'tcsetup', xtype: 'htmleditor', scrollable: true }] }] }, { columnWidth: 0.5, items: [{ title: 'Break Down', layout: 'fit', items: [{ id: 'ncf-breakdown_doc', name: 'tcbreakdown', xtype: 'htmleditor', scrollable: true }] }] }] }, { layout: 'column', title: 'Actions', items: [{ columnWidth: 0.5, items: [{ title: 'Action', layout: 'fit', items: [{ id: 'ncf-action', name: 'tcaction', xtype: 'htmleditor', scrollable: true, listeners: { 'initialize': function(h){ var httpRequest = new Ext.data.Connection(); httpRequest.request({ url: 'tr_quicksearch.cgi', params: { action: 'get_action', bug_id: Ext.urlDecode(location.search.substring(1)).bug }, success: function(d){ h.setValue(d.responseText); }, failure: Testopia.Util.error }); } } }] }] }, { columnWidth: 0.5, items: [{ title: 'Expected Results', layout: 'fit', items: [{ id: 'ncf-effect', name: 'tceffect', xtype: 'htmleditor', scrollable: true, listeners: { 'initialize': function(h){ var httpRequest = new Ext.data.Connection(); httpRequest.request({ url: 'tr_quicksearch.cgi', params: { action: 'get_effect', bug_id: Ext.urlDecode(location.search.substring(1)).bug }, success: function(d){ h.setValue(d.responseText); }, failure: Testopia.Util.error }); } } }] }] }] }, new Testopia.Attachment.Form(), { title: 'Components', id: 'component_picker', height: 250, layout: 'fit', xtype: 'grid', store: new Testopia.TestCase.ComponentStore({ product_id: product_id }, true), columns: [{ sortable: true, dataIndex: 'name', width: 500 }], sm: new Ext.grid.RowSelectionModel({ singleSelect: false }), tbar: ['Product', ' ', new Testopia.Product.Combo({ mode: 'local', value: product_id, id: 'comp_product_combo' })] }] }], buttons: [{ text: 'Submit', handler: function(){ if (!Ext.getCmp('newcaseform').getForm().isValid()) { return; } Ext.getCmp('newcaseform').getForm().submit({ method: 'POST', success: function(form, data){ if (data.result.err) { alert('One or more attachments were either too large or were empty. These have been ignored.'); } Ext.Msg.show({ title: 'Test Case Created', msg: 'Test case ' + data.result.tc + ' Created. Would you like to go there now?', buttons: Ext.Msg.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { window.location = 'tr_show_case.cgi?case_id=' + data.result.tc; } } }); if (Ext.getCmp('plan_case_grid')) { Ext.getCmp('plan_case_grid').store.reload(); } else if (Ext.getCmp('newrun_casegrid')) { Ext.getCmp('newrun_casegrid').store.reload(); } else if (Ext.getCmp('caserun_grid')) { Ext.getCmp('caserun_grid').store.reload(); } else if (Ext.getCmp('product_case_grid')) { Ext.getCmp('product_case_grid').store.reload(); } }, failure: Testopia.Util.error }); } }, { text: 'Cancel', id: 'ncf_cancel_btn', handler: function(){ Ext.getCmp('newcaseform').getForm().reset(); try { if (Ext.getCmp('newcase-win')) { Ext.getCmp('newcase-win').close(); } else { window.location = 'tr_show_product.cgi'; } } catch (err) { } } }] }); Ext.getCmp('comp_product_combo').on('select', function(c, r, i){ Ext.getCmp('component_picker').store.baseParams.product_id = r.get('id'); Ext.getCmp('component_picker').store.load(); }); Ext.getCmp('component_picker').getSelectionModel().on('rowselect', function(m, i, r){ Ext.getCmp('compfield').setValue(Testopia.Util.getSelectedObjects(Ext.getCmp('component_picker'), 'id')); Ext.getCmp('default_tester').setValue(r.get('qa')); }); Ext.getCmp('ncf_tabs').on('tabchange', function(t, p){ p.doLayout(); }); }; Ext.extend(Testopia.TestCase.NewCaseForm, Ext.form.FormPanel); Testopia.TestCase.NewCasePopup = function(plans, product_id, run_id){ var win = new Ext.Window({ id: 'newcase-win', closable: true, width: Ext.getBody().getViewSize().width - 150, height: Ext.getBody().getViewSize().height - 150, plain: true, shadow: false, layout: 'fit', items: [new Testopia.TestCase.NewCaseForm(plans, product_id, run_id)] }); win.show(this); }; Testopia.TestCase.PlanList = function(tcid, product_id){ this.remove = function(){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_process_case.cgi', params: { action: 'unlink', plan_id: Testopia.Util.getSelectedObjects(Ext.getCmp('case_plan_grid'), 'plan_id'), case_id: tcid }, success: function(){ ds.load(); }, failure: Testopia.Util.error }); }; this.store = new Ext.data.JsonStore({ url: 'tr_process_case.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getplans', case_id: tcid }, root: 'plans', id: 'plan_id', fields: [{ name: 'plan_id', mapping: 'plan_id' }, { name: 'plan_name', mapping: 'plan_name' }] }); var ds = this.store; this.columns = [{ header: 'ID', dataIndex: 'plan_id', hideable: false, renderer: Testopia.Util.makeLink.createDelegate(this,['plan'],true) }, { header: 'Name', width: 150, dataIndex: 'plan_name', id: 'plan_name', sortable: true, hideable: false }]; var newplan = new Ext.form.ComboBox({ store: new Testopia.TestPlan.Store({ product_id: product_id, viewall: 1 }, false), loadingText: 'Looking up plans...', id: 'link_plan_combo', width: 150, displayField: 'name', valueField: 'plan_id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, emptyText: 'Choose a Plan...' }); var addButton = new Ext.Button({ icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', tooltip: 'Link to plan', handler: function(){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_process_case.cgi', params: { action: 'link', plan_ids: newplan.getValue(), case_id: tcid }, success: function(){ ds.load(); }, failure: Testopia.Util.error }); } }); var deleteButton = new Ext.Button({ icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', tooltip: 'Unlink Selected Plans', handler: this.remove }); Testopia.TestCase.PlanList.superclass.constructor.call(this, { title: 'Plans', split: true, layout: 'fit', autoExpandColumn: "plan_name", collapsible: true, id: 'case_plan_grid', loadMask: { msg: 'Loading plans...' }, autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: true }), viewConfig: { forceFit: true }, tbar: [newplan, addButton, deleteButton] }); ds.on('load', function(s, r, o){ if (s.getCount() == 1) { deleteButton.disable(); } else { deleteButton.enable(); } }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestCase.PlanList, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ grid.getSelectionModel().selectRow(index); if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'tags-ctx-menu', items: [{ text: 'Unlink Selected Plans', id: 'plan_remove_mnu', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', handler: grid.remove }, { text: 'Go to Plan', handler: function(){ window.location = 'tr_show_plan.cgi?plan_id=' + grid.getSelectionModel().getSelected().get('plan_id'); } }, { text: 'Refresh', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }] }); } if (this.store.getCount() == 1) { Ext.getCmp('plan_remove_mnu').disable(); } else { Ext.getCmp('plan_remove_mnu').enable(); } e.stopEvent(); this.menu.showAt(e.getXY()); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load(); } } }); Testopia.TestCase.Clone = function(product_id, cases){ var pgrid = new Testopia.TestPlan.Grid({ product_id: product_id }, { id: 'plan_clone_grid' }); Testopia.TestCase.Clone.superclass.constructor.call(this, { id: 'case-clone-panel', layout: 'border', items: [{ region: 'north', layout: 'fit', border: false, height: 300, items: [pgrid] }, { region: 'center', xtype: 'form', title: 'Clone Options', id: 'case_clone_frm', border: false, frame: true, autoScroll: true, bodyStyle: 'padding: 10px', labelWidth: 250, height: 280, items: [{ xtype: 'fieldset', autoHeight: true, checkboxToggle: true, checkboxName: 'copy_cases', title: 'Create a copy (Unchecking will create a link to selected plans)', id: 'case_copy_method', collapsed: true, items: [{ xtype: 'hidden', id: 'case_copy_plan_ids', name: 'plan_ids' }, { xtype: 'hidden', id: 'case_clone_product_id', value: product_id, name: 'product_id' }, { xtype: 'checkbox', boxLabel: 'Keep Author (unchecking will make you the author of copied cases)', hideLabel: true, name: 'keep_author', checked: true }, { xtype: 'checkbox', boxLabel: 'Keep Default Tester (unchecking will make you the default tester of copied cases)', hideLabel: true, name: 'keep_tester', checked: true }, { xtype: 'checkbox', boxLabel: 'Copy case document (action, expected results, etc.)', hideLabel: true, name: 'copy_doc', checked: true }, { xtype: 'checkbox', boxLabel: 'Copy Attachments', hideLabel: true, name: 'copy_attachments' }, { xtype: 'checkbox', boxLabel: 'Copy Tags', hideLabel: true, name: 'copy_tags', checked: true }, { xtype: 'checkbox', boxLabel: 'Copy components', hideLabel: true, name: 'copy_comps', checked: true }, { xtype: 'checkbox', boxLabel: 'Copy category to new product', hideLabel: true, disabled: true, id: 'case_clone_category_box', name: 'copy_category', checked: true }] }] }], buttons: [{ text: 'Submit', handler: function(){ var form = Ext.getCmp('case_clone_frm').getForm(); var params = form.getValues(); form.baseParams = {}; form.baseParams.action = 'clone'; form.baseParams.ids = cases; form.baseParams.plan_ids = Testopia.Util.getSelectedObjects(Ext.getCmp('plan_clone_grid'), 'plan_id'); form.baseParams.product_id = Ext.getCmp('case_clone_win_product_chooser').getValue(); form.submit({ url: 'tr_list_cases.cgi', success: function(form, data){ if (params.copy_cases) { if (data.result.tclist.length == 1) { Ext.Msg.show({ title: 'Test Case Copied', msg: 'Test case ' + data.result.tclist[0] + ' Copied from Case ' + cases + '. Would you like to go there now?', buttons: Ext.Msg.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { window.location = 'tr_show_case.cgi?case_id=' + data.result.tclist[0]; } } }); } else { Ext.Msg.show({ title: 'Test Case Copied', msg: data.result.tclist.length + ' Test cases Copied successfully View List', buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); } } else { Ext.Msg.show({ title: 'Test Case(s) Linked', msg: 'Test cases ' + cases + ' Linked successfully', buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); } Ext.getCmp('case-clone-win').close(); try { Ext.getCmp('case_plan_grid').store.reload(); } catch (err) { }; }, failure: Testopia.Util.error }); } }, { text: 'Cancel', handler: function(){ try { Ext.getCmp('case-clone-win').close(); } catch (err) { window.location = 'tr_show_product.cgi'; } } }] }); }; Ext.extend(Testopia.TestCase.Clone, Ext.Panel); Testopia.TestCase.clonePopup = function(product_id, cases){ var win = new Ext.Window({ id: 'case-clone-win', closable: true, width: 800, height: 550, plain: true, shadow: false, layout: 'fit', items: [new Testopia.TestCase.Clone(product_id, cases)] }); var pg = Ext.getCmp('plan_clone_grid'); Ext.apply(pg, { title: 'Select plans to clone cases to' }); win.show(this); var pchooser = new Testopia.Product.Combo({ id: 'case_clone_win_product_chooser', mode: 'local', value: product_id }); pchooser.on('select', function(c, r, i){ pg.store.baseParams = { ctype: 'json', product_id: r.get('id') }; if (r.get('id') != product_id) { Ext.getCmp('case_clone_category_box').enable(); } else { Ext.getCmp('case_clone_category_box').disable(); } Ext.getCmp('case_clone_product_id').setValue(r.get('id')); pg.store.load(); }); pg.getTopToolbar().removeAll(); pg.getTopToolbar().add('Product: ', pchooser); pg.getSelectionModel().un('rowselect', pg.getSelectionModel().events['rowselect'].listeners[0].fn); pg.getSelectionModel().un('rowdeselect', pg.getSelectionModel().events['rowdeselect'].listeners[0].fn); pg.store.load(); }; /* * END OF FILE - /testopia/extensions/Testopia/js/case.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/caserun.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.TestCase.Bugs.Grid = function(id){ var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {}); function bug_link(id){ return '' + id + ''; } var tcid; if (id) { tcid = id; } this.tcid = tcid; this.store = new Ext.data.JsonStore({ url: 'tr_process_case.cgi', root: 'bugs', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getbugs' }, fields: [{ name: 'run_id', mapping: 'run_id' }, { name: 'build', mapping: 'build' }, { name: 'env', mapping: 'env' }, { name: 'summary', mapping: 'summary' }, { name: 'case_run_id', mapping: 'case_run_id' }, { name: 'bug_id', mapping: 'bug_id' }, { name: 'status', mapping: 'status' }, { name: 'resolution', mapping: 'resolution' }, { name: 'assignee', mapping: 'assignee' }, { name: 'severity', mapping: 'severity' }, { name: 'priority', mapping: 'priority' }] }); addbug = function(){ tcid = this.tcid; var ids; var type = 'case'; if (Ext.getCmp('caserun_grid')) { type = 'caserun'; ids = Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'); } else { ids = tcid; } testopia_form.submit({ url: 'tr_list_cases.cgi', params: { action: 'update_bugs', bug_action: 'attach', bugs: Ext.getCmp('attachbug').getValue(), type: type, ids: ids }, success: function(){ ds.load({ params: { case_id: tcid } }); Ext.getCmp('attachbug').reset(); }, failure: Testopia.Util.error }); }; removebug = function(){ tcid = this.tcid; var type = 'case'; if (Ext.getCmp('caserun_grid')) { type = 'caserun'; ids = Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'); } else { ids = tcid; } testopia_form.submit({ url: 'tr_list_cases.cgi', params: { action: 'update_bugs', bugs: Testopia.Util.getSelectedObjects(Ext.getCmp('case_bugs_panel'), 'bug_id'), type: type, ids: ids }, success: function(){ ds.load({ params: { case_id: tcid } }); }, failure: Testopia.Util.error }); }; newbug = function(){ var bug_panel = new Ext.Panel({ id: 'new_bug_panel' }); var caserun_id; if (Ext.getCmp('caserun_grid') && Ext.getCmp('caserun_grid').getSelectionModel().getCount()) { caserun_id = Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('caserun_id'); } var store = new Ext.data.Store({ url: 'tr_process_case.cgi', baseParams: { action: 'case_to_bug', case_id: this.tcid, caserun_id: caserun_id }, reader: new Ext.data.XmlReader({ record: 'newbug', id: 'case_id' }, [{ name: 'product', mapping: 'product' }, { name: 'version', mapping: 'version' }, { name: 'component', mapping: 'component' }, { name: 'comment', mapping: 'comment' }, { name: 'case_id', mapping: 'case_id' }, { name: 'assigned_to', mapping: 'assigned_to' }, { name: 'qa_contact', mapping: 'qa_contact' }, { name: 'short_desc', mapping: 'short_desc' }]) }); store.load(); store.on('load', function(){ // var url = 'enter_bug.cgi?'; var f = document.createElement("form"); f.setAttribute("method", "post"); f.setAttribute("action", "enter_bug.cgi"); f.setAttribute("target", "_blank"); f.setAttribute("style", "display: none"); for (var i = 0; i < store.fields.keys.length; i++) { // url = url + store.fields.keys[i] + '=' + escape(store.getAt(0).get(store.fields.keys[i])) + '&'; if (store.fields.keys[i] == 'comment'){ h = document.createElement("textarea"); h.setAttribute("name", store.fields.keys[i]); h.value = store.getAt(0).get(store.fields.keys[i]); } else { h = document.createElement("input"); h.setAttribute("name", store.fields.keys[i]); txt = store.getAt(0).get(store.fields.keys[i]).replace(/\n/,' '); h.setAttribute("value", store.getAt(0).get(store.fields.keys[i])); } f.appendChild(h); } h = document.createElement("input"); h.setAttribute("name", "caserun_id"); h.setAttribute("value", caserun_id); f.appendChild(h); document.body.appendChild(f); f.submit(); // url = url + 'caserun_id=' + caserun_id; // window.open(url); }); }; var ds = this.store; this.columns = [{ header: "Bug", width: 150, dataIndex: 'bug_id', sortable: true, renderer: bug_link }, { header: "Found In Run", width: 50, dataIndex: 'run_id', sortable: true, renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true) }, { header: "With Build", width: 50, dataIndex: 'build', sortable: true }, { header: "Environment", width: 50, dataIndex: 'env', sortable: true }, { id: 'bugs_summary', header: "Summary", width: 200, dataIndex: 'summary', sortable: true }, { header: "Status", width: 50, dataIndex: 'status', sortable: true }, { header: "Resolution", width: 50, dataIndex: 'resolution', sortable: true }, { header: "Severity", width: 50, dataIndex: 'severity', sortable: true }, { header: "Asignee", width: 150, dataIndex: 'assignee', sortable: true }, { header: "Priority", width: 50, dataIndex: 'priority', sortable: true }]; Testopia.TestCase.Bugs.Grid.superclass.constructor.call(this, { tbar: [new Ext.form.TextField({ width: 50, id: 'attachbug' }), { xtype: 'button', tooltip: "Attach a Bug", icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', handler: addbug.createDelegate(this) }, { xtype: 'button', tooltip: "File new Bug", icon: 'extensions/Testopia/img/new.png', iconCls: 'img_button_16x', handler: newbug.createDelegate(this) }, { xtype: 'button', tooltip: "Remove selected bugs from test case or run", icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', handler: removebug.createDelegate(this) }, '-', 'This view includes all bugs attached to the selected test case regardless of run'], border: false, title: 'Bugs', id: 'case_bugs_panel', bodyBorder: false, autoExpandColumn: 'bugs_summary', loadMask: { msg: 'Loading...' }, autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: true }) }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestCase.Bugs.Grid, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ this.menu = new Ext.menu.Menu({ id: 'tags-ctx-menu', items: [{ text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }, { text: 'Attach Selected Bug to Current Run/Build/Environment', id: 'reattach_bug', icon: 'extensions/Testopia/img/add.png', disabled: Ext.getCmp('caserun_grid') ? false : true, iconCls: 'img_button_16x', handler: function(){ var r = grid.store.getAt(index); var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {}); testopia_form.submit({ url: 'tr_list_cases.cgi', params: { action: 'update_bugs', bug_action: 'attach', bugs: Testopia.Util.getSelectedObjects(Ext.getCmp('case_bugs_panel'), 'bug_id'), type: 'caserun', ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, success: function(){ Ext.getCmp('caserun_grid').store.reload(); grid.store.reload(); Ext.getCmp('attachbug').reset(); }, failure: Testopia.Util.error }); } }] }); e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } this.menu.showAt(e.getXY()); }, onActivate: function(event){ this.store.load({ params: { case_id: this.tcid } }); } }); Testopia.TestCase.Components = function(id){ var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {}); var tcid; var product_id; if (id) { tcid = id; } else { if (Ext.getCmp('caserun_grid').getSelectionModel().getCount()) { tcid = Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('case_id'); } } try { if (run) { product_id = run.plan.product_id; } } catch (err) { try{ if (tcase) { product_id = tcase.product_id; } } catch (e) {} } this.tcid = tcid; this.store = new Ext.data.JsonStore({ url: 'tr_process_case.cgi', root: 'comps', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getcomponents' }, id: 'component_id', fields: [{ name: 'name', mapping: 'name' }, { name: 'id', mapping: 'id' }, { name: 'product', mapping: 'product' }] }); var ds = this.store; this.columns = [{ header: "ID", width: 150, dataIndex: 'id', sortable: false, hidden: true }, { id: 'comp_name', header: "Component", width: 150, dataIndex: 'name', sortable: true }, { id: 'product', header: "Product", width: 150, dataIndex: 'product', sortable: true }]; var pchooser = new Testopia.Product.Combo({ id: 'comp_product_chooser', mode: 'local', value: product_id }); var compchooser = new Testopia.TestCase.ComponentCombo({ params: { product_id: product_id } }); this.pchooser = pchooser; pchooser.on('select', function(){ compchooser.reset(); compchooser.store.baseParams = { product_id: pchooser.getValue(), action: 'getcomponents' }; compchooser.store.load(); }); addcomp = function(){ tcid = this.tcid; if (typeof tcid == 'object') { testopia_form.submit({ url: 'tr_list_cases.cgi', params: { action: 'update', comp_action: 'add', components: compchooser.getValue(), ids: Testopia.Util.getSelectedObjects(tcid, 'case_id') }, success: function(){ Testopia.Util.notify.msg('Component Added', 'Added component {0} to {1} cases(s)', compchooser.getRawValue(), tcid.getSelectionModel().getCount()); }, failure: Testopia.Util.error }); return; } testopia_form.submit({ url: 'tr_process_case.cgi', params: { action: 'addcomponent', component_id: compchooser.getValue(), case_id: this.tcid }, success: function(){ ds.load({ params: { case_id: tcid } }); }, failure: Testopia.Util.error }); }; removecomp = function(){ tcid = this.tcid; if (typeof tcid == 'object') { testopia_form.submit({ url: 'tr_list_cases.cgi', params: { action: 'update', comp_action: 'rem', components: compchooser.getValue(), ids: Testopia.Util.getSelectedObjects(tcid, 'case_id') }, success: function(){ Testopia.Util.notify.msg('Component Removed', 'Removed component {0} from {1} cases(s)', compchooser.getRawValue(), tcid.getSelectionModel().getCount()); }, failure: Testopia.Util.error }); return; } testopia_form.submit({ url: 'tr_process_case.cgi', params: { action: 'removecomponent', component_id: Testopia.Util.getSelectedObjects(Ext.getCmp('case_comps_panel'), 'id'), case_id: this.tcid }, success: function(){ ds.load({ params: { case_id: tcid } }); }, failure: Testopia.Util.error }); }; Testopia.TestCase.Components.superclass.constructor.call(this, { tbar: [pchooser, compchooser, { xtype: 'button', tooltip: "Attach selected component", icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', handler: addcomp.createDelegate(this) }, { xtype: 'button', tooltip: "Remove component from test case", icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', handler: removecomp.createDelegate(this) }], border: false, title: 'Components', id: 'case_comps_panel', bodyBorder: false, autoExpandColumn: 'comp_name', loadMask: { msg: 'Loading...' }, autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: false }) }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestCase.Components, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'tags-ctx-menu', items: [{ text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }] }); } e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } this.menu.showAt(e.getXY()); }, onActivate: function(event){ this.store.load({ params: { case_id: this.tcid }, callback: function(r, o, s){ if (s === false) { Testopia.Util.loadError(); } } }); this.pchooser.store.load(); } }); Testopia.TestCase.Bugs.update = function(grid){ function commitBug(action, value, grid){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_list_cases.cgi', params: { action: 'update_bugs', bug_action: action, bugs: value, type: 'case', ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, success: function(){ }, failure: Testopia.Util.error }); } var win = new Ext.Window({ title: 'Add or Remove Bugs', id: 'bugs_edit_win', layout: 'fit', split: true, plain: true, shadow: false, listeners: {'afterlayout':function(){Ext.getCmp('bug_field').focus('',10);}}, width: 350, height: 150, items: [new Ext.FormPanel({ labelWidth: '40', bodyStyle: 'padding: 5px', items: [{ xtype: 'textfield', name: 'bugs', id: 'bug_field', fieldLabel: 'Bugs' }] })], buttons: [{ text: 'Attach Bug', handler: function(){ commitBug('attach', Ext.getCmp('bug_field').getValue(), grid); win.close(); } }, { text: 'Remove Bug', handler: function(){ commitBug('remove', Ext.getCmp('bug_field').getValue(), grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(); }; Testopia.TestCaseRun.History = function(){ this.store = new Ext.data.JsonStore({ url: 'tr_caserun.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'gethistory' }, root: 'records', fields: [{ name: 'caserun_id', mapping: 'case_run_id' }, { name: 'build', mapping: 'build_name' }, { name: 'environment', mapping: 'env_name' }, { name: 'status', mapping: 'status_name' }, { name: 'testedby', mapping: 'testedby' }, { name: 'closed', mapping: 'close_date' }, { name: 'isactive', mapping: 'isactive' }, { name: "bug_list", mapping: "bug_list" }] }); this.columns = [{ header: "Build", width: 150, dataIndex: 'build', sortable: true }, { header: "Environment", width: 150, dataIndex: 'environment', sortable: true }, { header: "Status", width: 50, dataIndex: 'status', sortable: true, renderer: Testopia.Util.displayStatusIcon }, { header: "Tested By", width: 200, dataIndex: 'testedby', sortable: true }, { header: "Closed", width: 150, dataIndex: 'closed', sortable: true }, { header: "Bugs In This Build and Environment", width: 100, dataIndex: "bug_list", sortable: false, hideable: true, renderer: function(v){ if (!v) { return; } var bugs = v.bugs; var rets = ''; for (var i = 0; i < bugs.length; i++) { if (typeof bugs[i] != 'function') { rets = rets + '' + bugs[i].bug_id + ', '; } } return rets; } }]; Testopia.TestCaseRun.History.superclass.constructor.call(this, { border: false, title: 'History', id: 'caserun_history_panel', bodyBorder: false, loadMask: { msg: 'Loading Test Cases...' }, autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: true }) }); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestCaseRun.History, Ext.grid.GridPanel, { onActivate: function(event){ this.store.load({ params: { action: 'gethistory', caserun_id: Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('caserun_id') } }); } }); Testopia.TestCaseRun.StatusListStore = function(auto){ Testopia.TestCaseRun.StatusListStore.superclass.constructor.call(this, { url: 'tr_quicksearch.cgi', root: 'statuses', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getcaserunstatus' }, autoLoad: auto, id: 'id', fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }] }); }; Ext.extend(Testopia.TestCaseRun.StatusListStore, Ext.data.JsonStore); /* * Testopia.TestCaseRun.StatusListCombo */ Testopia.TestCaseRun.StatusListCombo = function(cfg){ Testopia.TestCaseRun.StatusListCombo.superclass.constructor.call(this, { id: cfg.id || 'case_run_status_combo', store: cfg.transform ? false : new Testopia.TestCaseRun.StatusListStore(cfg.mode == 'local' ? true : false), loadingText: 'Looking up statuses...', displayField: 'name', valueField: 'id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.TestCaseRun.StatusListCombo, Ext.form.ComboBox); Testopia.TestCaseRun.Panel = function(params, run){ var cgrid = new Testopia.TestCaseRun.Grid(params, run); var filter = new Testopia.TestCaseRun.Filter(); var cr = new Testopia.TestCaseRun.Info(); this.cgrid = cgrid; this.store = cgrid.store; this.params = params; this.caserun = cr; Testopia.TestCaseRun.Panel.superclass.constructor.call(this, { layout: 'border', title: 'Test Cases', id: 'caserun-panel', border: false, bodyBorder: false, items: [filter, cgrid, cr] }); cr.disable(); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestCaseRun.Panel, Ext.Panel, { onActivate: function(event){ this.store.load(); } }); Testopia.TestCaseRun.Filter = function(){ this.form = new Ext.form.BasicForm('caserun_filter_form', {}); var searchform = this.form; Testopia.TestCaseRun.Filter.superclass.constructor.call(this, { title: 'Search for Test Results', id: 'caserun_search', region: 'north', border: false, bodyBorder: false, layout: 'fit', split: true, frame: true, collapsible: true, height: 'auto', autoScroll: true, contentEl: 'caserun-filter-div', buttons: [new Ext.form.TextField({ id: 'caserun_save_filter_txt', validateOnBlur: false, allowBlank: false }), { text: 'Save Filter', handler: function(){ if (!Ext.getCmp('caserun_save_filter_txt').isValid()) { Ext.Msg.show({ title: 'Invalid Entry', msg: 'Please enter a name for this filter', buttons: Ext.Msg.OK, icon: Ext.MessageBox.WARNING }); return false; } var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {}); var params = searchform.getValues(); params.action = 'save_filter'; params.query_name = Ext.getCmp('caserun_save_filter_txt').getValue(); testopia_form.submit({ url: 'tr_process_run.cgi', params: params, success: function(){ Ext.getCmp('run_east_panel').activate('run_filter_grid'); Ext.getCmp('run_filter_grid').store.reload(); Testopia.Util.notify.msg('Filter Saved', 'Added filter {0}', params.query_name); }, failure: Testopia.Util.error }); } }, // new Ext.Toolbar.Fill(), { text: 'Reset', handler: function(){ document.getElementById('caserun_filter_form').reset(); var ds = Ext.getCmp('caserun_grid').store; var run_id = ds.baseParams.run_id; var ctype = ds.baseParams.ctype; ds.baseParams = {}; ds.baseParams.run_id = run_id; ds.baseParams.ctype = ctype; ds.baseParams.limit = Ext.getCmp('caserun_pager').pageSize; ds.load({ callback: function(){ Ext.getCmp('caserun_filtered_txt').hide(); Ext.getCmp('run_filter_grid').getSelectionModel().clearSelections(); if (Ext.getCmp('caserun_grid').getSelectionModel().getCount() < 1) { Ext.getCmp('caserun-panel').caserun.disable(); } } }); } }, { text: 'Filter', handler: function(){ var ds = Ext.getCmp('caserun_grid').store; ds.baseParams = searchform.getValues(); ds.baseParams.limit = Ext.getCmp('caserun_pager').pageSize; ds.baseParams.distinct = 1; ds.load({ callback: function(){ Ext.getCmp('caserun_filtered_txt').show(); if (Ext.getCmp('caserun_grid').getSelectionModel().getCount() < 1) { Ext.getCmp('caserun-panel').caserun.disable(); } } }); } }] }); }; Ext.extend(Testopia.TestCaseRun.Filter, Ext.Panel); Testopia.TestCaseRun.List = function(params, cfg){ this.params = params; this.store = new Ext.data.GroupingStore({ url: 'tr_list_caseruns.cgi', baseParams: params, reader: new Ext.data.JsonReader({ totalProperty: 'totalResultsAvailable', root: 'Result', id: 'caserun_id', fields: [{ name: "caserun_id", mapping: "case_run_id" }, { name: "case_id", mapping: "case_id" }, { name: "run_id", mapping: "run_id" }, { name: "build", mapping: "build_name" }, { name: "environment", mapping: "env_name" }, { name: "assignee", mapping: "assignee_name" }, { name: "testedby", mapping: "testedby" }, { name: "status", mapping: "status" }, { name: "category", mapping: "category" }, { name: "priority", mapping: "priority" }, { name: "close_date", mapping: "close_date" }, { name: "bug_count", mapping: "bug_count" }, { name: "case_summary", mapping: "case_summary" }, { name: "component", mapping: "component" }, { name: "bug_list", mapping: "bug_list" }, { name: "case_bug_list", mapping: "case_bug_list" }, { name: "plan_name", mapping:"plan_name" }] }), remoteSort: true, sortInfo: { field: 'run_id', direction: "ASC" }, groupField: 'run_id' }); var ds = this.store; ds.paramNames.sort = "order"; ds.on('beforeload', function(store, o){ store.baseParams.ctype = 'json'; }); this.summary_sort = function(){ this.store.sortInfo.field = 'summary'; this.store.sortInfo.direction == 'DESC' ? this.store.sortInfo.direction = 'ASC' : this.store.sortInfo.direction = 'DESC'; this.getView().mainHd.select('td').removeClass(this.getView().sortClasses); this.store.load(); }; this.bbar = new Testopia.Util.PagingBar('caserun', this.store); this.columns = [{ header: "Case", width: 50, dataIndex: 'case_id', sortable: true, groupRenderer: function(v){ return v; }, renderer: Testopia.Util.makeLink.createDelegate(this,['case'],true) }, { header: "Run", width: 50, dataIndex: 'run_id', sortable: true, groupRenderer: function(v){ return v; }, renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true) }, { header: "Build", width: 50, dataIndex: 'build', sortable: true, id: 'caserun_list_build_col' }, { header: "Environment", width: 50, dataIndex: 'environment', sortable: true }, { header: "Assignee", width: 150, sortable: true, dataIndex: 'assignee' }, { header: "Tested By", width: 150, sortable: true, dataIndex: 'testedby' }, { header: "Status", width: 30, sortable: true, dataIndex: 'status', groupRenderer: function(v){ return v; }, renderer: Testopia.Util.displayStatusIcon }, { header: "Closed", width: 60, sortable: true, dataIndex: 'close_date' }, { header: "Priority", width: 60, sortable: true, dataIndex: 'priority' }, { header: "Category", width: 100, sortable: true, dataIndex: 'category' }, { header: "Component", width: 100, sortable: true, dataIndex: 'component' },{ header: "Plan Name", width: 100, sortable: true, hidden: true, dataIndex: 'plan_name' }, { header: "Bugs In This Build and Environment", width: 100, dataIndex: "bug_list", sortable: false, hideable: true, renderer: function(v){ var bugs = v.bugs; var rets = ''; for (var i = 0; i < bugs.length; i++) { if (typeof bugs[i] != 'function') { rets = rets + '' + bugs[i].bug_id + ', '; } } return rets; } }, { header: "Bugs In All Builds and Environments", width: 100, dataIndex: "case_bug_list", sortable: false, hideable: true, renderer: function(v){ var bugs = v.bugs; var rets = ''; for (var i = 0; i < bugs.length; i++) { if (typeof bugs[i] != 'function') { rets = rets + '' + bugs[i].bug_id + ', '; } } return rets; } }]; this.view = new Ext.grid.GroupingView({ forceFit: true, groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})', enableRowBody: true, getRowClass: function(record, rowIndex, p, ds){ p.body = '

Summary: ' + record.data.case_summary + '

'; return 'x-grid3-row-expanded'; } }); this.tbar = [new Ext.Toolbar.Fill(), { xtype: 'button', id: 'caserun_grid_tocsv', icon: 'extensions/Testopia/img/csv.png', iconCls: 'img_button_16x', tooltip: 'Export Results to CSV', handler: function(){ window.location = 'tr_list_caseruns.cgi?ctype=csv&viewall=1&' + Testopia.Util.JSONToURLQuery( Ext.getCmp(cfg.id || 'caserun_list_grid').store.baseParams, '', ['viewall', 'ctype']); } },{ xtype: 'button', id: 'save_caserun_list_btn', icon: 'extensions/Testopia/img/save.png', iconCls: 'img_button_16x', tooltip: 'Save this search', handler: function(b, e){ Testopia.Search.save('caserun', Ext.getCmp(cfg.id || 'caserun_list_grid').store.baseParams); } }, { xtype: 'button', id: 'link_case_list_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this list', handler: function(b, e){ Testopia.Search.LinkPopup(Ext.getCmp(cfg.id || 'caserun_list_grid').store.baseParams); } }]; Testopia.TestCaseRun.List.superclass.constructor.call(this, { id: cfg.id || 'caserun_list_grid', title: 'Case Run History', loadMask: { msg: 'Loading Test Cases...' }, layout: 'fit', region: 'center', stripeRows: true, autoExpandColumn: "caserun_list_build_col", autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: false }), viewConfig: { forceFit: true } }); Ext.apply(this, cfg); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestCaseRun.List, Ext.grid.GridPanel, { deleteList: function(){ var grid = this; Ext.Msg.show({ title: 'Confirm Delete?', msg: CASERUN_DELETE_WARNING, buttons: Ext.Msg.YESNO, animEl: 'caserun-delete-btn', icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { var testopia_form = new Ext.form.BasicForm('testopia_helper_frm'); testopia_form.submit({ url: 'tr_list_caseruns.cgi', params: { caserun_ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id'), action: 'delete', deltype: 'cr', single: true, ctype: 'json' }, success: function(data){ Ext.Msg.show({ msg: "Test cases removed", buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); grid.store.reload(); }, failure: function(f, a){ Testopia.Util.error(f, a); grid.store.reload(); } }); } } }); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load(); } } }); Testopia.TestCaseRun.Grid = function(params, run){ params.limit = Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25); this.params = params; this.run = run; var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {}); var selected; this.summary_sort = function(){ this.store.sortInfo.field = 'summary'; this.store.sortInfo.direction == 'DESC' ? this.store.sortInfo.direction = 'ASC' : this.store.sortInfo.direction = 'DESC'; this.getView().mainHd.select('td').removeClass(this.getView().sortClasses); this.store.load(); }; envRenderer = function(v, md, r, ri, ci, s){ var f = this.getColumnModel().getCellEditor(ci, ri).field; record = f.store.getById(v); if (record) { return '' + record.data[f.displayField] + ''; } else { return '' + v + ''; } }; this.store = new Ext.data.GroupingStore({ url: 'tr_list_caseruns.cgi', baseParams: params, reader: new Ext.data.JsonReader({ totalProperty: 'totalResultsAvailable', root: 'Result', id: 'caserun_id', fields: [{ name: "caserun_id", mapping: "case_run_id" }, { name: "sortkey", mapping: "sortkey" }, { name: "case_id", mapping: "case_id" }, { name: "run_id", mapping: "run_id" }, { name: "build", mapping: "build_name" }, { name: "environment", mapping: "env_name" }, { name: "env_id", mapping: "env_id" }, { name: "assignee", mapping: "assignee_name" }, { name: "testedby", mapping: "testedby" }, { name: "status", mapping: "status" }, { name: "requirement", mapping: "requirement" }, { name: "category", mapping: "category" }, { name: "priority", mapping: "priority" }, { name: "close_date", mapping: "close_date" }, { name: "bug_count", mapping: "bug_count" }, { name: "case_summary", mapping: "case_summary" }, { name: "type", mapping: "type" }, { name: "id", mapping: "id" }, { name: "component", mapping: "component" }, { name: "bug_list", mapping: "bug_list" }, { name: "case_bug_list", mapping: "case_bug_list" }, { name: "plan_name", mapping:"plan_name" }] }), remoteSort: true, sortInfo: { field: 'sortkey', direction: "ASC" }, groupField: 'run_id' }); var ds = this.store; ds.paramNames.sort = "order"; ds.on('beforeload', function(store, o){ store.baseParams.ctype = 'json'; }); var buildCombo = new Testopia.Build.Combo({ id: 'tb_build', width: 100, fieldLabel: 'Build', hiddenName: 'build', mode: 'remote', forceSelection: false, allowBlank: false, typeAhead: true, disabled: true, params: { product_id: run.plan.product_id, activeonly: 1 } }); var envCombo = new Testopia.Environment.Combo({ id: 'tb_environment', width: 100, fieldLabel: 'Environment', hiddenName: 'environment', mode: 'remote', forceSelection: false, allowBlank: false, typeAhead: true, disabled: true, params: { product_id: run.plan.product_id, isactive: 1 } }); buildCombo.on('select', function(c, r, i){ params = { build_id: r.get('build_id'), ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }; Testopia.Util.updateFromList('caserun', params, Ext.getCmp('caserun_grid')); }); envCombo.on('select', function(c, r, i){ params = { env_id: r.get('environment_id'), ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }; Testopia.Util.updateFromList('caserun', params, Ext.getCmp('caserun_grid')); }); this.object_type = 'environment'; this.columns = [{ header: "Case", width: 50, dataIndex: 'case_id', sortable: true, renderer: Testopia.Util.makeLink.createDelegate(this,['case'],true) }, { header: "Run", width: 50, dataIndex: 'run_id', sortable: true, renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true), hidden: true }, { header: "Index", width: 50, dataIndex: 'sortkey', sortable: true, editor: new Ext.grid.GridEditor(new Ext.form.NumberField()) }, { header: "Build", width: 50, dataIndex: 'build', sortable: true, editor: new Ext.grid.GridEditor(new Testopia.Build.Combo({ params: { product_id: run.plan.product_id, activeonly: 1 } })), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Environment", width: 50, dataIndex: 'environment', sortable: true, editor: new Ext.grid.GridEditor(new Testopia.Environment.Combo({ params: { product_id: run.plan.product_id, isactive: 1 } })), renderer: envRenderer.createDelegate(this) }, { header: "Assignee", width: 150, sortable: true, dataIndex: 'assignee', editor: new Ext.grid.GridEditor(new Testopia.User.Lookup({ id: 'caserun_assignee' })), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Tested By", width: 150, sortable: true, dataIndex: 'testedby', hidden: true }, { header: "Closed", width: 90, sortable: true, dataIndex: 'close_date' }, { header: "Status", width: 30, sortable: true, dataIndex: 'status', align: 'center', renderer: Testopia.Util.displayStatusIcon }, { header: "Priority", width: 60, sortable: true, dataIndex: 'priority', editor: new Ext.grid.GridEditor(new Testopia.TestCase.PriorityCombo({ id: 'caserun_priority' })), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Category", width: 100, sortable: true, dataIndex: 'category', editor: new Ext.grid.GridEditor(new Testopia.Category.Combo({ id: 'caserun_category', params: { product_id: run.plan.product_id } })), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Requirement", width: 150, sortable: true, dataIndex: 'requirement', hidden: true }, { header: "Component", width: 100, sortable: true, dataIndex: 'component' }, { header: "Plan Name", width: 100, sortable: true, hidden: true, dataIndex: 'plan_name' }, { header: "Bugs In This Build and Environment", width: 100, dataIndex: "bug_list", sortable: false, hideable: true, renderer: function(v){ var bugs = v.bugs; var rets = ''; for (var i = 0; i < bugs.length; i++) { if (typeof bugs[i] != 'function') { rets = rets + '' + bugs[i].bug_id + ', '; } } return rets; } }, { header: "Bugs In All Builds and Environments", width: 100, dataIndex: "case_bug_list", sortable: false, hideable: true, renderer: function(v){ var bugs = v.bugs; var rets = ''; for (var i = 0; i < bugs.length; i++) { if (typeof bugs[i] != 'function') { rets = rets + '' + bugs[i].bug_id + ', '; } } return rets; } }]; this.form = new Ext.form.BasicForm('testopia_helper_frm', {}); this.bbar = new Testopia.Util.PagingBar('caserun', this.store); this.tbar = new Ext.Toolbar({ id: 'caserun_grid_tb', items: [{ xtype: 'button', template: imgButtonTpl, text: '', tooltip: 'Mark as IDLE (Not Run)', disabled: true, handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 1, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }, { xtype: 'button', template: imgButtonTpl, text: '', tooltip: 'Mark as PASSED', disabled: true, handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 2, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'), update_bug: Ext.getCmp('update_bugs').getValue() }, Ext.getCmp('caserun_grid')); } }, { xtype: 'button', template: imgButtonTpl, text: '', tooltip: 'Mark as FAILED', disabled: true, handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 3, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'), update_bug: Ext.getCmp('update_bugs').getValue() }, Ext.getCmp('caserun_grid')); } }, { xtype: 'button', template: imgButtonTpl, text: '', tooltip: 'Mark as RUNNING', disabled: true, handler: function(){ var reassign = 0; var isowner = 1; var sel = Ext.getCmp('caserun_grid').getSelectionModel().getSelections(); for (var i = 0; i < sel.length; i++) { if (sel[i].get('assignee') != user_login) { isowner = 0; break; } } if (isowner === 0) { Ext.Msg.show({ title: "Reassign Test Case?", msg: 'Setting this test case to Running will lock it so that only the assignee can update it. Would you like to make yourself the assignee?', buttons: Ext.MessageBox.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { reassign = 1; } Testopia.Util.updateFromList('caserun', { status_id: 4, reassign: reassign, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }); } else { Testopia.Util.updateFromList('caserun', { status_id: 4, reassign: reassign, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } } }, { xtype: 'button', template: imgButtonTpl, text: '', tooltip: 'Mark as PAUSED', disabled: true, handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 5, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }, { xtype: 'button', template: imgButtonTpl, text: '', tooltip: 'Mark as BLOCKED', disabled: true, handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 6, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }, { xtype: 'button', template: imgButtonTpl, text: '', tooltip: 'Mark as ERROR', disabled: true, handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 7, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }, ' ', '-', 'Update Bugs: ', new Ext.form.Checkbox({ id: 'update_bugs', disabled: true }), ' ', '-', ' ', buildCombo, ' ', envCombo, new Ext.Toolbar.Fill(), { xtype: 'button', id: 'caserun_grid_tocsv', icon: 'extensions/Testopia/img/csv.png', iconCls: 'img_button_16x', tooltip: 'Export Results to CSV', handler: function(){ window.location = 'tr_list_caseruns.cgi?ctype=csv&viewall=1&run_id=' + run.run_id; } }, { xtype: 'button', id: 'add_case_to_run_btn', tooltip: "Add cases to this run", icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', handler: function(){ Testopia.TestRun.AddCasePopup(run); } }, { xtype: 'button', id: 'new_case_to_run_btn', tooltip: "Create a new case and add it to this run", icon: 'extensions/Testopia/img/new.png', iconCls: 'img_button_16x', handler: function(){ Testopia.TestCase.NewCasePopup(run.plan_id, run.product_id, run.run_id); } }, { xtype: 'button', id: 'caserun_grid_edit_btn', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', tooltip: 'Edit Selected Test Case', handler: function(){ Testopia.Util.editFirstSelection(Ext.getCmp('caserun_grid')); } }, { xtype: 'button', id: 'caserun_grid_delete_btn', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', tooltip: 'Remove Selected Test Cases from This Run', handler: this.deleteList.createDelegate(this) }, new Testopia.TestRun.ProgressBar({ id: 'run_progress', text: '0%', width: 100 })] }); Testopia.TestCaseRun.Grid.superclass.constructor.call(this, { region: 'center', id: 'caserun_grid', border: false, bodyBorder: false, height: '400', stripeRows: true, split: true, enableDragDrop: true, loadMask: { msg: 'Loading Test Cases...' }, autoExpandColumn: "case_summary", autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: false, listeners: { 'rowdeselect': function(sm, n, r){ if (sm.getCount() < 1) { Ext.getCmp('case_details_panel').disable(); Ext.getCmp('tb_build').disable(); Ext.getCmp('tb_environment').disable(); Ext.getCmp('update_bugs').disable(); var items = this.grid.getTopToolbar().items.items; for (var i = 0; i < items.length; i++) { if ((items[i].id == 'add_case_to_run_btn' || items[i].id == 'run_progress')) { if (Ext.getCmp('run_status_cycle').text == 'RUNNING') { items[i].enable(); } } else { items[i].disable(); } } } }, 'rowselect': function(sm, n, r){ Ext.getCmp('case_details_panel').enable(); if (Ext.getCmp('run_status_cycle').text == 'RUNNING') { Ext.getCmp('summary_tb').enable(); Ext.getCmp('tb_build').enable(); Ext.getCmp('tb_environment').enable(); Ext.getCmp('update_bugs').enable(); var items = sm.grid.getTopToolbar().items.items; for (var i = 0; i < items.length; i++) { items[i].enable(); } } if (n == selected) { return; } var sel = []; for (var i = 0; i < sm.grid.store.data.items.length; i++) { if (sm.grid.getSelectionModel().isSelected(i)) { sel.push(sm.grid.store.getAt(i).get('case_id')); } } sm.grid.selectedRows = sel; if (sm.getCount() > 1) { return; } Ext.getCmp('case_bugs_panel').tcid = r.get('case_id'); Ext.getCmp('case_comps_panel').tcid = r.get('case_id'); Ext.getCmp('attachments_panel').object = r.data; Ext.getCmp('case_details_panel').caserun_id = r.get('caserun_id'); Ext.getCmp('casetagsgrid').obj_id = r.get('case_id'); var tab = Ext.getCmp('caserun_center_region').getActiveTab(); Ext.getCmp(tab.id).fireEvent('activate'); if (Ext.getCmp('case_bugs_panel')) { Ext.getCmp('case_bugs_panel').case_id = r.get('case_id'); } if (Ext.getCmp('case_bugs_panel')) { Ext.getCmp('case_bugs_panel').case_id = r.get('case_id'); } Ext.getCmp('case_details_panel').store.load({ params: { caserun_id: r.get('caserun_id'), action: 'gettext' } }); selected = n; } } }), viewConfig: { forceFit: true, enableRowBody: true, getRowClass: function(record, rowIndex, p, ds){ p.body = '

Summary: ' + record.data.case_summary + '

'; return 'x-grid3-row-expanded'; } } }); this.on('rowcontextmenu', this.onContextClick, this); this.on('afteredit', this.onGridEdit, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestCaseRun.Grid, Ext.grid.EditorGridPanel, { onContextClick: function(grid, index, e){ grid.selindex = index; if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'caserun-ctx-menu', items: [{ text: 'Change', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', menu: { items: [{ text: 'Build', handler: function(){ var win = new Ext.Window({ title: 'Edit Build', id: 'status-win', plain: true, shadow: false, width: 320, height: 150, listeners: {'afterlayout':function(){Ext.getCmp('multi_build').focus('',10);}}, layout: 'form', bodyStyle: 'padding: 5px', items: [new Testopia.Build.Combo({ params: { product_id: grid.run.plan.product_id, activeonly: 1 }, fieldLabel: 'Build', id: 'multi_build' }), new Ext.form.Checkbox({ fieldLabel: 'Apply to all cases in this run', id: 'build_applyall' })], buttons: [{ text: 'Submit', handler: function(){ params = { run_id: grid.run.run_id, applyall: Ext.getCmp('build_applyall').getValue(), build_id: Ext.getCmp('multi_build').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id') }; Testopia.Util.updateFromList('caserun', params, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }, { text: 'Environment', handler: function(){ var win = new Ext.Window({ title: 'Edit Environment', id: 'status-win', plain: true, shadow: false, width: 320, height: 150, listeners: {'afterlayout':function(){Ext.getCmp('multi_env').focus('',10);}}, layout: 'form', bodyStyle: 'padding: 5px', items: [new Testopia.Environment.Combo({ params: { product_id: grid.run.plan.product_id, isactive: 1 }, fieldLabel: 'Environment', id: 'multi_env' }), new Ext.form.Checkbox({ fieldLabel: 'Apply to all cases in this run', id: 'env_applyall' })], buttons: [{ text: 'Submit', handler: function(){ params = { run_id: grid.run.run_id, applyall: Ext.getCmp('env_applyall').getValue(), env_id: Ext.getCmp('multi_env').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id') }; Testopia.Util.updateFromList('caserun', params, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }, { text: 'Priority', handler: function(){ var win = new Ext.Window({ title: 'Edit Priority', id: 'priority-win', plain: true, shadow: false, width: 320, height: 150, listeners: {'afterlayout':function(){Ext.getCmp('multi_priority').focus('',10);}}, layout: 'form', bodyStyle: 'padding: 5px', items: [new Testopia.TestCase.PriorityCombo({ fieldLabel: 'Priority', id: 'multi_priority' })], buttons: [{ text: 'Submit', handler: function(){ params = { run_id: grid.run.run_id, priority: Ext.getCmp('multi_priority').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id') }; Testopia.Util.updateFromList('caserun', params, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }, { text: 'Category', handler: function(){ var win = new Ext.Window({ title: 'Edit Category', id: 'status-win', plain: true, shadow: false, width: 300, height: 150, listeners: {'afterlayout':function(){Ext.getCmp('multi_category').focus('',10);}}, items: [new Testopia.Category.Combo({ fieldLabel: 'Category', id: 'multi_category', params: { product_id: run.product_id } })], buttons: [{ text: 'Submit', handler: function(){ Testopia.Util.updateFromList('case', { category: Ext.getCmp('case_category_combo').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }, { text: 'Assignee', handler: function(){ var win = new Ext.Window({ title: 'Edit Assignee', id: 'status-win', plain: true, shadow: false, width: 320, height: 150, listeners: {'afterlayout':function(){Ext.getCmp('multi_assignee').focus('',10);}}, layout: 'form', bodyStyle: 'padding: 5px', items: [new Testopia.User.Lookup({ fieldLabel: 'Assignee', id: 'multi_assignee' }), new Ext.form.Checkbox({ fieldLabel: 'Apply to all cases in this run', id: 'assignee_applyall' })], buttons: [{ text: 'Submit', handler: function(){ params = { run_id: grid.run.run_id, applyall: Ext.getCmp('assignee_applyall').getValue(), assignee: Ext.getCmp('multi_assignee').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id') }; Testopia.Util.updateFromList('caserun', params, grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(this); } }] } }, { text: 'Remove Selected Cases', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', handler: this.deleteList.createDelegate(this) }, { text: 'Add or Remove Tags', handler: function(){ Testopia.Tags.update('case', grid); } }, { text: 'New Test Run', id: 'addRun', handler: function(){ window.location = "tr_new_run.cgi?plan_id=" + run.plan_id; } }, { text: 'Clone Run with Selected Cases', handler: function(){ Testopia.TestRun.ClonePopup(grid.run.product_id, grid.run.run_id, Testopia.Util.getSelectedObjects(grid, 'case_id')); } }, { text: 'Copy or Link Selected Test Cases to Plan(s)... ', handler: function(){ var r = grid.getSelectionModel().getSelected(); Testopia.TestCase.clonePopup(grid.run.product_id, Testopia.Util.getSelectedObjects(grid, 'case_id')); } }, { text: 'Add Selected Test Cases to Run... ', handler: function(){ Ext.Msg.prompt('Add to runs', '', function(btn, text){ if (btn == 'ok') { Testopia.Util.updateFromList('case', { addruns: text, ids: Testopia.Util.getSelectedObjects(grid, 'case_id') }, grid); } }); } }, { text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }, { text: 'View Test Case in a New Window', handler: function(){ window.open('tr_show_case.cgi?case_id=' + grid.store.getAt(grid.selindex).get('case_id')); } }, { text: 'List These Test Cases in a New Window', handler: function(){ var params = Ext.getCmp('caserun_search').form.getValues(); if (params) { window.open('tr_list_cases.cgi?' + Testopia.Util.JSONToURLQuery(params, '', ['current_tab']) + '&isactive=1'); } else { window.open('tr_list_cases.cgi?run_id=' + grid.store.getAt(grid.selindex).get('run_id')); } } }] }); } e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } this.menu.showAt(e.getXY()); }, onGridEdit: function(gevent){ var myparams = { caserun_id: gevent.record.get('caserun_id') }; var ds = this.store; switch (gevent.field) { case 'sortkey': myparams.action = 'update_sortkey'; myparams.sortkey = gevent.value; break; case 'build': myparams.action = 'update_build'; myparams.build_id = gevent.value; break; case 'environment': myparams.action = 'update_environment'; myparams.caserun_env = gevent.value; break; case 'assignee': myparams.action = 'update_assignee'; myparams.assignee = gevent.value; break; case 'priority': myparams.action = 'update_priority'; myparams.priority = gevent.value; break; case 'category': myparams.action = 'update_category'; myparams.category = gevent.value; break; } this.form.submit({ url: "tr_caserun.cgi", params: myparams, success: function(f, a){ if (a.result.caserun) { var switched = gevent.grid.store.reader.readRecords({ Result: [a.result.caserun] }).records[0]; gevent.grid.store.insert(gevent.row, switched); ds.commitChanges(); gevent.grid.store.remove(gevent.record); gevent.grid.getSelectionModel().selectRow(gevent.row); } else { ds.commitChanges(); } }, failure: function(f, a){ Testopia.Util.error(f, a); ds.rejectChanges(); } }); }, deleteList: function(){ var grid = this; if (grid.getSelectionModel().getCount() < 1) { return; } var win = new Ext.Window({ title: 'Confirm Delete?', id: 'case_delete_win', plain: true, shadow: false, width: 520, height: 250, layout: 'table', bodyStyle: 'padding: 5px', layoutConfig: { columns: 1, width: '100%' }, items: [{ html: CASERUN_DELETE_WARNING, bodyStyle: 'padding: 5px; font-weight:bold; color: red' }, { xtype: 'fieldset', items:[{ xtype: 'radio', name: 'delete_cases_options', id: 'delete_cases_radio_group', inputValue: 'cr_all', checked: true, boxLabel: 'Remove case from this run for all builds and environments', hideLabel: true }, { xtype: 'radio', name: 'delete_cases_options', inputValue: 'cr', boxLabel: 'Remove case from this run for SELECTED build and environment only', hideLabel: true }, { xtype: 'radio', name: 'delete_cases_options', inputValue: 'plan_single', boxLabel: 'Remove case from this run and from this test plan', hideLabel: true }, { xtype: 'radio', name: 'delete_cases_options', inputValue: 'all_plans', boxLabel: 'Delete this case completely (remove from all test plans)', hideLabel: true }] }], buttons: [{ text: 'Submit', handler: function(){ var testopia_form = new Ext.form.BasicForm('testopia_helper_frm'); testopia_form.submit({ url: 'tr_list_caseruns.cgi', params: { caserun_ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id'), action: 'delete', deltype: Ext.getCmp('delete_cases_radio_group').getGroupValue(), ctype: 'json' }, success: function(data){ Ext.Msg.show({ msg: "Test cases removed", buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); grid.store.reload(); }, failure: function(f, a){ Testopia.Util.error(f, a); grid.store.reload(); } }); win.close(); } }, { text: 'Cancel', handler: function(){ win.close(); } }] }); win.show(this); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load(); } } }); Testopia.TestCaseRun.Info = function(){ this.caserun_id; this.store = new Ext.data.Store({ url: 'tr_caserun.cgi', baseParams: { action: 'gettext' }, reader: new Ext.data.XmlReader({ record: 'casetext', id: 'case_id' }, [{ name: 'action', mapping: 'action' }, { name: 'results', mapping: 'effect' }, { name: 'setup', mapping: 'setup' }, { name: 'breakdown', mapping: 'breakdown' }, { name: 'case_id', mapping: 'case_id' }, { name: 'summary', mapping: 'summary' }, { name: 'notes', mapping: 'notes' }]) }); var store = this.store; store.on('load', function(s, r){ Ext.getCmp('action_editor').setValue(r[0].get('action')); Ext.getCmp('effect_editor').setValue(r[0].get('results')); Ext.getCmp('setup_editor').setValue(r[0].get('setup')); Ext.getCmp('breakdown_editor').setValue(r[0].get('breakdown')); Ext.getCmp('caserun_tb_summary').setText('Case ' + r[0].get('case_id') + ' - ' + r[0].get('summary')); }); appendNote = function(){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_list_caseruns.cgi', params: { action: 'update', note: Ext.getCmp('caserun_append_note_fld').getValue(), ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, success: function(){ Ext.getCmp('caserun_append_note_fld').reset(); store.reload(); }, failure: Testopia.Util.error }); }; processText = function(){ var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {}); var params = {}; params.tcsetup = Ext.getCmp('setup_editor').getValue(); params.tcbreakdown = Ext.getCmp('breakdown_editor').getValue(); params.tcaction = Ext.getCmp('action_editor').getValue(); params.tceffect = Ext.getCmp('effect_editor').getValue(); params.case_id = Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('case_id'); params.action = 'update_doc'; testopia_form.submit({ url: 'tr_process_case.cgi', params: params, success: function(){ Testopia.Util.notify.msg('Test case updated', 'Test Case {0} was updated successfully', 'Document'); }, failure: Testopia.Util.error }); }; var summary_tb = new Ext.Toolbar({ id: 'summary_tb', disabled: true, items: [{ template: imgButtonTpl, xtype: 'button', text: '', tooltip: 'Mark as IDLE (Not Run)', handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 1, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }, { template: imgButtonTpl, xtype: 'button', text: '', tooltip: 'Mark as PASSED', handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 2, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'), update_bug: Ext.getCmp('update_bugs').getValue() }, Ext.getCmp('caserun_grid')); } }, { template: imgButtonTpl, xtype: 'button', text: '', tooltip: 'Mark as FAILED', handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 3, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'), update_bug: Ext.getCmp('update_bugs').getValue() }, Ext.getCmp('caserun_grid')); } }, { template: imgButtonTpl, xtype: 'button', text: '', tooltip: 'Mark as RUNNING', handler: function(){ var reassign = 0; var isowner = 1; var sel = Ext.getCmp('caserun_grid').getSelectionModel().getSelections(); for (var i = 0; i < sel.length; i++) { if (sel[i].get('assignee') != user_login) { isowner = 0; break; } } if (isowner === 0) { Ext.Msg.show({ title: "Reassign Test Case?", msg: 'Setting this test case to Running will lock it so that only the assignee can update it. Would you like to make yourself the assignee?', buttons: Ext.MessageBox.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { reassign = 1; } Testopia.Util.updateFromList('caserun', { status_id: 4, reassign: reassign, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }); } else { Testopia.Util.updateFromList('caserun', { status_id: 4, reassign: reassign, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } } }, { template: imgButtonTpl, xtype: 'button', text: '', tooltip: 'Mark as PAUSED', handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 5, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }, { template: imgButtonTpl, xtype: 'button', text: '', tooltip: 'Mark as BLOCKED', handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 6, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }, { template: imgButtonTpl, xtype: 'button', text: '', tooltip: 'Mark as ERROR', handler: function(){ Testopia.Util.updateFromList('caserun', { status_id: 7, ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id') }, Ext.getCmp('caserun_grid')); } }, new Ext.Toolbar.TextItem({text:'', id:'caserun_tb_summary'})] }); Testopia.TestCaseRun.Info.superclass.constructor.call(this, { id: 'case_details_panel', layout: 'fit', region: 'south', split: true, border: false, style: 'padding-bottom: 10px', bodyBorder: false, collapsible: true, height: 340, items: [{ xtype: 'tabpanel', bodyBorder: false, activeTab: 0, id: 'caserun_center_region', title: 'Details', tbar: summary_tb, items: [{ layout: 'column', title: 'Action / Expected Results', id: 'action_panel', items: [{ columnWidth: 0.5, layout: 'fit', items: { title: 'Action', height: Ext.state.Manager.get('bigtext_height', 230), id: 'cr_action_panel', bodyBorder: false, border: false, layout: 'fit', autoScroll: true, items: [{ id: 'action_editor', xtype: 'htmleditor' }] } }, { columnWidth: 0.5, layout: 'fit', items: { title: 'Expected Results', height: Ext.state.Manager.get('bigtext_height', 230), id: 'cr_results_panel', bodyBorder: false, border: false, autoScroll: true, layout: 'fit', items: [{ id: 'effect_editor', xtype: 'htmleditor' }] } }], buttons: [{ text: 'Update Action/Results', handler: processText.createDelegate(this) }] }, { layout: 'column', title: 'Set Up / Break Down', items: [{ columnWidth: 0.5, layout: 'fit', items: { title: 'Setup', height: Ext.state.Manager.get('bigtext_height', 230), id: 'cr_setup_panel', bodyBorder: false, autoScroll: true, border: false, layout: 'fit', items: [{ id: 'setup_editor', xtype: 'htmleditor' }] } }, { columnWidth: 0.5, layout: 'fit', items: { title: 'Breakdown', height: Ext.state.Manager.get('bigtext_height', 230), id: 'cr_breakdown_panel', bodyBorder: false, autoScroll: true, border: false, layout: 'fit', items: [{ id: 'breakdown_editor', xtype: 'htmleditor' }] } }], buttons: [{ text: 'Update Setup/Breakdown', handler: processText.createDelegate(this) }] }, { title: 'Notes', id: 'caserun_notes_panel', border: false, bodyBorder: false, autoScroll: true, layout: 'fit', items: [{ xtype: 'dataview', bodyBorder: false, store: store, itemSelector: 'div.breakdowndiv', loadingText: 'Loading...', tpl: new Ext.XTemplate('', '
{notes}
', '
', '
') }], tbar: ['Add a Note: ', { xtype: 'textfield', id: 'caserun_append_note_fld', listeners: {'afterrender': function(){ this.setWidth(Ext.getCmp('caserun_notes_panel').container.getWidth() - 150); }}, width: 650 }, { xtype: 'button', text: 'Append Note', handler: appendNote.createDelegate(this) }] }, new Testopia.TestCaseRun.History(), new Testopia.Attachment.Grid({id: 0,type: 'caserun'}), new Testopia.TestCase.Bugs.Grid('caserun_bugs_grid'), new Testopia.TestCase.Components(), new Testopia.Tags.ObjectTags('case', 0) ] }] }); }; Ext.extend(Testopia.TestCaseRun.Info, Ext.Panel, this); /* * END OF FILE - /testopia/extensions/Testopia/js/caserun.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/run.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.TestRun.Grid = function(params, cfg){ params.limit = Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25); params.current_tab = 'run'; this.params = params; this.store = new Ext.data.JsonStore({ url: 'tr_list_runs.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: params, totalProperty: 'totalResultsAvailable', root: 'Result', id: 'run_id', fields: [{ name: "run_id", mapping: "run_id" }, { name: "plan_id", mapping: "plan_id" }, { name: "summary", mapping: "summary" }, { name: "manager", mapping: "manager_name" }, { name: "start_date", mapping: "start_date" }, { name: "stop_date", mapping: "stop_date" }, { name: "build", mapping: "build.name" }, { name: "environment", mapping: "environment.name" }, { name: "status", mapping: "status" }, { name: "case_count", mapping: "case_count" }, { name: "run_product_version", mapping: "product_version" }, { name: "product_id", mapping: "product_id" }, { name: "passed_pct", mapping: "passed_pct" }, { name: "failed_pct", mapping: "failed_pct" }, { name: "blocked_pct", mapping: "blocked_pct" }, { name: "complete_pct", mapping: "complete_pct" }, { name: "plan_version", mapping: "plan_version" }, { name: "bug_list", mapping: "bug_list" }], remoteSort: true }); var ds = this.store; ds.paramNames.sort = "order"; ds.on('beforeload', function(store, o){ store.baseParams.ctype = 'json'; }); var bcombo = new Testopia.Build.Combo({ hiddenName: 'build', id: 'run_grid_build', mode: 'remote', params: { product_id: params.product_id, activeonly: 1 }, listeners: { 'startedit': function(){ var pid = Ext.getCmp(cfg.id || 'run_grid').getSelectionModel().getSelected().get('product_id'); if (bcombo.store.baseParams.product_id != pid) { bcombo.store.baseParams.product_id = pid; bcombo.store.load(); } } } }); var ecombo = new Testopia.Environment.Combo({ hiddenName: 'environment', id: 'run_grid_env', mode: 'remote', params: { product_id: params.product_id, isactive: 1 }, listeners: { 'startedit': function(){ var pid = Ext.getCmp(cfg.id || 'run_grid').getSelectionModel().getSelected().get('product_id'); if (ecombo.store.baseParams.product_id != pid) { ecombo.store.baseParams.product_id = pid; ecombo.store.load(); } } } }); var vcombo = new Testopia.Product.VersionCombo({ hiddenName: 'run_product_version', id: 'run_grid_version', mode: 'remote', params: { product_id: params.product_id }, listeners: { 'startedit': function(){ var pid = Ext.getCmp(cfg.id || 'run_grid').getSelectionModel().getSelected().get('product_id'); if (vcombo.store.baseParams.product_id != pid) { vcombo.store.baseParams.product_id = pid; vcombo.store.load(); } } } }); this.columns = [{ header: "Run ID", width: 30, dataIndex: "run_id", id: "run_id", sortable: true, renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true), hideable: false }, { header: "Summary", width: 220, dataIndex: "summary", id: "run_name", sortable: true, editor: { xtype: 'textfield', allowBlank: false } }, { header: "Manager Name", width: 150, dataIndex: "manager", id: "manager_name_col", sortable: true, hidden: true, editor: new Testopia.User.Lookup({ hiddenName: 'manager' }), renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Start Date", width: 110, dataIndex: "start_date", sortable: true, hidden: true }, { header: "Stop Date", width: 110, dataIndex: "stop_date", sortable: true, hidden: true }, { header: "Build", width: 110, dataIndex: "build", id: "build_col", sortable: true, editor: bcombo, renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Enviroment", width: 110, dataIndex: "environment", id: "environment", sortable: true, editor: ecombo, renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Status", width: 50, dataIndex: "status", id: "status", sortable: true }, { header: "Case Count", width: 30, dataIndex: "case_count", sortable: false, hidden: true }, { header: "Product Version", width: 150, dataIndex: "product_version", id: "product_version", sortable: true, hidden: true, editor: vcombo, renderer: Testopia.Util.ComboRenderer.createDelegate(this) }, { header: "Plan ID", width: 30, dataIndex: "plan_id", sortable: true, hidden: true, renderer: Testopia.Util.makeLink.createDelegate(this,['plan'],true) }, { header: "Complete", width: 110, dataIndex: "complete_pct", sortable: false, hideable: true, renderer: function(v, m, r){ var val = ''; val = val + '
'; val = val + '
'; val = val + '
'; val = val + '
'; val = val + '
'; val = val + '
'; val = val + '
' + v + '
'; val = val + '
'; val = val + '
'; val = val + '
' + v + '
'; val = val + '
'; val = val + '
'; val = val + '
'; return val; } }]; this.form = new Ext.form.BasicForm('testopia_helper_frm', {}); this.bbar = new Testopia.Util.PagingBar('run', this.store); Testopia.TestRun.Grid.superclass.constructor.call(this, { title: 'Test Runs', id: cfg.id || 'run_grid', loadMask: { msg: 'Loading Test Runs...' }, autoExpandColumn: "run_summary", autoScroll: true, stripeRows: true, plugins: [new Ext.ux.grid.RowEditor({ id:'run_row_editor', saveText: 'Update' })], sm: new Ext.grid.RowSelectionModel({ singleSelect: false, listeners: { 'rowselect': function(sm, i, r){ Ext.getCmp('new_case_to_run_button').enable(); Ext.getCmp('delete_run_list_btn').enable(); Ext.getCmp('edit_run_list_btn').enable(); }, 'rowdeselect': function(sm, i, r){ if (sm.getCount() < 1) { Ext.getCmp('new_case_to_run_button').disable(); Ext.getCmp('delete_run_list_btn').disable(); Ext.getCmp('edit_run_list_btn').disable(); } } } }), viewConfig: { forceFit: true }, tbar: [{ xtype: 'button', text: 'Add Test Cases to Selected Runs', id: 'new_case_to_run_button', disabled: true, handler: function(){ var run = Ext.getCmp(cfg.id || 'run_grid').getSelectionModel().getSelected(); Testopia.TestRun.AddCasePopup(run); } }, new Ext.Toolbar.Fill(), { xtype: 'button', id: 'save_run_list_btn', icon: 'extensions/Testopia/img/save.png', iconCls: 'img_button_16x', tooltip: 'Save this search', handler: function(b, e){ Testopia.Search.save('run', Ext.getCmp(cfg.id || 'run_grid').store.baseParams); } }, { xtype: 'button', id: 'link_run_list_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this list', handler: function(b, e){ Testopia.Search.LinkPopup(Ext.getCmp(cfg.id || 'run_grid').store.baseParams); } }, { xtype: 'button', id: 'edit_run_list_btn', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', disabled: true, tooltip: 'Edit Selected Test Run', handler: function(){ Testopia.Util.editFirstSelection(Ext.getCmp(cfg.id || 'run_grid')); } }, { xtype: 'button', id: 'add_run_list_btn', icon: 'extensions/Testopia/img/new.png', iconCls: 'img_button_16x', tooltip: 'Create a New Test Run', handler: function(){ try { if (plan) { Testopia.TestRun.NewRunPopup(plan); } } catch (err) { window.location = 'tr_new_run.cgi'; } } }, { xtype: 'button', id: 'delete_run_list_btn', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', disabled: true, tooltip: 'Delete Selected Test Runs', handler: this.deleteList.createDelegate(this) }] }); Ext.apply(this, cfg); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); Ext.getCmp('run_row_editor').on('afteredit', this.onGridEdit, this); }; Ext.extend(Testopia.TestRun.Grid, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ grid.selindex = index; if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'run-ctx-menu', enableScrolling: false, items: [{ text: "Reports", menu: { enableScrolling: false, items: [{ text: 'New Run Status Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Status Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=status&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id'); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); } }, { text: 'New Run Completion Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Completion Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=completion&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id'); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); } }, { text: 'New Run Execution Report', handler: function(){ var win = new Ext.Window({ title: 'Select a date range', id: 'run_execution_win', layout: 'fit', split: true, plain: true, shadow: false, width: 350, height: 150, items: [new Ext.FormPanel({ labelWidth: '40', bodyStyle: 'padding: 5px', items: [{ xtype: 'datefield', id: 'execution_start_date', fieldLabel: 'Start Date', name: 'chfieldfrom' }, { xtype: 'datefield', fieldLabel: 'Stop Date', id: 'execution_stop_date', emptyText: 'Now', name: 'chfieldto' }, new Testopia.User.Lookup({ id: 'exec_tester', fieldLabel: 'Tester (optional)' })] })], buttons: [{ text: 'Submit', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Execution Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=execution&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id') + '&chfieldfrom=' + Ext.getCmp('execution_start_date').getValue() + '&chfieldto=' + Ext.getCmp('execution_stop_date').getValue() + '&tester=' + Ext.getCmp('exec_tester').getValue(); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); win.close(); } }, { text: 'Cancel', handler: function(){ win.close(); } }] }); win.show(); } }, { text: 'New Priority Breakdown Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Status Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=priority&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id'); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); } }, { text: 'New Run Bug Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Bug Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=bug_grid&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id') + '&noheader=1'; Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ scripts: true, url: newPortlet.url }); } }, { text: 'Worst Offender Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Worst Offender Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_run_reports.cgi?type=worst&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id') + '&noheader=1'; Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ scripts: true, url: newPortlet.url }); } }, { text: 'Case Roll-up Report', handler: function(){ window.open('tr_list_caseruns.cgi?report_type=rollup&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id')); } }] } }, { text: 'Edit', menu: { items: [{ text: 'Manager', handler: function(){ var win = new Ext.Window({ title: 'Change Run Manager', id: 'run_manager_win', layout: 'fit', split: true, plain: true, shadow: false, listeners: {'afterlayout':function(){Ext.getCmp('manager_update').focus('',10)}}, width: 350, height: 150, items: [new Ext.FormPanel({ labelWidth: '40', bodyStyle: 'padding: 5px', items: [new Testopia.User.Lookup({ id: 'manager_update', fieldLabel: 'Run Manager' })] })], buttons: [{ text: 'Update Manager', handler: function(){ Testopia.Util.updateFromList('run', { manager: Ext.getCmp('manager_update').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'run_id') }, grid); win.close(); } }, { text: 'Cancel', handler: function(){ win.close(); } }] }); win.show(); } }, { text: 'Tags', handler: function(){ Testopia.Tags.update('run', grid); } }, { text: 'Targets', handler: function(){ var win = new Ext.Window({ title: 'Change Run Targets', id: 'run_target_win', layout: 'fit', split: true, plain: true, shadow: false, listeners: {'afterlayout':function(){Ext.getCmp('target_completion').focus('',10)}}, width: 350, height: 150, items: [new Ext.FormPanel({ bodyStyle: 'padding: 5px', items: [new Ext.form.NumberField({ maxValue: 100, minValue: 0, id: 'target_completion', allowBlank: true, fieldLabel: 'Target Completion Rate', hiddenName: 'target_completion', listeners: { 'valid': function(f){ Ext.getCmp('target_pass').maxValue = f.getValue(); } } }), new Ext.form.NumberField({ maxValue: 100, minValue: 0, allowBlank: true, id: 'target_pass', fieldLabel: 'Target Pass Rate', hiddenName: 'target_pass' })] })], buttons: [{ text: 'Update Targets', handler: function(){ Testopia.Util.updateFromList('run', { target_pass: Ext.getCmp('target_pass').getValue(), target_completion: Ext.getCmp('target_completion').getValue(), ids: Testopia.Util.getSelectedObjects(grid, 'run_id') }, grid); win.close(); } }, { text: 'Cancel', handler: function(){ win.close(); } }] }); win.show(); } }] } }, { text: 'Clone Selected Test Runs', icon: 'extensions/Testopia/img/copy.png', iconCls: 'img_button_16x', handler: function(){ Testopia.TestRun.ClonePopup(grid.getSelectionModel().getSelected().get('product_id'), Testopia.Util.getSelectedObjects(grid, 'run_id')); } }, { text: 'Delete Selected Test Runs', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', handler: this.deleteList.createDelegate(this) }, { text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }, { text: 'View Test Run in a New Window', handler: function(){ window.open('tr_show_run.cgi?run_id=' + grid.store.getAt(grid.selindex).get('run_id')); } }, { text: 'View Run\'s Test Cases in a New Window', handler: function(){ window.open('tr_list_cases.cgi?run_id=' + grid.store.getAt(grid.selindex).get('run_id')); } },{ text: 'Export Results as CSV', handler: function(){ window.location = 'tr_list_caseruns.cgi?ctype=csv&viewall=1&run_id=' + Testopia.Util.getSelectedObjects(grid, 'run_id'); } }] }); } e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } this.menu.showAt(e.getXY()); }, onGridEdit: function(e){ var ds = this.store; var myparams = e.record.data; myparams.action = 'edit'; status = myparams.status; delete myparams.status; var manager; if (!myparams.manager.match('@')){ manager = myparams.manager; delete myparams.manager; } this.form.submit({ url: "tr_process_run.cgi", params: myparams, success: function(f, a){ myparams.manager = manager; myparams.status = status; ds.commitChanges(); }, failure: function(f, a){ Testopia.Util.error(f, a); myparams.manager = manager; ds.rejectChanges(); } }); }, deleteList: function(){ var grid = this; Ext.Msg.show({ title: 'Confirm Delete?', msg: RUN_DELETE_WARNING, buttons: Ext.Msg.YESNO, animEl: 'run-delete-btn', icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { var testopia_form = new Ext.form.BasicForm('testopia_helper_frm'); testopia_form.submit({ url: 'tr_list_runs.cgi', params: { run_ids: Testopia.Util.getSelectedObjects(grid, 'run_id'), action: 'delete' }, success: function(data){ Ext.Msg.show({ msg: "Test runs deleted", buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); grid.store.reload(); }, failure: function(f, a){ Testopia.Util.error(f, a); grid.store.reload(); } }); } } }); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load(); } } }); Testopia.TestRun.NewRunForm = function(plan){ if (plan.data) { plan = plan.data; } var casegrid = new Testopia.TestCase.Grid({ plan_id: plan.plan_id, case_status: 'CONFIRMED' }, { title: 'Select From Existing Cases', region: 'center', id: 'newrun_casegrid', height: 500 }); this.casegrid = casegrid; casegrid.on('render', function(g){ for (var i = 0; i < g.getTopToolbar().items.length; i++) { g.getTopToolbar().items.items[i].destroy(); } g.getTopToolbar().add({ xtype: 'button', text: 'Select All', handler: function(){ casegrid.getSelectionModel().selectAll(); } }, '->', { xtype: 'checkbox', id: 'selectall' }, ' ', ' Include all CONFIRMED Cases in Plan ' + plan.id); }); Testopia.TestRun.NewRunForm.superclass.constructor.call(this, { url: 'tr_new_run.cgi', id: 'newrunform', baseParams: { action: 'add' }, labelAlign: 'left', frame: true, title: 'New Run', bodyStyle: 'padding:5px 5px 0', width: 1050, height: 800, layout: 'border', items: [{ region: 'north', title: 'Filter Cases', height: 168, collapsible: true, listeners: { 'render': function(p){ p.load({ url: 'tr_process_plan.cgi', params: { action: 'getfilter', plan_id: plan.plan_id }, scripts: true }); } }, autoShow: true, autoScroll: true, buttons: [{ text: 'Filter', handler: function(){ var filter = new Ext.form.BasicForm('case_filter'); var params = filter.getValues(); params.plan_id = plan.plan_id; params.status = 'CONFIRMED'; casegrid.store.baseParams = params; casegrid.store.load(); } }] }, casegrid, { region: 'south', xtype: 'form', url: 'tr_new_run.cgi', bodyStyle: 'padding: 10px', id: 'newrunsouth', height: 200, items: [{ layout: 'column', items: [{ columnWidth: 0.5, layout: 'form', items: [new Testopia.Product.VersionCombo({ fieldLabel: 'Product Version', hiddenName: 'prod_version', mode: 'local', forceSelection: true, allowBlank: false, typeAhead: true, params: { product_id: plan.product_id } }), new Testopia.User.Lookup({ id: 'new_run_manager', hiddenName: 'manager', fieldLabel: 'Run Manager', allowBlank: false }), new Ext.form.NumberField({ maxValue: 100, minValue: 0, allowBlank: true, id: 'target_completion', fieldLabel: 'Target Completion Rate', hiddenName: 'target_completion', listeners: { 'valid': function(f){ Ext.getCmp('target_pass').maxValue = f.getValue(); } } })] }, { columnWidth: 0.5, layout: 'form', items: [new Testopia.Build.Combo({ fieldLabel: 'Build', hiddenName: 'build', mode: 'local', forceSelection: false, allowBlank: false, typeAhead: true, params: { product_id: plan.product_id, activeonly: 1 }, emptyText: 'Select or type a new name' }), new Testopia.Environment.Combo({ fieldLabel: 'Environment', hiddenName: 'environment', mode: 'local', forceSelection: false, allowBlank: false, typeAhead: true, params: { product_id: plan.product_id, isactive: 1 }, emptyText: 'Select or type a new name' }), new Ext.form.NumberField({ maxValue: 100, minValue: 0, allowBlank: true, id: 'target_pass', fieldLabel: 'Target Pass Rate', hiddenName: 'target_pass' })] }] }, { xtype: 'textfield', fieldLabel: 'Summary', layout: 'fit', id: 'run_summary', name: 'summary', anchor: '100%', width: 600, allowBlank: false }, { xtype: 'hidden', name: 'plan_id', value: plan.plan_id }, { layout: 'fit', fieldLabel: 'Notes', id: 'notes', xtype: 'textarea', width: 600, height: 80 }] }], buttons: [{ text: 'Create New Case', handler: function(){ Testopia.TestCase.NewCasePopup(plan.plan_id, plan.product_id); } }, { text: 'Submit', handler: function(){ if (!Ext.getCmp('newrunsouth').getForm().isValid()) { return; } var values = { action: 'add' }; if (Ext.getCmp('selectall').getValue()) { values.getall = Ext.getCmp('selectall').getValue() ? 1 : 0; } else { values.case_ids = Testopia.Util.getSelectedObjects(casegrid, 'case_id'); } if (Ext.getCmp('build_combo').selectedIndex == -1) { values.new_build = Ext.getCmp('build_combo').getValue(); } if (Ext.getCmp('environment_combo').selectedIndex == -1) { values.new_env = Ext.getCmp('environment_combo').getValue(); } Ext.getCmp('newrunsouth').getForm().submit({ params: values, success: function(form, data){ Ext.Msg.show({ title: 'Test Run Created', msg: 'Test run ' + data.result.run_id + ' Created. Would you like to go there now?', buttons: Ext.Msg.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { window.location = 'tr_show_run.cgi?run_id=' + data.result.run_id; } } }); if (Ext.getCmp('plan_run_grid')) { Ext.getCmp('plan_run_grid').store.reload(); } }, failure: Testopia.Util.error }); } }, { text: 'Cancel', type: 'reset', id: 'nrf_cancel_btn', handler: function(){ Ext.getCmp('newrunsouth').getForm().reset(); try { Ext.getCmp('newRun-win').close(); } catch (err) { window.location = 'tr_show_product.cgi'; } } }] }); this.on('render', function(){ casegrid.store.load(); Ext.getCmp('new_run_manager').setValue(Testopia_user.login); }); }; Ext.extend(Testopia.TestRun.NewRunForm, Ext.Panel); Testopia.TestRun.NewRunPopup = function(plan){ var win = new Ext.Window({ id: 'newRun-win', closable: true, width: Ext.getBody().getViewSize().width - 150, height: Ext.getBody().getViewSize().height - 150, plain: true, shadow: false, layout: 'fit', items: [new Testopia.TestRun.NewRunForm(plan)] }); win.show(this); }; Testopia.TestRun.CloneForm = function(product_id, runs, caselist){ var pgrid = new Testopia.TestPlan.Grid({ product_id: product_id }, { id: 'run_clone_plan_grid' }); var vbox = new Testopia.Product.VersionCombo({ id: 'run_clone_version_chooser', mode: 'local', hiddenName: 'new_run_prod_version', fieldLabel: 'Product Version', params: { product_id: product_id } }); var bbox = new Testopia.Build.Combo({ fieldLabel: 'Select a Build', id: 'run_clone_build_chooser', mode: 'local', hiddenName: 'new_run_build', params: { product_id: product_id, activeonly: 1 } }); var ebox = new Testopia.Environment.Combo({ fieldLabel: 'Select an Environment', id: 'run_clone_environment_chooser', mode: 'local', hiddenName: 'new_run_env', params: { product_id: product_id, isactive: 1 } }); function doSubmit(){ var form = Ext.getCmp('run_clone_frm').getForm(); form.baseParams = {}; if (Ext.getCmp('run_copy_cases').collapsed === false){ switch(Ext.getCmp('copy_cases_radio_group').getGroupValue()){ case 'copy_filtered_cases': form.baseParams = Ext.getCmp('caserun_search').form.getValues(); break; case 'copy_selected_cases': form.baseParams.case_list = Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'); break; } } form.baseParams.action = 'clone'; form.baseParams.ids = runs; form.baseParams.new_run_build = bbox.getValue(); form.baseParams.new_run_environment = ebox.getValue(); form.baseParams.plan_ids = Testopia.Util.getSelectedObjects(pgrid, 'plan_id'); var p = form.getValues(); if (form.isValid()) { form.submit({ success: function(f, a){ var msg; if (a.result.runlist.length == 1) { msg = a.result.failures.length > 0 ? 'Test cases ' + a.result.failures.join(',') + ' were not included. They are either DISABLED or PROPOSED.
' : ''; Ext.Msg.show({ title: 'Run Copied', msg: msg + 'Run ' + a.result.runlist[0] + ' Created. Would you like to go there now?', buttons: Ext.Msg.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { window.location = 'tr_show_run.cgi?run_id=' + a.result.runlist[0]; } } }); } else { msg = a.result.failures.length > 0 ? a.result.failures.join.length + ' Test cases were not included. They are either DISABLED or PROPOSED. View List
' : ''; Ext.Msg.show({ title: 'Test Run Copied', msg: msg + a.result.runlist.length + ' Test runs Copied successfully. View List', buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); } }, failure: Testopia.Util.error }) } } Testopia.TestRun.CloneForm.superclass.constructor.call(this, { id: 'run_clone_form', border: false, width: 600, layout: 'border', items: [{ region: 'north', layout: 'fit', border: false, height: 300, items: [pgrid] }, { region: 'center', xtype: 'form', url: 'tr_list_runs.cgi', title: 'Clone Options', autoScroll: true, id: 'run_clone_frm', border: false, frame: true, bodyStyle: 'padding: 10px', labelWidth: 160, height: 350, items: [{ layout: 'table', border: false, autoScroll: true, layoutConfig: { columns: 2, width: '100%' }, items: [{ colspan: 2, layout: 'form', border: false, items: [{ id: 'run_clone_name', xtype: 'textfield', fieldLabel: 'New Run Summary', name: 'new_run_summary', width: 500 }] }, { layout: 'form', border: false, items: [vbox, bbox, ebox] }, { layout: 'form', border: false, items: [{ xtype: 'checkbox', name: 'copy_tags', checked: true, boxLabel: 'Copy Run Tags', hideLabel: true }, { xtype: 'checkbox', name: 'copy_filters', checked: true, boxLabel: 'Copy Run Filters', hideLabel: true }, { xtype: 'hidden', id: 'run_clone_product_id', name: 'product_id', value: product_id }] }, { colspan: 2, layout: 'form', border: false, items: [{ xtype: 'checkbox', name: 'keep_run_manager', checked: false, boxLabel: 'Maintain original manager (unchecking will make me the manager of the new run)', hideLabel: true }, { xtype: 'fieldset', autoHeight: true, checkboxToggle: true, checkboxName: 'copy_cases', id: 'run_copy_cases', title: 'Copy Test Cases', collapsed: caselist ? false : true, items: [{ xtype: 'radio', name: 'copy_cases_options', id: 'copy_cases_radio_group', inputValue: 'copy_all_cases', checked: true, boxLabel: 'Include all CONFIRMED cases in selected run(s)', hideLabel: true }, { xtype: 'radio', name: 'copy_cases_options', inputValue: 'copy_filtered_cases', boxLabel: 'Only include cases that match the selected filter', hideLabel: true }, { xtype: 'radio', name: 'copy_cases_options', inputValue: 'copy_selected_cases', boxLabel: 'Only include cases that are currently selected', checked: caselist ? true : false, hideLabel: true }, { xtype: 'checkbox', name: 'keep_indexes', checked: true, boxLabel: 'Copy Case Indexes', hideLabel: true }, { xtype: 'checkbox', name: 'keep_statuses', boxLabel: 'Maintain status of copied cases (unchecking will set case copies to IDLE (Not Run))', hideLabel: true }] }] }] }] }], buttons: [{ text: 'Submit', handler: doSubmit.createDelegate(this) }, { text: 'Cancel', handler: function(){ Ext.getCmp('run-clone-win').close(); } }] }); }; Ext.extend(Testopia.TestRun.CloneForm, Ext.Panel); Testopia.TestRun.ClonePopup = function(product_id, runs, caselist){ var win = new Ext.Window({ id: 'run-clone-win', closable: true, width: 800, height: 600, plain: true, shadow: false, layout: 'fit', items: [new Testopia.TestRun.CloneForm(product_id, runs, caselist)] }); var pg = Ext.getCmp('run_clone_plan_grid'); Ext.apply(pg, { title: 'Select plans to clone runs to' }); win.show(this); var pchooser = new Testopia.Product.Combo({ id: 'run_clone_win_product_chooser', mode: 'local', value: product_id }); pchooser.on('select', function(c, r, i){ pg.store.baseParams = { ctype: 'json', product_id: r.get('id') }; Ext.getCmp('run_clone_version_chooser').reset(); Ext.getCmp('run_clone_build_chooser').reset(); Ext.getCmp('run_clone_environment_chooser').reset(); Ext.getCmp('run_clone_version_chooser').store.baseParams.product_id = r.id; Ext.getCmp('run_clone_build_chooser').store.baseParams.product_id = r.id; Ext.getCmp('run_clone_environment_chooser').store.baseParams.product_id = r.id; Ext.getCmp('run_clone_version_chooser').store.load(); Ext.getCmp('run_clone_build_chooser').store.load(); Ext.getCmp('run_clone_environment_chooser').store.load(); if (r.get('id') != product_id) { Ext.getCmp('run_clone_build_chooser').allowBlank = false; Ext.getCmp('run_clone_environment_chooser').allowBlank = false; Ext.getCmp('run_clone_version_chooser').allowBlank = false; } else { Ext.getCmp('run_clone_build_chooser').allowBlank = true; Ext.getCmp('run_clone_environment_chooser').allowBlank = true; Ext.getCmp('run_clone_version_chooser').allowBlank = true; } Ext.getCmp('run_clone_product_id').setValue(r.get('id')); pg.store.load(); }); pg.getTopToolbar().removeAll(); pg.getTopToolbar().add('Product: ', pchooser); pg.getSelectionModel().un('rowselect', pg.getSelectionModel().events['rowselect'].listeners[0].fn); pg.getSelectionModel().un('rowdeselect', pg.getSelectionModel().events['rowdeselect'].listeners[0].fn); pg.store.load(); }; Testopia.TestRun.AddCaseForm = function(run){ if (run.data) { run = run.data; } var casegrid = new Testopia.TestCase.Grid({ plan_id: run.plan_id, case_status: 'CONFIRMED', exclude: run.run_id }, { title: 'Select From Existing Cases', region: 'center', id: 'newrun_casegrid', height: 500 }); casegrid.on('render', function(g){ for (var i = 0; i < g.getTopToolbar().items.length; i++) { g.getTopToolbar().items.items[i].destroy(); } g.getTopToolbar().add({ xtype: 'button', text: 'Select All', handler: function(){ casegrid.getSelectionModel().selectAll(); } }); casegrid.store.load(); }); Testopia.TestRun.AddCaseForm.superclass.constructor.call(this, { url: 'tr_new_run.cgi', id: 'add_cases_form', title: 'Add Cases to Run', bodyStyle: 'padding:5px 5px 0', width: 1050, height: 800, layout: 'border', items: [{ region: 'north', title: 'Filter Cases', height: 172, collapsible: true, listeners: { 'render': function(p){ p.load({ url: 'tr_process_plan.cgi', params: { action: 'getfilter', plan_id: run.plan_id }, scripts: true }); } }, autoShow: true, autoScroll: true, buttons: [{ text: 'Filter', handler: function(){ var filter = new Ext.form.BasicForm('case_filter'); var params = filter.getValues(); params.plan_id = run.plan_id; params.exclude = run.run_id; params.status = 'CONFIRMED'; params.limit = Ext.getCmp('case_pager').pageSize; casegrid.store.baseParams = params; casegrid.store.load(); } }] }, casegrid], buttons: [{ text: 'Add Selected Cases to Run', handler: function(){ var form = new Ext.form.BasicForm('testopia_helper_frm'); form.submit({ url: 'tr_list_cases.cgi', params: { action: 'update', addruns: run.run_id, ids: Testopia.Util.getSelectedObjects(casegrid, 'case_id') }, success: function(){ if (Ext.getCmp('add_case_to_run_win')) { Ext.getCmp('add_case_to_run_win').close(); } if (Ext.getCmp('caserun_grid')) { Ext.getCmp('caserun_grid').store.reload(); } }, failure: Testopia.Util.error }); } }] }); }; Ext.extend(Testopia.TestRun.AddCaseForm, Ext.Panel); Testopia.TestRun.AddCasePopup = function(run){ var win = new Ext.Window({ id: 'add_case_to_run_win', closable: true, width: Ext.getBody().getViewSize().width - 150, height: Ext.getBody().getViewSize().height - 150, plain: true, shadow: false, layout: 'fit', items: [new Testopia.TestRun.AddCaseForm(run)] }); win.show(this); }; Testopia.TestRun.FiltersList = function(run){ this.store = new Ext.data.JsonStore({ url: 'tr_process_run.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'getfilters', run_id: run.run_id }, root: 'filters', fields: ["name", "query"] }); var ds = this.store; this.columns = [{ header: "Name", width: 30, dataIndex: "name", sortable: true }]; Testopia.TestRun.FiltersList.superclass.constructor.call(this, { title: "Filters", id: "run_filter_grid", loadMask: { msg: "Loading Filters ..." }, autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: true, listeners: { 'rowselect': function(sm, index, r){ var name = r.get('name'); Ext.getCmp('object_panel').setActiveTab('caserun-panel'); var params = Testopia.Util.urlQueryToJSON(r.get('query')); var f = document.getElementById('caserun_filter_form'); for (var i = 0; i < f.length; i++) { if (f[i].type == 'select-multiple') { for (var k = 0; k < f[i].options.length; k++) { f[i].options[k].selected = false; } var list = params[f[i].name]; if (!list) { continue; } if (typeof list != 'object') { list = new Array(list); } for (j = 0; j < list.length; j++) { for (k = 0; k < f[i].options.length; k++) { if (f[i].options[k].value == list[j]) { f[i].options[k].selected = true; break; } } } } else { f[i].value = params[f[i].name]; } } Ext.getCmp('caserun_grid').store.baseParams = params; Ext.getCmp('caserun_grid').store.load(); } } }), viewConfig: { forceFit: true } }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.TestRun.FiltersList, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'run_filter_ctx', items: [{ text: 'Delete Saved Filter', handler: function(){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_process_run.cgi', params: { action: 'delete_filter', query_name: grid.store.getAt(index).get('name'), run_id: grid.store.baseParams.run_id }, success: function(){ Testopia.Util.notify.msg('Filter removed', 'filter removed successfully'); grid.store.reload(); }, failure: Testopia.Util.error }); } }] }); } e.stopEvent(); this.menu.showAt(e.getXY()); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load(); } } }); Testopia.BugReport = function(params){ params.type = 'bug'; this.store = new Ext.data.GroupingStore({ url: 'tr_run_reports.cgi', baseParams: params, reader: new Ext.data.JsonReader({ root: 'Result', fields: [{ name: "case_id", mapping: "case_id" }, { name: "run_id", mapping: "run_id" }, { name: "bug_id", mapping: "bug_id" }, { name: "case_status", mapping: "case_status" }, { name: "bug_status", mapping: "bug_status" }, { name: "severity", mapping: "bug_severity" }] }), remoteSort: false, sortInfo: { field: 'run_id', direction: "ASC" }, groupField: 'bug_id' }); this.store.isTreport = true; this.view = new Ext.grid.GroupingView({ forceFit: true, groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})' }); this.columns = [{ header: 'Run', dataIndex: 'run_id', sortable: true, hideable: true, groupRenderer: function(v){ return v; }, renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true) }, { header: 'Case', dataIndex: 'case_id', sortable: true, hideable: true, groupRenderer: function(v){ return v; }, renderer: Testopia.Util.makeLink.createDelegate(this,['case'],true) }, { header: 'Bug', dataIndex: 'bug_id', sortable: true, hideable: true, groupRenderer: function(v){ return v; }, renderer: Testopia.Util.makeLink.createDelegate(this,['bug'],true) }, { header: 'Bug Status', dataIndex: 'bug_status', sortable: true, hideable: true }, { header: 'Case Status', dataIndex: 'case_status', sortable: true, hideable: true }, { header: 'Severity', dataIndex: 'severity', sortable: true, hideable: true }]; Testopia.BugReport.superclass.constructor.call(this, { sm: new Ext.grid.RowSelectionModel(), layout: 'fit', height: 250, autoScroll: true }); }; Ext.extend(Testopia.BugReport, Ext.grid.GridPanel); /* * Testopia.TestRun.ProgressBar - Create a multicolored version of the Ext ProgressBar. */ Testopia.TestRun.ProgressBar = function(cfg){ Testopia.TestRun.ProgressBar.superclass.constructor.call(this, cfg); }; Ext.extend(Testopia.TestRun.ProgressBar, Ext.ProgressBar, { onRender: function(ct, position){ Ext.ProgressBar.superclass.onRender.call(this, ct, position); var tpl = new Ext.Template('
', '
', '
', '
', '
', '
', '
 
', '
', '
', '
 
', '
', '
', '
'); if (position) { this.el = tpl.insertBefore(position, { cls: this.baseCls }, true); } else { this.el = tpl.append(ct, { cls: this.baseCls }, true); } if (this.id) { this.el.dom.id = this.id; } this.progressBar = Ext.get(this.el.dom.firstChild); this.gbar = Ext.get(this.progressBar.dom.firstChild); this.rbar = Ext.get(this.gbar.dom.nextSibling); this.obar = Ext.get(this.rbar.dom.nextSibling); if (this.textEl) { //use an external text el this.textEl = Ext.get(this.textEl); delete this.textTopEl; } else { //setup our internal layered text els this.textTopEl = Ext.get(this.progressBar.dom.childNodes[3]); var textBackEl = Ext.get(this.progressBar.dom.childNodes[4]); this.textTopEl.setStyle("z-index", 99).addClass('x-hidden'); this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]); this.textEl.setWidth(this.progressBar.offsetWidth); } if (this.gvalue || this.rvalue || this.ovalue) { this.updateProgress(this.gvalue, this.rvalue, this.ovalue, this.text); } else { this.updateText(this.text); } this.setSize(this.width || 'auto', 'auto'); this.progressBar.setHeight(this.progressBar.offsetHeight); }, updateProgress: function(gvalue, rvalue, ovalue, text){ this.gvalue = gvalue || 0; this.rvalue = rvalue || 0; this.ovalue = ovalue || 0; if (text) { this.updateText(text); } var gw = Math.floor(gvalue * this.el.dom.firstChild.offsetWidth); var rw = Math.floor(rvalue * this.el.dom.firstChild.offsetWidth); var ow = Math.floor(ovalue * this.el.dom.firstChild.offsetWidth); this.gbar.setWidth(gw); this.rbar.setWidth(rw); this.obar.setWidth(ow); return this; }, setSize: function(w, h){ Ext.ProgressBar.superclass.setSize.call(this, w, h); if (this.textTopEl) { this.textEl.setSize(this.el.dom.offsetWidth, this.el.dom.offsetHeight); } return this; } }); /* * END OF FILE - /testopia/extensions/Testopia/js/run.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/build.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.Build.Store = function(params, auto){ params.action = 'list'; Testopia.Build.Store.superclass.constructor.call(this, { url: 'tr_builds.cgi', root: 'builds', listeners: { 'exception': Testopia.Util.loadError }, baseParams: params, id: 'build_id', autoLoad: auto, fields: [{ name: "build_id", mapping: "build_id" }, { name: "name", mapping: "name" }, { name: "milestone", mapping: "milestone" }, { name: "description", mapping: "description" }, { name: "product_id", mapping: "product_id" }, { name: "isactive", mapping: "isactive" }] }); }; Ext.extend(Testopia.Build.Store, Ext.data.JsonStore); /* * Testopia.Build.Combo */ Testopia.Build.Combo = function(cfg){ Testopia.Build.Combo.superclass.constructor.call(this, { id: cfg.id || 'build_combo', store: cfg.transform ? false : new Testopia.Build.Store(cfg.params, cfg.mode == 'local' ? true : false), loadingText: 'Looking up builds...', displayField: 'name', valueField: 'build_id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Builds...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.Build.Combo, Ext.form.ComboBox); Testopia.Build.Grid = function(product_id){ this.product_id = product_id; this.store = new Testopia.Build.Store({}, false); var mbox = new Testopia.Product.MilestoneCombo({ hiddenField: 'milestone', mode: 'remote', params: { product_id: product_id }, listeners: { 'startedit': function(){ var pid = Ext.getCmp('products_pane').getSelectionModel().getSelectedNode().id; if (mbox.store.baseParams.product_id != pid) { mbox.store.baseParams.product_id = pid; mbox.store.load(); } } } }); this.columns = [{ header: "Name", width: 80, sortable: true, dataIndex: 'name', editor: { xtype: 'textfield', value: 'name', allowBlank: false } }, { header: "Description", width: 120, editor: { xtype: 'textfield' }, sortable: true, dataIndex: 'description' }, { header: "Milestone", width: 120, sortable: true, dataIndex: 'milestone', editor: mbox }, { header: 'Active', dataIndex: 'isactive', trueText: 'Yes', falseText: 'No', sortable: true, xtype: 'booleancolumn', editor:{ xtype: 'checkbox', value: 'isactive' }, width: 25 }]; this.form = new Ext.form.BasicForm('testopia_helper_frm'); Testopia.Build.Grid.superclass.constructor.call(this, { title: 'Builds', id: 'build_grid', loadMask: { msg: 'Loading Builds...' }, autoExpandColumn: "build_name", autoScroll: true, plugins: [new Ext.ux.grid.RowEditor({ id:'build_row_editor', saveText: 'Update' })], sm: new Ext.grid.RowSelectionModel({ singleSelect: true }), viewConfig: { forceFit: true }, tbar: [new Ext.Toolbar.Fill(), { xtype: 'button', id: 'edit_build_btn', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', tooltip: 'Edit Selected Build', handler: function(){ Testopia.Util.editFirstSelection(Ext.getCmp('build_grid')); } }, { xtype: 'button', id: 'add_build_btn', icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', tooltip: 'Add a new Build', handler: this.newRecord }] }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); Ext.getCmp('build_row_editor').on('afteredit', this.onGridEdit, this); }; Ext.extend(Testopia.Build.Grid, Ext.grid.GridPanel, { newRecord: function(){ NewBuild = Ext.data.Record.create([{ name: 'name', type: 'string' }, { name: 'milestone' }, { name: 'description', type: 'string' }, { name: 'isactive', type: 'bool' }]); var b = new NewBuild({ name: '', milestone: Ext.getCmp('products_pane').getSelectionModel().getSelectedNode().attributes.attributes.defaultmilestone, description: '', isactive: true }); var g = Ext.getCmp('build_grid'); g.store.insert(0, b); Ext.getCmp('build_row_editor').startEditing(0); }, onContextClick: function(grid, index, e){ grid.getSelectionModel().selectRow(index); if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'build-ctx-menu', enableScrolling: false, items: [{ text: "Reports", enableScrolling: false, menu: { items: [{ text: 'New Completion Report', handler: function(){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: 'Build Completion Report', closable: true, autoScroll: true, tools: PortalTools }); newPortlet.url = 'tr_builds.cgi?action=report&product_id=' + grid.product_id + '&build_ids=' + Testopia.Util.getSelectedObjects(grid, 'id'); Testopia.Search.dashboard_urls.push(newPortlet.url); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: newPortlet.url }); } }] } }, { text: 'Add a Build', icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', handler: this.newRecord }, { text: 'Edit This Build', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', handler: function(){ Testopia.Util.editFirstSelection(grid); } }, { text: 'Refresh', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }] }); } e.stopEvent(); this.menu.showAt(e.getXY()); }, onGridEdit: function(e){ var myparams = e.record.data; var ds = this.store; myparams.product_id = this.product_id; if (myparams.build_id) { myparams.action = "edit"; } else { myparams.action = "add"; } this.form.submit({ url: "tr_builds.cgi", params: myparams, success: function(f, a){ if (a.result.build_id) { e.record.set('build_id', a.result.build_id); } ds.commitChanges(); }, failure: function(f, a){ Testopia.Util.error(f, a); ds.rejectChanges(); } }); }, onActivate: function(event){ if (!this.product_id) { Ext.Msg.alert('Error', 'Please select a product.'); Ext.getCmp('edit_build_btn').disable(); Ext.getCmp('add_build_btn').disable(); return; } else { if (!this.store.getCount()) { this.store.load({ params: { product_id: this.product_id } }); } } } }); /* * END OF FILE - /testopia/extensions/Testopia/js/build.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/category.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.Category.Store = function(params, auto){ params.action = 'list'; Testopia.Category.Store.superclass.constructor.call(this, { url: 'tr_categories.cgi', root: 'categories', listeners: { 'exception': Testopia.Util.loadError }, baseParams: params, id: 'category_id', autoLoad: auto, fields: [{ name: "category_id", mapping: "category_id" }, { name: "name", mapping: "name" }, { name: "description", mapping: "description" }] }); }; Ext.extend(Testopia.Category.Store, Ext.data.JsonStore); /* * Testopia.Category.Combo */ Testopia.Category.Combo = function(cfg){ Testopia.Category.Combo.superclass.constructor.call(this, { id: cfg.id || 'case_category_combo', store: cfg.transform ? false : new Testopia.Category.Store(cfg.params, cfg.mode == 'local' ? true : false), loadingText: 'Looking up categories...', displayField: 'name', valueField: 'category_id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.Category.Combo, Ext.form.ComboBox); Testopia.Category.Grid = function(product_id){ this.product_id = product_id; this.store = new Testopia.Category.Store({}, false); var ds = this.store; this.columns = [{ header: "Name", width: 120, sortable: true, dataIndex: 'name', editor: { xtype: 'textfield', value: 'name', allowBlank: false } }, { header: "Description", width: 120, id: 'category_desc_column', editor: { xtype: 'textfield', value: 'description' }, sortable: true, dataIndex: 'description' }]; this.form = new Ext.form.BasicForm('testopia_helper_frm', {}); Testopia.Category.Grid.superclass.constructor.call(this, { title: 'Categories', id: 'category_grid', loadMask: { msg: 'Loading Categories...' }, autoExpandColumn: "category_desc_column", autoScroll: true, plugins: [new Ext.ux.grid.RowEditor({ id:'category_row_editor', saveText: 'Update' })], enableColumnHide: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: true }), viewConfig: { forceFit: true }, tbar: [new Ext.Toolbar.Fill(), { xtype: 'button', id: 'edit_category_btn', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', tooltip: 'Edit Selected Category', handler: function(){ Testopia.Util.editFirstSelection(Ext.getCmp('category_grid')); } }, { xtype: 'button', id: 'add_category_btn', icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', tooltip: 'Add a new Category', handler: this.newRecord }, { xtype: 'button', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', tooltip: 'Delete this Category', handler: function(){ var m = Ext.getCmp('category_grid').getSelectionModel().getSelected(); if (!m) { Ext.MessageBox.alert('Message', 'Please select at least one Category to delete'); } else { Testopia.Category.remove(product_id); } } }] }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); Ext.getCmp('category_row_editor').on('afteredit', this.onGridEdit, this); }; Ext.extend(Testopia.Category.Grid, Ext.grid.GridPanel, { newRecord: function(){ NewCategory = Ext.data.Record.create([{ name: 'name', type: 'string' }, { name: 'description', type: 'string' }]); var b = new NewCategory({ name: '', description: '' }); var g = Ext.getCmp('category_grid'); g.store.insert(0, b); Ext.getCmp('category_row_editor').startEditing(0); }, onContextClick: function(grid, index, e){ grid.getSelectionModel().selectRow(index); if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'category-ctx-menu', enableScrolling: false, items: [{ text: 'Add a Category', icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', handler: this.newRecord }, { text: 'Edit This Category', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', handler: function(){ Testopia.Util.editFirstSelection(grid); } }, { text: 'Refresh', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }] }); } e.stopEvent(); this.menu.showAt(e.getXY()); }, onGridEdit: function(e){ var myparams = e.record.data; var ds = this.store; myparams.product_id = this.product_id; if (myparams.category_id) { myparams.action = "edit"; } else { myparams.action = "add"; } this.form.submit({ url: "tr_categories.cgi", params: myparams, success: function(f, a){ if (a.result.category_id) { e.record.set('category_id', a.result.category_id); } ds.commitChanges(); }, failure: function(f, a){ Testopia.Util.error(f, a); ds.rejectChanges(); } }); }, onActivate: function(event){ if (!this.product_id) { Ext.Msg.alert('Error', 'Please select a product.'); Ext.getCmp('edit_category_btn').disable(); Ext.getCmp('add_category_btn').disable(); return; } else { if (!this.store.getCount()) { this.store.load({ params: { product_id: this.product_id } }); } } } }); Testopia.Category.remove = function(){ if (!Ext.getCmp('category_grid').getSelectionModel().getSelected().get('category_id')) { Ext.getCmp('category_grid').store.reload(); return; } Ext.Msg.show({ title: 'Confirm Delete?', msg: CASE_CATEGORY_DELETE_WARNING, buttons: Ext.Msg.YESNO, animEl: 'casecategory-delete-btn', icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { var testopia_form = new Ext.form.BasicForm('testopia_helper_frm'); testopia_form.submit({ url: 'tr_categories.cgi', params: { category_id: Ext.getCmp('category_grid').getSelectionModel().getSelected().get('category_id'), action: 'delete', product_id: Ext.getCmp('category_grid').product_id }, success: function(data){ Ext.Msg.show({ msg: "Test case category deleted", buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); Ext.getCmp('category_grid').store.reload(); }, failure: Testopia.Util.error }); } } }); }; /* * END OF FILE - /testopia/extensions/Testopia/js/category.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/diff-tabs.js */ Ext.ux.TabCloseMenu = function(){ var tabs, menu, ctxItem; this.init = function(tp){ tabs = tp; tabs.on('contextmenu', onContextMenu); } function onContextMenu(ts, item, e){ if(!menu){ // create context menu on first right click menu = new Ext.menu.Menu([{ id: tabs.id + '-close', text: 'Close Tab', handler : function(){ tabs.remove(ctxItem); } },{ id: tabs.id + '-close-others', text: 'Close Other Tabs', handler : function(){ tabs.items.each(function(item){ if(item.closable && item != ctxItem){ tabs.remove(item); } }); } }]); } ctxItem = item; var items = menu.items; items.get(tabs.id + '-close').setDisabled(!item.closable); var disableOthers = true; tabs.items.each(function(){ if(this != item && this.closable){ disableOthers = false; return false; } }); items.get(tabs.id + '-close-others').setDisabled(disableOthers); menu.showAt(e.getPoint()); } }; diff_tab_panel = function(type, id, doctype){ var self = this; var doc_store = new Ext.data.JsonStore({ url: "tr_history.cgi", listeners: { 'exception': Testopia.Util.loadError }, baseParams: {action: 'getversions', type: type, id: id}, root: 'versions', fields: [ {name: 'name', mapping: 'name', name: 'id', mapping: 'id'} ] }) diff_tab_panel.superclass.constructor.call(this, { title: 'Test Panel', height: 500, resizeTabs:true, // turn on tab resizing minTabWidth: 115, tabWidth:135, enableTabScroll:true, defaults: {autoScroll:true}, plugins: new Ext.ux.TabCloseMenu(), activeTab: 0, tbar: [ new Ext.form.ComboBox({ displayField: 'name', valueField: 'id', name: 'product', id: 'product_combo', fieldLabel: "Product", store: doc_store, emptyText: 'Select a version...', width: 200 }), " Right: ", new Ext.Toolbar.Spacer(), new Ext.form.ComboBox({ }), " HTML: ", new Ext.form.Radio({ id: 'format', value: 'html', checked: true }), " Raw: ", new Ext.form.Radio({ id: 'format', value: 'raw' }), new Ext.Button({ text: 'Diff', handler: addTab }), new Ext.Toolbar.Separator(), "Show Version: ", new Ext.form.ComboBox({ }), new Ext.Button({ text: 'Show', handler: addTab }) ] }); function addTab() { self.add({ title: 'New Tab ', iconCls: 'tabs', html: 'diff_text', closable:true }).show(); } } Ext.extend(diff_tab_panel, Ext.TabPanel); /* * END OF FILE - /testopia/extensions/Testopia/js/diff-tabs.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/environment.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.Environment.Store = function(params, auto){ params.ctype = 'json'; Testopia.Environment.Store.superclass.constructor.call(this, { url: 'tr_list_environments.cgi', listeners: { 'exception': Testopia.Util.loadError }, root: 'Result', baseParams: params, totalProperty: 'totalResultsAvailable', autoLoad: auto, id: 'environment_id', fields: [{ name: "environment_id", mapping: "environment_id" }, { name: "name", mapping: "name" }, { name: "run_count", mapping: "run_count" }, { name: "isactive", mapping: "isactive" }, { name: "product", mapping: "product_name" }], remoteSort: true }); this.paramNames.sort = "order"; }; Ext.extend(Testopia.Environment.Store, Ext.data.JsonStore); /* * Testopia.Environment.Combo */ Testopia.Environment.Combo = function(cfg){ if (cfg.params) { cfg.params.viewall = 1; } Testopia.Environment.Combo.superclass.constructor.call(this, { id: cfg.id || 'environment_combo', store: cfg.transform ? false : new Testopia.Environment.Store(cfg.params, cfg.mode == 'local' ? true : false), loadingText: 'Looking up environments...', displayField: 'name', valueField: 'environment_id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Environments...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.Environment.Combo, Ext.form.ComboBox); Testopia.Environment.Grid = function(params, cfg){ this.params = params; this.product_id = params.product_id; function environmentLink(id){ return '' + id + ''; } function productLink(id){ return '' + id + ''; } this.store = new Testopia.Environment.Store(params, false); var ds = this.store; this.columns = [{ header: "ID", width: 30, dataIndex: "environment_id", sortable: true, renderer: environmentLink, hideable: false }, { header: "Environment Name", width: 110, dataIndex: "name", id: 'env_name_col', sortable: true, editor: new Ext.grid.GridEditor(new Ext.form.TextField({ allowBlank: false }), { id: 'env_name_edt' }) }, { header: "Product Name", width: 150, dataIndex: "product", sortable: true, hidden: true }, { header: "Run Count", width: 30, dataIndex: "run_count", sortable: false }, new Ext.grid.CheckColumn({ sortable: true, header: 'Active', dataIndex: 'isactive', editor: new Ext.grid.GridEditor(new Ext.form.Checkbox({ value: 'isactive' })), width: 25 })]; this.form = new Ext.form.BasicForm('testopia_helper_frm', {}); this.bbar = new Testopia.Util.PagingBar('environment', this.store); Testopia.Environment.Grid.superclass.constructor.call(this, { title: 'Environments', id: 'environment-grid', loadMask: { msg: 'Loading Environments...' }, autoExpandColumn: "env_name_col", autoScroll: true, plugins: [new Ext.ux.grid.RowEditor({ saveText: 'Update' })], sm: new Ext.grid.RowSelectionModel({ singleSelect: true, listeners: { 'rowselect': function(sm, i, r){ Ext.getCmp('delete_env_list_btn').enable(); Ext.getCmp('clone_env_list_btn').enable(); }, 'rowdeselect': function(sm, i, r){ if (sm.getCount() < 1) { Ext.getCmp('delete_env_list_btn').disable(); Ext.getCmp('clone_env_list_btn').disable(); } } } }), viewConfig: { forceFit: true }, tbar: [{ xtype: 'button', text: 'Import', handler: this.importEnv.createDelegate(this) }, new Ext.Toolbar.Fill(), { xtype: 'button', id: 'add_env_list_btn', icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', tooltip: 'Add an Environment', handler: this.createEnv.createDelegate(this, ['', 'add']) }, { xtype: 'button', id: 'clone_env_list_btn', disabled: true, icon: 'extensions/Testopia/img/copy.png', iconCls: 'img_button_16x', tooltip: 'Clone this Environment', handler: this.cloneEnv.createDelegate(this) }, { xtype: 'button', id: 'delete_env_list_btn', disabled: true, icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', tooltip: 'Delete this Environment', handler: this.deleteEnv.createDelegate(this) }] }); Ext.apply(this, cfg); this.on('rowcontextmenu', this.onContextClick, this); this.on('afteredit', this.onGridEdit, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Environment.Grid, Ext.grid.EditorGridPanel, { onContextClick: function(grid, index, e){ if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ enableScrolling: false, id: 'run-ctx-menu', items: [{ text: 'Create a new environment', handler: function(){ window.location = "tr_new_environment.cgi"; } }, { text: 'Delete Environments', handler: this.deleteEnv.createDelegate(this) }, { text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }] }); } e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } this.menu.showAt(e.getXY()); }, onGridEdit: function(e){ var myparams = { env_id: e.record.get('environment_id') }; var ds = this.store; switch (e.field) { case 'name': myparams.action = 'rename'; myparams.name = e.value; break; case 'isactive': myparams.action = 'toggle'; break; } this.form.submit({ url: "tr_environments.cgi", params: myparams, success: function(f, a){ ds.commitChanges(); }, failure: function(f, a){ Testopia.Util.error(f, a); ds.rejectChanges(); } }); }, deleteEnv: function(){ var grid = this; Ext.Msg.show({ title: 'Confirm Delete?', msg: ENVIRONMENT_DELETE_WARNING, buttons: Ext.Msg.YESNO, animEl: 'case-delete-btn', icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_environments.cgi', params: { env_id: grid.getSelectionModel().getSelected().get('environment_id'), action: 'delete' }, success: function(){ Ext.Msg.show({ msg: "Test environment deleted", buttons: Ext.Msg.OK, icon: Ext.MessageBox.INFO }); grid.store.reload(); }, failure: function(f, a){ Testopia.Util.error(f, a); grid.store.reload(); } }); } } }); }, createEnv: function(name, action, id){ var grid = this; action = action || 'add'; var win = new Ext.Window({ id: 'create-env-win', title: 'Environment XML Import', closable: true, width: 400, height: 230, plain: true, shadow: false, layout: 'fit', items: [{ xtype: 'form', url: 'tr_environments.cgi', bodyStyle: 'padding: 10px', id: 'env_create_frm', items: [{ xtype: 'field', fieldLabel: 'Name', inputType: 'text', name: 'name', value: name != '' ? 'Copy of ' + name : '', allowBlank: false }, new Testopia.Product.Combo({ mode: 'local', fieldLabel: 'Product', value: grid.product_id, hiddenName: 'product_id' }), { xtype: 'hidden', name: 'action', value: action }, { xtype: 'hidden', name: 'env_id', value: id }], buttons: [{ text: 'Create', handler: function(){ Ext.getCmp('env_create_frm').getForm().submit({ success: function(form, data){ Ext.Msg.show({ title: 'Test Environment Created', msg: 'Test environment ' + data.result.id + ' Created. Would you like to go there now?', buttons: Ext.Msg.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn){ if (btn == 'yes') { window.location = 'tr_environments.cgi?env_id=' + data.result.id; } else { grid.store.reload(); } } }); Ext.getCmp('create-env-win').close(); }, failure: Testopia.Util.error }); } }, { text: 'Cancel', handler: function(){ Ext.getCmp('create-env-win').close(); } }] }] }); win.show(this); }, cloneEnv: function(){ this.createEnv(this.getSelectionModel().getSelected().get('name'), 'clone', this.getSelectionModel().getSelected().get('environment_id')); }, importEnv: function(){ grid = this; var win = new Ext.Window({ id: 'import-env-win', title: 'Environment XML Import', closable: true, width: 400, height: 130, plain: true, shadow: false, layout: 'fit', items: [{ xtype: 'form', url: 'tr_import_environment.cgi', bodyStyle: 'padding: 10px', id: 'env_xml_import_frm', fileUpload: true, items: [{ xtype: 'field', fieldLabel: 'XML', inputType: 'file', name: 'xml', allowBlank: false }], buttons: [{ text: 'Import', handler: function(){ Ext.getCmp('env_xml_import_frm').getForm().submit(); Ext.getCmp('import-env-win').close(); grid.store.reload(); } }, { text: 'Cancel', handler: function(){ Ext.getCmp('import-env-win').close(); } }] }] }); win.show(this); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load(); } } }); /* * END OF FILE - /testopia/extensions/Testopia/js/environment.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/product.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.Product.Store = function(class_id, auto){ Testopia.Product.Store.superclass.constructor.call(this, { url: 'tr_quicksearch.cgi', root: 'products', listeners: { 'exception': Testopia.Util.loadError }, autoLoad: auto, id: 'id', baseParams: { action: 'getproducts', class_id: class_id }, fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }] }); }; Ext.extend(Testopia.Product.Store, Ext.data.JsonStore); Testopia.Product.VersionStore = function(params, auto){ params.action = 'getversions'; Testopia.Product.VersionStore.superclass.constructor.call(this, { url: 'tr_quicksearch.cgi', root: 'versions', listeners: { 'exception': Testopia.Util.loadError }, baseParams: params, autoLoad: auto, id: 'id', fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }] }); }; Ext.extend(Testopia.Product.VersionStore, Ext.data.JsonStore); Testopia.Product.MilestoneStore = function(params, auto){ params.action = 'getmilestones'; Testopia.Product.MilestoneStore.superclass.constructor.call(this, { url: 'tr_quicksearch.cgi', root: 'milestones', listeners: { 'exception': Testopia.Util.loadError }, autoLoad: auto, baseParams: params, id: 'id', fields: [{ name: 'id', mapping: 'id' }, { name: 'name', mapping: 'name' }] }); }; Ext.extend(Testopia.Product.MilestoneStore, Ext.data.JsonStore); /* * Testopia.Product.Combo */ Testopia.Product.Combo = function(cfg){ Testopia.Product.Combo.superclass.constructor.call(this, { id: cfg.id || 'product_combo', store: cfg.transform ? false : new Testopia.Product.Store(cfg.params, cfg.mode == 'local' ? true : false), loadingText: 'Looking up products...', displayField: 'name', valueField: 'id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.Product.Combo, Ext.form.ComboBox); /* * Testopia.Product.VersionCombo */ Testopia.Product.VersionCombo = function(cfg){ Testopia.Product.VersionCombo.superclass.constructor.call(this, { id: cfg.id || 'product_version_combo', store: cfg.transform ? false : new Testopia.Product.VersionStore(cfg.params, cfg.mode == 'local' ? true : false), loadingText: 'Looking up versions...', displayField: 'name', valueField: 'id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.Product.VersionCombo, Ext.form.ComboBox); /* * Testopia.Product.MilestoneCombo */ Testopia.Product.MilestoneCombo = function(cfg){ Testopia.Product.MilestoneCombo.superclass.constructor.call(this, { id: cfg.id || 'milestone_combo', store: cfg.transform ? false : new Testopia.Product.MilestoneStore(cfg.params, cfg.mode == 'local' ? true : false), loadingText: 'Looking up milestones...', displayField: 'name', valueField: 'id', typeAhead: true, triggerAction: 'all', minListWidth: 300, forceSelection: true, transform: cfg.transform, emptyText: 'Please select...' }); Ext.apply(this, cfg); this.store.on('load', function(){ if (cfg.value) { this.setValue(cfg.value); } }, this); }; Ext.extend(Testopia.Product.MilestoneCombo, Ext.form.ComboBox); /* * END OF FILE - /testopia/extensions/Testopia/js/product.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/search.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ Testopia.Search.save = function(type, params){ var loc; var ntype; if (type == 'dashboard') { ntype = 3; loc = Testopia.Search.dashboard_urls.join('::>'); } else if (type == 'custom') { loc = params; params = { report: true }; ntype = 1; } else { if (type == 'caserun') { params.current_tab = 'case_run'; } else { params.current_tab = type; } if (params.report) { loc = 'tr_' + type + '_reports.cgi?'; ntype = 1; } else { loc = 'tr_list_' + type + 's.cgi?'; ntype = 0; } loc = loc + Testopia.Util.JSONToURLQuery(params, '', ['ctype']); } var form = new Ext.form.BasicForm('testopia_helper_frm', {}); Ext.Msg.prompt('Save As', '', function(btn, text){ if (btn == 'ok') { form.submit({ url: 'tr_query.cgi', params: { action: 'save_query', query_name: text, query_part: loc, type: ntype }, success: function(){ if (Ext.getCmp('searches_grid')) { Ext.getCmp('searches_grid').store.load(); } if (Ext.getCmp('reports_grid')) { Ext.getCmp('reports_grid').store.load(); } if (Ext.getCmp('dashboard_grid')) { Ext.getCmp('dashboard_grid').store.load(); } Testopia.Util.notify.msg('Saved', 'Your search or report was saved.'); }, failure: Testopia.Util.error }); } }); }; Testopia.Search.fillInForm = function(type, params, name){ var f = document.getElementById(type + '_search_form'); for (var i=0; i < f.length; i++){ if (f[i].type == 'select-multiple'){ for (k=0; k < f[i].options.length; k++){ f[i].options[k].selected = false; } var list = params[f[i].name]; if(!list){ continue; } if (typeof list != 'object'){ list = new Array(list); } for (j=0; j < list.length; j++){ for (k=0; k < f[i].options.length; k++){ if(f[i].options[k].value == list[j]){ f[i].options[k].selected = true; break; } } } } else{ if (params[f[i].name]){ f[i].value = params[f[i].name] || ''; } } } }; Testopia.Search.DashboardPanel = function(cfg){ Testopia.Search.DashboardPanel.superclass.constructor.call(this, { title: cfg.title || 'Dashboard', layout: 'fit', closable: cfg.closable || false, id: cfg.id || 'dashboardpanel', tbar: [{ xtype: 'button', text: 'Add Custom Panel', handler: function(b, e){ Ext.Msg.prompt('Enter URL', '', function(btn, text){ if (btn == 'ok') { var url = text + '&noheader=1'; Testopia.Search.dashboard_urls.push(url); var newPortlet = new Ext.ux.Portlet({ title: 'Custom', closable: true, autoScroll: true, tools: PortalTools, url: url }); Ext.getCmp('dashboard_leftcol').add(newPortlet); Ext.getCmp('dashboard_leftcol').doLayout(); newPortlet.load({ url: url, scripts: false }); } }); } }, new Ext.Toolbar.Fill()], items: [{ xtype: 'portal', margins: '35 5 5 0', items: [{ columnWidth: 0.5, baseCls: 'x-plain', bodyStyle: 'padding:10px 10px 10px 10px', id: cfg.lc || 'dashboard_leftcol', items: [{ title: ' ', hidden: true }] }, { columnWidth: 0.5, baseCls: 'x-plain', bodyStyle: 'padding:10px 10px 10px 10px', id: cfg.rc || 'dashboard_rightcol', items: [{ title: ' ', hidden: true }] }] }] }); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Search.DashboardPanel, Ext.Panel, { onActivate: function(p){ p.doLayout(); } }); Testopia.Search.Popup = function(tab, params){ var win = new Ext.Window({ id: 'search_win', closable: true, width: Ext.getBody().getViewSize().width - 150, height: Ext.getBody().getViewSize().height - 150, plain: true, shadow: false, layout: 'fit', items: [new Testopia.Search.Panel(tab, params)] }); win.show(); }; Testopia.Search.Panel = function(tab, params){ params = params || {}; Testopia.Search.Panel.superclass.constructor.call(this,{ title: 'Create a Search', id: 'search_panel', autoScroll: true, activeTab: tab + '_search_panel', defaults: { // applied to each contained panel bodyStyle:'padding:10px', autoScroll: true }, items:[ new Testopia.Search.PlansForm(params), new Testopia.Search.CasesForm(params), new Testopia.Search.RunsForm(params), new Testopia.Search.CaseRunsForm(params) ] }); }; Ext.extend(Testopia.Search.Panel, Ext.TabPanel); Testopia.Search.PlansForm = function(params){ this.params = params; Testopia.Search.PlansForm.superclass.constructor.call(this,{ title: 'Plan Search', id: 'plan_search_panel', layout:'fit', autoLoad: { url: 'tr_query.cgi?current_tab=plan', params: params, scripts: true, text: 'Loading search form...', callback: Testopia.Search.fillInForm.createDelegate(this,['plan',this.params]) }, buttons:[{ text: 'Submit', handler: function(){ var form = new Ext.form.BasicForm('plan_search_form'); var values = form.getValues(); var searchnum = Math.round(Math.random()*100); try { // EXT BUG - Closing always causes an error: // http://extjs.com/forum/showthread.php?t=20930 Ext.getCmp('search_win').close(); } catch(err){} if (params.report){ Ext.getCmp('object_panel').add(new Ext.Panel({ id: 'plan_search' + searchnum, closable: true, title: 'Plan Report', autoScroll: true, listeners: { 'render': function(){ this.load({ url: 'tr_plan_reports.cgi', params: values }); }}, tbar:[new Ext.Toolbar.Fill(), { xtype: 'button', id: 'save_plan_report_btn', icon: 'extensions/Testopia/img/save.png', iconCls: 'img_button_16x', tooltip: 'Save this report', handler: function(b,e){ Testopia.Search.save('plan', values); } },{ xtype: 'button', id: 'link_plan_report_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this report', handler: function(b,e){ Testopia.Search.LinkPopup(values); } }] })); Ext.getCmp('object_panel').activate('plan_search' + searchnum); } else{ Ext.getCmp('object_panel').add(new Testopia.TestPlan.Grid(values,{ id: 'plan_search' + searchnum, closable: true, title: 'Plan Search' })); Ext.getCmp('object_panel').activate('plan_search' + searchnum); } } }] }); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Search.PlansForm, Ext.Panel,{ onActivate: function(event){ if (!this.rendered){ return; } if (Ext.get('case_search_form')){ Ext.get('case_search_form').remove(); } if (Ext.get('run_search_form')){ Ext.get('run_search_form').remove(); } if (Ext.get('caserun_search_form')){ Ext.get('caserun_search_form').remove(); } this.params.current_tab = 'plan'; this.load({ url: 'tr_query.cgi', params: this.params, scripts: true, text: 'Loading search form...', callback: Testopia.Search.fillInForm.createDelegate(this,['plan',this.params]) }); } }); Testopia.Search.CasesForm = function(params){ this.params = params; Testopia.Search.CasesForm.superclass.constructor.call(this,{ title: 'Case Search', id: 'case_search_panel', layout:'fit', autoLoad: { url: 'tr_query.cgi?current_tab=case', params: params, scripts: true, text: 'Loading search form...', callback: Testopia.Search.fillInForm.createDelegate(this,['case',this.params]) }, buttons:[{ text: 'Submit', handler: function(){ var form = new Ext.form.BasicForm('case_search_form'); var values = form.getValues(); var searchnum = Math.round(Math.random()*100); try { // EXT BUG - Closing always causes an error: // http://extjs.com/forum/showthread.php?t=20930 Ext.getCmp('search_win').close(); } catch(err){} if (params.report){ Ext.getCmp('object_panel').add(new Ext.Panel({ id: 'case_search' + searchnum, closable: true, title: 'Case Report', autoScroll: true, listeners: { 'render': function(){ this.load({ url: 'tr_case_reports.cgi', params: values }); }}, tbar:[new Ext.Toolbar.Fill(), { xtype: 'button', id: 'save_case_report_btn', icon: 'extensions/Testopia/img/save.png', iconCls: 'img_button_16x', tooltip: 'Save this report', handler: function(b,e){ Testopia.Search.save('case', values); } },{ xtype: 'button', id: 'link_case_report_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this report', handler: function(b,e){ Testopia.Search.LinkPopup(values); } }] })); Ext.getCmp('object_panel').activate('case_search' + searchnum); } else{ Ext.getCmp('object_panel').add(new Testopia.TestCase.Grid(values,{ id: 'case_search' + searchnum, closable: true, title: 'Case Search' })); } Ext.getCmp('object_panel').activate('case_search' + searchnum); } }] }); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Search.CasesForm, Ext.Panel,{ onActivate: function(event){ if (!this.rendered){ return; } if (Ext.get('run_search_form')){ Ext.get('run_search_form').remove(); } if (Ext.get('plan_search_form')){ Ext.get('plan_search_form').remove(); } if (Ext.get('caserun_search_form')){ Ext.get('caserun_search_form').remove(); } this.params.current_tab = 'case'; this.load({ url: 'tr_query.cgi', params: this.params, scripts: true, text: 'Loading search form...', callback: Testopia.Search.fillInForm.createDelegate(this,['case',this.params]) }); } }); Testopia.Search.RunsForm = function(params){ this.params = params; Testopia.Search.RunsForm.superclass.constructor.call(this,{ title: 'Run Search', id: 'run_search_panel', layout:'fit', autoLoad: { url: 'tr_query.cgi?current_tab=run', params: params, scripts: true, text: 'Loading search form...', callback: Testopia.Search.fillInForm.createDelegate(this,['run',this.params]) }, buttons:[{ text: 'Submit', handler: function(){ var form = new Ext.form.BasicForm('run_search_form'); var values = form.getValues(); if (params.qname) values.qname = params.qname; var searchnum = Math.round(Math.random()*100); try { // EXT BUG - Closing always causes an error: // http://extjs.com/forum/showthread.php?t=20930 Ext.getCmp('search_win').close(); } catch(err){} if (params.report){ Ext.getCmp('object_panel').add(new Ext.Panel({ id: 'run_search' + searchnum, closable: true, title: 'Run Report', autoScroll: true, listeners: { 'render': function(){ this.load({ url: 'tr_run_reports.cgi', params: values }); }}, tbar:[new Ext.Toolbar.Fill(), { xtype: 'button', id: 'save_run_report_btn', icon: 'extensions/Testopia/img/save.png', iconCls: 'img_button_16x', tooltip: 'Save this report', handler: function(b,e){ Testopia.Search.save('run', values); } },{ xtype: 'button', id: 'link_run_report_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this report', handler: function(b,e){ Testopia.Search.LinkPopup(values); } }] })); Ext.getCmp('object_panel').activate('run_search' + searchnum); } else{ Ext.getCmp('object_panel').add(new Testopia.TestRun.Grid(values,{ id: 'run_search' + searchnum, closable: true, title: 'Run Search' })); } Ext.getCmp('object_panel').activate('run_search' + searchnum); } }] }); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Search.RunsForm, Ext.Panel,{ onActivate: function(event){ if (!this.rendered){ return; } if (Ext.get('case_search_form')){ Ext.get('case_search_form').remove(); } if (Ext.get('plan_search_form')){ Ext.get('plan_search_form').remove(); } if (Ext.get('caserun_search_form')){ Ext.get('caserun_search_form').remove(); } this.params.current_tab = 'run'; this.load({ url: 'tr_query.cgi', params: this.params, scripts: true, text: 'Loading search form...', callback: Testopia.Search.fillInForm.createDelegate(this,['run',this.params]) }); } }); Testopia.Search.CaseRunsForm = function(params){ this.params = params; Testopia.Search.CaseRunsForm.superclass.constructor.call(this,{ title: 'Case-Run Search', id: 'caserun_search_panel', layout:'fit', autoLoad:{ url: 'tr_query.cgi?current_tab=case_run', params: params, scripts: true, text: 'Loading search form...', callback: Testopia.Search.fillInForm.createDelegate(this,['caserun',this.params]) }, buttons:[{ text: 'Submit', handler: function(){ var form = new Ext.form.BasicForm('caserun_search_form'); var values = form.getValues(); var searchnum = Math.round(Math.random()*100); try { // EXT BUG - Closing always causes an error: // http://extjs.com/forum/showthread.php?t=20930 Ext.getCmp('search_win').close(); } catch(err){} if (params.report){ Ext.getCmp('object_panel').add(new Ext.Panel({ id: 'case_run_search' + searchnum, closable: true, title: 'Case-Run Report', autoScroll: true, listeners: { 'render': function(){ this.load({ url: 'tr_caserun_reports.cgi', params: values }); }}, tbar:[new Ext.Toolbar.Fill(), { xtype: 'button', id: 'save_caserun_report_btn', icon: 'extensions/Testopia/img/save.png', iconCls: 'img_button_16x', tooltip: 'Save this report', handler: function(b,e){ Testopia.Search.save('caserun', values); } },{ xtype: 'button', id: 'link_plan_list_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this report', handler: function(b,e){ Testopia.Search.LinkPopup(values); } }] })); Ext.getCmp('object_panel').activate('case_run_search' + searchnum); } else{ Ext.getCmp('object_panel').add(new Testopia.TestCaseRun.List(values,{ id: 'case_run_search' + searchnum, closable: true, title: 'Case-Run Search' })); } Ext.getCmp('object_panel').activate('case_run_search' + searchnum); } }] }); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Search.CaseRunsForm, Ext.Panel,{ onActivate: function(event){ if (!this.rendered){ return; } if (Ext.get('case_search_form')){ Ext.get('case_search_form').remove(); } if (Ext.get('run_search_form')){ Ext.get('run_search_form').remove(); } if (Ext.get('plan_search_form')){ Ext.get('plan_search_form').remove(); } this.params.current_tab = 'case_run'; this.load({ url: 'tr_query.cgi', params: this.params, scripts: true, text: 'Loading search form...', callback: Testopia.Search.fillInForm.createDelegate(this,['caserun',this.params]) }); } }); Testopia.Search.SavedReportsList = function(cfg){ this.store = new Ext.data.JsonStore({ url: 'tr_query.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: {action: 'get_saved_searches', type: cfg.type}, root: 'searches', fields: ["name","query","author","type"] }); var ds = this.store; var current_col = 'dashboard_leftcol'; this.columns = [ {header: "Name", width: 30, dataindex: "name", sortable: true} ]; Testopia.Search.SavedReportsList.superclass.constructor.call(this, { id: cfg.id || "reports_grid", loadMask: {msg: "Loading ..."}, autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: true, listeners: {'rowselect': function(sm, i, r){ var name = r.get('name'); if(r.get('type') == 1){ Ext.getCmp('object_panel').setActiveTab('dashboardpanel'); var newPortlet = new Ext.ux.Portlet({ title: name, id: name, closable: true, autoScroll: true, tools: PortalTools, url: r.get('query') }); Ext.getCmp(current_col).add(newPortlet); Ext.getCmp(current_col).doLayout(); Testopia.Search.dashboard_urls.push(r.get('query')); newPortlet.load({ scripts: true, url: r.get('query') }); current_col = current_col == 'dashboard_leftcol' ? 'dashboard_rightcol' : 'dashboard_leftcol'; } else{ sm.grid.loadPanel(r); } }} }), viewConfig: { forceFit:true } }); Ext.apply(this,cfg); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Search.SavedReportsList, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ var d = grid.store.getAt(index).get('query').match(/(tr_list_|_reports)/); if (d){ var g = grid.store.getAt(index).get('query').match(/completion/); if (g) d = null; } this.menu = new Ext.menu.Menu({ id:'run-ctx-menu', enableScrolling: false, items: [{ text: 'Open in a new tab', disabled: d ? false : true, handler: function(){ var r = grid.store.getAt(index); if (r.get('type') == 0){ grid.loadPanel(r); } else{ var newTab = new Ext.Panel({ title: r.get('name'), closable: true, id: 'search' + r.get('name'), autoScroll: true }); Ext.getCmp('object_panel').add(newTab); Ext.getCmp('object_panel').activate('search' + r.get('name')); newTab.load({ url: r.get('query') }); } } },{ text: 'Edit', icon: 'extensions/Testopia/img/edit.png', iconCls: 'img_button_16x', disabled: d ? false : true, handler: function(){ var r = grid.store.getAt(index); var name = r.get('name'); var q = r.get('query'); var type; type = q.match(/tr_list_(run|case|plan|caserun)s/); if (!type) { type = q.match(/tr_(run|case|plan|caserun)_reports/); if (!type) { Ext.Msg.show({ title: "Non-editable", msg: "This Search or Report cannot be edited", icon: Ext.MessageBox.ERROR, buttons: Ext.MessageBox.OK }); return; } } type = type[1]; var params = Testopia.Util.urlQueryToJSON(r.get('query')); Testopia.Search.Popup(type, params); } },{ text: 'Delete', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', handler: function (){ var form = new Ext.form.BasicForm('testopia_helper_frm',{}); Ext.Msg.show({ msg: 'Are you sure you want to delete this search?', buttons: Ext.MessageBox.YESNO, icon: Ext.MessageBox.QUESTION, fn: function(btn, text){ if (btn == 'yes'){ var r = grid.store.getAt(index); form.submit({ url: 'tr_query.cgi', params: {action: 'delete_query', query_name: r.get('name')}, success: function(){ if (grid){ grid.store.load(); } }, failure: Testopia.Util.error }); } } }); } },{ text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }] }); e.stopEvent(); this.menu.showAt(e.getXY()); }, onActivate: function(event){ if (!this.store.getCount()){ this.store.load(); } }, loadPanel: function(r){ var cfg = { id: 'search' + r.get('name'), closable: true, title: r.get('name'), lc: 'lc_' + r.get('name'), rc: 'rc_' + r.get('name') }; if (r.get('type') == 3){ Ext.getCmp('object_panel').add(new Testopia.Search.DashboardPanel(cfg)); Ext.getCmp('object_panel').activate('search' + r.get('name')); Ext.getCmp('search' + r.get('name')).getTopToolbar().add({ xtype: 'button', id: 'link_dashboard_btn', icon: 'extensions/Testopia/img/link.png', iconCls: 'img_button_16x', tooltip: 'Create a link to this dashboard', handler: function(b,e){ var l = window.location; var pathprefix = l.pathname.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/); pathprefix = pathprefix[1]; var win = new Ext.Window({ width: 300, plain: true, shadow: false, items: [new Ext.form.TextField({ value: encodeURI(l.protocol + '//' + l.host + pathprefix + '/' + 'tr_show_product.cgi?dashboard=' + r.get('name') + '&userid=' + Testopia_user.id), width: 287 })] }); win.show(); } }); var current_col = 'lc_' + r.get('name'); var urls = r.get('query').split('::>'); var newPortlet; for (var i in urls){ if (typeof urls[i] != 'string'){ continue; } var p = Testopia.Util.urlQueryToJSON(urls[i]); var t; typeof p.qname == 'object' ? t = p.qname[0] : t = p.qname; newPortlet = new Ext.ux.Portlet({ title: t || ' ', id: 'search' + r.get('name') + i, closable: true, autoScroll: true, tools: PortalTools, url: urls[i] }); Ext.getCmp(current_col).add(newPortlet); Ext.getCmp(current_col).doLayout(); current_col = current_col == 'lc_' + r.get('name') ? 'rc_' + r.get('name') : 'lc_' + r.get('name'); newPortlet.load({ scripts: true, url: urls[i] }); } } else{ var params = Testopia.Util.urlQueryToJSON(r.get('query')); var tab = params.current_tab; switch(tab){ case 'plan': Ext.getCmp('object_panel').add(new Testopia.TestPlan.Grid(params,cfg)); break; case 'run': Ext.getCmp('object_panel').add(new Testopia.TestRun.Grid(params,cfg)); break; case 'case': Ext.getCmp('object_panel').add(new Testopia.TestCase.Grid(params,cfg)); break; default: Ext.Msg.show({ title:'No Type Found', msg: 'There must have been a problem saving this search. I can\'t find a type', buttons: Ext.Msg.OK, icon: Ext.MessageBox.ERROR }); return; } Ext.getCmp('object_panel').activate('search' + r.get('name')); } } }); PortalTools = [{ id:'gear', handler: function(e,target,panel){ var form = new Ext.form.BasicForm('testopia_helper_frm',{}); this.menu = new Ext.menu.Menu({ id: 'portal_tools_menu', items: [ { text: 'Save', handler: function(){ Ext.Msg.prompt('Save Report As', '', function(btn, text){ if (btn == 'ok'){ form.submit({ url: 'tr_query.cgi', params: {action: 'save_query', query_name: text, query_part: panel.url, type: 1}, success: function(){ Ext.getCmp('reports_grid').store.load(); panel.title = text; }, failure: Testopia.Util.error }); } }); } },{ text: 'Refresh', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ panel.load({url: panel.url}); } },{ text: 'Link to this report', handler: function(){ var path; if (panel.url.match(/^http/)){ path = panel.url; path = path.replace(/\&noheader=1/gi, ''); } else{ var l = window.location; var pathprefix = l.pathname.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/); pathprefix = pathprefix[1]; path = l.protocol + '//' + l.host + pathprefix + '/' + panel.url; path = path.replace(/\&noheader=1/gi, ''); } var win = new Ext.Window({ width: 300, plain: true, shadow: false, items: [new Ext.form.TextField({ value: path, width: 287 })] }); win.show(); } },{ text: 'Delete', handler: function(){ Ext.Msg.show({ title:'Confirm Delete?', icon: Ext.MessageBox.QUESTION, msg: 'Are you sure you want to delete this report?', buttons: Ext.Msg.YESNO, fn: function(btn, text){ if (btn == 'yes'){ form.submit({ url: 'tr_query.cgi', params: {action: 'delete_query', query_name: panel.title}, success: function(){ Ext.getCmp('reports_grid').store.load(); panel.ownerCt.remove(panel, true); }, failure: Testopia.Util.error }); } } }); } }] }); e.stopEvent(); this.menu.showAt(e.getXY()); } },{ id:'close', handler: function(e, target, panel){ panel.ownerCt.remove(panel, true); } }]; Testopia.Search.LinkPopup = function(params){ if (params.current_tab == 'case_run') { params.current_tab = 'caserun'; } var file; if (params.report) { file = 'tr_' + params.current_tab + '_reports.cgi'; } else { file = 'tr_list_' + params.current_tab + 's.cgi'; } var l = window.location; var pathprefix = l.pathname.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/); pathprefix = pathprefix[1]; var win = new Ext.Window({ width: 300, plain: true, shadow: false, items: [new Ext.form.TextField({ value: l.protocol + '//' + l.host + pathprefix + '/' + file + '?' + Testopia.Util.JSONToURLQuery(params, '', ['ctype']), width: 287 })] }); win.show(); }; /* * END OF FILE - /testopia/extensions/Testopia/js/search.js */ /* * START OF FILE - /testopia/extensions/Testopia/js/tags.js */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Bugzilla Testopia System. * * The Initial Developer of the Original Code is Greg Hendricks. * Portions created by Greg Hendricks are Copyright (C) 2006 * Novell. All Rights Reserved. * * Contributor(s): Greg Hendricks * Ryan Hamilton * Daniel Parker */ /* * Testopia.Tags.Lookup - This generates a typeahead lookup for Tagnames. * It can be used anywhere in Testopia. Extends Ext ComboBox */ Testopia.Tags.Lookup = function(cfg){ Testopia.Tags.Lookup.superclass.constructor.call(this, { id: cfg.id || 'tag_lookup', store: new Ext.data.JsonStore({ url: 'tr_quicksearch.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'gettag' }, root: 'tags', totalProperty: 'total', fields: [{ name: 'id', mapping: 'tag_id' }, { name: 'name', mapping: 'tag_name' }] }), queryParam: 'search', loadingText: 'Looking up tags...', displayField: 'name', valueField: 'id', typeAhead: false, hiddenName: 'tag', hideTrigger: true, minListWidth: 300, minChars: 2, width: 150, editable: true, forceSelection: false, emptyText: 'Type a tagname...', listeners: { 'specialkey': function(f, e){ if (e.getKey() == e.ENTER) { Ext.getCmp('tag_add_btn').fireEvent('click'); } } } }); Ext.apply(this, cfg); }; Ext.extend(Testopia.Tags.Lookup, Ext.form.ComboBox); Testopia.Tags.renderer = function(v, md, r, ri, ci, s, type, pid){ return '
' + v + '
'; }; Testopia.Tags.list = function(type, product, tag){ var cfg = { title: 'Tag Results: ' + tag, closable: true, id: tag + 'search' + product, autoScroll: true }; var search = { product_id: product, tags: tag }; var newTab if (type == 'case') { newTab = new Testopia.TestCase.Grid(search, cfg); } else if (type == 'plan') { newTab = new Testopia.TestPlan.Grid(search, cfg); } else if (type == 'run') { newTab = new Testopia.TestRun.Grid(search, cfg); } Ext.getCmp('object_panel').add(newTab); Ext.getCmp('object_panel').activate(tag + 'search' + product); }; Testopia.Tags.ObjectTags = function(obj, obj_id){ this.orig_id = obj_id; this.obj_id = obj_id; this.store = new Ext.data.JsonStore({ url: 'tr_tags.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'gettags', type: obj }, root: 'tags', id: 'tag_id', fields: [{ name: 'tag_id', mapping: 'tag_id' }, { name: 'tag_name', mapping: 'tag_name' }, { name: 'run_count', mapping: 'run_count' }, { name: 'case_count', mapping: 'case_count' }, { name: 'plan_count', mapping: 'plan_count' }] }); var ds = this.store; this.remove = function(){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_tags.cgi', params: { action: 'removetag', type: obj, id: this.obj_id, tag: Testopia.Util.getSelectedObjects(Ext.getCmp(obj + 'tagsgrid'), 'tag_name') }, success: function(){ ds.reload(); }, failure: Testopia.Util.error }); }; this.add = function(){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_tags.cgi', params: { action: 'addtag', type: obj, id: this.obj_id, tag: Ext.getCmp(obj + 'tag_lookup').getRawValue() }, success: function(){ ds.reload(); }, failure: Testopia.Util.error }); }; this.columns = [{ dataIndex: 'tag_id', hidden: true, hideable: false }, { header: 'Name', width: 150, dataIndex: 'tag_name', id: 'tag_name', sortable: true, hideable: false }, { header: 'Cases', width: 35, dataIndex: 'case_count', sortable: true, hidden: true, renderer: Testopia.Tags.renderer.createDelegate(this, ['case'], true) }, { header: 'Runs', width: 35, dataIndex: 'run_count', sortable: true, hidden: true, renderer: Testopia.Tags.renderer.createDelegate(this, ['run'], true) }, { header: 'Plans', width: 35, dataIndex: 'plan_count', sortable: true, hidden: true, renderer: Testopia.Tags.renderer.createDelegate(this, ['plan'], true) }]; var addButton = new Ext.Button({ id: 'tag_add_btn', icon: 'extensions/Testopia/img/add.png', iconCls: 'img_button_16x', handler: this.add.createDelegate(this) }); var deleteButton = new Ext.Button({ icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', handler: this.remove.createDelegate(this) }); Testopia.Tags.ObjectTags.superclass.constructor.call(this, { title: 'Tags', split: true, region: 'east', layout: 'fit', width: 200, autoExpandColumn: "tag_name", collapsible: true, id: obj + 'tagsgrid', loadMask: { msg: 'Loading ' + obj + ' tags...' }, autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: false }), viewConfig: { forceFit: true }, tbar: [new Testopia.Tags.Lookup({ id: obj + 'tag_lookup' }), addButton, deleteButton] }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Tags.ObjectTags, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'tags-ctx-menu', enableScrolling: false, items: [{ text: 'Remove Selected Tags', icon: 'extensions/Testopia/img/delete.png', iconCls: 'img_button_16x', obj_id: this.obj_id, handler: this.remove }, { text: 'Refresh List', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ grid.store.reload(); } }] }); } e.stopEvent(); if (grid.getSelectionModel().getCount() < 1) { grid.getSelectionModel().selectRow(index); } this.menu.showAt(e.getXY()); }, onActivate: function(event){ if (!this.store.getCount() || this.orig_id != this.obj_id) { this.store.load({ params: { id: this.obj_id } }); } } }); /* * Testopia.Tags.ProductTags - Display a grid of tags for a product, or a user. */ Testopia.Tags.ProductTags = function(title, type, product_id){ var tag_id; this.product_id = product_id; this.store = new Ext.data.JsonStore({ url: 'tr_tags.cgi', listeners: { 'exception': Testopia.Util.loadError }, baseParams: { action: 'gettags', type: type }, root: 'tags', id: 'tag_id', fields: [{ name: 'tag_id', mapping: 'tag_id' }, { name: 'tag_name', mapping: 'tag_name' }, { name: 'run_count', mapping: 'run_count' }, { name: 'case_count', mapping: 'case_count' }, { name: 'plan_count', mapping: 'plan_count' }] }); var ds = this.store; this.columns = [{ header: "ID", dataIndex: 'tag_id', hidden: true }, { header: 'Name', width: 150, dataIndex: 'tag_name', id: 'tag_name', sortable: true }, { header: 'Cases', width: 35, dataIndex: 'case_count', sortable: true, renderer: Testopia.Tags.renderer.createDelegate(this, ['case', product_id], true) }, { header: 'Runs', width: 35, dataIndex: 'run_count', sortable: true, renderer: Testopia.Tags.renderer.createDelegate(this, ['run', product_id], true) }, { header: 'Plans', width: 35, dataIndex: 'plan_count', sortable: true, renderer: Testopia.Tags.renderer.createDelegate(this, ['plan', product_id], true) }]; var filter = new Ext.form.TextField({ allowBlank: true, id: 'rungrid-filter', selectOnFocus: true }); Testopia.Tags.ProductTags.superclass.constructor.call(this, { title: title, id: type + 'tags', loadMask: { msg: 'Loading ' + title + ' ...' }, autoExpandColumn: "tag_name", autoScroll: true, sm: new Ext.grid.RowSelectionModel({ singleSelect: false }), viewConfig: { forceFit: true } }); this.on('rowcontextmenu', this.onContextClick, this); this.on('activate', this.onActivate, this); }; Ext.extend(Testopia.Tags.ProductTags, Ext.grid.GridPanel, { onContextClick: function(grid, index, e){ if (!this.menu) { // create context menu on first right click this.menu = new Ext.menu.Menu({ id: 'tags-ctx-menu', enableScrolling: false, items: [{ text: 'Refresh', icon: 'extensions/Testopia/img/refresh.png', iconCls: 'img_button_16x', handler: function(){ ds.reload(); } }] }); } e.stopEvent(); this.menu.showAt(e.getXY()); }, onActivate: function(event){ if (!this.store.getCount()) { this.store.load({ params: { product_id: this.product_id } }); } } }); Testopia.Tags.update = function(type, grid){ function commitTag(action, value, grid){ var form = new Ext.form.BasicForm('testopia_helper_frm', {}); form.submit({ url: 'tr_tags.cgi', params: { action: action, tag: value, type: type, id: Testopia.Util.getSelectedObjects(grid, type + '_id') }, success: function(){ }, failure: Testopia.Util.error }); } var win = new Ext.Window({ title: 'Add or Remove Tags', id: 'tags_edit_win', layout: 'fit', split: true, plain: true, shadow: false, width: 350, listeners: {'afterlayout':function(){Ext.getCmp('tags_update').focus('',10)}}, height: 150, items: [new Ext.FormPanel({ labelWidth: '40', bodyStyle: 'padding: 5px', items: [new Testopia.Tags.Lookup({ id: 'tags_update', fieldLabel: 'Tags' })] })], buttons: [{ text: 'Add Tag', handler: function(){ commitTag('addtag', Ext.getCmp('tags_update').getRawValue(), grid); win.close(); } }, { text: 'Remove Tag', handler: function(){ commitTag('removetag', Ext.getCmp('tags_update').getRawValue(), grid); win.close(); } }, { text: 'Close', handler: function(){ win.close(); } }] }); win.show(); }; /* * END OF FILE - /testopia/extensions/Testopia/js/tags.js */ /* * JavaScript file created by Rockstarapps Concatenation */