Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invitations2024 #2486

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
76 changes: 76 additions & 0 deletions app/controllers/event/invitation_lists_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# encoding: utf-8

# Copyright (c) 2023, Carbon. This file is part of
# hitobito and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito.

class Event::InvitationListsController < SimpleCrudController

skip_authorization_check
skip_authorize_resource

respond_to :js, only: :new

helper_method :group

def create
new_invitations = build_new_invitations
ActiveRecord::Base.transaction do
new_invitations.map(&:save).all?(&:present?)
end

redirect_to(group_people_path(group),
notice: flash_message(:success, count: new_invitations.count))
end

def new
@people_ids = params[:ids]
@event_type = params[:type]
@event_label = params[:label]
render 'new'
end

def self.model_class
Event::Invitation
end

private

def build_new_invitations
people.map do |person|
invitation = event.invitations.new
invitation.person_id = person.id
invitation.participation_type = params[:role][:type]
authorize!(:create, invitation)
end
end

def flash_message(type, attrs = {})
attrs[:event] = event.name
attrs[:event_type] = event.class.label
I18n.t("event.invitation_lists.#{action_name}.#{type}", **attrs) +
I18n.t("event.invitation_lists.#{action_name}.hint", **attrs)
end

def role_type
event.find_role_type!(params[:role][:type]) if params[:role]
end

def group
@group ||= Group.find(params[:group_id])
end

def event
@event ||= Event.find(params[:event_id])
end

def people
@people ||= Person.where(id: people_ids).distinct
end

def people_ids
list_param(:ids)
end
end

37 changes: 36 additions & 1 deletion app/controllers/event/invitations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,37 @@
# https://github.com/hitobito/hitobito.

class Event::InvitationsController < CrudController
#todo-later: include AsyncDownload

self.permitted_attrs = [:event_id, :person_id, :participation_type]

self.nesting = [Group, Event]

# TODO: open / accepted is not distinguished yet
#todo: open / accepted is not distinguished yet
self.sort_mappings = { 'status': ['declined_at'] }

decorates :group, :event

prepend_before_action :parent, :group


## def index: respond_to
## see hitobito/app/controllers/events_controller.rb
## + job
## + ..

def create
super(location: group_event_invitations_path(@group, @event))
end

def index
respond_to do |format|
format.html { super }
#todo-later: format.csv { render_tabular_in_background(:csv) }
format.csv { render_tabular(:csv) }
end
end

private

def group
Expand Down Expand Up @@ -48,6 +64,25 @@ def authorize_class
authorize!(:index_invitations, event)
end

# todo-later: This seems not to work yet...
#def render_tabular_in_background(format, name = :invitation_export)
# with_async_download_cookie(format, name) do |filename|
# Export::InvitationsExportJob.new(format,
# current_person.id,
# group.id,
# filename: filename).enqueue!
# end
#end

def render_tabular(format)
exporter = Export::Tabular::Invitations::List
send_data exporter.export(format, entries, ability), type: format
end

def ability
@ability ||= Ability.new(Person.find(current_user.id))
end

class << self
def model_class
Event::Invitation
Expand Down
11 changes: 8 additions & 3 deletions app/domain/export/tabular/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Base
self.row_class = Export::Tabular::Row
self.auto_filter = true

attr_reader :list
attr_reader :list, :ability

class << self
def export(format, *args)
Expand All @@ -40,8 +40,9 @@ def generator(format)
end
end

def initialize(list)
def initialize(list, abilitiy = nil)
@list = list
@ability = abilitiy
end

# The list of all attributes exported to the csv/xlsx.
Expand Down Expand Up @@ -95,7 +96,11 @@ def values(entry, format = nil)
end

def row_for(entry, format = nil)
row_class.new(entry, format)
row = row_class.new(entry, format)
# see comment in Export::Tabular::Row for explanation
# why this is not included in `new()`
row.ability = ability
return row
end

end
Expand Down
20 changes: 20 additions & 0 deletions app/domain/export/tabular/invitations/list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# Copyright (c) 2014-2023, Carbon. This file is part of
# hitobito and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito.

module Export::Tabular::Invitations
class List < Export::Tabular::Base

self.model_class = Event::Invitation
self.row_class = Export::Tabular::Invitations::Row

def attributes
attrs = [:person, :mail, :participation_type, :status, :declined_at, :created_at]
end

end
end

