diff options
author | Simon Brandhof <simon.brandhof@gmail.com> | 2011-12-22 12:23:41 +0100 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@gmail.com> | 2011-12-22 12:35:55 +0100 |
commit | 181b2f8504f684d709ca79acfb3055e7e9d9dae1 (patch) | |
tree | 3cf4be986ce857b3bc1f571f4b6be19f24b667c0 /sonar-server | |
parent | 7f861f1403794ee1d5711c00a5a64914840c5e47 (diff) | |
download | sonarqube-181b2f8504f684d709ca79acfb3055e7e9d9dae1.tar.gz sonarqube-181b2f8504f684d709ca79acfb3055e7e9d9dae1.zip |
SONAR-983 Display resource viewers when selecting a file
* New javascript global variable : baseUrl. Examples : '/dev' or ''
Diffstat (limited to 'sonar-server')
21 files changed, 858 insertions, 774 deletions
diff --git a/sonar-server/pom.xml b/sonar-server/pom.xml index 98c21266162..d2540db4111 100644 --- a/sonar-server/pom.xml +++ b/sonar-server/pom.xml @@ -256,7 +256,8 @@ <include>**/dashboard-min.js</include> <include>**/protovis-min.js</include> <include>**/protovis-sonar-min.js</include> - <include>**/duplications-min.js</include> + <include>**/duplication-min.js</include> + <include>**/resource-min.js</include> </includes> <output>${project.build.directory}/${project.build.finalName}/javascripts/sonar.js</output> </aggregation> @@ -305,7 +306,7 @@ **/*.log,*.iml,WEB-INF/script/,WEB-INF/test/, javascripts/application*.js,javascripts/prototype*.js,javascripts/scriptaculous*.js,javascripts/tablekit*.js,javascripts/tablekit*.js, javascripts/prototip*.js,javascripts/dashboard*.js,javascripts/protovis.js,javascripts/protovis-min.js,javascripts/protovis-sonar*.js, - javascripts/protovis-msie-min.js,javascripts/duplications*.js,protovis-msie-min.js, + javascripts/protovis-msie-min.js,javascripts/duplication*.js,protovis-msie-min.js,resource*.js, stylesheets/yui-2.6.0*.css,stylesheets/calendar*.css,stylesheets/style*.css,stylesheets/sonar-colorizer*.css,stylesheets/dashboard*.css </packagingExcludes> <warSourceExcludes> 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 ece45af6db9..0514b55e8b7 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 @@ -29,8 +29,6 @@ import org.sonar.api.platform.PluginRepository; import org.sonar.api.profiles.ProfileExporter; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.resources.Language; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Scopes; import org.sonar.api.rules.RulePriority; import org.sonar.api.rules.RuleRepository; import org.sonar.api.utils.ValidationMessages; @@ -39,8 +37,6 @@ import org.sonar.core.i18n.RuleI18nManager; import org.sonar.markdown.Markdown; import org.sonar.persistence.Database; import org.sonar.persistence.DatabaseMigrator; -import org.sonar.persistence.resource.ResourceIndexerDao; -import org.sonar.persistence.resource.ResourceIndexerFilter; import org.sonar.server.configuration.Backup; import org.sonar.server.configuration.ProfilesManager; import org.sonar.server.filters.Filter; @@ -382,12 +378,4 @@ public final class JRubyFacade { public ComponentContainer getContainer() { return Platform.getInstance().getContainer(); } - - - // RESOURCE SEARCH ENGINE - public void indexResources() { - getContainer().getComponentByType(ResourceIndexerDao.class).index(ResourceIndexerFilter.create() - .setQualifiers(new String[]{Qualifiers.PROJECT, Qualifiers.VIEW, Qualifiers.SUBVIEW, Qualifiers.FILE, Qualifiers.CLASS, Qualifiers.UNIT_TEST_FILE}) - .setScopes(new String[]{Scopes.PROJECT, Scopes.FILE})); - } } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb index aa37b23de42..16db07a5da0 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb @@ -27,10 +27,23 @@ class DashboardController < ApplicationController def index # TODO display error page if no dashboard or no resource load_resource() - load_dashboard() - load_authorized_widget_definitions() - unless @dashboard - redirect_to home_path + if @resource.display_dashboard? + load_dashboard() + load_authorized_widget_definitions() + unless @dashboard + redirect_to home_path + end + else + # display the layout of the parent, usually the directory, but display the file viewers + @file = @resource + @snapshot = @snapshot.parent_snapshot + if @snapshot + @resource = @snapshot.resource + @project = @resource + render :action => 'no_dashboard' + else + redirect_to home_path + end end end @@ -138,8 +151,6 @@ class DashboardController < ApplicationController end - - private def load_dashboard @@ -173,6 +184,8 @@ class DashboardController < ApplicationController not_found("Resource not found") unless @resource access_denied unless has_role?(:user, @resource) @snapshot = @resource.last_snapshot + not_found("Snapshot not found") unless @snapshot + @project=@resource # variable name used in old widgets end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/search_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/search_controller.rb index 83cb45e7d79..7aa2cde96d7 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/search_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/search_controller.rb @@ -21,11 +21,9 @@ class SearchController < ApplicationController SECTION=Navigation::SECTION_HOME - verify :method => :post, :only => [:reset] - before_filter :admin_required, :except => ['index'] - # Do not exceed 1000 because of the Oracle limition on IN statements MAX_RESULTS = 6 + MIN_SEARCH_SIZE=3 def index @@ -64,19 +62,6 @@ class SearchController < ApplicationController render :partial => 'search/autocomplete' end - # - # TO DELETE !!!!! - # - # - # Start indexing resources - # - # curl -v -u admin:admin -X POST http://localhost:9000/search/reset - def reset - java_facade.indexResources() - render :text => 'indexing' - end - - private def fix_qualifier(q) case q diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb index 62f4d8b44f2..871d6041a0b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb @@ -341,20 +341,6 @@ module ApplicationHelper end - def link_to_resource_home(resource, options={}) - period_index=options[:period] - period_index=nil if period_index && period_index<=0 - if resource.display_dashboard? - link_to(options[:name] || resource.name, {:controller => 'dashboard', :action => 'index', :id => (resource.copy_resource_id||resource.id), :period => period_index, :tab => options[:tab], :rule => options[:rule]}, :title => options[:title]) - else - if options[:line] - anchor= 'L' + options[:line].to_s - end - link_to(options[:name] || resource.name, {:controller => 'resource', :action => 'index', :anchor => anchor, :id => resource.id, :period => period_index, :tab => options[:tab], :rule => options[:rule], :metric => options[:metric]}, :popup => ['resource', 'height=800,width=900,scrollbars=1,resizable=1'], :title => options[:title]) - end - end - - # # # JFree Eastwood is a partial implementation of Google Chart Api diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/no_dashboard.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/no_dashboard.html.erb new file mode 100644 index 00000000000..6d99650df91 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/no_dashboard.html.erb @@ -0,0 +1,17 @@ +<%= render :partial => 'gwt/base', :locals => {:resource => nil, :popup => false, :metric => nil} -%> +<%= render :partial => 'gwt/resource_viewers' -%> + +<img id="page_loading" src="<%= ApplicationController.root_context -%>/images/loading.gif"> +<div id="resource_container"></div> + +<script type="text/javascript"> + new Ajax.Updater('resource_container', '<%= ApplicationController.root_context-%>/resource/index/<%= @file.id -%>', + { + asynchronous:true, + evalScripts:true, + onComplete:function (transport) { + $('page_loading').hide() + } + }); + +</script>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/_header.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/_header.html.erb index 0545dff41c7..104d8671a08 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/_header.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/_header.html.erb @@ -1,32 +1,16 @@ -<%= render :partial => 'gwt/base', :locals => {:resource => nil, :popup => false, :metric => @metric.key} -%> +<%= render :partial => 'gwt/base', :locals => {:resource => nil, :popup => false, :metric => (@metric ? @metric.key : nil)} -%> <%= render :partial => 'gwt/resource_viewers' -%> <script type="text/javascript"> /* display resource */ function d(resourceId, display_title) { var loading = new Image(); - loading.src = "<%= ApplicationController.root_context-%>/images/loading.gif"; + loading.src = baseUrl + "/images/loading.gif"; $('resource_container').update(loading); - if (display_title==undefined) { - display_title=true; + if (display_title == undefined) { + display_title = true; } - new Ajax.Updater('resource_container', '<%= ApplicationController.root_context-%>/resource/index/' + resourceId + '?metric=<%= @metric.id if @metric -%>&rule=<%= @rule ? @rule.id : @severity -%>&period=<%= @period -%>&display_title=' + display_title, {asynchronous:true, evalScripts:true}); + new Ajax.Updater('resource_container', baseUrl + '/resource/index/' + resourceId + '?metric=<%= @metric.id if @metric -%>&rule=<%= @rule ? @rule.id : @severity -%>&period=<%= @period -%>&display_title=' + display_title, {asynchronous:true, evalScripts:true}); return false; } - - function loadAjaxTab(resourceId, tab, display_title) { - $('resource-loading').show(); - if (display_title==undefined) { - display_title=true; - } - new Ajax.Updater('resource_container', '<%= ApplicationController.root_context-%>/resource/index/' + resourceId + '?tab=' + tab + '&display_title=' + display_title, {asynchronous:true, evalScripts:true}); - return false; - } - - /* display GWT component, executed from tabs */ - function loadGWT(gwtId, resourceId, resourceKey, resourceName, resourceScope, resourceQualifier, resourceLanguage) { - config["resource"]=[{"id": resourceId, "key": resourceKey, "name" : resourceName, "scope": resourceScope, "qualifier": resourceQualifier, "lang": resourceLanguage}]; - config["resource_key"]=resourceId; - modules[gwtId](); - } </script> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/measures.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/measures.html.erb index b68fdbdf113..0d2dc97ed29 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/measures.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/measures.html.erb @@ -1,4 +1,3 @@ -<%= render :partial => 'resource/javascript' -%> <%= render :partial => 'header' -%> <% if params[:period] && @snapshot.project_snapshot.periods? %> @@ -37,7 +36,8 @@ <table id="drilldown" class="width100" style="clear:left"> <% if @highlighted_metric!=@metric %> <tr> - <td colspan="<%= @drilldown.columns.size -%>"><%= message('drilldown.drilldown_on') -%> <b><%= format_measure(@metric.key, :period => @period) -%> <%= @metric.short_name -%></b></td> + <td colspan="<%= @drilldown.columns.size -%>"><%= message('drilldown.drilldown_on') -%> + <b><%= format_measure(@metric.key, :period => @period) -%> <%= @metric.short_name -%></b></td> </tr> <tr> <% end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/violations.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/violations.html.erb index e6523a83ffa..3e4232c3633 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/violations.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/drilldown/violations.html.erb @@ -1,4 +1,3 @@ -<%= render :partial => 'resource/javascript' -%> <%= render :partial => 'header' -%> <div id="snapshot_title" class="page_title"> @@ -126,43 +125,43 @@ @drilldown.columns.each_with_index do |column, index| %> <td class="column <%= 'first' if index==0 -%>" nowrap width="<%= column_width -%>%"> - <div class="scrollable" id="col_<%= column.scope -%>"> - <table class="spaced"> - <% - column.measures.each do |measure| - resource=column.resource(measure) - clazz = cycle('even', 'odd', :name => "col_#{column.scope}") - selected = column.selected_snapshot && column.selected_snapshot.project_id==resource.id - if selected - clazz += ' selected' - paths << [h(resource.name), @selected_rids-[resource.id]] - end - %> - <tr class="<%= clazz -%>"> - <td nowrap> - <% - if resource.entity? - if resource.copy_resource_id %> - <%= qualifier_icon(resource) -%> - <%= link_to(h(resource.name), {:only_path => true, :overwrite_params => {:rids => nil, :id => resource.copy_resource_id}}) -%> - <% else %> - <%= qualifier_icon(resource) -%> - <a href="#" onclick="d(<%= resource.id -%>, '<%= @period_index -%>', '<%= @rule ? @rule.key : @severity -%>');" alt="<%= resource.name(true) -%>" title="<%= resource.name(true) -%>"><%= resource.name(false) %></a> + <div class="scrollable" id="col_<%= column.scope -%>"> + <table class="spaced"> + <% + column.measures.each do |measure| + resource=column.resource(measure) + clazz = cycle('even', 'odd', :name => "col_#{column.scope}") + selected = column.selected_snapshot && column.selected_snapshot.project_id==resource.id + if selected + clazz += ' selected' + paths << [h(resource.name), @selected_rids-[resource.id]] + end + %> + <tr class="<%= clazz -%>"> + <td nowrap> <% - end - else %> - <%= link_to(image_tag('zoom.png'), {:id => resource.id}, {:class => 'nolink'}) %> - <%= qualifier_icon(resource) %> - <%= link_to(h(resource.name), {:only_path => true, :overwrite_params => {:rids => (selected ? rids-[resource.id] : rids+[resource.id])}}) -%> - <% end %> - </td> - <td class="right last" nowrap> - <%= @period ? format_variation(measure, :period => @period, :style => 'light') : measure.formatted_value -%> - </td> - </tr> - <% end %> - </table> - </div> + if resource.entity? + if resource.copy_resource_id %> + <%= qualifier_icon(resource) -%> + <%= link_to(h(resource.name), {:only_path => true, :overwrite_params => {:rids => nil, :id => resource.copy_resource_id}}) -%> + <% else %> + <%= qualifier_icon(resource) -%> + <a href="#" onclick="d(<%= resource.id -%>, '<%= @period_index -%>', '<%= @rule ? @rule.key : @severity -%>');" alt="<%= resource.name(true) -%>" title="<%= resource.name(true) -%>"><%= resource.name(false) %></a> + <% + end + else %> + <%= link_to(image_tag('zoom.png'), {:id => resource.id}, {:class => 'nolink'}) %> + <%= qualifier_icon(resource) %> + <%= link_to(h(resource.name), {:only_path => true, :overwrite_params => {:rids => (selected ? rids-[resource.id] : rids+[resource.id])}}) -%> + <% end %> + </td> + <td class="right last" nowrap> + <%= @period ? format_variation(measure, :period => @period, :style => 'light') : measure.formatted_value -%> + </td> + </tr> + <% end %> + </table> + </div> </td> <% rids<<column.selected_snapshot.project_id if column.selected_snapshot diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/gwt/_base.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/gwt/_base.html.erb index 242ac153fae..a7c83fa0c8c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/gwt/_base.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/gwt/_base.html.erb @@ -1,30 +1,30 @@ <script type="text/javascript"> var config = { - "sonar_url":"<%= url_for(:controller => '/', :action => '', :only_path => true, :trailing_slash => false)[0...-2] -%>", + "sonar_url":baseUrl, "version":"<%= sonar_version -%>", - "popup": "<%= popup -%>" -<% if metric %> - ,"metric": "<%= metric -%>" -<% end %> + "popup":"<%= popup -%>" + <% if metric %>, "metric":"<%= metric -%>" + <% end %> -<% - if resource -%> - ,"resource_key": "<%= resource.id -%>", - "resource":[{"id": <%= resource.id -%>, "key":"<%= resource.key -%>","scope": "<%= resource.scope -%>", "qualifier": "<%= resource.qualifier -%>", "name": "<%= resource.name -%>", "lang":"<%= resource.language -%>"}] -<% end %> + <% + if resource + %>, "resource_key":"<%= resource.id -%>", + "resource":[ + {"id": <%= resource.id -%>, "key":"<%= resource.key -%>", "scope":"<%= resource.scope -%>", "qualifier":"<%= resource.qualifier -%>", "name":"<%= resource.name -%>", "lang":"<%= resource.language -%>"} + ] + <% end %> }; var rp = { - <% - index=0 - params.each do |key,value| - %> + <% + index=0 + params.each do |key,value| + %> <%= ',' if index>0 -%>"<%= key -%>":"<%= value -%>" - <% - index+=1 - end - %> + <% + index+=1 + end + %> }; var modules = new Object(); diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb index 637ec62a561..83360313865 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb @@ -29,7 +29,8 @@ <%= javascript_include_tag 'dashboard' %> <%= javascript_include_tag 'protovis' %> <%= javascript_include_tag 'protovis-sonar' %> -<%= javascript_include_tag 'duplications' %> +<%= javascript_include_tag 'duplication' %> +<%= javascript_include_tag 'resource' %> <% end %> <!--[if lte IE 6]><link href="<%= ApplicationController.root_context -%>/ie6/index" media="all" rel="stylesheet" type="text/css" /><![endif]--> <!--[if lte IE 8]><%= javascript_include_tag 'protovis-msie' -%><![endif]--> @@ -37,7 +38,7 @@ <% if @project %> <link rel="alternate" title="Sonar Alerts on <%= @project.name -%>" href="<%= ApplicationController.root_context -%>/feeds/project/<%= @project.key -%>?category=<%= EventCategory::KEY_ALERT -%>" type="application/atom+xml"> -<% else %> -<link rel="alternate" title="Sonar Alerts" href="<%= ApplicationController.root_context -%>/feeds/projects/<%= EventCategory::KEY_ALERT -%>" type="application/atom+xml"> -<% end %> +<% else +%><link rel="alternate" title="Sonar Alerts" href="<%= ApplicationController.root_context -%>/feeds/projects/<%= EventCategory::KEY_ALERT -%>" type="application/atom+xml"><% +end %><script>var baseUrl = '<%= ApplicationController.root_context -%>';</script> </head><body>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb index 1434e3c1975..6a83896baa1 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb @@ -7,7 +7,7 @@ <%= render :partial => 'layouts/breadcrumb' %> <ol id="nav"> <li> - <input type="text" size="15" name="search" id="searchResourcesInput" onFocus="autocompleteResources('<%= ApplicationController.root_context -%>')" accesskey="/" value="<%= message('search_verb') -%>"/> + <input type="text" size="15" name="search" id="searchResourcesInput" onFocus="autocompleteResources()" value="<%= message('search_verb') -%>"/> <img src="<%= ApplicationController.root_context -%>/images/loading-black.gif" id="searchingResources" style="display: none"> </li> <li> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb deleted file mode 100644 index a4e72396f74..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_javascript.html.erb +++ /dev/null @@ -1,161 +0,0 @@ -<script type="text/javascript"> - // show violation actions - function sVA(violation_id) { - var elt = $('vMsg' + violation_id); - if (elt != null) { - elt.hide(); - } - elt = $('vActions' + violation_id); - if (elt != null) { - elt.show(); - } - return false; - } - - // hide violation actions - function hVA(violation_id) { - var elt = $('vMsg' + violation_id); - if (elt != null) { - elt.show(); - } - elt = $('vActions' + violation_id); - if (elt != null) { - elt.hide(); - } - return false; - } - - // cancel action : hide form and refresh violation - function cancelViolationAction(violation_id) { - new Ajax.Updater( - 'vId' + violation_id, - '<%= ApplicationController.root_context -%>/reviews/display_violation/' + violation_id, - { - asynchronous:true, - evalScripts:true - }); - return false; - } - - // show the form to comment violation - function sCF(violation_id) { - new Ajax.Updater('reviewForm' + violation_id, - '<%= ApplicationController.root_context -%>/reviews/violation_comment_form/' + violation_id, - { - asynchronous:true, - evalScripts:true, - onComplete:function (request) { - $('vBody' + violation_id).remove(); - $('reviewForm' + violation_id).show(); - $('commentText' + violation_id).focus(); - } - }); - return false; - } - - // show the form to change severity - function sCSF(violation_id) { - new Ajax.Updater('reviewForm' + violation_id, - '<%= ApplicationController.root_context -%>/reviews/violation_change_severity_form/' + violation_id, - { - asynchronous:true, - evalScripts:true, - onComplete:function (request) { - $('vBody' + violation_id).remove(); - $('reviewForm' + violation_id).show(); - $('selectSeverity' + violation_id).focus(); - } - }); - return false; - } - - // show the form to change status - function sCStF(violation_id) { - new Ajax.Updater('reviewForm' + violation_id, - '<%= ApplicationController.root_context -%>/reviews/violation_change_status_form/' + violation_id, - { - asynchronous:true, - evalScripts:true, - onComplete:function (request) { - $('vBody' + violation_id).remove(); - $('reviewForm' + violation_id).show(); - $('commentText' + violation_id).focus(); - } - }); - return false; - } - - // show the form to flag as false-positive - function sFPF(violation_id) { - new Ajax.Updater('reviewForm' + violation_id, - '<%= ApplicationController.root_context -%>/reviews/violation_false_positive_form/' + violation_id, - { - asynchronous:true, - evalScripts:true, - onComplete:function (request) { - $('vBody' + violation_id).remove(); - $('reviewForm' + violation_id).show(); - $('commentText' + violation_id).focus(); - } - }); - return false; - } - - // show the form to assign violation - function sAF(violation_id) { - new Ajax.Updater('reviewForm' + violation_id, - '<%= ApplicationController.root_context -%>/reviews/violation_assign_form/' + violation_id, - { - asynchronous:true, - evalScripts:true, - onComplete:function (request) { - $('vBody' + violation_id).remove(); - $('reviewForm' + violation_id).show(); - $('assignee_login').focus(); - } - }); - return false; - } - - // show the form to link a review to an action plan - function sAPF(violation_id) { - new Ajax.Updater('reviewForm' + violation_id, - '<%= ApplicationController.root_context -%>/reviews/violation_action_plan_form/' + violation_id, - { - asynchronous:true, - evalScripts:true, - onComplete:function (request) { - $('vBody' + violation_id).remove(); - $('reviewForm' + violation_id).show(); - $('action_plan').focus(); - } - }); - return false; - } - - // show the form to create violation - function sVF(resource, line, gray_colspan, white_colspan) { - row = $('createViolationForm' + line); - if (row == null) { - new Ajax.Updater( - 'pos' + line, - '<%= ApplicationController.root_context -%>/resource/show_create_violation_form', - { - parameters:{resource:resource, line:line, gray_colspan:gray_colspan, white_colspan:white_colspan}, - asynchronous:true, - evalScripts:true, - insertion:'after' - }); - } - return false; - } - - // hide review form - function hVF(line) { - row = $('createViolationRow' + line); - if (row != null) { - row.remove(); - } - return false; - } -</script>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb index 221c1b3680f..c0754df974b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb @@ -2,91 +2,91 @@ if display_options %> -<div id="source_options"> - <script> - applyOptions=function() { - $('resource-loading').show(); - <% if request.xhr? %> + <div id="source_options"> + <script> + applyOptions = function () { + $('resource_loading').show(); + <% if request.xhr? %> var params = Form.serialize($('options-form')); new Ajax.Updater('resource_container', '<%= url_for :controller => 'resource', :action => 'index', :id => @resource.key -%>', {asynchronous:true, parameters:params}); return true; - <% else %> + <% else %> $('options-form').submit(); return false; - <% end %> - }; - </script> - <form method="GET" action="<%= url_for :controller => 'resource', :action => 'index', :id => @resource.key -%>" id="options-form"> - <input type="hidden" name="tab" value="<%= params[:tab] -%>"/> - <input type="hidden" name="metric" value="<%= params[:metric] -%>"/> - <input type="hidden" name="period" value="<%= params[:period] -%>"/> + <% end %> + }; + </script> + <form method="GET" action="<%= url_for :controller => 'resource', :action => 'index', :id => @resource.key -%>" id="options-form"> + <input type="hidden" name="tab" value="<%= params[:tab] -%>"/> + <input type="hidden" name="metric" value="<%= params[:metric] -%>"/> + <input type="hidden" name="period" value="<%= params[:period] -%>"/> - <table> - <tr> - <% - first=true - if @expandable %> - <td class="<%= 'first' if first -%>"> - <input type="checkbox" value="true" name="expand" id="expand" <%= 'checked' if @expanded -%> onclick="applyOptions()"/> - <label for="expand"><%= message('full_source') -%></label> - </td> - <% first=false - end %> - - <% if @scm_available && !@display_violations && @snapshot.project_snapshot.periods? %> - <td class="<%= 'first' if first -%>"> - <select id="period" name="period" onchange="applyOptions()"> - <option value=""><%= message('time_changes') -%>...</option> - <%= period_select_options(@snapshot, 1) -%> - <%= period_select_options(@snapshot, 2) -%> - <%= period_select_options(@snapshot, 3) -%> - <%= period_select_options(@snapshot, 4) -%> - <%= period_select_options(@snapshot, 5) -%> - </select> - </td> - <% - first=false - end %> + <table> + <tr> + <% + first=true + if @expandable %> + <td class="<%= 'first' if first -%>"> + <input type="checkbox" value="true" name="expand" id="expand" <%= 'checked' if @expanded -%> onclick="applyOptions()"/> + <label for="expand"><%= message('full_source') -%></label> + </td> + <% first=false + end %> - <% if @display_violations %> - <td class="<%= 'first' if first -%>"> - <select id="period" name="period" onchange="applyOptions()"> - <option value=""><%= message('time_changes') -%>...</option> - <%= violation_period_select_options(@snapshot, 1) -%> - <%= violation_period_select_options(@snapshot, 2) -%> - <%= violation_period_select_options(@snapshot, 3) -%> - <%= violation_period_select_options(@snapshot, 4) -%> - <%= violation_period_select_options(@snapshot, 5) -%> - </select> - </td> + <% if @scm_available && !@display_violations && @snapshot.project_snapshot.periods? %> + <td class="<%= 'first' if first -%>"> + <select id="period" name="period" onchange="applyOptions()"> + <option value=""><%= message('time_changes') -%>...</option> + <%= period_select_options(@snapshot, 1) -%> + <%= period_select_options(@snapshot, 2) -%> + <%= period_select_options(@snapshot, 3) -%> + <%= period_select_options(@snapshot, 4) -%> + <%= period_select_options(@snapshot, 5) -%> + </select> + </td> + <% + first=false + end %> - <td class="<%= 'first' if first -%>"><%= render :partial => 'rules_filter' -%></td> - <% first=false - end %> + <% if @display_violations %> + <td class="<%= 'first' if first -%>"> + <select id="period" name="period" onchange="applyOptions()"> + <option value=""><%= message('time_changes') -%>...</option> + <%= violation_period_select_options(@snapshot, 1) -%> + <%= violation_period_select_options(@snapshot, 2) -%> + <%= violation_period_select_options(@snapshot, 3) -%> + <%= violation_period_select_options(@snapshot, 4) -%> + <%= violation_period_select_options(@snapshot, 5) -%> + </select> + </td> - <% if @display_coverage %> - <td class="<%= 'first' if first -%>"> - <select id="coverage_filter" name="coverage_filter" onchange="applyOptions()"> - <optgroup label="<%= h message('coverage_viewer.unit_tests') -%>"> - <option value="lines_to_cover" <%= 'selected' if @coverage_filter=='lines_to_cover' -%>><%= Metric.name_for('lines_to_cover') -%></option> - <option value="uncovered_lines" <%= 'selected' if @coverage_filter=='uncovered_lines' -%>><%= Metric.name_for('uncovered_lines') -%></option> - <option value="conditions_to_cover" <%= 'selected' if @coverage_filter=='conditions_to_cover' -%>><%= Metric.name_for('conditions_to_cover') -%></option> - <option value="uncovered_conditions" <%= 'selected' if @coverage_filter=='uncovered_conditions' -%>><%= Metric.name_for('uncovered_conditions') -%></option> - </optgroup> - <% if @display_it_coverage %> - <optgroup label="<%= h message('coverage_viewer.integration_tests') -%>"> - <option value="it_lines_to_cover" <%= 'selected' if @coverage_filter=='it_lines_to_cover' -%>><%= Metric.name_for('it_lines_to_cover') -%></option> - <option value="it_uncovered_lines" <%= 'selected' if @coverage_filter=='it_uncovered_lines' -%>><%= Metric.name_for('it_uncovered_lines') -%></option> - <option value="it_conditions_to_cover" <%= 'selected' if @coverage_filter=='it_conditions_to_cover' -%>><%= Metric.name_for('it_conditions_to_cover') -%></option> - <option value="it_uncovered_conditions" <%= 'selected' if @coverage_filter=='it_uncovered_conditions' -%>><%= Metric.name_for('it_uncovered_conditions') -%></option> - </optgroup> - <% end %> - </select> - </td> - <% first=false - end %> - </tr> - </table> - </form> -</div> + <td class="<%= 'first' if first -%>"><%= render :partial => 'rules_filter' -%></td> + <% first=false + end %> + + <% if @display_coverage %> + <td class="<%= 'first' if first -%>"> + <select id="coverage_filter" name="coverage_filter" onchange="applyOptions()"> + <optgroup label="<%= h message('coverage_viewer.unit_tests') -%>"> + <option value="lines_to_cover" <%= 'selected' if @coverage_filter=='lines_to_cover' -%>><%= Metric.name_for('lines_to_cover') -%></option> + <option value="uncovered_lines" <%= 'selected' if @coverage_filter=='uncovered_lines' -%>><%= Metric.name_for('uncovered_lines') -%></option> + <option value="conditions_to_cover" <%= 'selected' if @coverage_filter=='conditions_to_cover' -%>><%= Metric.name_for('conditions_to_cover') -%></option> + <option value="uncovered_conditions" <%= 'selected' if @coverage_filter=='uncovered_conditions' -%>><%= Metric.name_for('uncovered_conditions') -%></option> + </optgroup> + <% if @display_it_coverage %> + <optgroup label="<%= h message('coverage_viewer.integration_tests') -%>"> + <option value="it_lines_to_cover" <%= 'selected' if @coverage_filter=='it_lines_to_cover' -%>><%= Metric.name_for('it_lines_to_cover') -%></option> + <option value="it_uncovered_lines" <%= 'selected' if @coverage_filter=='it_uncovered_lines' -%>><%= Metric.name_for('it_uncovered_lines') -%></option> + <option value="it_conditions_to_cover" <%= 'selected' if @coverage_filter=='it_conditions_to_cover' -%>><%= Metric.name_for('it_conditions_to_cover') -%></option> + <option value="it_uncovered_conditions" <%= 'selected' if @coverage_filter=='it_uncovered_conditions' -%>><%= Metric.name_for('it_uncovered_conditions') -%></option> + </optgroup> + <% end %> + </select> + </td> + <% first=false + end %> + </tr> + </table> + </form> + </div> <% end %>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_tabs.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_tabs.html.erb index f2fb607c2ca..7f62bb968e9 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_tabs.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_tabs.html.erb @@ -2,9 +2,9 @@ display_title=(params[:display_title]!='false') if display_title %> -<div id="source_title"> - <span class="h1"><%= qualifier_icon(@resource) -%> <%= @resource.long_name -%></span> -</div> + <div id="source_title"> + <span class="h1"><%= qualifier_icon(@resource) -%> <%= @resource.name(true) -%></span> + </div> <% end %> <div id="source_tabs"> @@ -13,26 +13,37 @@ first=true if @snapshot.source %> - <li class="<%= 'first' if first -%>"><a href="<%= ApplicationController.root_context -%>/api/sources?resource=<%= @resource.key -%>&format=txt"><%= message('raw') -%></a></li> - <% first=false + <li class="<%= 'first' if first -%>"><a href="<%= ApplicationController.root_context -%>/api/sources?resource=<%= @resource.key -%>&format=txt"><%= message('raw') -%></a> + </li> + <% first=false end if request.xhr? %> - <li class="<%= 'first' if first -%>"><a href="<%= ApplicationController.root_context -%>/resource/index/<%= @resource.key -%>" onclick="window.open(this.href,'resource','height=800,width=900,scrollbars=1,resizable=1');return false;"><%= message('new_window') -%></a></li> + <li class="<%= 'first' if first -%>"> + <a href="<%= ApplicationController.root_context -%>/resource/index/<%= @resource.key -%>" onclick="window.open(this.href,'resource','height=800,width=900,scrollbars=1,resizable=1');return false;"><%= message('new_window') -%></a> + </li> <% end %> </ul> - <ul class="tabs" > - <% if request.xhr? %> - <% @extensions.each do |extension| %> - <li><a href="#" onclick="return loadAjaxTab('<%= @resource.id -%>','<%= extension.getId() -%>',<%= display_title -%>)" class="<%= 'selected' if @extension && @extension.getId()==extension.getId() -%>"><%= message(extension.getId() + '.page', :default => extension.getTitle()) %></a></li> - <% end %> - <% else %> - <script>function loadTab(url) {$('resource-loading').show();document.location.href=url;return false;}</script> - <% @extensions.each do |extension| %> - <li><a href="#" onClick="return loadTab('<%= url_for(:overwrite_params => {:tab => extension.getId(), :metric => nil}) -%>')" class="<%= 'selected' if @extension && @extension.getId()==extension.getId() -%>"><%= message(extension.getId() + '.page', :default => extension.getTitle()) %></a></li> + <ul class="tabs"> + <% if request.xhr? %> + <% @extensions.each do |extension| %> + <li> + <a href="#" onclick="return loadResourceViewer('<%= @resource.id -%>','<%= extension.getId() -%>',<%= display_title -%>)" class="<%= 'selected' if @extension && @extension.getId()==extension.getId() -%>"><%= message(extension.getId() + '.page', :default => extension.getTitle()) %></a> + </li> + <% end %> + <% else %> + <script>function loadTab(url) { + $('resource_loading').show(); + document.location.href = url; + return false; + }</script> + <% @extensions.each do |extension| %> + <li> + <a href="#" onClick="return loadTab('<%= url_for(:overwrite_params => {:tab => extension.getId(), :metric => nil}) -%>')" class="<%= 'selected' if @extension && @extension.getId()==extension.getId() -%>"><%= message(extension.getId() + '.page', :default => extension.getTitle()) %></a> + </li> + <% end %> <% end %> - <% end %> - <li> - <img src="<%= ApplicationController.root_context -%>/images/loading.gif" id="resource-loading" style="display:none"/> - </li> + <li> + <img src="<%= ApplicationController.root_context -%>/images/loading.gif" id="resource_loading" style="display:none"/> + </li> </ul> </div> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/index.html.erb index 103503bbbc7..1dae1f827f9 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/index.html.erb @@ -1,5 +1,4 @@ <%= render :partial => 'tabs' -%> -<%= render :partial => 'resource/javascript' -%> <%= render :partial => "resource/header_#{@extension.getId()}" -%> <% if @display_violations && @global_violations && @global_violations.size>0 -%> diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/resourceable.rb b/sonar-server/src/main/webapp/WEB-INF/lib/resourceable.rb index 341d249bbcc..606b3d3e3d8 100644 --- a/sonar-server/src/main/webapp/WEB-INF/lib/resourceable.rb +++ b/sonar-server/src/main/webapp/WEB-INF/lib/resourceable.rb @@ -35,7 +35,7 @@ module Resourceable QUALIFIER_CLASS='CLA' QUALIFIER_UNIT_TEST_CLASS='UTS' QUALIFIER_LIB='LIB' - QUALIFIERS=[QUALIFIER_VIEW,QUALIFIER_SUBVIEW,QUALIFIER_PROJECT,QUALIFIER_MODULE,QUALIFIER_DIRECTORY,QUALIFIER_PACKAGE,QUALIFIER_FILE,QUALIFIER_CLASS,QUALIFIER_UNIT_TEST_CLASS,QUALIFIER_LIB] + QUALIFIERS=[QUALIFIER_VIEW, QUALIFIER_SUBVIEW, QUALIFIER_PROJECT, QUALIFIER_MODULE, QUALIFIER_DIRECTORY, QUALIFIER_PACKAGE, QUALIFIER_FILE, QUALIFIER_CLASS, QUALIFIER_UNIT_TEST_CLASS, QUALIFIER_LIB] QUALIFIER_NAMES={ QUALIFIER_VIEW => 'view', QUALIFIER_SUBVIEW => 'sub_view', @@ -48,6 +48,7 @@ module Resourceable QUALIFIER_UNIT_TEST_CLASS => 'unit_test', QUALIFIER_LIB => 'library' } + def set? scope==SCOPE_SET end @@ -88,8 +89,8 @@ module Resourceable qualifier==QUALIFIER_FILE end - NO_DASHBOARD_QUALIFIERS=[QUALIFIER_FILE,QUALIFIER_CLASS,QUALIFIER_UNIT_TEST_CLASS] - + NO_DASHBOARD_QUALIFIERS=[QUALIFIER_FILE, QUALIFIER_CLASS, QUALIFIER_UNIT_TEST_CLASS] + def display_dashboard? !NO_DASHBOARD_QUALIFIERS.include?(qualifier) end diff --git a/sonar-server/src/main/webapp/javascripts/application.js b/sonar-server/src/main/webapp/javascripts/application.js index b61673c0b77..973b49254b7 100644 --- a/sonar-server/src/main/webapp/javascripts/application.js +++ b/sonar-server/src/main/webapp/javascripts/application.js @@ -12,16 +12,16 @@ function info(message) { showMessage('info', message); } -function autocompleteResources(base_url) { +function autocompleteResources() { $('searchResourcesInput').value = ''; - new Ajax.Autocompleter('searchResourcesInput', 'searchResourcesResults', base_url + '/search', { + new Ajax.Autocompleter('searchResourcesInput', 'searchResourcesResults', baseUrl + '/search', { method:'post', minChars:3, indicator:'searchingResources', paramName:'s', updateElement:function (item) { if (item.id) { - window.location = base_url + '/dashboard/index/' + item.id; + window.location = baseUrl + '/dashboard/index/' + item.id; } }, onShow:function (element, update) { /* no update */ diff --git a/sonar-server/src/main/webapp/javascripts/duplications.js b/sonar-server/src/main/webapp/javascripts/duplication.js index d8664f19cce..b563873dafa 100644 --- a/sonar-server/src/main/webapp/javascripts/duplications.js +++ b/sonar-server/src/main/webapp/javascripts/duplication.js @@ -8,7 +8,7 @@ function updateDuplicationLines(url, groupId, itemId, linesCount, fromLine, toLi $('duplLoading-' + groupId).addClassName('loading'); if ($('source-' + groupId).childElements()[0].hasClassName('expanded')) { - toLine = fromLine + linesCount -1; + toLine = fromLine + linesCount - 1; } new Ajax.Updater('source-' + groupId, url + "&to_line=" + toLine + "&from_line=" + fromLine + "&lines_count=" + linesCount + "&group_index=" + groupId, {asynchronous:true, evalScripts:true}); diff --git a/sonar-server/src/main/webapp/javascripts/protovis-sonar.js b/sonar-server/src/main/webapp/javascripts/protovis-sonar.js index 9b415412add..022c58b11ca 100755 --- a/sonar-server/src/main/webapp/javascripts/protovis-sonar.js +++ b/sonar-server/src/main/webapp/javascripts/protovis-sonar.js @@ -1,210 +1,250 @@ -window.SonarWidgets = {} +window.SonarWidgets = {}; //******************* STACK AREA CHART ******************* // SonarWidgets.StackArea = function (divId) { - this.wDivId = divId; - this.wHeight; - this.wData; - this.wSnapshots; - this.wMetrics; - this.wColors; - this.height = function(height) { - this.wHeight = height; - return this; - } - this.data = function(data) { - this.wData = data; - return this; - } - this.snapshots = function(snapshots) { - this.wSnapshots = snapshots; - return this; - } - this.metrics = function(metrics) { - this.wMetrics = metrics; - return this; - } - this.colors = function(colors) { - this.wColors = colors; - return this; - } -} - -SonarWidgets.StackArea.prototype.render = function() { - - var trendData = this.wData; - var metrics = this.wMetrics; - var snapshots = this.wSnapshots; - var colors = this.wColors; - - var widgetDiv = $(this.wDivId); - var headerFont = "10.5px Arial,Helvetica,sans-serif"; - - /* Computes the total of the trendData of each date */ - var total = []; - for (i=0; i<trendData[0].size(); i++) { - total[i] = 0; - for (j=0; j<metrics.size();j++) { - total[i] += trendData[j][i].y; - } - total[i] = "" + Math.round(total[i]*10)/10 - } - - /* Computes the highest Y value */ - var maxY = 0; - for (i=0; i<trendData[0].size(); i++) { - var currentYSum = 0; - for (j=0; j<trendData.size(); j++) { - currentYSum += trendData[j][i].y; - } - if (currentYSum > maxY) { maxY = currentYSum;} - } - - /* Computes minimum width of left margin according to the max Y value so that the Y-axis is correctly displayed */ - var leftMargin = 25; - var maxYLength = (Math.round(maxY) + "").length; - minMargin = maxYLength * 7 + Math.floor(maxYLength /3) * 2; // first part is for numbers and second for commas (1000-separator) - if (minMargin > leftMargin) { leftMargin = minMargin; } - - /* Sizing and scales. */ - var headerHeight = 40; - var w = widgetDiv.getOffsetParent().getWidth() - leftMargin - 40; - var h = (this.wHeight == null ? 200 : this.wHeight) + headerHeight; - - var x = pv.Scale.linear(pv.blend(pv.map(trendData, function(d) {return d;})), function(d) {return d.x}).range(0, w); - var y = pv.Scale.linear(0, maxY).range(0, h-headerHeight); - var idx_numbers = trendData[0].size(); - var idx = idx_numbers - 1; - - function computeIdx(xPixels) { - var mx = x.invert(xPixels); - var i = pv.search(trendData[0].map(function(d) {return d.x;}), mx); - i = i < 0 ? (-i - 2) : i; - i = i < 0 ? 0 : i; - return i; - } - - /* The root panel. */ - var vis = new pv.Panel() - .canvas(widgetDiv) - .width(w) - .height(h) - .left(leftMargin) - .right(20) - .bottom(30) - .top(20) - .strokeStyle("#CCC"); - - /* X-axis */ - vis.add(pv.Rule) - .data(x.ticks()) - .left(x) - .bottom(-10) - .height(10) - .anchor("bottom") - .add(pv.Label) - .text(x.tickFormat); - - /* Y-axis and ticks. */ - vis.add(pv.Rule) - .data(y.ticks(6)) - .bottom(y) - .strokeStyle("rgba(128,128,128,.2)") - .anchor("left") - .add(pv.Label) - .text(y.tickFormat); - - /* The stack layout */ - var area = vis.add(pv.Layout.Stack) - .layers(trendData) - .x(function(d) {return x(d.x);}) - .y(function(d) {return y(d.y);}) - .layer - .add(pv.Area) - .fillStyle(function() {return colors[this.parent.index % colors.size()][0];}) - .strokeStyle("rgba(128,128,128,.8)"); - - /* Stack labels. */ - var firstIdx = computeIdx(w/5); - var lastIdx = computeIdx(w*4/5); - vis.add(pv.Panel) - .extend(area.parent) - .add(pv.Area) - .extend(area) - .fillStyle(null) - .strokeStyle(null) - .anchor(function() {return (idx==idx_numbers-1 || idx > lastIdx) ? "right" : ((idx==0 || idx < firstIdx) ? "left" : "center");}) - .add(pv.Label) - .visible(function(d) {return this.index == idx && d.y != 0;}) - .font(function(d) { return Math.round(5 + Math.sqrt(y(d.y))) + "px sans-serif";}) - .textStyle("#DDD") - .text(function(d) {return metrics[this.parent.index] + ": " + d.y;}); - - /* The total cost of the selected dot in the header. */ - vis.add(pv.Label) - .left(8) - .top(16) - .font(headerFont) - .text(function() {return "Total: " + total[idx];}); - - /* The date of the selected dot in the header. */ - vis.add(pv.Label) - .left(w/2) - .top(16) - .font(headerFont) - .text(function() {return snapshots[idx].ld;}); - - - /* The event labels */ + this.wDivId = divId; + this.wHeight; + this.wData; + this.wSnapshots; + this.wMetrics; + this.wColors; + this.height = function (height) { + this.wHeight = height; + return this; + }; + this.data = function (data) { + this.wData = data; + return this; + }; + this.snapshots = function (snapshots) { + this.wSnapshots = snapshots; + return this; + }; + this.metrics = function (metrics) { + this.wMetrics = metrics; + return this; + }; + this.colors = function (colors) { + this.wColors = colors; + return this; + } +}; + +SonarWidgets.StackArea.prototype.render = function () { + + var trendData = this.wData; + var metrics = this.wMetrics; + var snapshots = this.wSnapshots; + var colors = this.wColors; + + var widgetDiv = $(this.wDivId); + var headerFont = "10.5px Arial,Helvetica,sans-serif"; + + /* Computes the total of the trendData of each date */ + var total = []; + for (i = 0; i < trendData[0].size(); i++) { + total[i] = 0; + for (j = 0; j < metrics.size(); j++) { + total[i] += trendData[j][i].y; + } + total[i] = "" + Math.round(total[i] * 10) / 10 + } + + /* Computes the highest Y value */ + var maxY = 0; + for (i = 0; i < trendData[0].size(); i++) { + var currentYSum = 0; + for (j = 0; j < trendData.size(); j++) { + currentYSum += trendData[j][i].y; + } + if (currentYSum > maxY) { + maxY = currentYSum; + } + } + + /* Computes minimum width of left margin according to the max Y value so that the Y-axis is correctly displayed */ + var leftMargin = 25; + var maxYLength = (Math.round(maxY) + "").length; + minMargin = maxYLength * 7 + Math.floor(maxYLength / 3) * 2; // first part is for numbers and second for commas (1000-separator) + if (minMargin > leftMargin) { + leftMargin = minMargin; + } + + /* Sizing and scales. */ + var headerHeight = 40; + var w = widgetDiv.getOffsetParent().getWidth() - leftMargin - 40; + var h = (this.wHeight == null ? 200 : this.wHeight) + headerHeight; + + var x = pv.Scale.linear(pv.blend(pv.map(trendData, function (d) { + return d; + })), + function (d) { + return d.x + }).range(0, w); + var y = pv.Scale.linear(0, maxY).range(0, h - headerHeight); + var idx_numbers = trendData[0].size(); + var idx = idx_numbers - 1; + + function computeIdx(xPixels) { + var mx = x.invert(xPixels); + var i = pv.search(trendData[0].map(function (d) { + return d.x; + }), mx); + i = i < 0 ? (-i - 2) : i; + i = i < 0 ? 0 : i; + return i; + } + + /* The root panel. */ + var vis = new pv.Panel() + .canvas(widgetDiv) + .width(w) + .height(h) + .left(leftMargin) + .right(20) + .bottom(30) + .top(20) + .strokeStyle("#CCC"); + + /* X-axis */ + vis.add(pv.Rule) + .data(x.ticks()) + .left(x) + .bottom(-10) + .height(10) + .anchor("bottom") + .add(pv.Label) + .text(x.tickFormat); + + /* Y-axis and ticks. */ + vis.add(pv.Rule) + .data(y.ticks(6)) + .bottom(y) + .strokeStyle("rgba(128,128,128,.2)") + .anchor("left") + .add(pv.Label) + .text(y.tickFormat); + + /* The stack layout */ + var area = vis.add(pv.Layout.Stack) + .layers(trendData) + .x(function (d) { + return x(d.x); + }) + .y(function (d) { + return y(d.y); + }) + .layer + .add(pv.Area) + .fillStyle(function () { + return colors[this.parent.index % colors.size()][0]; + }) + .strokeStyle("rgba(128,128,128,.8)"); + + /* Stack labels. */ + var firstIdx = computeIdx(w / 5); + var lastIdx = computeIdx(w * 4 / 5); + vis.add(pv.Panel) + .extend(area.parent) + .add(pv.Area) + .extend(area) + .fillStyle(null) + .strokeStyle(null) + .anchor(function () { + return (idx == idx_numbers - 1 || idx > lastIdx) ? "right" : ((idx == 0 || idx < firstIdx) ? "left" : "center"); + }) + .add(pv.Label) + .visible(function (d) { + return this.index == idx && d.y != 0; + }) + .font(function (d) { + return Math.round(5 + Math.sqrt(y(d.y))) + "px sans-serif"; + }) + .textStyle("#DDD") + .text(function (d) { + return metrics[this.parent.index] + ": " + d.y; + }); + + /* The total cost of the selected dot in the header. */ + vis.add(pv.Label) + .left(8) + .top(16) + .font(headerFont) + .text(function () { + return "Total: " + total[idx]; + }); + + /* The date of the selected dot in the header. */ + vis.add(pv.Label) + .left(w / 2) + .top(16) + .font(headerFont) + .text(function () { + return snapshots[idx].ld; + }); + + + /* The event labels */ eventColor = "rgba(75,159,213,1)"; eventHoverColor = "rgba(202,227,242,1)"; vis.add(pv.Line) - .strokeStyle("rgba(0,0,0,.001)") - .data(snapshots) - .left(function(s) {return x(s.d);}) - .bottom(0) - .anchor("top") - .add(pv.Dot) - .bottom(-6) - .shape("triangle") - .angle(pv.radians(180)) - .strokeStyle("grey") - .visible(function(s) {return s.e.size() > 0;}) - .fillStyle(function() {return this.index == idx ? eventHoverColor : eventColor;}) - .add(pv.Dot) - .radius(3) - .visible(function(s) {return s.e.size() > 0 && this.index == idx;}) - .left(w/2+8) - .top(24) - .shape("triangle") - .fillStyle(function() {return this.index == idx ? eventHoverColor : eventColor;}) - .strokeStyle("grey") - .anchor("right") - .add(pv.Label) - .font(headerFont) - .text(function(s) {return s.e.size() == 0 ? "" : s.e[0] + ( s.e[1] ? " (... +" + (s.e.size()-1) + ")" : "");}); - - /* An invisible bar to capture events (without flickering). */ - vis.add(pv.Bar) - .fillStyle("rgba(0,0,0,.001)") - .width(w+30) - .height(h+30) - .event("mouseout", function() { - i = -1; - return vis; - }) - .event("mousemove", function() { - idx = computeIdx(vis.mouse().x); - return vis; - }); - - vis.render(); + .strokeStyle("rgba(0,0,0,.001)") + .data(snapshots) + .left(function (s) { + return x(s.d); + }) + .bottom(0) + .anchor("top") + .add(pv.Dot) + .bottom(-6) + .shape("triangle") + .angle(pv.radians(180)) + .strokeStyle("grey") + .visible(function (s) { + return s.e.size() > 0; + }) + .fillStyle(function () { + return this.index == idx ? eventHoverColor : eventColor; + }) + .add(pv.Dot) + .radius(3) + .visible(function (s) { + return s.e.size() > 0 && this.index == idx; + }) + .left(w / 2 + 8) + .top(24) + .shape("triangle") + .fillStyle(function () { + return this.index == idx ? eventHoverColor : eventColor; + }) + .strokeStyle("grey") + .anchor("right") + .add(pv.Label) + .font(headerFont) + .text(function (s) { + return s.e.size() == 0 ? "" : s.e[0] + ( s.e[1] ? " (... +" + (s.e.size() - 1) + ")" : ""); + }); + + /* An invisible bar to capture events (without flickering). */ + vis.add(pv.Bar) + .fillStyle("rgba(0,0,0,.001)") + .width(w + 30) + .height(h + 30) + .event("mouseout", function () { + i = -1; + return vis; + }) + .event("mousemove", function () { + idx = computeIdx(vis.mouse().x); + return vis; + }); + + vis.render(); }; - //******************* TIMELINE CHART ******************* // /* * Displays the evolution of metrics on a line chart, displaying related events. @@ -221,187 +261,226 @@ SonarWidgets.StackArea.prototype.render = function() { * * Example: displays 2 metrics: * -<code> -function d(y,m,d,h,min,s) { - return new Date(y,m,d,h,min,s); -} -var data = [ - [{x:d(2011,5,15,0,1,0),y:912.00,yl:"912"},{x:d(2011,6,21,0,1,0),y:152.10,yl:"152.10"}], - [{x:d(2011,5,15,0,1,0),y:52.20,yi:"52.20"},{x:d(2011,6,21,0,1,0),y:1452.10,yi:"1,452.10"}] - ]; -var metrics = ["Lines of code","Rules compliance"]; -var snapshots = [{sid:1,d:"June 15, 2011 00:01"},{sid:30,d:"July 21, 2011 00:01"}]; -var events = [ - {sid:1,d:d(2011,5,15,0,1,0),l:[{n:"0.6-SNAPSHOT"},{n:"Sun checks"}]}, - {sid:30,d:d(2011,6,21,0,1,0),l:[{n:"0.7-SNAPSHOT"}]} - ]; - -var timeline = new SonarWidgets.Timeline('timeline-chart-20') - .height(160) - .data(data) - .snapshots(snapshots) - .metrics(metrics) - .events(events); -timeline.render(); -</code> + <code> + function d(y,m,d,h,min,s) { + return new Date(y,m,d,h,min,s); + } + var data = [ + [{x:d(2011,5,15,0,1,0),y:912.00,yl:"912"},{x:d(2011,6,21,0,1,0),y:152.10,yl:"152.10"}], + [{x:d(2011,5,15,0,1,0),y:52.20,yi:"52.20"},{x:d(2011,6,21,0,1,0),y:1452.10,yi:"1,452.10"}] + ]; + var metrics = ["Lines of code","Rules compliance"]; + var snapshots = [{sid:1,d:"June 15, 2011 00:01"},{sid:30,d:"July 21, 2011 00:01"}]; + var events = [ + {sid:1,d:d(2011,5,15,0,1,0),l:[{n:"0.6-SNAPSHOT"},{n:"Sun checks"}]}, + {sid:30,d:d(2011,6,21,0,1,0),l:[{n:"0.7-SNAPSHOT"}]} + ]; + + var timeline = new SonarWidgets.Timeline('timeline-chart-20') + .height(160) + .data(data) + .snapshots(snapshots) + .metrics(metrics) + .events(events); + timeline.render(); + </code> * */ SonarWidgets.Timeline = function (divId) { - this.wDivId = divId; - this.wHeight; - this.wData; - this.wSnapshots; - this.wMetrics; - this.wEvents; - this.height = function(height) { - this.wHeight = height; - return this; - }; - this.data = function(data) { - this.wData = data; - return this; - }; - this.snapshots = function(snapshots) { - this.wSnapshots = snapshots; - return this; - }; - this.metrics = function(metrics) { - this.wMetrics = metrics; - return this; - }; - this.events = function(events) { - this.wEvents = events; - return this; - }; + this.wDivId = divId; + this.wHeight; + this.wData; + this.wSnapshots; + this.wMetrics; + this.wEvents; + this.height = function (height) { + this.wHeight = height; + return this; + }; + this.data = function (data) { + this.wData = data; + return this; + }; + this.snapshots = function (snapshots) { + this.wSnapshots = snapshots; + return this; + }; + this.metrics = function (metrics) { + this.wMetrics = metrics; + return this; + }; + this.events = function (events) { + this.wEvents = events; + return this; + }; }; -SonarWidgets.Timeline.prototype.render = function() { - - var trendData = this.wData; - var metrics = this.wMetrics; - var snapshots = this.wSnapshots; - var events = this.wEvents; - - var widgetDiv = $(this.wDivId); - var headerFont = "10.5px Arial,Helvetica,sans-serif"; - - /* Sizing and scales. */ - var headerHeight = 4 + Math.max(this.wMetrics.size(), events ? 2 : 1) * 18; - var w = widgetDiv.getOffsetParent().getWidth() - 60; - var h = (this.wHeight==null || this.wHeight<=0 ? 80 : this.wHeight) + headerHeight; - var yMaxHeight = h-headerHeight; - - var x = pv.Scale.linear(pv.blend(pv.map(trendData, function(d) {return d;})), function(d) {return d.x}).range(0, w); - var y = new Array(trendData.size()); - for(var i = 0; i < trendData.size(); i++){ - y[i]=pv.Scale.linear(trendData[i], function(d) {return d.y;}).range(20, yMaxHeight); - } - var interpolate = "linear"; /* cardinal or linear */ - var idx = trendData[0].size() - 1; - - /* The root panel. */ - var vis = new pv.Panel() - .canvas(widgetDiv) - .width(w) - .height(h) - .left(20) - .right(20) - .bottom(30) - .top(5) - .strokeStyle("#CCC"); - - /* X-axis */ - vis.add(pv.Rule) - .data(x.ticks()) - .left(x) - .bottom(-10) - .height(10) - .anchor("bottom") - .add(pv.Label) - .text(x.tickFormat); - - /* A panel for each data series. */ - var panel = vis.add(pv.Panel) - .data(trendData); - - /* The line. */ - var line = panel.add(pv.Line) - .data(function(array) {return array;}) - .left(function(d) {return x(d.x);}) - .bottom(function(d) {var yAxis = y[this.parent.index](d.y); return isNaN(yAxis) ? yMaxHeight : yAxis;}) - .interpolate(function() {return interpolate;}) - .lineWidth(2); - - /* The mouseover dots and label in header. */ - line.add(pv.Dot) - .data(function(d) {return [d[idx]];}) - .fillStyle(function() {return line.strokeStyle();}) - .strokeStyle("#000") - .size(20) - .lineWidth(1) - .add(pv.Dot) - .radius(3) - .left(10) - .top(function() {return 10 + this.parent.index * 14;}) - .anchor("right").add(pv.Label) - .font(headerFont) - .text(function(d) {return metrics[this.parent.index] + ": " + d.yl;}); - - /* The date of the selected dot in the header. */ - vis.add(pv.Label) - .left(w/2) - .top(16) - .font(headerFont) - .text(function() {return snapshots[idx].d;}); - - /* The event labels */ - if (events) { - eventColor = "rgba(75,159,213,1)"; - eventHoverColor = "rgba(202,227,242,1)"; - vis.add(pv.Line) - .strokeStyle("rgba(0,0,0,.001)") - .data(events) - .left(function(e) {return x(e.d);}) - .bottom(0) - .anchor("top") - .add(pv.Dot) - .bottom(-6) - .shape("triangle") - .angle(pv.radians(180)) - .strokeStyle("grey") - .fillStyle(function(e) {return e.sid == snapshots[idx].sid ? eventHoverColor : eventColor;}) - .add(pv.Dot) - .radius(3) - .visible(function(e) { return e.sid == snapshots[idx].sid;}) - .left(w/2+8) - .top(24) - .shape("triangle") - .fillStyle(function(e) {return e.sid == snapshots[idx].sid ? eventHoverColor : eventColor;}) - .strokeStyle("grey") - .anchor("right") - .add(pv.Label) - .font(headerFont) - .text(function(e) {return e.l[0].n + ( e.l[1] ? " (... +" + (e.l.size()-1) + ")" : "");}); - } - - /* An invisible bar to capture events (without flickering). */ - vis.add(pv.Bar) - .fillStyle("rgba(0,0,0,.001)") - .width(w+30) - .height(h+30) - .event("mouseout", function() { - i = -1; - return vis; - }) - .event("mousemove", function() { - var mx = x.invert(vis.mouse().x); - idx = pv.search(trendData[0].map(function(d) {return d.x;}), mx); - idx = idx < 0 ? (-idx - 2) : idx; - idx = idx < 0 ? 0 : idx; - return vis; - }); - - vis.render(); - -}
\ No newline at end of file +SonarWidgets.Timeline.prototype.render = function () { + + var trendData = this.wData; + var metrics = this.wMetrics; + var snapshots = this.wSnapshots; + var events = this.wEvents; + + var widgetDiv = $(this.wDivId); + var headerFont = "10.5px Arial,Helvetica,sans-serif"; + + /* Sizing and scales. */ + var headerHeight = 4 + Math.max(this.wMetrics.size(), events ? 2 : 1) * 18; + var w = widgetDiv.getOffsetParent().getWidth() - 60; + var h = (this.wHeight == null || this.wHeight <= 0 ? 80 : this.wHeight) + headerHeight; + var yMaxHeight = h - headerHeight; + + var x = pv.Scale.linear(pv.blend(pv.map(trendData, function (d) { + return d; + })), + function (d) { + return d.x + }).range(0, w); + var y = new Array(trendData.size()); + for (var i = 0; i < trendData.size(); i++) { + y[i] = pv.Scale.linear(trendData[i], + function (d) { + return d.y; + }).range(20, yMaxHeight); + } + var interpolate = "linear"; + /* cardinal or linear */ + var idx = trendData[0].size() - 1; + + /* The root panel. */ + var vis = new pv.Panel() + .canvas(widgetDiv) + .width(w) + .height(h) + .left(20) + .right(20) + .bottom(30) + .top(5) + .strokeStyle("#CCC"); + + /* X-axis */ + vis.add(pv.Rule) + .data(x.ticks()) + .left(x) + .bottom(-10) + .height(10) + .anchor("bottom") + .add(pv.Label) + .text(x.tickFormat); + + /* A panel for each data series. */ + var panel = vis.add(pv.Panel) + .data(trendData); + + /* The line. */ + var line = panel.add(pv.Line) + .data(function (array) { + return array; + }) + .left(function (d) { + return x(d.x); + }) + .bottom(function (d) { + var yAxis = y[this.parent.index](d.y); + return isNaN(yAxis) ? yMaxHeight : yAxis; + }) + .interpolate(function () { + return interpolate; + }) + .lineWidth(2); + + /* The mouseover dots and label in header. */ + line.add(pv.Dot) + .data(function (d) { + return [d[idx]]; + }) + .fillStyle(function () { + return line.strokeStyle(); + }) + .strokeStyle("#000") + .size(20) + .lineWidth(1) + .add(pv.Dot) + .radius(3) + .left(10) + .top(function () { + return 10 + this.parent.index * 14; + }) + .anchor("right").add(pv.Label) + .font(headerFont) + .text(function (d) { + return metrics[this.parent.index] + ": " + d.yl; + }); + + /* The date of the selected dot in the header. */ + vis.add(pv.Label) + .left(w / 2) + .top(16) + .font(headerFont) + .text(function () { + return snapshots[idx].d; + }); + + /* The event labels */ + if (events) { + eventColor = "rgba(75,159,213,1)"; + eventHoverColor = "rgba(202,227,242,1)"; + vis.add(pv.Line) + .strokeStyle("rgba(0,0,0,.001)") + .data(events) + .left(function (e) { + return x(e.d); + }) + .bottom(0) + .anchor("top") + .add(pv.Dot) + .bottom(-6) + .shape("triangle") + .angle(pv.radians(180)) + .strokeStyle("grey") + .fillStyle(function (e) { + return e.sid == snapshots[idx].sid ? eventHoverColor : eventColor; + }) + .add(pv.Dot) + .radius(3) + .visible(function (e) { + return e.sid == snapshots[idx].sid; + }) + .left(w / 2 + 8) + .top(24) + .shape("triangle") + .fillStyle(function (e) { + return e.sid == snapshots[idx].sid ? eventHoverColor : eventColor; + }) + .strokeStyle("grey") + .anchor("right") + .add(pv.Label) + .font(headerFont) + .text(function (e) { + return e.l[0].n + ( e.l[1] ? " (... +" + (e.l.size() - 1) + ")" : ""); + }); + } + + /* An invisible bar to capture events (without flickering). */ + vis.add(pv.Bar) + .fillStyle("rgba(0,0,0,.001)") + .width(w + 30) + .height(h + 30) + .event("mouseout", function () { + i = -1; + return vis; + }) + .event("mousemove", function () { + var mx = x.invert(vis.mouse().x); + idx = pv.search(trendData[0].map(function (d) { + return d.x; + }), mx); + idx = idx < 0 ? (-idx - 2) : idx; + idx = idx < 0 ? 0 : idx; + return vis; + }); + + vis.render(); +};
\ 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 new file mode 100644 index 00000000000..11e8627b59f --- /dev/null +++ b/sonar-server/src/main/webapp/javascripts/resource.js @@ -0,0 +1,181 @@ +/* + Functions used in resource viewers + */ + +function loadResourceViewer(resourceId, tab, display_title) { + $('resource_loading').show(); + if (display_title == undefined) { + display_title = true; + } + new Ajax.Updater('resource_container', baseUrl + '/resource/index/' + resourceId + '?tab=' + tab + '&display_title=' + display_title, {asynchronous:true, evalScripts:true}); + return false; +} + +// Display GWT component +function loadGWT(gwtId, resourceId, resourceKey, resourceName, resourceScope, resourceQualifier, resourceLanguage) { + config["resource"] = [ + {"id":resourceId, "key":resourceKey, "name":resourceName, "scope":resourceScope, "qualifier":resourceQualifier, "lang":resourceLanguage} + ]; + config["resource_key"] = resourceId; + modules[gwtId](); +} + +// show violation actions +function sVA(violation_id) { + var elt = $('vMsg' + violation_id); + if (elt != null) { + elt.hide(); + } + elt = $('vActions' + violation_id); + if (elt != null) { + elt.show(); + } + return false; +} + +// hide violation actions +function hVA(violation_id) { + var elt = $('vMsg' + violation_id); + if (elt != null) { + elt.show(); + } + elt = $('vActions' + violation_id); + if (elt != null) { + elt.hide(); + } + return false; +} + +// cancel action : hide form and refresh violation +function cancelViolationAction(violation_id) { + new Ajax.Updater( + 'vId' + violation_id, + baseUrl + '/reviews/display_violation/' + violation_id, + { + asynchronous:true, + evalScripts:true + }); + return false; +} + +// show the form to comment violation +function sCF(violation_id) { + new Ajax.Updater('reviewForm' + violation_id, + baseUrl + '/reviews/violation_comment_form/' + violation_id, + { + asynchronous:true, + evalScripts:true, + onComplete:function (request) { + $('vBody' + violation_id).remove(); + $('reviewForm' + violation_id).show(); + $('commentText' + violation_id).focus(); + } + }); + return false; +} + +// show the form to change severity +function sCSF(violation_id) { + new Ajax.Updater('reviewForm' + violation_id, + baseUrl + '/reviews/violation_change_severity_form/' + violation_id, + { + asynchronous:true, + evalScripts:true, + onComplete:function (request) { + $('vBody' + violation_id).remove(); + $('reviewForm' + violation_id).show(); + $('selectSeverity' + violation_id).focus(); + } + }); + return false; +} + +// show the form to change status +function sCStF(violation_id) { + new Ajax.Updater('reviewForm' + violation_id, + baseUrl + '/reviews/violation_change_status_form/' + violation_id, + { + asynchronous:true, + evalScripts:true, + onComplete:function (request) { + $('vBody' + violation_id).remove(); + $('reviewForm' + violation_id).show(); + $('commentText' + violation_id).focus(); + } + }); + return false; +} + +// show the form to flag as false-positive +function sFPF(violation_id) { + new Ajax.Updater('reviewForm' + violation_id, + baseUrl + '/reviews/violation_false_positive_form/' + violation_id, + { + asynchronous:true, + evalScripts:true, + onComplete:function (request) { + $('vBody' + violation_id).remove(); + $('reviewForm' + violation_id).show(); + $('commentText' + violation_id).focus(); + } + }); + return false; +} + +// show the form to assign violation +function sAF(violation_id) { + new Ajax.Updater('reviewForm' + violation_id, + baseUrl + '/reviews/violation_assign_form/' + violation_id, + { + asynchronous:true, + evalScripts:true, + onComplete:function (request) { + $('vBody' + violation_id).remove(); + $('reviewForm' + violation_id).show(); + $('assignee_login').focus(); + } + }); + return false; +} + +// show the form to link a review to an action plan +function sAPF(violation_id) { + new Ajax.Updater('reviewForm' + violation_id, + baseUrl + '/reviews/violation_action_plan_form/' + violation_id, + { + asynchronous:true, + evalScripts:true, + onComplete:function (request) { + $('vBody' + violation_id).remove(); + $('reviewForm' + violation_id).show(); + $('action_plan').focus(); + } + }); + return false; +} + +// show the form to create violation +function sVF(resource, line, gray_colspan, white_colspan) { + row = $('createViolationForm' + line); + if (row == null) { + new Ajax.Updater( + 'pos' + line, + baseUrl + '/resource/show_create_violation_form', + { + parameters:{resource:resource, line:line, gray_colspan:gray_colspan, white_colspan:white_colspan}, + asynchronous:true, + evalScripts:true, + insertion:'after' + }); + } + return false; +} + +// hide review form +function hVF(line) { + row = $('createViolationRow' + line); + if (row != null) { + row.remove(); + } + return false; +}
\ No newline at end of file |