]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4406 Rework design page
authorStas Vilchik <vilchiks@gmail.com>
Thu, 14 Aug 2014 07:46:43 +0000 (13:46 +0600)
committerStas Vilchik <vilchiks@gmail.com>
Thu, 14 Aug 2014 07:47:45 +0000 (13:47 +0600)
server/sonar-web/src/main/coffee/design/info-view.coffee [new file with mode: 0644]
server/sonar-web/src/main/coffee/design/view.coffee
server/sonar-web/src/main/hbs/design/design.hbs
server/sonar-web/src/main/hbs/design/dsm-info.hbs [new file with mode: 0644]
server/sonar-web/src/main/js/common/handlebars-extensions.js
server/sonar-web/src/main/less/dsm.less
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/design_controller.rb

diff --git a/server/sonar-web/src/main/coffee/design/info-view.coffee b/server/sonar-web/src/main/coffee/design/info-view.coffee
new file mode 100644 (file)
index 0000000..8020d88
--- /dev/null
@@ -0,0 +1,11 @@
+define [
+  'backbone.marionette',
+  'templates/design'
+], (
+  Marionette,
+  Templates
+) ->
+
+
+  class extends Marionette.ItemView
+    template: Templates['dsm-info']
index 6d788a39bbb7dcdba458c49f4bf5b422aa09f98c..10f24f8a7525f118f9dc860ba5617e2d11eee574 100644 (file)
 define [
   'backbone.marionette',
+  'design/info-view',
   'templates/design'
 ], (
   Marionette,
+  InfoView
   Templates
 ) ->
 
   $ = jQuery
+  API_DEPENDECIES = "#{baseUrl}/api/dependencies"
 
 
 
-  class AppLayout extends Marionette.Layout
+  class extends Marionette.Layout
     template: Templates['design']
     className: 'dsm'
 
 
+    regions:
+      infoRegion: '.dsm-info'
+
+
     ui:
       titles: '.dsm-body-title'
+      cells: '.dsm-body-cell'
+      dependencies: '.dsm-body-dependency'
 
 
     events:
       'click @ui.titles': 'highlightComponent'
+      'dblclick @ui.titles': 'goToComponent'
+      'click @ui.cells': 'highlightCell'
+      'dblclick @ui.dependencies': 'showDependencies'
+
+
+    clearCells: ->
+      @ui.titles.removeClass 'dsm-body-highlighted dsm-body-usage dsm-body-dependency'
+      @ui.cells.removeClass 'dsm-body-highlighted dsm-body-usage dsm-body-dependency'
 
 
     highlightComponent: (e) ->
-      e.preventDefault()
       index = @ui.titles.index $(e.currentTarget)
-      @$('.dsm-body-highlighted').removeClass 'dsm-body-highlighted'
-      @$('.dsm-body-usage').removeClass 'dsm-body-usage'
-      @$('.dsm-body-dependency').removeClass 'dsm-body-dependency'
+      @clearCells()
       @highlightRow index
       @highlightColumn index
       @highlightUsages index
       @highlightDependencies index
 
 
+    highlightCell: (e) ->
+      cell = $(e.currentTarget)
+      column = cell.parent().children().index(cell) - 1
+      row = cell.parent().parent().children().index cell.parent()
+      @clearCells()
+      if row == column
+        @highlightRow row
+        @highlightColumn row
+        @highlightUsages row
+        @highlightDependencies row
+      else
+        @highlightRow column, 'dsm-body-usage'
+        @highlightColumn column, 'dsm-body-usage'
+        @highlightRow row, 'dsm-body-dependency'
+        @highlightColumn row, 'dsm-body-dependency'
+
 
-    highlightRow: (index) ->
-      @$(".dsm-body tr:eq(#{index}) td").addClass 'dsm-body-highlighted'
+    highlightRow: (index, c = 'dsm-body-highlighted') ->
+      @$(".dsm-body tr:eq(#{index}) td").addClass c
 
 
-    highlightColumn: (index) ->
+    highlightColumn: (index, c = 'dsm-body-highlighted') ->
       @$(".dsm-body tr").each ->
-        $(this).find("td:eq(#{index + 1})").addClass 'dsm-body-highlighted'
+        $(this).find("td:eq(#{index + 1})").addClass c
 
 
     highlightUsages: (index) ->
       @collection.at(index).get('v').forEach (d, i) =>
         if i < index && d.w?
