diff options
author | simonbrandhof <simon.brandhof@gmail.com> | 2011-03-02 14:49:14 +0100 |
---|---|---|
committer | simonbrandhof <simon.brandhof@gmail.com> | 2011-03-02 14:49:14 +0100 |
commit | 3635c6c5f851ebbc6ca3e3a11f4f687570884d6e (patch) | |
tree | 52319abb38679afd2355107f35f61275a40cd184 /sonar-server | |
parent | 81a28a44dde692fd30f2f2196ace32bff229f892 (diff) | |
download | sonarqube-3635c6c5f851ebbc6ca3e3a11f4f687570884d6e.tar.gz sonarqube-3635c6c5f851ebbc6ca3e3a11f4f687570884d6e.zip |
SONAR-2218 display headers of source, coverage and violations tabs
Diffstat (limited to 'sonar-server')
13 files changed, 648 insertions, 184 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java b/sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java new file mode 100644 index 00000000000..e49af9fe149 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java @@ -0,0 +1,94 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 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 + */ +package org.sonar.server.ui; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.resources.Resource; +import org.sonar.api.web.*; + +/** + * @since 2.7 + */ +public final class DefaultPages { + + private static final View[] PAGES = {new SourceTab(), new CoverageTab(), new ViolationsTab()}; + + public static View[] getPages() { + return PAGES; + } + + @ResourceScope(Resource.SCOPE_ENTITY) + @NavigationSection(NavigationSection.RESOURCE_TAB) + @DefaultTab + @UserRole(UserRole.CODEVIEWER) + private static final class SourceTab implements RubyRailsPage { + public String getTemplate() { + //not used, hardcoded in BrowseController + return "browse/index"; + } + + public String getId() { + return "source"; + } + + public String getTitle() { + return "Source"; + } + } + + + @ResourceQualifier(Resource.QUALIFIER_CLASS) + @NavigationSection(NavigationSection.RESOURCE_TAB) + @DefaultTab(metrics = {CoreMetrics.COVERAGE_KEY, CoreMetrics.LINES_TO_COVER_KEY, CoreMetrics.UNCOVERED_LINES_KEY, CoreMetrics.LINE_COVERAGE_KEY, CoreMetrics.CONDITIONS_TO_COVER_KEY, CoreMetrics.UNCOVERED_CONDITIONS_KEY, CoreMetrics.BRANCH_COVERAGE_KEY}) + @UserRole(UserRole.CODEVIEWER) + private static final class CoverageTab implements RubyRailsPage { + public String getTemplate() { + //not used, hardcoded in BrowseController + return "browse/index"; + } + + public String getId() { + return "coverage"; + } + + public String getTitle() { + return "Coverage"; + } + } + + @NavigationSection(NavigationSection.RESOURCE_TAB) + @DefaultTab(metrics = {CoreMetrics.VIOLATIONS_DENSITY_KEY, CoreMetrics.WEIGHTED_VIOLATIONS_KEY, CoreMetrics.VIOLATIONS_KEY, CoreMetrics.BLOCKER_VIOLATIONS_KEY, CoreMetrics.CRITICAL_VIOLATIONS_KEY, CoreMetrics.MAJOR_VIOLATIONS_KEY, CoreMetrics.MINOR_VIOLATIONS_KEY, CoreMetrics.INFO_VIOLATIONS_KEY}) + @ResourceQualifier({Resource.QUALIFIER_CLASS, Resource.QUALIFIER_FILE}) + @UserRole(UserRole.CODEVIEWER) + private static final class ViolationsTab implements RubyRailsPage { + public String getTemplate() { + //not used, hardcoded in BrowseController + return "browse/index"; + } + + public String getId() { + return "violations"; + } + + public String getTitle() { + return "Violations"; + } + } +} 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 06675cd00c8..d0544c03692 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 @@ -28,7 +28,6 @@ import org.sonar.api.ServerComponent; import org.sonar.api.profiles.ProfileExporter; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.resources.Language; -import org.sonar.api.rules.DefaultRulesManager; import org.sonar.api.rules.RuleRepository; import org.sonar.api.utils.ValidationMessages; import org.sonar.api.web.*; @@ -132,6 +131,10 @@ public final class JRubyFacade implements ServerComponent { return getContainer().getComponent(Views.class).getPages(NavigationSection.RESOURCE_TAB, null, null, null); } + public List<ViewProxy<Page>> getResourceTabs(String scope, String qualifier, String language) { + return getContainer().getComponent(Views.class).getPages(NavigationSection.RESOURCE_TAB, scope, qualifier, language); + } + public ViewProxy<Page> getPage(String id) { return getContainer().getComponent(Views.class).getPage(id); } diff --git a/sonar-server/src/main/java/org/sonar/server/ui/Views.java b/sonar-server/src/main/java/org/sonar/server/ui/Views.java index 94b789eda46..d1bf0e9c80d 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/Views.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/Views.java @@ -40,16 +40,23 @@ public class Views implements ServerComponent { } public Views(View[] views) { + for (View view : DefaultPages.getPages()) { + register(view); + } for (View view : views) { - ViewProxy proxy = new ViewProxy(view); - if (view instanceof Widget) { - widgets.add(proxy); - widgetsPerId.put(proxy.getId(), proxy); - - } else if (view instanceof Page) { - pagesPerId.put(proxy.getId(), proxy); - pages.add(proxy); - } + register(view); + } + } + + private void register(View view) { + ViewProxy proxy = new ViewProxy(view); + if (view instanceof Widget) { + widgets.add(proxy); + widgetsPerId.put(proxy.getId(), proxy); + + } else if (view instanceof Page) { + pagesPerId.put(proxy.getId(), proxy); + pages.add(proxy); } } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/browse_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/browse_controller.rb index 5021fe3eefc..bacf6c73325 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/browse_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/browse_controller.rb @@ -27,7 +27,23 @@ class BrowseController < ApplicationController if (@resource && has_role?(:user, @resource)) @snapshot=@resource.last_snapshot - render_resource() + + params[:layout]='false' + load_extensions() + + if @extension + if (@extension.getId()=='violations') + render_violations() + elsif (@extension.getId()=='coverage') + render_coverage() + elsif (@extension.getId()=='source') + render_source() + else + render_extension() + end + else + render_nothing() + end else access_denied end @@ -35,8 +51,23 @@ class BrowseController < ApplicationController private + def load_extensions + @extensions=[] + java_facade.getResourceTabs(@resource.scope, @resource.qualifier, @resource.language).each do |tab| + tab.getUserRoles().each do |role| + if has_role?(role, @resource) + @extensions<<tab + break + end + end + end - def render_resource + selected_tab_id=params[:tab] + @extension=@extensions.find{|extension| extension.getId()==selected_tab_id} unless selected_tab_id.blank? + @extension=@extensions.find{|extension| extension.isDefaultTab()} if @extension==nil + end + + def load_sources @period = params[:period].to_i unless params[:period].blank? @expanded=(params[:expand]=='true') @@ -57,19 +88,9 @@ class BrowseController < ApplicationController line.datetime=(date_string ? DateTime::strptime(date_string): nil) end end - - if (params[:tab]=='violations') - load_violations_tab() - elsif (params[:tab]=='coverage') - load_coverage_tab() - else - load_source_tab() - end - - params[:layout]='false' end - def load_scm() + def load_scm @scm_available=(@snapshot.measure('last_commit_datetimes_by_line')!=nil) @display_scm=(params[:scm]=='true') if @display_scm @@ -88,7 +109,8 @@ class BrowseController < ApplicationController m ? m.data_as_line_distribution() : {} end - def load_coverage_tab + def render_coverage + load_sources() @display_coverage=true @hits_by_line=load_distribution('coverage_line_hits_data') @conditions_by_line=load_distribution('conditions_by_line') @@ -104,9 +126,13 @@ class BrowseController < ApplicationController end filter_lines_by_date() + render :action => 'index' end - def load_violations_tab + + + def render_violations + load_sources() @display_violations=true @global_violations=[] @expandable=true @@ -135,7 +161,8 @@ class BrowseController < ApplicationController end end - RuleFailure.find(:all, :include => 'rule', :conditions => [conditions] + values, :order => 'failure_level DESC').each do |violation| + @violations=RuleFailure.find(:all, :include => 'rule', :conditions => [conditions] + values, :order => 'failure_level DESC') + @violations.each do |violation| # sorted by severity => from blocker to info if violation.line && violation.line>0 @lines[violation.line-1].add_violation(violation) @@ -155,12 +182,19 @@ class BrowseController < ApplicationController end end end + render :action => 'index' end + + + - def load_source_tab + def render_source + load_sources() filter_lines_by_date() + render :action => 'index' end + def filter_lines_by_date if @period date=@snapshot.period_datetime(@period) @@ -201,4 +235,15 @@ class BrowseController < ApplicationController @datetime ? @datetime.to_date : nil end end + + + + + def render_extension() + render :action => 'extension' + end + +def render_nothing() + render :action => 'nothing' + end end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_coverage.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_coverage.html.erb new file mode 100644 index 00000000000..696f331c72c --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_coverage.html.erb @@ -0,0 +1,40 @@ +<div id="coverage_header" class="tab_header"> + <table class="col"> + <tr> + <td class="big"><%= format_measure('coverage', :default => '-') -%></td> + </tr> + </table> + + <table class="col"> + <% if m=measure('line_coverage') %> + <tr> + <td class="name">Line coverage:</td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('uncovered_lines') %> + <tr> + <td class="name">Uncovered lines:</td> + <td class="value"><%= format_measure(m) -%> / <%= format_measure('lines_to_cover') -%></td> + </tr> + <% end %> + </table> + + <table class="col"> + <% if m=measure('branch_coverage') %> + <tr> + <td class="name">Branch coverage:</td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('uncovered_conditions') %> + <tr> + <td class="name">Uncovered conditions:</td> + <td class="value"><%= format_measure(m) -%> / <%= format_measure('conditions_to_cover') -%></td> + </tr> + <% end %> + </table> + + <div class="clear"></div> +</div> + diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_source.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_source.html.erb new file mode 100644 index 00000000000..dd0e808d83a --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_source.html.erb @@ -0,0 +1,139 @@ +<div id="source_header" class="tab_header"> + <table class="col"> + <% if m=measure('lines') %> + <tr> + <td class="name">Lines: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('ncloc') %> + <tr> + <td class="name">Lines of code: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('functions') %> + <tr> + <td class="name">Methods: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('accessors') %> + <tr> + <td class="name">Accessors: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('paragraphs') %> + <tr> + <td class="name">Paragraphs: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + </table> + + <table class="col"> + <% if m=measure('statements') %> + <tr> + <td class="name">Statements: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('complexity') %> + <tr> + <td class="name">Complexity: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('function_complexity') %> + <tr> + <td class="name">Complexity/method: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('paragraph_complexity') %> + <tr> + <td class="name">Complexity/paragraph: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + </table> + + <table class="col"> + <% if m=measure('comment_lines_density') %> + <tr> + <td class="name">Comments: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('comment_lines') %> + <tr> + <td class="name">Comment lines: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('commented_out_code_lines') %> + <tr> + <td class="name">Commented-out LOC: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('comment_blank_lines') %> + <tr> + <td class="name">Blank comments: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + </table> + + <table class="col"> + <% if m=measure('public_documented_api_density') %> + <tr> + <td class="name">Public documented API: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('public_undocumented_api') %> + <tr> + <td class="name">Public undocumented API: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('public_api') %> + <tr> + <td class="name">Public API: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + </table> + + <table class="col"> + <% if m=measure('classes') %> + <tr> + <td class="name">Classes: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('noc') %> + <tr> + <td class="name">Number of Children: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('dit') %> + <tr> + <td class="name">Depth in Tree: </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + <% if m=measure('rfc') %> + <tr> + <td class="name">Response for Class (RFC): </td> + <td class="value"><%= format_measure(m) -%></td> + </tr> + <% end %> + </table> + + <div class="clear"></div> +</div> + diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_violations.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_violations.html.erb new file mode 100644 index 00000000000..ad5aadeed0d --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_header_violations.html.erb @@ -0,0 +1,38 @@ +<div id="violations_header" class="tab_header"> + <table class="col"> + <tr> + <td><span class="big"><%= format_measure('violations', :default => '-') -%></span> violations</td> + </tr> + </table> + + <table class="col"> + <tr> + <td><%= image_tag 'priority/BLOCKER.png'-%></td> + <td class="name">Blocker:</td> + <td class="value"><%= format_measure('blocker_violations', :default => 0) -%></td> + </tr> + <tr> + <td><%= image_tag 'priority/CRITICAL.png'-%></td> + <td class="name">Critical:</td> + <td class="value"><%= format_measure('critical_violations', :default => 0) -%></td> + </tr> + <tr> + <td><%= image_tag 'priority/MAJOR.png'-%></td> + <td class="name">Major:</td> + <td class="value"><%= format_measure('major_violations', :default => 0) -%></td> + </tr> + <tr> + <td><%= image_tag 'priority/MINOR.png'-%></td> + <td class="name">Minor:</td> + <td class="value"><%= format_measure('minor_violations', :default => 0) -%></td> + </tr> + <tr> + <td><%= image_tag 'priority/INFO.png'-%></td> + <td class="name">Info:</td> + <td class="value"><%= format_measure('info_violations', :default => 0) -%></td> + </tr> + </table> + + <div class="clear"></div> +</div> + diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_rules_filter.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_rules_filter.html.erb new file mode 100644 index 00000000000..cd37ea4255e --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_rules_filter.html.erb @@ -0,0 +1,47 @@ +<% + blocker_violations = @snapshot.measure('blocker_violations') + critical_violations = @snapshot.measure('critical_violations') + major_violations = @snapshot.measure('major_violations') + minor_violations = @snapshot.measure('minor_violations') + info_violations = @snapshot.measure('info_violations') + + rule_counts={} + rules=[] + + @violations.each do |violation| + count=(rule_counts[violation.rule_id]||0) +1 + rule_counts[violation.rule_id]=count + rules<<violation.rule + end + + + rule_options=[] + rules.uniq.sort_by{|rule| rule.name}.each do |rule| + rule_options<<["#{h rule.name} (#{rule_counts[rule.id]})", rule.key] + end +%> +<select id="rule" name="rule" class="small" onchange="submit()"> + <option value="">No filters</option> + <optgroup label="Severity"> + <% if blocker_violations && blocker_violations.value>0 %> + <option value="<%= Sonar::RulePriority::PRIORITY_BLOCKER-%>" <%= 'selected' if params[:rule]==Sonar::RulePriority::PRIORITY_BLOCKER.to_s -%>>Blocker (<%= blocker_violations.formatted_value -%>)</option> + <% end %> + <% if critical_violations && critical_violations.value>0 %> + <option value="<%= Sonar::RulePriority::PRIORITY_CRITICAL -%>" <%= 'selected' if params[:rule]==Sonar::RulePriority::PRIORITY_CRITICAL.to_s -%>>Critical (<%= critical_violations.formatted_value -%>)</option> + <% end %> + <% if major_violations && major_violations.value>0 %> + <option value="<%= Sonar::RulePriority::PRIORITY_MAJOR -%>" <%= 'selected' if params[:rule]==Sonar::RulePriority::PRIORITY_MAJOR.to_s -%>>Major (<%= major_violations.formatted_value -%>)</option> + <% end %> + <% if minor_violations && minor_violations.value>0 %> + <option value="<%= Sonar::RulePriority::PRIORITY_MINOR -%>" <%= 'selected' if params[:rule]==Sonar::RulePriority::PRIORITY_MINOR.to_s -%>>Minor (<%= minor_violations.formatted_value -%>)</option> + <% end %> + <% if info_violations && info_violations.value>0 %> + <option value="<%= Sonar::RulePriority::PRIORITY_INFO -%>" <%= 'selected' if params[:rule]==Sonar::RulePriority::PRIORITY_INFO.to_s -%>>Info (<%= info_violations.formatted_value -%>)</option> + <% end %> + </optgroup> + + + <optgroup label="Rule"> + <%= options_for_select(rule_options, params[:rule]) -%> + </optgroup> +</select>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_tabs.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_tabs.html.erb new file mode 100644 index 00000000000..bfa00de46dd --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/_tabs.html.erb @@ -0,0 +1,168 @@ +<style> +#source_metrics { + width: 100%; +} +#source_metrics { + width: 100%; +} +.sources2 { + width: 100%; + border-top: 1px solid #DDD; + border-bottom: 1px solid #DDD; + margin: 0; +} +.sources2 td.lid { + background-color: #ECECEC; + border-right: 1px solid #DDDDDD; + border-left: 1px solid #DDDDDD; + text-align: right; + padding: 2px 0.5em 0 0.5em; + vertical-align: top; + font-size: 11px; +} +.sources2 td.lid a { + text-decoration: none; + color: #AAA; +} +.sources2 td.scm { + border-right: 1px solid #DDD; + border-left: 1px solid #DDD; + background-color: #ECECEC; +} +.sources2 td.revision { + border-top: 1px solid #DDD; + vertical-align: top; + padding: 2px 0.3em; + white-space: nowrap; +} +.sources2 span.date, .sources2 span.date a { + color: #AAA; + font-size: 11px; + text-decoration: none; +} +.sources2 span.author, .sources2 span.author a { + font-size: 11px; +} +.sources2 td.rule { + padding: 1px 0.5em; + border-left: 1px solid #DDDDDD; +} +.sources2 td.violations { + background-color: #ECECEC; + min-width: 450px; +} +span.rulename, span.rulename a { + color: #4183C4; + text-decoration: none; +} +span.violation_date { + color: #AAA; + font-size: 11px; +} +span.rulename a:hover { + text-decoration: underline; +} +.sources2 td.violations img { + vertical-align: sub; +} +.sources2 td.line { + padding-left: 1em; + width: 100%; + white-space: pre; + font-size: 12px; + font-family: monospace; + border-right: 1px solid #DDD; +} +.sources2 td.section { + border-top: 1px solid #DDD; + border-bottom: 1px solid #DDD; +} +.sources2 td.ind { + border-right: 1px solid #DDD; + min-width: 1.5em; + padding: 0 0.3em; + text-align: center; + vertical-align: middle; +} +.sources2 td.ok { + background-color: #ACE97C; + border-top: 1px solid #6EC563; + border-bottom: 1px solid #6EC563; +} +.sources2 td.sev0, .sources2 td.sev1, .sources2 td.warn { + /* info, minor */ + background-color: #FFF6BF; + border-top: 1px solid #FFD324; + border-bottom: 1px solid #FFD324; +} +.sources2 td.sev2, .sources2 td.sev3, .sources2 td.sev4, .sources2 td.ko { + /* major, critical, blocker */ + background-color: #FF9090; + border-top: 1px solid #FF5252; + border-bottom: 1px solid #FF5252; +} +.sources2 td.new_section { + border-top: 1px solid #DDD; + border-bottom: 1px solid #DDD; + height: 40px; +} +#source_title { + padding: 10px 0; +} +#source_title span.h1 { + font-size: 16px; + margin-right: 10px; +} +.source_links { + font-size: 11px; +} +#global_violations { + width: 100%; + border: 1px solid #DDD; + margin-bottom: 10px; +} +#global_violations td { + background-color: #ECECEC; + padding: 3px 0.5em; +} +#global_violations td img, #source_title img { + vertical-align: sub; +} +.tab_header { + width: 100%; + border: 1px solid #DDD; + border-top-width: 0; + background-color: #ECECEC; + padding: 5px 10px; + margin-bottom: 10px; + color: #555555; +} + +.tab_header table.col { + margin-right: 30px; + float: left; +} +.tab_header td { + padding-right: 7px; +} +.tab_header td.name { + font-weight: bold; + text-align: left; +} +.tab_header td.value { + text-align: right; +} +</style> + +<div id="source_title"> + <span class="h1"><%= qualifier_icon(@resource) -%> <%= @resource.long_name -%></span> + <% if @lines %> + | <span class="source_link"><a href="<%= ApplicationController.root_context -%>/api/sources?resource=<%= @resource.key -%>&format=txt">raw</a></span> + <% end %> +</div> + +<ul id="source_tabs" class="tabs"> + <% @extensions.each do |extension| %> + <li><a href="<%= url_for(:overwrite_params => {:tab => extension.getId()}) -%>" class="<%= 'selected' if @extension.getId()==extension.getId() -%>"><%= extension.getTitle() -%></a></li> + <% end %> +</ul> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/extension.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/extension.html.erb new file mode 100644 index 00000000000..f45db54fb12 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/extension.html.erb @@ -0,0 +1,16 @@ +<%= render :partial => 'tabs' -%> + +<% if @extension.isGwt() %> + <%= render :partial => 'gwt/base', :locals => {:resource => @resource, :popup => false, :metric => nil} -%> + + <div id="gwtpage"> </div> + + <!-- for SmartGWT --> + <script> var isomorphicDir = "<%= "#{ApplicationController.root_context}/deploy/gwt/#{@extension.getId()}" -%>/sc/";</script> + + + <script src="<%= ApplicationController.root_context -%>/deploy/gwt/<%= @extension.getId() -%>/<%= @extension.getId() -%>.nocache.js?<%= sonar_version -%>"></script> + +<% else # ruby on rails page %> + <%= render :inline => @page.getTemplate() %> +<% end %>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/index.html.erb index 202b3fb2b4a..da557c0651c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/index.html.erb @@ -1,149 +1,19 @@ -<style> -#source_metrics { - width: 100%; -} -#source_metrics { - width: 100%; -} -.sources2 { - width: 100%; - border-top: 1px solid #DDD; - border-bottom: 1px solid #DDD; - margin: 0; -} -.sources2 td.lid { - background-color: #ECECEC; - border-right: 1px solid #DDDDDD; - border-left: 1px solid #DDDDDD; - text-align: right; - padding: 2px 0.5em 0 0.5em; - vertical-align: top; - font-size: 11px; -} -.sources2 td.lid a { - text-decoration: none; - color: #AAA; -} -.sources2 td.scm { - border-right: 1px solid #DDD; - border-left: 1px solid #DDD; - background-color: #ECECEC; -} -.sources2 td.revision { - border-top: 1px solid #DDD; - vertical-align: top; - padding: 2px 0.3em; - white-space: nowrap; -} -.sources2 span.date, .sources2 span.date a { - color: #AAA; - font-size: 11px; - text-decoration: none; -} -.sources2 span.author, .sources2 span.author a { - font-size: 11px; -} -.sources2 td.rule { - padding: 1px 0.5em; - border-left: 1px solid #DDDDDD; -} -.sources2 td.violations { - background-color: #ECECEC; - min-width: 450px; -} -span.rulename, span.rulename a { - color: #4183C4; - text-decoration: none; -} -span.violation_date { - color: #AAA; - font-size: 11px; -} -span.rulename a:hover { - text-decoration: underline; -} -.sources2 td.violations img { - vertical-align: sub; -} -.sources2 td.line { - padding-left: 1em; - width: 100%; - white-space: pre; - font-size: 12px; - font-family: monospace; - border-right: 1px solid #DDD; -} -.sources2 td.section { - border-top: 1px solid #DDD; - border-bottom: 1px solid #DDD; -} -.sources2 td.ind { - border-right: 1px solid #DDD; - min-width: 1.5em; - padding: 0 0.3em; - text-align: center; - vertical-align: middle; -} -.sources2 td.ok { - background-color: #ACE97C; - border-top: 1px solid #6EC563; - border-bottom: 1px solid #6EC563; -} -.sources2 td.sev0, .sources2 td.sev1, .sources2 td.warn { - /* info, minor */ - background-color: #FFF6BF; - border-top: 1px solid #FFD324; - border-bottom: 1px solid #FFD324; -} -.sources2 td.sev2, .sources2 td.sev3, .sources2 td.sev4, .sources2 td.ko { - /* major, critical, blocker */ - background-color: #FF9090; - border-top: 1px solid #FF5252; - border-bottom: 1px solid #FF5252; -} -.sources2 td.new_section { - border-top: 1px solid #DDD; - border-bottom: 1px solid #DDD; - height: 40px; -} -#source_title { - padding: 10px 0; -} -#source_title span.h1 { - font-size: 16px; - margin-right: 10px; -} -.source_links { - font-size: 11px; -} -#global_violations { - width: 100%; - border: 1px solid #DDD; - margin-bottom: 10px; -} -#global_violations td { - background-color: #ECECEC; - padding: 3px 0.5em; -} -#global_violations td img, #source_title img { - vertical-align: sub; -} -</style> +<%= render :partial => 'tabs' -%> + +<%= render :partial => "browse/header_#{@extension.getId()}" -%> -<div id="source_title"> - <span class="h1"><%= qualifier_icon(@resource) -%> <%= @resource.long_name -%></span> - <% if @lines %> - | <span class="source_link"><a href="<%= ApplicationController.root_context -%>/api/sources?resource=<%= @resource.key -%>&format=txt">raw</a></span> - <% end %> -</div> -<ul id="source_tabs" class="tabs"> - <li><a href="<%= url_for(:overwrite_params => {:tab => 'source'}) -%>" class="<%= 'selected' if params[:tab]=='source' || params[:tab].blank? -%>">source</a></li> - <li><a href="<%= url_for(:overwrite_params => {:tab => 'coverage'}) -%>" class="<%= 'selected' if params[:tab]=='coverage' -%>">coverage</a></li> - <li><a href="<%= url_for(:overwrite_params => {:tab => 'violations'}) -%>" class="<%= 'selected' if params[:tab]=='violations' -%>">violations</a></li> -</ul> +<% if @display_violations && @global_violations && @global_violations.size>0 -%> + <table id="global_violations" cellpadding="0" cellspacing="0" border="0"> + <% @global_violations.each do |violation| %> + <tr> + <td><%= render :partial => 'violation', :locals => {:violation => violation} -%></td> + </tr> + <% end %> + </table> +<% end %> -<div id="source_header"> +<div id="source_options"> <form method="GET" action="<%= url_for :controller => 'browse', :id => @resource.key -%>"> <input type="hidden" name="tab" value="<%= params[:tab] -%>"/> <% if @scm_available %> @@ -166,19 +36,11 @@ span.rulename a:hover { <input type="checkbox" value="true" name="expand" id="expand" <%= 'checked' if @expanded -%> onclick="submit()"/> <label for="expand">Expand</label> <% end %> + + <%= render :partial => 'rules_filter' if @display_violations -%> </form> </div> -<% if @display_violations && @global_violations && @global_violations.size>0 -%> - <table id="global_violations" cellpadding="0" cellspacing="0" border="0"> - <% @global_violations.each do |violation| %> - <tr> - <td><%= render :partial => 'violation', :locals => {:violation => violation} -%></td> - </tr> - <% end %> - </table> -<% end %> - <% if @lines && @lines.size>0 %> <table id="sources" class="sources2 code" cellpadding="0" cellspacing="0" border="0"> <% diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/browse/nothing.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/nothing.html.erb new file mode 100644 index 00000000000..d22506de4cf --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/browse/nothing.html.erb @@ -0,0 +1 @@ +<%= render :partial => 'tabs' -%>
\ No newline at end of file diff --git a/sonar-server/src/test/java/org/sonar/server/ui/ViewsTest.java b/sonar-server/src/test/java/org/sonar/server/ui/ViewsTest.java index b05a115d532..c1930b2e136 100644 --- a/sonar-server/src/test/java/org/sonar/server/ui/ViewsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/ui/ViewsTest.java @@ -32,12 +32,16 @@ import java.util.List; import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; +import static org.junit.matchers.JUnitMatchers.hasItem; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class ViewsTest { - private static final View[] VIEWS = {new FakePage(), new FakeResourceViewer(), new FakeWidget()}; + private static FakeResourceViewer FAKE_TAB = new FakeResourceViewer(); + private static FakeWidget FAKE_WIDGET = new FakeWidget(); + private static FakePage FAKE_PAGE = new FakePage(); + private static final View[] VIEWS = {FAKE_PAGE, FAKE_TAB, FAKE_WIDGET}; @Test public void getPageById() { @@ -63,9 +67,9 @@ public class ViewsTest { @Test public void getResourceViewers() { final Views views = new Views(VIEWS); - List<ViewProxy<Page>> resourceViewers = views.getPages(NavigationSection.RESOURCE_TAB); - assertThat(resourceViewers.size(), is(1)); - assertThat(resourceViewers.get(0).getTarget(), is(FakeResourceViewer.class)); + List resourceViewers = views.getPages(NavigationSection.RESOURCE_TAB); + assertThat(resourceViewers.size(), is(1 + 3 /* default */)); + assertThat(resourceViewers.contains(new ViewProxy((View)FAKE_TAB)), is(true)); } @Test |