Index: lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/web/NbAuthoringV2Action.java =================================================================== diff -u --- lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/web/NbAuthoringV2Action.java (revision 0) +++ lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/web/NbAuthoringV2Action.java (revision 1186a113f98c243e375a9e80df090e2393a8e78d) @@ -0,0 +1,535 @@ +/* + *Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * + *This program is free software; you can redistribute it and/or modify + *it under the terms of the GNU General Public License as published by + *the Free Software Foundation; either version 2 of the License, or + *(at your option) any later version. + * + *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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + *USA + * + *http://www.gnu.org/licenses/gpl.txt + */ + +/* + * Created on Aug 8, 2005 + * + */ +package org.lamsfoundation.lams.tool.noticeboard.web; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map; +import java.util.HashMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +//import org.apache.struts.actions.LookupDispatchAction; +import org.lamsfoundation.lams.web.action.LamsLookupDispatchAction; +//import org.lamsfoundation.lams.web.action.LamsAction; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; + +import org.lamsfoundation.lams.tool.noticeboard.NoticeboardConstants; +import org.lamsfoundation.lams.tool.noticeboard.NoticeboardContent; +import org.lamsfoundation.lams.tool.noticeboard.NoticeboardAttachment; +import org.lamsfoundation.lams.tool.noticeboard.NbApplicationException; +import org.lamsfoundation.lams.tool.noticeboard.util.NbWebUtil; +import org.lamsfoundation.lams.tool.noticeboard.util.NbToolContentHandler; +import org.lamsfoundation.lams.tool.noticeboard.service.INoticeboardService; +import org.lamsfoundation.lams.tool.noticeboard.service.NoticeboardServiceProxy; +import org.apache.struts.upload.FormFile; +import org.apache.struts.util.MessageResources; +import org.lamsfoundation.lams.util.WebUtil; + +//import org.lamsfoundation.lams.contentrepository.CrNodeVersionProperty; +import org.lamsfoundation.lams.contentrepository.InvalidParameterException; +import org.lamsfoundation.lams.contentrepository.NodeKey; +import org.lamsfoundation.lams.contentrepository.RepositoryCheckedException; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * @author mtruong + * + * ----------------XDoclet Tags-------------------- + * + * @struts:action path="/authoringv2" name="NbAuthoringForm" scope="session" + * type="org.lamsfoundation.lams.tool.noticeboard.web.NbAuthoringV2Action" + * parameter="method" validate="true" input="/author_page.jsp" + * + * @struts.action-exception key="error.exception.NbApplication" scope="request" + * type="org.lamsfoundation.lams.tool.noticeboard.NbApplicationException" + * path=".error" + * handler="org.lamsfoundation.lams.tool.noticeboard.web.CustomStrutsExceptionHandler" + * @struts.action-exception key="error.exception.NbApplication" scope="request" + * type="java.lang.NullPointerException" + * path=".error" + * handler="org.lamsfoundation.lams.tool.noticeboard.web.CustomStrutsExceptionHandler" + * + * @struts:action-forward name="authoringContent2" path="/author_page.jsp" + * @struts:action-forward name="displayMessage" path=".message" + * + * ----------------XDoclet Tags-------------------- + */ +public class NbAuthoringV2Action extends LamsLookupDispatchAction { + static Logger logger = Logger.getLogger(NbAuthoringV2Action.class.getName()); + public final static String FORM="NbAuthoringForm"; + + private NbToolContentHandler toolContentHandler; + + private NbToolContentHandler getToolContentHandler() + { + if ( toolContentHandler == null ) { + WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet().getServletContext()); + toolContentHandler = (NbToolContentHandler) wac.getBean(NbToolContentHandler.SPRING_BEAN_NAME); + } + return toolContentHandler; + } + + protected Map getKeyMethodMap() + { + Map map = new HashMap(); + map.put(NoticeboardConstants.BUTTON_SAVE, "save"); + map.put(NoticeboardConstants.BUTTON_UPLOAD, "upload"); + map.put(NoticeboardConstants.LINK_DELETE, "deleteAttachment"); + + return map; + } + + + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws NbApplicationException { + + MessageResources resources = getResources(request); + + //to ensure that we are working with a new form, not one from previous session + NbAuthoringForm nbForm = new NbAuthoringForm(); + NbWebUtil.cleanAuthoringSession(request); + + Long contentId = NbWebUtil.convertToLong(request.getParameter(NoticeboardConstants.TOOL_CONTENT_ID)); + + if(contentId == null) + { + //String error = "Tool content id missing. Unable to continue."; + String error = resources.getMessage(NoticeboardConstants.ERR_MISSING_PARAM, "Tool Content Id"); + logger.error(error); + throw new NbApplicationException(error); + } + nbForm.setToolContentId(contentId.toString()); + + /* if there is a defineLater request parameter, set the form value + * If a defineLater request parameter is not present, then it is just set to null. + * This is used in the basic screen, if defineLater is set, then in the basic page, + * the three tabs {Basic, Advanced, Instructions} are not visible. + */ + nbForm.setDefineLater((String)request.getParameter(NoticeboardConstants.DEFINE_LATER)); + + request.getSession().setAttribute(NoticeboardConstants.TOOL_CONTENT_ID, contentId); + + /* + * Retrieve the Service + */ + INoticeboardService nbService = NoticeboardServiceProxy.getNbService(getServlet().getServletContext()); + Map attachmentMap = nbForm.getAttachments(); + + if (!contentExists(nbService, contentId)) + { + // Pre-fill the form with the default content + NoticeboardContent nb = nbService.retrieveNoticeboard(NoticeboardConstants.DEFAULT_CONTENT_ID); + + /** TODO: add a check to see if object is null */ + + //create a new noticeboard object and prefill with default content, save to database + NoticeboardContent nbContentNew = new NoticeboardContent(contentId, + nb.getTitle(), + nb.getContent(), + nb.getOnlineInstructions(), + nb.getOfflineInstructions(), + new Date(System.currentTimeMillis())); + + nbContentNew = setTrueIfDefineLaterIsSet(nbForm, nbContentNew); + + //save new tool content into db + nbService.saveNoticeboard(nbContentNew); + + //initialise the values in the form, so the values will be shown in the jsp + nbForm.populateFormWithNbContentValues(nbContentNew); + + + + + } + else //content already exists on the database + { + //get the values from the database + NoticeboardContent nb = nbService.retrieveNoticeboard(contentId); + + /* If retrieving existing content, check whether the contentInUse flag is set, if set, the + * author is not allowed to edit content + */ + + if (NbWebUtil.isContentEditable(nb)) + { + /* Define later set to true when the edit activity tab is brought up + * So that users cannot start using the content while the staff member is editing the content */ + nbForm.populateFormWithNbContentValues(nb); + nb = setTrueIfDefineLaterIsSet(nbForm, nb); + nbService.updateNoticeboard(nb); + + + + } + else + { + //The contentInUse flag is set and a user has already reached this activity. + saveMessages(request, null); //ensure there are no existing messages + ActionMessages message = new ActionMessages(); + message.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("message.contentInUseSet")); + saveMessages(request, message); + return mapping.findForward(NoticeboardConstants.DISPLAY_MESSAGE); + + } + + //Setup the map containing the files that have been uploaded for this particular tool content id + + List attachmentIdList = nbService.getAttachmentIdsFromContent(nb); + for (int i=0; itoolContentId to check + */ + private void checkContentId(Long contentId) + { + if (contentId == null) + { + String error = "Unable to continue. Tool content id missing."; + + throw new NbApplicationException(error); + } + } + + /** + * This method copies the values of the request parameters richTextOnlineInstructions + * richTextOfflineInstructions richTextContent into the form properties + * onlineInstructions, offlineInstructions and content respectively. + * If a null value is returned for the request parameter, the form value is not modified. + * The request parameters are set as optional because the form spans amongst two pages. + * + * @param request HttpServlet request + * @param form The ActionForm class containing data submitted by the forms. + */ + private void copyAuthoringFormValuesIntoFormBean(HttpServletRequest request, NbAuthoringForm form) + { + String onlineInstruction = WebUtil.readStrParam(request, NoticeboardConstants.RICH_TEXT_ONLINE_INSTRN, true); + String offlineInstruction = WebUtil.readStrParam(request, NoticeboardConstants.RICH_TEXT_OFFLINE_INSTRN, true); + String content = WebUtil.readStrParam(request, NoticeboardConstants.RICH_TEXT_CONTENT, true); + String title = WebUtil.readStrParam(request, NoticeboardConstants.RICH_TEXT_TITLE, true); + + if(title != null) + form.setTitle(title); + if(content != null) + form.setContent(content); + if(onlineInstruction != null) + form.setOnlineInstructions(onlineInstruction); + if(offlineInstruction != null) + form.setOfflineInstructions(offlineInstruction); + + } + /** + * This method checks whether a file + * already exists in the database. If this file already exists, then the + * type of file is checked, along with the associated toolContentId. + * If both files are also of the same type, ie. + * both are offline files or both are online files and the tool content Id matches + * toolContentId, then this method will + * return true, to indicate that the file already exists in the database. + * Otherwise false is returned. + * @param filename The filename of the attachment to check + * @param isOnlineFile A boolean to indicate whether it is an online File. 1 indicates an online file. The value 0 indicates an offline file. + * @return + */ + private boolean fileExists(Long toolContentId, NoticeboardAttachment fileFromDatabase, boolean isFileUploadedAnOnlineFile) + { + + if (fileFromDatabase == null) + { + return false; + } + else + { + /** + * true && true = true <-- both files are both online files + * true && false = false <-- the files are different types + * false && true = false <-- the files are different types + * false && false = true <-- both files are offline files + */ + if (fileFromDatabase.isOnlineFile() && isFileUploadedAnOnlineFile && fileFromDatabase.getNbContent().getNbContentId().equals(toolContentId)) + { + return true; + } + else + return false; + } + } + + + +} + Index: lams_tool_nb/web/author_page/css/aqua.css =================================================================== diff -u --- lams_tool_nb/web/author_page/css/aqua.css (revision 0) +++ lams_tool_nb/web/author_page/css/aqua.css (revision 1186a113f98c243e375a9e80df090e2393a8e78d) @@ -0,0 +1,203 @@ +/*This is a theme CSS file. Which one will be loaded into the JSP depends on a variable passed in from FLASH.*/ + +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + background-color: #A2BCF9; + font-size: small; +} + +h1 { + font-size: large; + background-color: #B4C8FE; + border-top-width: 1px; + border-top-style: solid; + border-top-color: #999999; + border-left-width: 1px; + border-left-style: solid; + border-left-color: #999999; +} +h2 { + font-size: small; + border-bottom-style: solid; + border-bottom-width: 1px; + border-bottom-color: #666666; + margin-bottom: 1px; + + +} + +th { + font-size: small; + color: #FFFFFF; + background-color: #075A8B; + text-align: left; +} + +.formtablecontainer{ + text-align:center; +} + +.datatablecontainer{ + width:100%; +} + +.buttoncontainer { + +} + + +input, select, textarea { + font-family: 'Verdana', 'Arial', 'Helvetica', sans-serif; + font-size: small; +} + +.forms { + border: 1px solid #999999; + font-size: small; + font-style: normal; + width: 100%; +} + +.formlabel { + font-size: small; + font-style: normal; + text-align: right; + width: 20%; +} + +.formcontrol { + font-size: small; + font-style: normal; + text-align: left; +} + +/*tab styles*/ +.tab{ + text-align:center; +} + +.tab a{ + font-size: 11px; + color: #000000; + text-decoration:none; +} +.tab a:hover{ + font-size: 11px; + color: #000000; + text-decoration:underline +} +.tabcentre{ + background-image:url(../images/aqua_tab_centre.gif); + background-repeat:repeat-x; +} + + +.tabcentre_selected{ + background-image:url(../images/aqua_tab_s_centre.gif); + background-repeat:repeat-x; +} + + + +/*Tab content containers*/ +.tabbody{ + + + background-color : #D9E8FF; + float:left; + + margin : 0; + border-right-width: 1px; + border-left-width: 1px; + border-right-style: solid; + border-left-style: solid; + border-right-color: #0D3F59; + border-left-color: #0D3F59; + + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: #0D3F59; + padding:5px; + +} + + +/*specific styles for the content divs of the tabs*/ +.content_b{ + z-index: 0; + position:relative; + visibility:visible; +} +.content_a{ + z-index: 1; + position:absolute; + visibility: hidden; +} +.content_i{ + z-index: 2; + position:absolute; + visibility: hidden; +} +/*end tabs*/ + +a.button{ + float:right; + font-size: 12px; + color: #000000; + text-decoration:none; + text-align: center; + background-color:#B4C8FE; + margin: 2px 5px 2px 5px; + padding:3px; + width: 80px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-color: #FFFFFF; + border-right-color: #0D3F59; + border-bottom-color: #0D3F59; + border-left-color: #FFFFFF; +} + + + +a.button:link{ + color: #000000; + text-decoration:none; + background-color:#B4C8FE; +} + +a.button:visited{ + color: #000000; + text-decoration:none; + background-color:#B4C8FE; +} + + + +a.button:hover{ + text-decoration:none; + background-color:#FFFFFF; +} + +a.button:active{ + text-decoration:none; + background-color:#CCCCCC; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-bottom-color: #FFFFFF; + border-left-color: #0D3F59; + border-top-color: #0D3F59; + border-right-color: #FFFFFF; +} Index: lams_tool_nb/web/author_page/css/base.css =================================================================== diff -u --- lams_tool_nb/web/author_page/css/base.css (revision 0) +++ lams_tool_nb/web/author_page/css/base.css (revision 1186a113f98c243e375a9e80df090e2393a8e78d) @@ -0,0 +1,3 @@ +/* +This is the Base CSS, it will define the location of images etc and other core, non user configurable items. (Admin configurable) +*/ \ No newline at end of file Index: lams_tool_nb/web/author_page/css/xp.css =================================================================== diff -u --- lams_tool_nb/web/author_page/css/xp.css (revision 0) +++ lams_tool_nb/web/author_page/css/xp.css (revision 1186a113f98c243e375a9e80df090e2393a8e78d) @@ -0,0 +1,3 @@ +/* +Another theme CSS, would have diufferent colours and layout techniques +*/ \ No newline at end of file Index: lams_tool_nb/web/author_page/images/aqua_tab_centre.gif =================================================================== diff -u Binary files differ Index: lams_tool_nb/web/author_page/images/aqua_tab_left.gif =================================================================== diff -u Binary files differ Index: lams_tool_nb/web/author_page/images/aqua_tab_right.gif =================================================================== diff -u Binary files differ Index: lams_tool_nb/web/author_page/images/aqua_tab_s_centre.gif =================================================================== diff -u Binary files differ Index: lams_tool_nb/web/author_page/images/aqua_tab_s_left.gif =================================================================== diff -u Binary files differ Index: lams_tool_nb/web/author_page/images/aqua_tab_s_right.gif =================================================================== diff -u Binary files differ Index: lams_tool_nb/web/author_page/js/tabcontroller.js =================================================================== diff -u --- lams_tool_nb/web/author_page/js/tabcontroller.js (revision 0) +++ lams_tool_nb/web/author_page/js/tabcontroller.js (revision 1186a113f98c243e375a9e80df090e2393a8e78d) @@ -0,0 +1,119 @@ + +var tabsContents = new Array(); +var tab_lefts = new Array(); +//TODO:we need to set this variable, maybe from the praent or direct from JSP/Java +var themeName = "aqua"; + +function getKey(keyStroke) { + isNetscape=(document.layers); + eventChooser = (isNetscape) ? keyStroke.which : event.keyCode; + which = String.fromCharCode(eventChooser).toLowerCase(); + if(which=="a" || which=="b" || which=="i"){ + showTab(which); + } + + +} +document.onkeypress = getKey; + +function initTabs(){ + //put all the tab contents in an array + tabsContents.push(document.getElementById('content_b')); + tabsContents.push(document.getElementById('content_a')); + tabsContents.push(document.getElementById('content_i')); + + //position the advanced (a) and instructions (i) layers over the basic (b) layer + var bTabC_x = findPosX(tabsContents[0]); + var bTabC_y = findPosY(tabsContents[0]); + + tabsContents[1].style.left = bTabC_x+'px'; + tabsContents[1].style.top = bTabC_y+'px'; + tabsContents[2].style.left = bTabC_x+'px'; + tabsContents[2].style.top = bTabC_y+'px'; + tabsContents[1].style.visibility="hidden"; + tabsContents[2].style.visibility="hidden"; +} + +function deSelectTab(tabId){ + //swap images of side parts + var tl = document.getElementById("tab_left_"+tabId); + tl.src="author_page/images/"+themeName+"_tab_left.gif"; + tl.height = 22; + var tr = document.getElementById("tab_right_"+tabId); + tr.src="author_page/images/"+themeName+"_tab_right.gif"; + tr.height = 22; + //swap css of centre class + var tc = document.getElementById("tab_tbl_centre_"+tabId); + tc.className="tab tabcentre"; +} + +function selectTab(tabId){ + //swap images of side parts + var tl = document.getElementById("tab_left_"+tabId); + tl.src="author_page/images/"+themeName+"_tab_s_left.gif"; + tl.height = 25; + var tr = document.getElementById("tab_right_"+tabId); + tr.src="author_page/images/"+themeName+"_tab_s_right.gif"; + tr.height = 25; + //swap css of centre class + var tc = document.getElementById("tab_tbl_centre_"+tabId); + tc.className="tab tabcentre_selected"; + +} + +function showTab(tabId){ + + selectTab(tabId); + + if(tabId == "i"){ + deSelectTab("a"); + deSelectTab("b"); + }else if(tabId=="a"){ + deSelectTab("i"); + deSelectTab("b"); + }else{ + deSelectTab("i"); + deSelectTab("a"); + } + + //sort out the content + var contentId = "content_"+tabId; + for(var i=0; i < tabsContents.length; i++){ + if(tabsContents[i].id==contentId){ + tabsContents[i].style.visibility="visible"; + }else{ + tabsContents[i].style.visibility="hidden"; + } + } + +} + +function findPosX(obj) { + var curleft = 0; + if(obj.offsetParent) + while(1) + { + curleft += obj.offsetLeft; + if(!obj.offsetParent) + break; + obj = obj.offsetParent; + } + else if(obj.x) + curleft += obj.x; + return curleft; + } + +function findPosY(obj) { + var curtop = 0; + if(obj.offsetParent) + while(1) + { + curtop += obj.offsetTop; + if(!obj.offsetParent) + break; + obj = obj.offsetParent; + } + else if(obj.y) + curtop += obj.y; + return curtop; + }