diff options
18 files changed, 368 insertions, 19 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index e9daf7bf788..dc4a9877d7f 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -40,6 +40,7 @@ import org.sonar.plugins.core.dashboards.DefaultDashboard; import org.sonar.plugins.core.dashboards.HotspotsDashboard; import org.sonar.plugins.core.dashboards.ReviewsDashboard; import org.sonar.plugins.core.dashboards.TimeMachineDashboard; +import org.sonar.plugins.core.reviews.JiraLinkReviewAction; import org.sonar.plugins.core.security.ApplyProjectRolesDecorator; import org.sonar.plugins.core.sensors.BranchCoverageDecorator; import org.sonar.plugins.core.sensors.CheckAlertThresholds; @@ -241,7 +242,6 @@ import java.util.List; defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_5, category = CoreProperties.CATEGORY_DIFFERENTIAL_VIEWS), - // SERVER-SIDE TECHNICAL PROPERTIES @Property( @@ -385,6 +385,9 @@ public final class CorePlugin extends SonarPlugin { extensions.add(NewItCoverageFileAnalyzer.class); extensions.add(NewCoverageAggregator.class); + // reviews + extensions.add(JiraLinkReviewAction.class); + return extensions; } } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/reviews/JiraLinkReviewAction.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/reviews/JiraLinkReviewAction.java new file mode 100644 index 00000000000..7184c6ecba8 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/reviews/JiraLinkReviewAction.java @@ -0,0 +1,31 @@ +package org.sonar.plugins.core.reviews; + +import org.sonar.api.reviews.LinkReviewAction; + +import java.util.Map; +import java.util.Map.Entry; + +/** + * @since 3.1 + */ +public class JiraLinkReviewAction implements LinkReviewAction { + + public String getId() { + return "jira-link"; + } + + public String getName() { + return "Link to JIRA"; + } + + public void execute(Map<String, String> reviewContext) { + System.out.println("============>"); + + for (Entry<String, String> mapEntry : reviewContext.entrySet()) { + System.out.println(mapEntry.getKey() + " // " + mapEntry.getValue()); + } + + System.out.println("<============"); + } + +} diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java index 113301c2f11..cf12b8a3064 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseUtils.java @@ -72,6 +72,7 @@ public final class DatabaseUtils { "resource_index", "reviews", "review_comments", + "review_data", "rules", "rules_parameters", "rules_profiles", diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java index 63e9ae79b84..053615c2761 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java @@ -32,7 +32,7 @@ import java.util.List; */ public class DatabaseVersion implements BatchComponent, ServerComponent { - public static final int LAST_VERSION = 302; + public static final int LAST_VERSION = 302; public static enum Status { UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl index 9233e1b9a57..0c331f6db42 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-derby.ddl @@ -506,6 +506,13 @@ CREATE TABLE "AUTHORS" ( "UPDATED_AT" TIMESTAMP ); +CREATE TABLE "REVIEW_DATA" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(200), + "REVIEW_ID" INTEGER, + "DATA" BLOB(2147483647) +); + -- ---------------------------------------------- -- DDL Statements for indexes @@ -605,6 +612,8 @@ CREATE INDEX "INDEX_RULE_NOTES_ON_ACTIVE_RULE_ID" ON "RULE_NOTES" ("RULE_ID"); CREATE INDEX "REVIEWS_RID" ON "REVIEWS" ("RESOURCE_ID"); +CREATE INDEX "REVIEW_DATA_REVIEW_ID" ON "REVIEW_DATA" ("REVIEW_ID"); + -- ---------------------------------------------- -- DDL Statements for keys @@ -696,3 +705,5 @@ ALTER TABLE "RULE_NOTES" ADD PRIMARY KEY ("ID"); ALTER TABLE "AUTHORS" ADD PRIMARY KEY ("ID"); ALTER TABLE "RESOURCE_INDEX" ADD PRIMARY KEY ("ID"); + +ALTER TABLE "REVIEW_DATA" ADD PRIMARY KEY ("ID"); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/reviews/LinkReviewAction.java b/sonar-plugin-api/src/main/java/org/sonar/api/reviews/LinkReviewAction.java new file mode 100644 index 00000000000..823012c157e --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/reviews/LinkReviewAction.java @@ -0,0 +1,11 @@ +package org.sonar.api.reviews; + +import com.google.common.annotations.Beta; + +/** + * @since 3.1 + */ +@Beta +public interface LinkReviewAction extends ReviewAction { + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/reviews/ReviewAction.java b/sonar-plugin-api/src/main/java/org/sonar/api/reviews/ReviewAction.java new file mode 100644 index 00000000000..d6f49ab6968 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/reviews/ReviewAction.java @@ -0,0 +1,20 @@ +package org.sonar.api.reviews; + +import com.google.common.annotations.Beta; +import org.sonar.api.ServerExtension; + +import java.util.Map; + +/** + * @since 3.1 + */ +@Beta +public interface ReviewAction extends ServerExtension { + + String getId(); + + String getName(); + + void execute(Map<String, String> reviewContext); + +} diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 52ec833c377..76cb88f4c70 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -41,7 +41,11 @@ import org.sonar.core.i18n.I18nManager; import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; -import org.sonar.core.persistence.*; +import org.sonar.core.persistence.DaoUtils; +import org.sonar.core.persistence.DatabaseMigrator; +import org.sonar.core.persistence.DatabaseVersion; +import org.sonar.core.persistence.DefaultDatabase; +import org.sonar.core.persistence.MyBatis; import org.sonar.core.qualitymodel.DefaultModelFinder; import org.sonar.core.rule.DefaultRuleFinder; import org.sonar.core.user.DefaultUserFinder; @@ -60,11 +64,29 @@ import org.sonar.server.database.EmbeddedDatabaseFactory; import org.sonar.server.filters.FilterExecutor; import org.sonar.server.notifications.NotificationService; import org.sonar.server.notifications.reviews.ReviewsNotificationManager; -import org.sonar.server.plugins.*; +import org.sonar.server.plugins.ApplicationDeployer; +import org.sonar.server.plugins.DefaultServerPluginRepository; +import org.sonar.server.plugins.PluginDeployer; +import org.sonar.server.plugins.PluginDownloader; +import org.sonar.server.plugins.ServerExtensionInstaller; +import org.sonar.server.plugins.UpdateCenterClient; +import org.sonar.server.plugins.UpdateCenterMatrixFactory; import org.sonar.server.qualitymodel.DefaultModelManager; +import org.sonar.server.reviews.ReviewActionsManager; import org.sonar.server.rules.ProfilesConsole; import org.sonar.server.rules.RulesConsole; -import org.sonar.server.startup.*; +import org.sonar.server.startup.ActivateDefaultProfiles; +import org.sonar.server.startup.DeleteDeprecatedMeasures; +import org.sonar.server.startup.EnableProfiles; +import org.sonar.server.startup.GeneratePluginIndex; +import org.sonar.server.startup.GwtPublisher; +import org.sonar.server.startup.JdbcDriverDeployer; +import org.sonar.server.startup.RegisterMetrics; +import org.sonar.server.startup.RegisterNewDashboards; +import org.sonar.server.startup.RegisterProvidedProfiles; +import org.sonar.server.startup.RegisterQualityModels; +import org.sonar.server.startup.RegisterRules; +import org.sonar.server.startup.ServerMetadataPersister; import org.sonar.server.ui.CodeColorizers; import org.sonar.server.ui.JRubyI18n; import org.sonar.server.ui.SecurityRealmFactory; @@ -218,6 +240,9 @@ public final class Platform { servicesContainer.addSingleton(DefaultNotificationManager.class); servicesContainer.addSingleton(ReviewsNotificationManager.class); + // Reviews + servicesContainer.addSingleton(ReviewActionsManager.class); + servicesContainer.startComponents(); } diff --git a/sonar-server/src/main/java/org/sonar/server/reviews/ReviewActionsManager.java b/sonar-server/src/main/java/org/sonar/server/reviews/ReviewActionsManager.java new file mode 100644 index 00000000000..6a9f547f057 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/reviews/ReviewActionsManager.java @@ -0,0 +1,54 @@ +package org.sonar.server.reviews; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.sonar.api.reviews.ReviewAction; +import org.sonar.api.utils.SonarException; + +import java.util.Collection; +import java.util.Map; + +/** + * @since 3.1 + */ +public class ReviewActionsManager { + + private Map<String, ReviewAction> idToAction = Maps.newHashMap(); + private Map<String, Collection<ReviewAction>> interfaceToAction = Maps.newHashMap(); + + public ReviewActionsManager(ReviewAction[] reviewActions) { + for (ReviewAction reviewAction : reviewActions) { + idToAction.put(reviewAction.getId(), reviewAction); + } + } + + public ReviewActionsManager() { + this(new ReviewAction[0]); + } + + public ReviewAction getAction(String actionId) { + return idToAction.get(actionId); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public Collection<ReviewAction> getActions(String interfaceName) { + Collection<ReviewAction> result = interfaceToAction.get(interfaceName); + if (result == null) { + result = Lists.newArrayList(); + interfaceToAction.put(interfaceName, result); + try { + Class interfaceClass = Class.forName(interfaceName); + for (ReviewAction reviewAction : idToAction.values()) { + if (interfaceClass.isAssignableFrom(reviewAction.getClass())) { + result.add(reviewAction); + } + } + } catch (ClassNotFoundException e) { + throw new SonarException("The following interface for review actions does not exist: " + interfaceName); + } + + } + return result; + } + +} diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index a7b5b34efbd..5e726fbc4f3 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -33,10 +33,15 @@ import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.resources.Language; import org.sonar.api.resources.ResourceType; import org.sonar.api.resources.ResourceTypes; +import org.sonar.api.reviews.ReviewAction; import org.sonar.api.rules.RulePriority; import org.sonar.api.rules.RuleRepository; import org.sonar.api.utils.ValidationMessages; -import org.sonar.api.web.*; +import org.sonar.api.web.Footer; +import org.sonar.api.web.NavigationSection; +import org.sonar.api.web.Page; +import org.sonar.api.web.RubyRailsWebservice; +import org.sonar.api.web.Widget; import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.persistence.Database; import org.sonar.core.persistence.DatabaseMigrator; @@ -52,12 +57,18 @@ import org.sonar.server.notifications.reviews.ReviewsNotificationManager; import org.sonar.server.platform.GlobalSettingsUpdater; import org.sonar.server.platform.Platform; import org.sonar.server.platform.ServerIdGenerator; -import org.sonar.server.plugins.*; +import org.sonar.server.plugins.DefaultServerPluginRepository; +import org.sonar.server.plugins.PluginDeployer; +import org.sonar.server.plugins.PluginDownloader; +import org.sonar.server.plugins.UpdateCenterMatrix; +import org.sonar.server.plugins.UpdateCenterMatrixFactory; +import org.sonar.server.reviews.ReviewActionsManager; import org.sonar.server.rules.ProfilesConsole; import org.sonar.server.rules.RulesConsole; import org.sonar.updatecenter.common.Version; import javax.annotation.Nullable; + import java.net.InetAddress; import java.sql.Connection; import java.util.Collection; @@ -167,7 +178,6 @@ public final class JRubyFacade { return getContainer().getComponentByType(PluginRepository.class).getMetadata(); } - // SYNTAX HIGHLIGHTING ------------------------------------------------------ public String colorizeCode(String code, String language) { @@ -184,7 +194,6 @@ public final class JRubyFacade { return Markdown.convertToHtml(input); } - public List<ViewProxy<Widget>> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage, Object[] availableMeasures) { return getContainer().getComponentByType(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage, (String[]) availableMeasures); } @@ -466,4 +475,15 @@ public final class JRubyFacade { public ComponentContainer getContainer() { return Platform.getInstance().getContainer(); } + + // REVIEWS ------------------------------------------------------------------ + + public Collection<ReviewAction> getReviewActions(String interfaceName) { + return getContainer().getComponentByType(ReviewActionsManager.class).getActions(interfaceName); + } + + public ReviewAction getReviewAction(String actionId) { + return getContainer().getComponentByType(ReviewActionsManager.class).getAction(actionId); + } + } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb index 2342c9eb750..928c04ae9ec 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/reviews_controller.rb @@ -138,6 +138,9 @@ class ReviewsController < ApplicationController if !params[:comment_id].blank? && @violation.review @comment = @violation.review.comments.find(params[:comment_id]) end + unless params[:review_action_id].blank? + @review_action = Review.getAction(params[:review_action_id]) + end render :partial => 'reviews/violation_comment_form' end @@ -157,11 +160,11 @@ class ReviewsController < ApplicationController :user => current_user) end - unless params[:text].blank? + if !params[:text].blank? || !params[:review_action_id].blank? if params[:comment_id] violation.review.edit_comment(current_user, params[:comment_id].to_i, params[:text]) else - violation.review.create_comment(:user => current_user, :text => params[:text]) + violation.review.create_comment({:user => current_user, :text => params[:text]}, params[:review_action_id]) end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb index 7ee6e2281b7..bede6e6c2ba 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb @@ -24,6 +24,7 @@ class Review < ActiveRecord::Base belongs_to :project, :class_name => "Project", :foreign_key => "project_id" belongs_to :rule has_many :review_comments, :order => "created_at", :dependent => :destroy + has_many :review_data, :class_name => 'ReviewData', :dependent => :destroy alias_attribute :comments, :review_comments has_and_belongs_to_many :action_plans @@ -71,12 +72,25 @@ class Review < ActiveRecord::Base # # - # params are mandatory: + # params of 'comment_values' are mandatory: # - :user # - :text - def create_comment(options={}) - comment = comments.create!(options) + # + # param review_action_id is optional (=> specifies an action to + # trigger instead of creating a simple comment) + def create_comment(comment_values={}, review_action_id=nil) + if review_action_id + action = Review.getAction(review_action_id) + if action + action.execute({"review.id" => id.to_s, "user.login" => comment_values[:user].login, "comment.text" => comment_values[:text]}) + end + else + # simple comment + comment = comments.create!(comment_values) + end touch + comments.reload + comment = comments.last notification_manager.notifyChanged(id.to_i, comment.user.login.to_java, to_java_map, to_java_map("comment" => comment.text)) end @@ -250,6 +264,25 @@ class Review < ActiveRecord::Base action_plans[0] end + def self.available_link_actions(current_review=nil) + link_actions = Java::OrgSonarServerUi::JRubyFacade.getInstance().getReviewActions("org.sonar.api.reviews.LinkReviewAction") + if current_review + link_actions.select do |action| + data_found = false + current_review.review_data.each do |data| + data_found = true if data.key==action.getId() + end + !data_found + end + else + link_actions + end + end + + def self.getAction(actionId) + Java::OrgSonarServerUi::JRubyFacade.getInstance().getReviewAction(actionId) + end + # # # SEARCH METHODS diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/review_data.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/review_data.rb new file mode 100644 index 00000000000..c87e2da1aed --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/review_data.rb @@ -0,0 +1,26 @@ +# +# Sonar, entreprise quality control tool. +# Copyright (C) 2008-2012 SonarSource +# mailto:contact AT sonarsource DOT com +# +# Sonar is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# Sonar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with Sonar; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 +# +class ReviewData < ActiveRecord::Base + set_table_name :review_data + + belongs_to :review + alias_attribute :key, :kee + +end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb index df816fa995e..0463ec16202 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_violation.html.erb @@ -129,6 +129,11 @@ <% unless violation.review && violation.review.resolved? %> <li><%= link_to_function message('reviews.change_severity'), "sCSF(#{violation.id})", :name => 'bChangeSeverity' -%></li> <li><%= link_to_function message('reviews.link_to_action_plan'), "sAPF(#{violation.id})", :name => 'bLinkActionPlan' -%></li> + + <% Review.available_link_actions(violation.review).each do |action| %> + <li><%= link_to_function action.getName(), "sCF(#{violation.id}, '#{action.getId()}')", :name => 'bComment' -%></li> + <% end %> + <% end %> </ul> </div> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb index 51ac1848fba..8c6c899a03c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/reviews/_violation_comment_form.html.erb @@ -1,5 +1,9 @@ <% - button_label=(@comment ? message('reviews.update_comment_submit') : message('reviews.comment_submit')) + if @review_action + button_label = @review_action.getName() + else + button_label=(@comment ? message('reviews.update_comment_submit') : message('reviews.comment_submit')) + end %> <form method="POST" onsubmit="new Ajax.Updater('vId<%= params[:id] -%>', '<%= url_for :action => 'violation_save_comment' -%>', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)});return false;"> @@ -7,11 +11,18 @@ <% if @comment %> <input type="hidden" name="comment_id" value="<%= @comment.id -%>"/> <% end %> + <% if @review_action %> + <input type="hidden" name="review_action_id" value="<%= @review_action.getId() -%>"/> + <% end %> <table class="width100"> <tr> <td style="vertical-align:top"> - <textarea id="commentText<%= params[:id] -%>" rows="4" name="text" style="width: 100%" onkeyup="if (this.value=='') $('submit_btn<%= params[:id] -%>').disabled='true'; else $('submit_btn<%= params[:id] -%>').disabled='';"><%= @comment.text if @comment -%></textarea> + <textarea id="commentText<%= params[:id] -%>" + <% unless @review_action -%> + onkeyup="if (this.value=='') $('submit_btn<%= params[:id] -%>').disabled='true'; else $('submit_btn<%= params[:id] -%>').disabled='';" + <% end %> + rows="4" name="text" style="width: 100%"><%= @comment.text if @comment -%></textarea> </td> <td class="sep"></td> <td style="vertical-align:top;width: 90px"> @@ -25,7 +36,7 @@ <%= submit_to_remote "submit_btn"+params[:id], button_label, :url => {:action => 'violation_save_comment'}, - :html => {:id => "submit_btn"+params[:id], :disabled => "true"}, + :html => {:id => "submit_btn"+params[:id]}.merge(@review_action ? {} : {:disabled => "true"}), :update => 'vId'+params[:id] -%> <%= link_to_function message('cancel'), "cancelViolationAction(#{params[:id]})" -%> diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/301_add_review_data.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/301_add_review_data.rb new file mode 100644 index 00000000000..e38e1981081 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/301_add_review_data.rb @@ -0,0 +1,31 @@ +# +# Sonar, open source software quality management tool. +# Copyright (C) 2008-2012 SonarSource +# mailto:contact AT sonarsource DOT com +# +# Sonar is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# Sonar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with Sonar; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 +# +class AddReviewData < ActiveRecord::Migration + + def self.up + create_table :review_data do |t| + t.column 'kee', :string, :null => true, :limit => 200 + t.column :review_id, :integer, :null => true + t.column :data, :binary, :null => true + end + add_index :review_data, :review_id, :name => 'review_data_review_id' + end + +end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/javascripts/resource.js b/sonar-server/src/main/webapp/javascripts/resource.js index 1223897743a..7b64d3a74a3 100644 --- a/sonar-server/src/main/webapp/javascripts/resource.js +++ b/sonar-server/src/main/webapp/javascripts/resource.js @@ -40,10 +40,11 @@ function hideMoreViolationActions(violation_id) { } // show the form to comment violation -function sCF(violation_id) { +function sCF(violation_id, review_action_id) { hideMoreViolationActions(violation_id); new Ajax.Updater('reviewForm' + violation_id, - baseUrl + '/reviews/violation_comment_form/' + violation_id, + baseUrl + '/reviews/violation_comment_form/' + violation_id + + (review_action_id==null ? "" : "?review_action_id=" + review_action_id), { asynchronous:true, evalScripts:true, diff --git a/sonar-server/src/test/java/org/sonar/server/reviews/ReviewActionsManagerTest.java b/sonar-server/src/test/java/org/sonar/server/reviews/ReviewActionsManagerTest.java new file mode 100644 index 00000000000..3d71fb549d6 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/reviews/ReviewActionsManagerTest.java @@ -0,0 +1,63 @@ +package org.sonar.server.reviews; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.reviews.LinkReviewAction; +import org.sonar.api.reviews.ReviewAction; + +import java.util.Collection; +import java.util.Map; + +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class ReviewActionsManagerTest { + + private ReviewAction fakeLinkReviewAction = new FakeLinkReviewAction(); + private ReviewAction simpleReviewAction = new SimpleReviewAction(); + private ReviewActionsManager manager; + + @Before + public void init() throws Exception { + manager = new ReviewActionsManager(new ReviewAction[] {fakeLinkReviewAction, simpleReviewAction}); + } + + @Test + public void shouldReturnActionsById() throws Exception { + assertThat(manager.getAction("fake-link-review"), is(fakeLinkReviewAction)); + assertThat(manager.getAction("simple-review-action"), is(simpleReviewAction)); + } + + @Test + public void shouldReturnActionsByInterfaceName() throws Exception { + Collection<ReviewAction> reviewActions = manager.getActions("org.sonar.api.reviews.LinkReviewAction"); + assertThat(reviewActions.size(), is(1)); + assertThat(reviewActions, hasItem(fakeLinkReviewAction)); + } + + class FakeLinkReviewAction implements LinkReviewAction { + public String getId() { + return "fake-link-review"; + } + + public String getName() { + return "Fake action"; + } + + public void execute(Map<String, String> reviewContext) { + } + } + class SimpleReviewAction implements ReviewAction { + public String getId() { + return "simple-review-action"; + } + + public String getName() { + return "Simple action"; + } + + public void execute(Map<String, String> reviewContext) { + } + } +} |