From 358b9cee87c154e7ed9b689acfc35bf58b481614 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 27 Jun 2014 15:25:40 -0700 Subject: [PATCH 001/172] Adding a module to allow organizations to track usage of Jenkins within their domain. There is a privacy concern in having this information reported, but OTOH in a corporate network this seems like a reasonable compromise, and people really often do not have any clues where they are running. --- war/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/war/pom.xml b/war/pom.xml index d4d10cd1b0..6179ef6247 100644 --- a/war/pom.xml +++ b/war/pom.xml @@ -106,6 +106,11 @@ THE SOFTWARE. 2.3 test + + org.jenkins-ci.modules + domain-discovery + 1.0 + org.jenkins-ci.modules instance-identity From dad9cb6e6defb60bcd714cb5f8e0c7fe2423e1c9 Mon Sep 17 00:00:00 2001 From: Baptiste Mathus Date: Fri, 15 Jan 2016 21:27:00 +0100 Subject: [PATCH 002/172] [JENKINS-26466] Decouple AbstractProject from DiskSpaceMonitor This modification is one of the preliminary steps to the full plugin extraction later (see JIRA above). Basically reverts a8c3a031c. --- core/src/main/java/hudson/model/AbstractProject.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java index 458d1b8f64..d807695eb4 100644 --- a/core/src/main/java/hudson/model/AbstractProject.java +++ b/core/src/main/java/hudson/model/AbstractProject.java @@ -55,7 +55,6 @@ import hudson.model.queue.CauseOfBlockage; import hudson.model.queue.QueueTaskFuture; import hudson.model.queue.SubTask; import hudson.model.queue.SubTaskContributor; -import hudson.node_monitors.DiskSpaceMonitor; import hudson.scm.ChangeLogSet; import hudson.scm.ChangeLogSet.Entry; import hudson.scm.NullSCM; @@ -1265,13 +1264,7 @@ public abstract class AbstractProject

