Browse Source

Added abaility for admins to add registrations

development
Godwin 8 years ago
parent
commit
481c186e08
  1. 29
      app/assets/javascripts/registrations.js
  2. 166
      app/assets/stylesheets/_application.scss
  3. 26
      app/controllers/conferences_controller.rb
  4. 54
      app/helpers/application_helper.rb
  5. 16
      app/views/conferences/admin/_stats.html.haml
  6. 4
      config/locales/en.yml

29
app/assets/javascripts/registrations.js

@ -52,6 +52,7 @@
request.open('POST', url, true); request.open('POST', url, true);
cells = editRow.getElementsByClassName('cell-editor'); cells = editRow.getElementsByClassName('cell-editor');
data.append('key', row.getAttribute('data-key')); data.append('key', row.getAttribute('data-key'));
data.append('button', 'update');
var changed = false; var changed = false;
for (var i = 0; i < cells.length; i++) { for (var i = 0; i < cells.length; i++) {
if (cells[i].value !== cells[i].getAttribute('data-value')) { if (cells[i].value !== cells[i].getAttribute('data-value')) {
@ -133,4 +134,32 @@
searchControl.addEventListener('keyup', filterTable); searchControl.addEventListener('keyup', filterTable);
searchControl.addEventListener('search', filterTable); searchControl.addEventListener('search', filterTable);
forEachElement('[data-expands]', function(button) {
button.addEventListener('click', function(event) {
var element = document.getElementById(event.target.getAttribute('data-expands'));
document.body.classList.add('expanded-element');
element.classList.add('expanded');
});
});
forEachElement('[data-contracts]', function(button) {
button.addEventListener('click', function(event) {
var element = document.getElementById(event.target.getAttribute('data-contracts'));
document.body.classList.remove('expanded-element');
element.classList.remove('expanded');
});
});
forEachElement('[data-opens-modal]', function(button) {
button.addEventListener('click', function(event) {
var element = document.getElementById(event.target.getAttribute('data-opens-modal'));
document.body.classList.add('modal-open');
element.classList.add('open');
});
});
forEachElement('[data-closes-modal]', function(element) {
element.addEventListener('click', function(event) {
document.getElementById(event.target.getAttribute('data-closes-modal')).classList.remove('open');
document.body.classList.remove('modal-open');
});
});
})(); })();

166
app/assets/stylesheets/_application.scss

