Agent Steps reordering with acts_as_list gem and jQuery UI sortable

James Peret vor 10 Jahren
Ursprung
Commit
f775f36b17

+ 2 - 0
Gemfile

@@ -22,6 +22,7 @@ gem 'coffee-rails', '~> 4.0.0'
22 22
 
23 23
 # Use jquery as the JavaScript library
24 24
 gem 'jquery-rails'
25
+gem 'jquery-ui-rails'
25 26
 
26 27
 # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
27 28
 gem 'turbolinks'
@@ -70,6 +71,7 @@ gem 'valid_email', :require => 'valid_email/email_validator'
70 71
 gem 'hirb'
71 72
 gem 'wirble'
72 73
 gem 'roadie-rails'
74
+gem 'acts_as_list'
73 75
 
74 76
 group :development do
75 77
   gem "rename"

+ 6 - 0
Gemfile.lock

@@ -25,6 +25,8 @@ GEM
25 25
       multi_json (~> 1.3)
26 26
       thread_safe (~> 0.1)
27 27
       tzinfo (~> 0.3.37)
28
+    acts_as_list (0.6.0)
29
+      activerecord (>= 3.0)
28 30
     addressable (2.3.6)
29 31
     arel (4.0.2)
30 32
     bcrypt (3.1.7)
@@ -144,6 +146,8 @@ GEM
144 146
     jquery-turbolinks (2.1.0)
145 147
       railties (>= 3.1.0)
146 148
       turbolinks
149
+    jquery-ui-rails (5.0.3)
150
+      railties (>= 3.2.16)
147 151
     json (1.8.1)
148 152
     kgio (2.9.2)
149 153
     launchy (2.4.2)
@@ -315,6 +319,7 @@ PLATFORMS
315 319
   ruby
316 320
 
317 321
 DEPENDENCIES
322
+  acts_as_list
318 323
   bootstrap-switch-rails
319 324
   bootstrap-timepicker-rails
320 325
   bootstrap_form
@@ -338,6 +343,7 @@ DEPENDENCIES
338 343
   jbuilder (~> 1.2)
339 344
   jquery-rails
340 345
   jquery-turbolinks
346
+  jquery-ui-rails
341 347
   less-rails
342 348
   letter_opener (~> 1.3.0)
343 349
   mini_magick

+ 1 - 0
app/assets/javascripts/application.js

@@ -13,6 +13,7 @@
13 13
 //= require jquery
14 14
 //= require jquery.turbolinks	
15 15
 //= require jquery_ujs
16
+//= require jquery-ui/sortable
16 17
 //= require twitter/bootstrap
17 18
 //= require bootstrap-switch
18 19
 //= require jasny-bootstrap

+ 17 - 0
app/assets/javascripts/mission_editor.js

@@ -28,6 +28,23 @@ function attachHandler(jQuery) {
28 28
 	  
29 29
 	});
30 30
 	
31
+	$('#steps_container').sortable({
32
+	     axis:'y',
33
+	     handle: '.handle',
34
+		cursor: 'crosshair',
35
+		item: 'div',
36
+	     update: function(){
37
+			console.log("Serialize:" + $('#steps_container').sortable('serialize', {attribute: "id"}, { key: "agent_step" }));
38
+		     $.ajax({
39
+		            url: $(this).data('update'),
40
+		            type: 'post',
41
+		            data: $('#steps_container').sortable("serialize", {attribute: "id"}, { key: "agent_step" }),
42
+		            dataType: 'script'
43
+		    });
44
+	     	
45
+	     }
46
+	});
47
+	
31 48
 }
32 49
 
33 50
 $(document).ready(attachHandler);

+ 7 - 0
app/controllers/mission_editor/agents_controller.rb

@@ -64,6 +64,13 @@ class MissionEditor::AgentsController < ApplicationController
64 64
       format.json { head :no_content }
65 65
     end
66 66
   end
67
+  
68
+  def sort_steps
69
+    params[:agent_step].each_with_index do |step, index| 
70
+      AgentStep.find(step).update(position: (index + 1)) 
71
+    end 
72
+    render nothing: true 
73
+  end
67 74
 
