Bladeren bron

Add Subgroups

Maarten van den Berg 7 jaren geleden
bovenliggende
commit
4e32d8c687

+ 53 - 3
app/controllers/activities_controller.rb

@@ -1,11 +1,12 @@
1 1
 class ActivitiesController < ApplicationController
2 2
   include GroupsHelper
3 3
   include ActivitiesHelper
4
-  before_action :set_activity_and_group, only: [:show, :edit, :update, :destroy, :presence, :change_organizer]
5
-  before_action :set_group,            except: [:show, :edit, :update, :destroy, :presence, :change_organizer]
4
+  before_action :set_activity_and_group, only: [:show, :edit, :update, :destroy, :presence, :change_organizer, :create_subgroup, :update_subgroup, :destroy_subgroup]
5
+  before_action :set_group,            except: [:show, :edit, :update, :destroy, :presence, :change_organizer, :create_subgroup, :update_subgroup, :destroy_subgroup]
6
+  before_action :set_subgroup, only: [:update_subgroup, :destroy_subgroup]
6 7
   before_action :require_membership!
7 8
   before_action :require_leader!, only: [:mass_new, :mass_create, :new, :create, :destroy]
8
-  before_action :require_organizer!, only: [:edit, :update, :change_organizer]
9
+  before_action :require_organizer!, only: [:edit, :update, :change_organizer, :create_subgroup, :update_subgroup, :destroy_subgroup]
9 10
 
10 11
   # GET /groups/:id/activities
11 12
   # GET /activities.json
@@ -33,6 +34,10 @@ class ActivitiesController < ApplicationController
33 34
       .find_by(person: current_person)
34 35
     @counts = @activity.state_counts
35 36
     @num_participants = @counts.values.sum
37
+    @assignable_subgroups = @activity.subgroups
38
+      .where(is_assignable: true)
39
+      .order(name: :asc)
40
+      .pluck(:name)
36 41
   end
37 42
 
38 43
   # GET /activities/new
@@ -55,6 +60,9 @@ class ActivitiesController < ApplicationController
55 60
 
56 61
     @non_organizers_options.sort!
57 62
     @organizers_options.sort!
63
+
64
+    @subgroup = Subgroup.new if !@subgroup
65
+    @subgroups = @activity.subgroups.order(is_assignable: :desc, name: :asc)
58 66
   end
59 67
 
60 68
   # POST /activities
@@ -125,6 +133,40 @@ class ActivitiesController < ApplicationController
125 133
     end
126 134
   end
127 135
 
136
+  # POST /activities/1/subgroups
137
+  def create_subgroup
138
+    @subgroup = Subgroup.new(subgroup_params)
139
+    @subgroup.activity = @activity
140
+
141
+    if @subgroup.save
142
+      flash_message :success, I18n.t('activities.subgroups.created')
143
+      redirect_to edit_group_activity_path(@group, @activity)
144
+    else
145
+      flash_message :danger, I18n.t('activities.subgroups.create_failed')
146
+      set_edit_parameters!
147
+      render :edit
148
+    end
149
+  end
150
+
151
+  # PATCH /activities/1/subgroups/:subgroup_id
152
+  def update_subgroup
153
+    if @subgroup.update(subgroup_params)
154
+      flash_message :success, I18n.t('activities.subgroups.updated')
155
+      redirect_to edit_group_activity_path(@group, @activity)
156
+    else
157
+      flash_message :danger, I18n.t('activities.subgroups.update_failed')
158
+      set_edit_parameters!
159
+      render :edit
160
+    end
161
+  end
162
+
163
+  # DELETE /activities/1/subgroups/:subgroup_id
164
+  def destroy_subgroup
165
+    @subgroup.destroy
166
+    flash_message :success, I18n.t('activities.subgroups.destroyed')
167
+    redirect_to edit_group_activity_path(@group, @activity)
168
+  end
169
+
128 170
   # PATCH/PUT /groups/:group_id/activities/:id/presence
