Index: lams_central/src/java/org/lamsfoundation/lams/web/DisplayGroupAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/DisplayGroupAction.java,v diff -u -r1.1 -r1.2 --- lams_central/src/java/org/lamsfoundation/lams/web/DisplayGroupAction.java 19 Oct 2007 02:32:38 -0000 1.1 +++ lams_central/src/java/org/lamsfoundation/lams/web/DisplayGroupAction.java 25 Oct 2007 07:19:49 -0000 1.2 @@ -23,19 +23,30 @@ /* $Id$ */ package org.lamsfoundation.lams.web; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.naming.InitialContext; +import javax.naming.NamingException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.sql.DataSource; import org.apache.log4j.Logger; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.learningdesign.LearningDesign; import org.lamsfoundation.lams.lesson.Lesson; import org.lamsfoundation.lams.usermanagement.Organisation; import org.lamsfoundation.lams.usermanagement.OrganisationState; @@ -60,6 +71,7 @@ private static IUserManagementService service; private Integer stateId = OrganisationState.ACTIVE; + @SuppressWarnings({"unchecked"}) public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, @@ -85,11 +97,13 @@ return mapping.findForward("group"); } - //@SuppressWarnings({"unchecked","static-access"}) - private IndexOrgBean createOrgBean(Organisation org, List roles, String username, boolean isSysAdmin) { + @SuppressWarnings({"unchecked"}) + private IndexOrgBean createOrgBean(Organisation org, List roles, String username, boolean isSysAdmin) + throws SQLException, NamingException { User user = (User)getService().findByProperty(User.class, "login", username).get(0); - IndexOrgBean orgBean = new IndexOrgBean(org.getName(), org.getOrganisationType().getOrganisationTypeId()); + IndexOrgBean orgBean = new IndexOrgBean(org.getOrganisationId(), org.getName(), org.getOrganisationType().getOrganisationTypeId()); + // set org links List links = new ArrayList(); if(isSysAdmin && stateId.equals(OrganisationState.ACTIVE)){ if (orgBean.getType().equals(OrganisationType.COURSE_TYPE)) { @@ -111,56 +125,21 @@ } orgBean.setLinks(links); + // set archived date if archived if (stateId.equals(OrganisationState.ARCHIVED) && org.getOrganisationState().getOrganisationStateId().equals(OrganisationState.ARCHIVED)) { orgBean.setArchivedDate(org.getArchivedDate()); } - - List lessonBeans = new ArrayList(); - Set lessons = org.getLessons(); - for(Lesson lesson:lessons) { - if(isInLesson(user,lesson)){ - if(!lesson.isPreviewLesson()){ - List lessonLinks = new ArrayList(); - String url = null; - if(stateId.equals(OrganisationState.ACTIVE)){ - if(contains(roles,Role.ROLE_GROUP_MANAGER)||contains(roles,Role.ROLE_MONITOR)){ - if(!lesson.getLessonStateId().equals(lesson.REMOVED_STATE)){ - lessonLinks.add(new IndexLinkBean("index.monitor", "javascript:openMonitorLesson(" + lesson.getLessonId()+")")); - } - } - if(contains(roles,Role.ROLE_LEARNER)){ - log.debug("Lesson State:"+lesson.getLessonStateId()); - if(lesson.getLessonStateId().equals(lesson.STARTED_STATE)||lesson.getLessonStateId().equals(lesson.FINISHED_STATE)){ - url = "javascript:openLearner("+lesson.getLessonId()+")"; - } - } - }else if(stateId.equals(OrganisationState.ARCHIVED)){ - if(contains(roles,Role.ROLE_GROUP_MANAGER)){ - if(!lesson.getLessonStateId().equals(lesson.REMOVED_STATE)){ - lessonLinks.add(new IndexLinkBean("index.monitor", "javascript:openMonitorLesson(" + lesson.getLessonId()+")")); - } - } - if(contains(roles,Role.ROLE_LEARNER)){ - log.debug("Lesson State:"+lesson.getLessonStateId()); - if(lesson.getLessonStateId().equals(lesson.STARTED_STATE)||lesson.getLessonStateId().equals(lesson.FINISHED_STATE)){ - lessonLinks.add(new IndexLinkBean("label.export.portfolio","javascript:openExportPortfolio("+lesson.getLessonId()+")")); - } - } - } - if(lessonLinks.size()>0 || url!=null){ - IndexLessonBean lessonBean = new IndexLessonBean(lesson.getLessonName(), - lesson.getLessonDescription(), - url, - lesson.getLessonStateId(), - lessonLinks); - lessonBeans.add(lessonBean); - } - } - } + + // set lesson beans + List lessonBeans = null; + try { + lessonBeans = getLessonBeans(user.getUserId(), org.getOrganisationId(), roles, org.getOrderedLessonIds()); + } catch (Exception e) { + log.error("Failed retrieving user's lessons from database: " + e, e); } - Collections.sort(lessonBeans); orgBean.setLessons(lessonBeans); + // create subgroup beans if(orgBean.getType().equals(OrganisationType.COURSE_TYPE)){ Set children = org.getChildOrganisations(); @@ -189,10 +168,92 @@ } return orgBean; } - - private boolean isInLesson(User user, Lesson lesson) { - return lesson.getLessonClass().isStaffMember(user)||lesson.getLessonClass().getLearners().contains(user); + + // get lesson beans and sort them + private List getLessonBeans(Integer userId, Integer orgId, List roles, String orderedLessonIds) + throws SQLException, NamingException { + Map map = populateLessonBeans(userId, orgId, roles); + ArrayList orderedList = new ArrayList(); + + if (orderedLessonIds != null) { + List idList = Arrays.asList(orderedLessonIds.split(",")); + + // sort mapped lesson beans according to orderedLessonIds + for (String idString : idList) { + try { + Long id = new Long(Long.parseLong(idString)); + if (map.containsKey(id)) { + orderedList.add(map.get(id)); + map.remove(id); + } + } catch (NumberFormatException e) { + continue; + } + } + } + + // append lesson beans not mentioned in orderedLessonIds + if (!map.values().isEmpty()) { + orderedList.addAll(map.values()); + } + + return orderedList; } + + // create lesson beans + private Map populateLessonBeans(Integer userId, Integer orgId, List roles) + throws SQLException, NamingException { + + // iterate through user's lessons where they are learner + Map map = getLessonsByOrgAndUser(userId, orgId, false); + for (IndexLessonBean bean : map.values()) { + List lessonLinks = new ArrayList(); + String url = null; + Integer lessonStateId = bean.getState(); + if (stateId.equals(OrganisationState.ACTIVE)) { + if (contains(roles, Role.ROLE_LEARNER)) { + if (lessonStateId.equals(Lesson.STARTED_STATE) || lessonStateId.equals(Lesson.FINISHED_STATE)) { + url = "javascript:openLearner("+bean.getId()+")"; + } + } + } else if (stateId.equals(OrganisationState.ARCHIVED)) { + if (contains(roles, Role.ROLE_LEARNER)) { + if (lessonStateId.equals(Lesson.STARTED_STATE) || lessonStateId.equals(Lesson.FINISHED_STATE)) { + lessonLinks.add(new IndexLinkBean("label.export.portfolio","javascript:openExportPortfolio("+bean.getId()+")")); + } + } + } + if (lessonLinks.size()>0 || url!=null) { + bean.setUrl(url); + bean.setLinks(lessonLinks); + } + } + + // iterate through user's lessons where they are staff, and add staff links to the beans in the map. + Map staffMap = getLessonsByOrgAndUser(userId, orgId, true); + for (IndexLessonBean bean : staffMap.values()) { + if (map.containsKey(bean.getId())) { + bean = map.get(bean.getId()); + } + List lessonLinks = bean.getLinks(); + if (lessonLinks == null) lessonLinks = new ArrayList(); + if (stateId.equals(OrganisationState.ACTIVE)) { + if (contains(roles, Role.ROLE_GROUP_MANAGER) || contains(roles, Role.ROLE_MONITOR)){ + lessonLinks.add(new IndexLinkBean("index.monitor", "javascript:openMonitorLesson(" + bean.getId()+")")); + } + } else if (stateId.equals(OrganisationState.ARCHIVED)) { + if (contains(roles, Role.ROLE_GROUP_MANAGER)) { + lessonLinks.add(new IndexLinkBean("index.monitor", "javascript:openMonitorLesson(" + bean.getId()+")")); + } + } + if (lessonLinks.size() > 0) { + bean.setLinks(lessonLinks); + } + map.put(bean.getId(), bean); + } + + return map; + } private boolean contains(List roles, Integer roleId) { for (int i = 0; i < roles.size(); i++) { @@ -209,5 +270,55 @@ } return service; } + + // get lesson beans where user is learner (if isStaff=true, gets lessons where user is staff) + private Map getLessonsByOrgAndUser(Integer userId, Integer orgId, boolean isStaff) + throws SQLException, NamingException { + String learnerQuery = "select l.lesson_id, l.name, l.description, l.lesson_state_id " + + " from lams_lesson l, lams_learning_design ld, lams_group g, lams_user_group ug, lams_grouping gi" + + " where l.learning_design_id=ld.learning_design_id" + + " and ld.copy_type_id!=" + LearningDesign.COPY_TYPE_PREVIEW + + " and l.organisation_id=?" + + " and l.class_grouping_id=g.grouping_id" + + " and l.lesson_state_id!=" + Lesson.REMOVED_STATE + + " and ug.group_id=g.group_id" + + " and ug.user_id=?" + + " and gi.grouping_id=g.grouping_id" + + " and g.group_id" + (isStaff ? "" : "!") + "=gi.staff_group_id"; + + InitialContext ctx = new InitialContext(); + DataSource ds = (DataSource) ctx.lookup("java:/jdbc/lams-ds"); + Connection conn = null; + + HashMap map = new HashMap(); + + try { + conn = ds.getConnection(); + PreparedStatement ps = conn.prepareStatement(learnerQuery); + ps.setInt(1, orgId.intValue()); + ps.setInt(2, userId.intValue()); + ResultSet rs = ps.executeQuery(); + + // check if there is any result + while (rs.next() != false) { + long id = rs.getLong(1); + String name = rs.getString(2); + String description = rs.getString(3); + int state = rs.getInt(4); + IndexLessonBean bean = new IndexLessonBean( + new Long(id), name, description, new Integer(state) + ); + map.put(new Long(id), bean); + } + + rs.close(); + } finally { + if (conn != null && !conn.isClosed()) { + conn.close(); + } + } + + return map; + } } \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/web/IndexLessonBean.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/Attic/IndexLessonBean.java,v diff -u -r1.7 -r1.8 --- lams_central/src/java/org/lamsfoundation/lams/web/IndexLessonBean.java 19 Oct 2007 02:32:38 -0000 1.7 +++ lams_central/src/java/org/lamsfoundation/lams/web/IndexLessonBean.java 25 Oct 2007 07:19:49 -0000 1.8 @@ -36,6 +36,7 @@ * Created at 10:13:43 on 14/06/2006 */ public class IndexLessonBean implements Comparable{ + private Long id; private String name; private String description; private String url; @@ -47,9 +48,17 @@ this.url = url; } - public IndexLessonBean(String name, String description, String url, Integer state, List links) { + public IndexLessonBean(Long id, String name, String description, Integer state) { + this.id = id; this.name = name; this.description = description; + this.state = state; + } + + public IndexLessonBean(Long id, String name, String description, String url, Integer state, List links) { + this.id = id; + this.name = name; + this.description = description; this.url = url; this.state = state; this.links = links; @@ -66,6 +75,12 @@ public void setLinks(List links) { this.links = links; } + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } /** * @return Returns the name. */ Index: lams_central/src/java/org/lamsfoundation/lams/web/IndexOrgBean.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/Attic/IndexOrgBean.java,v diff -u -r1.5 -r1.6 --- lams_central/src/java/org/lamsfoundation/lams/web/IndexOrgBean.java 14 Sep 2007 07:45:16 -0000 1.5 +++ lams_central/src/java/org/lamsfoundation/lams/web/IndexOrgBean.java 25 Oct 2007 07:19:49 -0000 1.6 @@ -39,6 +39,7 @@ */ public class IndexOrgBean implements Comparable { + private Integer id; private String name; private Date archivedDate; private Integer type; @@ -47,7 +48,8 @@ private List childIndexOrgBeans; - public IndexOrgBean(String name, Integer type) { + public IndexOrgBean(Integer id, String name, Integer type) { + this.id = id; this.name = name; this.type = type; this.links = new ArrayList(); @@ -91,6 +93,18 @@ this.links = links; } /** + * @return Returns the id. + */ + public Integer getId() { + return id; + } + /** + * @param id The id to set. + */ + public void setId(Integer id) { + this.id = id; + } + /** * @return Returns the name. */ public String getName() { Index: lams_central/src/java/org/lamsfoundation/lams/web/LessonOrderServlet.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/LessonOrderServlet.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lams_central/src/java/org/lamsfoundation/lams/web/LessonOrderServlet.java 25 Oct 2007 07:19:50 -0000 1.1 @@ -0,0 +1,154 @@ +/**************************************************************** + * 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 + * **************************************************************** + */ + +/* $Id: LessonOrderServlet.java,v 1.1 2007/10/25 07:19:50 jliew Exp $ */ +package org.lamsfoundation.lams.web; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.lamsfoundation.lams.lesson.Lesson; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.service.UserManagementService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.util.HttpSessionManager; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * Used by main.jsp to persist the ordering of lessonIds when lessons are + * ordered by a staff member for a group. Currently stores lessonIds as a + * single comma separated string in lams_organisation. + * + * @author jliew + * + * @web:servlet name="saveLessonOrder" + * @web:servlet-mapping url-pattern="/servlet/saveLessonOrder" + */ +public class LessonOrderServlet extends HttpServlet { + + private static Logger log = Logger.getLogger(LessonOrderServlet.class); + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + Integer orgId = WebUtil.readIntParam(request, "orgId", false); + String ids = request.getParameter("ids"); + + WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(HttpSessionManager.getInstance().getServletContext()); + UserManagementService service = (UserManagementService) ctx.getBean("userManagementService"); + + if (orgId != null && ids != null) { + Organisation org = (Organisation)service.findById(Organisation.class, orgId); + + if (org != null) { + // verify the ids are lessons that belong to orgId; + // necessary since javascript on index page doesn't restrict + // where user drops a lesson when sorting. + // TODO: remove this validation when the javascript sortable's + // containment parameter is working. + List idList = Arrays.asList(ids.split(",")); + Set lessons = org.getLessons(); + for (String id : idList) { + try { + Long l = new Long(Long.parseLong(id)); + if (!contains(lessons, l)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN); + } + } catch(NumberFormatException e) { + continue; + } + } + + String oldIds = org.getOrderedLessonIds(); + String updatedIds = mergeLessonIds((oldIds!=null ? oldIds : ""), ids); + org.setOrderedLessonIds(updatedIds); + service.save(org); + } + } + + } + + private boolean contains(Set lessons, Long id) { + Iterator it = lessons.iterator(); + while (it.hasNext()) { + Lesson lesson = (Lesson)it.next(); + if (lesson.getLessonId().equals(id)) return true; + } + return false; + } + + // take the updated list and insert elements of the old list that don't exist in it; + private String mergeLessonIds(String old, String updated) { + List oldIds = Arrays.asList(old.split(",")); + List updatedIds = Arrays.asList(updated.split(",")); + ArrayList mergedIds = new ArrayList(updatedIds); + + for (int i=0; i oldIds, List updatedIds) { + for (int j=i; j -1) { + return index; + } + } + return -1; + } + + // implode strings in list separated by commas + private String joinString(List list) { + String s = ""; + if (list != null) { + for (String i : list) { + s += i + ","; + } + s = s.substring(0, s.length()-1); + } + return s; + } +} + \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/web/ProfileAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/ProfileAction.java,v diff -u -r1.11 -r1.12 --- lams_central/src/java/org/lamsfoundation/lams/web/ProfileAction.java 14 Sep 2007 07:45:16 -0000 1.11 +++ lams_central/src/java/org/lamsfoundation/lams/web/ProfileAction.java 25 Oct 2007 07:19:49 -0000 1.12 @@ -119,7 +119,7 @@ // insert or update bean if it is a course if (orgTypeId.equals(OrganisationType.COURSE_TYPE)) { IndexOrgBean orgBean = (!orgBeansMap.containsKey(orgId)) - ? new IndexOrgBean(org.getName(), orgTypeId) + ? new IndexOrgBean(org.getOrganisationId(), org.getName(), orgTypeId) : orgBeansMap.get(orgId); orgBean.addLesson(lessonBean); orgBeansMap.put(orgId, orgBean); @@ -129,10 +129,10 @@ Organisation parentOrg = org.getParentOrganisation(); Integer parentOrgId = parentOrg.getOrganisationId(); IndexOrgBean parentOrgBean = (!orgBeansMap.containsKey(parentOrgId)) - ? new IndexOrgBean(parentOrg.getName(), OrganisationType.COURSE_TYPE) + ? new IndexOrgBean(parentOrg.getOrganisationId(), parentOrg.getName(), OrganisationType.COURSE_TYPE) : orgBeansMap.get(parentOrgId); // create new bean for class, or use existing bean - IndexOrgBean orgBean = new IndexOrgBean(org.getName(), orgTypeId); + IndexOrgBean orgBean = new IndexOrgBean(org.getOrganisationId(), org.getName(), orgTypeId); List childOrgBeans = parentOrgBean.getChildIndexOrgBeans(); if (childOrgBeans.contains(orgBean)) { orgBean = getOrgBean(org.getName(), childOrgBeans); Index: lams_central/web/group.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_central/web/group.jsp,v diff -u -r1.1 -r1.2 --- lams_central/web/group.jsp 19 Oct 2007 02:32:38 -0000 1.1 +++ lams_central/web/group.jsp 25 Oct 2007 07:19:50 -0000 1.2 @@ -8,7 +8,7 @@
-

+

( )

@@ -21,11 +21,11 @@
-
+
- -

+

    " class="j-lessons"> +

    " class="j-single-lesson">  () @@ -42,7 +42,7 @@

    -
    +
Index: lams_central/web/main.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_central/web/main.jsp,v diff -u -r1.18 -r1.19 --- lams_central/web/main.jsp 19 Oct 2007 02:32:38 -0000 1.18 +++ lams_central/web/main.jsp 25 Oct 2007 07:19:50 -0000 1.19 @@ -29,16 +29,41 @@ +