Browse Source

Add mass importing activities, activity index

Maarten van den Berg 7 years ago
parent
commit
3038e2830f

+ 3 - 2
Gemfile

@@ -48,8 +48,9 @@ gem 'yard'
48 48
 # Use Mailgun for mail
49 49
 gem 'mailgun_rails'
50 50
 
51
-# Use Capistrano for deployment
52
-# gem 'capistrano-rails', group: :development
51
+# Pagination
52
+gem 'will_paginate', '~> 3.1.0'
53
+gem 'bootstrap-will_paginate'
53 54
 
54 55
 group :development, :test do
55 56
   # Call 'byebug' anywhere in the code to stop execution and get a debugger console

+ 5 - 0
Gemfile.lock

@@ -50,6 +50,8 @@ GEM
50 50
     bootstrap-sass (3.3.7)
51 51
       autoprefixer-rails (>= 5.2.1)
52 52
       sass (>= 3.3.4)
53
+    bootstrap-will_paginate (1.0.0)
54
+      will_paginate
53 55
     builder (3.2.3)
54 56
     byebug (9.0.6)
55 57
     coffee-rails (4.2.1)
@@ -185,6 +187,7 @@ GEM
185 187
     websocket-driver (0.6.5)
186 188
       websocket-extensions (>= 0.1.0)
187 189
     websocket-extensions (0.1.2)
190
+    will_paginate (3.1.6)
188 191
     x-editable-rails (1.5.5)
189 192
       railties
190 193
     yard (0.9.8)
@@ -197,6 +200,7 @@ DEPENDENCIES
197 200
   babel-transpiler
198 201
   bcrypt (~> 3.1.7)
199 202
   bootstrap-sass (~> 3.3.6)
203
+  bootstrap-will_paginate
200 204
   byebug
201 205
   coffee-rails (~> 4.2)
202 206
   faker
@@ -218,6 +222,7 @@ DEPENDENCIES
218 222
   tzinfo-data
219 223
   uglifier (>= 1.3.0)
220 224
   web-console
225
+  will_paginate (~> 3.1.0)
221 226
   x-editable-rails
222 227
   yard
223 228
 

+ 18 - 1
app/controllers/activities_controller.rb

@@ -3,11 +3,12 @@ class ActivitiesController < ApplicationController
3 3
   before_action :set_activity, only: [:show, :edit, :update, :destroy, :presence]
4 4
   before_action :set_group
5 5
   before_action :require_membership!
6
+  before_action :require_leader!, only: [:mass_new, :mass_create, :new, :create, :destroy]
6 7
 
7 8
   # GET /groups/:id/activities
8 9
   # GET /activities.json
9 10
   def index
10
-    @activities = @group.activities
11
+    @activities = @group.activities.paginate(page: params[:page], per_page: 5)
11 12
   end
12 13
 
13 14
   # GET /activities/1
@@ -130,6 +131,22 @@ class ActivitiesController < ApplicationController
130 131
     participant.update_attributes(params.permit(:notes, :attending))
131 132
   end
132 133
 
134
+  def mass_new
135
+  end
136
+
137
+  def mass_create
138
+    require 'csv'
139
+    uploaded_io = params[:spreadsheet]
140
+    result = Activity.from_csv(uploaded_io.read, @group)
141
+
142
+    result.each do |a|
143
+      a.save!
144
+    end
145
+
146
+    flash_message(:success, I18n.t('activities.mass_imported', count: result.count))
147
+    redirect_to group_activities_path(@group)
148
+  end
149
+
133 150
   private
134 151
     # Use callbacks to share common setup or constraints between actions.
135 152
     def set_activity

+ 41 - 0
app/models/activity.rb

@@ -70,6 +70,15 @@ class Activity < ApplicationRecord
70 70
     self.participants.group(:attending).count
71 71
   end
72 72
 
73
+  # Return participants attending, absent, unknown
74
+  def human_state_counts
75
+    c = self.state_counts
76
+    p = c[true]
77
+    a = c[false]
78
+    u = c[nil]
79
+    return "#{p or 0}, #{a or 0}, #{u or 0}"
80
+  end
81
+
73 82
   # Determine whether the passed Person may change this activity.
74 83
   def may_change?(person)
75 84
     person.is_admin ||
@@ -94,6 +103,38 @@ class Activity < ApplicationRecord
94 103
     end
95 104
   end
96 105
 
106
+  # Create multiple Activities from data in a CSV file, assign to a group, return.
107
+  def self.from_csv(content, group)
108
+    reader = CSV.parse(content, {headers: true, skip_blanks: true})
109
+
110
+    result = []
111
+    reader.each do |row|
112
+      a = Activity.new
113
+      a.group       = group
114
+      a.name        = row['name']
115
+      a.description = row['description']
116
+      a.location    = row['location']
117
+
118
+      sd            = Date.strptime(row['start_date'])
119
+      st            = Time.strptime(row['start_time'], '%H:%M')
120
+      a.start       = DateTime.new(sd.year, sd.month, sd.day, st.hour, st.min)
121
+
122
+      if not row['end_date'].blank?
123
+        ed          = Date.strptime(row['end_date'])
124
+        et          = Time.strptime(row['end_time'], '%H:%M')
125
+        a.end       = DateTime.new(ed.year, ed.month, ed.day, et.hour, et.min)
126
+      end
127
+
128
+      dd            = Date.strptime(row['deadline_date'])
129
+      dt            = Time.strptime(row['deadline_time'], '%H:%M')
130
+      a.deadline    = DateTime.new(dd.year, dd.month, dd.day, dt.hour, dt.min)
131
+
132
+      result << a
133
+    end
134
+
135
+    result
136
+  end
137
+
97 138
   private