-          @$("tr:eq(#{i})").addClass 'dsm-body-usage'
+          @$("tr:eq(#{i}) .dsm-body-title").addClass 'dsm-body-usage'
 
 
     highlightDependencies: (index) ->
       @collection.forEach (model, i) =>
         if model.get('v')[index].w?
-          @$("tr:eq(#{i})").addClass 'dsm-body-dependency'
+          @$("tr:eq(#{i}) .dsm-body-title").addClass 'dsm-body-dependency'
+
+
+    goToComponent: (e) ->
+      cell = $(e.currentTarget)
+      row = cell.parent().parent().children().index cell.parent()
+      model = @collection.at(row)
+      page = if model.get('q') == 'CLA' || model.get('q') == 'FIL' then 'dashboard' else 'design'
+      window.location = "#{baseUrl}/#{page}/index/#{model.get 'i'}"
+
+
+    showDependencies: (e) ->
+      cell = $(e.currentTarget)
+      column = cell.parent().children().index(cell) - 1
+      row = cell.parent().parent().children().index cell.parent()
+      id = @collection.at(row).get('v')[column].i
+      @showInfoViewSpinner()
+      @scrollToInfoView()
+      $.get API_DEPENDECIES, parent: id, (data) =>
+        @infoRegion.show new InfoView
+          collection: new Backbone.Collection data
+        @scrollToInfoView()
+
+
+    showInfoViewSpinner: ->
+      @infoRegion.reset()
+      @$(@infoRegion.el).html '<i class="spinner"></i>'
+
 
+    scrollToInfoView: ->
+      delta = @$(@infoRegion.el).offset().top - 40
+      $('html, body').animate { scrollTop: delta }, 500
index cbb30d4f668d45e97b55a5b0ae3767313ef569a1..743c4db6ebd50bbc17cfc9f0260e1b225fb9bbc7 100644 (file)
 <div class="dsm-body">
   <table>
     <tbody>
