diff --git a/src/Default.css b/src/Default.css
index 12d2fa6..0690cf7 100644
--- a/src/Default.css
+++ b/src/Default.css
@@ -121,6 +121,11 @@ s|RadioButton
skinClass: ClassReference("org.bigbluebutton.view.skins.RadioButtonSkin");
}
+s|CheckBox
+{
+ skinClass: ClassReference("org.bigbluebutton.view.skins.CheckBoxSkin")
+}
+
s|Image.bbbLogoStyle
{
verticalCenter: 0;
@@ -283,6 +288,11 @@ global
backgroundImage: Embed(source="assets/res/drawable-mdpi/deskshare.png");
}
+ ui|NavigationButton.pollsBtnStyle
+ {
+ backgroundImage: Embed(source="assets/res/drawable-mdpi/polling.png");
+ }
+
s|Button.logoutButtonStyle
{
height: 50;
@@ -398,6 +408,12 @@ global
eclipseBottom: 10;
}
+ s|CheckBox
+ {
+ height: 40;
+ width: 40;
+ }
+
s|Image.bbbLogoStyle
{
imageSource: Embed(source="assets/res/drawable-mdpi/ic_launcher.png");
@@ -550,6 +566,11 @@ global
backgroundImage: Embed(source="assets/res/drawable-hdpi/deskshare.png");
}
+ ui|NavigationButton.pollsBtnStyle
+ {
+ backgroundImage: Embed(source="assets/res/drawable-hdpi/polling.png");
+ }
+
s|Button.topButtonStyle
{
width: 45;
@@ -642,6 +663,12 @@ global
eclipseBottom: 15;
}
+ s|CheckBox
+ {
+ height: 60;
+ width: 60;
+ }
+
s|Image.bbbLogoStyle
{
imageSource: Embed(source="assets/res/drawable-hdpi/ic_launcher.png");
@@ -793,6 +820,11 @@ global
backgroundImage: Embed(source="assets/res/drawable-xhdpi/deskshare.png");
}
+ ui|NavigationButton.pollsBtnStyle
+ {
+ backgroundImage: Embed(source="assets/res/drawable-xhdpi/polling.png");
+ }
+
s|Button.topButtonStyle
{
width: 60;
@@ -880,6 +912,12 @@ global
eclipseBottom: 20;
}
+ s|CheckBox
+ {
+ height: 80;
+ width: 80;
+ }
+
s|Image.bbbLogoStyle
{
imageSource: Embed(source="assets/res/drawable-xhdpi/ic_launcher.png");
@@ -1008,6 +1046,11 @@ global
backgroundImage: Embed(source="assets/res/drawable-xxhdpi/deskshare.png");
}
+ ui|NavigationButton.pollsBtnStyle
+ {
+ backgroundImage: Embed(source="assets/res/drawable-xxhdpi/polling.png");
+ }
+
s|Button.logoutButtonStyle
{
height: 150;
@@ -1128,6 +1171,12 @@ global
eclipseBottom: 30;
}
+ s|CheckBox
+ {
+ height: 120;
+ width: 120;
+ }
+
s|Group.userDetailGroupStyle
{
height: 90;
diff --git a/src/Main.mxml b/src/Main.mxml
index 88cc6bc..6e46fa5 100644
--- a/src/Main.mxml
+++ b/src/Main.mxml
@@ -48,6 +48,9 @@
import org.bigbluebutton.view.navigation.pages.selectparticipant.SelectParticipantConfig;
import org.bigbluebutton.view.navigation.pages.userdetails.UserDetaisConfig;
import org.bigbluebutton.view.navigation.pages.videochat.VideoChatConfig;
+ import org.bigbluebutton.view.navigation.pages.pollslist.PollsListConfig;
+ import org.bigbluebutton.view.navigation.pages.takepoll.TakePollConfig;
+ import org.bigbluebutton.view.navigation.pages.pollresults.PollResultsConfig;
import org.bigbluebutton.view.ui.MicButtonConfig;
import org.bigbluebutton.view.ui.NavigationButtonConfig;
import org.bigbluebutton.view.ui.RecordingStatusConfig;
@@ -125,6 +128,9 @@
.configure(DisconnectPageConfig)
.configure(DeskshareConfig)
.configure(MenuButtonsConfig)
+ .configure(PollsListConfig)
+ .configure(TakePollConfig)
+ .configure(PollResultsConfig)
.configure(RecordingStatusConfig)
.configure(new ContextView(this));
diff --git a/src/assets/res/drawable-hdpi/polling.png b/src/assets/res/drawable-hdpi/polling.png
new file mode 100644
index 0000000..a8dd943
Binary files /dev/null and b/src/assets/res/drawable-hdpi/polling.png differ
diff --git a/src/assets/res/drawable-mdpi/polling.png b/src/assets/res/drawable-mdpi/polling.png
new file mode 100644
index 0000000..802c6f7
Binary files /dev/null and b/src/assets/res/drawable-mdpi/polling.png differ
diff --git a/src/assets/res/drawable-xhdpi/polling.png b/src/assets/res/drawable-xhdpi/polling.png
new file mode 100644
index 0000000..40d57f7
Binary files /dev/null and b/src/assets/res/drawable-xhdpi/polling.png differ
diff --git a/src/assets/res/drawable-xxhdpi/polling.png b/src/assets/res/drawable-xxhdpi/polling.png
new file mode 100644
index 0000000..e58df61
Binary files /dev/null and b/src/assets/res/drawable-xxhdpi/polling.png differ
diff --git a/src/assets/res/drawable-xxxhdpi/polling.png b/src/assets/res/drawable-xxxhdpi/polling.png
new file mode 100644
index 0000000..12d1ebb
Binary files /dev/null and b/src/assets/res/drawable-xxxhdpi/polling.png differ
diff --git a/src/locale/en_US/resources.properties b/src/locale/en_US/resources.properties
index 9ceec95..4d2e2bb 100644
--- a/src/locale/en_US/resources.properties
+++ b/src/locale/en_US/resources.properties
@@ -41,4 +41,13 @@ disconnect.reason.userLoggedOut=You have logged out of the meeting
disconnect.reason.userKickedOut=You have been kicked out of the meeting
disconnect.reason.userExit=Exit
deskshare.noDeskshare = No desktop stream to display
-deskshare.title = Desktop Sharing
\ No newline at end of file
+deskshare.title = Desktop Sharing
+pollsList.title=Poll List
+pollsList.notStarted=[Not Started]
+pollsList.closed=[Closed - View Results]
+pollsList.alreadyVoted=[Already Voted - View Results]
+pollsList.voteNow=[Vote Now]
+takePoll.title=Take Poll
+takePoll.submit=Submit
+takePoll.errorMessage=Please make sure to respond to each question
+pollResults.title=Poll Results
\ No newline at end of file
diff --git a/src/org/bigbluebutton/AppConfig.as b/src/org/bigbluebutton/AppConfig.as
index 8fcf638..48df782 100644
--- a/src/org/bigbluebutton/AppConfig.as
+++ b/src/org/bigbluebutton/AppConfig.as
@@ -38,7 +38,8 @@ package org.bigbluebutton
import org.bigbluebutton.model.UserUISession;
import org.bigbluebutton.model.chat.ChatMessagesSession;
import org.bigbluebutton.model.chat.IChatMessagesSession;
-
+ import org.bigbluebutton.core.IPollService;
+ import org.bigbluebutton.core.PollService;
import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
@@ -63,6 +64,7 @@ package org.bigbluebutton
injector.map(IChatMessageService).toSingleton(ChatMessageService);
injector.map(IPresentationService).toSingleton(PresentationService);
injector.map(IChatMessagesSession).toSingleton(ChatMessagesSession);
+ injector.map(IPollService).toSingleton(PollService);
injector.map(IDeskshareConnection).toSingleton(DeskshareConnection);
// Type mapping
diff --git a/src/org/bigbluebutton/command/ConnectCommand.as b/src/org/bigbluebutton/command/ConnectCommand.as
index a446b32..a766b7a 100644
--- a/src/org/bigbluebutton/command/ConnectCommand.as
+++ b/src/org/bigbluebutton/command/ConnectCommand.as
@@ -16,9 +16,10 @@ package org.bigbluebutton.command
import org.bigbluebutton.model.IUserSession;
import org.bigbluebutton.model.IUserUISession;
import org.bigbluebutton.view.navigation.pages.PagesENUM;
+ import org.bigbluebutton.core.IPollService;
import org.osmf.logging.Log;
- import robotlegs.bender.bundles.mvcs.Command;
+ import robotlegs.bender.bundles.mvcs.Command;
public class ConnectCommand extends Command
{
@@ -55,6 +56,9 @@ package org.bigbluebutton.command
[Inject]
public var presentationService: IPresentationService;
+ [Inject]
+ public var pollService:IPollService;
+
override public function execute():void {
connection.uri = uri;
@@ -88,6 +92,7 @@ package org.bigbluebutton.command
// Set up remaining message sender and receivers:
chatService.setupMessageSenderReceiver();
presentationService.setupMessageSenderReceiver();
+ pollService.setupMessageSenderReceiver();
// set up and connect the remaining connections
videoConnection.uri = userSession.config.getConfigFor("VideoConfModule").@uri + "/" + conferenceParameters.room;
@@ -108,20 +113,21 @@ package org.bigbluebutton.command
deskshareConnection.connect();
userSession.deskshareConnection = deskshareConnection;
-
- // Query the server for chat, users, and presentation info
+
+ // Query the server for chat, users, polls, and presentation info
chatService.sendWelcomeMessage();
chatService.getPublicChatMessages();
presentationService.getPresentationInfo();
-
+
userSession.userList.allUsersAddedSignal.add(successUsersAdded);
usersService.queryForParticipants();
usersService.queryForRecordingStatus();
+ pollService.getPolls();
+
userSession.successJoiningMeetingSignal.remove(successJoiningMeeting);
userSession.unsuccessJoiningMeetingSignal.remove(unsuccessJoiningMeeting);
- usersService.getRoomLockState();
}
private function unsuccessJoiningMeeting():void {
diff --git a/src/org/bigbluebutton/core/IPollService.as b/src/org/bigbluebutton/core/IPollService.as
new file mode 100644
index 0000000..f7a34ca
--- /dev/null
+++ b/src/org/bigbluebutton/core/IPollService.as
@@ -0,0 +1,11 @@
+package org.bigbluebutton.core
+{
+ import org.bigbluebutton.model.polling.Responses;
+
+ public interface IPollService
+ {
+ function setupMessageSenderReceiver():void;
+ function getPolls():void;
+ function respondPoll(pollID:String, responses:Array):void;
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/core/PollMessageReceiver.as b/src/org/bigbluebutton/core/PollMessageReceiver.as
new file mode 100644
index 0000000..0cdfe26
--- /dev/null
+++ b/src/org/bigbluebutton/core/PollMessageReceiver.as
@@ -0,0 +1,180 @@
+package org.bigbluebutton.core
+{
+ import org.bigbluebutton.model.IMessageListener;
+ import org.bigbluebutton.model.IUserSession;
+ import org.bigbluebutton.model.polling.Poll;
+ import org.bigbluebutton.model.polling.Question;
+ import org.bigbluebutton.model.polling.Responder;
+ import org.bigbluebutton.model.polling.Response;
+
+
+ public class PollMessageReceiver implements IMessageListener
+ {
+ public var userSession:IUserSession;
+
+ public function PollMessageReceiver(userSession:IUserSession) {
+ this.userSession = userSession;
+ }
+
+ public function onMessage(messageName:String, message:Object):void {
+ switch(messageName) {
+ case "pollGetPollsReply":
+ handleGetPollsReply(message);
+ break;
+ case "pollCreatedMessage":
+ handlePollCreatedMessage(message);
+ break;
+ case "pollUpdatedMessage":
+ handlePollUpdatedMessage(message);
+ break;
+ case "pollDestroyedMessage":
+ handlePollDestroyedMessage(message);
+ break;
+ case "pollStartedMessage":
+ handlePollStartedMessage(message);
+ break;
+ case "pollStoppedMessage":
+ handlePollStoppedMessage(message);
+ break;
+ case "pollResultUpdatedMessage":
+ handlePollResultUpdatedMessage(message);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private function handleGetPollsReply(m:Object):void {
+ var polls:Array = JSON.parse(m.msg) as Array;
+ trace("PollMessageReceiver::handleGetPollsReply() -- [" + polls.length + "] polls received from server");
+
+ for(var i:int = 0; i < polls.length; i++) {
+ userSession.pollModel.createPoll(buildPoll(polls[i]));
+ }
+ }
+
+ private function handlePollCreatedMessage(m:Object):void {
+ var poll:Object = JSON.parse(m.msg);
+ trace("PollMessageReceiver::handlePollCreatedMessage() -- creating poll [" + poll.title + "]");
+ userSession.pollModel.createPoll(buildPoll(poll));
+ }
+
+ private function handlePollUpdatedMessage(m:Object):void {
+ var poll:Object = JSON.parse(m.msg);
+ trace("PollMessageReceiver::handlePollUpdatedMessage() -- updating poll [" + poll.title + "]");
+ if(userSession.pollModel.hasPoll(poll.id)) {
+ userSession.pollModel.updatePoll(buildPoll(poll));
+ }
+ }
+
+ private function handlePollDestroyedMessage(m:Object):void {
+ var poll:Object = JSON.parse(m.msg);
+ trace("PollMessageReceiver::handlePollDestroyedMessage() -- destroying poll [" + poll.title + "]");
+ if(userSession.pollModel.hasPoll(poll.pollID)) {
+ userSession.pollModel.destroyPoll(poll.pollID);
+ }
+ }
+
+ private function handlePollStartedMessage(m:Object):void {
+ var poll:Object = JSON.parse(m.msg);
+ trace("PollMessageReceiver::handlePollStartedMessage() -- starting poll [" + poll.title + "]");
+ if(userSession.pollModel.hasPoll(poll.pollID)) {
+ userSession.pollModel.startPoll(poll.pollID);
+ }
+ }
+
+ private function handlePollStoppedMessage(m:Object):void {
+ var poll:Object = JSON.parse(m.msg);
+ trace("PollMessageReceiver::handlePollStoppedMessage() -- stopping poll [" + poll.title + "]");
+ if(userSession.pollModel.hasPoll(poll.pollID)) {
+ userSession.pollModel.stopPoll(poll.pollID);
+ }
+ }
+
+ private function handlePollResultUpdatedMessage(m:Object):void {
+ var message:Object = JSON.parse(m.msg);
+
+ /*** The format of 'message':
+ * {
+ * "response":
+ * {
+ * "pollID":"pollID-103",
+ * "responses":
+ * [
+ * {
+ * "questionID":"q1",
+ * "responseIDs":["0","1"]
+ * },
+ *
+ * ...
+ * ]
+ * },
+ *
+ * "responder":
+ * {
+ * "userID":"enfjadjc5xnn",
+ * "name":"RED"
+ * }
+ * }
+ */
+
+ var response:Object = message.response;
+
+ if(userSession.pollModel.hasPoll(response.pollID)) {
+ var responses:Array = response.responses;
+ var responder:Responder = buildResponder(message.responder);
+
+ for(var i:int = 0; i < responses.length; i++) {
+ var individualResponse:Object = responses[i];
+ var responseIDs:Array = individualResponse.responseIDs;
+
+ for(var j:int = 0; j < responseIDs.length; j++) {
+ userSession.pollModel.updateResults(response.pollID, individualResponse.questionID, responseIDs[j], responder);
+ }
+ }
+ }
+ }
+
+ private function buildPoll(pollObj:Object):Poll {
+ trace("PollMessageReceiver::handleGetPollsReply() -- building poll [" + pollObj.title + "]");
+ var questions:Array = pollObj.questions;
+ var qs:Array = new Array();
+
+ for(var i:int = 0; i < questions.length; i++) {
+ qs.push(buildQuestion(questions[i]));
+ }
+
+ return new Poll(pollObj.id, pollObj.title, qs, pollObj.started, pollObj.stopped);
+ }
+
+ private function buildQuestion(questionObj:Object):Question {
+ trace("PollMessageReceiver::buildQuestion() -- building question [" + questionObj.question + "]");
+ var responses:Array = questionObj.responses;
+ var rs:Array = new Array();
+
+ for(var i:int = 0; i < responses.length; i++) {
+ rs.push(buildResponse(responses[i]));
+ }
+
+ return new Question(questionObj.id, questionObj.multiResponse, questionObj.question, rs);
+ }
+
+ private function buildResponse(responseObj:Object):Response {
+ trace("PollMessageReceiver::buildResponse -- building response [" + responseObj.text + "]");
+ var responders:Array = responseObj.responders;
+ var rs:Array = new Array();
+
+ for(var i:int = 0; i < responders.length; i++) {
+ rs.push(buildResponder(responders[i]));
+ }
+
+ return new Response(responseObj.id, responseObj.text, rs);
+ }
+
+ private function buildResponder(responderObj:Object):Responder {
+ trace("PollMessageReceiver::buildResponder -- building responder for userID [" + responderObj.userID + "], name [" + responderObj.name + "]");
+ return new Responder(responderObj.userID, responderObj.name);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/core/PollMessageSender.as b/src/org/bigbluebutton/core/PollMessageSender.as
new file mode 100644
index 0000000..f08ecbb
--- /dev/null
+++ b/src/org/bigbluebutton/core/PollMessageSender.as
@@ -0,0 +1,33 @@
+package org.bigbluebutton.core
+{
+ import org.bigbluebutton.model.IUserSession;
+
+ public class PollMessageSender
+ {
+ public var userSession:IUserSession;
+
+ // The default callbacks of userSession.mainconnection.sendMessage
+ private var defaultSuccessResponse:Function = function(result:String):void { trace(result); };
+ private var defaultFailureResponse:Function = function(status:String):void { trace(status); };
+
+ public function PollMessageSender(userSession:IUserSession) {
+ this.userSession = userSession;
+ }
+
+ public function getPolls():void {
+ trace("PollMessageSender::getPolls() -- Sending [poll.getPolls] message to server");
+ userSession.mainConnection.sendMessage("poll.getPolls", defaultSuccessResponse, defaultFailureResponse);
+ }
+
+ public function respondPoll(pollID:String, responses:Array):void {
+ var messageObject:Object = new Object();
+ messageObject["pollID"] = pollID;
+ messageObject["questions"] = responses;
+
+ var message:String = JSON.stringify(messageObject);
+ trace("PollMessageSender::getPolls() -- Sending [poll.respondPoll] message to server with message: " + message);
+
+ userSession.mainConnection.sendMessage("poll.respondPoll", defaultSuccessResponse, defaultFailureResponse, message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/core/PollService.as b/src/org/bigbluebutton/core/PollService.as
new file mode 100644
index 0000000..1535026
--- /dev/null
+++ b/src/org/bigbluebutton/core/PollService.as
@@ -0,0 +1,34 @@
+package org.bigbluebutton.core
+{
+ import org.bigbluebutton.model.IMessageListener;
+ import org.bigbluebutton.model.IUserSession;
+
+ public class PollService implements IPollService
+ {
+ [Inject]
+ public var userSession: IUserSession;
+
+ public var pollMessageSender:PollMessageSender;
+ public var pollMessageReceiver:PollMessageReceiver;
+
+ public function PollService() {
+
+ }
+
+ public function setupMessageSenderReceiver():void {
+ pollMessageSender = new PollMessageSender(userSession);
+ pollMessageReceiver = new PollMessageReceiver(userSession);
+
+ userSession.mainConnection.addMessageListener(pollMessageReceiver as IMessageListener);
+ }
+
+ public function getPolls():void {
+ pollMessageSender.getPolls();
+ }
+
+ public function respondPoll(pollID:String, responses:Array):void {
+ pollMessageSender.respondPoll(pollID, responses);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/model/IUserSession.as b/src/org/bigbluebutton/model/IUserSession.as
index 75fdba7..5e5371f 100644
--- a/src/org/bigbluebutton/model/IUserSession.as
+++ b/src/org/bigbluebutton/model/IUserSession.as
@@ -3,17 +3,17 @@ package org.bigbluebutton.model
import flash.net.NetConnection;
import org.bigbluebutton.core.IBigBlueButtonConnection;
+ import org.bigbluebutton.core.IDeskshareConnection;
import org.bigbluebutton.core.IVideoConnection;
import org.bigbluebutton.core.IVoiceConnection;
import org.bigbluebutton.core.VideoConnection;
import org.bigbluebutton.core.VoiceConnection;
import org.bigbluebutton.core.VoiceStreamManager;
import org.bigbluebutton.model.chat.ChatMessages;
+ import org.bigbluebutton.model.polling.PollModel;
import org.bigbluebutton.model.presentation.PresentationList;
import org.osflash.signals.ISignal;
- import org.osflash.signals.Signal;
- import org.bigbluebutton.core.IVoiceConnection;
- import org.bigbluebutton.core.IDeskshareConnection;
+ import org.osflash.signals.Signal;
public interface IUserSession
@@ -34,6 +34,7 @@ package org.bigbluebutton.model
function get deskshareConnection():IDeskshareConnection;
function set deskshareConnection(value:IDeskshareConnection):void;
function get presentationList():PresentationList;
+ function get pollModel():PollModel;
function get guestSignal():ISignal;
function get successJoiningMeetingSignal():ISignal;
function get unsuccessJoiningMeetingSignal():ISignal;
diff --git a/src/org/bigbluebutton/model/UserList.as b/src/org/bigbluebutton/model/UserList.as
index ada420e..06b6708 100644
--- a/src/org/bigbluebutton/model/UserList.as
+++ b/src/org/bigbluebutton/model/UserList.as
@@ -21,6 +21,15 @@ package org.bigbluebutton.model
private var _users:ArrayCollection;
+ public function UserList()
+ {
+ _me = new User();
+ _users = new ArrayCollection();
+ _sort = new Sort();
+ _sort.compareFunction = sortFunction;
+ _users.sort = _sort;
+ }
+
[Bindable]
public function get users():ArrayCollection
{
@@ -46,15 +55,6 @@ package org.bigbluebutton.model
private var _sort:Sort;
- public function UserList()
- {
- _me = new User();
- _users = new ArrayCollection();
- _sort = new Sort();
- _sort.compareFunction = sortFunction;
- _users.sort = _sort;
- }
-
/**
* Dispatched when all participants are added
*/
diff --git a/src/org/bigbluebutton/model/UserSession.as b/src/org/bigbluebutton/model/UserSession.as
index 322a5fa..f5f958a 100644
--- a/src/org/bigbluebutton/model/UserSession.as
+++ b/src/org/bigbluebutton/model/UserSession.as
@@ -11,6 +11,7 @@ package org.bigbluebutton.model
import org.bigbluebutton.core.VoiceConnection;
import org.bigbluebutton.core.VoiceStreamManager;
import org.bigbluebutton.model.chat.ChatMessages;
+ import org.bigbluebutton.model.polling.PollModel;
import org.bigbluebutton.model.presentation.PresentationList;
import org.hamcrest.core.throws;
import org.osflash.signals.ISignal;
@@ -28,6 +29,7 @@ package org.bigbluebutton.model
protected var _userList:UserList;
protected var _presentationList:PresentationList;
protected var _recording:Boolean;
+ protected var _pollModel:PollModel;
protected var _guestSignal:ISignal = new Signal();
protected var _successJoiningMeetingSignal:ISignal = new Signal();
@@ -35,6 +37,14 @@ package org.bigbluebutton.model
protected var _recordingStatusChangedSignal:ISignal = new Signal();
protected var _logoutSignal:Signal = new Signal();
+
+ public function UserSession()
+ {
+ _userList = new UserList();
+ _presentationList = new PresentationList();
+ _pollModel = new PollModel();
+ }
+
public function get userList():UserList
{
return _userList;
@@ -110,18 +120,16 @@ package org.bigbluebutton.model
{
_deskshareConnection = value;
}
-
- public function UserSession()
- {
- _userList = new UserList();
- _presentationList = new PresentationList();
- }
public function get presentationList():PresentationList
{
return _presentationList
}
+ public function get pollModel():PollModel {
+ return _pollModel;
+ }
+
public function get guestSignal():ISignal
{
return _guestSignal;
diff --git a/src/org/bigbluebutton/model/polling/Poll.as b/src/org/bigbluebutton/model/polling/Poll.as
new file mode 100644
index 0000000..c7fa902
--- /dev/null
+++ b/src/org/bigbluebutton/model/polling/Poll.as
@@ -0,0 +1,96 @@
+package org.bigbluebutton.model.polling
+{
+ public class Poll
+ {
+ private var _id:String;
+ private var _title:String;
+ private var _questions:Array;
+
+ private var _started:Boolean = false;
+ private var _stopped:Boolean = false;
+
+ private var _startedOn:Date;
+ private var _stoppedOn:Date;
+ private var _durationInMinutes:int = 5;
+
+ private var _hasResponded:Boolean = false;
+
+ public function Poll(id:String, title:String, questions:Array, started:Boolean, stopped:Boolean) {
+ _id = id;
+ _title = title;
+ _questions = questions;
+ _started = started;
+ _stopped = stopped;
+ }
+
+ public function get id():String {
+ return _id;
+ }
+
+ public function get title():String {
+ return _title;
+ }
+
+ public function get questions():Array {
+ return _questions;
+ }
+
+ public function get started():Boolean {
+ return _started;
+ }
+
+ public function get stopped():Boolean {
+ return _stopped;
+ }
+
+ public function get duration():int {
+ return _durationInMinutes;
+ }
+
+ public function start():void {
+ _started = true;
+ _startedOn = new Date();
+ }
+
+ public function stop():void {
+ _stopped = true;
+ _stoppedOn = new Date();
+ }
+
+ public function timeRemainingInSeconds():int {
+ var timeRemainingInSeconds:Number = (_durationInMinutes * 60) - (new Date().time - _startedOn.time) / 1000;
+ if(timeRemainingInSeconds <= 0) {
+ return 0;
+ }
+ else {
+ return timeRemainingInSeconds;
+ }
+ }
+
+ private function getQuestion(questionID:String):Question {
+ for (var i:int = 0; i < _questions.length; i++) {
+ var q:Question = _questions[i] as Question;
+ if(q && q.id == questionID) {
+ return q;
+ }
+ }
+
+ return null;
+ }
+
+ public function updateResults(questionID:String, responseID:String, responder:Responder):void {
+ var q:Question = getQuestion(questionID);
+ if(q) {
+ q.updateResult(responseID, responder);
+ }
+ }
+
+ public function userResponded():void {
+ _hasResponded = true;
+ }
+
+ public function get hasResponded():Boolean {
+ return _hasResponded;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/model/polling/PollModel.as b/src/org/bigbluebutton/model/polling/PollModel.as
new file mode 100644
index 0000000..ecf3d57
--- /dev/null
+++ b/src/org/bigbluebutton/model/polling/PollModel.as
@@ -0,0 +1,132 @@
+package org.bigbluebutton.model.polling
+{
+ import mx.collections.ArrayCollection;
+
+ import org.osflash.signals.ISignal;
+ import org.osflash.signals.Signal;
+
+ public class PollModel
+ {
+ public static const POLL_CREATED:int = 0;
+ public static const POLL_DESTROYED:int = 1;
+ public static const POLL_STARTED:int = 2;
+ public static const POLL_STOPPED:int = 3;
+ public static const POLL_UPDATED:int = 4;
+ public static const POLL_RESULTS_UPDATED:int = 5;
+ public static const I_RESPONDED_TO_POLL:int = 6;
+
+ public var pollsChangedSignal:ISignal = new Signal();
+ public var responseToPollSignal:ISignal = new Signal();
+
+ private var _polls:ArrayCollection;
+
+ public function PollModel() {
+ _polls = new ArrayCollection();
+ }
+
+ public function get Polls():ArrayCollection {
+ return _polls;
+ }
+
+ public function createPoll(poll:Poll):void {
+ if(poll && !hasPoll(poll.id)) {
+ _polls.addItem(poll);
+ }
+
+ pollsChangedSignal.dispatch(POLL_CREATED, poll.id);
+ }
+
+ public function destroyPoll(pollID:String):void {
+ if(hasPoll(pollID)) {
+ _polls.removeItemAt(getPollIndex(pollID));
+ }
+
+ pollsChangedSignal.dispatch(POLL_DESTROYED, pollID);
+ }
+
+ public function startPoll(pollID:String):void {
+ if(hasPoll(pollID)) {
+ var poll:Poll = getPoll(pollID);
+ poll.start();
+ }
+
+ pollsChangedSignal.dispatch(POLL_STARTED, pollID);
+ }
+
+ public function stopPoll(pollID:String):void {
+ if(hasPoll(pollID)) {
+ var poll:Poll = getPoll(pollID);
+ poll.stop();
+ }
+
+ pollsChangedSignal.dispatch(POLL_STOPPED, pollID);
+ }
+
+ public function updatePoll(poll:Poll):void {
+ if(hasPoll(poll.id)) {
+ _polls.removeItemAt(getPollIndex(poll.id));
+ _polls.addItem(poll);
+ }
+
+ pollsChangedSignal.dispatch(POLL_UPDATED, poll.id);
+ }
+
+ public function updateResults(pollID:String, questionID:String, responseID:String, responder:Responder):void {
+ if(hasPoll(pollID)) {
+ var poll:Poll = getPoll(pollID);
+ poll.updateResults(questionID, responseID, responder);
+ }
+
+ responseToPollSignal.dispatch(pollID, questionID, responseID);
+ }
+
+ public function getPoll(pollID:String):Poll {
+ if(hasPoll(pollID)) {
+ return _polls.getItemAt(getPollIndex(pollID)) as Poll;
+ }
+ return null;
+ }
+
+ private function getPollIndex(pollID:String):int {
+ for(var i:int = 0; i < _polls.length; i++) {
+ var p:Poll = _polls.getItemAt(i) as Poll;
+ if(p && p.id == pollID) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public function hasPoll(pollID:String):Boolean {
+ for(var i:int = 0; i < _polls.length; i++) {
+ var p:Poll = _polls.getItemAt(i) as Poll;
+ if(p && p.id == pollID) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public function userHasResponded(pollID:String):void {
+ for(var i:int = 0; i < _polls.length; i++) {
+ var p:Poll = _polls.getItemAt(i) as Poll;
+ if(p && p.id == pollID) {
+ p.userResponded();
+ }
+ }
+
+ pollsChangedSignal.dispatch(I_RESPONDED_TO_POLL, pollID);
+ }
+
+ public function hasUserResponded(pollID:String):Boolean {
+ for(var i:int = 0; i < _polls.length; i++) {
+ var p:Poll = _polls.getItemAt(i) as Poll;
+ if(p && p.id == pollID) {
+ return p.hasResponded;
+ }
+ }
+ return false;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/model/polling/Question.as b/src/org/bigbluebutton/model/polling/Question.as
new file mode 100644
index 0000000..6b12060
--- /dev/null
+++ b/src/org/bigbluebutton/model/polling/Question.as
@@ -0,0 +1,43 @@
+package org.bigbluebutton.model.polling
+{
+ public class Question
+ {
+ private var _id: String;
+ private var _multiResponse:Boolean;
+ private var _question:String;
+ private var _responses:Array;
+
+ public function Question(id:String, multiResponse:Boolean, question:String, responses:Array) {
+ _id = id;
+ _multiResponse = multiResponse;
+ _question = question;
+ _responses = responses;
+ }
+
+ public function get id():String {
+ return _id;
+ }
+
+ public function get multiResponse():Boolean {
+ return _multiResponse;
+ }
+
+ public function get question():String {
+ return _question;
+ }
+
+ public function get responses():Array {
+ return _responses;
+ }
+
+ public function updateResult(responseID:String, responder:Responder):void {
+ for(var i:int = 0; i < _responses.length; i++) {
+ var r:Response = _responses[i] as Response;
+ if(r && r.id == responseID) {
+ r.addResponder(responder);
+ }
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/model/polling/Responder.as b/src/org/bigbluebutton/model/polling/Responder.as
new file mode 100644
index 0000000..86e4cf4
--- /dev/null
+++ b/src/org/bigbluebutton/model/polling/Responder.as
@@ -0,0 +1,21 @@
+package org.bigbluebutton.model.polling
+{
+ public class Responder
+ {
+ private var _userID:String;
+ private var _username:String;
+
+ public function Responder(userID:String, username:String) {
+ _userID = userID;
+ _username = username;
+ }
+
+ public function get userID():String {
+ return _userID;
+ }
+
+ public function get username():String {
+ return _username;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/model/polling/Response.as b/src/org/bigbluebutton/model/polling/Response.as
new file mode 100644
index 0000000..fec85eb
--- /dev/null
+++ b/src/org/bigbluebutton/model/polling/Response.as
@@ -0,0 +1,31 @@
+package org.bigbluebutton.model.polling
+{
+ public class Response
+ {
+ private var _id:String;
+ private var _response:String;
+ private var _responders:Array;
+
+ public function Response(id:String, response:String, responders:Array) {
+ _id = id;
+ _response = response;
+ _responders = responders;
+ }
+
+ public function get id():String {
+ return _id;
+ }
+
+ public function get response():String {
+ return _response;
+ }
+
+ public function addResponder(r:Responder):void {
+ _responders.push(r);
+ }
+
+ public function get numResponses():int {
+ return _responders.length;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/model/polling/Responses.as b/src/org/bigbluebutton/model/polling/Responses.as
new file mode 100644
index 0000000..cbb0c91
--- /dev/null
+++ b/src/org/bigbluebutton/model/polling/Responses.as
@@ -0,0 +1,21 @@
+package org.bigbluebutton.model.polling
+{
+ public class Responses
+ {
+ private var _questionID:String;
+ private var _responses:Array;
+
+ public function Responses(questionID:String, responses:Array) {
+ _questionID = questionID;
+ _responses = responses;
+ }
+
+ public function get questionID():String {
+ return _questionID;
+ }
+
+ public function get responseIDs():Array {
+ return _responses;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/view/navigation/PagesNavigatorViewMediator.as b/src/org/bigbluebutton/view/navigation/PagesNavigatorViewMediator.as
index bce96d0..28a91cb 100644
--- a/src/org/bigbluebutton/view/navigation/PagesNavigatorViewMediator.as
+++ b/src/org/bigbluebutton/view/navigation/PagesNavigatorViewMediator.as
@@ -69,7 +69,13 @@ package org.bigbluebutton.view.navigation
break;
}
}
- if(pageName == PagesENUM.PARTICIPANTS || pageName == PagesENUM.PRESENTATION || pageName == PagesENUM.VIDEO_CHAT || pageName == PagesENUM.CHATROOMS)
+
+ if(pageName == PagesENUM.PARTICIPANTS
+ || pageName == PagesENUM.PRESENTATION
+ || pageName == PagesENUM.VIDEO_CHAT
+ || pageName == PagesENUM.CHATROOMS
+ || pageName == PagesENUM.DESKSHARE
+ || pageName == PagesENUM.POLLS_LIST)
{
view.popAll();
view.pushView(PagesENUM.getClassfromName(pageName), null, null, transition);
diff --git a/src/org/bigbluebutton/view/navigation/pages/PagesENUM.as b/src/org/bigbluebutton/view/navigation/pages/PagesENUM.as
index 6a18fff..4908996 100644
--- a/src/org/bigbluebutton/view/navigation/pages/PagesENUM.as
+++ b/src/org/bigbluebutton/view/navigation/pages/PagesENUM.as
@@ -13,6 +13,9 @@ package org.bigbluebutton.view.navigation.pages
import org.bigbluebutton.view.navigation.pages.userdetails.UserDetaisView;
import org.bigbluebutton.view.navigation.pages.videochat.VideoChatView;
import org.bigbluebutton.view.navigation.pages.deskshare.DeskshareView;
+ import org.bigbluebutton.view.navigation.pages.pollslist.PollsListView;
+ import org.bigbluebutton.view.navigation.pages.takepoll.TakePollView;
+ import org.bigbluebutton.view.navigation.pages.pollresults.PollResultsView;
public class PagesENUM
{
@@ -27,6 +30,9 @@ package org.bigbluebutton.view.navigation.pages
public static const SELECT_PARTICIPANT:String = "selectparticipant";
public static const DISCONNECT:String = "Disconnect";
public static const DESKSHARE:String = "Deskshare";
+ public static const POLLS_LIST:String = "PollsList";
+ public static const TAKE_POLL:String = "TakePoll";
+ public static const POLL_RESULTS:String = "PollResults";
/**
* Especials
@@ -48,6 +54,9 @@ package org.bigbluebutton.view.navigation.pages
dic[SELECT_PARTICIPANT] = SelectParticipantView;
dic[DISCONNECT] = DisconnectPageView;
dic[DESKSHARE] = DeskshareView;
+ dic[POLLS_LIST] = PollsListView;
+ dic[TAKE_POLL] = TakePollView;
+ dic[POLL_RESULTS] = PollResultsView;
dicInitiated = true;
}
diff --git a/src/org/bigbluebutton/view/navigation/pages/common/MenuButtons.mxml b/src/org/bigbluebutton/view/navigation/pages/common/MenuButtons.mxml
index b9d35ad..75a5151 100644
--- a/src/org/bigbluebutton/view/navigation/pages/common/MenuButtons.mxml
+++ b/src/org/bigbluebutton/view/navigation/pages/common/MenuButtons.mxml
@@ -18,6 +18,7 @@
+
diff --git a/src/org/bigbluebutton/view/navigation/pages/common/MenuButtonsView.as b/src/org/bigbluebutton/view/navigation/pages/common/MenuButtonsView.as
index a3d3aec..1b97428 100644
--- a/src/org/bigbluebutton/view/navigation/pages/common/MenuButtonsView.as
+++ b/src/org/bigbluebutton/view/navigation/pages/common/MenuButtonsView.as
@@ -4,6 +4,10 @@ package org.bigbluebutton.view.navigation.pages.common
public class MenuButtonsView extends MenuButtons implements IMenuButtonsView
{
+ public function get menuPollsButton():NavigationButton
+ {
+ return pollsBtn0;
+ }
public function get menuDeskshareButton():NavigationButton
{
diff --git a/src/org/bigbluebutton/view/navigation/pages/common/MenuButtonsViewMediator.as b/src/org/bigbluebutton/view/navigation/pages/common/MenuButtonsViewMediator.as
index 6e31913..d3dcb0d 100644
--- a/src/org/bigbluebutton/view/navigation/pages/common/MenuButtonsViewMediator.as
+++ b/src/org/bigbluebutton/view/navigation/pages/common/MenuButtonsViewMediator.as
@@ -29,6 +29,9 @@ package org.bigbluebutton.view.navigation.pages.common
{
/*var users:ArrayCollection = userSession.userList.users;*/
userUISession.loadingSignal.remove(loadingFinished);
+
+ userSession.pollModel.pollsChangedSignal.add(onPollChange);
+
if (userSession.deskshareConnection != null)
{
view.menuDeskshareButton.visible = view.menuDeskshareButton.includeInLayout = userSession.deskshareConnection.isStreaming;
@@ -45,6 +48,12 @@ package org.bigbluebutton.view.navigation.pages.common
}*/
}
}
+
+ public function onPollChange(change:int, pollID:String):void
+ {
+ view.menuPollsButton.visible = view.menuPollsButton.includeInLayout = true;
+ }
+
/**
* If we recieve signal that deskshare stream is on - include Deskshare button to the layout
*/
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollresults/IPollResultsView.as b/src/org/bigbluebutton/view/navigation/pages/pollresults/IPollResultsView.as
new file mode 100644
index 0000000..089b256
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollresults/IPollResultsView.as
@@ -0,0 +1,11 @@
+package org.bigbluebutton.view.navigation.pages.pollresults
+{
+ import org.bigbluebutton.core.view.IView;
+
+ import spark.components.Group;
+
+ public interface IPollResultsView extends IView
+ {
+ function get resultsList():Group
+ }
+}
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsConfig.as b/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsConfig.as
new file mode 100644
index 0000000..d850cb2
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsConfig.as
@@ -0,0 +1,54 @@
+package org.bigbluebutton.view.navigation.pages.pollresults
+{
+
+ import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
+ import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
+ import robotlegs.bender.framework.api.IConfig;
+ import robotlegs.bender.framework.api.IInjector;
+
+
+ public class PollResultsConfig implements IConfig
+ {
+ [Inject]
+ public var injector: IInjector;
+
+ [Inject]
+ public var mediatorMap: IMediatorMap;
+
+ [Inject]
+ public var signalCommandMap: ISignalCommandMap;
+
+ public function configure(): void
+ {
+ dependencies();
+ mediators();
+ signals();
+ }
+
+ /**
+ * Specifies all the dependencies for the feature
+ * that will be injected onto objects used by the
+ * application.
+ */
+ private function dependencies(): void
+ {
+
+ }
+
+ /**
+ * Maps view mediators to views.
+ */
+ private function mediators(): void
+ {
+ mediatorMap.map(IPollResultsView).toMediator(PollResultsViewMediator);
+ }
+
+ /**
+ * Maps signals to commands using the signalCommandMap.
+ */
+ private function signals(): void
+ {
+
+ }
+ }
+}
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsView.as b/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsView.as
new file mode 100644
index 0000000..9413878
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsView.as
@@ -0,0 +1,19 @@
+package org.bigbluebutton.view.navigation.pages.pollresults
+{
+ import spark.components.Group;
+
+ public class PollResultsView extends PollResultsViewBase implements IPollResultsView
+ {
+ public function get resultsList():Group {
+ return resultsList0;
+ }
+
+ override protected function childrenCreated():void {
+ super.childrenCreated();
+ }
+
+ public function dispose():void {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsViewBase.mxml b/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsViewBase.mxml
new file mode 100644
index 0000000..937f33a
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsViewBase.mxml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsViewMediator.as b/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsViewMediator.as
new file mode 100644
index 0000000..6da4bbe
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollresults/PollResultsViewMediator.as
@@ -0,0 +1,114 @@
+package org.bigbluebutton.view.navigation.pages.pollresults
+{
+ import mx.core.FlexGlobals;
+ import mx.resources.ResourceManager;
+
+ import org.bigbluebutton.model.IUserSession;
+ import org.bigbluebutton.model.IUserUISession;
+ import org.bigbluebutton.model.polling.PollModel;
+ import org.bigbluebutton.model.polling.Question;
+ import org.bigbluebutton.model.polling.Response;
+ import org.bigbluebutton.view.navigation.pages.PagesENUM;
+
+ import robotlegs.bender.bundles.mvcs.Mediator;
+
+ import spark.components.Group;
+
+ public class PollResultsViewMediator extends Mediator
+ {
+ [Inject]
+ public var userSession:IUserSession;
+
+ [Inject]
+ public var userUISession: IUserUISession;
+
+ [Inject]
+ public var view:IPollResultsView;
+
+ private var id:String;
+
+ override public function initialize():void {
+ id = userUISession.currentPageDetails.id;
+
+ userSession.pollModel.responseToPollSignal.add(handleResponseToPoll);
+ userSession.pollModel.pollsChangedSignal.add(handlePollModelChanged);
+
+ FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'pollResults.title');
+
+ addPollResults();
+ }
+
+ private function addPollResults():void {
+ var questions:Array = userSession.pollModel.getPoll(id).questions;
+
+ for(var i:int = 0; i < questions.length; i++) {
+ var question:Question = questions[i];
+ var responseListView:ResponseListView = new ResponseListView();
+
+ responseListView.initialize();
+ responseListView.id = question.id;
+ responseListView.question.text = question.question;
+
+ var responses:Array = question.responses;
+
+ for(var j:int = 0; j < responses.length; j++) {
+ var response:Response = responses[j];
+ var responseView:ResponseView = new ResponseView();
+
+ responseView.initialize();
+ responseView.id = response.id;
+ responseView.response.text = response.response;
+ responseView.numberOfResponses.text = response.numResponses.toString();
+
+ responseListView.responsesList.addElement(responseView);
+ }
+ view.resultsList.addElement(responseListView);
+ }
+ }
+
+ private function handleResponseToPoll(pollID:String, questionID:String, responseID:String): void {
+ if(id == pollID) {
+ var responseListView:ResponseListView = getResponseListView(questionID);
+ if(responseListView) {
+ var responsesList:Group = responseListView.responsesList;
+ for(var i:int = 0; i < responsesList.numElements; i++) {
+ var responseView:ResponseView = responsesList.getElementAt(i) as ResponseView;
+ if(responseView && responseID == responseView.id) {
+ var temp:Number = Number(responseView.numberOfResponses.text);
+ temp++;
+ responseView.numberOfResponses.text = temp.toString();
+ }
+ }
+ }
+ }
+ }
+
+ private function getResponseListView(questionID:String):ResponseListView {
+ var resultsList:Group = view.resultsList;
+ for(var i:int = 0; i < resultsList.numElements; i++) {
+ var responseListView:ResponseListView = resultsList.getElementAt(i) as ResponseListView;
+ if(responseListView && questionID == responseListView.id) {
+ return responseListView;
+ }
+ }
+ return null;
+ }
+
+ private function handlePollModelChanged(change:int, pollID:String):void {
+ if(change == PollModel.POLL_DESTROYED && id == pollID) {
+ userUISession.pushPage(PagesENUM.POLLS_LIST);
+ }
+ }
+
+ override public function destroy():void {
+ super.destroy();
+
+ userSession.pollModel.responseToPollSignal.remove(handleResponseToPoll);
+ userSession.pollModel.pollsChangedSignal.remove(handlePollModelChanged);
+
+ view.dispose();
+ view = null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollresults/ResponseListView.mxml b/src/org/bigbluebutton/view/navigation/pages/pollresults/ResponseListView.mxml
new file mode 100644
index 0000000..fc45990
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollresults/ResponseListView.mxml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollresults/ResponseView.mxml b/src/org/bigbluebutton/view/navigation/pages/pollresults/ResponseView.mxml
new file mode 100644
index 0000000..01149d4
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollresults/ResponseView.mxml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollslist/IPollsListView.as b/src/org/bigbluebutton/view/navigation/pages/pollslist/IPollsListView.as
new file mode 100644
index 0000000..f129032
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollslist/IPollsListView.as
@@ -0,0 +1,11 @@
+package org.bigbluebutton.view.navigation.pages.pollslist
+{
+ import org.bigbluebutton.core.view.IView;
+
+ import spark.components.List;
+
+ public interface IPollsListView extends IView
+ {
+ function get list():List;
+ }
+}
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListConfig.as b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListConfig.as
new file mode 100644
index 0000000..9f5fda5
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListConfig.as
@@ -0,0 +1,54 @@
+package org.bigbluebutton.view.navigation.pages.pollslist
+{
+
+ import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
+ import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
+ import robotlegs.bender.framework.api.IConfig;
+ import robotlegs.bender.framework.api.IInjector;
+
+
+ public class PollsListConfig implements IConfig
+ {
+ [Inject]
+ public var injector: IInjector;
+
+ [Inject]
+ public var mediatorMap: IMediatorMap;
+
+ [Inject]
+ public var signalCommandMap: ISignalCommandMap;
+
+ public function configure(): void
+ {
+ dependencies();
+ mediators();
+ signals();
+ }
+
+ /**
+ * Specifies all the dependencies for the feature
+ * that will be injected onto objects used by the
+ * application.
+ */
+ private function dependencies(): void
+ {
+
+ }
+
+ /**
+ * Maps view mediators to views.
+ */
+ private function mediators(): void
+ {
+ mediatorMap.map(IPollsListView).toMediator(PollsListViewMediator);
+ }
+
+ /**
+ * Maps signals to commands using the signalCommandMap.
+ */
+ private function signals(): void
+ {
+
+ }
+ }
+}
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListItemRenderer.mxml b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListItemRenderer.mxml
new file mode 100644
index 0000000..878ff1e
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListItemRenderer.mxml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListView.as b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListView.as
new file mode 100644
index 0000000..8cd8d88
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListView.as
@@ -0,0 +1,21 @@
+package org.bigbluebutton.view.navigation.pages.pollslist
+{
+
+ import spark.components.List;
+
+ public class PollsListView extends PollsListViewBase implements IPollsListView
+ {
+ public function get list():List {
+ return pollsList;
+ }
+
+ override protected function childrenCreated():void {
+ super.childrenCreated();
+ }
+
+ public function dispose():void {
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListViewBase.mxml b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListViewBase.mxml
new file mode 100644
index 0000000..5f0f00a
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListViewBase.mxml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListViewMediator.as b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListViewMediator.as
new file mode 100644
index 0000000..3d27e3d
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/pollslist/PollsListViewMediator.as
@@ -0,0 +1,85 @@
+package org.bigbluebutton.view.navigation.pages.pollslist
+{
+ import mx.collections.ArrayCollection;
+ import mx.core.FlexGlobals;
+ import mx.resources.ResourceManager;
+
+ import org.bigbluebutton.model.IUserSession;
+ import org.bigbluebutton.model.IUserUISession;
+ import org.bigbluebutton.model.polling.PollModel;
+ import org.bigbluebutton.view.navigation.pages.PagesENUM;
+
+ import robotlegs.bender.bundles.mvcs.Mediator;
+
+ import spark.components.List;
+ import spark.events.IndexChangeEvent;
+
+
+ public class PollsListViewMediator extends Mediator
+ {
+ [Inject]
+ public var userSession:IUserSession;
+
+ [Inject]
+ public var userUISession: IUserUISession;
+
+ [Inject]
+ public var view:IPollsListView;
+
+ private var pollsList:List;
+
+ private var dataProvider:ArrayCollection = new ArrayCollection();
+
+ override public function initialize():void {
+ dataProvider = userSession.pollModel.Polls;
+
+ pollsList = view.list;
+ pollsList.dataProvider = dataProvider;
+
+ userSession.pollModel.pollsChangedSignal.add(handlePollModelChanged);
+ pollsList.addEventListener(IndexChangeEvent.CHANGE, onIndexChangeHandler);
+
+ FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'pollsList.title');
+ }
+
+ private function onIndexChangeHandler(event:IndexChangeEvent):void {
+ var item:Object = dataProvider.getItemAt(event.newIndex);
+ if(item) {
+ if(!item.started) {
+ return;
+ }
+ else if(item.stopped || item.hasResponded) {
+ userUISession.pushPage(PagesENUM.POLL_RESULTS, item)
+ }
+ else {
+ userUISession.pushPage(PagesENUM.TAKE_POLL, item);
+ }
+ }
+ }
+
+ private function handlePollModelChanged(change:int, pollID:String):void {
+ switch(change) {
+ case PollModel.POLL_CREATED:
+ case PollModel.POLL_DESTROYED:
+ case PollModel.POLL_STARTED:
+ case PollModel.POLL_STOPPED:
+ case PollModel.I_RESPONDED_TO_POLL:
+ dataProvider.refresh();
+ break;
+ default:
+ break;
+ }
+ }
+
+ override public function destroy():void {
+ super.destroy();
+
+ pollsList.removeEventListener(IndexChangeEvent.CHANGE, onIndexChangeHandler);
+ userSession.pollModel.pollsChangedSignal.remove(handlePollModelChanged);
+
+ view.dispose();
+ view = null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/view/navigation/pages/takepoll/ITakePollView.as b/src/org/bigbluebutton/view/navigation/pages/takepoll/ITakePollView.as
new file mode 100644
index 0000000..fd3d965
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/takepoll/ITakePollView.as
@@ -0,0 +1,14 @@
+package org.bigbluebutton.view.navigation.pages.takepoll
+{
+ import org.bigbluebutton.core.view.IView;
+
+ import spark.components.Button;
+ import spark.components.Group;
+ import spark.components.Label;
+
+ public interface ITakePollView extends IView {
+ function get questionViews():Group;
+ function get submitButton():Button;
+ function get errorMessage():Label;
+ }
+}
diff --git a/src/org/bigbluebutton/view/navigation/pages/takepoll/QuestionView.mxml b/src/org/bigbluebutton/view/navigation/pages/takepoll/QuestionView.mxml
new file mode 100644
index 0000000..22531ad
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/takepoll/QuestionView.mxml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollConfig.as b/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollConfig.as
new file mode 100644
index 0000000..fa9b591
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollConfig.as
@@ -0,0 +1,54 @@
+package org.bigbluebutton.view.navigation.pages.takepoll
+{
+
+ import robotlegs.bender.extensions.mediatorMap.api.IMediatorMap;
+ import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
+ import robotlegs.bender.framework.api.IConfig;
+ import robotlegs.bender.framework.api.IInjector;
+
+
+ public class TakePollConfig implements IConfig
+ {
+ [Inject]
+ public var injector: IInjector;
+
+ [Inject]
+ public var mediatorMap: IMediatorMap;
+
+ [Inject]
+ public var signalCommandMap: ISignalCommandMap;
+
+ public function configure(): void
+ {
+ dependencies();
+ mediators();
+ signals();
+ }
+
+ /**
+ * Specifies all the dependencies for the feature
+ * that will be injected onto objects used by the
+ * application.
+ */
+ private function dependencies(): void
+ {
+
+ }
+
+ /**
+ * Maps view mediators to views.
+ */
+ private function mediators(): void
+ {
+ mediatorMap.map(ITakePollView).toMediator(TakePollViewMediator);
+ }
+
+ /**
+ * Maps signals to commands using the signalCommandMap.
+ */
+ private function signals(): void
+ {
+
+ }
+ }
+}
diff --git a/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollView.as b/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollView.as
new file mode 100644
index 0000000..693d2dd
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollView.as
@@ -0,0 +1,30 @@
+package org.bigbluebutton.view.navigation.pages.takepoll
+{
+ import spark.components.Button;
+ import spark.components.Group;
+ import spark.components.Label;
+
+ public class TakePollView extends TakePollViewBase implements ITakePollView
+ {
+ override protected function childrenCreated():void {
+ super.childrenCreated();
+ }
+
+ public function get questionViews():Group {
+ return questionViewGroup;
+ }
+
+ public function get submitButton():Button {
+ return submitButton0;
+ }
+
+ public function get errorMessage():Label {
+ return errorMessage0;
+ }
+
+ public function dispose():void {
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollViewBase.mxml b/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollViewBase.mxml
new file mode 100644
index 0000000..0d89286
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollViewBase.mxml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollViewMediator.as b/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollViewMediator.as
new file mode 100644
index 0000000..a301418
--- /dev/null
+++ b/src/org/bigbluebutton/view/navigation/pages/takepoll/TakePollViewMediator.as
@@ -0,0 +1,213 @@
+package org.bigbluebutton.view.navigation.pages.takepoll
+{
+
+ import flash.events.MouseEvent;
+
+ import mx.core.FlexGlobals;
+ import mx.resources.ResourceManager;
+
+ import org.bigbluebutton.core.IPollService;
+ import org.bigbluebutton.model.IUserSession;
+ import org.bigbluebutton.model.IUserUISession;
+ import org.bigbluebutton.model.polling.Poll;
+ import org.bigbluebutton.model.polling.PollModel;
+ import org.bigbluebutton.model.polling.Question;
+ import org.bigbluebutton.model.polling.Responses;
+ import org.bigbluebutton.view.navigation.pages.PagesENUM;
+
+ import robotlegs.bender.bundles.mvcs.Mediator;
+
+ import spark.components.CheckBox;
+ import spark.components.Group;
+ import spark.components.RadioButton;
+
+
+ public class TakePollViewMediator extends Mediator
+ {
+ [Inject]
+ public var userSession:IUserSession;
+
+ [Inject]
+ public var userUISession: IUserUISession;
+
+ [Inject]
+ public var pollService:IPollService;
+
+ [Inject]
+ public var view:ITakePollView;
+
+ private var id:String;
+ private var questionViewGroup:Group;
+
+ override public function initialize():void {
+ id = userUISession.currentPageDetails.id
+ questionViewGroup = view.questionViews;
+
+ userSession.pollModel.pollsChangedSignal.add(handlePollModelChanged);
+ view.submitButton.addEventListener(MouseEvent.CLICK, onSubmit);
+
+ FlexGlobals.topLevelApplication.pageName.text = ResourceManager.getInstance().getString('resources', 'takePoll.title');
+
+ addPollToView(userSession.pollModel.getPoll(id));
+ }
+
+ private function addPollToView(poll:Poll):void {
+ var questions:Array = poll.questions;
+
+ for(var i:int = 0; i < questions.length; i++) {
+ var question:Question = questions[i];
+ addQuestionToView(question.id, question.question, question.multiResponse, question.responses);
+ }
+ }
+
+ private function addQuestionToView(questionID:String, questionText:String, multiResponse:Boolean, responses:Array):void {
+ var qv:QuestionView = new QuestionView();
+
+ qv.initialize();
+ qv.id = questionID;
+ qv.question.text = questionText;
+ qv.multiResponse = multiResponse;
+
+ if(multiResponse) {
+ for(var i:int = 0; i < responses.length; i++) {
+ qv.responses.addElement(buildCheckBoxFromResponse(responses[i]));
+ }
+ }
+ else {
+ for(var j:int = 0; j < responses.length; j++) {
+ qv.responses.addElement(buildRadioButtonFromResponse(responses[j]));
+ }
+ }
+
+ questionViewGroup.addElement(qv);
+ }
+
+ private function buildCheckBoxFromResponse(response:Object):CheckBox {
+ var checkBox:CheckBox = new CheckBox();
+ checkBox.id = response.id;
+ checkBox.label = response.response;
+ checkBox.percentWidth = 100;
+ return checkBox;
+ }
+
+ private function buildRadioButtonFromResponse(response:Object):RadioButton {
+ var radioButton:RadioButton = new RadioButton();
+ radioButton.id = response.id;
+ radioButton.label = response.response;
+ radioButton.percentWidth = 100;
+ return radioButton;
+ }
+
+ private function onSubmit(event:MouseEvent):void {
+ var questionResponseArray:Array = new Array();
+
+ for(var i:int = 0; i < questionViewGroup.numElements; i++) {
+ var q:QuestionView = questionViewGroup.getElementAt(i) as QuestionView;
+
+ if(q) {
+ if(q.multiResponse) {
+ var cb_responses:Array = getCheckBoxResponses(q.responses);
+ if(cb_responses.length == 0) { // User did not respond
+ view.errorMessage.visible = true;
+ return;
+ }
+ questionResponseArray.push(new Responses(q.id, cb_responses));
+ }
+ else {
+ var rb_responses:Array = getRadioButtonResponses(q.responses);
+ if(rb_responses.length == 0) { // User did not respond
+ view.errorMessage.visible = true;
+ return;
+ }
+ questionResponseArray.push(new Responses(q.id, rb_responses));
+ }
+ }
+ }
+
+ view.submitButton.enabled = false;
+ pollService.respondPoll(id, questionResponseArray);
+ userSession.pollModel.userHasResponded(id);
+ }
+
+ private function getCheckBoxResponses(groupOfCheckBoxes:Group):Array {
+ var responses:Array = new Array();
+
+ for(var j:int = 0; j < groupOfCheckBoxes.numElements; j++) {
+ var cb:CheckBox = groupOfCheckBoxes.getElementAt(j) as CheckBox;
+ if(cb && cb.selected) {
+ responses.push(cb.id);
+ }
+ }
+
+ return responses;
+ }
+
+ private function getRadioButtonResponses(groupOfRadioButton:Group):Array {
+ var responses:Array = new Array();
+
+ for(var i:int = 0; i < groupOfRadioButton.numElements; i++) {
+ var rb:RadioButton = groupOfRadioButton.getElementAt(i) as RadioButton;
+ if(rb && rb.selected) {
+ responses.push(rb.id);
+ }
+ }
+
+ return responses;
+ }
+
+ private function handlePollModelChanged(change:int, pollID:String):void {
+ switch(change) {
+ case PollModel.POLL_DESTROYED:
+ handlePollDestroyed(pollID);
+ break;
+ case PollModel.POLL_STOPPED:
+ handlePollStopped(pollID);
+ break;
+ case PollModel.POLL_UPDATED:
+ handlePollUpdated(pollID);
+ break;
+ case PollModel.I_RESPONDED_TO_POLL:
+ handleIRespondedToPoll(pollID);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private function handlePollDestroyed(pollID:String):void {
+ if(id == pollID) {
+ userUISession.popPage();
+ }
+ }
+
+ private function handlePollStopped(pollID:String):void {
+ if(id == pollID) {
+ userUISession.popPage();
+ }
+ }
+
+ private function handlePollUpdated(pollID:String):void {
+ if(id == pollID) {
+ questionViewGroup.removeAllElements();
+ addPollToView(userSession.pollModel.getPoll(pollID));
+ }
+ }
+
+ private function handleIRespondedToPoll(pollID:String):void {
+ if(id == pollID) {
+ userUISession.pushPage(PagesENUM.POLL_RESULTS, {id: id});
+ }
+ }
+
+ override public function destroy():void {
+ super.destroy();
+
+ userSession.pollModel.pollsChangedSignal.remove(handlePollModelChanged);
+ view.submitButton.removeEventListener(MouseEvent.CLICK, onSubmit);
+
+ view.dispose();
+ view = null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/org/bigbluebutton/view/skins/CheckBoxSkin.mxml b/src/org/bigbluebutton/view/skins/CheckBoxSkin.mxml
new file mode 100644
index 0000000..2348cdb
--- /dev/null
+++ b/src/org/bigbluebutton/view/skins/CheckBoxSkin.mxml
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/bigbluebutton/view/skins/RadioButtonSkin.mxml b/src/org/bigbluebutton/view/skins/RadioButtonSkin.mxml
index bd367fd..e5b0722 100644
--- a/src/org/bigbluebutton/view/skins/RadioButtonSkin.mxml
+++ b/src/org/bigbluebutton/view/skins/RadioButtonSkin.mxml
@@ -132,8 +132,8 @@ in accordance with the terms of the license agreement accompanying it.
+ left="{hostComponent.getStyle('width')}" textAlign="left" verticalCenter="2" fontWeight="normal" />