Added conference list page, administration tools, and re-designed conference administration
							
								
								
									
										17
									
								
								Rakefile
									
									
									
									
									
								
							
							
						
						@ -4,3 +4,20 @@
 | 
				
			|||||||
require File.expand_path('../config/application', __FILE__)
 | 
					require File.expand_path('../config/application', __FILE__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BikeBike::Application.load_tasks
 | 
					BikeBike::Application.load_tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					task regenerate_images: :environment do
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    conference: [ :cover, :poster ],
 | 
				
			||||||
 | 
					    organization: [ :logo, :avatar, :cover ]
 | 
				
			||||||
 | 
					  }.each do | model_class, attributes |
 | 
				
			||||||
 | 
					    Object.const_get(model_class.to_s.titlecase).all.each do | model |
 | 
				
			||||||
 | 
					      attributes.each do | attribute |
 | 
				
			||||||
 | 
					        uploader = model.send(attribute)
 | 
				
			||||||
 | 
					        if uploader.present?
 | 
				
			||||||
 | 
					          puts "Regenerating #{model_class}.#{attribute} = #{uploader.url}"
 | 
				
			||||||
 | 
					          uploader.recreate_versions!
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -1,84 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
					 | 
				
			||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
					 | 
				
			||||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
					 | 
				
			||||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
					 | 
				
			||||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
   xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
					 | 
				
			||||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
					 | 
				
			||||||
   width="1000"
 | 
					 | 
				
			||||||
   height="1000"
 | 
					 | 
				
			||||||
   id="svg2"
 | 
					 | 
				
			||||||
   version="1.1"
 | 
					 | 
				
			||||||
   inkscape:version="0.48.2 r9819"
 | 
					 | 
				
			||||||
   sodipodi:docname="New document 1">
 | 
					 | 
				
			||||||
  <defs
 | 
					 | 
				
			||||||
     id="defs4" />
 | 
					 | 
				
			||||||
  <sodipodi:namedview
 | 
					 | 
				
			||||||
     id="base"
 | 
					 | 
				
			||||||
     pagecolor="#ffffff"
 | 
					 | 
				
			||||||
     bordercolor="#666666"
 | 
					 | 
				
			||||||
     borderopacity="1.0"
 | 
					 | 
				
			||||||
     inkscape:pageopacity="0.0"
 | 
					 | 
				
			||||||
     inkscape:pageshadow="2"
 | 
					 | 
				
			||||||
     inkscape:zoom="0.49497475"
 | 
					 | 
				
			||||||
     inkscape:cx="1268.2181"
 | 
					 | 
				
			||||||
     inkscape:cy="-8.1858472"
 | 
					 | 
				
			||||||
     inkscape:document-units="px"
 | 
					 | 
				
			||||||
     inkscape:current-layer="layer1"
 | 
					 | 
				
			||||||
     showgrid="false"
 | 
					 | 
				
			||||||
     fit-margin-left="0.5"
 | 
					 | 
				
			||||||
     fit-margin-bottom="0.5"
 | 
					 | 
				
			||||||
     fit-margin-top="0.5"
 | 
					 | 
				
			||||||
     fit-margin-right="0.5"
 | 
					 | 
				
			||||||
     inkscape:window-width="1920"
 | 
					 | 
				
			||||||
     inkscape:window-height="1028"
 | 
					 | 
				
			||||||
     inkscape:window-x="-8"
 | 
					 | 
				
			||||||
     inkscape:window-y="-8"
 | 
					 | 
				
			||||||
     inkscape:window-maximized="1">
 | 
					 | 
				
			||||||
    <inkscape:grid
 | 
					 | 
				
			||||||
       type="xygrid"
 | 
					 | 
				
			||||||
       id="grid2996"
 | 
					 | 
				
			||||||
       empspacing="5"
 | 
					 | 
				
			||||||
       visible="true"
 | 
					 | 
				
			||||||
       enabled="true"
 | 
					 | 
				
			||||||
       snapvisiblegridlinesonly="true" />
 | 
					 | 
				
			||||||
  </sodipodi:namedview>
 | 
					 | 
				
			||||||
  <metadata
 | 
					 | 
				
			||||||
     id="metadata7">
 | 
					 | 
				
			||||||
    <rdf:RDF>
 | 
					 | 
				
			||||||
      <cc:Work
 | 
					 | 
				
			||||||
         rdf:about="">
 | 
					 | 
				
			||||||
        <dc:format>image/svg+xml</dc:format>
 | 
					 | 
				
			||||||
        <dc:type
 | 
					 | 
				
			||||||
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
					 | 
				
			||||||
        <dc:title></dc:title>
 | 
					 | 
				
			||||||
      </cc:Work>
 | 
					 | 
				
			||||||
    </rdf:RDF>
 | 
					 | 
				
			||||||
  </metadata>
 | 
					 | 
				
			||||||
  <g
 | 
					 | 
				
			||||||
     inkscape:label="Layer 1"
 | 
					 | 
				
			||||||
     inkscape:groupmode="layer"
 | 
					 | 
				
			||||||
     id="layer1"
 | 
					 | 
				
			||||||
     transform="translate(-39.499999,287.13782)">
 | 
					 | 
				
			||||||
    <g
 | 
					 | 
				
			||||||
       id="g3005"
 | 
					 | 
				
			||||||
       transform="matrix(1.7404181,0,0,1.7404181,-29.616725,-527.44586)">
 | 
					 | 
				
			||||||
      <path
 | 
					 | 
				
			||||||
         sodipodi:nodetypes="ssssscccssss"
 | 
					 | 
				
			||||||
         inkscape:connector-curvature="0"
 | 
					 | 
				
			||||||
         id="rect3000"
 | 
					 | 
				
			||||||
         d="m 71,138.36218 512,0 c 17.174,0 31,13.826 31,31 l 0,512 c 0,17.174 -13.826,31 -31,31 l -146.5,0 -45.81978,-37.88194 -44.18022,37.88194 -275.5,0 c -17.174,0 -31,-13.826 -31,-31 l 0,-512 c 0,-17.174 13.826,-31 31,-31 z"
 | 
					 | 
				
			||||||
         style="fill:#3b579d;fill-opacity:1;stroke:none" />
 | 
					 | 
				
			||||||
      <path
 | 
					 | 
				
			||||||
         sodipodi:nodetypes="ccccccccccccccccc"
 | 
					 | 
				
			||||||
         inkscape:connector-curvature="0"
 | 
					 | 
				
			||||||
         id="path3002"
 | 
					 | 
				
			||||||
         d="m 346.5,712.36218 0,-222.5 -75,0 0,-86.5 75,0 0,-66 c 0,-69.18633 42.89263,-112.18866 110.45353,-112.18866 40.67053,0 68.04647,3.18866 68.04647,3.18866 l 0,78 -45.82143,0 c -29.03699,0 -42.67857,10.21289 -42.67857,41 l 0,56 85.5,0 -11,86.5 -74.5,0 0,222.5 z"
 | 
					 | 
				
			||||||
         style="fill:#ffffff;stroke:none" />
 | 
					 | 
				
			||||||
    </g>
 | 
					 | 
				
			||||||
  </g>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 131 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/administrators.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 100 125"><path d="M32.5 30.1a4.63 4.63 0 1 1-4.62-4.6 4.62 4.62 0 0 1 4.62 4.6zm58.17 42.73V91H71.3V81h-9.9V70.64h-9.88v-6a29.28 29.28 0 1 1 14.7-16.25zm-4 1.66L61.6 49.23l.4-1.15a25.4 25.4 0 1 0-9.6 11.46l3.1-2v9.08h9.88V77h9.88v10h11.4z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 320 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/broadcast.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 9.9 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/broadcast.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 40"><path d="M0 25.5h7.7v5.7l7-5.7H32V.8H0v24.7zM2 2.8h28v20.7H14l-.5.4-3.8 3v-3.7H2V2.8z"/><path d="M8.8 4.7H17v2H8.8zm0 3.7h11.8v2H8.8zm0 3.6h14.5v2H8.8zm0 3.8h11.8v2H8.8zm0 3.6h8.6v2H8.8z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 255 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/dates.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 8.6 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/dates.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="0 0 62 72.5"><path d="M0 0v58h62V0H0zm12 56H2V46h10v10zm12 0H14V46h10v10zm12 0H26V46h10v10zm12 0H38V46h10v10zm12 0H50V46h10v10zm0-36v2H50v10h10v12H50V34h-2v10H38V34h-2v10H26V34h-2v10H14V34h-2v10H2V32h10V22H2V10h10v10h2V10h10v10h2V10h10v10h2V10h10v10h2V10h10v10z"/><path d="M14 22h10v10H14zm12 0h10v10H26zm12 0h10v10H38z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 389 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/description.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 8.3 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/description.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M76 24.6l-8-8H24v67h52v-59zM68.5 20l4 4h-4v-4zM26 81.4v-63h40.5V26H74v55.5H26z"/><path d="M30 24h20v2H30zm0 5h40v2H30zm0 5h25v2H30zm27.5 0H70v2H57.5zM30 39h40v2H30zm0 5h15v2H30zm17.5 0H70v2H47.5zM30 49h40v2H30zm0 5h17.5v2H30zm20 0h20v2H50zm-20 5h40v2H30zm0 5h7.5v2H30zm10 0h30v2H40zm-10 5h40v2H30zm0 5h40v2H30z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 390 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/events.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 28 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/events.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 640"><path d="M510 209.6c0-68.5-47.8-124.2-106.6-124.2-16 0-31.8 4.3-46.3 12.5-19-42-57-70-101-70-43 0-81 28-101 70-14-9-30-13-46-13C50 85 2 141 2 209c0 59 36.8 123.2 88.4 136L65 380.4h35.6l-7.6 15c-8.2 16.4-3 36.4 12.3 46.5 5 3 8.2 8 8.8 14 1 6-1 12-5 16l11 12c8-8 12-19 11-30s-7-21-16-27c-8-5.6-11-16.5-7-25.5l11-22.4h27l-24-34c30-5 57.6-28 75.5-62.7 13 10.5 27.6 18.2 43.5 21.3L216 338h35l-7.6 15c-8.2 16.5-3 36.5 12.3 46.6 5 3.2 8.2 8.5 8.8 14.5.6 6-1.5 12-5.7 16l-8.5 9 11.7 11 8-8.5c7.8-8 11.6-18.5 10.6-29.3-1.2-11-7-20.5-16-26.5-8.4-5.5-11.3-16.4-7-25.4l11.4-22h27.5l-25-34c16-3 30.6-11 43.5-21.5 17.3 33.7 43.8 56 72.6 62.2l-25 34.5h35.7l-7.6 15c-8.3 16.5-3 36.5 12.2 46.6 5 3 8 8.5 8 14.5s-2 12-6 16l12 12c7-7.8 11-18.5 10-29-1-11-7-21-16-27-8.6-5.3-11-16.2-7-25.2l11-22.8h28l-24-33c53-11 91-76.6 91-136zM105.5 352l8.5 12H97l8.5-12zm3-21c-51.5 0-90-64-90-121.4 0-59.5 40.4-108 90-108 14 0 27.8 4 40.3 11.6-5 15-7.5 30.7-7.5 46.8 0 41 16.4 83.2 43 112-17.3 36.5-46 59-75.7 59zM256 311l8.5 12h-17l8.5-12zm0-21c-56.3 0-98.3-68.6-98.3-130 0-63.8 44-115.7 98.3-115.7s98.3 52 98.3 115.6c0 61-42 130-98.3 130zm139 74l8.5-12 8.5 12h-17zm8.4-33c-29.7 0-58.4-22.4-75.8-59 26.7-28.8 43-71 43-112 0-16-2.4-31.8-7.4-46.8 12.5-7.5 26.3-11.4 40.2-11.4 49.7 0 90.2 48.4 90.2 108 0 57-38.6 121.3-90.2 121.3z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/housing.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 8.9 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/housing.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 125"><path d="M67.5 20c0-5.5-4.5-10-10-10h-15c-5.5 0-10 4.5-10 10v2.5H5V90h90V22.5H67.5V20zm-30 0c0-2.8 2.2-5 5-5h15c2.8 0 5 2.2 5 5v2.5h-25V20zm36.3 7.5V85H26.3V27.5h47.5zm-63.8 0h13.8V85H10V27.5zM90 85H76.3V27.5H90V85z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 286 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/locations.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 20 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/locations.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 45 56.25"><path d="M11 37.5l.8.4V17l-.7-.5M22 13v21l.6-.3h.4V13l-.3-.3M34.2 16l-1 .6V38l1-.7"/><path fill="none" d="M25 13l-2.5-1-10.7 4.3-7.4-4v22.2l7.5 4 10-4.2 2.5 1 8 3.3 7.4-4V12.2l-7.4 4-2.4-1"/><path d="M33 14l-1.8-.6-.7 2 2.6 1 8-4v22l-8 4.3-8-3.3-2.3-1h-.2L12 38.6l-7.6-4V12.2l7.4 4L22.5 12l2.6 1-1-2.6-1-.6L12 14 2.3 9v26.7l9.4 5 10.7-4.2L33 40.8l9.6-5v-27"/><path d="M28.2 3.4c-2.3 0-4 2-4 4.2v1.2l4 10 4-10.3c.2-.3.2-.6.2-1 0-2.2-2-4-4.2-4zm0 6.2c-1 0-1.7-.8-1.7-1.8S27.3 6 28.2 6s1.8.8 1.8 1.8-.8 1.8-1.8 1.8z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 584 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/meals.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 22 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/meals.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" class="stroked"><circle cx="386.5" cy="16.5" r="3.6"/><path stroke-width="2" d="M392 16.5c0 2.4-3.5 7.2-4.9 9.1-.3.4-.9.4-1.2 0-1.4-2-4.9-6.7-4.9-9.1 0-3 2.5-5.5 5.5-5.5s5.5 2.4 5.5 5.5z"/><circle cx="404.1" cy="45.6" r="3.6"/><path stroke-width="2" d="M409.6 45.6c0 2.4-3.5 7.2-4.9 9.1-.3.4-.9.4-1.2 0-1.4-2-4.9-6.7-4.9-9.1 0-3 2.5-5.5 5.5-5.5 3.1.1 5.5 2.5 5.5 5.5z"/><path stroke-width="2" d="M381.2.9h27.9c4.5 0 8.1 3.7 8.1 8.1v54.6c0 4.5-3.7 8.1-8.1 8.1h-27.9c-4.5 0-8.1-3.7-8.1-8.1V9.1c0-4.5 3.6-8.2 8.1-8.2z"/><path d="M382 6.1h26.4c2.4 0 4.4 2 4.4 4.4v47.7c0 2.4-2 4.4-4.4 4.4H382c-2.4 0-4.4-2-4.4-4.4V10.5c-.1-2.4 1.9-4.4 4.4-4.4z"/><circle cx="395.2" cy="67.2" r="1.9"/><line x1="388.8" y1="3.6" x2="395.8" y2="3.6"/><line x1="398.7" y1="3.6" x2="402.2" y2="3.6"/><path stroke-width="2" d="M386.5 29.3h14.3c2 0 3.7 1.7 3.7 3.7s-1.7 3.7-3.7 3.7H386c-2.1 0-3.7 1.7-3.7 3.7v14.4c0 2.1 1.7 3.7 3.7 3.7h18.5"/><polygon stroke-width="2" points="23.7,80.7 78.4,80.7 24.7,27"/><polyline stroke-width="2" points="24.7,27 27.3,24.5 80.9,78.1 78.4,80.7"/><path stroke-width="0.9766" d="M30.5 22.5h.1c2.8 0 5.1 2.3 5.1 5.1v.2c0 2.8 2.3 5.1 5.1 5.1h.4c2.8 0 5.1 2.3 5.1 5.1v.1c0 2.8 2.3 5.1 5.1 5.1h.2c2.8 0 5.1 2.3 5.1 5.1v.3c0 2.8 2.3 5.1 5.1 5.1h.3c2.8 0 5.1 2.3 5.1 5.1v.3c0 2.8 2.3 5.1 5.1 5.1h.4c2.8 0 5.1 2.3 5.1 5.1v.3c0 2.8 2.3 5.1 5.1 5.1h.2"/><path d="M68.3 57.6v.2c0 2.8 2.3 5.1 5.1 5.1h.4M57.7 47.1v.2c0 2.8 2.3 5.1 5.1 5.1h.2M47.4 36.8c0 2.8 2.3 5.1 5.1 5.1h.1M42.1 31.6h-.2c-1.7 0-3.2-.8-4.1-2.1m-.9-3.2v.2c0 .5.1 1 .2 1.4"/><rect x="22.9" y="42.6" transform="rotate(-135 60.783 44.59)" stroke-width="2" width="75.9" height="3.9"/><line stroke-width="2" x1="32.5" y1="19.3" x2="32.5" y2="20.3"/><line stroke-width="2" x1="32.6" y1="25.3" x2="32.6" y2="29.4"/><line stroke-width="2" x1="86.2" y1="72.8" x2="83" y2="72.8"/><line stroke-width="2" x1="76.6" y1="72.8" x2="75.8" y2="72.8"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/payment.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 20 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/payment.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 640"><path d="M92.1 227.3c-13.6 0-24.6 11-24.6 24.6 0 13.6 11 24.6 24.6 24.6s24.6-11 24.6-24.6c0-13.5-11-24.6-24.6-24.6zm0 32.8c-4.5 0-8.2-3.7-8.2-8.2 0-4.5 3.7-8.2 8.2-8.2 4.5 0 8.2 3.7 8.2 8.2 0 4.5-3.7 8.2-8.2 8.2z"/><path d="M359.9 133.8c1.7-6.9 2.6-14 2.6-21.2 0-49.7-40.4-90.1-90.1-90.1-49.7 0-90.1 40.4-90.1 90.1 0 5.9.6 11.7 1.7 17.3-7.3 1.7-14.6 3.5-21.5 5.6-16.7-24.4-44.6-39.3-74.3-39.3-26.1 0-52.1 13.5-52.1 13.5l20.5 7.7c20.7 7.8 36.8 24.3 43.9 45-29.8 17.8-52.7 40.1-66.6 65H2V342h31.8c17.5 31.3 49.5 58.6 91.1 77.7v69.8h98.3v-43.3c25 2.8 49.1 3.1 73.7.9v42.4h98.3v-66.1c72-30.1 114.8-81.6 114.8-138.7 0-66.8-58.7-125.3-150.1-150.9zm-87.5-94.9c40.7 0 73.7 33.1 73.7 73.7 0 18.3-6.6 35.7-18.8 49.2h-46.7v-9.7c9.5-3.4 16.4-12.4 16.4-23.1 0-13.6-11-24.6-24.6-24.6-4.5 0-8.2-3.7-8.2-8.2 0-4.5 3.7-8.2 8.2-8.2 4.5 0 8.2 3.7 8.2 8.2H297c0-10.7-6.9-19.7-16.4-23.1v-9.7h-16.4v9.7c-9.5 3.4-16.4 12.4-16.4 23.1 0 13.6 11 24.6 24.6 24.6 4.5 0 8.2 3.7 8.2 8.2 0 4.5-3.7 8.2-8.2 8.2-4.5 0-8.2-3.7-8.2-8.2h-16.4c0 10.7 6.9 19.7 16.4 23.1v9.7h-46.8c-12.1-13.5-18.8-30.8-18.8-49.2 0-40.7 33.1-73.7 73.8-73.7zm111.7 371.4l-5.2 2.1v60.8h-65.5v-44.3l-9.1 1c-29.3 3.3-58.1 3.1-88.1-1.1l-9.3-1.3v45.6h-65.5V409l-4.9-2.1c-42.5-18.5-74.6-45.7-90.3-76.7l-2.3-4.5H18.4v-81.9h25.4s19-45.2 70.3-70.3l5.5-3.1-1.5-6.1c-5.3-21-18-39.2-35.4-51.4 27.8-2 55 12.3 69.1 36.5l3.3 5.7s24.1-7.2 33.5-9.4c2.2 5.6 5 11 8.3 16.1h-14.6v16.4h180.3v-16.4H348c2.6-4 4.8-8.1 6.7-12.4 83.4 23.2 139 76.9 139 135.4-.1 51.3-41 98.3-109.6 125.5z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/payment_message.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 60"><path d="M8.5 46.7V35.3h-8v-34h47v34H19.9L8.5 46.7zm-6-13.4h8v8.6l8.6-8.6h26.4v-30h-43v30z"/><path d="M23.5 28.6v-2c-1-.1-1.8-.4-2.5-.7-.6-.3-1.2-.9-1.7-1.6-.5-.7-.7-1.6-.8-2.7l2-.4c.2 1.1.4 1.9.8 2.4.6.7 1.3 1.1 2.1 1.2v-6.5c-.8-.2-1.7-.5-2.6-1-.6-.4-1.1-.9-1.5-1.5-.4-.6-.5-1.4-.5-2.2 0-1.4.5-2.6 1.5-3.5.7-.6 1.7-1 3.1-1.1V8h1.2v1c1.2.1 2.1.5 2.8 1 .9.7 1.4 1.8 1.6 3l-2 .4c-.1-.8-.4-1.4-.8-1.8-.4-.4-.9-.7-1.6-.8v5.9l2 .6c.6.3 1.2.6 1.6 1 .4.4.7.9.9 1.4.2.6.3 1.1.3 1.8 0 1.4-.4 2.6-1.3 3.5-.9.9-2.1 1.4-3.5 1.5v2.1h-1.1zm0-17.9c-.8.1-1.4.4-1.9 1-.5.5-.7 1.1-.7 1.8s.2 1.3.6 1.7c.4.5 1 .8 2 1.1v-5.6zm1.2 14.1c.8-.1 1.4-.4 2-1 .5-.6.8-1.3.8-2.2 0-.7-.2-1.3-.5-1.8-.4-.4-1.1-.9-2.2-1.2v6.2z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 762 B  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/paypal.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 640"><path d="M92.1 227.3c-13.6 0-24.6 11-24.6 24.6 0 13.6 11 24.6 24.6 24.6s24.6-11 24.6-24.6c0-13.5-11-24.6-24.6-24.6zm0 32.8c-4.5 0-8.2-3.7-8.2-8.2 0-4.5 3.7-8.2 8.2-8.2 4.5 0 8.2 3.7 8.2 8.2 0 4.5-3.7 8.2-8.2 8.2z"/><path d="M359.9 133.8c1.7-6.9 2.6-14 2.6-21.2 0-49.7-40.4-90.1-90.1-90.1-49.7 0-90.1 40.4-90.1 90.1 0 5.9.6 11.7 1.7 17.3-7.3 1.7-14.6 3.5-21.5 5.6-16.7-24.4-44.6-39.3-74.3-39.3-26.1 0-52.1 13.5-52.1 13.5l20.5 7.7c20.7 7.8 36.8 24.3 43.9 45-29.8 17.8-52.7 40.1-66.6 65H2V342h31.8c17.5 31.3 49.5 58.6 91.1 77.7v69.8h98.3v-43.3c25 2.8 49.1 3.1 73.7.9v42.4h98.3v-66.1c72-30.1 114.8-81.6 114.8-138.7 0-66.8-58.7-125.3-150.1-150.9zm-87.5-94.9c40.7 0 73.7 33.1 73.7 73.7 0 18.3-6.6 35.7-18.8 49.2h-46.7v-9.7c9.5-3.4 16.4-12.4 16.4-23.1 0-13.6-11-24.6-24.6-24.6-4.5 0-8.2-3.7-8.2-8.2 0-4.5 3.7-8.2 8.2-8.2 4.5 0 8.2 3.7 8.2 8.2H297c0-10.7-6.9-19.7-16.4-23.1v-9.7h-16.4v9.7c-9.5 3.4-16.4 12.4-16.4 23.1 0 13.6 11 24.6 24.6 24.6 4.5 0 8.2 3.7 8.2 8.2 0 4.5-3.7 8.2-8.2 8.2-4.5 0-8.2-3.7-8.2-8.2h-16.4c0 10.7 6.9 19.7 16.4 23.1v9.7h-46.8c-12.1-13.5-18.8-30.8-18.8-49.2 0-40.7 33.1-73.7 73.8-73.7zm111.7 371.4l-5.2 2.1v60.8h-65.5v-44.3l-9.1 1c-29.3 3.3-58.1 3.1-88.1-1.1l-9.3-1.3v45.6h-65.5V409l-4.9-2.1c-42.5-18.5-74.6-45.7-90.3-76.7l-2.3-4.5H18.4v-81.9h25.4s19-45.2 70.3-70.3l5.5-3.1-1.5-6.1c-5.3-21-18-39.2-35.4-51.4 27.8-2 55 12.3 69.1 36.5l3.3 5.7s24.1-7.2 33.5-9.4c2.2 5.6 5 11 8.3 16.1h-14.6v16.4h180.3v-16.4H348c2.6-4 4.8-8.1 6.7-12.4 83.4 23.2 139 76.9 139 135.4-.1 51.3-41 98.3-109.6 125.5z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/poster.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/poster.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 640"><path d="M233.8 277.6l-25.8-43-64 106.7h224L282.7 192l-49 85.6zm-52 42.4l26.2-44 13.6 22.8-12 21.2h-28zm52.3 0l48.8-85 48.5 85h-97z"/><path d="M416 85.3h-21.3V64h-21.4V0H352v64h-21.3v21.3H181.3V64H160V0h-21.3v64h-21.4v21.3H74.7V512h362.6V85.3H416zm-64 0h21.3v21.4H352V85.3zm-213.3 0H160v21.4h-21.3V85.3zM416 490.7H96v-384h21.3V128h64v-21.3h149.4V128h64v-21.3H416v384z"/><path d="M298.7 426.7h-85.4c-6 0-10.6 4.7-10.6 10.6s4.7 10.7 10.6 10.7h85.4c6 0 10.6-4.8 10.6-10.7s-4.7-10.6-10.6-10.6zm42.6-42.7H170.7c-6 0-10.7 4.8-10.7 10.7 0 6 4.8 10.6 10.7 10.6h170.6c6 0 10.7-4.7 10.7-10.6 0-6-4.8-10.7-10.7-10.7z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 676 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/providers.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 20 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/providers.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 80"><path d="M2.2 46.5V64h23V46.5L14 38.3 2.2 46.5zm21 15.5h-19V47.5l9.6-6.8 9.5 6.8V62z"/><path d="M0 42.4v3.3l13.8-10 13.7 10v-3.3l-13.7-9.8m25 14V64h23V46.5L50 38.3l-11.5 8.2zm21 15.4h-19V47.5l9.4-6.8 9.6 6.8V62z"/><path d="M36.5 42.4v3.3l13.7-10 13.8 10v-3.3l-13.8-9.8M20.4 14v17.4h23.2V14L32 5.6 20.4 14zm21.2 15.4H22.4V15L32 8l9.6 7v14.4z"/><path d="M45.8 10L32 0 18.2 10v3L32 3.4 45.8 13"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 459 B  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/publish_schedule.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 125"><path d="M71.8 33.2c7.2 0 13-5.8 13-13s-5.8-13-13-13-13 5.8-13 13c0 1.5.3 2.9.7 4.2L36.9 41c-2.3-2.3-5.6-3.7-9.1-3.7-7.2 0-13 5.8-13 13s5.8 13 13 13c3.5 0 6.8-1.4 9.1-3.7l22.6 16.6c-.4 1.3-.7 2.7-.7 4.2 0 7.2 5.8 13 13 13s13-5.8 13-13-5.8-13-13-13c-3.5 0-6.8 1.4-9.1 3.7L40.1 54.4c.4-1.3.7-2.7.7-4.2s-.3-2.9-.7-4.2l22.6-16.6c2.3 2.4 5.5 3.8 9.1 3.8zm0-20c3.9 0 7 3.1 7 7s-3.1 7-7 7-7-3.1-7-7 3.1-7 7-7zm-44 44c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.2 7-7 7zm44 16c3.9 0 7 3.1 7 7s-3.1 7-7 7-7-3.1-7-7 3.1-7 7-7z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 582 B  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/registration_status.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 125"><path d="M38.7 72.4l34.9-22.6-34.9-22.6v45.2zm4-37.8l23.5 15.2L42.7 65V34.6z"/><path d="M50 0C22.4 0 0 22.4 0 50s22.4 50 50 50 50-22.4 50-50S77.6 0 50 0zm0 96C24.6 96 4 75.4 4 50S24.6 4 50 4s46 20.6 46 46-20.6 46-46 46z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 290 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/registrations.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 7.8 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/registrations.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 26.25"><path d="M0 21h24V0H0v21zM19 1h4v3h-4V1zm0 4h4v3h-4V5zm0 4h4v3h-4V9zm0 4h4v3h-4v-3zm0 4h4v3h-4v-3zM14 1h4v3h-4V1zm0 4h4v3h-4V5zm0 4h4v3h-4V9zm0 4h4v3h-4v-3zm0 4h4v3h-4v-3zM9 1h4v3H9V1zm0 4h4v3H9V5zm0 4h4v3H9V9zm0 4h4v3H9v-3zm0 4h4v3H9v-3zM1 1h7v3H1V1zm0 4h7v3H1V5zm0 4h7v3H1V9zm0 4h7v3H1v-3zm0 4h7v3H1v-3z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 377 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/schedule.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 8.0 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/schedule.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 73 67.5" class="stroked"><path stroke-width="2.5" d="M32.2 8v5.8H41v-6z"/><path d="M37.2 13.7v10m0 6.3v10m0 5.6v6.2h34v-50h-34v6m-1 6v9.8m0 6v10m0 6.4v5.8h-34v-50h34v6" stroke-width="3.5"/><path stroke-width="2.5" d="M32.2 24v5.8H41v-6zm0 16v5.8H41v-6zM8.5 13.8h18m-18 6.7h18m-18 6.3h18m-18 6.4h18m-18 6.6h18m20-26h18m-18 6.7h18m-18 6.3h18m-18 6.4h18m-18 6.6h18"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 423 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/stats.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 8.1 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/stats.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 112.5"><path d="M74.8 80V41.8H61.6V80H58V26.8H45V80h-3.2V42H28.6v38h-3V57.6H12.3V80h-3V10h-4v74.2H86V80H74.8zm-9-34h4.7v33.5H66V46zM49.4 31H54v48.7h-4.7V31zM33 46.3h4.5v33.5H33V46.3zM16.5 80V61.8H21V80h-4.5z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 272 B  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/suggested_amounts.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 125"><switch><foreignObject requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" x="0" y="0" width="1" height="1"/><g><g fill="none" stroke="#000" stroke-width="3" stroke-miterlimit="10"><line x1="19.3" y1="50" x2="19.3" y2="57.1"/><line x1="36.8" y1="50" x2="36.8" y2="57.1"/><line x1="19.3" y1="56" x2="19.3" y2="63.1"/><line x1="36.8" y1="56" x2="36.8" y2="63.1"/><line x1="19.3" y1="62" x2="19.3" y2="69.1"/><line x1="36.8" y1="62" x2="36.8" y2="69.1"/><ellipse cx="28" cy="50" rx="8.8" ry="4.9"/><path d="M36.8 56c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5m17.6 6c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5m17.6 6c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5m17.6 6c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="19.3" y1="68" x2="19.3" y2="75.1"/><line x1="36.8" y1="68" x2="36.8" y2="75.1"/><line x1="41.3" y1="38" x2="41.3" y2="45.1"/><line x1="58.8" y1="38" x2="58.8" y2="45.1"/><line x1="41.3" y1="44" x2="41.3" y2="51.1"/><line x1="58.8" y1="44" x2="58.8" y2="51.1"/><line x1="41.3" y1="50" x2="41.3" y2="57.1"/><line x1="58.8" y1="50" x2="58.8" y2="57.1"/><line x1="41.3" y1="56" x2="41.3" y2="63.1"/><line x1="58.8" y1="56" x2="58.8" y2="63.1"/><line x1="41.3" y1="62" x2="41.3" y2="69.1"/><line x1="58.8" y1="62" x2="58.8" y2="69.1"/><ellipse cx="50" cy="38" rx="8.8" ry="4.9"/><path d="M58.8 44c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5m17.6 6c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5m17.6 6c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5m17.6 6c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5m17.6 6c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5m17.6 6c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="41.3" y1="68" x2="41.3" y2="75.1"/><line x1="58.8" y1="68" x2="58.8" y2="75.1"/><line x1="63.3" y1="26" x2="63.3" y2="33.1"/><line x1="63.3" y1="32" x2="63.3" y2="39.1"/><line x1="63.3" y1="38" x2="63.3" y2="45.1"/><line x1="63.3" y1="44" x2="63.3" y2="51.1"/><line x1="63.3" y1="50" x2="63.3" y2="57.1"/><line x1="63.3" y1="56" x2="63.3" y2="63.1"/><line x1="63.3" y1="61.1" x2="63.3" y2="68.2"/><line x1="63.3" y1="67" x2="63.3" y2="74.1"/><ellipse cx="72" cy="26" rx="8.8" ry="4.9"/><path d="M80.8 32c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="80.8" y1="26" x2="80.8" y2="33.1"/><path d="M80.8 38c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="80.8" y1="32" x2="80.8" y2="39.1"/><path d="M80.8 44c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="80.8" y1="38" x2="80.8" y2="45.1"/><path d="M80.8 50c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="80.8" y1="44" x2="80.8" y2="51.1"/><path d="M80.8 56c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="80.8" y1="50" x2="80.8" y2="57.1"/><path d="M80.8 62c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="80.8" y1="56" x2="80.8" y2="63.1"/><path d="M80.8 68c0 2.8-4 5-8.8 5s-8.8-2.2-8.8-5"/><line x1="80.8" y1="61.1" x2="80.8" y2="68.2"/><path d="M80.8 74c0 2.7-4 5-8.8 5s-8.8-2.3-8.8-5"/><line x1="80.8" y1="67" x2="80.8" y2="74.1"/></g></g></switch></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/admin/workshop_times.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 18 KiB  | 
							
								
								
									
										1
									
								
								app/assets/images/admin/workshop_times.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 91 113.75"><path d="M45.2 18.6C30 18.6 17.6 31 17.6 46.2 17.6 61.5 30 74 45.2 74c15.2 0 27.6-12.6 27.6-28 0-15.2-12.4-27.6-27.6-27.6zm0 52C31.8 70.6 21 59.6 21 46c0-13 10.8-24 24.2-24 13.4 0 24.2 11 24.2 24.2 0 13.4-10.8 24.3-24.2 24.3z"/><path d="M47 26.3h-3.4V48h11v-3.5H47m-3.4 17.2H47V66h-3.4zM25.2 44.5h4.4V48h-4.4zm35.6 0h4.4V48h-4.4zm-29.2-13l3.2 3-2.3 2.4-3.2-3zM58.8 61l-3.2-3 2.3-2.6 3 3zM33 62l-2.5-2 3-3.3L36 59zm24.4-31.7l2.5 2.3-3 3.2-2.8-2.3z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 519 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/assets/images/conferences.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 858 KiB  | 
