- merge in branches/developers/ritzalam/bbb-web-playback
git-svn-id: http://bigbluebutton.googlecode.com/svn/trunk@1336 af16638f-c34d-0410-8cfa-b39d5352b314
This commit is contained in:
parent
db9cb9bfc3
commit
29c99178eb
@ -15,7 +15,6 @@
|
||||
<classpathentry kind="lib" path="lib/mysql-connector-java-5.1.6-bin.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-httpclient.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-codec-1.3.jar"/>
|
||||
<classpathentry kind="output" path="web-app/WEB-INF/classes"/>
|
||||
<classpathentry kind="var" path="GRAILS_HOME/ant/lib/ant.jar"/>
|
||||
<classpathentry kind="var" path="GRAILS_HOME/lib/ant-junit.jar"/>
|
||||
<classpathentry kind="var" path="GRAILS_HOME/lib/ant-launcher.jar"/>
|
||||
@ -89,4 +88,9 @@
|
||||
<classpathentry kind="var" path="GRAILS_HOME/dist/grails-test-1.0.4.jar"/>
|
||||
<classpathentry kind="var" path="GRAILS_HOME/dist/grails-web-1.0.4.jar"/>
|
||||
<classpathentry kind="var" path="GRAILS_HOME/dist/grails-webflow-1.0.4.jar"/>
|
||||
<classpathentry kind="lib" path="plugins/jsecurity-0.3/lib/jsecurity-jdk14.jar"/>
|
||||
<classpathentry kind="lib" path="lib/activemq-core-5.1.0.jar"/>
|
||||
<classpathentry kind="lib" path="lib/geronimo-j2ee-management_1.0_spec-1.0.jar"/>
|
||||
<classpathentry kind="lib" path="lib/geronimo-jms_1.1_spec-1.0.jar"/>
|
||||
<classpathentry kind="output" path="web-app/WEB-INF/classes"/>
|
||||
</classpath>
|
||||
|
@ -1,3 +1,5 @@
|
||||
|
||||
#Wed Apr 01 14:07:27 EDT 2009
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
|
||||
|
||||
|
@ -1,34 +1,29 @@
|
||||
import org.jsecurity.crypto.hash.Sha1Hash
|
||||
//import org.springframework.jms.listener.DefaultMessageListenerContainer
|
||||
import org.bigbluebutton.web.domain.Role
|
||||
import org.bigbluebutton.web.domain.User
|
||||
import org.bigbluebutton.web.domain.UserRoleRel
|
||||
|
||||
class BootStrap {
|
||||
def jmsContainer
|
||||
|
||||
def init = { servletContext ->
|
||||
log.debug "Bootstrapping"
|
||||
// Administrator user and role.
|
||||
def adminRole = new Role(name: "Administrator").save()
|
||||
def adminUser = new User(username: "admin", passwordHash: new Sha1Hash("admin").toHex(),
|
||||
email: "admin@test.com", fullName: "Admin").save()
|
||||
def adminUser = new User(username: "admin@test.com", passwordHash: new Sha1Hash("admin").toHex(),
|
||||
fullName: "Admin").save()
|
||||
new UserRoleRel(user: adminUser, role: adminRole).save()
|
||||
|
||||
// A normal user.
|
||||
def userRole = new Role(name: "User").save()
|
||||
def normalUser = new User(username: "phil", passwordHash: new Sha1Hash("password").toHex(),
|
||||
email: "phil@test.com", fullName: "Phil").save()
|
||||
def normalUser = new User(username: "phil@test.com", passwordHash: new Sha1Hash("password").toHex(),
|
||||
fullName: "Phil").save()
|
||||
new UserRoleRel(user: normalUser, role: userRole).save()
|
||||
|
||||
// Give another user the "User" role.
|
||||
normalUser = new User(username: "alice", passwordHash: new Sha1Hash("changeit").toHex(),
|
||||
email: "alice@test.com", fullName: "Alice").save()
|
||||
normalUser = new User(username: "alice@test.com", passwordHash: new Sha1Hash("changeit").toHex(),
|
||||
fullName: "Alice").save()
|
||||
new UserRoleRel(user: normalUser, role: userRole).save()
|
||||
|
||||
/** Start the JMS Container defined in resources.groovy**/
|
||||
|
||||
log.info "Starting JMS Container"
|
||||
println "Starting JMS Container"
|
||||
jmsContainer.initialize()
|
||||
jmsContainer.start()
|
||||
println "Started JMS Container"
|
||||
}
|
||||
|
||||
def destroy = {
|
||||
|
@ -34,11 +34,11 @@ grails.converters.encoding="UTF-8"
|
||||
grails.enable.native2ascii = true
|
||||
|
||||
// set per-environment serverURL stem for creating absolute links
|
||||
environments {
|
||||
production {
|
||||
grails.serverURL = "http://www.changeme.com"
|
||||
}
|
||||
}
|
||||
//environments {
|
||||
// production {
|
||||
// grails.serverURL = "http://www.changeme.com"
|
||||
// }
|
||||
//}
|
||||
|
||||
// log4j configuration
|
||||
log4j {
|
||||
@ -49,6 +49,10 @@ log4j {
|
||||
appender.'errors.layout'="org.apache.log4j.PatternLayout"
|
||||
appender.'errors.layout.ConversionPattern'='[%r] %c{2} %m%n'
|
||||
appender.'errors.File'="stacktrace.log"
|
||||
appender.logfile = "org.apache.log4j.DailyRollingFileAppender "
|
||||
appender.'logfile.File' = "bbb-web.log"
|
||||
appender.'logfile.layout' = "org.apache.log4j.PatternLayout"
|
||||
appender.'logfile.layout.ConversionPattern' = '%d{[dd.MM.yy HH:mm:ss.SSS]} %-5p %c %x - %m%n'
|
||||
rootLogger="error,stdout"
|
||||
logger {
|
||||
grails="error"
|
||||
@ -69,4 +73,41 @@ log4j {
|
||||
additivity.StackTrace=false
|
||||
}
|
||||
|
||||
environments {
|
||||
development {
|
||||
grails.serverURL = "http://localhost:8080"
|
||||
log4j {
|
||||
appender.'logfile.File' = "bbb-web-dev.log"
|
||||
/* GRAILS 1.04 doesn't seem to like this format (ralam 04/19/2009)
|
||||
* logger {
|
||||
* grails.app.controller="debug, stdout, logfile"
|
||||
* }
|
||||
*/
|
||||
logger.grails.app="debug, stdout, logfile"
|
||||
}
|
||||
}
|
||||
production {
|
||||
grails.serverURL = "http://www.changeme.com"
|
||||
log4j {
|
||||
appender.'logfile.File' = "bbb-web-prod.log"
|
||||
/* GRAILS 1.04 doesn't seem to like this format (ralam 04/19/2009)
|
||||
* logger {
|
||||
* grails.app.controller="debug, stdout, logfile"
|
||||
* }
|
||||
*/
|
||||
logger.grails.app="debug, stdout, logfile"
|
||||
}
|
||||
}
|
||||
test {
|
||||
log4j {
|
||||
appender.'logfile.File' = "bbb-web-test.log"
|
||||
/* GRAILS 1.04 doesn't seem to like this format (ralam 04/19/2009)
|
||||
* logger {
|
||||
* grails.app.controller="debug, stdout, logfile"
|
||||
* }
|
||||
*/
|
||||
logger.grails.app="debug, stdout, logfile"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ environments {
|
||||
}
|
||||
test {
|
||||
dataSource {
|
||||
dbCreate = "update"
|
||||
dbCreate = 'create'
|
||||
url = "jdbc:hsqldb:mem:testDb"
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,16 @@ class SecurityFilters {
|
||||
auth(controller: "*", action: "*") {
|
||||
before = {
|
||||
// Exclude the "join" controller.
|
||||
if ((controllerName == "join") || (controllerName == "presentation")) return true
|
||||
//if ((controllerName == "join") || (controllerName == "presentation")) return true
|
||||
|
||||
switch (controllerName) {
|
||||
case 'join':
|
||||
case 'presentation':
|
||||
return true
|
||||
break
|
||||
case 'publicScheduledSession':
|
||||
return true
|
||||
}
|
||||
// This just means that the user must be authenticated. He does
|
||||
// not need any particular role or permission.
|
||||
accessControl { true }
|
||||
|
@ -5,28 +5,32 @@ class UrlMappings {
|
||||
// action = [GET:'show', POST:'upload', DELETE:'delete']
|
||||
// }
|
||||
"/presentation/upload"(controller:"presentation") {
|
||||
println 'executing /presentation/default mapping'
|
||||
action = [GET:'show', POST:'upload', DELETE:'delete']
|
||||
}
|
||||
|
||||
"/presentation/$presentation_name/slides"(controller:"presentation") {
|
||||
"/presentation/$conference/$room/$presentation_name/slides"(controller:"presentation") {
|
||||
action = [GET:'numberOfSlides']
|
||||
}
|
||||
|
||||
"/presentation/$presentation_name/slide/$id"(controller:"presentation") {
|
||||
"/presentation/$conference/$room/$presentation_name/slide/$id"(controller:"presentation") {
|
||||
action = [GET:'showSlide']
|
||||
}
|
||||
|
||||
"/presentation/$presentation_name/thumbnails"(controller:"presentation") {
|
||||
"/presentation/$conference/$room/$presentation_name/thumbnails"(controller:"presentation") {
|
||||
action = [GET:'numberOfThumbnails']
|
||||
}
|
||||
|
||||
"/presentation/$presentation_name/thumbnail/$id"(controller:"presentation") {
|
||||
"/presentation/$conference/$room/$presentation_name/thumbnail/$id"(controller:"presentation") {
|
||||
action = [GET:'showThumbnail']
|
||||
}
|
||||
|
||||
"/conference-session/$action?/$id?"(controller:"publicScheduledSession")
|
||||
|
||||
"/schedule/$action?/$id?"(controller:"scheduledSession") {
|
||||
// action = [GET:'show', POST:'create', DELETE:'delete']
|
||||
}
|
||||
|
||||
"/$controller/$action?/$id?"{
|
||||
println "${controller} ${action} mapping"
|
||||
constraints {
|
||||
// apply constraints here
|
||||
}
|
||||
|
@ -5,9 +5,16 @@ asterisk.host=192.168.0.101
|
||||
ami.user=ralam
|
||||
ami.password=secure
|
||||
|
||||
beans.presentationService.swfTools=E:/swftools
|
||||
beans.presentationService.imageMagick=E:/ImageMagick-6.5.1-Q16
|
||||
# we separate these so we can inject it manually
|
||||
# to test PresentationService.groovy
|
||||
swfTools=C:/swftools-0.9
|
||||
imageMagick=C:/ImageMagick-6.4.9-Q16
|
||||
presentationDir=c:/temp/bigbluebutton
|
||||
ghostScript=C:/gs/gs8.63/bin/gswin32c.exe
|
||||
|
||||
beans.presentationService.swfTools=${swfTools}
|
||||
beans.presentationService.imageMagick=${imageMagick}
|
||||
beans.presentationService.presentationDir=${presentationDir}
|
||||
# Use fullpath to ghostscript executable since the exec names are different
|
||||
# for each platform.
|
||||
beans.presentationService.ghostScript=E:/ghostscript8.64/gs8.64/bin/gswin32c
|
||||
beans.presentationService.presentationDir=E:/temp/bigbluebutton
|
||||
beans.presentationService.ghostScript=${ghostScript}
|
||||
|
@ -3,7 +3,6 @@
|
||||
beans = {
|
||||
|
||||
jmsFactory(org.apache.activemq.pool.PooledConnectionFactory) { bean ->
|
||||
bean.destroyMethod = "stop"
|
||||
connectionFactory = {org.apache.activemq.ActiveMQConnectionFactory cf ->
|
||||
brokerURL = "tcp://localhost:61616"
|
||||
}
|
||||
@ -12,33 +11,4 @@ beans = {
|
||||
jmsTemplate(org.springframework.jms.core.JmsTemplate) {
|
||||
connectionFactory = jmsFactory
|
||||
}
|
||||
|
||||
jmsMessageListener(org.springframework.jms.listener.adapter.MessageListenerAdapter, ref("recordService")) {
|
||||
//delegate = ref("recordService")
|
||||
defaultListenerMethod = "handleRecordMessage"
|
||||
}
|
||||
|
||||
messageListener(org.bigbluebutton.web.jms.RecordMessageListener)
|
||||
|
||||
recordQueue(org.apache.activemq.command.ActiveMQQueue, "RecordQueue")
|
||||
|
||||
jmsContainer(org.springframework.jms.listener.DefaultMessageListenerContainer) {
|
||||
connectionFactory = jmsFactory
|
||||
concurrentConsumers = 1
|
||||
destination = ref("recordQueue")
|
||||
messageListener = messageListener
|
||||
transactionManager = ref("transactionManager")
|
||||
autoStartup = false
|
||||
}
|
||||
|
||||
////destination = ref("recordDestination")
|
||||
//destinationName = "RecordQueue"
|
||||
// pbxLive(org.bigbluebutton.pbx.PbxLive) { bean ->
|
||||
// bean.initMethod = "startup"
|
||||
// bean.destroyMethod = "shutdown"
|
||||
// asteriskServer = ref("asteriskServer")
|
||||
// }
|
||||
|
||||
// asteriskServer(org.asteriskjava.live.DefaultAsteriskServer,
|
||||
// "192.168.0.101", "ralam", "secure") {}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
|
||||
class AttendeesController {
|
||||
def index = { redirect(action:list,params:params) }
|
||||
|
||||
// the delete, save and update actions only accept POST requests
|
||||
def allowedMethods = [delete:'POST', save:'POST', update:'POST']
|
||||
|
||||
def list = {
|
||||
if(!params.max) params.max = 50
|
||||
def conf = new Integer(params.conferenceNumber)
|
||||
def startTime = new Date(new Long(params.start))
|
||||
def endTime = new Date(new Long(params.start) + 5*60*1000)
|
||||
flash.message = "${startTime} ${endTime}"
|
||||
return [ attendeesList:
|
||||
Attendees.findAllByConferenceNumberAndDateJoinedBetween(conf, startTime, endTime)]
|
||||
}
|
||||
|
||||
def show = {
|
||||
def attendees = Attendees.get( params.id )
|
||||
|
||||
if(!attendees) {
|
||||
flash.message = "Attendees not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
else { return [ attendees : attendees ] }
|
||||
}
|
||||
|
||||
def delete = {
|
||||
def attendees = Attendees.get( params.id )
|
||||
if(attendees) {
|
||||
attendees.delete()
|
||||
flash.message = "Attendees ${params.id} deleted"
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
flash.message = "Attendees not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
}
|
||||
|
||||
def edit = {
|
||||
def attendees = Attendees.get( params.id )
|
||||
|
||||
if(!attendees) {
|
||||
flash.message = "Attendees not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
return [ attendees : attendees ]
|
||||
}
|
||||
}
|
||||
|
||||
def update = {
|
||||
def attendees = Attendees.get( params.id )
|
||||
if(attendees) {
|
||||
attendees.properties = params
|
||||
if(!attendees.hasErrors() && attendees.save()) {
|
||||
flash.message = "Attendees ${params.id} updated"
|
||||
redirect(action:show,id:attendees.id)
|
||||
}
|
||||
else {
|
||||
render(view:'edit',model:[attendees:attendees])
|
||||
}
|
||||
}
|
||||
else {
|
||||
flash.message = "Attendees not found with id ${params.id}"
|
||||
redirect(action:edit,id:params.id)
|
||||
}
|
||||
}
|
||||
|
||||
def create = {
|
||||
def attendees = new Attendees()
|
||||
attendees.properties = params
|
||||
return ['attendees':attendees]
|
||||
}
|
||||
|
||||
def save = {
|
||||
def attendees = new Attendees(params)
|
||||
if(!attendees.hasErrors() && attendees.save()) {
|
||||
flash.message = "Attendees ${attendees.id} created"
|
||||
redirect(action:show,id:attendees.id)
|
||||
}
|
||||
else {
|
||||
render(view:'create',model:[attendees:attendees])
|
||||
}
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
import org.jsecurity.authc.AuthenticationException
|
||||
import org.jsecurity.authc.UsernamePasswordToken
|
||||
import org.jsecurity.SecurityUtils
|
||||
import org.jsecurity.session.Session
|
||||
import org.jsecurity.subject.Subject
|
||||
|
||||
class JoinController {
|
||||
|
||||
def index = { redirect(action: 'login', params: params) }
|
||||
|
||||
def login = {
|
||||
return [ fullname: params.fullname, conference: (params.conference), password: params.password ]
|
||||
}
|
||||
|
||||
def signIn = {
|
||||
def fullname = params.fullname
|
||||
def conference = Conference.findByConferenceNumber(params.conference)
|
||||
def schedule = null
|
||||
def role = ''
|
||||
|
||||
if (!conference) {
|
||||
def returnString = """
|
||||
<join>
|
||||
<returncode>FAILED</returncode>
|
||||
<message>Could not find conference ${params.conference}.</message>
|
||||
</join> """
|
||||
render(text:"${returnString}",contentType:"text/xml",encoding:"UTF-8")
|
||||
} else {
|
||||
def long _10_minutes = 10*60*1000
|
||||
def now = new Date().time
|
||||
|
||||
conference.schedules.each {
|
||||
def startTime = it.startDateTime.time - _10_minutes
|
||||
def endTime = it.startDateTime.time + _10_minutes + (it.lengthOfConference * 60 * 60 * 1000) // length * min * sec * ms
|
||||
|
||||
if ((startTime <= now) && (now <= endTime)) {
|
||||
if (it.hostPassword == params.password) {
|
||||
role = "MODERATOR"
|
||||
schedule = it
|
||||
} else if (it.attendeePassword == params.password) {
|
||||
role = "VIEWER"
|
||||
schedule = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!schedule) {
|
||||
def returnString = """
|
||||
<join>
|
||||
<returncode>FAILED</returncode>
|
||||
<message>Either you typed the wrong password or you are early. Please
|
||||
try 10 minutes before the scheduled conference.
|
||||
</message>
|
||||
</join> """
|
||||
render(text:"${returnString}",contentType:"text/xml",encoding:"UTF-8")
|
||||
} else {
|
||||
Subject currentUser = SecurityUtils.getSubject()
|
||||
Session session = currentUser.getSession()
|
||||
session.setAttribute( "fullname", params.fullname )
|
||||
session.setAttribute( "role", role )
|
||||
session.setAttribute( "conference", params.conference )
|
||||
session.setAttribute( "room", schedule.scheduleId )
|
||||
|
||||
def fname = session.getAttribute("fullname")
|
||||
def rl = session.getAttribute("role")
|
||||
def cnf = session.getAttribute("conference")
|
||||
def rm = session.getAttribute("room")
|
||||
|
||||
def returnString = """
|
||||
<join>
|
||||
<returncode>SUCCESS</returncode>
|
||||
<principal>${currentUser.principal}</principal>
|
||||
<name>${schedule.scheduleName}</name>
|
||||
<fullname>${fname}</fullname>
|
||||
<role>${rl}</role>
|
||||
<conference>${cnf}</conference>
|
||||
<room>${rm}</room>
|
||||
</join> """
|
||||
render(text:"${returnString}",contentType:"text/xml",encoding:"UTF-8")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def enter = {
|
||||
Subject currentUser = SecurityUtils.getSubject()
|
||||
Session session = currentUser.getSession()
|
||||
|
||||
def fname = session.getAttribute("fullname")
|
||||
def rl = session.getAttribute("role")
|
||||
def cnf = session.getAttribute("conference")
|
||||
def rm = session.getAttribute("room")
|
||||
|
||||
if (!rm) {
|
||||
def returnString = """
|
||||
<join>
|
||||
<returncode>FAILED</returncode>
|
||||
<message>Either you typed the wrong password or you are early. Please
|
||||
try 10 minutes before the scheduled conference.
|
||||
</message>
|
||||
</join> """
|
||||
render(text:"${returnString}",contentType:"text/xml",encoding:"UTF-8")
|
||||
} else {
|
||||
def returnString = """
|
||||
<join>
|
||||
<returncode>SUCCESS</returncode>
|
||||
<fullname>${fname}</fullname>
|
||||
<role>${rl}</role>
|
||||
<conference>${cnf}</conference>
|
||||
<room>${rm}</room>
|
||||
</join> """
|
||||
render(text:"${returnString}",contentType:"text/xml",encoding:"UTF-8")
|
||||
}
|
||||
}
|
||||
|
||||
def signOut = {
|
||||
// Log the user out of the application.
|
||||
SecurityUtils.subject?.logout()
|
||||
|
||||
// For now, redirect back to the home page.
|
||||
redirect(uri: '/')
|
||||
}
|
||||
|
||||
def unauthorized = {
|
||||
render 'You do not have permission to access this page.'
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
import java.util.UUID;
|
||||
|
||||
class ScheduleController {
|
||||
|
||||
def index = { redirect(action:list,params:params) }
|
||||
|
||||
// the delete, save and update actions only accept POST requests
|
||||
def allowedMethods = [delete:'POST', save:'POST', update:'POST']
|
||||
|
||||
def list = {
|
||||
if(!params.max) params.max = 10
|
||||
[ scheduleInstanceList: Schedule.list( params ) ]
|
||||
}
|
||||
|
||||
def show = {
|
||||
def scheduleInstance = Schedule.get( params.id )
|
||||
|
||||
if(!scheduleInstance) {
|
||||
flash.message = "Schedule not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
else { return [ scheduleInstance : scheduleInstance ] }
|
||||
}
|
||||
|
||||
def delete = {
|
||||
def scheduleInstance = Schedule.get( params.id )
|
||||
if(scheduleInstance) {
|
||||
scheduleInstance.delete()
|
||||
flash.message = "Schedule ${scheduleInstance.scheduleName} deleted"
|
||||
redirect(controller:'conference', action:show,id:scheduleInstance.conferenceId)
|
||||
}
|
||||
else {
|
||||
flash.message = "Schedule not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
}
|
||||
|
||||
def edit = {
|
||||
def scheduleInstance = Schedule.get( params.id )
|
||||
|
||||
if(!scheduleInstance) {
|
||||
flash.message = "Schedule not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
return [ scheduleInstance : scheduleInstance ]
|
||||
}
|
||||
}
|
||||
|
||||
def update = {
|
||||
def scheduleInstance = Schedule.get( params.id )
|
||||
if(scheduleInstance) {
|
||||
scheduleInstance.properties = params
|
||||
if(!scheduleInstance.hasErrors() && scheduleInstance.save()) {
|
||||
flash.message = "Schedule ${scheduleInstance.scheduleName} updated"
|
||||
redirect(action:show,id:scheduleInstance.id)
|
||||
}
|
||||
else {
|
||||
render(view:'edit',model:[scheduleInstance:scheduleInstance])
|
||||
}
|
||||
}
|
||||
else {
|
||||
flash.message = "Schedule not found with id ${params.id}"
|
||||
redirect(action:edit,id:params.id)
|
||||
}
|
||||
}
|
||||
|
||||
def create = {
|
||||
def scheduleInstance = new Schedule()
|
||||
scheduleInstance.properties = params
|
||||
return ['scheduleInstance':scheduleInstance, 'conferenceId':params.conferenceId]
|
||||
}
|
||||
|
||||
def save = {
|
||||
def conference = Conference.get(params.conferenceId)
|
||||
params.conference = conference
|
||||
def scheduleInstance = new Schedule(params)
|
||||
scheduleInstance.scheduleId = UUID.randomUUID();
|
||||
scheduleInstance.scheduledBy = session.username
|
||||
|
||||
if(!scheduleInstance.hasErrors() && scheduleInstance.save()) {
|
||||
flash.message = "Schedule ${scheduleInstance.scheduleName} created"
|
||||
redirect(controller:'conference', action:show,id:scheduleInstance.conferenceId)
|
||||
}
|
||||
else {
|
||||
render(view:'create',model:[scheduleInstance:scheduleInstance, 'conferenceId':params.conferenceId])
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.jsecurity.authc.AuthenticationException
|
||||
import org.jsecurity.authc.UsernamePasswordToken
|
||||
import org.jsecurity.SecurityUtils
|
||||
import org.jsecurity.session.Session
|
||||
import org.jsecurity.subject.Subject
|
||||
import org.bigbluebutton.web.domain.User
|
||||
|
||||
class AuthController {
|
||||
|
||||
def jsecSecurityManager
|
||||
|
||||
def index = { redirect(action: 'login', params: params) }
|
||||
@ -29,22 +33,24 @@ class AuthController {
|
||||
|
||||
// Store the username in the session
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
Session session = currentUser.getSession();
|
||||
session.setAttribute( "username", params.username );
|
||||
Session jsecSession = currentUser.getSession();
|
||||
jsecSession.setAttribute( "username", params.username );
|
||||
User user = User.findByUsername(params.username)
|
||||
session.setAttribute( "userid", user.id );
|
||||
jsecSession.setAttribute( "userid", user.id );
|
||||
|
||||
session["username"] = params.username
|
||||
session["userid"] = user.id
|
||||
log.debug "$params.username has signedin."
|
||||
|
||||
// If a controller redirected to this page, redirect back
|
||||
// to it. Otherwise redirect to the root URI.
|
||||
def targetUri = params.targetUri ?: "/"
|
||||
|
||||
log.info "Redirecting to '${targetUri}'."
|
||||
redirect(uri: targetUri)
|
||||
}
|
||||
catch (AuthenticationException ex){
|
||||
// Authentication failed, so display the appropriate message
|
||||
// on the login page.
|
||||
log.info "Authentication failure for user '${params.username}'."
|
||||
log.debug "Authentication failure for user '${params.username}'."
|
||||
flash.message = message(code: "login.failed")
|
||||
|
||||
// Keep the username and "remember me" setting so that the
|
||||
@ -67,7 +73,7 @@ class AuthController {
|
||||
def signOut = {
|
||||
// Log the user out of the application.
|
||||
SecurityUtils.subject?.logout()
|
||||
|
||||
session.invalidate()
|
||||
// For now, redirect back to the home page.
|
||||
redirect(uri: '/')
|
||||
}
|
@ -1,6 +1,11 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.jsecurity.SecurityUtils
|
||||
import org.jsecurity.session.Session
|
||||
import org.jsecurity.subject.Subject
|
||||
import org.bigbluebutton.web.domain.Conference
|
||||
import org.bigbluebutton.web.domain.User
|
||||
import org.bigbluebutton.web.domain.ScheduledSession
|
||||
|
||||
class ConferenceController {
|
||||
def index = { redirect(action:list,params:params) }
|
||||
@ -10,12 +15,12 @@ class ConferenceController {
|
||||
|
||||
def list = {
|
||||
if(!params.max) params.max = 10
|
||||
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
Session session = currentUser.getSession();
|
||||
def username = session.getAttribute( "username");
|
||||
|
||||
return [ conferenceList: Conference.findAllByUsername(username)]
|
||||
def username = session["username"]
|
||||
log.debug "Getting conference owned by $username"
|
||||
def user = User.findByUsername(username)
|
||||
def conferenceList = Conference.findAllByUser(user)
|
||||
if (conferenceList == null) conferenceList = []
|
||||
return [ conferenceList: conferenceList]
|
||||
}
|
||||
|
||||
def show = {
|
||||
@ -26,7 +31,20 @@ class ConferenceController {
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
return [ conference : conference ]
|
||||
def scheduledSessions = ScheduledSession.findAllByConference(conference)
|
||||
def sessionsList = []
|
||||
def hostUrl = grailsApplication.config.grails.serverURL
|
||||
|
||||
scheduledSessions.each {
|
||||
def sss = new Expando()
|
||||
sss.id = it.id
|
||||
sss.name = it.name
|
||||
sss.token = it.tokenId
|
||||
sss.hostUrl = hostUrl
|
||||
sss.expired = true
|
||||
sessionsList << sss
|
||||
}
|
||||
return [ conference : conference, sessions : sessionsList ]
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +52,7 @@ class ConferenceController {
|
||||
def conference = Conference.get( params.id )
|
||||
if(conference) {
|
||||
conference.delete()
|
||||
flash.message = "${conference.conferenceName} has been deleted."
|
||||
flash.message = "${conference.name} has been deleted."
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
@ -47,7 +65,7 @@ class ConferenceController {
|
||||
def conference = Conference.get( params.id )
|
||||
|
||||
if(!conference) {
|
||||
flash.message = "Cannot find conference ${conference.conferenceName}."
|
||||
flash.message = "Cannot find conference ${conference.name}."
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
@ -59,6 +77,9 @@ class ConferenceController {
|
||||
def conference = Conference.get( params.id )
|
||||
if(conference) {
|
||||
conference.properties = params
|
||||
def userid = session["userid"]
|
||||
def user = User.get(userid)
|
||||
conference.updatedBy = user.fullName
|
||||
if(!conference.hasErrors() && conference.save()) {
|
||||
flash.message = "The conference has been updated."
|
||||
redirect(action:show,id:conference.id)
|
||||
@ -76,39 +97,25 @@ class ConferenceController {
|
||||
def create = {
|
||||
def conference = new Conference()
|
||||
conference.properties = params
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
Session session = currentUser.getSession();
|
||||
conference.username = session.getAttribute( "username");
|
||||
def now = new Date()
|
||||
conference.conferenceName = "$now Conference"
|
||||
conference.name = "$now Conference"
|
||||
return ['conference':conference]
|
||||
}
|
||||
|
||||
def save = {
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
Session session = currentUser.getSession();
|
||||
params.username = session.getAttribute("username");
|
||||
def userid = session.getAttribute( "userid");
|
||||
def user = User.get(userid)
|
||||
params.user = user
|
||||
|
||||
def conference = new Conference(params)
|
||||
/*
|
||||
def highestConfId = Conference.listOrderByConferenceNumber(max:1, order:"desc")
|
||||
def nextConfId
|
||||
if (highestConfId) {
|
||||
nextConfId = highestConfId[0].conferenceNumber + 1
|
||||
} else {
|
||||
nextConfId = 8000 + 1
|
||||
}
|
||||
conference.conferenceNumber = nextConfId
|
||||
*/
|
||||
|
||||
def userid = session["userid"]
|
||||
def user = User.get(userid)
|
||||
conference.createdBy = user.fullName
|
||||
conference.updatedBy = user.fullName
|
||||
conference.user = user
|
||||
|
||||
if(!conference.hasErrors() && conference.save()) {
|
||||
flash.message = "You have successfully created a conference."
|
||||
redirect(action:show,id:conference.id)
|
||||
}
|
||||
else {
|
||||
System.out.println("Username ${conference.username}")
|
||||
render(view:'create',model:[conference:conference])
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.jsecurity.authc.AuthenticationException
|
||||
import org.jsecurity.authc.UsernamePasswordToken
|
||||
import org.jsecurity.SecurityUtils
|
||||
import org.jsecurity.session.Session
|
||||
import org.jsecurity.subject.Subject
|
||||
import grails.converters.*
|
||||
import org.bigbluebutton.web.domain.Conference
|
||||
|
||||
class JoinController {
|
||||
|
||||
def index = { redirect(action: 'login', params: params) }
|
||||
|
||||
def joinIn = {
|
||||
println "join $params.id"
|
||||
return [ fullname: params.fullname, id: (params.id), password: params.password ]
|
||||
}
|
||||
|
||||
def login = {
|
||||
return [ fullname: params.fullname, conference: (params.conference), password: params.password ]
|
||||
}
|
||||
|
||||
def signIn = {
|
||||
def fullname = params.fullname
|
||||
def conference = Conference.findByConferenceNumber(params.conference)
|
||||
def schedule = null
|
||||
def role = ''
|
||||
|
||||
if (!conference) {
|
||||
withFormat {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
'join'() {
|
||||
returnCode("FAILED")
|
||||
message("Could not find conference ${params.conference}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
def long _10_minutes = 10*60*1000
|
||||
def now = new Date().time
|
||||
|
||||
conference.schedules.each {
|
||||
def startTime = it.startDateTime.time - _10_minutes
|
||||
def endTime = it.startDateTime.time + _10_minutes + (it.lengthOfConference * 60 * 60 * 1000) // length * min * sec * ms
|
||||
|
||||
if ((startTime <= now) && (now <= endTime)) {
|
||||
if (it.hostPassword == params.password) {
|
||||
role = "MODERATOR"
|
||||
schedule = it
|
||||
} else if (it.attendeePassword == params.password) {
|
||||
role = "VIEWER"
|
||||
schedule = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!schedule) {
|
||||
withFormat {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
'join'() {
|
||||
returnCode("FAILED")
|
||||
message("Could not find schedule for conference ${params.conference}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
session["fullname"] = params.fullname
|
||||
session["role"] = role
|
||||
session["conference"] = params.conference
|
||||
session["room"] = schedule.scheduleId
|
||||
|
||||
def fname = session["fullname"]
|
||||
def rl = session["role"]
|
||||
def cnf = session["conference"]
|
||||
def rm = session["room"]
|
||||
|
||||
withFormat {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
'join'() {
|
||||
returncode("SUCCESS")
|
||||
schedulename("${schedule.scheduleName}")
|
||||
participantname("$fname")
|
||||
participantrole("$rl")
|
||||
conferencenumber("$cnf")
|
||||
conferenceroom("$rm")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def enter = {
|
||||
// Subject currentUser = SecurityUtils.getSubject()
|
||||
// Session session = currentUser.getSession()
|
||||
|
||||
def fname = session["fullname"]
|
||||
def rl = session["role"]
|
||||
def cnf = session["conference"]
|
||||
def rm = session["room"]
|
||||
|
||||
if (!rm) {
|
||||
withFormat {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
'join'() {
|
||||
returnCode("FAILED")
|
||||
message("Could not find conference ${params.conference}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withFormat {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
'join'() {
|
||||
returnCode("SUCCESS")
|
||||
fullname("$fname")
|
||||
role("$rl")
|
||||
conference("$cnf")
|
||||
room("$rm")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def signOut = {
|
||||
// Log the user out of the application.
|
||||
session.invalidate()
|
||||
|
||||
// For now, redirect back to the home page.
|
||||
redirect(uri: '/')
|
||||
}
|
||||
|
||||
def unauthorized = {
|
||||
render 'You do not have permission to access this page.'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.jsecurity.authc.AuthenticationException
|
||||
import org.jsecurity.authc.UsernamePasswordToken
|
||||
import org.jsecurity.SecurityUtils
|
||||
@ -6,6 +8,7 @@ import org.jsecurity.subject.Subject
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
import grails.converters.*
|
||||
import org.bigbluebutton.web.services.PresentationService
|
||||
|
||||
class PresentationController {
|
||||
PresentationService presentationService
|
||||
@ -53,8 +56,13 @@ class PresentationController {
|
||||
def file = request.getFile('fileUpload')
|
||||
if(!file.empty) {
|
||||
flash.message = 'Your file has been uploaded'
|
||||
def f = confInfo()
|
||||
presentationService.processUploadedPresentation(params.conference, params.room, params.presentation_name, file)
|
||||
def presentationName = params.presentation_name.replace(' ', '-')
|
||||
File uploadDir = presentationService.uploadedPresentationDirectory(params.conference, params.room, presentationName)
|
||||
|
||||
def newFilename = file.getOriginalFilename().replace(' ', '-')
|
||||
def pres = new File( uploadDir.absolutePath + File.separatorChar + newFilename )
|
||||
file.transferTo( pres )
|
||||
presentationService.processUploadedPresentation(params.conference, params.room, presentationName, pres)
|
||||
}
|
||||
else {
|
||||
flash.message = 'file cannot be empty'
|
||||
@ -79,12 +87,14 @@ class PresentationController {
|
||||
|
||||
def showSlide = {
|
||||
def presentationName = params.presentation_name
|
||||
def conf = params.conference
|
||||
def rm = params.room
|
||||
def slide = params.id
|
||||
|
||||
InputStream is = null;
|
||||
try {
|
||||
def f = confInfo()
|
||||
def pres = presentationService.showSlide(f.conference, f.room, presentationName, slide)
|
||||
// def f = confInfo()
|
||||
def pres = presentationService.showSlide(conf, rm, presentationName, slide)
|
||||
if (pres.exists()) {
|
||||
def bytes = pres.readBytes()
|
||||
response.addHeader("Cache-Control", "no-cache")
|
||||
@ -100,12 +110,13 @@ class PresentationController {
|
||||
|
||||
def showThumbnail = {
|
||||
def presentationName = params.presentation_name
|
||||
def conf = params.conference
|
||||
def rm = params.room
|
||||
def thumb = params.id
|
||||
|
||||
InputStream is = null;
|
||||
try {
|
||||
def f = confInfo()
|
||||
def pres = presentationService.showThumbnail(f.conference, f.room, presentationName, thumb)
|
||||
def pres = presentationService.showThumbnail(conf, rm, presentationName, thumb)
|
||||
if (pres.exists()) {
|
||||
def bytes = pres.readBytes()
|
||||
response.addHeader("Cache-Control", "no-cache")
|
||||
@ -161,23 +172,19 @@ class PresentationController {
|
||||
}
|
||||
|
||||
def numberOfSlides = {
|
||||
def filename = params.presentation_name
|
||||
def f = confInfo()
|
||||
/* Let's just use the thumbnail count */
|
||||
|
||||
def numThumbs = presentationService.numberOfThumbnails(f.conference, f.room, filename)
|
||||
//def numThumbs = 5
|
||||
|
||||
|
||||
def presentationName = params.presentation_name
|
||||
def conf = params.conference
|
||||
def rm = params.room
|
||||
|
||||
def numThumbs = presentationService.numberOfThumbnails(conf, rm, presentationName)
|
||||
response.addHeader("Cache-Control", "no-cache")
|
||||
withFormat {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
conference(id:f.conference, room:f.room) {
|
||||
presentation(name:filename) {
|
||||
conference(id:conf, room:rm) {
|
||||
presentation(name:presentationName) {
|
||||
slides(count:numThumbs) {
|
||||
for (def i=0; i<numThumbs;i++) {
|
||||
for (def i = 1; i <= numThumbs; i++) {
|
||||
slide(number:"${i}", name:"slide/${i}", thumb:"thumbnail/${i}")
|
||||
}
|
||||
}
|
||||
@ -210,14 +217,15 @@ class PresentationController {
|
||||
}
|
||||
|
||||
def confInfo = {
|
||||
Subject currentUser = SecurityUtils.getSubject()
|
||||
Session session = currentUser.getSession()
|
||||
// Subject currentUser = SecurityUtils.getSubject()
|
||||
// Session session = currentUser.getSession()
|
||||
|
||||
def fname = session.getAttribute("fullname")
|
||||
def rl = session.getAttribute("role")
|
||||
def conf = session.getAttribute("conference")
|
||||
def rm = session.getAttribute("room")
|
||||
def fname = session["fullname"]
|
||||
def rl = session["role"]
|
||||
def conf = session["conference"]
|
||||
def rm = session["room"]
|
||||
println "Conference info: ${conf} ${rm}"
|
||||
return [conference:conf, room:rm]
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
class PublicConferenceController {
|
||||
|
||||
def index = { }
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.bigbluebutton.web.domain.ScheduledSession
|
||||
import grails.converters.*
|
||||
|
||||
class PublicScheduledSessionController {
|
||||
def index = {
|
||||
redirect(action:show)
|
||||
}
|
||||
|
||||
def show = {
|
||||
def tokenId = session['conference']
|
||||
def sessionId = session['room']
|
||||
|
||||
if (!tokenId || !sessionId) {
|
||||
redirect(action:joinIn,id:tokenId)
|
||||
}
|
||||
|
||||
def scheduledSessionInstance = ScheduledSession.findByTokenId( tokenId )
|
||||
|
||||
if(!scheduledSessionInstance) {
|
||||
flash.message = "Could not find conference session."
|
||||
redirect(action:joinIn)
|
||||
}
|
||||
else {
|
||||
def hostUrl = grailsApplication.config.grails.serverURL
|
||||
def now = new Date().time
|
||||
|
||||
def inSession = ((now > scheduledSessionInstance.startDateTime.time) && (now < scheduledSessionInstance.endDateTime.time))
|
||||
return [ scheduledSessionInstance : scheduledSessionInstance, hostUrl:hostUrl, inSession:inSession ]
|
||||
}
|
||||
}
|
||||
|
||||
def joinIn = {
|
||||
println "join $params.id"
|
||||
return [ fullname: params.fullname, id:(params.id), password: params.password ]
|
||||
}
|
||||
|
||||
def signIn = {
|
||||
println 'signIn start'
|
||||
def confSession = ScheduledSession.findByTokenId(params.id)
|
||||
def role = ''
|
||||
def signedIn = false
|
||||
|
||||
if (confSession) {
|
||||
println 'signIn: has conference session'
|
||||
|
||||
println 'Found scheduled session'
|
||||
switch (params.password) {
|
||||
case confSession.hostPassword:
|
||||
println 'as host'
|
||||
role = "HOST"
|
||||
signedIn = true
|
||||
break
|
||||
case confSession.moderatorPassword:
|
||||
println 'as moderator'
|
||||
role = "MODERATOR"
|
||||
signedIn = true
|
||||
break
|
||||
case confSession.attendeePassword:
|
||||
println 'as viewer'
|
||||
role = "VIEWER"
|
||||
signedIn = true
|
||||
break
|
||||
}
|
||||
if (signedIn) {
|
||||
println 'successful'
|
||||
session["fullname"] = params.fullname
|
||||
session["role"] = role
|
||||
session["conference"] = params.id
|
||||
session["room"] = confSession.sessionId
|
||||
session["voicebridge"] = confSession.voiceConferenceBridge
|
||||
}
|
||||
|
||||
|
||||
def long _10_MINUTES = 10*60*1000
|
||||
def now = new Date().time
|
||||
|
||||
def startTime = confSession.startDateTime.time - _10_MINUTES
|
||||
def endTime = confSession.endDateTime.time + _10_MINUTES
|
||||
|
||||
if ((startTime <= now) && (now <= endTime)) {
|
||||
session["mode"] = "LIVE"
|
||||
session["record"] = false
|
||||
if (confSession.record) {
|
||||
session["record"] = true
|
||||
}
|
||||
} else {
|
||||
session["mode"] = "PLAYBACK"
|
||||
}
|
||||
|
||||
println 'rendering signIn'
|
||||
//render(view:"signIn")
|
||||
def hostUrl = grailsApplication.config.grails.serverURL
|
||||
redirect(url:"$hostUrl/client/BigBlueButton.html")
|
||||
}
|
||||
|
||||
if (!signedIn) {
|
||||
println 'failed'
|
||||
flash.message = "Failed to join the conference session."
|
||||
redirect(action:joinIn,id:params.id, params:[fullname:params.fullname])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def enter = {
|
||||
def fname = session["fullname"]
|
||||
def rl = session["role"]
|
||||
def cnf = session["conference"]
|
||||
def rm = session["room"]
|
||||
def vb = session["voicebridge"]
|
||||
def rec = session["record"]
|
||||
def md = session["mode"]
|
||||
|
||||
if (!rm) {
|
||||
withFormat {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
'join'() {
|
||||
returnCode("FAILED")
|
||||
message("Could not find conference ${params.conference}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withFormat {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
'join'() {
|
||||
returncode("SUCCESS")
|
||||
fullname("$fname")
|
||||
role("$rl")
|
||||
conference("$cnf")
|
||||
room("$rm")
|
||||
voicebridge("${vb}")
|
||||
mode("$md")
|
||||
record("$rec")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def signOut = {
|
||||
// Log the user out of the application.
|
||||
session.invalidate()
|
||||
|
||||
// For now, redirect back to the home page.
|
||||
redirect(uri: '/')
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.bigbluebutton.web.domain.ScheduledSession
|
||||
import java.util.UUID
|
||||
import org.bigbluebutton.web.domain.User
|
||||
import org.bigbluebutton.web.domain.Conference
|
||||
|
||||
class ScheduledSessionController {
|
||||
|
||||
def index = { redirect(action:list,params:params) }
|
||||
|
||||
// the delete, save and update actions only accept POST requests
|
||||
def allowedMethods = [delete:'POST', save:'POST', update:'POST']
|
||||
|
||||
def list = {
|
||||
if(!params.max) params.max = 10
|
||||
[ scheduledSessionInstanceList: ScheduledSession.list( params ) ]
|
||||
}
|
||||
|
||||
def show = {
|
||||
def scheduledSessionInstance = ScheduledSession.get( params.id )
|
||||
|
||||
if(!scheduledSessionInstance) {
|
||||
flash.message = "ScheduledSession not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
def hostUrl = grailsApplication.config.grails.serverURL
|
||||
|
||||
return [ scheduledSessionInstance : scheduledSessionInstance, hostUrl:hostUrl ]
|
||||
}
|
||||
}
|
||||
|
||||
def delete = {
|
||||
def scheduledSessionInstance = ScheduledSession.get( params.id )
|
||||
if(scheduledSessionInstance) {
|
||||
scheduledSessionInstance.delete()
|
||||
flash.message = "ScheduledSession ${params.id} deleted"
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
flash.message = "ScheduledSession not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
}
|
||||
|
||||
def edit = {
|
||||
def scheduledSessionInstance = ScheduledSession.get( params.id )
|
||||
|
||||
if(!scheduledSessionInstance) {
|
||||
flash.message = "ScheduledSession not found with id ${params.id}"
|
||||
redirect(action:list)
|
||||
}
|
||||
else {
|
||||
return [ scheduledSessionInstance : scheduledSessionInstance ]
|
||||
}
|
||||
}
|
||||
|
||||
def update = {
|
||||
def scheduledSessionInstance = ScheduledSession.get( params.id )
|
||||
if(scheduledSessionInstance) {
|
||||
scheduledSessionInstance.properties = params
|
||||
if(!scheduledSessionInstance.hasErrors() && scheduledSessionInstance.save()) {
|
||||
flash.message = "ScheduledSession ${params.id} updated"
|
||||
redirect(action:show,id:scheduledSessionInstance.id)
|
||||
}
|
||||
else {
|
||||
render(view:'edit',model:[scheduledSessionInstance:scheduledSessionInstance])
|
||||
}
|
||||
}
|
||||
else {
|
||||
flash.message = "ScheduledSession not found with id ${params.id}"
|
||||
redirect(action:edit,id:params.id)
|
||||
}
|
||||
}
|
||||
|
||||
def create = {
|
||||
def scheduledSessionInstance = new ScheduledSession()
|
||||
scheduledSessionInstance.properties = params
|
||||
println "Conference Id = ${params.id}"
|
||||
return ['scheduledSessionInstance':scheduledSessionInstance, conferenceId:params.id]
|
||||
}
|
||||
|
||||
def save = {
|
||||
def userid = session["userid"]
|
||||
def user = User.get(userid)
|
||||
|
||||
params.createdBy = user.fullName
|
||||
params.modifiedBy = user.fullName
|
||||
|
||||
def conf = Conference.get(params.conferenceId)
|
||||
|
||||
def scheduledSessionInstance = new ScheduledSession(params)
|
||||
scheduledSessionInstance.sessionId = UUID.randomUUID()
|
||||
scheduledSessionInstance.tokenId = UUID.randomUUID()
|
||||
scheduledSessionInstance.conference = conf
|
||||
|
||||
scheduledSessionInstance.voiceConferenceBridge = generateUniqueVoiceConferenceBridgeNumber()
|
||||
|
||||
if(!scheduledSessionInstance.hasErrors() && scheduledSessionInstance.save()) {
|
||||
flash.message = "ScheduledSession ${scheduledSessionInstance.id} created"
|
||||
redirect(action:show,id:scheduledSessionInstance.id)
|
||||
}
|
||||
else {
|
||||
println "Returning conference id ${params.conferenceId}"
|
||||
render(view:'create',model:[scheduledSessionInstance:scheduledSessionInstance, conferenceId:params.conferenceId])
|
||||
}
|
||||
}
|
||||
|
||||
def generateVoiceConferenceBridgeNumber = {
|
||||
// Let's setup our conference number as six digits
|
||||
def MAX = 999999
|
||||
def MIN = 100000
|
||||
|
||||
return new Integer((int) (Math.random() * (MAX - MIN + 1)) + MIN)
|
||||
}
|
||||
|
||||
def generateUniqueVoiceConferenceBridgeNumber() {
|
||||
def bridgeExists = true
|
||||
def voiceBridge
|
||||
while (bridgeExists) {
|
||||
voiceBridge = generateVoiceConferenceBridgeNumber()
|
||||
// Check if the bridge has already exists
|
||||
def vb = ScheduledSession.findByVoiceConferenceBridge(voiceBridge.toString())
|
||||
if (vb == null) {
|
||||
bridgeExists = false
|
||||
}
|
||||
}
|
||||
|
||||
return voiceBridge
|
||||
}
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.jsecurity.crypto.hash.Sha1Hash
|
||||
import org.bigbluebutton.web.domain.User
|
||||
import org.bigbluebutton.web.domain.UserRoleRel
|
||||
|
||||
class UserController {
|
||||
|
||||
@ -116,3 +120,5 @@ class UserController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
class Attendees {
|
||||
Integer conferenceNumber
|
||||
String channelId
|
||||
Integer userNumber
|
||||
Date dateJoined
|
||||
Date dateLeft
|
||||
String callerName
|
||||
String callerNumber
|
||||
|
||||
String toString() {"${this.callerName} ${this.callerNumber}"}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
class Conference implements Comparable {
|
||||
Date dateCreated
|
||||
Date lastUpdated
|
||||
String username
|
||||
String conferenceName
|
||||
Integer conferenceNumber
|
||||
SortedSet schedules
|
||||
|
||||
static hasMany = [ schedules : Schedule ]
|
||||
static belongsTo = [user : User]
|
||||
|
||||
static constraints = {
|
||||
username(blank:false)
|
||||
conferenceName(maxLength:50, blank:false)
|
||||
conferenceNumber(maxLength:10, unique:true, blank:false)
|
||||
}
|
||||
|
||||
String toString() {"${this.conferenceName}"}
|
||||
|
||||
int compareTo(obj) {
|
||||
obj.id.compareTo(id)
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
class Schedule implements Comparable {
|
||||
Date dateCreated
|
||||
Date lastUpdated
|
||||
String scheduledBy
|
||||
String scheduleName
|
||||
String scheduleId
|
||||
Integer numberOfAttendees = new Integer(3)
|
||||
Date startDateTime = new Date()
|
||||
Integer lengthOfConference
|
||||
Boolean record = false
|
||||
String hostPassword
|
||||
String attendeePassword
|
||||
|
||||
static belongsTo = [conference : Conference]
|
||||
|
||||
static constraints = {
|
||||
scheduleName(maxLength:50, blank:false)
|
||||
scheduleId(blank:false)
|
||||
lengthOfConference(inList:[1, 2, 3, 4])
|
||||
numberOfAttendees()
|
||||
hostPassword(blank:false)
|
||||
attendeePassword(blank:false)
|
||||
scheduledBy(blank:false)
|
||||
}
|
||||
|
||||
String toString() {"${this.scheduleName}"}
|
||||
|
||||
int compareTo(obj) {
|
||||
obj.id.compareTo(id)
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
class User {
|
||||
String username
|
||||
String passwordHash
|
||||
String email
|
||||
String fullName
|
||||
SortedSet conferences
|
||||
Date dateCreated
|
||||
Date lastUpdated
|
||||
|
||||
static hasMany = [ conferences: Conference ]
|
||||
|
||||
static constraints = {
|
||||
username(nullable: false, blank: false)
|
||||
email(email:true,unique:true)
|
||||
fullName(blank:false)
|
||||
}
|
||||
|
||||
String toString() {"${this.fullName}"}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class Account implements Comparable {
|
||||
Date created
|
||||
Date lastUpdated
|
||||
String createdBy
|
||||
String updatedBy
|
||||
String type
|
||||
String name
|
||||
String description
|
||||
|
||||
static belongsTo = [owner:User]
|
||||
static hasMany = [users:User, conferences:Conference]
|
||||
|
||||
static constraints = {
|
||||
name(maxLength:50, blank:false)
|
||||
type(inList:['BASIC', 'ESSENTIAL', 'PREMIUM'])
|
||||
}
|
||||
|
||||
String toString() {"${this.name}"}
|
||||
|
||||
int compareTo(obj) {
|
||||
obj.id.compareTo(id)
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class Conference implements Comparable {
|
||||
Date dateCreated
|
||||
Date lastUpdated
|
||||
String createdBy
|
||||
String updatedBy
|
||||
String name
|
||||
User user
|
||||
|
||||
SortedSet sessions
|
||||
|
||||
static hasMany = [sessions:ScheduledSession]
|
||||
|
||||
static constraints = {
|
||||
name(maxLength:50, blank:false)
|
||||
}
|
||||
|
||||
String toString() {"${this.id}:${this.name} ${this.user}"}
|
||||
|
||||
int compareTo(obj) {
|
||||
obj.id.compareTo(id)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class Permission {
|
||||
String type
|
||||
String possibleActions
|
||||
@ -7,3 +9,4 @@ class Permission {
|
||||
possibleActions(nullable:false, blank: false)
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class Role {
|
||||
String name
|
||||
|
||||
@ -5,3 +7,5 @@ class Role {
|
||||
name(nullable: false, blank: false, unique: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class RolePermissionRel {
|
||||
Role role
|
||||
Permission permission
|
||||
@ -8,3 +10,5 @@ class RolePermissionRel {
|
||||
actions(nullable: false, blank: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,44 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class ScheduledSession implements Comparable {
|
||||
Date dateCreated
|
||||
Date lastUpdated
|
||||
String createdBy
|
||||
String modifiedBy
|
||||
|
||||
String name
|
||||
String description
|
||||
/* The id for this session. This can be used as the conference room in Red5, for example. */
|
||||
String sessionId
|
||||
/* An id that we can use in the URL to join this conference session */
|
||||
String tokenId
|
||||
Integer numberOfAttendees = new Integer(3)
|
||||
/* Is there a time limit for this session? */
|
||||
Boolean timeLimited = true
|
||||
Date startDateTime = new Date()
|
||||
/* If there is a time limit, until when? */
|
||||
Date endDateTime
|
||||
/* Is this session going to be recorded? */
|
||||
Boolean record = false
|
||||
/* Do we require a password to join this session? */
|
||||
Boolean passwordProtect = true
|
||||
String hostPassword = 'change-me-please'
|
||||
String moderatorPassword = 'change-me-please'
|
||||
String attendeePassword = 'change-me-please'
|
||||
String voiceConferenceBridge
|
||||
|
||||
Conference conference
|
||||
|
||||
static constraints = {
|
||||
name(maxLength:50, blank:false)
|
||||
tokenId(blank:false)
|
||||
sessionId(blank:false)
|
||||
numberOfAttendees()
|
||||
}
|
||||
|
||||
String toString() {"${this.id}:${this.name} - ${this.sessionId} ${this.tokenId}"}
|
||||
|
||||
int compareTo(obj) {
|
||||
obj.id.compareTo(id)
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class User {
|
||||
String username
|
||||
String passwordHash
|
||||
String fullName
|
||||
Date dateCreated
|
||||
Date lastUpdated
|
||||
|
||||
static constraints = {
|
||||
username(nullable: false, blank:false,email:true,unique:true)
|
||||
fullName(blank:false)
|
||||
}
|
||||
|
||||
String toString() {"${this.id}:${this.username},${this.fullName}"}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class UserPermissionRel {
|
||||
User user
|
||||
Permission permission
|
||||
@ -9,3 +11,5 @@ class UserPermissionRel {
|
||||
actions(nullable: false, blank: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class UserRoleRel {
|
||||
User user
|
||||
Role role
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class VoiceConferenceBridge {
|
||||
Date dateCreated
|
||||
Date lastUpdated
|
||||
String createdBy
|
||||
String modifiedBy
|
||||
|
||||
|
||||
}
|
@ -2,6 +2,12 @@ import org.jsecurity.authc.AccountException
|
||||
import org.jsecurity.authc.IncorrectCredentialsException
|
||||
import org.jsecurity.authc.UnknownAccountException
|
||||
import org.jsecurity.authc.SimpleAccount
|
||||
import org.bigbluebutton.web.domain.User
|
||||
import org.bigbluebutton.web.domain.UserRoleRel
|
||||
import org.bigbluebutton.web.domain.UserPermissionRel
|
||||
import org.bigbluebutton.web.domain.Role
|
||||
import org.bigbluebutton.web.domain.RolePermissionRel
|
||||
import org.bigbluebutton.web.domain.Permission
|
||||
|
||||
class DbRealm {
|
||||
static authTokenClass = org.jsecurity.authc.UsernamePasswordToken
|
||||
|
@ -1,539 +0,0 @@
|
||||
import javax.jms.Message
|
||||
import javax.jms.Session
|
||||
import javax.jms.JMSException
|
||||
import javax.jms.MapMessage
|
||||
import org.springframework.jms.core.JmsTemplate
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
class PresentationService {
|
||||
|
||||
boolean transactional = false
|
||||
def jmsTemplate
|
||||
def imageMagick
|
||||
def ghostScript
|
||||
def swfTools
|
||||
def presentationDir
|
||||
|
||||
private static String JMS_UPDATES_Q = 'UpdatesQueue'
|
||||
|
||||
//using java.util.concurrent.* for converting presentation
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
|
||||
def deletePresentation = {conf, room, filename ->
|
||||
def directory = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + filename)
|
||||
deleteDirectory(directory)
|
||||
}
|
||||
|
||||
def deleteDirectory = {directory ->
|
||||
System.out.println("delete = ${directory}")
|
||||
/**
|
||||
* Go through each directory and check if it's not empty.
|
||||
* We need to delete files inside a directory before a
|
||||
* directory can be deleted.
|
||||
**/
|
||||
File[] files = directory.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].isDirectory()) {
|
||||
deleteDirectory(files[i])
|
||||
} else {
|
||||
files[i].delete()
|
||||
}
|
||||
}
|
||||
// Now that the directory is empty. Delete it.
|
||||
directory.delete()
|
||||
}
|
||||
|
||||
def listPresentations = {conf, room ->
|
||||
def presentationsList = []
|
||||
def directory = roomDirectory(conf, room)
|
||||
println "directory ${directory.absolutePath}"
|
||||
if( directory.exists() ){
|
||||
directory.eachFile(){ file->
|
||||
System.out.println(file.name)
|
||||
if( file.isDirectory() )
|
||||
presentationsList.add( file.name )
|
||||
}
|
||||
}
|
||||
return presentationsList
|
||||
}
|
||||
|
||||
def processUploadedPresentation = {conf, room, presentation_name, presentation ->
|
||||
def dir = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentation_name)
|
||||
println "upload to directory ${dir.absolutePath}"
|
||||
|
||||
/* If the presentation name already exist, delete it. We should provide a check later on to notify user
|
||||
that there is already a presentation with that name. */
|
||||
if (dir.exists()) deleteDirectory(dir)
|
||||
|
||||
dir.mkdirs()
|
||||
def newFilename = presentation.getOriginalFilename().replace(' ', '-')
|
||||
def pres = new File( dir.absolutePath + File.separatorChar + newFilename )
|
||||
presentation.transferTo( pres )
|
||||
|
||||
Thread.start //for "fast-return" this http request
|
||||
{
|
||||
new Timer().runAfter(1000)
|
||||
{
|
||||
/*
|
||||
//this code cannot be built by grails(inner class problem by grails), so we have to add more classes who implements Callable and override call() there
|
||||
Callable<Integer> task_convertUploadedPresentation =
|
||||
new Callable<Integer>(){
|
||||
public Integer call(){
|
||||
//return convertUploadedPresentation(conf, room, presentation_name, pres);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
//first we need to know how many pages in this pdf
|
||||
def numPages = getPresentationNumPages(conf, room, presentation_name, pres)
|
||||
assert((new Integer(numPages).intValue()) != -1)
|
||||
|
||||
println "PresentationService.groory::processUploadedPresentation()... now we get how many pages in this pdf with swftools: numPages=" + numPages
|
||||
|
||||
//CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(executor);
|
||||
|
||||
//then submit a task to processUploadedPresentation
|
||||
//swftools(0.8.1) has concurrency problem(the newer pdf2swf-thread will cancel old one), so we need to make sure to use newer one, like swftools-2009-04-13-0127.exe
|
||||
println "PresentationService.groory::processUploadedPresentation()... now call Callable_convertUploadedPresentation"
|
||||
Callable<Integer> task_convertUploadedPresentation = new Callable_convertUploadedPresentation(this, conf, room, presentation_name, pres, numPages);
|
||||
Future<Integer> future_convertUploadedPresentation = executor.submit(task_convertUploadedPresentation);
|
||||
//completionService.submit(task_convertUploadedPresentation);
|
||||
|
||||
//then submit a task to createThumbnails
|
||||
println "PresentationService.groory::processUploadedPresentation()... now call Callable_createThumbnails"
|
||||
Callable<Integer> task_createThumbnails = new Callable_createThumbnails(this, pres, numPages);
|
||||
Future<Integer> future_createThumbnails = executor.submit(task_createThumbnails);
|
||||
//completionService.submit(task_createThumbnails);
|
||||
|
||||
|
||||
//then wait for future_convertUploadedPresentation.get()
|
||||
try{
|
||||
int errorcode = future_convertUploadedPresentation.get().intValue();
|
||||
assert(errorcode != -1)
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// Re-assert the thread's interrupted status
|
||||
Thread.currentThread().interrupt();
|
||||
// We don't need the result, so cancel the task too
|
||||
future_convertUploadedPresentation.cancel(true);
|
||||
} catch (ExecutionException e) {
|
||||
//throw launderThrowable(e.getCause());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//then wait for future_createThumbnails.get()
|
||||
try{
|
||||
int errorcode = future_createThumbnails.get().intValue();
|
||||
assert(errorcode != -1)
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// Re-assert the thread's interrupted status
|
||||
Thread.currentThread().interrupt();
|
||||
// We don't need the result, so cancel the task too
|
||||
future_convertUploadedPresentation.cancel(true);
|
||||
} catch (ExecutionException e) {
|
||||
//throw launderThrowable(e.getCause());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//then wait for the above two completionService(tasks)
|
||||
try {
|
||||
for (int t = 0; t < 2; t++) {
|
||||
Future<Integer> f = completionService.take();
|
||||
int errorcode = f.get().intValue();
|
||||
assert(errorcode != -1)
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (ExecutionException e) {
|
||||
//throw launderThrowable(e.getCause());
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* We just assume that everything is OK. Send a SUCCESS message to the client */
|
||||
println "PresentationService.groory::processUploadedPresentation()... now converting(slides & thumbnails) is OK, we send message by JMS"
|
||||
def msg = new HashMap()
|
||||
msg.put("room", room)
|
||||
msg.put("presentationName", presentation_name)
|
||||
msg.put("returnCode", "SUCCESS")
|
||||
msg.put("message", "The presentation is now ready.")
|
||||
System.out.println("Sending presentation conversion success.")
|
||||
jmsTemplate.convertAndSend(JMS_UPDATES_Q,msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def getPresentationNumPages = {conf, room, presentation_name, presentation ->
|
||||
def numPages = -1 //total numbers of this pdf, also used as errorcode(-1)
|
||||
|
||||
try
|
||||
{
|
||||
def command = swfTools + "/pdf2swf -I " + presentation.getAbsolutePath()
|
||||
println "PresentationService.groory::processUploadedPresentation()... first get how many pages in this pdf with swftools: command=" + command
|
||||
def p = Runtime.getRuntime().exec(command);
|
||||
|
||||
//p.waitFor();
|
||||
|
||||
def stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
def stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
def info
|
||||
def str //output information to console for stdInput and stdError
|
||||
while ((info = stdInput.readLine()) != null) {
|
||||
//The output would be something like this 'page=21 width=718.00 height=538.00'.
|
||||
//We need to extract the page number (i.e. 21) from it.
|
||||
def infoRegExp = /page=([0-9]+)(?: .+)/
|
||||
def matcher = (info =~ infoRegExp)
|
||||
if (matcher.matches()) {
|
||||
//if ((matcher[0][1]) > numPages) {
|
||||
numPages = matcher[0][1]
|
||||
// println "Number of pages = ${numPages}"
|
||||
// } else {
|
||||
// println "Number of pages = ${numPages} match=" + matcher[0][1]
|
||||
// }
|
||||
} else {
|
||||
println "no match info: ${info}"
|
||||
}
|
||||
}
|
||||
while ((info = stdError.readLine()) != null) {
|
||||
System.out.println("Got error getting info from file):\n");
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
//assert(p.exitValue() == 0)
|
||||
if(p.exitValue() != 0) return -1;
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("exception happened - here's what I know: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return numPages
|
||||
}
|
||||
|
||||
def showSlide(String conf, String room, String presentationName, String id) {
|
||||
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar + "slide-${id}.swf")
|
||||
}
|
||||
|
||||
def showPresentation = {conf, room, filename ->
|
||||
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + filename + File.separatorChar + "slides.swf")
|
||||
}
|
||||
|
||||
def showThumbnail = {conf, room, presentationName, thumb ->
|
||||
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar +
|
||||
"thumbnails" + File.separatorChar + "thumb-${thumb}.png")
|
||||
}
|
||||
|
||||
def numberOfThumbnails = {conf, room, name ->
|
||||
def thumbDir = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + name + File.separatorChar + "thumbnails")
|
||||
System.out.println(thumbDir.absolutePath + " " + thumbDir.listFiles().length)
|
||||
thumbDir.listFiles().length
|
||||
}
|
||||
|
||||
def roomDirectory = {conf, room ->
|
||||
return new File(presentationDir + File.separatorChar + conf + File.separatorChar + room)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Callable_convertUploadedPresentation implements Callable
|
||||
{
|
||||
def caller
|
||||
def conf
|
||||
def room
|
||||
def presentation_name
|
||||
def presentation
|
||||
def numPages
|
||||
|
||||
Callable_convertUploadedPresentation(PresentationService caller, String conf, String room, String presentation_name, File presentation, String numPages)
|
||||
{
|
||||
this.caller = caller;
|
||||
this.conf = conf;
|
||||
this.room = room;
|
||||
this.presentation_name = presentation_name;
|
||||
this.presentation = presentation;
|
||||
this.numPages = numPages;
|
||||
}
|
||||
|
||||
public Integer call(){
|
||||
return convertUploadedPresentation(conf, room, presentation_name, presentation, numPages);
|
||||
}
|
||||
|
||||
def convertUploadedPresentation = {conf, room, presentation_name, presentation, numPages ->
|
||||
def command
|
||||
def Process p
|
||||
def BufferedReader stdInput
|
||||
def BufferedReader stdError
|
||||
def info
|
||||
def page = 0
|
||||
def str //output information to console for stdInput and stdError
|
||||
|
||||
println "PresentationService.groory@Callable_convertUploadedPresentation::convertUploadedPresentation()... numPages=" + numPages + " now start to convert this pdf one page by one page....."
|
||||
try
|
||||
{
|
||||
Future<Integer>[] futures = new Future<Integer>[(new Integer(numPages)).intValue()];
|
||||
|
||||
for (page = 1; page <= new Integer(numPages); page++)
|
||||
{
|
||||
println "PresentationService.groory@Callable_convertUploadedPresentation::convertUploadedPresentation()... submit task: page=" + page
|
||||
Callable<Integer> task_convertOnePage = new Callable_convertOnePage(caller, conf, room, presentation_name, presentation, numPages, page);
|
||||
futures[page-1] = caller.executor.submit(task_convertOnePage);
|
||||
}
|
||||
|
||||
for (page = 1; page <= new Integer(numPages); page++)
|
||||
{
|
||||
println "PresentationService.groory@Callable_convertUploadedPresentation::convertUploadedPresentation()... get future: page=" + page
|
||||
try
|
||||
{
|
||||
int errorcode = futures[page-1].get().intValue();
|
||||
if(errorcode != 0) return new Integer(-1)
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// Re-assert the thread's interrupted status
|
||||
Thread.currentThread().interrupt();
|
||||
// We don't need the result, so cancel the task too
|
||||
futures[page-1].cancel(true);
|
||||
} catch (ExecutionException e) {
|
||||
//throw launderThrowable(e.getCause());
|
||||
println(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new Integer(0)
|
||||
}
|
||||
}
|
||||
|
||||
class Callable_createThumbnails implements Callable
|
||||
{
|
||||
def caller
|
||||
def presentation
|
||||
def numPages
|
||||
|
||||
Callable_createThumbnails(PresentationService caller, File presentation, String numPages)
|
||||
{
|
||||
this.caller = caller;
|
||||
this.presentation = presentation;
|
||||
this.numPages = numPages;
|
||||
}
|
||||
|
||||
public Integer call(){
|
||||
return createThumbnails(presentation, numPages);
|
||||
}
|
||||
|
||||
def createThumbnails = {presentation, numPages ->
|
||||
/* We create thumbnails for the uploaded presentation. */
|
||||
try {
|
||||
System.out.println("Creating thumbnails:\n");
|
||||
def thumbsDir = new File(presentation.getParent() + File.separatorChar + "thumbnails")
|
||||
thumbsDir.mkdir()
|
||||
|
||||
def command
|
||||
def num = new Integer(numPages)
|
||||
if(num == 1) command = caller.imageMagick + "/convert -thumbnail 150x150 " + presentation.getAbsolutePath() + " " + thumbsDir.getAbsolutePath() + "/thumb-0.png"
|
||||
else command = caller.imageMagick + "/convert -thumbnail 150x150 " + presentation.getAbsolutePath() + " " + thumbsDir.getAbsolutePath() + "/thumb.png"
|
||||
Process p = Runtime.getRuntime().exec(command);
|
||||
|
||||
BufferedReader stdInput = new BufferedReader(new
|
||||
InputStreamReader(p.getInputStream()));
|
||||
BufferedReader stdError = new BufferedReader(new
|
||||
InputStreamReader(p.getErrorStream()));
|
||||
def str
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
// read any errors from the attempted command
|
||||
System.out.println("Here is the standard error of the command (if any):\n");
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
//assert(p.exitValue() == 0)
|
||||
if(p.exitValue() != 0) return new Integer(-1);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("exception happened - here's what I know: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new Integer(0);
|
||||
}
|
||||
}
|
||||
|
||||
class Callable_convertOnePage implements Callable
|
||||
{
|
||||
def caller
|
||||
def conf
|
||||
def room
|
||||
def presentation_name
|
||||
def presentation
|
||||
def numPages
|
||||
def page
|
||||
|
||||
Callable_convertOnePage(PresentationService caller, String conf, String room, String presentation_name, File presentation, String numPages, Integer page)
|
||||
{
|
||||
this.caller = caller;
|
||||
this.conf = conf;
|
||||
this.room = room;
|
||||
this.presentation_name = presentation_name;
|
||||
this.presentation = presentation;
|
||||
this.numPages = numPages;
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public Integer call(){
|
||||
return convertOnePage(conf, room, presentation_name, presentation, numPages, page);
|
||||
}
|
||||
|
||||
def convertOnePage = {conf, room, presentation_name, presentation, numPages, page ->
|
||||
def command
|
||||
def Process p
|
||||
def BufferedReader stdInput
|
||||
def BufferedReader stdError
|
||||
def info
|
||||
def str //output information to console for stdInput and stdError
|
||||
|
||||
println "PresentationService.groory@Callable_convertOnePage::convertOnePage()... numPages=" + numPages + " now start to convert this page by one page..... page=" + page
|
||||
try
|
||||
{
|
||||
/* Now we convert the pdf file to swf
|
||||
* We start the output with a page number starting at zero (0) so it's consistent
|
||||
* with the naming convention when we create the thumbnails. Looks like ImageMagick
|
||||
* uses zero-base when creating the thumbnails.
|
||||
*/
|
||||
command = caller.swfTools + "/pdf2swf -p " + page + " " + presentation.getAbsolutePath() + " -o " + presentation.parent + File.separatorChar + "slide-" + (page-1) + ".swf"
|
||||
println "PresentationService.groory::convertUploadedPresentation()... first we use swftools to convert this page: command=" + command
|
||||
p = Runtime.getRuntime().exec(command)
|
||||
|
||||
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
System.out.println("Converting slide: ${page}\n");
|
||||
def numSlidesProcessed = 0
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
def msg = new HashMap()
|
||||
msg.put("room", room)
|
||||
msg.put("presentationName", presentation_name)
|
||||
msg.put("returnCode", "CONVERT")
|
||||
msg.put("totalSlides", numPages)
|
||||
|
||||
/* The convert output is something like ''NOTICE processing PDF page 2 (718x538:0:0) (move:-37:-37)'.
|
||||
* We extract the page number from it taking it as a successful conversion.
|
||||
*/
|
||||
def convertRegExp = /NOTICE (?: .+) page ([0-9]+)(?: .+)/
|
||||
def matcher = (str =~ convertRegExp)
|
||||
if (matcher.matches()) {
|
||||
//println matcher[0][1]
|
||||
numSlidesProcessed++ // increment the number of slides processed
|
||||
msg.put("slidesCompleted", page)
|
||||
println "number of slides completed ${page}"
|
||||
caller.jmsTemplate.convertAndSend(caller.JMS_UPDATES_Q,msg)
|
||||
} else {
|
||||
println "no match convert: ${str}"
|
||||
}
|
||||
}
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println("Got error converting file):\n");
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
//got error for "pdf-swf" way with swftools, so now we switch to "pdf-jpeg-swf" way with ImageMagick
|
||||
if(p.exitValue()!=0)
|
||||
{
|
||||
println("PresentationService.groory::convertUploadedPresentation()... got error for 'pdf-swf' with swftools, so now we switch to 'pdf-jpeg-swf' with GhostScript&ImageMagick&swftools(jpeg2swf), page=" + page);
|
||||
def tempDir = new File(presentation.getParent() + File.separatorChar + "temp")
|
||||
tempDir.mkdir()
|
||||
|
||||
//extract that specific page and create a temp-pdf(only one page) with GhostScript
|
||||
command = caller.ghostScript + " -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -dFirstPage=" + page +" -dLastPage=" + page + " -sOutputFile=" + (tempDir.getAbsolutePath() + "/temp.pdf") + " " + presentation.getAbsolutePath()
|
||||
println("PresentationService.groory::convertUploadedPresentation()... extract this page from pdf and create a temp-pdf(one page only) with GhostScript: command=" + command);
|
||||
p = Runtime.getRuntime().exec(command);
|
||||
|
||||
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
// read any errors from the attempted command
|
||||
System.out.println("Here is the standard error of the command (if any):\n");
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
//assert(p.exitValue() == 0)
|
||||
if(p.exitValue() != 0) return new Integer(-1);
|
||||
|
||||
//convert that temp-pdf to jpeg with ImageMagick
|
||||
def num = new Integer(numPages)
|
||||
if(num == 1) command = caller.imageMagick + "/convert " + (tempDir.getAbsolutePath() + "/temp.pdf") + " " + (tempDir.getAbsolutePath() + "/temp-0.jpeg")
|
||||
else command = caller.imageMagick + "/convert " + (tempDir.getAbsolutePath() + "/temp.pdf") + " " + (tempDir.getAbsolutePath() + "/temp.jpeg")
|
||||
println("PresentationService.groory::convertUploadedPresentation()... convert that temp-pdf to jpeg with ImageMagick: command=" + command);
|
||||
p = Runtime.getRuntime().exec(command);
|
||||
|
||||
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
// read any errors from the attempted command
|
||||
System.out.println("Here is the standard error of the command (if any):\n");
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
//assert(p.exitValue() == 0)
|
||||
if(p.exitValue() != 0) return new Integer(-1);
|
||||
|
||||
//now convert that jpeg to swf with swftools(jpeg2swf)
|
||||
command = caller.swfTools + "/jpeg2swf -o " + presentation.parent + File.separatorChar + "slide-" + (page-1) + ".swf" + " " + presentation.parent + File.separatorChar + "temp/temp-" + (page-1) + ".jpeg"
|
||||
println("PresentationService.groory::convertUploadedPresentation()... convert that jpeg to swf with swftools(jpeg2swf): command=" + command);
|
||||
p = Runtime.getRuntime().exec(command);
|
||||
|
||||
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
// read any errors from the attempted command
|
||||
System.out.println("Here is the standard error of the command (if any):\n");
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
//assert(p.exitValue() == 0)
|
||||
if(p.exitValue() != 0) return new Integer(-1);
|
||||
}
|
||||
else{
|
||||
println("PresentationService.groory::convertUploadedPresentation()... convert this page to swf with swftools OK, page=" + page);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("exception happened - here's what I know: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new Integer(0)
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import javax.jms.MapMessage
|
||||
|
||||
class RecordService {
|
||||
|
||||
boolean transactional = true
|
||||
|
||||
def handleRecordMessage = {message ->
|
||||
|
||||
println "--Got JMS message"
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
import org.apache.commons.httpclient.*
|
||||
import org.apache.commons.httpclient.auth.AuthScope
|
||||
import org.apache.commons.httpclient.methods.*
|
||||
|
||||
public class VolunteerOttawaService {
|
||||
|
||||
boolean transactional = true
|
||||
|
||||
static final URL = "http://www.volunteerottawa.ca/vo-clean/ws.php"
|
||||
static final reply = """
|
||||
<sessionid>3ba9c30076797e7dc3bef88be5cbbefe</sessionid>
|
||||
<userid>1110</userid>
|
||||
<email>wow@crystalbaymedia.com</email>
|
||||
<login>Conference</login>
|
||||
<firstname></firstname>
|
||||
<lastname></lastname>
|
||||
<vologin>
|
||||
</vologin>
|
||||
"""
|
||||
|
||||
private vologin(String sessionId, Closure callable) {
|
||||
|
||||
// build the URL
|
||||
def url = "${URL}?sessionId=${sessionId}"
|
||||
|
||||
def client = new HttpClient()
|
||||
|
||||
def get = new GetMethod(url)
|
||||
|
||||
client.executeMethod(get)
|
||||
callable( new XmlSlurper().parseText(get.getResponseBodyAsString() ) )
|
||||
}
|
||||
|
||||
def loginToVo(sessionId) {
|
||||
vologin(sessionId) { xml ->
|
||||
println xml
|
||||
println "email ${xml.email} fullname ${xml.firstname} ${xml.lastname}"
|
||||
def res = [email: xml.email, fullname: "${xml.firstname} ${xml.lastname}"]
|
||||
return res
|
||||
}
|
||||
|
||||
/*
|
||||
def url = new URL("http://www.volunteerottawa.ca/vo-clean/ws.php?sessionId=${sessionId}")
|
||||
def connection = url.openConnection()
|
||||
|
||||
def result = [:]
|
||||
if(connection.responseCode == 200){
|
||||
def xml = connection.content.text
|
||||
println xml
|
||||
def user = new XmlSlurper().parseText(xml)
|
||||
result.email = user.email as String
|
||||
result.fullname = (user.firstname as String) + " " + (user.lastname as String)
|
||||
// result.lastname = user.lastname as String
|
||||
}
|
||||
else{
|
||||
log.error("GeocoderService.geocodeAirport FAILED")
|
||||
log.error(url)
|
||||
log.error(connection.responseCode)
|
||||
log.error(connection.responseMessage)
|
||||
}
|
||||
return result
|
||||
*/
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ import java.sql.SQLException;
|
||||
import javax.sql.DataSource;
|
||||
*/
|
||||
|
||||
import Conference;
|
||||
import org.bigbluebutton.web.domain.Conference;
|
||||
|
||||
class AsteriskAgi implements AgiScript {
|
||||
|
||||
|
@ -1,121 +0,0 @@
|
||||
package org.bigbluebutton.pbx.asterisk;
|
||||
|
||||
import org.asteriskjava.live.AsteriskChannel;
|
||||
import org.asteriskjava.live.AsteriskQueue;
|
||||
import org.asteriskjava.live.AsteriskServer;
|
||||
import org.asteriskjava.live.AsteriskServerListener;
|
||||
import org.asteriskjava.live.DefaultAsteriskServer;
|
||||
import org.asteriskjava.live.ManagerCommunicationException;
|
||||
import org.asteriskjava.live.MeetMeRoom;
|
||||
import org.asteriskjava.live.MeetMeUser;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import Attendees;
|
||||
|
||||
class ConferenceAttendanceRecorder implements AsteriskServerListener, PropertyChangeListener
|
||||
{
|
||||
private AsteriskServer asteriskServer;
|
||||
DataSource dataSource
|
||||
|
||||
def void setAsteriskServer(AsteriskServer server) {
|
||||
asteriskServer = server;
|
||||
}
|
||||
|
||||
def void startup() throws ManagerCommunicationException
|
||||
{
|
||||
// listen for new events
|
||||
asteriskServer.addAsteriskServerListener(this);
|
||||
|
||||
for (MeetMeRoom meetMeRoom : asteriskServer.getMeetMeRooms())
|
||||
{
|
||||
for (MeetMeUser user : meetMeRoom.getUsers())
|
||||
{
|
||||
System.out.println("Startup")
|
||||
printUser(user)
|
||||
user.addPropertyChangeListener(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def void onNewAsteriskChannel(AsteriskChannel channel)
|
||||
{
|
||||
}
|
||||
|
||||
def void onNewMeetMeUser(MeetMeUser user)
|
||||
{
|
||||
user.addPropertyChangeListener(this);
|
||||
System.out.print("onNewMeetMeUser ")
|
||||
saveRecord(user)
|
||||
}
|
||||
|
||||
def void propertyChange(PropertyChangeEvent propertyChangeEvent)
|
||||
{
|
||||
System.out.println("propertyChange 0")
|
||||
if (propertyChangeEvent.getSource() instanceof MeetMeUser) {
|
||||
System.out.println("propertyChange 1")
|
||||
// System.out.println(propertyChangeEvent);
|
||||
MeetMeUser user = (MeetMeUser) propertyChangeEvent.getSource();
|
||||
saveRecord(user)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def void shutdown() {
|
||||
asteriskServer.shutdown();
|
||||
}
|
||||
|
||||
def printUser(MeetMeUser user) {
|
||||
System.out.println(
|
||||
user.getRoom().getRoomNumber() + " " +
|
||||
user.getChannel().getId() + " " +
|
||||
user.getDateJoined() + " " +
|
||||
user.getDateLeft() + " " +
|
||||
user.getUserNumber() + " " +
|
||||
user.getChannel().getCallerId().getName() + " " +
|
||||
user.getChannel().getCallerId().getNumber());
|
||||
}
|
||||
|
||||
def saveRecord(MeetMeUser user) {
|
||||
printUser(user)
|
||||
System.out.println("Saving Record ")
|
||||
|
||||
def cdr = Attendees.findByChannelIdAndConferenceNumber(user.getChannel().getId(),
|
||||
user.getRoom().getRoomNumber())
|
||||
def conf = Conference.findByConferenceNumber(user.getRoom().getRoomNumber())
|
||||
|
||||
System.out.println("Finding Record " + conf)
|
||||
|
||||
if (!cdr) {
|
||||
System.out.println("Creating ")
|
||||
def rec = new Attendees(
|
||||
conferenceNumber : user.getRoom().getRoomNumber(),
|
||||
channelId : user.getChannel().getId(),
|
||||
dateJoined : user.getDateJoined(),
|
||||
dateLeft : user.getDateLeft() ? user.getDateLeft() : new Date(),
|
||||
userNumber : user.getUserNumber(),
|
||||
callerName : user.getChannel().getCallerId().getName() ? user.getChannel().getCallerId().getName() : "Unknown",
|
||||
callerNumber : user.getChannel().getCallerId().getNumber() ? user.getChannel().getCallerId().getNumber() : "Unknown"
|
||||
)
|
||||
|
||||
rec.save()
|
||||
System.out.println("Created ${cdr.conferenceNumber} ${cdr.channelId}")
|
||||
} else {
|
||||
System.out.println("Updating ")
|
||||
// cdr.conferenceNumber = user.getRoom().getRoomNumber()
|
||||
// cdr.channelId = user.getChannel().getId()
|
||||
cdr.dateJoined = user.getDateJoined()
|
||||
cdr.dateLeft = user.getDateLeft()
|
||||
cdr.userNumber = user.getUserNumber()
|
||||
cdr.callerName = user.getChannel().getCallerId().getName() ? user.getChannel().getCallerId().getName() : "Unknown"
|
||||
cdr.callerNumber = user.getChannel().getCallerId().getNumber() ? user.getChannel().getCallerId().getNumber() : "Unknown"
|
||||
cdr.save()
|
||||
System.out.println("updated ${cdr.conferenceNumber} ${cdr.channelId}")
|
||||
}
|
||||
System.out.println("Saved Record ")
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,383 @@
|
||||
package org.bigbluebutton.web.services
|
||||
|
||||
import javax.jms.Message
|
||||
import javax.jms.Session
|
||||
import javax.jms.JMSException
|
||||
import javax.jms.MapMessage
|
||||
import org.springframework.jms.core.JmsTemplate
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.lang.InterruptedException
|
||||
class PresentationService {
|
||||
|
||||
boolean transactional = false
|
||||
def jmsTemplate
|
||||
def imageMagick
|
||||
def ghostScript
|
||||
def swfTools
|
||||
def presentationDir
|
||||
|
||||
private static String JMS_UPDATES_Q = 'UpdatesQueue'
|
||||
|
||||
def deletePresentation = {conf, room, filename ->
|
||||
def directory = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + filename)
|
||||
deleteDirectory(directory)
|
||||
}
|
||||
|
||||
def deleteDirectory = {directory ->
|
||||
log.debug "delete = ${directory}"
|
||||
/**
|
||||
* Go through each directory and check if it's not empty.
|
||||
* We need to delete files inside a directory before a
|
||||
* directory can be deleted.
|
||||
**/
|
||||
File[] files = directory.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].isDirectory()) {
|
||||
deleteDirectory(files[i])
|
||||
} else {
|
||||
files[i].delete()
|
||||
}
|
||||
}
|
||||
// Now that the directory is empty. Delete it.
|
||||
directory.delete()
|
||||
}
|
||||
|
||||
def listPresentations = {conf, room ->
|
||||
def presentationsList = []
|
||||
def directory = roomDirectory(conf, room)
|
||||
log.debug "directory ${directory.absolutePath}"
|
||||
if( directory.exists() ){
|
||||
directory.eachFile(){ file->
|
||||
System.out.println(file.name)
|
||||
if( file.isDirectory() )
|
||||
presentationsList.add( file.name )
|
||||
}
|
||||
}
|
||||
return presentationsList
|
||||
}
|
||||
|
||||
public File uploadedPresentationDirectory(String conf, String room, String presentation_name) {
|
||||
println "Uploaded presentation ${presentation_name}"
|
||||
File dir = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentation_name)
|
||||
println "upload to directory ${dir.absolutePath}"
|
||||
|
||||
/* If the presentation name already exist, delete it. We should provide a check later on to notify user
|
||||
that there is already a presentation with that name. */
|
||||
if (dir.exists()) deleteDirectory(dir)
|
||||
dir.mkdirs()
|
||||
|
||||
assert dir.exists()
|
||||
return dir
|
||||
}
|
||||
|
||||
def processUploadedPresentation = {conf, room, presentationName, presentationFile ->
|
||||
// Run conversion on another thread.
|
||||
new Timer().runAfter(1000)
|
||||
{
|
||||
//first we need to know how many pages in this pdf
|
||||
int numPages = determineNumberOfPages(presentationFile)
|
||||
log.info "There are $numPages pages in $presentationFile.absolutePath"
|
||||
convertUploadedPresentation(room, presentationName, presentationFile, numPages)
|
||||
}
|
||||
}
|
||||
|
||||
public int determineNumberOfPages(File presentationFile) {
|
||||
def numPages = -1 //total numbers of this pdf, also used as errorcode(-1)
|
||||
|
||||
try
|
||||
{
|
||||
def command = swfTools + "/pdf2swf -I " + presentationFile.getAbsolutePath()
|
||||
def p = Runtime.getRuntime().exec(command);
|
||||
|
||||
def stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
def stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
def info
|
||||
def str //output information to console for stdInput and stdError
|
||||
while ((info = stdInput.readLine()) != null) {
|
||||
//The output would be something like this 'page=21 width=718.00 height=538.00'.
|
||||
//We need to extract the page number (i.e. 21) from it.
|
||||
def infoRegExp = /page=([0-9]+)(?: .+)/
|
||||
def matcher = (info =~ infoRegExp)
|
||||
if (matcher.matches()) {
|
||||
numPages = matcher[0][1]
|
||||
} else {
|
||||
println "no match info: ${info}"
|
||||
}
|
||||
}
|
||||
while ((info = stdError.readLine()) != null) {
|
||||
System.out.println("Got error getting info from file):\n");
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
//assert(p.exitValue() == 0)
|
||||
if(p.exitValue() != 0) return -1;
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("exception happened - here's what I know: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new Integer(numPages).intValue()
|
||||
}
|
||||
|
||||
def showSlide(String conf, String room, String presentationName, String id) {
|
||||
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar + "slide-${id}.swf")
|
||||
}
|
||||
|
||||
def showPresentation = {conf, room, filename ->
|
||||
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + filename + File.separatorChar + "slides.swf")
|
||||
}
|
||||
|
||||
def showThumbnail = {conf, room, presentationName, thumb ->
|
||||
def thumbFile = roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar +
|
||||
"thumbnails" + File.separatorChar + "thumb-${thumb}.png"
|
||||
log.debug "showing $thumbFile"
|
||||
|
||||
new File(thumbFile)
|
||||
}
|
||||
|
||||
def numberOfThumbnails = {conf, room, name ->
|
||||
def thumbDir = new File(roomDirectory(conf, room).absolutePath + File.separatorChar + name + File.separatorChar + "thumbnails")
|
||||
thumbDir.listFiles().length
|
||||
}
|
||||
|
||||
def roomDirectory = {conf, room ->
|
||||
return new File(presentationDir + File.separatorChar + conf + File.separatorChar + room)
|
||||
}
|
||||
|
||||
public boolean convertUploadedPresentation(String room, String presentationName, File presentationFile, int numPages) {
|
||||
log.debug "Converting uploaded presentation $presentationFile.absolutePath"
|
||||
for (int page = 1; page <= numPages; page++)
|
||||
{
|
||||
def msg = new HashMap()
|
||||
msg.put("room", room)
|
||||
msg.put("returnCode", "CONVERT")
|
||||
msg.put("presentationName", presentationName)
|
||||
msg.put("totalSlides", new Integer(numPages))
|
||||
msg.put("slidesCompleted", new Integer(page))
|
||||
sendJmsMessage(msg)
|
||||
|
||||
log.debug "Converting page $page of $presentationFile.absolutePath"
|
||||
|
||||
convertPage(presentationFile, page)
|
||||
}
|
||||
|
||||
log.debug "Creating thumbnails for $presentationFile.absolutePath"
|
||||
createThumbnails(presentationFile)
|
||||
|
||||
def msg = new HashMap()
|
||||
msg.put("room", room)
|
||||
msg.put("returnCode", "SUCCESS")
|
||||
msg.put("presentationName", presentationName)
|
||||
msg.put("message", "The presentation is now ready.")
|
||||
log.info "Sending presentation conversion success for $presentationFile.absolutePath."
|
||||
sendJmsMessage(msg)
|
||||
}
|
||||
|
||||
public boolean convertPage(File presentationFile, int page) {
|
||||
if (! convertUsingPdf2Swf(presentationFile, page)) {
|
||||
log.info "cannot convert page $page"
|
||||
if (extractPageUsingGhostScript(presentationFile, page)) {
|
||||
log.info "created using ghostscript page $page"
|
||||
if (convertUsingImageMagick(presentationFile, page)) {
|
||||
log.info "created using imagemagick page $page"
|
||||
if (convertUsingJpeg2Swf(presentationFile, page)) {
|
||||
log.info "create using jpeg page $page"
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public boolean extractPageUsingGhostScript(File presentationFile, int page) {
|
||||
def tempDir = new File(presentationFile.parent + File.separatorChar + "temp")
|
||||
tempDir.mkdir()
|
||||
|
||||
String OPTIONS = "-sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH"
|
||||
String PAGE = "-dFirstPage=${page} -dLastPage=${page}"
|
||||
String dest = tempDir.absolutePath + File.separator + "temp-${page}.pdf"
|
||||
|
||||
//extract that specific page and create a temp-pdf(only one page) with GhostScript
|
||||
def command = ghostScript + " " + OPTIONS + " " + PAGE + " " + "-sOutputFile=${dest}" + " " + presentationFile
|
||||
println command
|
||||
|
||||
def process
|
||||
try {
|
||||
def now = new Date()
|
||||
println "GS starting $now"
|
||||
|
||||
process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// Wait for the process to finish.
|
||||
int exitVal = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "GS starting $now"
|
||||
|
||||
def stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
def stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
def str
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
// read any errors from the attempted command
|
||||
System.out.println("Here is the standard error of the command (if any):\n");
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
|
||||
if (process.exitValue() == 0) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public boolean convertUsingJpeg2Swf(File presentationFile, int page) {
|
||||
def tempDir = new File(presentationFile.getParent() + File.separatorChar + "temp")
|
||||
|
||||
def source = tempDir.absolutePath + File.separator + "temp-${page}.jpeg"
|
||||
def dest = presentationFile.parent + File.separatorChar + "slide-${page}.swf"
|
||||
println "converting $source to $dest"
|
||||
|
||||
def now = new Date()
|
||||
println "JPEG2SWF starting $now"
|
||||
|
||||
def command = swfTools + "/jpeg2swf -o " + dest + " " + source
|
||||
def process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// Wait for the process to finish.
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "JPEG2SWF ended $now"
|
||||
|
||||
def stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
def stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
def str
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
// read any errors from the attempted command
|
||||
System.out.println("Here is the standard error of the command (if any):\n");
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
File destFile = new File(dest)
|
||||
if (destFile.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public boolean convertUsingImageMagick(File presentationFile, int page) {
|
||||
def tempDir = new File(presentationFile.getParent() + File.separatorChar + "temp")
|
||||
tempDir.mkdir()
|
||||
|
||||
def source = tempDir.getAbsolutePath() + "/temp-${page}.pdf"
|
||||
def dest = tempDir.getAbsolutePath() + "/temp-${page}.jpeg"
|
||||
|
||||
def now = new Date()
|
||||
println "IMAGEMAGICK starting $now"
|
||||
|
||||
def command = imageMagick + "/convert " + source + " " + dest
|
||||
|
||||
def process = Runtime.getRuntime().exec(command);
|
||||
// Wait for the process to finish.
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "IMAGEMAGICK ends $now"
|
||||
|
||||
File destFile = new File(dest)
|
||||
if (destFile.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public boolean convertUsingPdf2Swf(File presentationFile, int page) {
|
||||
def source = presentationFile.getAbsolutePath()
|
||||
def dest = presentationFile.parent + File.separatorChar + "slide-" + page + ".swf"
|
||||
|
||||
def command = swfTools + "/pdf2swf -p " + page + " " + source + " -o " + dest
|
||||
def process = Runtime.getRuntime().exec(command)
|
||||
|
||||
// Wait for the process to finish
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
File destFile = new File(dest)
|
||||
if (destFile.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public boolean createThumbnails(File presentationFile) {
|
||||
try {
|
||||
log.debug "Creating thumbnails:"
|
||||
def thumbsDir = new File(presentationFile.getParent() + File.separatorChar + "thumbnails")
|
||||
thumbsDir.mkdir()
|
||||
|
||||
def source = presentationFile.getAbsolutePath()
|
||||
def dest = thumbsDir.getAbsolutePath() + "/temp-thumb.png"
|
||||
|
||||
def command = imageMagick + "/convert -thumbnail 150x150 " + source + " " + dest
|
||||
Process p = Runtime.getRuntime().exec(command);
|
||||
int exitValue = p.waitFor()
|
||||
|
||||
renameThumbnails(thumbsDir)
|
||||
|
||||
if (exitValue == 0) return true
|
||||
|
||||
return false
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
log.error "exception happened - here's what I know: "
|
||||
log.error e.printStackTrace()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private renameThumbnails(File dir) {
|
||||
dir.eachFile{file ->
|
||||
// filename should be something like 'c:/temp/bigluebutton/presname/thumbnails/temp-thumb-1.png'
|
||||
def filename = file.absolutePath
|
||||
|
||||
// Extract the page number. There should be 3 matches.
|
||||
// 1. c:/temp/bigluebutton/presname/thumbnails/temp-thumb
|
||||
// 2. 1 ---> what we are interested in
|
||||
// 3. .png
|
||||
def infoRegExp = /(.+-thumb)-([0-9]+)(.png)/
|
||||
def matcher = (filename =~ infoRegExp)
|
||||
if (matcher.matches()) {
|
||||
// We are interested in the second match.
|
||||
int pageNum = new Integer(matcher[0][2]).intValue()
|
||||
def newFilename = "thumb-${++pageNum}.png"
|
||||
File renamedFile = new File(file.parent + File.separator + newFilename)
|
||||
file.renameTo(renamedFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sendJmsMessage(HashMap message) {
|
||||
jmsTemplate.convertAndSend(JMS_UPDATES_Q, message)
|
||||
}
|
||||
}
|
||||
|
||||
/*** Helper classes **/
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.File;
|
||||
class PngFilter implements FilenameFilter {
|
||||
public boolean accept(File dir, String name) {
|
||||
return (name.endsWith(".png"));
|
||||
}
|
||||
}
|
@ -27,21 +27,11 @@
|
||||
<tbody>
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="conferenceName">Conference Name:</label>
|
||||
<label for="name">Conference Name:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:conferenceInstance,field:'conferenceName','errors')}">
|
||||
<input type="text" id="conferenceName" name="conferenceName" value="${fieldValue(bean:conferenceInstance,field:'conferenceName')}"/>
|
||||
<td valign="top" class="value ${hasErrors(bean:conferenceInstance,field:'name','errors')}">
|
||||
<input type="text" id="name" name="name" value="${fieldValue(bean:conferenceInstance,field:'name')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="conferenceNumber">Conference Number:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:conferenceInstance,field:'conferenceNumber','errors')}">
|
||||
<input type="text" id="conferenceNumber" name="conferenceNumber" value="${fieldValue(bean:conferenceInstance,field:'conferenceNumber')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -34,17 +34,8 @@
|
||||
<td valign="top" class="name">
|
||||
<label for="conferenceName">Conference Name:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:conference,field:'conferenceName','errors')}">
|
||||
<input type="text" id="conferenceName" name="conferenceName" value="${fieldValue(bean:conference,field:'conferenceName')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="conferenceNumber">Conference Number:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:conference,field:'conferenceNumber','errors')}">
|
||||
${conference.conferenceNumber}
|
||||
<td valign="top" class="value ${hasErrors(bean:conference,field:'name','errors')}">
|
||||
<input type="text" id="name" name="name" value="${fieldValue(bean:conference,field:'name')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -68,10 +59,10 @@
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="username">Created By:</label>
|
||||
<label for="createdBy">Created By:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:conference,field:'username','errors')}">
|
||||
${conference.username}
|
||||
<td valign="top" class="value ${hasErrors(bean:conference,field:'createdBy','errors')}">
|
||||
${conference.createdBy}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -20,9 +20,7 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<g:sortableColumn property="conferenceName" title="Conference Name" />
|
||||
<g:sortableColumn property="conferenceNumber" title="Conference Number" />
|
||||
<g:sortableColumn property="username" title="Username" />
|
||||
<g:sortableColumn property="name" title="Conference Name" />
|
||||
<g:sortableColumn property="dateCreated" title="Date Created" />
|
||||
<g:sortableColumn property="lastUpdated" title="Last Updated" />
|
||||
</tr>
|
||||
@ -30,9 +28,7 @@
|
||||
<tbody>
|
||||
<g:each in="${conferenceList}" status="i" var="conference">
|
||||
<tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
|
||||
<td><g:link action="show" id="${conference.id}">${fieldValue(bean:conference, field:'conferenceName')}</g:link></td>
|
||||
<td>${fieldValue(bean:conference, field:'conferenceNumber')}</td>
|
||||
<td>${fieldValue(bean:conference, field:'username')}</td>
|
||||
<td><g:link action="show" id="${conference.id}">${fieldValue(bean:conference, field:'name')}</g:link></td>
|
||||
<td>${fieldValue(bean:conference, field:'dateCreated')}</td>
|
||||
<td>${fieldValue(bean:conference, field:'lastUpdated')}</td>
|
||||
</tr>
|
||||
@ -40,9 +36,6 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="paginateButtons">
|
||||
<g:paginate total="${Conference.count()}" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -11,6 +11,7 @@
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
<span class="menuButton"><g:link class="list" action="list">Your Conferences</g:link></span>
|
||||
<span class="menuButton"><g:link class="create" action="create">New Conference</g:link></span>
|
||||
<span class="menuButton"><g:link controller="schedule" class="create" id="${conference?.id}" action="create">Schedule Session</g:link></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Show Conference</h1>
|
||||
@ -24,21 +25,14 @@
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Created By:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:conference, field:'username')}</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:conference, field:'createdBy')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Conference Name:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:conference, field:'conferenceName')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Conference Number:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:conference, field:'conferenceNumber')}</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:conference, field:'name')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
@ -54,34 +48,6 @@
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:conference, field:'lastUpdated')}</td>
|
||||
|
||||
</tr>
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="schedules"></label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:conferenceInstance,field:'schedules','errors')}">
|
||||
|
||||
<ul>
|
||||
<g:each var="s" in="${conferenceInstance?.schedules?}">
|
||||
<li><g:link controller="schedule" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
|
||||
</g:each>
|
||||
</ul>
|
||||
<g:link controller="schedule" params="['conferenceId':conference.id]" action="create">Add Schedule</g:link>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Schedules:</td>
|
||||
|
||||
<td valign="top" style="text-align:left;" class="value">
|
||||
<ul>
|
||||
<g:each var="s" in="${conference.schedules}">
|
||||
<li><g:link controller="schedule" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
|
||||
</g:each>
|
||||
</ul>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
@ -95,5 +61,32 @@
|
||||
</g:form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Scheduled Sessions</h1>
|
||||
<div class="list">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<g:sortableColumn property="name" title="Name" />
|
||||
<g:sortableColumn property="tokenId" title="Link" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<g:each in="${sessions}" status="i" var="schedSession">
|
||||
<tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
|
||||
<td>${schedSession.name?.encodeAsHTML()}</td>
|
||||
<g:if test="${schedSession.expired}">
|
||||
<td><g:link controller="schedule" action="show" id="${schedSession.id}">
|
||||
display</g:link>
|
||||
</td>
|
||||
</g:if>
|
||||
|
||||
|
||||
</tr>
|
||||
</g:each>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,39 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="layout" content="main" />
|
||||
<title>Login</title>
|
||||
</head>
|
||||
<body>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
<g:form controller="conference-session" action="signIn">
|
||||
<g:if test="${id}">
|
||||
<input type="hidden" name="id" value="${id}" />
|
||||
</g:if>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Fullname:</td>
|
||||
<td><input type="text" name="fullname" value="${fullname}" /></td>
|
||||
</tr>
|
||||
<g:if test="${!id}">
|
||||
<tr>
|
||||
<td>Session Id:</td>
|
||||
<td><input type="text" name="id" value="${id}" /></td>
|
||||
</tr>
|
||||
</g:if>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td><g:passwordField name="password" value="" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td />
|
||||
<td><input type="submit" value="Sign in" /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</g:form>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,89 @@
|
||||
|
||||
<%@ page import="org.bigbluebutton.web.domain.ScheduledSession" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Show ScheduledSession</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Information on ${scheduledSessionInstance.name}</h1>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
<div class="dialog">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Session:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'name')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Description:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'description')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Voice Conference Bridge:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'voiceConferenceBridge')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Link:</td>
|
||||
|
||||
<td valign="top" class="value">
|
||||
<g:if test="${inSession}">
|
||||
<g:link controller="conference-session" action="joinIn" id="${scheduledSessionInstance.tokenId}">Join</g:link>
|
||||
</g:if>
|
||||
<g:else>
|
||||
<g:link controller="conference-session" action="joinIn" id="${scheduledSessionInstance.tokenId}">Play</g:link>
|
||||
</g:else>
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Start Date Time:</td>
|
||||
|
||||
<td valign="top" class="value">
|
||||
<g:formatDate format="EEE, d MMM yyyy 'at' hh:mm aaa" date="${scheduledSessionInstance.startDateTime}"/>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">End Date Time:</td>
|
||||
<td valign="top" class="value">
|
||||
<g:formatDate format="EEE, d MMM yyyy 'at' hh:mm aaa" date="${scheduledSessionInstance.endDateTime}"/>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Conference:</td>
|
||||
|
||||
<td valign="top" class="value">
|
||||
${scheduledSessionInstance?.conference?.name.encodeAsHTML()}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,14 @@
|
||||
|
||||
<%@ page import="org.bigbluebutton.web.domain.ScheduledSession" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Show ScheduledSession</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,102 +0,0 @@
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Create Schedule</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Create Schedule</h1>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
<g:hasErrors bean="${scheduleInstance}">
|
||||
<div class="errors">
|
||||
<g:renderErrors bean="${scheduleInstance}" as="list" />
|
||||
</div>
|
||||
</g:hasErrors>
|
||||
<g:form action="save" method="post" >
|
||||
<input type="hidden" name="conferenceId" value="${conferenceId}" />
|
||||
<div class="dialog">
|
||||
<table>
|
||||
<tbody>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="scheduleName">Name this schedule:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'scheduleName','errors')}">
|
||||
<input type="text" id="scheduleName" name="scheduleName" value="${fieldValue(bean:scheduleInstance,field:'scheduleName')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="lengthOfConference">How long (hours)?:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'lengthOfConference','errors')}">
|
||||
<input type="text" id="lengthOfConference" name="lengthOfConference" value="${fieldValue(bean:scheduleInstance,field:'lengthOfConference')}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="numberOfAttendees">How many will attend?:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'numberOfAttendees','errors')}">
|
||||
<input type="text" id="numberOfAttendees" name="numberOfAttendees" value="${fieldValue(bean:scheduleInstance,field:'numberOfAttendees')}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="hostPassword">Password for Host?:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'hostPassword','errors')}">
|
||||
<input type="text" id="hostPassword" name="hostPassword" value="${fieldValue(bean:scheduleInstance,field:'hostPassword')}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="attendeePassword">Password for Attendee?:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'attendeePassword','errors')}">
|
||||
<input type="text" id="attendeePassword" name="attendeePassword" value="${fieldValue(bean:scheduleInstance,field:'attendeePassword')}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="record">Record the conference?:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'record','errors')}">
|
||||
<g:checkBox name="record" value="${scheduleInstance?.record}" ></g:checkBox>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="startDateTime">Please enter the start date and time:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'startDateTime','errors')}">
|
||||
<g:datePicker name="startDateTime" value="${scheduleInstance?.startDateTime}" ></g:datePicker>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<span class="button"><input class="save" type="submit" value="Create" /></span>
|
||||
<span class="button"><g:link controller="conference" action="show" id="${conferenceId}">Cancel</g:link></span>
|
||||
</div>
|
||||
</g:form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,93 +0,0 @@
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Edit Schedule</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Edit Schedule</h1>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
<g:hasErrors bean="${scheduleInstance}">
|
||||
<div class="errors">
|
||||
<g:renderErrors bean="${scheduleInstance}" as="list" />
|
||||
</div>
|
||||
</g:hasErrors>
|
||||
<g:form method="post" >
|
||||
<input type="hidden" name="id" value="${scheduleInstance?.id}" />
|
||||
<div class="dialog">
|
||||
<table>
|
||||
<tbody>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="scheduleName">Schedule Name:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'scheduleName','errors')}">
|
||||
<input type="text" id="scheduleName" name="scheduleName" value="${fieldValue(bean:scheduleInstance,field:'scheduleName')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="lengthOfConference">Length Of Conference:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'lengthOfConference','errors')}">
|
||||
<input type="text" id="lengthOfConference" name="lengthOfConference" value="${fieldValue(bean:scheduleInstance,field:'lengthOfConference')}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="numberOfAttendees">Number Of Attendees:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'numberOfAttendees','errors')}">
|
||||
<input type="text" id="numberOfAttendees" name="numberOfAttendees" value="${fieldValue(bean:scheduleInstance,field:'numberOfAttendees')}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="record">Record:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'record','errors')}">
|
||||
<g:checkBox name="record" value="${scheduleInstance?.record}" ></g:checkBox>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="startDateTime">Start Date Time:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'startDateTime','errors')}">
|
||||
<g:datePicker name="startDateTime" value="${scheduleInstance?.startDateTime}" ></g:datePicker>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="scheduledBy">Scheduled By:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduleInstance,field:'scheduledBy','errors')}">
|
||||
${scheduleInstance.scheduledBy}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<span class="button"><g:actionSubmit class="save" value="Update" /></span>
|
||||
<span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
|
||||
<span class="button"><g:link action="show" id="${scheduleInstance.id}">Cancel</g:link></span>
|
||||
</div>
|
||||
</g:form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,98 +0,0 @@
|
||||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Show Schedule</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Show Schedule</h1>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
<div class="dialog">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Schedule Name:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'scheduleName')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Schedule Id:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'scheduleId')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Length Of Conference:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'lengthOfConference')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Number Of Attendees:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'numberOfAttendees')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Password for Host:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'hostPassword')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Password for Attendees:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'attendeePassword')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Scheduled By:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'scheduledBy')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Date Created:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'dateCreated')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Last Updated:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'lastUpdated')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Record:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'record')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Start Date Time:</td>
|
||||
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduleInstance, field:'startDateTime')}</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<g:form>
|
||||
<input type="hidden" name="id" value="${scheduleInstance?.id}" />
|
||||
<input type="hidden" name="conferenceId" value="${scheduleInstance?.conferenceId}" />
|
||||
<span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
|
||||
<span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
|
||||
<span class="button"><g:link controller="conference" action="show" id="${scheduleInstance.conferenceId}">Back to Conference</g:link></span>
|
||||
</g:form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
138
bigbluebutton-web/grails-app/views/scheduledSession/create.gsp
Normal file
138
bigbluebutton-web/grails-app/views/scheduledSession/create.gsp
Normal file
@ -0,0 +1,138 @@
|
||||
|
||||
<%@ page import="org.bigbluebutton.web.domain.ScheduledSession" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Create ScheduledSession</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
<span class="menuButton"><g:link class="list" action="list">ScheduledSession List</g:link></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Create ScheduledSession</h1>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
<g:hasErrors bean="${scheduledSessionInstance}">
|
||||
<div class="errors">
|
||||
<g:renderErrors bean="${scheduledSessionInstance}" as="list" />
|
||||
</div>
|
||||
</g:hasErrors>
|
||||
<g:form action="save" method="post" >
|
||||
<input type="hidden" name="conferenceId" value="${conferenceId}" />
|
||||
<div class="dialog">
|
||||
<table>
|
||||
<tbody>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="name">Name:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'name','errors')}">
|
||||
<input type="text" id="name" name="name" value="${fieldValue(bean:scheduledSessionInstance,field:'name')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="name">Description:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'description','errors')}">
|
||||
<g:textArea name="description" value="${fieldValue(bean:scheduledSessionInstance,field:'description')}" rows="5" cols="40"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="numberOfAttendees">Number Of Attendees:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'numberOfAttendees','errors')}">
|
||||
<input type="text" id="numberOfAttendees" name="numberOfAttendees" value="${fieldValue(bean:scheduledSessionInstance,field:'numberOfAttendees')}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="record">Record:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'record','errors')}">
|
||||
<g:checkBox name="record" value="${scheduledSessionInstance?.record}" ></g:checkBox>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="timeLimited">Time Limited:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'timeLimited','errors')}">
|
||||
<g:checkBox name="timeLimited" value="${scheduledSessionInstance?.timeLimited}" ></g:checkBox>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="startDateTime">Start Date Time:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'startDateTime','errors')}">
|
||||
<g:datePicker name="startDateTime" value="${scheduledSessionInstance?.startDateTime}" ></g:datePicker>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="endDateTime">End Date Time:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'endDateTime','errors')}">
|
||||
<g:datePicker name="endDateTime" value="${scheduledSessionInstance?.endDateTime}" ></g:datePicker>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="passwordProtect">Password Protect:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'passwordProtect','errors')}">
|
||||
<g:checkBox name="passwordProtect" value="${scheduledSessionInstance?.passwordProtect}" ></g:checkBox>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="attendeePassword">Attendee Password:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'attendeePassword','errors')}">
|
||||
<input type="text" id="attendeePassword" name="attendeePassword" value="${fieldValue(bean:scheduledSessionInstance,field:'attendeePassword')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="hostPassword">Host Password:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'hostPassword','errors')}">
|
||||
<input type="text" id="hostPassword" name="hostPassword" value="${fieldValue(bean:scheduledSessionInstance,field:'hostPassword')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="moderatorPassword">Moderator Password:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'moderatorPassword','errors')}">
|
||||
<input type="text" id="moderatorPassword" name="moderatorPassword" value="${fieldValue(bean:scheduledSessionInstance,field:'moderatorPassword')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<span class="button"><input class="save" type="submit" value="Create" /></span>
|
||||
</div>
|
||||
</g:form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
177
bigbluebutton-web/grails-app/views/scheduledSession/edit.gsp
Normal file
177
bigbluebutton-web/grails-app/views/scheduledSession/edit.gsp
Normal file
@ -0,0 +1,177 @@
|
||||
|
||||
<%@ page import="org.bigbluebutton.web.domain.ScheduledSession" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Edit ScheduledSession</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
<span class="menuButton"><g:link class="list" action="list">ScheduledSession List</g:link></span>
|
||||
<span class="menuButton"><g:link class="create" action="create">New ScheduledSession</g:link></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Edit ScheduledSession</h1>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
<g:hasErrors bean="${scheduledSessionInstance}">
|
||||
<div class="errors">
|
||||
<g:renderErrors bean="${scheduledSessionInstance}" as="list" />
|
||||
</div>
|
||||
</g:hasErrors>
|
||||
<g:form method="post" >
|
||||
<input type="hidden" name="id" value="${scheduledSessionInstance?.id}" />
|
||||
<div class="dialog">
|
||||
<table>
|
||||
<tbody>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="name">Name:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'name','errors')}">
|
||||
<input type="text" id="name" name="name" value="${fieldValue(bean:scheduledSessionInstance,field:'name')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="numberOfAttendees">Number Of Attendees:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'numberOfAttendees','errors')}">
|
||||
<input type="text" id="numberOfAttendees" name="numberOfAttendees" value="${fieldValue(bean:scheduledSessionInstance,field:'numberOfAttendees')}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="record">Record:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'record','errors')}">
|
||||
<g:checkBox name="record" value="${scheduledSessionInstance?.record}" ></g:checkBox>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="timeLimited">Time Limited:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'timeLimited','errors')}">
|
||||
<g:checkBox name="timeLimited" value="${scheduledSessionInstance?.timeLimited}" ></g:checkBox>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="startDateTime">Start Date Time:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'startDateTime','errors')}">
|
||||
<g:datePicker name="startDateTime" value="${scheduledSessionInstance?.startDateTime}" ></g:datePicker>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="startDateTime">End Date Time:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'endDateTime','errors')}">
|
||||
<g:datePicker name="endDateTime" value="${scheduledSessionInstance?.endDateTime}" ></g:datePicker>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="passwordProtect">Password Protect:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'passwordProtect','errors')}">
|
||||
<g:checkBox name="passwordProtect" value="${scheduledSessionInstance?.passwordProtect}" ></g:checkBox>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="attendeePassword">Attendee Password:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'attendeePassword','errors')}">
|
||||
<input type="text" id="attendeePassword" name="attendeePassword" value="${fieldValue(bean:scheduledSessionInstance,field:'attendeePassword')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="hostPassword">Host Password:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'hostPassword','errors')}">
|
||||
<input type="text" id="hostPassword" name="hostPassword" value="${fieldValue(bean:scheduledSessionInstance,field:'hostPassword')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="moderatorPassword">Moderator Password:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'moderatorPassword','errors')}">
|
||||
<input type="text" id="moderatorPassword" name="moderatorPassword" value="${fieldValue(bean:scheduledSessionInstance,field:'moderatorPassword')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="conference">Conference:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'conference','errors')}">
|
||||
${scheduledSessionInstance?.conference?.name}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="createdBy">Created By:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'createdBy','errors')}">
|
||||
${fieldValue(bean:scheduledSessionInstance,field:'createdBy')}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="dateCreated">Date Created:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'dateCreated','errors')}">
|
||||
${scheduledSessionInstance?.dateCreated}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="lastUpdated">Last Updated:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'lastUpdated','errors')}">
|
||||
${scheduledSessionInstance?.lastUpdated}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">
|
||||
<label for="modifiedBy">Modified By:</label>
|
||||
</td>
|
||||
<td valign="top" class="value ${hasErrors(bean:scheduledSessionInstance,field:'modifiedBy','errors')}">
|
||||
${fieldValue(bean:scheduledSessionInstance,field:'modifiedBy')}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<span class="button"><g:actionSubmit class="save" value="Update" /></span>
|
||||
<span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
|
||||
</div>
|
||||
</g:form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,18 +1,18 @@
|
||||
|
||||
|
||||
<%@ page import="org.bigbluebutton.web.domain.ScheduledSession" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Schedule List</title>
|
||||
<title>ScheduledSession List</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
<span class="menuButton"><g:link class="create" action="create">New Schedule</g:link></span>
|
||||
<span class="menuButton"><g:link class="create" action="create">New ScheduledSession</g:link></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Schedule List</h1>
|
||||
<h1>ScheduledSession List</h1>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
@ -23,33 +23,33 @@
|
||||
|
||||
<g:sortableColumn property="id" title="Id" />
|
||||
|
||||
<g:sortableColumn property="scheduleName" title="Schedule Name" />
|
||||
<g:sortableColumn property="name" title="Name" />
|
||||
|
||||
<g:sortableColumn property="scheduleNumber" title="Schedule Number" />
|
||||
<g:sortableColumn property="tokenId" title="Token Id" />
|
||||
|
||||
<g:sortableColumn property="lengthOfConference" title="Length Of Conference" />
|
||||
<g:sortableColumn property="sessionId" title="Session Id" />
|
||||
|
||||
<g:sortableColumn property="duration" title="Duration" />
|
||||
|
||||
<g:sortableColumn property="numberOfAttendees" title="Number Of Attendees" />
|
||||
|
||||
<g:sortableColumn property="scheduledBy" title="Scheduled By" />
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<g:each in="${scheduleInstanceList}" status="i" var="scheduleInstance">
|
||||
<g:each in="${scheduledSessionInstanceList}" status="i" var="scheduledSessionInstance">
|
||||
<tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
|
||||
|
||||
<td><g:link action="show" id="${scheduleInstance.id}">${fieldValue(bean:scheduleInstance, field:'id')}</g:link></td>
|
||||
<td><g:link action="show" id="${scheduledSessionInstance.id}">${fieldValue(bean:scheduledSessionInstance, field:'id')}</g:link></td>
|
||||
|
||||
<td>${fieldValue(bean:scheduleInstance, field:'scheduleName')}</td>
|
||||
<td>${fieldValue(bean:scheduledSessionInstance, field:'name')}</td>
|
||||
|
||||
<td>${fieldValue(bean:scheduleInstance, field:'scheduleId')}</td>
|
||||
<td>${fieldValue(bean:scheduledSessionInstance, field:'tokenId')}</td>
|
||||
|
||||
<td>${fieldValue(bean:scheduleInstance, field:'lengthOfConference')}</td>
|
||||
<td>${fieldValue(bean:scheduledSessionInstance, field:'sessionId')}</td>
|
||||
|
||||
<td>${fieldValue(bean:scheduleInstance, field:'numberOfAttendees')}</td>
|
||||
<td>${fieldValue(bean:scheduledSessionInstance, field:'duration')}</td>
|
||||
|
||||
<td>${fieldValue(bean:scheduleInstance, field:'scheduledBy')}</td>
|
||||
<td>${fieldValue(bean:scheduledSessionInstance, field:'numberOfAttendees')}</td>
|
||||
|
||||
</tr>
|
||||
</g:each>
|
||||
@ -57,7 +57,7 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="paginateButtons">
|
||||
<g:paginate total="${Schedule.count()}" />
|
||||
<g:paginate total="${ScheduledSession.count()}" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
130
bigbluebutton-web/grails-app/views/scheduledSession/show.gsp
Normal file
130
bigbluebutton-web/grails-app/views/scheduledSession/show.gsp
Normal file
@ -0,0 +1,130 @@
|
||||
|
||||
<%@ page import="org.bigbluebutton.web.domain.ScheduledSession" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta name="layout" content="main" />
|
||||
<title>Show ScheduledSession</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<span class="menuButton"><a class="home" href="${createLinkTo(dir:'')}">Home</a></span>
|
||||
<span class="menuButton"><g:link class="list" action="list">ScheduledSession List</g:link></span>
|
||||
<span class="menuButton"><g:link class="create" action="create">New ScheduledSession</g:link></span>
|
||||
</div>
|
||||
<div class="body">
|
||||
<h1>Show ScheduledSession</h1>
|
||||
<g:if test="${flash.message}">
|
||||
<div class="message">${flash.message}</div>
|
||||
</g:if>
|
||||
<div class="dialog">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Name:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'name')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Description:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'description')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Voice Conference Bridge:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'voiceConferenceBridge')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Link:</td>
|
||||
<td valign="top" class="value">
|
||||
${hostUrl}/${scheduledSessionInstance.tokenId}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">End Date Time:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'endDateTime')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Number Of Attendees:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'numberOfAttendees')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Attendee Password:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'attendeePassword')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Conference:</td>
|
||||
<td valign="top" class="value">
|
||||
<g:link controller="conference" action="show" id="${scheduledSessionInstance?.conference?.id}">
|
||||
${scheduledSessionInstance?.conference?.encodeAsHTML()}
|
||||
</g:link>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Created By:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'createdBy')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Date Created:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'dateCreated')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Host Password:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'hostPassword')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Last Updated:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'lastUpdated')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Moderator Password:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'moderatorPassword')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Modified By:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'modifiedBy')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Password Protect:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'passwordProtect')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Record:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'record')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Time Limited:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'timeLimited')}</td>
|
||||
</tr>
|
||||
|
||||
<tr class="prop">
|
||||
<td valign="top" class="name">Start Date Time:</td>
|
||||
<td valign="top" class="value">${fieldValue(bean:scheduledSessionInstance, field:'startDateTime')}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<g:form>
|
||||
<input type="hidden" name="id" value="${scheduledSessionInstance?.id}" />
|
||||
<span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
|
||||
<span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
|
||||
</g:form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,27 +0,0 @@
|
||||
package org.bigbluebutton.web.jms
|
||||
|
||||
import javax.jms.MapMessage
|
||||
import javax.jms.Message
|
||||
import javax.jms.MessageListener
|
||||
|
||||
import org.springframework.jms.core.JmsTemplate
|
||||
|
||||
/**
|
||||
* Listener for Map messages containing messages to record.
|
||||
*
|
||||
* @author Richard Alam
|
||||
*/
|
||||
class RecordMessageListener implements MessageListener {
|
||||
|
||||
def jmsTemplate
|
||||
|
||||
public void onMessage(Message message) {
|
||||
|
||||
MapMessage map = (MapMessage) message
|
||||
String msg = map.getString("message")
|
||||
|
||||
println "Got ${msg}"
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
class AttendeeControllerTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
class AttendeesTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
class BookTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
class ConferenceControllerTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
class PresentationServiceTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
class RecordServiceTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
class ScheduleControllerTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
import VolunteerOttawaService
|
||||
|
||||
class VolunteerOttawaServiceTests extends GroovyTestCase {
|
||||
|
||||
VolunteerOttawaService voService
|
||||
|
||||
void setUp() {
|
||||
voService = new VolunteerOttawaService()
|
||||
}
|
||||
|
||||
void testSomething() {
|
||||
assert voService != null
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.jsecurity.crypto.hash.Sha1Hash
|
||||
import org.bigbluebutton.web.domain.Role
|
||||
import org.bigbluebutton.web.domain.User
|
||||
import org.bigbluebutton.web.domain.UserRoleRel
|
||||
|
||||
class AuthControllerTests extends GroovyTestCase {
|
||||
|
||||
void testLogin() {
|
||||
// Administrator user and role.
|
||||
def adminRole = new Role(name: "Administrator").save()
|
||||
def adminUser = new User(username: "admin@test.com", passwordHash: new Sha1Hash("admin").toHex(),
|
||||
fullName: "Admin").save()
|
||||
new UserRoleRel(user: adminUser, role: adminRole).save()
|
||||
|
||||
// A normal user.
|
||||
def userRole = new Role(name: "User").save()
|
||||
def normalUser = new User(username: "phil@test.com", passwordHash: new Sha1Hash("password").toHex(),
|
||||
fullName: "Phil").save()
|
||||
new UserRoleRel(user: normalUser, role: userRole).save()
|
||||
|
||||
// Give another user the "User" role.
|
||||
normalUser = new User(username: "alice@test.com", passwordHash: new Sha1Hash("changeit").toHex(),
|
||||
fullName: "Alice").save()
|
||||
new UserRoleRel(user: normalUser, role: userRole).save()
|
||||
|
||||
assertEquals 3, User.list().size()
|
||||
|
||||
def ac = new AuthController()
|
||||
ac.params.username = "admin@test.com"
|
||||
ac.params.password = "admin"
|
||||
ac.params.targetUri = "/login-success"
|
||||
ac.signIn()
|
||||
|
||||
assertEquals "/login-success", ac.response.redirectedUrl
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.bigbluebutton.web.domain.Conference
|
||||
import org.jsecurity.crypto.hash.Sha1Hash
|
||||
import org.bigbluebutton.web.domain.User
|
||||
|
||||
class ConferenceControllerTests extends GroovyTestCase {
|
||||
def CONFERENCE_NAME = 'test-conference'
|
||||
def USERNAME = "admin@test.com"
|
||||
def USER_PASSWORD = "admin"
|
||||
def USER_FULLNAME = "Admin User"
|
||||
|
||||
void testCreateConference() {
|
||||
// Let's create a user to own the conference
|
||||
def adminUser = new User(username:USERNAME , passwordHash: new Sha1Hash(USER_PASSWORD).toHex(),
|
||||
fullName: USER_FULLNAME).save()
|
||||
assertEquals 1, adminUser.id
|
||||
assertEquals USERNAME, adminUser.username
|
||||
|
||||
// setup our controller
|
||||
def cc = new ConferenceController()
|
||||
// setup our mocked session
|
||||
cc.session["userid"] = adminUser.id
|
||||
// mock the params that get's sent from the client
|
||||
cc.params.name = CONFERENCE_NAME
|
||||
// now save to create the conference
|
||||
cc.save()
|
||||
assertEquals 1, Conference.list().size()
|
||||
def conf = Conference.findByName(CONFERENCE_NAME)
|
||||
assertEquals CONFERENCE_NAME, conf.name
|
||||
assertEquals adminUser.id, conf.user.id
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
class PresentationControllerTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
class PublicConferenceControllerTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
class PublicScheduledSessionControllerTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
import org.bigbluebutton.web.domain.Conference
|
||||
import org.bigbluebutton.web.domain.User
|
||||
import org.bigbluebutton.web.domain.ScheduledSession
|
||||
import org.jsecurity.crypto.hash.Sha1Hash
|
||||
|
||||
class ScheduleSessionControllerTests extends GroovyTestCase {
|
||||
def CONFERENCE_NAME = 'test-conference'
|
||||
def USERNAME = "admin@test.com"
|
||||
def USER_PASSWORD = "admin"
|
||||
def USER_FULLNAME = "Admin User"
|
||||
|
||||
void testCreateConference() {
|
||||
// Let's create a user to own the conference
|
||||
def adminUser = new User(username:USERNAME , passwordHash: new Sha1Hash(USER_PASSWORD).toHex(),
|
||||
fullName: USER_FULLNAME).save()
|
||||
assertEquals 1, adminUser.id
|
||||
assertEquals USERNAME, adminUser.username
|
||||
|
||||
def c = new Conference()
|
||||
c.createdBy = adminUser.fullName
|
||||
c.updatedBy = adminUser.fullName
|
||||
c.name = CONFERENCE_NAME
|
||||
c.user = adminUser
|
||||
c.save()
|
||||
|
||||
assertEquals 1, Conference.list().size()
|
||||
def conf = Conference.findByName(CONFERENCE_NAME)
|
||||
assertEquals CONFERENCE_NAME, conf.name
|
||||
assertEquals adminUser.id, conf.user.id
|
||||
|
||||
def ssc = new ScheduledSessionController()
|
||||
ssc.session["userid"] = adminUser.id
|
||||
ssc.params.conferenceId = conf.id
|
||||
ssc.params.name = 'test-conference-schedule'
|
||||
ssc.params.duration = 2
|
||||
ssc.params.record = true
|
||||
ssc.params.passwordProtect = true
|
||||
ssc.params.hostPassword = 'TestMostPassword'
|
||||
ssc.params.moderatorPassword = 'TestModeratorPassword'
|
||||
ssc.params.attendeePassword = 'TestAttendeePassword'
|
||||
|
||||
ssc.save()
|
||||
assertEquals 1, ScheduledSession.list().size()
|
||||
conf = Conference.get(conf.id)
|
||||
println conf.sessions
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.controllers
|
||||
|
||||
class UserControllerTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class AccountTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class AccountTypeTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class BasicAccountTypeTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class ConferenceSessionTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class ConferenceTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class PermissionTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class RolePermissionRelTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class RoleTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class ScheduleTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class ScheduledSessionTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class UserPermissionRelTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class UserRoleRelTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class UserTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.web.domain
|
||||
|
||||
class VoiceConferenceBridgeTests extends GroovyTestCase {
|
||||
|
||||
void testSomething() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,286 @@
|
||||
package org.bigbluebutton.web.services
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
import org.codehaus.groovy.grails.commons.*
|
||||
|
||||
class PresentationServiceTests extends GroovyTestCase {
|
||||
|
||||
def SWFTOOLS = "C:/swftools-0.9"
|
||||
def IMAGEMAGICK = "C:/ImageMagick-6.4.9-Q16/"
|
||||
def GHOSTSCRIPT = "C:/gs/gs8.63/bin/gswin32c.exe"
|
||||
def PRESENTATIONDIR = "c:/temp/bigbluebutton"
|
||||
|
||||
def presService
|
||||
|
||||
void setUp() {
|
||||
/* Get the values from bigbluebutton.properties
|
||||
* We have to set this manually unlike when running
|
||||
* as an application where spring injects these
|
||||
* values for us.
|
||||
*/
|
||||
def config = ConfigurationHolder.config
|
||||
SWFTOOLS = config.swfTools
|
||||
IMAGEMAGICK = config.imageMagick
|
||||
PRESENTATIONDIR = config.presentationDir
|
||||
GHOSTSCRIPT = config.ghostScript
|
||||
|
||||
presService = new PresentationService()
|
||||
presService.swfTools = SWFTOOLS
|
||||
presService.imageMagick = IMAGEMAGICK
|
||||
presService.ghostScript = GHOSTSCRIPT
|
||||
presService.presentationDir = PRESENTATIONDIR
|
||||
|
||||
|
||||
}
|
||||
|
||||
void testGetUploadDirectory() {
|
||||
def uploadedFilename = 'sample-presentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "test-presentation"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
}
|
||||
|
||||
void testGetNumberOfPagesForPresentation() {
|
||||
def uploadedFilename = 'sample-presentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "test-presentation"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 8, numPages
|
||||
}
|
||||
|
||||
void testConvertUsingPdf2Swf() {
|
||||
def uploadedFilename = 'sample-presentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "test-presentation"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 8, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingPdf2Swf(uploadedPresentation, page)
|
||||
}
|
||||
}
|
||||
|
||||
void testExtractPageUsingGhostscript() {
|
||||
def uploadedFilename = 'sample-presentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "test-presentation"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 8, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
def result = presService.extractPageUsingGhostScript(uploadedPresentation, page)
|
||||
assertTrue result
|
||||
}
|
||||
|
||||
File tempdir = new File(uploadedPresentation.parent + File.separator + "temp")
|
||||
FilenameFilter filter = new PdfFilter();
|
||||
String[] files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
def result = presService.convertUsingImageMagick(uploadedPresentation, page)
|
||||
assertTrue result
|
||||
}
|
||||
|
||||
filter = new JpegFilter();
|
||||
files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
def result = presService.convertUsingJpeg2Swf(uploadedPresentation, page)
|
||||
assertTrue result
|
||||
}
|
||||
|
||||
File outDir = new File(uploadedPresentation.parent)
|
||||
filter = new SwfFilter();
|
||||
files = outDir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
}
|
||||
|
||||
void testProcessOneSlideWithTooManyObjectsPresentation() {
|
||||
def uploadedFilename = 'big.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "big"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 1, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.extractPageUsingGhostScript(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File tempdir = new File(uploadedPresentation.parent + File.separator + "temp")
|
||||
FilenameFilter filter = new PdfFilter();
|
||||
String[] files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingImageMagick(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
filter = new JpegFilter();
|
||||
files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingJpeg2Swf(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File outDir = new File(uploadedPresentation.parent)
|
||||
filter = new SwfFilter();
|
||||
files = outDir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
}
|
||||
|
||||
|
||||
void testProcessSeveralSlidesWithTooManyObjectsPresentation() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "severalbig"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 5, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.extractPageUsingGhostScript(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File tempdir = new File(uploadedPresentation.parent + File.separator + "temp")
|
||||
FilenameFilter filter = new PdfFilter();
|
||||
String[] files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingImageMagick(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
filter = new JpegFilter();
|
||||
files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingJpeg2Swf(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File outDir = new File(uploadedPresentation.parent)
|
||||
filter = new SwfFilter();
|
||||
files = outDir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
}
|
||||
|
||||
|
||||
void testConvertPage() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "convertpage"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 5, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertPage(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File outDir = new File(uploadedPresentation.parent)
|
||||
FilenameFilter filter = new SwfFilter();
|
||||
String[] files = outDir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
}
|
||||
|
||||
void testCreateThumbnails() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 5, numPages
|
||||
|
||||
presService.createThumbnails(uploadedPresentation)
|
||||
|
||||
|
||||
// File outDir = new File(uploadedPresentation.parent)
|
||||
// FilenameFilter filter = new SwfFilter();
|
||||
// String[] files = outDir.list(filter)
|
||||
// assertEquals numPages, files.length
|
||||
}
|
||||
}
|
||||
|
||||
/*** Helper classes **/
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.File;
|
||||
class JpegFilter implements FilenameFilter {
|
||||
public boolean accept(File dir, String name) {
|
||||
return (name.endsWith(".jpeg"));
|
||||
}
|
||||
}
|
||||
|
||||
class PdfFilter implements FilenameFilter {
|
||||
public boolean accept(File dir, String name) {
|
||||
return (name.endsWith(".pdf"));
|
||||
}
|
||||
}
|
||||
|
||||
class SwfFilter implements FilenameFilter {
|
||||
public boolean accept(File dir, String name) {
|
||||
return (name.endsWith(".swf"));
|
||||
}
|
||||
}
|
BIN
bigbluebutton-web/test/resources/GoodPresentation.pdf
Normal file
BIN
bigbluebutton-web/test/resources/GoodPresentation.pdf
Normal file
Binary file not shown.
BIN
bigbluebutton-web/test/resources/OneBigPagePresentation.pdf
Normal file
BIN
bigbluebutton-web/test/resources/OneBigPagePresentation.pdf
Normal file
Binary file not shown.
BIN
bigbluebutton-web/test/resources/OnePage.pdf
Normal file
BIN
bigbluebutton-web/test/resources/OnePage.pdf
Normal file
Binary file not shown.
BIN
bigbluebutton-web/test/resources/SeveralBigPagesPresentation.pdf
Normal file
BIN
bigbluebutton-web/test/resources/SeveralBigPagesPresentation.pdf
Normal file
Binary file not shown.
BIN
bigbluebutton-web/test/resources/big.pdf
Normal file
BIN
bigbluebutton-web/test/resources/big.pdf
Normal file
Binary file not shown.
BIN
bigbluebutton-web/test/resources/sample-presentation.pdf
Normal file
BIN
bigbluebutton-web/test/resources/sample-presentation.pdf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user