]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5646 Widget drag'n'drop
authorStas Vilchik <vilchiks@gmail.com>
Mon, 29 Sep 2014 06:21:26 +0000 (12:21 +0600)
committerStas Vilchik <vilchiks@gmail.com>
Mon, 29 Sep 2014 06:21:33 +0000 (12:21 +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.hbs

index 678f4b3bdf3fa9b25f10522143397e922bb55d75..9968cb1b73d12963877265f31d442382525ef256 100644 (file)
@@ -35,6 +35,14 @@ requirejs [
   App.state = new Backbone.Model configure: false
 
 
+  App.saveDashboard = ->
+    layout = @widgetsView.getLayout()
+    data =
+      did: App.dashboard.id
+      layout: layout
+    $.post "#{baseUrl}/api/dashboards/save", data
+
+
   App.addInitializer ->
     @widgetsView = new WidgetsView
       collection: @widgets
@@ -45,8 +53,7 @@ requirejs [
 
 
   requestDetails = ->
-    $.get "#{baseUrl}/api/dashboards/details", did: App.dashboard, (data) ->
-      console.log JSON.stringify data
+    $.get "#{baseUrl}/api/dashboards/details", key: App.dashboard, (data) ->
       App.dashboard = new Backbone.Model _.omit data, 'widgets'
       App.widgets = new Widgets data.widgets
 
index 141b2d372f9d8b54aee599b79e12f415196c2e14..9ddbf901b105c9eb8d566b72b7563152538e46e4 100644 (file)
@@ -15,6 +15,7 @@ define ['third-party/jquery.mockjax'], ->
 
       widgets: [
         {
+          id: 1
           key: 'measure_filter_list'
           name: 'Measure Filter as List'
           properties: [
@@ -29,6 +30,7 @@ define ['third-party/jquery.mockjax'], ->
           }
         }
         {
+          id: 2
           key: 'my_reviews'
           name: 'My Unresolved Issues'
           properties: [
@@ -43,6 +45,7 @@ define ['third-party/jquery.mockjax'], ->
           }
         }
         {
+          id: 3
           key: 'hotspot_most_violated_rules'
           name: 'Most Violated Rules'
           properties: [
@@ -132,3 +135,9 @@ define ['third-party/jquery.mockjax'], ->
             row: 1
           }
         }
+
+
+        jQuery.mockjax
+          url: "#{baseUrl}/api/dashboards/save"
+          responseText: JSON.stringify
+            status: 'ok'
index 6665b537821252753c44ba3dc3e89c33f127897f..c448b96f6f8ede8a381099519fe9817a32a58654 100644 (file)
@@ -2,8 +2,6 @@ define ['backbone'], (Backbone) ->
 
 
   class extends Backbone.Model
-    idAttribute: 'key'
-
 
     mergeProperties: (properties) ->
       props = @get 'properties'
index a4c3bf35a3fb80c51ff2171b1108cb421863e9d4..be34011106a7743a3f5228200456e71fb62416c3 100644 (file)
@@ -11,6 +11,7 @@ define [
 
   class extends Marionette.ItemView
     template: Templates['widget']
+    className: 'block'
 
 
     events:
@@ -24,8 +25,14 @@ define [
       @requestContent()
 
 
+    onRender: ->
+      @$el.data 'id', @model.id
+      if @options.app.state.get 'configure'
+        @$el.prop 'draggable', true
+
+
     requestContent: ->
-      payload = id: @model.id
+      payload = id: @model.get 'key'
       if @options.app.resource
         payload.resource = @options.app.resource
       _.extend payload, @getWidgetProps()
@@ -43,7 +50,7 @@ define [
 
 
     editWidget: ->
-      $.get "#{baseUrl}/api/dashboards/configure_widget", id: @model.id, (data) =>
+      $.get "#{baseUrl}/api/dashboards/configure_widget", id: @model.get('key'), (data) =>
         @model.mergeProperties data.widget.properties
         @showEditForm()
 
index d004647a845eb6f742a6e4ca54fa878e3a0d3a8c..84191e4601b9f11abc7bb5500ed562d744fae351 100644 (file)
@@ -8,6 +8,9 @@ define [
   WidgetView
 ) ->
 
+  $ = jQuery
+
+
   class extends Marionette.CompositeView
     template: Templates['widgets']
     itemView: WidgetView
@@ -34,6 +37,45 @@ define [
       $container.eq(column).append itemView.el
 
 
+    onRender: ->
+      @initializeDragging() if @options.app.state.get 'configure'
+
+
+    initializeDragging: ->
+      blocks = @$('.block')
+      columnHandle = @$('.column-handle')
+      draggable = null
+
+      onDragLeave = (e) ->
+        $(e.currentTarget).removeClass 'block-hover'
+
+      onDrop = (e) =>
+        e.preventDefault()
+        draggable.detach().insertBefore $(e.currentTarget)
+        onDragLeave e
+        @options.app.saveDashboard()
+
+      blocks.on 'selectstart', ->
+        @dragDrop()
+        false
+      blocks.on 'dragstart', (e) ->
+        e.originalEvent.dataTransfer.setData 'Text', 'drag'
+        draggable = $(@)
+        columnHandle.show()
+      blocks.on 'dragover', (e) ->
+        if draggable.data('id') != $(@).data('id')
+          e.preventDefault()
+          $(e.currentTarget).addClass 'block-hover'
+      blocks.on 'drop', onDrop
+      blocks.on 'dragleave', onDragLeave
+
+      columnHandle.on 'dragover', (e) ->
+        e.preventDefault()
+        $(e.currentTarget).addClass 'block-hover'
+      columnHandle.on 'drop', onDrop
+      columnHandle.on 'dragleave', onDragLeave
+
+
     configureWidgets: ->
       @options.app.state.set configure: true
 
@@ -42,6 +84,13 @@ define [
       @options.app.state.set configure: false
 
 
+    getLayout: ->
+      layout = $('.dashboard-column').map( ->
+          blocks = $(@).find '.block'
+          blocks.map( -> $(@).data('id')).get().join(',')
+      ).get().join(';')
+
+
     serializeData: ->
       _.extend super,
         dashboard: @options.dashboard.toJSON()
index 7b9480965981e3e74448911ce7f81567f46543f3..844c3ec0c4e83a4f206f7ee2b5e0c1430c18fc46 100644 (file)
@@ -1,31 +1,28 @@
-<div class="block">
+{{#if state.configure}}
 
-  {{#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 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="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 class="configure_widget">
+    <div class="transparent"></div>
+    <div class="widget">
+        {{#if html}}{{{html}}}{{else}}<i class="spinner spinner-margin"></i>{{/if}}
     </div>
+  </div>
 
-  {{else}}
+{{else}}
 
-    <div class="widget">
-      {{#if html}}{{{html}}}{{else}}<i class="spinner spinner-margin"></i>{{/if}}
-    </div>
+  <div class="widget">
+    {{#if html}}{{{html}}}{{else}}<i class="spinner spinner-margin"></i>{{/if}}
+  </div>
 
-  {{/if}}
-</div>
+{{/if}}