@ -1,3 +1,5 @@
$bug-list: ("search-element-appearance": ());
@import "bumbleberry"; @import "bumbleberry";
@import "settings"; @import "settings";
@ -187,20 +189,15 @@ table, .table {
tr[data-key] { tr[data-key] {
cursor: cell; cursor: cell;
&:hover { &.editable:hover {
background-color: lighten($colour-2, 33%); background-color: lighten($colour-2, 33%);
} }
&.editable {
+ .editor { + .editor {
display: none; display: none;
background-color: lighten($colour-1, 50%); background-color: lighten($colour-1, 50%);
td { td {
position: relative;
vertical-align: top;
background: inherit;
cursor: default;
opacity: 0.5; opacity: 0.5;
&.has-editor { &.has-editor {
@ -217,6 +214,34 @@ table, .table {
} }
} }
.cell-editor {
&[type=number]::-webkit-inner-spin-button,
&[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
}
select.cell-editor {
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
appearance: none;
cursor: pointer;
}
&.date .cell-editor {
text-align-last: right;
}
}
}
+ .editor, &.always-edit {
td {
position: relative;
vertical-align: top;
background: inherit;
cursor: default;
.cell-editor { .cell-editor {
top: 0; top: 0;
right: 0; right: 0;
@ -234,25 +259,12 @@ table, .table {
overflow: hidden; overflow: hidden;
box-shadow: none; box-shadow: none;
text-align: inherit; text-align: inherit;
&[type=number]::-webkit-inner-spin-button,
&[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
} }
} }
select.cell-editor {
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
appearance: none;
cursor: pointer;
} }
&.date .cell-editor { &.always-edit td .cell-editor {
text-align-last: right; position: absolute;
}
}
} }
&.editing { &.editing {
@ -268,20 +280,22 @@ table, .table {
} }
} }
/*td[name] { &.always-editing {
position: relative; tr {
cursor: text; cursor: default;
&:hover { &:hover {
background-color: lighten($colour-2, 25%); background-color: transparent;
} }
input, textarea, select {
} }
.cell-editor {
position: absolute;
} }
&[data-editing="1"] { td.text {
}*/ height: 5em;
}
} }
tr.editable, tr.editor { tr.editable, tr.editor {
@ -320,8 +334,98 @@ table, .table {
.table-scroller { .table-scroller {
overflow: auto; overflow: auto;
background-color: #F8F8F8;
@include _(box-shadow, inset 0 0 10em 0 rgba(0,0,0,0.125));
table {
background-color: $white;
margin: 0 0 8.5em;
}
body.expanded-element .expanded & {
overflow: visible;
}
}
.goes-fullscreen {
[data-contracts] {
display: none;
}
}
body.modal-open {
overflow: hidden;
}
body.expanded-element {
overflow: hidden;
.goes-fullscreen.expanded {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
background-color: $white;
overflow: auto;
padding: 0 1em;
[data-expands] {
display: none;
}
[data-contracts] {
display: block;
}
}
}
#main .columns .modal-edit {
display: none;
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: 1001;
margin: 0;
background-color: rgba($black, 0.5);
&.open {
display: block;
}
.modal-edit-overlay {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
cursor: pointer;
}
table {
margin: 0;
}
.modal-edit-content {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
max-width: 40em;
margin: auto;
overflow: auto;
z-index: 1002;
background-color: #F8F8F8;
}
table {
background-color: $white; background-color: $white;
} }
}
.table { .table {
display: table; display: table;
@ -1111,6 +1215,10 @@ fieldset {
button, .button { button, .button {
width: 100%; width: 100%;
text-align: center; text-align: center;
+ button, + .button {
margin-left: 0.75em;
}
} }
} }

26
app/controllers/conferences_controller.rb

@ -508,6 +508,7 @@ class ConferencesController < ApplicationController
column_types: { column_types: {
name: :bold, name: :bold,
date: :datetime, date: :datetime,
email: :email,
companion_email: :email, companion_email: :email,
arrival: [:date, :day], arrival: [:date, :day],
departure: [:date, :day], departure: [:date, :day],
@ -532,7 +533,7 @@ class ConferencesController < ApplicationController
bike: 'forms.labels.generic.bike', bike: 'forms.labels.generic.bike',
food: 'forms.labels.generic.food', food: 'forms.labels.generic.food',
companion: 'articles.conference_registration.terms.companion', companion: 'articles.conference_registration.terms.companion',
companion_email: 'forms.labels.generic.email', companion_email: 'articles.conference_registration.terms.companion_email',
allergies: 'forms.labels.generic.allergies', allergies: 'forms.labels.generic.allergies',
registration_fees_paid: 'articles.conference_registration.headings.fees_paid', registration_fees_paid: 'articles.conference_registration.headings.fees_paid',
other: 'articles.conference_registration.headings.other', other: 'articles.conference_registration.headings.other',
@ -645,7 +646,7 @@ class ConferencesController < ApplicationController
preferred_language: I18n.backend.enabled_locales.map { |l| [ preferred_language: I18n.backend.enabled_locales.map { |l| [
(view_context.language_name l), l (view_context.language_name l), l
] }, ] },
is_attending: yes_no, is_attending: [yes_no.first],
can_provide_housing: yes_no, can_provide_housing: yes_no,
first_day: view_context.conference_days_options_list(:before), first_day: view_context.conference_days_options_list(:before),
last_day: view_context.conference_days_options_list(:after) last_day: view_context.conference_days_options_list(:after)
@ -782,10 +783,25 @@ class ConferencesController < ApplicationController
case params[:admin_step] case params[:admin_step]
when 'stats' when 'stats'
if params[:button] == 'save' || params[:button] == 'update'
if params[:button] == 'save'
return do_404 unless params[:email].present? && params[:name].present?
user = User.find_by_email(params[:email]) || User.create(email: params[:email])
user.firstname = params[:name]
user.save!
registration = ConferenceRegistration.new(
conference: @this_conference,
user_id: user.id,
steps_completed: []
)
else
registration = ConferenceRegistration.where( registration = ConferenceRegistration.where(
id: params[:key].to_i, id: params[:key].to_i,
conference_id: @this_conference.id conference_id: @this_conference.id
).limit(1).first ).limit(1).first
end
user_changed = false user_changed = false
params.each do | key, value | params.each do | key, value |
case key.to_sym case key.to_sym
@ -831,10 +847,16 @@ class ConferencesController < ApplicationController
end end
registration.user.save! if user_changed registration.user.save! if user_changed
registration.save! registration.save!
if params[:button] == 'save'
return redirect_to register_step_path(@this_conference.slug, :administration)
end
get_stats(true, params[:key].to_i) get_stats(true, params[:key].to_i)
options = view_context.registrations_table_options options = view_context.registrations_table_options
options[:html] = true options[:html] = true
return render html: view_context.excel_rows(@excel_data, {}, options) return render html: view_context.excel_rows(@excel_data, {}, options)
end
when 'edit' when 'edit'
case params[:button] case params[:button]
when 'save' when 'save'

54
app/helpers/application_helper.rb

@ -1538,6 +1538,27 @@ module ApplicationHelper
end end
end end
def html_edit_table(excel_data, options = {})
attributes = { class: options[:class], id: options[:id] }
attributes[:data] = { 'update-url' => options[:editable] } if options[:editable].present?
content_tag(:table, attributes) do
(content_tag(:tbody) do
rows = ''
excel_data[:columns].each do |column|
if (excel_data[:column_types] || {})[column] != :table && ((options[:column_names] || []).include? column)
rows += content_tag(:tr, { class: 'always-edit', data: { key: '' } }) do
attributes = { class: [excel_data[:column_types][column]], data: { 'column-id' => column } }
columns = content_tag(:th, excel_data[:keys][column].present? ? _(excel_data[:keys][column]) : '') +
edit_column(nil, column, nil, attributes, excel_data, options)
end
end
end
rows.html_safe
end)
end
end
def html_table(excel_data, options = {}) def html_table(excel_data, options = {})
options[:html] = true options[:html] = true
attributes = { class: options[:class], id: options[:id] } attributes = { class: options[:class], id: options[:id] }
@ -1672,10 +1693,22 @@ module ApplicationHelper
end end
if (options[:column_names] || []).include? column if (options[:column_names] || []).include? column
columns += edit_column(row, column, value, attributes, data, options)
else
columns += content_tag(:td, value, attributes)
end
end
end
pad_columns(columns, padding)
end
def edit_column(row, column, value, attributes, data, options)
attributes[:class] << 'has-editor' attributes[:class] << 'has-editor'
raw_value = row[:raw_values][column] || value raw_value = row.present? ? (row[:raw_values][column] || value) : nil
if options[:html] && row[:html_values].present? && row[:html_values][column].present? if row.present? && options[:html] && row[:html_values].present? && row[:html_values][column].present?
value = row[:html_values][column] value = row[:html_values][column]
end end
@ -1691,17 +1724,13 @@ module ApplicationHelper
else else
editor_attributes[:name] = column editor_attributes[:name] = column
editor_attributes[:value] = raw_value editor_attributes[:value] = raw_value
editor_attributes[:required] = :required if (options[:required_columns] || []).include? column
type = data[:column_types][column] || :unknown type = data[:column_types][column] || :unknown
editor_attributes[:type] = { money: :number, number: :number, email: :email }[type] || :text editor_attributes[:type] = { money: :number, number: :number, email: :email }[type] || :text
value = (editor_value.html_safe + content_tag(:input, nil, editor_attributes)).html_safe value = (editor_value.html_safe + content_tag(:input, nil, editor_attributes)).html_safe
end end
end
columns += content_tag(:td, value, attributes) return content_tag(:td, value, attributes)
end
end
pad_columns(columns, padding)
end end
def excel_sub_tables(row, data, padding = {}, options = {}) def excel_sub_tables(row, data, padding = {}, options = {})
@ -1747,6 +1776,15 @@ module ApplicationHelper
rows.html_safe rows.html_safe
end end
def registrations_edit_table_options
options = registrations_table_options
options[:id] = 'create-table'
options[:class] << 'always-editing'
options[:column_names] += [:name, :email]
options[:required_columns] = [:name, :email]
return options
end
def registrations_table_options def registrations_table_options
{ {
id: 'search-table', id: 'search-table',

16
app/views/conferences/admin/_stats.html.haml

@ -19,7 +19,19 @@
.actions .actions
= link_to (_'links.download.Excel'), administration_step_path(@this_conference.slug, :stats, :format => :xlsx), class: [:button, :download] = link_to (_'links.download.Excel'), administration_step_path(@this_conference.slug, :stats, :format => :xlsx), class: [:button, :download]
= link_to (_'links.download.Organizations_Excel'), administration_step_path(@this_conference.slug, :organizations, :format => :xlsx), class: [:button, :download, :subdued] = link_to (_'links.download.Organizations_Excel'), administration_step_path(@this_conference.slug, :organizations, :format => :xlsx), class: [:button, :download, :subdued]
%h4 Registrations %h4=_'articles.admin.stats.headings.Registrations'
= searchfield :search, nil, big: true .goes-fullscreen#registrations-table
.flex-column
= searchfield :search, nil, big: true, stretch: true
%a.button{data: { expands: 'registrations-table' }}='expand'
%a.button.delete{data: { contracts: 'registrations-table' }}='close'
%a.button.modify{data: { 'opens-modal': 'new-registration' }}='+'
.table-scroller .table-scroller
= html_table @excel_data, registrations_table_options = html_table @excel_data, registrations_table_options
= form_tag administration_update_path(@this_conference.slug, :stats), id: 'new-registration', class: 'modal-edit' do
.modal-edit-overlay{data: { 'closes-modal': 'new-registration' }}
.modal-edit-content
=html_edit_table @excel_data, registrations_edit_table_options
.actions
%a.button.subdued{data: { 'closes-modal': 'new-registration' }}='Cancel'
= button_tag :save, value: :save, class: :modify

4
config/locales/en.yml

@ -882,7 +882,8 @@ en:
vegan: Vegans vegan: Vegans
registrations: Number of registrations registrations: Number of registrations
completed_registrations: Number of registrations completed_registrations: Number of registrations
incomplete_registrations: Incomplete registrations completed_registrations: Number of registrations
Registrations: Registrations
meals: meals:
description: On this page you can schedule the meals that you will be serving. description: On this page you can schedule the meals that you will be serving.
no_locations_warning: Before you can add meals, you must first add locations. no_locations_warning: Before you can add meals, you must first add locations.
@ -1116,6 +1117,7 @@ en:
preregistered: Preregistered preregistered: Preregistered
registered: Registered registered: Registered
companion: Companion companion: Companion
companion_email: Companion Email
Preferred_Languages: Preferred Language Preferred_Languages: Preferred Language
is_attending: Attending? is_attending: Attending?
about_bikebike: about_bikebike:

Loading…
Cancel
Save