129 171
   # PATCH/PUT /groups/:group_id/activities/:id/presence.json
130 172
   def presence
@@ -176,8 +218,16 @@ class ActivitiesController < ApplicationController
176 218
       @group = Group.find(params[:group_id])
177 219
     end
178 220
 
221
+    def set_subgroup
222
+      @subgroup = Subgroup.find(params[:subgroup_id])
223
+    end
224
+
179 225
     # Never trust parameters from the scary internet, only allow the white list through.
180 226
     def activity_params
181 227
       params.require(:activity).permit(:name, :description, :location, :start, :end, :deadline, :reminder_at)
182 228
     end
229
+
230
+    def subgroup_params
231
+      params.require(:subgroup).permit(:name, :is_assignable)
232
+    end
183 233
 end

+ 16 - 0
app/models/activity.rb

@@ -45,6 +45,9 @@ class Activity < ApplicationRecord
45 45
     dependent: :destroy
46 46
   has_many :people, through: :participants
47 47
 
48
+  has_many :subgroups,
49
+    dependent: :destroy
50
+
48 51
   validates :name, presence: true
49 52
   validates :start, presence: true
50 53
   validate  :deadline_before_start, unless: "self.deadline.blank?"
@@ -52,6 +55,7 @@ class Activity < ApplicationRecord
52 55
   validate  :reminder_before_deadline, unless: "self.reminder_at.blank?"
53 56
 
54 57
   after_create :create_missing_participants!
58
+  after_create :copy_default_subgroups!
55 59
   after_commit :schedule_reminder, if: Proc.new {|a| a.previous_changes["reminder_at"] }
56 60
 
57 61
   # Get all people (not participants) that are organizers. Does not include
@@ -115,6 +119,18 @@ class Activity < ApplicationRecord
115 119
     end
116 120
   end
117 121
 
122
+  # Create Subgroups from the defaults set using DefaultSubgroups
123
+  def copy_default_subgroups!
124
+    defaults = self.group.default_subgroups
125
+
126
+    defaults.each do |dsg|
127
+      sg = Subgroup.new(activity: self)
128
+      sg.name = dsg.name
129
+      sg.is_assignable = dsg.is_assignable
130
+      sg.save! # Should never fail, as DSG and SG have identical validation, and names cannot clash.
131
+    end
132
+  end
133
+
118 134
   # Create multiple Activities from data in a CSV file, assign to a group, return.
119 135
   def self.from_csv(content, group)
120 136
     reader = CSV.parse(content, {headers: true, skip_blanks: true})

+ 6 - 0
app/models/subgroup.rb

@@ -0,0 +1,6 @@
1
+class Subgroup < ApplicationRecord
2
+  belongs_to :activity
3
+
4
+  validates :name, presence: true, uniqueness: { scope: :activity, case_sensitive: false }
5
+  validates :activity, presence: true
6
+end

+ 65 - 3
app/views/activities/edit.html.haml

@@ -33,6 +33,68 @@
33 33
     - else
34 34
       = t 'activities.organizers.no_organizers'
35 35
 