68 75
   private
69 76
     # Use callbacks to share common setup or constraints between actions.

+ 1 - 1
app/controllers/missions_controller.rb

@@ -124,7 +124,7 @@ class MissionsController < ApplicationController
124 124
   def step_submission
125 125
     mission = Mission.friendly.find(params[:id])
126 126
     agent = mission.mission_agents.friendly.find(params[:agent])
127
-    step = agent.agent_steps.find_by_step(params[:step])
127
+    step = agent.agent_steps.where(id: params[:step]).last
128 128
     submission = step.create_submission(step_submission_params, params[:step_submission][:submission_contents_attributes].values)
129 129
     respond_to do |format|
130 130
       if submission.save

+ 2 - 0
app/models/agent_step.rb

@@ -5,6 +5,8 @@ class AgentStep < ActiveRecord::Base
5 5
   
6 6
   accepts_nested_attributes_for :step_validations, allow_destroy:true
7 7
   
8
+  acts_as_list scope: :mission_agent
9
+  
8 10
   def create_submission(step_submission, contents)
9 11
     submission = StepSubmission.new(step_submission)
10 12
     submission.agent_step = self

+ 2 - 2
app/models/mission_agent.rb

@@ -7,7 +7,7 @@ class MissionAgent < ActiveRecord::Base
7 7
   belongs_to :mission
8 8
   belongs_to :user
9 9
   
10
-  has_many :agent_steps, :dependent => :destroy 
10
+  has_many :agent_steps, -> { order("position ASC") }, :dependent => :destroy
11 11
   has_many :mission_candidates, :dependent => :destroy
12 12
   
13 13
   has_and_belongs_to_many :rewards
@@ -16,7 +16,7 @@ class MissionAgent < ActiveRecord::Base
16 16
   accepts_nested_attributes_for :mission_candidates
17 17
   
18 18
   def is_assigned
19
-    if self.mission_candidates.find_all_by_status(1).last == nil
19
+    if self.user == nil
20 20
       return false
21 21
     else
22 22
       return true

+ 0 - 6
app/models/step_validation.rb

@@ -3,8 +3,6 @@ class StepValidation < ActiveRecord::Base
3 3
   has_many :submission_contents
4 4
   belongs_to :validation, polymorphic: true
5 5
   
6
-  after_save :create_validation
7
-  
8 6
   attr_writer :description
9 7
   
10 8
   def icon
@@ -33,8 +31,4 @@ class StepValidation < ActiveRecord::Base
33 31
     end
34 32
   end
35 33
   
36
-  def create_validation
37
-    
38
-  end
39
-  
40 34
 end

+ 1 - 1
app/views/mission_editor/agents/_form.html.erb

@@ -14,7 +14,7 @@
14 14
 	<% end %>
15 15
   <% end %>
16 16
   
17
-  <%= render :partial => 'form_step', locals: { mission_agent: @mission_agent, f: f } %>
17
+  <%= render :partial => 'form_step', locals: { mission_agent: @mission_agent, f: f, mission: @mission } %>
18 18
 
19 19
   
20 20
   <%= content_tag(:div, class: "form-submit-center") do %>

+ 5 - 5
app/views/mission_editor/agents/_form_step.html.erb

@@ -1,9 +1,9 @@
1
-<%= content_tag(:div, id: 'steps_container') do %>
1
+<%= content_tag(:div, id: 'steps_container', class: 'list', data: {update: sort_agent_steps_path(mission.slug) }) do %>
2 2
 	<% step_number = 0 %>
3
-	<%= f.fields_for :agent_steps, show_empty: false do |ff| %>
3
+	<%= f.fields_for :agent_steps, :wrapper => false, show_empty: false do |ff| %>
4 4
 		<% step_number = step_number + 1%>
