Added excel sheet to housing page
This commit is contained in:
		
							parent
							
								
									2c976d40a4
								
							
						
					
					
						commit
						9356aa2d31
					
				
							
								
								
									
										5
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Gemfile
									
									
									
									
									
								
							| @ -42,16 +42,13 @@ gem 'geocoder' | ||||
| gem 'paper_trail', '~> 3.0.5' | ||||
| gem 'sitemap_generator' | ||||
| gem 'activerecord-session_store' | ||||
| # gem 'paypal-express', '0.7.1' | ||||
| gem 'sass-json-vars' | ||||
| gem 'premailer-rails' | ||||
| gem 'redcarpet' | ||||
| gem 'sidekiq' | ||||
| gem 'letter_opener' | ||||
| gem 'launchy' | ||||
| # gem 'axlsx' | ||||
| # gem 'excelinator' | ||||
| gem 'to_spreadsheet'#, :git => 'git://github.com/glebm/to_spreadsheet.git' | ||||
| gem 'to_spreadsheet', :git => 'git://github.com/glebm/to_spreadsheet.git' | ||||
| 
 | ||||
| group :test do | ||||
| 	gem 'rspec' | ||||
|  | ||||
| @ -92,84 +92,4 @@ | ||||
| 			closeGuestSelector(); | ||||
| 		} | ||||
| 	}); | ||||
| 	function closeOnTop() { | ||||
| 		document.documentElement.removeAttribute('data-ontop'); | ||||
| 		document.getElementById('guest_id').value = ''; | ||||
| 		var target = document.querySelector('.on-top-target'); | ||||
| 		target.removeAttribute('style'); | ||||
| 		document.querySelector('body').removeAttribute('style'); | ||||
| 		forEachElement('.on-top-control', function(control) { | ||||
| 			control.classList.remove('on-top-control'); | ||||
| 		}); | ||||
| 	} | ||||
| 	forEachElement('#guests .guest', function(guest) { | ||||
| 		var button = guest.querySelector('.set-host'); | ||||
| 		button.addEventListener('click', function(event) { | ||||
| 			var target = document.querySelector('.on-top-target'); | ||||
| 			var body = document.querySelector('body'); | ||||
| 			// maintain our current height
 | ||||
| 			body.setAttribute('style', 'height: ' + body.clientHeight + 'px'); | ||||
| 			document.documentElement.setAttribute('data-ontop', 'set-host'); | ||||
| 			guest.classList.add('on-top-control'); | ||||
| 			target.setAttribute('style', 'bottom: ' + guest.clientHeight + 'px'); | ||||
| 			document.getElementById('guest_id').value = guest.dataset.id; | ||||
| 		}); | ||||
| 	}); | ||||
| 	forEachElement('#hosts .host', function(host) { | ||||
| 		initHost(host); | ||||
| 	}); | ||||
| 
 | ||||