| 
		 Before Width: | Height: | Size: 308 B After Width: | Height: | Size: 308 B  | 
							
								
								
									
										1
									
								
								app/assets/images/facebook.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="-723 0 1000 1000" class="icons"><path d="M222.5,0.5h-891.1c-29.9,0-54,24.1-54,54v891.1c0,29.9,24.1,54,54,54h479.5V612.3h-130.5V461.7h130.5V346.8 c0-120.4,74.7-195.3,192.2-195.3c70.8,0,118.4,5.5,118.4,5.5v135.8H41.9c-50.5,0-74.3,17.8-74.3,71.4v97.5h148.8L97.2,612.3H-32.4 v387.2h255c29.9,0,54-24.1,54-54V54.5C276.5,24.6,252.4,0.5,222.5,0.5z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 397 B  | 
| 
		 Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 470 B  | 
							
								
								
									
										1
									
								
								app/assets/images/github.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" class="icons"><path xmlns="http://www.w3.org/2000/svg" d="M512 0C229.25 0 0 229.2 0 512c0 226.2 146.7 418.1 350.2 485.8 25.6 4.7 34.938-11.125 34.938-24.625 0-12.188-0.469-52.562-0.719-95.312C242 908.8 211.9 817.5 211.9 817.5c-23.312-59.125-56.844-74.875-56.844-74.875-46.531-31.75 3.53-31.125 3.53-31.125 51.4 3.6 78.5 52.8 78.5 52.8 45.7 78.2 119.9 55.6 149 42.5 4.654-33 17.904-55.625 32.5-68.375C304.906 725.4 185.3 681.5 185.3 485.312c0-55.938 19.969-101.562 52.656-137.406-5.219-13-22.844-65.094 5.062-135.562 0 0 42.938-13.75 140.8 52.5 40.812-11.406 84.594-17.031 128.125-17.219 43.5 0.2 87.3 5.9 128.2 17.3 97.688-66.312 140.688-52.5 140.688-52.5 28 70.5 10.4 122.6 5.1 135.5 32.8 35.8 52.6 81.5 52.6 137.4 0 196.688-119.75 240-233.812 252.7 18.4 15.9 34.8 47 34.8 94.8 0 68.438-0.688 123.625-0.688 140.5 0 13.6 9.3 29.6 35.2 24.562C877.438 930 1024 738.1 1024 512 1024 229.2 794.8 0 512 0z"/></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 972 B  | 
| 
		 Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB  | 