,R extends A return true; // no SCM FilePath workspace = build.getWorkspace(); - try { - workspace.mkdirs(); - } catch (IOException e) { - // Can't create workspace dir - Is slave disk full ? - new DiskSpaceMonitor().markNodeOfflineIfDiskspaceIsTooLow(build.getBuiltOn().toComputer()); - throw e; - } + workspace.mkdirs(); boolean r = scm.checkout(build, launcher, workspace, listener, changelogFile); if (r) { From 49d9f0e1b5872b7eea4d22c8b5edd634cc28e9f6 Mon Sep 17 00:00:00 2001 From: "Ing. Pavel Janousek" Date: Mon, 11 Jan 2016 10:42:48 +0100 Subject: [PATCH 003/172] [JENKINS-32273] Refactored return error codes and messages --- core/src/main/java/hudson/cli/CLICommand.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/hudson/cli/CLICommand.java b/core/src/main/java/hudson/cli/CLICommand.java index a40a8b5bac..b5599b7c53 100644 --- a/core/src/main/java/hudson/cli/CLICommand.java +++ b/core/src/main/java/hudson/cli/CLICommand.java @@ -237,30 +237,36 @@ public abstract class CLICommand implements ExtensionPoint, Cloneable { Jenkins.getInstance().checkPermission(Jenkins.READ); return run(); } catch (CmdLineException e) { - stderr.println(e.getMessage()); + stderr.println("\nERROR: " + e.getMessage()); printUsage(stderr, p); - return -1; - } catch (AccessDeniedException e) { - stderr.println(e.getMessage()); - return -1; + return 2; + } catch (IllegalStateException e) { + stderr.println("\nERROR: " + e.getMessage()); + return 4; + } catch (IllegalArgumentException e) { + stderr.println("\nERROR: " + e.getMessage()); + return 3; } catch (AbortException e) { // signals an error without stack trace - stderr.println(e.getMessage()); - return -1; + stderr.println("\nERROR: " + e.getMessage()); + return 5; + } catch (AccessDeniedException e) { + stderr.println("\nERROR: " + e.getMessage()); + return 6; } catch (BadCredentialsException e) { // to the caller, we can't reveal whether the user didn't exist or the password didn't match. // do that to the server log instead String id = UUID.randomUUID().toString(); - LOGGER.log(Level.INFO, "CLI login attempt failed: "+id, e); - stderr.println("Bad Credentials. Search the server log for "+id+" for more details."); - return -1; + LOGGER.log(Level.INFO, "CLI login attempt failed: " + id, e); + stderr.println("\nERROR: Bad Credentials. Search the server log for " + id + " for more details."); + return 7; } catch (Exception e) { - final String errorMsg = String.format("Unexpected exception occurred while performing %s command!", + final String errorMsg = String.format("Unexpected exception occurred while performing %s command.", getName()); stderr.println(errorMsg); LOGGER.log(Level.WARNING, errorMsg, e); e.printStackTrace(stderr); - return -1; + return 1; } finally { sc.setAuthentication(old); // restore } From 71c2ad38d3c1520a790ef5d503d76a26fc92f12b Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 20 Jan 2016 22:24:17 -0800 Subject: [PATCH 004/172] [maven-release-plugin] prepare release jenkins-1.642.1 --- cli/pom.xml | 2 +- core/pom.xml | 2 +- plugins/pom.xml | 10 +++++----- pom.xml | 4 ++-- test/pom.xml | 2 +- war/pom.xml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cli/pom.xml b/cli/pom.xml index f058b424f6..51fcde1aef 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.main pom - 1.642.1-SNAPSHOT + 1.642.1 cli diff --git a/core/pom.xml b/core/pom.xml index 3f895b877b..d07b8fde49 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -29,7 +29,7 @@ THE SOFTWARE. org.jenkins-ci.main pom - 1.642.1-SNAPSHOT + 1.642.1 jenkins-core diff --git a/plugins/pom.xml b/plugins/pom.xml index 8c7e7b2de8..ae70e60b03 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -12,7 +12,7 @@ org.jenkins-ci.plugins plugin Jenkins plugin POM - 1.642.1-SNAPSHOT + 1.642.1 pom - + diff --git a/core/src/main/resources/hudson/model/Job/configure.properties b/core/src/main/resources/hudson/model/Job/configure.properties index f6f01a21a9..1eef961fb3 100644 --- a/core/src/main/resources/hudson/model/Job/configure.properties +++ b/core/src/main/resources/hudson/model/Job/configure.properties @@ -20,4 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -name={0} name \ No newline at end of file +name={0} name +Save=Save All +Apply=Apply All \ No newline at end of file diff --git a/core/src/main/resources/lib/form/apply.jelly b/core/src/main/resources/lib/form/apply.jelly index 0551d1d115..86455202ec 100644 --- a/core/src/main/resources/lib/form/apply.jelly +++ b/core/src/main/resources/lib/form/apply.jelly @@ -32,8 +32,11 @@ THE SOFTWARE. When this button is pressed, the FORM element fires the "jenkins:apply" event that allows interested parties to write back whatever states back into the INPUT elements. + + The text of the apply button. + - + \ No newline at end of file diff --git a/core/src/main/resources/lib/form/checkbox.jelly b/core/src/main/resources/lib/form/checkbox.jelly index eda309a14e..4c626aed64 100644 --- a/core/src/main/resources/lib/form/checkbox.jelly +++ b/core/src/main/resources/lib/form/checkbox.jelly @@ -63,7 +63,7 @@ THE SOFTWARE. name="${name}" value="${attrs.value}" title="${attrs.tooltip}" - onclick="${attrs.onclick}" id="${attrs.id}" class="${attrs.negative!=null ? 'negative' : null} ${attrs.checkUrl!=null?'validated':''}" + onclick="${attrs.onclick}" id="${attrs.id}" class="${attrs.class} ${attrs.negative!=null ? 'negative' : null} ${attrs.checkUrl!=null?'validated':''}" checkUrl="${attrs.checkUrl}" checkDependsOn="${attrs.checkDependsOn}" json="${attrs.json}" checked="${value ? 'true' : null}"/> diff --git a/core/src/main/resources/lib/form/optionalBlock.jelly b/core/src/main/resources/lib/form/optionalBlock.jelly index 08408527d7..13425038e3 100644 --- a/core/src/main/resources/lib/form/optionalBlock.jelly +++ b/core/src/main/resources/lib/form/optionalBlock.jelly @@ -68,7 +68,7 @@ THE SOFTWARE. - diff --git a/core/src/main/resources/lib/form/radioBlock.jelly b/core/src/main/resources/lib/form/radioBlock.jelly index 2a6135a917..197036a2cf 100644 --- a/core/src/main/resources/lib/form/radioBlock.jelly +++ b/core/src/main/resources/lib/form/radioBlock.jelly @@ -58,7 +58,7 @@ THE SOFTWARE. diff --git a/core/src/main/resources/lib/layout/css.jelly b/core/src/main/resources/lib/layout/css.jelly new file mode 100644 index 0000000000..a15d383023 --- /dev/null +++ b/core/src/main/resources/lib/layout/css.jelly @@ -0,0 +1,37 @@ + + + + + + Client-side CSS loading tag. Similar to adjunct, but driven from the client. See page-init.js. + + @since 2.0 + + CSS source path (relative to Jenkins). + + + +

