Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20171117.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20171117.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20171117.sql (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -0,0 +1,32 @@ +-- Turn off autocommit, so nothing is committed if there is an error + +SET AUTOCOMMIT = 0; +SET FOREIGN_KEY_CHECKS=0; + +-- LDEV-4454 Add tables for Kumalive polls + +CREATE TABLE lams_kumalive_poll ( + poll_id BIGINT(20) NOT NULL AUTO_INCREMENT + , kumalive_id BIGINT(20) NOT NULL + , name VARCHAR(250) + , start_date DATETIME NOT NULL + , finish_date DATETIME + , PRIMARY KEY (poll_id) + , CONSTRAINT FK_lams_kumalive_poll_1 FOREIGN KEY (kumalive_id) + REFERENCES lams_kumalive (kumalive_id) ON DELETE CASCADE ON UPDATE CASCADE +); + +CREATE TABLE lams_kumalive_poll_answer ( + answer_id BIGINT(20) NOT NULL AUTO_INCREMENT + , poll_id BIGINT(20) NOT NULL + , order_id TINYINT NOT NULL + , name VARCHAR(250) + , PRIMARY KEY (answer_id) + , CONSTRAINT FK_lams_kumalive_poll_answer_1 FOREIGN KEY (poll_id) + REFERENCES lams_kumalive_poll (poll_id) ON DELETE CASCADE ON UPDATE CASCADE +); + +-- If there were no errors, commit and restore autocommit to on +SET FOREIGN_KEY_CHECKS=0; +COMMIT; +SET AUTOCOMMIT = 1; Index: lams_learning/conf/hibernate/mappings/org/lamsfoundation/lams/learning/kumalive/KumalivePoll.hbm.xml =================================================================== diff -u --- lams_learning/conf/hibernate/mappings/org/lamsfoundation/lams/learning/kumalive/KumalivePoll.hbm.xml (revision 0) +++ lams_learning/conf/hibernate/mappings/org/lamsfoundation/lams/learning/kumalive/KumalivePoll.hbm.xml (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Index: lams_learning/conf/hibernate/mappings/org/lamsfoundation/lams/learning/kumalive/KumalivePollAnswer.hbm.xml =================================================================== diff -u --- lams_learning/conf/hibernate/mappings/org/lamsfoundation/lams/learning/kumalive/KumalivePollAnswer.hbm.xml (revision 0) +++ lams_learning/conf/hibernate/mappings/org/lamsfoundation/lams/learning/kumalive/KumalivePollAnswer.hbm.xml (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/KumaliveWebsocketServer.java =================================================================== diff -u -r3f99af7413ffdfdf7f69c54fd2a773f9443ac899 -redcf26c6dbd1e4ff36858d876e908774abb7910d --- lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/KumaliveWebsocketServer.java (.../KumaliveWebsocketServer.java) (revision 3f99af7413ffdfdf7f69c54fd2a773f9443ac899) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/KumaliveWebsocketServer.java (.../KumaliveWebsocketServer.java) (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -67,6 +67,7 @@ private Integer speaker; private final Map learners = new ConcurrentHashMap<>(); private final JSONArray rubrics = new JSONArray(); + private JSONObject poll = null; private KumaliveDTO(Kumalive kumalive) throws JSONException { this.id = kumalive.getKumaliveId(); @@ -170,6 +171,9 @@ case "score": score(requestJSON, session); break; + case "startPoll": + startPoll(requestJSON, session); + break; case "finish": finish(requestJSON, session); break; @@ -293,6 +297,8 @@ } responseJSON.put("speaker", kumalive.speaker); + responseJSON.put("poll", kumalive.poll); + // each learner's details JSONArray learnersJSON = new JSONArray(); JSONObject logins = new JSONObject(); @@ -332,7 +338,7 @@ } /** - * Tell learners that the teacher asked + * Tell learners that the teacher asked a question */ private void raiseHandPrompt(JSONObject requestJSON, Session websocket) throws IOException, JSONException { Integer organisationId = Integer @@ -501,6 +507,34 @@ } /** + * Tell learners that the teacher started a poll + */ + private void startPoll(JSONObject requestJSON, Session websocket) throws IOException, JSONException { + Integer organisationId = Integer + .valueOf(websocket.getRequestParameterMap().get(AttributeNames.PARAM_ORGANISATION_ID).get(0)); + KumaliveDTO kumalive = kumalives.get(organisationId); + + User user = getUser(websocket); + Integer userId = user.getUserId(); + + if (!KumaliveWebsocketServer.getSecurityService().hasOrgRole(organisationId, userId, + new String[] { Role.GROUP_MANAGER, Role.MONITOR }, "kumalive poll start", false)) { + String warning = "User " + userId + " is not a monitor of organisation " + organisationId; + logger.warn(warning); + return; + } + + kumalive.poll = requestJSON.getJSONObject("poll"); + Long pollId = KumaliveWebsocketServer.getKumaliveService().startPoll(kumalive.id, + kumalive.poll.getString("name"), kumalive.poll.getJSONArray("answers")); + kumalive.poll.put("id", pollId); + if (logger.isDebugEnabled()) { + logger.debug("Teacher " + userId + " started poll " + pollId + " in Kumalive " + kumalive.id); + } + sendRefresh(kumalive); + } + + /** * End Kumalive */ private void finish(JSONObject requestJSON, Session websocket) throws IOException, JSONException { Index: lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/dao/IKumaliveDAO.java =================================================================== diff -u -r5b60c76a61d420733e2c4c96513249cb9a65a484 -redcf26c6dbd1e4ff36858d876e908774abb7910d --- lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/dao/IKumaliveDAO.java (.../IKumaliveDAO.java) (revision 5b60c76a61d420733e2c4c96513249cb9a65a484) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/dao/IKumaliveDAO.java (.../IKumaliveDAO.java) (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -27,6 +27,7 @@ import org.lamsfoundation.lams.dao.IBaseDAO; import org.lamsfoundation.lams.learning.kumalive.model.Kumalive; +import org.lamsfoundation.lams.learning.kumalive.model.KumalivePoll; import org.lamsfoundation.lams.learning.kumalive.model.KumaliveRubric; import org.lamsfoundation.lams.learning.kumalive.model.KumaliveScore; @@ -42,4 +43,6 @@ List findKumaliveScore(Long kumaliveId, boolean isAscending); List findKumaliveScore(Long kumaliveId, Integer userId); + + KumalivePoll findPoll(Integer organisationId); } \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/dao/hibernate/KumaliveDAO.java =================================================================== diff -u -r5b60c76a61d420733e2c4c96513249cb9a65a484 -redcf26c6dbd1e4ff36858d876e908774abb7910d --- lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/dao/hibernate/KumaliveDAO.java (.../KumaliveDAO.java) (revision 5b60c76a61d420733e2c4c96513249cb9a65a484) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/dao/hibernate/KumaliveDAO.java (.../KumaliveDAO.java) (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -29,6 +29,7 @@ import org.lamsfoundation.lams.dao.hibernate.LAMSBaseDAO; import org.lamsfoundation.lams.learning.kumalive.dao.IKumaliveDAO; import org.lamsfoundation.lams.learning.kumalive.model.Kumalive; +import org.lamsfoundation.lams.learning.kumalive.model.KumalivePoll; import org.lamsfoundation.lams.learning.kumalive.model.KumaliveRubric; import org.lamsfoundation.lams.learning.kumalive.model.KumaliveScore; import org.springframework.stereotype.Repository; @@ -47,6 +48,8 @@ + " AS s WHERE s.rubric.kumalive.kumaliveId = ? ORDER BY s.user.firstName "; private static final String FIND_SCORE_BY_KUMALIVE_AND_USER = "FROM " + KumaliveScore.class.getName() + " AS s WHERE s.rubric.kumalive.kumaliveId = ? AND s.user.userId = ?"; + private static final String FIND_CURRENT_POLL_BY_ORGANISATION = "FROM " + KumalivePoll.class.getName() + + " AS p WHERE p.kumalive.organisation.organisationId = ? AND k.finishDate IS NULL"; @Override @SuppressWarnings("unchecked") @@ -104,4 +107,11 @@ public List findKumaliveScore(Long kumaliveId, Integer userId) { return (List) doFind(FIND_SCORE_BY_KUMALIVE_AND_USER, kumaliveId, userId); } + + @Override + @SuppressWarnings("unchecked") + public KumalivePoll findPoll(Integer organisationId) { + List result = (List) doFind(FIND_CURRENT_POLL_BY_ORGANISATION, organisationId); + return result.isEmpty() ? null : result.get(0); + } } \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/model/KumalivePoll.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/model/KumalivePoll.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/model/KumalivePoll.java (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.learning.kumalive.model; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +public class KumalivePoll implements Serializable { + + private static final long serialVersionUID = 5154401897739494150L; + + private Long pollId; + private Kumalive kumalive; + private String name; + private Date startDate; + private Date finishDate; + private Set answers; + + public KumalivePoll() { + } + + public KumalivePoll(Kumalive kumalive, String name) { + this.kumalive = kumalive; + this.name = name; + this.startDate = new Date(); + this.answers = new HashSet(); + } + + public Long getPollId() { + return pollId; + } + + public void setPollId(Long pollId) { + this.pollId = pollId; + } + + public Kumalive getKumalive() { + return kumalive; + } + + public void setKumalive(Kumalive kumalive) { + this.kumalive = kumalive; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getFinishDate() { + return finishDate; + } + + public void setFinishDate(Date endDate) { + this.finishDate = endDate; + } + + public Set getAnswers() { + return answers; + } + + public void setAnswers(Set answers) { + this.answers = answers; + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/model/KumalivePollAnswer.java =================================================================== diff -u --- lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/model/KumalivePollAnswer.java (revision 0) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/model/KumalivePollAnswer.java (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.learning.kumalive.model; + +import java.io.Serializable; + +public class KumalivePollAnswer implements Serializable { + + private static final long serialVersionUID = -760184191959618734L; + + private Long answerId; + private KumalivePoll poll; + private Short orderId; + private String name; + + public KumalivePollAnswer() { + } + + public KumalivePollAnswer(KumalivePoll poll, Short orderId, String name) { + this.poll = poll; + this.orderId = orderId; + this.name = name; + } + + public Long getAnswerId() { + return answerId; + } + + public void setAnswerId(Long answerId) { + this.answerId = answerId; + } + + public KumalivePoll getPoll() { + return poll; + } + + public void setPoll(KumalivePoll poll) { + this.poll = poll; + } + + public Short getOrderId() { + return orderId; + } + + public void setOrderId(Short orderId) { + this.orderId = orderId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/service/IKumaliveService.java =================================================================== diff -u -re3ce54ff7b473269e6148ad285f0148c61ae20af -redcf26c6dbd1e4ff36858d876e908774abb7910d --- lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/service/IKumaliveService.java (.../IKumaliveService.java) (revision e3ce54ff7b473269e6148ad285f0148c61ae20af) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/service/IKumaliveService.java (.../IKumaliveService.java) (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -30,6 +30,7 @@ import org.apache.tomcat.util.json.JSONException; import org.apache.tomcat.util.json.JSONObject; import org.lamsfoundation.lams.learning.kumalive.model.Kumalive; +import org.lamsfoundation.lams.learning.kumalive.model.KumalivePoll; import org.lamsfoundation.lams.learning.kumalive.model.KumaliveRubric; import org.lamsfoundation.lams.util.ExcelCell; @@ -59,4 +60,8 @@ LinkedHashMap exportKumalives(List kumaliveIds); LinkedHashMap exportKumalives(Integer organisationId); + + KumalivePoll getPollByOrganisation(Integer organisationId); + + Long startPoll(Long kumaliveId, String name, JSONArray answersJSON) throws JSONException; } \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/service/KumaliveService.java =================================================================== diff -u -re3ce54ff7b473269e6148ad285f0148c61ae20af -redcf26c6dbd1e4ff36858d876e908774abb7910d --- lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/service/KumaliveService.java (.../KumaliveService.java) (revision e3ce54ff7b473269e6148ad285f0148c61ae20af) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/kumalive/service/KumaliveService.java (.../KumaliveService.java) (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -48,6 +48,8 @@ import org.lamsfoundation.lams.gradebook.util.UserComparator; import org.lamsfoundation.lams.learning.kumalive.dao.IKumaliveDAO; import org.lamsfoundation.lams.learning.kumalive.model.Kumalive; +import org.lamsfoundation.lams.learning.kumalive.model.KumalivePoll; +import org.lamsfoundation.lams.learning.kumalive.model.KumalivePollAnswer; import org.lamsfoundation.lams.learning.kumalive.model.KumaliveRubric; import org.lamsfoundation.lams.learning.kumalive.model.KumaliveScore; import org.lamsfoundation.lams.security.ISecurityService; @@ -85,8 +87,6 @@ /** * Fetches or creates a Kumalive - * - * @throws JSONException */ @Override public Kumalive startKumalive(Integer organisationId, Integer userId, String name, JSONArray rubricsJSON, @@ -541,6 +541,40 @@ return rows.toArray(new ExcelCell[][] {}); } + @Override + public KumalivePoll getPollByOrganisation(Integer organisationId) { + return kumaliveDAO.findPoll(organisationId); + } + + /** + * Creates a poll + */ + @Override + public Long startPoll(Long kumaliveId, String name, JSONArray answersJSON) throws JSONException { + Kumalive kumalive = getKumalive(kumaliveId); + if (kumalive == null) { + return null; + } + KumalivePoll poll = new KumalivePoll(kumalive, name); + kumaliveDAO.insert(poll); + + Set answers = new HashSet<>(); + for (Short answerIndex = 0; answerIndex < answersJSON.length(); answerIndex++) { + String answerName = answersJSON.getString(answerIndex.intValue()); + KumalivePollAnswer answer = new KumalivePollAnswer(poll, answerIndex, answerName); + kumaliveDAO.insert(answer); + answers.add(answer); + } + poll.setAnswers(answers); + kumaliveDAO.update(poll); + + if (logger.isDebugEnabled()) { + logger.debug("Teacher started poll " + poll.getPollId()); + } + + return poll.getPollId(); + } + public void setSecurityService(ISecurityService securityService) { this.securityService = securityService; } Index: lams_learning/web/includes/javascript/kumalive.js =================================================================== diff -u -recd3b320baed53ab184cc7c5d1a67def50651fe2 -redcf26c6dbd1e4ff36858d876e908774abb7910d --- lams_learning/web/includes/javascript/kumalive.js (.../kumalive.js) (revision ecd3b320baed53ab184cc7c5d1a67def50651fe2) +++ lams_learning/web/includes/javascript/kumalive.js (.../kumalive.js) (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -633,12 +633,13 @@ // validation if (question) { $('#pollSetupQuestionGroup').removeClass('has-error'); - poll.question = question; + poll.name = question; } else { $('#pollSetupQuestionGroup').addClass('has-error'); } - if ($('#pollSetupAnswer option:selected').val() === 'custom'){ + var selectedOption = $('#pollSetupAnswer option:selected'); + if (selectedOption.val() === 'custom'){ $('#pollSetupAnswerCustomParseError').hide(); var answerString = $('#pollSetupAnswerCustom').val(); // check if brackets are closed and there is nothing between them, for example "{aaa} {bb" or "{aaa} bb {ccc}" @@ -685,12 +686,18 @@ } else { $('#pollSetupAnswerCustomGroup').addClass('has-error'); } + } else { + var answers = []; + $.each(selectedOption.text().split(','), function() { + answers.push(this.trim()); + }); + poll.answers = answers; } - if (!poll.question || !poll.answers) { + if (!poll.name || !poll.answers) { return; } - + kumaliveWebsocket.send(JSON.stringify({ 'type' : 'startPoll', 'poll' : poll Index: lams_learning/web/kumalive/kumalive.jsp =================================================================== diff -u -recd3b320baed53ab184cc7c5d1a67def50651fe2 -redcf26c6dbd1e4ff36858d876e908774abb7910d --- lams_learning/web/kumalive/kumalive.jsp (.../kumalive.jsp) (revision ecd3b320baed53ab184cc7c5d1a67def50651fe2) +++ lams_learning/web/kumalive/kumalive.jsp (.../kumalive.jsp) (revision edcf26c6dbd1e4ff36858d876e908774abb7910d) @@ -96,7 +96,8 @@
+ placeholder="" + maxlength="250" required/>