@ -1,2 +1,2 @@
 | 
				
			|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 291 288.5" id="bb-icon-logo"><path d="m290.7 136.1c-8.8.9-16.9-5.1-18.4-14-1.5-8.8 4-17.3 12.6-19.4-1.6-5.4-3.5-10.7-5.7-15.8-8 3.9-17.6 1-22.1-6.8-4.5-7.8-2.1-17.6 5.2-22.5-3.3-4.5-7-8.8-10.8-12.9-6.2 6.3-16.2 6.9-23.1 1.2-6.9-5.8-8-15.8-2.8-23-4.7-3.1-9.5-5.9-14.5-8.4-3.6 8.1-12.9 12.1-21.3 9-8.4-3.1-12.9-12.1-10.5-20.6-5.4-1.3-10.9-2.2-16.5-2.9-.6 8.8-8 15.8-16.9 15.8-9 0-16.3-7-16.9-15.8-5.5.6-10.9 1.6-16.2 2.8 2.4 8.5-2.1 17.5-10.6 20.6-8.4 3-17.7-1-21.3-9.1-5 2.5-9.9 5.3-14.5 8.4 5.2 7.2 4 17.2-2.9 23-6.9 5.7-17 5.1-23.1-1.2-3.8 4.1-7.5 8.3-10.8 12.8 7.3 5 9.6 14.8 5.1 22.6-4.5 7.8-14.2 10.6-22.1 6.7-2.2 5.1-4.1 10.4-5.8 15.8 8.6 2.2 14.1 10.6 12.6 19.4-1.6 8.8-9.7 14.8-18.5 13.9-.2 2.8-.3 5.7-.3 8.6 0 2.8.1 5.5.2 8.2 8.8-.9 16.9 5.1 18.4 14 1.5 8.8-4 17.3-12.6 19.4 1.6 5.4 3.5 10.7 5.7 15.8 8-3.9 17.6-1 22.1 6.8 4.5 7.8 2.1 17.6-5.2 22.5 3.3 4.5 7 8.8 10.8 12.9 6.2-6.3 16.2-6.9 23.1-1.2 6.9 5.8 8 15.8 2.8 23 4.7 3.1 9.5 5.9 14.5 8.4 3.6-8.1 12.9-12.1 21.3-9 8.4 3.1 12.9 12.1 10.5 20.6 5.4 1.3 10.9 2.2 16.5 2.9.6-8.8 8-15.8 16.9-15.8 9 0 16.3 7 16.9 15.8 5.5-.6 10.9-1.6 16.1-2.8-2.4-8.5 2.1-17.5 10.6-20.6 8.4-3 17.7 1 21.3 9.1 5-2.5 9.9-5.3 14.6-8.4-5.2-7.2-4-17.2 2.9-23 6.9-5.7 17-5.1 23.1 1.2 3.8-4.1 7.5-8.3 10.8-12.8-7.3-5-9.6-14.8-5.1-22.6 4.5-7.8 14.2-10.6 22.2-6.7 2.2-5.1 4.1-10.4 5.8-15.8-8.6-2.2-14.1-10.6-12.6-19.4 1.6-8.8 9.7-14.8 18.5-13.9.2-2.8.3-5.7.3-8.6-.1-2.8-.1-5.5-.3-8.2m-117.5 55.4c-.6 1.2-1.2 2.4-1.8 3.5-.6 1.1-1.2 2.1-1.9 3.1-4.5 5.8-10.2 10-17 12.6-2.6 1-5.4 1.7-8.2 2.1-2.8.4-5.8.7-8.9.9-1.6.1-3.2.1-4.8-.1-1.6-.2-3.2-.4-4.7-.5-.7 0-1.3-.1-1.9-.3-.6-.2-1.2-.3-1.9-.3-.6 0-1.1-.2-1.7-.4-.6-.3-1.2-.4-1.9-.3-.6 0-1.1-.1-1.7-.3-.6-.2-1.2-.4-1.8-.6l-57-15.5c-2.2-.6-4-1.2-5.5-1.8-1.4-.6-2.3-1.8-2.5-3.5-.1-1.1.2-2.8.8-4.9.6-2.1 1.2-3.9 1.5-5.4l30.8-114.8c.4-1.6.8-3.2 1.2-5 .4-1.8 1.1-3.1 2-4 .8-.8 1.9-1.2 3.5-1.2.3-.1.6 0 .8.1.2.1.5.2.8.1l58.3 15.6c.9.2 1.8.5 2.8.6.9.2 1.8.4 2.5.8.6.4 1.2.7 1.9.7.7 0 1.3.2 2 .5l1.2.3c.7.5 1.5.8 2.4.9.9.2 1.7.5 2.6 1 1 .5 1.9 1 2.9 1.4.9.4 1.9.9 2.9 1.4 2.2 1.6 4.3 3.1 6.3 4.5 2 1.4 3.7 3.1 5.2 4.8 2.1 2.5 3.7 5.4 4.6 8.6 1 3.2 1.5 6.7 1.6 10.5 0 1-.1 1.9-.2 2.9-.2.9-.3 2-.3 3.1 0 .6-.1 1.1-.3 1.6-.2.5-.3 1-.3 1.6 0 .4-.1.9-.3 1.5-.2.6-.4 1-.6 1.2l-.5 1.8c-.1.4-.3.8-.5 1.3-.2.5-.3.9-.4 1.1-.5.8-.9 1.6-1.1 2.3-.3.7-.6 1.3-1 1.9-3 4.2-6.2 7.5-9.7 9.8-1.2.7-2.3 1.2-3.6 1.6-1.2.4-2.4 1-3.4 1.8-.3.2-.7.5-1.2.8-.5.4-.6.9-.5 1.6 0 1.1.6 2.2 1.8 3.3 1.2 1.1 2.3 2.1 3.2 3 2.9 3.3 5 6.8 6.4 10.5 1.3 3.6 2 7.5 2.1 11.9.1 1.2.1 2.3-.1 3.4-.2 1.1-.3 2.3-.3 3.4l-.6 2.2c-.1 1.5-.6 3.4-1.4 5.7-1.2 2.6-1.9 4.3-2.6 5.6m38.9 17.5c-.2 1.2-.5 2.5-.9 4l-3.8 14.1c-.4 1.4-.8 2.7-1.2 3.9-.4 1.1-1.1 1.9-1.9 2.4-1.1.4-2.3.5-3.6.2-1.3-.3-2.7-.6-4.1-1l-13.1-3.5c-1.4-.4-2.8-.8-4.1-1.2-1.3-.4-2.2-1.1-2.6-2.1-.4-1-.6-2.1-.4-3.3.2-1.3.5-2.6.9-4.1l3.3-12.3c.3-1.3.7-2.6 1-3.8.3-1.2.9-2.2 1.6-2.8.7-.6 1.9-1 3.5-1.2.3-.1.6 0 .9.1.3.2.6.2.9.1l15.4 4.1c1.6.4 3 .8 4.4 1.3 1.4.4 2.4 1.1 3.1 2 .7.9.9 1.9.7 3.1m28.4-108.9c-.3 1.2-.6 2.4-1 3.7l-5.8 21.7c-.2.8-.4 1.7-.5 2.7-.1 1-.4 1.8-.9 2.4l-.6 2.2c-.5.8-.9 1.8-1.1 2.8-.2 1-.5 1.8-1 2.6-.4.6-.7 1.2-.8 1.8-.1.6-.4 1.2-.8 1.8-.6 1.1-1 2.2-1.3 3.3-.3 1.1-.7 2.2-1.3 3.1-.3.5-.5 1-.6 1.4-.1.5-.3.9-.6 1.4-.7 1.6-1.4 3.3-2 5.1-.6 1.8-1.4 3.5-2.2 5.1-.5.8-.8 1.7-1 2.5-.1.8-.5 1.7-1 2.7-1.2 2.2-2.1 4.6-2.8 7.1-.7 2.5-1.8 4.9-3 7-.9 1.7-1.6 3.5-2.2 5.4-.6 1.9-1.6 3.1-3.2 3.7-.5.2-1 .2-1.5.2-.6 0-1.2 0-1.9-.1l-2.7-.7c-1.3-.3-2.4-.8-3.3-1.3-.9-.5-1.5-1.2-1.9-2-.4-1-.5-1.9-.3-2.8.2-.9.4-1.9.4-3 0-1.5.2-3.1.5-4.7.4-1.6.5-3.1.5-4.7.3-1 .4-1.8.4-2.2.1-.8.2-1.6.4-2.4.2-.8.4-1.6.4-2.4 0-2 .2-4 .7-6 .5-2 .8-4 .9-6 0-.7.1-1.3.3-1.9.2-.6.3-1.2.3-1.9.1-1.2.2-2.5.5-3.8.3-1.3.5-2.7.6-4 .1-.3.1-.5.1-.8 0-.3 0-.5.1-.8 0-1.1.2-2.2.4-3.1.3-1 .4-2 .4-3.1.1-3 .7-6.2 1.6-9.6 1-3.4 1.9-6.8 2.8-10.1l4-15.1c.4-1.4.8-2.8 1.1-4.1.3-1.3 1-2.3 1.9-3.1.9-.6 1.9-.9 3.2-.8.3-.1.6 0 .8.1.2.1.5.2.8.1l15.1 4c1.6.4 3 .9 4.3 1.4 1.3.5 2.2 1.3 2.6 2.4.5.6.5 1.6.2 2.8"/>
 | 
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 291 288.5" id="bb-icon-logo" class="icons bb-icon-logo"><path d="m290.7 136.1c-8.8.9-16.9-5.1-18.4-14-1.5-8.8 4-17.3 12.6-19.4-1.6-5.4-3.5-10.7-5.7-15.8-8 3.9-17.6 1-22.1-6.8-4.5-7.8-2.1-17.6 5.2-22.5-3.3-4.5-7-8.8-10.8-12.9-6.2 6.3-16.2 6.9-23.1 1.2-6.9-5.8-8-15.8-2.8-23-4.7-3.1-9.5-5.9-14.5-8.4-3.6 8.1-12.9 12.1-21.3 9-8.4-3.1-12.9-12.1-10.5-20.6-5.4-1.3-10.9-2.2-16.5-2.9-.6 8.8-8 15.8-16.9 15.8-9 0-16.3-7-16.9-15.8-5.5.6-10.9 1.6-16.2 2.8 2.4 8.5-2.1 17.5-10.6 20.6-8.4 3-17.7-1-21.3-9.1-5 2.5-9.9 5.3-14.5 8.4 5.2 7.2 4 17.2-2.9 23-6.9 5.7-17 5.1-23.1-1.2-3.8 4.1-7.5 8.3-10.8 12.8 7.3 5 9.6 14.8 5.1 22.6-4.5 7.8-14.2 10.6-22.1 6.7-2.2 5.1-4.1 10.4-5.8 15.8 8.6 2.2 14.1 10.6 12.6 19.4-1.6 8.8-9.7 14.8-18.5 13.9-.2 2.8-.3 5.7-.3 8.6 0 2.8.1 5.5.2 8.2 8.8-.9 16.9 5.1 18.4 14 1.5 8.8-4 17.3-12.6 19.4 1.6 5.4 3.5 10.7 5.7 15.8 8-3.9 17.6-1 22.1 6.8 4.5 7.8 2.1 17.6-5.2 22.5 3.3 4.5 7 8.8 10.8 12.9 6.2-6.3 16.2-6.9 23.1-1.2 6.9 5.8 8 15.8 2.8 23 4.7 3.1 9.5 5.9 14.5 8.4 3.6-8.1 12.9-12.1 21.3-9 8.4 3.1 12.9 12.1 10.5 20.6 5.4 1.3 10.9 2.2 16.5 2.9.6-8.8 8-15.8 16.9-15.8 9 0 16.3 7 16.9 15.8 5.5-.6 10.9-1.6 16.1-2.8-2.4-8.5 2.1-17.5 10.6-20.6 8.4-3 17.7 1 21.3 9.1 5-2.5 9.9-5.3 14.6-8.4-5.2-7.2-4-17.2 2.9-23 6.9-5.7 17-5.1 23.1 1.2 3.8-4.1 7.5-8.3 10.8-12.8-7.3-5-9.6-14.8-5.1-22.6 4.5-7.8 14.2-10.6 22.2-6.7 2.2-5.1 4.1-10.4 5.8-15.8-8.6-2.2-14.1-10.6-12.6-19.4 1.6-8.8 9.7-14.8 18.5-13.9.2-2.8.3-5.7.3-8.6-.1-2.8-.1-5.5-.3-8.2m-117.5 55.4c-.6 1.2-1.2 2.4-1.8 3.5-.6 1.1-1.2 2.1-1.9 3.1-4.5 5.8-10.2 10-17 12.6-2.6 1-5.4 1.7-8.2 2.1-2.8.4-5.8.7-8.9.9-1.6.1-3.2.1-4.8-.1-1.6-.2-3.2-.4-4.7-.5-.7 0-1.3-.1-1.9-.3-.6-.2-1.2-.3-1.9-.3-.6 0-1.1-.2-1.7-.4-.6-.3-1.2-.4-1.9-.3-.6 0-1.1-.1-1.7-.3-.6-.2-1.2-.4-1.8-.6l-57-15.5c-2.2-.6-4-1.2-5.5-1.8-1.4-.6-2.3-1.8-2.5-3.5-.1-1.1.2-2.8.8-4.9.6-2.1 1.2-3.9 1.5-5.4l30.8-114.8c.4-1.6.8-3.2 1.2-5 .4-1.8 1.1-3.1 2-4 .8-.8 1.9-1.2 3.5-1.2.3-.1.6 0 .8.1.2.1.5.2.8.1l58.3 15.6c.9.2 1.8.5 2.8.6.9.2 1.8.4 2.5.8.6.4 1.2.7 1.9.7.7 0 1.3.2 2 .5l1.2.3c.7.5 1.5.8 2.4.9.9.2 1.7.5 2.6 1 1 .5 1.9 1 2.9 1.4.9.4 1.9.9 2.9 1.4 2.2 1.6 4.3 3.1 6.3 4.5 2 1.4 3.7 3.1 5.2 4.8 2.1 2.5 3.7 5.4 4.6 8.6 1 3.2 1.5 6.7 1.6 10.5 0 1-.1 1.9-.2 2.9-.2.9-.3 2-.3 3.1 0 .6-.1 1.1-.3 1.6-.2.5-.3 1-.3 1.6 0 .4-.1.9-.3 1.5-.2.6-.4 1-.6 1.2l-.5 1.8c-.1.4-.3.8-.5 1.3-.2.5-.3.9-.4 1.1-.5.8-.9 1.6-1.1 2.3-.3.7-.6 1.3-1 1.9-3 4.2-6.2 7.5-9.7 9.8-1.2.7-2.3 1.2-3.6 1.6-1.2.4-2.4 1-3.4 1.8-.3.2-.7.5-1.2.8-.5.4-.6.9-.5 1.6 0 1.1.6 2.2 1.8 3.3 1.2 1.1 2.3 2.1 3.2 3 2.9 3.3 5 6.8 6.4 10.5 1.3 3.6 2 7.5 2.1 11.9.1 1.2.1 2.3-.1 3.4-.2 1.1-.3 2.3-.3 3.4l-.6 2.2c-.1 1.5-.6 3.4-1.4 5.7-1.2 2.6-1.9 4.3-2.6 5.6m38.9 17.5c-.2 1.2-.5 2.5-.9 4l-3.8 14.1c-.4 1.4-.8 2.7-1.2 3.9-.4 1.1-1.1 1.9-1.9 2.4-1.1.4-2.3.5-3.6.2-1.3-.3-2.7-.6-4.1-1l-13.1-3.5c-1.4-.4-2.8-.8-4.1-1.2-1.3-.4-2.2-1.1-2.6-2.1-.4-1-.6-2.1-.4-3.3.2-1.3.5-2.6.9-4.1l3.3-12.3c.3-1.3.7-2.6 1-3.8.3-1.2.9-2.2 1.6-2.8.7-.6 1.9-1 3.5-1.2.3-.1.6 0 .9.1.3.2.6.2.9.1l15.4 4.1c1.6.4 3 .8 4.4 1.3 1.4.4 2.4 1.1 3.1 2 .7.9.9 1.9.7 3.1m28.4-108.9c-.3 1.2-.6 2.4-1 3.7l-5.8 21.7c-.2.8-.4 1.7-.5 2.7-.1 1-.4 1.8-.9 2.4l-.6 2.2c-.5.8-.9 1.8-1.1 2.8-.2 1-.5 1.8-1 2.6-.4.6-.7 1.2-.8 1.8-.1.6-.4 1.2-.8 1.8-.6 1.1-1 2.2-1.3 3.3-.3 1.1-.7 2.2-1.3 3.1-.3.5-.5 1-.6 1.4-.1.5-.3.9-.6 1.4-.7 1.6-1.4 3.3-2 5.1-.6 1.8-1.4 3.5-2.2 5.1-.5.8-.8 1.7-1 2.5-.1.8-.5 1.7-1 2.7-1.2 2.2-2.1 4.6-2.8 7.1-.7 2.5-1.8 4.9-3 7-.9 1.7-1.6 3.5-2.2 5.4-.6 1.9-1.6 3.1-3.2 3.7-.5.2-1 .2-1.5.2-.6 0-1.2 0-1.9-.1l-2.7-.7c-1.3-.3-2.4-.8-3.3-1.3-.9-.5-1.5-1.2-1.9-2-.4-1-.5-1.9-.3-2.8.2-.9.4-1.9.4-3 0-1.5.2-3.1.5-4.7.4-1.6.5-3.1.5-4.7.3-1 .4-1.8.4-2.2.1-.8.2-1.6.4-2.4.2-.8.4-1.6.4-2.4 0-2 .2-4 .7-6 .5-2 .8-4 .9-6 0-.7.1-1.3.3-1.9.2-.6.3-1.2.3-1.9.1-1.2.2-2.5.5-3.8.3-1.3.5-2.7.6-4 .1-.3.1-.5.1-.8 0-.3 0-.5.1-.8 0-1.1.2-2.2.4-3.1.3-1 .4-2 .4-3.1.1-3 .7-6.2 1.6-9.6 1-3.4 1.9-6.8 2.8-10.1l4-15.1c.4-1.4.8-2.8 1.1-4.1.3-1.3 1-2.3 1.9-3.1.9-.6 1.9-.9 3.2-.8.3-.1.6 0 .8.1.2.1.5.2.8.1l15.1 4c1.6.4 3 .9 4.3 1.4 1.3.5 2.2 1.3 2.6 2.4.5.6.5 1.6.2 2.8"/>
 | 
				
			||||||
</svg>
 | 
					</svg>
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB  | 
@ -1,3 +0,0 @@
 | 
				
			|||||||
