]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5646 Widget configuration
authorStas Vilchik <vilchiks@gmail.com>
Thu, 25 Sep 2014 08:21:34 +0000 (14:21 +0600)
committerStas Vilchik <vilchiks@gmail.com>
Fri, 26 Sep 2014 07:24:31 +0000 (13:24 +0600)
server/sonar-web/src/main/coffee/dashboard/app.coffee
server/sonar-web/src/main/coffee/dashboard/mockjax.coffee
server/sonar-web/src/main/coffee/dashboard/models/widget.coffee
server/sonar-web/src/main/coffee/dashboard/views/widget-view.coffee
server/sonar-web/src/main/coffee/dashboard/views/widgets-view.coffee
server/sonar-web/src/main/hbs/dashboard/_widget-props.hbs [new file with mode: 0644]
server/sonar-web/src/main/hbs/dashboard/widget.hbs
server/sonar-web/src/main/hbs/dashboard/widgets.hbs
server/sonar-web/src/main/less/dashboard.less
server/sonar-web/src/main/less/ui.less

index b3bf24c3b74ce3850560e16d8ef316c14229e8ce..678f4b3bdf3fa9b25f10522143397e922bb55d75 100644 (file)
@@ -32,6 +32,8 @@ requirejs [
   App = new Marionette.Application()
   App.dashboard = window.did
   App.resource = window.resource
+  App.state = new Backbone.Model configure: false
+
 
   App.addInitializer ->
     @widgetsView = new WidgetsView
@@ -41,11 +43,13 @@ requirejs [
       app: @
     @widgetsView.render();
 
+
   requestDetails = ->
     $.get "#{baseUrl}/api/dashboards/details", did: App.dashboard, (data) ->
       console.log JSON.stringify data
       App.dashboard = new Backbone.Model _.omit data, 'widgets'
       App.widgets = new Widgets data.widgets
 
+
   $.when(requestDetails(), window.requestMessages()).done -> App.start()
 
index db00287aa6477550db8b7392d48580dd8cd86b2e..141b2d372f9d8b54aee599b79e12f415196c2e14 100644 (file)
@@ -11,16 +11,16 @@ define ['third-party/jquery.mockjax'], ->
       shared: true
       layout: '50%-50%'
 
-      canManageDashboards: true
       canManageWidgets: true
 
       widgets: [
         {
           key: 'measure_filter_list'
-          props: [
+          name: 'Measure Filter as List'
+          properties: [
             {
               key: 'filter'
-              value: '48'
+              value: 48
             }
           ]
           layout: {
@@ -30,15 +30,27 @@ define ['third-party/jquery.mockjax'], ->
         }
         {
           key: 'my_reviews'
-          props: []
+          name: 'My Unresolved Issues'
+          properties: [
+            {
+              key: 'numberOfLines'
+              value: 5
+            }
+          ]
           layout: {
-            column: 1,
+            column: 1
             row: 2
           }
-        },
+        }
         {
-          key: 'hotspot_most_violated_rules',
-          props: [],
+          key: 'hotspot_most_violated_rules'
+          name: 'Most Violated Rules'
+          properties: [
+            {
+              key: 'numberOfLines'
+              value: 5
+            }
+          ]
           layout: {
             column: 2
             row: 1
@@ -58,3 +70,65 @@ define ['third-party/jquery.mockjax'], ->
           props: []
         }
       ]
+
+
+  jQuery.mockjax
+    url: "#{baseUrl}/api/dashboards/configure_widget"
+    responseText: JSON.stringify
+      "widget": {
+        "key": "measure_filter_list",
+        "properties": [
+          {
+            "key": "filter",
+            "value": 48,
+            "type": "FILTER",
+            "optional": false,
+            "options": {
+              "39": "My favourites"
+              "86": "Nemo &amp; Dory"
+              "36": "New recent issues by developer"
+              "37": "New recent violations by project"
+              "54": "Projects"
+              "50": "Projects Activity since last version"
+              "38": "Projects Treemap"
+              "49": "Projects by license"
+              "100": "Projects not analyzed since 2 days"
+              "82": "Quality Gate"
+              "57": "Super Heroes with new issues"
+              "32": "Super Heroes"
+              "48": "Teams"
+            }
+          },
+          {
+            "key": "pageSize",
+            "type": "INTEGER",
+            "defaultValue": "30",
+            "optional": true
+          },
+          {
+            "key": "displayFilterDescription",
+            "type": "BOOLEAN",
+            "defaultValue": "false",
+            "optional": true
+          }
+        ]
+      }
+
+
+    jQuery.mockjax
+      url: "#{baseUrl}/api/dashboards/save_widget"
+      responseText: JSON.stringify
+        widget: {
+          key: 'measure_filter_list'
+          name: 'Measure Filter as List'
+          properties: [
+            {
+              key: 'filter'
+              value: 48
+            }
+          ]
+          layout: {
+            column: 1
+            row: 1
+          }
+        }
index 72de8631a7faf1f9da0a7e9ae6d7b4fc7674cd8f..6665b537821252753c44ba3dc3e89c33f127897f 100644 (file)
@@ -1,4 +1,13 @@
 define ['backbone'], (Backbone) ->
 
+
   class extends Backbone.Model
     idAttribute: 'key'
+
+
+    mergeProperties: (properties) ->
+      props = @get 'properties'
+      props = properties.map (prop) ->
+        data = _.findWhere props, key: prop.key
+        _.extend prop, data
+      @set 'properties', props
index e34624fa02dca6acec7e0f40ff72d946ab3aadbd..a4c3bf35a3fb80c51ff2171b1108cb421863e9d4 100644 (file)
@@ -12,8 +12,16 @@ define [
   class extends Marionette.ItemView
     template: Templates['widget']
 
-    initialize: ->
-        @requestContent()
+
+    events:
+      'click .js-edit-widget': 'editWidget'
+      'click .js-cancel-edit-widget': 'cancelEditWidget'
+      'submit .js-edit-widget-form': 'saveWidget'
+
+
+    initialize: (options) ->
+#      @listenTo options.app.state, 'change', @render
+      @requestContent()
 
 
     requestContent: ->
@@ -27,8 +35,41 @@ define [
 
 
     getWidgetProps: ->
-      props = @model.get 'props'
+      properties = @model.get 'properties'
       r = {}
-      props.forEach (prop) ->
-        r[prop.key] = prop.value
+      properties.forEach (prop) ->
+        r[prop.key] = prop.value if prop.value?
       r
+
+
+    editWidget: ->
+      $.get "#{baseUrl}/api/dashboards/configure_widget", id: @model.id, (data) =>
+        @model.mergeProperties data.widget.properties
+        @showEditForm()
+
+
+    showEditForm: ->
+      @render()
+      @$('.widget_props').removeClass 'hidden'
+      @$('.configure_widget').addClass 'hidden'
+
+
+    cancelEditWidget: ->
+      @$('.widget_props').addClass 'hidden'
+      @$('.configure_widget').removeClass 'hidden'
+
+
+    saveWidget: (e) ->
+      e.preventDefault()
+      data = id: @model.id
+      @$('.js-edit-widget-form').serializeArray().forEach (p) ->
+        data[p.name] = p.value
+      $.post "#{baseUrl}/api/dashboards/save_widget", data, (data) =>
+        @model.set data.widget
+        @requestContent()
+
+
+    serializeData: ->
+      _.extend super,
+        baseUrl: baseUrl
+        state: @options.app.state.toJSON()
index 349d40e7cfbe186a5760b5fcc40310c63e3ee963..d004647a845eb6f742a6e4ca54fa878e3a0d3a8c 100644 (file)
@@ -14,8 +14,17 @@ define [
     itemViewContainer: '.dashboard-column'
 
 
+    events:
+      'click .js-configure-widgets': 'configureWidgets'
+      'click .js-back-to-dashboard': 'stopConfigureWidgets'
+
+
+    initialize: (options) ->
+      @listenTo options.app.state, 'change', @render
+
+
     itemViewOptions: ->
-      { app: @options.app }
+      app: @options.app
 
 
     appendHtml: (compositeView, itemView) ->
@@ -25,7 +34,16 @@ define [
       $container.eq(column).append itemView.el
 
 
+    configureWidgets: ->
+      @options.app.state.set configure: true
+
+
+    stopConfigureWidgets: ->
+      @options.app.state.set configure: false
+
+
     serializeData: ->
       _.extend super,
         dashboard: @options.dashboard.toJSON()
         manageDashboardsUrl: "#{baseUrl}/dashboards"
+        state: @options.app.state.toJSON()
diff --git a/server/sonar-web/src/main/hbs/dashboard/_widget-props.hbs b/server/sonar-web/src/main/hbs/dashboard/_widget-props.hbs
new file mode 100644 (file)
index 0000000..68595b6
--- /dev/null
@@ -0,0 +1,43 @@
+<form class="js-edit-widget-form">
+  <table class="table width100">
+    <tbody>
+    {{! <% if !widget.java_definition.global && @dashboard.global %> }}
+
+    {{#each properties}}
+      <tr>
+        <td class="form-key-cell">
+          {{t 'widget' ../key 'property' key 'name'}}
+          {{#unless optional}}*{{/unless}}
+        </td>
+        <td class="form-val-cell">
+          {{#eq type "FILTER"}}
+            <select name="{{key}}">
+              {{#each options}}
+                <option value="{{@key}}" {{#eq @key ../value}}selected{{/eq}}>{{this}}</option>
+              {{/each}}
+            </select>
+            <a href="{{baseUrl}}/measures/manage">Edit my filters</a>
+          {{/eq}}
+          {{#eq type "INTEGER"}}
+            <input value="{{value}}" name="{{key}}" type="text" size="10">
+          {{/eq}}
+          {{#eq type "BOOLEAN"}}
+            <input type="checkbox" name="{{key}}">
+          {{/eq}}
+
+          {{#if defaultValue}}
+            <div class="form-val-note">Default: {{defaultValue}}</div>
+          {{/if}}
+        </td>
+      </tr>
+    {{/each}}
+
+    <tr>
+      <td colspan="2">
+        <input type="submit" value="Save">
+        <a class="js-cancel-edit-widget">Cancel</a>
+      </td>
+    </tr>
+    </tbody>
+  </table>
+</form>
index 91dcae71e968862bcd49142f489dce2e8045c7b9..7b9480965981e3e74448911ce7f81567f46543f3 100644 (file)
@@ -1,9 +1,31 @@
 <div class="block">
-  <div class="widget">
-    {{#if html}}
-      {{{html}}}
-    {{else}}
-      <i class="spinner spinner-margin"></i>
-    {{/if}}
-  </div>
+
+  {{#if state.configure}}
+
+    <div class="widget-header">
+      <div class="widget-actions">
+        {{#notEmpty properties}}<a class="js-edit-widget">Edit</a>{{/notEmpty}}
+        <a class="js-delete-widget">Delete</a>
+      </div>
+      <div class="widget-handle">{{name}}</div>
+    </div>
+
+    <div class="widget_props hidden">
+      {{> '_widget-props'}}
+    </div>
+
+    <div class="configure_widget">
+      <div class="transparent"></div>
+      <div class="widget">
+          {{#if html}}{{{html}}}{{else}}<i class="spinner spinner-margin"></i>{{/if}}
+      </div>
+    </div>
+
+  {{else}}
+
+    <div class="widget">
+      {{#if html}}{{{html}}}{{else}}<i class="spinner spinner-margin"></i>{{/if}}
+    </div>
+
+  {{/if}}
 </div>
index 7dd17d1b8eac1c49cea8a6d8d747ea3743836b0f..1ae5f8b11a91e8a9d8eaf532c344b641596bb888 100644 (file)
@@ -1,6 +1,10 @@
 <div class="line-block">
   <div class="operations noprint button-group">
-    <button>{{t 'dashboard.configure_widgets'}}</button>
+    {{#unless state.configure}}
+      <button class="js-configure-widgets">{{t 'dashboard.configure_widgets'}}</button>
+    {{else}}
+      <button class="js-back-to-dashboard">{{t 'dashboard.back_to_dashboard'}}</button>
+    {{/unless}}
     <a class="button" href="{{manageDashboardsUrl}}">{{t 'dashboard.manage_dashboards'}}</a>
   </div>
 </div>
index dfcd068296bbe4160d5b8649d59211db22c49448..a5bcb867a887e67b630a5a1c40edc1d1ed306a78 100644 (file)
   line-height: 16px;
   padding: 3px 5px 5px;
   background-color: #efefef;
-  border: 1px solid #ddd;
   border-bottom: 0;
 }
 
index a2e1b2f161dad8a6b471935df54f7a0d89f4dd7a..eeea142f5c4b3418efd5a4c43575935e91031fac 100644 (file)
@@ -85,6 +85,11 @@ select::-moz-focus-inner, input::-moz-focus-inner, button::-moz-focus-inner {
   text-transform: none;
 }
 
+.hidden {
+  display: none !important;
+  visibility: hidden !important;
+}
+
 
 /*
  * Links