Skip to content

Commit

Permalink
Merge branch 'dev' into dev-france
Browse files Browse the repository at this point in the history
  • Loading branch information
nicmarti committed May 8, 2016
2 parents 212a832 + 44b3731 commit fd7bea1
Show file tree
Hide file tree
Showing 15 changed files with 296 additions and 129 deletions.
121 changes: 121 additions & 0 deletions app/controllers/PaperGuide.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2013 Association du Paris Java User Group.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package controllers

import java.io.{PrintWriter, File}

import models.{Speaker, Slot, ConferenceDescriptor, ScheduleConfiguration}
import org.apache.commons.lang3.StringEscapeUtils
import play.api.i18n.Messages

/**
* Simple controller used to export the whole program as a CSV file.
* Practical if you want to print the schedule.
*
* @author created by N.Martignole, Innoteria, on 11/04/16.
*/
object PaperGuide extends SecureCFPController {

def exportProgram() = SecuredAction(IsMemberOf("cfp")) {
implicit request: SecuredRequest[play.api.mvc.AnyContent] =>
implicit val context = scala.concurrent.ExecutionContext.Implicits.global


val allScheduledConf: List[ScheduleConfiguration] = for (confType <- ConferenceDescriptor.ConferenceProposalTypes.ALL;
scheduleId <- ScheduleConfiguration.getPublishedSchedule(confType.id);
scheduledConf <- ScheduleConfiguration.loadScheduledConfiguration(scheduleId)
) yield scheduledConf

val file = new File("./target", "DEVOXX_UTF8_" + allScheduledConf.hashCode() + ".csv")
val writer = new PrintWriter(file, "MacRoman") // !!! ENCODING !!!
// val writer = new PrintWriter(file, "UTF-8")
writer.println("id,name,day,from,to,roomName,proposalId,proposalTitle,proposalLang,track,firstSpeaker,secondarySpeaker,thirdSpeaker,fourthSpeaker,fifthSpeaker")

allScheduledConf.foreach {
scheduleConf: ScheduleConfiguration =>
scheduleConf.slots.foreach {
slot: Slot =>
writer.print(slot.id)
writer.print(",")
writer.print(slot.name)
writer.print(",")
writer.print(slot.day)
writer.print(",")
writer.print(slot.from.toString("HH:mm"))
writer.print(",")
writer.print(slot.to.toString("HH:mm"))
writer.print(",")
writer.print(slot.room.name)
writer.print(",")
slot.proposal.map {
proposal =>
writer.print(proposal.id)
writer.print(",")
writer.print(StringEscapeUtils.escapeCsv(proposal.title))
writer.print(",")
writer.print(proposal.lang)
writer.print(",")
writer.print(StringEscapeUtils.escapeCsv(Messages(proposal.track.label)))
writer.print(",")

Speaker.findByUUID(proposal.mainSpeaker).map {
speaker: Speaker =>
writer.print(StringEscapeUtils.escapeCsv(speaker.cleanName))
writer.print(",")
}.getOrElse(writer.print(",,"))

proposal.secondarySpeaker.map {
secSpeaker =>
Speaker.findByUUID(secSpeaker).map {
s: Speaker =>
writer.print(StringEscapeUtils.escapeCsv(s.cleanName))
writer.print(",")
}.getOrElse(writer.print(",,"))
}.getOrElse(writer.print(",,"))

val otherSpeakersNames = proposal.otherSpeakers.map{
id:String=>
Speaker.findByUUID(id).map{s=>
StringEscapeUtils.escapeCsv(s.cleanName) + ","
}.getOrElse(",,")
}

val paddedToSixSpeakers = otherSpeakersNames.padTo(6,",")

paddedToSixSpeakers.foreach{token=>writer.print(token)}

}.getOrElse {
writer.print(",,,,,,,,")
}
writer.println("")

}
}
writer.close()

Ok("Done - Check target CFP folder")

}

}
50 changes: 28 additions & 22 deletions app/controllers/Publisher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ package controllers