| 	function initHost(host) { | ||||
| 		forEachElement('.place-guest', function(button) { | ||||
| 			button.addEventListener('click', function(event) { | ||||
| 				var guest_id = document.getElementById('guest_id').value; | ||||
| 				if (guest_id) { | ||||
| 					var guest = document.getElementById('guest-' + guest_id); | ||||
| 					var form = document.getElementById('hosts'); | ||||
| 					var data = new FormData(form); | ||||
| 
 | ||||
| 					host.classList.add('requesting'); | ||||
| 					if (guest.dataset.affectedHosts) { | ||||
| 						data.append('affected-hosts', guest.dataset.affectedHosts); | ||||
| 						forEach(guest.dataset.affectedHosts.split(','), function(host_id) { | ||||
| 							h = document.getElementById('host-' + host_id); | ||||
| 							if (h) { | ||||
| 								h.classList.add('requesting'); | ||||
| 							} | ||||
| 						}); | ||||
| 					} | ||||
| 					data.append('button', button.value); | ||||
| 
 | ||||
| 					var request = new XMLHttpRequest(); | ||||
| 					request.onreadystatechange = function() { | ||||
| 						if (request.readyState == 4) { | ||||
| 							if (request.status == 200) { | ||||
| 								var response = JSON.parse(request.responseText); | ||||
| 								for (var host_id in response.hosts) { | ||||
| 									host_element = document.getElementById('host-' + host_id); | ||||
| 									widget = response.hosts[host_id]; | ||||
| 									host_element.className = widget.class; | ||||
| 									host_element.querySelector('.guests').innerHTML = widget.html; | ||||
| 									initHost(host_element); | ||||
| 									host_element.classList.remove('requesting'); | ||||
| 								} | ||||
| 								for (var guest_id in response.affected_hosts) { | ||||
| 									guest_element = document.getElementById('guest-' + guest_id); | ||||
| 									if (guest_element) { | ||||
| 										guest_element.setAttribute('data-affected-hosts', response.affected_hosts[guest_id].join(',')); | ||||
| 									} | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 					request.open('POST', form.getAttribute('action'), true); | ||||
| 					request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); | ||||
| 					request.send(data); | ||||
| 				} | ||||
| 			}); | ||||
| 		}, host); | ||||
| 	} | ||||
| 	forEachElement('.on-top-close', function(button) { | ||||
| 		button.addEventListener('click', closeOnTop); | ||||
| 	}); | ||||
| })(); | ||||
|  | ||||
| @ -288,7 +288,7 @@ class ConferencesController < ApplicationController | ||||
| 				@organizations = Organization.all | ||||
| 
 | ||||
| 				if request.format.xlsx? | ||||
| 					logger.info "Generating stats.xls" | ||||
| 					logger.info "Generating organizations.xls" | ||||
| 					@excel_data = { | ||||
| 						columns: [:name, :street_address, :city, :subregion, :country, :postal_code, :email, :phone, :status], | ||||
| 						keys: { | ||||
| @ -439,6 +439,80 @@ class ConferencesController < ApplicationController | ||||
| 			when :housing | ||||
| 				# do a full analysis | ||||
| 				analyze_housing | ||||
| 				 | ||||
| 				if request.format.xlsx? | ||||
| 					logger.info "Generating housing.xls" | ||||
| 					@excel_data = { | ||||
| 						columns: [:name, :phone, :street_address, :email, :availability, :considerations, :empty, :empty, :empty, :guests], | ||||
| 						keys: { | ||||
| 								name: 'forms.labels.generic.name', | ||||
| 								street_address: 'forms.labels.generic.street_address', | ||||
| 								email: 'forms.labels.generic.email', | ||||
| 								phone: 'forms.labels.generic.phone', | ||||
| 								availability: 'articles.conference_registration.headings.host.availability', | ||||
| 								considerations: 'articles.conference_registration.headings.host.considerations' | ||||
| 							}, | ||||
| 						column_types: { | ||||
| 								name: :bold, | ||||
| 								guests: :table | ||||
| 							}, | ||||
| 						data: [], | ||||
| 					} | ||||
| 					@hosts.each do | id, host | | ||||
| 						data = (host.housing_data || {}) | ||||
| 						host_data = { | ||||
| 							name: host.user.name, | ||||
| 							street_address: data['address'], | ||||
| 							email: host.user.email, | ||||
| 							phone: data['phone'], | ||||
| 							availability: data['availability'].present? && data['availability'][1].present? ? view_context.date_span(data['availability'][0].to_date, data['availability'][1].to_date) : '', | ||||
| 							considerations: (data['considerations'].map { | consideration | view_context._"articles.conference_registration.host.considerations.#{consideration}" }).join(', '), | ||||
| 							empty: '', | ||||
| 							guests: { | ||||
| 								columns: [:name, :area, :email, :arrival_departure, :allergies, :food, :companion, :city], | ||||
| 								keys: { | ||||
| 									name: 'forms.labels.generic.name', | ||||
| 									area: 'articles.workshops.headings.space', | ||||
| 									email: 'forms.labels.generic.email', | ||||
| 									arrival_departure: 'articles.admin.housing.headings.arrival_departure', | ||||
| 									companion: 'forms.labels.generic.companion', | ||||
| 									city: 'forms.labels.generic.city', | ||||
| 									food: 'forms.labels.generic.food', | ||||
| 									allergies: 'forms.labels.generic.allergies' | ||||
| 								}, | ||||
| 								column_types: { | ||||
| 									name: :bold | ||||
| 								}, | ||||
| 								data: [] | ||||
| 							} | ||||
| 						} | ||||
| 
 | ||||
| 						@housing_data[id][:guests].each do | space, space_data | | ||||
| 							space_data.each do | guest_id, guest_data | | ||||
| 								guest = guest_data[:guest] | ||||
| 								if guest.present? | ||||
| 									companion = view_context.companion(guest) | ||||
| 
 | ||||
| 									host_data[:guests][:data] << { | ||||
| 										name: guest.user.name, | ||||
| 										area: (view_context._"forms.labels.generic.#{space}"), | ||||
| 										email: guest.user.email, | ||||
| 										arrival_departure: guest.arrival.present? && guest.departure.present? ? view_context.date_span(guest.arrival.to_date, guest.departure.to_date) : '', | ||||
| 										companion: companion.present? ? (companion.is_a?(User) ? companion.name : (view_context._"articles.conference_registration.terms.registration_status.#{companion}")) : '', | ||||
| 										city: guest.city, | ||||
| 										food: (view_context._"articles.conference_registration.questions.food.#{guest.food}"), | ||||
| 										allergies: guest.allergies | ||||
| 									} | ||||
| 								end | ||||
| 							end | ||||
| 						end | ||||
| 
 | ||||
| 						@excel_data[:data] << host_data | ||||
| 					end | ||||
| 					return respond_to do | format | | ||||
| 						format.xlsx { render xlsx: :stats, filename: "housing" } | ||||
| 					end | ||||
| 				end | ||||
| 			when :locations | ||||
| 				@locations = EventLocation.where(:conference_id => @this_conference.id) | ||||
| 			when :events | ||||
|  | ||||
| @ -1529,6 +1529,122 @@ module ApplicationHelper | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	def excel_table(excel_data) | ||||
| 		format_xls 'table' do | ||||
| 			workbook use_autowidth: true | ||||
| 			format bg_color: '333333' | ||||
| 			format 'td', font_name: 'Calibri', fg_color: '333333' | ||||
| 			format 'th', font_name: 'Calibri', b: true, bg_color: '333333', fg_color: 'ffffff' | ||||
| 			format 'th.sub-table', font_name: 'Calibri', b: true, bg_color: 'DDDDDD', 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.money', num_fmt: 2, font_name: 'Courier New', sz: 10, fg_color: '333333' | ||||
| 			format 'td.bold', font_name: 'Calibri', fg_color: '333333', b: true | ||||
| 		end | ||||
| 
 | ||||
| 		key = excel_data[:key] || 'excel.columns' | ||||
| 		 | ||||
| 		content_tag(:table) do | ||||
| 			(content_tag(:thead) do | ||||
| 				content_tag(:tr, excel_header_columns(excel_data)) | ||||
| 			end) + | ||||
| 			content_tag(:tbody, excel_rows(excel_data)) | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	def excel_header_columns(data, padding = {}, class_name = nil) | ||||
| 		columns = '' | ||||
| 
 | ||||
| 		data[:columns].each do |column| | ||||
| 			unless data[:column_types].present? && data[:column_types][column] == :table | ||||
| 				# columns += content_tag(:th, _(data[:keys][column].present? ? data[:keys][column] : "#{key}.#{column.to_s}"), class: class_name) | ||||
| 				columns += content_tag(:th, data[:keys][column].present? ? _(data[:keys][column]) : '', class: class_name) | ||||
| 			end | ||||
| 		end | ||||
| 
 | ||||
| 		pad_columns(columns, padding, :th) | ||||
| 	end | ||||
| 
 | ||||
| 	def excel_empty_row(data, padding = {}) | ||||
| 		columns = '' | ||||
| 
 | ||||
| 		data[:columns].each do |column| | ||||
| 			unless data[:column_types].present? && data[:column_types][column] == :table | ||||
| 				columns += content_tag(:td) | ||||
| 			end | ||||
| 		end | ||||
| 
 | ||||
| 		content_tag(:tr, pad_columns(columns, padding)) | ||||
| 	end | ||||
| 
 | ||||
| 	def pad_columns(columns, padding, column_type = :td) | ||||
| 		left = '' | ||||
| 
 | ||||
| 		for i in 1..(padding['left'] || 0) | ||||
| 			left += content_tag(:td) | ||||
| 		end | ||||
| 
 | ||||
| 		right = '' | ||||
| 		for i in 1..(padding['right'] || 0) | ||||
| 			right += content_tag(:td) | ||||
| 		end | ||||
| 
 | ||||
| 		(left + columns + right).html_safe | ||||
| 	end | ||||
| 
 | ||||
| 	def excel_columns(row, data, padding = {}) | ||||
| 		columns = '' | ||||
| 
 | ||||
| 		data[:columns].each do |column| | ||||
| 			value = row[column].present? ? (_!row[column].to_s) : '' | ||||
| 			class_name = nil | ||||
| 			is_sub_table = false | ||||
| 
 | ||||
| 			if data[:column_types].present? && data[:column_types][column].present? | ||||
| 				if data[:column_types][column] == :table | ||||
| 					is_sub_table = true | ||||
| 				else | ||||
| 					class_name = data[:column_types][column] | ||||
| 				end | ||||
| 			end | ||||
| 
 | ||||
| 			columns += content_tag(:td, value, { class: class_name }) unless is_sub_table | ||||
| 		end | ||||
| 
 | ||||
| 		pad_columns(columns, padding) | ||||
| 	end | ||||
| 
 | ||||
| 	def excel_sub_tables(row, data, padding = {}) | ||||
| 		rows = '' | ||||
| 
 | ||||
| 		# shift the table right | ||||
| 		new_padding = { | ||||
| 			'left' => (padding['right'] || 0) + 1, | ||||
| 			'right' => (padding['right'] || 0) - 1 | ||||
| 		} | ||||
| 
 | ||||
| 		data[:columns].each do |column| | ||||
| 			if data[:column_types].present? && data[:column_types][column] == :table | ||||
| 				puts row[column].to_json.to_s | ||||
| 				rows += content_tag(:tr, excel_header_columns(row[column], new_padding, 'sub-table')) | ||||
| 				rows += excel_rows(row[column], new_padding) | ||||
| 				rows += excel_empty_row(row[column], new_padding) | ||||
| 			end | ||||
| 
 | ||||
| 		end | ||||
| 
 | ||||
| 		rows.html_safe | ||||
| 	end | ||||
| 
 | ||||
| 	def excel_rows(data, padding = {}) | ||||
| 		rows = '' | ||||
| 		data[:data].each do |row| | ||||
| 			rows += content_tag(:tr, excel_columns(row, data, padding)) + | ||||
| 				excel_sub_tables(row, data, padding) | ||||
| 		end | ||||
| 		rows.html_safe | ||||
| 	end | ||||
| 
 | ||||
| 	private | ||||
| 		def _original_content(value, lang) | ||||
| 			content_tag(:div, ( | ||||
|  | ||||
| @ -5,3 +5,6 @@ | ||||
| 	= form_tag administration_update_path(@this_conference.slug, :housing), class: 'guest-dlg', id: 'guest-list-table' do | ||||
| 		%h3 Select a Guest | ||||
| 		#table | ||||
| .actions | ||||
| 	= link_to (_'links.download.Excel'), administration_step_path(@this_conference.slug, :housing, :format => :xlsx), class: [:button, :download] | ||||
| 
 | ||||
|  | ||||
| @ -4,15 +4,15 @@ | ||||
| 	= data_set(:h4, 'articles.admin.stats.headings.incomplete_registrations') do | ||||
| 		= ((@registration_count - @completed_registrations) || 0).to_s | ||||
| 	= data_set(:h4, 'articles.admin.stats.headings.bikes') do | ||||
| 		= (@completed_registrations || 0) > 0 ? "#{@bikes} (#{(@bikes / @completed_registrations.to_f).round(4) * 100.0}%)" : "0" | ||||
| 		= (@completed_registrations || 0) > 0 ? "#{@bikes} (#{number_to_percentage(@bikes / @completed_registrations.to_f * 100.0)})" : "0" | ||||
| 	= data_set(:h4, 'articles.admin.stats.headings.food.meat') do | ||||
| 		= (@food[:all] || 0) > 0 ? "#{@food[:meat]} (#{(@food[:meat] / @food[:all].to_f).round(4) * 100.0}%)" : "0" | ||||
| 		= (@food[:all] || 0) > 0 ? "#{@food[:meat]} (#{number_to_percentage(@food[:meat] / @food[:all].to_f * 100.0)})" : "0" | ||||
| 	= data_set(:h4, 'articles.admin.stats.headings.food.vegetarian') do | ||||
| 		= (@food[:all] || 0) > 0 ? "#{@food[:vegetarian]} (#{(@food[:vegetarian] / @food[:all].to_f).round(4) * 100.0}%)" : "0" | ||||
| 		= (@food[:all] || 0) > 0 ? "#{@food[:vegetarian]} (#{number_to_percentage(@food[:vegetarian] / @food[:all].to_f * 100.0)})" : "0" | ||||
| 	= data_set(:h4, 'articles.admin.stats.headings.food.vegan') do | ||||
| 		= (@food[:all] || 0) > 0 ? "#{@food[:vegan]} (#{(@food[:vegan] / @food[:all].to_f).round(4) * 100.0}%)" : "0" | ||||
| 		= (@food[:all] || 0) > 0 ? "#{@food[:vegan]} (#{number_to_percentage(@food[:vegan] / @food[:all].to_f * 100.0)})" : "0" | ||||
| 	= data_set(:h4, 'articles.admin.stats.headings.donation_count') do | ||||
| 		= (@completed_registrations || 0) > 0 ? "#{@donation_count} (#{(@donation_count / @completed_registrations.to_f).round(4) * 100.0}%)" : "0" | ||||
| 		= (@completed_registrations || 0) > 0 ? "#{@donation_count} (#{number_to_percentage(@donation_count / @completed_registrations.to_f * 100.0)})" : "0" | ||||
| 	= data_set(:h4, 'articles.admin.stats.headings.donation_total') do | ||||
| 		= "$#{@donations || 0.00}" | ||||
| .actions | ||||
|  | ||||
| @ -1,21 +1 @@ | ||||
| - key = @excel_data[:key] || 'excel.columns' | ||||
| %table | ||||
|   %thead | ||||
|     %tr | ||||
|       - @excel_data[:columns].each do |column| | ||||
|         %th=_(@excel_data[:keys][column].present? ? @excel_data[:keys][column] : "#{key}.#{column.to_s}") | ||||
|   %tbody | ||||
|     - @excel_data[:data].each do |row| | ||||
|       %tr | ||||
|         - @excel_data[:columns].each do |column| | ||||
|           %td{class: (@excel_data[:column_types].present? && @excel_data[:column_types][column].present?) ? @excel_data[:column_types][column] : nil}=(row[column].present? ? (_!row[column]) : '') | ||||
| 
 | ||||
| - format_xls 'table' do | ||||
|   - workbook use_autowidth: true | ||||
|   - format bg_color: '333333' | ||||
|   - format 'td', font_name: 'Calibri', fg_color: '333333' | ||||
|   - format 'th', font_name: 'Calibri', b: true, bg_color: '333333', fg_color: 'ffffff' | ||||
|   - 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.money', num_fmt: 2, font_name: 'Courier New', sz: 10, fg_color: '333333' | ||||
|   - format 'td.bold', font_name: 'Calibri', fg_color: '333333', b: true | ||||
| = excel_table(@excel_data) | ||||
|  | ||||
| @ -1264,7 +1264,7 @@ en: | ||||
|         subregion: State / Province | ||||
|         country: Country | ||||
|         postal_code: Postal Code | ||||
|         status: Status, | ||||
|         status: Status | ||||
|         bike: Bike | ||||
|         food: Food | ||||
|         housing: Housing | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user