36
-= link_to t(:back), group_activity_path(@group, @activity)
37
-|
38
-= link_to t(:overview), group_activities_path(@group)
36
+%h2
37
+  = t 'activities.subgroups.manage'
38
+
39
+.row
40
+  .col-md-6
41
+    %h4
42
+      = t 'activities.subgroups.create'
43
+
44
+    = form_for(@subgroup, url: group_activity_create_subgroup_path(@group, @activity), method: :post) do |f|
45
+
46
+      - if @subgroup.errors.any?
47
+        .has-error.form-group#error_explanation
48
+          %ul
49
+            - @subgroup.errors.full_messages.each do |message|
50
+              %li= message
51
+
52
+      .form-group{ class: [ ('has-error' if @subgroup.errors.any?) ] }
53
+
54
+        %label
55
+          = t 'activerecord.attributes.subgroup.name'
56
+        = f.text_field :name, class: 'form-control'
57
+
58
+      .form-group
59
+        .check-box
60
+          %label
61
+            = f.check_box :is_assignable
62
+            = t 'activerecord.attributes.subgroup.is_assignable'
63
+            (
64
+            %i.fa.fa-random
65
+            )
66
+
67
+      = f.submit t('activities.subgroups.create'), class: 'btn btn-success'
68
+
69
+  .col-md-6
70
+    - if @activity.subgroups.blank?
71
+      %p
72
+        = t 'activities.subgroups.none'
73
+    - else
74
+      %table.table
75
+        %tr
76
+          %th
77
+            = t 'activerecord.attributes.subgroup.name'
78
+
79
+          %th
80
+            %i.fa.fa-random
81
+
82
+          %th
83
+            %i.fa.fa-cogs
84
+        - @subgroups.each do |sg|
85
+          %tr
86
+            %td= sg.name
87
+            %td
88
+              = link_to group_activity_update_subgroup_path(@group, @activity, sg.id, 'subgroup[is_assignable]' => !sg.is_assignable), method: :patch, class: 'btn btn-default btn-xs' do
89
+                - if sg.is_assignable
90
+                  %i.fa.fa-check
91
+                - else
92
+                  %i.fa.fa-times
93
+
94
+            %td
95
+              = link_to group_activity_destroy_subgroup_path(@group, @activity, sg.id), method: :delete, class: 'btn btn-danger btn-xs' do
96
+                %i.fa.fa-trash
97
+
98
+.btn-group
99
+  = link_to t(:back), group_activity_path(@group, @activity), class: 'btn btn-default'
100
+  = link_to t(:overview), group_activities_path(@group), class: 'btn btn-default'

+ 8 - 0
app/views/activities/show.html.haml

@@ -63,6 +63,14 @@
63 63
             - if @activity.deadline
64 64
               = l @activity.deadline, format: :long
65 65
 
66
+        - if @assignable_subgroups.any?
67
+          %tr
68
+            %td
69
+              = t 'activerecord.attributes.activity.subgroups'
70
+
71
+            %td
72
+              = @assignable_subgroups.join(', ')
73
+
66 74
   - if @ownparticipant
67 75
     .col-md-3
68 76
       .panel.panel-default

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

@@ -75,3 +75,17 @@ en:
75 75
         subject: "You are now listed as 'attending' for %{activity}"
76 76
         havenot_responded: "You have not yet indicated if you will be at %{activity}. Because we assume that you're present if you don't respond, your response has been set to 'attending'."
77 77
         if_cannot: "If you wish to change this, you can change your response until %{deadline} using the following link:"
78
+
79
+    subgroups:
80
+      manage: 'Manage subgroups'
81
+      create: 'Create subgroup'
82
+      created: 'Subgroup created.'
83
+      create_failed: 'Could not create subgroup!'
84
+
85
+      update: 'Update subgroup'
86
+      updated: 'Subgroup updated.'
87
+      update_failed: 'Could not update subgroup!'
88
+
89
+      destroy: 'Destroy subgroup'
90
+      destroyed: 'Subgroup destroyed.'
91
+      none: 'There are no subgroups.'

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

@@ -83,3 +83,17 @@ nl:
83 83
         subject: "Je bent automatisch aangemeld voor %{activity}"
84 84
         havenot_responded: "Je hebt nog niet aangegeven of je bij %{activity} kunt zijn. Omdat we ervan uitgaan dat je er bent als je niks aangeeft, is je reactie automatisch op 'aanwezig' gezet."
85 85
         if_cannot: "Als je toch niet aanwezig kunt zijn, kan je dit tot %{deadline} aangeven via de volgende link:"