import akka.util.Crypt
import library.search.ElasticSearch
import library.{LogURL, SendQuestionToSpeaker, ZapActor}
import library.{LogURL, ZapActor}
import models._
import play.api.cache.Cache
import play.api.data.Form
Expand All @@ -36,14 +36,14 @@ import play.api.mvc._


/**
* Publisher is the controller responsible for the Web content of your conference Program.
* Created by nicolas on 12/02/2014.
*/
* Publisher is the controller responsible for the Web content of your conference Program.
* Created by nicolas on 12/02/2014.
*/
object Publisher extends Controller {
def homePublisher = Action {
implicit request =>
val result = views.html.Publisher.homePublisher()
val etag = Crypt.md5(result.toString()+"dvx").toString
val etag = Crypt.md5(result.toString() + "dvx").toString
val maybeETag = request.headers.get(IF_NONE_MATCH)

maybeETag match {
Expand All @@ -54,16 +54,23 @@ object Publisher extends Controller {

def showAllSpeakers = Action {
implicit request =>
import play.api.Play.current
val speakers = Cache.getOrElse[List[Speaker]]("allSpeakersWithAcceptedTerms", 600) {
Speaker.allSpeakersWithAcceptedTerms()
}
val etag = speakers.hashCode().toString + "_2"
val maybeETag = request.headers.get(IF_NONE_MATCH)
maybeETag match {
case Some(oldEtag) if oldEtag == etag => NotModified
case other => Ok(views.html.Publisher.showAllSpeakers(speakers)).withHeaders(ETAG -> etag)

// First load published slots
val publishedConf = ScheduleConfiguration.loadAllPublishedSlots().filter(_.proposal.isDefined)
val allSpeakersIDs = publishedConf.flatMap(_.proposal.get.allSpeakerUUIDs).toSet
val etag = allSpeakersIDs.hashCode.toString

request.headers.get(IF_NONE_MATCH) match {
case Some(tag) if tag == etag =>
NotModified

case other =>
val onlySpeakersThatAcceptedTerms: Set[String] = allSpeakersIDs.filterNot(uuid => Speaker.needsToAccept(uuid))
val speakers = Speaker.loadSpeakersFromSpeakerIDs(onlySpeakersThatAcceptedTerms)
Ok(views.html.Publisher.showAllSpeakers(speakers)).withHeaders(ETAG -> etag)

}

}

def showSpeakerByName(name: String) = Action {
Expand Down Expand Up @@ -126,40 +133,40 @@ object Publisher extends Controller {
maybeScheduledConfiguration match {
case Some(slotConfig) if day == null => {
val updatedConf = slotConfig.copy(slots = slotConfig.slots)
Ok(views.html.Publisher.showAgendaByConfType(updatedConf, confType, "wednesday"))
Ok(views.html.Publisher.showAgendaByConfType(updatedConf.slots, confType, "wednesday"))
}
case Some(slotConfig) if day == "monday" => {
val updatedConf = slotConfig.copy(slots = slotConfig.slots.filter(_.day == "monday")
, timeSlots = slotConfig.timeSlots.filter(_.start.getDayOfWeek == 1))
Ok(views.html.Publisher.showAgendaByConfType(updatedConf, confType, "monday"))
Ok(views.html.Publisher.showAgendaByConfType(updatedConf.slots, confType, "monday"))
}
case Some(slotConfig) if day == "tuesday" => {
val updatedConf = slotConfig.copy(
slots = slotConfig.slots.filter(_.day == "tuesday")
, timeSlots = slotConfig.timeSlots.filter(_.start.getDayOfWeek == 2)
)
Ok(views.html.Publisher.showAgendaByConfType(updatedConf, confType, "tuesday"))
Ok(views.html.Publisher.showAgendaByConfType(updatedConf.slots, confType, "tuesday"))
}
case Some(slotConfig) if day == "wednesday" => {
val updatedConf = slotConfig.copy(
slots = slotConfig.slots.filter(_.day == "wednesday")
, timeSlots = slotConfig.timeSlots.filter(_.start.getDayOfWeek == 3)
)
Ok(views.html.Publisher.showAgendaByConfType(updatedConf, confType, "wednesday"))
Ok(views.html.Publisher.showAgendaByConfType(updatedConf.slots, confType, "wednesday"))
}
case Some(slotConfig) if day == "thursday" => {
val updatedConf = slotConfig.copy(
slots = slotConfig.slots.filter(_.day == "thursday")
, timeSlots = slotConfig.timeSlots.filter(_.start.getDayOfWeek == 4)
)
Ok(views.html.Publisher.showAgendaByConfType(updatedConf, confType, "thursday"))
Ok(views.html.Publisher.showAgendaByConfType(updatedConf.slots, confType, "thursday"))
}
case Some(slotConfig) if day == "friday" => {
val updatedConf = slotConfig.copy(
slots = slotConfig.slots.filter(_.day == "friday")
, timeSlots = slotConfig.timeSlots.filter(_.start.getDayOfWeek == 5)
)
Ok(views.html.Publisher.showAgendaByConfType(updatedConf, confType, "friday"))
Ok(views.html.Publisher.showAgendaByConfType(updatedConf.slots, confType, "friday"))
}

case None => NotFound(views.html.Publisher.agendaNotYetPublished())
Expand All @@ -169,9 +176,8 @@ object Publisher extends Controller {

def showByDay(day: String) = Action {
implicit request =>

def _showDay(slots: List[Slot], day: String) = {
val rooms = slots.groupBy(_.room).keys.toList.sortBy(_.id)
val rooms = slots.groupBy(_.room).keys.toList
val allSlots = ScheduleConfiguration.getPublishedScheduleByDay(day)
Ok(views.html.Publisher.showOneDay(allSlots, rooms, day))
}
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/RestAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ object RestAPI extends Controller {
))
)
)
Ok(jsonObject).as(JSON).withHeaders(ETAG -> etag, "Links" -> ("<" + routes.RestAPI.profile("conference").absoluteURL().toString + ">; rel=\"profile\""))
Ok(jsonObject).as(JSON).withHeaders(ETAG -> etag,
"Links" -> ("<" + routes.RestAPI.profile("conference").absoluteURL() + ">; rel=\"profile\""))
}
}
}.getOrElse(NotFound("Conference not found"))
Expand Down
18 changes: 7 additions & 11 deletions app/models/ConferenceDescriptor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ object ConferenceDescriptor {

// Tip : I use the ID to sort-by on the view per day... So if the exhibition floor id is "aaa" it will be
// the first column on the HTML Table

// Do not change the ID's once the program is published
val HALL_EXPO = Room("a_hall", "Exhibition floor", 2300, "special", "")
val HALL_A = Room("x_hall_a", "Open Data Camp", 100, "special", "")

Expand Down Expand Up @@ -459,23 +461,17 @@ object ConferenceDescriptor {
val keynoteThursdaySlot2 = ConferenceRooms.keynoteRoom.map {
r2 =>
SlotBuilder(ConferenceProposalTypes.KEY.id, "thursday",
new DateTime("2016-04-21T09:40:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")),
new DateTime("2016-04-21T10:00:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")), r2)
new DateTime("2016-04-21T09:45:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")),
new DateTime("2016-04-21T10:05:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")), r2)
}
val keynoteThursdaySlot3 = ConferenceRooms.keynoteRoom.map {
r3 =>
SlotBuilder(ConferenceProposalTypes.KEY.id, "thursday",
new DateTime("2016-04-21T10:05:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")),
new DateTime("2016-04-21T10:25:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")), r3)
}
val keynoteThursdaySlot4 = ConferenceRooms.keynoteRoom.map {
r4 =>
SlotBuilder(ConferenceProposalTypes.KEY.id, "thursday",
new DateTime("2016-04-21T10:25:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")),
new DateTime("2016-04-21T10:45:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")), r4)
new DateTime("2016-04-21T10:10:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")),
new DateTime("2016-04-21T10:30:00.000+02:00").toDateTime(DateTimeZone.forID("Europe/Paris")), r3)
}