37 changes: 37 additions & 0 deletions app/domain/export/tabular/invitations/row.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

# Copyright (c) 2023-2023, Carbon. This file is part of
# hitobito and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito.

module Export::Tabular::Invitations
class Row < Export::Tabular::Row

def person
entry.person
end

def mail
entry.person.email if can?(:show, entry.person)
end

def participation_type
entry.participation_type.constantize.model_name.human
end

def status
I18n.t("activerecord.attributes.event/invitation.statuses.#{entry.status}")
end

def declined_at
entry.declined_at
end

def created_at
entry.created_at
end

end
end

17 changes: 16 additions & 1 deletion app/domain/export/tabular/row.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,17 @@ class Row

attr_reader :entry, :format

def initialize(entry, format = nil)
# setter is needed as some child-classes redefine the
# `initialize`-methode with only two parameters.
# Due to this, generic calls (i.e. from Export::Tabular::Base)
# can not set ability when initializing
# todo: refactor all child-classes to new interface
attr_accessor :ability

def initialize(entry, format = nil, ability = nil)
@entry = entry
@format = format
@ability = ability
end

def fetch(attr)
Expand All @@ -30,6 +38,13 @@ def fetch(attr)

private

def can?(*args)
if not ability
raise "Ability not initialized yet."
end
ability.can?(*args)
end

def value_for(attr)
if dynamic_attribute?(attr.to_s)
handle_dynamic_attribute(attr)
Expand Down
10 changes: 10 additions & 0 deletions app/helpers/dropdown/participation_lists.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ def init_items
add_item(event.label,
build_event_participation_lists_path(event),
**participation_lists_options)
if event.supports_invitations
add_item(event.label+" ("+I18n.t("activerecord.models.event/invitation.one")+")",
build_event_invite_path(event),
**participation_lists_options)
end
end
end

Expand All @@ -36,6 +41,11 @@ def build_event_participation_lists_path(event)
template.group_events_participation_lists_new_path(@group, type: type, label: event.label)
end

def build_event_invite_path(event)
type = event == ::Event ? nil : event.to_s
template.group_events_invitation_lists_new_path(@group, type: type, label: event.label)
end

def participation_lists_options
{ data: { checkable: true, method: :get }, remote: true }
end
Expand Down
33 changes: 33 additions & 0 deletions app/javascript/javascripts/modules/invitation_lists.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright (c) 2023, Carbon. This file is part of
# hitobito_sbv and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito.

app = window.App ||= {}

app.InvitationLists = {
updatePath: (e) ->
event = JSON.parse(e)
form = $('form#new_event_invitation')[0]
$("#new_event_invitation button[type='submit']").prop('disabled', false)
form.action = form.action.replace(/(\d|-)*?(?=\/\w*$)/, event['id'])
metaToken = $('meta[name=csrf-token]')[0].content
form.elements['authenticity_token'].value = metaToken
app.InvitationLists.resetOptions(event.types)
event.label

resetOptions: (types) ->
select = $('#role_type')
if types.length == 0
select.hide()
return

select.show()
select.empty()

$.each types, (_index, type) ->
select.append $('<option></option>').attr('value', type.name).text(type.label)
return

}

30 changes: 30 additions & 0 deletions app/jobs/export/invitation_export_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# encoding: utf-8

# Copyright (c) 2023, Cevi Schweiz. This file is part of
# hitobito and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito.

class Export::InvitationsExportJob < Export::ExportBaseJob

self.parameters = PARAMETERS + [:event_id]

def initialize(user_id, event_id, options)
super(:csv, user_id, options)
@exporter = Export::Tabular::Invitations::List
@event_id = event_id
end

private

def entries
event.invitations
.without_deleted
.order(:lft)
end

def group
@event ||= Event.find(@event_id)
end
end

30 changes: 30 additions & 0 deletions app/jobs/export/invitations_export_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# encoding: utf-8

# Copyright (c) 2023, Cevi Schweiz. This file is part of
# hitobito and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito.

class Export::InvitationsExportJob < Export::ExportBaseJob

self.parameters = PARAMETERS + [:event_id]

def initialize(format, user_id, event_id, options)
super(format, user_id, options)
@event_id = event_id
@exporter = Export::Tabular::Invitations::List
end

private

def entries
event.invitations
.without_deleted
.order(:lft)
end

def group
@event ||= Event.find(@event_id)
end
end