5
-		<%= content_tag(:div, class: "panel panel-white #{'hidden' if ff.object == nil}") do %>
6
-			<%= content_tag(:div, class: 'panel-heading') do %>
5
+		<%= content_tag(:div, id: "agent_step_#{ff.object.id}" ,class: "fields panel panel-white step  #{'hidden' if ff.object == nil}") do %>
6
+			<%= content_tag(:div, class: 'panel-heading handle') do %>
7 7
 				<%= content_tag(:h3, class: 'panel-title') do %>
8 8
 					<%= content_tag(:span, (ff.object.step.to_s != '' ? ff.object.step.to_s : '#'), class: 'task-number') %>
9 9
 					<a class="accordion-toggle" data-toggle="collapse" data-parent="#colapse_steps" href="#collapse_step_<%= step_number.to_s %>">
@@ -23,7 +23,7 @@
23 23
 						<%= ff.text_area :description, label: (t 'mission_editor.agents.description'), class: 'input-block-level', rows: 10 %>
24 24
 					<% end %>
25 25
 				<% end %>
26
-				<%= render :partial => 'form_step_validation', locals: {ff: ff} %>
26
+				<%= render :partial => 'form_step_validation', locals: {ff: ff, mission: mission} %>
27 27
 
28 28
 			<% end %>
29 29
 		<% end %>

+ 1 - 1
app/views/mission_mailer/step_denied_notification.html.erb

@@ -203,7 +203,7 @@
203 203
 									<%= content_tag(:div, class: 'page-header') do %>
204 204
 										<%= content_tag(:small, ((t 'mission.notification')+':').html_safe) %>
205 205
 										<%= content_tag(:h2) do %>
206
-											<%= "#{t 'mission.step'} #{@step.step.to_s} #{t 'step.denied'}".html_safe %>
206
+											<%= "#{t 'mission.step'} #{@step.position.to_s} #{t 'step.denied'}".html_safe %>
207 207
 										<% end %>
208 208
 										<hr>
209 209
 										<%= content_tag(:small, ((t 'mission.step')+':').html_safe) %>

+ 1 - 1
app/views/mission_mailer/step_denied_notification.text.erb

@@ -1,6 +1,6 @@
1 1
 -----------------
2 2
 
3
-<%= "#{t 'mission.step'} #{@step.step.to_s} #{t 'step.denied'} - #{@step.title}" %>
3
+<%= "#{t 'mission.step'} #{@step.position.to_s} #{t 'step.denied'} - #{@step.title}" %>
4 4
 
5 5
 <%= "#{t 'mission.mission'}:" %>
6 6
 <%= @step.mission_agent.mission.title %>

+ 1 - 1
app/views/mission_mailer/step_validation_notification.html.erb

@@ -203,7 +203,7 @@
203 203
 									<%= content_tag(:div, class: 'page-header') do %>
204 204
 										<%= content_tag(:small, ((t 'mission.notification')+':').html_safe) %>
205 205
 										<%= content_tag(:h2) do %>
206
-											<%= "#{t 'mission.step'} #{@step.step.to_s} #{t 'step.validated'}".html_safe %>
206
+											<%= "#{t 'mission.step'} #{@step.position.to_s} #{t 'step.validated'}".html_safe %>
207 207
 										<% end %>
208 208
 										<hr>
209 209
 										<%= content_tag(:small, ((t 'mission.step')+':').html_safe) %>

+ 1 - 1
app/views/mission_mailer/step_validation_notification.text.erb

@@ -1,6 +1,6 @@
1 1
 -----------------
2 2
 
3
-<%= "#{t 'mission.step'} #{@step.step.to_s} #{t 'step.validated'} - #{@step.title}" %>
3
+<%= "#{t 'mission.step'} #{@step.position.to_s} #{t 'step.validated'} - #{@step.title}" %>
4 4
 
5 5
 <%= "#{t 'mission.mission'}:" %>
6 6
 <%= @step.mission_agent.mission.title %>

+ 1 - 1
app/views/missions/_step_quick_list.html.erb

@@ -7,7 +7,7 @@
7 7
 		<% if step_count <= 2 || agent.agent_steps.count <= 3 %>