keynoteThursdayWelcome ++keynoteThursdaySlot1 ++ keynoteThursdaySlot2 ++ keynoteThursdaySlot3 ++ keynoteThursdaySlot4
keynoteThursdayWelcome ++keynoteThursdaySlot1 ++ keynoteThursdaySlot2 ++ keynoteThursdaySlot3
}

val keynoteSlotsFriday: List[Slot] = {
Expand Down
43 changes: 38 additions & 5 deletions app/models/Slot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ package models

import org.joda.time.DateTime
import play.api.libs.json.Json
import play.api.libs.json._
import play.api.libs.functional.syntax._

/**
* Time slots and Room are defined as static file.
Expand All @@ -38,8 +36,6 @@ import play.api.libs.functional.syntax._

case class Room(id: String, name: String, capacity: Int, setup: String, recorded:String) extends Ordered[Room] {

import scala.math.Ordered.orderingToOrdered

def index: Int = {
val regexp = "[\\D\\s]+(\\d+)".r
id match {
Expand All @@ -48,7 +44,17 @@ case class Room(id: String, name: String, capacity: Int, setup: String, recorded
}
}

def compare(that: Room): Int = (this.id.substring(0, 3), this.index) compare(that.id.substring(0, 3), that.index)
def compare(that: Room): Int = {
// TODO a virer apres Devoxx FR 2016
// Hack for Devoxx France => I cannot change the Room IDs so I fix the order in an IndexedSeq here
if(Room.fixedOrderForRoom.indexOf(this.id) < Room.fixedOrderForRoom.indexOf(that.id)){
return -1
}
if(Room.fixedOrderForRoom.indexOf(this.id) > Room.fixedOrderForRoom.indexOf(that.id)){
return 1
}
return 0
}
}

object Room {
Expand All @@ -62,6 +68,33 @@ object Room {
ConferenceDescriptor.ConferenceRooms.allRooms.find(r => r.id == roomId).getOrElse(OTHER)
}

// TODO à virer apres Devoxx FR 2016
val fixedOrderForRoom = IndexedSeq("a_hall",
"b_amphi",
"c_maillot",
"d_par241",
"f_neu251",
"e_neu252",
"par242AB",
"par242A",
"par242AT",
"par242B",
"par242BT",
"par243",
"neu253",
"neu253_t",
"par243_t",
"par201",
"par202_203",
"par204",
"par221M-222M",
"par224M-225M",
"neu_232_232",
"neu_234_235",
"neu_212_213",
"x_hall_a"
)

}

case class SlotBreak(id: String, nameEN: String, nameFR: String, room: Room)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@(proposals: List[(Speaker, Iterable[Proposal])])(implicit lang: Lang, flash: Flash, req: RequestHeader)
@(speakersAndProposals: List[(Speaker, Iterable[Proposal])])(implicit lang: Lang, flash: Flash, req: RequestHeader)

@main("CFP Speakers") {
<div class="row">
Expand All @@ -24,17 +24,18 @@ <h2><i class="icon-thumbs-up-alt"></i> CFP Admin</h2>
<div class="panel-heading">
<h3>All speakers with a badge</h3>
<em>Primary or secondary speaker, with a speaker badge</em>
<em>CFP or Red Coat not included</em>
<em>No Quickies or B.O.F</em>
<span class="label label-info">@proposals.size speakers</span>
<span class="label label-info">@speakersAndProposals.size speakers</span>
</div>
<div class="panel-footer">
<a href="@routes.CFPAdmin.allSpeakers()" class="btn btn-sm btn-primary"><i class="icon-group"></i> @Messages("admin.btn.speakers")</a>
</div>
</div>
</div>
<pre>
@proposals.sortBy(_._1.name.map(_.capitalize)).map{case(speaker,props)=>
@speaker.name.get.head.toString;@speaker.name.map(_.toUpperCase);@speaker.firstName.get;@speaker.email;@speaker.company.getOrElse("");@speaker.twitter.getOrElse("") }
@speakersAndProposals.sortBy(_._1.name.map(_.capitalize)).map{case(speaker,props)=>
"@speaker.name.get.head.toString","@speaker.name.map(_.toUpperCase)","@speaker.firstName.get","@speaker.email.trim","@speaker.company.getOrElse("")","@speaker.cleanTwitter.map(_.drop(1))" }
</pre>

</div>
Expand Down
Loading

0 comments on commit fd7bea1

Please sign in to comment.