diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java index fa4dfd6180952501ceae7373d90053b8f1d5e1d5..2c861be83bc1779340ffa0d1b8177e1ff8cc4b40 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java @@ -230,6 +230,11 @@ public interface FlexiTableElement extends FormItem { */ public void selectAll(); + /** + * Select all rows visible on the current page. + */ + public void selectPage(); + /** * Remove all multi selected index. */ diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java index dc310a1dcf1ed9ffd22970a8eb0bda3b1c0b530c..b65247113ba09602e9ca8dabd2548bfa21653113 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java @@ -405,11 +405,22 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere sb.append("<div class='o_table_footer'><div class='o_table_checkall input-sm'>"); if(ftE.isSelectAllEnable()) { + FlexiTableDataModel<?> dataModel = ftE.getTableDataModel(); + int numOfRows = dataModel.getRowCount(); + sb.append("<a id='") .append(dispatchId).append("_sa' href=\"javascript:o_table_toggleCheck('").append(formName).append("', true);") .append(FormJSHelper.getXHRFnCallFor(ftE.getRootForm(), dispatchId, 1, true, true, true, new NameValuePair("select", "checkall"))) - .append("\"><i class='o_icon o_icon-lg o_icon_check_on'> </i> <span>").append(translator.translate("form.checkall")) + .append("\"><i class='o_icon o_icon-lg o_icon_check_on'> </i> <span>") + .append(translator.translate("form.checkall.numbered", new String[] { Integer.toString(numOfRows) })) + .append("</span></a>"); + + sb.append("<a id='") + .append(dispatchId).append("_sa' href=\"javascript:o_table_toggleCheck('").append(formName).append("', true);") + .append(FormJSHelper.getXHRFnCallFor(ftE.getRootForm(), dispatchId, 1, true, true, true, + new NameValuePair("select", "checkpage"))) + .append("\"><i class='o_icon o_icon-lg o_icon_check_on'> </i> <span>").append(translator.translate("form.checkpage")) .append("</span></a>"); sb.append("<a id='") diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java index d6fad8e3d64685762740498a1426cb1cff648bb3..3e3819ce9123fd00275eaebb9568ab7343d3b4e9 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java @@ -163,7 +163,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle for(int i=dataModel.getTableColumnModel().getColumnCount(); i-->0; ) { FlexiColumnModel col = dataModel.getTableColumnModel().getColumnModel(i); if(col.isDefaultVisible()) { - enabledColumnIndex.add(new Integer(col.getColumnIndex())); + enabledColumnIndex.add(Integer.valueOf(col.getColumnIndex())); } } @@ -923,6 +923,8 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle doExport(ureq); } else if(dispatchuri != null && select != null && select.equals("checkall")) { selectAll(); + } else if(dispatchuri != null && select != null && select.equals("checkpage")) { + selectPage(); } else if(dispatchuri != null && select != null && select.equals("uncheckall")) { doUnSelectAll(); } else if(customButton != null @@ -998,7 +1000,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle } else if(searchFieldEl.getComponent() == source) { if(event instanceof AutoCompleteEvent) { AutoCompleteEvent ace = (AutoCompleteEvent)event; - doSearch(ureq, FlexiTableSearchEvent.QUICK_SEARCH_KEY_SELECTION, ace.getKey(), null); + doSearch(ureq, FlexiTableReduceEvent.QUICK_SEARCH_KEY_SELECTION, ace.getKey(), null); } } } @@ -1081,7 +1083,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle for(int i=dataModel.getRowCount(); i-->0; ) { Object obj = dataModel.getObject(i); if(obj != null && selectedObjects.contains(obj)) { - multiSelectedIndex.put(new Integer(i), obj); + multiSelectedIndex.put(Integer.valueOf(i), obj); } } @@ -1184,7 +1186,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle } component.setDirty(true); - getRootForm().fireFormEvent(ureq, new FlexiTableFilterEvent(FlexiTableFilterEvent.FILTER, this, + getRootForm().fireFormEvent(ureq, new FlexiTableFilterEvent(FlexiTableReduceEvent.FILTER, this, getQuickSearchString(), getSelectedFilters(), getSelectedExtendedFilters(), null, FormEvent.ONCLICK)); } @@ -1213,7 +1215,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle } } - getRootForm().fireFormEvent(ureq, new FlexiTableSearchEvent(FlexiTableSearchEvent.EXTENDED_FILTER, this, + getRootForm().fireFormEvent(ureq, new FlexiTableSearchEvent(FlexiTableReduceEvent.EXTENDED_FILTER, this, getSearchText(), getSelectedFilters(), getSelectedExtendedFilters(), getConditionalQueries(), FormEvent.ONCLICK)); } @@ -1512,7 +1514,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle search = searchFieldEl.getValue(); } List<String> condQueries = extendedSearchCtrl.getConditionalQueries(); - doSearch(ureq, FlexiTableSearchEvent.SEARCH, search, condQueries); + doSearch(ureq, FlexiTableReduceEvent.SEARCH, search, condQueries); } protected void evalSearchRequest(UserRequest ureq) { @@ -1528,9 +1530,9 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle String search = searchFieldEl.getValue(); if(key != null) { - doSearch(ureq, FlexiTableSearchEvent.QUICK_SEARCH_KEY_SELECTION, key, null); + doSearch(ureq, FlexiTableReduceEvent.QUICK_SEARCH_KEY_SELECTION, key, null); } else if(StringHelper.containsNonWhitespace(search)) { - doSearch(ureq, FlexiTableSearchEvent.QUICK_SEARCH, search, null); + doSearch(ureq, FlexiTableReduceEvent.QUICK_SEARCH, search, null); } else { resetSearch(ureq); } @@ -1559,7 +1561,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle } if(StringHelper.containsNonWhitespace(search)) { searchFieldEl.setValue(search); - doSearch(ureq, FlexiTableSearchEvent.QUICK_SEARCH, search, null); + doSearch(ureq, FlexiTableReduceEvent.QUICK_SEARCH, search, null); } } @@ -1574,11 +1576,30 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle int numOfRows = getRowCount(); for(int i=0; i<numOfRows;i++) { Object objectRow = dataModel.getObject(i); - multiSelectedIndex.put(new Integer(i), objectRow); + multiSelectedIndex.put(Integer.valueOf(i), objectRow); } allSelectedNeedLoadOfWholeModel = true; } + @Override + public void selectPage() { + if(multiSelectedIndex != null) { + multiSelectedIndex.clear(); + } else { + multiSelectedIndex = new HashMap<>(); + } + + int firstRow = getFirstRow(); + int maxRows = getMaxRows(); + int rows = dataModel.getRowCount(); + int lastRow = Math.min(rows, firstRow + maxRows); + for (int i = firstRow; i < lastRow; i++) { + Object objectRow = dataModel.getObject(i); + multiSelectedIndex.put(Integer.valueOf(i), objectRow); + } + allSelectedNeedLoadOfWholeModel = false; + } + protected void doUnSelectAll() { if(multiSelectedIndex != null) { multiSelectedIndex.clear(); @@ -1668,7 +1689,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle @Override public boolean isMultiSelectedIndex(int index) { - return multiSelectedIndex != null && multiSelectedIndex.containsKey(new Integer(index)); + return multiSelectedIndex != null && multiSelectedIndex.containsKey(Integer.valueOf(index)); } protected void toogleSelectIndex(String selection) { @@ -1685,7 +1706,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle } try { - Integer row = new Integer(rowStr); + Integer row = Integer.valueOf(rowStr); if(multiSelectedIndex.containsKey(row)) { if(multiSelectedIndex.remove(row) != null && allSelectedNeedLoadOfWholeModel) { allSelectedNeedLoadOfWholeModel = false; @@ -1703,12 +1724,12 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle if(multiSelectedIndex == null) { multiSelectedIndex = new HashMap<>(); } - //selection format row_{formDispId}-{index} + // selection format row_{formDispId}-{index} if(selections != null && selections.length > 0) { int firstIndex = getPageSize() * getPage(); int lastResult = firstIndex + getPageSize() -1; for(int i=firstIndex; i<lastResult; i++) { - multiSelectedIndex.remove(new Integer(i)); + multiSelectedIndex.remove(Integer.valueOf(i)); } for(String selection:selections) { @@ -1717,7 +1738,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle String rowStr = selection.substring(index+1); int row = Integer.parseInt(rowStr); Object objectRow = dataModel.getObject(row); - multiSelectedIndex.put(new Integer(row), objectRow); + multiSelectedIndex.put(Integer.valueOf(row), objectRow); } } } diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_de.properties index 9fd2ddba78e45034a3b0ea54da2c337e629d4885..88bcb8bda50509d6252556d0a6a445081e96a906 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_de.properties @@ -2,4 +2,6 @@ page.size.a=Zeige {0} bis {1} von {2} Zeilen. page.size.b=Eintr\u00E4ge pro Seite show.all=Alle -remove.filters=Filter entfernen \ No newline at end of file +remove.filters=Filter entfernen +form.checkall.numbered=Alle {0} Zeilen ausw\u00E4hlen +form.checkpage=Alle Zeilen der Seite ausw\u00E4hlen diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_en.properties index 006a8c0051895681015b31be27b822e83b4d1313..a3062842fa1801a01fb1cebcf6fa6c95d7fac7e0 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_en.properties @@ -2,4 +2,6 @@ page.size.a=Show {0} to {1} of {2} rows. page.size.b=Entries per page show.all=All -remove.filters=Remove filters \ No newline at end of file +remove.filters=Remove filters +form.checkall.numbered=Select all {0} rows +form.checkpage=Select page's rows diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_fr.properties index efeb7e90534bc12aef7f1f3ff480e23e6a98fc80..f6771ff811217194c2f1d9a28424b1b8eb782b54 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_i18n/LocalStrings_fr.properties @@ -3,3 +3,5 @@ page.size.a=Montre {0} \u00E0 {1} de {2} lignes. page.size.b=Entr\u00E9es par page remove.filters=Enlever les filtres show.all=Toutes +form.checkall.numbered=S\u00E9lectionner toutes les {0} lignes +form.checkpage=S\u00E9lectionner la page diff --git a/src/main/java/org/olat/core/util/vfs/LocalFileImpl.java b/src/main/java/org/olat/core/util/vfs/LocalFileImpl.java index 768c7fc55b50f2fa8bd068152341c66ce50dd15f..c4742d70ff27b154ec143a8ca1384072be9cdb37 100644 --- a/src/main/java/org/olat/core/util/vfs/LocalFileImpl.java +++ b/src/main/java/org/olat/core/util/vfs/LocalFileImpl.java @@ -168,10 +168,12 @@ public class LocalFileImpl extends LocalImpl implements VFSLeaf { private VFSStatus deleteBasefile() { VFSStatus status = VFSConstants.NO; try { - Files.delete(getBasefile().toPath()); + if(!Files.deleteIfExists(getBasefile().toPath())) { + log.debug("Cannot delete base file because it doesn't exist: {}", this); + } status = VFSConstants.YES; } catch(IOException e) { - log.error("Cannot delete base file: " + this, e); + log.error("Cannot delete base file: {}", this, e); } return status; } diff --git a/src/main/java/org/olat/core/util/xml/XStreamHelper.java b/src/main/java/org/olat/core/util/xml/XStreamHelper.java index 5efa6c9d26a9992052de3b03ebc453a6a49485f2..446bc767942469d0dd6a0ae4c64ff15e5b8738a7 100644 --- a/src/main/java/org/olat/core/util/xml/XStreamHelper.java +++ b/src/main/java/org/olat/core/util/xml/XStreamHelper.java @@ -178,8 +178,7 @@ public class XStreamHelper { */ public static Object xstreamClone(Object in) { String data = unconfiguredXStream.toXML(in); - Object out = unconfiguredXStream.fromXML(data); - return out; + return unconfiguredXStream.fromXML(data); } /** diff --git a/src/main/java/org/olat/course/CourseFactory.java b/src/main/java/org/olat/course/CourseFactory.java index 2c749c57f57e623a127a5d49d44ccf21c3dfdb15..5d9a17177256ccbb8b8ba8e17cdd4920f21547e5 100644 --- a/src/main/java/org/olat/course/CourseFactory.java +++ b/src/main/java/org/olat/course/CourseFactory.java @@ -552,11 +552,11 @@ public class CourseFactory { CourseConfigManager courseConfigMgr = CoreSpringFactory.getImpl(CourseConfigManager.class); courseConfigMgr.deleteConfigOf(newCourse); - // Unzip course strucure in new course + // Unzip course structure in new course LocalFolderImpl courseBaseContainer = newCourse.getCourseBaseContainer(); File fCanonicalCourseBasePath = courseBaseContainer.getBasefile(); if (ZipUtil.unzip(zipFile, fCanonicalCourseBasePath)) { - // Load course strucure now + // Load course structure now try { newCourse.load(); CourseConfig cc = courseConfigMgr.loadConfigFor(newCourse); diff --git a/src/main/java/org/olat/fileresource/types/FileResource.java b/src/main/java/org/olat/fileresource/types/FileResource.java index c7dd66add0fc226ac72e47d4518e0c1955f815b2..dcd6535fb42fa74b883ceb1e9bb2a6776368af95 100644 --- a/src/main/java/org/olat/fileresource/types/FileResource.java +++ b/src/main/java/org/olat/fileresource/types/FileResource.java @@ -69,12 +69,12 @@ public class FileResource implements OLATResourceable { public FileResource() { typeName = GENERIC_TYPE_NAME; - typeId = new Long(CodeHelper.getForeverUniqueID()); + typeId = Long.valueOf(CodeHelper.getForeverUniqueID()); } public FileResource(String typeName) { this.typeName = typeName; - typeId = new Long(CodeHelper.getForeverUniqueID()); + typeId = Long.valueOf(CodeHelper.getForeverUniqueID()); } /** diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumService.java b/src/main/java/org/olat/modules/curriculum/CurriculumService.java index a4bcc8571e862fbda217ee9c88339ef88ce0a3ec..ff15ce66fba072e8e44564e7bd31d2c44342694e 100644 --- a/src/main/java/org/olat/modules/curriculum/CurriculumService.java +++ b/src/main/java/org/olat/modules/curriculum/CurriculumService.java @@ -66,6 +66,9 @@ public interface CurriculumService { public Curriculum getCurriculum(CurriculumRef ref); public Curriculum updateCurriculum(Curriculum curriculum); + + public void deleteCurriculum(CurriculumRef curriculum); + public List<Curriculum> getCurriculums(Collection<? extends CurriculumRef> refs); diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumDAO.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumDAO.java index 75960f18f010bac9acb6f1f017d9391f27bc472f..e308f50cfc3d49dbe6cd12739942fdede8ddd8fa 100644 --- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumDAO.java +++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumDAO.java @@ -27,6 +27,7 @@ import java.util.stream.Collectors; import javax.persistence.TypedQuery; +import org.olat.basesecurity.Group; import org.olat.basesecurity.GroupRoles; import org.olat.basesecurity.IdentityRef; import org.olat.basesecurity.OrganisationRoles; @@ -342,6 +343,13 @@ public class CurriculumDAO { return dbInstance.getCurrentEntityManager().merge(curriculum); } + public void delete(CurriculumImpl curriculum) { + Group group = curriculum.getGroup(); + groupDao.removeMemberships(group); + dbInstance.getCurrentEntityManager().remove(curriculum); + groupDao.removeGroup(group); + } + public List<Identity> getMembersIdentity(CurriculumRef curriculum, String role) { StringBuilder sb = new StringBuilder(256); sb.append("select ident from curriculum cur") diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumImportHandler.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumImportHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..dc26693615b9a69ee58b3ece8c91fc1f028b2120 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumImportHandler.java @@ -0,0 +1,227 @@ +/** + * <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.curriculum.manager; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.UUID; + +import org.apache.logging.log4j.Logger; +import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; +import org.olat.core.id.Organisation; +import org.olat.core.logging.Tracing; +import org.olat.core.util.PathUtils; +import org.olat.core.util.StringHelper; +import org.olat.core.util.WebappHelper; +import org.olat.course.CourseFactory; +import org.olat.course.ICourse; +import org.olat.fileresource.types.ResourceEvaluation; +import org.olat.modules.curriculum.Curriculum; +import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumService; +import org.olat.modules.curriculum.model.CurriculumElementImpl; +import org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef; +import org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRefs; +import org.olat.modules.curriculum.model.CurriculumImpl; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryStatusEnum; +import org.olat.repository.handlers.RepositoryHandler; +import org.olat.repository.handlers.RepositoryHandlerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 19 juil. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class CurriculumImportHandler { + + private static final Logger log = Tracing.createLoggerFor(CurriculumImportHandler.class); + + @Autowired + private DB dbInstance; + @Autowired + private CurriculumService curriculumService; + @Autowired + private RepositoryHandlerFactory repositoryHandlerFactory; + + public String getCurriculumName(File archive) { + try (FileSystem fileSystem=FileSystems.newFileSystem(archive.toPath(), null)) { + Path curriculumXml = fileSystem.getPath("/curriculum.xml"); + Curriculum curriculum = CurriculumXStream.curriculumFromPath(curriculumXml); + if(curriculum != null) { + return curriculum.getDisplayName(); + } + } catch (Exception e) { + log.error("", e); + } + return null; + } + + public boolean importCurriculum(File archive, String curriculumName, Organisation organisation, Identity author, Locale locale) { + try (FileSystem fileSystem=FileSystems.newFileSystem(archive.toPath(), null)) { + Path curriculumXml = fileSystem.getPath("/curriculum.xml"); + Curriculum curriculum = CurriculumXStream.curriculumFromPath(curriculumXml); + if(curriculum == null) { + return false; + } + if(StringHelper.containsNonWhitespace(curriculumName)) { + curriculum.setDisplayName(curriculumName); + } + Map<Long,CurriculumElement> archiveKeyToCurriculumElements = new HashMap<>(); + importCurriculumStructure(curriculum, organisation, archiveKeyToCurriculumElements); + + Path curriculumEntriesXml = fileSystem.getPath("/curriculum_entries.xml"); + CurriculumElementToRepositoryEntryRefs entryRefs = CurriculumXStream.entryRefsFromPath(curriculumEntriesXml); + if(entryRefs != null) { + importEntries(entryRefs, archiveKeyToCurriculumElements, organisation, fileSystem, author, locale); + } + return true; + } catch (Exception e) { + log.error("", e); + return false; + } + } + + private void importEntries(CurriculumElementToRepositoryEntryRefs entryRefs, + Map<Long,CurriculumElement> archiveKeyToCurriculumElements, Organisation organisation, + FileSystem fileSystem, Identity author, Locale locale) throws IOException { + List<CurriculumElementToRepositoryEntryRef> entriesRefs = entryRefs.getEntryRefs(); + Map<Long,RepositoryEntry> archivedRepositoryEntryKeys = new HashMap<>(); + + for(CurriculumElementToRepositoryEntryRef entryRef:entriesRefs) { + CurriculumElement element = archiveKeyToCurriculumElements.get(entryRef.getCurriculumElementKey()); + if(element == null) { + continue; + } + + RepositoryEntry entry; + if(archivedRepositoryEntryKeys.containsKey(entryRef.getRepositoryEntryKey())) { + entry = archivedRepositoryEntryKeys.get(entryRef.getRepositoryEntryKey()); + } else { + entry = importRepositoryEntry(entryRef, organisation, fileSystem, author, locale); + } + if(entry != null) { + curriculumService.addRepositoryEntry(element, entry, false); + } + archivedRepositoryEntryKeys.put(entryRef.getRepositoryEntryKey(), entry); + } + } + + private RepositoryEntry importRepositoryEntry(CurriculumElementToRepositoryEntryRef archivedRef, Organisation organisation, + FileSystem fileSystem, Identity author, Locale locale) throws IOException { + String zipName = "repo_" + archivedRef.getRepositoryEntryKey() + ".zip"; + Path curriculumXml = fileSystem.getPath("/" + zipName); + + RepositoryEntry importedEntry = null; + if(Files.exists(curriculumXml)) { + File tmpArchive = new File(WebappHelper.getTmpDir(), UUID.randomUUID() + zipName); + tmpArchive.mkdirs(); + PathUtils.copyFileToDir(curriculumXml, tmpArchive.getParentFile(), tmpArchive.getName()); + + for(String type:repositoryHandlerFactory.getSupportedTypes()) { + RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(type); + ResourceEvaluation eval = handler.acceptImport(tmpArchive, tmpArchive.getName()); + if(eval != null && eval.isValid()) { + importedEntry = handler.importResource(author, archivedRef.getRepositoryEntryInitialAuthor(), + archivedRef.getRepositoryEntryDisplayname(), archivedRef.getRepositoryEntryDescription(), + true, organisation, locale, tmpArchive, zipName); + dbInstance.commit(); + if("CourseModule".equals(importedEntry.getOlatResource().getResourceableTypeName())) { + ICourse course = CourseFactory.loadCourse(importedEntry); + CourseFactory.publishCourse(course, RepositoryEntryStatusEnum.preparation, false, false, author, locale); + } + } + } + + if(!Files.deleteIfExists(tmpArchive.toPath())) { + log.warn("Cannot delete {}", tmpArchive.getAbsolutePath()); + } + dbInstance.commitAndCloseSession(); + } + return importedEntry; + } + + private void importCurriculumStructure(Curriculum archiveCurriculum, Organisation organisation, Map<Long,CurriculumElement> archiveKeyToCurriculumElements) { + Curriculum curriculum = curriculumService + .createCurriculum(archiveCurriculum.getIdentifier(), archiveCurriculum.getDisplayName(), archiveCurriculum.getDescription(), organisation); + curriculum.setDegree(archiveCurriculum.getDegree()); + curriculum.setStatus(archiveCurriculum.getStatus()); + curriculum = curriculumService.updateCurriculum(curriculum); + + List<CurriculumElementType> elementTypes = curriculumService.getCurriculumElementTypes(); + for(CurriculumElement rootElement:((CurriculumImpl)archiveCurriculum).getRootElements()) { + importCurriculumElements(curriculum, rootElement, null, elementTypes, archiveKeyToCurriculumElements); + } + } + + private void importCurriculumElements(Curriculum curriculum, CurriculumElement archivedElement, + CurriculumElement parentElement, List<CurriculumElementType> elementTypes, Map<Long,CurriculumElement> archiveKeyToCurriculumElements) { + if(archivedElement == null) return; + + CurriculumElementType elementType = findType(archivedElement.getType(), elementTypes); + + CurriculumElement element = curriculumService.createCurriculumElement(archivedElement.getIdentifier(), archivedElement.getDisplayName(), archivedElement.getElementStatus(), + archivedElement.getBeginDate(), archivedElement.getEndDate(), parentElement, elementType, + archivedElement.getCalendars(), archivedElement.getLectures(), curriculum); + element.setElementStatus(archivedElement.getElementStatus()); + + archiveKeyToCurriculumElements.put(archivedElement.getKey(), element); + + for(CurriculumElement childElement:((CurriculumElementImpl)archivedElement).getChildren()) { + importCurriculumElements(curriculum, childElement, element, elementTypes, archiveKeyToCurriculumElements); + } + } + + private CurriculumElementType findType(CurriculumElementType archivedType, List<CurriculumElementType> elementTypes) { + if(archivedType == null || elementTypes.isEmpty()) return null; + + for(CurriculumElementType elementType:elementTypes) { + if(elementType.getIdentifier() != null && elementType.getIdentifier().equals(archivedType.getIdentifier())) { + return elementType; + } + } + + for(CurriculumElementType elementType:elementTypes) { + if(elementType.getDisplayName() != null && elementType.getDisplayName().equals(archivedType.getDisplayName())) { + return elementType; + } + } + + CurriculumElementType newElementType = curriculumService.createCurriculumElementType(archivedType.getIdentifier(), + archivedType.getDisplayName(), archivedType.getDescription(), archivedType.getExternalId()); + elementTypes.add(newElementType); + dbInstance.commit(); + return newElementType; + } +} diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java index 97969f7a7cb8d3a39a22be69fcb053edc2e1c997..af7adb3108d3ac91cad6a006df9026abc27a0a4f 100644 --- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java +++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java @@ -72,6 +72,7 @@ import org.olat.modules.curriculum.model.CurriculumElementRepositoryEntryViews; import org.olat.modules.curriculum.model.CurriculumElementSearchInfos; import org.olat.modules.curriculum.model.CurriculumElementSearchParams; import org.olat.modules.curriculum.model.CurriculumElementWebDAVInfos; +import org.olat.modules.curriculum.model.CurriculumImpl; import org.olat.modules.curriculum.model.CurriculumInfos; import org.olat.modules.curriculum.model.CurriculumMember; import org.olat.modules.curriculum.model.CurriculumRefImpl; @@ -141,6 +142,18 @@ public class CurriculumServiceImpl implements CurriculumService, OrganisationDat return curriculumDao.update(curriculum); } + @Override + public void deleteCurriculum(CurriculumRef curriculumRef) { + CurriculumImpl curriculum = (CurriculumImpl)getCurriculum(curriculumRef); + for(CurriculumElement rootElement:curriculum.getRootElements()) { + deleteCurriculumElement(rootElement); + } + dbInstance.commit(); + curriculum = (CurriculumImpl)getCurriculum(curriculumRef); + curriculumDao.delete(curriculum); + dbInstance.commit(); + } + @Override public List<Curriculum> getCurriculums(Collection<? extends CurriculumRef> refs) { return curriculumDao.loadByKeys(refs); diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumXStream.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumXStream.java new file mode 100644 index 0000000000000000000000000000000000000000..30401379ad8b63a4e62271ee2fe7d62e26e23034 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumXStream.java @@ -0,0 +1,128 @@ +/** + * <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.curriculum.manager; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.zip.ZipOutputStream; + +import org.apache.logging.log4j.Logger; +import org.olat.core.logging.Tracing; +import org.olat.core.util.io.ShieldOutputStream; +import org.olat.core.util.xml.XStreamHelper; +import org.olat.modules.curriculum.Curriculum; +import org.olat.modules.curriculum.CurriculumCalendars; +import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementToTaxonomyLevel; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeManagedFlag; +import org.olat.modules.curriculum.CurriculumLectures; +import org.olat.modules.curriculum.model.CurriculumElementImpl; +import org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef; +import org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRefs; +import org.olat.modules.curriculum.model.CurriculumElementToTaxonomyLevelImpl; +import org.olat.modules.curriculum.model.CurriculumElementTypeImpl; +import org.olat.modules.curriculum.model.CurriculumImpl; +import org.olat.modules.portfolio.handler.BinderXStream; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.security.ExplicitTypePermission; + +/** + * + * Initial date: 17 juil. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumXStream { + + private static final Logger log = Tracing.createLoggerFor(BinderXStream.class); + private static final XStream xstream = XStreamHelper.createXStreamInstanceForDBObjects(); + + static { + XStream.setupDefaultSecurity(xstream); + Class<?>[] types = new Class[] { + Curriculum.class, CurriculumImpl.class, CurriculumElement.class, CurriculumElementImpl.class, + CurriculumElementType.class, CurriculumElementTypeImpl.class, + CurriculumElementTypeManagedFlag.class, CurriculumLectures.class, CurriculumCalendars.class, + CurriculumElementToTaxonomyLevel.class, CurriculumElementToTaxonomyLevelImpl.class, + CurriculumElementToRepositoryEntryRef.class, CurriculumElementToRepositoryEntryRefs.class, + Hashtable.class, HashMap.class + }; + xstream.addPermission(new ExplicitTypePermission(types)); + + xstream.omitField(CurriculumImpl.class, "group"); + xstream.omitField(CurriculumImpl.class, "organisation"); + xstream.omitField(CurriculumElementImpl.class, "group"); + xstream.omitField(CurriculumElementImpl.class, "curriculumParent"); + xstream.omitField(CurriculumElementImpl.class, "taxonomyLevels"); + } + + public static final Curriculum curriculumFromPath(Path path) + throws IOException { + try(InputStream inStream = Files.newInputStream(path)) { + return (Curriculum)xstream.fromXML(inStream); + } catch (Exception e) { + log.error("Cannot import this map: {}", path, e); + return null; + } + } + + public static final CurriculumElementToRepositoryEntryRefs entryRefsFromPath(Path path) + throws IOException { + try(InputStream inStream = Files.newInputStream(path)) { + return (CurriculumElementToRepositoryEntryRefs)xstream.fromXML(inStream); + } catch (Exception e) { + log.error("Cannot import this map: {}", path, e); + return null; + } + } + + public static final Curriculum fromXml(String xml) { + return (Curriculum)xstream.fromXML(xml); + } + + public static final String toXml(Curriculum curriculum) { + return xstream.toXML(curriculum); + } + + public static final void toStream(Curriculum curriculum, ZipOutputStream zout) + throws IOException { + try(OutputStream out=new ShieldOutputStream(zout)) { + xstream.toXML(curriculum, out); + } catch (Exception e) { + log.error("Cannot export this curriculum: {}", curriculum, e); + } + } + + public static final void toStream(CurriculumElementToRepositoryEntryRefs entryRefs, ZipOutputStream zout) + throws IOException { + try(OutputStream out=new ShieldOutputStream(zout)) { + xstream.toXML(entryRefs, out); + } catch (Exception e) { + log.error("Cannot export these entries references: {}", entryRefs, e); + } + } +} diff --git a/src/main/java/org/olat/modules/curriculum/manager/ExportCurriculumMediaResource.java b/src/main/java/org/olat/modules/curriculum/manager/ExportCurriculumMediaResource.java new file mode 100644 index 0000000000000000000000000000000000000000..403a7b8fccd5996378cd6e4eb11ff3ba69d0f088 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/manager/ExportCurriculumMediaResource.java @@ -0,0 +1,236 @@ +/** + * <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.curriculum.manager; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.logging.log4j.Logger; +import org.hibernate.Hibernate; +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.media.MediaResource; +import org.olat.core.id.OLATResourceable; +import org.olat.core.logging.Tracing; +import org.olat.core.util.FileUtils; +import org.olat.core.util.StringHelper; +import org.olat.core.util.io.HttpServletResponseOutputStream; +import org.olat.core.util.io.ShieldOutputStream; +import org.olat.modules.curriculum.Curriculum; +import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumService; +import org.olat.modules.curriculum.model.CurriculumElementImpl; +import org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef; +import org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRefs; +import org.olat.modules.curriculum.model.CurriculumImpl; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.handlers.RepositoryHandler; +import org.olat.repository.handlers.RepositoryHandlerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 17 juil. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ExportCurriculumMediaResource implements MediaResource { + private static final Logger log = Tracing.createLoggerFor(ExportCurriculumMediaResource.class); + + private final Curriculum curriculum; + + @Autowired + private CurriculumService curriculumService; + @Autowired + private RepositoryHandlerFactory handlerFactory; + + public ExportCurriculumMediaResource(Curriculum curriculum) { + CoreSpringFactory.autowireObject(this); + this.curriculum = curriculum; + } + + @Override + public long getCacheControlDuration() { + return 0; + } + + @Override + public boolean acceptRanges() { + return false; + } + + @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 release() { + // + } + + @Override + public void prepare(HttpServletResponse hres) { + try { + hres.setCharacterEncoding("UTF-8"); + } catch (Exception e) { + log.error("", e); + } + + try(ZipOutputStream zout = new ZipOutputStream(hres.getOutputStream())) { + Curriculum loadedCurriculum = curriculumService.getCurriculum(curriculum); + unproxy(loadedCurriculum); + String label = loadedCurriculum.getDisplayName(); + String secureLabel = StringHelper.transformDisplayNameToFileSystemName(label); + + String file = secureLabel + ".zip"; + hres.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + StringHelper.urlEncodeUTF8(file)); + hres.setHeader("Content-Description", StringHelper.urlEncodeUTF8(label)); + + zout.setLevel(9); + + // curriculum structure + zout.putNextEntry(new ZipEntry("curriculum.xml")); + CurriculumXStream.toStream(loadedCurriculum, zout); + zout.closeEntry(); + + // curriculum element to repository entry + List<ExportRepositoryEntry> collectedEntries = new ArrayList<>(); + for(CurriculumElement element:((CurriculumImpl)loadedCurriculum).getRootElements()) { + collectEntries(element, collectedEntries); + } + CurriculumElementToRepositoryEntryRefs entryRefs = new CurriculumElementToRepositoryEntryRefs(new ArrayList<>()); + for(ExportRepositoryEntry collectedEntry:collectedEntries) { + entryRefs.getEntryRefs().add(new CurriculumElementToRepositoryEntryRef(collectedEntry.getEntry(), + collectedEntry.getCurriculumElement().getKey())); + } + zout.putNextEntry(new ZipEntry("curriculum_entries.xml")); + CurriculumXStream.toStream(entryRefs, zout); + zout.closeEntry(); + + // export repository entries + Set<Long> duplicates = new HashSet<>(); + for(ExportRepositoryEntry exportedEntry:collectedEntries) { + if(!duplicates.contains(exportedEntry.getEntry().getKey())) { + exportEntries(exportedEntry, zout); + duplicates.add(exportedEntry.getEntry().getKey()); + } + } + } catch (Exception e) { + log.error("", e); + } + } + + private void exportEntries(ExportRepositoryEntry exportedEntry, ZipOutputStream zout) + throws IOException { + RepositoryEntry entry = exportedEntry.getEntry(); + OLATResourceable ores = entry.getOlatResource(); + RepositoryHandler handler = handlerFactory.getRepositoryHandler(entry); + + MediaResource mr = handler.getAsMediaResource(ores); + zout.putNextEntry(new ZipEntry("repo_" + entry.getKey() + ".zip")); + + try(OutputStream out=new ShieldOutputStream(zout); + InputStream in = mr.getInputStream()) { + if(in == null) { + HttpServletResponseOutputStream response = new HttpServletResponseOutputStream(out); + mr.prepare(response); + } else { + FileUtils.copy(in, out); + } + } catch(Exception e) { + log.error("", e); + } + zout.closeEntry(); + } + + private void collectEntries(CurriculumElement curriculumElement, List<ExportRepositoryEntry> collectedEntries) { + if(curriculumElement == null) return; + + List<RepositoryEntry> entries = curriculumService.getRepositoryEntries(curriculumElement); + for(RepositoryEntry entry:entries) { + collectedEntries.add(new ExportRepositoryEntry(entry, curriculumElement)); + } + + for(CurriculumElement element:((CurriculumElementImpl)curriculumElement).getChildren()) { + collectEntries(element, collectedEntries); + } + } + + private void unproxy(Curriculum loadedCurriculum) { + loadedCurriculum.getOrganisation(); + for(CurriculumElement element:((CurriculumImpl)loadedCurriculum).getRootElements()) { + unproxy(element); + } + } + + private void unproxy(CurriculumElement curriculumElement) { + if(curriculumElement == null) return; + + curriculumElement.getCurriculum(); + curriculumElement.setType(Hibernate.unproxy(curriculumElement.getType(), CurriculumElementType.class)); + for(CurriculumElement element:((CurriculumElementImpl)curriculumElement).getChildren()) { + unproxy(element); + } + } + + private static class ExportRepositoryEntry { + + private final RepositoryEntry entry; + private final CurriculumElement curriculumElement; + + public ExportRepositoryEntry(RepositoryEntry entry, CurriculumElement curriculumElement) { + this.entry = entry; + this.curriculumElement = curriculumElement; + } + + public RepositoryEntry getEntry() { + return entry; + } + + public CurriculumElement getCurriculumElement() { + return curriculumElement; + } + } +} diff --git a/src/main/java/org/olat/modules/curriculum/model/CurriculumElementToRepositoryEntryRef.java b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementToRepositoryEntryRef.java new file mode 100644 index 0000000000000000000000000000000000000000..edcc28f6d31d9f7063b0054201f5105e0974bcc6 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementToRepositoryEntryRef.java @@ -0,0 +1,91 @@ +/** + * <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.curriculum.model; + +import org.olat.repository.RepositoryEntry; + +/** + * This is only used for import/export operations + * + * Initial date: 19 juil. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumElementToRepositoryEntryRef { + + private Long repositoryEntryKey; + private String repositoryEntryDisplayname; + private String repositoryEntryDescription; + private String repositoryEntryInitialAuthor; + + private Long curriculumElementKey; + + public CurriculumElementToRepositoryEntryRef() { + // + } + + public CurriculumElementToRepositoryEntryRef(RepositoryEntry repositoryEntry, Long curriculumElementKey) { + repositoryEntryKey = repositoryEntry.getKey(); + repositoryEntryDisplayname = repositoryEntry.getDisplayname(); + repositoryEntryDescription = repositoryEntry.getDescription(); + repositoryEntryInitialAuthor = repositoryEntry.getInitialAuthor(); + this.curriculumElementKey = curriculumElementKey; + } + + public Long getRepositoryEntryKey() { + return repositoryEntryKey; + } + + public void setRepositoryEntryKey(Long repositoryEntryKey) { + this.repositoryEntryKey = repositoryEntryKey; + } + + public String getRepositoryEntryDisplayname() { + return repositoryEntryDisplayname; + } + + public void setRepositoryEntryDisplayname(String repositoryEntryDisplayname) { + this.repositoryEntryDisplayname = repositoryEntryDisplayname; + } + + public String getRepositoryEntryDescription() { + return repositoryEntryDescription; + } + + public void setRepositoryEntryDescription(String repositoryEntryDescription) { + this.repositoryEntryDescription = repositoryEntryDescription; + } + + public String getRepositoryEntryInitialAuthor() { + return repositoryEntryInitialAuthor; + } + + public void setRepositoryEntryInitialAuthor(String repositoryEntryInitialAuthor) { + this.repositoryEntryInitialAuthor = repositoryEntryInitialAuthor; + } + + public Long getCurriculumElementKey() { + return curriculumElementKey; + } + + public void setCurriculumElementKey(Long curriculumElementKey) { + this.curriculumElementKey = curriculumElementKey; + } +} diff --git a/src/main/java/org/olat/modules/curriculum/model/CurriculumElementToRepositoryEntryRefs.java b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementToRepositoryEntryRefs.java new file mode 100644 index 0000000000000000000000000000000000000000..472d35cbae702de6ef1f42c93c9fb4da612f1480 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementToRepositoryEntryRefs.java @@ -0,0 +1,50 @@ +/** + * <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.curriculum.model; + +import java.util.List; + +/** + * This is only used for import/export operations + * + * Initial date: 19 juil. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumElementToRepositoryEntryRefs { + + private List<CurriculumElementToRepositoryEntryRef> entryRefs; + + public CurriculumElementToRepositoryEntryRefs() { + // + } + + public CurriculumElementToRepositoryEntryRefs(List<CurriculumElementToRepositoryEntryRef> entryRefs) { + this.entryRefs = entryRefs; + } + + public List<CurriculumElementToRepositoryEntryRef> getEntryRefs() { + return entryRefs; + } + + public void setEntryRefs(List<CurriculumElementToRepositoryEntryRef> entryRefs) { + this.entryRefs = entryRefs; + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/ConfirmCurriculumDeleteController.java b/src/main/java/org/olat/modules/curriculum/ui/ConfirmCurriculumDeleteController.java new file mode 100644 index 0000000000000000000000000000000000000000..cebd73160932f3d426890b027230d13d1099e24f --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/ConfirmCurriculumDeleteController.java @@ -0,0 +1,127 @@ +/** + * <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.curriculum.ui; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.link.Link; +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.modules.curriculum.CurriculumService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 19 juil. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ConfirmCurriculumDeleteController extends FormBasicController { + + private static final String[] onKeys = new String[]{ "on" }; + + private FormLink deleteButton; + private MultipleSelectionElement acknowledgeEl; + + private final CurriculumRow rowToDelete; + + @Autowired + private CurriculumService curriculumService; + + public ConfirmCurriculumDeleteController(UserRequest ureq, WindowControl wControl, CurriculumRow rowToDelete) { + super(ureq, wControl, "confirm_delete_curriculum"); + this.rowToDelete = rowToDelete; + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + if(formLayout instanceof FormLayoutContainer) { + String[] args = new String[] { + StringHelper.escapeHtml(rowToDelete.getDisplayName()), + Long.toString(rowToDelete.getNumOfElements()) + }; + String msg = translate("confirmation.delete.curriculum", args); + ((FormLayoutContainer)formLayout).contextPut("msg", msg); + } + + FormLayoutContainer layoutCont = FormLayoutContainer.createDefaultFormLayout("confirm", getTranslator()); + formLayout.add("confirm", layoutCont); + layoutCont.setRootForm(mainForm); + + uifactory.addStaticTextElement("curriculum.displayName", "curriculum.displayName", + StringHelper.escapeHtml(rowToDelete.getDisplayName()), layoutCont); + + String[] onValues = new String[]{ translate("delete.curriculum.acknowledge") }; + acknowledgeEl = uifactory.addCheckboxesHorizontal("acknowledge", "confirmation", layoutCont, onKeys, onValues); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + layoutCont.add(buttonsCont); + uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + deleteButton = uifactory.addFormLink("delete", buttonsCont, Link.BUTTON); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); + + acknowledgeEl.clearError(); + if(!acknowledgeEl.isAtLeastSelected(1)) { + acknowledgeEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + + return allOk; + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(deleteButton == source) { + if(validateFormLogic(ureq)) { + curriculumService.deleteCurriculum(rowToDelete); + fireEvent(ureq, Event.DONE_EVENT); + } + } + super.formInnerEvent(ureq, source, event); + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementCalendarController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementCalendarController.java index a19f90041c140f4627d3a1b57fefd162a3c32c88..efb5d4f8a9090e142cf30a6f10e955ac28491f36 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementCalendarController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementCalendarController.java @@ -27,6 +27,7 @@ import java.util.List; import org.olat.commons.calendar.CalendarManager; import org.olat.commons.calendar.model.CalendarUserConfiguration; +import org.olat.commons.calendar.ui.CalendarController; import org.olat.commons.calendar.ui.WeeklyCalendarController; import org.olat.commons.calendar.ui.components.KalendarRenderWrapper; import org.olat.commons.calendar.ui.events.CalendarGUIModifiedEvent; @@ -84,7 +85,7 @@ public class CurriculumElementCalendarController extends BasicController impleme calendars = loadCalendars(ureq, entries); callerOres = OresHelper.createOLATResourceableInstance(CurriculumElement.class, element.getKey()); - calendarController = new WeeklyCalendarController(ureq, wControl, calendars, WeeklyCalendarController.CALLER_CURRICULUM, + calendarController = new WeeklyCalendarController(ureq, wControl, calendars, CalendarController.CALLER_CURRICULUM, callerOres, false); calendarController.setDifferentiateManagedEvent(CourseCalendars.needToDifferentiateManagedEvents(calendars)); listenTo(calendarController); diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumListManagerController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumListManagerController.java index db23654fe2614debf178f65241ec7af5babcbc91..de294f91f37e493db768d6212da09b67985b72b5 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/CurriculumListManagerController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumListManagerController.java @@ -54,9 +54,11 @@ import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController; import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.gui.media.MediaResource; import org.olat.core.id.Roles; import org.olat.core.id.context.ContextEntry; import org.olat.core.id.context.StateEntry; +import org.olat.core.util.StringHelper; import org.olat.core.util.resource.OresHelper; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElementMembership; @@ -65,6 +67,7 @@ import org.olat.modules.curriculum.CurriculumManagedFlag; import org.olat.modules.curriculum.CurriculumSecurityCallback; import org.olat.modules.curriculum.CurriculumSecurityCallbackFactory; import org.olat.modules.curriculum.CurriculumService; +import org.olat.modules.curriculum.manager.ExportCurriculumMediaResource; import org.olat.modules.curriculum.model.CurriculumElementRefImpl; import org.olat.modules.curriculum.model.CurriculumInfos; import org.olat.modules.curriculum.model.CurriculumSearchParameters; @@ -81,6 +84,7 @@ public class CurriculumListManagerController extends FormBasicController impleme private FlexiTableElement tableEl; private Link newCurriculumButton; + private Link importCurriculumButton; private CurriculumManagerDataModel tableModel; private final TooledStackedPanel toolbarPanel; @@ -88,7 +92,9 @@ public class CurriculumListManagerController extends FormBasicController impleme private CloseableModalController cmc; private CurriculumComposerController composerCtrl; private EditCurriculumController newCurriculumCtrl; + private ImportCurriculumController importCurriculumCtrl; private EditCurriculumOverviewController editCurriculumCtrl; + private ConfirmCurriculumDeleteController deleteCurriculumCtrl; private CloseableCalloutWindowController toolsCalloutCtrl; private int counter = 0; @@ -113,6 +119,10 @@ public class CurriculumListManagerController extends FormBasicController impleme @Override public void initTools() { if(secCallback.canNewCurriculum()) { + importCurriculumButton = LinkFactory.createToolLink("import.curriculum", translate("import.curriculum"), this, "o_icon_import"); + importCurriculumButton.setElementCssClass("o_sel_import_curriculum"); + toolbarPanel.addTool(importCurriculumButton, Align.left); + newCurriculumButton = LinkFactory.createToolLink("add.curriculum", translate("add.curriculum"), this, "o_icon_add"); newCurriculumButton.setElementCssClass("o_sel_add_curriculum"); toolbarPanel.addTool(newCurriculumButton, Align.left); @@ -246,7 +256,8 @@ public class CurriculumListManagerController extends FormBasicController impleme } cmc.deactivate(); cleanUp(); - } else if(editCurriculumCtrl == source) { + } else if(editCurriculumCtrl == source || importCurriculumCtrl == source + || deleteCurriculumCtrl == source) { if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) { loadModel(tableEl.getQuickSearchString(), false); } @@ -259,8 +270,12 @@ public class CurriculumListManagerController extends FormBasicController impleme } private void cleanUp() { + removeAsListenerAndDispose(importCurriculumCtrl); + removeAsListenerAndDispose(deleteCurriculumCtrl); removeAsListenerAndDispose(newCurriculumCtrl); removeAsListenerAndDispose(cmc); + importCurriculumCtrl = null; + deleteCurriculumCtrl = null; newCurriculumCtrl = null; cmc = null; } @@ -269,6 +284,8 @@ public class CurriculumListManagerController extends FormBasicController impleme public void event(UserRequest ureq, Component source, Event event) { if(newCurriculumButton == source) { doNewCurriculum(ureq); + } else if(importCurriculumButton == source) { + doImportCurriculum(ureq); } else if(toolbarPanel == source) { if(event instanceof PopEvent) { PopEvent pe = (PopEvent)event; @@ -311,6 +328,17 @@ public class CurriculumListManagerController extends FormBasicController impleme loadModel(event.getSearch(), true); } + private void doImportCurriculum(UserRequest ureq) { + if(importCurriculumCtrl != null) return; + + importCurriculumCtrl = new ImportCurriculumController(ureq, getWindowControl()); + listenTo(importCurriculumCtrl); + + cmc = new CloseableModalController(getWindowControl(), "close", importCurriculumCtrl.getInitialComponent(), true, translate("import.curriculum")); + listenTo(cmc); + cmc.activate(); + } + private void doNewCurriculum(UserRequest ureq) { if(newCurriculumCtrl != null) return; @@ -335,6 +363,29 @@ public class CurriculumListManagerController extends FormBasicController impleme } } + private void doDeleteCurriculum(UserRequest ureq, CurriculumRow row) { + removeAsListenerAndDispose(deleteCurriculumCtrl); + + Curriculum curriculum = curriculumService.getCurriculum(row); + if(curriculum == null) { + showWarning("warning.curriculum.deleted"); + } else { + deleteCurriculumCtrl = new ConfirmCurriculumDeleteController(ureq, getWindowControl(), row); + listenTo(deleteCurriculumCtrl); + + String title = translate("delete.curriculum.title", new String[] { StringHelper.escapeHtml(row.getDisplayName()) }); + cmc = new CloseableModalController(getWindowControl(), "close", deleteCurriculumCtrl.getInitialComponent(), true, title); + listenTo(cmc); + cmc.activate(); + } + } + + private void doExportCurriculum(UserRequest ureq, CurriculumRow row) { + Curriculum curriculum = curriculumService.getCurriculum(row); + MediaResource mr = new ExportCurriculumMediaResource(curriculum); + ureq.getDispatchResult().setResultingMediaResource(mr); + } + private void doSelectCurriculum(UserRequest ureq, CurriculumRow row, List<ContextEntry> entries) { Curriculum curriculum = curriculumService.getCurriculum(row); if(curriculum == null) { @@ -378,6 +429,7 @@ public class CurriculumListManagerController extends FormBasicController impleme private Link editLink; private Link deleteLink; + private Link exportLink; private final VelocityContainer mainVC; private CurriculumRow row; @@ -392,6 +444,8 @@ public class CurriculumListManagerController extends FormBasicController impleme //edit editLink = addLink("edit", "o_icon_edit", links); + exportLink = addLink("export", "o_icon_export", links); + if(!CurriculumManagedFlag.isManaged(curriculum, CurriculumManagedFlag.delete)) { links.add("-"); deleteLink = addLink("delete", "o_icon_delete_item", links); @@ -421,7 +475,10 @@ public class CurriculumListManagerController extends FormBasicController impleme doEditCurriculum(ureq, row); } else if(deleteLink == source) { close(); - showWarning("Not implemented"); + doDeleteCurriculum(ureq, row); + } else if(exportLink == source) { + close(); + doExportCurriculum(ureq, row); } } diff --git a/src/main/java/org/olat/modules/curriculum/ui/ImportCurriculumController.java b/src/main/java/org/olat/modules/curriculum/ui/ImportCurriculumController.java new file mode 100644 index 0000000000000000000000000000000000000000..b4427e957160764966320e0c06502c2c3fc9619f --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/ImportCurriculumController.java @@ -0,0 +1,167 @@ +/** + * <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.curriculum.ui; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.olat.basesecurity.OrganisationModule; +import org.olat.basesecurity.OrganisationRoles; +import org.olat.basesecurity.OrganisationService; +import org.olat.basesecurity.model.OrganisationRefImpl; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FileElement; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +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.id.Organisation; +import org.olat.core.id.Roles; +import org.olat.core.util.StringHelper; +import org.olat.core.util.UserSession; +import org.olat.modules.curriculum.manager.CurriculumImportHandler; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 17 juil. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ImportCurriculumController extends FormBasicController { + + private FileElement uploadFileEl; + private TextElement displayNameEl; + private SingleSelection organisationEl; + + @Autowired + private OrganisationModule organisationModule; + @Autowired + private OrganisationService organisationService; + @Autowired + private CurriculumImportHandler curriculumImportHandler; + + public ImportCurriculumController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + uploadFileEl = uifactory.addFileElement(getWindowControl(), "curriculum.file", formLayout); + uploadFileEl.limitToMimeType(Collections.singleton("application/zip"), "error.mimetype", new String[]{ "ZIP" }); + uploadFileEl.setMandatory(true); + uploadFileEl.addActionListener(FormEvent.ONCHANGE); + + displayNameEl = uifactory.addTextElement("curriculum.displayName", 255, "", formLayout); + displayNameEl.setMandatory(true); + + initFormOrganisations(formLayout, ureq.getUserSession()); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + uifactory.addFormSubmitButton("import.curriculum", buttonsCont); + } + + private void initFormOrganisations(FormItemContainer formLayout, UserSession usess) { + Roles roles = usess.getRoles(); + List<Organisation> organisations = organisationService.getOrganisations(getIdentity(), roles, + OrganisationRoles.administrator, OrganisationRoles.curriculummanager); + + List<String> keyList = new ArrayList<>(); + List<String> valueList = new ArrayList<>(); + for(Organisation organisation:organisations) { + keyList.add(organisation.getKey().toString()); + valueList.add(organisation.getDisplayName()); + } + + organisationEl = uifactory.addDropdownSingleselect("curriculum.organisation", formLayout, + keyList.toArray(new String[keyList.size()]), valueList.toArray(new String[valueList.size()])); + organisationEl.setVisible(organisationModule.isEnabled()); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); + + displayNameEl.clearError(); + if(!StringHelper.containsNonWhitespace(displayNameEl.getValue())) { + displayNameEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + + uploadFileEl.clearError(); + if(uploadFileEl.getUploadFile() == null) { + uploadFileEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } else { + validateFormItem(uploadFileEl); + } + + return allOk; + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(uploadFileEl == source) { + if(!StringHelper.containsNonWhitespace(displayNameEl.getValue()) + && uploadFileEl.getUploadFile() != null) { + String name = curriculumImportHandler.getCurriculumName(uploadFileEl.getUploadFile()); + displayNameEl.setValue(name); + } + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void formOK(UserRequest ureq) { + File archive = uploadFileEl.getUploadFile(); + + Organisation organisation; + if(organisationEl.isOneSelected()) { + Long organisationKey = Long.valueOf(organisationEl.getSelectedKey()); + organisation = organisationService.getOrganisation(new OrganisationRefImpl(organisationKey)); + } else { + organisation = organisationService.getDefaultOrganisation(); + } + String curriculumName = displayNameEl.getValue(); + curriculumImportHandler.importCurriculum(archive, curriculumName, organisation, getIdentity(), getLocale()); + fireEvent(ureq, Event.DONE_EVENT); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/_content/confirm_delete_curriculum.html b/src/main/java/org/olat/modules/curriculum/ui/_content/confirm_delete_curriculum.html new file mode 100644 index 0000000000000000000000000000000000000000..2e8fdedae59c72e0d7bd0d26b46e251667162464 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/_content/confirm_delete_curriculum.html @@ -0,0 +1,4 @@ +<div class="o_error"> + <p><i class="o_icon o_icon-lg o_icon_important"> </i> $msg</p> +</div> +$r.render("confirm") \ No newline at end of file diff --git a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties index 440d5cca7eb2f520c11ae7bc9703e9766922721f..c0b4bf630247d5d65d22af09f23c54e21c1a3cf4 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties @@ -16,9 +16,11 @@ confirm.remove.member.title=Mitglieder entfernen confirm.remove.member.text=Wollen Sie wirklich diese Mitglieder entfernen? confirm.remove.resource.title=Lernresourcen entfernen confirm.remove.resource.text=Wollen Sie wirklich diese Lernresourcen entfernen? +confirmation=Best\u00E4tigung confirmation.delete.type=Wollen Sie wirklich den Typ "{0}" l\u00F6schen? confirmation.delete.type.title=Typ "{0}" l\u00F6schen confirmation.delete.element=Wollen Sie wirklich dieses Curriculum Element "{0}" l\u00F6schen? +confirmation.delete.curriculum=Wollen Sie wirklich dieses Curriculum "{0}" l\u00F6schen? Er enth\u00E4lt <strong>{1} Elementen</strong>. confirmation.delete.element.title=Curriculum Element "{0}" l\u00F6schen copy.element=Element kopieren copy.element.title=Element "{0}" kopieren @@ -48,10 +50,13 @@ curriculum.external.id=Externe ID curriculum.identifier=Bezeichnung curriculum.in.my.courses.enabled=Curriculum in "Meine Kurse" curriculum.inactive.explain=Sie haben kein aktives Curriculum Element mit einem publizierten Kurs in diesem Curriculum. +curriculum.file=Datei curriculum.key=ID curriculum.metadata=Metadaten curriculum.organisation=Organisation curriculum.search=Suchen +delete.curriculum.acknowledge=Ich verstehe, dass das Curriculum und alle seine Elementen werden definitive gel\u00F6scht. +delete.curriculum.title=Curriculum "{0}" l\u00F6schen details=Infoseite details.copy=Kopieren details.delete=L\u00F6schen @@ -61,6 +66,7 @@ error.target.no.insertion.point=Sie m\u00FCssen eine Position w\u00E4hlen. filter.active=$\:status.active filter.deleted=$\:status.deleted filter.inactive=$\:status.inactive +import.curriculum=Curriculum importieren import.member=$org.olat.group.ui.main\:import.member info.copy.element.type.sucessfull=Der Typ "{0}" wurde erfolgreich kopiert. override.member=Externe Verwaltung \u00FCbergehen diff --git a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties index d66b8c97e91abd392485ff27896ce584ccce3457..543913620d4204e31101e8ac7e4741ebb6104927 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties @@ -16,6 +16,8 @@ confirm.remove.member.text=Do you really want to remove this member(s)? confirm.remove.member.title=Remove member confirm.remove.resource.text=Do you really want to remove this learn resource(s)? confirm.remove.resource.title=Remove learn resources +confirmation=Confirmation +confirmation.delete.curriculum=Do you really want to delete this curriculum "{0}"? It contains <strong>{1} elements</strong>. confirmation.delete.element=Do you really want to delete this curriculum element "{0}"? confirmation.delete.element.title=Delete curriculum element "{0}" confirmation.delete.type=Do you really want to delete this type "{0}"? @@ -48,10 +50,13 @@ curriculum.external.id=External ID curriculum.identifier=Identifier curriculum.in.my.courses.enabled=Curriculum in "My courses" curriculum.inactive.explain=You don't have an active curriculum element in this curriculum with a published course. +curriculum.file=File curriculum.key=ID curriculum.metadata=Metadata curriculum.organisation=Organisation curriculum.search=Search +delete.binder.acknowledge=I understand that the curriculum and all its elements will be definitely deleted. +delete.curriculum.title=Delete curriculum "{0}" details=Info page details.copy=Copy details.delete=Delete @@ -61,6 +66,7 @@ error.target.no.insertion.point=You must choose a position. filter.active=$\:status.active filter.deleted=$\:status.deleted filter.inactive=$\:status.inactive +import.curriculum=Import curriculum import.member=$org.olat.group.ui.main\:import.member info.copy.element.type.sucessfull=The type "{0}" was successfully copied. lectures=Absences diff --git a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties index 7bf718c0d54838ab25238ba25e1befbf13c0d925..f40e2186857e11f0cd63634537438f950860ecc9 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties @@ -144,7 +144,7 @@ delete.assignment.in.use.confirm.descr=$\:delete.assignment.confirm.descr <div c delete.assignment.template.confirm.descr=Do you really want to delete this template "{0}"? delete.assignment.template.confirm.title=Delete template delete.binder=Delete binder -delete.binder.acknowledge=I understand that the binder and all its entries will be definetly deleted. +delete.binder.acknowledge=I understand that the binder and all its entries will be definitely deleted. delete.binder.acknowledge.2=I understand that the binder cannot be restored again. delete.binder.success=Binder is successfully deleted. delete.binder.warning=Do you really want to delete the binder "{0}"? It contains <strong>{1}</strong> sections, <strong>{2}</strong> entries and <strong>{3}</strong> comments. diff --git a/src/main/java/org/olat/modules/taxonomy/ui/EditTaxonomyController.java b/src/main/java/org/olat/modules/taxonomy/ui/EditTaxonomyController.java index 8decbac7f4802adfe5563b855c5194c5c01ae74b..725a1e55b8eb1fc6ce6e6184c26afe5043a87679 100644 --- a/src/main/java/org/olat/modules/taxonomy/ui/EditTaxonomyController.java +++ b/src/main/java/org/olat/modules/taxonomy/ui/EditTaxonomyController.java @@ -63,6 +63,8 @@ public class EditTaxonomyController extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + formLayout.setElementCssClass("o_sel_taxonomy_form"); + if(taxonomy != null) { String key = taxonomy.getKey().toString(); uifactory.addStaticTextElement("taxonomy.key", key, formLayout); @@ -98,7 +100,7 @@ public class EditTaxonomyController extends FormBasicController { @Override protected boolean validateFormLogic(UserRequest ureq) { - boolean allOk = true; + boolean allOk = super.validateFormLogic(ureq); displayNameEl.clearError(); if(!StringHelper.containsNonWhitespace(displayNameEl.getValue())) { @@ -112,7 +114,7 @@ public class EditTaxonomyController extends FormBasicController { allOk &= false; } - return allOk & super.validateFormLogic(ureq); + return allOk; } @Override diff --git a/src/main/java/org/olat/modules/taxonomy/ui/EditTaxonomyLevelController.java b/src/main/java/org/olat/modules/taxonomy/ui/EditTaxonomyLevelController.java index 7f550ac2565f86f451a718590f08756c90c51ec4..1812a960e8dcf5a92c2cf0ec614de57cbbfbc0d2 100644 --- a/src/main/java/org/olat/modules/taxonomy/ui/EditTaxonomyLevelController.java +++ b/src/main/java/org/olat/modules/taxonomy/ui/EditTaxonomyLevelController.java @@ -271,14 +271,14 @@ public class EditTaxonomyLevelController extends FormBasicController { String selectedTypeKey = taxonomyLevelTypeEl.getSelectedKey(); if(StringHelper.containsNonWhitespace(selectedTypeKey)) { - TaxonomyLevelTypeRef typeRef = new TaxonomyLevelTypeRefImpl(new Long(selectedTypeKey)); + TaxonomyLevelTypeRef typeRef = new TaxonomyLevelTypeRefImpl(Long.valueOf(selectedTypeKey)); TaxonomyLevelType type = taxonomyService.getTaxonomyLevelType(typeRef); level.setType(type); } else { level.setType(null); } if(StringHelper.isLong(sortOrderEl.getValue())) { - level.setSortOrder(new Integer(sortOrderEl.getValue())); + level.setSortOrder(Integer.valueOf(sortOrderEl.getValue())); } else { level.setSortOrder(null); } diff --git a/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java b/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java index 3ffa9de9215415cec130a721950217eeece549fe..640b2d205fa5d8b8a12036b1048d19b6ef62e3a7 100644 --- a/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java +++ b/src/main/java/org/olat/repository/ui/RepositoryEntryRuntimeController.java @@ -643,7 +643,7 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController } } - protected void processPopEvent(@SuppressWarnings("unused") UserRequest ureq, PopEvent pop) { + protected void processPopEvent(UserRequest ureq, PopEvent pop) { if(pop.getController() == settingsCtrl && settingsChanged) { RepositoryEntry entry = repositoryService.loadByKey(getRepositoryEntry().getKey()); refreshRepositoryEntry(entry); @@ -676,8 +676,6 @@ public class RepositoryEntryRuntimeController extends MainLayoutBasicController doClose(ureq); } else if(event instanceof ReloadSettingsEvent) { processReloadSettingsEvent((ReloadSettingsEvent)event); - } else if(event instanceof ReloadSettingsEvent) { - processReloadSettingsEvent((ReloadSettingsEvent)event); } else if (event == RepositoryEntryLifeCycleChangeController.closedEvent || event == RepositoryEntryLifeCycleChangeController.unclosedEvent) { processClosedUnclosedEvent(ureq); diff --git a/src/main/java/org/olat/repository/ui/author/AuthorListController.java b/src/main/java/org/olat/repository/ui/author/AuthorListController.java index a2623d33301f9f0b44bc64b24af6176c896ba1a2..8165e395e9876d7eb47d0dead9d038ff8051cc61 100644 --- a/src/main/java/org/olat/repository/ui/author/AuthorListController.java +++ b/src/main/java/org/olat/repository/ui/author/AuthorListController.java @@ -1066,7 +1066,7 @@ public class AuthorListController extends FormBasicController implements Activat boolean isAlreadyLocked = typeToDownload.isLocked(ores); try { lockResult = typeToDownload.acquireLock(ores, ureq.getIdentity()); - if(lockResult == null || (lockResult !=null && lockResult.isSuccess() && !isAlreadyLocked)) { + if(lockResult == null || (lockResult.isSuccess() && !isAlreadyLocked)) { MediaResource mr = typeToDownload.getAsMediaResource(ores); if(mr!=null) { repositoryService.incrementDownloadCounter(entry); diff --git a/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java b/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java index 1dc9f8761bd953f25b4e6daddc205a247574a9cc..ca624a1f8dedec6a140c6652adc6145989f57a81 100644 --- a/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java +++ b/src/main/java/org/olat/repository/ui/author/ImportRepositoryEntryController.java @@ -320,7 +320,7 @@ public class ImportRepositoryEntryController extends FormBasicController { String displayName = ""; boolean references = false; - if (handlers != null && handlers.size() > 0) { // add image and typename code + if (handlers != null && !handlers.isEmpty()) { // add image and typename code ResourceHandler handler = handlers.get(0); displayName = handler.getEval().getDisplayname(); references = handler.getEval().isReferences(); @@ -358,7 +358,7 @@ public class ImportRepositoryEntryController extends FormBasicController { if(references) { referencesEl.select(refKeys[0], true); } - importButton.setEnabled(handlers.size() > 0); + importButton.setEnabled(!handlers.isEmpty()); } private class ResourceHandler { diff --git a/src/test/java/org/olat/modules/curriculum/manager/CurriculumXStreamTest.java b/src/test/java/org/olat/modules/curriculum/manager/CurriculumXStreamTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1720acbce94f4505fefe945aceeb64e95e5987d6 --- /dev/null +++ b/src/test/java/org/olat/modules/curriculum/manager/CurriculumXStreamTest.java @@ -0,0 +1,84 @@ +/** + * <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.curriculum.manager; + +import java.io.File; +import java.net.URL; +import java.util.Date; + +import org.junit.Assert; +import org.junit.Test; +import org.olat.core.commons.persistence.DB; +import org.olat.modules.curriculum.Curriculum; +import org.olat.modules.curriculum.CurriculumCalendars; +import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementStatus; +import org.olat.modules.curriculum.CurriculumLectures; +import org.olat.modules.curriculum.CurriculumService; +import org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRefs; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 17 juil. 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumXStreamTest extends OlatTestCase { + + @Autowired + private DB dbInstance; + @Autowired + private CurriculumService curriculumService; + + @Test + public void toStream() { + Curriculum curriculum = curriculumService.createCurriculum("CUR-XSTREAM-1", "My Curriculum 1", "Short desc.", null); + CurriculumElement element = curriculumService.createCurriculumElement("Element-1", "1. Element", CurriculumElementStatus.active, + new Date(), new Date(), null, null, CurriculumCalendars.disabled, CurriculumLectures.disabled, curriculum); + dbInstance.commitAndCloseSession(); + + Curriculum loadedCurriculum = curriculumService.getCurriculum(curriculum); + String xml = CurriculumXStream.toXml(loadedCurriculum); + Assert.assertTrue(xml.contains(curriculum.getDisplayName())); + Assert.assertTrue(xml.contains(element.getDisplayName())); + + Curriculum streamedCurriculum = CurriculumXStream.fromXml(xml); + Assert.assertNotNull(streamedCurriculum); + Assert.assertEquals(loadedCurriculum.getKey(), streamedCurriculum.getKey()); + } + + @Test + public void curriculumFromXml_version14x() throws Exception { + URL input = CurriculumXStreamTest.class.getResource("curriculum.xml"); + File inputFile = new File(input.getFile()); + Curriculum export = CurriculumXStream.curriculumFromPath(inputFile.toPath()); + Assert.assertNotNull(export); + } + + @Test + public void entriesFromXml_version14x() throws Exception { + URL input = CurriculumXStreamTest.class.getResource("curriculum_entries.xml"); + File inputFile = new File(input.getFile()); + CurriculumElementToRepositoryEntryRefs export = CurriculumXStream.entryRefsFromPath(inputFile.toPath()); + Assert.assertNotNull(export); + } +} diff --git a/src/test/java/org/olat/modules/curriculum/manager/curriculum.xml b/src/test/java/org/olat/modules/curriculum/manager/curriculum.xml new file mode 100644 index 0000000000000000000000000000000000000000..a747d3d67d367438bbf42a263c595ba2f0daf57f --- /dev/null +++ b/src/test/java/org/olat/modules/curriculum/manager/curriculum.xml @@ -0,0 +1,328 @@ +<org.olat.modules.curriculum.model.CurriculumImpl> + <key>1</key> + <creationDate class="sql-timestamp">2018-07-13 14:04:18.723</creationDate> + <lastModified class="sql-timestamp">2018-07-13 14:04:18.723</lastModified> + <identifier>Physik</identifier> + <displayName>Physik</displayName> + <description></description> + <rootElements> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>1</key> + <creationDate class="sql-timestamp">2018-07-13 14:04:36.1</creationDate> + <lastModified class="sql-timestamp">2018-10-22 12:38:22.917</lastModified> + <posCurriculum>0</posCurriculum> + <identifier>Astrophysik</identifier> + <displayName>Astrophysik</displayName> + <description></description> + <calendarsEnabledString>disabled</calendarsEnabledString> + <status>active</status> + <materializedPathKeys>/1/</materializedPathKeys> + <children> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>8</key> + <creationDate class="sql-timestamp">2018-07-18 16:33:55.543</creationDate> + <lastModified class="sql-timestamp">2019-02-19 10:39:31.199</lastModified> + <pos>0</pos> + <identifier>Solar system</identifier> + <displayName>Solar system</displayName> + <description></description> + <calendarsEnabledString>disabled</calendarsEnabledString> + <lecturesEnabledString>enabled</lecturesEnabledString> + <status>active</status> + <beginDate class="sql-timestamp">2019-02-11 23:00:00</beginDate> + <endDate class="sql-timestamp">2019-02-27 23:00:00</endDate> + <materializedPathKeys>/1/8/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>10</key> + <creationDate class="sql-timestamp">2018-07-18 16:34:29.45</creationDate> + <lastModified class="sql-timestamp">2018-10-22 12:37:33.456</lastModified> + <pos>0</pos> + <identifier>Saturn</identifier> + <displayName>Saturn</displayName> + <description></description> + <calendarsEnabledString>enabled</calendarsEnabledString> + <status>active</status> + <materializedPathKeys>/1/8/10/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../../../.."/> + <type class="org.olat.modules.curriculum.model.CurriculumElementTypeImpl"> + <key>4</key> + <creationDate class="sql-timestamp">2018-10-22 12:35:23.921</creationDate> + <lastModified class="sql-timestamp">2018-10-22 12:35:23.923</lastModified> + <identifier>Seminar</identifier> + <displayName>Seminar</displayName> + <description></description> + <cssClass></cssClass> + <calendarsEnabledString>enabled</calendarsEnabledString> + <allowedSubTypes> + <isTempSession>false</isTempSession> + <initialized>false</initialized> + <owner class="org.olat.modules.curriculum.model.CurriculumElementTypeImpl" reference="../.."/> + <cachedSize>-1</cachedSize> + <role>org.olat.modules.curriculum.model.CurriculumElementTypeImpl.allowedSubTypes</role> + <key class="long">4</key> + <dirty>false</dirty> + <elementRemoved>false</elementRemoved> + <allowLoadOutsideTransaction>false</allowLoadOutsideTransaction> + </allowedSubTypes> + </type> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>11</key> + <creationDate class="sql-timestamp">2018-07-18 16:34:42.244</creationDate> + <lastModified class="sql-timestamp">2018-10-11 08:20:32.406</lastModified> + <pos>1</pos> + <identifier>Jupiter</identifier> + <displayName>Jupiter</displayName> + <description></description> + <calendarsEnabledString>disabled</calendarsEnabledString> + <status>active</status> + <beginDate class="sql-timestamp">2018-10-05 22:00:00</beginDate> + <endDate class="sql-timestamp">2018-10-26 22:00:00</endDate> + <materializedPathKeys>/1/8/11/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + </children> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../.."/> + <type class="org.olat.modules.curriculum.model.CurriculumElementTypeImpl"> + <key>2</key> + <creationDate class="sql-timestamp">2018-10-22 12:34:59.867</creationDate> + <lastModified class="sql-timestamp">2019-02-13 14:08:32.946</lastModified> + <identifier>Semester</identifier> + <displayName>Semester</displayName> + <description></description> + <cssClass></cssClass> + <calendarsEnabledString>enabled</calendarsEnabledString> + <lecturesEnabledString>enabled</lecturesEnabledString> + <allowedSubTypes> + <isTempSession>false</isTempSession> + <initialized>false</initialized> + <owner class="org.olat.modules.curriculum.model.CurriculumElementTypeImpl" reference="../.."/> + <cachedSize>-1</cachedSize> + <role>org.olat.modules.curriculum.model.CurriculumElementTypeImpl.allowedSubTypes</role> + <key class="long">2</key> + <dirty>false</dirty> + <elementRemoved>false</elementRemoved> + <allowLoadOutsideTransaction>false</allowLoadOutsideTransaction> + </allowedSubTypes> + </type> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>9</key> + <creationDate class="sql-timestamp">2018-07-18 16:34:14.697</creationDate> + <lastModified class="sql-timestamp">2018-10-15 14:27:47.814</lastModified> + <pos>1</pos> + <identifier>Galaxy</identifier> + <displayName>Galaxy</displayName> + <description></description> + <calendarsEnabledString>disabled</calendarsEnabledString> + <status>active</status> + <beginDate class="sql-timestamp">2018-09-30 22:00:00</beginDate> + <endDate class="sql-timestamp">2018-10-02 22:00:00</endDate> + <materializedPathKeys>/1/9/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + </children> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../.."/> + <type class="org.olat.modules.curriculum.model.CurriculumElementTypeImpl"> + <key>1</key> + <creationDate class="sql-timestamp">2018-10-05 07:18:24.409</creationDate> + <lastModified class="sql-timestamp">2018-10-22 12:35:04.245</lastModified> + <identifier>Bildungsgang</identifier> + <displayName>Bildungsgang</displayName> + <description></description> + <cssClass></cssClass> + <calendarsEnabledString>enabled</calendarsEnabledString> + <allowedSubTypes> + <isTempSession>false</isTempSession> + <initialized>false</initialized> + <owner class="org.olat.modules.curriculum.model.CurriculumElementTypeImpl" reference="../.."/> + <cachedSize>-1</cachedSize> + <role>org.olat.modules.curriculum.model.CurriculumElementTypeImpl.allowedSubTypes</role> + <key class="long">1</key> + <dirty>false</dirty> + <elementRemoved>false</elementRemoved> + <allowLoadOutsideTransaction>false</allowLoadOutsideTransaction> + </allowedSubTypes> + </type> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>2</key> + <creationDate class="sql-timestamp">2018-07-18 16:31:54.842</creationDate> + <lastModified class="sql-timestamp">2018-10-16 12:57:04.003</lastModified> + <posCurriculum>1</posCurriculum> + <identifier>Quantum Physik</identifier> + <displayName>Quantum Physik</displayName> + <description></description> + <calendarsEnabledString>enabled</calendarsEnabledString> + <status>active</status> + <materializedPathKeys>/2/</materializedPathKeys> + <children> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>25</key> + <creationDate class="sql-timestamp">2018-10-16 12:57:29.674</creationDate> + <lastModified class="sql-timestamp">2018-10-16 13:01:11.316</lastModified> + <pos>0</pos> + <identifier>Chromodynamique quantique</identifier> + <displayName>Chromodynamique quantique</displayName> + <description></description> + <calendarsEnabledString>enabled</calendarsEnabledString> + <status>active</status> + <materializedPathKeys>/2/25/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>27</key> + <creationDate class="sql-timestamp">2018-10-16 13:00:48.07</creationDate> + <lastModified class="sql-timestamp">2019-02-19 10:57:29.496</lastModified> + <pos>0</pos> + <identifier>Chromodynamique quantique aspects pratiques</identifier> + <displayName>Chromodynamique quantique aspects pratiques</displayName> + <description></description> + <calendarsEnabledString>disabled</calendarsEnabledString> + <lecturesEnabledString>enabled</lecturesEnabledString> + <status>active</status> + <materializedPathKeys>/2/25/27/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>28</key> + <creationDate class="sql-timestamp">2018-10-16 13:01:04.464</creationDate> + <lastModified class="sql-timestamp">2018-10-16 13:01:04.464</lastModified> + <pos>1</pos> + <identifier>Chromodynamique quantique théorie math.</identifier> + <displayName>Chromodynamique quantique théorie math.</displayName> + <calendarsEnabledString>disabled</calendarsEnabledString> + <status>active</status> + <materializedPathKeys>/2/25/28/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + </children> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>26</key> + <creationDate class="sql-timestamp">2018-10-16 12:58:20.489</creationDate> + <lastModified class="sql-timestamp">2018-10-16 12:58:20.489</lastModified> + <pos>1</pos> + <identifier>Mécanique quantique relativiste</identifier> + <displayName>Mécanique quantique relativiste</displayName> + <calendarsEnabledString>disabled</calendarsEnabledString> + <status>active</status> + <materializedPathKeys>/2/26/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + </children> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>3</key> + <creationDate class="sql-timestamp">2018-07-18 16:32:22.429</creationDate> + <lastModified class="sql-timestamp">2018-07-18 16:32:22.429</lastModified> + <posCurriculum>2</posCurriculum> + <identifier>Math</identifier> + <displayName>Math</displayName> + <status>active</status> + <materializedPathKeys>/3/</materializedPathKeys> + <children> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>4</key> + <creationDate class="sql-timestamp">2018-07-18 16:32:39.837</creationDate> + <lastModified class="sql-timestamp">2018-07-18 16:32:39.837</lastModified> + <pos>0</pos> + <identifier>Topology</identifier> + <displayName>Topology</displayName> + <status>active</status> + <materializedPathKeys>/3/4/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>5</key> + <creationDate class="sql-timestamp">2018-07-18 16:32:59.384</creationDate> + <lastModified class="sql-timestamp">2018-07-18 16:32:59.384</lastModified> + <pos>1</pos> + <identifier>Numerische Simulation</identifier> + <displayName>Numerische Simulation</displayName> + <status>inactive</status> + <materializedPathKeys>/3/5/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>6</key> + <creationDate class="sql-timestamp">2018-07-18 16:33:16.646</creationDate> + <lastModified class="sql-timestamp">2018-07-18 16:33:16.646</lastModified> + <pos>0</pos> + <identifier>R Software</identifier> + <displayName>R Software</displayName> + <status>active</status> + <materializedPathKeys>/3/5/6/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>7</key> + <creationDate class="sql-timestamp">2018-07-18 16:33:39.025</creationDate> + <lastModified class="sql-timestamp">2018-10-15 14:27:58.13</lastModified> + <pos>1</pos> + <identifier>Fortran</identifier> + <displayName>Fortran</displayName> + <description></description> + <calendarsEnabledString>disabled</calendarsEnabledString> + <status>active</status> + <beginDate class="sql-timestamp">2018-09-30 22:00:00</beginDate> + <endDate class="sql-timestamp">2018-10-02 22:00:00</endDate> + <materializedPathKeys>/3/5/7/</materializedPathKeys> + <parent class="org.olat.modules.curriculum.model.CurriculumElementImpl" reference="../../.."/> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + </children> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + </children> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>17</key> + <creationDate class="sql-timestamp">2018-07-26 16:46:33.362</creationDate> + <lastModified class="sql-timestamp">2018-07-26 16:58:46.45</lastModified> + <pos>0</pos> + <posCurriculum>3</posCurriculum> + <identifier>To delete 5</identifier> + <displayName>To delete 5</displayName> + <status>deleted</status> + <materializedPathKeys>/17/</materializedPathKeys> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + <org.olat.modules.curriculum.model.CurriculumElementImpl> + <key>20</key> + <creationDate class="sql-timestamp">2018-07-26 19:32:10.768</creationDate> + <lastModified class="sql-timestamp">2018-07-26 19:36:07.528</lastModified> + <pos>0</pos> + <posCurriculum>4</posCurriculum> + <identifier>To delete 8</identifier> + <displayName>To delete 8</displayName> + <status>deleted</status> + <materializedPathKeys>/20/</materializedPathKeys> + <children/> + <curriculum class="org.olat.modules.curriculum.model.CurriculumImpl" reference="../../.."/> + </org.olat.modules.curriculum.model.CurriculumElementImpl> + </rootElements> +</org.olat.modules.curriculum.model.CurriculumImpl> \ No newline at end of file diff --git a/src/test/java/org/olat/modules/curriculum/manager/curriculum_entries.xml b/src/test/java/org/olat/modules/curriculum/manager/curriculum_entries.xml new file mode 100644 index 0000000000000000000000000000000000000000..e6a05aff603e11aa9fe83a7e0bdaddeabc0a01d5 --- /dev/null +++ b/src/test/java/org/olat/modules/curriculum/manager/curriculum_entries.xml @@ -0,0 +1,95 @@ +<org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRefs> + <entryRefs> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>319913984</repositoryEntryKey> + <repositoryEntryDisplayname>4 Generate courses</repositoryEntryDisplayname> + <repositoryEntryDescription>Training<br /></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>1</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>1201504256</repositoryEntryKey> + <repositoryEntryDisplayname>Assessment docs</repositoryEntryDisplayname> + <repositoryEntryDescription></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>1</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>1408073728</repositoryEntryKey> + <repositoryEntryDisplayname>Curriculum course</repositoryEntryDisplayname> + <repositoryEntryDescription></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>1</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>1529020417</repositoryEntryKey> + <repositoryEntryDisplayname>Refactoring 3 (book)</repositoryEntryDisplayname> + <repositoryEntryDescription></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>1</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>321880064</repositoryEntryKey> + <repositoryEntryDisplayname>Course with members list</repositoryEntryDisplayname> + <repositoryEntryDescription></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>10</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>819789824</repositoryEntryKey> + <repositoryEntryDisplayname>Lectures</repositoryEntryDisplayname> + <repositoryEntryDescription><p>Bla bla</p></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>10</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>1495105536</repositoryEntryKey> + <repositoryEntryDisplayname>Curriculum calendar</repositoryEntryDisplayname> + <repositoryEntryDescription><p>This is a course in a curriculum with calender</p></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>10</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>1496940544</repositoryEntryKey> + <repositoryEntryDisplayname>Course curriculum Reï</repositoryEntryDisplayname> + <repositoryEntryDescription></repositoryEntryDescription> + <repositoryEntryInitialAuthor>rei</repositoryEntryInitialAuthor> + <curriculumElementKey>10</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>1603698688</repositoryEntryKey> + <repositoryEntryDisplayname>Optional Tasks</repositoryEntryDisplayname> + <repositoryEntryDescription></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>10</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>1495105536</repositoryEntryKey> + <repositoryEntryDisplayname>Curriculum calendar</repositoryEntryDisplayname> + <repositoryEntryDescription><p>This is a course in a curriculum with calender</p></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>27</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>1495105536</repositoryEntryKey> + <repositoryEntryDisplayname>Curriculum calendar</repositoryEntryDisplayname> + <repositoryEntryDescription><p>This is a course in a curriculum with calender</p></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>26</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>330956800</repositoryEntryKey> + <repositoryEntryDisplayname>Assessment mode</repositoryEntryDisplayname> + <repositoryEntryDescription></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>4</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + <repositoryEntryKey>977698816</repositoryEntryKey> + <repositoryEntryDisplayname>Participants folders</repositoryEntryDisplayname> + <repositoryEntryDescription></repositoryEntryDescription> + <repositoryEntryInitialAuthor>kanu</repositoryEntryInitialAuthor> + <curriculumElementKey>4</curriculumElementKey> + </org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRef> + </entryRefs> +</org.olat.modules.curriculum.model.CurriculumElementToRepositoryEntryRefs> \ No newline at end of file diff --git a/src/test/java/org/olat/selenium/ImsQTI21EditorTest.java b/src/test/java/org/olat/selenium/ImsQTI21EditorTest.java index 3def4cd2ca5af86e21893446edcf5afd93ed3bd7..92c8f3ee8f5bf61cb92b9abe6e05e5b032314781 100644 --- a/src/test/java/org/olat/selenium/ImsQTI21EditorTest.java +++ b/src/test/java/org/olat/selenium/ImsQTI21EditorTest.java @@ -2503,6 +2503,7 @@ public class ImsQTI21EditorTest extends Deployments { // make the test QTI21Page .getQTI21Page(participantBrowser) + .assertOnAssessmentItem() .answerMatchDropSourceToTarget("Einstein", "Physicist") .answerMatchDropSourceToTarget("Planck", "Physicist") .answerMatchDropSourceToTarget("Euler", "Mathematician") @@ -2694,6 +2695,7 @@ public class ImsQTI21EditorTest extends Deployments { // make the test QTI21Page .getQTI21Page(participantBrowser) + .assertOnAssessmentItem() .saveAnswer() .assertFeedback("Correct feedback") .nextAnswer() diff --git a/src/test/java/org/olat/selenium/ImsQTI21InteractionsTest.java b/src/test/java/org/olat/selenium/ImsQTI21InteractionsTest.java index 75cbefc3e76f1093d72052084cb155d8a0f65c37..e633ce745064452dd438392e95298c19daf92183 100644 --- a/src/test/java/org/olat/selenium/ImsQTI21InteractionsTest.java +++ b/src/test/java/org/olat/selenium/ImsQTI21InteractionsTest.java @@ -666,8 +666,8 @@ public class ImsQTI21InteractionsTest extends Deployments { .clickToolbarRootCrumb(); QTI21Page qtiPage = QTI21Page - .getQTI21Page(browser) - .assertOnAssessmentItem(); + .getQTI21Page(browser) + .assertOnAssessmentItem(); qtiPage .settings() .options() @@ -715,8 +715,8 @@ public class ImsQTI21InteractionsTest extends Deployments { .clickToolbarRootCrumb(); QTI21Page qtiPage = QTI21Page - .getQTI21Page(browser) - .assertOnAssessmentItem(); + .getQTI21Page(browser) + .assertOnAssessmentItem(); qtiPage .settings() .options() @@ -764,8 +764,8 @@ public class ImsQTI21InteractionsTest extends Deployments { .clickToolbarRootCrumb(); QTI21Page qtiPage = QTI21Page - .getQTI21Page(browser) - .assertOnAssessmentItem(); + .getQTI21Page(browser) + .assertOnAssessmentItem(); qtiPage .settings() .options() diff --git a/src/test/java/org/olat/selenium/ImsQTI21Test.java b/src/test/java/org/olat/selenium/ImsQTI21Test.java index 9f3d03563ff3e349258737478f523dbedce29428..1c5213922b1df74bdd419078b0892de5a844614c 100644 --- a/src/test/java/org/olat/selenium/ImsQTI21Test.java +++ b/src/test/java/org/olat/selenium/ImsQTI21Test.java @@ -189,12 +189,12 @@ public class ImsQTI21Test extends Deployments { NavigationPage navBar = NavigationPage.load(browser); navBar .openAuthoringEnvironment() - .uploadResource(qtiTestTitle, qtiTestFile); + .uploadResource(qtiTestTitle, qtiTestFile) + .clickToolbarRootCrumb(); QTI21Page qtiPage = QTI21Page .getQTI21Page(browser); qtiPage - .clickToolbarBack() .settings() .options() .showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions()) @@ -244,12 +244,12 @@ public class ImsQTI21Test extends Deployments { NavigationPage navBar = NavigationPage.load(browser); navBar .openAuthoringEnvironment() - .uploadResource(qtiTestTitle, qtiTestFile); + .uploadResource(qtiTestTitle, qtiTestFile) + .clickToolbarRootCrumb(); QTI21Page qtiPage = QTI21Page .getQTI21Page(browser); qtiPage - .clickToolbarBack() .settings() .options() .showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions()) @@ -603,6 +603,7 @@ public class ImsQTI21Test extends Deployments { QTI21Page qtiPage = QTI21Page .getQTI21Page(browser); qtiPage + .assertOnStart() .start() .answerSingleChoiceWithParagraph("Right") .saveAnswer() @@ -691,6 +692,7 @@ public class ImsQTI21Test extends Deployments { QTI21Page qtiPage = QTI21Page .getQTI21Page(browser); qtiPage + .assertOnStart() .start() .answerSingleChoiceWithParagraph("Right") .saveAnswer() @@ -788,6 +790,7 @@ public class ImsQTI21Test extends Deployments { QTI21Page qtiPage = QTI21Page .getQTI21Page(browser); qtiPage + .assertOnStart() .start() .answerSingleChoiceWithParagraph("Correct") .saveAnswer() @@ -806,6 +809,7 @@ public class ImsQTI21Test extends Deployments { qtiPage = QTI21Page .getQTI21Page(browser); qtiPage + .assertOnStart() .start() .assertOnAssessmentItem("Kprim") .answerCorrectKPrim("True", "Right") @@ -921,6 +925,7 @@ public class ImsQTI21Test extends Deployments { QTI21Page qtiPage = QTI21Page .getQTI21Page(participantBrowser); qtiPage + .assertOnStart() .start() .assertOnAssessmentItem() .answerSingleChoiceWithParagraph("Correct response") @@ -1042,6 +1047,7 @@ public class ImsQTI21Test extends Deployments { QTI21Page qtiPage = QTI21Page .getQTI21Page(participantBrowser); qtiPage + .assertOnStart() .start() .assertOnAssessmentItem() .answerSingleChoiceWithParagraph("Correct answer") @@ -1182,6 +1188,7 @@ public class ImsQTI21Test extends Deployments { QTI21Page qtiPage = QTI21Page .getQTI21Page(browser); qtiPage + .assertOnStart() .start() .answerSingleChoiceWithParagraph("Right") .saveAnswer() diff --git a/src/test/java/org/olat/selenium/QuestionPoolTest.java b/src/test/java/org/olat/selenium/QuestionPoolTest.java index c319dae75196febeabc287fe69200f7336d99d07..7308baef78400d9252ffa3d8fd286cbb8d00c08f 100644 --- a/src/test/java/org/olat/selenium/QuestionPoolTest.java +++ b/src/test/java/org/olat/selenium/QuestionPoolTest.java @@ -120,6 +120,7 @@ public class QuestionPoolTest extends Deployments { administration .openTaxonomy() .selectTaxonomy("QPOOL") + .assertOnMetadata() .selectTaxonomyTree() .atLeastOneLevel("at-least-one", "At least one") .selectTaxonomyLevel("at-least-one") diff --git a/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java b/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java index d3ef98e91cec85322d5e1d53e2aef77b9a8ff70e..05a615b6572fc7bf87683b0ee6f2eca24c7a743b 100644 --- a/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java +++ b/src/test/java/org/olat/selenium/page/course/CourseEditorPageFragment.java @@ -201,8 +201,20 @@ public class CourseEditorPageFragment { By nodeBy = By.xpath("//div[@id='o_course_editor_choose_nodetype']//a[contains(@class,'o_sel_course_editor_node-" + nodeAlias + "')]"); OOGraphene.moveAndClick(nodeBy, browser); - OOGraphene.waitBusy(browser); OOGraphene.waitModalDialogDisappears(browser); + return assertOnNodeTitle(); + } + + /** + * Wait until the short title and description field are + * there. + * + * @return Itself + */ + public CourseEditorPageFragment assertOnNodeTitle() { + By shortTitleBy = By.className("o_sel_node_editor_shorttitle"); + OOGraphene.waitElement(shortTitleBy, browser); + OOGraphene.waitTinymce(browser); return this; } @@ -214,8 +226,9 @@ public class CourseEditorPageFragment { * @return Itself */ public CourseEditorPageFragment nodeTitle(String title) { + assertOnNodeTitle(); + By shortTitleBy = By.cssSelector("div.o_sel_node_editor_shorttitle input[type='text']"); - OOGraphene.waitElement(shortTitleBy, browser); WebElement shortTitleEl = browser.findElement(shortTitleBy); shortTitleEl.clear(); shortTitleEl.sendKeys(title); diff --git a/src/test/java/org/olat/selenium/page/course/RemindersPage.java b/src/test/java/org/olat/selenium/page/course/RemindersPage.java index 0a1a98588e5731efaedb1d0dd536787282b3ac9a..977bcc4e1f646b6332e27bba953bdccdaa9124fb 100644 --- a/src/test/java/org/olat/selenium/page/course/RemindersPage.java +++ b/src/test/java/org/olat/selenium/page/course/RemindersPage.java @@ -71,9 +71,8 @@ public class RemindersPage { */ public RemindersPage openActionMenu(String title) { By rowBy = By.xpath("//fieldset[contains(@class,'o_sel_course_reminder_list')]//table//tr[//td//a[contains(text(), '" + title + "')]]//td//a[contains(@class,'o_sel_course_reminder_tools')]"); - List<WebElement> reminderListEls = browser.findElements(rowBy); - Assert.assertEquals(1, reminderListEls.size()); - reminderListEls.get(0).click(); + OOGraphene.waitElement(rowBy, browser); + browser.findElement(rowBy).click(); OOGraphene.waitBusy(browser); return this; } diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java index d31a89fda3aa44c8f998cb62b65cd2a2d1518cdf..04d8a29654a75f2de9331e3f2f65a65b51069ead 100644 --- a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java +++ b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java @@ -50,6 +50,13 @@ public class QTI21Page { this.browser = browser; } + /** + * Get only the page. You need to assert on start or assessment item + * to make it reliable. + * + * @param browser The browser + * @return The QTI 2.1 page + */ public static QTI21Page getQTI21Page(WebDriver browser) { By mainBy = By.id("o_main_wrapper"); OOGraphene.waitElement(mainBy, browser); @@ -64,8 +71,8 @@ public class QTI21Page { public QTI21Page start() { By startBy = By.cssSelector("a.o_sel_start_qti21assessment"); - WebElement startButton = browser.findElement(startBy); - startButton.click(); + OOGraphene.waitElement(startBy, browser); + browser.findElement(startBy).click(); OOGraphene.waitBusy(browser); By mainBy = By.cssSelector("div.qtiworks.o_assessmenttest"); OOGraphene.waitElement(mainBy, browser); @@ -82,6 +89,7 @@ public class QTI21Page { public QTI21Page startTestPart() { By startBy = By.xpath("//button[contains(@onclick,'advanceTestPart')]"); + OOGraphene.waitElement(startBy, browser); browser.findElement(startBy).click(); OOGraphene.waitBusy(browser); By menuBy = By.id("o_qti_menu"); @@ -960,6 +968,8 @@ public class QTI21Page { } public QTI21SettingsPage settings() { + By toolsLinkBy = By.cssSelector("ul.o_tools li.o_tool_dropdown a.o_sel_repository_tools"); + OOGraphene.waitElement(toolsLinkBy, browser); if(!browser.findElement(toolsMenu).isDisplayed()) { openToolsMenu(); } diff --git a/src/test/java/org/olat/selenium/page/repository/RepositorySettingsPage.java b/src/test/java/org/olat/selenium/page/repository/RepositorySettingsPage.java index d1c0e2b64c599f8c74785b3f52bc006b5b886734..d81d78c30f884934c44f7683a09afa6e7351bf4a 100644 --- a/src/test/java/org/olat/selenium/page/repository/RepositorySettingsPage.java +++ b/src/test/java/org/olat/selenium/page/repository/RepositorySettingsPage.java @@ -40,6 +40,7 @@ public class RepositorySettingsPage { public RepositoryEditDescriptionPage assertOnInfos() { By infosBy = By.cssSelector("fieldset.o_sel_edit_repositoryentry"); OOGraphene.waitElement(infosBy, browser); + OOGraphene.waitTinymce(browser); return new RepositoryEditDescriptionPage(browser); } diff --git a/src/test/java/org/olat/selenium/page/taxonomy/TaxonomyAdminPage.java b/src/test/java/org/olat/selenium/page/taxonomy/TaxonomyAdminPage.java index c1988376ec1fae35f32d63555914d497067287f0..3f34285b5011a1e9f87c0575558141bb296d841e 100644 --- a/src/test/java/org/olat/selenium/page/taxonomy/TaxonomyAdminPage.java +++ b/src/test/java/org/olat/selenium/page/taxonomy/TaxonomyAdminPage.java @@ -45,7 +45,6 @@ public class TaxonomyAdminPage { public TaxonomyPage selectTaxonomy(String identifier) { OOGraphene.scrollTop(browser);//scroll top if the settings were set - OOGraphene.waitingALittleBit(); By selectBy = By.xpath("//div[@class='o_taxonomy_row'][div/div/h4/small[text()[contains(.,'" + identifier + "')]]]/div/div[@class='panel-body']/div[@class='pull-right']/a"); OOGraphene.waitElement(selectBy, browser); diff --git a/src/test/java/org/olat/selenium/page/taxonomy/TaxonomyPage.java b/src/test/java/org/olat/selenium/page/taxonomy/TaxonomyPage.java index e941f3f36c1ca00944edbbfa538efee60d79d56c..bd0371e2999820f572d8f92096c1546fe122b650 100644 --- a/src/test/java/org/olat/selenium/page/taxonomy/TaxonomyPage.java +++ b/src/test/java/org/olat/selenium/page/taxonomy/TaxonomyPage.java @@ -37,6 +37,18 @@ public class TaxonomyPage { this.browser = browser; } + /** + * Assert on the edit page of the taxonomy. + * + * @return Itsefl + */ + public TaxonomyPage assertOnMetadata() { + By selectLevelsBy = By.cssSelector(".o_sel_taxonomy_form"); + OOGraphene.waitElement(selectLevelsBy, browser); + OOGraphene.waitTinymce(browser); + return this; + } + /** * Select the tab to manage the taxonomy levels. *