-    {{#each items}}
+    {{#eachIndex items}}
       <tr>
-        <td>
-          <a class="dsm-body-title">
-            {{qualifierIcon q}} {{n}}
-            <span class="dsm-body-title-indicator"></span>
-          </a>
+        <td class="dsm-body-title">
+          {{qualifierIcon q}} {{n}}
+          <span class="dsm-body-title-indicator"></span>
         </td>
-        {{#each v}}
-          <td>
-            <div class="dsm-body-cell {{#if status}}dsm-body-cell-{{status}}{{/if}}">
-              {{w}}
-            </div>
+        {{#eachIndex v}}
+          <td class="dsm-body-cell {{#if status}}dsm-body-cell-{{status}}{{/if}}">
+            {{#eq index ../index}}–{{else}}{{w}}{{/eq}}
           </td>
-        {{/each}}
+        {{/eachIndex}}
       </tr>
-    {{/each}}
+    {{/eachIndex}}
     </tbody>
   </table>
 </div>
+
+<div class="dsm-info"></div>
diff --git a/server/sonar-web/src/main/hbs/design/dsm-info.hbs b/server/sonar-web/src/main/hbs/design/dsm-info.hbs
new file mode 100644 (file)
index 0000000..b02c323
--- /dev/null
@@ -0,0 +1,17 @@
+<table>
+  <tbody>
+  {{#each items}}
+    <tr>
+      <td>
+        {{qualifierIcon fq}}
+        <a href="/dashboard/index/{{fk}}">{{fn}}</a>
+      </td>
+      <td>{{u}}</td>
+      <td>
+        {{qualifierIcon tq}}
+        <a href="/dashboard/index/{{tk}}"> {{tn}} </a>
+      </td>
+    </tr>
+  {{/each}}
+  </tbody>
+</table>
index 7846b6069903b274a9f775ae1a3851c9e3b2d672..9b0a2e65bf4510c8a82f6d0e21af7b50735c25b9 100644 (file)
@@ -88,6 +88,15 @@ define(['handlebars'], function (Handlebars) {
     }
   });
 
+  Handlebars.registerHelper('eachIndex', function (context, options) {
+    var ret = '';
+    context.forEach(function (d, i) {
+      var c = _.extend({ index: i }, d);
+      ret += options.fn(c);
+    });
+    return ret;
+  });
+
   Handlebars.registerHelper('eq', function(v1, v2, options) {
     return v1 == v2 ? options.fn(this) : options.inverse(this);
   });
index 5f7d1ef851100b114f94df30a2886f9217dc5cb2..6b5f7229c3af5bc756983a1463b8044de0851caf 100644 (file)
@@ -2,7 +2,7 @@
 @import (reference) 'mixins';
 @import (reference) 'ui';
 
-@cellSize: 18px;
+@cellSize: 22px;
 
 .dsm {
 
@@ -28,9 +28,9 @@
 
   &.gray { background-color: @grey; }
   &.red { background-color: @red; }
-  &.green { background-color: @green; }
+  &.green { .dsm-usage-mixin; }
   &.blue { background-color: @blue; }
-  &.yellow { background-color: @orange; }
+  &.yellow { .dsm-dependency-mixin; }
 }
 
 .dsm-legend-label {
 }
 
 
-.dsm-body {
-  td {
-    padding: 4px;
-    border: 1px solid @barBorderColor;
-    .trans(background-color);
-  }
+.dsm-body td {
+  border: 1px solid @barBorderColor;
 }
 
+
 .dsm-body-title {
   position: relative;
-  display: block;
-  height: @cellSize + 8px;
-  line-height: @cellSize + 8px;
-  margin: -4px;
-  padding: 0 15px 0 5px;
+  vertical-align: middle;
+  padding: 2px 15px 2px 4px;
+  border-right: 2px solid darken(@barBorderColor, 8%) !important;
   color: @baseFontColor;
+  cursor: pointer;
   .link-no-underline;
+  .trans(background-color);
 
-  &:hover, &:focus { background-color: @barBackgroundColor; }
-}
-
-.dsm-body-title-indicator {
-  position: absolute;
-  top: 0; right: 0;
-  .size(10px, 26px);
-
-  .dsm-body-usage & { background-color: @green; }
-  .dsm-body-dependency & { background-color: @orange; }
-  .dsm-body-usage.dsm-body-dependency & { background-color: @red; }
+  &:hover { background-color: @barBackgroundColor; }
 }
 
 .dsm-body-cell {
-  min-width: @cellSize;
-  height: @cellSize;
-  line-height: @cellSize;
-  padding: 0 2px;
+  min-width: 23px;
+  padding: 2px 4px;
   .box-sizing(border-box);
   text-align: center;
+  cursor: pointer;
+  .trans(background-color);
+}
+
+.dsm-body-cell-dependency {
+  background-color: @grey;
+}
+
+.dsm-body-cell-cycle {
+  background-color: @red !important;
+  color: #fff !important;
 }
 
-.dsm-body-cell-dependency { background-color: @grey; }
-.dsm-body-cell-cycle { background-color: @red; color: #fff; }
 
 .dsm-body-highlighted {
-  background-color: @lightBlue;
+  background-color: #dff2fd;
 
-  .dsm-body-title:hover,
-  .dsm-body-title:focus {
-    background-color: @lightBlue;
+  &:hover { background-color: #dff2fd; }
+}
+
+.dsm-body-usage, .dsm-body-usage:hover { .dsm-usage-mixin; }
+.dsm-body-dependency, .dsm-body-dependency:hover { .dsm-dependency-mixin; }
+
+
+.dsm-usage-mixin() {
+  background-color: #e2ffbe;
+}
+
+.dsm-dependency-mixin() {
+  background-color: #fde9cc;
+}
+
+
+.dsm-info {
+  margin-top: 15px;
+
+  td {
+    padding: 2px 5px;
   }
 }
index 7ab8c83c379fdc0c1c7ea9f7118230a6513aa488..5a873242d81863c9e149af115e14476b329f2c8c 100644 (file)
@@ -31,9 +31,7 @@ class DesignController < ApplicationController
 
   def load_resource
     @resource=Project.by_key(params[:id])
-    return redirect_to(home_path) unless @resource
-    access_denied unless has_role?(:admin, @resource)
-    @snapshot=@resource.last_snapshot
+    redirect_to(home_path) unless @resource
   end
 
 end