8 8
 			<%= content_tag(:div, class: 'thumbnail-task') do %>
9 9
 				<%= content_tag(:p) do %>
10
-					<%= content_tag(:span, step.step, class: 'task-number') %>
10
+					<%= content_tag(:span, step.position, class: 'task-number') %>
11 11
 					<%= content_tag(:span, step.title, class: 'task-text') %>
12 12
 					<%= content_tag(:span, step.icons.html_safe, class: 'task-icon pull-right') %>
13 13
 				<% end %>

+ 2 - 2
app/views/missions/_step_submission.html.erb

@@ -1,4 +1,4 @@
1
-<% submission_id = 'collapse_step_' + step.step.to_s + '_validations' %>
1
+<% submission_id = 'collapse_step_' + step.position.to_s + '_validations' %>
2 2
 <%= content_tag(:div, class: 'panel-group accordion', id: submission_id) do %>
3 3
 	<% step.step_validations.each do |validation| %>
4 4
 		<% validation_id = 'collapse_validation_' + validation.id.to_s %>
@@ -7,7 +7,7 @@
7 7
 				<%= link_to(('#'+ validation_id), class: 'accordion-toggle', :data => {toggle: 'collapse', parent: submission_id}) do %>
8 8
 					<%= content_tag(:span, validation.icon.html_safe, class: 'task-icon pull-left') %>
9 9
 					<%= content_tag(:span, '', class: 'caret caret-center') %>
10
-					<%= content_tag(:span, (step.step_validations.first != nil ? step.step_validations.first.validation.description : 'test'), class: 'task-text') %>
10
+					<%= content_tag(:span, (step.step_validations.first.description != nil ? step.step_validations.first.validation.description : 'test'), class: 'task-text') %>
11 11
 				<% end %>
12 12
 				
13 13
 			<% end %>

+ 4 - 4
app/views/missions/show_agent_details.html.erb

@@ -71,12 +71,12 @@
71 71
 			<% # Steps %>
72 72
 			<% @agent.agent_steps.order('step ASC').each do |step| %>
73 73
 				<% step_submission = StepSubmission.new %>
74
-				<%= bootstrap_nested_form_for(StepSubmission.new, url: step_submission_path(step: step.step, mission: @mission.slug, agent: @agent.slug)) do |f| %>
74
+				<%= bootstrap_nested_form_for(StepSubmission.new, url: step_submission_path(step: step.id, mission: @mission.slug, agent: @agent.slug)) do |f| %>
75 75
 					<%= content_tag(:div, class: 'panel panel-default') do %>
76 76
 						<%= content_tag(:div, class: 'panel-heading') do %>
77 77
 							<%= content_tag(:h3, class: 'panel-title') do %>
78
-								<%= content_tag(:span, step.step, class: 'task-number') %>
79
-								<a class="accordion-toggle" data-toggle="collapse" data-parent="#colapse_steps" href="#collapse_step_<%= step.step %>">
78
+								<%= content_tag(:span, step.position, class: 'task-number') %>
79
+								<a class="accordion-toggle" data-toggle="collapse" data-parent="#colapse_steps" href="#collapse_step_<%= step.position %>">
80 80
 									<span class="caret"></span>
81 81
 									<%= content_tag(:span, step.title, class: 'task-text') %>
82 82
 									
@@ -92,7 +92,7 @@
92 92
 								<% end %>
93 93
 							<% end %>
94 94
 						<% end %>
95
-						<%= content_tag(:div, class: 'panel-body collapse', id: ('collapse_step_'+ step.step.to_s)) do %>
95
+						<%= content_tag(:div, class: 'panel-body collapse', id: ('collapse_step_'+ step.position.to_s)) do %>
96 96
 							<%= content_tag(:div, class: "panel-content") do %>
97 97
 								<%= content_tag(:div, class: "panel-text") do %>
98 98
 									<%= step.description.html_safe if step.description %>

+ 12 - 12
config/environments/development.rb

@@ -30,17 +30,17 @@ Avalanche2::Application.configure do
30 30
   config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