98 139
   # Assert that the deadline for participants to change the deadline, if any,
99 140
   # is set before the event starts.

+ 0 - 23
app/views/activities/index.html.erb

@@ -1,23 +0,0 @@
1
-<h1>Activities</h1>
2
-
3
-<table class="table">
4
-  <thead>
5
-    <tr>
6
-      <th colspan="3"></th>
7
-    </tr>
8
-  </thead>
9
-
10
-  <tbody>
11
-    <% @activities.each do |activity| %>
12
-      <tr>
13
-        <td><%= link_to t(:show), group_activity_path(@group, activity) %></td>
14
-        <td><%= link_to t(:edit), edit_group_activity_path(@group, activity) %></td>
15
-        <td><%= link_to t(:destroy), group_activity_path(@group, activity), method: :delete, data: { confirm: t(:areyousure) } %></td>
16
-      </tr>
17
-    <% end %>
18
-  </tbody>
19
-</table>
20
-
21
-<br>
22
-
23
-<%= link_to t('activities.new'), new_group_activity_path(@group) %>

+ 43 - 0
app/views/activities/index.html.haml

@@ -0,0 +1,43 @@
1
+%h1
2
+  = t 'activerecord.models.activity.other'
3
+
4
+= link_to new_group_activity_path(@group), class: 'btn btn-default pull-right' do
5
+  %i.fa.fa-plus
6
+  = t 'activities.new'
7
+
8
+- isleader = @group.leaders.include?(current_person) || current_person.is_admin?
9
+
10
+%table.table
11
+  %thead
12
+    %tr
13
+      %th
14
+        = t 'activerecord.attributes.activities.name'
15
+
16
+      %th
17
+        = t 'activerecord.attributes.activities.start'
18
+
19
+      %th
20
+        P/A/?
21
+
22
+      - if isleader
23
+        %th
24
+
25
+  %tbody
26
+    - @activities.each do |a|
27
+      %tr
28
+        %td
29
+          = link_to a.name, group_activity_path(@group, a)
30
+
31
+        %td
32
+          = l a.start, format: :short
33
+
34
+        %td
35
+          = a.human_state_counts
36
+
37
+        - if isleader
38
+          %td
39
+            = link_to edit_group_activity_path(@group, a) do
40
+              %i.fa.fa-pencil
41
+
42
+= will_paginate @activities
43
+

+ 6 - 0
app/views/activities/mass_new.html.haml

@@ -0,0 +1,6 @@
1
+.container
2
+  .row
3
+    .col-md-12
4
+      = form_tag(group_activities_mass_new_path(@group), method: 'post', multipart: true) do
5
+        = file_field_tag 'spreadsheet'
6
+        = submit_tag

+ 1 - 0
config/locales/activities/en.yml

@@ -7,6 +7,7 @@ en:
7 7
     created: "Activity created."
8 8
     updated: "Activity updated."
9 9
     destroyed: "Activity destroyed."
10
+    mass_imported: "%{count} activities created!"
10 11
 
11 12
     upcoming_yours: "Upcoming activities organized by you"
12 13
     yours: "Your activities"

+ 1 - 0
config/locales/activities/nl.yml

@@ -7,6 +7,7 @@ nl:
7 7
     created: "Activiteit aangemaakt."
8 8
     updated: "Activiteit bijgewerkt."
9 9
     destroyed: "Activiteit verwijderd."
10
+    mass_imported: "%{count} activiteiten aangemaakt!"
10 11
 
11 12
     upcoming_yours: "Aankomende activiteiten georganiseerd door jou"
12 13
     yours: "Jouw activiteiten"

+ 3 - 0
config/routes.rb

@@ -37,6 +37,9 @@ Rails.application.routes.draw do
37 37
       post 'demote', to: 'members#demote', on: :member
38 38
     end
39 39
 
40
+    get 'activities/mass_new', to: 'activities#mass_new'
41
+    post 'activities/mass_new', to: 'activities#mass_create'
42
+
40 43
     resources :activities do
41 44
       post 'change_organizer', to: 'activities#change_organizer'
42 45
       put 'presence', to: 'activities#presence', on: :member

+ 2 - 0
public/batch_activities.csv

@@ -0,0 +1,2 @@
1
+name,description,location,start_date,start_time,end_date,end_time,deadline_date,deadline_time
2
+Name,Description,Location,2017-12-31,12:34:00,2017-12-31,12:43:00,2017-12-28,13:37:00