Editable registrations
This commit is contained in:
parent
32474fae1c
commit
fe9dd2b493
@ -3,15 +3,17 @@
|
|||||||
|
|
||||||
function filterTable() {
|
function filterTable() {
|
||||||
forEach(document.getElementById('search-table').getElementsByTagName('TBODY')[0].getElementsByTagName('TR'), function(tr) {
|
forEach(document.getElementById('search-table').getElementsByTagName('TBODY')[0].getElementsByTagName('TR'), function(tr) {
|
||||||
tr.classList.remove('hidden');
|
if (tr.classList.contains('editable')) {
|
||||||
|
tr.classList.remove('hidden');
|
||||||
|
|
||||||
var value = searchControl.value;
|
var value = searchControl.value;
|
||||||
if (value) {
|
if (value) {
|
||||||
var words = value.split(/\s+/);
|
var words = value.split(/\s+/);
|
||||||
for (var i = 0; i < words.length; i++) {
|
for (var i = 0; i < words.length; i++) {
|
||||||
var word = new RegExp(words[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), "i");
|
var word = new RegExp(words[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), "i");
|
||||||
if (tr.innerHTML.search(word) == -1) {
|
if (tr.innerHTML.search(word) == -1) {
|
||||||
tr.classList.add('hidden');
|
tr.classList.add('hidden');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,39 +32,50 @@
|
|||||||
function saveRow(row) {
|
function saveRow(row) {
|
||||||
if (row) {
|
if (row) {
|
||||||
row.classList.remove('editing');
|
row.classList.remove('editing');
|
||||||
/*row.removeAttribute('data-editing');
|
var table = row.parentElement.parentElement;
|
||||||
forEach(row.getElementsByTagName('TD'), function(cell) {
|
var editRow = row.nextSibling;
|
||||||
var input = cell.getElementsByClassName('cell-editor')[0];
|
var url = table.getAttribute('data-update-url');
|
||||||
if (input) {
|
var data = new FormData();
|
||||||
cell.removeChild(input);
|
var request = new XMLHttpRequest();
|
||||||
|
request.onreadystatechange = function() {
|
||||||
|
if (request.readyState == 4) {
|
||||||
|
row.classList.remove('requesting');
|
||||||
|
if (request.status == 200 && request.responseText) {
|
||||||
|
var tempTable = document.createElement('table');
|
||||||
|
tempTable.innerHTML = request.responseText;
|
||||||
|
var rows = tempTable.getElementsByTagName('tr');
|
||||||
|
row.innerHTML = rows[0].innerHTML;
|
||||||
|
editRow.innerHTML = rows[1].innerHTML;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});*/
|
request.open('POST', url, true);
|
||||||
|
cells = editRow.getElementsByClassName('cell-editor');
|
||||||
|
data.append('key', row.getAttribute('data-key'));
|
||||||
|
var changed = false;
|
||||||
|
for (var i = 0; i < cells.length; i++) {
|
||||||
|
if (cells[i].value !== cells[i].getAttribute('data-value')) {
|
||||||
|
data.append(cells[i].getAttribute('name'), cells[i].value);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
row.classList.add('requesting');
|
||||||
|
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||||
|
request.send(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function editTableCell(cell) {
|
function editTableCell(cell) {
|
||||||
if (selectorMatches(cell, 'tr[data-key].editable td')) {
|
if (selectorMatches(cell, 'tr[data-key].editable td')) {
|
||||||
editTableRow(cell.parentElement, cell);
|
editTableRow(cell.parentElement, cell);
|
||||||
}
|
} else if (!selectorMatches(cell, 'tr[data-key].editable + tr, tr[data-key].editable + tr *')) {
|
||||||
/*var currentRow = document.querySelector('[data-key][data-editing="1"]');
|
var currentRow = document.querySelector('tr[data-key].editable.editing');
|
||||||
if (currentRow && !currentRow.contains(cell)) {
|
if (currentRow) {
|
||||||
saveRow(currentRow);
|
saveRow(currentRow);
|
||||||
}
|
|
||||||
|
|
||||||
if (selectorMatches(cell, 'tr[data-key] td[name]')) {
|
|
||||||
if (!cell.getElementsByClassName('cell-editor').length) {
|
|
||||||
//var tr = cell.parentElement;
|
|
||||||
|
|
||||||
//saveRow(document.querySelector('[data-key][data-editing="1"]'), tr);
|
|
||||||
cell.parentElement.setAttribute('data-editing', "1");
|
|
||||||
|
|
||||||
var value = cell.innerHTML;
|
|
||||||
cell.innerHTML += '<textarea type="text" name="' + cell.getAttribute('name') + '" class="cell-editor">' + value + '</textarea>';
|
|
||||||
cell.parentElement.classList.add();
|
|
||||||
setTimeout(function() { cell.getElementsByClassName('cell-editor')[0].focus(); }, 100);
|
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
function editTableRow(row, cell) {
|
function editTableRow(row, cell) {
|
||||||
if (selectorMatches(row, 'tr[data-key].editable')) {
|
if (selectorMatches(row, 'tr[data-key].editable')) {
|
||||||
@ -78,11 +91,39 @@
|
|||||||
if (cell) {
|
if (cell) {
|
||||||
focusElement = editor.querySelector('td[data-column-id="' + cell.getAttribute('data-column-id') + '"] .cell-editor');
|
focusElement = editor.querySelector('td[data-column-id="' + cell.getAttribute('data-column-id') + '"] .cell-editor');
|
||||||
}
|
}
|
||||||
(focusElement || editor.getElementsByClassName('cell-editor')[0]).focus();
|
focusElement = focusElement || editor.getElementsByClassName('cell-editor')[0];
|
||||||
|
focusElement.focus();
|
||||||
|
if (focusElement.tagName === 'TEXTAREA' || (focusElement.tagName === 'INPUT' && focusElement.type != 'number' && focusElement.type != 'email')) {
|
||||||
|
focusElement.setSelectionRange(0, focusElement.value.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener('click', function (event) { editTableCell(event.target); });
|
document.addEventListener('click', function (event) { editTableCell(event.target); });
|
||||||
|
document.addEventListener('keyup', function (event) {
|
||||||
|
if (event.code === "Enter") {
|
||||||
|
var currentRow = document.querySelector('tr[data-key].editable.editing');
|
||||||
|
if (currentRow) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
var next = event.shiftKey ? 'previousSibling' : 'nextSibling';
|
||||||
|
var cell = document.activeElement.parentElement.getAttribute('data-column-id');
|
||||||
|
var row = currentRow[next] ? currentRow[next][next] : null;
|
||||||
|
if (!row) {
|
||||||
|
rows = currentRow.parentElement.children;
|
||||||
|
row = event.shiftKey ? rows[rows.length - 2] : rows[0];
|
||||||
|
}
|
||||||
|
editTableRow(row, row.querySelector('[data-column-id="' + cell + '"]'));
|
||||||
|
}
|
||||||
|
} else if (event.code === "Escape") {
|
||||||
|
var currentRow = document.querySelector('tr[data-key].editable.editing');
|
||||||
|
if (currentRow) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
saveRow(currentRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
if (document.observe) {
|
if (document.observe) {
|
||||||
document.observe("focusin", function (event) { editTableCell(event.target); });
|
document.observe("focusin", function (event) { editTableCell(event.target); });
|
||||||
} else {
|
} else {
|
||||||
|
@ -185,7 +185,7 @@ table, .table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tr[data-key] {
|
tr[data-key] {
|
||||||
cursor: default;
|
cursor: cell;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: lighten($colour-2, 33%);
|
background-color: lighten($colour-2, 33%);
|
||||||
@ -205,6 +205,16 @@ table, .table {
|
|||||||
|
|
||||||
&.has-editor {
|
&.has-editor {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
|
@include after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 0.25em;
|
||||||
|
background-color: rgba($black, 0.125);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell-editor {
|
.cell-editor {
|
||||||
@ -224,8 +234,13 @@ table, .table {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
text-align: inherit;
|
text-align: inherit;
|
||||||
//border-bottom: 0.25em solid rgba(0,0,0,0.25);
|
|
||||||
|
&[type=number]::-webkit-inner-spin-button,
|
||||||
|
&[type=number]::-webkit-outer-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
select.cell-editor {
|
select.cell-editor {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
@ -233,6 +248,10 @@ table, .table {
|
|||||||
appearance: none;
|
appearance: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.date .cell-editor {
|
||||||
|
text-align-last: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,15 +288,32 @@ table, .table {
|
|||||||
td {
|
td {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
&.text {
|
&.date, &.datetime, &.money, &.number {
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.date, &.datetime, &.money {
|
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.text {
|
||||||
|
max-width: 20em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.editable td.text,
|
||||||
|
tr.editor td.text .value {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.editor {
|
||||||
|
td.text .cell-editor {
|
||||||
|
white-space: normal;
|
||||||
|
bottom: auto;
|
||||||
|
height: 10em;
|
||||||
|
z-index: 1;
|
||||||
|
background: inherit;
|
||||||
|
overflow: auto !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,94 +336,7 @@ class ConferencesController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
when :stats
|
when :stats
|
||||||
@registrations = ConferenceRegistration.where(:conference_id => @this_conference.id).sort { |a,b| (a.user.present? ? (a.user.firstname || '') : '').downcase <=> (b.user.present? ? (b.user.firstname || '') : '').downcase }
|
get_stats(!request.format.xlsx?)
|
||||||
@excel_data = {
|
|
||||||
columns: [
|
|
||||||
:name,
|
|
||||||
:email,
|
|
||||||
:status,
|
|
||||||
:registration_fees_paid,
|
|
||||||
:date,
|
|
||||||
:city,
|
|
||||||
:preferred_language,
|
|
||||||
:languages,
|
|
||||||
:arrival,
|
|
||||||
:departure,
|
|
||||||
:housing,
|
|
||||||
:bike,
|
|
||||||
:food,
|
|
||||||
:companion,
|
|
||||||
:companion_email,
|
|
||||||
:allergies
|
|
||||||
],
|
|
||||||
column_types: {
|
|
||||||
name: :bold,
|
|
||||||
date: :datetime,
|
|
||||||
arrival: [:date, :day],
|
|
||||||
departure: [:date, :day],
|
|
||||||
registration_fees_paid: :money,
|
|
||||||
allergies: :text
|
|
||||||
},
|
|
||||||
keys: {
|
|
||||||
name: 'forms.labels.generic.name',
|
|
||||||
email: 'forms.labels.generic.email',
|
|
||||||
status: 'forms.labels.generic.registration_status',
|
|
||||||
city: 'forms.labels.generic.location',
|
|
||||||
date: 'articles.conference_registration.terms.Date',
|
|
||||||
languages: 'articles.conference_registration.terms.Languages',
|
|
||||||
preferred_language: 'articles.conference_registration.terms.Preferred_Languages',
|
|
||||||
arrival: 'forms.labels.generic.arrival',
|
|
||||||
departure: 'forms.labels.generic.departure',
|
|
||||||
housing: 'forms.labels.generic.housing',
|
|
||||||
bike: 'forms.labels.generic.bike',
|
|
||||||
food: 'forms.labels.generic.food',
|
|
||||||
companion: 'articles.conference_registration.terms.companion',
|
|
||||||
companion_email: 'forms.labels.generic.email',
|
|
||||||
allergies: 'forms.labels.generic.allergies',
|
|
||||||
registration_fees_paid: 'articles.conference_registration.headings.fees_paid'
|
|
||||||
},
|
|
||||||
data: []
|
|
||||||
}
|
|
||||||
@registrations.each do | r |
|
|
||||||
user = r.user_id ? User.where(id: r.user_id).first : nil
|
|
||||||
if user.present?
|
|
||||||
companion = view_context.companion(r)
|
|
||||||
companion = companion.is_a?(User) ? companion.name : (view_context._"articles.conference_registration.terms.registration_status.#{companion}") if companion.present?
|
|
||||||
steps = r.steps_completed || []
|
|
||||||
|
|
||||||
@excel_data[:data] << {
|
|
||||||
id: r.id,
|
|
||||||
name: user.firstname || '',
|
|
||||||
email: user.email || '',
|
|
||||||
status: (view_context._"articles.conference_registration.terms.registration_status.#{(steps.include? 'questions') ? 'registered' : ((steps.include? 'contact_info') ? 'preregistered' : 'unregistered')}"),
|
|
||||||
date: r.created_at ? r.created_at.strftime("%F %T") : '',
|
|
||||||
city: r.city || '',
|
|
||||||
preferred_language: user.locale.present? ? (view_context.language_name user.locale) : '',
|
|
||||||
languages: ((r.languages || []).map { |x| view_context.language_name x }).join(', ').to_s,
|
|
||||||
arrival: r.arrival ? r.arrival.strftime("%F %T") : '',
|
|
||||||
departure: r.departure ? r.departure.strftime("%F %T") : '',
|
|
||||||
housing: r.housing.present? ? (view_context._"articles.conference_registration.questions.housing.#{r.housing}") : '',
|
|
||||||
bike: r.bike.present? ? (view_context._"articles.conference_registration.questions.bike.#{r.bike}") : '',
|
|
||||||
food: r.food.present? ? (view_context._"articles.conference_registration.questions.food.#{r.food}") : '',
|
|
||||||
companion: companion,
|
|
||||||
companion_email: ((r.housing_data || {})['companions'] || ['']).first,
|
|
||||||
allergies: r.allergies,
|
|
||||||
registration_fees_paid: r.registration_fees_paid,
|
|
||||||
raw_values: {
|
|
||||||
housing: r.housing,
|
|
||||||
bike: r.bike,
|
|
||||||
food: r.food,
|
|
||||||
arrival: r.arrival,
|
|
||||||
departure: r.departure
|
|
||||||
},
|
|
||||||
html_values: {
|
|
||||||
date: r.created_at.present? ? r.created_at.strftime("%F %T") : '',
|
|
||||||
arrival: r.arrival.present? ? view_context.date(r.arrival.to_date, :span_same_year_date_1) : '',
|
|
||||||
departure: r.departure.present? ? view_context.date(r.departure.to_date, :span_same_year_date_1) : ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if request.format.xlsx?
|
if request.format.xlsx?
|
||||||
logger.info "Generating stats.xls"
|
logger.info "Generating stats.xls"
|
||||||
@ -437,22 +350,6 @@ class ConferencesController < ApplicationController
|
|||||||
@donation_count = 0
|
@donation_count = 0
|
||||||
@donations = 0
|
@donations = 0
|
||||||
@food = { meat: 0, vegan: 0, vegetarian: 0, all: 0 }
|
@food = { meat: 0, vegan: 0, vegetarian: 0, all: 0 }
|
||||||
@column_options = {
|
|
||||||
housing: ConferenceRegistration.all_housing_options.map { |h| [
|
|
||||||
(view_context._"articles.conference_registration.questions.housing.#{h}"),
|
|
||||||
h] },
|
|
||||||
bike: ConferenceRegistration.all_bike_options.map { |b| [
|
|
||||||
(view_context._"articles.conference_registration.questions.bike.#{b}"),
|
|
||||||
b] },
|
|
||||||
food: ConferenceRegistration.all_food_options.map { |f| [
|
|
||||||
(view_context._"articles.conference_registration.questions.food.#{f}"),
|
|
||||||
f] },
|
|
||||||
arrival: view_context.conference_days_options_list(:before_plus_one),
|
|
||||||
departure: view_context.conference_days_options_list(:after_minus_one),
|
|
||||||
preferred_language: I18n.backend.enabled_locales.map { |l| [
|
|
||||||
(view_context.language_name l), l
|
|
||||||
] }
|
|
||||||
}
|
|
||||||
@registrations.each do | r |
|
@registrations.each do | r |
|
||||||
if r.steps_completed.include? 'questions'
|
if r.steps_completed.include? 'questions'
|
||||||
@completed_registrations += 1
|
@completed_registrations += 1
|
||||||
@ -576,6 +473,191 @@ class ConferencesController < ApplicationController
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_stats(html_format = false, id = nil)
|
||||||
|
@registrations = ConferenceRegistration.where(:conference_id => @this_conference.id).sort { |a,b| (a.user.present? ? (a.user.firstname || '') : '').downcase <=> (b.user.present? ? (b.user.firstname || '') : '').downcase }
|
||||||
|
@excel_data = {
|
||||||
|
columns: [
|
||||||
|
:name,
|
||||||
|
:email,
|
||||||
|
:status,
|
||||||
|
:is_attending,
|
||||||
|
:registration_fees_paid,
|
||||||
|
:date,
|
||||||
|
:city,
|
||||||
|
:preferred_language
|
||||||
|
] +
|
||||||
|
User.AVAILABLE_LANGUAGES.map { |l| "language_#{l}".to_sym } +
|
||||||
|
[
|
||||||
|
:arrival,
|
||||||
|
:departure,
|
||||||
|
:housing,
|
||||||
|
:bike,
|
||||||
|
:food,
|
||||||
|
:companion,
|
||||||
|
:companion_email,
|
||||||
|
:allergies,
|
||||||
|
:other,
|
||||||
|
:can_provide_housing,
|
||||||
|
:first_day,
|
||||||
|
:last_day,
|
||||||
|
:address,
|
||||||
|
:phone
|
||||||
|
] + ConferenceRegistration.all_spaces + [
|
||||||
|
:notes
|
||||||
|
],
|
||||||
|
column_types: {
|
||||||
|
name: :bold,
|
||||||
|
date: :datetime,
|
||||||
|
companion_email: :email,
|
||||||
|
arrival: [:date, :day],
|
||||||
|
departure: [:date, :day],
|
||||||
|
registration_fees_paid: :money,
|
||||||
|
allergies: :text,
|
||||||
|
other: :text,
|
||||||
|
first_day: [:date, :day],
|
||||||
|
last_day: [:date, :day],
|
||||||
|
notes: :text
|
||||||
|
},
|
||||||
|
keys: {
|
||||||
|
name: 'forms.labels.generic.name',
|
||||||
|
email: 'forms.labels.generic.email',
|
||||||
|
status: 'forms.labels.generic.registration_status',
|
||||||
|
is_attending: 'articles.conference_registration.terms.is_attending',
|
||||||
|
city: 'forms.labels.generic.location',
|
||||||
|
date: 'articles.conference_registration.terms.Date',
|
||||||
|
preferred_language: 'articles.conference_registration.terms.Preferred_Languages',
|
||||||
|
arrival: 'forms.labels.generic.arrival',
|
||||||
|
departure: 'forms.labels.generic.departure',
|
||||||
|
housing: 'forms.labels.generic.housing',
|
||||||
|
bike: 'forms.labels.generic.bike',
|
||||||
|
food: 'forms.labels.generic.food',
|
||||||
|
companion: 'articles.conference_registration.terms.companion',
|
||||||
|
companion_email: 'forms.labels.generic.email',
|
||||||
|
allergies: 'forms.labels.generic.allergies',
|
||||||
|
registration_fees_paid: 'articles.conference_registration.headings.fees_paid',
|
||||||
|
other: 'articles.conference_registration.headings.other',
|
||||||
|
can_provide_housing: 'articles.conference_registration.can_provide_housing',
|
||||||
|
first_day: 'forms.labels.generic.first_day',
|
||||||
|
last_day: 'forms.labels.generic.last_day',
|
||||||
|
notes: 'forms.labels.generic.notes',
|
||||||
|
phone: 'forms.labels.generic.phone',
|
||||||
|
address: 'forms.labels.generic.address'
|
||||||
|
},
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
User.AVAILABLE_LANGUAGES.each do | l |
|
||||||
|
@excel_data[:keys]["language_#{l}".to_sym] = "languages.#{l.to_s}"
|
||||||
|
end
|
||||||
|
ConferenceRegistration.all_spaces.each do |s|
|
||||||
|
@excel_data[:column_types][s] = :number
|
||||||
|
@excel_data[:keys][s] = "forms.labels.generic.#{s.to_s}"
|
||||||
|
end
|
||||||
|
@registrations.each do | r |
|
||||||
|
user = r.user_id ? User.where(id: r.user_id).first : nil
|
||||||
|
if user.present?
|
||||||
|
companion = view_context.companion(r)
|
||||||
|
companion = companion.is_a?(User) ? companion.name : (view_context._"articles.conference_registration.terms.registration_status.#{companion}") if companion.present?
|
||||||
|
steps = r.steps_completed || []
|
||||||
|
|
||||||
|
if id.nil? || id == r.id
|
||||||
|
housing_data = r.housing_data || {}
|
||||||
|
availability = housing_data['availability'] || []
|
||||||
|
availability[0] = Date.parse(availability[0]) if availability[0].present?
|
||||||
|
availability[1] = Date.parse(availability[1]) if availability[1].present?
|
||||||
|
|
||||||
|
data = {
|
||||||
|
id: r.id,
|
||||||
|
name: user.firstname || '',
|
||||||
|
email: user.email || '',
|
||||||
|
status: (view_context._"articles.conference_registration.terms.registration_status.#{(steps.include? 'questions') ? 'registered' : ((steps.include? 'contact_info') ? 'preregistered' : 'unregistered')}"),
|
||||||
|
is_attending: (view_context._"articles.conference_registration.questions.bike.#{r.is_attending == 'n' ? 'no' : 'yes'}"),
|
||||||
|
date: r.created_at ? r.created_at.strftime("%F %T") : '',
|
||||||
|
city: r.city || '',
|
||||||
|
preferred_language: user.locale.present? ? (view_context.language_name user.locale) : '',
|
||||||
|
#languages: ((r.languages || []).map { |x| view_context.language_name x }).join(', ').to_s,
|
||||||
|
arrival: r.arrival ? r.arrival.strftime("%F %T") : '',
|
||||||
|
departure: r.departure ? r.departure.strftime("%F %T") : '',
|
||||||
|
housing: r.housing.present? ? (view_context._"articles.conference_registration.questions.housing.#{r.housing}") : '',
|
||||||
|
bike: r.bike.present? ? (view_context._"articles.conference_registration.questions.bike.#{r.bike}") : '',
|
||||||
|
food: r.food.present? ? (view_context._"articles.conference_registration.questions.food.#{r.food}") : '',
|
||||||
|
companion: companion,
|
||||||
|
companion_email: (housing_data['companions'] || ['']).first,
|
||||||
|
allergies: r.allergies,
|
||||||
|
registration_fees_paid: r.registration_fees_paid,
|
||||||
|
other: r.other,
|
||||||
|
can_provide_housing: r.can_provide_housing ? (view_context._'articles.conference_registration.questions.bike.yes') : '',
|
||||||
|
first_day: availability[0].present? ? availability[0].strftime("%F %T") : '',
|
||||||
|
last_day: availability[1].present? ? availability[1].strftime("%F %T") : '',
|
||||||
|
notes: housing_data['notes'],
|
||||||
|
address: housing_data['address'],
|
||||||
|
phone: housing_data['phone'],
|
||||||
|
raw_values: {
|
||||||
|
housing: r.housing,
|
||||||
|
bike: r.bike,
|
||||||
|
food: r.food,
|
||||||
|
arrival: r.arrival.present? ? r.arrival.to_date : nil,
|
||||||
|
departure: r.departure.present? ? r.departure.to_date : nil,
|
||||||
|
preferred_language: user.locale,
|
||||||
|
is_attending: r.is_attending != 'n',
|
||||||
|
can_provide_housing: r.can_provide_housing,
|
||||||
|
first_day: availability[0].present? ? availability[0].to_date : nil,
|
||||||
|
last_day: availability[1].present? ? availability[1].to_date : nil
|
||||||
|
},
|
||||||
|
html_values: {
|
||||||
|
date: r.created_at.present? ? r.created_at.strftime("%F %T") : '',
|
||||||
|
arrival: r.arrival.present? ? view_context.date(r.arrival.to_date, :span_same_year_date_1) : '',
|
||||||
|
departure: r.departure.present? ? view_context.date(r.departure.to_date, :span_same_year_date_1) : '',
|
||||||
|
first_day: availability[0].present? ? view_context.date(availability[0].to_date, :span_same_year_date_1) : '',
|
||||||
|
last_day: availability[1].present? ? view_context.date(availability[1].to_date, :span_same_year_date_1) : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
User.AVAILABLE_LANGUAGES.each do | l |
|
||||||
|
can_speak = ((user.languages || []).include? l.to_s)
|
||||||
|
data["language_#{l}".to_sym] = (can_speak ? (view_context._'articles.conference_registration.questions.bike.yes') : '')
|
||||||
|
data[:raw_values]["language_#{l}".to_sym] = can_speak
|
||||||
|
end
|
||||||
|
ConferenceRegistration.all_spaces.each do |s|
|
||||||
|
space = (housing_data['space'] || {})[s.to_s]
|
||||||
|
data[s] = space.present? ? space.to_i : nil
|
||||||
|
end
|
||||||
|
@excel_data[:data] << data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if html_format
|
||||||
|
yes_no = [
|
||||||
|
[(view_context._"articles.conference_registration.questions.bike.yes"), true],
|
||||||
|
[(view_context._"articles.conference_registration.questions.bike.no"), false]
|
||||||
|
]
|
||||||
|
@column_options = {
|
||||||
|
housing: ConferenceRegistration.all_housing_options.map { |h| [
|
||||||
|
(view_context._"articles.conference_registration.questions.housing.#{h}"),
|
||||||
|
h] },
|
||||||
|
bike: ConferenceRegistration.all_bike_options.map { |b| [
|
||||||
|
(view_context._"articles.conference_registration.questions.bike.#{b}"),
|
||||||
|
b] },
|
||||||
|
food: ConferenceRegistration.all_food_options.map { |f| [
|
||||||
|
(view_context._"articles.conference_registration.questions.food.#{f}"),
|
||||||
|
f] },
|
||||||
|
arrival: view_context.conference_days_options_list(:before_plus_one),
|
||||||
|
departure: view_context.conference_days_options_list(:after_minus_one),
|
||||||
|
preferred_language: I18n.backend.enabled_locales.map { |l| [
|
||||||
|
(view_context.language_name l), l
|
||||||
|
] },
|
||||||
|
is_attending: yes_no,
|
||||||
|
can_provide_housing: yes_no,
|
||||||
|
first_day: view_context.conference_days_options_list(:before),
|
||||||
|
last_day: view_context.conference_days_options_list(:after)
|
||||||
|
}
|
||||||
|
User.AVAILABLE_LANGUAGES.each do | l |
|
||||||
|
@column_options["language_#{l}".to_sym] = [
|
||||||
|
[(view_context._"articles.conference_registration.questions.bike.yes"), true]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get_housing_data
|
def get_housing_data
|
||||||
@hosts = {}
|
@hosts = {}
|
||||||
@guests = {}
|
@guests = {}
|
||||||
@ -699,6 +781,60 @@ class ConferencesController < ApplicationController
|
|||||||
@admin_step = params[:admin_step]
|
@admin_step = params[:admin_step]
|
||||||
|
|
||||||
case params[:admin_step]
|
case params[:admin_step]
|
||||||
|
when 'stats'
|
||||||
|
registration = ConferenceRegistration.where(
|
||||||
|
id: params[:key].to_i,
|
||||||
|
conference_id: @this_conference.id
|
||||||
|
).limit(1).first
|
||||||
|
user_changed = false
|
||||||
|
params.each do | key, value |
|
||||||
|
case key.to_sym
|
||||||
|
when :city
|
||||||
|
registration.city = value.present? ? view_context.location(Geocoder.search(value, language: @this_conference.locale).first, @this_conference.locale) : nil
|
||||||
|
when :housing, :bike, :food, :allergies, :other
|
||||||
|
registration.send("#{key.to_s}=", value)
|
||||||
|
when :registration_fees_paid
|
||||||
|
registration.registration_fees_paid = value.to_i
|
||||||
|
when :can_provide_housing
|
||||||
|
registration.send("#{key.to_s}=", value.present?)
|
||||||
|
when :arrival, :departure
|
||||||
|
registration.send("#{key.to_s}=", value.present? ? Date.parse(value) : nil)
|
||||||
|
when :companion_email
|
||||||
|
registration.housing_data ||= {}
|
||||||
|
registration.housing_data['companions'] = [value]
|
||||||
|
when :preferred_language
|
||||||
|
registration.user.locale = value
|
||||||
|
user_changed = true
|
||||||
|
when :is_attending
|
||||||
|
registration.is_attending = value.present? ? 'y' : 'n'
|
||||||
|
when :address, :phone, :first_day, :last_day, :notes
|
||||||
|
registration.housing_data ||= {}
|
||||||
|
registration.housing_data[key.to_s] = value
|
||||||
|
else
|
||||||
|
if key.start_with?('language_')
|
||||||
|
l = key.split('_').last
|
||||||
|
if User.AVAILABLE_LANGUAGES.include? l.to_sym
|
||||||
|
registration.user.languages ||= []
|
||||||
|
if value.present?
|
||||||
|
registration.user.languages |= [l]
|
||||||
|
else
|
||||||
|
registration.user.languages -= [l]
|
||||||
|
end
|
||||||
|
user_changed = true
|
||||||
|
end
|
||||||
|
elsif ConferenceRegistration.all_spaces.include? key.to_sym
|
||||||
|
registration.housing_data ||= {}
|
||||||
|
registration.housing_data['space'] ||= {}
|
||||||
|
registration.housing_data['space'][key.to_s] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
registration.user.save! if user_changed
|
||||||
|
registration.save!
|
||||||
|
get_stats(true, params[:key].to_i)
|
||||||
|
options = view_context.registrations_table_options
|
||||||
|
options[:html] = true
|
||||||
|
return render html: view_context.excel_rows(@excel_data, {}, options)
|
||||||
when 'edit'
|
when 'edit'
|
||||||
case params[:button]
|
case params[:button]
|
||||||
when 'save'
|
when 'save'
|
||||||
|
@ -756,7 +756,7 @@ module ApplicationHelper
|
|||||||
belongs_to_periods << :before_plus_one if day <= (conference.start_date + 1.day)
|
belongs_to_periods << :before_plus_one if day <= (conference.start_date + 1.day)
|
||||||
belongs_to_periods << :after_minus_one if day >= (conference.end_date - 1.day)
|
belongs_to_periods << :after_minus_one if day >= (conference.end_date - 1.day)
|
||||||
belongs_to_periods << :during if day >= conference.start_date && day <= conference.end_date
|
belongs_to_periods << :during if day >= conference.start_date && day <= conference.end_date
|
||||||
days << [date(day.to_date, format || :span_same_year_date_1), day] if belongs_to_periods.include?(period)
|
days << [date(day.to_date, format || :span_same_year_date_1), day.to_date] if belongs_to_periods.include?(period)
|
||||||
end
|
end
|
||||||
return days
|
return days
|
||||||
end
|
end
|
||||||
@ -1558,6 +1558,7 @@ module ApplicationHelper
|
|||||||
format 'td.datetime', num_fmt: 22, font_name: 'Courier New', sz: 10, fg_color: '333333'
|
format 'td.datetime', num_fmt: 22, font_name: 'Courier New', sz: 10, fg_color: '333333'
|
||||||
format 'td.date.day', num_fmt: 14, font_name: 'Courier New', sz: 10, fg_color: '333333'
|
format 'td.date.day', num_fmt: 14, font_name: 'Courier New', sz: 10, fg_color: '333333'
|
||||||
format 'td.money', num_fmt: 2, font_name: 'Courier New', sz: 10, fg_color: '333333'
|
format 'td.money', num_fmt: 2, font_name: 'Courier New', sz: 10, fg_color: '333333'
|
||||||
|
format 'td.number', font_name: 'Courier New', sz: 10, fg_color: '333333'
|
||||||
format 'td.bold', font_name: 'Calibri', fg_color: '333333', b: true
|
format 'td.bold', font_name: 'Calibri', fg_color: '333333', b: true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1670,16 +1671,27 @@ module ApplicationHelper
|
|||||||
|
|
||||||
if (options[:column_names] || []).include? column
|
if (options[:column_names] || []).include? column
|
||||||
attributes[:class] << 'has-editor'
|
attributes[:class] << 'has-editor'
|
||||||
raw_value = value
|
raw_value = row[:raw_values][column] || value
|
||||||
|
|
||||||
if options[:html] && row[:html_values].present? && row[:html_values][column].present?
|
if options[:html] && row[:html_values].present? && row[:html_values][column].present?
|
||||||
value = row[:html_values][column]
|
value = row[:html_values][column]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
editor_attributes = { class: 'cell-editor', data: { value: raw_value.to_s } }
|
||||||
|
|
||||||
# create the control but add the original value to set the width and height
|
# create the control but add the original value to set the width and height
|
||||||
|
editor_value = content_tag(:span, CGI::escapeHTML(value), class: 'value')
|
||||||
if (options[:column_options] || {})[column].present?
|
if (options[:column_options] || {})[column].present?
|
||||||
value = (value + select_tag(column, options_for_select(options[:column_options][column], row[:raw_values][column] || raw_value), class: 'cell-editor')).html_safe
|
value = (editor_value.html_safe + select_tag(column, options_for_select([['', '']] + options[:column_options][column], raw_value), editor_attributes)).html_safe
|
||||||
|
elsif data[:column_types][column] == :text
|
||||||
|
editor_attributes[:name] = column
|
||||||
|
value = (editor_value.html_safe + content_tag(:textarea, raw_value, editor_attributes)).html_safe
|
||||||
else
|
else
|
||||||
value = (value + content_tag(:textarea, raw_value, name: column, class: 'cell-editor')).html_safe
|
editor_attributes[:name] = column
|
||||||
|
editor_attributes[:value] = raw_value
|
||||||
|
type = data[:column_types][column] || :unknown
|
||||||
|
editor_attributes[:type] = { money: :number, number: :number, email: :email }[type] || :text
|
||||||
|
value = (editor_value.html_safe + content_tag(:input, nil, editor_attributes)).html_safe
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1724,7 +1736,6 @@ module ApplicationHelper
|
|||||||
|
|
||||||
if options[:editable]
|
if options[:editable]
|
||||||
attributes[:class] << :editable
|
attributes[:class] << :editable
|
||||||
# attributes[:tabindex] = 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
rows += content_tag(:tr, excel_columns(row, data, padding, options), attributes) +
|
rows += content_tag(:tr, excel_columns(row, data, padding, options), attributes) +
|
||||||
@ -1734,6 +1745,38 @@ module ApplicationHelper
|
|||||||
rows.html_safe
|
rows.html_safe
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def registrations_table_options
|
||||||
|
{
|
||||||
|
id: 'search-table',
|
||||||
|
class: ['registrations', 'admin-edit'],
|
||||||
|
primary_key: :id,
|
||||||
|
column_names: [
|
||||||
|
:registration_fees_paid,
|
||||||
|
:is_attending,
|
||||||
|
:city,
|
||||||
|
:preferred_language,
|
||||||
|
:arrival,
|
||||||
|
:departure,
|
||||||
|
:housing,
|
||||||
|
:bike,
|
||||||
|
:food,
|
||||||
|
:companion_email,
|
||||||
|
:allergies,
|
||||||
|
:other,
|
||||||
|
:can_provide_housing,
|
||||||
|
:address,
|
||||||
|
:phone,
|
||||||
|
:first_day,
|
||||||
|
:last_day,
|
||||||
|
:notes
|
||||||
|
] +
|
||||||
|
User.AVAILABLE_LANGUAGES.map { |l| "language_#{l}".to_sym } +
|
||||||
|
ConferenceRegistration.all_spaces,
|
||||||
|
editable: administration_update_path(@this_conference.slug, :stats),
|
||||||
|
column_options: @column_options
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def _original_content(value, lang)
|
def _original_content(value, lang)
|
||||||
content_tag(:div, (
|
content_tag(:div, (
|
||||||
|
@ -13,6 +13,10 @@ class ConferenceRegistration < ActiveRecord::Base
|
|||||||
[:none, :tent, :house]
|
[:none, :tent, :house]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.all_spaces
|
||||||
|
[:bed_space, :floor_space, :tent_space]
|
||||||
|
end
|
||||||
|
|
||||||
def self.all_bike_options
|
def self.all_bike_options
|
||||||
[:yes, :no]
|
[:yes, :no]
|
||||||
end
|
end
|
||||||
@ -20,4 +24,8 @@ class ConferenceRegistration < ActiveRecord::Base
|
|||||||
def self.all_food_options
|
def self.all_food_options
|
||||||
[:meat, :vegetarian, :vegan]
|
[:meat, :vegetarian, :vegan]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.all_considerations
|
||||||
|
[:vegan, :smoking, :pets, :quiet]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -13,7 +13,7 @@ class User < ActiveRecord::Base
|
|||||||
accepts_nested_attributes_for :authentications
|
accepts_nested_attributes_for :authentications
|
||||||
|
|
||||||
before_save do |user|
|
before_save do |user|
|
||||||
user.locale = I18n.locale
|
user.locale ||= I18n.locale
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_translate?(to_locale = nil, from_locale = nil)
|
def can_translate?(to_locale = nil, from_locale = nil)
|
||||||
@ -48,9 +48,6 @@ class User < ActiveRecord::Base
|
|||||||
user = where(email: email).first
|
user = where(email: email).first
|
||||||
|
|
||||||
unless user
|
unless user
|
||||||
# not really a good UX so we should fix this later
|
|
||||||
#do_404
|
|
||||||
#return
|
|
||||||
user = new(email: email)
|
user = new(email: email)
|
||||||
user.save!
|
user.save!
|
||||||
end
|
end
|
||||||
|
@ -6,14 +6,14 @@
|
|||||||
= textfield :address, @hosting_data['address'], required: true, heading: 'articles.conference_registration.headings.host.address', help: 'articles.conference_registration.paragraphs.host.address'
|
= textfield :address, @hosting_data['address'], required: true, heading: 'articles.conference_registration.headings.host.address', help: 'articles.conference_registration.paragraphs.host.address'
|
||||||
= telephonefield :phone, @hosting_data['phone'], required: true
|
= telephonefield :phone, @hosting_data['phone'], required: true
|
||||||
= fieldset :space, heading: 'articles.conference_registration.headings.host.space', help: 'articles.conference_registration.paragraphs.host.space' do
|
= fieldset :space, heading: 'articles.conference_registration.headings.host.space', help: 'articles.conference_registration.paragraphs.host.space' do
|
||||||
- [:bed_space, :floor_space, :tent_space].each do | space |
|
- ConferenceRegistration.all_spaces.each do | space |
|
||||||
= numberfield space, @hosting_data['space'][space.to_s] || 0, min: 0, required: true
|
= numberfield space, @hosting_data['space'][space.to_s] || 0, min: 0, required: true
|
||||||
= fieldset :hosting_dates, heading: 'articles.conference_registration.headings.host.availability', help: 'articles.conference_registration.paragraphs.host.availability' do
|
= fieldset :hosting_dates, heading: 'articles.conference_registration.headings.host.availability', help: 'articles.conference_registration.paragraphs.host.availability' do
|
||||||
- first_day_options = conference_days_options_list(:before)
|
- first_day_options = conference_days_options_list(:before)
|
||||||
- last_day_options = conference_days_options_list(:after)
|
- last_day_options = conference_days_options_list(:after)
|
||||||
= selectfield :first_day, @hosting_data['availability'][0] || first_day_options.first.last, first_day_options
|
= selectfield :first_day, @hosting_data['availability'][0] || first_day_options.first.last, first_day_options
|
||||||
= selectfield :last_day, @hosting_data['availability'][1] || last_day_options.last.last, last_day_options
|
= selectfield :last_day, @hosting_data['availability'][1] || last_day_options.last.last, last_day_options
|
||||||
= checkboxes :considerations, [:vegan, :smoking, :pets, :quiet], @hosting_data['considerations'], 'articles.conference_registration.host.considerations', heading: 'articles.conference_registration.headings.host.considerations', help: 'articles.conference_registration.paragraphs.host.considerations', vertical: true
|
= checkboxes :considerations, ConferenceRegistration.all_considerations, @hosting_data['considerations'], 'articles.conference_registration.host.considerations', heading: 'articles.conference_registration.headings.host.considerations', help: 'articles.conference_registration.paragraphs.host.considerations', vertical: true
|
||||||
= textarea :notes, @hosting_data['notes'], help: 'articles.conference_registration.paragraphs.host.notes', edit_on: :focus
|
= textarea :notes, @hosting_data['notes'], help: 'articles.conference_registration.paragraphs.host.notes', edit_on: :focus
|
||||||
.actions.next-prev
|
.actions.next-prev
|
||||||
= button_tag (params[:step] == :save ? :save : :next), value: :hosting
|
= button_tag (params[:step] == :save ? :save : :next), value: :hosting
|
||||||
|
@ -22,4 +22,4 @@
|
|||||||
%h4 Registrations
|
%h4 Registrations
|
||||||
= searchfield :search, nil, big: true
|
= searchfield :search, nil, big: true
|
||||||
.table-scroller
|
.table-scroller
|
||||||
= html_table @excel_data, id: 'search-table', class: ['registrations', 'admin-edit'], primary_key: :id, column_names: [:registration_fees_paid, :city, :preferred_language, :arrival, :departure, :housing, :bike, :food, :companion_email, :allergies], editable: administration_update_path(@this_conference.slug, :stats), column_options: @column_options
|
= html_table @excel_data, registrations_table_options
|
||||||
|
@ -1117,6 +1117,7 @@ en:
|
|||||||
registered: Registered
|
registered: Registered
|
||||||
companion: Companion
|
companion: Companion
|
||||||
Preferred_Languages: Preferred Language
|
Preferred_Languages: Preferred Language
|
||||||
|
is_attending: Attending?
|
||||||
about_bikebike:
|
about_bikebike:
|
||||||
paragraphs:
|
paragraphs:
|
||||||
bicycle_project_paragraph: 'From collectives that use the bicycle as an excuse to change society, economy and the environment. Non-profit groups that have a community bike shops, cooperatives and other projects that promote the use of the bicycle and that come together to turn their communities into a place where riding is easier, more inclusive, safer and more fun. The list below uses the criteria found in the old Bicycle Organization Organization Project for what constitutes a community bike shop. The bike project need not meet all these criteria. Rather, it is a general list of qualities which are common among many bicycle projects.'
|
bicycle_project_paragraph: 'From collectives that use the bicycle as an excuse to change society, economy and the environment. Non-profit groups that have a community bike shops, cooperatives and other projects that promote the use of the bicycle and that come together to turn their communities into a place where riding is easier, more inclusive, safer and more fun. The list below uses the criteria found in the old Bicycle Organization Organization Project for what constitutes a community bike shop. The bike project need not meet all these criteria. Rather, it is a general list of qualities which are common among many bicycle projects.'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user