31 31
   config.action_mailer.raise_delivery_errors = true
32 32
   
33
-  #config.action_mailer.delivery_method = :letter_opener
34
-  config.action_mailer.delivery_method = :smtp
35
-
36
-  config.action_mailer.smtp_settings = {
37
-      :address   => "smtp.mandrillapp.com",
38
-      :port      => 587, # ports 587 and 2525 are also supported with STARTTLS
39
-      :enable_starttls_auto => true, # detects and uses STARTTLS
40
-      :user_name => ENV["MANDRILL_USERNAME"],
41
-      :password  => ENV["MANDRILL_KEY"], # SMTP password is any valid API key
42
-      :authentication => 'login', # Mandrill supports 'plain' or 'login'
43
-      :domain => ENV["DOMAIN_NAME"] # your domain to identify your server when connecting
44
-  }
33
+  config.action_mailer.delivery_method = :letter_opener
34
+  # config.action_mailer.delivery_method = :smtp
35
+#
36
+#   config.action_mailer.smtp_settings = {
37
+#       :address   => "smtp.mandrillapp.com",
38
+#       :port      => 587, # ports 587 and 2525 are also supported with STARTTLS
39
+#       :enable_starttls_auto => true, # detects and uses STARTTLS
40
+#       :user_name => ENV["MANDRILL_USERNAME"],
41
+#       :password  => ENV["MANDRILL_KEY"], # SMTP password is any valid API key
42
+#       :authentication => 'login', # Mandrill supports 'plain' or 'login'
43
+#       :domain => ENV["DOMAIN_NAME"] # your domain to identify your server when connecting
44
+#   }
45 45
   
46 46
 end

+ 4 - 1
config/routes.rb

@@ -35,11 +35,14 @@ Avalanche2::Application.routes.draw do
35 35
   get 'missions/:id/mission_control/reject_step_submission/:step_submission_id' => 'missions#reject_step_submission', as: :reject_step_submission
36 36
   
37 37
   # Mission Editor
38
-  get    'missions/:id/editor' => 'missions#edit', as: :mission_editor
38
+  get   'missions/:id/editor' => 'missions#edit', as: :mission_editor
39
+  
39 40
   scope 'missions/:mission/editor' do
40 41
     resources :rewards, :controller => "mission_editor/rewards"
41 42
     resources :mission_agents, :controller => "mission_editor/agents", path: '/agents'
43
+    post  '/sort_steps', :controller => "mission_editor/agents", :action => "sort_steps", as: :sort_agent_steps
42 44
   end
45
+
43 46
   
44 47
   # get    'missions/:id/editor/rewards' => 'rewards#index', as: :mission_editor_rewards_list
45 48
   # get    'missions/:id/editor/rewards/new' => 'rewards#new', as: :mission_editor_new_reward

+ 5 - 0
db/migrate/20150315034117_add_position_to_agent_step.rb

@@ -0,0 +1,5 @@
1
+class AddPositionToAgentStep < ActiveRecord::Migration
2
+  def change
3
+    add_column :agent_steps, :position, :integer
4
+  end
5
+end

+ 2 - 1
db/schema.rb

@@ -11,7 +11,7 @@
11 11
 #
12 12
 # It's strongly recommended that you check this file into your version control system.
13 13
 
14
-ActiveRecord::Schema.define(version: 20150314233050) do
14
+ActiveRecord::Schema.define(version: 20150315034117) do
15 15
 
16 16
   # These are extensions that must be enabled in order to support this database
17 17
   enable_extension "plpgsql"
@@ -27,6 +27,7 @@ ActiveRecord::Schema.define(version: 20150314233050) do
27 27
     t.datetime "updated_at"
28 28
     t.integer  "step_submissions_id"
29 29
     t.integer  "step_validations_id"
30
+    t.integer  "position"
30 31
   end
31 32
 
32 33
   add_index "agent_steps", ["mission_agent_id"], name: "index_agent_steps_on_mission_agent_id", using: :btree