86
+
87
+    subgroups:
88
+      manage: 'Subgroepen aanpassen'
89
+      create: 'Subgroep aanmaken'
90
+      created: 'Subgroep aangemaakt.'
91
+      create_failed: 'Kon subgroep niet opslaan!'
92
+
93
+      update: 'Subgroep bijwerken'
94
+      updated: 'Subgroep bijgewerkt.'
95
+      update_failed: 'Kon subgroep niet bijwerken!'
96
+
97
+      destroy: 'Subgroep verwijderen'
98
+      destroyed: 'Subgroep verwijderd.'
99
+      none: 'Er zijn geen subgroepen.'

+ 9 - 0
config/locales/translation_nl.yml

@@ -28,6 +28,10 @@ nl:
28 28
         one: Standaardgroep
29 29
         other: Standaardgroepen
30 30
 
31
+      subgroup:
32
+        one: Subgroep
33
+        other: Subgroepen
34
+
31 35
     attributes:
32 36
       activity:
33 37
         deadline: Deadline  #g
@@ -41,6 +45,7 @@ nl:
41 45
         start: Start  #g
42 46
         reminder_at: Herinnering om
43 47
         reminder_done: Herinnering verstuurd
48
+        subgroups: :activerecord.models.subgroup.other
44 49
 
45 50
       group:
46 51
         activities: Activiteiten  #g
@@ -96,3 +101,7 @@ nl:
96 101
       default_subgroup:
97 102
         name: Naam
98 103
         is_assignable: Gebruiken voor indelen
104
+
105
+      subgroup:
106
+        name: Naam
107
+        is_assignable: Gebruiken voor indelen

+ 4 - 0
config/routes.rb

@@ -52,6 +52,10 @@ Rails.application.routes.draw do
52 52
       post 'change_organizer', to: 'activities#change_organizer'
53 53
       put 'presence', to: 'activities#presence', on: :member
54 54
       patch 'presence', to: 'activities#presence', on: :member
55
+
56
+      post 'subgroups', to: 'activities#create_subgroup', as: 'create_subgroup'
57
+      patch 'subgroups/:subgroup_id', to: 'activities#update_subgroup', as: 'update_subgroup'
58
+      delete 'subgroups(/:subgroup_id)', to: 'activities#destroy_subgroup', as: 'destroy_subgroup'
55 59
     end
56 60
   end
57 61
   get 'my_groups', to: 'groups#user_groups', as: :user_groups

+ 11 - 0
db/migrate/20171001124009_create_subgroups.rb

@@ -0,0 +1,11 @@
1
+class CreateSubgroups < ActiveRecord::Migration[5.0]
2
+  def change
3
+    create_table :subgroups do |t|
4
+      t.references :activity, foreign_key: true
5
+      t.string :name, null: false
6
+      t.boolean :is_assignable
7
+
8
+      t.timestamps
9
+    end
10
+  end
11
+end

+ 10 - 1
db/schema.rb

@@ -10,7 +10,7 @@
10 10
 #
11 11
 # It's strongly recommended that you check this file into your version control system.
12 12
 
13
-ActiveRecord::Schema.define(version: 20170930201201) do
13
+ActiveRecord::Schema.define(version: 20171001124009) do
14 14
 
15 15
   create_table "activities", force: :cascade do |t|
16 16
     t.string   "name"
@@ -105,6 +105,15 @@ ActiveRecord::Schema.define(version: 20170930201201) do
105 105
     t.index ["user_id"], name: "index_sessions_on_user_id"
106 106
   end
107 107
 
108
+  create_table "subgroups", force: :cascade do |t|
109
+    t.integer  "activity_id"
110
+    t.string   "name",          null: false
111
+    t.boolean  "is_assignable"
112
+    t.datetime "created_at",    null: false
113
+    t.datetime "updated_at",    null: false
114
+    t.index ["activity_id"], name: "index_subgroups_on_activity_id"
115
+  end
116
+
108 117
   create_table "tokens", force: :cascade do |t|
109 118
     t.string   "token"
110 119
     t.datetime "expires"