+ \ No newline at end of file diff --git a/core/src/main/resources/lib/layout/js.jelly b/core/src/main/resources/lib/layout/js.jelly new file mode 100644 index 0000000000..88edf8dafd --- /dev/null +++ b/core/src/main/resources/lib/layout/js.jelly @@ -0,0 +1,37 @@ + + + + + + Client-side JavaScript loading tag. Similar to adjunct, but driven from the client. See page-init.js. + + @since 2.0 + + JavaScript source path (relative to Jenkins). + + + +
+ \ No newline at end of file diff --git a/core/src/main/resources/lib/layout/layout.jelly b/core/src/main/resources/lib/layout/layout.jelly index 2caba28563..632f576388 100644 --- a/core/src/main/resources/lib/layout/layout.jelly +++ b/core/src/main/resources/lib/layout/layout.jelly @@ -166,6 +166,8 @@ ${h.initPageVariables(context)} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
Quiet period
Number of seconds
SCM checkout retry count
+ + +
+ +
+ + +
Directory
Display Name
+ +
+ + + + + + +
#Build Triggers
+ + + + + + + + + + +
#Build
+ + + + +
+
+
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/war/src/test/js/widgets/config/tabbar-spec.js b/war/src/test/js/widgets/config/tabbar-spec.js index e3c64eac5c..73edbe4d1b 100644 --- a/war/src/test/js/widgets/config/tabbar-spec.js +++ b/war/src/test/js/widgets/config/tabbar-spec.js @@ -10,15 +10,15 @@ describe("tabbar-spec tests", function () { var jQD = require('jquery-detached'); var $ = jQD.getJQuery(); - expect($('.section-header-row', firstTableMetadata.configTable).size()).toBe(6); + expect($('.section-header-row', firstTableMetadata.configTable).size()).toBe(4); expect(firstTableMetadata.sectionCount()).toBe(4); - expect($('.tabBar .tab').size()).toBe(8); + expect($('.tabBar .tab').size()).toBe(4); expect(firstTableMetadata.sectionIds().toString()) - .toBe('config_general,config__build_triggers,config__advanced_project_options,config__workflow'); + .toBe('config_general,config__advanced_project_options,config__build_triggers,config__build'); done(); - }, 'widgets/config/workflow-config.html'); + }, 'widgets/config/freestyle-config.html'); }); it("- test section activation", function (done) { @@ -31,39 +31,45 @@ describe("tabbar-spec tests", function () { expect(firstTableMetadata.activeSectionCount()).toBe(1); firstTableMetadata.onShowSection(function() { - expect(this.id).toBe('config__workflow'); + expect(this.id).toBe('config__build'); expect(firstTableMetadata.activeSectionCount()).toBe(1); var activeSection = firstTableMetadata.activeSection(); - expect(activeSection.id).toBe('config__workflow'); - expect(activeSection.activeRowCount()).toBe(4); - expect(firstTableMetadata.getTopRows().filter('.active').size()).toBe(3); // should be the same as activeSection.activeRowCount() + expect(activeSection.id).toBe('config__build'); + expect(activeSection.activeRowCount()).toBe(2); + expect(firstTableMetadata.getTopRows().filter('.active').size()).toBe(1); // should be activeSection.activeRowCount() - 1 done(); }); // Mimic the user clicking on one of the tabs. Should make that section active, // with all of the rows in that section having an "active" class. - firstTableMetadata.activateSection('config__workflow'); + firstTableMetadata.activateSection('config__build'); // above 'firstTableMetadata.onShowSection' handler should get called now - }, 'widgets/config/workflow-config.html'); + }, 'widgets/config/freestyle-config.html'); }); - it("- test row-set activation", function (done) { + it("- test row-group modeling", function (done) { jsTest.onPage(function() { var configTabBar = jsTest.requireSrcModule('widgets/config/tabbar'); var firstTableMetadata = configTabBar.addTabsOnFirst(); var generalSection = firstTableMetadata.activeSection(); expect(generalSection.id).toBe('config_general'); - expect(generalSection.rowGroups.length).toBe(3); - expect(generalSection.getRowGroupLabels().toString()).toBe('Discard Old Builds,This build is parameterized,Execute concurrent builds if necessary,Quiet period'); - expect(generalSection.rowGroups[0].getRowCount()).toBe(6); - expect(generalSection.rowGroups[1].getRowCount()).toBe(1); + + var sectionRowGroups = generalSection.rowGroups; + + expect(sectionRowGroups.length).toBe(1); + expect(sectionRowGroups[0].getRowCount(false)).toBe(0); // zero because it does not have any non row-group rows nested immediately inside i.e. does not have any "normal" rows + expect(sectionRowGroups[0].getRowCount(true)).toBe(4); // there are some nested down in the children. see below + expect(sectionRowGroups[0].rowGroups.length).toBe(1); + expect(sectionRowGroups[0].rowGroups[0].getRowCount(false)).toBe(4); // The inner grouping has rows + expect(sectionRowGroups[0].rowGroups[0].getRowCount()).toBe(4); // Same as above ... just making sure they're direct child rows and not nested below + expect(generalSection.getRowGroupLabels().toString()).toBe('Discard Old Builds'); done(); - }, 'widgets/config/workflow-config.html'); + }, 'widgets/config/freestyle-config.html'); }); }); diff --git a/war/src/test/js/widgets/config/workflow-config.html b/war/src/test/js/widgets/config/workflow-config.html deleted file mode 100644 index ee76983409..0000000000 --- a/war/src/test/js/widgets/config/workflow-config.html +++ /dev/null @@ -1,1436 +0,0 @@ -
-
- -
-
-
General
-
Build Triggers
-
Advanced Project Options
-
Workflow
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Workflow name - - -
 Description - - -
-
- [Plain text] Preview  - - -
-
 Strategy
Help for feature: This build is parameterized
Help for feature: Quiet period
-
Loading...
-
 Quiet period
Number of seconds
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file From cdbbc8ccc578d02af8b30c674ce8683f45ca033f Mon Sep 17 00:00:00 2001 From: tfennelly Date: Wed, 17 Feb 2016 19:01:59 +0000 Subject: [PATCH 169/172] Added some finder tests --- .../js/widgets/config/model/ConfigSection.js | 36 ++++++- .../config/model/ConfigTableMetaData.js | 22 +---- war/src/main/js/widgets/jenkins-widgets.less | 7 +- .../js/widgets/config/freestyle-config.html | 3 +- war/src/test/js/widgets/config/tabbar-spec.js | 96 +++++++++++++++++++ 5 files changed, 140 insertions(+), 24 deletions(-) diff --git a/war/src/main/js/widgets/config/model/ConfigSection.js b/war/src/main/js/widgets/config/model/ConfigSection.js index 827c8678e8..295181af82 100644 --- a/war/src/main/js/widgets/config/model/ConfigSection.js +++ b/war/src/main/js/widgets/config/model/ConfigSection.js @@ -102,6 +102,29 @@ ConfigSection.prototype.markRowsAsActive = function() { this.updateRowGroupVisibility(); }; +ConfigSection.prototype.hasText = function(text) { + var $ = jQD.getJQuery(); + var selector = ":containsci('" + text + "')"; + var sectionRows = this.getRows(); + + for (var i1 = 0; i1 < sectionRows.length; i1++) { + var row = sectionRows[i1]; + var elementsWithText = $(selector, row); + + if (elementsWithText.size() > 0) { + return true; + } + } + + for (var i2 = 0; i2 < this.subSections.length; i2++) { + if (this.subSections[i2].hasText(text)) { + return true; + } + } + + return false; +}; + ConfigSection.prototype.activeRowCount = function() { var activeRowCount = 0; var rows = this.getRows(); @@ -190,8 +213,8 @@ ConfigSection.prototype.highlightText = function(text) { var selector = ":containsci('" + text + "')"; var rows = this.getRows(); - for (var i = 0; i < rows.length; i++) { - var row = rows[i]; + for (var i1 = 0; i1 < rows.length; i1++) { + var row = rows[i1]; /*jshint loopfunc: true */ $('span.highlight-split', row).each(function() { // jshint ignore:line @@ -209,11 +232,16 @@ ConfigSection.prototype.highlightText = function(text) { $this.contents().each(function () { // We specifically only mess with text nodes if (this.nodeType === 3) { - var highlightedMarkup = this.wholeText.replace(regex, '$1'); - $(this).replaceWith('' + highlightedMarkup + ''); + var $textNode = $(this); + var highlightedMarkup = $textNode.text().replace(regex, '$1'); + $textNode.replaceWith('' + highlightedMarkup + ''); } }); }); } } + + for (var i2 = 0; i2 < this.subSections.length; i2++) { + this.subSections[i2].highlightText(text); + } }; diff --git a/war/src/main/js/widgets/config/model/ConfigTableMetaData.js b/war/src/main/js/widgets/config/model/ConfigTableMetaData.js index a3940eb684..6ee7905a80 100644 --- a/war/src/main/js/widgets/config/model/ConfigTableMetaData.js +++ b/war/src/main/js/widgets/config/model/ConfigTableMetaData.js @@ -262,7 +262,7 @@ ConfigTableMetaData.prototype.showSections = function(withText) { if (withText === '') { if (this.hasSections()) { for (var i1 = 0; i1 < this.sections.length; i1++) { - this.sections[i1].activator.show(); + this.sections[i1].activator.removeClass('hidden'); } var activeSection = this.activeSection(); if (!activeSection) { @@ -273,30 +273,16 @@ ConfigTableMetaData.prototype.showSections = function(withText) { } } else { if (this.hasSections()) { - var $ = jQD.getJQuery(); - var selector = ":containsci('" + withText + "')"; var sectionsWithText = []; for (var i2 = 0; i2 < this.sections.length; i2++) { var section = this.sections[i2]; - var containsText = false; - var sectionRows = section.getRows(); - - for (var i3 = 0; i3 < sectionRows.length; i3++) { - var row = sectionRows[i3]; - var elementsWithText = $(selector, row); - if (elementsWithText.size() > 0) { - containsText = true; - break; - } - } - - if (containsText) { - section.activator.show(); + if (section.hasText(withText)) { + section.activator.removeClass('hidden'); sectionsWithText.push(section); } else { - section.activator.hide(); + section.activator.addClass('hidden'); } } diff --git a/war/src/main/js/widgets/jenkins-widgets.less b/war/src/main/js/widgets/jenkins-widgets.less index 49fc0a6bf2..c2a9e87f6b 100644 --- a/war/src/main/js/widgets/jenkins-widgets.less +++ b/war/src/main/js/widgets/jenkins-widgets.less @@ -10,4 +10,9 @@ /* * Widget styles */ -@import "config/tabbar"; \ No newline at end of file +@import "config/tabbar"; + + +.hidden { + display: none; +} \ No newline at end of file diff --git a/war/src/test/js/widgets/config/freestyle-config.html b/war/src/test/js/widgets/config/freestyle-config.html index c01cf97fd6..a236ee0f45 100644 --- a/war/src/test/js/widgets/config/freestyle-config.html +++ b/war/src/test/js/widgets/config/freestyle-config.html @@ -129,7 +129,8 @@ - + + diff --git a/war/src/test/js/widgets/config/tabbar-spec.js b/war/src/test/js/widgets/config/tabbar-spec.js index 73edbe4d1b..071dda22cc 100644 --- a/war/src/test/js/widgets/config/tabbar-spec.js +++ b/war/src/test/js/widgets/config/tabbar-spec.js @@ -71,6 +71,102 @@ describe("tabbar-spec tests", function () { done(); }, 'widgets/config/freestyle-config.html'); }); + + it("- test finder - via handler triggering", function (done) { + jsTest.onPage(function() { + var configTabBarWidget = jsTest.requireSrcModule('widgets/config/tabbar'); + var configTabBar = configTabBarWidget.addTabsOnFirst(); + var jQD = require('jquery-detached'); + + var $ = jQD.getJQuery(); + + var tabBar = $('.tabBar'); + + // All tabs should be visible... + expect($('.tab', tabBar).size()).toBe(4); + expect($('.tab.hidden', tabBar).size()).toBe(0); + + var finder = configTabBar.findInput; + expect(finder.size()).toBe(1); + + // Find sections that have the text "trigger" in them... + keydowns('trigger', finder); + + // Need to wait for the change to happen ... there's a 300ms delay. + // We could just call configTabBar.showSections(), but ... + setTimeout(function() { + expect($('.tab.hidden', tabBar).size()).toBe(3); + expect(textCleanup($('.tab.hidden', tabBar).text())).toBe('General|#Advanced Project Options|#Build'); + + var activeSection = configTabBar.activeSection(); + expect(textCleanup(activeSection.title)).toBe('#Build Triggers'); + + expect($('.highlight-split .highlight').text()).toBe('Trigger'); + + done(); + }, 600); + }, 'widgets/config/freestyle-config.html'); + }); + + it("- test finder - via showSections()", function (done) { + jsTest.onPage(function() { + var configTabBarWidget = jsTest.requireSrcModule('widgets/config/tabbar'); + var configTabBar = configTabBarWidget.addTabsOnFirst(); + var jQD = require('jquery-detached'); + + var $ = jQD.getJQuery(); + + var tabBar = $('.tabBar'); + + configTabBar.showSections('quiet period'); + expect($('.tab.hidden', tabBar).size()).toBe(3); + expect(textCleanup($('.tab.hidden', tabBar).text())).toBe('General|#Build Triggers|#Build'); + + var activeSection = configTabBar.activeSection(); + expect(textCleanup(activeSection.title)).toBe('#Advanced Project Options'); + + done(); + }, 'widgets/config/freestyle-config.html'); + }); + + it("- test finder - via showSections() - in inner row-group", function (done) { + jsTest.onPage(function() { + var configTabBarWidget = jsTest.requireSrcModule('widgets/config/tabbar'); + var configTabBar = configTabBarWidget.addTabsOnFirst(); + var jQD = require('jquery-detached'); + + var $ = jQD.getJQuery(); + + var tabBar = $('.tabBar'); + + configTabBar.showSections('Strategy'); + expect($('.tab.hidden', tabBar).size()).toBe(3); + expect(textCleanup($('.tab.hidden', tabBar).text())).toBe('#Advanced Project Options|#Build Triggers|#Build'); + + var activeSection = configTabBar.activeSection(); + expect(textCleanup(activeSection.title)).toBe('General'); + + done(); + }, 'widgets/config/freestyle-config.html'); + }); + + function keydowns(text, onInput) { + var jQD = require('jquery-detached'); + var $ = jQD.getJQuery(); + + // hmmm, for some reason, the key events do not result in the text being + // set in the input, so setting it manually. + onInput.val(text); + + // Now fire a keydown event to trigger the handler + var e = $.Event("keydown"); + e.which = 116; + onInput.trigger(e); + } + + function textCleanup(text) { + return text.trim().replace(/(\r\n|\n|\r)/gm, "").replace(/ +/g, "|"); + } }); // TODO: lots more tests !!! \ No newline at end of file From 9fe3362f012bc16076e9ea4883462612562d3466 Mon Sep 17 00:00:00 2001 From: tfennelly Date: Wed, 17 Feb 2016 19:12:07 +0000 Subject: [PATCH 170/172] Test section adoption As well as finding in sections after adoption. --- war/src/test/js/widgets/config/tabbar-spec.js | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/war/src/test/js/widgets/config/tabbar-spec.js b/war/src/test/js/widgets/config/tabbar-spec.js index 071dda22cc..46af54fa09 100644 --- a/war/src/test/js/widgets/config/tabbar-spec.js +++ b/war/src/test/js/widgets/config/tabbar-spec.js @@ -150,6 +150,39 @@ describe("tabbar-spec tests", function () { }, 'widgets/config/freestyle-config.html'); }); + it("- test adopt sections ", function (done) { + jsTest.onPage(function() { + var configTabBarWidget = jsTest.requireSrcModule('widgets/config/tabbar'); + var configTabBar = configTabBarWidget.addTabsOnFirst(); + var jQD = require('jquery-detached'); + + var $ = jQD.getJQuery(); + + var tabBar = $('.tabBar'); + + // Move the advanced stuff into the general section + var general = configTabBar.getSection('config_general'); + general.adoptSection('config__advanced_project_options'); + + // Only 3 tabs should be visible + // (used to be 4 before the merge/adopt)... + expect($('.tab', tabBar).size()).toBe(3); + expect(textCleanup($('.tab', tabBar).text())).toBe('General|#Build Triggers|#Build'); + + // And if we try to use the finder now to find something + // that was in the advanced section, it should now appear in the + // General section ... + configTabBar.showSections('quiet period'); + expect($('.tab.hidden', tabBar).size()).toBe(2); + expect(textCleanup($('.tab.hidden', tabBar).text())).toBe('#Build Triggers|#Build'); + + var activeSection = configTabBar.activeSection(); + expect(textCleanup(activeSection.title)).toBe('General'); + + done(); + }, 'widgets/config/freestyle-config.html'); + }); + function keydowns(text, onInput) { var jQD = require('jquery-detached'); var $ = jQD.getJQuery(); From 41252c27f36652ea2d0eff3130651a065966efec Mon Sep 17 00:00:00 2001 From: kzantow Date: Sat, 5 Mar 2016 19:19:07 -0500 Subject: [PATCH 171/172] Move dependency toggle out of label, so it won't affect the nearby checkbox, fix stray 'deps' element --- war/src/main/js/pluginSetupWizardGui.js | 5 +- .../js/templates/pluginSelectionPanel.hbs | 40 ++++--- war/src/main/less/pluginSetupWizard.less | 110 +++++++++--------- 3 files changed, 78 insertions(+), 77 deletions(-) diff --git a/war/src/main/js/pluginSetupWizardGui.js b/war/src/main/js/pluginSetupWizardGui.js index 5cbcb25354..c90b1dad68 100644 --- a/war/src/main/js/pluginSetupWizardGui.js +++ b/war/src/main/js/pluginSetupWizardGui.js @@ -282,6 +282,7 @@ var createPluginSetupWizard = function() { // toggles visibility of dependency listing for a plugin var toggleDependencyList = function() { var $btn = $(this); + var $toggle = $btn.parents('.deps:first'); var plugName = $btn.attr('data-plugin-name'); if(!visibleDependencies[plugName]) { visibleDependencies[plugName] = true; @@ -290,10 +291,10 @@ var createPluginSetupWizard = function() { visibleDependencies[plugName] = false; } if(!visibleDependencies[plugName]) { - $btn.removeClass('active'); + $toggle.removeClass('show'); } else { - $btn.addClass('active'); + $toggle.addClass('show'); } }; diff --git a/war/src/main/js/templates/pluginSelectionPanel.hbs b/war/src/main/js/templates/pluginSelectionPanel.hbs index d85d16629d..cdc758f4ca 100644 --- a/war/src/main/js/templates/pluginSelectionPanel.hbs +++ b/war/src/main/js/templates/pluginSelectionPanel.hbs @@ -31,30 +31,32 @@

{{@key}} {{pluginCountForCategory @key}}

{{#each this}} -
diff --git a/war/src/main/less/pluginSetupWizard.less b/war/src/main/less/pluginSetupWizard.less index 5027b30e8d..5610e697ab 100644 --- a/war/src/main/less/pluginSetupWizard.less +++ b/war/src/main/less/pluginSetupWizard.less @@ -376,62 +376,6 @@ vertical-align: middle; } - .deps { - .toggle-dependency-list { - position: absolute; - top: 2px; - right: 5px; - color: #777; - border: 0; - text-decoration: none; - padding: 4px 8px; - - .badge { - margin-left: 7px; - } - - &:hover, &.active { - text-decoration: underline; - } - - &.active { - &:after { - content: ''; - display: inline-block; - position: absolute; - top: 50%; - right: 100%; - width: 0; - height: 0; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-top: 7px solid #999; - margin: -3px -3px 0 0; - } - + .dep-list { - display: block; - } - } - } - - .dep-list { - padding: 10px 0 6px 0; - display: none; - - .badge { - padding: 4px 8px; - margin: 5px 3px 0 0; - } - } - } - - &.selected .deps { - .toggle-dependency-list { - top: 1px; - right: 4px; - } - } - + .tooltip { left: 2px !important; margin-right: 16px; @@ -449,6 +393,60 @@ } } } + + .deps { + display: block; + position: relative; + + .toggle-dependency-list { + position: absolute; + top: 0; + right: 0; + color: #777; + border: 0; + text-decoration: none; + padding: 5px 13px; + z-index: 100; + + .badge { + margin-left: 7px; + } + + &:hover, &.active { + text-decoration: underline; + } + } + + .dep-list { + padding: 10px 0 6px 0; + display: none; + + .badge { + padding: 4px 8px; + margin: 5px 3px 0 0; + } + } + + &.show { + .toggle-dependency-list:after { + content: ''; + display: inline-block; + position: absolute; + top: 50%; + right: 100%; + width: 0; + height: 0; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #999; + margin: -3px -3px 0 0; + } + + .dep-list { + display: block; + } + } + } .categories { position: relative; From 83050b618aaa41d64500c1a56a840eee2572107d Mon Sep 17 00:00:00 2001 From: kzantow Date: Tue, 8 Mar 2016 10:00:25 -0500 Subject: [PATCH 172/172] Nesting bug, modify to use better structure, don't rely on label element as plugin container --- war/src/main/js/pluginSetupWizardGui.js | 12 +- .../js/templates/pluginSelectionPanel.hbs | 6 +- war/src/main/less/pluginSetupWizard.less | 201 +++++++++--------- 3 files changed, 109 insertions(+), 110 deletions(-) diff --git a/war/src/main/js/pluginSetupWizardGui.js b/war/src/main/js/pluginSetupWizardGui.js index c90b1dad68..637c6cc5aa 100644 --- a/war/src/main/js/pluginSetupWizardGui.js +++ b/war/src/main/js/pluginSetupWizardGui.js @@ -282,7 +282,7 @@ var createPluginSetupWizard = function() { // toggles visibility of dependency listing for a plugin var toggleDependencyList = function() { var $btn = $(this); - var $toggle = $btn.parents('.deps:first'); + var $toggle = $btn.parents('.plugin:first'); var plugName = $btn.attr('data-plugin-name'); if(!visibleDependencies[plugName]) { visibleDependencies[plugName] = true; @@ -291,10 +291,10 @@ var createPluginSetupWizard = function() { visibleDependencies[plugName] = false; } if(!visibleDependencies[plugName]) { - $toggle.removeClass('show'); + $toggle.removeClass('show-dependencies'); } else { - $toggle.addClass('show'); + $toggle.addClass('show-dependencies'); } }; @@ -552,7 +552,7 @@ var createPluginSetupWizard = function() { findIndex = (findIndex+1) % matches.length; } var $el = $(matches[findIndex]); - $el = $el.parents('label:first'); // scroll to the block + $el = $el.parents('.plugin:first'); // scroll to the block if($el && $el.length > 0) { var pos = $pl.scrollTop() + $el.position().top; $pl.stop(true).animate({ @@ -571,7 +571,7 @@ var createPluginSetupWizard = function() { // search for given text, optionally scroll to the next match, set classes on appropriate elements from the search match var searchForPlugins = function(text, scroll) { var $pl = $('.plugin-list'); - var $containers = $pl.find('label'); + var $containers = $pl.find('.plugin'); // must always do this, as it's called after refreshing the panel (e.g. check/uncheck plugs) $containers.removeClass('match'); @@ -583,7 +583,7 @@ var createPluginSetupWizard = function() { } else { var matches = findElementsWithText($pl[0], text.toLowerCase(), function(d) { return d.toLowerCase(); }); - $(matches).parents('label').addClass('match'); + $(matches).parents('.plugin').addClass('match'); if(lastSearch !== text && scroll) { scrollPlugin($pl, matches, text); } diff --git a/war/src/main/js/templates/pluginSelectionPanel.hbs b/war/src/main/js/templates/pluginSelectionPanel.hbs index cdc758f4ca..11bcfcb329 100644 --- a/war/src/main/js/templates/pluginSelectionPanel.hbs +++ b/war/src/main/js/templates/pluginSelectionPanel.hbs @@ -31,13 +31,13 @@

{{@key}} {{pluginCountForCategory @key}}

{{#each this}} - +
{{#hasDependencies plugin.name}} {{/hasDependencies}} -
{{/hasDependencies}} +
{{/each}} -
{{/each}}
diff --git a/war/src/main/less/pluginSetupWizard.less b/war/src/main/less/pluginSetupWizard.less index 5610e697ab..af80db4c25 100644 --- a/war/src/main/less/pluginSetupWizard.less +++ b/war/src/main/less/pluginSetupWizard.less @@ -282,7 +282,7 @@ } &.searching-with-transition { - label { + .plugin { display: none; transition: all .25s; @@ -312,7 +312,7 @@ } &.searching { - label { + .plugin { display: none; transition: all .25s; @@ -331,119 +331,118 @@ } } } - - label { - font-weight: normal; - padding: 7px 2px 7px 27px; + + .plugin { position: relative; - display: block; - cursor: pointer; - margin: 4px -7px; - - &:hover{ - background: rgba(100, 200, 255, 0.1); - box-shadow:inset 0 400px 400px -100px rgba(100, 200, 255, 0.33), inset 0 0 0 1px rgba(100, 200, 255, 0.33); - } - - &.selected { + + &.selected label { background: #dff0d8; margin: 4px -7px; padding: 6px 0 6px 26px; border-radius: 2px; border: 1px solid #C2E0A9; color: #3c763d; - } - .title { - display: block; - font-weight: bold; - white-space: nowrap; + .dependencies { + color: #777; + } + } + + label { + font-weight: normal; + padding: 7px 2px 7px 27px; position: relative; - } - - .description { display: block; - margin-top: .5em; + cursor: pointer; + margin: 4px -7px; + + &:hover{ + background: rgba(100, 200, 255, 0.1); + box-shadow:inset 0 400px 400px -100px rgba(100, 200, 255, 0.33), inset 0 0 0 1px rgba(100, 200, 255, 0.33); + } + + .title { + display: block; + font-weight: bold; + white-space: nowrap; + position: relative; + } + + .description { + display: block; + margin-top: .5em; + } + + input[type=checkbox] { + float: left; + margin: 2px -18px; + vertical-align: middle; + } + + + .tooltip { + left: 2px !important; + margin-right: 16px; + + .tooltip-arrow { + left: 4em !important; + } + + .tooltip-inner { + max-width: none; + padding: .5em 1em; + text-align: left; + } + } } - - &.selected .dependencies { + + .toggle-dependency-list { + position: absolute; + top: 0; + right: 0; color: #777; + border: 0; + text-decoration: none; + padding: 5px 13px; + z-index: 100; + + .badge { + margin-left: 7px; + } + + &:hover, &.active { + text-decoration: underline; + } } - - input[type=checkbox] { - float: left; - margin: 2px -18px; - vertical-align: middle; + + .dep-list { + padding: 10px 0 6px 0; + display: none; + + .badge { + padding: 4px 8px; + margin: 5px 3px 0 0; + } + } + + &.show-dependencies { + .toggle-dependency-list:after { + content: ''; + display: inline-block; + position: absolute; + top: 50%; + right: 100%; + width: 0; + height: 0; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #999; + margin: -3px -3px 0 0; + } + + .dep-list { + display: block; + } } - - + .tooltip { - left: 2px !important; - margin-right: 16px; - - .tooltip-arrow { - left: 4em !important; - } - - .tooltip-inner { - max-width: none; - padding: .5em 1em; - text-align: left; - } - } - } - } - } - - .deps { - display: block; - position: relative; - - .toggle-dependency-list { - position: absolute; - top: 0; - right: 0; - color: #777; - border: 0; - text-decoration: none; - padding: 5px 13px; - z-index: 100; - - .badge { - margin-left: 7px; - } - - &:hover, &.active { - text-decoration: underline; - } - } - - .dep-list { - padding: 10px 0 6px 0; - display: none; - - .badge { - padding: 4px 8px; - margin: 5px 3px 0 0; - } - } - - &.show { - .toggle-dependency-list:after { - content: ''; - display: inline-block; - position: absolute; - top: 50%; - right: 100%; - width: 0; - height: 0; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-top: 7px solid #999; - margin: -3px -3px 0 0; - } - - .dep-list { - display: block; } } }