Reworked housing page
This commit is contained in:
		
							parent
							
								
									2f375f7ff2
								
							
						
					
					
						commit
						2c976d40a4
					
				| @ -1,4 +1,97 @@ | |||||||
| (function() { | (function() { | ||||||
|  | 	function closeGuestSelector() { | ||||||
|  | 		document.getElementById('guest-selector').classList.remove('open'); | ||||||
|  | 	} | ||||||
|  | 	function _post(form, params, f) { | ||||||
|  | 		var request = new XMLHttpRequest(); | ||||||
|  | 		request.onreadystatechange = function() { | ||||||
|  | 			if (request.readyState == 4) { | ||||||
|  | 				if (request.status == 200) { | ||||||
|  | 					f(request.responseText); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		request.open('POST', form.getAttribute('action'), true); | ||||||
|  | 		request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); | ||||||
|  | 		params['authenticity_token'] = form.querySelector('[name="authenticity_token"]').value; | ||||||
|  | 		var data = []; | ||||||
|  | 		for (var key in params) { | ||||||
|  | 			//data.push(key + '=' + encodeURI(params[key]));
 | ||||||
|  | 			data.push(key + '=' + params[key]); | ||||||
|  | 		} | ||||||
|  | 		request.send(data.join('&')); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	function initHostTable(table) { | ||||||
|  | 		forEachElement('.select-guest', function(button) { | ||||||
|  | 			button.addEventListener('click', function(event) { | ||||||
|  | 				event.preventDefault(); | ||||||
|  | 				document.getElementById('guest-selector').classList.add('open'); | ||||||
|  | 				var table = document.getElementById('table'); | ||||||
|  | 				table.classList.add('loading'); | ||||||
|  | 				_post( | ||||||
|  | 						document.getElementById('housing-table-form'), | ||||||
|  | 						{ | ||||||
|  | 							host: button.getAttribute('data-host'), | ||||||
|  | 							space: button.getAttribute('data-space'), | ||||||
|  | 							button: 'get-guest-list' | ||||||
|  | 						}, | ||||||
|  | 						function (response) { | ||||||
|  | 							var table = document.getElementById('table'); | ||||||
|  | 							table.innerHTML = response; | ||||||
|  | 							table.classList.remove('loading'); | ||||||
|  | 							forEachElement('tr.selectable', function(row) { | ||||||
|  | 								row.addEventListener('click', function(event) { | ||||||
|  | 									var table = document.getElementById('housing-table'); | ||||||
|  | 									table.classList.add('loading'); | ||||||
|  | 									closeGuestSelector(); | ||||||
|  | 									_post( | ||||||
|  | 											document.getElementById('guest-list-table'), | ||||||
|  | 											{ | ||||||
|  | 												host: row.getAttribute('data-host'), | ||||||
|  | 												guest: row.getAttribute('data-guest'), | ||||||
|  | 												space: row.getAttribute('data-space'), | ||||||
|  | 												button: 'set-guest' | ||||||
|  | 											}, | ||||||
|  | 											function(response) { | ||||||
|  | 												table.innerHTML = response; | ||||||
|  | 												table.classList.remove('loading'); | ||||||
|  | 												initHostTable(table); | ||||||
|  | 											} | ||||||
|  | 										) | ||||||
|  | 								}); | ||||||
|  | 							}, table); | ||||||
|  | 						} | ||||||
|  | 					); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		forEachElement('.remove-guest', function(button) { | ||||||
|  | 			button.addEventListener('click', function(event) { | ||||||
|  | 				event.preventDefault(); | ||||||
|  | 				var table = document.getElementById('housing-table'); | ||||||
|  | 				table.classList.add('loading'); | ||||||
|  | 				_post( | ||||||
|  | 						document.getElementById('housing-table-form'), | ||||||
|  | 						{ | ||||||
|  | 							guest: button.getAttribute('data-guest'), | ||||||
|  | 							button: 'remove-guest' | ||||||
|  | 						}, | ||||||
|  | 						function (response) { | ||||||
|  | 							table.innerHTML = response; | ||||||
|  | 							table.classList.remove('loading'); | ||||||
|  | 							initHostTable(table); | ||||||
|  | 						} | ||||||
|  | 					); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 	initHostTable(document.getElementById('housing-table')); | ||||||
|  | 	document.getElementById('guest-selector').addEventListener('click', function(event) { | ||||||
|  | 		if (event.target.id == 'guest-selector') { | ||||||
|  | 			closeGuestSelector(); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
| 	function closeOnTop() { | 	function closeOnTop() { | ||||||
| 		document.documentElement.removeAttribute('data-ontop'); | 		document.documentElement.removeAttribute('data-ontop'); | ||||||
| 		document.getElementById('guest_id').value = ''; | 		document.getElementById('guest_id').value = ''; | ||||||
|  | |||||||
| @ -1490,6 +1490,43 @@ ul.warnings li, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #admin-housing { | #admin-housing { | ||||||
|  | 	.guests-housed { | ||||||
|  | 		margin-bottom: 1em; | ||||||
|  | 		text-align: right; | ||||||
|  | 
 | ||||||
|  | 		h5 { | ||||||
|  | 			display: inline-block; | ||||||
|  | 			margin: 0; | ||||||
|  | 			padding-right: 0.5em; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		.data { | ||||||
|  | 			display: inline-block; | ||||||
|  | 			font-size: 1.125em; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	#housing-table { | ||||||
|  | 		@include _(transition, opacity 1s ease-in-out); | ||||||
|  | 
 | ||||||
|  | 		&.loading { | ||||||
|  | 			@include _(opacity, 0.5); | ||||||
|  | 			pointer-events: none; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		tr.host { | ||||||
|  | 			th { | ||||||
|  | 				vertical-align: top; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			.address { | ||||||
|  | 				margin-top: 1em; | ||||||
|  | 				text-align: right; | ||||||
|  | 				@include font-family(primary); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	.host-table { | 	.host-table { | ||||||
| 		tr.place-guest { | 		tr.place-guest { | ||||||
| 			td { | 			td { | ||||||
| @ -1498,6 +1535,14 @@ ul.warnings li, | |||||||
| 				&:hover { | 				&:hover { | ||||||
| 					background-color: $colour-1; | 					background-color: $colour-1; | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
|  | 				&.full { | ||||||
|  | 					background-color: #E8E8E8; | ||||||
|  | 
 | ||||||
|  | 					&:hover { | ||||||
|  | 						background-color: #CCC; | ||||||
|  | 					}					 | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			a { | 			a { | ||||||
| @ -1512,6 +1557,7 @@ ul.warnings li, | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		.remove-guest, | ||||||
| 		button, .button { | 		button, .button { | ||||||
| 			float: right; | 			float: right; | ||||||
| 		} | 		} | ||||||
| @ -1535,13 +1581,15 @@ ul.warnings li, | |||||||
| 				top: 0; | 				top: 0; | ||||||
| 				background-color: $white; | 				background-color: $white; | ||||||
| 				border: 0.1em solid #CCC; | 				border: 0.1em solid #CCC; | ||||||
| 				padding: 0.25em 0.75em; | 				padding: 0.25em 0.75em 0.25em 1.5em; | ||||||
| 				margin: 0; | 				margin: 0; | ||||||
| 				list-style: none; | 				list-style-type: square; | ||||||
| 				@include default-box-shadow(top, 2); | 				@include default-box-shadow(top, 2); | ||||||
|  | 				z-index: 10; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			li { | 			li { | ||||||
|  | 				white-space: nowrap; | ||||||
| 				margin: 0; | 				margin: 0; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| @ -1554,12 +1602,19 @@ ul.warnings li, | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	#guest-selector { | 	#guest-selector { | ||||||
|  | 		display: none; | ||||||
| 		position: fixed; | 		position: fixed; | ||||||
| 		top: 0; | 		top: 0; | ||||||
| 		right: 0; | 		right: 0; | ||||||
| 		bottom: 0; | 		bottom: 0; | ||||||
| 		left: 0; | 		left: 0; | ||||||
| 		background-color: rgba($black, 0.5); | 		background-color: rgba($black, 0.5); | ||||||
|  | 		cursor: pointer; | ||||||
|  | 		z-index: 1000; | ||||||
|  | 
 | ||||||
|  | 		&.open { | ||||||
|  | 			display: block; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		.guest-dlg { | 		.guest-dlg { | ||||||
| 			position: absolute; | 			position: absolute; | ||||||
| @ -1569,12 +1624,144 @@ ul.warnings li, | |||||||
| 			left: 0; | 			left: 0; | ||||||
| 			background-color: $white; | 			background-color: $white; | ||||||
| 			width: 80%; | 			width: 80%; | ||||||
| 			max-width: 25em; | 			margin: auto; | ||||||
|  | 			padding: 1em; | ||||||
|  | 			height: 80%; | ||||||
|  | 			cursor: default; | ||||||
| 			@include default-box-shadow(top, 2); | 			@include default-box-shadow(top, 2); | ||||||
|  | 
 | ||||||
|  | 			h3 { | ||||||
|  | 				margin: 0 0 1em; | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @include keyframes(whiten) { | ||||||
|  | 	to { background-color: $white; } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #table { | ||||||
|  | 	position: relative; | ||||||
|  | 	overflow: auto; | ||||||
|  | 	height: 80%; | ||||||
|  | 	height: calc(100% - 4em); | ||||||
|  | 	background-color: $white; | ||||||
|  | 	@include _(transition, background-color 250ms ease-in-out); | ||||||
|  | 
 | ||||||
|  | 	&.loading { | ||||||
|  | 		background-color: #CCC; | ||||||
|  | 		@include _(animation, whiten ease-in-out 1s infinite alternate both); | ||||||
|  | 
 | ||||||
|  | 		.host-field, table, .legend { | ||||||
|  | 			display: none; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	table { | ||||||
|  | 		min-width: 100em; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	h4 { | ||||||
|  | 		margin: 0; | ||||||
|  | 
 | ||||||
|  | 		&.inline { | ||||||
|  | 			display: inline-block; | ||||||
|  | 			padding-right: 0.5em; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	.plain-value { | ||||||
|  | 		font-size: 1.2em; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	blockquote { | ||||||
|  | 		margin-top: 0; | ||||||
|  | 		font-size: 0.85em; | ||||||
|  | 
 | ||||||
|  | 		> :first-child { | ||||||
|  | 			margin-top: 0; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	tr.selectable { | ||||||
|  | 		cursor: pointer; | ||||||
|  | 
 | ||||||
|  | 		&:hover { | ||||||
|  | 			th { | ||||||
|  | 				background-color: $colour-2; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		&.other-host, &.other-space, &.bad-match { | ||||||
|  | 			td, th { | ||||||
|  | 				opacity: 0.5; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		&.selected-space, &.other-space { | ||||||
|  | 			td { | ||||||
|  | 				background-color: lighten($colour-5, 35); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			th { | ||||||
|  | 				background-color: $colour-5; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		&.other-host { | ||||||
|  | 			td { | ||||||
|  | 				background-color: lighten($colour-1, 40%); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			th { | ||||||
|  | 				background-color: $colour-1; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		&:hover { | ||||||
|  | 			td { | ||||||
|  | 				opacity: 1; | ||||||
|  | 				background-color: lighten($colour-2, 25%); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	.legend ul { | ||||||
|  | 		@include _-(display, flex); | ||||||
|  | 		list-style: none; | ||||||
|  | 		padding: 0; | ||||||
|  | 
 | ||||||
|  | 		li { | ||||||
|  | 			@include _(flex, 1); | ||||||
|  | 			text-align: center; | ||||||
|  | 			margin-bottom: 0.5em; | ||||||
|  | 			padding: 0.125em 0.5em; | ||||||
|  | 			margin: 0.1em; | ||||||
|  | 			border: 0.1em solid #EEE; | ||||||
|  | 			background-color: #F8F8F8; | ||||||
|  | 			@include font-family(secondary); | ||||||
|  | 
 | ||||||
|  | 			&.other-host, &.other-space, &.bad-match { | ||||||
|  | 				opacity: 0.5; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			&.selected-space, &.other-space { | ||||||
|  | 				background-color: $colour-5; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			&.other-host { | ||||||
|  | 				background-color: $colour-1; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	.p { | ||||||
|  | 		max-height: 4em; | ||||||
|  | 		overflow: auto; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #admin-housing { | #admin-housing { | ||||||
| 	#hosts { | 	#hosts { | ||||||
| 		background-color: $white; | 		background-color: $white; | ||||||
| @ -1862,9 +2049,9 @@ table.schedule { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .event-dlg { | .event-dlg { | ||||||
|     @include _-(flex, 0); | 	@include _-(flex, 0); | ||||||
|     position: relative; | 	position: relative; | ||||||
|     z-index: 1000; | 	z-index: 1000; | ||||||
| 	background-color: $white; | 	background-color: $white; | ||||||
| 	text-align: left; | 	text-align: left; | ||||||
| 	padding: 2em 2em 0.5em; | 	padding: 2em 2em 0.5em; | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ class ApplicationController < LinguaFrancaApplicationController | |||||||
| 
 | 
 | ||||||
| 	# Prevent CSRF attacks by raising an exception. | 	# Prevent CSRF attacks by raising an exception. | ||||||
| 	# For APIs, you may want to use :null_session instead. | 	# For APIs, you may want to use :null_session instead. | ||||||
| 	protect_from_forgery with: :exception, :except => [:do_confirm, :js_error] | 	protect_from_forgery with: :exception, :except => [:do_confirm, :js_error, :admin_update] | ||||||
| 
 | 
 | ||||||
| 	before_filter :capture_page_info | 	before_filter :capture_page_info | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -138,7 +138,7 @@ class ConferencesController < ApplicationController | |||||||
| 					} | 					} | ||||||
| 				when :questions | 				when :questions | ||||||
| 					# create the companion's user account and send a registration link unless they have already registered | 					# create the companion's user account and send a registration link unless they have already registered | ||||||
| 					generate_confirmation(User.create(email: params[:companion]), register_path(@this_conference.slug)) unless User.find_by_email(params[:companion]) | 					generate_confirmation(User.create(email: params[:companion]), register_path(@this_conference.slug)) if params[:companion].present? && User.find_by_email(params[:companion]).nil? | ||||||
| 					 | 					 | ||||||
| 					@registration.housing = params[:housing] | 					@registration.housing = params[:housing] | ||||||
| 					@registration.arrival = params[:arrival] | 					@registration.arrival = params[:arrival] | ||||||
| @ -225,7 +225,18 @@ class ConferencesController < ApplicationController | |||||||
| 		# prepare the form | 		# prepare the form | ||||||
| 		case @register_template | 		case @register_template | ||||||
| 		when :questions | 		when :questions | ||||||
| 			@registration.housing_data ||= { } | 			# see if someone else has asked to be your companion | ||||||
|  | 			if @registration.housing_data.blank? | ||||||
|  | 				ConferenceRegistration.where( | ||||||
|  | 					conference_id: @this_conference.id, can_provide_housing: [nil, false] | ||||||
|  | 					).where.not(housing_data: nil).each do | r | | ||||||
|  | 					@registration.housing_data = { | ||||||
|  | 							companions: [ r.user.email ] | ||||||
|  | 						} if r.housing_data['companions'].present? && r.housing_data['companions'].include?(current_user.email) | ||||||
|  | 				end | ||||||
|  | 				 | ||||||
|  | 				@registration.housing_data ||= { } | ||||||
|  | 			end | ||||||
| 			@page_title = 'articles.conference_registration.headings.Registration_Info' | 			@page_title = 'articles.conference_registration.headings.Registration_Info' | ||||||
| 		when :payment | 		when :payment | ||||||
| 			@page_title = 'articles.conference_registration.headings.Payment' | 			@page_title = 'articles.conference_registration.headings.Payment' | ||||||
| @ -337,7 +348,7 @@ class ConferencesController < ApplicationController | |||||||
| 							], | 							], | ||||||
| 						column_types: { | 						column_types: { | ||||||
| 								name: :bold, | 								name: :bold, | ||||||
| 								#date: :date, | 								date: :datetime, | ||||||
| 								arrival: [:date, :day], | 								arrival: [:date, :day], | ||||||
| 								departure: [:date, :day], | 								departure: [:date, :day], | ||||||
| 								registration_fees_paid: :money | 								registration_fees_paid: :money | ||||||
| @ -483,11 +494,15 @@ class ConferencesController < ApplicationController | |||||||
| 				@housing_data[id][:space][s.to_sym] = size | 				@housing_data[id][:space][s.to_sym] = size | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
|  | 		 | ||||||
|  | 		@guests_housed = 0 | ||||||
|  | 
 | ||||||
| 		@guests.each do | guest_id, guest | | 		@guests.each do | guest_id, guest | | ||||||
| 			data = guest.housing_data || {} | 			data = guest.housing_data || {} | ||||||
| 			@hosts_affected_by_guests[guest_id] ||= [] | 			@hosts_affected_by_guests[guest_id] ||= [] | ||||||
| 
 | 
 | ||||||
| 			if data['host'] | 			if data['host'] | ||||||
|  | 				@guests_housed += 1 | ||||||
| 				host_id = (data['host'].present? ? data['host'].to_i : nil) | 				host_id = (data['host'].present? ? data['host'].to_i : nil) | ||||||
| 				host = host_id.present? ? @hosts[host_id] : nil | 				host = host_id.present? ? @hosts[host_id] : nil | ||||||
| 
 | 
 | ||||||
| @ -506,21 +521,14 @@ class ConferencesController < ApplicationController | |||||||
| 
 | 
 | ||||||
| 					@housing_data[host_id][:guests][space][guest_id] = { guest: guest } | 					@housing_data[host_id][:guests][space][guest_id] = { guest: guest } | ||||||
| 
 | 
 | ||||||
| 					# make sure the host isn't overbooked |  | ||||||
| 					space_available = ((host_data['space'] || {})[space.to_s] || 0).to_i |  | ||||||
| 					if @housing_data[host_id][:guests][space].size > space_available |  | ||||||
| 						@housing_data[host_id][:warnings] ||= {} |  | ||||||
| 						@housing_data[host_id][:warnings][:space] ||= {} |  | ||||||
| 						@housing_data[host_id][:warnings][:space][space] ||= [] |  | ||||||
| 						@housing_data[host_id][:warnings][:space][space] << :overbooked |  | ||||||
| 					end |  | ||||||
| 
 |  | ||||||
| 					@housing_data[host_id][:guest_data] ||= {} | 					@housing_data[host_id][:guest_data] ||= {} | ||||||
| 					@housing_data[host_id][:guest_data][guest_id] = { warnings: {}, errors: {} } | 					@housing_data[host_id][:guest_data][guest_id] = { warnings: {}, errors: {} } | ||||||
| 
 | 
 | ||||||
|  | 					@housing_data[host_id][:guest_data][guest_id][:warnings][:dates] = {} unless view_context.available_dates_match?(host, guest) | ||||||
|  | 
 | ||||||
| 					if (guest.housing == 'house' && space == :tent) || | 					if (guest.housing == 'house' && space == :tent) || | ||||||
| 						(guest.housing == 'tent' && (space == :bed_space || space == :floor_space)) | 						(guest.housing == 'tent' && (space == :bed_space || space == :floor_space)) | ||||||
| 						@housing_data[host_id][:guest_data][guest_id][:warnings][:space] = { actual: space.to_s, expected: guest.housing} | 						@housing_data[host_id][:guest_data][guest_id][:warnings][:space] = { actual: (view_context._"forms.labels.generic.#{space.to_s}"), expected: (view_context._"articles.conference_registration.questions.housing.#{guest.housing}")} | ||||||
| 					end | 					end | ||||||
| 
 | 
 | ||||||
| 					companions = data['companions'] || [] | 					companions = data['companions'] || [] | ||||||
| @ -534,14 +542,10 @@ class ConferencesController < ApplicationController | |||||||
| 							if reg.present? && @guests[reg.id].present? | 							if reg.present? && @guests[reg.id].present? | ||||||
| 								housing_data = reg.housing_data || {} | 								housing_data = reg.housing_data || {} | ||||||
| 								companion_host = housing_data['host'].present? ? housing_data['host'].to_i : nil | 								companion_host = housing_data['host'].present? ? housing_data['host'].to_i : nil | ||||||
| 								if companion_host.blank? | 								@hosts_affected_by_guests[guest_id] << companion_host | ||||||
| 									@hosts_affected_by_guests[guest_id] << companion_host | 								if companion_host != host_id && reg.housing.present? && reg.housing != 'none' | ||||||
| 									if companion_host != host_id && reg.housing.present? && reg.housing != 'none' | 									# set this as an error if the guest has selected only one other to stay with, but if they have requested to stay with more, make this only a warning | ||||||
| 										# set this as an error if the guest has selected only one other to stay with, but if they have requested to stay with more, make this only a warning | 									@housing_data[host_id][:guest_data][guest_id][:warnings][:companions] = { name: "<strong>#{reg.user.name}</strong>".html_safe, id: reg.id } | ||||||
| 										status = companions.size > 1 ? :warnings : :errors |  | ||||||
| 										@housing_data[host_id][:guest_data][guest_id][status][:companions] ||= [] |  | ||||||
| 										@housing_data[host_id][:guest_data][guest_id][status][:companions] << { name: reg.user.name, id: reg.id } |  | ||||||
| 									end |  | ||||||
| 								end | 								end | ||||||
| 							end | 							end | ||||||
| 						end | 						end | ||||||
| @ -554,6 +558,24 @@ class ConferencesController < ApplicationController | |||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
|  | 		 | ||||||
|  | 		@hosts.each do | id, host | | ||||||
|  | 			host_data = host.housing_data | ||||||
|  | 
 | ||||||
|  | 			@hosts[id].housing_data['space'].each do | space, size | | ||||||
|  | 				# make sure the host isn't overbooked | ||||||
|  | 				space = space.to_sym | ||||||
|  | 				space_available = (size || 0).to_i | ||||||
|  | 				@housing_data[id][:warnings] ||= {} | ||||||
|  | 				@housing_data[id][:warnings][:space] ||= {} | ||||||
|  | 				@housing_data[id][:warnings][:space][space] ||= [] | ||||||
|  | 
 | ||||||
|  | 				if @housing_data[id][:guests][space].size > space_available | ||||||
|  | 					@housing_data[id][:warnings][:space][space] << :overbooked | ||||||
|  | 				end | ||||||
|  | 			end | ||||||
|  | 		end | ||||||
|  | 
 | ||||||
| 		return @hosts_affected_by_guests | 		return @hosts_affected_by_guests | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
| @ -607,41 +629,41 @@ class ConferencesController < ApplicationController | |||||||
| 				return redirect_to administration_step_path(@this_conference.slug, :payment) | 				return redirect_to administration_step_path(@this_conference.slug, :payment) | ||||||
| 			end | 			end | ||||||
| 		when 'housing' | 		when 'housing' | ||||||
| 			space = params[:button].split(':')[0] |  | ||||||
| 			host_id = params[:button].split(':')[1].to_i |  | ||||||
| 			guest_id = params[:guest_id].to_i |  | ||||||
| 			 |  | ||||||
| 			get_housing_data |  | ||||||
| 
 |  | ||||||
| 			# modify the guest data | 			# modify the guest data | ||||||
| 			@guests[guest_id].housing_data ||= {} |  | ||||||
| 			@guests[guest_id].housing_data['space'] = space |  | ||||||
| 			@guests[guest_id].housing_data['host'] = host_id |  | ||||||
| 			@guests[guest_id].save! |  | ||||||
| 
 | 
 | ||||||
| 			if request.xhr? | 			if params[:button] == 'get-guest-list' | ||||||
|  | 				# get_housing_data | ||||||
|  | 				analyze_housing | ||||||
|  | 				return render partial: 'conferences/admin/select_guest_table', locals: { host: @hosts[params['host'].to_i], space: params['space'] } | ||||||
|  | 			elsif params[:button] == 'set-guest' | ||||||
|  | 				guest = ConferenceRegistration.where( | ||||||
|  | 						id: params[:guest].to_i, | ||||||
|  | 						conference_id: @this_conference.id | ||||||
|  | 					).limit(1).first | ||||||
|  | 
 | ||||||
|  | 				guest.housing_data ||= {} | ||||||
|  | 				guest.housing_data['space'] = params[:space] | ||||||
|  | 				guest.housing_data['host'] = params[:host].to_i | ||||||
|  | 				guest.save! | ||||||
|  | 				 | ||||||
| 				analyze_housing | 				analyze_housing | ||||||
| 
 | 
 | ||||||
| 				# get the hosts that need updating | 				return render partial: 'conferences/admin/hosts_table' | ||||||
| 				affected_hosts = {} | 			elsif params[:button] == 'remove-guest' | ||||||
| 				affected_hosts[host_id] = @hosts[host_id] | 				guest = ConferenceRegistration.where( | ||||||
| 				if params['affected-hosts'].present? | 						id: params[:guest].to_i, | ||||||
| 					params['affected-hosts'].split(',').each do | id | | 						conference_id: @this_conference.id | ||||||
| 						affected_hosts[id.to_i] = @hosts[id.to_i] | 					).limit(1).first | ||||||
| 					end |  | ||||||
| 				end |  | ||||||
| 				@hosts_affected_by_guests[guest_id].each do | id | |  | ||||||
| 					affected_hosts[id] ||= @hosts[id] |  | ||||||
| 				end |  | ||||||
| 
 | 
 | ||||||
| 				json = { hosts: {}, affected_hosts: @hosts_affected_by_guests } | 				guest.housing_data ||= {} | ||||||
| 				puts @hosts_affected_by_guests[guest_id].to_json.to_s | 				guest.housing_data.delete('space') | ||||||
| 				affected_hosts.each do | id, host | | 				guest.housing_data.delete('host') | ||||||
| 					json[:hosts][id] = view_context.host_guests_widget(host) | 				guest.save! | ||||||
| 				end | 				 | ||||||
| 				return render json: json | 				analyze_housing | ||||||
|  | 
 | ||||||
|  | 				return render partial: 'conferences/admin/hosts_table' | ||||||
| 			end | 			end | ||||||
| 			return redirect_to administration_step_path(@this_conference.slug, :housing) |  | ||||||
| 		when 'broadcast' | 		when 'broadcast' | ||||||
| 			@hide_description = true | 			@hide_description = true | ||||||
| 			@subject = params[:subject] | 			@subject = params[:subject] | ||||||
|  | |||||||
| @ -1003,20 +1003,20 @@ module ApplicationHelper | |||||||
| 				@housing_data[id][:guest_data][guest_id][:errors].each do | error, value | | 				@housing_data[id][:guest_data][guest_id][:errors].each do | error, value | | ||||||
| 					if value.is_a?(Array) | 					if value.is_a?(Array) | ||||||
| 						value.each do | v | | 						value.each do | v | | ||||||
| 							status_html += _("errors.housing.space.#{error.to_s}", vars: {value: v}) | 							status_html += content_tag(:li, _("errors.messages.housing.space.#{error.to_s}", vars: v)) | ||||||
| 						end | 						end | ||||||
| 					else | 					else | ||||||
| 						status_html += _("errors.housing.space.#{error.to_s}", vars: {value: value }) | 						status_html += content_tag(:li, _("errors.messages.housing.space.#{error.to_s}", vars: value)) | ||||||
| 					end | 					end | ||||||
| 				end | 				end | ||||||
| 
 | 
 | ||||||
| 				@housing_data[id][:guest_data][guest_id][:warnings].each do | error, value | | 				@housing_data[id][:guest_data][guest_id][:warnings].each do | error, value | | ||||||
| 					if value.is_a?(Array) | 					if value.is_a?(Array) | ||||||
| 						value.each do | v | | 						value.each do | v | | ||||||
| 							status_html += _("warnings.housing.space.#{error.to_s}", v) | 							status_html += content_tag(:li, _("warnings.messages.housing.space.#{error.to_s}", v)) | ||||||
| 						end | 						end | ||||||
| 					else | 					else | ||||||
| 						status_html += _("warnings.housing.space.#{error.to_s}", vars: value) | 						status_html += content_tag(:li, _("warnings.messages.housing.space.#{error.to_s}", vars: value)) | ||||||
| 					end | 					end | ||||||
| 				end | 				end | ||||||
| 
 | 
 | ||||||
| @ -1028,23 +1028,26 @@ module ApplicationHelper | |||||||
| 					(content_tag :td, guest[:guest].user.name) + | 					(content_tag :td, guest[:guest].user.name) + | ||||||
| 					(content_tag :td do | 					(content_tag :td do | ||||||
| 						(guest[:guest].city +  | 						(guest[:guest].city +  | ||||||
| 						(button_tag :remove, class: [:small, :delete])).html_safe | 						(content_tag :a, (_'actions.workshops.Remove'), href: '#', class: 'remove-guest', data: { guest: guest_id })).html_safe | ||||||
| 					end) + | 					end) + | ||||||
| 					(content_tag :td, status_html.html_safe, class: [:state, status_html.present? ? :unhappy : :happy]) | 					(content_tag :td, status_html.html_safe, class: [:state, status_html.present? ? :unhappy : :happy]) | ||||||
| 				end | 				end | ||||||
|  | 			end | ||||||
| 
 | 
 | ||||||
| 				for i in guests.size..(@housing_data[id][:space][area] || 0) | 			space_size = (@housing_data[id][:space][area] || 0) | ||||||
| 					guest_rows += content_tag :tr, class: 'empty-space' do | 
 | ||||||
| 						(content_tag :td, '', colspan: 2) + | 			# add empty rows to represent empty guest spots | ||||||
| 						(content_tag :td) | 			for i in guests.size...space_size | ||||||
| 					end | 				guest_rows += content_tag :tr, class: 'empty-space' do | ||||||
|  | 					(content_tag :td, ' '.html_safe, colspan: 2) + | ||||||
|  | 					(content_tag :td) | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
| 
 | 
 | ||||||
| 			status_html = '' | 			status_html = '' | ||||||
| 			if @housing_data[id][:warnings].present? && @housing_data[id][:warnings][:space].present? && @housing_data[id][:warnings][:space][area].present? | 			if @housing_data[id][:warnings].present? && @housing_data[id][:warnings][:space].present? && @housing_data[id][:warnings][:space][area].present? | ||||||
| 				@housing_data[id][:warnings][:space][area].each do | w | | 				@housing_data[id][:warnings][:space][area].each do | w | | ||||||
| 					status_html += content_tag(:li, _("warnings.housing.space.#{w.to_s}")) | 					status_html += content_tag(:li, _("warnings.messages.housing.space.#{w.to_s}")) | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
| 			if status_html.present? | 			if status_html.present? | ||||||
| @ -1057,7 +1060,7 @@ module ApplicationHelper | |||||||
| 			end | 			end | ||||||
| 			html += guest_rows | 			html += guest_rows | ||||||
| 			html += content_tag :tr, class: 'place-guest' do | 			html += content_tag :tr, class: 'place-guest' do | ||||||
| 				content_tag :td, colspan: 3 do | 				content_tag :td, class: guests.size >= space_size ? 'full' : nil, colspan: 3 do | ||||||
| 					content_tag :a, (_'forms.actions.generic.place_guest'), class: 'select-guest', href: '#', data: { host: id, space: area } | 					content_tag :a, (_'forms.actions.generic.place_guest'), class: 'select-guest', href: '#', data: { host: id, space: area } | ||||||
| 				end | 				end | ||||||
| 			end | 			end | ||||||
| @ -1066,6 +1069,43 @@ module ApplicationHelper | |||||||
| 		content_tag :table, html.html_safe, class: 'host-table' | 		content_tag :table, html.html_safe, class: 'host-table' | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
|  | 	def get_housing_match(host, guest, space) | ||||||
|  | 		housing_data = guest.housing_data || [] | ||||||
|  | 		 | ||||||
|  | 		if housing_data['host'].present? | ||||||
|  | 			if housing_data['host'] == host.id | ||||||
|  | 				return space == housing_data['space'] ? :selected_space : :other_space | ||||||
|  | 			end | ||||||
|  | 
 | ||||||
|  | 			return :other_host | ||||||
|  | 		end | ||||||
|  | 
 | ||||||
|  | 		if space_matches?(space, guest.housing) && available_dates_match?(host, guest) | ||||||
|  | 			return :good_match | ||||||
|  | 		end | ||||||
|  | 
 | ||||||
|  | 		return :bad_match | ||||||
|  | 	end | ||||||
|  | 
 | ||||||
|  | 	def space_matches?(host_space, guest_space) | ||||||
|  | 		return false unless host_space.present? && guest_space.present? | ||||||
|  | 
 | ||||||
|  | 		if host_space.to_s == 'bed_space' || host_space.to_s == 'floor_space' | ||||||
|  | 			return guest_space.to_s == 'house' | ||||||
|  | 		end | ||||||
|  | 
 | ||||||
|  | 		return host_space.to_s == 'tent_space' && guest_space.to_s == 'tent' | ||||||
|  | 	end | ||||||
|  | 
 | ||||||
|  | 	def available_dates_match?(host, guest) | ||||||
|  | 		if host.housing_data['availability'][0] <= guest.arrival && | ||||||
|  | 		 	host.housing_data['availability'][1] >= guest.departure | ||||||
|  | 		 	return true | ||||||
|  | 		 end | ||||||
|  | 
 | ||||||
|  | 		 return false | ||||||
|  | 	end | ||||||
|  | 	 | ||||||
| 	def host_guests_widget(registration) | 	def host_guests_widget(registration) | ||||||
| 		html = '' | 		html = '' | ||||||
| 		classes = ['host'] | 		classes = ['host'] | ||||||
| @ -1460,6 +1500,22 @@ module ApplicationHelper | |||||||
| 		return html.html_safe | 		return html.html_safe | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
|  | 	def companion(registration) | ||||||
|  | 		if registration.housing_data.present? && registration.housing_data['companions'].present? && registration.housing_data['companions'].first.present? | ||||||
|  | 			companion_user = User.find_by_email(registration.housing_data['companions'].first) | ||||||
|  | 
 | ||||||
|  | 			if companion_user.present? | ||||||
|  | 				cr = ConferenceRegistration.where(user_id: companion_user.id).order(created_at: :desc).limit(1).first | ||||||
|  | 
 | ||||||
|  | 				if cr.present? && ((cr.steps_completed || []).include? 'questions') | ||||||
|  | 					return companion_user | ||||||
|  | 				end | ||||||
|  | 			end | ||||||
|  | 			return :unregistered | ||||||
|  | 		end | ||||||
|  | 		return nil | ||||||
|  | 	end | ||||||
|  | 
 | ||||||
| 	def comment(comment) | 	def comment(comment) | ||||||
| 		add_inline_script :time | 		add_inline_script :time | ||||||
| 		add_js_translation('datetime.distance_in_words') | 		add_js_translation('datetime.distance_in_words') | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								app/views/conferences/admin/_hosts_table.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/views/conferences/admin/_hosts_table.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | .guests-housed | ||||||
|  | 	%h5 Guests Housed: | ||||||
|  | 	.data="#{@guests_housed} / #{@guests.size}" | ||||||
|  | 
 | ||||||
|  | %table.hosts.admin-edit | ||||||
|  | 	- @hosts.each do | id, registration | | ||||||
|  | 		%tr.host | ||||||
|  | 			%th | ||||||
|  | 				.name=registration.user.name | ||||||
|  | 				.address=registration.housing_data['address'] | ||||||
|  | 				%td.inner-table{colspan: 2}=host_guests_table(registration) | ||||||
| @ -1,47 +1,7 @@ | |||||||
| - add_inline_script :housing | - add_inline_script :housing | ||||||
| = form_tag administration_update_path(@this_conference.slug, :housing), id: :hosts, class: 'on-top-target' do | = form_tag administration_update_path(@this_conference.slug, :housing), id: 'housing-table-form' do | ||||||
| 	= hidden_field_tag :guest_id | 	#housing-table= render partial: 'conferences/admin/hosts_table' | ||||||
| 	.on-top-controls | #guest-selector | ||||||
| 		= button_tag :close, type: :button, class: ['on-top-close'] | 	= form_tag administration_update_path(@this_conference.slug, :housing), class: 'guest-dlg', id: 'guest-list-table' do | ||||||
| 	%ul | 		%h3 Select a Guest | ||||||
| 		- @hosts.each do | id, registration | | 		#table | ||||||
| 			- if registration.user.present? |  | ||||||
| 				- widget_data = host_guests_widget(registration) |  | ||||||
| 				%li{id: "host-#{id}", class: widget_data[:class]} |  | ||||||
| 					%h4=registration.user.name |  | ||||||
| 					.email=registration.user.email |  | ||||||
| 					.address=registration.housing_data['address'] |  | ||||||
| 					.guests=widget_data[:html] |  | ||||||
| #guests |  | ||||||
| 	%h4=_'articles.admin.housing.headings.guests', :t |  | ||||||
| 	%ul.guests |  | ||||||
| 		- @guests.each do | id, registration | |  | ||||||
| 			- if registration.user.present? |  | ||||||
| 				%li.guest{id: "guest-#{id}", data: { id: id, 'affected-hosts': @hosts_affected_by_guests[id].join(',') }} |  | ||||||
| 					%h4= registration.user.name |  | ||||||
| 					.city=registration.city |  | ||||||
| 					.on-top-only.details |  | ||||||
| 						= data_set(:h4, 'articles.admin.housing.headings.email') do |  | ||||||
| 							= registration.user.email |  | ||||||
| 						= data_set(:h4, 'articles.admin.housing.headings.housing') do |  | ||||||
| 							= registration.housing |  | ||||||
| 						- if registration.arrival.present? |  | ||||||
| 							= data_set(:h4, 'articles.admin.housing.headings.arrival_departure') do |  | ||||||
| 								= date_span(registration.arrival.to_date, registration.departure.to_date) |  | ||||||
| 						- if (registration.housing_data || {})['companions'].present? |  | ||||||
| 							= data_set(:h4, 'articles.admin.housing.headings.companion') do |  | ||||||
| 								- companion = User.find_by_email(registration.housing_data['companions'].first) |  | ||||||
| 								- if companion |  | ||||||
| 									= "#{companion.firstname} (#{companion.email})" |  | ||||||
| 								- else |  | ||||||
| 									= registration.housing_data['companions'].first |  | ||||||
| 									= _'articles.admin.housing.headings.unregistered' |  | ||||||
| 						- if registration.allergies.present? |  | ||||||
| 							= data_set(:h4, 'articles.admin.housing.headings.allergies') do |  | ||||||
| 								= registration.allergies |  | ||||||
| 						- if registration.other.present? |  | ||||||
| 							= data_set(:h4, 'articles.admin.housing.headings.other') do |  | ||||||
| 								= registration.other |  | ||||||
| 					= button_tag :set_host, type: :button, class: [:small, 'set-host', 'not-on-top'] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  | |||||||
							
								
								
									
										46
									
								
								app/views/conferences/admin/_select_guest_table.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								app/views/conferences/admin/_select_guest_table.html.haml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | = hidden_field_tag :host, host.id | ||||||
|  | .host-field | ||||||
|  | 	%h4.inline=_'forms.labels.generic.name' | ||||||
|  | 	%span.plain-value= host.user.name | ||||||
|  | .host-field | ||||||
|  | 	%h4.inline=_'articles.conference_registration.headings.host.availability' | ||||||
|  | 	%span.plain-value= date_span(host.housing_data['availability'][0].to_date, host.housing_data['availability'][1].to_date) | ||||||
|  | - if host.housing_data['considerations'].present? | ||||||
|  | 	.host-field | ||||||
|  | 		%h4.inline=_'articles.conference_registration.headings.host.considerations' | ||||||
|  | 		%span.plain-value= (host.housing_data['considerations'].map { | consideration | _"articles.conference_registration.host.considerations.#{consideration}" }).join(', ') | ||||||
|  | - if sanitize(host.housing_data['notes'], tags: []).present? | ||||||
|  | 	.host-field | ||||||
|  | 		%h4=_'articles.conference_registration.headings.host.notes' | ||||||
|  | 		%blockquote= host.housing_data['notes'].html_safe | ||||||
|  | %table.guests.admin-edit | ||||||
|  | 	%tr | ||||||
|  | 		%th.corner | ||||||
|  | 		%th=_'forms.labels.generic.city' | ||||||
|  | 		%th=_'forms.labels.generic.housing' | ||||||
|  | 		%th=_'articles.admin.housing.headings.arrival_departure' | ||||||
|  | 		%th=_'forms.labels.generic.companion' | ||||||
|  | 		%th=_'forms.labels.generic.food' | ||||||
|  | 		%th=_'forms.labels.generic.allergies' | ||||||
|  | 		%th=_'forms.labels.generic.other' | ||||||
|  | 	- @guests.each do | id, registration | | ||||||
|  | 		%tr.selectable{class: get_housing_match(host, registration, space).to_s.gsub('_', '-'), data: {host: host.id, guest: id, space: space}} | ||||||
|  | 			%th=registration.user.name | ||||||
|  | 			%td=registration.city | ||||||
|  | 			%td=_"articles.conference_registration.questions.housing.#{registration.housing}" | ||||||
|  | 			%td=date_span(registration.arrival.to_date, registration.departure.to_date) | ||||||
|  | 			- companion = companion(registration) | ||||||
|  | 			%td=companion.present? ? (companion.is_a?(User) ? companion.name : (_"articles.conference_registration.terms.registration_status.#{companion}")) : '' | ||||||
|  | 			%td=_"articles.conference_registration.questions.food.#{registration.food}" | ||||||
|  | 			%td=registration.allergies | ||||||
|  | 			%td | ||||||
|  | 				.p=registration.other | ||||||
|  | 
 | ||||||
|  | .legend | ||||||
|  | 	%h4 Legend | ||||||
|  | 	%ul | ||||||
|  | 		%li.good-match Good Match | ||||||
|  | 		%li.bad-match Poor Match | ||||||
|  | 		%li.selected-space Also in this space | ||||||
|  | 		%li.other-space Also with this host | ||||||
|  | 		%li.other-host Already hosted | ||||||
| @ -15,7 +15,7 @@ | |||||||
|   - format bg_color: '333333' |   - format bg_color: '333333' | ||||||
|   - format 'td', font_name: 'Calibri', fg_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', font_name: 'Calibri', b: true, bg_color: '333333', fg_color: 'ffffff' | ||||||
|   - format 'td.date', 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.bold', font_name: 'Calibri', fg_color: '333333', b: true |   - format 'td.bold', font_name: 'Calibri', fg_color: '333333', b: true | ||||||
|  | |||||||
| @ -167,6 +167,9 @@ en: | |||||||
|           empty: 'Please enter an address' |           empty: 'Please enter an address' | ||||||
|         space: |         space: | ||||||
|           empty: 'Please select a space' |           empty: 'Please select a space' | ||||||
|  |       housing: | ||||||
|  |         space: | ||||||
|  |           companions: This host wishes to be housed with %{name} | ||||||
|     template: |     template: | ||||||
|       body: 'There were problems with the following fields:' |       body: 'There were problems with the following fields:' | ||||||
|       header: |       header: | ||||||
| @ -177,7 +180,10 @@ en: | |||||||
|       location_corrected: Your location was corrected from "%{original}" to "%{corrected}". If this doesn't reflect your intended location, you can change this again in the contact info step. |       location_corrected: Your location was corrected from "%{original}" to "%{corrected}". If this doesn't reflect your intended location, you can change this again in the contact info step. | ||||||
|       housing: |       housing: | ||||||
|           space: |           space: | ||||||
|             overbooked: Overbooked |             overbooked: This space is overbooked | ||||||
|  |             companions: This guest wishes to be housed with %{name} | ||||||
|  |             space: This guest wishes to be housed in a %{expected} | ||||||
|  |             dates: This guest's arrival or departure dates conflict with the host's availability dates | ||||||
|   helpers: |   helpers: | ||||||
|     select: |     select: | ||||||
|       prompt: Please select |       prompt: Please select | ||||||
| @ -887,12 +893,13 @@ en: | |||||||
|         description: On this page you can schedule workshops and publish your schedule to the front page. |         description: On this page you can schedule workshops and publish your schedule to the front page. | ||||||
|         no_locations_warning: Before you can schedule workshops, you must first add locations. |         no_locations_warning: Before you can schedule workshops, you must first add locations. | ||||||
|       housing: |       housing: | ||||||
|         description: The housing tool can be used to help you set up visitors that have requested to be housed with a host. |         description: The housing tool can be used to help you set up visitors that have requested to be housed with a host. When you see an error icon beside a host's space or a guest's details, hover over it to see warnings. Ideally you should only check marks which will indicate that all hosts and guests are happy. | ||||||
|         headings: |         headings: | ||||||
|           hosts: Hosts |           hosts: Hosts | ||||||
|           guests: Guests |           guests: Guests | ||||||
|           email: Email |           email: Email | ||||||
|           housing: Preference |           housing: Preference | ||||||
|  |           arrival_departure: In City | ||||||
|       locations: |       locations: | ||||||
|         description: Locations are used to schedule workshops, events, and meals. Once your schedule is published, users will be able to see the name and address and be given a link to a map so that they can find their way. |         description: Locations are used to schedule workshops, events, and meals. Once your schedule is published, users will be able to see the name and address and be given a link to a map so that they can find their way. | ||||||
|         headings: |         headings: | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user