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  | 
@ -1,115 +1,130 @@
 | 
				
			|||||||
(function() {
 | 
					(function() {
 | 
				
			||||||
	var pens = {};
 | 
					    var pens = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Array.prototype.forEach.call(document.querySelectorAll('.textarea'), function(editor) {
 | 
					    Array.prototype.forEach.call(document.querySelectorAll('.textarea'), function(editor) {
 | 
				
			||||||
		var event= editor.dataset.editOn;
 | 
					        var event= editor.dataset.editOn;
 | 
				
			||||||
		if (event == 'load') {
 | 
					        if (event == 'load') {
 | 
				
			||||||
			startEditing(editor);
 | 
					            startEditing(editor);
 | 
				
			||||||
		} else {
 | 
					        } else {
 | 
				
			||||||
			editor.addEventListener(event, function() {
 | 
					            editor.addEventListener(event, function() {
 | 
				
			||||||
				if (editor.getAttribute('contenteditable') !== 'true') {
 | 
					                if (editor.getAttribute('contenteditable') !== 'true') {
 | 
				
			||||||
					startEditing(editor);
 | 
					                    startEditing(editor);
 | 
				
			||||||
					// for content editable, we need to refocus to show the caret
 | 
					                    // for content editable, we need to refocus to show the caret
 | 
				
			||||||
					editor.blur(); 
 | 
					                    editor.blur(); 
 | 
				
			||||||
					editor.focus();
 | 
					                    editor.focus();
 | 
				
			||||||
				}
 | 
					                }
 | 
				
			||||||
			});
 | 
					            });
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	});
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function startEditing(editor) {
 | 
					    function startEditing(editor) {
 | 
				
			||||||
		var name = editor.dataset.name;
 | 
					        var name = editor.dataset.name;
 | 
				
			||||||
		pens[name] = new Pen({
 | 
					        pens[name] = new Pen({
 | 
				
			||||||
			editor: editor,
 | 
					            editor: editor,
 | 
				
			||||||
			class: 'pen',
 | 
					            class: 'pen',
 | 
				
			||||||
			textarea: '<textarea name="' + name + '"></textarea>',
 | 
					            textarea: '<textarea name="' + name + '"></textarea>',
 | 
				
			||||||
			list: ['p', 'h1', 'h2', 'blockquote', 'insertorderedlist', 'insertunorderedlist', 'bold', 'italic', 'underline', 'strikethrough', 'createlink', 'insertimage'],
 | 
					            list: ['p', 'h1', 'h2', 'blockquote', 'insertorderedlist', 'insertunorderedlist', 'bold', 'italic', 'underline', 'strikethrough', 'createlink', 'insertimage'],
 | 
				
			||||||
			title: {
 | 
					            title: {
 | 
				
			||||||
				'p': 'Paragraph',
 | 
					                'p': 'Paragraph',
 | 
				
			||||||
				'h1': 'Major Heading',
 | 
					                'h1': 'Major Heading',
 | 
				
			||||||
				'h2': 'Minor Heading',
 | 
					                'h2': 'Minor Heading',
 | 
				
			||||||
				'blockquote': 'Quotation',
 | 
					                'blockquote': 'Quotation',
 | 
				
			||||||
				'insertorderedlist': 'Ordered List',
 | 
					                'insertorderedlist': 'Ordered List',
 | 
				
			||||||
				'insertunorderedlist': 'Unordered List',
 | 
					                'insertunorderedlist': 'Unordered List',
 | 
				
			||||||
				'bold': 'Bold',
 | 
					                'bold': 'Bold',
 | 
				
			||||||
				'italic': 'Italic',
 | 
					                'italic': 'Italic',
 | 
				
			||||||
				'underline': 'Underline',
 | 
					                'underline': 'Underline',
 | 
				
			||||||
				'strikethrough': 'Strikethrough',
 | 
					                'strikethrough': 'Strikethrough',
 | 
				
			||||||
				'createlink': 'Link',
 | 
					                'createlink': 'Link',
 | 
				
			||||||
				'insertimage': 'Image'
 | 
					                'insertimage': 'Image'
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
		return pens[name];
 | 
					        return pens[name];
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Array.prototype.forEach.call(document.querySelectorAll('form'), function(form) {
 | 
					    Array.prototype.forEach.call(document.querySelectorAll('form'), function(form) {
 | 
				
			||||||
		var shouldAllowAlert = false;
 | 
					        var shouldAllowAlert = false;
 | 
				
			||||||
		form.addEventListener('submit', function() {
 | 
					        form.addEventListener('submit', function() {
 | 
				
			||||||
			if (shouldAllowAlert) {
 | 
					            if (shouldAllowAlert) {
 | 
				
			||||||
				return;
 | 
					                return;
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
			Array.prototype.forEach.call(document.querySelectorAll('.textarea'), function(editor) {
 | 
					            Array.prototype.forEach.call(document.querySelectorAll('.textarea'), function(editor) {
 | 
				
			||||||
				var name = editor.dataset.name;
 | 
					                var name = editor.dataset.name;
 | 
				
			||||||
				var textarea = document.querySelector('textarea[name="' + name + '"]');
 | 
					                var textarea = document.querySelector('textarea[name="' + name + '"]');
 | 
				
			||||||
				if (!textarea) {
 | 
					                if (!textarea) {
 | 
				
			||||||
					textarea = document.createElement('textarea');
 | 
					                    textarea = document.createElement('textarea');
 | 
				
			||||||
					textarea.name = name;
 | 
					                    textarea.name = name;
 | 
				
			||||||
					textarea.style.display = 'none';
 | 
					                    textarea.style.display = 'none';
 | 
				
			||||||
					form.appendChild(textarea);
 | 
					                    form.appendChild(textarea);
 | 
				
			||||||
				}
 | 
					                }
 | 
				
			||||||
				textarea.value = editor.innerHTML;
 | 
					                textarea.value = editor.innerHTML;
 | 
				
			||||||
				if (pens[name]) {
 | 
					                if (pens[name]) {
 | 
				
			||||||
					pens[name].destroy();
 | 
					                    pens[name].destroy();
 | 
				
			||||||
				}
 | 
					                }
 | 
				
			||||||
			});
 | 
					            });
 | 
				
			||||||
		}, false);
 | 
					        }, false);
 | 
				
			||||||
		Array.prototype.forEach.call(form.querySelectorAll('button'), function(button) {
 | 
					        Array.prototype.forEach.call(form.querySelectorAll('button'), function(button) {
 | 
				
			||||||
			form.addEventListener('click', function(event) {
 | 
					            form.addEventListener('click', function(event) {
 | 
				
			||||||
				shouldAllowAlert = (event.target.value === 'cancel');
 | 
					                shouldAllowAlert = (event.target.value === 'cancel');
 | 
				
			||||||
			});
 | 
					            });
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
	});
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Array.prototype.forEach.call(document.querySelectorAll('.check-box-field .other input'), function(input) {
 | 
					    Array.prototype.forEach.call(document.querySelectorAll('.check-box-field .other input'), function(input) {
 | 
				
			||||||
		var checkbox = document.getElementById(input.parentElement.parentElement.attributes.for.value);
 | 
					        var checkbox = document.getElementById(input.parentElement.parentElement.attributes.for.value);
 | 
				
			||||||
		input.addEventListener('keyup', function(event) {
 | 
					        input.addEventListener('keyup', function(event) {
 | 
				
			||||||
			if (event.target.value) {
 | 
					            if (event.target.value) {
 | 
				
			||||||
				checkbox.checked = true;
 | 
					                checkbox.checked = true;
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
		input.addEventListener('click', function(event) {
 | 
					        input.addEventListener('click', function(event) {
 | 
				
			||||||
			checkbox.checked = true;
 | 
					            checkbox.checked = true;
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
		var setRequired = function() {
 | 
					        var setRequired = function() {
 | 
				
			||||||
			if (checkbox.checked) {
 | 
					            if (checkbox.checked) {
 | 
				
			||||||
				input.setAttribute('required',  'required');
 | 
					                input.setAttribute('required',  'required');
 | 
				
			||||||
			} else {
 | 
					            } else {
 | 
				
			||||||
				input.removeAttribute('required');
 | 
					                input.removeAttribute('required');
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		};
 | 
					        };
 | 
				
			||||||
		Array.prototype.forEach.call(document.querySelectorAll('.check-box-field input'), function(_input) {
 | 
					        Array.prototype.forEach.call(document.querySelectorAll('.check-box-field input'), function(_input) {
 | 
				
			||||||
			_input.addEventListener('change', function(event) { setRequired(); });
 | 
					            _input.addEventListener('change', function(event) { setRequired(); });
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
	});
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Array.prototype.forEach.call(document.querySelectorAll('[data-toggles]'), function(checkbox) {
 | 
					    Array.prototype.forEach.call(document.querySelectorAll('[data-toggles]'), function(checkbox) {
 | 
				
			||||||
		var toggles = document.getElementById(checkbox.dataset.toggles);
 | 
					        var toggles = document.getElementById(checkbox.dataset.toggles);
 | 
				
			||||||
		toggles.classList.add('toggleable');
 | 
					        toggles.classList.add('toggleable');
 | 
				
			||||||
		var form = checkbox.parentNode;
 | 
					        var form = checkbox.parentNode;
 | 
				
			||||||
		while (form && form.nodeName != 'FORM') {
 | 
					        while (form && form.nodeName != 'FORM') {
 | 
				
			||||||
			form = form.parentNode;
 | 
					            form = form.parentNode;
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
		var toggle = function() {
 | 
					        var toggle = function() {
 | 
				
			||||||
			toggles.classList[checkbox.checked ? 'add' : 'remove']('open');
 | 
					            toggles.classList[checkbox.checked ? 'add' : 'remove']('open');
 | 
				
			||||||
			if (form) {
 | 
					            if (form) {
 | 
				
			||||||
				if (checkbox.checked) {
 | 
					                if (checkbox.checked) {
 | 
				
			||||||
					form.removeAttribute('novalidate');
 | 
					                    form.removeAttribute('novalidate');
 | 
				
			||||||
				} else {
 | 
					                } else {
 | 
				
			||||||
					form.setAttribute('novalidate', 'novalidate');
 | 
					                    form.setAttribute('novalidate', 'novalidate');
 | 
				
			||||||
				}
 | 
					                }
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		};
 | 
					        };
 | 
				
			||||||
		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,156 +14,165 @@ $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%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@mixin default-box-shadow($direction: top, $distance: 1, $inset: false, $additional-shadow: false) {
 | 
					@mixin default-box-shadow($direction: top, $distance: 1, $inset: false, $additional-shadow: false) {
 | 
				
			||||||
	@if capable_of(box-shadow) {
 | 
					    @if capable_of(box-shadow) {
 | 
				
			||||||
		$offset: 0.2em;
 | 
					        $offset: 0.2em;
 | 
				
			||||||
		@if $direction == right or $direction == bottom {
 | 
					        @if $direction == right or $direction == bottom {
 | 
				
			||||||
			$offset: -$offset;
 | 
					            $offset: -$offset;
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
		@if $direction == left or $direction == right {
 | 
					        @if $direction == left or $direction == right {
 | 
				
			||||||
			$offset: '#{$offset} 0';
 | 
					            $offset: '#{$offset} 0';
 | 
				
			||||||
		} @else {
 | 
					        } @else {
 | 
				
			||||||
			$offset: '0 #{$offset}';
 | 
					            $offset: '0 #{$offset}';
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
		@if $inset {
 | 
					        @if $inset {
 | 
				
			||||||
			$offset: 'inset #{$offset}';
 | 
					            $offset: 'inset #{$offset}';
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
		@if $additional-shadow {
 | 
					        @if $additional-shadow {
 | 
				
			||||||
			$additional-shadow: ', #{$additional-shadow}';
 | 
					            $additional-shadow: ', #{$additional-shadow}';
 | 
				
			||||||
		} @else {
 | 
					        } @else {
 | 
				
			||||||
			$additional-shadow: '';
 | 
					            $additional-shadow: '';
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
		@include _(box-shadow, #{$offset} 0.8em #{-0.2em * $distance} #000#{$additional-shadow});
 | 
					        @include _(box-shadow, #{$offset} 0.8em #{-0.2em * $distance} #000#{$additional-shadow});
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@mixin monospace-font {
 | 
					@mixin monospace-font {
 | 
				
			||||||
	@include font(monospace);
 | 
					    @include font(monospace);
 | 
				
			||||||
	@include font(monospace-bold);
 | 
					    @include font(monospace-bold);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@mixin translation-pointer {
 | 
					@mixin translation-pointer {
 | 
				
			||||||
	@include keyframes(bouncy) {
 | 
					    @include keyframes(bouncy) {
 | 
				
			||||||
		from { transform: translateY(-0.25em); }
 | 
					        from { transform: translateY(-0.25em); }
 | 
				
			||||||
		to   { transform: translateY(0.25em); }
 | 
					        to   { transform: translateY(0.25em); }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#lingua-franca-pointer {
 | 
					    #lingua-franca-pointer {
 | 
				
			||||||
		$colour: $colour-5;
 | 
					        $colour: $colour-5;
 | 
				
			||||||
		width: 0.6667em;
 | 
					        width: 0.6667em;
 | 
				
			||||||
		height: 1.25em;
 | 
					        height: 1.25em;
 | 
				
			||||||
		background-color: $colour;
 | 
					        background-color: $colour;
 | 
				
			||||||
		z-index: 1000;
 | 
					        z-index: 1000;
 | 
				
			||||||
		margin-left: -0.5em;
 | 
					        margin-left: -0.5em;
 | 
				
			||||||
	    margin-top: -2em;
 | 
					        margin-top: -2em;
 | 
				
			||||||
	    @include _(mix-blend-mode, exclusion);
 | 
					        @include _(mix-blend-mode, exclusion);
 | 
				
			||||||
		@include default-box-shadow(top, 2);
 | 
					        @include default-box-shadow(top, 2);
 | 
				
			||||||
		@include _(animation, bouncy 1s infinite alternate);
 | 
					        @include _(animation, bouncy 1s infinite alternate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$twidth: 0.8em;
 | 
					        $twidth: 0.8em;
 | 
				
			||||||
		@include after {
 | 
					        @include after {
 | 
				
			||||||
			content: '';
 | 
					            content: '';
 | 
				
			||||||
			width: 0;
 | 
					            width: 0;
 | 
				
			||||||
			height: 0;
 | 
					            height: 0;
 | 
				
			||||||
			position: absolute;
 | 
					            position: absolute;
 | 
				
			||||||
			border-style: solid;
 | 
					            border-style: solid;
 | 
				
			||||||
			border-color: $colour transparent transparent;
 | 
					            border-color: $colour transparent transparent;
 | 
				
			||||||
			border-width: $twidth $twidth 0;
 | 
					            border-width: $twidth $twidth 0;
 | 
				
			||||||
			top: 100%;
 | 
					            top: 100%;
 | 
				
			||||||
			left: -.4em;
 | 
					            left: -.4em;
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		&.up {
 | 
					        &.up {
 | 
				
			||||||
	    	margin-top: 2em;
 | 
					            margin-top: 2em;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			@include after {
 | 
					            @include after {
 | 
				
			||||||
				top: auto;
 | 
					                top: auto;
 | 
				
			||||||
				bottom: 100%;
 | 
					                bottom: 100%;
 | 
				
			||||||
				border-color: transparent transparent $colour;
 | 
					                border-color: transparent transparent $colour;
 | 
				
			||||||
				border-width: 0 $twidth $twidth;
 | 
					                border-width: 0 $twidth $twidth;
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@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;
 | 
				
			||||||
	color: $white;
 | 
					    color: $white;
 | 
				
			||||||
	background-color: $colour-1;
 | 
					    background-color: $colour-1;
 | 
				
			||||||
	border: 0;
 | 
					    border: 0;
 | 
				
			||||||
	padding: 0.5em 1em;
 | 
					    padding: 0.5em 1em;
 | 
				
			||||||
	font-size: 1.25em;
 | 
					    font-size: 1.25em;
 | 
				
			||||||
	outline: 0;
 | 
					    outline: 0;
 | 
				
			||||||
	border-bottom: 0.125em solid rgba(0, 0, 0, 0.15);
 | 
					    border-bottom: 0.125em solid rgba(0, 0, 0, 0.15);
 | 
				
			||||||
	@include _(border-radius, 0.15em);
 | 
					    @include _(border-radius, 0.15em);
 | 
				
			||||||
	@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: '';
 | 
				
			||||||
		position: absolute;
 | 
					        position: absolute;
 | 
				
			||||||
		top: 0;
 | 
					        top: 0;
 | 
				
			||||||
		right: 0;
 | 
					        right: 0;
 | 
				
			||||||
		bottom: 0;
 | 
					        bottom: 0;
 | 
				
			||||||
		left: 0;
 | 
					        left: 0;
 | 
				
			||||||
		background-color: rgba(0,0,0,0);
 | 
					        background-color: rgba(0,0,0,0);
 | 
				
			||||||
		@include _(transition, background-color 150ms ease-in-out);
 | 
					        @include _(transition, background-color 150ms ease-in-out);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	/*@include before-and-after {
 | 
					    /*@include before-and-after {
 | 
				
			||||||
		content: '';
 | 
					        content: '';
 | 
				
			||||||
		position: absolute;
 | 
					        position: absolute;
 | 
				
			||||||
		display: block;
 | 
					        display: block;
 | 
				
			||||||
		top: 0;
 | 
					        top: 0;
 | 
				
			||||||
		right: 100%;
 | 
					        right: 100%;
 | 
				
			||||||
		font-size: 1.15em;
 | 
					        font-size: 1.15em;
 | 
				
			||||||
		background-color: rgba(0, 0, 0, 0);
 | 
					        background-color: rgba(0, 0, 0, 0);
 | 
				
			||||||
		border-color: transparent;
 | 
					        border-color: transparent;
 | 
				
			||||||
		@include _(transition, all 250ms ease-in-out);
 | 
					        @include _(transition, all 250ms ease-in-out);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	@include before {
 | 
					    @include before {
 | 
				
			||||||
		height: 100%;
 | 
					        height: 100%;
 | 
				
			||||||
		width: 100%;
 | 
					        width: 100%;
 | 
				
			||||||
		margin-right: 1em;
 | 
					        margin-right: 1em;
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	@include after {
 | 
					    @include after {
 | 
				
			||||||
		border-style: solid;
 | 
					        border-style: solid;
 | 
				
			||||||
		border-width: 1em 0 1em 1em;
 | 
					        border-width: 1em 0 1em 1em;
 | 
				
			||||||
	}*/
 | 
					    }*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*&:hover,
 | 
					    /*&:hover,
 | 
				
			||||||
	&:focus {
 | 
					    &:focus {
 | 
				
			||||||
		@include before-and-after {
 | 
					        @include before-and-after {
 | 
				
			||||||
			right: -1em;
 | 
					            right: -1em;
 | 
				
			||||||
			border-left-color: rgba(0, 0, 0, 0.15);
 | 
					            border-left-color: rgba(0, 0, 0, 0.15);
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}*/
 | 
					    }*/
 | 
				
			||||||
	&:hover,
 | 
					    &:hover,
 | 
				
			||||||
	&:focus {
 | 
					    &:focus {
 | 
				
			||||||
		@include before {
 | 
					        @include before {
 | 
				
			||||||
			background-color: rgba(0, 0, 0, 0.15);
 | 
					            background-color: rgba(0, 0, 0, 0.15);
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	&:active {
 | 
					    &:active {
 | 
				
			||||||
		@include _(transform, scale(0.95));
 | 
					        @include _(transform, scale(0.95));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@include after {
 | 
					        @include after {
 | 
				
			||||||
			left: 120%;
 | 
					            left: 120%;
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	&:disabled {
 | 
					    &:disabled {
 | 
				
			||||||
		@include _(opacity, 0.5);
 | 
					        @include _(opacity, 0.5);
 | 
				
			||||||
		cursor: inherit;
 | 
					        cursor: inherit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@include before-and-after {
 | 
					        @include before-and-after {
 | 
				
			||||||
			display: none;
 | 
					            display: none;
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
							
								
								
									
										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
 | 
				
			||||||
@ -1,180 +1,180 @@
 | 
				
			|||||||
require 'diffy'
 | 
					require 'diffy'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UserMailer < ActionMailer::Base
 | 
					class UserMailer < ActionMailer::Base
 | 
				
			||||||
	add_template_helper(ApplicationHelper)
 | 
					  add_template_helper(ApplicationHelper)
 | 
				
			||||||
	include LinguaFrancaHelper
 | 
					  include LinguaFrancaHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	before_filter :set_host
 | 
					  before_filter :set_host
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default from: "Bike!Bike! <noreply@bikebike.org>"
 | 
					  default from: "Bike!Bike! <noreply@bikebike.org>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def email_confirmation(confirmation)
 | 
					  def email_confirmation(confirmation)
 | 
				
			||||||
		@confirmation = EmailConfirmation.find(confirmation) if confirmation.present?
 | 
					    @confirmation = EmailConfirmation.find(confirmation) if confirmation.present?
 | 
				
			||||||
		I18n.locale = @confirmation.user.locale if @confirmation.user.locale.present?
 | 
					    I18n.locale = @confirmation.user.locale if @confirmation.user.locale.present?
 | 
				
			||||||
		@subject = _'email.subject.confirm_email','Please confirm your email address'
 | 
					    @subject = _'email.subject.confirm_email','Please confirm your email address'
 | 
				
			||||||
		mail to: @confirmation.user.named_email, subject: @subject
 | 
					    mail to: @confirmation.user.named_email, subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def registration_confirmation(registration)
 | 
					  def registration_confirmation(registration)
 | 
				
			||||||
		@registration = ConferenceRegistration.find(registration) if registration.present?
 | 
					    @registration = ConferenceRegistration.find(registration) if registration.present?
 | 
				
			||||||
		@conference = @registration.conference
 | 
					    @conference = @registration.conference
 | 
				
			||||||
		@user = @registration.user
 | 
					    @user = @registration.user
 | 
				
			||||||
		I18n.locale = @user.locale if @user.locale.present?
 | 
					    I18n.locale = @user.locale if @user.locale.present?
 | 
				
			||||||
		@subject = @conference.registration_status.to_sym == :pre ?
 | 
					    @subject = @conference.registration_status.to_sym == :pre ?
 | 
				
			||||||
			_(
 | 
					      _(
 | 
				
			||||||
				'email.subject.pre_registration_confirmed',
 | 
					        'email.subject.pre_registration_confirmed',
 | 
				
			||||||
				"Thank you for pre-registering for #{@conference.title}",
 | 
					        "Thank you for pre-registering for #{@conference.title}",
 | 
				
			||||||
				:vars => {:conference_title => @conference.title}
 | 
					        :vars => {:conference_title => @conference.title}
 | 
				
			||||||
			) : _(
 | 
					      ) : _(
 | 
				
			||||||
				'email.subject.registration_confirmed',
 | 
					        'email.subject.registration_confirmed',
 | 
				
			||||||
				"Thank you for registering for #{@conference.title}",
 | 
					        "Thank you for registering for #{@conference.title}",
 | 
				
			||||||
				:vars => {:conference_title => @conference.title}
 | 
					        :vars => {:conference_title => @conference.title}
 | 
				
			||||||
			)
 | 
					      )
 | 
				
			||||||
		mail to: @user.named_email, subject: @subject
 | 
					    mail to: @user.named_email, subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def broadcast(host, subject, content, user, conference)
 | 
					  def broadcast(host, subject, content, user, conference)
 | 
				
			||||||
		@host = host
 | 
					    @host = host
 | 
				
			||||||
		@content = content
 | 
					    @content = content
 | 
				
			||||||
		@banner = nil
 | 
					    @banner = nil
 | 
				
			||||||
		@conference = Conference.find(conference) if conference.present?
 | 
					    @conference = Conference.find(conference) if conference.present?
 | 
				
			||||||
		@user = User.find(user) if user.present?
 | 
					    @user = User.find(user) if user.present?
 | 
				
			||||||
		@subject = "[#{@conference ? @conference.title : 'Bike!Bike!'}] #{subject}"
 | 
					    @subject = "[#{@conference ? @conference.title : 'Bike!Bike!'}] #{subject}"
 | 
				
			||||||
		if @user && @user.named_email
 | 
					    if @user && @user.named_email
 | 
				
			||||||
			mail to: @user.named_email, subject: @subject
 | 
					      mail to: @user.named_email, subject: @subject
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def workshop_facilitator_request(workshop, requester, message)
 | 
					  def workshop_facilitator_request(workshop, requester, message)
 | 
				
			||||||
		@workshop = Workshop.find(workshop) if workshop.present?
 | 
					    @workshop = Workshop.find(workshop) if workshop.present?
 | 
				
			||||||
		@requester = User.find(requester) if requester.present?
 | 
					    @requester = User.find(requester) if requester.present?
 | 
				
			||||||
		addresses = []
 | 
					    addresses = []
 | 
				
			||||||
		I18n.locale = @workshop.active_facilitators.first.locale if @workshop.active_facilitators.first.locale.present?
 | 
					    I18n.locale = @workshop.active_facilitators.first.locale if @workshop.active_facilitators.first.locale.present?
 | 
				
			||||||
		@workshop.active_facilitators.each do |f|
 | 
					    @workshop.active_facilitators.each do |f|
 | 
				
			||||||
			addresses << f.named_email
 | 
					      addresses << f.named_email
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
		@message = message
 | 
					    @message = message
 | 
				
			||||||
		@conference = Conference.find(@workshop.conference_id)
 | 
					    @conference = Conference.find(@workshop.conference_id)
 | 
				
			||||||
		@subject = _('email.subject.workshop_facilitator_request',
 | 
					    @subject = _('email.subject.workshop_facilitator_request',
 | 
				
			||||||
			 		"Request to facilitate #{@workshop.title} from #{@requester.name}",
 | 
					          "Request to facilitate #{@workshop.title} from #{@requester.name}",
 | 
				
			||||||
			 		:vars => {:workshop_title => @workshop.title, :requester_name => @requester.firstname})
 | 
					          :vars => {:workshop_title => @workshop.title, :requester_name => @requester.firstname})
 | 
				
			||||||
		mail to: addresses, reply_to: addresses + [@requester.named_email], subject: @subject
 | 
					    mail to: addresses, reply_to: addresses + [@requester.named_email], subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def workshop_facilitator_request_approved(workshop, user)
 | 
					  def workshop_facilitator_request_approved(workshop, user)
 | 
				
			||||||
		@workshop = Workshop.find(workshop) if workshop.present?
 | 
					    @workshop = Workshop.find(workshop) if workshop.present?
 | 
				
			||||||
		@conference = Conference.find(@workshop.conference_id)
 | 
					    @conference = Conference.find(@workshop.conference_id)
 | 
				
			||||||
		@user = User.find(user) if user.present?
 | 
					    @user = User.find(user) if user.present?
 | 
				
			||||||
		I18n.locale = @user.locale if @user.locale.present?
 | 
					    I18n.locale = @user.locale if @user.locale.present?
 | 
				
			||||||
		@subject = (_'email.subject.workshop_request_approved',
 | 
					    @subject = (_'email.subject.workshop_request_approved',
 | 
				
			||||||
					"You have been added as a facilitator of #{@workshop.title}",
 | 
					          "You have been added as a facilitator of #{@workshop.title}",
 | 
				
			||||||
					:vars => {:workshop_title => @workshop.title})
 | 
					          :vars => {:workshop_title => @workshop.title})
 | 
				
			||||||
		mail to: @user.named_email, subject: @subject
 | 
					    mail to: @user.named_email, subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def workshop_facilitator_request_denied(workshop, user)
 | 
					  def workshop_facilitator_request_denied(workshop, user)
 | 
				
			||||||
		@workshop = Workshop.find(workshop) if workshop.present?
 | 
					    @workshop = Workshop.find(workshop) if workshop.present?
 | 
				
			||||||
		@conference = @workshop.conference
 | 
					    @conference = @workshop.conference
 | 
				
			||||||
		@user = User.find(user) if user.present?
 | 
					    @user = User.find(user) if user.present?
 | 
				
			||||||
		I18n.locale = @user.locale if @user.present? && @user.locale.present?
 | 
					    I18n.locale = @user.locale if @user.present? && @user.locale.present?
 | 
				
			||||||
		@subject = (_'email.subject.workshop_request_denied',
 | 
					    @subject = (_'email.subject.workshop_request_denied',
 | 
				
			||||||
					"Your request to facilitate #{@workshop.title} has been denied",
 | 
					          "Your request to facilitate #{@workshop.title} has been denied",
 | 
				
			||||||
					:vars => {:workshop_title => @workshop.title})
 | 
					          :vars => {:workshop_title => @workshop.title})
 | 
				
			||||||
		mail to: @user.named_email, subject: @subject
 | 
					    mail to: @user.named_email, subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def workshop_translated(workshop, data, locale, user, translator)
 | 
					  def workshop_translated(workshop, data, locale, user, translator)
 | 
				
			||||||
		@workshop = Workshop.find(workshop) if workshop.present?
 | 
					    @workshop = Workshop.find(workshop) if workshop.present?
 | 
				
			||||||
		@data = data
 | 
					    @data = data
 | 
				
			||||||
		@locale = locale
 | 
					    @locale = locale
 | 
				
			||||||
		@locale_name = language_name(locale)
 | 
					    @locale_name = language_name(locale)
 | 
				
			||||||
		@user = User.find(user) if user.present?
 | 
					    @user = User.find(user) if user.present?
 | 
				
			||||||
		I18n.locale = @user.locale if @user.present? && @user.locale.present?
 | 
					    I18n.locale = @user.locale if @user.present? && @user.locale.present?
 | 
				
			||||||
		@translator = User.find(translator) if translator.present?
 | 
					    @translator = User.find(translator) if translator.present?
 | 
				
			||||||
		@subject = (_'email.subject.workshop_translated',
 | 
					    @subject = (_'email.subject.workshop_translated',
 | 
				
			||||||
					"The #{@locale_name} translation for #{@workshop.title} has been modified",
 | 
					          "The #{@locale_name} translation for #{@workshop.title} has been modified",
 | 
				
			||||||
					vars: {language: @language_name, workshop_title: @workshop.title})
 | 
					          vars: {language: @language_name, workshop_title: @workshop.title})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@wrapper_id = :full_width
 | 
					    @wrapper_id = :full_width
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mail to: @user.named_email, subject: @subject
 | 
					    mail to: @user.named_email, subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def workshop_original_content_changed(workshop, data, user, translator)
 | 
					  def workshop_original_content_changed(workshop, data, user, translator)
 | 
				
			||||||
		@workshop = Workshop.find(workshop) if workshop.present?
 | 
					    @workshop = Workshop.find(workshop) if workshop.present?
 | 
				
			||||||
		@data = data
 | 
					    @data = data
 | 
				
			||||||
		@user = User.find(user) if user.present?
 | 
					    @user = User.find(user) if user.present?
 | 
				
			||||||
		I18n.locale = @user.locale if @user.present? && @user.locale.present?
 | 
					    I18n.locale = @user.locale if @user.present? && @user.locale.present?
 | 
				
			||||||
		@translator = User.find(translator) if translator.present?
 | 
					    @translator = User.find(translator) if translator.present?
 | 
				
			||||||
		@subject = (_'email.subject.workshop_original_content_changed',
 | 
					    @subject = (_'email.subject.workshop_original_content_changed',
 | 
				
			||||||
					"Original content for #{@workshop.title} has been modified",
 | 
					          "Original content for #{@workshop.title} has been modified",
 | 
				
			||||||
					vars: {workshop_title: @workshop.title})
 | 
					          vars: {workshop_title: @workshop.title})
 | 
				
			||||||
		@data.each do |field, values|
 | 
					    @data.each do |field, values|
 | 
				
			||||||
			diff = Diffy::Diff.new(values[:old], values[:new])
 | 
					      diff = Diffy::Diff.new(values[:old], values[:new])
 | 
				
			||||||
			@data[field][:diff] = {
 | 
					      @data[field][:diff] = {
 | 
				
			||||||
				text: diff.to_s(:text),
 | 
					        text: diff.to_s(:text),
 | 
				
			||||||
				html: diff.to_s(:html)
 | 
					        html: diff.to_s(:html)
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@wrapper_id = :full_width
 | 
					    @wrapper_id = :full_width
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mail to: @user.named_email, subject: @subject
 | 
					    mail to: @user.named_email, subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def workshop_comment(workshop, comment, user)
 | 
					  def workshop_comment(workshop, comment, user)
 | 
				
			||||||
		@workshop = Workshop.find(workshop) if workshop.present?
 | 
					    @workshop = Workshop.find(workshop) if workshop.present?
 | 
				
			||||||
		@comment = Comment.find(comment) if comment.present?
 | 
					    @comment = Comment.find(comment) if comment.present?
 | 
				
			||||||
		@user = User.find(user) if user.present?
 | 
					    @user = User.find(user) if user.present?
 | 
				
			||||||
		I18n.locale = @user.locale if @user.present? && @user.locale.present?
 | 
					    I18n.locale = @user.locale if @user.present? && @user.locale.present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if @comment.reply?
 | 
					    if @comment.reply?
 | 
				
			||||||
			@subject = (_'email.subject.workshop_comment.reply', vars: { user_name: @comment.user.name })
 | 
					      @subject = (_'email.subject.workshop_comment.reply', vars: { user_name: @comment.user.name })
 | 
				
			||||||
		else
 | 
					    else
 | 
				
			||||||
			@subject = (_'email.subject.workshop_comment.comment', vars: { user_name: @comment.user.name, workshop_title: @workshop.title })
 | 
					      @subject = (_'email.subject.workshop_comment.comment', vars: { user_name: @comment.user.name, workshop_title: @workshop.title })
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mail to: @user.named_email, subject: @subject
 | 
					    mail to: @user.named_email, subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def error_report(subject, message, report, exception, request, params, user, time = nil)
 | 
					  def error_report(subject, message, report, exception, request, params, user, time = nil)
 | 
				
			||||||
		@subject = subject
 | 
					    @subject = subject
 | 
				
			||||||
		@message = message
 | 
					    @message = message
 | 
				
			||||||
		@report = report
 | 
					    @report = report
 | 
				
			||||||
		@exception = exception
 | 
					    @exception = exception
 | 
				
			||||||
		@request = request
 | 
					    @request = request
 | 
				
			||||||
		@params = params
 | 
					    @params = params
 | 
				
			||||||
		@time = time
 | 
					    @time = time
 | 
				
			||||||
		@user = User.find(user) if user.present?
 | 
					    @user = User.find(user) if user.present?
 | 
				
			||||||
		mail to: 'goodgodwin@hotmail.com', subject: @subject
 | 
					    mail to: 'goodgodwin@hotmail.com', subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def contact(from, subject, message, email_list)
 | 
					  def contact(from, subject, message, email_list)
 | 
				
			||||||
		@message = message
 | 
					    @message = message
 | 
				
			||||||
		@subject = subject
 | 
					    @subject = subject
 | 
				
			||||||
		@from = from.is_a?(Integer) ? User.find(from) : from
 | 
					    @from = from.is_a?(Integer) ? User.find(from) : from
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mail to: email_list.join(', '), subject: @subject, reply_to: @from.is_a?(User) ? @from.named_email : @from
 | 
					    mail to: email_list.join(', '), subject: @subject, reply_to: @from.is_a?(User) ? @from.named_email : @from
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def contact_details(from, subject, message, request, params)
 | 
					  def contact_details(from, subject, message, request, params)
 | 
				
			||||||
		@message = message
 | 
					    @message = message
 | 
				
			||||||
		@subject = "Details for: \"#{subject}\""
 | 
					    @subject = "Details for: \"#{subject}\""
 | 
				
			||||||
		@from = from.is_a?(Integer) ? User.find(from) : from
 | 
					    @from = from.is_a?(Integer) ? User.find(from) : from
 | 
				
			||||||
		@request = request
 | 
					    @request = request
 | 
				
			||||||
		@params = params
 | 
					    @params = params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mail to: 'goodgodwin@hotmail.com', subject: @subject
 | 
					    mail to: 'goodgodwin@hotmail.com', subject: @subject
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private
 | 
					  private
 | 
				
			||||||
	def set_host(*args)
 | 
					  def set_host(*args)
 | 
				
			||||||
		if Rails.env.production?
 | 
					    if Rails.env.production?
 | 
				
			||||||
			@host = "https://#{I18n.locale.to_s}.bikebike.org"
 | 
					      @host = "https://#{I18n.locale.to_s}.bikebike.org"
 | 
				
			||||||
		elsif Rails.env.preview?
 | 
					    elsif Rails.env.preview?
 | 
				
			||||||
			@host = "https://preview-#{I18n.locale.to_s}.bikebike.org"
 | 
					      @host = "https://preview-#{I18n.locale.to_s}.bikebike.org"
 | 
				
			||||||
		else
 | 
					    else
 | 
				
			||||||
			@host = UserMailer.default_url_options[:host]
 | 
					      @host = UserMailer.default_url_options[:host]
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
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
 | 
				
			||||||
@ -1,27 +1,27 @@
 | 
				
			|||||||
class Comment < ActiveRecord::Base
 | 
					class Comment < ActiveRecord::Base
 | 
				
			||||||
	belongs_to :user
 | 
					  belongs_to :user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def comment_object
 | 
					  def comment_object
 | 
				
			||||||
		model_type.classify.constantize.find(model_id)
 | 
					    model_type.classify.constantize.find(model_id)
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def set_model(model)
 | 
					  def set_model(model)
 | 
				
			||||||
		model_type = model.class.name.tableize
 | 
					    model_type = model.class.name.tableize
 | 
				
			||||||
		model_id = model.id
 | 
					    model_id = model.id
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.for(model)
 | 
					  def self.for(model)
 | 
				
			||||||
		where(model_type: model.class.name.tableize, model_id: model.id).order(created_at: :asc)
 | 
					    where(model_type: model.class.name.tableize, model_id: model.id).order(created_at: :asc)
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.create_for(model, user, comment)
 | 
					  def self.create_for(model, user, comment)
 | 
				
			||||||
		create(
 | 
					    create(
 | 
				
			||||||
			model_type: model.class.name.tableize,
 | 
					      model_type: model.class.name.tableize,
 | 
				
			||||||
			model_id: model.id,
 | 
					      model_id: model.id,
 | 
				
			||||||
			user_id: user.id,
 | 
					      user_id: user.id,
 | 
				
			||||||
			comment: comment
 | 
					      comment: comment
 | 
				
			||||||
		)
 | 
					    )
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_comment(user, comment)
 | 
					    def add_comment(user, comment)
 | 
				
			||||||
        Comment.create_for(self, user, comment)
 | 
					        Comment.create_for(self, user, comment)
 | 
				
			||||||
@ -32,6 +32,6 @@ class Comment < ActiveRecord::Base
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def reply?
 | 
					    def reply?
 | 
				
			||||||
    	model_type == 'comments'
 | 
					      model_type == 'comments'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -1,71 +1,136 @@
 | 
				
			|||||||
class Conference < ActiveRecord::Base
 | 
					class Conference < ActiveRecord::Base
 | 
				
			||||||
	translates :info, :title, :payment_message
 | 
					  translates :info, :title, :payment_message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mount_uploader :cover, CoverUploader
 | 
					  mount_uploader :cover, CoverUploader
 | 
				
			||||||
	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 :event_locations
 | 
					  has_many :conference_administrators, dependent: :destroy
 | 
				
			||||||
 | 
					  has_many :administrators, through: :conference_administrators, source: :user
 | 
				
			||||||
 | 
					  has_many :event_locations
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
	#has_many :conference_registration_form_fields, :order => 'position ASC', :dependent => :destroy#, :class_name => '::ConferenceRegistrationFormField'
 | 
					  has_many :workshops
 | 
				
			||||||
	#has_many :registration_form_fields, :through => :conference_registration_form_fields
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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?(user)
 | 
					  def host_organization?(org)
 | 
				
			||||||
		return false unless user.present?
 | 
					    return false unless org.present?
 | 
				
			||||||
		organizations.each do |o|
 | 
					    org_id = org.is_a?(Organization) ? org.id : org
 | 
				
			||||||
			return true if o.host?(user)
 | 
					 | 
				
			||||||
		end
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def url(action = :show)
 | 
					    organizations.each do |o|
 | 
				
			||||||
		path(action)
 | 
					      return true if o.id = org_id
 | 
				
			||||||
	end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def path(action = :show)
 | 
					    return false
 | 
				
			||||||
		action = action.to_sym
 | 
					  end
 | 
				
			||||||
		'/conferences/' + conference_type.slug + '/' + slug + (action == :show ? '' : '/' + action.to_s)
 | 
					 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def location
 | 
					  def host?(user)
 | 
				
			||||||
		organizations.first.location
 | 
					    if user.present?
 | 
				
			||||||
	end
 | 
					      return true if user.administrator?
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
	def registered?(user)
 | 
					      conference_administrators.each do |u|
 | 
				
			||||||
		registration = ConferenceRegistration.find_by(:user_id => user.id, :conference_id => id)
 | 
					        return true if user.id == u.id
 | 
				
			||||||
		return registration ? registration.is_attending : false
 | 
					      end
 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
	def registration_exists?(user)
 | 
					      organizations.each do |o|
 | 
				
			||||||
		ConferenceRegistration.find_by(:user_id => user.id, :conference_id => id).present?
 | 
					        return true if o.host?(user)
 | 
				
			||||||
	end
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    return false
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def registration_open
 | 
					  def url(action = :show)
 | 
				
			||||||
		registration_status == :open
 | 
					    path(action)
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def registration_status
 | 
					  def path(action = :show)
 | 
				
			||||||
		s = read_attribute(:registration_status)
 | 
					    action = action.to_sym
 | 
				
			||||||
		s.present? ? s.to_sym : nil
 | 
					    '/conferences/' + conference_type.slug + '/' + slug + (action == :show ? '' : '/' + action.to_s)
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def registration_status=(new_registration_status)
 | 
					  def location
 | 
				
			||||||
		write_attribute :registration_status, new_registration_status.to_s
 | 
					    return nil unless organizations.present?
 | 
				
			||||||
	end
 | 
					    organizations.first.location
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.default_payment_amounts
 | 
					  def registered?(user)
 | 
				
			||||||
		[25, 50, 100]
 | 
					    registration = ConferenceRegistration.find_by(:user_id => user.id, :conference_id => id)
 | 
				
			||||||
	end
 | 
					    return registration ? registration.is_attending : false
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def registration_exists?(user)
 | 
				
			||||||
 | 
					    ConferenceRegistration.find_by(:user_id => user.id, :conference_id => id).present?
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def registration_open
 | 
				
			||||||
 | 
					    registration_status == :open
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def registration_status
 | 
				
			||||||
 | 
					    s = read_attribute(:registration_status)
 | 
				
			||||||
 | 
					    s.present? ? s.to_sym : nil
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def registration_status=(new_registration_status)
 | 
				
			||||||
 | 
					    write_attribute :registration_status, new_registration_status.to_s
 | 
				
			||||||
 | 
					  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
 | 
				
			||||||
 | 
					    [25, 50, 100]
 | 
				
			||||||
 | 
					  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
 | 
				
			||||||
@ -1,58 +1,58 @@
 | 
				
			|||||||
class ConferenceRegistration < ActiveRecord::Base
 | 
					class ConferenceRegistration < ActiveRecord::Base
 | 
				
			||||||
	belongs_to :conference
 | 
					  belongs_to :conference
 | 
				
			||||||
	belongs_to :user
 | 
					  belongs_to :user
 | 
				
			||||||
	has_many :conference_registration_responses
 | 
					  has_many :conference_registration_responses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AttendingOptions = [:yes, :no]
 | 
					  AttendingOptions = [:yes, :no]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def languages
 | 
					  def languages
 | 
				
			||||||
		user.languages
 | 
					    user.languages
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.all_housing_options
 | 
					  def self.all_housing_options
 | 
				
			||||||
		[:none, :tent, :house]
 | 
					    [:none, :tent, :house]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.all_spaces
 | 
					  def self.all_spaces
 | 
				
			||||||
		[:bed_space, :floor_space, :tent_space]
 | 
					    [:bed_space, :floor_space, :tent_space]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.all_bike_options
 | 
					  def self.all_bike_options
 | 
				
			||||||
		[:yes, :no]
 | 
					    [:yes, :no]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.all_food_options
 | 
					  def self.all_food_options
 | 
				
			||||||
		[:meat, :vegetarian, :vegan]
 | 
					    [:meat, :vegetarian, :vegan]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.all_considerations
 | 
					  def self.all_considerations
 | 
				
			||||||
		[:vegan, :smoking, :pets, :quiet]
 | 
					    [:vegan, :smoking, :pets, :quiet]
 | 
				
			||||||
	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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	around_update :check_status
 | 
					  around_update :check_status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def check_status
 | 
					  def check_status
 | 
				
			||||||
		yield
 | 
					    yield
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
		old_status = status(true)
 | 
					    old_status = status(true)
 | 
				
			||||||
		new_status = status
 | 
					    new_status = status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if old_status.present? && old_status != new_status
 | 
					    if old_status.present? && old_status != new_status
 | 
				
			||||||
			if (conference.registration_status == :pre && new_status == :preregistered) ||
 | 
					      if (conference.registration_status == :pre && new_status == :preregistered) ||
 | 
				
			||||||
				(conference.registration_status == :open && new_status == :registered)
 | 
					        (conference.registration_status == :open && new_status == :registered)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				UserMailer.send_mail :registration_confirmation do
 | 
					        UserMailer.send_mail :registration_confirmation do
 | 
				
			||||||
					{
 | 
					          {
 | 
				
			||||||
						:args => self
 | 
					            :args => self
 | 
				
			||||||
					}
 | 
					          }
 | 
				
			||||||
				end
 | 
					        end
 | 
				
			||||||
			end
 | 
					      end
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -1,20 +1,20 @@
 | 
				
			|||||||
class Event < ActiveRecord::Base
 | 
					class Event < ActiveRecord::Base
 | 
				
			||||||
    translates :info, :title
 | 
					  translates :info, :title
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    belongs_to :conference
 | 
					  belongs_to :conference
 | 
				
			||||||
    belongs_to :event_location
 | 
					  belongs_to :event_location
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def conference_day
 | 
					  def conference_day
 | 
				
			||||||
        return nil unless start_time.present? && end_time.present?
 | 
					    return nil unless start_time.present? && end_time.present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        start_day = conference.start_date.change(hour: 0, minute: 0, second: 0)
 | 
					    start_day = conference.start_date.change(hour: 0, minute: 0, second: 0)
 | 
				
			||||||
        w_start_day = start_time.change(hour: 0, minute: 0, second: 0)
 | 
					    w_start_day = start_time.change(hour: 0, minute: 0, second: 0)
 | 
				
			||||||
        return (((w_start_day - start_day) / 86400) + 1).to_i
 | 
					    return (((w_start_day - start_day) / 86400) + 1).to_i
 | 
				
			||||||
    end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def duration
 | 
					  def duration
 | 
				
			||||||
        return nil unless start_time.present? && end_time.present?
 | 
					    return nil unless start_time.present? && end_time.present?
 | 
				
			||||||
        ((end_time - start_time) / 60).to_i
 | 
					    ((end_time - start_time) / 60).to_i
 | 
				
			||||||
    end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
class LocationsOrganization < ActiveRecord::Base
 | 
					class LocationsOrganization < ActiveRecord::Base
 | 
				
			||||||
	belongs_to :location
 | 
					  belongs_to :location
 | 
				
			||||||
	belongs_to :organization
 | 
					  belongs_to :organization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	self.primary_key = :location_id
 | 
					  self.primary_key = :location_id
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -1,71 +1,77 @@
 | 
				
			|||||||
class Organization < ActiveRecord::Base
 | 
					class Organization < ActiveRecord::Base
 | 
				
			||||||
	mount_uploader :logo, LogoUploader
 | 
					  mount_uploader :logo, LogoUploader
 | 
				
			||||||
	mount_uploader :avatar, AvatarUploader
 | 
					  mount_uploader :avatar, AvatarUploader
 | 
				
			||||||
	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
 | 
				
			||||||
	before_create :make_slug
 | 
					  before_create :make_slug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def location
 | 
					  def location
 | 
				
			||||||
		locations.first
 | 
					    locations.first
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def longitude
 | 
					  def longitude
 | 
				
			||||||
		location.longitude
 | 
					    location.longitude
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def latitude
 | 
					  def latitude
 | 
				
			||||||
		location.latitude
 | 
					    location.latitude
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def to_param
 | 
					  def to_param
 | 
				
			||||||
		slug
 | 
					    slug
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def host?(user)
 | 
					  def host?(user)
 | 
				
			||||||
		return false unless user.present?
 | 
					    return false unless user.present?
 | 
				
			||||||
		return true if user.administrator?
 | 
					    return true if user.administrator?
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
		users.each do |u|
 | 
					    users.each do |u|
 | 
				
			||||||
			return true if u.id == user.id
 | 
					      return true if u.id == user.id
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
		return false
 | 
					    return false
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def generate_slug(name, location = nil)
 | 
					  def generate_slug(name, location = nil)
 | 
				
			||||||
		s = name.gsub(/[^a-z1-9]+/i, '-').chomp('-').gsub(/\-([A-Z])/, '\1')
 | 
					    s = name.gsub(/[^a-z1-9]+/i, '-').chomp('-').gsub(/\-([A-Z])/, '\1')
 | 
				
			||||||
		if Organization.find_by(:slug => s).present? && !location.nil?
 | 
					    if Organization.find_by(:slug => s).present? && !location.nil?
 | 
				
			||||||
			if location.city.present?
 | 
					      if location.city.present?
 | 
				
			||||||
				s += '-' + location.city
 | 
					        s += '-' + location.city
 | 
				
			||||||
			end
 | 
					      end
 | 
				
			||||||
			if Organization.find_by(:slug => s).present? && location.territory.present?
 | 
					      if Organization.find_by(:slug => s).present? && location.territory.present?
 | 
				
			||||||
				s += '-' + location.territory
 | 
					        s += '-' + location.territory
 | 
				
			||||||
			end
 | 
					      end
 | 
				
			||||||
			if Organization.find_by(:slug => s).present?
 | 
					      if Organization.find_by(:slug => s).present?
 | 
				
			||||||
				s += '-' + location.country
 | 
					        s += '-' + location.country
 | 
				
			||||||
			end
 | 
					      end
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
		attempt = 1
 | 
					    attempt = 1
 | 
				
			||||||
		ss = s
 | 
					    ss = s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		while Organization.find_by(:slug => s)
 | 
					    while Organization.find_by(:slug => s)
 | 
				
			||||||
			attempt += 1
 | 
					      attempt += 1
 | 
				
			||||||
			s = ss + '-' + attempt.to_s
 | 
					      s = ss + '-' + attempt.to_s
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
		s
 | 
					    s
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private
 | 
					  def self.find_by_city(city)
 | 
				
			||||||
		def make_slug
 | 
					    Organization.joins(:locations).where(locations: {
 | 
				
			||||||
			if !self.slug
 | 
					        city_id: city.is_a?(City) ? city.id : city
 | 
				
			||||||
				self.slug = generate_slug(self.name, self.locations && self.locations[0])
 | 
					      })
 | 
				
			||||||
			end
 | 
					  end
 | 
				
			||||||
		end
 | 
					
 | 
				
			||||||
 | 
					  private
 | 
				
			||||||
 | 
					    def make_slug
 | 
				
			||||||
 | 
					      if !self.slug
 | 
				
			||||||
 | 
					        self.slug = generate_slug(self.name, self.locations && self.locations[0])
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -1,62 +1,67 @@
 | 
				
			|||||||
class User < ActiveRecord::Base
 | 
					class User < ActiveRecord::Base
 | 
				
			||||||
	authenticates_with_sorcery! do |config|
 | 
					  authenticates_with_sorcery! do |config|
 | 
				
			||||||
        config.authentications_class = Authentication
 | 
					        config.authentications_class = Authentication
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	validates :email, uniqueness: true
 | 
					  validates :email, uniqueness: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mount_uploader :avatar, AvatarUploader
 | 
					  mount_uploader :avatar, AvatarUploader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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 :authentications, :dependent => :destroy
 | 
					  has_many :conferences, through: :conference_administrators
 | 
				
			||||||
    accepts_nested_attributes_for :authentications
 | 
					  has_many :authentications, :dependent => :destroy
 | 
				
			||||||
 | 
					  accepts_nested_attributes_for :authentications
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	before_update do |user|
 | 
					  before_update do |user|
 | 
				
			||||||
		user.locale ||= I18n.locale
 | 
					    user.locale ||= I18n.locale
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	before_save do |user|
 | 
					  before_save do |user|
 | 
				
			||||||
		user.locale ||= I18n.locale
 | 
					    user.locale ||= I18n.locale
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def can_translate?(to_locale = nil, from_locale = nil)
 | 
					  def can_translate?(to_locale = nil, from_locale = nil)
 | 
				
			||||||
		is_translator unless to_locale.present?
 | 
					    is_translator unless to_locale.present?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		from_locale = I18n.locale unless from_locale.present?
 | 
					    from_locale = I18n.locale unless from_locale.present?
 | 
				
			||||||
		return languages.present? &&
 | 
					    return languages.present? &&
 | 
				
			||||||
			to_locale.to_s != from_locale.to_s &&
 | 
					      to_locale.to_s != from_locale.to_s &&
 | 
				
			||||||
			languages.include?(to_locale.to_s) &&
 | 
					      languages.include?(to_locale.to_s) &&
 | 
				
			||||||
			languages.include?(from_locale.to_s)
 | 
					      languages.include?(from_locale.to_s)
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def name
 | 
					  def name
 | 
				
			||||||
		firstname || username || email
 | 
					    firstname || username || email
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def named_email
 | 
					  def named_email
 | 
				
			||||||
		name = firstname || username
 | 
					    name = firstname || username
 | 
				
			||||||
		return email unless name
 | 
					    return email unless name
 | 
				
			||||||
		return "#{name} <#{email}>"
 | 
					    return "#{name} <#{email}>"
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def administrator?
 | 
					  def administrator?
 | 
				
			||||||
		role == 'administrator'
 | 
					    role == 'administrator'
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.AVAILABLE_LANGUAGES
 | 
					  def self.AVAILABLE_LANGUAGES
 | 
				
			||||||
		[:en, :es, :fr, :ar]
 | 
					    [:en, :es, :fr, :ar]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def self.get(email)
 | 
					  def self.get(email)
 | 
				
			||||||
		user = where(email: email).first
 | 
					    user = where(email: email).first
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		unless user
 | 
					    unless user
 | 
				
			||||||
			user = new(email: email)
 | 
					      user = new(email: email)
 | 
				
			||||||
			user.save!
 | 
					      user.save!
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return user
 | 
					    return user
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def self.find_user(email)
 | 
				
			||||||
 | 
					    User.where('lower(email) = ?', email.downcase).first
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,11 @@
 | 
				
			|||||||
class UserOrganizationRelationship < ActiveRecord::Base
 | 
					class UserOrganizationRelationship < ActiveRecord::Base
 | 
				
			||||||
	belongs_to :user
 | 
					  belongs_to :user
 | 
				
			||||||
	belongs_to :organization
 | 
					  belongs_to :organization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Administrator = 'administrator'
 | 
					  Administrator = 'administrator'
 | 
				
			||||||
	Member = 'member'
 | 
					  Member = 'member'
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
	DefaultRelationship = Member
 | 
					  DefaultRelationship = Member
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AllRelationships = [Administrator, Member]
 | 
					  AllRelationships = [Administrator, Member]
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -3,102 +3,102 @@ require 'carrierwave/processing/mini_magick'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class AvatarUploader < CarrierWave::Uploader::Base
 | 
					class AvatarUploader < CarrierWave::Uploader::Base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	include CarrierWave::ImageOptimizer
 | 
					  include CarrierWave::ImageOptimizer
 | 
				
			||||||
	include CarrierWave::MiniMagick
 | 
					  include CarrierWave::MiniMagick
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Include RMagick or MiniMagick support:
 | 
					  # Include RMagick or MiniMagick support:
 | 
				
			||||||
	# include CarrierWave::RMagick
 | 
					  # include CarrierWave::RMagick
 | 
				
			||||||
	# include CarrierWave::MiniMagick
 | 
					  # include CarrierWave::MiniMagick
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Choose what kind of storage to use for this uploader:
 | 
					  # Choose what kind of storage to use for this uploader:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	storage :file
 | 
					  storage :file
 | 
				
			||||||
	process :optimize
 | 
					  process :optimize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@@sizes = {:thumb => [120, 120], :icon => [48, 48], :preview => [360, 120], :normal => [512, 512]}
 | 
					  @@sizes = {:thumb => [120, 120], :icon => [48, 48], :preview => [360, 120], :normal => [512, 512]}
 | 
				
			||||||
	# storage :fog
 | 
					  # storage :fog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Override the directory where uploaded files will be stored.
 | 
					  # Override the directory where uploaded files will be stored.
 | 
				
			||||||
	# This is a sensible default for uploaders that are meant to be mounted:
 | 
					  # This is a sensible default for uploaders that are meant to be mounted:
 | 
				
			||||||
	def store_dir
 | 
					  def store_dir
 | 
				
			||||||
		"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
 | 
					    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
 | 
				
			||||||
	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]
 | 
				
			||||||
	#
 | 
					  #
 | 
				
			||||||
	#def scale(width, height)
 | 
					  #def scale(width, height)
 | 
				
			||||||
	#end
 | 
					  #end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Create different versions of your uploaded files:
 | 
					  # Create different versions of your uploaded files:
 | 
				
			||||||
	version :thumb do
 | 
					  version :thumb do
 | 
				
			||||||
		process :resize_to_fill => @@sizes[:thumb]
 | 
					    process :resize_to_fill => @@sizes[:thumb]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version :icon do
 | 
					  version :icon do
 | 
				
			||||||
		process :resize_to_fill => @@sizes[:icon]
 | 
					    process :resize_to_fill => @@sizes[:icon]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version :preview do
 | 
					  version :preview do
 | 
				
			||||||
		process :resize_to_fit => @@sizes[:preview]
 | 
					    process :resize_to_fit => @@sizes[:preview]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version :normal do
 | 
					  version :normal do
 | 
				
			||||||
		process :resize_to_fit => @@sizes[:normal]
 | 
					    process :resize_to_fit => @@sizes[:normal]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Add a white list of extensions which are allowed to be uploaded.
 | 
					  # Add a white list of extensions which are allowed to be uploaded.
 | 
				
			||||||
	# For images you might use something like this:
 | 
					  # For images you might use something like this:
 | 
				
			||||||
	# def extension_white_list
 | 
					  # def extension_white_list
 | 
				
			||||||
	#	 %w(jpg jpeg gif png)
 | 
					  #  %w(jpg jpeg gif png)
 | 
				
			||||||
	# end
 | 
					  # end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Override the filename of the uploaded files:
 | 
					  # Override the filename of the uploaded files:
 | 
				
			||||||
	# Avoid using model.id or version_name here, see uploader/store.rb for details.
 | 
					  # Avoid using model.id or version_name here, see uploader/store.rb for details.
 | 
				
			||||||
	# def filename
 | 
					  # def filename
 | 
				
			||||||
	#	 "something.jpg" if original_filename
 | 
					  #  "something.jpg" if original_filename
 | 
				
			||||||
	# end
 | 
					  # end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def image
 | 
					  def image
 | 
				
			||||||
		@image ||= MiniMagick::Image.open(file.path)
 | 
					    @image ||= MiniMagick::Image.open(file.path)
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def is_landscape?
 | 
					  def is_landscape?
 | 
				
			||||||
		image['width'] > (image['height'] * 1.25)
 | 
					    image['width'] > (image['height'] * 1.25)
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#def recreate_versions!(*versions)
 | 
					  #def recreate_versions!(*versions)
 | 
				
			||||||
	#	if !current_path.nil?
 | 
					  # if !current_path.nil?
 | 
				
			||||||
	#		current_path = "'" + (current_path || '') + "'"
 | 
					  #   current_path = "'" + (current_path || '') + "'"
 | 
				
			||||||
	#	end
 | 
					  # end
 | 
				
			||||||
	#	super(*versions)
 | 
					  # super(*versions)
 | 
				
			||||||
	#end
 | 
					  #end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#	def manipulate!
 | 
					# def manipulate!
 | 
				
			||||||
#		cache_stored_file! if !cached?
 | 
					#   cache_stored_file! if !cached?
 | 
				
			||||||
#		image = ::MiniMagick::Image.open(current_path)
 | 
					#   image = ::MiniMagick::Image.open(current_path)
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#		begin
 | 
					#   begin
 | 
				
			||||||
#			image.format(@format.to_s.downcase) if @format
 | 
					#     image.format(@format.to_s.downcase) if @format
 | 
				
			||||||
#			image = yield(image)
 | 
					#     image = yield(image)
 | 
				
			||||||
#			image.write(current_path)
 | 
					#     image.write(current_path)
 | 
				
			||||||
#			image.run_command("identify", '"' + current_path + '"')
 | 
					#     image.run_command("identify", '"' + current_path + '"')
 | 
				
			||||||
#		ensure
 | 
					#   ensure
 | 
				
			||||||
#			image.destroy!
 | 
					#     image.destroy!
 | 
				
			||||||
#		end
 | 
					#   end
 | 
				
			||||||
#	rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
 | 
					# rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
 | 
				
			||||||
#		default = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :locale => :en)
 | 
					#   default = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :locale => :en)
 | 
				
			||||||
#		message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :default => default)
 | 
					#   message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :default => default)
 | 
				
			||||||
#		raise CarrierWave::ProcessingError, message
 | 
					#   raise CarrierWave::ProcessingError, message
 | 
				
			||||||
#	end
 | 
					# end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -3,67 +3,67 @@ require 'carrierwave/processing/mini_magick'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class PosterUploader < CarrierWave::Uploader::Base
 | 
					class PosterUploader < CarrierWave::Uploader::Base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	include CarrierWave::ImageOptimizer
 | 
					  include CarrierWave::ImageOptimizer
 | 
				
			||||||
	include CarrierWave::MiniMagick
 | 
					  include CarrierWave::MiniMagick
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	storage :file
 | 
					  storage :file
 | 
				
			||||||
	process :optimize
 | 
					  process :optimize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@@sizes = {
 | 
					  @@sizes = {
 | 
				
			||||||
		:thumb   => [120,  120],
 | 
					    :thumb   => [120,  120],
 | 
				
			||||||
		:icon    => [48,   48],
 | 
					    :icon    => [48,   48],
 | 
				
			||||||
		:preview => [512,  512],
 | 
					    :preview => [512,  512],
 | 
				
			||||||
		:full    => [1024, 1024]
 | 
					    :full    => [1024, 1024]
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def store_dir
 | 
					  def store_dir
 | 
				
			||||||
		"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
 | 
					    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version :thumb do
 | 
					  version :thumb do
 | 
				
			||||||
		process :resize_to_fill => @@sizes[:thumb]
 | 
					    process :resize_to_fill => @@sizes[:thumb]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version :icon do
 | 
					  version :icon do
 | 
				
			||||||
		process :resize_to_fill => @@sizes[:icon]
 | 
					    process :resize_to_fill => @@sizes[:icon]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version :preview do
 | 
					  version :preview do
 | 
				
			||||||
		process :resize_to_fit => @@sizes[:preview]
 | 
					    process :resize_to_fit => @@sizes[:preview]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version :full do
 | 
					  version :full do
 | 
				
			||||||
		process :resize_to_fit => @@sizes[:full]
 | 
					    process :resize_to_fit => @@sizes[:full]
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def image
 | 
					  def image
 | 
				
			||||||
		@image ||= MiniMagick::Image.open(file.path)
 | 
					    @image ||= MiniMagick::Image.open(file.path)
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def is_landscape?
 | 
					  def is_landscape?
 | 
				
			||||||
		image['width'] > image['height']
 | 
					    image['width'] > image['height']
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def manipulate!
 | 
					  def manipulate!
 | 
				
			||||||
		cache_stored_file! if !cached?
 | 
					    cache_stored_file! if !cached?
 | 
				
			||||||
		image = ::MiniMagick::Image.open(current_path)
 | 
					    image = ::MiniMagick::Image.open(current_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		begin
 | 
					    begin
 | 
				
			||||||
			image.format(@format.to_s.downcase) if @format
 | 
					      image.format(@format.to_s.downcase) if @format
 | 
				
			||||||
			image = yield(image)
 | 
					      image = yield(image)
 | 
				
			||||||
			image.write(current_path)
 | 
					      image.write(current_path)
 | 
				
			||||||
			begin
 | 
					      begin
 | 
				
			||||||
				image.run_command("identify", current_path)
 | 
					        image.run_command("identify", current_path)
 | 
				
			||||||
			rescue
 | 
					      rescue
 | 
				
			||||||
				image.run_command("identify", '"' + current_path + '"')
 | 
					        image.run_command("identify", '"' + current_path + '"')
 | 
				
			||||||
			end
 | 
					      end
 | 
				
			||||||
		ensure
 | 
					    ensure
 | 
				
			||||||
			image.destroy!
 | 
					      image.destroy!
 | 
				
			||||||
		end
 | 
					    end
 | 
				
			||||||
	rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
 | 
					  rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
 | 
				
			||||||
		default = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :locale => :en)
 | 
					    default = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :locale => :en)
 | 
				
			||||||
		message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :default => default)
 | 
					    message = I18n.translate(:"errors.messages.mini_magick_processing_error", :e => e, :default => default)
 | 
				
			||||||
		raise CarrierWave::ProcessingError, message
 | 
					    raise CarrierWave::ProcessingError, message
 | 
				
			||||||
	end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										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'
 | 
				
			||||||
@ -1,20 +1,20 @@
 | 
				
			|||||||
- content_for :banner do
 | 
					- content_for :banner do
 | 
				
			||||||
	- image = image_path(image_file || 'empty-racks.jpg')
 | 
					  - image = image_path(image_file || 'empty-racks.jpg')
 | 
				
			||||||
	- style = nil
 | 
					  - style = nil
 | 
				
			||||||
	- cover = nil
 | 
					  - cover = nil
 | 
				
			||||||
	- figure = nil
 | 
					  - figure = nil
 | 
				
			||||||
	- if capable_of(:css_mixblendmode)
 | 
					  - if capable_of(:css_mixblendmode)
 | 
				
			||||||
		- cover = "<div class=\"cover\" style=\"background-image: url(#{image})\"></div>"
 | 
					    - cover = "<div class=\"cover\" style=\"background-image: url(#{image})\"></div>"
 | 
				
			||||||
	- else
 | 
					  - else
 | 
				
			||||||
		- style = "background-image: url(#{image})"
 | 
					    - style = "background-image: url(#{image})"
 | 
				
			||||||
	#header-title.short{style: style}
 | 
					  #header-title.short{style: style}
 | 
				
			||||||
		= (render banner_image, {:image => image}) if defined?(banner_image) == "local-variable"
 | 
					    = (render banner_image, {:image => image}) if defined?(banner_image) == "local-variable"
 | 
				
			||||||
		= 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 })
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,25 +1,25 @@
 | 
				
			|||||||
= render :partial => 'application/header', :locals => {:image_file => @banner_image || 'grafitti.jpg'}
 | 
					= render :partial => 'application/header', :locals => {:image_file => @banner_image || 'grafitti.jpg'}
 | 
				
			||||||
%article
 | 
					%article
 | 
				
			||||||
	= row do
 | 
					  = row do
 | 
				
			||||||
		= columns do
 | 
					    = columns do
 | 
				
			||||||
			- if logged_in?
 | 
					      - if logged_in?
 | 
				
			||||||
				%h2=_'articles.user_settings.headings.Your_Account'
 | 
					        %h2=_'articles.user_settings.headings.Your_Account'
 | 
				
			||||||
				- if @conference.present? && (@conference.registration_status == :pre || @conference.registration_status == :open)
 | 
					        - if @conference.present? && (@conference.registration_status == :pre || @conference.registration_status == :open)
 | 
				
			||||||
					%p=_'articles.user_settings.paragraphs.conference_registration', :t
 | 
					          %p=_'articles.user_settings.paragraphs.conference_registration', :t
 | 
				
			||||||
					= link_to (_'actions.conference.edit_registration'), register_path(@conference.slug), class: :button
 | 
					          = link_to (_'actions.conference.edit_registration'), register_path(@conference.slug), class: :button
 | 
				
			||||||
				- if @conferences.present?
 | 
					        - if @conferences.present?
 | 
				
			||||||
					%h3=_'articles.user_settings.headings.Your_Conferences'
 | 
					          %h3=_'articles.user_settings.headings.Your_Conferences'
 | 
				
			||||||
					.link-dump
 | 
					          .link-dump
 | 
				
			||||||
						- @conferences.each do | conference |
 | 
					            - @conferences.each do | conference |
 | 
				
			||||||
							= link_to (_!conference.title), administration_step_path(conference.slug, :edit), class: :button
 | 
					              = link_to (_!conference.title), administration_step_path(conference.slug, :edit), class: :button
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				= form_tag update_settings_path do
 | 
					        = form_tag update_settings_path do
 | 
				
			||||||
					= textfield :name, current_user.name, required: true, heading: 'articles.conference_registration.headings.name', big: true
 | 
					          = textfield :name, current_user.name, required: true, heading: 'articles.conference_registration.headings.name', big: true
 | 
				
			||||||
					= checkboxes :languages, User.AVAILABLE_LANGUAGES, current_user.languages || [I18n.locale], 'languages', heading: 'articles.conference_registration.headings.languages'
 | 
					          = checkboxes :languages, User.AVAILABLE_LANGUAGES, current_user.languages || [I18n.locale], 'languages', heading: 'articles.conference_registration.headings.languages'
 | 
				
			||||||
					= radiobuttons :preferred_language, I18n.backend.enabled_locales, current_user.locale || I18n.locale, 'languages', heading: 'articles.conference_registration.headings.preferred_language'
 | 
					          = radiobuttons :preferred_language, I18n.backend.enabled_locales, current_user.locale || I18n.locale, 'languages', heading: 'articles.conference_registration.headings.preferred_language'
 | 
				
			||||||
					= checkbox :email_subscribe, current_user.is_subscribed != false, 'articles.user_settings.email_subscribe', heading: 'articles.user_settings.headings.email_subscribe', help: 'articles.user_settings.paragraphs.email_subscribe', inline: true, right_help: true
 | 
					          = checkbox :email_subscribe, current_user.is_subscribed != false, 'articles.user_settings.email_subscribe', heading: 'articles.user_settings.headings.email_subscribe', help: 'articles.user_settings.paragraphs.email_subscribe', inline: true, right_help: true
 | 
				
			||||||
					.actions
 | 
					          .actions
 | 
				
			||||||
						= button_tag :save, value: :save
 | 
					            = button_tag :save, value: :save
 | 
				
			||||||
			- else
 | 
					      - else
 | 
				
			||||||
				%h2=_'forms.actions.generic.login'
 | 
					        %h2=_'forms.actions.generic.login'
 | 
				
			||||||
				= render 'login'
 | 
					        = render 'login'
 | 
				
			||||||
@ -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
 | 
				
			||||||