diff --git a/src/main/java/de/bps/course/nodes/ChecklistCourseNode.java b/src/main/java/de/bps/course/nodes/ChecklistCourseNode.java index d14a9b6ff171e792d5698e28d1b351f06f0f7696..5f391a64c432dc149c0994cb0540bad0d4ddb46f 100644 --- a/src/main/java/de/bps/course/nodes/ChecklistCourseNode.java +++ b/src/main/java/de/bps/course/nodes/ChecklistCourseNode.java @@ -20,16 +20,25 @@ package de.bps.course.nodes; import java.io.File; +import java.io.IOException; +import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.tabbable.TabbableController; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.ExportUtil; import org.olat.core.util.FileUtils; +import org.olat.core.util.Formatter; +import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.ValidationStatus; import org.olat.core.util.WebappHelper; @@ -51,6 +60,7 @@ import org.olat.course.properties.CoursePropertyManager; import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; @@ -74,7 +84,8 @@ import de.bps.olat.modules.cl.CheckpointMode; * @author skoeber <skoeber@bps-system.de> */ public class ChecklistCourseNode extends AbstractAccessableCourseNode { - + private static final long serialVersionUID = -8978938639489414749L; + private static final OLog log = Tracing.createLoggerFor(ChecklistCourseNode.class); private static final String TYPE = "cl"; public static final String CONF_COURSE_ID = "cl_course_id"; public static final String CONF_COURSE_NODE_ID = "cl_course_node_id"; @@ -304,16 +315,23 @@ public class ChecklistCourseNode extends AbstractAccessableCourseNode { } @Override - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - XStream xstream = new XStream(); + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { + String filename = "checklist_" + + StringHelper.transformDisplayNameToFileSystemName(getShortName()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); + Checklist checklist = loadOrCreateChecklist(course.getCourseEnvironment().getCoursePropertyManager()); - String exportContent = xstream.toXML(checklist); - String exportFilename = ExportUtil.createFileNameWithTimeStamp("checklist_"+this.getIdent(), "xml"); - ExportUtil.writeContentToFile(exportFilename, exportContent, exportDirectory, WebappHelper.getDefaultCharset()); - - return true; + String exportContent = XStreamHelper.createXStreamInstance().toXML(checklist); + try { + exportStream.putNextEntry(new ZipEntry(filename)); + IOUtils.write(exportContent, exportStream); + exportStream.closeEntry(); + } catch (IOException e) { + log.error("", e); + } + return true; } - + private String getExportFilename() { return "checklist_"+this.getIdent()+".xml"; } diff --git a/src/main/java/de/bps/onyx/plugin/OnyxExportManager.java b/src/main/java/de/bps/onyx/plugin/OnyxExportManager.java index 4d1f4336ba0e5abe01ce15924434175450fd9660..46066dcff9cd6a956c836eea42cbe452112a0d17 100644 --- a/src/main/java/de/bps/onyx/plugin/OnyxExportManager.java +++ b/src/main/java/de/bps/onyx/plugin/OnyxExportManager.java @@ -31,7 +31,10 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; import org.olat.core.gui.media.MediaResource; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; @@ -112,6 +115,24 @@ public class OnyxExportManager { } return filename; } + + public void exportResults(List<QTIResultSet> resultSets, ZipOutputStream exportStream, CourseNode currentCourseNode) { + final String path = createTargetFilename(currentCourseNode.getShortTitle(), "TEST"); + for (final QTIResultSet rs : resultSets) { + String resultXml = getResultXml(rs.getIdentity().getName(), + currentCourseNode.getModuleConfiguration().get(IQEditController.CONFIG_KEY_TYPE).toString(), + currentCourseNode.getIdent(), rs.getAssessmentID()); + + String filename = path + "/" + rs.getIdentity().getName() + "_" + rs.getCreationDate() + ".xml"; + try { + exportStream.putNextEntry(new ZipEntry(filename)); + IOUtils.write(resultXml, exportStream); + exportStream.closeEntry(); + } catch (IOException e) { + log.error("", e); + } + } + } /** * Method exports the result.xmls of the given Survey in a zip file without the usernames. diff --git a/src/main/java/org/olat/_spring/extensionContext.xml b/src/main/java/org/olat/_spring/extensionContext.xml index b50f8cc96a9d63dae1a9a4c3a2f93e4ebb9fdacc..4015e1c541281908414843f3ba5d87a7ed9d5f1a 100644 --- a/src/main/java/org/olat/_spring/extensionContext.xml +++ b/src/main/java/org/olat/_spring/extensionContext.xml @@ -826,24 +826,6 @@ </property> <property name="order" value="11" /> </bean> - - - <!-- Extension for SCORM Results export --> - <bean class="org.olat.modules.scorm.archiver.ArchiverActionExtension" init-method="initExtensionPoints"> - <property name="actionController"> - <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> - <property name="className" value="org.olat.modules.scorm.archiver.ScormResultArchiveController"/> - </bean> - </property> - <property name="extensionPoints"> - <list> - <value>org.olat.course.archiver.ArchiverMainController</value> - </list> - </property> - <property name="order" value="35" /> - </bean> - - <!-- portfolioContext.xml : property name="order" value="37" --> <!-- template for extension of type GenericActionExtension <bean id="NAMEIToptional" class="org.olat.core.extensions.action.GenericActionExtension" init-method="initExtensionPoints"> @@ -882,5 +864,4 @@ <property name="order" value="38" /> </bean> --> - </beans> \ No newline at end of file diff --git a/src/main/java/org/olat/core/gui/components/panel/Panel.java b/src/main/java/org/olat/core/gui/components/panel/Panel.java index 720944d0ca41e8f3f20d693c83e9e49b53574319..d2b046a39f50c3b2fd556ff53981e9f3edf67f1e 100644 --- a/src/main/java/org/olat/core/gui/components/panel/Panel.java +++ b/src/main/java/org/olat/core/gui/components/panel/Panel.java @@ -46,7 +46,7 @@ public class Panel extends Container { private static final ComponentRenderer RENDERER = new PanelRenderer(); private Component curContent; - protected final List<Component> stackList = new ArrayList<Component>(3);; // allow access to extending classes + protected final List<Component> stackList = new ArrayList<Component>(3); // allow access to extending classes /** * @param name diff --git a/src/main/java/org/olat/core/util/vfs/VFSManager.java b/src/main/java/org/olat/core/util/vfs/VFSManager.java index dcc61daebc982f441e40135fc8c1f2ea8ec83879..7fea9be18c3dd790c4ef00c6d3b0455934baf256 100644 --- a/src/main/java/org/olat/core/util/vfs/VFSManager.java +++ b/src/main/java/org/olat/core/util/vfs/VFSManager.java @@ -115,6 +115,14 @@ public class VFSManager extends BasicManager { return false; } + public static boolean isDirectoryAndNotEmpty(VFSItem directory){ + if(directory instanceof VFSContainer) { + List<VFSItem> children = ((VFSContainer)directory).getItems(); + return !children.isEmpty(); + } + return false; + } + /** * @see org.olat.core.util.vfs.VFSItem#resolveFile(java.lang.String) */ diff --git a/src/main/java/org/olat/course/CourseFactory.java b/src/main/java/org/olat/course/CourseFactory.java index 8036a731b2fa9b07b850587f07521ca902d2a1d5..daf48f5929550082552f1207859a64337f050a99 100644 --- a/src/main/java/org/olat/course/CourseFactory.java +++ b/src/main/java/org/olat/course/CourseFactory.java @@ -26,8 +26,11 @@ package org.olat.course; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -35,7 +38,9 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.zip.ZipOutputStream; +import org.apache.poi.util.IOUtils; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityManager; import org.olat.basesecurity.Constants; @@ -1188,87 +1193,76 @@ public class CourseFactory extends BasicManager { } } } -} - - - -/** -* OLAT - Online Learning and Training<br> -* http://www.olat.org -* <p> -* Licensed under the Apache License, Version 2.0 (the "License"); <br> -* you may not use this file except in compliance with the License.<br> -* You may obtain a copy of the License at -* <p> -* http://www.apache.org/licenses/LICENSE-2.0 -* <p> -* Unless required by applicable law or agreed to in writing,<br> -* software distributed under the License is distributed on an "AS IS" BASIS, <br> -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> -* See the License for the specific language governing permissions and <br> -* limitations under the License. -* <p> -* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> -* University of Zurich, Switzerland. -* <hr> -* <a href="http://www.openolat.org"> -* OpenOLAT - Online Learning and Training</a><br> -* This file has been modified by the OpenOLAT community. Changes are licensed -* under the Apache 2.0 license as the original file. -*/ + + private static class NodeArchiveVisitor implements Visitor { + private File exportPath; + private Locale locale; + private ICourse course; + private String charset; -class NodeArchiveVisitor implements Visitor { - private File exportPath; - private Locale locale; - private ICourse course; - private String charset; + /** + * @param locale + * @param course + * @param exportPath + * @param charset + */ + public NodeArchiveVisitor(Locale locale, ICourse course, File exportPath, String charset) { + this.locale = locale; + this.exportPath = exportPath; + //o_clusterOk by guido: save to hold reference to course inside editor + this.course = course; + this.charset = charset; + } - /** - * @param locale - * @param course - * @param exportPath - * @param charset - */ - public NodeArchiveVisitor(Locale locale, ICourse course, File exportPath, String charset) { - this.locale = locale; - this.exportPath = exportPath; - //o_clusterOk by guido: save to hold reference to course inside editor - this.course = course; - this.charset = charset; - } + /** + * @see org.olat.core.util.tree.Visitor#visit(org.olat.core.util.nodes.INode) + */ + public void visit(INode node) { + CourseNode cn = (CourseNode) node; - /** - * @see org.olat.core.util.tree.Visitor#visit(org.olat.core.util.nodes.INode) - */ - public void visit(INode node) { - CourseNode cn = (CourseNode) node; - cn.archiveNodeData(locale, course, exportPath, charset); + String archiveName = cn.getType() + "_" + + StringHelper.transformDisplayNameToFileSystemName(cn.getShortName()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); + + FileOutputStream fileStream = null; + ZipOutputStream exportStream = null; + try { + File exportFile = new File(exportPath, archiveName); + fileStream = new FileOutputStream(exportFile); + exportStream = new ZipOutputStream(fileStream); + cn.archiveNodeData(locale, course, null, exportStream, charset); + } catch (FileNotFoundException e) { + log.error("", e); + } finally { + IOUtils.closeQuietly(exportStream); + IOUtils.closeQuietly(fileStream); + } + } } -} - -class NodeDeletionVisitor implements Visitor { + + private static class NodeDeletionVisitor implements Visitor { - private ICourse course; + private ICourse course; - /** - * Constructor of the node deletion visitor - * - * @param course - */ - public NodeDeletionVisitor(ICourse course) { - this.course = course; - } + /** + * Constructor of the node deletion visitor + * + * @param course + */ + public NodeDeletionVisitor(ICourse course) { + this.course = course; + } - /** - * Visitor pattern to delete the course nodes - * - * @see org.olat.core.util.tree.Visitor#visit(org.olat.core.util.nodes.INode) - */ - public void visit(INode node) { - CourseNode cNode = (CourseNode) node; - cNode.cleanupOnDelete(course); + /** + * Visitor pattern to delete the course nodes + * + * @see org.olat.core.util.tree.Visitor#visit(org.olat.core.util.nodes.INode) + */ + public void visit(INode node) { + CourseNode cNode = (CourseNode) node; + cNode.cleanupOnDelete(course); + } } - } /** diff --git a/src/main/java/org/olat/course/archiver/ArchiveResource.java b/src/main/java/org/olat/course/archiver/ArchiveResource.java new file mode 100644 index 0000000000000000000000000000000000000000..694fecd6b4415fc82afc1f18ffe72c1a2ff41302 --- /dev/null +++ b/src/main/java/org/olat/course/archiver/ArchiveResource.java @@ -0,0 +1,117 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.archiver; + +import java.io.InputStream; +import java.util.Date; +import java.util.Locale; +import java.util.zip.ZipOutputStream; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.olat.core.gui.media.MediaResource; +import org.olat.core.id.OLATResourceable; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.Formatter; +import org.olat.core.util.StringHelper; +import org.olat.course.CourseFactory; +import org.olat.course.ICourse; +import org.olat.course.nodes.CourseNode; +import org.olat.group.BusinessGroup; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ArchiveResource implements MediaResource { + + private static final OLog log = Tracing.createLoggerFor(ArchiveResource.class); + + private final Locale locale; + private final String encoding = "UTF-8"; + private final BusinessGroup group; + private final CourseNode courseNode; + private final OLATResourceable courseOres; + + public ArchiveResource(CourseNode courseNode, OLATResourceable courseOres, + BusinessGroup group, Locale locale) { + this.group = group; + this.locale = locale; + this.courseNode = courseNode; + this.courseOres = courseOres; + } + + @Override + public String getContentType() { + return "application/zip"; + } + + @Override + public Long getSize() { + return null; + } + + @Override + public InputStream getInputStream() { + return null; + } + + @Override + public Long getLastModified() { + return null; + } + + @Override + public void prepare(HttpServletResponse hres) { + try { + hres.setCharacterEncoding(encoding); + } catch (Exception e) { + log.error("", e); + } + + String label = courseNode.getType() + "_" + + StringHelper.transformDisplayNameToFileSystemName(courseNode.getShortName()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())) + + ".zip"; + String urlEncodedLabel = StringHelper.urlEncodeISO88591(label); + hres.setHeader("Content-Disposition","attachment; filename=\"" + urlEncodedLabel + "\""); + hres.setHeader("Content-Description", urlEncodedLabel); + + ZipOutputStream zout = null; + try { + zout = new ZipOutputStream(hres.getOutputStream()); + zout.setLevel(9); + ICourse course = CourseFactory.loadCourse(courseOres); + courseNode.archiveNodeData(locale, course, group, zout, encoding); + } catch (Exception e) { + log.error("", e); + } finally { + IOUtils.closeQuietly(zout); + } + } + + @Override + public void release() { + // + } +} diff --git a/src/main/java/org/olat/course/archiver/ArchiverMainController.java b/src/main/java/org/olat/course/archiver/ArchiverMainController.java index 0abc8f0a98a8f89acd3c93fe59c280ae3e4edcd9..99db791db44d41db63f5112ada5985d1349443ba 100644 --- a/src/main/java/org/olat/course/archiver/ArchiverMainController.java +++ b/src/main/java/org/olat/course/archiver/ArchiverMainController.java @@ -51,6 +51,7 @@ import org.olat.course.ICourse; import org.olat.course.nodes.DialogCourseNode; import org.olat.course.nodes.FOCourseNode; import org.olat.course.nodes.ProjectBrokerCourseNode; +import org.olat.course.nodes.ScormCourseNode; import org.olat.course.nodes.TACourseNode; import org.olat.course.nodes.WikiCourseNode; import org.olat.ims.qti.export.CourseQTIArchiveController; @@ -72,6 +73,7 @@ public class ArchiverMainController extends MainLayoutBasicController { private static final String CMD_FORUMS = "forums"; private static final String CMD_DIALOGS = "dialogs"; private static final String CMD_WIKIS = "wikis"; + private static final String CMD_SCORM = "scorm"; private IArchiverCallback archiverCallback; @@ -127,7 +129,9 @@ public class ArchiverMainController extends MainLayoutBasicController { if (event.getCommand().equals(MenuTree.COMMAND_TREENODE_CLICKED)) { // goto node in edit mode TreeNode selTreeNode = menuTree.getSelectedNode(); Object cmd = selTreeNode.getUserObject(); - if(cmd instanceof ActionExtension) launchExtensionController(ureq, cmd); + if(cmd instanceof ActionExtension) { + launchExtensionController(ureq, cmd); + } else launchArchiveControllers(ureq, (String)cmd); } } @@ -220,6 +224,13 @@ public class ArchiverMainController extends MainLayoutBasicController { gtn.setAltText(translate("menu.wikis.alt")); root.addChild(gtn); } + if (archiverCallback.mayArchiveWikis()) { + gtn = new GenericTreeNode(); + gtn.setTitle(translate("menu.scorm")); + gtn.setUserObject(CMD_SCORM); + gtn.setAltText(translate("menu.scorm.alt")); + root.addChild(gtn); + } //add extension menues ExtManager extm = ExtManager.getInstance(); @@ -249,40 +260,35 @@ public class ArchiverMainController extends MainLayoutBasicController { private void launchArchiveControllers(UserRequest ureq, String menuCommand) { if (menuCommand.equals(CMD_INDEX)) { main.setContent(intro); - } - else { + } else { removeAsListenerAndDispose(contentCtr); if (menuCommand.equals(CMD_QTIRESULTS)) { - this.contentCtr = new CourseQTIArchiveController(ureq, getWindowControl(), ores); + contentCtr = new CourseQTIArchiveController(ureq, getWindowControl(), ores); main.setContent(contentCtr.getInitialComponent()); - } - else if (menuCommand.equals(CMD_SCOREACCOUNTING)) { - this.contentCtr = new ScoreAccountingArchiveController(ureq, getWindowControl(), ores); + } else if (menuCommand.equals(CMD_SCOREACCOUNTING)) { + contentCtr = new ScoreAccountingArchiveController(ureq, getWindowControl(), ores); main.setContent(contentCtr.getInitialComponent()); - } - else if (menuCommand.equals(CMD_ARCHIVELOGFILES)) { - this.contentCtr = new CourseLogsArchiveController(ureq, getWindowControl(), ores); + } else if (menuCommand.equals(CMD_ARCHIVELOGFILES)) { + contentCtr = new CourseLogsArchiveController(ureq, getWindowControl(), ores); main.setContent(contentCtr.getInitialComponent()); - } - else if (menuCommand.equals(CMD_HANDEDINTASKS)) { //TACourseNode - this.contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new TACourseNode()); + } else if (menuCommand.equals(CMD_HANDEDINTASKS)) { //TACourseNode + contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new TACourseNode()); main.setContent(contentCtr.getInitialComponent()); - } - else if (menuCommand.equals(CMD_PROJECTBROKER)) { - this.contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new ProjectBrokerCourseNode()); + } else if (menuCommand.equals(CMD_PROJECTBROKER)) { + contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new ProjectBrokerCourseNode()); + main.setContent(contentCtr.getInitialComponent()); + } else if (menuCommand.equals(CMD_FORUMS)) { + contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new FOCourseNode()); + main.setContent(contentCtr.getInitialComponent()); + } else if (menuCommand.equals(CMD_DIALOGS)) { + contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new DialogCourseNode()); + main.setContent(contentCtr.getInitialComponent()); + } else if (menuCommand.equals(CMD_WIKIS)) { + contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new WikiCourseNode()); + main.setContent(contentCtr.getInitialComponent()); + } else if (menuCommand.equals(CMD_SCORM)) { + contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new ScormCourseNode()); main.setContent(contentCtr.getInitialComponent()); - } - else if (menuCommand.equals(CMD_FORUMS)) { - this.contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new FOCourseNode()); - main.setContent(contentCtr.getInitialComponent()); - } - else if (menuCommand.equals(CMD_DIALOGS)) { - this.contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new DialogCourseNode()); - main.setContent(contentCtr.getInitialComponent()); - } - else if (menuCommand.equals(CMD_WIKIS)) { - this.contentCtr = new GenericArchiveController(ureq, getWindowControl(), ores, new WikiCourseNode()); - main.setContent(contentCtr.getInitialComponent()); } listenTo(contentCtr); } diff --git a/src/main/java/org/olat/course/archiver/ChooseGroupController.java b/src/main/java/org/olat/course/archiver/ChooseGroupController.java new file mode 100644 index 0000000000000000000000000000000000000000..dec685e676c1e69a2fdf8d62b94a60de4d8835bf --- /dev/null +++ b/src/main/java/org/olat/course/archiver/ChooseGroupController.java @@ -0,0 +1,108 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.archiver; + +import java.util.List; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.olat.course.nodes.CourseNode; +import org.olat.group.BusinessGroup; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ChooseGroupController extends FormBasicController { + + private final CourseNode courseNode; + private final List<BusinessGroup> relatedGroups; + private SingleSelection selectGroupEl; + + public ChooseGroupController(UserRequest ureq, WindowControl wControl, + CourseNode courseNode, List<BusinessGroup> relatedGroups) { + super(ureq, wControl); + this.courseNode = courseNode; + this.relatedGroups = relatedGroups; + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormDescription("select.group.desc"); + + String[] theKeys = new String[1 + relatedGroups.size()]; + theKeys[0] = "all"; + String[] theValues = new String[1 + relatedGroups.size()]; + theValues[0] = translate("select.group.all"); + for(int i=0; i<relatedGroups.size(); i++) { + theKeys[i+1] = Integer.toString(i); + theValues[i+1] = StringHelper.escapeHtml(relatedGroups.get(i).getName()); + } + selectGroupEl = uifactory.addDropdownSingleselect("select.group", formLayout, theKeys, theValues, null); + + FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator()); + formLayout.add(buttonLayout); + buttonLayout.setRootForm(mainForm); + uifactory.addFormSubmitButton("ok", buttonLayout); + uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl()); + } + + @Override + protected void doDispose() { + // + } + + public BusinessGroup getSelectedGroup() { + if(!selectGroupEl.isOneSelected() || selectGroupEl.isSelected(0)) { + return null; + } + String key = selectGroupEl.getSelectedKey(); + if(StringHelper.isLong(key)) { + int pos = Integer.parseInt(key); + if(pos >= 0 && pos <relatedGroups.size()) { + return relatedGroups.get(pos); + } + } + return null; + } + + public CourseNode getCourseNode() { + return courseNode; + } + + @Override + protected void formOK(UserRequest ureq) { + fireEvent(ureq, Event.DONE_EVENT); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/archiver/CourseForumsArchiveController.java b/src/main/java/org/olat/course/archiver/CourseForumsArchiveController.java deleted file mode 100644 index 51c642c0bd66c4bf6604eac8a9299485f00da85c..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/course/archiver/CourseForumsArchiveController.java +++ /dev/null @@ -1,230 +0,0 @@ -/** -* OLAT - Online Learning and Training<br> -* http://www.olat.org -* <p> -* Licensed under the Apache License, Version 2.0 (the "License"); <br> -* you may not use this file except in compliance with the License.<br> -* You may obtain a copy of the License at -* <p> -* http://www.apache.org/licenses/LICENSE-2.0 -* <p> -* Unless required by applicable law or agreed to in writing,<br> -* software distributed under the License is distributed on an "AS IS" BASIS, <br> -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> -* See the License for the specific language governing permissions and <br> -* limitations under the License. -* <p> -* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> -* University of Zurich, Switzerland. -* <hr> -* <a href="http://www.openolat.org"> -* OpenOLAT - Online Learning and Training</a><br> -* This file has been modified by the OpenOLAT community. Changes are licensed -* under the Apache 2.0 license as the original file. -*/ - -package org.olat.course.archiver; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.components.Component; -import org.olat.core.gui.components.panel.Panel; -import org.olat.core.gui.components.table.ColumnDescriptor; -import org.olat.core.gui.components.table.CustomRenderColumnDescriptor; -import org.olat.core.gui.components.table.DefaultColumnDescriptor; -import org.olat.core.gui.components.table.Table; -import org.olat.core.gui.components.table.TableController; -import org.olat.core.gui.components.table.TableEvent; -import org.olat.core.gui.components.table.TableGuiConfiguration; -import org.olat.core.gui.components.velocity.VelocityContainer; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.Event; -import org.olat.core.gui.control.WindowControl; -import org.olat.core.gui.control.controller.BasicController; -import org.olat.core.id.OLATResourceable; -import org.olat.course.CourseFactory; -import org.olat.course.ICourse; -import org.olat.course.assessment.AssessmentHelper; -import org.olat.course.assessment.IndentedNodeRenderer; -import org.olat.course.assessment.NodeTableDataModel; -import org.olat.course.nodes.CourseNode; -import org.olat.course.nodes.FOCourseNode; -import org.olat.user.UserManager; - -/** - * @author schneider - * Comment: - * Archives the user selected forum of a course to the personal folder of this user. - */ -public class CourseForumsArchiveController extends BasicController { - private static final String CMD_SELECT_NODE = "cmd.select.node"; - - private Panel main; - private VelocityContainer nodeChoose; - private NodeTableDataModel nodeTableModel; - private TableController nodeListCtr; - private FOCourseNode currentCourseNode; - - private OLATResourceable ores; - - /** - * Constructor for the assessment tool controller. - * @param ureq - * @param wControl - * @param course - */ - public CourseForumsArchiveController(UserRequest ureq, WindowControl wControl, OLATResourceable ores) { - super(ureq, wControl); - this.ores = ores; - main = new Panel("main"); - nodeChoose = createVelocityContainer("fonodechoose"); - doNodeChoose(ureq); - putInitialPanel(main); - } - - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, - * org.olat.core.gui.components.Component, org.olat.core.gui.control.Event) - */ - public void event(UserRequest ureq, Component source, Event event) { - //no interesting events - } - - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, - * org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event) - */ - public void event(UserRequest ureq, Controller source, Event event) { - if (source == nodeListCtr) { - if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) { - TableEvent te = (TableEvent) event; - String actionid = te.getActionId(); - if (actionid.equals(CMD_SELECT_NODE)) { - int rowid = te.getRowId(); - Map nodeData = (Map) nodeTableModel.getObject(rowid); - ICourse course = CourseFactory.loadCourse(ores); - CourseNode node = course.getRunStructure().getNode((String) nodeData.get(AssessmentHelper.KEY_IDENTIFYER)); - this.currentCourseNode = (FOCourseNode) node; - // cast should be save, only ta course nodes nodes are selectable - boolean successfullyArchived = archiveForumNode(ureq); - if (successfullyArchived) { - showInfo("archive.fo.successfully"); - } else { - showWarning("archive.fo.notsuccessfully"); - } - } - } - } - } - - /** - * - * @param ureq - */ - private void doNodeChoose(UserRequest ureq){ - //table configuraton - TableGuiConfiguration tableConfig = new TableGuiConfiguration(); - tableConfig.setTableEmptyMessage(translate("fonodesoverview.nonodes")); - tableConfig.setDownloadOffered(false); - tableConfig.setColumnMovingOffered(false); - tableConfig.setSortingEnabled(false); - tableConfig.setDisplayTableHeader(true); - tableConfig.setDisplayRowCount(false); - tableConfig.setPageingEnabled(false); - - removeAsListenerAndDispose(nodeListCtr); - nodeListCtr = new TableController(tableConfig, ureq, getWindowControl(), getTranslator()); - listenTo(nodeListCtr); - - // table columns - nodeListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor("table.header.node", 0, - null, ureq.getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, new IndentedNodeRenderer())); - nodeListCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.action.select", 1, - CMD_SELECT_NODE, ureq.getLocale())); - - // get list of course node data and populate table data model - ICourse course = CourseFactory.loadCourse(ores); - CourseNode rootNode = course.getRunStructure().getRootNode(); - List nodesTableObjectArrayList = addForumNodesAndParentsToList(0, rootNode); - - // only populate data model if data available - if (nodesTableObjectArrayList == null) { - nodeChoose.contextPut("hasForumNodes", Boolean.FALSE); - } else { - nodeChoose.contextPut("hasForumNodes", Boolean.TRUE); - nodeTableModel = new NodeTableDataModel(nodesTableObjectArrayList, getTranslator()); - nodeListCtr.setTableDataModel(nodeTableModel); - nodeChoose.put("fonodeTable", nodeListCtr.getInitialComponent()); - } - - // set main content to nodechoose, do not use wrapper - main.setContent(nodeChoose); - - } - - /** - * Recursive method that adds forum nodes and all its parents to a list - * @param recursionLevel - * @param courseNode - * @return A list of maps containing the node data - */ - @SuppressWarnings("unchecked") - private List addForumNodesAndParentsToList(int recursionLevel, CourseNode courseNode) { - // 1) Get list of children data using recursion of this method - List childrenData = new ArrayList(); - for (int i = 0; i < courseNode.getChildCount(); i++) { - CourseNode child = (CourseNode) courseNode.getChildAt(i); - List childData = addForumNodesAndParentsToList( (recursionLevel + 1), child); - if (childData != null) - childrenData.addAll(childData); - } - - if (childrenData.size() > 0 || courseNode instanceof FOCourseNode) { - // Store node data in map. This map array serves as data model for - // the tasks overview table. Leave user data empty since not used in - // this table. (use only node data) - Map nodeData = new HashMap(); - // indent - nodeData.put(AssessmentHelper.KEY_INDENT, new Integer(recursionLevel)); - // course node data - nodeData.put(AssessmentHelper.KEY_TYPE, courseNode.getType()); - nodeData.put(AssessmentHelper.KEY_TITLE_SHORT, courseNode.getShortTitle()); - nodeData.put(AssessmentHelper.KEY_TITLE_LONG, courseNode.getLongTitle()); - nodeData.put(AssessmentHelper.KEY_IDENTIFYER, courseNode.getIdent()); - - if (courseNode instanceof FOCourseNode){ - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.TRUE); - } - else { - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.FALSE); - } - - List nodeAndChildren = new ArrayList(); - nodeAndChildren.add(nodeData); - - nodeAndChildren.addAll(childrenData); - return nodeAndChildren; - } - return null; - } - - private boolean archiveForumNode(UserRequest ureq){ - ICourse course = CourseFactory.loadCourse(ores); - File exportDir = CourseFactory.getOrCreateDataExportDirectory(ureq.getIdentity(), course.getCourseTitle()); - UserManager um = UserManager.getInstance(); - String charset = um.getUserCharset(ureq.getIdentity()); - return currentCourseNode.archiveNodeData(ureq.getLocale(), course, exportDir, charset); - } - - /** - * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) - */ - protected void doDispose() { - // - } -} diff --git a/src/main/java/org/olat/course/archiver/GenericArchiveController.java b/src/main/java/org/olat/course/archiver/GenericArchiveController.java index c4c091212d34de2368a4bea5fa66f995587dd749..38993f05c671b04053dc79c58bb67635c75ef49b 100644 --- a/src/main/java/org/olat/course/archiver/GenericArchiveController.java +++ b/src/main/java/org/olat/course/archiver/GenericArchiveController.java @@ -25,11 +25,8 @@ package org.olat.course.archiver; -import java.io.File; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; @@ -46,14 +43,17 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.id.OLATResourceable; import org.olat.course.CourseFactory; import org.olat.course.ICourse; -import org.olat.course.assessment.AssessmentHelper; import org.olat.course.assessment.IndentedNodeRenderer; import org.olat.course.assessment.NodeTableDataModel; +import org.olat.course.assessment.NodeTableRow; +import org.olat.course.groupsandrights.CourseGroupManager; import org.olat.course.nodes.CourseNode; -import org.olat.user.UserManager; +import org.olat.course.nodes.TACourseNode; +import org.olat.group.BusinessGroup; /** * @author schnider Comment: Archives the User selected wiki's to the personal @@ -62,13 +62,15 @@ import org.olat.user.UserManager; public class GenericArchiveController extends BasicController { private static final String CMD_SELECT_NODE = "cmd.select.node"; - private Panel main; - private VelocityContainer nodeChoose; - private NodeTableDataModel nodeTableModel; + + private final Panel main; private TableController nodeListCtr; - protected CourseNode currentCourseNode; - private CourseNode nodeType; - protected OLATResourceable ores; + private NodeTableDataModel nodeTableModel; + private CloseableModalController cmc; + private ChooseGroupController chooseGroupCtrl; + + private final CourseNode nodeType; + private final OLATResourceable ores; /** * Constructor for the assessment tool controller. @@ -82,52 +84,57 @@ public class GenericArchiveController extends BasicController { this.ores = ores; this.nodeType = nodeType; + main = new Panel("main"); - nodeChoose = createVelocityContainer("nodechoose"); + VelocityContainer nodeChoose = createVelocityContainer("nodechoose"); nodeChoose.contextPut("nodeType",nodeType.getType()); - doNodeChoose(ureq); + doNodeChoose(ureq, nodeChoose); putInitialPanel(main); } - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, - * org.olat.core.gui.components.Component, - * org.olat.core.gui.control.Event) - */ + @Override public void event(UserRequest ureq, Component source, Event event) { // no interesting events } - /** - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, - * org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event) - */ + @Override public void event(UserRequest ureq, Controller source, Event event) { if (source == nodeListCtr) { if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) { - ICourse course = CourseFactory.loadCourse(ores); - TableEvent te = (TableEvent) event; + TableEvent te = (TableEvent)event; String actionid = te.getActionId(); if (actionid.equals(CMD_SELECT_NODE)) { - int rowid = te.getRowId(); - Map nodeData = (Map) nodeTableModel.getObject(rowid); - CourseNode node = course.getRunStructure().getNode((String) nodeData.get(AssessmentHelper.KEY_IDENTIFYER)); - this.currentCourseNode = node; - boolean successfullyArchived = archiveNode(ureq); - if(successfullyArchived) { - showInfo("archive."+nodeType.getType()+".successfully"); - } else { - showWarning("archive."+nodeType.getType()+".notsuccessfully"); - } + NodeTableRow nodeData = nodeTableModel.getObject(te.getRowId()); + doSelectNode(ureq, nodeData); } } + } else if(source == chooseGroupCtrl) { + cmc.deactivate(); + CourseNode courseNode = chooseGroupCtrl.getCourseNode(); + BusinessGroup group = chooseGroupCtrl.getSelectedGroup(); + cleanUpPopups(); + if(Event.DONE_EVENT == event) { + archiveNode(ureq, courseNode, group); + } + } else if (source == cmc) { + cleanUpPopups(); } } + + /** + * Aggressive clean up all popup controllers + */ + protected void cleanUpPopups() { + removeAsListenerAndDispose(chooseGroupCtrl); + removeAsListenerAndDispose(cmc); + chooseGroupCtrl = null; + cmc = null; + } /** * @param ureq */ - private void doNodeChoose(UserRequest ureq) { + private void doNodeChoose(UserRequest ureq, VelocityContainer nodeChoose) { // table configuraton TableGuiConfiguration tableConfig = new TableGuiConfiguration(); tableConfig.setTableEmptyMessage(translate("nodesoverview.nonodes")); @@ -143,14 +150,14 @@ public class GenericArchiveController extends BasicController { listenTo(nodeListCtr); // table columns - nodeListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor("table.header.node", 0, null, ureq.getLocale(), + nodeListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor("table.header.node", 0, null, getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, new IndentedNodeRenderer())); - nodeListCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.action.select", 1, CMD_SELECT_NODE, ureq.getLocale())); + nodeListCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.action.select", 1, CMD_SELECT_NODE, getLocale())); // get list of course node data and populate table data model ICourse course = CourseFactory.loadCourse(ores); CourseNode rootNode = course.getRunStructure().getRootNode(); - List nodesTableObjectArrayList = addNodesAndParentsToList(0, rootNode); + List<NodeTableRow> nodesTableObjectArrayList = addNodesAndParentsToList(0, rootNode); // only populate data model if data available if (nodesTableObjectArrayList == null) { @@ -164,7 +171,6 @@ public class GenericArchiveController extends BasicController { // set main content to nodechoose, do not use wrapper main.setContent(nodeChoose); - } /** @@ -174,52 +180,62 @@ public class GenericArchiveController extends BasicController { * @param courseNode * @return A list of maps containing the node data */ - @SuppressWarnings("unchecked") - private List addNodesAndParentsToList(int recursionLevel, CourseNode courseNode) { + private List<NodeTableRow> addNodesAndParentsToList(int recursionLevel, CourseNode courseNode) { // 1) Get list of children data using recursion of this method - List childrenData = new ArrayList(); + List<NodeTableRow> childrenData = new ArrayList<>(); for (int i = 0; i < courseNode.getChildCount(); i++) { CourseNode child = (CourseNode) courseNode.getChildAt(i); - List childData = addNodesAndParentsToList((recursionLevel + 1), child); - if (childData != null) childrenData.addAll(childData); + List<NodeTableRow> childData = addNodesAndParentsToList((recursionLevel + 1), child); + if (childData != null) { + childrenData.addAll(childData); + } } - String nodent = nodeType.getType(); if (childrenData.size() > 0 || courseNode.getType().equals(nodeType.getType())) { // Store node data in map. This map array serves as data model for // the tasks overview table. Leave user data empty since not used in // this table. (use only node data) - Map nodeData = new HashMap(); - // indent - nodeData.put(AssessmentHelper.KEY_INDENT, new Integer(recursionLevel)); - // course node data - nodeData.put(AssessmentHelper.KEY_TYPE, courseNode.getType()); - nodeData.put(AssessmentHelper.KEY_TITLE_SHORT, courseNode.getShortTitle()); - nodeData.put(AssessmentHelper.KEY_TITLE_LONG, courseNode.getLongTitle()); - nodeData.put(AssessmentHelper.KEY_IDENTIFYER, courseNode.getIdent()); - - if (courseNode.getType().equals(nodeType.getType())) { - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.TRUE); - } else { - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.FALSE); - } - - List nodeAndChildren = new ArrayList(); + NodeTableRow nodeData = new NodeTableRow(new Integer(recursionLevel), courseNode); + nodeData.setSelectable(courseNode.getType().equals(nodeType.getType())); + + List<NodeTableRow> nodeAndChildren = new ArrayList<>(); nodeAndChildren.add(nodeData); - nodeAndChildren.addAll(childrenData); return nodeAndChildren; } return null; } - - protected boolean archiveNode(UserRequest ureq) { + + private void doSelectNode(UserRequest ureq, NodeTableRow nodeData) { ICourse course = CourseFactory.loadCourse(ores); - File exportDir = CourseFactory.getOrCreateDataExportDirectory(ureq.getIdentity(), course.getCourseTitle()); - UserManager um = UserManager.getInstance(); - String charset = um.getUserCharset(ureq.getIdentity()); - boolean successfullyArchived = currentCourseNode.archiveNodeData(ureq.getLocale(), course, exportDir, charset); - return successfullyArchived; + CourseNode node = course.getRunStructure().getNode(nodeData.getIdent()); + //some node can limit the archive to a business group + if(node instanceof TACourseNode) { + CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager(); + List<BusinessGroup> relatedGroups = cgm.getAllBusinessGroups(); + if(relatedGroups.isEmpty()) { + archiveNode(ureq, node, null); + } else { + doSelectBusinessGroup(ureq, node, relatedGroups); + } + } else { + archiveNode(ureq, node, null); + } + } + + private void doSelectBusinessGroup(UserRequest ureq, CourseNode node, List<BusinessGroup> relatedGroups) { + chooseGroupCtrl = new ChooseGroupController(ureq, getWindowControl(), node, relatedGroups); + listenTo(chooseGroupCtrl); + cmc = new CloseableModalController(getWindowControl(), translate("close"), chooseGroupCtrl.getInitialComponent(), + true, translate("select.group")); + cmc.activate(); + listenTo(cmc); + } + + private void archiveNode(UserRequest ureq, CourseNode node, BusinessGroup group) { + ArchiveResource aResource = new ArchiveResource(node, ores, group, getLocale()); + ureq.getDispatchResult().setResultingMediaResource(aResource); + showInfo("archive." + nodeType.getType() + ".successfully"); } /** @@ -228,5 +244,4 @@ public class GenericArchiveController extends BasicController { protected void doDispose() { // } - -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/archiver/ScoreAccountingArchiveController.java b/src/main/java/org/olat/course/archiver/ScoreAccountingArchiveController.java index 4d73b384b464115ee824cc834b9135686d261f0f..295ed6f244ef1cf0430f09c6bc1ca9186dd1084e 100644 --- a/src/main/java/org/olat/course/archiver/ScoreAccountingArchiveController.java +++ b/src/main/java/org/olat/course/archiver/ScoreAccountingArchiveController.java @@ -34,17 +34,14 @@ import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.panel.Panel; import org.olat.core.gui.components.velocity.VelocityContainer; -import org.olat.core.gui.control.DefaultController; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.media.FileMediaResource; import org.olat.core.gui.media.MediaResource; -import org.olat.core.gui.translator.PackageTranslator; -import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.util.ExportUtil; -import org.olat.core.util.Util; import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.course.nodes.AssessableCourseNode; @@ -56,15 +53,12 @@ import org.olat.user.UserManager; * Initial Date: Sep 23, 2004 * @author gnaegi */ -public class ScoreAccountingArchiveController extends DefaultController { - private static final String PACKAGE = Util.getPackageName(ScoreAccountingArchiveController.class); - private static final String VELOCITY_ROOT = Util.getPackageVelocityRoot(PACKAGE); +public class ScoreAccountingArchiveController extends BasicController { private OLATResourceable ores; private Panel myPanel; private VelocityContainer myContent; private VelocityContainer vcFeedback; - private Translator t; private Link startButton, downloadButton; /** @@ -73,19 +67,13 @@ public class ScoreAccountingArchiveController extends DefaultController { * @param course */ public ScoreAccountingArchiveController(UserRequest ureq, WindowControl wControl, OLATResourceable ores) { - super(wControl); + super(ureq, wControl); this.ores = ores; - this.t = new PackageTranslator(PACKAGE, ureq.getLocale()); - - this.myPanel = new Panel("myPanel"); - myPanel.addListener(this); - - myContent = new VelocityContainer("myContent", VELOCITY_ROOT + "/start.html", t, this); + myPanel = putInitialPanel(myPanel); + myContent = createVelocityContainer("start"); startButton = LinkFactory.createButtonSmall("cmd.start", myContent, this); - myPanel.setContent(myContent); - setInitialComponent(myPanel); } /** @@ -94,28 +82,7 @@ public class ScoreAccountingArchiveController extends DefaultController { */ public void event(UserRequest ureq, Component source, Event event) { if (source == startButton) { - ICourse course = CourseFactory.loadCourse(ores); - List<Identity> users = ScoreAccountingHelper.loadUsers(course.getCourseEnvironment()); - List<AssessableCourseNode> nodes = ScoreAccountingHelper.loadAssessableNodes(course.getCourseEnvironment()); - - String result = ScoreAccountingHelper.createCourseResultsOverviewTable(users, nodes, course, ureq.getLocale()); - - String courseTitle = course.getCourseTitle(); - - String fileName = ExportUtil.createFileNameWithTimeStamp(courseTitle, "xls"); - // location for data export - File exportDirectory = CourseFactory.getOrCreateDataExportDirectory(ureq.getIdentity(), courseTitle); - // the user's charset - UserManager um = UserManager.getInstance(); - String charset = um.getUserCharset(ureq.getIdentity()); - - File downloadFile = ExportUtil.writeContentToFile(fileName, result, exportDirectory, charset); - - vcFeedback = new VelocityContainer("feedback", VELOCITY_ROOT + "/feedback.html", t, this); - vcFeedback.contextPut("body", vcFeedback.getTranslator().translate("course.res.feedback", new String[] { fileName })); - downloadButton = LinkFactory.createButtonSmall("cmd.download", vcFeedback, this); - downloadButton.setUserObject(downloadFile); - myPanel.setContent(vcFeedback); + doStartExport(); } else if(source == downloadButton) { File file = (File)downloadButton.getUserObject(); if(file != null) { @@ -124,6 +91,31 @@ public class ScoreAccountingArchiveController extends DefaultController { } } } + + private void doStartExport() { + ICourse course = CourseFactory.loadCourse(ores); + List<Identity> users = ScoreAccountingHelper.loadUsers(course.getCourseEnvironment()); + List<AssessableCourseNode> nodes = ScoreAccountingHelper.loadAssessableNodes(course.getCourseEnvironment()); + + String result = ScoreAccountingHelper.createCourseResultsOverviewTable(users, nodes, course, getLocale()); + + String courseTitle = course.getCourseTitle(); + + String fileName = ExportUtil.createFileNameWithTimeStamp(courseTitle, "xls"); + // location for data export + File exportDirectory = CourseFactory.getOrCreateDataExportDirectory(getIdentity(), courseTitle); + // the user's charset + UserManager um = UserManager.getInstance(); + String charset = um.getUserCharset(getIdentity()); + + File downloadFile = ExportUtil.writeContentToFile(fileName, result, exportDirectory, charset); + + vcFeedback = createVelocityContainer("feedback"); + vcFeedback.contextPut("body", translate("course.res.feedback", new String[] { fileName })); + downloadButton = LinkFactory.createButtonSmall("cmd.download", vcFeedback, this); + downloadButton.setUserObject(downloadFile); + myPanel.setContent(vcFeedback); + } /** * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) diff --git a/src/main/java/org/olat/course/archiver/ScoreAccountingHelper.java b/src/main/java/org/olat/course/archiver/ScoreAccountingHelper.java index 1d652a8a439c454edba1d946ae7a7aa7b4561c6d..a42d017a5506ecfc9f6be09dc3f3d64ecf273a91 100644 --- a/src/main/java/org/olat/course/archiver/ScoreAccountingHelper.java +++ b/src/main/java/org/olat/course/archiver/ScoreAccountingHelper.java @@ -376,7 +376,6 @@ public class ScoreAccountingHelper { * @param courseEnv * @return The list of identities from this course */ - //fxdiff VCRP-1,2: access control of resources public static List<Identity> loadUsers(CourseEnvironment courseEnv) { CourseGroupManager gm = courseEnv.getCourseGroupManager(); BaseSecurity securityManager = BaseSecurityManager.getInstance(); @@ -399,6 +398,11 @@ public class ScoreAccountingHelper { return userList; } + public static List<Identity> loadUsers(BusinessGroup group) { + BaseSecurity securityManager = BaseSecurityManager.getInstance(); + return securityManager.getIdentitiesOfSecurityGroup(group.getPartipiciantGroup()); + } + /** * Load all nodes which are assessable * diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_ar.properties index 08b6cf782c75acf7525ca25a89ccd2c03c96552d..43ce12308a4937a018141781e95e8c65ec50a7eb 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_ar.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_ar.properties @@ -103,16 +103,20 @@ menu.scoreaccounting=\u0646\u062A\u0627\u0626\u062C \u0627\u0644\u0645\u0642\u06 menu.scoreaccounting.alt=\u062D\u0641\u0638 \u0627\u0644\u0646\u062A\u0627\u0626\u062C \u0627\u0644\u0646\u0647\u0627\u0626\u064A\u0629 \u0645\u0646 \u0627\u0644\u0627\u062E\u062A\u0628\u0627\u0631\u0627\u062A \u0648\u0627\u0644\u062A\u0642\u064A\u064A\u0645\u0627\u062A \u0648\u0627\u0644\u0645\u0647\u0627\u0645 menu.wikis=\u0627\u0644\u0648\u064A\u0643\u0649 menu.wikis.alt=\u0623\u0631\u0634\u064A\u0641 \u0627\u0644\u0648\u064A\u0643\u0649 +menu.scorm=\u0646\u062A\u0627\u0626\u062C \u0627\u0633\u0643\u0648\u0631\u0645 +menu.scorm.alt=\u0646\u062A\u0627\u0626\u062C \u0633\u0643\u0648\u0631\u0645 nodechoose.intro.dialog=\u0627\u062E\u062A\u0631 \u0639\u0646\u0635\u0631 \u0627\u0644\u0645\u0642\u0631\u0631 \u062D\u062A\u0649 \u064A\u062A\u0645 \u062D\u0641\u0638 \u0645\u0644\u0641 \u0627\u0644\u062F\u062E\u0648\u0644 \u0627\u0644\u062E\u0627\u0635\u0629 \u0628\u0647\u060C \u0648\u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0627\u0644\u062D\u0648\u0627\u0631 \u0627\u0644\u0645\u062D\u0641\u0648\u0638 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649\u060C \u0642\u0633\u0645 \u0627\u0644\u062E\u0627\u0635/\u0627\u0644\u0623\u0631\u0634\u064A\u0641/[\u0627\u0633\u0645 \u0627\u0644\u0645\u0642\u0631\u0631]/\u0645\u0644\u0641 \u0627\u0644\u062D\u0648\u0627\u0631_\u0645\u0646\u062A\u062F\u0649. nodechoose.intro.fo=\u0627\u062E\u062A\u0631 \u0639\u0646\u0635\u0631 \u0627\u0644\u0645\u0642\u0631\u0631 \u062D\u062A\u0649 \u064A\u062A\u0645 \u062D\u0641\u0638 \u0627\u0644\u0645\u0646\u062A\u062F\u0649 \u0627\u0644\u062E\u0627\u0635 \u0628\u0647\u060C \u0648\u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0627\u0644\u0645\u0646\u062A\u062F\u0649 \u0627\u0644\u0645\u062D\u0641\u0648\u0638 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649\u060C \u0642\u0633\u0645 \u0627\u0644\u062E\u0627\u0635/\u0627\u0644\u0623\u0631\u0634\u064A\u0641/[\u0627\u0633\u0645 \u0627\u0644\u0645\u0642\u0631\u0631]/\u0645\u0646\u062A\u062F\u0649_\u0645\u0646\u062A\u062F\u0649. nodechoose.intro.projectbroker=\u0627\u062E\u062A\u0631 \u0639\u0646\u0635\u0631 \u0627\u0644\u0645\u0642\u0631\u0631 \u062D\u062A\u0649 \u064A\u062A\u0645 \u062D\u0641\u0638 \u0645\u0648\u0627\u0636\u064A\u0639 \u0627\u0644\u062A\u0628\u0627\u062F\u0644 \u0627\u0644\u062E\u0627\u0635 \u0628\u0647\u060C \u0648\u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0645\u0648\u0627\u0636\u064A\u0639 \u0627\u0644\u062A\u0628\u0627\u062F\u0644 \u0627\u0644\u0645\u062D\u0641\u0648\u0638\u0629 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649\u060C \u0642\u0633\u0645 \u0627\u0644\u062E\u0627\u0635/\u0627\u0644\u0623\u0631\u0634\u064A\u0641/[\u0627\u0633\u0645 \u0627\u0644\u0645\u0642\u0631\u0631]/\u0645\u0648\u0636\u0648\u0639 \u0627\u0644\u062A\u0628\u0627\u062F\u0644. nodechoose.intro.ta=\u0627\u062E\u062A\u0631 \u0639\u0646\u0635\u0631 \u0627\u0644\u0645\u0642\u0631\u0631 \u062D\u062A\u0649 \u064A\u062A\u0645 \u062D\u0641\u0638 \u0627\u0644\u0645\u0647\u0627\u0645/\u0627\u0644\u062D\u0644\u0648\u0644 \u0627\u0644\u062E\u0627\u0635\u0629 \u0628\u0647\u060C \u0648\u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0627\u0644\u0645\u0647\u0627\u0645/\u0627\u0644\u062D\u0644\u0648\u0644 \u0627\u0644\u0645\u062D\u0641\u0648\u0638\u0629 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649\u060C \u0642\u0633\u0645 \u0627\u0644\u062E\u0627\u0635/\u0627\u0644\u0623\u0631\u0634\u064A\u0641/[\u0627\u0633\u0645 \u0627\u0644\u0645\u0642\u0631\u0631]/\u0627\u0644\u0645\u0647\u0645\u0629_[\u0627\u0633\u0645 \u0639\u0646\u0635\u0631 \u0627\u0644\u0645\u0642\u0631\u0631] \u0643\u0645\u0644\u0641 \u0645\u0636\u063A\u0648\u0637. nodechoose.intro.wiki=\u0627\u062E\u062A\u0631 \u0639\u0646\u0635\u0631 \u0627\u0644\u0645\u0642\u0631\u0631 \u062D\u062A\u0649 \u064A\u062A\u0645 \u062D\u0641\u0638 \u0627\u0644\u0648\u064A\u0643\u0649 \u0627\u0644\u062E\u0627\u0635 \u0628\u0647\u060C \u0648\u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0627\u0644\u0648\u064A\u0643\u0649 \u0627\u0644\u0645\u062D\u0641\u0648\u0638 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649\u060C \u0642\u0633\u0645 \u0627\u0644\u062E\u0627\u0635/\u0627\u0644\u0623\u0631\u0634\u064A\u0641/[\u0627\u0633\u0645 \u0627\u0644\u0645\u0642\u0631\u0631]/\u0627\u0644\u0648\u064A\u0643\u0649_[\u0627\u0644\u062A\u0627\u0631\u064A\u062E\u064D]. +nodechoose.intro.scorm=\u0641\u0649 \u0627\u0644\u062D\u0648\u0627\u0631 \u0627\u0644\u062A\u0627\u0644\u0649 \u0627\u062E\u062A\u0631 \u0639\u0646\u0635\u0631 \u0627\u0633\u0643\u0648\u0631\u0645 \u0627\u0644\u0630\u0649 \u064A\u062A\u0645 \u062A\u0642\u064A\u064A\u0645\u0647\u060C \u0648\u0627\u0644\u0646\u062A\u0627\u0626\u062C \u0627\u0644\u0645\u062D\u0641\u0648\u0638\u0629 \u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u064A\u0647\u0627 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649. overview.nonodes.dialog=\u0647\u0630\u0627 \u0627\u0644\u0645\u0642\u0631\u0631 \u0644\u0627 \u064A\u062D\u062A\u0648\u0649 \u0639\u0644\u0649 \u0623\u0649 \u0645\u0644\u0641 \u062D\u0648\u0627\u0631\u0627\u062A. overview.nonodes.fo=\u0647\u0630\u0627 \u0627\u0644\u0645\u0642\u0631\u0631 \u0644\u0627 \u064A\u062D\u062A\u0648\u0649 \u0639\u0644\u0649 \u0623\u064A\u0629 \u0645\u0646\u062A\u062F\u064A\u0627\u062A. overview.nonodes.projectbroker=\u0647\u0630\u0627 \u0627\u0644\u0645\u0642\u0631\u0631 \u0644\u0627 \u064A\u062A\u0636\u0645\u0646 \u0623\u0649 \u0645\u0648\u0636\u0648\u0639\u0627\u062A \u0644\u0644\u062A\u0628\u0627\u062F\u0644. overview.nonodes.ta=\u0647\u0630\u0627 \u0627\u0644\u0645\u0642\u0631\u0631 \u0644\u0627 \u064A\u062D\u062A\u0648\u0649 \u0639\u0644\u0649 \u0623\u064A\u0629 \u0639\u0646\u0627\u0635\u0631 \u0645\u0647\u0627\u0645. overview.nonodes.wiki=\u0647\u0630\u0627 \u0627\u0644\u0645\u0642\u0631\u0631 \u0644\u0627 \u064A\u062D\u062A\u0648\u0649 \u0639\u0644\u0649 \u0623\u0649 \u0648\u064A\u0643\u0649. +overview.nonodes.scorm=\u0644\u0627 \u064A\u062D\u062A\u0648\u0649 \u0647\u0630\u0627 \u0627\u0644\u0645\u0642\u0631\u0631 \u0639\u0644\u0649 \u0623\u0649 \u0639\u0646\u0635\u0631 \u0627\u0633\u0643\u0648\u0631\u0645. projectbroker=\u062A\u0628\u0627\u062F\u0644 \u0645\u0648\u0636\u0648\u0639 readme=\u062A\u0644\u0645\u064A\u062D\r\n\r\n\u0644\u0643\u0648\u0646\u0643 \u0645\u0633\u062A\u0641\u064A\u062F \u0645\u0646 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0645\u062D\u0641\u0648\u0638\u0629 \u0641\u0623\u0646\u062A \u0645\u0633\u0624\u0648\u0644\u0627 \u0639\u0646 \u062D\u0642\u064A\u0642\u0629 \u0623\u0646 \u0647\u0630\u0647 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0644\u0627 \u062A\u0633\u062A\u062E\u062F\u0645 \u0625\u0644\u0627 \u0639\u0644\u0649 \u0627\u0644\u0646\u062D\u0648 \u0627\u0644\u0645\u0633\u0645\u0648\u062D \u0628\u0647.\r\n\r\n\r\n- \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0634\u062E\u0635\u064A\u0629 \u0631\u0628\u0645\u0627 \u062A\u0633\u062A\u062E\u062F\u0645 \u0644\u0623\u063A\u0631\u0627\u0636 \u0627\u0644\u0628\u062D\u062B \u0648\u0627\u0644\u062A\u062F\u0631\u064A\u0633 \u0648\u0627\u0644\u062A\u0642\u064A\u064A\u0645 \u0641\u0642\u0637 \u0641\u0649 \u0645\u0627 \u064A\u062A\u0635\u0644 \u0628\u0642\u0636\u0627\u064A\u0627 \u0627\u0644\u062C\u0627\u0645\u0639\u0629.\r\n\r\n- \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0645\u062C\u0647\u0648\u0644\u0629 \u064A\u0645\u0643\u0646 \u0627\u0633\u062A\u062E\u062F\u0627\u0645\u0647\u0627 \u0641\u0649 \u0627\u0644\u0623\u063A\u0631\u0627\u0636 \u0627\u0644\u0625\u062D\u0635\u0627\u0626\u064A\u0629.\r\n\r\n- \u0642\u062F \u064A\u062A\u0645 \u062D\u0641\u0638 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0634\u062E\u0635\u064A\u0629 \u0641\u0642\u0637 \u0627\u0630\u0627 \u0643\u0627\u0646 \u0630\u0644\u0643 \u0636\u0631\u0648\u0631\u064A\u0627.\r\n\r\n- \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u063A\u064A\u0631 \u0627\u0644\u0636\u0631\u0648\u0631\u064A\u0629 \u064A\u062A\u0645 \u062D\u0630\u0641\u0647\u0627. showfile=\u0639\u0631\u0636 \u0645\u062C\u0644\u062F \u0627\u0644\u0623\u0631\u0634\u064A\u0641 @@ -120,4 +124,5 @@ ta=\u0645\u0647\u0627\u0645/\u062D\u0644\u0648\u0644 table.action.select=\u0627\u062E\u062A\u064A\u0627\u0631 table.header.node=\u0639\u0646\u0635\u0631 \u0627\u0644\u0645\u0642\u0631\u0631 tool.name=\u0623\u062F\u0627\u0629 \u0627\u0644\u0623\u0631\u0634\u064A\u0641 +scorm=SCORM wiki=\u0648\u064A\u0643\u0649 diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_bg.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_bg.properties index 49ab7d0f162feb449fcc31692cea28e98be1910b..d6c55d3310e44f07319657e7a918ba313494ad25 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_bg.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_bg.properties @@ -101,3 +101,4 @@ table.action.select=\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 table.header.node=\u041A\u0443\u0440\u0441\u043E\u0432 \u0435\u043B\u0435\u043C\u0435\u043D\u0442 tool.name=\u0418\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442 \u0437\u0430 \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u0430\u043D\u0435 wiki=\u0423\u0438\u043A\u0438\u0442\u0430 +scorm=SCORM diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_cs.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_cs.properties index dc4ac5aa19f927b1fac342bea250e3dae477fffb..30c3e8901b7cd444efe885e90a5a0a0384369622 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_cs.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_cs.properties @@ -99,4 +99,5 @@ ta=\u00DAkoly/\u0159e\u0161en\u00ED table.action.select=Vybrat table.header.node=Element kurzu tool.name=Z\u00E1lohovac\u00ED n\u00E1stroj +scorm=SCORM wiki=Wiki diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_da.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_da.properties index 27b66945fbea68b26f1c1b2f17af8d2e3869f52a..22e24c74827dd8d4750c686acac5a6c5eb416639 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_da.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_da.properties @@ -76,3 +76,4 @@ menu.scoreaccounting.alt=Arkiver dine endelige resultater fra tests, vurderinger table.action.select=V\u00E6lg table.header.node=Kursuselement tool.name=Arkiveringsv\u00E6rkt\u00F8j +scorm=SCORM diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_de.properties index a350b5a0833bb7f598808ac139562a2b5500774f..8203c8d4f70a95caa61703a627aaacfd2d3a6074 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_de.properties @@ -106,6 +106,8 @@ menu.scoreaccounting=Kursresultate menu.scoreaccounting.alt=Endresultate von Tests, Bewertungen und Aufgaben archivieren menu.wikis=Wikis menu.wikis.alt=Wikis archivieren +menu.scorm=SCORM Resultate +menu.scorm.alt=SCORM Resultate menu.projectbroker=Themenvergabe menu.projectbroker.alt=Daten der Bausteine "Themenvergabe" archivieren nodechoose.intro.dialog=W\u00E4hlen Sie einen Kursbaustein aus, um dessen Dateidiskussion zu archivieren. Die archivierte Dateidiskussion finden Sie in Ihrem pers\u00F6nlichen Ordner unter private/archive/[Kursname]/Dateidiskussion_[forum_id] @@ -113,16 +115,23 @@ nodechoose.intro.fo=W\u00E4hlen Sie einen Kursbaustein aus, um dessen Forum zu a nodechoose.intro.ta=W\u00E4hlen Sie einen Kursbaustein aus, um dessen Aufgaben/L\u00F6sungen zu archivieren. Die archivierten Aufgaben/L\u00F6sungen finden Sie in Ihrem pers\u00F6nlichem Ordner unter private/archive/[Kursname]/task_[Bausteinname] als ZIP-Datei. nodechoose.intro.wiki=W\u00E4hlen Sie einen Kursbaustein aus, um dessen Wikis zu archivieren. Die archivierten Wikis finden Sie in Ihrem pers\u00F6nlichem Ordner unter private/archive/[Kursname]/Bausteinname_[Datum] als ZIP-Datei. nodechoose.intro.projectbroker=W\u00E4hlen Sie einen Kursbaustein aus, um dessen Themenvergabe zu archivieren. Die archivierte Themenvergabe finden Sie in Ihrem pers\u00F6nlichen Ordner unter private/archive/[Kursname]/projectbroker_[id] +nodechoose.intro.scorm=W\u00E4hlen Sie im folgenden Dialog den SCORM Baustein aus, der ausgewertet werden soll. Die archivierten Resultate finden Sie in Ihrem pers\u00F6nlichen Ordner unter private/archive/[Kursname]/[Dateiname]. overview.nonodes.dialog=Dieser Kurs enth\u00E4lt keine Dateidiskussionen. overview.nonodes.fo=Dieser Kurs enth\u00E4lt keine Foren overview.nonodes.ta=Dieser Kurs enth\u00E4lt keine Aufgabenkursbausteine overview.nonodes.wiki=Dieser Kurs enth\u00E4lt keine Wikis. overview.nonodes.projectbroker=Dieser Kurs enth\u00E4lt keinen Baustein "Themenvergabe". +overview.nonodes.scorm=Dieser Kurs hat keinen SCORM Baustein. +select.group=Gruppe ausw\u00E4hlen +select.group.all=Alle Teilnehmer +select.group.desc=Sie k\u00F6nnen den Download auf einem bestimmte Gruppe beschr\u00E4nken, oder nicht. readme=Hinweis \n \n Als Empf\u00E4nger bzw. Empf\u00E4ngerin der archivierten Daten sind Sie daf\u00FCr verantwortlich, dass die Daten nur im erlaubten Rahmen verwendet werden. \n \n \n- Personenbezogene Daten d\u00FCrfen f\u00FCr Forschung, Lehre und Evaluation verwendet werden, aber nur solange diese mit universit\u00E4ren Belangen im Zusammenhang steht. \n \n- Anonymisierte Daten k\u00F6nnen auch zu statistischen Zwecken verwendet werden. \n \n- Personenbezogene Daten d\u00FCrfen nur solange aufbewahrt werden, wie es der Zweck erfordert. \n \n- Nicht mehr ben\u00F6tigte Daten m\u00FCssen vernichtet werden. showfile=Archivordner anzeigen ta=Aufgaben/L\u00F6sungen table.action.select=Ausw\u00E4hlen +table.action.download=Download table.header.node=Kursbaustein tool.name=Datenarchivierung +scorm=SCORM wiki=Wikis projectbroker=Themenvergabe diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_el.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_el.properties index f88911adea774803b3bfea6ce2be546b5449f9bf..dd7c84f103498155c84e99de4812e43de56ea43c 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_el.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_el.properties @@ -103,16 +103,20 @@ menu.scoreaccounting=\u0391\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B menu.scoreaccounting.alt=\u0391\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03AD\u03C4\u03B7\u03C3\u03B7 \u03C4\u03B5\u03BB\u03B9\u03BA\u03CE\u03BD \u03B1\u03C0\u03BF\u03C4\u03B5\u03BB\u03B5\u03C3\u03BC\u03AC\u03C4\u03C9\u03BD \u03B1\u03C0\u03BF \u03C4\u03B5\u03C3\u03C4, \u03B1\u03BE\u03B9\u03BF\u03BB\u03BF\u03B3\u03AE\u03C3\u03B5\u03B9\u03C2 \u03BA\u03B1\u03B9 \u03B5\u03C1\u03B3\u03B1\u03C3\u03AF\u03B5\u03C2 menu.wikis=Wikis menu.wikis.alt=\u0391\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03AD\u03C4\u03B7\u03C3\u03B7 Wikis +menu.scorm=\u0391\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 SCORM +menu.scorm.alt=\u0391\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 SCORM nodechoose.intro.dialog=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03AE\u03C3\u03B5\u03C4\u03B5 \u03C4\u03BF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF \u03B4\u03B9\u03B1\u03BB\u03CC\u03B3\u03C9\u03BD. \u039F \u03B1\u03C0\u03BF\u03B8\u03B7\u03BA\u03B5\u03C5\u03BC\u03AD\u03BD\u03BF\u03C2 \u03B4\u03B9\u03AC\u03BB\u03BF\u03B3\u03BF\u03C2 \u03B2\u03C1\u03AF\u03C3\u03BA\u03B5\u03C4\u03B1\u03B9 \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 \u03C6\u03AC\u03BA\u03B5\u03BB\u03BF \u03C3\u03C4\u03BF \u03C4\u03BC\u03AE\u03BC\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC/\u03B1\u03C1\u03C7\u03B5\u03AF\u03BF/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2]/\u03B4\u03B9\u03AC\u03BB\u03BF\u03B3\u03BF \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD_[forum_id]. nodechoose.intro.fo=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03AE\u03C3\u03B5\u03C4\u03B5 \u03C4\u03BF forum \u03C4\u03BF\u03C5. \u03A4\u03BF \u03B1\u03C0\u03BF\u03B8\u03B7\u03BA\u03B5\u03C5\u03BC\u03AD\u03BD\u03BF forum \u03B2\u03C1\u03AF\u03C3\u03BA\u03B5\u03C4\u03B1\u03B9 \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 \u03C6\u03AC\u03BA\u03B5\u03BB\u03BF \u03C3\u03C4\u03BF \u03C4\u03BC\u03AE\u03BC\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC/\u03B1\u03C1\u03C7\u03B5\u03AF\u03BF/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2]/forum_[forum_id]. nodechoose.intro.projectbroker=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B5\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03AE\u03C3\u03B5\u03C4\u03B5 \u03C4\u03B7\u03BD \u03B1\u03BD\u03AC\u03B8\u03B5\u03C3\u03B7 \u03B8\u03AD\u03BC\u03B1\u03C4\u03CC\u03C2 \u03C4\u03BF\u03C5. \u03A4\u03B7\u03BD \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03B7\u03BC\u03AD\u03BD\u03B7 \u03B1\u03BD\u03AC\u03B8\u03B5\u03C3\u03B7 \u03B8\u03AD\u03BC\u03B1\u03C4\u03BF\u03C2 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF\u03C4\u03B5 \u03BD\u03B1 \u03C4\u03B7 \u03B2\u03C1\u03B5\u03AF\u03C4\u03B5 \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C6\u03AC\u03BA\u03B5\u03BB\u03BB\u03CC \u03C3\u03B1\u03C2, \u03C0\u03B5\u03C1\u03B9\u03BF\u03C7\u03AE private/archive/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2]/topic assignment_[id] nodechoose.intro.ta=\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03AE\u03C3\u03B5\u03C4\u03B5 \u0395\u03C1\u03B3\u03B1\u03C3\u03AF\u03B5\u03C2/ \u039B\u03CD\u03C3\u03B5\u03B9\u03C2 \u03C4\u03BF\u03C5. \u039F\u03B9 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03B7\u03BC\u03AD\u03BD\u03B5\u03C2 \u0395\u03C1\u03B3\u03B1\u03C3\u03AF\u03B5\u03C2/ \u039B\u03CD\u03C3\u03B5\u03B9\u03C2 \u03B1\u03C0\u03BF\u03B8\u03B7\u03BA\u03B5\u03CD\u03BF\u03BD\u03C4\u03B1\u03B9 \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 \u03C6\u03AC\u03BA\u03B5\u03BB\u03BF \u03C3\u03C4\u03BF \u03C4\u03BC\u03AE\u03BC\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC/\u03B1\u03C1\u03C7\u03B5\u03AF\u03BF/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2]/\u03B5\u03C1\u03B3\u03B1\u03C3\u03AF\u03B1_[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF\u03C5 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2] \u03C9\u03C2 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF zip. nodechoose.intro.wiki=S\u0395\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03AD\u03BD\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03AE\u03C3\u03B5\u03C4\u03B5 \u03C4\u03BF Wiki. \u03A4\u03BF \u03B1\u03C0\u03BF\u03B8\u03B7\u03BA\u03B5\u03C5\u03BC\u03AD\u03BD\u03BF Wiki \u03B2\u03C1\u03AF\u03C3\u03BA\u03B5\u03C4\u03B1\u03B9 \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 \u03C6\u03AC\u03BA\u03B5\u03BB\u03BF \u03C3\u03C4\u03BF \u03C4\u03BC\u03AE\u03BC\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC/\u03B1\u03C1\u03C7\u03B5\u03AF\u03BF/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2]/wiki_[\u03B7\u03BC\u03B5\u03C1\u03BF\u03BC\u03B7\u03BD\u03AF\u03B1]. +nodechoose.intro.scorm=\u03A3\u03C4\u03BF\u03BD \u03B1\u03BA\u03CC\u03BB\u03BF\u03C5\u03B8\u03BF \u03B4\u03B9\u03AC\u03BB\u03BF\u03B3\u03BF, \u03C0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B5\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03C4\u03BF \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF SCORM \u03C0\u03BF\u03C5 \u03B8\u03AD\u03BB\u03B5\u03C4\u03B5 \u03BD\u03B1 \u03B1\u03BE\u03B9\u03BF\u03BB\u03BF\u03B3\u03B7\u03B8\u03B5\u03AF. \u03A4\u03B1 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03B7\u03BC\u03AD\u03BD\u03B1 \u03B1\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF\u03C4\u03B5 \u03BD\u03B1 \u03C4\u03B1 \u03B2\u03C1\u03B5\u03AF\u03C4\u03B5 \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 \u03C6\u03AC\u03BA\u03B5\u03BB\u03BF, \u03C3\u03C4\u03BF \u03C4\u03BC\u03AE\u03BC\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC/\u03B1\u03C1\u03C7\u03B5\u03AF\u03BF/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2]/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5]. overview.nonodes.dialog=\u03A4\u03BF \u03BC\u03AC\u03B8\u03B7\u03BC\u03B1 \u03B4\u03B5\u03BD \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 \u03B4\u03B9\u03B1\u03BB\u03CC\u03B3\u03BF\u03C5\u03C2 \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD. overview.nonodes.fo=\u03A4\u03BF \u03BC\u03AC\u03B8\u03B7\u03BC\u03B1 \u03B4\u03B5\u03BD \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 forums. overview.nonodes.projectbroker=\u03A4\u03BF \u03BC\u03AC\u03B8\u03B7\u03BC\u03B1 \u03B4\u03B5\u03BD \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 \u03BA\u03AC\u03C0\u03BF\u03B9\u03B1 \u03B1\u03BD\u03AC\u03B8\u03B5\u03C3\u03B7 \u03B8\u03AD\u03BC\u03B1\u03C4\u03BF\u03C2. overview.nonodes.ta=\u03A4\u03BF \u03BC\u03AC\u03B8\u03B7\u03BC\u03B1 \u03B4\u03B5\u03BD \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03B1 \u03B5\u03C1\u03B3\u03B1\u03C3\u03B9\u03CE\u03BD. overview.nonodes.wiki=\u03A4\u03BF \u03BC\u03AC\u03B8\u03B7\u03BC\u03B1 \u03B4\u03B5\u03BD \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 Wikis. +overview.nonodes.scorm=\u03A4\u03BF \u03BC\u03AC\u03B8\u03B7\u03BC\u03B1 \u03B1\u03C5\u03C4\u03CC \u03B4\u03B5\u03BD \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 \u03BA\u03AC\u03C0\u03BF\u03B9\u03BF \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF SCORM. projectbroker=\u0391\u03BD\u03AC\u03B8\u03B5\u03C3\u03B7 \u03B8\u03AD\u03BC\u03B1\u03C4\u03BF\u03C2 readme=\u03A5\u03C0\u03CC\u03B4\u03B5\u03B9\u03BE\u03B7 \n \n \u03A9\u03C2 \u03C0\u03B1\u03C1\u03B1\u03BB\u03AE\u03C0\u03C4\u03B7\u03C2 \u03C4\u03C9\u03BD \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03B7\u03BC\u03AD\u03BD\u03C9\u03BD \u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD \u03B5\u03AF\u03C3\u03C4\u03B5 \u03C5\u03C0\u03B5\u03CD\u03B8\u03C5\u03BD\u03BF\u03C2 \u03B3\u03B9\u03B1 \u03C4\u03B7\u03BD \u03B5\u03C0\u03B9\u03C4\u03C1\u03B5\u03C0\u03CC\u03BC\u03B5\u03BD\u03B7 \u03C7\u03C1\u03AE\u03C3\u03B7 \u03B1\u03C5\u03C4\u03CE\u03BD. \n \n \n- \u03A4\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03AC \u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1 \u03BC\u03C0\u03BF\u03C1\u03BF\u03CD\u03BD \u03BD\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03BF\u03CD\u03BD\u03C4\u03B1\u03B9 \u03BC\u03CC\u03BD\u03BF \u03B3\u03B9\u03B1 \u03AD\u03C1\u03B5\u03C5\u03BD\u03B1, \u03B4\u03B9\u03B4\u03B1\u03C3\u03BA\u03B1\u03BB\u03AF\u03B1 \u03BA\u03B1\u03B9 \u03B1\u03C0\u03BF\u03C4\u03AF\u03BC\u03B7\u03C3\u03B7 \u03BC\u03CC\u03BD\u03BF \u03C3\u03B5 \u03C3\u03C7\u03AD\u03C3\u03B7 \u03BC\u03B5 \u03B8\u03AD\u03BC\u03B1\u03C4\u03B1 \u03C4\u03BF\u03C5 \u03C0\u03B1\u03BD\u03B5\u03C0\u03B9\u03C3\u03C4\u03B7\u03BC\u03AF\u03BF\u03C5. \n \n- \u03A4\u03B1 \u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1 \u03B1\u03BD\u03CE\u03BD\u03C5\u03BC\u03C9\u03BD \u03C7\u03C1\u03B7\u03C3\u03C4\u03CE\u03BD \u03BC\u03C0\u03BF\u03C1\u03BF\u03CD\u03BD \u03BD\u03B1 \u03C7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03BF\u03CD\u03BD\u03C4\u03B1\u03B9 \u03B3\u03B9\u03B1 \u03C3\u03C4\u03B1\u03C4\u03B9\u03C3\u03C4\u03B9\u03BA\u03BF\u03CD\u03C2 \u03C3\u03BA\u03BF\u03C0\u03BF\u03CD\u03C2. \n \n- \u03A4\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03AC \u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1 \u03BC\u03C0\u03BF\u03C1\u03BF\u03CD\u03BD \u03BD\u03B1 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03BF\u03CD\u03BD\u03C4\u03B1\u03B9 \u03BC\u03CC\u03BD\u03BF \u03B3\u03B9\u03B1 \u03CC\u03C3\u03BF \u03B1\u03C0\u03B1\u03B9\u03C4\u03B5\u03AF\u03C4\u03B1\u03B9. \n \n- \u039C\u03B7 \u03B1\u03C0\u03B1\u03C1\u03B1\u03AF\u03C4\u03B7\u03C4\u03B1 \u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1 \u03C0\u03C1\u03AD\u03C0\u03B5\u03B9 \u03BD\u03B1 \u03B4\u03B9\u03B1\u03B3\u03C1\u03AC\u03C6\u03BF\u03BD\u03C4\u03B1\u03B9. showfile=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_en.properties index 12f57fc385e479308a177fa41aef6a035c44c60d..b83b879d03b1912dc8fe76a8eab0e5f4504bed50 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_en.properties @@ -1,3 +1,4 @@ + #Mon May 16 17:10:05 CEST 2011 archive.dialog.notsuccessfully=This file dialog could not be archived. archive.dialog.successfully=This file dialog has been archived in your personal folder. @@ -108,16 +109,20 @@ menu.scoreaccounting=Course results menu.scoreaccounting.alt=Archive final results from tests, assessments and tasks menu.wikis=Wikis menu.wikis.alt=Archive Wikis +menu.scorm=SCORM results +menu.scorm.alt=SCORM results nodechoose.intro.dialog=Select a course element to archive its file dialog. This archived dialog can be found in your personal folder, section private/archive/[course name]/file dialog_[forum_id]. nodechoose.intro.fo=Select a course element to archive its forum. This archived forum can be found in your personal folder, section private/archive/[course name]/forum_[forum_id]. nodechoose.intro.projectbroker=Please select a course element to archive its topic assignment. Archived topic assignment can be found in your personal folder, section private/archive/[course's name]/topic assignment_[id] nodechoose.intro.ta=Select a course element in order to archive its tasks/solutions. These archived tasks/solutions are saved in your personal folder in the section private/archive/[course name]/task_[name of course element] as zip file. nodechoose.intro.wiki=Select a course element to archive its Wiki. This archived Wiki can be found in your personal folder, section private/archive/[course name]/wiki_[date] as zip file. +nodechoose.intro.scorm=In the following dialog please select the SCORM element to be assessed. Archived results can be found in your personal folder, section private/archive/[course name]/[file name]. overview.nonodes.dialog=This course does not contain any file dialogs. overview.nonodes.fo=This course does not contain any forums. overview.nonodes.projectbroker=This course does not contain any topic assignments. overview.nonodes.ta=This course does not contain any task elements. overview.nonodes.wiki=This course does not contain any Wikis. +overview.nonodes.scorm=This course does not contain any SCORM element. projectbroker=Topic assignment readme=Directive\r\n \r\n As recipient of archived data you are responsible for the fact that these data are used only as permitted. \r\n \r\n \r\n- Personal data may be used for research, teaching, and evaluation only as far as related to university issues. \r\n \r\n- Anonymous data can also be used for statistic purposes. \r\n \r\n- Personal data may be archived only as long as necessary. \r\n \r\n- Unnecessary data have to be deleted. showfile=Show archive folder diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_fr.properties index a15c402a90c3662b85a0e8439f0caf3791d5f08d..e846f364e3d65dfa78b0cc5a0b5e7c30d1f0c856 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_fr.properties @@ -107,17 +107,21 @@ menu.qtiresults.alt=Archiver les donn\u00E9es des tests et des questionnaires menu.scoreaccounting=R\u00E9sultats des cours menu.scoreaccounting.alt=Archiver les r\u00E9sultats finaux des tests, des \u00E9valuations et des devoirs menu.wikis=Wikis -menu.wikis.alt=Archiver Wikis +menu.wikis.alt=Archiver Wikis +menu.scorm=R\u00E9sultats SCORM +menu.scorm.alt=R\u00E9sultats SCORM nodechoose.intro.dialog=S\u00E9lectionnez un \u00E9l\u00E9ment de cours pour archiver ses discussions de fichiers. Les fichiers discut\u00E9s archiv\u00E9s se trouvent sous format zip dans votre dossier personnel sous private/archive/[nom_du_cours]/Dateidiskussion_[forum_id] nodechoose.intro.fo=S\u00E9lectionnez un \u00E9l\u00E9ment de cours pour archiver son forum. zu archivieren. Les forums archiv\u00E9s se trouvent sous format zip dans votre dossier personnel sous private/archive/[nom_du_cours]/forum_[forum_id] nodechoose.intro.projectbroker=S\u00E9lectionner un \u00E9l\u00E9ment de cours pour archiver son affectation des sujets. L'affectation des sujets archiv\u00E9e peut \u00EAtre trouv\u00E9e dans votre dossier personnel sous private/archive/[Kursname]/projectbroker_[id] nodechoose.intro.ta=S\u00E9lectionnez un \u00E9l\u00E9ment de cours pour archiver ses devoirs/solutions. Vous trouvez les devoirs/solutions achiv\u00E9es dans votre dossier personnel comme fichier zip sous private/archive/[nom_du_cours]/task_[nom de l'\u00E9l\u00E9ment]. nodechoose.intro.wiki=S\u00E9lectionnez un \u00E9l\u00E9ment de cours pour archiver ses Wikis. Les Wikis archiv\u00E9s se trouvent sous format zip dans votre dossier personnel sous private/archive/[nom_du_cours]/Bausteinname_[date]. +nodechoose.intro.scorm=Choisir dans le dialogue suivant l'\u00E9l\u00E9ment SCORM qui doit \u00EAtre \u00E9valu\u00E9. Les r\u00E9sultats archiv\u00E9s sont d\u00E9pos\u00E9s dans votre dossier personnel sous private/archive/[nom du cours]/[nom du fichier]. overview.nonodes.dialog=Dieser Kurs enth\u00E4lt keine Dateidiskussionen. overview.nonodes.fo=Dieser Kurs enth\u00E4lt keine Foren overview.nonodes.projectbroker=Ce cours ne contient pas d'affectation des sujets. overview.nonodes.ta=Dieser Kurs enth\u00E4lt keine Aufgabe-Kursbausteine overview.nonodes.wiki=Ce cours ne contient pas de wikis. +overview.nonodes.scorm=Ce cours n'a pas d'\u00E9l\u00E9ment SCORM. projectbroker=Affectation des sujets readme=Attention \n \n En tant que destinataire des donn\u00E9es archiv\u00E9es, vous \u00EAtes respondable que les donn\u00E9es ne sont utilis\u00E9es que dans le cadre autoris\u00E9. \n \n \n- Les donn\u00E9es relatives au personnes peuvent \u00EAtre utilis\u00E9es pour la recherche, l'enseignement et l'\u00E9valutation, mais seulement s'ils sont li\u00E9s \u00E0 des int\u00E9r\u00EAts universitaires. \n \n- Des donn\u00E9es anonymes peuvent \u00E9galement \u00EAtre utilis\u00E9es dans des buts statistiques.\n \n- Les donn\u00E9es personnelles ne doivent \u00EAtre gard\u00E9es qu'aussi longtemps que vraiment n\u00E9cessaire. \n \n- Les donn\u00E9es devenues superflues doivent \u00EAtre d\u00E9truites. showfile=Afficher dossier d'archivage diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_it.properties index 1bb8e59a64e9e33f8c04b16c162c51af70f64deb..b8f5fee228ee34ae27f80713271da0ce08438dca 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_it.properties @@ -103,16 +103,20 @@ menu.scoreaccounting=Risultati del corso menu.scoreaccounting.alt=Archiviare risultati finali di test, valutazioni e compiti menu.wikis=Wiki menu.wikis.alt=Archiviare wiki +menu.scorm=Risultati SCORM +menu.scorm.alt=Risultati SCORM nodechoose.intro.dialog=Selezioni un elemento di corso per archiviarne le discussioni documentate. Le discussioni documentate archiviate si trovano nella Sua cartella personale sotto private/archive/[nome del corso]/discussione documentata_[forum_id]. nodechoose.intro.fo=Selezioni un elemento di corso per archiviarne il forum. Il forum archiviato si trova nella Sua cartella personale sotto private/archive/[nome del corso]/forum_[forum_id]. nodechoose.intro.projectbroker=Selezioni un elemento di corso per archiviare l'assegnazione dei temi corrispondente. L'assegnazione dei temi archiviata si trova nella Sua cartella personale sotto private/archive/[nome del corso]/projectbroker_[id] nodechoose.intro.ta=Selezioni un elemento di corso per archiviarne i compiti e le soluzioni. I compiti e le soluzioni archiviati si trovano nella Sua cartella personale sotto private/archive/[nome del corso]/task_[nome dell'elemento] come file zip. nodechoose.intro.wiki=Selezioni un elemento di corso per archiviarne i wiki. I wiki archiviati si trovano nella Sua cartella personale sotto private/archive/[nome del corso]/nome dell'elemento_[data] come file zip. +nodechoose.intro.scorm=Selezioni l'elemento SCORM che deve essere valutato nel dialogo seguente. I risultati archiviati si trovano nella Sua cartella personale sotto private/archive/[Nome corso]/[Nome file]. overview.nonodes.dialog=Questo corso non contiene alcuna discussione documentata. overview.nonodes.fo=Questo corso non contiene alcun forum. overview.nonodes.projectbroker=Questo corso non contiene alcuna assegnazione dei temi. overview.nonodes.ta=Questo corso non contiene alcun compito. overview.nonodes.wiki=Questo corso non contiene alcun wiki. +overview.nonodes.scorm=Questo corso non contiene alcun elemento SCORM. projectbroker=Assegnazione dei temi readme=Avvertenza \n \n In quanto destinataria/o dei dati archiviati, Lei \u00E8 responsabile del loro uso nel rispetto delle norme vigenti. \n \n \n- I dati personali possono essere utilizzati per la ricerca, l'insegnamento e la valutazione, ma solo in relazione ad attivit\u00E0 universitarie. \n \n- I dati anonimizzati possono essere utilizzati per statistiche. \n \n- I dati personali possono essere conservati solo per la durata necessaria alla realizzazione dello scopo cui sono destinati. \n \n- I dati caduti in disuso devono essere distrutti. showfile=Mostrare cartella d'archivio diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_nl_NL.properties index 7b2b4f7ecee830cf99ff651633a5cd7a016575a2..ad5a141acfbb4776e8f2da9045a2c11fa35fc576 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_nl_NL.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_nl_NL.properties @@ -103,16 +103,20 @@ menu.scoreaccounting=Cursus resultaten menu.scoreaccounting.alt=Archiveer eindresultaten van testen, beoordeling en taken menu.wikis=Wikis menu.wikis.alt=Archiveer Wikis +menu.scorm=SCORM resultaten +menu.scorm.alt=SCORM results nodechoose.intro.dialog=Selecteer een cursuselement om het te archiveren in zijn bestandsdialoog. Deze gearchiveerde dialoog kan teruggevonden worden in uw persoonlijke map, sectie private/archive/[course name]/file dialog_[forum_id]. nodechoose.intro.fo=Selecteer een cursuselement om zijn forum te archiveren. Deze gearchiveerde forum kan teruggevonden worden in uw persoonlijke map, sectie private/archive/[course name]/forum_[forum_id]. nodechoose.intro.projectbroker=Selecteer een cursuselement om zijn onderwerp opdracht te archiveren. Deze gearchiveerde opdracht kan teruggevonden worden in uw persoonlijke map, sectie private/archive/[course's name]/topic assignment_[id] nodechoose.intro.ta=Selecteer een cursuselement om zo zijn taken/oplossingen te archiveren. Deze gearchiveerde taken/oplossingen zijn opgeslagen in uw persoonlijke map in de sectie private/archive/[course name]/task_[name of course element] als een ZIP bestand. nodechoose.intro.wiki=Selecteer een cursuselement om zijn Wiki te archiveren. Deze gearchiveerde Wiki kan teruggevonden worden in uw persoonlijke map, sectie private/archive/[course name]/wiki_[date] als een ZIP bestand. +nodechoose.intro.scorm=Gelieve in de volgende dialoog een SCORM element te selecteren dat moet worden beoordeeld. Gearchiveerde resultaten kunnen teruggevonden worden in uw persoonlijke map, sectie section private/archive/[cursusnaam]/[bestandsnaam]. overview.nonodes.dialog=Deze cursus bevat geen bestandsdialogen. overview.nonodes.fo=Deze cursus bevat geen fora. overview.nonodes.projectbroker=Deze cursus bevat geen onderwerp opdrachten. overview.nonodes.ta=Deze cursus bevat geen opdrachtelementen. overview.nonodes.wiki=Deze cursus bevat geen Wiki's. +overview.nonodes.scorm=Deze cursus bevat geen SCORM element. projectbroker=Onderwerp opdracht readme=Richtlijnen\r\n\r\n Als ontvanger van gearchiveerde data bent u er verantwoordelijk voor dat deze data alleen wordt gebruikt zoals toegestaan.\r\n\r\n\r\n- Persoonlijke data mag gebruikt worden voor onderzoek, het lesgeven en evaluatie zolang het te maken heeft met de universiteit.\r\n\r\n- Anonieme data kan ook gebruikt worden voor statistieke doeleinden.\r\n\r\n- Persoonlijke data mag enkel zolang als nodig opgeslagen worden.\r\n\r\n- Onnodige data moet verwijdert worden. showfile=Toon archiefmap diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_pl.properties index b61cdd0e0383439ab2cd26d17183b520f68412b0..28c2b5f1cab79401854dda455e1f660b18ffda32 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_pl.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_pl.properties @@ -103,16 +103,20 @@ menu.scoreaccounting=Wyniki kursu menu.scoreaccounting.alt=Archiwizuj wyniki ko\u0144cowe z test\u00F3w i zada\u0144 menu.wikis=Wiki menu.wikis.alt=Archiwizuj Wiki +menu.scorm=Wyniki SCORM +menu.scorm.alt=Wyniki SCORM nodechoose.intro.dialog=Wybierz element kursu, \u017Ceby zarchiwizowa\u0107 jego okno pliku. Archiwum zostanie zapisane w twoim folderze osobistym, w sekcji private/archive/[nazwa kursu]/file dialog_[file_dialog_id]. nodechoose.intro.fo=Wybierz element kursu, \u017Ceby zarchiwizowa\u0107 jego forum. Archiwum zostanie zapisane w twoim folderze osobistym, w sekcji private/archive/[nazwa kursu]/forum_[forum_id]. nodechoose.intro.projectbroker=Wybierz element kursu, \u017Ceby zarchiwizowa\u0107 przypisane zadania. Archiwum zostanie zapisane w twoim folderze osobistym, w sekcji private/archive/[nazwa kursu]/przypisanie zadania_[id] nodechoose.intro.ta=Wybierz element kursu, \u017Ceby zarchiwizowa\u0107 jego zadania/rozwi\u0105zania. Archiwum zostanie zapisane w twoim folderze osobistym, w sekcji private/archive/[nazwa kursu]/task_[nazwa elementu kursu] jako plik ZIP. nodechoose.intro.wiki=Wybierz element kursu by zarchiwizowa\u0107 jego wiki. To archiwum jest zapisane w Twoim prywatnym folderze w sekcji private/archive/[nazwa kursu]/wiki_[data]. +nodechoose.intro.scorm=W nast\u0119pnym oknie dialogowym wybierz element SCORM, kt\u00F3ry ma by\u0107 oceniany. Archiwum z wynikami znajdziesz w swoim folderze osobistym, w sekcji private/archive/[nazwa kursu]/[nazwa pliku]. overview.nonodes.dialog=Ten kurs nie zawiera elementu <b>Okno pliku</b>. overview.nonodes.fo=Ten kurs nie zawiera elementu\: <b>Forum</b>. overview.nonodes.projectbroker=Ten kurs nie posiada przypisanych zada\u0144. overview.nonodes.ta=Ten kurs nie zawiera elementu\: <b>Zadanie</b>. overview.nonodes.wiki=Kurs nie zawiera elementu <b>Wiki</b>. +overview.nonodes.scorm=Kurs nie zawiera tre\u015Bci SCORM. projectbroker=Przypisanie zada\u0144 readme=Wskaz\u00F3wka \n \n Jako odbiorca zarchiwizownych danych, jeste\u015B odpowiedzialny za nieudostepnianie ich osobom nieupowa\u017Cnionym. \n \n \n- Mo\u017Cesz ich u\u017Cywa\u0107 wy\u0142\u0105cznie w zwi\u0105zku z procesem nauki. \n \n- Dane anonimowe mog\u0105 by\u0107 \u017Ar\u00F3d\u0142em bada\u0144 statystycznych . \n \n- Dane osobowe powinny by\u0107 przechowywane jak najkr\u00F3cej. \n \n- Niepotrzebne dane musz\u0105 zosta\u0107 usuni\u0119te. showfile=Poka\u017C plik diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_pt_BR.properties index ad8c5d16a03852ac0c89a165156fbba842d34eba..5f6cb7ec71e29962aaa4d532fef17029e3fd6107 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_pt_BR.properties @@ -109,16 +109,20 @@ menu.scoreaccounting=Resultados do curso menu.scoreaccounting.alt=Arquivar resultados finais dos testes, avalia\u00E7\u00F5es e tarefas menu.wikis=Wikis menu.wikis.alt=Arquivar Wikis +menu.scorm=Resultados SCORM +menu.scorm.alt=Resultados SCORM nodechoose.intro.dialog=Selecionar um elemento de curso para arquivar file dialog. Este di\u00E1logo arquivado pode ser encontrado na sua pasta pessoal, se\u00E7\u00E3o confidencial/arquivo/[nomedocurso]/arquivo de di\u00E1logo_[f\u00F3rum_id]. nodechoose.intro.fo=Selecionar um elemento de curso para arquivar f\u00F3rum. Este f\u00F3rum arquivado pode ser encontrado em sua pasta pessoal, se\u00E7\u00E3o confidencial/arquivo/[nomedocurso]/f\u00F3rum_[f\u00F3rum_id]. nodechoose.intro.projectbroker=Por favor, selecione um elemento de curso para arquivar seu t\u00F3pico atribu\u00EDdo. T\u00F3picos atribu\u00EDdos arquivados podem ser encontrados em sua pasta pessoal, se\u00E7\u00E3o section private/archive/[course's name]/topic assignment_[id] nodechoose.intro.ta=Selecionar um elemento de curso para arquivar suas resolu\u00E7\u00F5es de tarefas. Estas tarefas/resolu\u00E7\u00F5es arquivadas est\u00E3o salvas em sua pasta pessoal na se\u00E7\u00E3o confidencial/arquivo/[nomedocurso]/tarefa_[nomedoelementodecurso] como arquivo zip. nodechoose.intro.wiki=Selecionar um elemento de curso para arquivar Wiki. Este Wiki arquivado pode ser encontrado na sua pasta pessoal, se\u00E7\u00E3o confidencial/arquivo/[nomedocurso]/wiki_[data]. +nodechoose.intro.scorm=Na janela seguinte selecione o elemento SCORM para ser avaliado. Os resultados arquivados podem ser encontrados na pasta pessoal, se\u00E7\u00E3o private/archive/[course name]/[file name]. overview.nonodes.dialog=Este curso n\u00E3o cont\u00E9m nenhum arquivo de di\u00E1logo. overview.nonodes.fo=Este curso n\u00E3o cont\u00E9m nenhum f\u00F3rum. overview.nonodes.projectbroker=Este curso n\u00E3o cont\u00EAm quaisquer atribui\u00E7\u00F5es de t\u00F3pico. overview.nonodes.ta=Este curso n\u00E3o cont\u00E9m nenhum elemento de tarefa. overview.nonodes.wiki=Este curso n\u00E3o cont\u00E9m nenhum Wiki. +overview.nonodes.scorm=Este curso n\u00E3o cont\u00EAm qualquer elemento SCORM. projectbroker=Atribui\u00E7\u00E3o de T\u00F3pico readme=Dica \n \n Como receptor de dados arquivados voc\u00EA \u00E9 respons\u00E1vel pelo fato de que esses dados s\u00E3o usados apenas como permitido. \n \n \n- Dados pessoais podem ser usados para pesquisa, ensino, e avalia\u00E7\u00E3o contanto somente se relacionado \u00E0 assuntos da universidade. \n \n- Dados an\u00F4nimos podem tamb\u00E9m serem usados para finalidades de estat\u00EDstica. \n \n- Dados pessoais devem ser arquivados somente se necess\u00E1rio. \n \n- Dados desnecess\u00E1rios tem que ser apagados. showfile=Exibir arquivo diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_ru.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_ru.properties index bc57a78a92fba3f972a7429ef1cca0eafd8cac0f..6ead22512e5a640cc700d5cc5b65a70f2ffdf8ac 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_ru.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_ru.properties @@ -91,14 +91,18 @@ menu.scoreaccounting=\u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044 menu.scoreaccounting.alt=\u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043A\u043E\u043D\u0435\u0447\u043D\u044B\u0435 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u0442\u0435\u0441\u0442\u043E\u0432, \u043E\u0446\u0435\u043D\u043E\u043A \u0443\u0441\u043F\u0435\u0432\u0430\u0435\u043C\u043E\u0441\u0442\u0438 \u0438 \u0437\u0430\u0434\u0430\u043D\u0438\u0439 menu.wikis=\u0412\u0438\u043A\u0438 menu.wikis.alt=\u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0412\u0438\u043A\u0438 +menu.scorm=SCORM \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B +menu.scorm.alt=SCORM \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B nodechoose.intro.dialog=\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u044B\u0439 \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043A\u0443\u0440\u0441\u0430, \u0447\u0442\u043E\u0431\u044B \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u041E\u0431\u0441\u0443\u0436\u0434\u0435\u043D\u0438\u0435 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430 \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0433\u043E \u043A\u0443\u0440\u0441\u0430. \u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0435 \u041E\u0431\u0441\u0443\u0436\u0434\u0435\u043D\u0438\u0435 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430 \u043D\u0430\u0445\u043E\u0434\u0438\u0442\u0441\u044F \u0432 \u0412\u0430\u0448\u0435\u0439 \u043B\u0438\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u0435 \u043A\u0430\u043A zip-\u0444\u0430\u0439\u043B \u0432 \u0441\u0435\u043A\u0446\u0438\u0438 private/archive/[\u0418\u043C\u044F \u043A\u0443\u0440\u0441\u0430]/Dateidiskussion_[\u0444\u043E\u0440\u0443\u043C_id] nodechoose.intro.fo=\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u044B\u0439 \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043A\u0443\u0440\u0441\u0430, \u0447\u0442\u043E\u0431\u044B \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0424\u043E\u0440\u0443\u043C \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0433\u043E \u043A\u0443\u0440\u0441\u0430. \u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0424\u043E\u0440\u0443\u043C \u043D\u0430\u0445\u043E\u0434\u0438\u0442\u0441\u044F \u0432 \u0412\u0430\u0448\u0435\u0439 \u043B\u0438\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u0435 \u043A\u0430\u043A zip-\u0444\u0430\u0439\u043B \u0432 \u0441\u0435\u043A\u0446\u0438\u0438 private/archive/[\u0418\u043C\u044F \u043A\u0443\u0440\u0441\u0430]/forum_[\u0444\u043E\u0440\u0443\u043C_id] nodechoose.intro.ta=\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u044B\u0439 \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043A\u0443\u0440\u0441\u0430, \u0447\u0442\u043E\u0431\u044B \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0417\u0430\u0434\u0430\u043D\u0438\u044F/\u0420\u0435\u0448\u0435\u043D\u0438\u044F \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0433\u043E \u043A\u0443\u0440\u0441\u0430. \u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u0417\u0430\u0434\u0430\u043D\u0438\u044F/\u0420\u0435\u0448\u0435\u043D\u0438\u044F \u043D\u0430\u0445\u043E\u0434\u044F\u0442\u0441\u044F \u0432 \u0412\u0430\u0448\u0435\u0439 \u043B\u0438\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u0435 \u043A\u0430\u043A zip-\u0444\u0430\u0439\u043B \u0432 \u0441\u0435\u043A\u0446\u0438\u0438 private/archive/[\u0418\u043C\u044F \u043A\u0443\u0440\u0441\u0430]/task_[\u0418\u043C\u044F \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u043E\u0433\u043E \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430]. nodechoose.intro.wiki=\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u044B\u0439 \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043A\u0443\u0440\u0441\u0430, \u0447\u0442\u043E\u0431\u044B \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0412\u0438\u043A\u0438 \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0433\u043E \u043A\u0443\u0440\u0441\u0430. \u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0435 \u0412\u0438\u043A\u0438 \u043D\u0430\u0445\u043E\u0434\u044F\u0442\u0441\u044F \u0432 \u0412\u0430\u0448\u0435\u0439 \u043B\u0438\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u0435 \u043A\u0430\u043A zip-\u0444\u0430\u0439\u043B \u0432 \u0441\u0435\u043A\u0446\u0438\u0438 private/archive/[\u0418\u043C\u044F \u043A\u0443\u0440\u0441\u0430]/Bausteinname_[\u0418\u043C\u044F \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u043E\u0433\u043E \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430]. +nodechoose.intro.scorm=\u0412 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C \u0434\u0438\u0430\u043B\u043E\u0433\u0435 \u0432\u044B\u0431\u0435\u0440\u0438\u0442\u0435 SCORM \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0431\u0443\u0434\u0435\u0442 \u043E\u0446\u0435\u043D\u0435\u043D. \u0410\u0440\u0445\u0438\u0432 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432 \u043C\u043E\u0436\u043D\u043E \u043D\u0430\u0439\u0442\u0438 \u0432 \u0432\u0430\u0448\u0435\u0439 \u043B\u0438\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u0435, \u0432 \u0440\u0430\u0437\u0434\u0435\u043B\u0435 private/archive/[\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043A\u0443\u0440\u0441\u0430]/[\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430]. overview.nonodes.dialog=\u0423 \u044D\u0442\u043E\u0433\u043E \u043A\u0443\u0440\u0441\u0430 \u043D\u0435\u0442 \u043E\u0431\u0441\u0443\u0436\u0434\u0435\u043D\u0438\u0439 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430. overview.nonodes.fo=\u0423 \u044D\u0442\u043E\u0433\u043E \u043A\u0443\u0440\u0441\u0430 \u043D\u0435\u0442 \u0444\u043E\u0440\u0443\u043C\u043E\u0432 overview.nonodes.ta=\u0423 \u044D\u0442\u043E\u0433\u043E \u043A\u0443\u0440\u0441\u0430 \u043D\u0435\u0442 \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u043E\u0433\u043E \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430 - \u0417\u0430\u0434\u0430\u043D\u0438\u0435 overview.nonodes.wiki=\u0423 \u044D\u0442\u043E\u0433\u043E \u043A\u0443\u0440\u0441\u0430 \u043D\u0435\u0442 \u0412\u0438\u043A\u0438. +overview.nonodes.scorm=\u042D\u0442\u043E\u0442 \u043A\u0443\u0440\u0441 \u043D\u0435 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 SCORM \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432. readme=\u041F\u0440\u0438\u043C\u0435\u0447\u0430\u043D\u0438\u0435 \n \n \u0412 \u043A\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0445 \u0434\u0430\u043D\u043D\u044B\u0445, \u0412\u044B \u044F\u0432\u043B\u044F\u0435\u0442\u0435\u0441\u044C \u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043D\u043D\u044B\u043C \u0437\u0430 \u0442\u043E, \u0447\u0442\u043E\u0431\u044B \u044D\u0442\u0438 \u0434\u0430\u043D\u043D\u044B\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043B\u0438\u0441\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u0443\u0437\u0430\u043A\u043E\u043D\u0435\u043D\u043D\u044B\u0445 \u0440\u0430\u043C\u043A\u0430\u0445. \n \n \n- \u041F\u0435\u0440\u0441\u043E\u043D\u0430\u043B\u044C\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u043C\u043E\u0433\u0443\u0442 \u0431\u044B\u0442\u044C \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u044B \u0432 \u043D\u0430\u0443\u0447\u043D\u044B\u0445, \u0443\u0447\u0435\u0431\u043D\u044B\u0445 \u0438 \u0430\u0442\u0442\u0435\u0441\u0442\u0430\u0446\u0438\u043E\u043D\u043D\u044B\u0445 \u0446\u0435\u043B\u044F\u0445 \u0434\u043E \u0442\u0435\u0445 \u043F\u043E\u0440, \u043F\u043E\u043A\u0430 \u044D\u0442\u043E \u043F\u043E\u0434\u043B\u0435\u0436\u0438\u0442 \u043E\u0431\u043B\u0430\u0441\u0442\u0438 \u0443\u043D\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0441\u043A\u043E\u0433\u043E \u0443\u0441\u0442\u0430\u0432\u0430. \n \n- \u0410\u043D\u043E\u043D\u0438\u043C\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u043C\u043E\u0433\u0443\u0442 \u0431\u044B\u0442\u044C \u0442\u0430\u043A\u0436\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u044B \u0432 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0445 \u0446\u0435\u043B\u044F\u0445. \n \n- \u041F\u0435\u0440\u0441\u043E\u043D\u0430\u043B\u044C\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u043C\u043E\u0433\u0443\u0442 \u0441\u043E\u0445\u0440\u0430\u043D\u044F\u0442\u044C\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043E \u0442\u0435\u0445 \u043F\u043E\u0440, \u043F\u043E\u043A\u0430 \u043E\u043D\u0438 \u0432\u043E\u0441\u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u044B. \n \n- \u041D\u0435\u043D\u0443\u0436\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435, \u0434\u043E\u043B\u0436\u043D\u044B \u0431\u044B\u0442\u044C \u0443\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D\u044B. showfile=\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0444\u0430\u0439\u043B ta=\u0417\u0430\u0434\u0430\u043D\u0438\u044F/\u0420\u0435\u0448\u0435\u043D\u0438\u044F diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_zh_CN.properties index 5f7d79ab5f1e4f3dea4b7ae860c04e6616f1428f..916325adcfdead52f8e7c4568364bb018da98b73 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_zh_CN.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_zh_CN.properties @@ -103,16 +103,20 @@ menu.scoreaccounting=\u8BFE\u7A0B\u7ED3\u679C menu.scoreaccounting.alt=\u5BF9\u6D4B\u8BD5\u3001\u8BC4\u4F30\u548C\u4EFB\u52A1\u7684\u6700\u7EC8\u7ED3\u679C\u8FDB\u884C\u5F52\u6863 menu.wikis=Wiki menu.wikis.alt=\u5F52\u6863Wikis +menu.scorm=SCORM \u6210\u7EE9 +menu.scorm.alt=SCORM \u6210\u7EE9 nodechoose.intro.dialog=\u9009\u62E9\u4E00\u4E2A\u8BFE\u7A0B\u5143\u7D20\u5F52\u6863\u5176\u6587\u4EF6\u8BA8\u8BBA. \u8BE5\u5F52\u6863\u5B58\u653E\u5728\u4F60\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939 private/archive/[course name]/file dialog_[forum_id]\u4E2D. nodechoose.intro.fo=\u9009\u62E9\u4E00\u4E2A\u8BFE\u7A0B\u5143\u7D20\u5F52\u6863\u5176\u8BBA\u575B. \u8BE5\u5F52\u6863\u5B58\u653E\u5728\u4F60\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939private/archive/[course name]/forum_[forum_id]\u4E2D. nodechoose.intro.projectbroker=\u8BF7\u9009\u62E9\u4E00\u4E2A\u5B66\u7A0B\u5143\u7D20\u4EE5\u4FDD\u5B58\u5176\u9879\u76EE\u7ECF\u7EAA\u4EBA\u3002\u60A8\u80FD\u591F\u5728\u60A8\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939\u4E2D\u627E\u5230\u4FDD\u5B58\u7684\u9879\u76EE\u7ECF\u7EAA\u4EBA\uFF0C\u5B83\u4F4D\u4E8E \u4E2A\u4EBA/\u5B58\u6863/[course's name]/projectbroker_[id] nodechoose.intro.ta=\u9009\u62E9\u4E00\u4E2A\u8BFE\u7A0B\u5143\u7D20\u5F52\u6863\u5176tasks/solutions. \u8BE5\u5F52\u6863\u5B58\u653E\u5728\u4F60\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939n private/archive/[course name]/task_[name of course element]\u4E2D. nodechoose.intro.wiki=\u9009\u62E9\u4E00\u4E2A\u8BFE\u7A0B\u5143\u7D20\u5F52\u6863\u5176wiki. \u8BE5\u5F52\u6863\u5B58\u653E\u5728\u4F60\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939 private/archive/[course name]/wiki_[date] \u4E2D. +nodechoose.intro.scorm=\u8BF7\u5728\u4EE5\u4E0B\u5BF9\u8BDD\u6846\u4E2D\u9009\u62E9\u8981\u8BC4\u4EF7\u7684SCORM\u5143\u7D20\u3002\u5B58\u50A8\u7684\u6210\u7EE9\u53EF\u4EE5\u5728\u60A8\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939\u4E2D\u627E\u5230\uFF0C\u5B83\u4F4D\u4E8E \u4E2A\u4EBA/\u5B58\u50A8/[course name]/[file name]\u3002 overview.nonodes.dialog=\u8BE5\u8BFE\u7A0B\u4E0D\u5305\u542B\u4EFB\u4F55\u6587\u4EF6\u8BA8\u8BBA overview.nonodes.fo=\u8BE5\u8BFE\u7A0B\u4E0D\u5305\u542B\u4EFB\u4F55\u8BBA\u575B overview.nonodes.projectbroker=\u672C\u5B66\u7A0B\u4E0D\u5305\u542B\u4EFB\u4F55\u9879\u76EE\u7ECF\u7EAA\u4EBA\u3002 overview.nonodes.ta=\u8BE5\u8BFE\u7A0B\u4E0D\u5305\u542B\u4EFB\u4F55\u4EFB\u52A1\u5143\u7D20 overview.nonodes.wiki=\u8BE5\u8BFE\u7A0B\u4E0D\u5305\u542B\u4EFB\u4F55wiki +overview.nonodes.scorm=\u672C\u5B66\u7A0B\u4E0D\u5305\u542B\u4EFB\u4F55SCORM\u5143\u7D20\u3002 projectbroker=\u9879\u76EE\u7ECF\u7EAA\u4EBA readme=\u63D0\u793A\n\n\u4F5C\u4E3A\u4E00\u4E2A\u5F52\u6863\u6570\u636E\u7684\u63A5\u53D7\u8005\uFF0C\u4F60\u5FC5\u987B\u786E\u4FDD\u8BE5\u6570\u636E\u53EA\u6709\u5728\u88AB\u6388\u6743\u7684\u60C5\u51B5\u4E0B\u624D\u88AB\u4F7F\u7528\u3002n \n \n- \u8DDF\u5927\u5B66\u95EE\u9898\u6709\u5173\u7684\u4E2A\u4EBA\u6570\u636E\u53EF\u7528\u4E8E\u7814\u7A76\uFF0C\u6559\u5B66\u548C\u8BC4\u4F30\u3002\n \n- \u533F\u540D\u6570\u636E\u4E5F\u53EF\u7528\u4E8E\u6570\u636E\u7EDF\u8BA1\u3002n \n- \u53EA\u8981\u6709\u5FC5\u8981\uFF0C\u8FD8\u53EF\u4EE5\u5F52\u6863\u4E2A\u4EBA\u6570\u636E\u3002\n \n- \u4E0D\u5FC5\u8981\u7684\u6570\u636E\u5FC5\u987B\u5220\u9664\u3002 showfile=\u663E\u793A\u6587\u4EF6 diff --git a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_zh_TW.properties index 2b895b7e8e5ea5fd97e9d203f6a7676edf3baa01..980baa6ed6f6f4824f497cf0212b1d946a510f43 100644 --- a/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_zh_TW.properties +++ b/src/main/java/org/olat/course/archiver/_i18n/LocalStrings_zh_TW.properties @@ -89,6 +89,8 @@ menu.scoreaccounting=\u8AB2\u7A0B\u7D50\u679C menu.scoreaccounting.alt=\u5099\u4EFD\u4F86\u81EA\u6E2C\u9A57\u3001\u8A55\u4F30\u548C\u4EFB\u52D9\u7684\u6700\u7D42\u7D50\u679C menu.wikis=Wikis menu.wikis.alt=\u5099\u4EFD Wikis +menu.scorm=SCORM \u7D50\u679C +menu.scorm.alt=SCORM \u7D50\u679C nodechoose.intro.dialog=\u9078\u64C7\u4E00\u500B\u8AB2\u7A0B\u5143\u7D20\u4F86\u5099\u4EFD\u5B83\u7684\u6A94\u6848\u5C0D\u8A71\u6846\u3002\u9019\u500B\u5099\u4EFD\u7684\u5C0D\u8A71\u6846\u53EF\u4EE5\u5728\u60A8\u7684\u500B\u4EBA\u8CC7\u6599\u593E\u4E2D\u627E\u5230\uFF0C \u5728\u8DEF\u5F91 private/archive/[course name]/file dialog_[forum_id]\u3002 nodechoose.intro.fo=\u9078\u64C7\u4E00\u500B\u8AB2\u7A0B\u5143\u7D20\u4F86\u5099\u4EFD\u5B83\u7684\u8AD6\u58C7\u3002 \u9019\u500B\u5099\u4EFD\u7684\u8AD6\u58C7\u53EF\u4EE5\u5728\u60A8\u7684\u500B\u4EBA\u8CC7\u6599\u593E\u4E2D\u627E\u5230\uFF0C\u5728\u8DEF\u5F91 private/archive/[course name]/forum_[forum_id]\u3002 nodechoose.intro.ta=\u9078\u64C7\u4E00\u500B\u8AB2\u7A0B\u5143\u7D20\u4EE5\u5099\u4EFD\u5B83\u7684\u4EFB\u52D9/\u89E3\u7B54\u3002\u9019\u4E9B\u5099\u4EFD\u7684\u4EFB\u52D9/\u89E3\u7B54\u662F\u5132\u5B58\u5728\u60A8\u7684\u500B\u4EBA\u8CC7\u6599\u593E\u7684 private/archive/[course name]/task_[name of course element] \u90E8\u5206\u4E0B\u7684 zip \u6A94\u3002 @@ -97,6 +99,7 @@ overview.nonodes.dialog=\u9019\u500B\u8AB2\u7A0B\u4E26\u6C92\u6709\u5305\u542B\u overview.nonodes.fo=\u9019\u500B\u8AB2\u7A0B\u4E26\u6C92\u6709\u5305\u542B\u4EFB\u4F55\u8AD6\u58C7\u3002 overview.nonodes.ta=\u9019\u500B\u8AB2\u7A0B\u4E26\u6C92\u6709\u5305\u542B\u4EFB\u4F55\u4EFB\u52D9\u5143\u7D20\u3002 overview.nonodes.wiki=\u9019\u500B\u8AB2\u7A0B\u4E26\u6C92\u6709\u5305\u542B\u4EFB\u4F55 Wikis\u3002 +overview.nonodes.scorm=\u9019\u500B\u8AB2\u7A0B\u4E26\u6C92\u6709\u5305\u542B\u4EFB\u4F55 SCORM \u5143\u7D20\u3002 readme=\u63D0\u793A \n \n \u8EAB\u70BA\u5099\u4EFD\u8CC7\u6599\u7684\u6536\u4EF6\u4EBA\u60A8\u5FC5\u9808\u5C0D\u9019\u4E9B\u8CC7\u6599\u53EA\u6709\u7D93\u904E\u8A31\u53EF\u624D\u53EF\u4EE5\u4F7F\u7528\u8CA0\u8CAC\u3002 \n \n \n- \u53EA\u8981\u8DDF\u5927\u5B78\u8B70\u984C\u76F8\u95DC\uFF0C\u500B\u4EBA\u8CC7\u6599\u53EF\u4EE5\u4F5C\u70BA\u7814\u7A76\u3001\u6559\u5B78\u548C\u8A55\u4F30\u4F7F\u7528\u3002 \n \n- \u533F\u540D\u8CC7\u6599\u4E5F\u53EF\u4EE5\u7528\u4F5C\u7D71\u8A08\u76EE\u7684\u3002\n \n- \u500B\u4EBA\u8CC7\u6599\u50C5\u80FD\u5728\u9700\u8981\u6642\u5099\u4EFD\u3002\n \n- \u4E0D\u9700\u8981\u7684\u8CC7\u6599\u5FC5\u9808\u88AB\u522A\u9664\u3002 showfile=\u986F\u793A\u6A94\u6848 ta=\u4EFB\u52D9/\u89E3\u7B54 diff --git a/src/main/java/org/olat/course/assessment/AssessmentMainController.java b/src/main/java/org/olat/course/assessment/AssessmentMainController.java index 8f4951e49f580ac2bf9add5763f703d4037fd3f2..6d668be6d8a39977f70bc7c5cc842cbf9289b58f 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentMainController.java +++ b/src/main/java/org/olat/course/assessment/AssessmentMainController.java @@ -27,7 +27,6 @@ package org.olat.course.assessment; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -99,6 +98,7 @@ import org.olat.course.nodes.CourseNodeFactory; import org.olat.course.nodes.ProjectBrokerCourseNode; import org.olat.course.nodes.STCourseNode; import org.olat.course.properties.CoursePropertyManager; +import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironmentImpl; import org.olat.group.BusinessGroup; @@ -208,7 +208,7 @@ public class AssessmentMainController extends MainLayoutBasicController implemen * @param course * @param assessmentCallback */ - AssessmentMainController(UserRequest ureq, WindowControl wControl, StackedController stackPanel, OLATResourceable ores, IAssessmentCallback assessmentCallback) { + public AssessmentMainController(UserRequest ureq, WindowControl wControl, StackedController stackPanel, OLATResourceable ores, IAssessmentCallback assessmentCallback) { super(ureq, wControl); onyxModule = CoreSpringFactory.getImpl(OnyxModule.class); @@ -518,8 +518,8 @@ public class AssessmentMainController extends MainLayoutBasicController implemen if (actionid.equals(CMD_SELECT_NODE)) { ICourse course = CourseFactory.loadCourse(ores); int rowid = te.getRowId(); - Map<String,Object> nodeData = (Map<String,Object>) nodeTableModel.getObject(rowid); - CourseNode node = course.getRunStructure().getNode((String) nodeData.get(AssessmentHelper.KEY_IDENTIFYER)); + NodeTableRow nodeData = nodeTableModel.getObject(rowid); + CourseNode node = course.getRunStructure().getNode(nodeData.getIdent()); this.currentCourseNode = (AssessableCourseNode) node; // cast should be save, only assessable nodes are selectable if((repoTutor && coachedGroups.isEmpty()) || (callback.mayAssessAllUsers() || callback.mayViewAllUsersAssessments())) { @@ -531,8 +531,8 @@ public class AssessmentMainController extends MainLayoutBasicController implemen } else if (actionid.equals(CMD_SHOW_ONYXREPORT)) { int rowid = te.getRowId(); ICourse course = CourseFactory.loadCourse(ores); - Map<String, Object> nodeData = (Map<String, Object>) nodeTableModel.getObject(rowid); - CourseNode node = course.getRunStructure().getNode((String) nodeData.get(AssessmentHelper.KEY_IDENTIFYER)); + NodeTableRow nodeData = nodeTableModel.getObject(rowid); + CourseNode node = course.getRunStructure().getNode(nodeData.getIdent()); this.currentCourseNode = (AssessableCourseNode) node; this.onyxReporterBackLocation = "nodeListCtr"; if (!showOnyxReporter(ureq)) { @@ -807,6 +807,20 @@ public class AssessmentMainController extends MainLayoutBasicController implemen AssessedIdentitiesTableDataModel tdm = new AssessedIdentitiesTableDataModel(wrappedIdentities, courseNode, getLocale(), isAdministrativeUser); tdm.addColumnDescriptors(userListCtr, CMD_CHOOSE_USER, mode == MODE_NODEFOCUS || mode == MODE_GROUPFOCUS || mode == MODE_USERFOCUS); userListCtr.setTableDataModel(tdm); + + List<String> toolCmpNames = new ArrayList<>(3); + if(courseNode != null) { + CourseEnvironment courseEnv = course.getCourseEnvironment(); + List<Controller> tools = courseNode.createAssessmentTools(ureq, getWindowControl(), courseEnv, group); + int count = 0; + for(Controller tool:tools) { + listenTo(tool); + String toolCmpName = "ctrl_" + (count++); + userChoose.put(toolCmpName, tool.getInitialComponent()); + toolCmpNames.add(toolCmpName); + } + } + userChoose.contextPut("toolCmpNames", toolCmpNames); if (mode == MODE_USERFOCUS) { userChoose.contextPut("showBack", Boolean.FALSE); @@ -890,7 +904,7 @@ public class AssessmentMainController extends MainLayoutBasicController implemen // get list of course node data and populate table data model CourseNode rootNode = course.getRunStructure().getRootNode(); - List<Map<String, Object>> nodesTableObjectArrayList = addAssessableNodesAndParentsToList(0, rootNode); + List<NodeTableRow> nodesTableObjectArrayList = addAssessableNodesAndParentsToList(0, rootNode); // only populate data model if data available if (nodesTableObjectArrayList == null) { @@ -927,12 +941,12 @@ public class AssessmentMainController extends MainLayoutBasicController implemen * @param courseNode * @return A list of maps containing the node data */ - private List<Map<String, Object>> addAssessableNodesAndParentsToList(int recursionLevel, CourseNode courseNode) { + private List<NodeTableRow> addAssessableNodesAndParentsToList(int recursionLevel, CourseNode courseNode) { // 1) Get list of children data using recursion of this method - List<Map<String, Object>> childrenData = new ArrayList<Map<String, Object>>(); + List<NodeTableRow> childrenData = new ArrayList<>(); for (int i = 0; i < courseNode.getChildCount(); i++) { CourseNode child = (CourseNode) courseNode.getChildAt(i); - List<Map<String, Object>> childData = addAssessableNodesAndParentsToList( (recursionLevel + 1), child); + List<NodeTableRow> childData = addAssessableNodesAndParentsToList( (recursionLevel + 1), child); if (childData != null) childrenData.addAll(childData); } @@ -942,26 +956,18 @@ public class AssessmentMainController extends MainLayoutBasicController implemen // TODO:cg 04.11.2010 ProjectBroker : no assessment-tool in V1.0 , remove projectbroker completely form assessment-tool gui // Store node data in hash map. This hash map serves as data model for // the user assessment overview table. Leave user data empty since not used in // this table. (use only node data) - Map<String,Object> nodeData = new HashMap<String, Object>(); - // indent - nodeData.put(AssessmentHelper.KEY_INDENT, new Integer(recursionLevel)); - // course node data - nodeData.put(AssessmentHelper.KEY_TYPE, courseNode.getType()); - nodeData.put(AssessmentHelper.KEY_TITLE_SHORT, courseNode.getShortTitle()); - + NodeTableRow nodeData = new NodeTableRow(recursionLevel, courseNode); if (courseNode.getReferencedRepositoryEntry() != null) { if (OnyxModule.isOnyxTest(courseNode.getReferencedRepositoryEntry().getOlatResource())) { - nodeData.put(KEY_IS_ONYX, Boolean.TRUE); + nodeData.setOnyx(true); if (getAllAssessableIdentities().size() <= 0) { - nodeData.put(KEY_IS_ONYX, Boolean.FALSE); + nodeData.setOnyx(false); } } else { - nodeData.put(KEY_IS_ONYX, Boolean.FALSE); + nodeData.setOnyx(false); } } - nodeData.put(AssessmentHelper.KEY_TITLE_LONG, courseNode.getLongTitle()); - nodeData.put(AssessmentHelper.KEY_IDENTIFYER, courseNode.getIdent()); if (courseNode instanceof AssessableCourseNode) { AssessableCourseNode assessableCourseNode = (AssessableCourseNode) courseNode; @@ -977,37 +983,37 @@ public class AssessmentMainController extends MainLayoutBasicController implemen if(assessableCourseNode.hasScoreConfigured()) { if(!(courseNode instanceof STCourseNode)) { Float min = assessableCourseNode.getMinScoreConfiguration(); - nodeData.put(AssessmentHelper.KEY_MIN, min); + nodeData.setMinScore(min); Float max = assessableCourseNode.getMaxScoreConfiguration(); - nodeData.put(AssessmentHelper.KEY_MAX, max); + nodeData.setMaxScore(max); } } if (assessableCourseNode.isEditableConfigured()) { // Assessable course nodes are selectable when they are aditable - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.TRUE); + nodeData.setSelectable(true); } else if (courseNode instanceof STCourseNode && (assessableCourseNode.hasScoreConfigured() || assessableCourseNode.hasPassedConfigured())) { // st node is special case: selectable on node choose list as soon as it // has score or passed - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.TRUE); + nodeData.setSelectable(true); } else { // assessable nodes that do not have score or passed are not selectable // (e.g. a st node with no defined rule - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.FALSE); + nodeData.setSelectable(false); } } else { // Not assessable nodes are not selectable. (e.g. a node that // has an assessable child node but is itself not assessable) - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.FALSE); + nodeData.setSelectable(false); } // 3) Add data of this node to mast list if node assessable or children list has any data. // Do only add nodes when they have any assessable element, otherwhise discard (e.g. empty course, // structure nodes without scoring rules)! When the discardEmptyNodes flag is set then only // add this node when there is user data found for this node. if (childrenData.size() > 0 || hasDisplayableValuesConfigured) { - List<Map<String, Object>> nodeAndChildren = new ArrayList<Map<String, Object>>(); + List<NodeTableRow> nodeAndChildren = new ArrayList<>(); nodeAndChildren.add(nodeData); // 4) Add children data list to master list nodeAndChildren.addAll(childrenData); diff --git a/src/main/java/org/olat/course/assessment/AssessmentUIFactory.java b/src/main/java/org/olat/course/assessment/AssessmentUIFactory.java index 0c0e3f3cbca6d22e2a6b253a9fe44f43e9b0b45d..178eeead546cbec75a9e505d8e4947502b1901c4 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentUIFactory.java +++ b/src/main/java/org/olat/course/assessment/AssessmentUIFactory.java @@ -24,19 +24,13 @@ */ package org.olat.course.assessment; -import java.util.List; - import org.olat.core.gui.UserRequest; -import org.olat.core.gui.components.stack.StackedController; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; -import org.olat.core.gui.control.generic.dtabs.Activateable2; -import org.olat.core.id.OLATResourceable; import org.olat.core.util.notifications.ContextualSubscriptionController; import org.olat.core.util.notifications.PublisherData; import org.olat.core.util.notifications.SubscriptionContext; import org.olat.course.ICourse; -import org.olat.ims.qti.export.QTIArchiveWizardController; /** * Description:<br> @@ -47,16 +41,6 @@ import org.olat.ims.qti.export.QTIArchiveWizardController; * @author patrickb */ public class AssessmentUIFactory { - - - public static Activateable2 createAssessmentMainController(UserRequest ureq, WindowControl wControl, StackedController stackPanel, OLATResourceable ores, IAssessmentCallback assessmentCallback) { - return new AssessmentMainController(ureq, wControl, stackPanel, ores, assessmentCallback); - } - - public static Controller createQTIArchiveWizardController(boolean dummyMode, UserRequest ureq, List nodesTableObjectArrayList, ICourse course, - WindowControl wControl) { - return new QTIArchiveWizardController(dummyMode, ureq, nodesTableObjectArrayList, course, wControl); - } /** * diff --git a/src/main/java/org/olat/course/assessment/EfficiencyStatementArchiver.java b/src/main/java/org/olat/course/assessment/EfficiencyStatementArchiver.java index 0f65142db52003e23e61b0fba0581f32b2128b95..d1f8a97afd70c1f0f288439ee6cc6095b8287255 100644 --- a/src/main/java/org/olat/course/assessment/EfficiencyStatementArchiver.java +++ b/src/main/java/org/olat/course/assessment/EfficiencyStatementArchiver.java @@ -30,7 +30,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.olat.core.gui.translator.PackageTranslator; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; import org.olat.core.util.FileUtils; @@ -61,10 +60,8 @@ public class EfficiencyStatementArchiver { * constructs an unitialised BusinessGroup, use setXXX for setting attributes */ public EfficiencyStatementArchiver() { - String myPackage = Util.getPackageName(this.getClass()); - String courseNodePackage = Util.getPackageName(CourseNode.class); - PackageTranslator fallBackTranslator = new PackageTranslator(courseNodePackage, I18nModule.getDefaultLocale()); - translator = new PackageTranslator(myPackage, I18nModule.getDefaultLocale(), fallBackTranslator); + Translator fallBackTranslator = Util.createPackageTranslator(CourseNode.class, I18nModule.getDefaultLocale()); + translator = Util.createPackageTranslator(this.getClass(), I18nModule.getDefaultLocale(), fallBackTranslator); // fallback for user properties translation translator = UserManager.getInstance().getPropertyHandlerTranslator(translator); // list of user property handlers used in this archiver @@ -75,19 +72,19 @@ public class EfficiencyStatementArchiver { return instance; } - public void archive(List efficiencyStatements, Identity identity, File archiveFile) { + public void archive(List<EfficiencyStatement> efficiencyStatements, Identity identity, File archiveFile) { FileUtils.save(new File(archiveFile, EFFICIENCY_ARCHIVE_FILE), toXls(efficiencyStatements, identity), "utf-8"); } - private String toXls(List efficiencyStatements, Identity identity) { - StringBuffer buf = new StringBuffer(); + private String toXls(List<EfficiencyStatement> efficiencyStatements, Identity identity) { + StringBuilder buf = new StringBuilder(); buf.append(translator.translate("efficiencystatement.title")); appendIdentityIntro(buf, identity); - for (Iterator iter = efficiencyStatements.iterator(); iter.hasNext();) { + for (Iterator<EfficiencyStatement> iter = efficiencyStatements.iterator(); iter.hasNext();) { buf.append(EOL); buf.append(EOL); - EfficiencyStatement efficiencyStatement = (EfficiencyStatement) iter.next(); + EfficiencyStatement efficiencyStatement = iter.next(); appendIntro(buf, efficiencyStatement); buf.append(EOL); appendDetailsHeader(buf); @@ -96,7 +93,7 @@ public class EfficiencyStatementArchiver { return buf.toString(); } - private void appendDetailsHeader(StringBuffer buf) { + private void appendDetailsHeader(StringBuilder buf) { buf.append( translator.translate("table.header.node") ); buf.append(DELIMITER); buf.append( translator.translate("table.header.details") ); @@ -111,9 +108,9 @@ public class EfficiencyStatementArchiver { buf.append(EOL); } - private void appendDetailsTable(StringBuffer buf, EfficiencyStatement efficiencyStatement) { - for (Iterator iter = efficiencyStatement.getAssessmentNodes().iterator(); iter.hasNext();) { - Map nodeData = (Map) iter.next(); + private void appendDetailsTable(StringBuilder buf, EfficiencyStatement efficiencyStatement) { + for (Iterator<Map<String,Object>> iter = efficiencyStatement.getAssessmentNodes().iterator(); iter.hasNext();) { + Map<String,Object> nodeData = iter.next(); appendValue(buf, nodeData, AssessmentHelper.KEY_TITLE_SHORT); appendValue(buf, nodeData, AssessmentHelper.KEY_TITLE_LONG); appendTypeValue(buf, nodeData, AssessmentHelper.KEY_TYPE); @@ -124,7 +121,7 @@ public class EfficiencyStatementArchiver { } } - private void appendTypeValue(StringBuffer buf, Map nodeData, String key_type) { + private void appendTypeValue(StringBuilder buf, Map<String,Object> nodeData, String key_type) { Object value = nodeData.get(key_type); if (value != null && (value instanceof String)) { String valueString = (String)value; @@ -139,7 +136,7 @@ public class EfficiencyStatementArchiver { buf.append(DELIMITER); } - private void appendIdentityIntro(StringBuffer buf, Identity identity) { + private void appendIdentityIntro(StringBuilder buf, Identity identity) { for (UserPropertyHandler propertyHandler : userPropertyHandler) { String label = translator.translate(propertyHandler.i18nColumnDescriptorLabelKey()); String value = propertyHandler.getUserProperty(identity.getUser(), translator.getLocale()); @@ -147,19 +144,19 @@ public class EfficiencyStatementArchiver { } } - private void appendIntro(StringBuffer buf, EfficiencyStatement efficiencyStatement) { + private void appendIntro(StringBuilder buf, EfficiencyStatement efficiencyStatement) { buf.append(EOL); appendLine(buf, translator.translate("course"), efficiencyStatement.getCourseTitle() + " (" + efficiencyStatement.getCourseRepoEntryKey().toString() +")"); appendLine(buf, translator.translate("date"), StringHelper.formatLocaleDateTime(efficiencyStatement.getLastUpdated(), I18nModule.getDefaultLocale()) ); - Map nodeData = (Map)efficiencyStatement.getAssessmentNodes().get(0); + Map<String,Object> nodeData = efficiencyStatement.getAssessmentNodes().get(0); if (nodeData != null) { appendLabelValueLine(buf, nodeData, translator.translate("table.header.score"), AssessmentHelper.KEY_SCORE); appendLabelValueLine(buf, nodeData, translator.translate("table.header.passed"), AssessmentHelper.KEY_PASSED); } } - private void appendValue(StringBuffer buf, Map nodeData, String key) { + private void appendValue(StringBuilder buf, Map<String,Object> nodeData, String key) { Object value = nodeData.get(key); if (value != null) { buf.append(value); @@ -169,22 +166,7 @@ public class EfficiencyStatementArchiver { buf.append(DELIMITER); } - private void appendValuePassed(StringBuffer buf, Map nodeData, String key) { - Object value = nodeData.get(key); - if (value != null && (value instanceof Boolean) ) { - if ( ((Boolean)value).booleanValue() ) { - translator.translate("form.passed.true"); - } else { - translator.translate("form.passed.false"); - } - buf.append(value); - } else { - buf.append(""); - } - buf.append(DELIMITER); - } - - private void appendLabelValueLine(StringBuffer buf, Map nodeData, String label, String key) { + private void appendLabelValueLine(StringBuilder buf, Map<String,Object> nodeData, String label, String key) { buf.append(label); buf.append(DELIMITER); Object value = nodeData.get(key); @@ -196,13 +178,11 @@ public class EfficiencyStatementArchiver { buf.append(EOL); } - private void appendLine(StringBuffer buf, String label, String value) { + private void appendLine(StringBuilder buf, String label, String value) { buf.append(label); buf.append(DELIMITER); buf.append(value); buf.append(DELIMITER); buf.append(EOL); } - - } \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/IndentedNodeRenderer.java b/src/main/java/org/olat/course/assessment/IndentedNodeRenderer.java index 9be00d20747e3f686eef4eb17307dc33acbae269..86cb08884464c6d624b76a180c33c783844cce17 100644 --- a/src/main/java/org/olat/course/assessment/IndentedNodeRenderer.java +++ b/src/main/java/org/olat/course/assessment/IndentedNodeRenderer.java @@ -69,18 +69,30 @@ public class IndentedNodeRenderer implements CustomCellRenderer { * @see org.olat.core.gui.components.table.CustomCellRenderer#render(org.olat.core.gui.render.StringOutput, org.olat.core.gui.render.Renderer, java.lang.Object, java.util.Locale, int, java.lang.String) */ public void render(StringOutput sb, Renderer renderer, Object val, Locale locale, int alignment, String action) { - Map nodeData = (Map) val; - Integer indent = (Integer) nodeData.get(AssessmentHelper.KEY_INDENT); - String type = (String) nodeData.get(AssessmentHelper.KEY_TYPE); - - String cssClass = CourseNodeFactory.getInstance().getCourseNodeConfigurationEvenForDisabledBB(type).getIconCSSClass(); - String title = (String) nodeData.get(AssessmentHelper.KEY_TITLE_SHORT); - String altText = (String) nodeData.get(AssessmentHelper.KEY_TITLE_LONG); + int indent; + String type; + String title; + String altText; + if(val instanceof Map) { + Map nodeData = (Map) val; + Integer indentObj = (Integer) nodeData.get(AssessmentHelper.KEY_INDENT); + indent = (indentObj == null ? 0 : indentObj.intValue()); + type = (String)nodeData.get(AssessmentHelper.KEY_TYPE); + title = (String)nodeData.get(AssessmentHelper.KEY_TITLE_SHORT); + altText = (String)nodeData.get(AssessmentHelper.KEY_TITLE_LONG); + } else if(val instanceof NodeTableRow) { + NodeTableRow row = (NodeTableRow)val; + indent = row.getIndent(); + type = row.getType(); + title = row.getShortTitle(); + altText = row.getLongTitle(); + } else { + return; + } - //fxdiff VCRP-4: assessment overview with max score + String cssClass = CourseNodeFactory.getInstance().getCourseNodeConfigurationEvenForDisabledBB(type).getIconCSSClass(); if(isIndentationEnabled()) { - Integer indentation = (Integer) nodeData.get(AssessmentHelper.KEY_INDENT); - appendIndent(sb,indentation); + appendIndent(sb, indent); } sb.append("<span class=\"b_with_small_icon_left ").append(cssClass); @@ -91,12 +103,10 @@ public class IndentedNodeRenderer implements CustomCellRenderer { sb.append(StringHelper.escapeHtml(title)); sb.append("</span>"); } - - private void appendIndent(StringOutput sb, Integer indent) { - for (int i = 0; i < indent.intValue(); i++) { + private void appendIndent(StringOutput sb, int indent) { + for (int i = 0; i < indent; i++) { sb.append(INDENT); } - } - -} + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/NodeTableDataModel.java b/src/main/java/org/olat/course/assessment/NodeTableDataModel.java index 3bdd52d137d7d615ae052d9c59a5c48c2d1fc851..daac695cef0293ddcb51e4a07b77b98d3591ba7f 100644 --- a/src/main/java/org/olat/course/assessment/NodeTableDataModel.java +++ b/src/main/java/org/olat/course/assessment/NodeTableDataModel.java @@ -26,7 +26,6 @@ package org.olat.course.assessment; import java.util.List; -import java.util.Map; import org.olat.core.gui.components.table.DefaultTableDataModel; import org.olat.core.gui.translator.Translator; @@ -39,18 +38,16 @@ import org.olat.core.gui.translator.Translator; * Comment: * Use the IndentedNodeRenderer to render the node element! */ - - -public class NodeTableDataModel extends DefaultTableDataModel { - private Translator trans; +public class NodeTableDataModel extends DefaultTableDataModel<NodeTableRow> { + private final Translator trans; /** * Constructor for the node table - * @param objects List maps containting the node data using the keys defined in AssessmentHelper + * @param objects List maps containing the node data using the keys defined in AssessmentHelper * @param trans The table model translator * any node select link */ - public NodeTableDataModel(List objects, Translator trans) { + public NodeTableDataModel(List<NodeTableRow> objects, Translator trans) { super(objects); this.trans = trans; } @@ -58,43 +55,26 @@ public class NodeTableDataModel extends DefaultTableDataModel { /** * @see org.olat.core.gui.components.table.TableDataModel#getColumnCount() */ + @Override public int getColumnCount() { - // node, select + // node, select return 2; } /** * @see org.olat.core.gui.components.table.TableDataModel#getValueAt(int, int) */ + @Override public Object getValueAt(int row, int col) { - Map nodeData = (Map) getObject(row); + NodeTableRow nodeData = getObject(row); switch (col) { - case 0: - // rendered using the indentedNodeRenderer - return nodeData; - case 1: - // selection command - Boolean courseNodeEditable = (Boolean) nodeData.get(AssessmentHelper.KEY_SELECTABLE); - if (courseNodeEditable.booleanValue()) return trans.translate("select"); - else return null; - //fxdiff VCRP-4: assessment overview with max score - case 2: - //min score - return nodeData.get(AssessmentHelper.KEY_MIN); - case 3: - //min score - return nodeData.get(AssessmentHelper.KEY_MAX); - case 4: - // show OnyxReport - final Boolean courseNodeIsOnyx = (Boolean) nodeData.get(AssessmentMainController.KEY_IS_ONYX); - if (courseNodeIsOnyx != null && courseNodeIsOnyx.booleanValue()) { - return trans.translate("table.action.showOnyxReporter"); - } else { - return ""; - } - default: - return "error"; - } + case 0: return nodeData;// rendered using the indentedNodeRenderer + case 1: return nodeData.isSelectable() ? trans.translate("select") : null; + case 2: return nodeData.getMinScore(); + case 3: return nodeData.getMaxScore(); + case 4: return nodeData.isOnyx() ? trans.translate("table.action.showOnyxReporter") : ""; + default: return "error"; + } } public enum Cols { diff --git a/src/main/java/org/olat/course/assessment/NodeTableRow.java b/src/main/java/org/olat/course/assessment/NodeTableRow.java new file mode 100644 index 0000000000000000000000000000000000000000..e684796b75faa01f932de5f865a8da18dcdf249b --- /dev/null +++ b/src/main/java/org/olat/course/assessment/NodeTableRow.java @@ -0,0 +1,111 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.assessment; + +import org.olat.course.nodes.CourseNode; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class NodeTableRow { + + private final int indent; + private final String ident; + private final String type; + private final String shortTitle; + private final String longTitle; + + private Float minScore; + private Float maxScore; + + private boolean selectable; + private boolean onyx = false; + + public NodeTableRow(int indent, CourseNode courseNode) { + this(indent, courseNode.getIdent(), courseNode.getType(), courseNode.getShortTitle(), courseNode.getLongTitle()); + } + + public NodeTableRow(int indent, String ident, String type, String shortTitle, String longTitle) { + this.indent = indent; + this.ident = ident; + this.type = type; + this.shortTitle = shortTitle; + this.longTitle = longTitle; + } + + public int getIndent() { + return indent; + } + + public String getIdent() { + return ident; + } + + public String getType() { + return type; + } + + + public String getShortTitle() { + return shortTitle; + } + + public String getLongTitle() { + return longTitle; + } + + public Float getMinScore() { + return minScore; + } + + + public void setMinScore(Float minScore) { + this.minScore = minScore; + } + + + public Float getMaxScore() { + return maxScore; + } + + + public void setMaxScore(Float maxScore) { + this.maxScore = maxScore; + } + + + public boolean isSelectable() { + return selectable; + } + + public void setSelectable(boolean selectable) { + this.selectable = selectable; + } + + public boolean isOnyx() { + return onyx; + } + + public void setOnyx(boolean onyx) { + this.onyx = onyx; + } +} diff --git a/src/main/java/org/olat/course/assessment/_content/userchoose.html b/src/main/java/org/olat/course/assessment/_content/userchoose.html index 85d417f4086a19e01dc833b8da32cfbae9faf3ef..969f389fb23440bf4ecc549a7a8987ed2c903650 100644 --- a/src/main/java/org/olat/course/assessment/_content/userchoose.html +++ b/src/main/java/org/olat/course/assessment/_content/userchoose.html @@ -23,4 +23,12 @@ <div style="clear:right"> $r.render("userlisttable") </div> +#if ($toolCmpNames) + <div class="b_button_group"> + #foreach($toolCmpName in $toolCmpNames) + $r.render($toolCmpName) + #end + </div> +#end + \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/bulk/BulkAssessmentToolController.java b/src/main/java/org/olat/course/assessment/bulk/BulkAssessmentToolController.java new file mode 100644 index 0000000000000000000000000000000000000000..8c0174a1c44e9092e71d1ed2a7ee0b020bf1bc1f --- /dev/null +++ b/src/main/java/org/olat/course/assessment/bulk/BulkAssessmentToolController.java @@ -0,0 +1,170 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.assessment.bulk; + +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.services.taskexecutor.TaskExecutorManager; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.control.generic.modal.DialogBoxController; +import org.olat.core.gui.control.generic.wizard.Step; +import org.olat.core.gui.control.generic.wizard.StepRunnerCallback; +import org.olat.core.gui.control.generic.wizard.StepsMainRunController; +import org.olat.core.gui.control.generic.wizard.StepsRunContext; +import org.olat.course.assessment.manager.BulkAssessmentTask; +import org.olat.course.assessment.model.BulkAssessmentDatas; +import org.olat.course.assessment.model.BulkAssessmentFeedback; +import org.olat.course.nodes.AssessableCourseNode; +import org.olat.course.run.environment.CourseEnvironment; +import org.olat.resource.OLATResource; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class BulkAssessmentToolController extends BasicController { + + private final Link startButton; + private final VelocityContainer mainVC; + private final AssessableCourseNode courseNode; + + private DialogBoxController errorCtrl; + private StepsMainRunController bulkAssessmentCtrl; + private final TaskExecutorManager taskManager; + private final OLATResource courseOres; + + public BulkAssessmentToolController(UserRequest ureq, WindowControl wControl, CourseEnvironment courseEnv, AssessableCourseNode courseNode) { + super(ureq, wControl); + this.courseNode = courseNode; + taskManager = CoreSpringFactory.getImpl(TaskExecutorManager.class); + courseOres = courseEnv.getCourseGroupManager().getCourseResource(); + + mainVC = createVelocityContainer("start_button"); + startButton = LinkFactory.createButton("bulk.wizard.title", mainVC, this); + putInitialPanel(mainVC); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(startButton == source) { + doOpen(ureq); + } + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(bulkAssessmentCtrl == source) { + if(event == Event.CANCELLED_EVENT || event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { + getWindowControl().pop(); + Feedback feedback = (Feedback)bulkAssessmentCtrl.getRunContext().get("feedback"); + removeAsListenerAndDispose(bulkAssessmentCtrl); + bulkAssessmentCtrl = null; + if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { + doBulkAssessmentSynchronous(ureq, feedback); + } + } + } + super.event(ureq, source, event); + } + + private void doOpen(UserRequest ureq) { + StepRunnerCallback finish = new StepRunnerCallback() { + @Override + public Step execute(UserRequest ureq, WindowControl wControl, StepsRunContext runContext) { + Date scheduledDate = (Date)runContext.get("scheduledDate"); + BulkAssessmentDatas datas = (BulkAssessmentDatas)runContext.get("datas"); + Feedback feedback = doBulkAssessment(scheduledDate, datas); + runContext.put("feedback", feedback); + return StepsMainRunController.DONE_MODIFIED; + } + }; + + Step start = new BulkAssessment_2_DatasStep(ureq, courseNode); + bulkAssessmentCtrl = new StepsMainRunController(ureq, getWindowControl(), start, finish, null, + translate("bulk.wizard.title"), "o_sel_bulk_assessment_wizard"); + listenTo(bulkAssessmentCtrl); + getWindowControl().pushAsModalDialog(bulkAssessmentCtrl.getInitialComponent()); + } + + private Feedback doBulkAssessment(Date scheduledDate, BulkAssessmentDatas datas) { + BulkAssessmentTask task = new BulkAssessmentTask(courseOres, courseNode, datas, getIdentity().getKey()); + Feedback feedback; + if(scheduledDate == null) { + List<BulkAssessmentFeedback> feedbacks = task.process(); + feedback = new Feedback(true, feedbacks); + } else { + taskManager.execute(task, getIdentity(), courseOres, courseNode.getIdent(), scheduledDate); + feedback = new Feedback(false, null); + } + return feedback; + } + + private void doBulkAssessmentSynchronous(UserRequest ureq, Feedback feedback) { + if(feedback.isSynchronous()) { + List<BulkAssessmentFeedback> feedbacks = feedback.getFeedbacks(); + if(feedbacks.isEmpty()) { + showInfo("bulk.assessment.done"); + } else { + String text = BulkAssessmentTask.renderFeedback(feedbacks, getTranslator()); + List<String> buttonLabels = Collections.singletonList(translate("ok")); + String title = translate("bulk.assessment.error.title"); + String translatedText = translate("bulk.assessment.error.feedback", new String[]{ text }); + errorCtrl = activateGenericDialog(ureq, title, translatedText, buttonLabels, errorCtrl); + } + } else { + showInfo("bulk.assessment.enlisted"); + } + } + + private static class Feedback { + private final boolean synchronous; + private final List<BulkAssessmentFeedback> feedbacks; + + public Feedback(boolean synchronous, List<BulkAssessmentFeedback> feedbacks) { + this.synchronous = synchronous; + this.feedbacks = feedbacks; + } + + public boolean isSynchronous() { + return synchronous; + } + + public List<BulkAssessmentFeedback> getFeedbacks() { + return feedbacks; + } + } +} diff --git a/src/main/java/org/olat/course/assessment/bulk/_content/start_button.html b/src/main/java/org/olat/course/assessment/bulk/_content/start_button.html new file mode 100644 index 0000000000000000000000000000000000000000..a80ea843e48f9cacf1fdf6aac3b527be629a79a0 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/bulk/_content/start_button.html @@ -0,0 +1 @@ +$r.render("bulk.wizard.title") \ No newline at end of file diff --git a/src/main/java/org/olat/course/editor/PublishProcess.java b/src/main/java/org/olat/course/editor/PublishProcess.java index caa97b8f070690d1803ce9f134d40d9256af2309..58b0a75edb0550d3c9a015ff1bcc08f808af27ee 100644 --- a/src/main/java/org/olat/course/editor/PublishProcess.java +++ b/src/main/java/org/olat/course/editor/PublishProcess.java @@ -25,13 +25,18 @@ package org.olat.course.editor; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.util.ArrayList; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.zip.ZipOutputStream; +import org.apache.poi.util.IOUtils; import org.olat.basesecurity.BaseSecurityManager; import org.olat.catalog.CatalogEntry; import org.olat.catalog.CatalogManager; @@ -42,7 +47,9 @@ import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; +import org.olat.core.util.Formatter; import org.olat.core.util.ObjectCloner; +import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.ValidationStatus; import org.olat.core.util.coordinate.CoordinatorManager; @@ -415,8 +422,7 @@ public class PublishProcess { // only clean up and archive of nodes which were already in run // save data, remove references deleteRefs(oldCn); - File exportDirectory = CourseFactory.getOrCreateDataExportDirectory(identity, course.getCourseTitle()); - oldCn.archiveNodeData(locale, course, exportDirectory, charset); + archiveDeletedNode(identity, cn, oldCn, locale, charset); // 2) delete all user data oldCn.cleanupOnDelete(course); } @@ -480,6 +486,27 @@ public class PublishProcess { */ } + + private void archiveDeletedNode(Identity identity, CourseNode cn, CourseNode oldCn, Locale locale, String charset) { + File exportDirectory = CourseFactory.getOrCreateDataExportDirectory(identity, course.getCourseTitle()); + String archiveName = cn.getType() + "_" + + StringHelper.transformDisplayNameToFileSystemName(cn.getShortName()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); + + FileOutputStream fileStream = null; + ZipOutputStream exportStream = null; + try { + File exportFile = new File(exportDirectory, archiveName); + fileStream = new FileOutputStream(exportFile); + exportStream = new ZipOutputStream(fileStream); + oldCn.archiveNodeData(locale, course, null, exportStream, charset); + } catch (FileNotFoundException e) { + log.error("", e); + } finally { + IOUtils.closeQuietly(exportStream); + IOUtils.closeQuietly(fileStream); + } + } /** * Update references of a course node in the run. If the course node is new, diff --git a/src/main/java/org/olat/course/nodes/AbstractAccessableCourseNode.java b/src/main/java/org/olat/course/nodes/AbstractAccessableCourseNode.java index 0614a067b305a4f26879a2177007727f0ca72366..8bc7d7e71ed5adfa98eca17a5e9b541636917d14 100644 --- a/src/main/java/org/olat/course/nodes/AbstractAccessableCourseNode.java +++ b/src/main/java/org/olat/course/nodes/AbstractAccessableCourseNode.java @@ -26,9 +26,11 @@ package org.olat.course.nodes; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Identity; import org.olat.course.condition.Condition; @@ -38,9 +40,11 @@ import org.olat.course.condition.additionalconditions.AdditionalConditionManager import org.olat.course.condition.interpreter.ConditionExpression; import org.olat.course.condition.interpreter.ConditionInterpreter; import org.olat.course.export.CourseEnvironmentMapper; +import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import de.bps.course.nodes.CourseNodePasswordManagerImpl; @@ -181,6 +185,12 @@ public abstract class AbstractAccessableCourseNode extends GenericCourseNode { // return retVal; } + + /** Factory method to launch course element assessment tools. limitToGroup is optional to skip he the group choose step */ + public List<Controller> createAssessmentTools(UserRequest ureq, WindowControl wControl, CourseEnvironment courseEnv, BusinessGroup limitToGroup) { + return Collections.emptyList(); + } + public List<AdditionalCondition> getAdditionalConditions(){ if(additionalConditions==null) diff --git a/src/main/java/org/olat/course/nodes/AssessableCourseNode.java b/src/main/java/org/olat/course/nodes/AssessableCourseNode.java index 5d5103163579cdc40fc62bcb2840bb60b2f2d796..c2e4b769a66d3ff669cc455a934ac6302d68868c 100644 --- a/src/main/java/org/olat/course/nodes/AssessableCourseNode.java +++ b/src/main/java/org/olat/course/nodes/AssessableCourseNode.java @@ -25,13 +25,17 @@ package org.olat.course.nodes; +import java.util.List; + import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Identity; +import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; /** @@ -144,6 +148,12 @@ public interface AssessableCourseNode extends CourseNode { * @return a controller or null if hasDetails=false */ public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl, StackedController stackPanel, UserCourseEnvironment userCourseEnvironment); + + + /** Factory method to launch course element assessment tools. limitToGroup is optional to skip he the group choose step */ + public List<Controller> createAssessmentTools(UserRequest ureq, WindowControl wControl, CourseEnvironment courseEnv, BusinessGroup limitToGroup); + + /** * * @param scoreEvaluation if scoreEvaluation.getScore() != null, then the score will be updated, and/or if scoreEvaluation.getPassed() != null, then 'passed' will be updated diff --git a/src/main/java/org/olat/course/nodes/CalCourseNode.java b/src/main/java/org/olat/course/nodes/CalCourseNode.java index 00c69118577c0776eeef27ac79d4e95ce86e4ef7..b1d660d25421eca6a1cc9b810aafbd84055fa179 100644 --- a/src/main/java/org/olat/course/nodes/CalCourseNode.java +++ b/src/main/java/org/olat/course/nodes/CalCourseNode.java @@ -21,7 +21,6 @@ package org.olat.course.nodes; import java.io.File; import java.util.List; -import java.util.Locale; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; @@ -55,6 +54,8 @@ import org.olat.repository.RepositoryEntry; */ public class CalCourseNode extends AbstractAccessableCourseNode { + private static final long serialVersionUID = -3174525063215323155L; + public static final String TYPE = "cal"; public static final String EDIT_CONDITION_ID = "editarticle"; private Condition preConditionEdit; @@ -178,14 +179,6 @@ public class CalCourseNode extends AbstractAccessableCourseNode { return null; } - /** - * @see org.olat.course.nodes.GenericCourseNode#archiveNodeData(java.util.Locale, - * org.olat.course.ICourse, java.io.File, java.lang.String) - */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - return true; - } - /** * Default set the write privileges to coaches and admin only * @return diff --git a/src/main/java/org/olat/course/nodes/CourseNode.java b/src/main/java/org/olat/course/nodes/CourseNode.java index 1ae15d31e46c8ebc6c1f1986f03cc432a21c2a9d..3009e3b60437a016cda817d4f2bbfa9f9e85dc65 100644 --- a/src/main/java/org/olat/course/nodes/CourseNode.java +++ b/src/main/java/org/olat/course/nodes/CourseNode.java @@ -28,6 +28,7 @@ package org.olat.course.nodes; import java.io.File; import java.util.List; import java.util.Locale; +import java.util.zip.ZipOutputStream; import org.olat.core.gui.ShortName; import org.olat.core.gui.UserRequest; @@ -47,6 +48,7 @@ import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.TreeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; import org.olat.repository.RepositoryEntry; @@ -297,12 +299,12 @@ public interface CourseNode extends INode, ShortName { * * @param locale The users locale * @param course The course - * @param exportDirectory The directory where the exported files should be + * @param exportStream The directory where the exported files should be * put. This directory must exist prior to calling this method. * @param value of charset property of current user * @return true if any data to be archived was found, false otherwise. */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset); + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream out, String charset); /** * Export all node user data to the given directory. This might be one file or diff --git a/src/main/java/org/olat/course/nodes/DialogCourseNode.java b/src/main/java/org/olat/course/nodes/DialogCourseNode.java index 490461dd740eab5d333770f1a1a2fd10ed4ecb6c..6c64051c437aeeb87585440c3d29c85a4b435e7e 100644 --- a/src/main/java/org/olat/course/nodes/DialogCourseNode.java +++ b/src/main/java/org/olat/course/nodes/DialogCourseNode.java @@ -26,13 +26,10 @@ package org.olat.course.nodes; import java.io.File; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.zip.ZipOutputStream; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.gui.UserRequest; @@ -42,6 +39,7 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.tabbable.TabbableController; import org.olat.core.util.Formatter; import org.olat.core.util.Util; +import org.olat.core.util.ZipUtil; import org.olat.core.util.notifications.NotificationsManager; import org.olat.core.util.notifications.SubscriptionContext; import org.olat.core.util.vfs.LocalFolderImpl; @@ -64,6 +62,7 @@ import org.olat.course.nodes.dialog.DialogCourseNodeRunController; import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; import org.olat.modules.dialog.DialogElement; import org.olat.modules.dialog.DialogElementsPropertyManager; @@ -72,6 +71,7 @@ import org.olat.modules.fo.ForumManager; import org.olat.modules.fo.archiver.ForumArchiveManager; import org.olat.modules.fo.archiver.formatters.ForumFormatter; import org.olat.modules.fo.archiver.formatters.ForumRTFFormatter; +import org.olat.modules.fo.archiver.formatters.ForumStreamedRTFFormatter; import org.olat.repository.RepositoryEntry; /** @@ -220,32 +220,6 @@ public class DialogCourseNode extends AbstractAccessableCourseNode { //delete property depm.deleteProperty(course.getResourceableId(), this.getIdent()); - - - - } - - /** - * Generic interface implementation. May be overriden by specific node's - * implementation. - * - * @see org.olat.course.nodes.CourseNode#archiveNodeData(java.util.Locale, - * org.olat.course.ICourse, java.io.File) - */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - boolean dataFound = false; - DialogElementsPropertyManager depm = DialogElementsPropertyManager.getInstance(); - DialogPropertyElements elements = depm.findDialogElements(course.getCourseEnvironment().getCoursePropertyManager(), this); - List<DialogElement> list = new ArrayList<DialogElement>(); - if (elements != null) list = elements.getDialogPropertyElements(); - - for (Iterator<DialogElement> iter = list.iterator(); iter.hasNext();) { - DialogElement element = iter.next(); - doArchiveElement(element, exportDirectory); - //at least one element found - dataFound = true; - } - return dataFound; } /** @@ -260,8 +234,7 @@ public class DialogCourseNode extends AbstractAccessableCourseNode { VFSContainer exportContainer = new LocalFolderImpl(exportDirectory); // append export timestamp to avoid overwriting previous export - DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH_mm_ss_SSS"); - String exportDirName = Formatter.makeStringFilesystemSave(getShortTitle())+"_"+element.getForumKey()+"_"+formatter.format(new Date(System.currentTimeMillis())); + String exportDirName = Formatter.makeStringFilesystemSave(getShortTitle())+"_"+element.getForumKey()+"_"+Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); VFSContainer diaNodeElemExportContainer = exportContainer.createChildContainer(exportDirName); // don't check quota diaNodeElemExportContainer.setLocalSecurityCallback(new FullAccessCallback()); @@ -269,7 +242,43 @@ public class DialogCourseNode extends AbstractAccessableCourseNode { ForumArchiveManager fam = ForumArchiveManager.getInstance(); ForumFormatter ff = new ForumRTFFormatter(diaNodeElemExportContainer, false); - fam.applyFormatter(ff, element.getForumKey().longValue(), null); + fam.applyFormatter(ff, element.getForumKey(), null); + } + + @Override + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { + boolean dataFound = false; + List<DialogElement> list = DialogElementsPropertyManager.getInstance() + .findDialogElements(course.getCourseEnvironment().getCoursePropertyManager(), this) + .getDialogPropertyElements(); + if(list.size() > 0) { + for (DialogElement element:list) { + doArchiveElement(element, exportStream); + dataFound = true; + } + } + return dataFound; + } + + /** + * Archive a single dialog element with files and forum + * @param element + * @param exportDirectory + */ + public void doArchiveElement(DialogElement element, ZipOutputStream exportStream) { + // append export timestamp to avoid overwriting previous export + String exportDirName = Formatter.makeStringFilesystemSave(getShortTitle()) + + "_" + element.getForumKey() + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); + + VFSContainer forumContainer = getForumContainer(element.getForumKey()); + for(VFSItem item: forumContainer.getItems(new VFSLeafFilter())) { + ZipUtil.addToZip(item, exportDirName, exportStream); + } + + ForumArchiveManager fam = ForumArchiveManager.getInstance(); + ForumFormatter ff = new ForumStreamedRTFFormatter(exportStream, exportDirName, false); + fam.applyFormatter(ff, element.getForumKey(), null); } /** diff --git a/src/main/java/org/olat/course/nodes/FOCourseNode.java b/src/main/java/org/olat/course/nodes/FOCourseNode.java index 05992dbb5e65f41702927d4c982af0325d51b77f..ac76d8192d433c7fae38b09fb9fe3fc6bdccbd8a 100644 --- a/src/main/java/org/olat/course/nodes/FOCourseNode.java +++ b/src/main/java/org/olat/course/nodes/FOCourseNode.java @@ -25,11 +25,11 @@ package org.olat.course.nodes; -import java.io.File; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.zip.ZipOutputStream; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; @@ -49,9 +49,6 @@ import org.olat.core.util.coordinate.SyncerCallback; import org.olat.core.util.notifications.NotificationsManager; import org.olat.core.util.notifications.SubscriptionContext; import org.olat.core.util.resource.OresHelper; -import org.olat.core.util.vfs.LocalFolderImpl; -import org.olat.core.util.vfs.VFSContainer; -import org.olat.core.util.vfs.VFSItem; import org.olat.course.CourseModule; import org.olat.course.ICourse; import org.olat.course.condition.Condition; @@ -71,12 +68,13 @@ import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; import org.olat.modules.fo.Forum; import org.olat.modules.fo.ForumCallback; import org.olat.modules.fo.ForumManager; import org.olat.modules.fo.archiver.ForumArchiveManager; -import org.olat.modules.fo.archiver.formatters.ForumRTFFormatter; +import org.olat.modules.fo.archiver.formatters.ForumStreamedRTFFormatter; import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; import org.olat.testutils.codepoints.server.Codepoint; @@ -352,7 +350,6 @@ public class FOCourseNode extends AbstractAccessableCourseNode { return oneClickStatusCache; } - /** * @see org.olat.course.nodes.CourseNode#getReferencedRepositoryEntry() */ @@ -367,41 +364,23 @@ public class FOCourseNode extends AbstractAccessableCourseNode { return false; } - - - /** - * - * @see org.olat.course.nodes.CourseNode#archiveNodeData(java.util.Locale, org.olat.course.ICourse, java.io.File, java.lang.String) - */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - boolean dataFound = false; + @Override + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager(); Property forumKeyProperty = cpm.findCourseNodeProperty(this, null, null, FORUM_KEY); - if(forumKeyProperty != null){ - Long forumKey = forumKeyProperty.getLongValue(); - if(ForumManager.getInstance().getMessagesByForumID(forumKey).size()>0) { - String forumName = Formatter.makeStringFilesystemSave(this.getShortTitle()); - - // append export timestamp to avoid overwriting previous export - Date tmp = new Date(System.currentTimeMillis()); - java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH_mm_ss_SSS"); - forumName += "_"+formatter.format(tmp); - - VFSContainer container = new LocalFolderImpl(exportDirectory); - VFSItem vfsItem = container.resolve(forumName); - - if (vfsItem == null || !(vfsItem instanceof VFSContainer)){ - vfsItem = container.createChildContainer(forumName); - } - container = (VFSContainer)vfsItem; - - ForumRTFFormatter rtff = new ForumRTFFormatter(container, false); - ForumArchiveManager fam = ForumArchiveManager.getInstance(); - fam.applyFormatter(rtff, forumKey.longValue(), null); - dataFound = true; - } + if(forumKeyProperty == null) { + return false; + } + Long forumKey = forumKeyProperty.getLongValue(); + if(ForumManager.getInstance().countThreadsByForumID(forumKey) <= 0) { + return false; } - return dataFound; + + String forumName = "forum_" + Formatter.makeStringFilesystemSave(getShortTitle()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); + ForumStreamedRTFFormatter rtff = new ForumStreamedRTFFormatter(exportStream, forumName, false); + ForumArchiveManager.getInstance().applyFormatter(rtff, forumKey, null); + return true; } /** @@ -503,7 +482,6 @@ public class FOCourseNode extends AbstractAccessableCourseNode { // return retVal; } - } /** * diff --git a/src/main/java/org/olat/course/nodes/GenericCourseNode.java b/src/main/java/org/olat/course/nodes/GenericCourseNode.java index 23f42d07f1a80bcdb96b10e52020e8ac2089f59d..c63d77c0cb4103e48aabf0e75886076421ce1432 100644 --- a/src/main/java/org/olat/course/nodes/GenericCourseNode.java +++ b/src/main/java/org/olat/course/nodes/GenericCourseNode.java @@ -29,6 +29,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.zip.ZipOutputStream; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; @@ -56,6 +57,7 @@ import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.TreeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.group.model.BGAreaReference; import org.olat.group.model.BusinessGroupReference; import org.olat.modules.ModuleConfiguration; @@ -362,11 +364,11 @@ public abstract class GenericCourseNode extends GenericNode implements CourseNod * implementation. * * @see org.olat.course.nodes.CourseNode#archiveNodeData(java.util.Locale, - * org.olat.course.ICourse, java.io.File) + * org.olat.course.ICourse, java.util.zip.ZipOutputStream, String charset) */ - //implemented by specialized node - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - // nothing to do in default implementation + @Override + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { + // nothing to do in default implementation return true; } diff --git a/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java b/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java index f618de53cd6859df269cb10f230ac99993b2816d..8a3fea8b3815a1e6c4769aff7f7e57cae896b8c1 100644 --- a/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java +++ b/src/main/java/org/olat/course/nodes/IQSELFCourseNode.java @@ -26,8 +26,10 @@ package org.olat.course.nodes; import java.io.File; +import java.io.IOException; import java.util.List; import java.util.Locale; +import java.util.zip.ZipOutputStream; import org.olat.basesecurity.BaseSecurityManager; import org.olat.core.gui.UserRequest; @@ -37,6 +39,8 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.tabbable.TabbableController; import org.olat.core.gui.translator.PackageTranslator; import org.olat.core.id.Identity; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.Util; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentManager; @@ -51,6 +55,7 @@ import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.ims.qti.QTIResultManager; import org.olat.ims.qti.QTIResultSet; import org.olat.ims.qti.export.QTIExportFormatter; @@ -72,7 +77,8 @@ import de.bps.onyx.plugin.OnyxModule; * @author BPS (<a href="http://www.bps-system.de/">BPS Bildungsportal Sachsen GmbH</a>) */ public class IQSELFCourseNode extends AbstractAccessableCourseNode implements SelfAssessableCourseNode, QTICourseNode { - + private static final long serialVersionUID = -1929987728611139729L; + private static final OLog log = Tracing.createLoggerFor(IQSELFCourseNode.class); private static final String PACKAGE_IQ = Util.getPackageName(IQRunController.class); private static final String TYPE = "iqself"; @@ -205,22 +211,19 @@ public class IQSELFCourseNode extends AbstractAccessableCourseNode implements Se } } - /** - * Override default implementation - * - * @see org.olat.course.nodes.CourseNode#archiveNodeData(java.util.Locale, - * org.olat.course.ICourse, java.io.File) - */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - super.archiveNodeData(locale, course, exportDirectory, charset); - + @Override + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { QTIExportManager qem = QTIExportManager.getInstance(); String repositorySoftKey = (String) getModuleConfiguration().get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY); - Long repKey = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftKey, true).getKey(); + RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftKey, true); - QTIExportFormatter qef = new QTIExportFormatterCSVType2(locale,null,"\t", "\"", "\\", "\r\n", false); - return qem.selectAndExportResults(qef, course.getResourceableId(), this.getShortTitle(), this.getIdent(), repKey, exportDirectory,charset, ".xls"); - + try { + QTIExportFormatter qef = new QTIExportFormatterCSVType2(locale, null, "\t", "\"", "\\", "\r\n", false); + return qem.selectAndExportResults(qef, course.getResourceableId(), getShortTitle(), getIdent(), re, exportStream, charset, ".xls"); + } catch (IOException e) { + log.error("", e); + return false; + } } /** diff --git a/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java b/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java index b262e2a35f905e44b283484dcab73b364f74d080..8754323dcb178bb36cc4fd08c5db0ea45b4e8800 100644 --- a/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java +++ b/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java @@ -26,8 +26,10 @@ package org.olat.course.nodes; import java.io.File; +import java.io.IOException; import java.util.List; import java.util.Locale; +import java.util.zip.ZipOutputStream; import org.olat.basesecurity.BaseSecurityManager; import org.olat.core.gui.UserRequest; @@ -37,6 +39,8 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.tabbable.TabbableController; import org.olat.core.gui.translator.PackageTranslator; import org.olat.core.id.Identity; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.Util; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentManager; @@ -51,6 +55,7 @@ import org.olat.course.repository.ImportReferencesController; import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.ims.qti.QTIResultManager; import org.olat.ims.qti.export.QTIExportFormatter; import org.olat.ims.qti.export.QTIExportFormatterCSVType3; @@ -68,6 +73,9 @@ import org.olat.repository.RepositoryManager; */ public class IQSURVCourseNode extends AbstractAccessableCourseNode implements QTICourseNode { + private static final long serialVersionUID = 1672009454920536416L; + private static final OLog log = Tracing.createLoggerFor(IQSURVCourseNode.class); + private static final String PACKAGE = Util.getPackageName(IQSURVCourseNode.class); private static final String TYPE = "iqsurv"; /** category that is used to persist the node properties */ @@ -200,22 +208,19 @@ public class IQSURVCourseNode extends AbstractAccessableCourseNode implements QT } } - /** - * Override default implementation - * - * @see org.olat.course.nodes.CourseNode#archiveNodeData(java.util.Locale, - * org.olat.course.ICourse, java.io.File) - */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - super.archiveNodeData(locale, course, exportDirectory, charset); - + @Override + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { QTIExportManager qem = QTIExportManager.getInstance(); String repositorySoftKey = (String) getModuleConfiguration().get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY); - Long repKey = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftKey, true).getKey(); + RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftKey, true); QTIExportFormatter qef = new QTIExportFormatterCSVType3(locale, null,"\t", "\"", "\\", "\r\n", false); - return qem.selectAndExportResults(qef, course.getResourceableId(), this.getShortTitle(), this.getIdent(), repKey, exportDirectory,charset, ".xls"); - + try { + return qem.selectAndExportResults(qef, course.getResourceableId(), getShortTitle(), getIdent(), re, exportStream, charset, ".xls"); + } catch (IOException e) { + log.error("", e); + return false; + } } /** diff --git a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java index 1ae8976bc9445d1c1d8bed32ea16cd8d94064ca6..f8c0c09fbd8b7eaf82558e033bc35ba1d89f5ee5 100644 --- a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java +++ b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java @@ -26,8 +26,10 @@ package org.olat.course.nodes; import java.io.File; +import java.io.IOException; import java.util.List; import java.util.Locale; +import java.util.zip.ZipOutputStream; import org.olat.basesecurity.BaseSecurityManager; import org.olat.core.gui.UserRequest; @@ -39,6 +41,8 @@ import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; import org.olat.core.logging.DBRuntimeException; import org.olat.core.logging.KnownIssueException; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.Util; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentManager; @@ -55,19 +59,29 @@ import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.ims.qti.QTIResultManager; +import org.olat.ims.qti.QTIResultSet; +import org.olat.ims.qti.export.QTIExportFormatter; +import org.olat.ims.qti.export.QTIExportFormatterCSVType1; +import org.olat.ims.qti.export.QTIExportManager; import org.olat.ims.qti.process.AssessmentInstance; import org.olat.modules.ModuleConfiguration; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryImportExport; import org.olat.repository.RepositoryManager; +import de.bps.onyx.plugin.OnyxExportManager; +import de.bps.onyx.plugin.OnyxModule; + /** * Initial Date: Feb 9, 2004 * @author Mike Stock Comment: * @author BPS (<a href="http://www.bps-system.de/">BPS Bildungsportal Sachsen GmbH</a>) */ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements AssessableCourseNode, QTICourseNode { + private static final long serialVersionUID = 5806292895738005387L; + private static final OLog log = Tracing.createLoggerFor(IQTESTCourseNode.class); private static final String TYPE = "iqtest"; private static final int CURRENT_CONFIG_VERSION = 2; @@ -359,21 +373,31 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As } } - - /** - * Override default implementation - * - * @see org.olat.course.nodes.CourseNode#archiveNodeData(java.util.Locale, - * org.olat.course.ICourse, java.io.File) - */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - super.archiveNodeData(locale, course, exportDirectory, charset); - String repositorySoftKey = (String) getModuleConfiguration().get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY); + @Override + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { + String repositorySoftKey = (String)getModuleConfiguration().get(IQEditController.CONFIG_KEY_REPOSITORY_SOFTKEY); Long courseResourceableId = course.getResourceableId(); - String shortTitle = this.getShortTitle(); - String ident = this.getIdent(); - return IQUIFactory.archive(locale, repositorySoftKey, courseResourceableId, shortTitle, ident, exportDirectory, charset); - + + try { + RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftKey, true); + boolean onyx = OnyxModule.isOnyxTest(re.getOlatResource()); + if (onyx) { + QTIResultManager qrm = QTIResultManager.getInstance(); + List<QTIResultSet> results = qrm.getResultSets(courseResourceableId, getIdent(), re.getKey(), null); + if (results.size() > 0) { + OnyxExportManager.getInstance().exportResults(results, exportStream, this); + } + return true; + } else { + String shortTitle = getShortTitle(); + QTIExportManager qem = QTIExportManager.getInstance(); + QTIExportFormatter qef = new QTIExportFormatterCSVType1(locale, "\t", "\"", "\\", "\r\n", false); + return qem.selectAndExportResults(qef, courseResourceableId, shortTitle, getIdent(), re, exportStream, charset, ".xls"); + } + } catch (IOException e) { + log.error("", e); + return false; + } } /** diff --git a/src/main/java/org/olat/course/nodes/MSCourseNode.java b/src/main/java/org/olat/course/nodes/MSCourseNode.java index c09f3184555db96a17af9aadf145211142acc638..b82ccb58411aba63906d771f63ea3f241e2f2c1b 100644 --- a/src/main/java/org/olat/course/nodes/MSCourseNode.java +++ b/src/main/java/org/olat/course/nodes/MSCourseNode.java @@ -25,6 +25,7 @@ package org.olat.course.nodes; +import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -44,6 +45,7 @@ import org.olat.core.logging.OLATRuntimeException; import org.olat.core.util.Util; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentManager; +import org.olat.course.assessment.bulk.BulkAssessmentToolController; import org.olat.course.auditing.UserNodeAuditManager; import org.olat.course.editor.CourseEditorEnv; import org.olat.course.editor.NodeEditController; @@ -53,10 +55,12 @@ import org.olat.course.nodes.ms.MSCourseNodeRunController; import org.olat.course.nodes.ms.MSEditFormController; import org.olat.course.properties.CoursePropertyManager; import org.olat.course.properties.PersistingCoursePropertyManager; +import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; @@ -69,8 +73,8 @@ import org.olat.resource.OLATResource; * @author BPS (<a href="http://www.bps-system.de/">BPS Bildungsportal Sachsen GmbH</a>) */ public class MSCourseNode extends AbstractAccessableCourseNode implements AssessableCourseNode { + private static final long serialVersionUID = -7741172700015384397L; private static final String PACKAGE_MS = Util.getPackageName(MSCourseNodeRunController.class); - private static final String PACKAGE = Util.getPackageName(MSCourseNode.class); private static final String TYPE = "ms"; @@ -430,6 +434,13 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Assess throw new OLATRuntimeException(MSCourseNode.class, "Details controler not available in MS nodes", null); } + @Override + public List<Controller> createAssessmentTools(UserRequest ureq, WindowControl wControl, CourseEnvironment courseEnv, BusinessGroup limitToGroup) { + List<Controller> tools = new ArrayList<>(1); + tools.add(new BulkAssessmentToolController(ureq, wControl, courseEnv, this)); + return tools; + } + /** * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListView(org.olat.course.run.userview.UserCourseEnvironment) */ diff --git a/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java b/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java index b700bc10d7a7f96ca484bbf3cf53a1f5ef85aa66..271ba7dcf76586627db9499038ccf74e4d4433a8 100644 --- a/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java +++ b/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java @@ -26,15 +26,18 @@ package org.olat.course.nodes; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.modules.bc.FolderConfig; +import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.commons.services.taskexecutor.TaskExecutorManager; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; @@ -50,14 +53,19 @@ import org.olat.core.id.context.BusinessControl; import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.logging.AssertException; import org.olat.core.logging.OLATRuntimeException; +import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.ExportUtil; import org.olat.core.util.FileUtils; +import org.olat.core.util.Formatter; import org.olat.core.util.Util; -import org.olat.core.util.WebappHelper; import org.olat.core.util.ZipUtil; +import org.olat.core.util.vfs.VFSContainer; +import org.olat.core.util.vfs.VFSItem; +import org.olat.core.util.vfs.VFSManager; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentManager; +import org.olat.course.assessment.bulk.BulkAssessmentToolController; import org.olat.course.auditing.UserNodeAuditManager; import org.olat.course.condition.Condition; import org.olat.course.condition.interpreter.ConditionExpression; @@ -79,10 +87,12 @@ import org.olat.course.nodes.ta.ReturnboxController; import org.olat.course.nodes.ta.TaskController; import org.olat.course.properties.CoursePropertyManager; import org.olat.course.properties.PersistingCoursePropertyManager; +import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; @@ -94,7 +104,10 @@ import org.olat.resource.OLATResource; */ public class ProjectBrokerCourseNode extends GenericCourseNode implements AssessableCourseNode { - + + private static final long serialVersionUID = -8177448874150049173L; + private static final OLog log = Tracing.createLoggerFor(ProjectBrokerCourseNode.class); + private transient static final String PACKAGE_PROJECTBROKER = Util.getPackageName(ProjectListController.class); private transient static final String PACKAGE = Util.getPackageName(ProjectBrokerCourseNode.class); @@ -655,6 +668,14 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess throw new AssertException("ProjectBroker does not support AssessmentTool"); } + /** Factory method to launch course element assessment tools. limitToGroup is optional to skip he the group choose step */ + @Override + public List<Controller> createAssessmentTools(UserRequest ureq, WindowControl wControl, CourseEnvironment courseEnv, BusinessGroup limitToGroup) { + List<Controller> tools = new ArrayList<>(1); + tools.add(new BulkAssessmentToolController(ureq, wControl, courseEnv, this)); + return tools; + } + /** * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListView(org.olat.course.run.userview.UserCourseEnvironment) */ @@ -692,127 +713,62 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess ProjectBroker projectBroker = ProjectBrokerManagerFactory.getProjectBrokerManager().createAndSaveProjectBroker(); CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager(); ProjectBrokerManagerFactory.getProjectBrokerManager().saveProjectBrokerId(projectBroker.getKey(), cpm, this); - return null; } - - /** - * archives the dropbox of this task course node to the user's personal folder - * under private/archive/[coursename]/dropboxes/[nodeIdent].zip - * - * @param locale - * @param course - * @param fArchiveDirectory - * @param charset - */ + @Override - public boolean archiveNodeData(Locale locale, ICourse course, File fArchiveDirectory, String charset) { + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { boolean dataFound = false; - String dropboxPath = FolderConfig.getCanonicalRoot() + DropboxController.getDropboxPathRelToFolderRoot(course.getCourseEnvironment(),this); - File dropboxDir = new File(dropboxPath); - String returnboxPath = FolderConfig.getCanonicalRoot() + ReturnboxController.getReturnboxPathRelToFolderRoot(course.getCourseEnvironment(),this); - File returnboxDir = new File(returnboxPath); - - if (dropboxDir.exists() || returnboxDir.exists() ){ - // Create Temp Dir for zipping - String tmpDirPath = WebappHelper.getTmpDir() + course.getCourseEnvironment().getCourseBaseContainer().getRelPath(); - File tmpDir = new File( tmpDirPath ); - if (!tmpDir.exists()) { - tmpDir.mkdirs(); - } - - // prepare writing course results overview table -// TODO:ch 28.01.2010 : ProjectBroker does not support assessment-tool in V1.0 -// -// List users = ScoreAccountingHelper.loadUsers(course.getCourseEnvironment()); -// List nodes = ScoreAccountingHelper.loadAssessableNodes(course.getCourseEnvironment()); -// String s = ScoreAccountingHelper.createCourseResultsOverviewTable(users, nodes, course, locale); -// -// String courseTitle = course.getCourseTitle(); -// String fileName = ExportUtil.createFileNameWithTimeStamp(courseTitle + "-score", "xls"); -// -// // write course results overview table to filesystem -// ExportUtil.writeContentToFile(fileName, s, tmpDir, charset); + String dropboxPath = DropboxController.getDropboxPathRelToFolderRoot(course.getCourseEnvironment(),this); + OlatRootFolderImpl dropboxDir = new OlatRootFolderImpl(dropboxPath, null); + String returnboxPath = ReturnboxController.getReturnboxPathRelToFolderRoot(course.getCourseEnvironment(),this); + OlatRootFolderImpl returnboxDir = new OlatRootFolderImpl(returnboxPath, null); + if (!dropboxDir.exists() && !returnboxDir.exists()) { + return false; + } + + String exportDirName = "projectbroker_" + Formatter.makeStringFilesystemSave(getShortName()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); + try { String projectBrokerTableExport = ProjectBrokerExportGenerator.createCourseResultsOverviewTable(this, course, locale); - String tableExportFileName = ExportUtil.createFileNameWithTimeStamp(this.getShortTitle() + "-projectbroker_overview", "xls"); - ExportUtil.writeContentToFile(tableExportFileName, projectBrokerTableExport, tmpDir, charset); + String tableExportFileName = ExportUtil.createFileNameWithTimeStamp(getShortTitle() + "-projectbroker_overview", "xls"); + exportStream.putNextEntry(new ZipEntry(exportDirName + "/" + tableExportFileName)); + IOUtils.write(projectBrokerTableExport, exportStream); + exportStream.closeEntry(); + } catch (IOException e) { + log.error("", e); + } - // prepare zipping the node directory and the course results overview table - Set<String> fileList = new HashSet<String>(); - // move xls file to tmp dir -// TODO:ch 28.01.2010 : ProjectBroker does not support assessment-tool in V1.0 -// fileList.add(fileName); - fileList.add(tableExportFileName); - - // copy dropboxes to tmp dir - if (dropboxDir.exists()) { - //OLAT-6426 archive only dropboxes of users that handed in at least one file -> prevent empty folders in archive - boolean validDropboxesfound = false; - File[] themaFolderArray = dropboxDir.listFiles(); - for(File themaFolder: themaFolderArray){ - File[] userFolderArray = themaFolder.listFiles(); - if(userFolderArray==null) continue; - for(File userFolder : userFolderArray){ - if(FileUtils.isDirectoryAndNotEmpty(userFolder)){ - validDropboxesfound= true; - File source = new File(dropboxDir+"/"+themaFolder.getName()+"/"+userFolder.getName()); - File target = new File(tmpDirPath+"/dropboxes/"+themaFolder.getName()+"/"+userFolder.getName()) ; - FileUtils.copyDirContentsToDir(source, target,false, "archive projectbroker dropboxes "); - } - } - } - - if(validDropboxesfound){ - // dropboxes exists, so there is something to archive - fileList.add("dropboxes"); - dataFound |= true; + // copy dropboxes to tmp dir + if (dropboxDir.exists()) { + //OLAT-6426 archive only dropboxes of users that handed in at least one file -> prevent empty folders in archive + for(VFSItem themaItem: dropboxDir.getItems()) { + if(!(themaItem instanceof VFSContainer)) continue; + List<VFSItem> userFolderArray = ((VFSContainer)themaItem).getItems(); + for(VFSItem userFolder : userFolderArray){ + if(!VFSManager.isDirectoryAndNotEmpty(userFolder)) continue; + String path = exportDirName + "/dropboxes/" + themaItem.getName(); + ZipUtil.addToZip(userFolder, path, exportStream); } } + } - // copy returnboxes to tmp dir - if (returnboxDir.exists()) { - boolean validReturnboxesfound = false; - File[] themaFolderArray = returnboxDir.listFiles(); - for(File themaFolder: themaFolderArray){ - File[] userFolderArray = themaFolder.listFiles(); - if(userFolderArray==null) continue; - for(File userFolder : userFolderArray){ - if(FileUtils.isDirectoryAndNotEmpty(userFolder)){ - validReturnboxesfound = true; - File source = new File(returnboxDir+"/"+themaFolder.getName()+"/"+userFolder.getName()); - File target = new File(tmpDirPath + "/returnboxes/"+themaFolder.getName()+"/"+userFolder.getName()) ; - FileUtils.copyDirContentsToDir(source , target , false, "archive projectbroker returnboxes"); - } - } - } - if(validReturnboxesfound){ - fileList.add("returnboxes"); - //returnboxes exists, so there is something to archive - dataFound |= true; + // copy returnboxes to tmp dir + if (returnboxDir.exists()) { + for(VFSItem themaItem:returnboxDir.getItems()) { + if(!(themaItem instanceof VFSContainer)) continue; + List<VFSItem> userFolderArray = ((VFSContainer)themaItem).getItems(); + for(VFSItem userFolder : userFolderArray){ + if(!VFSManager.isDirectoryAndNotEmpty(userFolder)) continue; + String path = exportDirName + "/returnboxes/" + themaItem.getName(); + ZipUtil.addToZip(userFolder, path, exportStream); } } - - if(dataFound) { - String zipName = ExportUtil.createFileNameWithTimeStamp(this.getIdent(), "zip"); - - java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH_mm_ss_SSS"); - String exportDirName = "projectbroker_" + this.getShortName() + "_" + formatter.format(new Date(System.currentTimeMillis())); - File fDropBoxArchiveDir = new File(fArchiveDirectory, exportDirName); - if (!fDropBoxArchiveDir.exists()) { - fDropBoxArchiveDir.mkdir(); - } - File archiveDir = new File(fDropBoxArchiveDir, zipName); - - // zip - dataFound &= ZipUtil.zip(fileList, tmpDir, archiveDir, true); - // Delete all temp files - } - FileUtils.deleteDirsAndFiles( tmpDir, true, true); - } - return dataFound; - } + } + return dataFound; + } /** * @see org.olat.course.nodes.GenericCourseNode#getConditionExpressions() diff --git a/src/main/java/org/olat/course/nodes/ScormCourseNode.java b/src/main/java/org/olat/course/nodes/ScormCourseNode.java index 1c3ba6394848e40ddd299d8cd94a7ed9215c28fa..20095e7d5fce3f6594e180604a68c4301bc95c14 100644 --- a/src/main/java/org/olat/course/nodes/ScormCourseNode.java +++ b/src/main/java/org/olat/course/nodes/ScormCourseNode.java @@ -26,9 +26,14 @@ package org.olat.course.nodes; import java.io.File; +import java.io.IOException; +import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; import org.olat.basesecurity.BaseSecurityManager; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; @@ -36,7 +41,12 @@ import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.iframe.DeliveryOptions; import org.olat.core.gui.control.generic.tabbable.TabbableController; +import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.Formatter; +import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentManager; @@ -53,9 +63,11 @@ import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; import org.olat.modules.scorm.ScormMainManager; import org.olat.modules.scorm.ScormPackageConfig; +import org.olat.modules.scorm.archiver.ScormExportManager; import org.olat.modules.scorm.assessment.ScormResultDetailsController; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryImportExport; @@ -66,7 +78,7 @@ import org.olat.repository.RepositoryEntryImportExport; * @author BPS (<a href="http://www.bps-system.de/">BPS Bildungsportal Sachsen GmbH</a>) */ public class ScormCourseNode extends AbstractAccessableCourseNode implements AssessableCourseNode { - + private static final OLog log = Tracing.createLoggerFor(ScormCourseNode.class); private static final long serialVersionUID = 2970594874787761801L; private static final String TYPE = "scorm"; private static final int CURRENT_CONFIG_VERSION = 5; @@ -336,6 +348,24 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Ass } } + @Override + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { + String fileName = "scorm_" + + StringHelper.transformDisplayNameToFileSystemName(getShortName()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())) + + ".xls"; + Translator trans = Util.createPackageTranslator(ScormExportManager.class, locale); + String results = ScormExportManager.getInstance().getResults(course.getCourseEnvironment(), this, trans); + try { + exportStream.putNextEntry(new ZipEntry(fileName)); + IOUtils.write(results, exportStream); + exportStream.closeEntry(); + } catch (IOException e) { + log.error("", e); + } + return true; + } + /** * @see org.olat.course.nodes.CourseNode#createInstanceForCopy() */ @@ -579,6 +609,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Ass /** * @see org.olat.course.nodes.CourseNode#cleanupOnDelete(org.olat.course.ICourse) */ + @Override public void cleanupOnDelete(ICourse course) { CoursePropertyManager pm = course.getCourseEnvironment().getCoursePropertyManager(); // 1) Delete all properties: score, passed, log, comment, coach_comment, @@ -591,24 +622,4 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Ass // I would consider refatoring this and setting up an upgrade task that moves the // folders accordingly } - - /** - * Override default implementation - * - * @see org.olat.course.nodes.CourseNode#archiveNodeData(java.util.Locale, - * org.olat.course.ICourse, java.io.File) - */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - return super.archiveNodeData(locale, course, exportDirectory, charset); - // copy all user directories containing the xml files into the export dir - - // FIXME gs - // we would have to work through all users - // of the system since data is stored under users name instead of the repo entry - // with many users on the system it could take quite some time and the user - // is waiting in a workflow - // see comment on cleanupOnDelete - } - - } \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/TACourseNode.java b/src/main/java/org/olat/course/nodes/TACourseNode.java index f2d61fedbec5797c1575aaed4c5aa68391a8f23f..4180eac948a39f90dcec5945ea178c28c1e16cab 100644 --- a/src/main/java/org/olat/course/nodes/TACourseNode.java +++ b/src/main/java/org/olat/course/nodes/TACourseNode.java @@ -28,12 +28,14 @@ package org.olat.course.nodes; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.modules.bc.FolderConfig; import org.olat.core.commons.modules.bc.vfs.OlatNamedContainerImpl; @@ -54,13 +56,16 @@ import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.ExportUtil; import org.olat.core.util.FileUtils; +import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; -import org.olat.core.util.WebappHelper; import org.olat.core.util.ZipUtil; +import org.olat.core.util.vfs.VFSItem; +import org.olat.core.util.vfs.VFSManager; import org.olat.course.ICourse; import org.olat.course.archiver.ScoreAccountingHelper; import org.olat.course.assessment.AssessmentManager; +import org.olat.course.assessment.bulk.BulkAssessmentToolController; import org.olat.course.auditing.UserNodeAuditManager; import org.olat.course.condition.Condition; import org.olat.course.condition.interpreter.ConditionExpression; @@ -71,6 +76,7 @@ import org.olat.course.editor.StatusDescription; import org.olat.course.export.CourseEnvironmentMapper; import org.olat.course.groupsandrights.CourseGroupManager; import org.olat.course.nodes.ms.MSEditFormController; +import org.olat.course.nodes.ta.BulkDownloadToolController; import org.olat.course.nodes.ta.DropboxController; import org.olat.course.nodes.ta.DropboxScoringViewController; import org.olat.course.nodes.ta.ReturnboxController; @@ -84,6 +90,7 @@ import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; @@ -672,14 +679,25 @@ public class TACourseNode extends GenericCourseNode implements AssessableCourseN * org.olat.core.gui.control.WindowControl, * org.olat.course.run.userview.UserCourseEnvironment) */ + @Override public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl, StackedController stackPanel, UserCourseEnvironment userCourseEnvironment) { // prepare file component return new DropboxScoringViewController(ureq, wControl, this, userCourseEnvironment); } + /** Factory method to launch course element assessment tools. limitToGroup is optional to skip he the group choose step */ + @Override + public List<Controller> createAssessmentTools(UserRequest ureq, WindowControl wControl, CourseEnvironment courseEnv, BusinessGroup limitToGroup) { + List<Controller> tools = new ArrayList<Controller>(1); + tools.add(new BulkAssessmentToolController(ureq, wControl, courseEnv, this)); + tools.add(new BulkDownloadToolController(ureq, wControl, courseEnv, limitToGroup, this)); + return tools; + } + /** * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListView(org.olat.course.run.userview.UserCourseEnvironment) */ + @Override public String getDetailsListView(UserCourseEnvironment userCourseEnvironment) { Identity identity = userCourseEnvironment.getIdentityEnvironment().getIdentity(); CoursePropertyManager propMgr = userCourseEnvironment.getCourseEnvironment().getCoursePropertyManager(); @@ -748,139 +766,89 @@ public class TACourseNode extends GenericCourseNode implements AssessableCourseN return null; } - /** - * archives the dropbox of this task course node to the user's personal folder - * under private/archive/[coursename]/dropboxes/[nodeIdent].zip - * - * @param locale - * @param course - * @param fArchiveDirectory - * @param charset - */ @Override - public boolean archiveNodeData(Locale locale, ICourse course, File fArchiveDirectory, String charset) { - boolean dataFound = false; - String dropboxPath = FolderConfig.getCanonicalRoot() + DropboxController.getDropboxPathRelToFolderRoot(course.getCourseEnvironment(),this); - File dropboxDir = new File(dropboxPath); - String solutionsPath = FolderConfig.getCanonicalRoot() + TACourseNode.getFoldernodesPathRelToFolderBase(course.getCourseEnvironment()) + "/" + this.getIdent(); - File solutionDir = new File(solutionsPath); - String returnboxPath = FolderConfig.getCanonicalRoot() + ReturnboxController.getReturnboxPathRelToFolderRoot(course.getCourseEnvironment(),this); - File returnboxDir = new File(returnboxPath); + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { + boolean dataFound = false; + String dropboxPath = DropboxController.getDropboxPathRelToFolderRoot(course.getCourseEnvironment(), this); + OlatRootFolderImpl dropboxDir = new OlatRootFolderImpl(dropboxPath, null); + String solutionsPath = TACourseNode.getFoldernodesPathRelToFolderBase(course.getCourseEnvironment()) + "/" + this.getIdent(); + OlatRootFolderImpl solutionDir = new OlatRootFolderImpl(solutionsPath, null); + String returnboxPath = ReturnboxController.getReturnboxPathRelToFolderRoot(course.getCourseEnvironment(), this); + OlatRootFolderImpl returnboxDir = new OlatRootFolderImpl(returnboxPath, null); + Boolean hasTask = (Boolean) getModuleConfiguration().get(TACourseNode.CONF_TASK_ENABLED); + + String dirName = "task_" + + StringHelper.transformDisplayNameToFileSystemName(getShortName()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); - if (dropboxDir.exists() || solutionDir.exists() || returnboxDir.exists() || hasTask.booleanValue()){ - // Create Temp Dir for zipping - String tmpDirPath = WebappHelper.getTmpDir() + course.getCourseEnvironment().getCourseBaseContainer().getRelPath(); - File tmpDir = new File(tmpDirPath); - - if (!tmpDir.exists()) { - tmpDir.mkdirs(); - } - //we need a unique dir name - File newDir = FileUtils.createTempDir("tmp", "", tmpDir); - if(newDir!=null) { - tmpDir = newDir; - try { - tmpDirPath = tmpDir.getCanonicalPath(); - } catch (IOException e) { - log.warn("tmpDir.getCanonicalPath() throws IOException!"); - } - } - + if (dropboxDir.exists() || solutionDir.exists() || returnboxDir.exists() || hasTask.booleanValue()){ // prepare writing course results overview table - List<Identity> users = ScoreAccountingHelper.loadUsers(course.getCourseEnvironment()); - List<AssessableCourseNode> nodes = new ArrayList<AssessableCourseNode>(); - nodes.add(this); - String s = ScoreAccountingHelper.createCourseResultsOverviewTable(users, nodes, course, locale); - + List<Identity> users = group == null ? ScoreAccountingHelper.loadUsers(course.getCourseEnvironment()) + : ScoreAccountingHelper.loadUsers(group); + String courseTitle = course.getCourseTitle(); String fileName = ExportUtil.createFileNameWithTimeStamp(courseTitle, "xls"); - + List<AssessableCourseNode> nodes = Collections.<AssessableCourseNode>singletonList(this); + String s = ScoreAccountingHelper.createCourseResultsOverviewTable(users, nodes, course, locale); // write course results overview table to filesystem - ExportUtil.writeContentToFile(fileName, s, tmpDir, charset); + try { + exportStream.putNextEntry(new ZipEntry(dirName + "/" + fileName)); + IOUtils.write(s, exportStream); + exportStream.closeEntry(); + } catch (IOException e) { + log.error("", e); + } - // prepare zipping the node directory and the course results overview table - Set<String> fileList = new HashSet<String>(); - // move xls file to tmp dir - fileList.add(fileName); // copy solutions to tmp dir if (solutionDir.exists()) { - if(FileUtils.isDirectoryAndNotEmpty(solutionDir)){ - FileUtils.copyDirContentsToDir(solutionDir, new File(tmpDirPath + "/solutions"), false, "archive task course node solutions"); - fileList.add("solutions"); + for(VFSItem child:solutionDir.getItems()) { + dataFound = true; + ZipUtil.addToZip(child, dirName + "/solutions", exportStream); } } + // copy dropboxes to tmp dir if (dropboxDir.exists()) { - //OLAT-6362 archive only dropboxes of users that handed in at least one file -> prevent empty folders in archive - File[] dropBoxContent = dropboxDir.listFiles(); - boolean validDropboxesfound = false; - for (File file : dropBoxContent) { - if(FileUtils.isDirectoryAndNotEmpty(file)){ - validDropboxesfound = true; - FileUtils.copyDirContentsToDir(file, new File(tmpDirPath + "/dropboxes/"+file.getName()), false, "archive task course node dropboxes "+file.getName()); + //OLAT-6362 archive only dropboxes of users that handed in at least one file -> prevent empty folders in archive + List<VFSItem> dropBoxContent = dropboxDir.getItems(); + for (VFSItem file:dropBoxContent) { + if(VFSManager.isDirectoryAndNotEmpty(file)){ + dataFound = true; + ZipUtil.addToZip(file, dirName + "/dropboxes", exportStream); } } - - if(validDropboxesfound){ - // dropboxes exists and at least one is not empty, so there is something to archive - dataFound = true; - fileList.add("dropboxes"); - } } + // copy only the choosen task to user taskfolder, loop over all users - String taskfolderPath = FolderConfig.getCanonicalRoot() + TACourseNode.getTaskFolderPathRelToFolderRoot(course.getCourseEnvironment(),this); - boolean taskFolderExist = false; + String taskfolderPath = TACourseNode.getTaskFolderPathRelToFolderRoot(course.getCourseEnvironment(),this); + OlatRootFolderImpl taskfolderDir = new OlatRootFolderImpl(taskfolderPath, null); for(Identity identity:users) { - // check if user already chose a task - String assignedTask = TaskController.getAssignedTask(identity, course.getCourseEnvironment(), this); - if (assignedTask != null) { - // copy choosen task to user folder - String tmpUserTaskDirPath = tmpDirPath + "/taskfolders/" + identity.getName(); - FileUtils.copyFileToDir(taskfolderPath + "/" + assignedTask, tmpUserTaskDirPath ); - taskFolderExist = true; - } - } - if (taskFolderExist) { - fileList.add("taskfolders"); + // check if user already chose a task + String assignedTask = TaskController.getAssignedTask(identity, course.getCourseEnvironment(), this); + if (assignedTask != null) { + VFSItem item = taskfolderDir.resolve(assignedTask); + if(item != null) { + // copy choosen task to user folder + ZipUtil.addToZip(item, dirName + "/taskfolders/" + identity.getName(), exportStream); + dataFound = true; + } + } } - - // copy returnboxes to tmp dir + + // copy returnboxes if (returnboxDir.exists()) { //OLAT-6362 archive only existing returnboxes -> prevent empty folders in archive - File[] returnBoxContent = returnboxDir.listFiles(); - boolean validReturnboxesfound = false; - for (File file : returnBoxContent) { - if(FileUtils.isDirectoryAndNotEmpty(file)){ - validReturnboxesfound = true; - FileUtils.copyDirContentsToDir(file, new File(tmpDirPath + "/returnboxes/"+file.getName()), false, "archive task course node returnboxes "+file.getName()); + List<VFSItem> returnBoxContent = returnboxDir.getItems(); + for (VFSItem file : returnBoxContent) { + if(VFSManager.isDirectoryAndNotEmpty(file)){ + dataFound = true; + ZipUtil.addToZip(file, dirName + "/returnboxes", exportStream); } } - - if(validReturnboxesfound){ - // returnboxes exists and at least one is not empty, so there is something to archive - dataFound = true; - fileList.add("returnboxes"); - } - } - - if(dataFound) { - String zipName = ExportUtil.createFileNameWithTimeStamp(this.getIdent(), "zip"); - - java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH_mm_ss_SSS"); - String exportDirName = "task_" + StringHelper.transformDisplayNameToFileSystemName(this.getShortName()) + "_" + formatter.format(new Date(System.currentTimeMillis())); - File fDropBoxArchiveDir = new File(fArchiveDirectory, exportDirName); - if (!fDropBoxArchiveDir.exists()) { - fDropBoxArchiveDir.mkdir(); - } - File archiveDir = new File(fDropBoxArchiveDir, zipName); - // zip - dataFound &= ZipUtil.zip(fileList, tmpDir, archiveDir, true); - // Delete all temp files } - FileUtils.deleteDirsAndFiles( tmpDir, true, true); } - return dataFound; + return dataFound; } /** diff --git a/src/main/java/org/olat/course/nodes/WikiCourseNode.java b/src/main/java/org/olat/course/nodes/WikiCourseNode.java index d7a3d0c934e300af323ba4b8bb40bd9ec80a1789..0fa7c46970975873b0cd712450faa574e99427ab 100644 --- a/src/main/java/org/olat/course/nodes/WikiCourseNode.java +++ b/src/main/java/org/olat/course/nodes/WikiCourseNode.java @@ -26,9 +26,11 @@ package org.olat.course.nodes; import java.io.File; +import java.io.IOException; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.zip.ZipOutputStream; import org.olat.basesecurity.BaseSecurityManager; import org.olat.core.gui.UserRequest; @@ -39,15 +41,14 @@ import org.olat.core.gui.control.generic.messages.MessageUIFactory; import org.olat.core.gui.control.generic.tabbable.TabbableController; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; +import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.Formatter; +import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.notifications.NotificationsManager; import org.olat.core.util.notifications.SubscriptionContext; -import org.olat.core.util.vfs.LocalFolderImpl; import org.olat.core.util.vfs.VFSContainer; -import org.olat.core.util.vfs.VFSLeaf; -import org.olat.core.util.vfs.VFSManager; import org.olat.course.ICourse; import org.olat.course.condition.Condition; import org.olat.course.condition.interpreter.ConditionInterpreter; @@ -61,7 +62,9 @@ import org.olat.course.repository.ImportReferencesController; import org.olat.course.run.navigation.NodeRunConstructionResult; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.wiki.Wiki; import org.olat.modules.wiki.WikiManager; import org.olat.modules.wiki.WikiToZipUtils; import org.olat.repository.RepositoryEntry; @@ -74,6 +77,8 @@ import org.olat.repository.RepositoryManager; * @author Felix Jost */ public class WikiCourseNode extends AbstractAccessableCourseNode { + + private static final OLog log = Tracing.createLoggerFor(WikiCourseNode.class); public static final String TYPE = "wiki"; private Condition preConditionEdit; @@ -223,46 +228,34 @@ public class WikiCourseNode extends AbstractAccessableCourseNode { return new ImportReferencesController(ureq, wControl, this, ImportReferencesController.IMPORT_WIKI,rie); } } - - - /** - * @see org.olat.course.nodes.GenericCourseNode#archiveNodeData(java.util.Locale, org.olat.course.ICourse, java.io.File, java.lang.String) - */ - public boolean archiveNodeData(Locale locale, ICourse course, File exportDirectory, String charset) { - String repoRef = (String)this.getModuleConfiguration().get("reporef"); + @Override + public boolean archiveNodeData(Locale locale, ICourse course, BusinessGroup group, ZipOutputStream exportStream, String charset) { + String repoRef = (String)getModuleConfiguration().get("reporef"); OLATResourceable ores = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repoRef, true).getOlatResource(); - if(WikiManager.getInstance().getOrLoadWiki(ores).getAllPagesWithContent().size()>0) { - //OK, there is somthing to archive - VFSContainer exportContainer = new LocalFolderImpl(exportDirectory); - VFSContainer wikiExportContainer = (VFSContainer)exportContainer.resolve(WikiManager.WIKI_RESOURCE_FOLDER_NAME); - if(wikiExportContainer == null){ - wikiExportContainer = exportContainer.createChildContainer(WikiManager.WIKI_RESOURCE_FOLDER_NAME); - } - String exportDirName = getShortTitle()+"_"+Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); - VFSContainer destination = wikiExportContainer.createChildContainer(exportDirName); - if (destination==null) { - exportDirName = VFSManager.rename(wikiExportContainer, exportDirName); - destination = wikiExportContainer.createChildContainer(exportDirName); - } - if (destination==null) { - Tracing.logError("archiveNodeData: Could not create destination directory: wikiExportContainer="+wikiExportContainer+", exportDirName="+exportDirName, getClass()); - return false; - } - - VFSContainer container = WikiManager.getInstance().getWikiContainer(ores, WikiManager.WIKI_RESOURCE_FOLDER_NAME); - if(container!=null) { //the container could be null if the wiki is an old empty one - so nothing to archive - VFSContainer parent = container.getParentContainer(); - VFSLeaf wikiZip = WikiToZipUtils.getWikiAsZip(parent); - destination.copyFrom(wikiZip); - } - return true; - } - //empty wiki, no need to archive - return false; + Wiki wiki = WikiManager.getInstance().getOrLoadWiki(ores); + if(wiki.getAllPagesWithContent().isEmpty()) { + return false; + } + + //OK, there is something to archive + String currentPath = "wiki_" + + StringHelper.transformDisplayNameToFileSystemName(getShortName()) + + "_" + Formatter.formatDatetimeFilesystemSave(new Date(System.currentTimeMillis())); + + VFSContainer container = WikiManager.getInstance().getWikiContainer(ores, WikiManager.WIKI_RESOURCE_FOLDER_NAME); + if(container != null) { //the container could be null if the wiki is an old empty one - so nothing to archive + try { + VFSContainer parent = container.getParentContainer(); + WikiToZipUtils.wikiToZip(parent, currentPath, exportStream); + } catch (IOException e) { + log.error("", e); + } + } + return true; } - + public Condition getPreConditionEdit() { if (preConditionEdit == null) { preConditionEdit = new Condition(); diff --git a/src/main/java/org/olat/course/nodes/iq/IQControllerCreator.java b/src/main/java/org/olat/course/nodes/iq/IQControllerCreator.java index ffd199ee9e2e5540ace50fbee0953401a6934075..67dd46c493653dccc52a962e49f07cd5a9a998ef 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQControllerCreator.java +++ b/src/main/java/org/olat/course/nodes/iq/IQControllerCreator.java @@ -24,9 +24,6 @@ */ package org.olat.course.nodes.iq; -import java.io.File; -import java.util.Locale; - import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; import org.olat.core.gui.control.Controller; @@ -106,15 +103,4 @@ public interface IQControllerCreator { public Controller createIQTestDetailsEditController(Long courseResourceableId, String ident, Identity identity, RepositoryEntry referencedRepositoryEntry, String qmdEntryTypeAssess, UserRequest ureq, WindowControl wControl); - - /** - * todo:remove to proper place - * @param locale - * @param course - * @param exportDirectory - * @param charset - * @return - */ - public boolean archiveIQTestCourseNode(Locale locale, String repositorySoftkey, Long courseResourceableId, String shortTitle, String ident, File exportDirectory, String charset); - } \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/iq/IQControllerCreatorOlat.java b/src/main/java/org/olat/course/nodes/iq/IQControllerCreatorOlat.java index 9503309a3afdfe6b9d6f0f26b901ea056e45fdde..f385061747c95ddfc52121e1408bd5d370217a47 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQControllerCreatorOlat.java +++ b/src/main/java/org/olat/course/nodes/iq/IQControllerCreatorOlat.java @@ -24,10 +24,6 @@ */ package org.olat.course.nodes.iq; -import java.io.File; -import java.util.List; -import java.util.Locale; - import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; import org.olat.core.gui.control.Controller; @@ -40,31 +36,22 @@ import org.olat.core.id.OLATResourceable; import org.olat.core.id.Roles; import org.olat.core.util.Util; import org.olat.core.util.coordinate.CoordinatorManager; -import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentManager; import org.olat.course.groupsandrights.CourseGroupManager; -import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.IQSELFCourseNode; import org.olat.course.nodes.IQSURVCourseNode; import org.olat.course.nodes.IQTESTCourseNode; import org.olat.course.run.userview.NodeEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.ims.qti.QTI12ResultDetailsController; -import org.olat.ims.qti.QTIResultManager; -import org.olat.ims.qti.QTIResultSet; -import org.olat.ims.qti.export.QTIExportFormatter; -import org.olat.ims.qti.export.QTIExportFormatterCSVType1; -import org.olat.ims.qti.export.QTIExportManager; import org.olat.ims.qti.fileresource.SurveyFileResource; import org.olat.ims.qti.fileresource.TestFileResource; import org.olat.modules.ModuleConfiguration; import org.olat.modules.iq.IQSecurityCallback; import org.olat.repository.RepositoryEntry; -import org.olat.repository.RepositoryManager; import de.bps.ims.qti.QTIResultDetailsController; -import de.bps.onyx.plugin.OnyxExportManager; import de.bps.onyx.plugin.OnyxModule; import de.bps.onyx.plugin.run.OnyxRunController; @@ -246,25 +233,4 @@ public class IQControllerCreatorOlat implements IQControllerCreator { return new QTI12ResultDetailsController(ureq, wControl, courseResourceableId, ident, identity, referencedRepositoryEntry, qmdEntryTypeAssess); } } - - @Override - public boolean archiveIQTestCourseNode(Locale locale, String repositorySoftkey, Long courseResourceableId, String shortTitle, String ident, File exportDirectory, String charset) { - boolean onyx = OnyxModule.isOnyxTest(RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftkey, true).getOlatResource()); - if (onyx) { - ICourse course = CourseFactory.loadCourse(courseResourceableId); - CourseNode currentCourseNode = course.getRunStructure().getNode(ident); - Long repKey = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftkey, true).getKey(); - QTIResultManager qrm = QTIResultManager.getInstance(); - List<QTIResultSet> results = qrm.getResultSets(courseResourceableId, ident, repKey, null); - if (results.size() > 0) { - OnyxExportManager.getInstance().exportResults(results, exportDirectory, currentCourseNode); - } - return true; - } else { - QTIExportManager qem = QTIExportManager.getInstance(); - Long repKey = RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repositorySoftkey, true).getKey(); - QTIExportFormatter qef = new QTIExportFormatterCSVType1(locale,"\t", "\"", "\\", "\r\n", false); - return qem.selectAndExportResults(qef, courseResourceableId, shortTitle, ident, repKey, exportDirectory,charset, ".xls"); - } - } } \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/iq/IQEditReplaceWizard.java b/src/main/java/org/olat/course/nodes/iq/IQEditReplaceWizard.java index 4d364c5bbecea2e0abc98c7935499b31ea301ab3..22b98af4ea1b71a8ef7f5198b57528f7cc5ef860 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQEditReplaceWizard.java +++ b/src/main/java/org/olat/course/nodes/iq/IQEditReplaceWizard.java @@ -194,8 +194,7 @@ public class IQEditReplaceWizard extends WizardController { String charset = um.getUserCharset(ureq.getIdentity()); QTIExportManager qem = QTIExportManager.getInstance(); Long repositoryRef = results.get(0).getResultSet().getRepositoryRef(); - QTIObjectTreeBuilder qotb = new QTIObjectTreeBuilder(repositoryRef); - List<QTIItemObject> qtiItemObjectList = qotb.getQTIItemObjectList(); + List<QTIItemObject> qtiItemObjectList = new QTIObjectTreeBuilder().getQTIItemObjectList(repositoryRef); QTIExportFormatter formatter = new QTIExportFormatterCSVType1(ureq.getLocale(), "\t", "\"", "\\", "\r\n", false); Map<Class<?>, QTIExportItemFormatConfig> qtiItemConfigs = getQTIItemConfigs(qtiItemObjectList); formatter.setMapWithExportItemConfigs(qtiItemConfigs); diff --git a/src/main/java/org/olat/course/nodes/iq/IQUIFactory.java b/src/main/java/org/olat/course/nodes/iq/IQUIFactory.java index 9eef41714723fcdd3ea9d5715875e9b4dc4223fd..37b9487b78fc1fbc6026daa04a3e6b43e329cbab 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQUIFactory.java +++ b/src/main/java/org/olat/course/nodes/iq/IQUIFactory.java @@ -24,9 +24,6 @@ */ package org.olat.course.nodes.iq; -import java.io.File; -import java.util.Locale; - import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.stack.StackedController; import org.olat.core.gui.control.Controller; @@ -106,9 +103,4 @@ public class IQUIFactory { return IQUIFactory.iqControllerCreator.createIQTestDetailsEditController(courseResourceableId, ident, identity, referencedRepositoryEntry, qmdEntryTypeAssess, ureq, wControl); } - - public static boolean archive(Locale locale, String repositorySoftkey, Long courseResourceableId, String shortTitle, String ident, File exportDirectory, String charset){ - return IQUIFactory.iqControllerCreator.archiveIQTestCourseNode(locale, repositorySoftkey, courseResourceableId, shortTitle, ident, exportDirectory, charset); - } - } diff --git a/src/main/java/org/olat/course/nodes/ta/BulkDownloadToolController.java b/src/main/java/org/olat/course/nodes/ta/BulkDownloadToolController.java new file mode 100644 index 0000000000000000000000000000000000000000..3e3c2172ba782849b8cd8917c97b74b2a43ecbc6 --- /dev/null +++ b/src/main/java/org/olat/course/nodes/ta/BulkDownloadToolController.java @@ -0,0 +1,77 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.nodes.ta; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.course.archiver.ArchiveResource; +import org.olat.course.nodes.AssessableCourseNode; +import org.olat.course.run.environment.CourseEnvironment; +import org.olat.group.BusinessGroup; +import org.olat.resource.OLATResource; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class BulkDownloadToolController extends BasicController { + + private final Link downloadButton; + + private final BusinessGroup group; + private final OLATResource courseOres; + private final AssessableCourseNode courseNode; + + public BulkDownloadToolController(UserRequest ureq, WindowControl wControl, CourseEnvironment courseEnv, + BusinessGroup group, AssessableCourseNode courseNode) { + super(ureq, wControl); + this.group = group; + this.courseNode = courseNode; + courseOres = courseEnv.getCourseGroupManager().getCourseResource(); + + VelocityContainer mainVC = createVelocityContainer("start_button"); + downloadButton = LinkFactory.createButton("bulk.download.title", mainVC, this); + putInitialPanel(mainVC); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(downloadButton == source) { + doDownload(ureq); + } + } + + private void doDownload(UserRequest ureq) { + ArchiveResource resource = new ArchiveResource(courseNode, courseOres, group, getLocale()); + ureq.getDispatchResult().setResultingMediaResource(resource); + } +} diff --git a/src/main/java/org/olat/course/nodes/ta/_content/start_button.html b/src/main/java/org/olat/course/nodes/ta/_content/start_button.html new file mode 100644 index 0000000000000000000000000000000000000000..dcf81d6f13e09451a370c9b1a757ca1c11213f14 --- /dev/null +++ b/src/main/java/org/olat/course/nodes/ta/_content/start_button.html @@ -0,0 +1 @@ +$r.render("bulk.download.title") \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/ta/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/ta/_i18n/LocalStrings_de.properties index 53898ac56d7322127b0a83246055235eec2f7f31..8e23a5e01b053692cf902ae1345e5ddb8e18c1e8 100644 --- a/src/main/java/org/olat/course/nodes/ta/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/nodes/ta/_i18n/LocalStrings_de.properties @@ -1,4 +1,5 @@ #Mon Mar 02 09:54:04 CET 2009 +bulk.download.title=Return box download chelp.ass1=Hier bestimmen Sie, wie die Aufgaben im $\:chelp.taskfolder an die Kursteilnehmer verteilt werden. chelp.ass2=Sie haben die M\u00F6glichkeit, den Benutzern eine Information anzeigen zu lassen. chelp.ass3=Entweder sieht der Benutzer die von Ihnen zur Verf\u00FCgung gestellten Aufgaben und kann sich eine Aufgabe ausw\u00E4hlen - oder ihm wird eine der Aufgaben automatisch zugeteilt. diff --git a/src/main/java/org/olat/course/run/RunMainController.java b/src/main/java/org/olat/course/run/RunMainController.java index 01ff99294d9ace375a12e49636290a399e99dd02..f4c885c1c49a3a3cbd80d6ecf771a53d93809015 100644 --- a/src/main/java/org/olat/course/run/RunMainController.java +++ b/src/main/java/org/olat/course/run/RunMainController.java @@ -88,7 +88,7 @@ import org.olat.course.ICourse; import org.olat.course.archiver.ArchiverMainController; import org.olat.course.archiver.IArchiverCallback; import org.olat.course.assessment.AssessmentChangedEvent; -import org.olat.course.assessment.AssessmentUIFactory; +import org.olat.course.assessment.AssessmentMainController; import org.olat.course.assessment.CoachingGroupAccessAssessmentCallback; import org.olat.course.assessment.EfficiencyStatementController; import org.olat.course.assessment.EfficiencyStatementManager; @@ -844,20 +844,20 @@ public class RunMainController extends MainLayoutBasicController implements Gene // 1) course admins and users with tool right: full access if (hasCourseRight(CourseRights.RIGHT_ASSESSMENT) || isCourseAdmin) { - Activateable2 assessmentToolCtr = - AssessmentUIFactory.createAssessmentMainController(ureq, swControl, all, course, new FullAccessAssessmentCallback(isCourseAdmin)); + AssessmentMainController assessmentToolCtr = new AssessmentMainController(ureq, swControl, all, course, + new FullAccessAssessmentCallback(isCourseAdmin)); assessmentToolCtr.activate(ureq, null, null); - currentToolCtr = (Controller)assessmentToolCtr; + currentToolCtr = assessmentToolCtr; listenTo(currentToolCtr); all.pushController(translate("command.openassessment"), currentToolCtr); return assessmentToolCtr; } // 2) users with coach right: limited access to coached groups else if (isCourseCoach) { - Activateable2 assessmentToolCtr = AssessmentUIFactory.createAssessmentMainController(ureq, swControl, all, course, + AssessmentMainController assessmentToolCtr = new AssessmentMainController(ureq, swControl, all, course, new CoachingGroupAccessAssessmentCallback()); assessmentToolCtr.activate(ureq, null, null); - currentToolCtr = (Controller)assessmentToolCtr; + currentToolCtr = assessmentToolCtr; listenTo(currentToolCtr); all.pushController(translate("command.openassessment"), currentToolCtr); return assessmentToolCtr; diff --git a/src/main/java/org/olat/ims/qti/export/CourseQTIArchiveController.java b/src/main/java/org/olat/ims/qti/export/CourseQTIArchiveController.java index 167034e09bd1eb7b45e47fa791575fd4d95f5aa5..d9623cf9dfe76ce301afe4cace36953662aece03 100644 --- a/src/main/java/org/olat/ims/qti/export/CourseQTIArchiveController.java +++ b/src/main/java/org/olat/ims/qti/export/CourseQTIArchiveController.java @@ -26,9 +26,7 @@ package org.olat.ims.qti.export; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; @@ -48,9 +46,8 @@ import org.olat.core.gui.control.generic.closablewrapper.CloseableModalControlle import org.olat.core.id.OLATResourceable; import org.olat.course.CourseFactory; import org.olat.course.ICourse; -import org.olat.course.assessment.AssessmentHelper; -import org.olat.course.assessment.AssessmentUIFactory; import org.olat.course.assessment.IndentedNodeRenderer; +import org.olat.course.assessment.NodeTableRow; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.IQSELFCourseNode; import org.olat.course.nodes.IQSURVCourseNode; @@ -76,7 +73,7 @@ public class CourseQTIArchiveController extends BasicController { private CloseableModalController cmc; private OLATResourceable ores; - private List nodesTableObjectArrayList; + private List<NodeTableRow> nodesTableObjectArrayList; private Link startExportDummyButton; private Link startExportButton; @@ -114,9 +111,9 @@ public class CourseQTIArchiveController extends BasicController { public void event(UserRequest ureq, Component source, Event event) { ICourse course = CourseFactory.loadCourse(ores); if (source == startExportButton){ - qawc = AssessmentUIFactory.createQTIArchiveWizardController(false, ureq, nodesTableObjectArrayList, course, getWindowControl()); + qawc = new QTIArchiveWizardController(false, ureq, nodesTableObjectArrayList, course, getWindowControl()); } else if (source == startExportDummyButton){ - qawc = AssessmentUIFactory.createQTIArchiveWizardController(true, ureq, nodesTableObjectArrayList, course, getWindowControl()); + qawc = new QTIArchiveWizardController(true, ureq, nodesTableObjectArrayList, course, getWindowControl()); } listenTo(qawc); cmc = new CloseableModalController(getWindowControl(), translate("close"), qawc.getInitialComponent()); @@ -140,7 +137,7 @@ public class CourseQTIArchiveController extends BasicController { * @param ureq * @return */ - private List doNodeChoose(UserRequest ureq){ + private List<NodeTableRow> doNodeChoose(UserRequest ureq){ //table configuraton TableGuiConfiguration tableConfig = new TableGuiConfiguration(); tableConfig.setTableEmptyMessage(translate("nodesoverview.nonodes")); @@ -163,7 +160,7 @@ public class CourseQTIArchiveController extends BasicController { // get list of course node data and populate table data model ICourse course = CourseFactory.loadCourse(ores); CourseNode rootNode = course.getRunStructure().getRootNode(); - List objectArrayList = addQTINodesAndParentsToList(0, rootNode); + List<NodeTableRow> objectArrayList = addQTINodesAndParentsToList(0, rootNode); return objectArrayList; } @@ -174,15 +171,15 @@ public class CourseQTIArchiveController extends BasicController { * @param courseNode * @return A list of Object[indent, courseNode, selectable] */ - @SuppressWarnings("unchecked") - private List addQTINodesAndParentsToList(int recursionLevel, CourseNode courseNode) { + private List<NodeTableRow> addQTINodesAndParentsToList(int recursionLevel, CourseNode courseNode) { // 1) Get list of children data using recursion of this method - List childrenData = new ArrayList(); + List<NodeTableRow> childrenData = new ArrayList<>(); for (int i = 0; i < courseNode.getChildCount(); i++) { CourseNode child = (CourseNode) courseNode.getChildAt(i); - List childData = addQTINodesAndParentsToList( (recursionLevel + 1), child); - if (childData != null) + List<NodeTableRow> childData = addQTINodesAndParentsToList( (recursionLevel + 1), child); + if (childData != null) { childrenData.addAll(childData); + } } if (childrenData.size() > 0 @@ -192,27 +189,17 @@ public class CourseQTIArchiveController extends BasicController { // Store node data in hash map. This hash map serves as data model for // the tasks overview table. Leave user data empty since not used in // this table. (use only node data) - Map nodeData = new HashMap(); - // indent - nodeData.put(AssessmentHelper.KEY_INDENT, new Integer(recursionLevel)); - // course node data - nodeData.put(AssessmentHelper.KEY_TYPE, courseNode.getType()); - nodeData.put(AssessmentHelper.KEY_TITLE_SHORT, courseNode.getShortTitle()); - nodeData.put(AssessmentHelper.KEY_TITLE_LONG, courseNode.getLongTitle()); - nodeData.put(AssessmentHelper.KEY_IDENTIFYER, courseNode.getIdent()); - + NodeTableRow nodeData = new NodeTableRow(recursionLevel, courseNode); if (courseNode instanceof IQTESTCourseNode || courseNode instanceof IQSELFCourseNode || courseNode instanceof IQSURVCourseNode){ - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.TRUE); - } - else { - nodeData.put(AssessmentHelper.KEY_SELECTABLE, Boolean.FALSE); + nodeData.setSelectable(true); + } else { + nodeData.setSelectable(false); } - List nodeAndChildren = new ArrayList(); + List<NodeTableRow> nodeAndChildren = new ArrayList<>(); nodeAndChildren.add(nodeData); - nodeAndChildren.addAll(childrenData); return nodeAndChildren; } diff --git a/src/main/java/org/olat/ims/qti/export/QTIArchiveWizardController.java b/src/main/java/org/olat/ims/qti/export/QTIArchiveWizardController.java index d1f3aa7448e04954214c55582a286bfe326d7b96..6246846ab609ad3c3feb2712d7e7060d952d5a4f 100644 --- a/src/main/java/org/olat/ims/qti/export/QTIArchiveWizardController.java +++ b/src/main/java/org/olat/ims/qti/export/QTIArchiveWizardController.java @@ -58,9 +58,9 @@ import org.olat.core.util.WebappHelper; import org.olat.core.util.coordinate.LockResult; import org.olat.course.CourseFactory; import org.olat.course.ICourse; -import org.olat.course.assessment.AssessmentHelper; import org.olat.course.assessment.IndentedNodeRenderer; import org.olat.course.assessment.NodeTableDataModel; +import org.olat.course.assessment.NodeTableRow; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.IQSELFCourseNode; import org.olat.course.nodes.IQSURVCourseNode; @@ -89,7 +89,6 @@ import de.bps.onyx.plugin.OnyxExportManager; */ public class QTIArchiveWizardController extends BasicController { private static final String CMD_SELECT_NODE = "cmd.select.node"; - private static final String CMD_BACK = "back"; private boolean dummyMode; @@ -125,8 +124,8 @@ public class QTIArchiveWizardController extends BasicController { private String targetFileName; private int type; private Map qtiItemConfigs; - private List results; - private List qtiItemObjectList; + private List<QTIResult> results; + private List<QTIItemObject> qtiItemObjectList; private Link showFileButton; private Link backLinkAtOptionChoose; private Link backLinkAtNoResults; @@ -134,7 +133,7 @@ public class QTIArchiveWizardController extends BasicController { private OLATResourceable ores; - public QTIArchiveWizardController(boolean dummyMode, UserRequest ureq, List nodesTableObjectArrayList, OLATResourceable ores, WindowControl wControl) { + public QTIArchiveWizardController(boolean dummyMode, UserRequest ureq, List<NodeTableRow> nodesTableObjectArrayList, OLATResourceable ores, WindowControl wControl) { super(ureq, wControl); this.dummyMode = dummyMode; this.ores = ores; @@ -219,9 +218,9 @@ public class QTIArchiveWizardController extends BasicController { String actionid = te.getActionId(); if (actionid.equals(CMD_SELECT_NODE)) { int rowid = te.getRowId(); - Map nodeData = (Map) nodeTableModel.getObject(rowid); + NodeTableRow nodeData = nodeTableModel.getObject(rowid); ICourse course = CourseFactory.loadCourse(ores); - this.currentCourseNode = course.getRunStructure().getNode((String) nodeData.get(AssessmentHelper.KEY_IDENTIFYER)); + this.currentCourseNode = course.getRunStructure().getNode(nodeData.getIdent()); boolean isOnyx = false; if (currentCourseNode.getModuleConfiguration().get(IQEditController.CONFIG_KEY_TYPE_QTI) != null) { @@ -275,10 +274,9 @@ public class QTIArchiveWizardController extends BasicController { QTIResultManager qrm = QTIResultManager.getInstance(); results = qrm.selectResults(olatResource, currentCourseNode.getIdent(), repKey, type); - QTIResult res0 = (QTIResult) results.get(0); + QTIResult res0 = results.get(0); - QTIObjectTreeBuilder qotb = new QTIObjectTreeBuilder(new Long(res0.getResultSet().getRepositoryRef())); - qtiItemObjectList = qotb.getQTIItemObjectList(); + qtiItemObjectList = new QTIObjectTreeBuilder().getQTIItemObjectList(new Long(res0.getResultSet().getRepositoryRef())); qtiItemConfigs = getQTIItemConfigs(); diff --git a/src/main/java/org/olat/ims/qti/export/QTIExportFormatter.java b/src/main/java/org/olat/ims/qti/export/QTIExportFormatter.java index ab10a5e5bdca7b48f83dacd1ae61c29db5740c97..f2e2753ba3eeec65ec0280b69385e0a020ea74ae 100644 --- a/src/main/java/org/olat/ims/qti/export/QTIExportFormatter.java +++ b/src/main/java/org/olat/ims/qti/export/QTIExportFormatter.java @@ -34,6 +34,7 @@ import org.olat.core.gui.translator.PackageTranslator; import org.olat.core.gui.translator.Translator; import org.olat.core.util.Util; import org.olat.ims.qti.export.helper.IdentityAnonymizerCallback; +import org.olat.ims.qti.export.helper.QTIItemObject; /** * Initial Date: May 23, 2006 <br> @@ -45,8 +46,8 @@ public abstract class QTIExportFormatter { protected StringBuilder sb; protected Translator translator; protected IdentityAnonymizerCallback anonymizerCallback; - protected List qtiItemObjectList; - protected Map mapWithExportItemConfigs; + protected List<QTIItemObject> qtiItemObjectList; + protected Map<Class<?>, QTIExportItemFormatConfig> mapWithExportItemConfigs; /** * @@ -71,7 +72,7 @@ public abstract class QTIExportFormatter { * * @param qtiItemObjectList */ - public void setQTIItemObjectList(List qtiItemObjectList){ + public void setQTIItemObjectList(List<QTIItemObject> qtiItemObjectList){ this.qtiItemObjectList = qtiItemObjectList; } @@ -79,7 +80,7 @@ public abstract class QTIExportFormatter { * * @param mapWithConfigs */ - public void setMapWithExportItemConfigs(Map mapWithConfigs){ + public void setMapWithExportItemConfigs(Map<Class<?>, QTIExportItemFormatConfig> mapWithConfigs){ this.mapWithExportItemConfigs = mapWithConfigs; } @@ -88,7 +89,7 @@ public abstract class QTIExportFormatter { * * @return */ - public Map getMapWithExportItemConfigs(){ + public Map<Class<?>, QTIExportItemFormatConfig> getMapWithExportItemConfigs(){ return this.mapWithExportItemConfigs; } } diff --git a/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType1.java b/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType1.java index 110d2d5856a7b3133bc31e855f511004e084ef87..38e590b000ac9ddf30ed7e4e511ca8be66590861 100644 --- a/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType1.java +++ b/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType1.java @@ -95,8 +95,8 @@ public class QTIExportFormatterCSVType1 extends QTIExportFormatter { StringBuilder hR2 = new StringBuilder(); int i = 1; - for (Iterator iter = qtiItemObjectList.iterator(); iter.hasNext();) { - QTIItemObject item = (QTIItemObject) iter.next(); + for (Iterator<QTIItemObject> iter = qtiItemObjectList.iterator(); iter.hasNext();) { + QTIItemObject item = iter.next(); if (displayItem(qeif.getExportItemConfig(item))) { hR1.append(emb); @@ -297,8 +297,8 @@ public class QTIExportFormatterCSVType1 extends QTIExportFormatter { sb.append(legend); sb.append(car + car); int y = 1; - for (Iterator iter = qtiItemObjectList.iterator(); iter.hasNext();) { - QTIItemObject element = (QTIItemObject) iter.next(); + for (Iterator<QTIItemObject> iter = qtiItemObjectList.iterator(); iter.hasNext();) { + QTIItemObject element = iter.next(); sb.append(element.getItemIdent()); sb.append(sep); @@ -505,10 +505,10 @@ public class QTIExportFormatterCSVType1 extends QTIExportFormatter { } private void setDefaultQTIItemConfigs() { - Map itConfigs = new HashMap(); + Map<Class<?>, QTIExportItemFormatConfig> itConfigs = new HashMap<>(); - for (Iterator iter = qtiItemObjectList.iterator(); iter.hasNext();) { - QTIItemObject item = (QTIItemObject) iter.next(); + for (Iterator<QTIItemObject> iter = qtiItemObjectList.iterator(); iter.hasNext();) { + QTIItemObject item = iter.next(); if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_SCQ)) { if (itConfigs.get(QTIExportSCQItemFormatConfig.class) == null) { QTIExportSCQItemFormatConfig confSCQ = new QTIExportSCQItemFormatConfig(true, false, false, false); diff --git a/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType2.java b/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType2.java index 9295d082cc9328eb4ef2a744355b185af0a96c54..3b78ebb91f712140552f5e5402c0b452147674e7 100644 --- a/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType2.java +++ b/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType2.java @@ -481,10 +481,10 @@ public class QTIExportFormatterCSVType2 extends QTIExportFormatter { } private void setDefaultQTIItemConfigs() { - Map itConfigs = new HashMap(); + Map<Class<?>, QTIExportItemFormatConfig> itConfigs = new HashMap<>(); - for (Iterator iter = qtiItemObjectList.iterator(); iter.hasNext();) { - QTIItemObject item = (QTIItemObject) iter.next(); + for (Iterator<QTIItemObject> iter = qtiItemObjectList.iterator(); iter.hasNext();) { + QTIItemObject item = iter.next(); if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_SCQ)) { if (itConfigs.get(QTIExportSCQItemFormatConfig.class) == null) { QTIExportSCQItemFormatConfig confSCQ = new QTIExportSCQItemFormatConfig(true, false, false, false); diff --git a/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType3.java b/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType3.java index c7a8d54eec938f2008ab674f37c7854fb13dd121..53503c69490b1c82f8baaee802d5b6ed56425d5c 100644 --- a/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType3.java +++ b/src/main/java/org/olat/ims/qti/export/QTIExportFormatterCSVType3.java @@ -100,8 +100,8 @@ public class QTIExportFormatterCSVType3 extends QTIExportFormatter{ StringBuilder hR2 = new StringBuilder(); int i = 1; - for (Iterator iter = qtiItemObjectList.iterator(); iter.hasNext();) { - QTIItemObject item = (QTIItemObject) iter.next(); + for (Iterator<QTIItemObject> iter = qtiItemObjectList.iterator(); iter.hasNext();) { + QTIItemObject item = iter.next(); if(displayItem(qeif.getExportItemConfig(item))){ hR1.append(emb); hR1.append(escape(item.getItemTitle())); @@ -262,8 +262,8 @@ public class QTIExportFormatterCSVType3 extends QTIExportFormatter{ sb.append(legend); sb.append(car+car); int y = 1; - for (Iterator iter = qtiItemObjectList.iterator(); iter.hasNext();) { - QTIItemObject element = (QTIItemObject) iter.next(); + for (Iterator<QTIItemObject> iter = qtiItemObjectList.iterator(); iter.hasNext();) { + QTIItemObject element = iter.next(); sb.append(element.getItemIdent()); sb.append(sep); @@ -399,11 +399,10 @@ public class QTIExportFormatterCSVType3 extends QTIExportFormatter{ return s.replaceAll(emb, emb + emb); } - @SuppressWarnings("unchecked") private void setDefaultQTIItemConfigs(){ - Map itConfigs = new HashMap(); + Map<Class<?>, QTIExportItemFormatConfig> itConfigs = new HashMap<>(); - for (Iterator iter = qtiItemObjectList.iterator(); iter.hasNext();) { + for (Iterator<QTIItemObject> iter = qtiItemObjectList.iterator(); iter.hasNext();) { QTIItemObject item = (QTIItemObject) iter.next(); if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_SCQ)){ if (itConfigs.get(QTIExportSCQItemFormatConfig.class) == null){ diff --git a/src/main/java/org/olat/ims/qti/export/QTIExportItemFactory.java b/src/main/java/org/olat/ims/qti/export/QTIExportItemFactory.java index e1103eefcfe34b9c5282f34761b7f2a452827fd9..6ba8d81dc77535f5b874c9368a73bd06dfb437e7 100644 --- a/src/main/java/org/olat/ims/qti/export/QTIExportItemFactory.java +++ b/src/main/java/org/olat/ims/qti/export/QTIExportItemFactory.java @@ -38,9 +38,9 @@ import org.olat.ims.qti.export.helper.QTIItemObject; * @author Alexander Schneider */ public class QTIExportItemFactory { - private Map configs; + private Map<Class<?>, QTIExportItemFormatConfig> configs; - public QTIExportItemFactory(Map mapWithConfigs){ + public QTIExportItemFactory(Map<Class<?>, QTIExportItemFormatConfig> mapWithConfigs){ this.configs = mapWithConfigs; } @@ -48,40 +48,40 @@ public class QTIExportItemFactory { QTIExportItem eItem = null; if(item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_SCQ)){ eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportSCQItemFormatConfig) configs.get(QTIExportSCQItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportSCQItemFormatConfig.class)); } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_MCQ)){ // Checkbox eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportMCQItemFormatConfig) configs.get(QTIExportMCQItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportMCQItemFormatConfig.class)); } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_KPRIM)){ // Kprim eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportKPRIMItemFormatConfig) configs.get(QTIExportKPRIMItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportKPRIMItemFormatConfig.class)); } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_ESSAY)){ // Area eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportEssayItemFormatConfig) configs.get(QTIExportEssayItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportEssayItemFormatConfig.class)); } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_FIB)){ // Blank eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportFIBItemFormatConfig) configs.get(QTIExportFIBItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportFIBItemFormatConfig.class)); } // if cannot find the type via the ItemParser, look for the QTIItemObject type else if (item.getItemType().equals(QTIItemObject.TYPE.A)){ eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportEssayItemFormatConfig) configs.get(QTIExportEssayItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportEssayItemFormatConfig.class)); } else if (item.getItemType().equals(QTIItemObject.TYPE.R)){ eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportSCQItemFormatConfig) configs.get(QTIExportSCQItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportSCQItemFormatConfig.class)); } else if (item.getItemType().equals(QTIItemObject.TYPE.C)){ eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportMCQItemFormatConfig) configs.get(QTIExportMCQItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportMCQItemFormatConfig.class)); } else if (item.getItemType().equals(QTIItemObject.TYPE.B)){ eItem = new QTIExportItem(qtir, item); - eItem.setConfig((QTIExportFIBItemFormatConfig) configs.get(QTIExportFIBItemFormatConfig.class)); + eItem.setConfig(configs.get(QTIExportFIBItemFormatConfig.class)); } else{ throw new OLATRuntimeException(null,"Can not resolve QTIItem type", null); @@ -92,37 +92,36 @@ public class QTIExportItemFactory { public QTIExportItemFormatConfig getExportItemConfig(QTIItemObject item){ QTIExportItemFormatConfig config = null; if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_SCQ)){ // Radio - config = (QTIExportSCQItemFormatConfig) configs.get(QTIExportSCQItemFormatConfig.class); + config = configs.get(QTIExportSCQItemFormatConfig.class); } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_MCQ)){ // Checkbox - config = (QTIExportMCQItemFormatConfig) configs.get(QTIExportMCQItemFormatConfig.class); + config = configs.get(QTIExportMCQItemFormatConfig.class); } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_KPRIM)){ // KPRIM - config = (QTIExportKPRIMItemFormatConfig) configs.get(QTIExportKPRIMItemFormatConfig.class); + config = configs.get(QTIExportKPRIMItemFormatConfig.class); } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_ESSAY)){ // Area - config = (QTIExportEssayItemFormatConfig) configs.get(QTIExportEssayItemFormatConfig.class); + config = configs.get(QTIExportEssayItemFormatConfig.class); } else if (item.getItemIdent().startsWith(ItemParser.ITEM_PREFIX_FIB)){ // Blank - config = (QTIExportFIBItemFormatConfig) configs.get(QTIExportFIBItemFormatConfig.class); + config = configs.get(QTIExportFIBItemFormatConfig.class); } // if cannot find the type via the ItemParser, look for the QTIItemObject type else if (item.getItemType().equals(QTIItemObject.TYPE.A)){ - config = (QTIExportEssayItemFormatConfig) configs.get(QTIExportEssayItemFormatConfig.class); + config = configs.get(QTIExportEssayItemFormatConfig.class); } else if (item.getItemType().equals(QTIItemObject.TYPE.R)){ - config = (QTIExportSCQItemFormatConfig) configs.get(QTIExportSCQItemFormatConfig.class); + config = configs.get(QTIExportSCQItemFormatConfig.class); } else if (item.getItemType().equals(QTIItemObject.TYPE.C)){ - config = (QTIExportMCQItemFormatConfig) configs.get(QTIExportMCQItemFormatConfig.class); + config = configs.get(QTIExportMCQItemFormatConfig.class); } else if (item.getItemType().equals(QTIItemObject.TYPE.B)){ - config = (QTIExportFIBItemFormatConfig) configs.get(QTIExportFIBItemFormatConfig.class); + config = configs.get(QTIExportFIBItemFormatConfig.class); } else{ throw new OLATRuntimeException(null,"Can not resolve QTIItem type", null); } return config; } - -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/ims/qti/export/QTIExportManager.java b/src/main/java/org/olat/ims/qti/export/QTIExportManager.java index 995993c2934421fae938d979affc023eec127f6d..e2afdcbcd8ef5d164e6356f13c2e8905c5910bf4 100644 --- a/src/main/java/org/olat/ims/qti/export/QTIExportManager.java +++ b/src/main/java/org/olat/ims/qti/export/QTIExportManager.java @@ -26,6 +26,7 @@ package org.olat.ims.qti.export; import java.io.File; +import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -33,7 +34,10 @@ import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; import org.olat.core.manager.BasicManager; import org.olat.core.util.ExportUtil; import org.olat.core.util.Formatter; @@ -41,6 +45,7 @@ import org.olat.ims.qti.QTIResult; import org.olat.ims.qti.QTIResultManager; import org.olat.ims.qti.export.helper.QTIItemObject; import org.olat.ims.qti.export.helper.QTIObjectTreeBuilder; +import org.olat.repository.RepositoryEntry; /** * Description: TODO @@ -82,17 +87,14 @@ public class QTIExportManager extends BasicManager{ * should be used (only for type 2 and 3) * @return */ - public boolean selectAndExportResults(QTIExportFormatter qef, Long olatResource, String shortTitle, String olatResourceDetail, Long repositoryRef, - File exportDirectory, String charset, String fileNameSuffix) { + public boolean selectAndExportResults(QTIExportFormatter qef, Long courseResId, String shortTitle, String olatResourceDetail, + Long testReKey, File exportDirectory, String charset, String fileNameSuffix) { boolean resultsFoundAndExported = false; QTIResultManager qrm = QTIResultManager.getInstance(); - List<QTIResult> results = qrm.selectResults(olatResource, olatResourceDetail, repositoryRef, qef.getType()); + List<QTIResult> results = qrm.selectResults(courseResId, olatResourceDetail, testReKey, qef.getType()); if(results.size() > 0){ QTIResult res0 = results.get(0); - - QTIObjectTreeBuilder qotb = new QTIObjectTreeBuilder(new Long(res0.getResultSet().getRepositoryRef())); - - List<QTIItemObject> qtiItemObjectList = qotb.getQTIItemObjectList(); + List<QTIItemObject> qtiItemObjectList = new QTIObjectTreeBuilder().getQTIItemObjectList(new Long(res0.getResultSet().getRepositoryRef())); qef.setQTIItemObjectList(qtiItemObjectList); if (results.size() > 0) { createContentOfExportFile(results,qtiItemObjectList,qef); @@ -103,6 +105,28 @@ public class QTIExportManager extends BasicManager{ return resultsFoundAndExported; } + public boolean selectAndExportResults(QTIExportFormatter qef, Long courseResId, String shortTitle, + String olatResourceDetail, RepositoryEntry testRe, ZipOutputStream exportStream, String charset, + String fileNameSuffix) throws IOException { + boolean resultsFoundAndExported = false; + QTIResultManager qrm = QTIResultManager.getInstance(); + List<QTIResult> results = qrm.selectResults(courseResId, olatResourceDetail, testRe.getKey(), qef.getType()); + if(results.size() > 0){ + List<QTIItemObject> qtiItemObjectList = new QTIObjectTreeBuilder().getQTIItemObjectList(testRe); + qef.setQTIItemObjectList(qtiItemObjectList); + if (results.size() > 0) { + createContentOfExportFile(results, qtiItemObjectList, qef); + String targetFileName = getFilename(shortTitle, qef, fileNameSuffix); + + exportStream.putNextEntry(new ZipEntry(targetFileName)); + IOUtils.write(qef.getReport(), exportStream); + exportStream.closeEntry(); + resultsFoundAndExported = true; + } + } + return resultsFoundAndExported; + } + /** * * @param qef @@ -114,7 +138,7 @@ public class QTIExportManager extends BasicManager{ * @param fileNameSuffix * @return */ - public String exportResults(QTIExportFormatter qef, List results, List qtiItemObjectList, String shortTitle, File exportDirectory, String charset, String fileNameSuffix) { + public String exportResults(QTIExportFormatter qef, List<QTIResult> results, List<QTIItemObject> qtiItemObjectList, String shortTitle, File exportDirectory, String charset, String fileNameSuffix) { String targetFileName = null; qef.setQTIItemObjectList(qtiItemObjectList); @@ -133,26 +157,24 @@ public class QTIExportManager extends BasicManager{ * @param anonymizerCallback * @return String */ - private void createContentOfExportFile(List qtiResults, List qtiItemObjectList, QTIExportFormatter qef) { + private void createContentOfExportFile(List<QTIResult> qtiResults, List<QTIItemObject> qtiItemObjectList, QTIExportFormatter qef) { qef.openReport(); //formatter has information about how to format the different qti objects - Map mapWithConfigs = qef.getMapWithExportItemConfigs(); + Map<Class<?>, QTIExportItemFormatConfig> mapWithConfigs = qef.getMapWithExportItemConfigs(); QTIExportItemFactory qeif = new QTIExportItemFactory(mapWithConfigs); while (qtiResults.size() > 0){ - List assessIDresults = stripNextAssessID(qtiResults); + List<QTIResult> assessIDresults = stripNextAssessID(qtiResults); - qef.openResultSet(new QTIExportSet((QTIResult)assessIDresults.get(0))); + qef.openResultSet(new QTIExportSet(assessIDresults.get(0))); - for (Iterator iter = qtiItemObjectList.iterator(); iter.hasNext();) { - QTIItemObject element = (QTIItemObject) iter.next(); + for (Iterator<QTIItemObject> iter = qtiItemObjectList.iterator(); iter.hasNext();) { + QTIItemObject element = iter.next(); - QTIResult qtir; - qtir = element.extractQTIResult(assessIDresults); + QTIResult qtir = element.extractQTIResult(assessIDresults); qef.visit(qeif.getExportItem(qtir,element)); - } qef.closeResultSet(); } @@ -164,6 +186,12 @@ public class QTIExportManager extends BasicManager{ */ private String writeContentToFile(String shortTitle, File exportDirectory, String charset, QTIExportFormatter qef, String fileNameSuffix) { // defining target filename + String targetFileName = getFilename(shortTitle, qef, fileNameSuffix); + ExportUtil.writeContentToFile(targetFileName, qef.getReport(), exportDirectory, charset); + return targetFileName; + } + + private String getFilename(String shortTitle, QTIExportFormatter qef, String fileNameSuffix) { StringBuilder tf = new StringBuilder(); tf.append(qef.getFileNamePrefix()); tf.append(Formatter.makeStringFilesystemSave(shortTitle)); @@ -173,9 +201,6 @@ public class QTIExportManager extends BasicManager{ tf.append(timestamp); tf.append(fileNameSuffix); String targetFileName = tf.toString(); - - ExportUtil.writeContentToFile(targetFileName, qef.getReport(), exportDirectory, charset); - return targetFileName; } @@ -184,12 +209,12 @@ public class QTIExportManager extends BasicManager{ * @param queryResult * @return List of results with the same assessmentid */ - private List stripNextAssessID(List queryResult){ - List result = new ArrayList(); + private List<QTIResult> stripNextAssessID(List<QTIResult> queryResult){ + List<QTIResult> result = new ArrayList<>(); if (queryResult.size()== 0) return result; - QTIResult qtir = (QTIResult) queryResult.remove(0); + QTIResult qtir = queryResult.remove(0); long currentAssessmentID = qtir.getResultSet().getAssessmentID(); result.add(qtir); diff --git a/src/main/java/org/olat/ims/qti/export/helper/QTIObjectTreeBuilder.java b/src/main/java/org/olat/ims/qti/export/helper/QTIObjectTreeBuilder.java index 43dea4e0ae74775edfabd1e7902f51a30b57fb10..c590de99dc77e97e9d8e934aaca844da614241bb 100644 --- a/src/main/java/org/olat/ims/qti/export/helper/QTIObjectTreeBuilder.java +++ b/src/main/java/org/olat/ims/qti/export/helper/QTIObjectTreeBuilder.java @@ -33,6 +33,7 @@ import org.dom4j.Document; import org.dom4j.Element; import org.olat.ims.qti.process.ImsRepositoryResolver; import org.olat.ims.qti.process.Resolver; +import org.olat.repository.RepositoryEntry; /** * <pre> @@ -84,31 +85,21 @@ import org.olat.ims.qti.process.Resolver; public class QTIObjectTreeBuilder { - private Long repositoryEntryKey; + public List<QTIItemObject> getQTIItemObjectList(Long entryKey) { + Resolver resolver = new ImsRepositoryResolver(entryKey); + return getQTIItemObjectList(resolver); + } - /** - * Constructor for QTIObjectTreeBuilder - * @param repositoryEntryKey - * @param downloadtrans - * @param type - * @param anonymizerCallback - */ - public QTIObjectTreeBuilder(Long repositoryEntryKey) { - this.repositoryEntryKey = repositoryEntryKey; + public List<QTIItemObject> getQTIItemObjectList(RepositoryEntry entry) { + Resolver resolver = new ImsRepositoryResolver(entry); + return getQTIItemObjectList(resolver); } - /** - * - * - */ - public List<QTIItemObject> getQTIItemObjectList() { - Resolver resolver = new ImsRepositoryResolver(repositoryEntryKey); + private final List<QTIItemObject> getQTIItemObjectList(Resolver resolver) { Document doc = resolver.getQTIDocument(); Element root = doc.getRootElement(); List<Element> items = root.selectNodes("//item"); - List<QTIItemObject> itemList = new ArrayList<QTIItemObject>(); - for (Iterator<Element> iter= items.iterator(); iter.hasNext();) { Element el_item= iter.next(); if (el_item.selectNodes(".//response_lid").size() > 0){ diff --git a/src/main/java/org/olat/ims/qti/process/ImsRepositoryResolver.java b/src/main/java/org/olat/ims/qti/process/ImsRepositoryResolver.java index e89b27210dfbf50240ba5f862c4f9e897790187e..b686d3976fada0b5e25c616a0f74b3eabe205529 100644 --- a/src/main/java/org/olat/ims/qti/process/ImsRepositoryResolver.java +++ b/src/main/java/org/olat/ims/qti/process/ImsRepositoryResolver.java @@ -33,6 +33,8 @@ import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.olat.core.id.OLATResourceable; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.FileUtils; import org.olat.core.util.WebappHelper; import org.olat.core.util.vfs.LocalFileImpl; @@ -51,6 +53,8 @@ import org.olat.resource.OLATResource; * @author Mike Stock Comment: */ public class ImsRepositoryResolver implements Resolver { + + private static final OLog log = Tracing.createLoggerFor(ImsRepositoryResolver.class); public static final String QTI_FILE = "qti.xml"; public static final String QTI_FIB_AUTOCOMPLETE_JS_FILE = "media/fibautocompl.js"; @@ -67,6 +71,13 @@ public class ImsRepositoryResolver implements Resolver { init(ores); } } + + public ImsRepositoryResolver(RepositoryEntry entry) { + if (entry != null) { + OLATResource ores = entry.getOlatResource(); + init(ores); + } + } public ImsRepositoryResolver(OLATResourceable fileResource) { init(fileResource); @@ -124,28 +135,27 @@ public class ImsRepositoryResolver implements Resolver { // no change log return new QTIChangeLogMessage[0]; } - List items = dirChangelog.getItems(); + List<VFSItem> items = dirChangelog.getItems(); // PRECONDITION: only changelog files in the changelog directory - QTIChangeLogMessage[] log = new QTIChangeLogMessage[items.size()]; + QTIChangeLogMessage[] logArr = new QTIChangeLogMessage[items.size()]; String filName; String msg; int i = 0; java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH_mm_ss"); - for (Iterator iter = items.iterator(); iter.hasNext();) { + for (Iterator<VFSItem> iter = items.iterator(); iter.hasNext();) { VFSLeaf file = (VFSLeaf) iter.next(); filName = file.getName(); String[] parts = filName.split("\\."); msg = FileUtils.load(file.getInputStream(), "utf-8"); try { - log[i] = new QTIChangeLogMessage(msg, parts[1].equals("all"), formatter.parse(parts[0]).getTime()); + logArr[i] = new QTIChangeLogMessage(msg, parts[1].equals("all"), formatter.parse(parts[0]).getTime()); i++; } catch (ParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + log.error("", e); } } - return log; + return logArr; } /** diff --git a/src/main/java/org/olat/modules/fo/ForumController.java b/src/main/java/org/olat/modules/fo/ForumController.java index ba685d2ca58fccafb4eb508f79c91293053ea122..6946ae486b0b59f5b18a237aefb98974826ad828 100644 --- a/src/main/java/org/olat/modules/fo/ForumController.java +++ b/src/main/java/org/olat/modules/fo/ForumController.java @@ -679,7 +679,7 @@ public class ForumController extends BasicController implements GenericEventList private void doArchiveForum(UserRequest ureq) { ForumRTFFormatter rtff = new ForumRTFFormatter(getArchiveContainer(ureq), false); ForumArchiveManager fam = ForumArchiveManager.getInstance(); - fam.applyFormatter(rtff, forum.getKey().longValue(), focallback); + fam.applyFormatter(rtff, forum.getKey(), focallback); } private void doArchiveThread(UserRequest ureq, Message currMsg) { @@ -688,7 +688,7 @@ public class ForumController extends BasicController implements GenericEventList ForumRTFFormatter rtff = new ForumRTFFormatter(getArchiveContainer(ureq), true); ForumArchiveManager fam = ForumArchiveManager.getInstance(); - fam.applyFormatterForOneThread(rtff, forum.getKey().longValue(), topMessageId.longValue()); + fam.applyFormatterForOneThread(rtff, forum.getKey(), topMessageId); } diff --git a/src/main/java/org/olat/modules/fo/ForumHelper.java b/src/main/java/org/olat/modules/fo/ForumHelper.java index 897b8a788c7f58627c7bba00caa7bc92d8102353..3690843e47810101f19c6d34e5cd57ec954de5c7 100644 --- a/src/main/java/org/olat/modules/fo/ForumHelper.java +++ b/src/main/java/org/olat/modules/fo/ForumHelper.java @@ -56,22 +56,8 @@ public class ForumHelper { * @return a MessageNode comparator. * @see java.util.Comparator */ - public static Comparator getMessageNodeComparator() { - return new Comparator(){ - //puts the sticky threads first - public int compare(final Object o1, final Object o2) { - MessageNode m1 = (MessageNode)o1; - MessageNode m2 = (MessageNode)o2; - if(m1.isSticky() && m2.isSticky()) { - return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first - } else if(m1.isSticky()) { - return -1; - } else if(m2.isSticky()){ - return 1; - } else { - return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first - } - }}; + public static Comparator<MessageNode> getMessageNodeComparator() { + return new MessageNodeComparator(); } /** @@ -171,4 +157,17 @@ public class ForumHelper { } } -} + private static class MessageNodeComparator implements Comparator<MessageNode> { + public int compare(final MessageNode m1, final MessageNode m2) { + if(m1.isSticky() && m2.isSticky()) { + return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first + } else if(m1.isSticky()) { + return -1; + } else if(m2.isSticky()){ + return 1; + } else { + return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first + } + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/modules/fo/ForumManager.java b/src/main/java/org/olat/modules/fo/ForumManager.java index e40193f81924ae74fda6fc34ecb0f520faf63dec..9f95ef823b3638a5e5be60fe4b17014cd8e5c511 100644 --- a/src/main/java/org/olat/modules/fo/ForumManager.java +++ b/src/main/java/org/olat/modules/fo/ForumManager.java @@ -66,6 +66,8 @@ public class ForumManager extends BasicManager { private static ForumManager INSTANCE; @Autowired private TextService txtService; + @Autowired + private DB dbInstance; /** * [spring] @@ -229,7 +231,7 @@ public class ForumManager extends BasicManager { return messages; } - private int countMessagesByForumID(Long forum_id, boolean onlyThreads) { + private int countMessagesByForumID(Long forumId, boolean onlyThreads) { StringBuilder query = new StringBuilder(); query.append("select count(msg) from ").append(MessageImpl.class.getName()).append(" as msg") .append(" where msg.forum.key=:forumId "); @@ -237,11 +239,11 @@ public class ForumManager extends BasicManager { query.append(" and msg.parent is null"); } - DBQuery dbQuery = DBFactory.getInstance().createQuery(query.toString()); - dbQuery.setLong("forumId", forum_id); - - Number totalCount = (Number)dbQuery.uniqueResult(); - return totalCount.intValue(); + return dbInstance.getCurrentEntityManager() + .createQuery(query.toString(), Number.class) + .setParameter("forumId", forumId) + .getSingleResult() + .intValue(); } /** diff --git a/src/main/java/org/olat/modules/fo/archiver/ForumArchiveManager.java b/src/main/java/org/olat/modules/fo/archiver/ForumArchiveManager.java index 42851f77ccd56d036930a66cd673b3b81f7c6331..650c3669498999f3af68ddf9c31809a8ac64a390 100644 --- a/src/main/java/org/olat/modules/fo/archiver/ForumArchiveManager.java +++ b/src/main/java/org/olat/modules/fo/archiver/ForumArchiveManager.java @@ -28,13 +28,11 @@ package org.olat.modules.fo.archiver; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Map; +import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; -import org.olat.core.manager.BasicManager; import org.olat.core.util.tree.TreeVisitor; import org.olat.modules.fo.Forum; import org.olat.modules.fo.ForumCallback; @@ -49,10 +47,10 @@ import org.olat.modules.fo.archiver.formatters.ForumFormatter; * @author Alexander Schneider */ -public class ForumArchiveManager extends BasicManager { - private static ForumArchiveManager instance = new ForumArchiveManager(); +public class ForumArchiveManager { + private static final OLog log = Tracing.createLoggerFor(ForumArchiveManager.class); + private static final ForumArchiveManager instance = new ForumArchiveManager(); - //TODO spring config private ForumArchiveManager() { // private since singleton } @@ -72,14 +70,12 @@ public class ForumArchiveManager extends BasicManager { * @param forumCallback * @return */ - public String applyFormatter(ForumFormatter forumFormatter, long forumId, ForumCallback forumCallback){ - Tracing.logInfo("Archiving complete forum: "+forumId, ForumArchiveManager.class); - Map metaInfo = new HashMap(); - metaInfo.put(ForumFormatter.MANDATORY_METAINFO_KEY ,new Long(forumId)); + public String applyFormatter(ForumFormatter forumFormatter, Long forumId, ForumCallback forumCallback){ + log.info("Archiving complete forum: " + forumId); //convert forum structure to trees - List threadTreesList = convertToThreadTrees(forumId, forumCallback); + List<MessageNode> threadTreesList = convertToThreadTrees(forumId, forumCallback); //format forum trees by using the formatter given by the callee - return formatForum(threadTreesList, forumFormatter, metaInfo); + return formatForum(threadTreesList, forumFormatter, forumId); } /** * It is assumed that if the caller of this method is allowed to see the forum thread @@ -89,12 +85,10 @@ public class ForumArchiveManager extends BasicManager { * @param topMessageId * @return the message thread as String formatted */ - public String applyFormatterForOneThread(ForumFormatter forumFormatter, long forumId, long topMessageId){ - Tracing.logInfo("Archiving forum.thread: "+forumId+"."+topMessageId, ForumArchiveManager.class); - Map metaInfo = new HashMap(); - metaInfo.put(ForumFormatter.MANDATORY_METAINFO_KEY ,new Long(forumId)); + public String applyFormatterForOneThread(ForumFormatter forumFormatter, Long forumId, Long topMessageId){ + log.info("Archiving forum.thread: "+forumId+"."+topMessageId); MessageNode topMessageNode = convertToThreadTree(topMessageId); - return formatThread(topMessageNode, forumFormatter, metaInfo); + return formatThread(topMessageNode, forumFormatter, forumId); } /** @@ -105,16 +99,15 @@ public class ForumArchiveManager extends BasicManager { * @param metaInfo * @return all top message nodes together with their children in a list */ - private List convertToThreadTrees(long forumId, ForumCallback forumCallback){ - List messages; - List topNodeList = new ArrayList(); + private List<MessageNode> convertToThreadTrees(Long forumId, ForumCallback forumCallback){ + List<MessageNode> topNodeList = new ArrayList<>(); ForumManager fm = ForumManager.getInstance(); - Long l = new Long(forumId); - Forum f = fm.loadForum(l); - messages = fm.getMessagesByForum(f); + + Forum f = fm.loadForum(forumId); + List<Message> messages = fm.getMessagesByForum(f); - for (Iterator iterTop = messages.iterator(); iterTop.hasNext();) { - Message msg = (Message) iterTop.next(); + for (Iterator<Message> iterTop = messages.iterator(); iterTop.hasNext();) { + Message msg = iterTop.next(); if (msg.getParent() == null) { iterTop.remove(); MessageNode topNode = new MessageNode(msg); @@ -135,8 +128,8 @@ public class ForumArchiveManager extends BasicManager { * @param topNodeList * @return the sorted list. */ - private List getMessagesSorted(List<Message> topNodeList) { - Comparator messageNodeComparator = ForumHelper.getMessageNodeComparator(); + private List<MessageNode> getMessagesSorted(List<MessageNode> topNodeList) { + Comparator<MessageNode> messageNodeComparator = ForumHelper.getMessageNodeComparator(); Collections.sort(topNodeList, messageNodeComparator); return topNodeList; } @@ -147,14 +140,11 @@ public class ForumArchiveManager extends BasicManager { * @param metaInfo * @return the top message node with all its children */ - private MessageNode convertToThreadTree(long topMessageId){ - List messages; + private MessageNode convertToThreadTree(Long topMessageId){ MessageNode topNode = null; - ForumManager fm = ForumManager.getInstance(); - Long l = new Long(topMessageId); - messages = fm.getThread(l); - for (Iterator iterTop = messages.iterator(); iterTop.hasNext();) { - Message msg = (Message) iterTop.next(); + List<Message> messages = ForumManager.getInstance().getThread(topMessageId); + for (Iterator<Message> iterTop = messages.iterator(); iterTop.hasNext();) { + Message msg = iterTop.next(); if (msg.getParent() == null) { iterTop.remove(); topNode = new MessageNode(msg); @@ -164,9 +154,9 @@ public class ForumArchiveManager extends BasicManager { return topNode; } - private void addChildren(List messages, MessageNode mn){ - for(Iterator iterMsg = messages.iterator();iterMsg.hasNext();){ - Message msg = (Message) iterMsg.next(); + private void addChildren(List<Message> messages, MessageNode mn){ + for(Iterator<Message> iterMsg = messages.iterator(); iterMsg.hasNext(); ) { + Message msg = iterMsg.next(); if ((msg.getParent() != null) && (msg.getParent().getKey() == mn.getKey())){ MessageNode childNode = new MessageNode(msg); mn.addChild(childNode); @@ -184,12 +174,12 @@ public class ForumArchiveManager extends BasicManager { * @param metaInfo * @return */ - private String formatForum(List topNodeList, ForumFormatter forumFormatter, Map metaInfo){ - forumFormatter.setForumMetaInformation(metaInfo); + private String formatForum(List<MessageNode> topNodeList, ForumFormatter forumFormatter, Long forumId) { + forumFormatter.setForumKey(forumId); StringBuilder formattedForum = new StringBuilder(); forumFormatter.openForum(); - for (Iterator iterTop = topNodeList.iterator(); iterTop.hasNext();){ - MessageNode mn = (MessageNode) iterTop.next(); + for (Iterator<MessageNode> iterTop = topNodeList.iterator(); iterTop.hasNext();){ + MessageNode mn = iterTop.next(); //a new top thread starts, inform formatter forumFormatter.openThread(); TreeVisitor tv = new TreeVisitor(forumFormatter, mn, false); @@ -207,8 +197,8 @@ public class ForumArchiveManager extends BasicManager { * @param metaInfo * @return */ - private String formatThread(MessageNode mn, ForumFormatter forumFormatter, Map metaInfo){ - forumFormatter.setForumMetaInformation(metaInfo); + private String formatThread(MessageNode mn, ForumFormatter forumFormatter, Long forumId){ + forumFormatter.setForumKey(forumId); StringBuilder formattedThread = new StringBuilder(); forumFormatter.openThread(); TreeVisitor tv = new TreeVisitor(forumFormatter, mn, false); diff --git a/src/main/java/org/olat/modules/fo/archiver/formatters/ForumFormatter.java b/src/main/java/org/olat/modules/fo/archiver/formatters/ForumFormatter.java index 33b7873729c2c9c4b418be3743ff9305e9bd4c43..0f4a0f5d90bb0e82bb48344c86b1a153bd2d0b2b 100644 --- a/src/main/java/org/olat/modules/fo/archiver/formatters/ForumFormatter.java +++ b/src/main/java/org/olat/modules/fo/archiver/formatters/ForumFormatter.java @@ -25,8 +25,6 @@ package org.olat.modules.fo.archiver.formatters; -import java.util.Map; - import org.olat.core.util.nodes.INode; import org.olat.core.util.tree.Visitor; @@ -35,12 +33,11 @@ import org.olat.core.util.tree.Visitor; * @author Patrick Brunner, Alexander Schneider */ -public abstract class ForumFormatter implements Visitor{ +public abstract class ForumFormatter implements Visitor{ protected StringBuilder sb; protected boolean isTopThread = false; protected boolean filePerThread = false; - protected Map metaInfo; - public final static String MANDATORY_METAINFO_KEY ="forum.metainfo.key"; + private Long forumKey; /** * init string buffer @@ -57,8 +54,8 @@ public abstract class ForumFormatter implements Visitor{ * * @param metaInfo */ - public void setForumMetaInformation(Map metaInfo){ - this.metaInfo = metaInfo; + public void setForumKey(Long forumKey){ + this.forumKey = forumKey; } /** * inform formatter that a new top thread has started, @@ -82,8 +79,8 @@ public abstract class ForumFormatter implements Visitor{ * @param key * @return value of key */ - public Object getMetainfo(String key){ - return metaInfo.get(key); + public Long getForumKey() { + return forumKey; } /** @@ -91,7 +88,7 @@ public abstract class ForumFormatter implements Visitor{ * @return true if every thread is saved in his own file; false if all threads are saved in one file */ public boolean isFilePerThread(){ - return this.filePerThread; + return filePerThread; } /** diff --git a/src/main/java/org/olat/modules/fo/archiver/formatters/ForumRTFFormatter.java b/src/main/java/org/olat/modules/fo/archiver/formatters/ForumRTFFormatter.java index a417901801b9f709f6dcbc7425bba93405989317..29135eb118b54b490c6485214a431cb5ba9dd492 100644 --- a/src/main/java/org/olat/modules/fo/archiver/formatters/ForumRTFFormatter.java +++ b/src/main/java/org/olat/modules/fo/archiver/formatters/ForumRTFFormatter.java @@ -43,6 +43,7 @@ import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.id.Identity; import org.olat.core.id.UserConstants; import org.olat.core.logging.AssertException; +import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.Formatter; import org.olat.core.util.WebappHelper; @@ -64,6 +65,8 @@ import org.olat.modules.fo.MessageNode; */ public class ForumRTFFormatter extends ForumFormatter { + + private static final OLog log = Tracing.createLoggerFor(ForumRTFFormatter.class); private VFSContainer container; private VFSItem vfsFil = null; @@ -97,10 +100,7 @@ public class ForumRTFFormatter extends ForumFormatter { super(); // where to write this.container = container; - this.filePerThread = filePerThread; - // - /*Translator translator = new PackageTranslator(PACKAGE, locale); - HIDDEN_STR = translator.translate("fo_hidden");*/ + this.filePerThread = filePerThread; } /** @@ -115,10 +115,10 @@ public class ForumRTFFormatter extends ForumFormatter { //to have a meaningful filename we create the file here String filName = "Thread_" + mn.getKey().toString(); tempContainer = makeTempVFSContainer(); - this.vfsFil=tempContainer.resolve(filName + ".rtf"); + vfsFil=tempContainer.resolve(filName + ".rtf"); if(vfsFil==null){ tempContainer.createChildLeaf(filName + ".rtf"); - this.vfsFil=tempContainer.resolve(filName + ".rtf"); + vfsFil=tempContainer.resolve(filName + ".rtf"); } } //important! @@ -157,8 +157,8 @@ public class ForumRTFFormatter extends ForumFormatter { } sb.append(" \\par}"); // attachment(s) - OlatRootFolderImpl msgContainer = fm.getMessageContainer((Long)(getMetainfo(ForumFormatter.MANDATORY_METAINFO_KEY)), mn.getKey()); - List attachments = msgContainer.getItems(); + OlatRootFolderImpl msgContainer = fm.getMessageContainer(getForumKey(), mn.getKey()); + List<VFSItem> attachments = msgContainer.getItems(); if (attachments != null && attachments.size() > 0){ VFSItem item = container.resolve("attachments"); if (item == null){ @@ -169,8 +169,7 @@ public class ForumRTFFormatter extends ForumFormatter { sb.append("{\\pard \\f0\\fs15 Attachment(s): "); boolean commaFlag = false; - for (Iterator iter = attachments.iterator(); iter.hasNext();) { - VFSItem attachment = (VFSItem) iter.next(); + for (VFSItem attachment: attachments) { if (commaFlag) sb.append(", "); sb.append(attachment.getName()); commaFlag = true; @@ -178,7 +177,6 @@ public class ForumRTFFormatter extends ForumFormatter { sb.append("} \\line"); } sb.append("{\\pard \\brdrb\\brdrs\\brdrw10 \\par}"); - } /** @@ -207,7 +205,7 @@ public class ForumRTFFormatter extends ForumFormatter { sb.append("}"); } writeToFile(append, sb); - if(this.filePerThread) { + if(filePerThread) { zipContainer(tempContainer); tempContainer.delete(); } @@ -221,7 +219,7 @@ public class ForumRTFFormatter extends ForumFormatter { public void openForum(){ if(!filePerThread){ //make one ForumFile - Long forumKey = (Long) metaInfo.get(ForumFormatter.MANDATORY_METAINFO_KEY); + Long forumKey = getForumKey(); String filName = forumKey.toString(); filName = "Threads_" + filName + ".rtf"; @@ -229,7 +227,7 @@ public class ForumRTFFormatter extends ForumFormatter { this.vfsFil=tempContainer.resolve(filName); if(vfsFil==null){ tempContainer.createChildLeaf(filName); - this.vfsFil=tempContainer.resolve(filName); + vfsFil = tempContainer.resolve(filName); } sb.append("{\\rtf1\\ansi\\deff0"); sb.append("{\\fonttbl {\\f0\\fswiss Arial;}} "); @@ -433,7 +431,7 @@ public class ForumRTFFormatter extends ForumFormatter { container.copyFrom(imgFile); fileNameList.add(file.getName()); } else { - Tracing.logError("Could not find image for forum RTF formatter::" + iconPath, ForumFormatter.class); + log.error("Could not find image for forum RTF formatter::" + iconPath); } } return fileNameList; @@ -454,7 +452,7 @@ public class ForumRTFFormatter extends ForumFormatter { * @return the temp container. */ private VFSContainer makeTempVFSContainer() { - Long forumKey = (Long) metaInfo.get(ForumFormatter.MANDATORY_METAINFO_KEY); + Long forumKey = getForumKey(); String dateStamp = String.valueOf(System.currentTimeMillis()); //TODO: (LD) could this filename regarded as unique or use System.nanoTime() instead? String fileName = "forum" + forumKey.toString() + "_" + dateStamp; diff --git a/src/main/java/org/olat/modules/fo/archiver/formatters/ForumStreamedRTFFormatter.java b/src/main/java/org/olat/modules/fo/archiver/formatters/ForumStreamedRTFFormatter.java new file mode 100644 index 0000000000000000000000000000000000000000..468fce2ea050d17126637b6b7923d5e3a7fa0ecb --- /dev/null +++ b/src/main/java/org/olat/modules/fo/archiver/formatters/ForumStreamedRTFFormatter.java @@ -0,0 +1,419 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <hr> +* <a href="http://www.openolat.org"> +* OpenOLAT - Online Learning and Training</a><br> +* This file has been modified by the OpenOLAT community. Changes are licensed +* under the Apache 2.0 license as the original file. +*/ + +package org.olat.modules.fo.archiver.formatters; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringEscapeUtils; +import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; +import org.olat.core.id.Identity; +import org.olat.core.id.UserConstants; +import org.olat.core.logging.AssertException; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.WebappHelper; +import org.olat.core.util.ZipUtil; +import org.olat.core.util.filter.FilterFactory; +import org.olat.core.util.nodes.INode; +import org.olat.core.util.vfs.VFSItem; +import org.olat.modules.fo.ForumManager; +import org.olat.modules.fo.MessageNode; + +/** + * Initial Date: Dec 19, 2013 <br> + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * @author Patrick Brunner, Alexander Schneider + */ +public class ForumStreamedRTFFormatter extends ForumFormatter { + + private static final OLog log = Tracing.createLoggerFor(ForumStreamedRTFFormatter.class); + + private ZipOutputStream exportStream; + private ForumManager fm = ForumManager.getInstance(); + + final Pattern PATTERN_HTML_BOLD = Pattern.compile("<strong>(.*?)</strong>", Pattern.CASE_INSENSITIVE); + final Pattern PATTERN_HTML_ITALIC = Pattern.compile("<em>(.*?)</em>", Pattern.CASE_INSENSITIVE); + final Pattern PATTERN_HTML_BREAK = Pattern.compile("<br />", Pattern.CASE_INSENSITIVE); + final Pattern PATTERN_HTML_PARAGRAPH = Pattern.compile("<p>(.*?)</p>", Pattern.CASE_INSENSITIVE); + final Pattern PATTERN_HTML_AHREF = Pattern.compile("<a href=\"([^\"]+)\"[^>]*>(.*?)</a>", Pattern.CASE_INSENSITIVE); + final Pattern PATTERN_HTML_LIST = Pattern.compile("<li>(.*?)</li>", Pattern.CASE_INSENSITIVE); + final Pattern HTML_SPACE_PATTERN = Pattern.compile(" "); + + final Pattern PATTERN_CSS_O_FOQUOTE = Pattern.compile("<div class=\"b_quote_wrapper\">\\s*<div class=\"b_quote_author mceNonEditable\">(.*?)</div>\\s*<blockquote class=\"b_quote\">\\s*(.*?)\\s*</blockquote>\\s*</div>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + + final Pattern PATTERN_THREEPOINTS = Pattern.compile("…", Pattern.CASE_INSENSITIVE); + final String THREEPOINTS = "..."; + + //TODO: (LD) translate this! + private String HIDDEN_STR = "VERBORGEN"; + private final String path; + + /** + * + * @param container + * @param filePerThread + */ + + public ForumStreamedRTFFormatter(ZipOutputStream exportStream, String path, boolean filePerThread) { + // init String Buffer in ForumFormatter + super(); + // where to write + this.exportStream = exportStream; + this.filePerThread = filePerThread; + this.path = path; + addStandardImages(); + } + + private String fileName; + + /** + * @see org.olat.core.util.tree.Visitor#visit(org.olat.core.util.nodes.INode) + */ + public void visit(INode node) { + MessageNode mn = (MessageNode)node; + if (isTopThread) { + //important! + fileName = "Thread_" + mn.getKey().toString() + ".rtf"; + isTopThread = false; + } + // Message Title + sb.append("{\\pard \\brdrb\\brdrs\\brdrw10 \\f1\\fs30\\b "); + sb.append(getImageRTF(mn)); + sb.append(getTitlePrefix(mn)); + sb.append(mn.getTitle()); + sb.append("\\par}"); + // Message Body + sb.append("{\\pard \\f0"); + sb.append(convertHTMLMarkupToRTF(mn.getBody())); + sb.append("\\par}"); + // Message key + sb.append("{\\pard \\f0\\fs15 Message key: "); + sb.append(mn.getKey()); + sb.append("} \\line "); + sb.append("{\\pard \\f0\\fs15 created: "); + // Creator and creation date + sb.append(mn.getCreator().getUser().getProperty(UserConstants.FIRSTNAME, null)); + sb.append(", "); + sb.append(mn.getCreator().getUser().getProperty(UserConstants.LASTNAME, null)); + sb.append(" "); + sb.append(mn.getCreationDate().toString()); + // Modifier and modified date + Identity modifier = mn.getModifier(); + if (modifier != null) { + sb.append(" \\line modified: "); + sb.append(modifier.getUser().getProperty(UserConstants.FIRSTNAME, null)); + sb.append(", "); + sb.append(modifier.getUser().getProperty(UserConstants.LASTNAME, null)); + sb.append(" "); + sb.append(mn.getModifiedDate().toString()); + } + sb.append(" \\par}"); + // attachment(s) + OlatRootFolderImpl msgContainer = fm.getMessageContainer(getForumKey(), mn.getKey()); + List<VFSItem> attachments = msgContainer.getItems(); + if (attachments != null && attachments.size() > 0){ + sb.append("{\\pard \\f0\\fs15 Attachment(s): "); + boolean commaFlag = false; + for (VFSItem attachment: attachments) { + if (commaFlag) sb.append(", "); + sb.append(attachment.getName()); + commaFlag = true; + + ZipUtil.addToZip(attachment, path + "/attachments", exportStream); + } + sb.append("} \\line"); + } + sb.append("{\\pard \\brdrb\\brdrs\\brdrw10 \\par}"); + } + + private void addStandardImages() { + String[] images = new String[]{ "fo_sticky_closed", "fo_closed", "fo_sticky"}; + try { + for(String image:images) { + String iconPath = getImagePath(image); + if (iconPath != null) { + File file = new File(iconPath); + if (file.exists()) { + exportStream.putNextEntry(new ZipEntry(path + "/" + file.getName())); + FileUtils.copyFile(file, exportStream); + exportStream.closeEntry(); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * + * @see org.olat.modules.fo.archiver.formatters.ForumFormatter#openThread() + */ + public void openThread() { + super.openThread(); + if(filePerThread){ + sb.append("{\\rtf1\\ansi\\deff0"); + sb.append("{\\fonttbl {\\f0\\fswiss Arial;}} "); + sb.append("\\deflang1033\\plain"); + } + sb.append("{\\pard \\brdrb \\brdrs \\brdrdb \\brsp20 \\par}{\\pard\\par}"); + } + + /** + * + * @see org.olat.modules.fo.archiver.formatters.ForumFormatter#getThreadResult() + */ + public StringBuilder closeThread() { + String footerThread = "{\\pard \\brdrb \\brdrs \\brdrw20 \\brsp20 \\par}{\\pard\\par}"; + sb.append(footerThread); + if(filePerThread){ + sb.append("}"); + writeToFile(sb); + sb = new StringBuilder(); + } + return sb; + } + + /** + * + * @see org.olat.modules.fo.archiver.formatters.ForumFormatter#openForum() + */ + public void openForum(){ + if(!filePerThread){ + //make one ForumFile + Long forumKey = getForumKey(); + fileName = "Threads_" + forumKey.toString() + ".rtf"; + sb.append("{\\rtf1\\ansi\\deff0"); + sb.append("{\\fonttbl {\\f0\\fswiss Arial;}} "); + sb.append("\\deflang1033\\plain"); + } + } + + /** + * + * @see org.olat.modules.fo.archiver.formatters.ForumFormatter#closeForum() + */ + public StringBuilder closeForum(){ + if(!filePerThread){ + String footerForum = "}"; + sb.append(footerForum); + writeToFile(sb); + } + return sb; + } + + /** + * + * @param append + * @param buff + */ + private void writeToFile(StringBuilder buff){ + try { + StringBuilder out = new StringBuilder(); + int len = buff.length(); + for (int i = 0; i < len; i++) { + char c = buff.charAt(i); + int val = c; + if (val > 127) { + out.append("\\u").append(String.valueOf(val)).append("?"); + } else { + out.append(c); + } + } + String encoded = out.toString(); + exportStream.putNextEntry(new ZipEntry(path + "/" + fileName)); + IOUtils.write(encoded, exportStream); + exportStream.closeEntry(); + } catch (UnsupportedEncodingException ueEx) { + throw new AssertException("could not encode stream from forum export file: " + ueEx); + } catch (IOException e) { + throw new AssertException("could not write to forum export file: " + e); + } + } + + /** + * + * @param originalText + * @return + */ + private String convertHTMLMarkupToRTF(String originalText){ + String htmlText = originalText; + + Matcher mb = PATTERN_HTML_BOLD.matcher(htmlText); + StringBuffer bolds = new StringBuffer(); + while (mb.find()) { + mb.appendReplacement(bolds, "{\\\\b $1} "); + } + mb.appendTail(bolds); + htmlText = bolds.toString(); + + Matcher mi = PATTERN_HTML_ITALIC.matcher(htmlText); + StringBuffer italics = new StringBuffer(); + while (mi.find()) { + mi.appendReplacement(italics, "{\\\\i $1} "); + } + mi.appendTail(italics); + htmlText = italics.toString(); + + Matcher mbr = PATTERN_HTML_BREAK.matcher(htmlText); + StringBuffer breaks = new StringBuffer(); + while(mbr.find()){ + mbr.appendReplacement(breaks, "\\\\line "); + } + mbr.appendTail(breaks); + htmlText = breaks.toString(); + + Matcher mofo = PATTERN_CSS_O_FOQUOTE.matcher(htmlText); + StringBuffer foquotes = new StringBuffer(); + while(mofo.find()){ + mofo.appendReplacement(foquotes, "\\\\line {\\\\i $1} {\\\\pard $2\\\\par}"); + } + mofo.appendTail(foquotes); + htmlText = foquotes.toString(); + + Matcher mp = PATTERN_HTML_PARAGRAPH.matcher(htmlText); + StringBuffer paragraphs = new StringBuffer(); + while(mp.find()){ + mp.appendReplacement(paragraphs, "\\\\line $1 \\\\line"); + } + mp.appendTail(paragraphs); + htmlText = paragraphs.toString(); + + Matcher mahref = PATTERN_HTML_AHREF.matcher(htmlText); + StringBuffer ahrefs = new StringBuffer(); + while(mahref.find()){ + mahref.appendReplacement(ahrefs, "{\\\\field{\\\\*\\\\fldinst{HYPERLINK\"$1\"}}{\\\\fldrslt{\\\\ul $2}}}"); + } + mahref.appendTail(ahrefs); + htmlText = ahrefs.toString(); + + Matcher mli = PATTERN_HTML_LIST.matcher(htmlText); + StringBuffer lists = new StringBuffer(); + while(mli.find()){ + mli.appendReplacement(lists, "$1\\\\line "); + } + mli.appendTail(lists); + htmlText = lists.toString(); + + Matcher mtp = PATTERN_THREEPOINTS.matcher(htmlText); + StringBuffer tps = new StringBuffer(); + while (mtp.find()) { + mtp.appendReplacement(tps, THREEPOINTS); + } + mtp.appendTail(tps); + htmlText = tps.toString(); + + // strip all other html-fragments, because not convertable that easy + htmlText = FilterFactory.getHtmlTagsFilter().filter(htmlText); + // Remove all + Matcher tmp = HTML_SPACE_PATTERN.matcher(htmlText); + htmlText = tmp.replaceAll(" "); + htmlText = StringEscapeUtils.unescapeHtml(htmlText); + + return htmlText; + } + + /** + * + * @param messageNode + * @return title prefix for hidden forum threads. + */ + private String getTitlePrefix(MessageNode messageNode) { + StringBuilder sb = new StringBuilder(); + if(messageNode.isHidden()) { + sb.append(HIDDEN_STR); + } + if(sb.length()>1) { + sb.append(": "); + } + return sb.toString(); + } + + /** + * Gets the RTF image section for the input messageNode. + * @param messageNode + * @return the RTF image section for the input messageNode. + */ + private String getImageRTF(MessageNode messageNode) { + StringBuilder sb = new StringBuilder(); + for(String fileName : addImagesToVFSContainer(messageNode)) { + sb.append("{\\field\\fldedit{\\*\\fldinst { INCLUDEPICTURE ") + .append("\"").append(fileName).append("\"") + .append(" \\\\d }}{\\fldrslt {}}}"); + } + return sb.toString(); + } + + /** + * Retrieves the appropriate images for the input messageNode, if any, + * and adds it to the input container. + * + * @param messageNode + * @param container + * @return + */ + private List<String> addImagesToVFSContainer(MessageNode messageNode) { + List<String> fileNameList = new ArrayList<String>(); + String iconPath = null; + if(messageNode.isClosed() && messageNode.isSticky()) { + iconPath = getImagePath("fo_sticky_closed"); + } else if(messageNode.isClosed()) { + iconPath = getImagePath("fo_closed"); + } else if(messageNode.isSticky()) { + iconPath = getImagePath("fo_sticky"); + } + if (iconPath != null) { + File file = new File(iconPath); + if (file.exists()) { + fileNameList.add(file.getName()); + } else { + log.error("Could not find image for forum RTF formatter::" + iconPath); + } + } + return fileNameList; + } + + /** + * TODO: LD: to clarify whether there it a better way to get the image path? + * Gets the image path. + * @param val + * @return the path of the static icon image. + */ + private String getImagePath(Object val) { + return WebappHelper.getContextRoot() + "/static/images/forum/" + val.toString() + ".png"; + } +} diff --git a/src/main/java/org/olat/modules/scorm/archiver/ArchiverActionExtension.java b/src/main/java/org/olat/modules/scorm/archiver/ArchiverActionExtension.java deleted file mode 100644 index 1020bef0689097b455d8bb131795aabcc12f2f3a..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/modules/scorm/archiver/ArchiverActionExtension.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.modules.scorm.archiver; - -import org.olat.core.extensions.action.GenericActionExtension; -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.WindowControl; -import org.olat.course.ICourse; - -public class ArchiverActionExtension extends GenericActionExtension { - - @Override - public Controller createController(UserRequest ureq, WindowControl wControl, Object arg) { - if(arg instanceof ICourse) { - return new ScormResultArchiveController(ureq, wControl, (ICourse)arg); - } - return super.createController(ureq, wControl, arg); - } -} diff --git a/src/main/java/org/olat/modules/scorm/archiver/ScormArchiveWizardController.java b/src/main/java/org/olat/modules/scorm/archiver/ScormArchiveWizardController.java deleted file mode 100644 index 5f42eda06461b100ab69ed164922fbebf30c2081..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/modules/scorm/archiver/ScormArchiveWizardController.java +++ /dev/null @@ -1,181 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.modules.scorm.archiver; - -import java.io.File; -import java.util.List; -import java.util.Map; - -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.components.Component; -import org.olat.core.gui.components.link.Link; -import org.olat.core.gui.components.link.LinkFactory; -import org.olat.core.gui.components.table.ColumnDescriptor; -import org.olat.core.gui.components.table.CustomRenderColumnDescriptor; -import org.olat.core.gui.components.table.DefaultColumnDescriptor; -import org.olat.core.gui.components.table.Table; -import org.olat.core.gui.components.table.TableController; -import org.olat.core.gui.components.table.TableEvent; -import org.olat.core.gui.components.table.TableGuiConfiguration; -import org.olat.core.gui.components.velocity.VelocityContainer; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.Event; -import org.olat.core.gui.control.WindowControl; -import org.olat.core.gui.control.controller.BasicController; -import org.olat.core.gui.control.generic.wizard.WizardController; -import org.olat.core.gui.media.MediaResource; -import org.olat.core.gui.media.MimedFileMediaResource; -import org.olat.core.util.StringHelper; -import org.olat.core.util.Util; -import org.olat.course.CourseFactory; -import org.olat.course.ICourse; -import org.olat.course.archiver.GenericArchiveController; -import org.olat.course.assessment.AssessmentHelper; -import org.olat.course.assessment.IndentedNodeRenderer; -import org.olat.course.assessment.NodeTableDataModel; -import org.olat.course.nodes.CourseNode; -import org.olat.course.nodes.ScormCourseNode; -import org.olat.user.UserManager; - -/** - * - * Description:<br> - * A wizard to export the results of a SCORM course in a tab separated file. There is two steps: - * select a SCORM element and then download the file. - * - * <P> - * Initial Date: 17 août 2009 <br> - * @author srosse - */ -public class ScormArchiveWizardController extends BasicController { - - private static final String CMD_SELECT_NODE = "cmd.select.node"; - - private final Long courseId; - private final NodeTableDataModel nodeTableModel; - - private Link showFileButton; - private WizardController wc; - private TableController nodeListCtr; - private VelocityContainer finishedVC; - private VelocityContainer noResultsVC; - private Link backLinkAtNoResults; - - private String charset; - private File exportDir; - private String targetFileName; - - public ScormArchiveWizardController(UserRequest ureq, List<Map<String,Object>> nodesTableObjectArrayList, Long courseId, WindowControl wControl) { - super(ureq, wControl, Util.createPackageTranslator(GenericArchiveController.class, ureq.getLocale())); - this.courseId = courseId; - - //table configuraton - TableGuiConfiguration tableConfig = new TableGuiConfiguration(); - tableConfig.setTableEmptyMessage(getTranslator().translate("nodesoverview.nonodes")); - tableConfig.setDownloadOffered(false); - tableConfig.setColumnMovingOffered(false); - tableConfig.setSortingEnabled(false); - tableConfig.setDisplayTableHeader(true); - tableConfig.setDisplayRowCount(false); - tableConfig.setPageingEnabled(false); - - nodeListCtr = new TableController(tableConfig, ureq, getWindowControl(), getTranslator()); - listenTo(nodeListCtr); - // table columns - nodeListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor("table.header.node", 0, - null, ureq.getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, new IndentedNodeRenderer())); - nodeListCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.action.select", 1, - CMD_SELECT_NODE, ureq.getLocale())); - - nodeTableModel = new NodeTableDataModel(nodesTableObjectArrayList, getTranslator()); - nodeListCtr.setTableDataModel(nodeTableModel); - - wc = new WizardController(ureq, wControl, 2); - listenTo(wc); - wc.setWizardTitle(getTranslator().translate("wizard.nodechoose.title")); - wc.setNextWizardStep(getTranslator().translate("wizard.nodechoose.howto"), nodeListCtr.getInitialComponent()); - putInitialPanel(wc.getInitialComponent()); - } - - @Override - protected void doDispose() { - // - } - - @Override - protected void event(UserRequest ureq, Component source, Event event) { - if (source == showFileButton){ - File exportFile = new File(exportDir, targetFileName); - MediaResource resource = new MimedFileMediaResource(exportFile, "application/vnd.ms-excel; charset="+charset, true); - ureq.getDispatchResult().setResultingMediaResource(resource); - showFileButton.setDirty(false); - } else if (source == backLinkAtNoResults){ - wc.setWizardTitle(getTranslator().translate("wizard.nodechoose.title")); - wc.setBackWizardStep(getTranslator().translate("wizard.nodechoose.howto"), nodeListCtr.getInitialComponent()); - } - } - - @Override - public void event(UserRequest ureq, Controller source, Event event) { - if(source == nodeListCtr) { - if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) { - TableEvent tae = (TableEvent)event; - - Map<String,Object> nodeData = (Map<String,Object>) nodeTableModel.getObject(tae.getRowId()); - ICourse course = CourseFactory.loadCourse(courseId); - CourseNode node = course.getRunStructure().getNode((String) nodeData.get(AssessmentHelper.KEY_IDENTIFYER)); - if(node instanceof ScormCourseNode) { - finishedVC = createVelocityContainer("finished"); - showFileButton = LinkFactory.createButton("showfile", finishedVC, this); - finishedVC.contextPut("nodetitle", node.getShortTitle()); - - targetFileName = doExport(ureq, (ScormCourseNode)node); - if(StringHelper.containsNonWhitespace(targetFileName)) { - finishedVC.contextPut("filename", targetFileName); - wc.setWizardTitle(getTranslator().translate("wizard.finished.title")); - wc.setNextWizardStep(getTranslator().translate("wizard.finished.howto"), finishedVC); - } else { // no success - noResultsVC = createVelocityContainer("noresults"); - backLinkAtNoResults = LinkFactory.createLinkBack(noResultsVC, this); - noResultsVC.contextPut("nodetitle", node.getShortTitle()); - - wc.setWizardTitle(getTranslator().translate("wizard.finished.title")); - wc.setNextWizardStep(getTranslator().translate("wizard.finished.howto"), noResultsVC); - } - } - } - } - else if (source == wc){ - if (event == Event.CANCELLED_EVENT) { - fireEvent(ureq, event); - } - } - } - - private String doExport(UserRequest ureq, ScormCourseNode node) { - ICourse course = CourseFactory.loadCourse(courseId); - exportDir = CourseFactory.getOrCreateDataExportDirectory(ureq.getIdentity(), course.getCourseTitle()); - UserManager um = UserManager.getInstance(); - charset = um.getUserCharset(ureq.getIdentity()); - - ScormExportManager sreManager = ScormExportManager.getInstance(); - return sreManager.exportResults(course.getCourseEnvironment(), node, getTranslator(), exportDir, charset); - } -} \ No newline at end of file diff --git a/src/main/java/org/olat/modules/scorm/archiver/ScormExportManager.java b/src/main/java/org/olat/modules/scorm/archiver/ScormExportManager.java index 26a0bf4ec71d8ac18429effa1793ec850c4df3a5..0e666bda9ab6173422150447a96691a633e5bd46 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/ScormExportManager.java +++ b/src/main/java/org/olat/modules/scorm/archiver/ScormExportManager.java @@ -19,7 +19,6 @@ */ package org.olat.modules.scorm.archiver; -import java.io.File; import java.util.List; import org.olat.core.commons.persistence.DBFactory; @@ -28,7 +27,6 @@ import org.olat.core.id.Identity; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.manager.BasicManager; -import org.olat.core.util.ExportUtil; import org.olat.core.util.vfs.LocalFileImpl; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSItem; @@ -80,18 +78,10 @@ public class ScormExportManager extends BasicManager { * @param charset * @return the name of the file, if any created or empty string otherwise */ - public String exportResults(CourseEnvironment courseEnv, ScormCourseNode node, Translator translator, File exportDirectory, String charset) { + public String getResults(CourseEnvironment courseEnv, ScormCourseNode node, Translator translator) { ScormExportVisitor visitor = new ScormExportFormatter(translator); - - boolean dataFound = visitScoDatas(courseEnv, node, visitor); - - if(dataFound) { - String content = visitor.toString(); - String fileName = ExportUtil.createFileNameWithTimeStamp("SCORM_" + node.getShortTitle(), "xls"); - ExportUtil.writeContentToFile(fileName, content, exportDirectory, charset); - return fileName; - } - return ""; + String content = visitor.toString(); + return content; } /** diff --git a/src/main/java/org/olat/modules/scorm/archiver/ScormResultArchiveController.java b/src/main/java/org/olat/modules/scorm/archiver/ScormResultArchiveController.java deleted file mode 100644 index 9921e6b50022290a26fec5419c801d00dbef8c8e..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/modules/scorm/archiver/ScormResultArchiveController.java +++ /dev/null @@ -1,183 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.modules.scorm.archiver; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.components.Component; -import org.olat.core.gui.components.link.Link; -import org.olat.core.gui.components.link.LinkFactory; -import org.olat.core.gui.components.table.ColumnDescriptor; -import org.olat.core.gui.components.table.CustomRenderColumnDescriptor; -import org.olat.core.gui.components.table.DefaultColumnDescriptor; -import org.olat.core.gui.components.table.TableController; -import org.olat.core.gui.components.table.TableGuiConfiguration; -import org.olat.core.gui.components.velocity.VelocityContainer; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.Event; -import org.olat.core.gui.control.WindowControl; -import org.olat.core.gui.control.controller.BasicController; -import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; -import org.olat.core.util.Util; -import org.olat.course.CourseFactory; -import org.olat.course.ICourse; -import org.olat.course.archiver.GenericArchiveController; -import org.olat.course.assessment.AssessmentHelper; -import org.olat.course.assessment.IndentedNodeRenderer; -import org.olat.course.nodes.CourseNode; -import org.olat.course.nodes.ScormCourseNode; - -/** - * - * Description:<br> - * Main controller for the SCORM archive export. All the job is done in the wizard - * - * <P> - * Initial Date: 17 august 2009 <br> - * @author srosse - */ -public class ScormResultArchiveController extends BasicController { - - private static final String CMD_SELECT_NODE = "cmd.select.node"; - - private VelocityContainer introVC; - - private TableController nodeListCtr; - private ScormArchiveWizardController wizardController; - private CloseableModalController cmc; - - private final Long courseId; - - private List<Map<String,Object>> nodesTableObjectArrayList; - private final Link startExportButton; - - public ScormResultArchiveController(UserRequest ureq, WindowControl wControl, ICourse course) { - super(ureq, wControl, Util.createPackageTranslator(GenericArchiveController.class, ureq.getLocale())); - - courseId = course.getResourceableId(); - - introVC = createVelocityContainer("intro"); - startExportButton = LinkFactory.createButtonSmall("command.start.exportwizard", introVC, this); - - nodesTableObjectArrayList = doNodeChoose(ureq); - - if (nodesTableObjectArrayList == null) { - introVC.contextPut("hasScormNodes", Boolean.FALSE); - } else { - introVC.contextPut("hasScormNodes", Boolean.TRUE); - } - - putInitialPanel(introVC); - } - - @Override - protected void doDispose() { - // controllers autodisposed by basic controller - } - - @Override - protected void event(UserRequest ureq, Component source, Event event) { - if (source == startExportButton){ - - removeAsListenerAndDispose(wizardController); - wizardController = new ScormArchiveWizardController(ureq, nodesTableObjectArrayList, courseId, getWindowControl()); - listenTo(wizardController); - - removeAsListenerAndDispose(cmc); - cmc = new CloseableModalController(getWindowControl(), translate("close"), wizardController.getInitialComponent()); - listenTo(cmc); - - cmc.activate(); - } - } - - @Override - public void event(UserRequest ureq, Controller source, Event event) { - if (source == wizardController){ - if (event == Event.DONE_EVENT || event == Event.CANCELLED_EVENT) { - cmc.deactivate(); - } - } - } - - private List<Map<String,Object>> doNodeChoose(UserRequest ureq){ - //table configuraton - TableGuiConfiguration tableConfig = new TableGuiConfiguration(); - tableConfig.setTableEmptyMessage(translate("nodesoverview.nonodes")); - tableConfig.setDownloadOffered(false); - tableConfig.setColumnMovingOffered(false); - tableConfig.setSortingEnabled(false); - tableConfig.setDisplayTableHeader(true); - tableConfig.setDisplayRowCount(false); - tableConfig.setPageingEnabled(false); - - removeAsListenerAndDispose(nodeListCtr); - nodeListCtr = new TableController(tableConfig, ureq, getWindowControl(), this.getTranslator()); - listenTo(nodeListCtr); - // table columns - nodeListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor("table.header.node", 0, - null, ureq.getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, new IndentedNodeRenderer())); - nodeListCtr.addColumnDescriptor(new DefaultColumnDescriptor("table.action.select", 1, - CMD_SELECT_NODE, ureq.getLocale())); - - // get list of course node data and populate table data model - ICourse course = CourseFactory.loadCourse(courseId); - CourseNode rootNode = course.getRunStructure().getRootNode(); - List<Map<String,Object>> objectArrayList = addScormNodesAndParentsToList(0, rootNode); - return objectArrayList; - } - - private List<Map<String,Object>> addScormNodesAndParentsToList(int recursionLevel, CourseNode courseNode) { - // 1) Get list of children data using recursion of this method - List<Map<String,Object>> childrenData = new ArrayList<Map<String,Object>>(); - for (int i = 0; i < courseNode.getChildCount(); i++) { - CourseNode child = (CourseNode) courseNode.getChildAt(i); - List<Map<String,Object>> childData = addScormNodesAndParentsToList( (recursionLevel + 1), child); - if (childData != null) { - childrenData.addAll(childData); - } - } - - if (!childrenData.isEmpty() || courseNode instanceof ScormCourseNode) { - // Store node data in hash map. This hash map serves as data model for - // the tasks overview table. Leave user data empty since not used in - // this table. (use only node data) - Map<String,Object> nodeData = new HashMap<String,Object>(); - // indent - nodeData.put(AssessmentHelper.KEY_INDENT, new Integer(recursionLevel)); - // course node data - nodeData.put(AssessmentHelper.KEY_TYPE, courseNode.getType()); - nodeData.put(AssessmentHelper.KEY_TITLE_SHORT, courseNode.getShortTitle()); - nodeData.put(AssessmentHelper.KEY_TITLE_LONG, courseNode.getLongTitle()); - nodeData.put(AssessmentHelper.KEY_IDENTIFYER, courseNode.getIdent()); - nodeData.put(AssessmentHelper.KEY_SELECTABLE, (courseNode instanceof ScormCourseNode) ? Boolean.TRUE : Boolean.FALSE); - - List<Map<String,Object>> nodeAndChildren = new ArrayList<Map<String,Object>>(); - nodeAndChildren.add(nodeData); - nodeAndChildren.addAll(childrenData); - return nodeAndChildren; - } - return null; - } -} \ No newline at end of file diff --git a/src/main/java/org/olat/modules/scorm/archiver/_content/finished.html b/src/main/java/org/olat/modules/scorm/archiver/_content/finished.html deleted file mode 100644 index 9fcc215abe2c0552498af692abdc2727c0f77232..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/modules/scorm/archiver/_content/finished.html +++ /dev/null @@ -1,7 +0,0 @@ -<p> - <strong>$r.translate("wizard.nodetitle"):</strong> $nodetitle -</p> -<p> - <span class="b_with_small_icon_left b_filetype_xls">$filename</span> $r.render("showfile") -</p> - diff --git a/src/main/java/org/olat/modules/scorm/archiver/_content/intro.html b/src/main/java/org/olat/modules/scorm/archiver/_content/intro.html deleted file mode 100644 index 5457aa0cd554497c148cc920a0fc235fdab87697..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/modules/scorm/archiver/_content/intro.html +++ /dev/null @@ -1,14 +0,0 @@ -<h4>$r.translate("wizard.intro.title")</h4> - -#if($hasScormNodes) - <p>$r.translate("wizard.intro.text")</p> - <ol> - <li>$r.translate("wizard.intro.nod")</li> - <li>$r.translate("wizard.intro.fin")</li> - </ol> - $r.render("command.start.exportwizard") -#else - <p> - $r.translate("nodesoverview.nonodes") - </p> -#end diff --git a/src/main/java/org/olat/modules/scorm/archiver/_content/noresults.html b/src/main/java/org/olat/modules/scorm/archiver/_content/noresults.html deleted file mode 100644 index 13a129344bc464831a746c1fcefb5bc731256452..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/modules/scorm/archiver/_content/noresults.html +++ /dev/null @@ -1,8 +0,0 @@ -$r.render("backLink") -<p> - <strong>$r.translate("wizard.nodetitle"):</strong> $nodetitle -</p> -<p> - $r.translate("archive.noresults") -</p> - \ No newline at end of file diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_ar.properties index 6387a2c6e2d7b5e420366ecaa2a632e331fb96ee..587274f5821675845c763734358d33418c7386b7 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_ar.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_ar.properties @@ -1,8 +1,4 @@ #Sun Feb 21 13:44:33 CET 2010 -ScormResultArchiveController.menu.title=\u0646\u062A\u0627\u0626\u062C \u0627\u0633\u0643\u0648\u0631\u0645 -ScormResultArchiveController.menu.title.alt=\u0646\u062A\u0627\u0626\u062C \u0633\u0643\u0648\u0631\u0645 -command.start.exportwizard=\u0628\u062F\u0627\u064A\u0629 \u0627\u0644\u0645\u062D\u0641\u0648\u0638\u0627\u062A -nodesoverview.nonodes=\u0644\u0627 \u064A\u062D\u062A\u0648\u0649 \u0647\u0630\u0627 \u0627\u0644\u0645\u0642\u0631\u0631 \u0639\u0644\u0649 \u0623\u0649 \u0639\u0646\u0635\u0631 \u0627\u0633\u0643\u0648\u0631\u0645. results.header=\u0646\u062A\u0627\u0626\u062C \u0627\u0633\u0643\u0648\u0631\u0645 results.table.foot.cr=\u0631\u062F \u0627\u0644\u0637\u0627\u0644\u0628 results.table.footer.sr=\u0627\u062C\u0627\u0628\u0629 \u0635\u062D\u064A\u062D\u0629 @@ -13,13 +9,4 @@ results.table.header.lessonStatus=\u0627\u0644\u062D\u0627\u0644\u0629 results.table.header.objective={0} \u0627\u0644\u062F\u0631\u062C\u0629 \u0627\u0644\u0639\u0638\u0645\u0649 results.table.header.rawScore=\u0627\u0644\u062F\u0631\u062C\u0629 \u0627\u0644\u0646\u0647\u0627\u0626\u064A\u0629 results.table.header.totalTime=\u0627\u0644\u0632\u0645\u0646 -results.table.header.username=\u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 -wizard.finished.howto=\u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0630\u0649 \u064A\u062D\u062A\u0648\u0649 \u0639\u0644\u0649 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0645\u062D\u0641\u0648\u0638\u0629 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649. -wizard.finished.title=\u062A\u0645 \u0627\u0646\u062A\u0647\u0627\u0621 \u0627\u0644\u062D\u0641\u0638 -wizard.intro.fin=\u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u0649 \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0630\u0649 \u064A\u062D\u062A\u0648\u0649 \u0639\u0644\u0649 \u0646\u062A\u0627\u0626\u062C\u0643 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649. -wizard.intro.nod=\u064A\u0631\u062C\u0649 \u0627\u062E\u062A\u064A\u0627\u0631 \u0639\u0646\u0635\u0631 \u0627\u0633\u0643\u0648\u0631\u0645. -wizard.intro.text=\u0641\u0649 \u0627\u0644\u062D\u0648\u0627\u0631 \u0627\u0644\u062A\u0627\u0644\u0649 \u0627\u062E\u062A\u0631 \u0639\u0646\u0635\u0631 \u0627\u0633\u0643\u0648\u0631\u0645 \u0627\u0644\u0630\u0649 \u064A\u062A\u0645 \u062A\u0642\u064A\u064A\u0645\u0647\u060C \u0648\u0627\u0644\u0646\u062A\u0627\u0626\u062C \u0627\u0644\u0645\u062D\u0641\u0648\u0638\u0629 \u064A\u0645\u0643\u0646 \u0627\u0644\u0639\u062B\u0648\u0631 \u0639\u0644\u064A\u0647\u0627 \u0641\u0649 \u0645\u062C\u0644\u062F\u0643 \u0627\u0644\u0634\u062E\u0635\u0649. -wizard.intro.title=\u0646\u062A\u0627\u0626\u062C \u0627\u0633\u0643\u0648\u0631\u0645 -wizard.nodechoose.howto=\u064A\u0631\u062C\u0649 \u0627\u062E\u062A\u064A\u0627\u0631 \u0639\u0646\u0635\u0631 \u0627\u0633\u0643\u0648\u0631\u0645. -wizard.nodechoose.title=\u0627\u062E\u062A\u064A\u0627\u0631 \u0639\u0646\u0635\u0631 \u0627\u0633\u0643\u0648\u0631\u0645 -wizard.nodetitle=\u0639\u0646\u0648\u0627\u0646 \u0639\u0646\u0635\u0631 \u0627\u0644\u0645\u0642\u0631\u0631 +results.table.header.username=\u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645 \ No newline at end of file diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_de.properties index 0e3302e87724f0386aef276ad9c4a68f334649b5..90972182344074fe8f3a25beedf05c77c2a5f333 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_de.properties @@ -1,8 +1,3 @@ -archive.noresults=F\u00FCr diesen Kursbaustein wurden noch keine Resultate gespeichert. -ScormResultArchiveController.menu.title=SCORM Resultate -ScormResultArchiveController.menu.title.alt=SCORM Resultate -command.start.exportwizard=Archivierung starten -nodesoverview.nonodes=Dieser Kurs hat keinen SCORM Baustein. results.header=SCORM Resultate results.table.foot.cr=Antwort Student results.table.footer.sr=Richtige Antwort @@ -14,12 +9,3 @@ results.table.header.totalTime=Zeit results.table.header.interaction=Frage {0} results.table.header.objective=Zielpunktzahl {0} results.table.header.comments=Kommentar -wizard.intro.title=SCORM Resultate -wizard.intro.text=W\u00E4hlen Sie im folgenden Dialog den SCORM Baustein aus, der ausgewertet werden soll. Die archivierten Resultate finden Sie in Ihrem pers\u00F6nlichen Ordner unter private/archive/[Kursname]/[Dateiname]. -wizard.intro.nod=W\u00E4hlen Sie einen SCORM Baustein aus. -wizard.intro.fin=Die Datei mit den Resultaten liegt in Ihrem pers\u00F6nlichen Ordner. -wizard.nodechoose.howto=W\u00E4hlen Sie einen SCORM Baustein aus. -wizard.nodechoose.title=Auswahl SCORM Baustein -wizard.nodetitle=Titel Kursbaustein -wizard.finished.howto=Die Datei mit den archivierten Daten finden Sie in Ihrem pers\u00F6nlichen Ordner. -wizard.finished.title=Archivierung beendet \ No newline at end of file diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_el.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_el.properties index 1463fbd019ffc86d6df6536247b234ede269c42a..eb50e1288f38db61ddfe33cc0ba89d1b362a1fc8 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_el.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_el.properties @@ -1,9 +1,4 @@ #Wed Sep 15 15:25:19 CEST 2010 -ScormResultArchiveController.menu.title=\u0391\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 SCORM -ScormResultArchiveController.menu.title.alt=\u0391\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 SCORM -archive.noresults=\u0394\u03B5\u03BD \u03B1\u03C0\u03BF\u03B8\u03B7\u03BA\u03B5\u03CD\u03C4\u03B7\u03BA\u03B1\u03BD \u03B1\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 \u03B3\u03B9'\u03B1\u03C5\u03C4\u03CC \u03C4\u03BF \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2. -command.start.exportwizard=\u0388\u03BD\u03B1\u03C1\u03BE\u03B7 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03AD\u03C4\u03B7\u03C3\u03B7\u03C2 -nodesoverview.nonodes=\u03A4\u03BF \u03BC\u03AC\u03B8\u03B7\u03BC\u03B1 \u03B1\u03C5\u03C4\u03CC \u03B4\u03B5\u03BD \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 \u03BA\u03AC\u03C0\u03BF\u03B9\u03BF \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF SCORM. results.header=\u0391\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 SCORM results.table.foot.cr=\u0391\u03C0\u03AC\u03BD\u03C4\u03B7\u03C3\u03B7 \u03BC\u03B1\u03B8\u03B7\u03C4\u03AE results.table.footer.sr=\u03A3\u03C9\u03C3\u03C4\u03AE \u03B1\u03C0\u03AC\u03BD\u03C4\u03B7\u03C3\u03B7 @@ -15,12 +10,3 @@ results.table.header.objective=\u039C\u03AD\u03B3\u03B9\u03C3\u03C4\u03B7 \u03B2 results.table.header.rawScore=\u03A4\u03B5\u03BB\u03B9\u03BA\u03AE \u03B2\u03B1\u03B8\u03BC\u03BF\u03BB\u03BF\u03B3\u03AF\u03B1 results.table.header.totalTime=\u038F\u03C1\u03B1 results.table.header.username=\u038C\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 -wizard.finished.howto=\u0391\u03C1\u03C7\u03B5\u03AF\u03BF \u03C0\u03BF\u03C5 \u03BD\u03B1 \u03C0\u03B5\u03C1\u03B9\u03AD\u03C7\u03B5\u03B9 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03B7\u03BC\u03AD\u03BD\u03B1 \u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF \u03BD\u03B1 \u03B2\u03C1\u03B5\u03B8\u03B5\u03AF \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 \u03C6\u03AC\u03BA\u03B5\u03BB\u03BF. -wizard.finished.title=\u0397 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03AD\u03C4\u03B7\u03C3\u03B7 \u03BF\u03BB\u03BF\u03BA\u03BB\u03B7\u03C1\u03CE\u03B8\u03B7\u03BA\u03B5 -wizard.intro.fin=\u03A4\u03BF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF \u03C0\u03BF\u03C5 \u03C0\u03B5\u03C1\u03B9\u03BB\u03B1\u03BC\u03B2\u03AC\u03BD\u03B5\u03B9 \u03C4\u03B1 \u03B1\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03AC \u03C3\u03B1\u03C2 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF\u03C4\u03B5 \u03BD\u03B1 \u03C4\u03BF \u03B2\u03C1\u03B5\u03AF\u03C4\u03B5 \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 \u03C6\u03AC\u03BA\u03B5\u03BB\u03BF. -wizard.intro.nod=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B5\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03B5\u03BD\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF SCORM. -wizard.intro.text=\u03A3\u03C4\u03BF\u03BD \u03B1\u03BA\u03CC\u03BB\u03BF\u03C5\u03B8\u03BF \u03B4\u03B9\u03AC\u03BB\u03BF\u03B3\u03BF, \u03C0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B5\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03C4\u03BF \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF SCORM \u03C0\u03BF\u03C5 \u03B8\u03AD\u03BB\u03B5\u03C4\u03B5 \u03BD\u03B1 \u03B1\u03BE\u03B9\u03BF\u03BB\u03BF\u03B3\u03B7\u03B8\u03B5\u03AF. \u03A4\u03B1 \u03B1\u03C1\u03C7\u03B5\u03B9\u03BF\u03B8\u03B5\u03C4\u03B7\u03BC\u03AD\u03BD\u03B1 \u03B1\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF\u03C4\u03B5 \u03BD\u03B1 \u03C4\u03B1 \u03B2\u03C1\u03B5\u03AF\u03C4\u03B5 \u03C3\u03C4\u03BF\u03BD \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC \u03C3\u03B1\u03C2 \u03C6\u03AC\u03BA\u03B5\u03BB\u03BF, \u03C3\u03C4\u03BF \u03C4\u03BC\u03AE\u03BC\u03B1 \u03C0\u03C1\u03BF\u03C3\u03C9\u03C0\u03B9\u03BA\u03CC/\u03B1\u03C1\u03C7\u03B5\u03AF\u03BF/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2]/[\u03CC\u03BD\u03BF\u03BC\u03B1 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5]. -wizard.intro.title=\u0391\u03C0\u03BF\u03C4\u03B5\u03BB\u03AD\u03C3\u03BC\u03B1\u03C4\u03B1 SCORM -wizard.nodechoose.howto=\u03A0\u03B1\u03C1\u03B1\u03BA\u03B1\u03BB\u03CE \u03B5\u03C0\u03B9\u03BB\u03AD\u03BE\u03C4\u03B5 \u03B5\u03BD\u03B1 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF SCORM. -wizard.nodechoose.title=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF\u03C5 SCORM -wizard.nodetitle=\u03A4\u03AF\u03C4\u03BB\u03BF\u03C2 \u03C3\u03C4\u03BF\u03B9\u03C7\u03B5\u03AF\u03BF\u03C5 \u03BC\u03B1\u03B8\u03AE\u03BC\u03B1\u03C4\u03BF\u03C2 diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_en.properties index 63f99ce4916c42656c482a12879e5652850cfb57..44481f0e16f52822fdc4984445798b42be1a0e1e 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_en.properties @@ -1,9 +1,4 @@ #Fri Aug 13 17:42:53 CEST 2010 -ScormResultArchiveController.menu.title=SCORM results -ScormResultArchiveController.menu.title.alt=SCORM results -archive.noresults=No results saved for this course element. -command.start.exportwizard=Start archiving -nodesoverview.nonodes=This course does not contain any SCORM element. results.header=SCORM results results.table.foot.cr=Reply student results.table.footer.sr=Correct answer @@ -15,12 +10,3 @@ results.table.header.objective=Maximum score {0} results.table.header.rawScore=Final score results.table.header.totalTime=Time results.table.header.username=User name -wizard.finished.howto=A file containing archived data can be found in your personal folder. -wizard.finished.title=Archiving finished -wizard.intro.fin=A file containing your results can be found in your personal folder. -wizard.intro.nod=Please select a SCORM element. -wizard.intro.text=In the following dialog please select the SCORM element to be assessed. Archived results can be found in your personal folder, section private/archive/[course name]/[file name]. -wizard.intro.title=SCORM results -wizard.nodechoose.howto=Please select a SCORM element. -wizard.nodechoose.title=Selection SCORM element -wizard.nodetitle=Title course element diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_fr.properties index 5d11900b3ba78b9dbd05ab4d066a2bad4545c3ce..86bf44fae5068ca86ed96757fe9aa42ff7c4aa15 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_fr.properties @@ -1,9 +1,4 @@ #Mon Aug 23 18:45:33 CEST 2010 -ScormResultArchiveController.menu.title=R\u00E9sultats SCORM -ScormResultArchiveController.menu.title.alt=R\u00E9sultats SCORM -archive.noresults=Aucun r\u00E9sultat enregistr\u00E9 pour cet \u00E9l\u00E9ment de cours. -command.start.exportwizard=D\u00E9marrer archivage -nodesoverview.nonodes=Ce cours n'a pas d'\u00E9l\u00E9ment SCORM. results.header=R\u00E9sultats SCORM results.table.foot.cr=R\u00E9ponse \u00E9tudiant results.table.footer.sr=R\u00E9ponse correcte @@ -15,12 +10,4 @@ results.table.header.objective=Nombre de points maximal {0} results.table.header.rawScore=R\u00E9sutat final results.table.header.totalTime=Temps results.table.header.username=Nom d'utilisateur -wizard.finished.howto=Ce fichier avec les donn\u00E9es archiv\u00E9es peut \u00EAtre trouv\u00E9 dans votre dossier personnel. -wizard.finished.title=Archivage termin\u00E9 -wizard.intro.fin=Le fichier avec les r\u00E9sultats est d\u00E9pos\u00E9 dans votre dossier personnel. -wizard.intro.nod=Choisissez un \u00E9l\u00E9ment SCORM. -wizard.intro.text=Choisir dans le dialogue suivant l'\u00E9l\u00E9ment SCORM qui doit \u00EAtre \u00E9valu\u00E9. Les r\u00E9sultats archiv\u00E9s sont d\u00E9pos\u00E9s dans votre dossier personnel sous private/archive/[nom du cours]/[nom du fichier]. -wizard.intro.title=R\u00E9sultats SCORM -wizard.nodechoose.howto=Choisissez un \u00E9l\u00E9ment de cours SCORM -wizard.nodechoose.title=S\u00E9lection \u00E9l\u00E9ment SCORM -wizard.nodetitle=Titre \u00E9l\u00E9ment de cours + diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_it.properties index 99ccfdd95cd5e268833d2d37996446c9e606add1..62535154c85340a118718b95e93af7c1d607c4d3 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_it.properties @@ -1,9 +1,4 @@ #Mon Aug 16 16:18:02 CEST 2010 -ScormResultArchiveController.menu.title=Risultati SCORM -ScormResultArchiveController.menu.title.alt=Risultati SCORM -archive.noresults=Nessun risultato salvato per questo elemento di corso. -command.start.exportwizard=Avviare archiviazione -nodesoverview.nonodes=Questo corso non contiene alcun elemento SCORM. results.header=Risultati SCORM results.table.foot.cr=Risposta studente results.table.footer.sr=Risposta corretta @@ -15,12 +10,3 @@ results.table.header.objective=Punteggio massimo {0} results.table.header.rawScore=Punteggio finale results.table.header.totalTime=Tempo results.table.header.username=Nome utente -wizard.finished.howto=Il file con i dati archiviati si trova nella Sua cartella personale. -wizard.finished.title=Archiviazione terminata -wizard.intro.fin=Il file con i risultati si trova nella Sua cartella personale. -wizard.intro.nod=Selezioni un elemento SCORM. -wizard.intro.text=Selezioni l'elemento SCORM che deve essere valutato nel dialogo seguente. I risultati archiviati si trovano nella Sua cartella personale sotto private/archive/[Nome corso]/[Nome file]. -wizard.intro.title=Risultati SCORM -wizard.nodechoose.howto=Selezioni un elemento SCORM. -wizard.nodechoose.title=Selezione elemento SCORM -wizard.nodetitle=Titolo elemento di corso diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_nl_NL.properties index 6dee4ae208416518ef09d4f828ffe441b1d7cd21..2e8d07bac0ba8ecd8c7d73a05bfba7b22a8ea6ac 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_nl_NL.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_nl_NL.properties @@ -1,9 +1,4 @@ #Thu Sep 08 16:42:46 CEST 2011 -ScormResultArchiveController.menu.title=SCORM resultaten -ScormResultArchiveController.menu.title.alt=SCORM results -archive.noresults=Er zijn voor dit cursuselement geen resultaten opgeslagen. -command.start.exportwizard=Start archivering -nodesoverview.nonodes=Deze cursus bevat geen SCORM element. results.header=SCORM resultaten results.table.foot.cr=Student beantwoorden results.table.footer.sr=Correcte antwoord @@ -15,12 +10,3 @@ results.table.header.objective=Maximum score {0} results.table.header.rawScore=Eindscore results.table.header.totalTime=Tijd results.table.header.username=Gebruikersnaam -wizard.finished.howto=Een bestand dat gearchiveerde data bevat, kan teruggevonden worden in uw persoonlijke map. -wizard.finished.title=Archivering be\u00EBindigd -wizard.intro.fin=Een bestand dat uw resultaten bevat, kan teruggevonden worden in uw persoonlijke map. -wizard.intro.nod=Gelieve een SCORM element te selecteren. -wizard.intro.text=Gelieve in de volgende dialoog een SCORM element te selecteren dat moet worden beoordeeld. Gearchiveerde resultaten kunnen teruggevonden worden in uw persoonlijke map, sectie section private/archive/[cursusnaam]/[bestandsnaam]. -wizard.intro.title=SCORM resultaten -wizard.nodechoose.howto=Gelieve een SCORM element te selecteren -wizard.nodechoose.title=Selectie SCORM element -wizard.nodetitle=Titel cursuselement diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_pl.properties index 0730d96d0123d27409dcc0b61fa80dce8348682c..44b80c66d9a970bb7c4acdb2b658c04a38f2f3ef 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_pl.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_pl.properties @@ -1,9 +1,4 @@ #Fri Sep 03 15:26:06 CEST 2010 -ScormResultArchiveController.menu.title=Wyniki SCORM -ScormResultArchiveController.menu.title.alt=Wyniki SCORM -archive.noresults=Brak zapisanych wynik\u00F3w dla tego elementu kursu. -command.start.exportwizard=Rozpocznij archiwizacj\u0119 -nodesoverview.nonodes=Kurs nie zawiera tre\u015Bci SCORM. results.header=Wyniki SCORM results.table.foot.cr=Odpowiedz studentowi results.table.footer.sr=Prawid\u0142owa odpowied\u017A @@ -15,12 +10,3 @@ results.table.header.objective=Wynik maksymalny {0} results.table.header.rawScore=Wynik ko\u0144cowy results.table.header.totalTime=Czas results.table.header.username=Nazwa u\u017Cytkownika -wizard.finished.howto=Plik zawieraj\u0105cy zarchiwizowane dane, powinien znajdowa\u0107 si\u0119 w twoim folderze osobistym. -wizard.finished.title=Archiwizacja uko\u0144czona -wizard.intro.fin=Plik zawieraj\u0105cy wyniki, znajduje si\u0119 w twoim folderze osobistym. -wizard.intro.nod=Wybierz element typu SCORM. -wizard.intro.text=W nast\u0119pnym oknie dialogowym wybierz element SCORM, kt\u00F3ry ma by\u0107 oceniany. Archiwum z wynikami znajdziesz w swoim folderze osobistym, w sekcji private/archive/[nazwa kursu]/[nazwa pliku]. -wizard.intro.title=Wyniki SCORM -wizard.nodechoose.howto=Wybierz element typu SCORM. -wizard.nodechoose.title=Wyb\u00F3r elementu typu SCORM -wizard.nodetitle=Nazwij element kursu diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_pt_BR.properties index d00e80f44599d196c74d408707533252fc1e6aa5..5e31052889a78af86da7ce69e6273ca1e3fba8f3 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_pt_BR.properties @@ -1,9 +1,4 @@ #Fri Sep 17 16:21:00 CEST 2010 -ScormResultArchiveController.menu.title=Resultados SCORM -ScormResultArchiveController.menu.title.alt=Resultados SCORM -archive.noresults=Nenhum resultado registrado para esse elemento do curso. -command.start.exportwizard=Iniciar arquivamento -nodesoverview.nonodes=Este curso n\u00E3o cont\u00EAm qualquer elemento SCORM. results.header=Resultados SCORM results.table.foot.cr=Responder estudante results.table.footer.sr=Corrigir resposta @@ -15,12 +10,3 @@ results.table.header.objective=Pontua\u00E7\u00E3o m\u00E1xima {0} results.table.header.rawScore=Pontua\u00E7\u00E3o Final results.table.header.totalTime=Tempo results.table.header.username=Usu\u00E1rio -wizard.finished.howto=Um arquivo contendo os dados arquivados podem ser encontrados em sua pasta pessoal. -wizard.finished.title=Arquivamento finalizado -wizard.intro.fin=Um arquivo contendo os resultados podem ser encontrados em sua pasta pessoal. -wizard.intro.nod=Por favor selecione um elemento SCORM. -wizard.intro.text=Na janela seguinte selecione o elemento SCORM para ser avaliado. Os resultados arquivados podem ser encontrados na pasta pessoal, se\u00E7\u00E3o private/archive/[course name]/[file name]. -wizard.intro.title=Resultados SCORM -wizard.nodechoose.howto=Por favor selecione um elemento SCORM. -wizard.nodechoose.title=Sele\u00E7\u00E3o elemento SCORM -wizard.nodetitle=T\u00EDtulo do elemento de curso diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_ru.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_ru.properties index f33b389df8d07c9a043ecf72ef5f15678970a938..c5594a7dab294556b73318768716862e41352db1 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_ru.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_ru.properties @@ -1,7 +1,4 @@ #Sun Jan 24 08:19:04 CET 2010 -ScormResultArchiveController.menu.title=SCORM \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B -command.start.exportwizard=\u0421\u0442\u0430\u0440\u0442 \u0430\u0440\u0445\u0438\u0432\u0430\u0446\u0438\u0438 -nodesoverview.nonodes=\u042D\u0442\u043E\u0442 \u043A\u0443\u0440\u0441 \u043D\u0435 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 SCORM \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432. results.header=SCORM \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B results.table.foot.cr=\u041E\u0442\u0432\u0435\u0442 \u0441\u0442\u0443\u0434\u0435\u043D\u0442\u0430 results.table.footer.sr=\u041F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u044B\u0439 \u043E\u0442\u0432\u0435\u0442 @@ -13,12 +10,3 @@ results.table.header.objective=\u041C\u0430\u043A\u0441\u0438\u043C\u0443\u043C results.table.header.rawScore=\u0417\u0430\u043A\u043B\u044E\u0447\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043E\u0446\u0435\u043D\u043A\u0430 results.table.header.totalTime=\u0412\u0440\u0435\u043C\u044F results.table.header.username=\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F -wizard.finished.howto=\u0424\u0430\u0439\u043B, \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0430\u0440\u0445\u0438\u0432\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u043C\u043E\u0436\u043D\u043E \u043D\u0430\u0439\u0442\u0438 \u0432 \u0432\u0430\u0448\u0435\u0439 \u043B\u0438\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u0435. -wizard.finished.title=\u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u043E\u043A\u043E\u043D\u0447\u0435\u043D\u043E -wizard.intro.fin=\u0424\u0430\u0439\u043B, \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0432\u0430\u0448\u0438 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043D\u0430\u0445\u043E\u0434\u0438\u0442\u0441\u044F \u0432 \u0432\u0430\u0448\u0435\u0439 \u043F\u0435\u0440\u0441\u043E\u043D\u0430\u043B\u044C\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u0435. -wizard.intro.nod=\u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0432\u044B\u0431\u0435\u0440\u0438\u0442\u0435 SCORM \u044D\u043B\u0435\u043C\u0435\u043D\u0442. -wizard.intro.text=\u0412 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C \u0434\u0438\u0430\u043B\u043E\u0433\u0435 \u0432\u044B\u0431\u0435\u0440\u0438\u0442\u0435 SCORM \u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0431\u0443\u0434\u0435\u0442 \u043E\u0446\u0435\u043D\u0435\u043D. \u0410\u0440\u0445\u0438\u0432 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432 \u043C\u043E\u0436\u043D\u043E \u043D\u0430\u0439\u0442\u0438 \u0432 \u0432\u0430\u0448\u0435\u0439 \u043B\u0438\u0447\u043D\u043E\u0439 \u043F\u0430\u043F\u043A\u0435, \u0432 \u0440\u0430\u0437\u0434\u0435\u043B\u0435 private/archive/[\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043A\u0443\u0440\u0441\u0430]/[\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430]. -wizard.intro.title=SCORM \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B -wizard.nodechoose.howto=\u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430 \u0432\u044B\u0431\u0435\u0440\u0438\u0442\u0435 SCORM \u044D\u043B\u0435\u043C\u0435\u043D\u0442. -wizard.nodechoose.title=\u0412\u044B\u0431\u043E\u0440 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430 SCORM -wizard.nodetitle=\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430 \u043A\u0443\u0440\u0441\u0430 diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_zh_CN.properties index 3765ca9126dbd6f7832d6525d6c10869825c7411..92bf7a4d1560e850ebab66ee6de50c4fceefd419 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_zh_CN.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_zh_CN.properties @@ -1,8 +1,4 @@ #Fri Feb 12 08:07:36 CET 2010 -ScormResultArchiveController.menu.title=SCORM \u6210\u7EE9 -ScormResultArchiveController.menu.title.alt=SCORM \u6210\u7EE9 -command.start.exportwizard=\u5F00\u59CB\u5B58\u50A8 -nodesoverview.nonodes=\u672C\u5B66\u7A0B\u4E0D\u5305\u542B\u4EFB\u4F55SCORM\u5143\u7D20\u3002 results.header=SCORM \u6210\u7EE9 results.table.foot.cr=\u56DE\u590D\u5B66\u751F results.table.footer.sr=\u6B63\u786E\u7B54\u6848 @@ -13,13 +9,4 @@ results.table.header.lessonStatus=\u72B6\u6001 results.table.header.objective=\u6700\u9AD8\u5206\u6570{0} results.table.header.rawScore=\u6700\u7EC8\u5F97\u5206 results.table.header.totalTime=\u65F6\u95F4 -results.table.header.username=\u7528\u6237\u540D -wizard.finished.howto=\u5305\u542B\u5B58\u50A8\u6570\u636E\u7684\u6587\u4EF6\u53EF\u4EE5\u5728\u60A8\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939\u4E2D\u627E\u5230\u3002 -wizard.finished.title=\u5DF2\u5B8C\u6210\u4FDD\u5B58 -wizard.intro.fin=\u5305\u542B\u60A8\u6210\u7EE9\u7684\u6587\u4EF6\u53EF\u4EE5\u5728\u60A8\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939\u4E2D\u627E\u5230\u3002 -wizard.intro.nod=\u8BF7\u9009\u62E9\u4E00\u4E2ASCORM\u5143\u7D20\u3002 -wizard.intro.text=\u8BF7\u5728\u4EE5\u4E0B\u5BF9\u8BDD\u6846\u4E2D\u9009\u62E9\u8981\u8BC4\u4EF7\u7684SCORM\u5143\u7D20\u3002\u5B58\u50A8\u7684\u6210\u7EE9\u53EF\u4EE5\u5728\u60A8\u7684\u4E2A\u4EBA\u6587\u4EF6\u5939\u4E2D\u627E\u5230\uFF0C\u5B83\u4F4D\u4E8E \u4E2A\u4EBA/\u5B58\u50A8/[course name]/[file name]\u3002 -wizard.intro.title=SCORM \u6210\u7EE9 -wizard.nodechoose.howto=\u8BF7\u9009\u62E9\u4E00\u4E2ASCORM\u5143\u7D20\u3002 -wizard.nodechoose.title=\u9009\u62E9SCORM\u5143\u7D20 -wizard.nodetitle=\u4E3A\u5B66\u7A0B\u5143\u7D20\u547D\u540D +results.table.header.username=\u7528\u6237\u540D \ No newline at end of file diff --git a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_zh_TW.properties index c16b2f55660726fb74075bf0c81e55d3b8f53c67..0ade1b1963d7617671dfcfc4e6d221951a8c780f 100644 --- a/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_zh_TW.properties +++ b/src/main/java/org/olat/modules/scorm/archiver/_i18n/LocalStrings_zh_TW.properties @@ -1,8 +1,4 @@ #Sun Feb 07 18:02:22 CET 2010 -ScormResultArchiveController.menu.title=SCORM \u7D50\u679C -ScormResultArchiveController.menu.title.alt=SCORM \u7D50\u679C -command.start.exportwizard=\u958B\u59CB\u5099\u4EFD -nodesoverview.nonodes=\u9019\u500B\u8AB2\u7A0B\u4E26\u6C92\u6709\u5305\u542B\u4EFB\u4F55 SCORM \u5143\u7D20\u3002 results.header=SCORM \u7D50\u679C results.table.foot.cr=\u56DE\u8986\u5B78\u751F results.table.footer.sr=\u6B63\u78BA\u7B54\u6848 @@ -14,11 +10,3 @@ results.table.header.objective=\u6700\u9AD8\u5206\u6578 {0} results.table.header.rawScore=\u6700\u7D42\u5206\u6578 results.table.header.totalTime=\u6642\u9593 results.table.header.username=\u4F7F\u7528\u8005\u540D\u7A31 -wizard.finished.howto=\u542B\u6709\u5DF2\u5099\u4EFD\u8CC7\u6599\u7684\u6A94\u6848\u53EF\u4EE5\u5728\u60A8\u7684\u500B\u4EBA\u8CC7\u6599\u593E\u4E2D\u627E\u5230\u3002 -wizard.finished.title=\u5099\u4EFD\u5B8C\u6210 -wizard.intro.fin=\u542B\u6709\u60A8\u7684\u7D50\u679C\u7684\u6A94\u6848\u53EF\u4EE5\u5728\u60A8\u7684\u500B\u4EBA\u8CC7\u6599\u593E\u4E2D\u627E\u5230\u3002 -wizard.intro.nod=\u8ACB\u9078\u64C7\u4E00\u500B SCORM \u5143\u7D20\u3002 -wizard.intro.title=SCORM \u7D50\u679C -wizard.nodechoose.howto=\u8ACB\u9078\u64C7\u4E00\u500B SCORM \u5143\u7D20\u3002 -wizard.nodechoose.title=\u9078\u64C7 SCORM \u5143\u7D20 -wizard.nodetitle=\u6A19\u660E\u8AB2\u7A0B\u5143\u7D20 diff --git a/src/main/java/org/olat/modules/wiki/WikiToZipUtils.java b/src/main/java/org/olat/modules/wiki/WikiToZipUtils.java index 242e77b4da8dc2c588d7a1324dca1b6709d365a1..820d12134b47a56179f732c81484a5d078dc8a5e 100644 --- a/src/main/java/org/olat/modules/wiki/WikiToZipUtils.java +++ b/src/main/java/org/olat/modules/wiki/WikiToZipUtils.java @@ -29,7 +29,10 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.IOUtils; import org.olat.core.logging.AssertException; import org.olat.core.util.FileUtils; import org.olat.core.util.ZipUtil; @@ -113,5 +116,23 @@ public class WikiToZipUtils { ZipUtil.zip(filesTozip, rootContainer.createChildLeaf("wiki.zip"), true); return (VFSLeaf)rootContainer.resolve("wiki.zip"); } - + + public static void wikiToZip(VFSContainer rootContainer, String currentPath, ZipOutputStream exportStream) + throws IOException { + for (VFSItem item:rootContainer.getItems()) { + if (item instanceof VFSContainer) { + VFSContainer folder = (VFSContainer) item; + List<VFSItem> items = folder.getItems(); + String overviewPage = WikiToZipUtils.createIndexPageForExport(items); + if(overviewPage != null){ + exportStream.putNextEntry(new ZipEntry(currentPath + "/index.html")); + IOUtils.write(overviewPage, exportStream); + exportStream.closeEntry(); + } + for(VFSItem wikiItem:items) { + ZipUtil.addToZip(wikiItem, currentPath, exportStream); + } + } + } + } }