<svg height="1024" width="1024" xmlns="http://www.w3.org/2000/svg">
 | 
					 | 
				
			||||||
  <path d="M512 0C229.25 0 0 229.25 0 512c0 226.25 146.688 418.125 350.156 485.812 25.594 4.688 34.938-11.125 34.938-24.625 0-12.188-0.469-52.562-0.719-95.312C242 908.812 211.906 817.5 211.906 817.5c-23.312-59.125-56.844-74.875-56.844-74.875-46.531-31.75 3.53-31.125 3.53-31.125 51.406 3.562 78.47 52.75 78.47 52.75 45.688 78.25 119.875 55.625 149 42.5 4.654-33 17.904-55.625 32.5-68.375C304.906 725.438 185.344 681.5 185.344 485.312c0-55.938 19.969-101.562 52.656-137.406-5.219-13-22.844-65.094 5.062-135.562 0 0 42.938-13.75 140.812 52.5 40.812-11.406 84.594-17.031 128.125-17.219 43.5 0.188 87.312 5.875 128.188 17.281 97.688-66.312 140.688-52.5 140.688-52.5 28 70.531 10.375 122.562 5.125 135.5 32.812 35.844 52.625 81.469 52.625 137.406 0 196.688-119.75 240-233.812 252.688 18.438 15.875 34.75 47 34.75 94.75 0 68.438-0.688 123.625-0.688 140.5 0 13.625 9.312 29.562 35.25 24.562C877.438 930 1024 738.125 1024 512 1024 229.25 794.75 0 512 0z" />
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 1.0 KiB  | 
@ -112,4 +112,19 @@
 | 
				
			|||||||
        toggle();
 | 
					        toggle();
 | 
				
			||||||
        checkbox.addEventListener('change', function(event) { toggle(); });
 | 
					        checkbox.addEventListener('change', function(event) { toggle(); });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Array.prototype.forEach.call(document.querySelectorAll('fieldset.translator'), function(translator) {
 | 
				
			||||||
 | 
					        Array.prototype.forEach.call(translator.querySelectorAll('.locale-select a'), function(selector) {
 | 
				
			||||||
 | 
					            selector.addEventListener('click', function(event) {
 | 
				
			||||||
 | 
					                event.preventDefault();
 | 
				
			||||||
 | 
					                var locale = event.target.parentElement.getAttribute('data-locale');
 | 
				
			||||||
 | 
					                Array.prototype.forEach.call(translator.querySelectorAll('.locale-select li'), function(_selector) {
 | 
				
			||||||
 | 
					                    _selector.className = _selector.getAttribute('data-locale') == locale ? 'selected' : '';
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                Array.prototype.forEach.call(translator.querySelectorAll('.text-editors li'), function(editor) {
 | 
				
			||||||
 | 
					                    editor.className = editor.getAttribute('data-locale') == locale ? 'selected' : '';
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
})();
 | 
					})();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										31
									
								
								app/assets/javascripts/filefield.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					(function() {
 | 
				
			||||||
 | 
					    document.addEventListener('DOMContentLoaded', function() {
 | 
				
			||||||
 | 
					        var fields = document.getElementsByClassName('file-field');
 | 
				
			||||||
 | 
					        for (var i = 0; i < fields.length; i++) {
 | 
				
			||||||
 | 
					            var field = fields[i];
 | 
				
			||||||
 | 
					            var input = field.getElementsByTagName('input')[0];
 | 
				
			||||||
 | 
					            var image = field.getElementsByTagName('img')[0];
 | 
				
			||||||
 | 
					            var state = field.getElementsByClassName('file-field-name')[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            input.onchange = function() {
 | 
				
			||||||
 | 
					                state.className = 'file-field-name selected';
 | 
				
			||||||
 | 
					                state.innerHTML = this.value.split(/[\/\\]/).reverse()[0];
 | 
				
			||||||
 | 
					                var uploadButton = this.form.querySelector('[value="upload"]');
 | 
				
			||||||
 | 
					                if (uploadButton) {
 | 
				
			||||||
 | 
					                    uploadButton.setAttribute('data-enabled', '1');
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if (this.files && this.files[0] && typeof FileReader !== "undefined") {
 | 
				
			||||||
 | 
					                    var reader = new FileReader();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    reader.onload = function (e) {
 | 
				
			||||||
 | 
					                        image.className = 'changed';
 | 
				
			||||||
 | 
					                        image.src = e.target.result;
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    reader.readAsDataURL(this.files[0]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }, false);
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
							
								
								
									
										4
									
								
								app/assets/javascripts/jquery.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						@ -230,4 +230,15 @@
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	initNode();
 | 
						initNode();
 | 
				
			||||||
 | 
						document.addEventListener('DOMContentLoaded', function() {
 | 
				
			||||||
 | 
							var errors = document.getElementsByClassName('has-error');
 | 
				
			||||||
 | 
							if (errors.length <= 0) {
 | 
				
			||||||
 | 
								errors = document.getElementsByClassName('info-message');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (errors.length > 0) {
 | 
				
			||||||
 | 
								errors[0].scrollIntoView();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
})();
 | 
					})();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										117
									
								
								app/assets/javascripts/map.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					(function() {
 | 
				
			||||||
 | 
					  function loadMap() {
 | 
				
			||||||
 | 
					    var projection = d3.geo.mercator();
 | 
				
			||||||
 | 
					    var path = d3.geo.path().projection(projection);
 | 
				
			||||||
 | 
					    var tooltip = document.getElementById('tooltip');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var initialScale = 3.5;
 | 
				
			||||||
 | 
					    var initialPosition = [-100, -175];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var zoom = d3.behavior.zoom()
 | 
				
			||||||
 | 
					      .scaleExtent([1, 20])
 | 
				
			||||||
 | 
					      .scale(initialScale).translate(initialPosition)
 | 
				
			||||||
 | 
					      .on("zoom", function() {
 | 
				
			||||||
 | 
					        setZoom(d3.event.translate, d3.event.scale);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function setZoom(translate, scale) {
 | 
				
			||||||
 | 
					        container.attr("transform", "translate(" + translate + ") scale(" + scale + ")").attr('data-scale', scale);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var container = d3.select('#map').call(zoom).insert('g', ':first-child').attr('class', 'map');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setZoom(initialPosition, initialScale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    container.append("path")
 | 
				
			||||||
 | 
					      .datum(d3.geo.graticule())
 | 
				
			||||||
 | 
					      .attr("class", "graticule")
 | 
				
			||||||
 | 
					      .attr("d", path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d3.selection.prototype.moveToFront = function() {
 | 
				
			||||||
 | 
					      return this.each(function(){
 | 
				
			||||||
 | 
					        this.parentNode.appendChild(this);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d3.json('/assets/world-110m.json', function(error, world) {
 | 
				
			||||||
 | 
					      if (error) {
 | 
				
			||||||
 | 
					        throw error;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      container.selectAll('path')
 | 
				
			||||||
 | 
					        .data(topojson.feature(world, world.objects.countries).features)
 | 
				
			||||||
 | 
					        .enter()
 | 
				
			||||||
 | 
					        .append('path')
 | 
				
			||||||
 | 
					        .attr('d', path)
 | 
				
			||||||
 | 
					        .attr('class', 'country');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var year = (new Date()).getFullYear();
 | 
				
			||||||
 | 
					      var conferences = document.querySelectorAll('#conferences .conference');
 | 
				
			||||||
 | 
					      var conference_path = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (var i = 0; i < conferences.length; i++) {
 | 
				
			||||||
 | 
					        var d = conferences[i];
 | 
				
			||||||
 | 
					        if (d.getAttribute('data-t') === 'annual') {
 | 
				
			||||||
 | 
					          var coords = projection([d.getAttribute('data-o'), d.getAttribute('data-a')]);
 | 
				
			||||||
 | 
					          if (conference_path.length) {
 | 
				
			||||||
 | 
					            conference_path[conference_path.length - 1].x2 = coords[0];
 | 
				
			||||||
 | 
					            conference_path[conference_path.length - 1].y2 = coords[1];
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          conference_path.push({
 | 
				
			||||||
 | 
					            x1: coords[0],
 | 
				
			||||||
 | 
					            y1: coords[1]
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      container.append('defs').html('<filter id="svg-gooey-filter"><feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur"></feGaussianBlur><feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -7" result="svg-gooey-filter"></feColorMatrix><feComposite in="SourceGraphic" in2="svg-gooey-filter" operator="atop"></feComposite></filter>')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var regionalConferences = container.append('g').attr('filter', 'url(#svg-gooey-filter)').attr('class', 'cities regional-conferences');
 | 
				
			||||||
 | 
					      var annualConferences = container.append('g').attr('filter', 'url(#svg-gooey-filter)').attr('class', 'cities annual-conferences');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      function mouseover(e) {
 | 
				
			||||||
 | 
					        c = document.getElementById('conference-' + event.target.getAttribute('data-c'));
 | 
				
			||||||
 | 
					        tooltip.innerHTML = '<h3>' + c.querySelector('.title').innerHTML + '</h3>' +
 | 
				
			||||||
 | 
					                            '<div class="conference-details">' + c.querySelector('.conference-details').innerHTML + '</div>';
 | 
				
			||||||
 | 
					        tooltip.className = 'open';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      function mouseout(e) {
 | 
				
			||||||
 | 
					        tooltip.className = '';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      function click(e) {
 | 
				
			||||||
 | 
					        l = document.querySelector('#conference-' + event.target.getAttribute('data-c') + ' .conference-link');
 | 
				
			||||||
 | 
					        window.location.href = l.getAttribute('href');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (var i = conferences.length - 1; i >= 0; i--) {
 | 
				
			||||||
 | 
					        var c = conferences[i];
 | 
				
			||||||
 | 
					        var type = c.getAttribute('data-t');
 | 
				
			||||||
 | 
					        var coords = projection([c.getAttribute('data-o'), c.getAttribute('data-a')]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        (type === 'annual' ? annualConferences : regionalConferences)
 | 
				
			||||||
 | 
					          .append('circle')
 | 
				
			||||||
 | 
					          .attr('class', 'city type-' + type)
 | 
				
			||||||
 | 
					          .attr('data-c', c.id.replace(/^conference\-/, ''))
 | 
				
			||||||
 | 
					          .attr('cx', function(d) { return coords[0]; })
 | 
				
			||||||
 | 
					          .attr('cy', function(d) { return coords[1]; })
 | 
				
			||||||
 | 
					          .attr('r', Math.max(3,
 | 
				
			||||||
 | 
					              (15 - (
 | 
				
			||||||
 | 
					                (year - parseInt(c.getAttribute('data-y'))) * 2.5)) * 1.125)
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					          .on('mouseover', mouseover)
 | 
				
			||||||
 | 
					          .on('mouseout', mouseout)
 | 
				
			||||||
 | 
					          .on('click', click);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d3.select("#map").attr('class', 'loaded');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  document.onreadystatechange = function () {
 | 
				
			||||||
 | 
					    if (document.readyState == 'complete') {
 | 
				
			||||||
 | 
					      loadMap();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
							
								
								
									
										26
									
								
								app/assets/javascripts/userfield.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					(function() {
 | 
				
			||||||
 | 
					    function find_user(email, f) {
 | 
				
			||||||
 | 
					        var request = new XMLHttpRequest();
 | 
				
			||||||
 | 
					        request.open('POST', '/user/find', true);
 | 
				
			||||||
 | 
					        request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
 | 
				
			||||||
 | 
					        request.setRequestHeader('X-CSRF-Token', encodeURI(document.querySelector('meta[name="csrf-token"]').getAttribute('content')));
 | 
				
			||||||
 | 
					        request.send('e=' + encodeURI(email));
 | 
				
			||||||
 | 
					        request.onreadystatechange = function() {
 | 
				
			||||||
 | 
					            if (request.readyState == 4) {
 | 
				
			||||||
 | 
					                if (request.status == 200) {
 | 
				
			||||||
 | 
					                    f(JSON.parse(request.responseText));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    f({error: request.status});
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    document.addEventListener('DOMContentLoaded', function() {
 | 
				
			||||||
 | 
					        var fields = document.getElementsByClassName('user-field');
 | 
				
			||||||
 | 
					        for (var i = 0; i < fields.length; i++) {
 | 
				
			||||||
 | 
					            var field = fields[i];
 | 
				
			||||||
 | 
					            var input = field.getElementsByTagName('input')[0];
 | 
				
			||||||
 | 
					            var name = field.getElementsByClassName('user-name')[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }, false);
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
@ -14,6 +14,11 @@ $colour-5: #02CA9E; // green
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
$white: #FFFEFE;
 | 
					$white: #FFFEFE;
 | 
				
			||||||
$black: #333;
 | 
					$black: #333;
 | 
				
			||||||
 | 
					$gray: #E8E8E8;
 | 
				
			||||||
 | 
					$light-gray: #EEE;
 | 
				
			||||||
 | 
					$mid-gray: #888;
 | 
				
			||||||
 | 
					// $red: #B24C63;
 | 
				
			||||||
 | 
					$red: #FF5A5F;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$link-colour: darken($colour-1, 13%);
 | 
					$link-colour: darken($colour-1, 13%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -89,6 +94,10 @@ $link-colour: darken($colour-1, 13%);
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mixin text-stroke {
 | 
				
			||||||
 | 
					    @include _(text-stroke, 1px rgba(0, 0, 0, 0.25));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@mixin button {
 | 
					@mixin button {
 | 
				
			||||||
    position: relative;
 | 
					    position: relative;
 | 
				
			||||||
    display: inline-block;
 | 
					    display: inline-block;
 | 
				
			||||||
@ -103,7 +112,7 @@ $link-colour: darken($colour-1, 13%);
 | 
				
			|||||||
    @include default-box-shadow(top, 2);
 | 
					    @include default-box-shadow(top, 2);
 | 
				
			||||||
    overflow: hidden;
 | 
					    overflow: hidden;
 | 
				
			||||||
    cursor: pointer;
 | 
					    cursor: pointer;
 | 
				
			||||||
	@include _(text-stroke, 1px rgba(0, 0, 0, 0.25));
 | 
					    @include text-stroke;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @include before {
 | 
					    @include before {
 | 
				
			||||||
        content: '';
 | 
					        content: '';
 | 
				
			||||||
 | 
				
			|||||||
@ -5,8 +5,8 @@
 | 
				
			|||||||
            "chrome": ["51"]
 | 
					            "chrome": ["51"]
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "development": {
 | 
					        "development": {
 | 
				
			||||||
            "and_chr": ["53"],
 | 
					            "and_chr": ["54"],
 | 
				
			||||||
            "chrome": ["53"],
 | 
					            "chrome": ["54"],
 | 
				
			||||||
            "edge": ["13"],
 | 
					            "edge": ["13"],
 | 
				
			||||||
            "firefox": ["44"],
 | 
					            "firefox": ["44"],
 | 
				
			||||||
            "ie": ["11"],
 | 
					            "ie": ["11"],
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										36
									
								
								app/controllers/admin_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					require 'geocoder/calculations'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AdminController < ApplicationController
 | 
				
			||||||
 | 
					  def new
 | 
				
			||||||
 | 
					    return do_404 unless logged_in? && current_user.administrator?
 | 
				
			||||||
 | 
					    @this_conference = Conference.new
 | 
				
			||||||
 | 
					    @page_title = 'articles.conferences.headings.new'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def edit
 | 
				
			||||||
 | 
					    return do_404 unless logged_in? && current_user.administrator?
 | 
				
			||||||
 | 
					    @this_conference = Conference.find_by!(slug: params[:slug])
 | 
				
			||||||
 | 
					    @page_title = 'articles.conferences.headings.edit'
 | 
				
			||||||
 | 
					    render 'new'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def save
 | 
				
			||||||
 | 
					    conference = params[:id].present? ? Conference.find_by!(id: params[:id]) : Conference.new
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if params[:button] == 'save'
 | 
				
			||||||
 | 
					      city = City.search(params[:city])
 | 
				
			||||||
 | 
					      conference.city_id = city.id
 | 
				
			||||||
 | 
					      conference.conferencetype = params[:type]
 | 
				
			||||||
 | 
					      conference.year = params[:year].to_i
 | 
				
			||||||
 | 
					      conference.is_public = params[:is_public].present?
 | 
				
			||||||
 | 
					      conference.is_featured = params[:is_featured].present?
 | 
				
			||||||
 | 
					      conference.make_slug(true)
 | 
				
			||||||
 | 
					      conference.save!
 | 
				
			||||||
 | 
					    elsif params[:button] == 'delete'
 | 
				
			||||||
 | 
					      conference.destroy
 | 
				
			||||||
 | 
					      return redirect_to conferences_url
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    redirect_to conference_url(conference.slug)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@ -4,14 +4,14 @@ module ActiveRecord
 | 
				
			|||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ApplicationController < LinguaFrancaApplicationController
 | 
					class ApplicationController < LinguaFrancaApplicationController
 | 
				
			||||||
	include ScheduleHelper
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # 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, :admin_update]
 | 
					  protect_from_forgery with: :exception, :except => [:do_confirm, :js_error, :admin_update]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  before_filter :capture_page_info
 | 
					  before_filter :capture_page_info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  helper_method :protect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @@test_host
 | 
					  @@test_host
 | 
				
			||||||
  @@test_location
 | 
					  @@test_location
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,8 +36,18 @@ class ApplicationController < LinguaFrancaApplicationController
 | 
				
			|||||||
    I18n.config.translator = current_user
 | 
					    I18n.config.translator = current_user
 | 
				
			||||||
    I18n.config.callback = self
 | 
					    I18n.config.callback = self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# get the current conference and set it globally
 | 
					    # get the current conferences and set them globally
 | 
				
			||||||
		@conference = Conference.order("start_date DESC").first
 | 
					    status_hierarchy = {
 | 
				
			||||||
 | 
					      open: 1,
 | 
				
			||||||
 | 
					      pre: 2,
 | 
				
			||||||
 | 
					      closed: 3
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    @conferences = Conference.where(is_featured: true, is_public: true).order("start_date DESC").sort do |a, b|
 | 
				
			||||||
 | 
					      status_hierarchy[(a.registration_status || :closed).to_sym] <=> status_hierarchy[(b.registration_status || :closed).to_sym]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # set the top conference
 | 
				
			||||||
 | 
					    @conference = @conferences.first
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # add some style sheets
 | 
					    # add some style sheets
 | 
				
			||||||
    @stylesheets ||= Array.new
 | 
					    @stylesheets ||= Array.new
 | 
				
			||||||
@ -72,16 +82,7 @@ class ApplicationController < LinguaFrancaApplicationController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if @conference.workshop_schedule_published
 | 
					    if @conference.workshop_schedule_published
 | 
				
			||||||
      @event_dlg = true
 | 
					      @event_dlg = true
 | 
				
			||||||
			#view_context.add_inline_script :schedule
 | 
					 | 
				
			||||||
      get_scheule_data(false)
 | 
					      get_scheule_data(false)
 | 
				
			||||||
			# @events = Event.where(:conference_id => @conference.id)
 | 
					 | 
				
			||||||
			# schedule = get_schedule_data
 | 
					 | 
				
			||||||
			# @schedule = schedule[:schedule]
 | 
					 | 
				
			||||||
			# @locations = Hash.new
 | 
					 | 
				
			||||||
			# EventLocation.where(:conference_id => @conference.id).each do |l|
 | 
					 | 
				
			||||||
			# 	@locations[l.id.to_s] = l
 | 
					 | 
				
			||||||
			# end
 | 
					 | 
				
			||||||
			# @day_parts = @conference.day_parts ? JSON.parse(@conference.day_parts) : {:morning => 0, :afternoon => 13, :evening => 18}
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -207,6 +208,13 @@ class ApplicationController < LinguaFrancaApplicationController
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  rescue_from StandardError do |exception|
 | 
					  rescue_from StandardError do |exception|
 | 
				
			||||||
 | 
					    handle_exception exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # show the error page
 | 
				
			||||||
 | 
					    error_500 exception
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def handle_exception(exception)
 | 
				
			||||||
    # log the error
 | 
					    # log the error
 | 
				
			||||||
    logger.info exception.to_s
 | 
					    logger.info exception.to_s
 | 
				
			||||||
    logger.info exception.backtrace.join("\n")
 | 
					    logger.info exception.backtrace.join("\n")
 | 
				
			||||||
@ -229,9 +237,14 @@ class ApplicationController < LinguaFrancaApplicationController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # raise the error if we are in development so that we can debug it
 | 
					    # raise the error if we are in development so that we can debug it
 | 
				
			||||||
    raise exception if Rails.env.development?
 | 
					    raise exception if Rails.env.development?
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# show the error page
 | 
					  def protect(&block)
 | 
				
			||||||
		error_500 exception
 | 
					    begin
 | 
				
			||||||
 | 
					      yield
 | 
				
			||||||
 | 
					    rescue Exception => exception
 | 
				
			||||||
 | 
					      handle_exception exception
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def generate_confirmation(user, url, expiry = nil)
 | 
					  def generate_confirmation(user, url, expiry = nil)
 | 
				
			||||||
@ -403,6 +416,23 @@ class ApplicationController < LinguaFrancaApplicationController
 | 
				
			|||||||
    redirect_to (params[:url] || '/')
 | 
					    redirect_to (params[:url] || '/')
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def find_user
 | 
				
			||||||
 | 
					    user = User.find_user(params[:e])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if user.present?
 | 
				
			||||||
 | 
					      return render json: {
 | 
				
			||||||
 | 
					        name: user.name,
 | 
				
			||||||
 | 
					        email: user.email,
 | 
				
			||||||
 | 
					        exists: true
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    render json: {
 | 
				
			||||||
 | 
					        name: I18n.t('user.not_found'),
 | 
				
			||||||
 | 
					        email: nil,
 | 
				
			||||||
 | 
					        exists: false
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def login_user(u)
 | 
					  def login_user(u)
 | 
				
			||||||
    auto_login(u)
 | 
					    auto_login(u)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@ -460,6 +490,38 @@ class ApplicationController < LinguaFrancaApplicationController
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_success_message(message, is_ajax = false)
 | 
				
			||||||
 | 
					    if is_ajax
 | 
				
			||||||
 | 
					      @success_message = message
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      flash[:success_message] = message
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_error_message(message, is_ajax = false)
 | 
				
			||||||
 | 
					    if is_ajax
 | 
				
			||||||
 | 
					      @error_message = message
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      flash[:error_message] = message
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_error(field, error, is_ajax = false)
 | 
				
			||||||
 | 
					    if is_ajax
 | 
				
			||||||
 | 
					      @errors ||= {}
 | 
				
			||||||
 | 
					      @errors[field] = error
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      flash[:errors] ||= {}
 | 
				
			||||||
 | 
					      flash[:errors][field] = error
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_flash_messages
 | 
				
			||||||
 | 
					    @errors = flash[:errors] || {}
 | 
				
			||||||
 | 
					    @warnings = flash[:warning] || []
 | 
				
			||||||
 | 
					    @success_message = flash[:success_message]
 | 
				
			||||||
 | 
					    @error_message = flash[:error_message] || []
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def get_block_data
 | 
					  def get_block_data
 | 
				
			||||||
    conference = @this_conference || @conference
 | 
					    conference = @this_conference || @conference
 | 
				
			||||||
@ -641,4 +703,39 @@ class ApplicationController < LinguaFrancaApplicationController
 | 
				
			|||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected
 | 
				
			||||||
 | 
					    def set_conference
 | 
				
			||||||
 | 
					      @this_conference = Conference.find_by!(slug: params[:slug])
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_conference_registration
 | 
				
			||||||
 | 
					      @registration = logged_in? ? ConferenceRegistration.find_by(user_id: current_user.id, conference_id: @this_conference.id) : nil
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_conference_registration!
 | 
				
			||||||
 | 
					      @registration = set_conference_registration
 | 
				
			||||||
 | 
					      raise ActiveRecord::PremissionDenied unless @registration.present?
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_or_create_conference_registration
 | 
				
			||||||
 | 
					      set_conference_registration
 | 
				
			||||||
 | 
					      return @registration if @registration.present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      @registration ||= ConferenceRegistration.new(
 | 
				
			||||||
 | 
					          conference:      @this_conference,
 | 
				
			||||||
 | 
					          user_id:         current_user.id,
 | 
				
			||||||
 | 
					          steps_completed: []
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					      last_registration_data = ConferenceRegistration.where(user_id: current_user.id).order(created_at: :desc).limit(1).first
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if last_registration_data.present?
 | 
				
			||||||
 | 
					        if last_registration_data['languages'].present? && current_user.languages.blank?
 | 
				
			||||||
 | 
					          current_user.languages = JSON.parse(last_registration_data['languages'])
 | 
				
			||||||
 | 
					          current_user.save!
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        @registration.city = last_registration_data.city if last_registration_data.city.present?
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1208
									
								
								app/controllers/conference_administration_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										355
									
								
								app/controllers/workshops_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,355 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					class WorkshopsController < ApplicationController
 | 
				
			||||||
 | 
					  def workshops
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    @workshops = Workshop.where(:conference_id => @this_conference.id)
 | 
				
			||||||
 | 
					    @my_workshops = Workshop.joins(:workshop_facilitators).where(:workshop_facilitators => {:user_id => current_user.id}, :conference_id => @this_conference.id)
 | 
				
			||||||
 | 
					    render 'workshops/index'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def view_workshop
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					    return do_404 unless @workshop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @translations_available_for_editing = []
 | 
				
			||||||
 | 
					    I18n.backend.enabled_locales.each do |locale|
 | 
				
			||||||
 | 
					      @translations_available_for_editing << locale if @workshop.can_translate?(current_user, locale)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    @page_title = 'page_titles.conferences.View_Workshop'
 | 
				
			||||||
 | 
					    @register_template = :workshops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render 'workshops/show'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def create_workshop
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    @workshop = Workshop.new
 | 
				
			||||||
 | 
					    @languages = [I18n.locale.to_sym]
 | 
				
			||||||
 | 
					    @needs = []
 | 
				
			||||||
 | 
					    @page_title = 'page_titles.conferences.Create_Workshop'
 | 
				
			||||||
 | 
					    @register_template = :workshops
 | 
				
			||||||
 | 
					    render 'workshops/new'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def translate_workshop
 | 
				
			||||||
 | 
					    @is_translating = true
 | 
				
			||||||
 | 
					    @translation = params[:locale]
 | 
				
			||||||
 | 
					    @page_title = 'page_titles.conferences.Translate_Workshop'
 | 
				
			||||||
 | 
					    @page_title_vars = { language: view_context.language_name(@translation) }
 | 
				
			||||||
 | 
					    @register_template = :workshops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    edit_workshop
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def edit_workshop
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return do_404 unless @workshop.present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @page_title ||= 'page_titles.conferences.Edit_Workshop'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @can_edit = @workshop.can_edit?(current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @is_translating ||= false
 | 
				
			||||||
 | 
					    if @is_translating
 | 
				
			||||||
 | 
					      return do_404 if @translation.to_s == @workshop.locale.to_s || !I18n.backend.enabled_locales.include?(@translation.to_s)
 | 
				
			||||||
 | 
					      return do_403 unless @workshop.can_translate?(current_user, @translation)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      @title = @workshop._title(@translation)
 | 
				
			||||||
 | 
					      @info = @workshop._info(@translation)
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      return do_403 unless @can_edit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      @title = @workshop.title
 | 
				
			||||||
 | 
					      @info = @workshop.info
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @needs = JSON.parse(@workshop.needs || '[]').map &:to_sym
 | 
				
			||||||
 | 
					    @languages = JSON.parse(@workshop.languages || '[]').map &:to_sym
 | 
				
			||||||
 | 
					    @space = @workshop.space.to_sym if @workshop.space
 | 
				
			||||||
 | 
					    @theme = @workshop.theme.to_sym if @workshop.theme
 | 
				
			||||||
 | 
					    @notes = @workshop.notes
 | 
				
			||||||
 | 
					    @register_template = :workshops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render 'workshops/new'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def delete_workshop
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return do_404 unless @workshop.present?
 | 
				
			||||||
 | 
					    return do_403 unless @workshop.can_delete?(current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if request.post?
 | 
				
			||||||
 | 
					      if params[:button] == 'confirm'
 | 
				
			||||||
 | 
					        if @workshop
 | 
				
			||||||
 | 
					          @workshop.workshop_facilitators.destroy_all
 | 
				
			||||||
 | 
					          @workshop.destroy
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect_to register_step_path(@this_conference.slug, 'workshops')
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      return redirect_to view_workshop_url(@this_conference.slug, @workshop.id)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    @register_template = :workshops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render 'workshops/delete'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  def save_workshop
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if params[:button].to_sym != :save
 | 
				
			||||||
 | 
					      if params[:workshop_id].present?
 | 
				
			||||||
 | 
					        return redirect_to view_workshop_url(@this_conference.slug, params[:workshop_id])
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      return redirect_to register_step_path(@this_conference.slug, 'workshops')
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if params[:workshop_id].present?
 | 
				
			||||||
 | 
					      workshop = Workshop.find(params[:workshop_id])
 | 
				
			||||||
 | 
					      return do_404 unless workshop.present?
 | 
				
			||||||
 | 
					      can_edit = workshop.can_edit?(current_user)
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      workshop = Workshop.new(:conference_id => @this_conference.id)
 | 
				
			||||||
 | 
					      workshop.workshop_facilitators = [WorkshopFacilitator.new(:user_id => current_user.id, :role => :creator)]
 | 
				
			||||||
 | 
					      can_edit = true
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    title = params[:title]
 | 
				
			||||||
 | 
					    info  = params[:info].gsub(/^\s*(.*?)\s*$/, '\1')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if params[:translation].present? && workshop.can_translate?(current_user, params[:translation])
 | 
				
			||||||
 | 
					      old_title = workshop._title(params[:translation])
 | 
				
			||||||
 | 
					      old_info = workshop._info(params[:translation])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      do_save = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      unless title == old_title
 | 
				
			||||||
 | 
					        workshop.set_column_for_locale(:title, params[:translation], title, current_user.id)
 | 
				
			||||||
 | 
					        do_save = true
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      unless info == old_info
 | 
				
			||||||
 | 
					        workshop.set_column_for_locale(:info, params[:translation], info, current_user.id)
 | 
				
			||||||
 | 
					        do_save = true
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      # only save if the text has changed, if we want to make sure only to update the translator id if necessary
 | 
				
			||||||
 | 
					      workshop.save_translations if do_save
 | 
				
			||||||
 | 
					    elsif can_edit
 | 
				
			||||||
 | 
					      workshop.title              = title
 | 
				
			||||||
 | 
					      workshop.info               = info
 | 
				
			||||||
 | 
					      workshop.languages          = (params[:languages] || {}).keys.to_json
 | 
				
			||||||
 | 
					      workshop.needs              = (params[:needs] || {}).keys.to_json
 | 
				
			||||||
 | 
					      workshop.theme              = params[:theme] == 'other' ? params[:other_theme] : params[:theme]
 | 
				
			||||||
 | 
					      workshop.space              = params[:space]
 | 
				
			||||||
 | 
					      workshop.notes              = params[:notes]
 | 
				
			||||||
 | 
					      workshop.needs_facilitators = params[:needs_facilitators].present?
 | 
				
			||||||
 | 
					      workshop.save
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # Rouge nil facilitators have been know to be created, just destroy them here now
 | 
				
			||||||
 | 
					      WorkshopFacilitator.where(:user_id => nil).destroy_all
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      return do_403
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    redirect_to view_workshop_url(@this_conference.slug, workshop.id)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def toggle_workshop_interest
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					    return do_404 unless workshop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # save the current state
 | 
				
			||||||
 | 
					    interested = workshop.interested? current_user
 | 
				
			||||||
 | 
					    # remove all associated fields
 | 
				
			||||||
 | 
					    WorkshopInterest.delete_all(:workshop_id => workshop.id, :user_id => current_user.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # creat the new interest row if we weren't interested before
 | 
				
			||||||
 | 
					    WorkshopInterest.create(:workshop_id => workshop.id, :user_id => current_user.id) unless interested
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if request.xhr?
 | 
				
			||||||
 | 
					      render json: [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          selector: '.interest-button',
 | 
				
			||||||
 | 
					          html: view_context.interest_button(workshop)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          selector: '.interest-text',
 | 
				
			||||||
 | 
					          html: view_context.interest_text(workshop)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      # go back to the workshop
 | 
				
			||||||
 | 
					      redirect_to view_workshop_url(@this_conference.slug, workshop.id)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def facilitate_workshop
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					    return do_404 unless @workshop
 | 
				
			||||||
 | 
					    return do_403 if @workshop.facilitator?(current_user) || !current_user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @register_template = :workshops
 | 
				
			||||||
 | 
					    render 'workshops/facilitate'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def facilitate_request
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					    return do_404 unless workshop
 | 
				
			||||||
 | 
					    return do_403 if workshop.facilitator?(current_user) || !current_user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # create the request by making the user a facilitator but making their role 'requested'
 | 
				
			||||||
 | 
					    WorkshopFacilitator.create(user_id: current_user.id, workshop_id: workshop.id, role: :requested)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UserMailer.send_mail :workshop_facilitator_request do
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        :args => [ workshop, current_user, params[:message] ]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    redirect_to sent_facilitate_workshop_url(@this_conference.slug, workshop.id)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def sent_facilitate_request
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    @workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					    return do_404 unless @workshop
 | 
				
			||||||
 | 
					    return do_403 unless @workshop.requested_collaborator?(current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @register_template = :workshops
 | 
				
			||||||
 | 
					    render 'workshops/facilitate_request_sent'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def approve_facilitate_request
 | 
				
			||||||
 | 
					    return do_403 unless logged_in?
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					    return do_404 unless workshop.present?
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    user_id = params[:user_id].to_i
 | 
				
			||||||
 | 
					    action = params[:approve_or_deny].to_sym
 | 
				
			||||||
 | 
					    user = User.find(user_id)
 | 
				
			||||||
 | 
					    case action
 | 
				
			||||||
 | 
					    when :approve
 | 
				
			||||||
 | 
					      if workshop.active_facilitator?(current_user) && workshop.requested_collaborator?(User.find(user_id))
 | 
				
			||||||
 | 
					        f = WorkshopFacilitator.find_by_workshop_id_and_user_id(
 | 
				
			||||||
 | 
					            workshop.id, user_id)
 | 
				
			||||||
 | 
					        f.role = :collaborator
 | 
				
			||||||
 | 
					        f.save
 | 
				
			||||||
 | 
					        UserMailer.send_mail :workshop_facilitator_request_approved, user.locale do
 | 
				
			||||||
 | 
					          [ workshop, user ]
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        return redirect_to view_workshop_url(@this_conference.slug, workshop.id)    
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    when :deny
 | 
				
			||||||
 | 
					      if workshop.active_facilitator?(current_user) && workshop.requested_collaborator?(User.find(user_id))
 | 
				
			||||||
 | 
					        WorkshopFacilitator.delete_all(
 | 
				
			||||||
 | 
					          :workshop_id => workshop.id,
 | 
				
			||||||
 | 
					          :user_id => user_id)
 | 
				
			||||||
 | 
					        UserMailer.send_mail :workshop_facilitator_request_denied, user.locale do
 | 
				
			||||||
 | 
					          [ workshop, user ]
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        return redirect_to view_workshop_url(@this_conference.slug, workshop.id)    
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    when :remove
 | 
				
			||||||
 | 
					      if workshop.can_remove?(current_user, user)
 | 
				
			||||||
 | 
					        WorkshopFacilitator.delete_all(
 | 
				
			||||||
 | 
					          :workshop_id => workshop.id,
 | 
				
			||||||
 | 
					          :user_id => user_id)
 | 
				
			||||||
 | 
					        return redirect_to view_workshop_url(@this_conference.slug, workshop.id)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    when :switch_ownership
 | 
				
			||||||
 | 
					      if workshop.creator?(current_user)
 | 
				
			||||||
 | 
					        f = WorkshopFacilitator.find_by_workshop_id_and_user_id(
 | 
				
			||||||
 | 
					            workshop.id, current_user.id)
 | 
				
			||||||
 | 
					        f.role = :collaborator
 | 
				
			||||||
 | 
					        f.save
 | 
				
			||||||
 | 
					        f = WorkshopFacilitator.find_by_workshop_id_and_user_id(
 | 
				
			||||||
 | 
					            workshop.id, user_id)
 | 
				
			||||||
 | 
					        f.role = :creator
 | 
				
			||||||
 | 
					        f.save
 | 
				
			||||||
 | 
					        return redirect_to view_workshop_url(@this_conference.slug, workshop.id)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return do_403
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def add_workshop_facilitator
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    user = User.find_by_email(params[:email])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # create the user if they don't exist and send them a link to register
 | 
				
			||||||
 | 
					    unless user
 | 
				
			||||||
 | 
					      user = User.create(email: params[:email])
 | 
				
			||||||
 | 
					      generate_confirmation(user, register_path(@this_conference.slug))
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return do_404 unless workshop && current_user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unless workshop.facilitator?(user)
 | 
				
			||||||
 | 
					      WorkshopFacilitator.create(user_id: user.id, workshop_id: workshop.id, role: :collaborator)
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      UserMailer.send_mail :workshop_facilitator_request_approved, user.locale do
 | 
				
			||||||
 | 
					        [ workshop, user ]
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return redirect_to view_workshop_url(@this_conference.slug, params[:workshop_id])
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def add_comment
 | 
				
			||||||
 | 
					    set_conference
 | 
				
			||||||
 | 
					    set_conference_registration!
 | 
				
			||||||
 | 
					    workshop = Workshop.find_by_id_and_conference_id(params[:workshop_id], @this_conference.id)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return do_404 unless workshop && current_user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if params[:button] == 'reply'
 | 
				
			||||||
 | 
					      comment = Comment.find_by!(id: params[:comment_id].to_i, model_type: :workshops, model_id: workshop.id)
 | 
				
			||||||
 | 
					      new_comment = comment.add_comment(current_user, params[:reply])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      unless comment.user.id == current_user.id
 | 
				
			||||||
 | 
					        UserMailer.send_mail :workshop_comment, comment.user.locale do
 | 
				
			||||||
 | 
					          [ workshop, new_comment, comment.user ]
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    elsif params[:button] = 'add_comment'
 | 
				
			||||||
 | 
					      new_comment = workshop.add_comment(current_user, params[:comment])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      workshop.active_facilitators.each do | u |
 | 
				
			||||||
 | 
					        unless u.id == current_user.id
 | 
				
			||||||
 | 
					          UserMailer.send_mail :workshop_comment, u.locale do
 | 
				
			||||||
 | 
					            [ workshop, new_comment, u ]
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      return do_404
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return redirect_to view_workshop_url(@this_conference.slug, workshop.id, anchor: "comment-#{new_comment.id}")
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@ -589,7 +589,7 @@ module ApplicationHelper
 | 
				
			|||||||
    city = nil
 | 
					    city = nil
 | 
				
			||||||
    region = nil
 | 
					    region = nil
 | 
				
			||||||
    country = nil
 | 
					    country = nil
 | 
				
			||||||
		if location.is_a?(Location)
 | 
					    if location.is_a?(Location) || location.is_a?(City)
 | 
				
			||||||
      country = location.country
 | 
					      country = location.country
 | 
				
			||||||
      region = location.territory
 | 
					      region = location.territory
 | 
				
			||||||
      city = location.city
 | 
					      city = location.city
 | 
				
			||||||
@ -639,7 +639,7 @@ module ApplicationHelper
 | 
				
			|||||||
    location1.eql? location2
 | 
					    location1.eql? location2
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def show_errors(field, value)
 | 
					  def show_errors(field, value = nil)
 | 
				
			||||||
    return '' unless @errors && @errors[field].present?
 | 
					    return '' unless @errors && @errors[field].present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    error_txt = _"errors.messages.fields.#{field.to_s}.#{@errors[field]}", :s, vars: { value: value }
 | 
					    error_txt = _"errors.messages.fields.#{field.to_s}.#{@errors[field]}", :s, vars: { value: value }
 | 
				
			||||||
@ -780,6 +780,16 @@ module ApplicationHelper
 | 
				
			|||||||
    return options
 | 
					    return options
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def month_select(value = nil, args = {})
 | 
				
			||||||
 | 
					    options = (1..12).to_a.map { |month| [ (I18n.t "date.#{args[:format] || 'month_names'}")[month], month ] }
 | 
				
			||||||
 | 
					    selectfield args[:name] || :month, value, options, args
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def month_day_select(value = nil, args = {})
 | 
				
			||||||
 | 
					    options = (1..31).to_a.map { |day| [ day, day ] }
 | 
				
			||||||
 | 
					    selectfield args[:name] || :month_day, value, options, args
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def day_select(value = nil, args = {})
 | 
					  def day_select(value = nil, args = {})
 | 
				
			||||||
    selectfield :day, value, conference_days_options_list(:during, nil, args[:format]), args
 | 
					    selectfield :day, value, conference_days_options_list(:during, nil, args[:format]), args
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@ -963,11 +973,41 @@ module ApplicationHelper
 | 
				
			|||||||
    return options
 | 
					    return options
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def admin_steps
 | 
					  def admin_steps # deprecated
 | 
				
			||||||
    [:stats, :edit, :payment, :broadcast, :housing, :locations, :meals, :events, :workshop_times, :schedule]
 | 
					    [:stats, :edit, :payment, :broadcast, :housing, :locations, :meals, :events, :workshop_times, :schedule]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def valid_admin_steps
 | 
					  def administration_steps
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      info: [:administrators, :dates, :description, :poster],
 | 
				
			||||||
 | 
					      payment: [:payment_message, :suggested_amounts, :paypal],
 | 
				
			||||||
 | 
					      registration: [:registration_status, :stats, :registrations, :broadcast],
 | 
				
			||||||
 | 
					      housing: [:providers, :housing],
 | 
				
			||||||
 | 
					      events: [:locations, :meals, :events],
 | 
				
			||||||
 | 
					      schedule: [:workshop_times, :schedule, :publish_schedule]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def administration_sub_steps
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      location_edit: :locations,
 | 
				
			||||||
 | 
					      event_edit: :events
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def get_administration_group(administration_step)
 | 
				
			||||||
 | 
					    admin_step = administration_step.to_sym
 | 
				
			||||||
 | 
					    admin_step = administration_sub_steps[admin_step] if administration_sub_steps[admin_step].present?
 | 
				
			||||||
 | 
					    administration_steps.each do | group, steps |
 | 
				
			||||||
 | 
					      steps.each do | step |
 | 
				
			||||||
 | 
					        return group if step == admin_step
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return nil
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def valid_admin_steps # deprecated
 | 
				
			||||||
    admin_steps + [:broadcast_sent, :organizations]
 | 
					    admin_steps + [:broadcast_sent, :organizations]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -985,6 +1025,10 @@ module ApplicationHelper
 | 
				
			|||||||
    content_tag :ul, steps.html_safe, id: 'registration-admin-menu'
 | 
					    content_tag :ul, steps.html_safe, id: 'registration-admin-menu'
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def admin_update_form(options = {}, &block)
 | 
				
			||||||
 | 
					    form_tag(administration_update_path(@this_conference.slug, @admin_step), options, &block)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def interest_button(workshop)
 | 
					  def interest_button(workshop)
 | 
				
			||||||
    interested = workshop.interested?(current_user) ? :remove_interest : :show_interest
 | 
					    interested = workshop.interested?(current_user) ? :remove_interest : :show_interest
 | 
				
			||||||
    id = "#{interested.to_s.gsub('_', '-')}-#{workshop.id}"
 | 
					    id = "#{interested.to_s.gsub('_', '-')}-#{workshop.id}"
 | 
				
			||||||
@ -1220,7 +1264,13 @@ module ApplicationHelper
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def button_with_confirmation(button_name, confirmation_text, args = {})
 | 
					  def button_with_confirmation(button_name, confirmation_text = nil, args = {})
 | 
				
			||||||
 | 
					    if confirmation_text.is_a? Hash
 | 
				
			||||||
 | 
					      args = confirmation_text
 | 
				
			||||||
 | 
					      confirmation_text = nil
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    confirmation_text ||= (_"forms.confirmations.#{button_name.to_s}", :p)
 | 
				
			||||||
    @confirmation_dlg ||= true
 | 
					    @confirmation_dlg ||= true
 | 
				
			||||||
    args[:data] ||= {}
 | 
					    args[:data] ||= {}
 | 
				
			||||||
    args[:data][:confirmation] = true
 | 
					    args[:data][:confirmation] = true
 | 
				
			||||||
@ -1243,8 +1293,113 @@ module ApplicationHelper
 | 
				
			|||||||
    strip_tags(text.gsub('>', '> ')).gsub(/^(.{40,60})\s.*$/m, '\1…').html_safe
 | 
					    strip_tags(text.gsub('>', '> ')).gsub(/^(.{40,60})\s.*$/m, '\1…').html_safe
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def translate_fields(object, field_options = {}, options = {})
 | 
				
			||||||
 | 
					    html = ''
 | 
				
			||||||
 | 
					    nav = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # set the selected locale
 | 
				
			||||||
 | 
					    selected_locale = (options[:locale] || object.locale || I18n.locale).to_sym
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    I18n.backend.enabled_locales.each do | locale |
 | 
				
			||||||
 | 
					      # ses if this should b the selected field
 | 
				
			||||||
 | 
					      class_name = selected_locale == locale.to_sym ? 'selected' : nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # add the locale to the nav
 | 
				
			||||||
 | 
					      nav += content_tag(:li,
 | 
				
			||||||
 | 
					          content_tag(:a, _("languages.#{locale}"), href: 'javascript:void(0)'),
 | 
				
			||||||
 | 
					        class: class_name, data: { locale: locale }).html_safe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      fields = ''
 | 
				
			||||||
 | 
					      field_options.each do | name, __options |
 | 
				
			||||||
 | 
					        _options = __options.deep_dup
 | 
				
			||||||
 | 
					        # add the field
 | 
				
			||||||
 | 
					        value = object.is_a?(Hash) ? object[locale.to_sym] : object.get_column_for_locale!(name, locale)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # use the default value if we need to
 | 
				
			||||||
 | 
					        if _options[:default].present? && value.blank?
 | 
				
			||||||
 | 
					          value = _(_options[:default], locale: locale)
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _options[:index] = locale
 | 
				
			||||||
 | 
					        _options[:lang] = locale
 | 
				
			||||||
 | 
					        _options[:parent_options] = { lang: locale }
 | 
				
			||||||
 | 
					        type = "#{_options[:type].to_s}"
 | 
				
			||||||
 | 
					        _options.delete(:type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fields += self.send(type, name, value, _options).html_safe
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      html += content_tag(:li, fields.html_safe, class: class_name, data: { locale: locale }).html_safe
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options[:class].nil?
 | 
				
			||||||
 | 
					      options[:class] = []
 | 
				
			||||||
 | 
					    elsif options[:class].is_a?(String)
 | 
				
			||||||
 | 
					      options[:class] = [options[:class]]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    options[:class] += ['translator', 'multi-field-translator']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (fieldset(nil, options) do
 | 
				
			||||||
 | 
					      content_tag(:ul, nav.html_safe, class: 'locale-select').html_safe + 
 | 
				
			||||||
 | 
					      content_tag(:ul, html.html_safe, class: 'text-editors').html_safe
 | 
				
			||||||
 | 
					    end).html_safe
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def translate_textarea(name, object, property = nil, options = {})
 | 
				
			||||||
 | 
					    html = ''
 | 
				
			||||||
 | 
					    nav = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # see if options was passed in as property
 | 
				
			||||||
 | 
					    if options.blank? && property.is_a?(Hash)
 | 
				
			||||||
 | 
					      options = property
 | 
				
			||||||
 | 
					      property = nil
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # set the selected locale
 | 
				
			||||||
 | 
					    selected_locale = (options[:locale] || object.locale || I18n.locale).to_sym
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    I18n.backend.enabled_locales.each do | locale |
 | 
				
			||||||
 | 
					      # ses if this should b the selected field
 | 
				
			||||||
 | 
					      class_name = selected_locale == locale.to_sym ? 'selected' : nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # add the locale to the nav
 | 
				
			||||||
 | 
					      nav += content_tag(:li,
 | 
				
			||||||
 | 
					          content_tag(:a, _("languages.#{locale}"), href: 'javascript:void(0)'),
 | 
				
			||||||
 | 
					        class: class_name, data: { locale: locale }).html_safe
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      # add the field
 | 
				
			||||||
 | 
					      value = object.is_a?(Hash) ? object[locale.to_sym] : object.get_column_for_locale!(name, locale)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # use the default value if we need to
 | 
				
			||||||
 | 
					      if options[:default].present? && value.blank?
 | 
				
			||||||
 | 
					        value = _(options[:default], locale: locale)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      html += content_tag(:li, textarea(name, value, {
 | 
				
			||||||
 | 
					          label: false,
 | 
				
			||||||
 | 
					          edit_on: options[:edit_on],
 | 
				
			||||||
 | 
					          parent_options: {
 | 
				
			||||||
 | 
					            lang: locale
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          index: locale
 | 
				
			||||||
 | 
					        }).html_safe, class: class_name, data: { locale: locale }).html_safe
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options[:class].nil?
 | 
				
			||||||
 | 
					      options[:class] = []
 | 
				
			||||||
 | 
					    elsif options[:class].is_a?(String)
 | 
				
			||||||
 | 
					      options[:class] = [options[:class]]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    options[:class] += ['translator']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (fieldset(name, options) do
 | 
				
			||||||
 | 
					      content_tag(:ul, nav.html_safe, class: 'locale-select').html_safe + 
 | 
				
			||||||
 | 
					      content_tag(:ul, html.html_safe, class: 'text-editors').html_safe
 | 
				
			||||||
 | 
					    end).html_safe
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def textarea(name, value = nil, options = {})
 | 
					  def textarea(name, value = nil, options = {})
 | 
				
			||||||
		id = name.to_s.gsub('[', '_').gsub(']', '')
 | 
					    id = unique_id(name)
 | 
				
			||||||
    label_id = "#{id}-label"
 | 
					    label_id = "#{id}-label"
 | 
				
			||||||
    description_id = nil
 | 
					    description_id = nil
 | 
				
			||||||
    html = ''
 | 
					    html = ''
 | 
				
			||||||
@ -1281,8 +1436,9 @@ module ApplicationHelper
 | 
				
			|||||||
        options[:short] === true ? :short : nil
 | 
					        options[:short] === true ? :short : nil
 | 
				
			||||||
      ].compact
 | 
					      ].compact
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    html_name = name.to_s + (options[:index] ? "[#{options[:index]}]" : '')
 | 
				
			||||||
    if options[:plain]
 | 
					    if options[:plain]
 | 
				
			||||||
			html += (text_area_tag name, value,
 | 
					      html += (text_area_tag html_name, value,
 | 
				
			||||||
        id: id,
 | 
					        id: id,
 | 
				
			||||||
        lang: options[:lang],
 | 
					        lang: options[:lang],
 | 
				
			||||||
        aria: aria,
 | 
					        aria: aria,
 | 
				
			||||||
@ -1291,7 +1447,7 @@ module ApplicationHelper
 | 
				
			|||||||
    else
 | 
					    else
 | 
				
			||||||
      html += content_tag(:div, value.present? ? value.html_safe : '',
 | 
					      html += content_tag(:div, value.present? ? value.html_safe : '',
 | 
				
			||||||
          id: id,
 | 
					          id: id,
 | 
				
			||||||
					data: { name: name, 'edit-on': options[:edit_on] || :load },
 | 
					          data: { name: html_name, 'edit-on': options[:edit_on] || :load },
 | 
				
			||||||
          lang: options[:lang],
 | 
					          lang: options[:lang],
 | 
				
			||||||
          aria: aria,
 | 
					          aria: aria,
 | 
				
			||||||
          tabindex: 0,
 | 
					          tabindex: 0,
 | 
				
			||||||
@ -1304,37 +1460,66 @@ module ApplicationHelper
 | 
				
			|||||||
      add_inline_script :editor
 | 
					      add_inline_script :editor
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		html = content_tag(:div, html.html_safe, class: ['text-area-field', 'input-field']).html_safe
 | 
					    parent_options = options[:parent_options] || {}
 | 
				
			||||||
 | 
					    if parent_options[:class].nil?
 | 
				
			||||||
 | 
					      parent_options[:class] = []
 | 
				
			||||||
 | 
					    elsif parent_options[:class].is_a?(String)
 | 
				
			||||||
 | 
					      parent_options[:class] = [parent_options[:class]]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parent_options[:class] += ['text-area-field', 'input-field']
 | 
				
			||||||
 | 
					    html = content_tag(:div, html.html_safe, parent_options).html_safe
 | 
				
			||||||
    html += _original_content(options[:original_value], options[:original_lang]) if options[:original_value].present?
 | 
					    html += _original_content(options[:original_value], options[:original_lang]) if options[:original_value].present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return html.html_safe
 | 
					    return html.html_safe
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def fieldset(name, options = {}, &block)
 | 
					  def fieldset(name = nil, options = {}, &block)
 | 
				
			||||||
    html = ''
 | 
					    html = ''
 | 
				
			||||||
		label_id = nil
 | 
					    label = ''
 | 
				
			||||||
 | 
					    description = ''
 | 
				
			||||||
    description_id = nil
 | 
					    description_id = nil
 | 
				
			||||||
 | 
					    errors = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if options[:heading].present?
 | 
					    if name.present?
 | 
				
			||||||
			label_id ||= "#{name.to_s}-label"
 | 
					      if options[:label] != false
 | 
				
			||||||
			html += content_tag(:h3, _(options[:heading], :t, vars: options[:vars] || {}), id: label_id)
 | 
					        label = content_tag(:legend,
 | 
				
			||||||
 | 
					          _((
 | 
				
			||||||
 | 
					            options[:label].is_a?(String) ?
 | 
				
			||||||
 | 
					            options[:label] :
 | 
				
			||||||
 | 
					            "forms.labels.generic.#{name}"), :t, vars: options[:vars] || {}))
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if options[:help].present?
 | 
					      if options[:help].present?
 | 
				
			||||||
			description_id ||= "#{name.to_s}-desc"
 | 
					        description_id = unique_id("#{name.to_s}-desc")
 | 
				
			||||||
			html += content_tag(:div, _(options[:help], :s, 2), class: 'input-field-help', id: description_id)
 | 
					        description = content_tag(:div, _(options[:help], :s, 2), class: 'input-field-help', id: description_id)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		(html + content_tag(:fieldset, content_tag(:div, class: :fieldgroup, &block).html_safe,
 | 
					      errors = (show_errors name)
 | 
				
			||||||
				aria: {
 | 
					    end
 | 
				
			||||||
					labelledby: label_id,
 | 
					
 | 
				
			||||||
					describedby: description_id
 | 
					    html = label + errors + description + content_tag(:div, class: :fieldgroup, &block)
 | 
				
			||||||
				}
 | 
					
 | 
				
			||||||
 | 
					    aria = description_id.present? ? { describedby: description_id } : nil
 | 
				
			||||||
 | 
					    (content_tag(:fieldset, html.html_safe,
 | 
				
			||||||
 | 
					        aria: aria,
 | 
				
			||||||
 | 
					        class: ((options[:class] || []) + [
 | 
				
			||||||
 | 
					            options[:inline] ? :inline : nil,
 | 
				
			||||||
 | 
					            options[:inline_label] ? 'inline-label' : nil,
 | 
				
			||||||
 | 
					            errors.present? ? 'has-error' : nil
 | 
				
			||||||
 | 
					          ]).compact
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    ).html_safe
 | 
					    ).html_safe
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def selectfield(name, value, select_options, options = {})
 | 
					  def selectfield(name, value, select_options, options = {})
 | 
				
			||||||
 | 
					    unless select_options.first.is_a?(Array)
 | 
				
			||||||
 | 
					      so = select_options
 | 
				
			||||||
 | 
					      select_options = []
 | 
				
			||||||
 | 
					      so.each do | opt |
 | 
				
			||||||
 | 
					        select_options << [ I18n.t("forms.options.#{name.to_s}.#{opt.to_s}"), opt]
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
    textfield(name, value, options.merge({type: :select, options: select_options}))
 | 
					    textfield(name, value, options.merge({type: :select, options: select_options}))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1350,10 +1535,23 @@ module ApplicationHelper
 | 
				
			|||||||
    textfield(name, value, options.merge({type: :search}))
 | 
					    textfield(name, value, options.merge({type: :search}))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def userfield(name, value, options = {})
 | 
				
			||||||
 | 
					    # eventually this will be a dynamic field to find users, for now we'll just use emails
 | 
				
			||||||
 | 
					    # add_inline_script :userfield
 | 
				
			||||||
 | 
					    emailfield(name, value, options)# .merge({
 | 
				
			||||||
 | 
					    #    parent_options: { class: ['user-field'] },
 | 
				
			||||||
 | 
					    #    after: content_tag(:div, '', class: 'user-name')
 | 
				
			||||||
 | 
					    #  }))
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def emailfield(name, value, options = {})
 | 
					  def emailfield(name, value, options = {})
 | 
				
			||||||
    textfield(name, value, options.merge({type: :email}))
 | 
					    textfield(name, value, options.merge({type: :email}))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def filefield(name, value, options = {})
 | 
				
			||||||
 | 
					    textfield(name, value, options.merge({type: :file}))
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def passwordfield(name, value, options = {})
 | 
					  def passwordfield(name, value, options = {})
 | 
				
			||||||
    textfield(name, value, options.merge({type: :password}))
 | 
					    textfield(name, value, options.merge({type: :password}))
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@ -1375,16 +1573,34 @@ module ApplicationHelper
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    html += show_errors name, value
 | 
					    html += show_errors name, value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inside_label = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options[:type] == :file
 | 
				
			||||||
 | 
					      inside_label = (content_tag(:div, class: 'file-field-selector') do
 | 
				
			||||||
 | 
					        (options[:preview] ? content_tag(:img, nil, src: value.present? ? value.url : nil).html_safe : '').html_safe +
 | 
				
			||||||
 | 
					        content_tag(:div, (value.present? ? File.basename(value.url) : (_'forms.labels.generic.no_file_selected')), class: 'file-field-name ' + (value.present? ? 'selected' : 'unselected')).html_safe +
 | 
				
			||||||
 | 
					        content_tag(:a, (_'forms.actions.generic.select_file'), class: :button)
 | 
				
			||||||
 | 
					      end)
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    label_text = nil
 | 
				
			||||||
    if options[:label].present?
 | 
					    if options[:label].present?
 | 
				
			||||||
			html += label_tag(id) do
 | 
					      label_text = _(options[:label], :t, vars: options[:vars] || {})
 | 
				
			||||||
				_(options[:label], :t, vars: options[:vars] || {})
 | 
					 | 
				
			||||||
			end
 | 
					 | 
				
			||||||
    elsif options[:label] != false
 | 
					    elsif options[:label] != false
 | 
				
			||||||
			html += label_tag id, (_"forms.labels.generic.#{name}")
 | 
					      label_text = (_"forms.labels.generic.#{name}")
 | 
				
			||||||
		elsif options[:type] == :select
 | 
					    elsif options[:type] == :select || options[:type] == :file
 | 
				
			||||||
      # add an empty label so that the drop down button will still appear
 | 
					      # add an empty label so that the drop down button will still appear
 | 
				
			||||||
			html += label_tag id, ''
 | 
					      label_text = ''
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    label_options = {}
 | 
				
			||||||
 | 
					    # let the label be selected if the input is hidden
 | 
				
			||||||
 | 
					    label_options[:tabindex] = 0 if options[:type] == :file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unless label_text.nil?
 | 
				
			||||||
 | 
					      html += label_tag id, (label_text + inside_label).html_safe
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    input_options = {
 | 
					    input_options = {
 | 
				
			||||||
        id: id,
 | 
					        id: id,
 | 
				
			||||||
        required: options[:required],
 | 
					        required: options[:required],
 | 
				
			||||||
@ -1419,11 +1635,19 @@ module ApplicationHelper
 | 
				
			|||||||
        option_list = ('<option value=""> </option>' + option_list).html_safe
 | 
					        option_list = ('<option value=""> </option>' + option_list).html_safe
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
      html += select_tag(name, option_list, input_options)
 | 
					      html += select_tag(name, option_list, input_options)
 | 
				
			||||||
 | 
					    when :file
 | 
				
			||||||
 | 
					      add_inline_script :filefield
 | 
				
			||||||
 | 
					      input_options[:tabindex] = '-1'
 | 
				
			||||||
 | 
					      html += off_screen(file_field_tag name, input_options)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      input_options[:autocomplete] = 'off' if options[:type] == :search
 | 
					      input_options[:autocomplete] = 'off' if options[:type] == :search
 | 
				
			||||||
      html += send("#{(options[:type] || :text).to_s}_field_tag", name, value, input_options)
 | 
					      html += send("#{(options[:type] || :text).to_s}_field_tag", name, value, input_options)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options[:after].present?
 | 
				
			||||||
 | 
					      html += options[:after].html_safe
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    html = content_tag(:div, html.html_safe,
 | 
					    html = content_tag(:div, html.html_safe,
 | 
				
			||||||
        class: [
 | 
					        class: [
 | 
				
			||||||
          "#{(options[:type] || :text).to_s}-field",
 | 
					          "#{(options[:type] || :text).to_s}-field",
 | 
				
			||||||
@ -1435,7 +1659,7 @@ module ApplicationHelper
 | 
				
			|||||||
          options[:full] ? 'full' : nil,
 | 
					          options[:full] ? 'full' : nil,
 | 
				
			||||||
          options[:inline_label] ? 'inline-label' : nil,
 | 
					          options[:inline_label] ? 'inline-label' : nil,
 | 
				
			||||||
          (@errors || {})[name].present? ? 'has-error' : nil
 | 
					          (@errors || {})[name].present? ? 'has-error' : nil
 | 
				
			||||||
			].compact)
 | 
					      ].compact + (((options[:parent_options] || {})[:class]) || []))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    html += _original_content(options[:original_value], options[:original_lang]) if options[:original_value].present?
 | 
					    html += _original_content(options[:original_value], options[:original_lang]) if options[:original_value].present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1489,8 +1713,14 @@ module ApplicationHelper
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    boxes_html = ''
 | 
					    boxes_html = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    labels = nil
 | 
				
			||||||
    is_single = !values.is_a?(Array)
 | 
					    is_single = !values.is_a?(Array)
 | 
				
			||||||
		unless boxes.length > 0 && boxes.first.is_a?(Integer)
 | 
					    if boxes.length > 0
 | 
				
			||||||
 | 
					      if boxes.first.is_a?(Array)
 | 
				
			||||||
 | 
					        labels = boxes.map(&:first) 
 | 
				
			||||||
 | 
					        boxes = boxes.map(&:last)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    elsif !boxes.first.is_a?(Integer)
 | 
				
			||||||
      values = values.present? ? values.map(&:to_s) : [] unless is_single
 | 
					      values = values.present? ? values.map(&:to_s) : [] unless is_single
 | 
				
			||||||
      boxes = boxes.map(&:to_s)
 | 
					      boxes = boxes.map(&:to_s)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
@ -1498,7 +1728,7 @@ module ApplicationHelper
 | 
				
			|||||||
    # convert the required value into a pure boolean
 | 
					    # convert the required value into a pure boolean
 | 
				
			||||||
    required = !!options[:required]
 | 
					    required = !!options[:required]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		boxes.each do | box |
 | 
					    boxes.each_with_index do | box, i |
 | 
				
			||||||
      checked = (is_single ? values.present? : values.include?(box))
 | 
					      checked = (is_single ? values.present? : values.include?(box))
 | 
				
			||||||
      values -= [box] if checked && !is_single
 | 
					      values -= [box] if checked && !is_single
 | 
				
			||||||
      id = nil
 | 
					      id = nil
 | 
				
			||||||
@ -1514,7 +1744,9 @@ module ApplicationHelper
 | 
				
			|||||||
      # we only need the required attribute on one element
 | 
					      # we only need the required attribute on one element
 | 
				
			||||||
      required = false
 | 
					      required = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if is_single
 | 
					      if labels.present?
 | 
				
			||||||
 | 
					        label = labels[i]
 | 
				
			||||||
 | 
					      elsif is_single
 | 
				
			||||||
        label = _(label_key.to_s)
 | 
					        label = _(label_key.to_s)
 | 
				
			||||||
      elsif box.is_a?(Integer)
 | 
					      elsif box.is_a?(Integer)
 | 
				
			||||||
        label = I18n.t(label_key.to_s)[box]
 | 
					        label = I18n.t(label_key.to_s)[box]
 | 
				
			||||||
@ -1920,7 +2152,7 @@ module ApplicationHelper
 | 
				
			|||||||
          other: 2
 | 
					          other: 2
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      required_columns: [:name, :email],
 | 
					      required_columns: [:name, :email],
 | 
				
			||||||
			editable: administration_update_path(@this_conference.slug, :stats),
 | 
					      editable: administration_update_path(@this_conference.slug, @admin_step),
 | 
				
			||||||
      column_options: @column_options
 | 
					      column_options: @column_options
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@ -1954,7 +2186,7 @@ module ApplicationHelper
 | 
				
			|||||||
        User.AVAILABLE_LANGUAGES.map { |l| "language_#{l}".to_sym } +
 | 
					        User.AVAILABLE_LANGUAGES.map { |l| "language_#{l}".to_sym } +
 | 
				
			||||||
        ConferenceRegistration.all_spaces +
 | 
					        ConferenceRegistration.all_spaces +
 | 
				
			||||||
        ConferenceRegistration.all_considerations,
 | 
					        ConferenceRegistration.all_considerations,
 | 
				
			||||||
			editable: administration_update_path(@this_conference.slug, :stats),
 | 
					      editable: administration_update_path(@this_conference.slug, @admin_step),
 | 
				
			||||||
      column_options: @column_options
 | 
					      column_options: @column_options
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										77
									
								
								app/models/city.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					require 'geocoder'
 | 
				
			||||||
 | 
					require 'geocoder/railtie'
 | 
				
			||||||
 | 
					require 'geocoder/calculations'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Geocoder::Railtie.insert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class City < ActiveRecord::Base
 | 
				
			||||||
 | 
					  geocoded_by :address
 | 
				
			||||||
 | 
					  translates :city
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  reverse_geocoded_by :latitude, :longitude, :address => :full_address
 | 
				
			||||||
 | 
					  after_validation :geocode, if: ->(obj){ obj.country_changed? or obj.territory_changed? or obj.city_changed? or obj.latitude.blank? or obj.longitude.blank?  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def address
 | 
				
			||||||
 | 
					    ([city!, territory, country] - [nil, '']).join(', ')
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def get_translation(locale)
 | 
				
			||||||
 | 
					    location = Geocoder.search(address, language: locale.to_s).first
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    location.data['address_components'].each do | component |
 | 
				
			||||||
 | 
					      if component['types'].first == 'locality'
 | 
				
			||||||
 | 
					        return component['short_name']
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return nil
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def translate_city(locale)
 | 
				
			||||||
 | 
					    translation = get_translation(locale)
 | 
				
			||||||
 | 
					    set_column_for_locale(:city, locale, translation)
 | 
				
			||||||
 | 
					    save!
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return translation
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def self.search(str)
 | 
				
			||||||
 | 
					    cache = CityCache.search(str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # return the city if this search is in our cache
 | 
				
			||||||
 | 
					    return cache.city if cache.present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # look up the city in the geocoder
 | 
				
			||||||
 | 
					    location = Geocoder.search(str, language: 'en').first
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # see if the city is already present in our database
 | 
				
			||||||
 | 
					    city = City.find_by_place_id(location.data['place_id'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # return the city if we found it in the db already
 | 
				
			||||||
 | 
					    return city if city.present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # otherwise build a new city
 | 
				
			||||||
 | 
					    component_alises = {
 | 
				
			||||||
 | 
					      'locality' => :city,
 | 
				
			||||||
 | 
					      'administrative_area_level_1' => :territory,
 | 
				
			||||||
 | 
					      'country' => :country
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    city_data = {
 | 
				
			||||||
 | 
					      locale: :en,
 | 
				
			||||||
 | 
					      latitude: location.data['geometry']['location']['lat'],
 | 
				
			||||||
 | 
					      longitude: location.data['geometry']['location']['lng'],
 | 
				
			||||||
 | 
					      place_id: location.data['place_id']
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    location.data['address_components'].each do | component |
 | 
				
			||||||
 | 
					      property = component_alises[component['types'].first]
 | 
				
			||||||
 | 
					      city_data[property] = component['short_name'] if property.present?
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # save the new city
 | 
				
			||||||
 | 
					    city = City.new(city_data)
 | 
				
			||||||
 | 
					    city.save!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # and return it
 | 
				
			||||||
 | 
					    return city
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										9
									
								
								app/models/city_cache.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					class CityCache < ActiveRecord::Base
 | 
				
			||||||
 | 
					  self.table_name = :city_cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  belongs_to :city
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def self.search(str)
 | 
				
			||||||
 | 
					    CityCache.find_by_search(str.downcase)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@ -5,27 +5,47 @@ class Conference < ActiveRecord::Base
 | 
				
			|||||||
  mount_uploader :poster, PosterUploader
 | 
					  mount_uploader :poster, PosterUploader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  belongs_to :conference_type
 | 
					  belongs_to :conference_type
 | 
				
			||||||
 | 
					  belongs_to :city
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	has_many :conference_host_organizations, :dependent => :destroy
 | 
					  has_many :conference_host_organizations, dependent: :destroy
 | 
				
			||||||
	has_many :organizations, :through => :conference_host_organizations
 | 
					  has_many :organizations, through: :conference_host_organizations
 | 
				
			||||||
 | 
					  has_many :conference_administrators, dependent: :destroy
 | 
				
			||||||
 | 
					  has_many :administrators, through: :conference_administrators, source: :user
 | 
				
			||||||
  has_many :event_locations
 | 
					  has_many :event_locations
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
	#has_many :conference_registration_form_fields, :order => 'position ASC', :dependent => :destroy#, :class_name => '::ConferenceRegistrationFormField'
 | 
					 | 
				
			||||||
	#has_many :registration_form_fields, :through => :conference_registration_form_fields
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  has_many :workshops
 | 
					  has_many :workshops
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	accepts_nested_attributes_for :conference_host_organizations, :reject_if => proc {|u| u[:organization_id].blank?}, :allow_destroy => true
 | 
					  accepts_nested_attributes_for :conference_host_organizations, reject_if: proc {|u| u[:organization_id].blank?}, allow_destroy: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    before_create :make_slug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def to_param
 | 
					  def to_param
 | 
				
			||||||
    slug
 | 
					    slug
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def host_organization?(org)
 | 
				
			||||||
 | 
					    return false unless org.present?
 | 
				
			||||||
 | 
					    org_id = org.is_a?(Organization) ? org.id : org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    organizations.each do |o|
 | 
				
			||||||
 | 
					      return true if o.id = org_id
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return false
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def host?(user)
 | 
					  def host?(user)
 | 
				
			||||||
		return false unless user.present?
 | 
					    if user.present?
 | 
				
			||||||
 | 
					      return true if user.administrator?
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      conference_administrators.each do |u|
 | 
				
			||||||
 | 
					        return true if user.id == u.id
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
      organizations.each do |o|
 | 
					      organizations.each do |o|
 | 
				
			||||||
        return true if o.host?(user)
 | 
					        return true if o.host?(user)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
    return false
 | 
					    return false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -39,6 +59,7 @@ class Conference < ActiveRecord::Base
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def location
 | 
					  def location
 | 
				
			||||||
 | 
					    return nil unless organizations.present?
 | 
				
			||||||
    organizations.first.location
 | 
					    organizations.first.location
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,8 +85,52 @@ class Conference < ActiveRecord::Base
 | 
				
			|||||||
    write_attribute :registration_status, new_registration_status.to_s
 | 
					    write_attribute :registration_status, new_registration_status.to_s
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def make_slug(reset = false)
 | 
				
			||||||
 | 
					    if reset
 | 
				
			||||||
 | 
					      self.slug = nil
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self.slug ||= Conference.generate_slug(
 | 
				
			||||||
 | 
					        conferencetype || :annual,
 | 
				
			||||||
 | 
					        conference_year,
 | 
				
			||||||
 | 
					        city_name.gsub(/\s/, '')
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def city_name
 | 
				
			||||||
 | 
					    return city.city if city.present?
 | 
				
			||||||
 | 
					    return location.present? ? location.city : nil
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def conference_year
 | 
				
			||||||
 | 
					    self.year || (end_date.present? ? end_date.year : nil)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def over?
 | 
				
			||||||
 | 
					    return false unless end_date.present?
 | 
				
			||||||
 | 
					    return end_date < DateTime.now
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.default_payment_amounts
 | 
					  def self.default_payment_amounts
 | 
				
			||||||
    [25, 50, 100]
 | 
					    [25, 50, 100]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def self.conference_types
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      annual: '%{city}%{year}',
 | 
				
			||||||
 | 
					      n:      'North%{year}',
 | 
				
			||||||
 | 
					      s:      'South%{year}',
 | 
				
			||||||
 | 
					      e:      'East%{year}',
 | 
				
			||||||
 | 
					      w:      'West%{year}',
 | 
				
			||||||
 | 
					      ne:     'Northeast%{year}',
 | 
				
			||||||
 | 
					      nw:     'Northwest%{year}',
 | 
				
			||||||
 | 
					      se:     'Southeast%{year}',
 | 
				
			||||||
 | 
					      sw:     'Southwest%{year}'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def self.generate_slug(type, year, city)
 | 
				
			||||||
 | 
					    Conference.conference_types[(type || :annual).to_sym].gsub('%{city}', city).gsub('%{year}', year.to_s)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								app/models/conference_administrator.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					class ConferenceAdministrator < ActiveRecord::Base
 | 
				
			||||||
 | 
					  belongs_to :user
 | 
				
			||||||
 | 
					  belongs_to :conference
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@ -30,7 +30,7 @@ class ConferenceRegistration < ActiveRecord::Base
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def status(was = false)
 | 
					  def status(was = false)
 | 
				
			||||||
		return :unregistered if user.firstname.blank? || self.send(was ? :city_was : :city).blank?
 | 
					    return :unregistered if user.nil? || user.firstname.blank? || self.send(was ? :city_was : :city).blank?
 | 
				
			||||||
    return :registered if self.send(was ? :housing_was : :housing).present? || (self.send(was ? :can_provide_housing_was : :can_provide_housing) && (self.send(was ? :housing_data_was : :housing_data) || {})['availability'].present?)
 | 
					    return :registered if self.send(was ? :housing_was : :housing).present? || (self.send(was ? :can_provide_housing_was : :can_provide_housing) && (self.send(was ? :housing_data_was : :housing_data) || {})['availability'].present?)
 | 
				
			||||||
    return :preregistered
 | 
					    return :preregistered
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
				
			|||||||
@ -4,10 +4,10 @@ class Organization < ActiveRecord::Base
 | 
				
			|||||||
  mount_uploader :cover, CoverUploader
 | 
					  mount_uploader :cover, CoverUploader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  has_many :locations_organization
 | 
					  has_many :locations_organization
 | 
				
			||||||
	has_many :locations, :through => :locations_organization
 | 
					  has_many :locations, through: :locations_organization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	has_many :user_organization_relationships, :dependent => :destroy
 | 
					  has_many :user_organization_relationships, dependent: :destroy
 | 
				
			||||||
	has_many :users, :through => :user_organization_relationships
 | 
					  has_many :users, through: :user_organization_relationships
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  accepts_nested_attributes_for :locations, :reject_if => proc {|l| l[id].blank?}
 | 
					  accepts_nested_attributes_for :locations, :reject_if => proc {|l| l[id].blank?}
 | 
				
			||||||
  accepts_nested_attributes_for :user_organization_relationships, :reject_if => proc {|u| u[:user_id].blank?}, :allow_destroy => true
 | 
					  accepts_nested_attributes_for :user_organization_relationships, :reject_if => proc {|u| u[:user_id].blank?}, :allow_destroy => true
 | 
				
			||||||
@ -62,6 +62,12 @@ class Organization < ActiveRecord::Base
 | 
				
			|||||||
    s
 | 
					    s
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def self.find_by_city(city)
 | 
				
			||||||
 | 
					    Organization.joins(:locations).where(locations: {
 | 
				
			||||||
 | 
					        city_id: city.is_a?(City) ? city.id : city
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
    def make_slug
 | 
					    def make_slug
 | 
				
			||||||
      if !self.slug
 | 
					      if !self.slug
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ class User < ActiveRecord::Base
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  has_many :user_organization_relationships
 | 
					  has_many :user_organization_relationships
 | 
				
			||||||
  has_many :organizations, through: :user_organization_relationships
 | 
					  has_many :organizations, through: :user_organization_relationships
 | 
				
			||||||
 | 
					  has_many :conferences, through: :conference_administrators
 | 
				
			||||||
  has_many :authentications, :dependent => :destroy
 | 
					  has_many :authentications, :dependent => :destroy
 | 
				
			||||||
  accepts_nested_attributes_for :authentications
 | 
					  accepts_nested_attributes_for :authentications
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,4 +60,8 @@ class User < ActiveRecord::Base
 | 
				
			|||||||
    return user
 | 
					    return user
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def self.find_user(email)
 | 
				
			||||||
 | 
					    User.where('lower(email) = ?', email.downcase).first
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -25,13 +25,13 @@ class AvatarUploader < CarrierWave::Uploader::Base
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Provide a default URL as a default if there hasn't been a file uploaded:
 | 
					  # Provide a default URL as a default if there hasn't been a file uploaded:
 | 
				
			||||||
	def default_url
 | 
					  # def default_url
 | 
				
			||||||
  #  # For Rails 3.1+ asset pipeline compatibility:
 | 
					  #  # For Rails 3.1+ asset pipeline compatibility:
 | 
				
			||||||
  #  # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
 | 
					  #  # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
 | 
				
			||||||
  #
 | 
					  #
 | 
				
			||||||
    #"/images/fallback/" + [version_name, "default.png"].compact.join('_')
 | 
					    #"/images/fallback/" + [version_name, "default.png"].compact.join('_')
 | 
				
			||||||
		"http://placehold.it/" + (@@sizes[version_name] || [300, 300]).join('x')
 | 
					  # "http://placehold.it/" + (@@sizes[version_name] || [300, 300]).join('x')
 | 
				
			||||||
	end
 | 
					  #end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Process files as they are uploaded:
 | 
					  # Process files as they are uploaded:
 | 
				
			||||||
  # process :scale => [200, 300]
 | 
					  # process :scale => [200, 300]
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										24
									
								
								app/views/admin/new.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					- body_class 'banner-bottom'
 | 
				
			||||||
 | 
					= render :partial => 'application/header', :locals  => {:page_group => :administration, :page_key => 'Administration', :image_file => 'admin.jpg'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%article
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = form_tag save_conference_path, class: 'composition' do
 | 
				
			||||||
 | 
					      = columns(medium: 12) do
 | 
				
			||||||
 | 
					        %h2=_@page_title, :t
 | 
				
			||||||
 | 
					        = hidden_field_tag :id, @this_conference.id if @this_conference.id.present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      = columns(medium: 12) do
 | 
				
			||||||
 | 
					        = textfield :city, location(@this_conference.city), required: true, big: true
 | 
				
			||||||
 | 
					      = columns(medium: 12, class: 'flex-column') do
 | 
				
			||||||
 | 
					        = selectfield :type, @this_conference.conferencetype, Conference.conference_types.keys.map { |k| [(_"forms.options.conferences.types.#{k}"), k]}, required: true, stretch: true
 | 
				
			||||||
 | 
					        = numberfield :year, @this_conference.conference_year || Date.today.year, required: true
 | 
				
			||||||
 | 
					      = columns(medium: 6) do
 | 
				
			||||||
 | 
					        = checkbox :is_public, @this_conference.is_public != false, 'forms.labels.generic.is_public'
 | 
				
			||||||
 | 
					      = columns(medium: 6) do
 | 
				
			||||||
 | 
					        = checkbox :is_featured, @this_conference.is_featured != false, 'forms.labels.generic.is_featured'
 | 
				
			||||||
 | 
					      = columns(medium: 12) do
 | 
				
			||||||
 | 
					        .actions.next-prev
 | 
				
			||||||
 | 
					          = button_tag :save, value: :save
 | 
				
			||||||
 | 
					          - if @this_conference.id.present?
 | 
				
			||||||
 | 
					            = button_with_confirmation :delete, value: :delete, class: 'delete'
 | 
				
			||||||
@ -12,9 +12,9 @@
 | 
				
			|||||||
    = cover.html_safe if cover
 | 
					    = cover.html_safe if cover
 | 
				
			||||||
    - if @page_title.present? || defined?(page_group)
 | 
					    - if @page_title.present? || defined?(page_group)
 | 
				
			||||||
      - content_for :title do
 | 
					      - content_for :title do
 | 
				
			||||||
				=@page_title.present? ? I18n.t(@page_title, @page_title_vars) : I18n.t("page_titles.#{page_group.to_s}.#{page_key.to_s}")
 | 
					        = I18n.t(@page_title || "page_titles.#{page_group.to_s}.#{page_key.to_s}", @page_title_vars)
 | 
				
			||||||
      = row do
 | 
					      = row do
 | 
				
			||||||
        = columns do
 | 
					        = columns do
 | 
				
			||||||
					%h1=_(@main_title || "page_titles.#{page_group.to_s}.#{page_key.to_s}", :t, @main_title_vars)
 | 
					          %h1=_(@main_title || "page_titles.#{page_group.to_s}.#{page_key.to_s}", :t, @main_title_vars || (@page_title_vars.present? && @page_title.blank? ? { vars: @page_title_vars } : nil))
 | 
				
			||||||
  - content_for :og_image do
 | 
					  - content_for :og_image do
 | 
				
			||||||
    = image
 | 
					    = image
 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +1,5 @@
 | 
				
			|||||||
- this_is_the_front_page
 | 
					- content_for :og_image do
 | 
				
			||||||
- if @conference
 | 
					  = @conference.poster.full.url || image_path('default_poster.jpg')
 | 
				
			||||||
	= render 'conferences/header'
 | 
					- if @conferences
 | 
				
			||||||
	%article
 | 
					  - @conferences.each do | conference |
 | 
				
			||||||
		= row do
 | 
					    = render 'conferences/conference', conference: conference, links: [ :read_more, :register ]
 | 
				
			||||||
			= columns(medium: 10, push: {medium: 1}) do
 | 
					 | 
				
			||||||
				%h2=_!@conference.title
 | 
					 | 
				
			||||||
				= richtext @conference.info
 | 
					 | 
				
			||||||
				- if @conference.registration_status == :open
 | 
					 | 
				
			||||||
					- if @conference.workshop_schedule_published
 | 
					 | 
				
			||||||
						- add_inline_script :home_schedule
 | 
					 | 
				
			||||||
						%h3=_'articles.workshops.headings.Schedule'
 | 
					 | 
				
			||||||
						= render 'conferences/admin/schedule'
 | 
					 | 
				
			||||||
					- else
 | 
					 | 
				
			||||||
						%h3=_'articles.workshops.headings.Proposed_Workshops'
 | 
					 | 
				
			||||||
						%p=_'articles.workshops.paragraphs.Proposed_Workshops'
 | 
					 | 
				
			||||||
						= render 'workshops/workshop_previews', :workshops => (@conference.workshops.sort { |a, b| a.title.downcase <=> b.title.downcase })
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					= columns(large: 8, push: { large: 2}) do
 | 
				
			||||||
 | 
					  %h3=_'articles.admin.info.headings.Host_Organizations'
 | 
				
			||||||
 | 
					  %p=_'articles.admin.info.descriptions.Host_Organizations', vars: { city_name: @this_conference.city.city }
 | 
				
			||||||
 | 
					  = admin_update_form do
 | 
				
			||||||
 | 
					    = checkboxes :organizations, (@organizations.map { |org| [org.name, org.id] }), @this_conference.organizations.map(&:id), 'test.test', vertical: true, big: true
 | 
				
			||||||
 | 
					    .actions.right.small
 | 
				
			||||||
 | 
					      = button_tag :save, value: :set_organizations
 | 
				
			||||||
 | 
					  - @this_conference.organizations.each do | organization |
 | 
				
			||||||
 | 
					    %h4=organization.name
 | 
				
			||||||
 | 
					    - if organization.users.present?
 | 
				
			||||||
 | 
					      .details.org-members
 | 
				
			||||||
 | 
					        - organization.users.each do | user |
 | 
				
			||||||
 | 
					          = raw_data_set(:h5, user.name) do
 | 
				
			||||||
 | 
					            = user.email
 | 
				
			||||||
 | 
					            - unless user.id == current_user.id && !current_user.administrator?
 | 
				
			||||||
 | 
					              = admin_update_form class: [:inline, :right] do
 | 
				
			||||||
 | 
					                = hidden_field_tag :user_id, user.id
 | 
				
			||||||
 | 
					                = hidden_field_tag :org_id, organization.id
 | 
				
			||||||
 | 
					                = button_tag :remove_member, value: :remove_org_member, class: [:small, :delete]
 | 
				
			||||||
 | 
					    = admin_update_form class: 'mini-flex-form' do
 | 
				
			||||||
 | 
					      = hidden_field_tag :org_id, organization.id
 | 
				
			||||||
 | 
					      = emailfield :email, nil, required: true
 | 
				
			||||||
 | 
					      = button_tag :add_member, value: :add_org_member, class: :small
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  %h3=_'articles.admin.info.headings.External_Administrators'
 | 
				
			||||||
 | 
					  %p=_'articles.admin.info.descriptions.External_Administrators'
 | 
				
			||||||
 | 
					  - if @this_conference.administrators.present?
 | 
				
			||||||
 | 
					    .details.org-members
 | 
				
			||||||
 | 
					      - @this_conference.administrators.each do | user |
 | 
				
			||||||
 | 
					        = raw_data_set(:h5, user.name) do
 | 
				
			||||||
 | 
					          = user.email
 | 
				
			||||||
 | 
					          - unless user.id == current_user.id && !current_user.administrator?
 | 
				
			||||||
 | 
					            = admin_update_form class: [:inline, :right] do
 | 
				
			||||||
 | 
					              = hidden_field_tag :user_id, user.id
 | 
				
			||||||
 | 
					              = button_tag :remove_member, value: :remove_administrator, class: [:small, :delete]
 | 
				
			||||||
 | 
					  = admin_update_form class: 'mini-flex-form' do
 | 
				
			||||||
 | 
					    = userfield :email, nil, required: true
 | 
				
			||||||
 | 
					    -#= emailfield :email, nil, required: true
 | 
				
			||||||
 | 
					    = button_tag :add_member, value: :add_administrator, class: :small
 | 
				
			||||||
 | 
					= columns(large: 2) do
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
							
								
								
									
										23
									
								
								app/views/conference_administration/_broadcast.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = admin_update_form do
 | 
				
			||||||
 | 
					    - if @broadcast_step == :preview || @broadcast_step == :test
 | 
				
			||||||
 | 
					      = hidden_field_tag :subject, @subject
 | 
				
			||||||
 | 
					      = hidden_field_tag :body, @body
 | 
				
			||||||
 | 
					      = hidden_field_tag :send_to, @send_to
 | 
				
			||||||
 | 
					      - if @broadcast_step == :preview
 | 
				
			||||||
 | 
					        %p= _'articles.conference_registration.paragraphs.admin.broadcast.test', vars: { send_to_count: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }
 | 
				
			||||||
 | 
					      - else
 | 
				
			||||||
 | 
					        .warning-info.make-room= _'articles.conference_registration.paragraphs.admin.broadcast.preview', vars: { send_to_count: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }
 | 
				
			||||||
 | 
					      .test-preview
 | 
				
			||||||
 | 
					        %h3=@subject
 | 
				
			||||||
 | 
					        = richtext @body, 4
 | 
				
			||||||
 | 
					      .actions.right
 | 
				
			||||||
 | 
					        = button_tag :test, value: :test, class: :secondary if @broadcast_step == :preview
 | 
				
			||||||
 | 
					        = button_with_confirmation :send, (_'modals.admin.broadcast.confirm', vars: { number: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }), value: :send, class: :delete if @broadcast_step == :test
 | 
				
			||||||
 | 
					        = button_tag :edit, value: :edit
 | 
				
			||||||
 | 
					    - else
 | 
				
			||||||
 | 
					      = selectfield :send_to, nil, broadcast_options, full: true
 | 
				
			||||||
 | 
					      = textfield :subject, @subject, required: true, big: true
 | 
				
			||||||
 | 
					      = textarea :body, @body, lang: @this_conference.locale, edit_on: :focus
 | 
				
			||||||
 | 
					      .actions.right
 | 
				
			||||||
 | 
					        = button_tag :preview, value: :preview
 | 
				
			||||||
							
								
								
									
										17
									
								
								app/views/conference_administration/_dates.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					= admin_update_form do
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = columns(medium: 6, push: { medium: 1 }) do
 | 
				
			||||||
 | 
					      = fieldset :start_date, inline: true, inline_label: true do
 | 
				
			||||||
 | 
					        = month_select @start_month, name: :start_month, label: false
 | 
				
			||||||
 | 
					        = month_day_select @start_day, name: :start_day, label: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = columns(medium: 6, push: { medium: 1 }) do
 | 
				
			||||||
 | 
					      = fieldset :end_date, inline: true, inline_label: true do
 | 
				
			||||||
 | 
					        = month_select @end_month, name: :end_month, label: false
 | 
				
			||||||
 | 
					        = month_day_select @end_day, name: :end_day, label: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = columns(medium: 6, push: { medium: 1 }) do
 | 
				
			||||||
 | 
					      .actions
 | 
				
			||||||
 | 
					        = button_tag :save, value: :save
 | 
				
			||||||
@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = admin_update_form do
 | 
				
			||||||
 | 
					    = translate_textarea :info, @this_conference, label: 'articles.conference_registration.headings.admin.edit.info', help: 'articles.conference_registration.paragraphs.admin.edit.info', edit_on: :focus
 | 
				
			||||||
 | 
					    .actions.right
 | 
				
			||||||
 | 
					      = button_tag :save, value: :save
 | 
				
			||||||
							
								
								
									
										41
									
								
								app/views/conference_administration/_events.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					- if @this_conference.event_locations.blank?
 | 
				
			||||||
 | 
					  = columns(medium: 12) do
 | 
				
			||||||
 | 
					    .warning-info=_'articles.admin.events.no_locations_warning'
 | 
				
			||||||
 | 
					- else
 | 
				
			||||||
 | 
					  = columns(medium: 12) do
 | 
				
			||||||
 | 
					    - if @events.present? && @event.id.blank?
 | 
				
			||||||
 | 
					      %table.events.admin-edit
 | 
				
			||||||
 | 
					        %tr
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.title'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.event_location'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.day'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.time'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.time_span'
 | 
				
			||||||
 | 
					          %th.form
 | 
				
			||||||
 | 
					        - @events.each do | event |
 | 
				
			||||||
 | 
					          %tr
 | 
				
			||||||
 | 
					            %th=event.title
 | 
				
			||||||
 | 
					            %td=_!(event.event_location.present? ? event.event_location.title : '')
 | 
				
			||||||
 | 
					            %td=date(event.start_time.to_date, :weekday)
 | 
				
			||||||
 | 
					            %td=time(event.start_time, :short)
 | 
				
			||||||
 | 
					            %td=hours(event.start_time, event.end_time)
 | 
				
			||||||
 | 
					            %td.form
 | 
				
			||||||
 | 
					              = admin_update_form do
 | 
				
			||||||
 | 
					                = hidden_field_tag :id, event.id
 | 
				
			||||||
 | 
					                = link_to (_'forms.actions.generic.edit'), edit_event_path(@this_conference, event.id), class: [:button, :small, :modify]
 | 
				
			||||||
 | 
					                = button_with_confirmation :delete, (_'modals.admin.generic.delete.confirm', :p, vars: { title: event.title }), value: :delete, class: [:delete, :small]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  = columns(medium: 12) do
 | 
				
			||||||
 | 
					    %h3=_"articles.admin.locations.headings.#{@event.id.present? ? 'edit' : 'add'}_event", :t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    = admin_update_form do
 | 
				
			||||||
 | 
					      = hidden_field_tag :id, @event.id if @event.id.present?
 | 
				
			||||||
 | 
					      .flex-inputs
 | 
				
			||||||
 | 
					        = location_select @event.event_location_id, small: true, stretch: true
 | 
				
			||||||
 | 
					        = day_select @day, small: true, format: :weekday
 | 
				
			||||||
 | 
					        = hour_select @time, small: true
 | 
				
			||||||
 | 
					        = length_select @length, small: true
 | 
				
			||||||
 | 
					      = translate_fields @event, { title: { type: :textfield, big: true, label: 'forms.labels.generic.title' }, info: { type: :textarea, label: 'forms.labels.generic.info', edit_on: :focus } }
 | 
				
			||||||
 | 
					      .actions.next-prev
 | 
				
			||||||
 | 
					        = button_tag :save, value: :save
 | 
				
			||||||
 | 
					        = button_tag :cancel, value: :cancel, class: :subdued, formnovalidate: true if @event.id.present?
 | 
				
			||||||
							
								
								
									
										11
									
								
								app/views/conference_administration/_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)
 | 
				
			||||||
							
								
								
									
										10
									
								
								app/views/conference_administration/_housing.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					- add_inline_script :housing
 | 
				
			||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = admin_update_form id: 'housing-table-form' do
 | 
				
			||||||
 | 
					    #housing-table= render partial: 'hosts_table'
 | 
				
			||||||
 | 
					  #guest-selector
 | 
				
			||||||
 | 
					    = admin_update_form 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, @admin_step, :format => :xlsx), class: [:button, :download]
 | 
				
			||||||
							
								
								
									
										42
									
								
								app/views/conference_administration/_locations.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					- unless @location.present?
 | 
				
			||||||
 | 
					  - if @locations.present?
 | 
				
			||||||
 | 
					    = columns(medium: 12) do
 | 
				
			||||||
 | 
					      %table.locations.admin-edit
 | 
				
			||||||
 | 
					        %tr
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.title'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.address'
 | 
				
			||||||
 | 
					          %th=_'articles.workshops.headings.space'
 | 
				
			||||||
 | 
					          %th=_'articles.admin.locations.headings.amenities'
 | 
				
			||||||
 | 
					          %th.form
 | 
				
			||||||
 | 
					        - @locations.each do | location |
 | 
				
			||||||
 | 
					          %tr
 | 
				
			||||||
 | 
					            %th=_!(location.title || '')
 | 
				
			||||||
 | 
					            %td=location_link location
 | 
				
			||||||
 | 
					            %td=location.space.present? ? (_"workshop.options.space.#{location.space}") : ''
 | 
				
			||||||
 | 
					            %td
 | 
				
			||||||
 | 
					              - amenities = location.amenities.present? ? JSON.parse(location.amenities) : []
 | 
				
			||||||
 | 
					              =_!(amenities.collect { |amenity| _"workshop.options.needs.#{amenity}" }).join(', ')
 | 
				
			||||||
 | 
					            %td.form
 | 
				
			||||||
 | 
					              = admin_update_form do
 | 
				
			||||||
 | 
					                = hidden_field_tag :id, location.id
 | 
				
			||||||
 | 
					                = link_to (_'forms.actions.generic.edit'), edit_location_path(@this_conference, location.id), class: [:button, :small, :modify]
 | 
				
			||||||
 | 
					                = button_with_confirmation :delete, (_'modals.admin.generic.delete.confirm', :p, vars: { title: location.title }), value: :delete, class: [:delete, :small]
 | 
				
			||||||
 | 
					= admin_update_form do
 | 
				
			||||||
 | 
					  = columns(medium: 12) do
 | 
				
			||||||
 | 
					    %h5=_"articles.admin.locations.headings.#{@location.present? ? 'edit' : 'add'}_location", :t
 | 
				
			||||||
 | 
					    = hidden_field_tag :id, @location.id if @location.present?
 | 
				
			||||||
 | 
					    = textfield :title, @location.present? ? @location.title : nil, required: true, big: true, help: 'articles.admin.locations.paragraphs.title'
 | 
				
			||||||
 | 
					    .flex-column.address-form
 | 
				
			||||||
 | 
					      = textfield :address, @location.present? ? @location.address : nil, required: true, help: 'articles.admin.locations.paragraphs.address', stretch: true
 | 
				
			||||||
 | 
					      .city=location(@this_conference.city)
 | 
				
			||||||
 | 
					  = columns(medium: 6) do
 | 
				
			||||||
 | 
					    = radiobuttons :space, EventLocation.all_spaces, @space, 'workshop.options.space', vertical: true, heading: 'articles.workshops.headings.space', required: true, help: 'articles.admin.locations.paragraphs.space'
 | 
				
			||||||
 | 
					  = columns(medium: 6) do
 | 
				
			||||||
 | 
					    = checkboxes :needs, EventLocation.all_amenities, @amenities || [], 'workshop.options.needs', vertical: true, heading: 'articles.admin.locations.headings.amenities', help: 'articles.admin.locations.paragraphs.amenities'
 | 
				
			||||||
 | 
					  = columns(medium: 12) do
 | 
				
			||||||
 | 
					    .actions.next-prev
 | 
				
			||||||
 | 
					      - if @location.present?
 | 
				
			||||||
 | 
					        = button_tag :save, value: :save
 | 
				
			||||||
 | 
					        = button_tag :cancel, value: :cancel, class: :subdued, formnovalidate: true
 | 
				
			||||||
 | 
					      - else
 | 
				
			||||||
 | 
					        = button_tag :create, value: :create
 | 
				
			||||||
							
								
								
									
										35
									
								
								app/views/conference_administration/_meals.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  - if @this_conference.event_locations.present?
 | 
				
			||||||
 | 
					    - if @this_conference.meals.present?
 | 
				
			||||||
 | 
					      %table.meals.admin-edit
 | 
				
			||||||
 | 
					        %tr
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.title'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.info'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.event_location'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.day'
 | 
				
			||||||
 | 
					          %th=_'forms.labels.generic.time'
 | 
				
			||||||
 | 
					          %th.form
 | 
				
			||||||
 | 
					        - @meals.each do | time, meal |
 | 
				
			||||||
 | 
					          %tr
 | 
				
			||||||
 | 
					            %th
 | 
				
			||||||
 | 
					              =_!(meal['title'] || '')
 | 
				
			||||||
 | 
					            %td=_!(meal['info'] || '')
 | 
				
			||||||
 | 
					            %td=_!location_name(meal['location'].to_i)
 | 
				
			||||||
 | 
					            %td=date(meal['day'], :weekday)
 | 
				
			||||||
 | 
					            %td=time(meal['time'].to_f)
 | 
				
			||||||
 | 
					            %td.form
 | 
				
			||||||
 | 
					              = admin_update_form do
 | 
				
			||||||
 | 
					                = hidden_field_tag :meal, time
 | 
				
			||||||
 | 
					                = button_tag :delete, value: :delete, class: [:small, :delete]
 | 
				
			||||||
 | 
					    = admin_update_form do
 | 
				
			||||||
 | 
					      %h3=_'articles.admin.locations.headings.add_meal', :t
 | 
				
			||||||
 | 
					      .flex-inputs
 | 
				
			||||||
 | 
					        = location_select nil, small: true, stretch: true
 | 
				
			||||||
 | 
					        = day_select nil, small: true, format: :weekday
 | 
				
			||||||
 | 
					        = hour_select nil, small: true
 | 
				
			||||||
 | 
					      = textfield :title, nil, required: true, big: true, help: 'articles.admin.locations.paragraphs.meal_title'
 | 
				
			||||||
 | 
					      = textfield :info, nil, help: 'articles.admin.locations.paragraphs.meal_info'
 | 
				
			||||||
 | 
					      .actions.next-prev
 | 
				
			||||||
 | 
					        = button_tag :add_meal, value: :add_meal
 | 
				
			||||||
 | 
					  - else
 | 
				
			||||||
 | 
					    .warning-info=_'articles.admin.meals.no_locations_warning'
 | 
				
			||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = form_tag administration_update_path(@this_conference.slug, @admin_step) do
 | 
				
			||||||
 | 
					    = translate_textarea :payment_message, @this_conference, default: 'articles.conference_registration.paragraphs.Payment', help: 'articles.conference_registration.paragraphs.admin.payment.message', edit_on: :focus, short: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .actions.right
 | 
				
			||||||
 | 
					      = button_tag :save, value: :save
 | 
				
			||||||
							
								
								
									
										8
									
								
								app/views/conference_administration/_paypal.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = form_tag administration_update_path(@this_conference.slug, @admin_step) do
 | 
				
			||||||
 | 
					    = emailfield :paypal_email_address, @this_conference.paypal_email_address || @this_conference.email_address || (@this_conference.organizations.present? && @this_conference.organizations.first.present? ? @this_conference.organizations.first.email_address : nil)
 | 
				
			||||||
 | 
					    = textfield :paypal_username, @this_conference.paypal_username
 | 
				
			||||||
 | 
					    = passwordfield :paypal_password, @this_conference.paypal_password
 | 
				
			||||||
 | 
					    = textfield :paypal_signature, @this_conference.paypal_signature
 | 
				
			||||||
 | 
					    .actions.right
 | 
				
			||||||
 | 
					      = button_tag :save, value: :save
 | 
				
			||||||
							
								
								
									
										5
									
								
								app/views/conference_administration/_poster.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = form_tag administration_update_path(@this_conference.slug, :poster), multipart: true do
 | 
				
			||||||
 | 
					    = filefield :poster, @this_conference.poster, required: true, label: false, preview: true
 | 
				
			||||||
 | 
					    .actions.left
 | 
				
			||||||
 | 
					      = button_tag :upload, value: :upload, id: 'upload-file'
 | 
				
			||||||
							
								
								
									
										2
									
								
								app/views/conference_administration/_providers.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  TO COME
 | 
				
			||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = form_tag administration_update_path(@this_conference.slug, @admin_step) do
 | 
				
			||||||
 | 
					    - if @this_conference.workshop_schedule_published
 | 
				
			||||||
 | 
					      %p=_'articles.conference_registration.paragraphs.admin.schedule.published', :p
 | 
				
			||||||
 | 
					      .actions= button_tag :un_publish, value: :publish, class: :delete
 | 
				
			||||||
 | 
					    - else
 | 
				
			||||||
 | 
					      %p=_'articles.conference_registration.paragraphs.admin.schedule.un_published', :p
 | 
				
			||||||
 | 
					      .actions= button_tag :publish, value: :publish
 | 
				
			||||||
@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = form_tag administration_update_path(@this_conference.slug, @admin_step) do
 | 
				
			||||||
 | 
					    = selectfield :registration_status, @this_conference.registration_status || 'closed', registration_status_options_list, inline_label: true
 | 
				
			||||||
 | 
					    .actions.left
 | 
				
			||||||
 | 
					      = button_tag :save, value: :save
 | 
				
			||||||
							
								
								
									
										17
									
								
								app/views/conference_administration/_registrations.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					- add_inline_script :registrations
 | 
				
			||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  .goes-fullscreen#registrations-table
 | 
				
			||||||
 | 
					    .flex-column
 | 
				
			||||||
 | 
					      = searchfield :search, nil, big: true, stretch: true
 | 
				
			||||||
 | 
					      %a.button{data: { expands: 'registrations-table' }}='expand'
 | 
				
			||||||
 | 
					      %a.button.delete{data: { contracts: 'registrations-table' }}='close'
 | 
				
			||||||
 | 
					      %a.button.modify{data: { 'opens-modal': 'new-registration' }}='+'
 | 
				
			||||||
 | 
					    .table-scroller
 | 
				
			||||||
 | 
					      = html_table @excel_data, registrations_table_options
 | 
				
			||||||
 | 
					    = admin_update_form id: 'new-registration', class: 'modal-edit' do
 | 
				
			||||||
 | 
					      .modal-edit-overlay{data: { 'closes-modal': 'new-registration' }}
 | 
				
			||||||
 | 
					      .modal-edit-content
 | 
				
			||||||
 | 
					        = html_edit_table @excel_data, registrations_edit_table_options
 | 
				
			||||||
 | 
					        .actions.right
 | 
				
			||||||
 | 
					          %a.button.subdued{data: { 'closes-modal': 'new-registration' }}='Cancel'
 | 
				
			||||||
 | 
					          = button_tag :save, value: :save, class: :modify
 | 
				
			||||||
							
								
								
									
										85
									
								
								app/views/conference_administration/_schedule.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  - conference = @this_conference || @conference
 | 
				
			||||||
 | 
					  - if conference.event_locations.blank? && @entire_page
 | 
				
			||||||
 | 
					    .warning-info=_'articles.admin.schedule.no_locations_warning'
 | 
				
			||||||
 | 
					  - else
 | 
				
			||||||
 | 
					    - add_inline_script :schedule if @entire_page
 | 
				
			||||||
 | 
					    #schedule-preview
 | 
				
			||||||
 | 
					      - @schedule.each do | day, data |
 | 
				
			||||||
 | 
					        %h4=date(day, :weekday)
 | 
				
			||||||
 | 
					        %table.schedule{class: [data[:locations].present? ? 'has-locations' : 'no-locations', "locations-#{data[:num_locations]}"]}
 | 
				
			||||||
 | 
					          - if data[:locations].present? && data[:locations].values.first != :add
 | 
				
			||||||
 | 
					            %thead
 | 
				
			||||||
 | 
					              %tr
 | 
				
			||||||
 | 
					                %th.corner
 | 
				
			||||||
 | 
					                - data[:locations].each do | id, location |
 | 
				
			||||||
 | 
					                  %th=location.is_a?(Symbol) ? '' : location.title
 | 
				
			||||||
 | 
					          %tbody
 | 
				
			||||||
 | 
					            - data[:times].each do | time, time_data |
 | 
				
			||||||
 | 
					              %tr
 | 
				
			||||||
 | 
					                - rowspan = (time_data[:length] * 2).to_i
 | 
				
			||||||
 | 
					                %th=time(time)
 | 
				
			||||||
 | 
					                - if time_data[:type] == :workshop
 | 
				
			||||||
 | 
					                  - data[:locations].each do | id, location |
 | 
				
			||||||
 | 
					                    - if time_data[:item][:workshops][id].present?
 | 
				
			||||||
 | 
					                      - workshop = time_data[:item][:workshops][id][:workshop]
 | 
				
			||||||
 | 
					                      - status = time_data[:item][:workshops][id][:status]
 | 
				
			||||||
 | 
					                    - else
 | 
				
			||||||
 | 
					                      - workshop = status = nil
 | 
				
			||||||
 | 
					                    %td{class: [time_data[:type], workshop.present? ? :filled : :open], rowspan: rowspan, data: workshop.present? ? nil : { block: time_data[:item][:block], day: day, location: id }}
 | 
				
			||||||
 | 
					                      - if workshop.present? && workshop.event_location.present?
 | 
				
			||||||
 | 
					                        = link_to view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' do
 | 
				
			||||||
 | 
					                          .details
 | 
				
			||||||
 | 
					                            .title=workshop.title
 | 
				
			||||||
 | 
					                        %template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }}
 | 
				
			||||||
 | 
					                          %h1.title=workshop.title
 | 
				
			||||||
 | 
					                          %p.address
 | 
				
			||||||
 | 
					                            = workshop.event_location.title + _!(': ')
 | 
				
			||||||
 | 
					                            = location_link workshop.event_location
 | 
				
			||||||
 | 
					                          .workshop-description= richtext workshop.info, 1
 | 
				
			||||||
 | 
					                        - if @can_edit
 | 
				
			||||||
 | 
					                          = form_tag administration_update_path(conference.slug, @admin_step), class: 'deschedule-workshop' do
 | 
				
			||||||
 | 
					                            .status
 | 
				
			||||||
 | 
					                              .conflict-score
 | 
				
			||||||
 | 
					                                %span.title Conflicts: 
 | 
				
			||||||
 | 
					                                %span.value="#{status[:conflict_score]} / #{workshop.interested.size}"
 | 
				
			||||||
 | 
					                              - if status[:errors].present?
 | 
				
			||||||
 | 
					                                .errors
 | 
				
			||||||
 | 
					                                  - status[:errors].each do | error |
 | 
				
			||||||
 | 
					                                    .error=_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars]
 | 
				
			||||||
 | 
					                            = hidden_field_tag :id, workshop.id
 | 
				
			||||||
 | 
					                            = button_tag :deschedule, value: :deschedule_workshop, class: [:delete, :small]
 | 
				
			||||||
 | 
					                      - elsif @can_edit
 | 
				
			||||||
 | 
					                        .title="Block #{time_data[:item][:block] + 1}"
 | 
				
			||||||
 | 
					                - elsif time_data[:type] != :nil
 | 
				
			||||||
 | 
					                  %td{class: time_data[:type], rowspan: rowspan, colspan: data[:locations].present? ? data[:locations].size : 1}
 | 
				
			||||||
 | 
					                    - case time_data[:type]
 | 
				
			||||||
 | 
					                      - when :meal
 | 
				
			||||||
 | 
					                        - location = EventLocation.where(id: time_data[:item]['location'].to_i).first
 | 
				
			||||||
 | 
					                        - if location.present?
 | 
				
			||||||
 | 
					                          %a.event-detail-link
 | 
				
			||||||
 | 
					                            .details
 | 
				
			||||||
 | 
					                              .title= time_data[:item]['title']
 | 
				
			||||||
 | 
					                              .location= location.title
 | 
				
			||||||
 | 
					                          %template.event-details
 | 
				
			||||||
 | 
					                            %h1.title=time_data[:item]['title']
 | 
				
			||||||
 | 
					                            %p.address
 | 
				
			||||||
 | 
					                              = location.title + _!(': ')
 | 
				
			||||||
 | 
					                              = location_link location
 | 
				
			||||||
 | 
					                      - when :event
 | 
				
			||||||
 | 
					                        - if time_data[:item].event_location.present?
 | 
				
			||||||
 | 
					                          %a.event-detail-link
 | 
				
			||||||
 | 
					                            .details
 | 
				
			||||||
 | 
					                              .title= time_data[:item][:title]
 | 
				
			||||||
 | 
					                              .location= time_data[:item].event_location.title
 | 
				
			||||||
 | 
					                          %template.event-details
 | 
				
			||||||
 | 
					                            %h1.title=time_data[:item][:title]
 | 
				
			||||||
 | 
					                            %p.address
 | 
				
			||||||
 | 
					                              = time_data[:item].event_location.title + _!(': ')
 | 
				
			||||||
 | 
					                              = location_link time_data[:item].event_location
 | 
				
			||||||
 | 
					                            = richtext time_data[:item][:info], 1
 | 
				
			||||||
 | 
					    - if @entire_page
 | 
				
			||||||
 | 
					      #workshop-selector
 | 
				
			||||||
 | 
					        = form_tag administration_update_path(@this_conference.slug, @admin_step), class: 'workshop-dlg', id: 'workshop-table-form' do
 | 
				
			||||||
 | 
					          %h3 Select a Workshop
 | 
				
			||||||
 | 
					          #table
 | 
				
			||||||
@ -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= host.housing_data['availability'].present? && host.housing_data['availability'][1].present? ? 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=_'articles.conference_registration.headings.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=registration.housing.present? ? (_"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.named_email : (_"articles.conference_registration.terms.registration_status.#{companion}")) : ''
 | 
				
			||||||
 | 
					      %td=registration.food.present? ? (_"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
 | 
				
			||||||
							
								
								
									
										21
									
								
								app/views/conference_administration/_stats.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  .details
 | 
				
			||||||
 | 
					    = data_set(:h3, 'articles.admin.stats.headings.completed_registrations') do
 | 
				
			||||||
 | 
					      = (@completed_registrations || 0).to_s
 | 
				
			||||||
 | 
					    = data_set(:h3, 'articles.admin.stats.headings.incomplete_registrations') do
 | 
				
			||||||
 | 
					      = ((@registration_count - @completed_registrations) || 0).to_s
 | 
				
			||||||
 | 
					    = data_set(:h3, 'articles.admin.stats.headings.bikes') do
 | 
				
			||||||
 | 
					      = (@completed_registrations || 0) > 0 ? "#{@bikes} (#{number_to_percentage(@bikes / @completed_registrations.to_f * 100.0)})" : "0"
 | 
				
			||||||
 | 
					    = data_set(:h3, 'articles.admin.stats.headings.food.meat') do
 | 
				
			||||||
 | 
					      = (@food[:all] || 0) > 0 ? "#{@food[:meat]} (#{number_to_percentage(@food[:meat] / @food[:all].to_f * 100.0)})" : "0"
 | 
				
			||||||
 | 
					    = data_set(:h3, 'articles.admin.stats.headings.food.vegetarian') do
 | 
				
			||||||
 | 
					      = (@food[:all] || 0) > 0 ? "#{@food[:vegetarian]} (#{number_to_percentage(@food[:vegetarian] / @food[:all].to_f * 100.0)})" : "0"
 | 
				
			||||||
 | 
					    = data_set(:h3, 'articles.admin.stats.headings.food.vegan') do
 | 
				
			||||||
 | 
					      = (@food[:all] || 0) > 0 ? "#{@food[:vegan]} (#{number_to_percentage(@food[:vegan] / @food[:all].to_f * 100.0)})" : "0"
 | 
				
			||||||
 | 
					    = data_set(:h3, 'articles.admin.stats.headings.donation_count') do
 | 
				
			||||||
 | 
					      = (@completed_registrations || 0) > 0 ? "#{@donation_count} (#{number_to_percentage(@donation_count / @completed_registrations.to_f * 100.0)})" : "0"
 | 
				
			||||||
 | 
					    = data_set(:h3, 'articles.admin.stats.headings.donation_total') do
 | 
				
			||||||
 | 
					      = "$#{@donations || 0.00}"
 | 
				
			||||||
 | 
					  .actions
 | 
				
			||||||
 | 
					    = link_to (_'links.download.Excel'), administration_step_path(@this_conference.slug, :stats, :format => :xlsx), class: [:button, :download]
 | 
				
			||||||
 | 
					    = link_to (_'links.download.Organizations_Excel'), administration_step_path(@this_conference.slug, :organizations, :format => :xlsx), class: [:button, :download, :subdued]
 | 
				
			||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  = form_tag administration_update_path(@this_conference.slug, @admin_step) do
 | 
				
			||||||
 | 
					    = fieldset :payment_amounts, label: false do
 | 
				
			||||||
 | 
					      - payment_amounts = @this_conference.payment_amounts.present? ? @this_conference.payment_amounts : Conference.default_payment_amounts
 | 
				
			||||||
 | 
					      - for i in 1..5 do
 | 
				
			||||||
 | 
					        = numberfield "payment_amounts[#{i - 1}]", payment_amounts[i - 1], step: 0.01, min: 0.00, label: false
 | 
				
			||||||
 | 
					    .actions.right
 | 
				
			||||||
 | 
					      = button_tag :save, value: :save
 | 
				
			||||||
@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					= columns(medium: 12) do
 | 
				
			||||||
 | 
					  .table.workshop-blocks
 | 
				
			||||||
 | 
					    .table-tr.header
 | 
				
			||||||
 | 
					      .table-th=_'forms.labels.generic.block_number'
 | 
				
			||||||
 | 
					      .table-th=_'forms.labels.generic.time'
 | 
				
			||||||
 | 
					      .table-th=_'forms.labels.generic.length'
 | 
				
			||||||
 | 
					      .table-th=_'forms.labels.generic.days'
 | 
				
			||||||
 | 
					      .table-th.form
 | 
				
			||||||
 | 
					    - @workshop_blocks.each_with_index do | info, block |
 | 
				
			||||||
 | 
					      - is_new = info['time'].blank?
 | 
				
			||||||
 | 
					      = form_tag administration_update_path(@this_conference.slug, @admin_step), class: ['table-tr', is_new ? 'new' : 'saved'] do
 | 
				
			||||||
 | 
					        .table-th.center.big= is_new ? '' : (block + 1)
 | 
				
			||||||
 | 
					        .table-td=hour_select info['time'], small: true, label: false
 | 
				
			||||||
 | 
					        .table-td=length_select info['length'], {small: true, label: false}, 0.5, 2
 | 
				
			||||||
 | 
					        .table-td=checkboxes :days, @block_days, info['days'].map(&:to_i), 'date.day_names', vertical: true, small: true
 | 
				
			||||||
 | 
					        .table-td.form
 | 
				
			||||||
 | 
					          = hidden_field_tag :workshop_block, block
 | 
				
			||||||
 | 
					          = button_tag :delete_block, value: :delete_block, class: [:small, :delete] if block == @workshop_blocks.length - 2
 | 
				
			||||||
 | 
					          = button_tag (is_new ? :add_block : :update_block), value: :save_block, class: [:small, :add]
 | 
				
			||||||
							
								
								
									
										27
									
								
								app/views/conference_administration/administration.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					- body_class 'banner-bottom' unless @this_conference.poster.present?
 | 
				
			||||||
 | 
					- content_for :banner do
 | 
				
			||||||
 | 
					  = render :partial => 'application/header', :locals  => { page_group: :administration, page_key: 'Administration', image_file: @this_conference.poster_url || 'admin.jpg'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%article
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = columns(medium: 12) do
 | 
				
			||||||
 | 
					      = columns(medium: 12, id: :conferences, class: 'list-view') do
 | 
				
			||||||
 | 
					        %h2=@this_conference.title
 | 
				
			||||||
 | 
					        %p=_'articles.admin.paragraphs.administration', :p
 | 
				
			||||||
 | 
					        %ul.break
 | 
				
			||||||
 | 
					          - administration_steps.each do | step, actions |
 | 
				
			||||||
 | 
					            %li
 | 
				
			||||||
 | 
					              .info
 | 
				
			||||||
 | 
					                %h3=_"articles.admin.#{step}.heading", :t
 | 
				
			||||||
 | 
					              .help
 | 
				
			||||||
 | 
					                %p=_"articles.admin.#{step}.description", :p
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                .actions.figures
 | 
				
			||||||
 | 
					                  - actions.each do | action |
 | 
				
			||||||
 | 
					                    - action_text = (_"articles.admin.#{step}.headings.#{action}", :t)
 | 
				
			||||||
 | 
					                    .figure
 | 
				
			||||||
 | 
					                      = link_to administration_step_path(@this_conference.slug, action.to_s) do
 | 
				
			||||||
 | 
					                        %header= action_text
 | 
				
			||||||
 | 
					                        .body
 | 
				
			||||||
 | 
					                          = svg "admin/#{action.to_s}", action_text
 | 
				
			||||||
 | 
					                          .description=(_"articles.admin.#{step}.descriptions.#{action}", :s)
 | 
				
			||||||
@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					- body_class 'banner-bottom' unless @this_conference.poster.present?
 | 
				
			||||||
 | 
					- content_for :banner do
 | 
				
			||||||
 | 
					  = render :partial => 'application/header', :locals  => { page_group: :administration, page_key: 'Administration', image_file: @this_conference.poster_url || 'admin.jpg'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%article{id: "admin-#{@admin_step}"}
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = columns(medium: 12) do
 | 
				
			||||||
 | 
					      %h2.floating=(_"articles.admin.#{@admin_group}.headings.#{@admin_step}", :t)
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = columns(medium: 12) do
 | 
				
			||||||
 | 
					      %nav.sub-nav
 | 
				
			||||||
 | 
					        %ul
 | 
				
			||||||
 | 
					          %li=link_to (_'articles.admin.headings.back'), administrate_conference_path(@this_conference.slug)
 | 
				
			||||||
 | 
					          - administration_steps[@admin_group].each do | step |
 | 
				
			||||||
 | 
					            %li
 | 
				
			||||||
 | 
					              - title = (_"articles.admin.#{@admin_group}.headings.#{step}", :t)
 | 
				
			||||||
 | 
					              - if step == @admin_step.to_sym
 | 
				
			||||||
 | 
					                = title
 | 
				
			||||||
 | 
					              - else
 | 
				
			||||||
 | 
					                = link_to title, administration_step_path(@this_conference.slug, step.to_s)
 | 
				
			||||||
 | 
					  - if @success_message.present?
 | 
				
			||||||
 | 
					    = row do
 | 
				
			||||||
 | 
					      = columns(class: 'info-messages') do
 | 
				
			||||||
 | 
					        .success-info.info-message=_"success.messages.admin.#{@success_message}", :s
 | 
				
			||||||
 | 
					  - if @error_message.present?
 | 
				
			||||||
 | 
					    = row do
 | 
				
			||||||
 | 
					      = columns(class: 'info-messages') do
 | 
				
			||||||
 | 
					        .error-info.info-message=_"errors.messages.admin.#{@error_message}", :s
 | 
				
			||||||
 | 
					  - if @warnings.present?
 | 
				
			||||||
 | 
					    = row class: 'warnings', tag: :ul do
 | 
				
			||||||
 | 
					      - @warnings.each do | warning |
 | 
				
			||||||
 | 
					        = columns tag: :li, class: 'warning-info info-message' do
 | 
				
			||||||
 | 
					          = warning
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = columns(medium: 12) do
 | 
				
			||||||
 | 
					      %p=((_"articles.admin.#{@admin_group}.descriptions.#{@admin_step}", :s)) unless @hide_description === true
 | 
				
			||||||
 | 
					  = row do
 | 
				
			||||||
 | 
					    = render @admin_step
 | 
				
			||||||
							
								
								
									
										34
									
								
								app/views/conferences/_conference.html.haml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					- links ||= [ :register ]
 | 
				
			||||||
 | 
					- sections ||= [ :info ]
 | 
				
			||||||
 | 
					%article
 | 
				
			||||||
 | 
					  = row(tag: :header) do
 | 
				
			||||||
 | 
					    = columns(class: 'conference-banner') do
 | 
				
			||||||
 | 
					      .title
 | 
				
			||||||
 | 
					        %h1=_!conference.title
 | 
				
			||||||
 | 
					        .details
 | 
				
			||||||
 | 
					          %h2.primary=location(conference.city || conference.location) if conference.city_name.present?
 | 
				
			||||||
 | 
					          - if conference.start_date.present? && conference.end_date.present?
 | 
				
			||||||
 | 
					            .secondary
 | 
				
			||||||
 | 
					              = date_span(conference.start_date.to_date, conference.end_date.to_date)
 | 
				
			||||||
 | 
					      - if conference.poster.present?
 | 
				
			||||||
 | 
					        %img{src: conference.poster.full.url || image_path('default_poster.jpg'), role: :presentation, alt: (_'images.conference.poster', vars: { conference_title: conference.title })}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  = row(class: 'conference-details') do
 | 
				
			||||||
 | 
					    = columns(medium: 10, push: {medium: 1}) do
 | 
				
			||||||
 | 
					      %h2=_!conference.title if conference.poster.present?
 | 
				
			||||||
 | 
					      = richtext conference.info
 | 
				
			||||||
 | 
					      - if conference.registration_status == :open && sections.include?(:workshops)
 | 
				
			||||||
 | 
					        - if conference.workshop_schedule_published
 | 
				
			||||||
 | 
					          - add_inline_script :home_schedule
 | 
				
			||||||
 | 
					          %h3=_'articles.workshops.headings.Schedule'
 | 
				
			||||||
 | 
					          = render 'conferences/admin/schedule'
 | 
				
			||||||
 | 
					        - else
 | 
				
			||||||
 | 
					          %h3=_'articles.workshops.headings.Proposed_Workshops'
 | 
				
			||||||
 | 
					          %p=_'articles.workshops.paragraphs.Proposed_Workshops'
 | 
				
			||||||
 | 
					          = render 'workshops/workshop_previews', :workshops => (conference.workshops.sort { |a, b| a.title.downcase <=> b.title.downcase })
 | 
				
			||||||
 | 
					      .links
 | 
				
			||||||
 | 
					        = (link_to (_'forms.actions.generic.register'), register_path(conference.slug), class: [:button, :register]) if links.include?(:register) && conference.registration_status == :open
 | 
				
			||||||
 | 
					        = (link_to (_'articles.workshops.info.read_more'), conference_path(conference.slug), class: :button) if links.include?(:read_more)
 | 
				
			||||||
 | 
					        = (link_to (_'forms.actions.generic.administrate'), administrate_conference_path(conference.slug), class: [:button]) if links.include?(:administrate)
 | 
				
			||||||
 | 
					        = (link_to (_'forms.actions.generic.edit'), edit_conference_path(conference.slug), class: [:button, :subdued]) if links.include?(:edit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
- content_for :banner do
 | 
					- content_for :banner do
 | 
				
			||||||
	.title
 | 
						.title
 | 
				
			||||||
		%h1=_!@conference.title
 | 
							%h1=_!@this_conference.title
 | 
				
			||||||
		.details
 | 
							.details
 | 
				
			||||||
			%h2.primary=location(@conference.organizations.first.locations.first)
 | 
								%h2.primary=location(@this_conference.city)
 | 
				
			||||||
			.secondary
 | 
								.secondary
 | 
				
			||||||
				= date_span(@conference.start_date.to_date, @conference.end_date.to_date)
 | 
									= date_span(@this_conference.start_date.to_date, @this_conference.end_date.to_date)
 | 
				
			||||||
	%img{src: @conference.poster.full.url || image_path('default_poster.jpg'), role: :presentation, alt: (_'images.conference.poster', vars: { conference_title: @conference.title })}
 | 
						%img{src: @this_conference.poster.full.url || image_path('default_poster.jpg'), role: :presentation, alt: (_'images.conference.poster', vars: { conference_title: @this_conference.title })}
 | 
				
			||||||
- content_for :og_image do
 | 
					- content_for :og_image do
 | 
				
			||||||
	= @conference.poster.full.url || image_path('default_poster.jpg')
 | 
						= @this_conference.poster.full.url || image_path('default_poster.jpg')
 | 
				
			||||||
 | 
				
			|||||||
@ -1 +1 @@
 | 
				
			|||||||
= render :partial => 'application/header', :locals  => {:page_group => :conferences, :page_key => page_key, :image_file => @conference.poster_url}
 | 
					= render :partial => 'application/header', :locals  => {:page_group => :conferences, :page_key => page_key, :image_file => @this_conference.poster_url}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,22 +0,0 @@
 | 
				
			|||||||
= form_tag administration_update_path(@this_conference.slug, :broadcast) do
 | 
					 | 
				
			||||||
	- if @broadcast_step == :preview || @broadcast_step == :test
 | 
					 | 
				
			||||||
		= hidden_field_tag :subject, @subject
 | 
					 | 
				
			||||||
		= hidden_field_tag :body, @body
 | 
					 | 
				
			||||||
		= hidden_field_tag :send_to, @send_to
 | 
					 | 
				
			||||||
		- if @broadcast_step == :preview
 | 
					 | 
				
			||||||
			%p= _'articles.conference_registration.paragraphs.admin.broadcast.test', vars: { send_to_count: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }
 | 
					 | 
				
			||||||
		- else
 | 
					 | 
				
			||||||
			.warning-info.make-room= _'articles.conference_registration.paragraphs.admin.broadcast.preview', vars: { send_to_count: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }
 | 
					 | 
				
			||||||
		.test-preview
 | 
					 | 
				
			||||||
			%h4=@subject
 | 
					 | 
				
			||||||
			= richtext @body, 4
 | 
					 | 
				
			||||||
		.actions.right
 | 
					 | 
				
			||||||
			= button_tag :test, value: :test, class: :secondary if @broadcast_step == :preview
 | 
					 | 
				
			||||||
			= button_with_confirmation :send, (_'modals.admin.broadcast.confirm', vars: { number: "<strong>#{(@send_to_count || 0)}</strong>".html_safe }), value: :send, class: :delete if @broadcast_step == :test
 | 
					 | 
				
			||||||
			= button_tag :edit, value: :edit
 | 
					 | 
				
			||||||
	- else
 | 
					 | 
				
			||||||
		= selectfield :send_to, nil, broadcast_options, full: true
 | 
					 | 
				
			||||||
		= textfield :subject, @subject, required: true, big: true
 | 
					 | 
				
			||||||
		= textarea :body, @body, lang: @this_conference.locale, edit_on: :focus
 | 
					 | 
				
			||||||
		.actions.right
 | 
					 | 
				
			||||||
			= button_tag :preview, value: :preview
 | 
					 | 
				
			||||||