From 38927ed278e729a43e4e15d477359dc797c2a79d Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Fri, 11 May 2018 15:26:51 +0200 Subject: [PATCH] OO-3290: implement curriculum element types UI --- .../modules/curriculum/CurriculumElement.java | 14 + .../CurriculumElementManagedFlag.java | 2 + .../curriculum/CurriculumElementType.java | 2 + .../CurriculumElementTypeManagedFlag.java | 141 ++++++++ .../modules/curriculum/CurriculumModule.java | 2 + .../modules/curriculum/CurriculumService.java | 28 +- .../manager/CurriculumElementDAO.java | 94 ++++- .../manager/CurriculumServiceImpl.java | 43 ++- .../model/CurriculumElementImpl.java | 24 ++ .../model/CurriculumElementTypeImpl.java | 11 + .../model/CurriculumElementTypeRefImpl.java | 40 +++ ...urriculumAdminConfigurationController.java | 101 ++++++ .../ui/CurriculumAdminController.java | 111 +++--- .../ui/CurriculumComposerController.java | 4 +- .../ui/CurriculumElementTypeRow.java | 65 ++++ .../CurriculumElementTypesEditController.java | 326 ++++++++++++++++++ .../ui/CurriculumElementTypesTableModel.java | 98 ++++++ ...lumElementTypesTableModelSortDelegate.java | 38 ++ .../ui/EditCurriculumElementController.java | 118 ++++++- ...itCurriculumElementOverviewController.java | 2 +- .../EditCurriculumElementTypeController.java | 164 +++++++++ .../curriculum/ui/_content/admin_types.html | 6 + .../ui/_content/curriculum_admin.html | 7 + .../ui/_i18n/LocalStrings_de.properties | 28 +- .../ui/_i18n/LocalStrings_en.properties | 27 +- .../database/mysql/alter_12_4_x_to_13_0_0.sql | 1 + .../database/mysql/setupDatabase.sql | 3 +- .../oracle/alter_12_4_x_to_13_0_0.sql | 1 + .../database/oracle/setupDatabase.sql | 1 + .../postgresql/alter_12_4_x_to_13_0_0.sql | 1 + .../database/postgresql/setupDatabase.sql | 1 + .../manager/CurriculumElementDAOTest.java | 124 ++++++- ...riculumRepositoryEntryRelationDAOTest.java | 6 +- 33 files changed, 1556 insertions(+), 78 deletions(-) create mode 100644 src/main/java/org/olat/modules/curriculum/CurriculumElementTypeManagedFlag.java create mode 100644 src/main/java/org/olat/modules/curriculum/model/CurriculumElementTypeRefImpl.java create mode 100644 src/main/java/org/olat/modules/curriculum/ui/CurriculumAdminConfigurationController.java create mode 100644 src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypeRow.java create mode 100644 src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesEditController.java create mode 100644 src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesTableModel.java create mode 100644 src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesTableModelSortDelegate.java create mode 100644 src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementTypeController.java create mode 100644 src/main/java/org/olat/modules/curriculum/ui/_content/admin_types.html create mode 100644 src/main/java/org/olat/modules/curriculum/ui/_content/curriculum_admin.html diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumElement.java b/src/main/java/org/olat/modules/curriculum/CurriculumElement.java index d0240145093..b42d71e8cab 100644 --- a/src/main/java/org/olat/modules/curriculum/CurriculumElement.java +++ b/src/main/java/org/olat/modules/curriculum/CurriculumElement.java @@ -19,6 +19,8 @@ */ package org.olat.modules.curriculum; +import java.util.Date; + import org.olat.basesecurity.Group; import org.olat.core.id.CreateInfo; import org.olat.core.id.ModifiedInfo; @@ -47,6 +49,16 @@ public interface CurriculumElement extends CurriculumElementRef, CreateInfo, Mod public void setExternalId(String externalId); + public Date getBeginDate(); + + public void setBeginDate(Date date); + + public Date getEndDate(); + + public void setEndDate(Date date); + + public String getMaterializedPathKeys(); + public CurriculumElementManagedFlag[] getManagedFlags(); public void setManagedFlags(CurriculumElementManagedFlag[] flags); @@ -57,6 +69,8 @@ public interface CurriculumElement extends CurriculumElementRef, CreateInfo, Mod public CurriculumElementType getType(); + public void setType(CurriculumElementType type); + public Group getGroup(); diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumElementManagedFlag.java b/src/main/java/org/olat/modules/curriculum/CurriculumElementManagedFlag.java index 9643f95a29f..3ebbcf956fc 100644 --- a/src/main/java/org/olat/modules/curriculum/CurriculumElementManagedFlag.java +++ b/src/main/java/org/olat/modules/curriculum/CurriculumElementManagedFlag.java @@ -39,6 +39,8 @@ public enum CurriculumElementManagedFlag { displayName(all), description(all), externalId(all), + dates(all), + type(all), members(all), move(all), addChildren(all), diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumElementType.java b/src/main/java/org/olat/modules/curriculum/CurriculumElementType.java index 81eb55a87c1..2bf1f3a9021 100644 --- a/src/main/java/org/olat/modules/curriculum/CurriculumElementType.java +++ b/src/main/java/org/olat/modules/curriculum/CurriculumElementType.java @@ -48,6 +48,8 @@ public interface CurriculumElementType extends CurriculumElementTypeRef, CreateI public void setExternalId(String externalId); + public CurriculumElementTypeManagedFlag[] getManagedFlags(); + public Set<CurriculumElementTypeToType> getAllowedSubTypes(); } diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumElementTypeManagedFlag.java b/src/main/java/org/olat/modules/curriculum/CurriculumElementTypeManagedFlag.java new file mode 100644 index 00000000000..49e36f5ab47 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/CurriculumElementTypeManagedFlag.java @@ -0,0 +1,141 @@ +/** + * <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; + +import java.util.Arrays; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; + +/** + * + * Initial date: 11 mai 2018<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public enum CurriculumElementTypeManagedFlag { + + all, + identifier(all), + displayName(all), + description(all), + externalId(all), + subTypes(all), + copy(all), + delete(all); + + private CurriculumElementTypeManagedFlag[] parents; + private static final OLog log = Tracing.createLoggerFor(CurriculumElementTypeManagedFlag.class); + public static final CurriculumElementTypeManagedFlag[] EMPTY_ARRAY = new CurriculumElementTypeManagedFlag[0]; + + private static CurriculumModule curriculumModule; + + private CurriculumElementTypeManagedFlag() { + // + } + + private CurriculumElementTypeManagedFlag(CurriculumElementTypeManagedFlag... parents) { + if(parents == null) { + this.parents = new CurriculumElementTypeManagedFlag[0]; + } else { + this.parents = parents; + } + } + + public static CurriculumElementTypeManagedFlag[] toEnum(String flags) { + if(StringHelper.containsNonWhitespace(flags)) { + String[] flagArr = flags.split(","); + CurriculumElementTypeManagedFlag[] flagEnums = new CurriculumElementTypeManagedFlag[flagArr.length]; + + int count = 0; + for(String flag:flagArr) { + if(StringHelper.containsNonWhitespace(flag)) { + try { + CurriculumElementTypeManagedFlag flagEnum = valueOf(flag); + flagEnums[count++] = flagEnum; + } catch (Exception e) { + log.warn("Cannot parse this managed flag: " + flag, e); + } + } + } + + if(count != flagEnums.length) { + flagEnums = Arrays.copyOf(flagEnums, count); + } + return flagEnums; + } + return EMPTY_ARRAY; + } + + public static String toString(CurriculumElementTypeManagedFlag... flags) { + StringBuilder sb = new StringBuilder(); + if(flags != null && flags.length > 0 && flags[0] != null) { + for(CurriculumElementTypeManagedFlag flag:flags) { + if(flag != null) { + if(sb.length() > 0) sb.append(","); + sb.append(flag.name()); + } + } + } + return sb.length() == 0 ? null : sb.toString(); + } + + public static boolean isManaged(CurriculumElementType elementType, CurriculumElementTypeManagedFlag marker) { + if(curriculumModule == null) { + curriculumModule = CoreSpringFactory.getImpl(CurriculumModule.class); + } + if(!curriculumModule.isCurriculumManaged()) { + return false; + } + return (elementType != null && (contains(elementType, marker) || contains(elementType, marker.parents))); + } + + public static boolean isManaged(CurriculumElementTypeManagedFlag[] flags, CurriculumElementTypeManagedFlag marker) { + if(curriculumModule == null) { + curriculumModule = CoreSpringFactory.getImpl(CurriculumModule.class); + } + if(!curriculumModule.isCurriculumManaged()) { + return false; + } + + return (flags != null && (contains(flags, marker) || contains(flags, marker.parents))); + } + + private static boolean contains(CurriculumElementType elementType, CurriculumElementTypeManagedFlag... markers) { + if(elementType == null) return false; + CurriculumElementTypeManagedFlag[] flags = elementType.getManagedFlags(); + return contains(flags, markers); + } + + private static boolean contains(CurriculumElementTypeManagedFlag[] flags, CurriculumElementTypeManagedFlag... markers) { + if(flags == null || flags.length == 0) return false; + + for(CurriculumElementTypeManagedFlag flag:flags) { + for(CurriculumElementTypeManagedFlag marker:markers) { + if(flag.equals(marker)) { + return true; + } + } + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumModule.java b/src/main/java/org/olat/modules/curriculum/CurriculumModule.java index 609a1152493..a0471033249 100644 --- a/src/main/java/org/olat/modules/curriculum/CurriculumModule.java +++ b/src/main/java/org/olat/modules/curriculum/CurriculumModule.java @@ -83,6 +83,7 @@ public class CurriculumModule extends AbstractSpringModule implements ConfigOnOf public void setEnabled(boolean enabled) { this.enabled = enabled; + setStringProperty(CURRICULUM_ENABLED, Boolean.toString(enabled), true); } public boolean isCurriculumManaged() { @@ -95,6 +96,7 @@ public class CurriculumModule extends AbstractSpringModule implements ConfigOnOf public void setCurriculumInMyCourses(boolean curriculumInMyCourses) { this.curriculumInMyCourses = curriculumInMyCourses; + setStringProperty(CURRICULUM_IN_MY_COURSES_ENABLED, Boolean.toString(curriculumInMyCourses), true); } diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumService.java b/src/main/java/org/olat/modules/curriculum/CurriculumService.java index 6e600edadf5..a71b1cd7d6e 100644 --- a/src/main/java/org/olat/modules/curriculum/CurriculumService.java +++ b/src/main/java/org/olat/modules/curriculum/CurriculumService.java @@ -19,6 +19,7 @@ */ package org.olat.modules.curriculum; +import java.util.Date; import java.util.List; import org.olat.basesecurity.IdentityRef; @@ -60,10 +61,25 @@ public interface CurriculumService { */ public List<CurriculumElementType> getCurriculumElementTypes(); + /** + * Load the curriculum element type with the specified primary key. + * + * @param ref The reference of the type + * @return A curriculum element type + */ + public CurriculumElementType getCurriculumElementType(CurriculumElementTypeRef typeRef); + + public CurriculumElementType createCurriculumElementType(String identifier, String displayName, String description, String externalId); + + public CurriculumElementType updateCurriculumElementType(CurriculumElementType elementType, List<CurriculumElementType> allowedSubTypes); + + public CurriculumElementType cloneCurriculumElementType(CurriculumElementTypeRef typeRef); + public boolean deleteCurriculumElementType(CurriculumElementTypeRef typeRef); - public CurriculumElement createCurriculumElement(String identifier, String displayName, - CurriculumElementRef parent, Curriculum curriculum); + + public CurriculumElement createCurriculumElement(String identifier, String displayName, Date beginDate, Date endDate, + CurriculumElementRef parent, CurriculumElementType elementType, Curriculum curriculum); public CurriculumElement getCurriculumElement(CurriculumElementRef element); @@ -74,6 +90,14 @@ public interface CurriculumService { * @return A list of curriculum elements */ public List<CurriculumElement> getCurriculumElements(CurriculumRef element); + + /** + * Return the parent line of the specified curriculum element. + * + * @param element A curriculum element + * @return A list of curriculum elements + */ + public List<CurriculumElement> getCurriculumElementParentLine(CurriculumElement element); public CurriculumElement updateCurriculumElement(CurriculumElement element); diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java index 6c96cb3f1e7..328ebc6fe75 100644 --- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java +++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java @@ -20,6 +20,8 @@ package org.olat.modules.curriculum.manager; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.List; @@ -31,6 +33,7 @@ import org.olat.core.util.StringHelper; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementRef; +import org.olat.modules.curriculum.CurriculumElementType; import org.olat.modules.curriculum.CurriculumRef; import org.olat.modules.curriculum.model.CurriculumElementImpl; import org.olat.modules.curriculum.model.CurriculumElementMember; @@ -51,22 +54,26 @@ public class CurriculumElementDAO { @Autowired private GroupDAO groupDao; - public CurriculumElement createCurriculumElement(String identifier, String displayName, CurriculumElementRef parentRef, Curriculum curriculum) { + public CurriculumElement createCurriculumElement(String identifier, String displayName, Date beginDate, Date endDate, + CurriculumElementRef parentRef, CurriculumElementType elementType, Curriculum curriculum) { CurriculumElementImpl element = new CurriculumElementImpl(); element.setCreationDate(new Date()); element.setLastModified(element.getCreationDate()); element.setIdentifier(identifier); element.setDisplayName(displayName); + element.setBeginDate(beginDate); + element.setEndDate(endDate); element.setCurriculum(curriculum); + element.setType(elementType); element.setGroup(groupDao.createGroup()); CurriculumElement parent = parentRef == null ? null : loadByKey(parentRef.getKey()); element.setParent(parent); dbInstance.getCurrentEntityManager().persist(element); - if(parent != null) { ((CurriculumElementImpl)parent).getChildren().add(element); dbInstance.getCurrentEntityManager().merge(parent); } + element.setMaterializedPathKeys(getMaterializedPathKeys(parent, element)); return element; } @@ -84,23 +91,50 @@ public class CurriculumElementDAO { return elements == null || elements.isEmpty() ? null : elements.get(0); } + public String getMaterializedPathKeys(CurriculumElement parent, CurriculumElement element) { + if(parent != null) { + String parentPathOfKeys = parent.getMaterializedPathKeys(); + if(parentPathOfKeys == null || "/".equals(parentPathOfKeys)) { + parentPathOfKeys = ""; + } + return parentPathOfKeys + element.getKey() + "/"; + } + return "/" + element.getKey() + "/"; + } + public CurriculumElement update(CurriculumElement element) { ((CurriculumElementImpl)element).setLastModified(new Date()); + ((CurriculumElementImpl)element).setMaterializedPathKeys(getMaterializedPathKeys(element.getParent(), element)); return dbInstance.getCurrentEntityManager().merge(element); } public CurriculumElement move(CurriculumElement element, CurriculumElement newParentElement) { - CurriculumElement parentLevel = element.getParent(); - if(parentLevel == null && newParentElement == null) { + CurriculumElement parentElement = element.getParent(); + if(parentElement == null && newParentElement == null) { return element;//already root - } else if(parentLevel != null && parentLevel.equals(newParentElement)) { + } else if(parentElement != null && parentElement.equals(newParentElement)) { return element;//same parent } + String keysPath = element.getMaterializedPathKeys(); + + List<CurriculumElement> descendants = getDescendants(element); CurriculumElementImpl elementImpl = (CurriculumElementImpl)element; elementImpl.setParent(newParentElement); elementImpl.setLastModified(new Date()); + String newKeysPath = getMaterializedPathKeys(newParentElement, elementImpl); + elementImpl.setMaterializedPathKeys(newKeysPath); elementImpl = dbInstance.getCurrentEntityManager().merge(elementImpl); + + for(CurriculumElement descendant:descendants) { + String descendantKeysPath = descendant.getMaterializedPathKeys(); + if(descendantKeysPath.indexOf(keysPath) == 0) { + String end = descendantKeysPath.substring(keysPath.length(), descendantKeysPath.length()); + String updatedPath = newKeysPath + end; + ((CurriculumElementImpl)descendant).setMaterializedPathKeys(updatedPath); + } + dbInstance.getCurrentEntityManager().merge(descendant); + } dbInstance.commit(); return elementImpl; } @@ -119,6 +153,44 @@ public class CurriculumElementDAO { .getResultList(); } + public List<CurriculumElement> getParentLine(CurriculumElement curriculumElement) { + StringBuilder sb = new StringBuilder(384); + sb.append("select el from curriculumelement as el") + .append(" inner join el.curriculum as curriculum") + .append(" inner join el.group as baseGroup") + .append(" left join fetch el.parent as parent") + .append(" left join fetch el.type as type") + .append(" where curriculum.key=:curriculumKey and locate(el.materializedPathKeys,:materializedPath) = 1"); + + List<CurriculumElement> elements = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), CurriculumElement.class) + .setParameter("curriculumKey", curriculumElement.getCurriculum().getKey()) + .setParameter("materializedPath", curriculumElement.getMaterializedPathKeys() + "%") + .getResultList(); + Collections.sort(elements, new PathMaterializedPathLengthComparator()); + return elements; + } + + public List<CurriculumElement> getDescendants(CurriculumElement curriculumElement) { + StringBuilder sb = new StringBuilder(384); + sb.append("select el from curriculumelement as el") + .append(" inner join el.curriculum as curriculum") + .append(" inner join el.group as baseGroup") + .append(" left join fetch el.parent as parent") + .append(" left join fetch el.type as type") + .append(" where el.curriculum.key=:curriculumKey") + .append(" and el.key!=:elementKey and el.materializedPathKeys like :materializedPath"); + + List<CurriculumElement> elements = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), CurriculumElement.class) + .setParameter("materializedPath", curriculumElement.getMaterializedPathKeys() + "%") + .setParameter("elementKey", curriculumElement.getKey()) + .setParameter("curriculumKey", curriculumElement.getCurriculum().getKey()) + .getResultList(); + Collections.sort(elements, new PathMaterializedPathLengthComparator()); + return elements; + } + public List<CurriculumElementMember> getMembers(CurriculumElementRef element) { StringBuilder sb = new StringBuilder(256); sb.append("select ident, membership.role, membership.inheritanceModeString from curriculumelement el") @@ -143,4 +215,16 @@ public class CurriculumElementDAO { } return members; } + + private static class PathMaterializedPathLengthComparator implements Comparator<CurriculumElement> { + @Override + public int compare(CurriculumElement c1, CurriculumElement c2) { + String s1 = c1.getMaterializedPathKeys(); + String s2 = c2.getMaterializedPathKeys(); + + int len1 = s1 == null ? 0 : s1.length(); + int len2 = s2 == null ? 0 : s2.length(); + return len1 - len2; + } + } } 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 84d364b3fa7..d1547759830 100644 --- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java +++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java @@ -19,6 +19,7 @@ */ package org.olat.modules.curriculum.manager; +import java.util.Date; import java.util.List; import org.olat.basesecurity.GroupMembershipInheritance; @@ -30,6 +31,7 @@ import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementRef; import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeRef; import org.olat.modules.curriculum.CurriculumRef; import org.olat.modules.curriculum.CurriculumRoles; import org.olat.modules.curriculum.CurriculumService; @@ -62,6 +64,8 @@ public class CurriculumServiceImpl implements CurriculumService { @Autowired private CurriculumElementTypeDAO curriculumElementTypeDao; @Autowired + private CurriculumElementTypeToTypeDAO curriculumElementTypeToTypeDao; + @Autowired private RepositoryEntryRelationDAO repositoryEntryRelationDao; @Autowired private CurriculumRepositoryEntryRelationDAO curriculumRepositoryEntryRelationDao; @@ -86,15 +90,43 @@ public class CurriculumServiceImpl implements CurriculumService { return curriculumElementTypeDao.load(); } + @Override + public CurriculumElementType getCurriculumElementType(CurriculumElementTypeRef typeRef) { + return curriculumElementTypeDao.loadByKey(typeRef.getKey()); + } + + @Override + public CurriculumElementType createCurriculumElementType(String identifier, String displayName, + String description, String externalId) { + return curriculumElementTypeDao.createCurriculumElementType(identifier, displayName, description, externalId); + } + + @Override + public CurriculumElementType updateCurriculumElementType(CurriculumElementType elementType, List<CurriculumElementType> allowedSubTypes) { + curriculumElementTypeToTypeDao.setAllowedSubType(elementType, allowedSubTypes); + return curriculumElementTypeDao.update(elementType); + } + + @Override + public CurriculumElementType cloneCurriculumElementType(CurriculumElementTypeRef typeRef) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean deleteCurriculumElementType(CurriculumElementTypeRef typeRef) { + return false; + } + @Override public List<Curriculum> getCurriculums(CurriculumSearchParameters params) { return curriculumDao.search(params); } @Override - public CurriculumElement createCurriculumElement(String identifier, String displayName, - CurriculumElementRef parentRef, Curriculum curriculum) { - return curriculumElementDao.createCurriculumElement(identifier, displayName, parentRef, curriculum); + public CurriculumElement createCurriculumElement(String identifier, String displayName, Date beginDate, Date endDate, + CurriculumElementRef parentRef, CurriculumElementType elementType, Curriculum curriculum) { + return curriculumElementDao.createCurriculumElement(identifier, displayName, beginDate, endDate, parentRef, elementType, curriculum); } @Override @@ -117,6 +149,11 @@ public class CurriculumServiceImpl implements CurriculumService { return curriculumElementDao.loadElements(curriculum); } + @Override + public List<CurriculumElement> getCurriculumElementParentLine(CurriculumElement element) { + return curriculumElementDao.getParentLine(element); + } + @Override public List<CurriculumElementMember> getMembers(CurriculumElement element) { return curriculumElementDao.getMembers(element); diff --git a/src/main/java/org/olat/modules/curriculum/model/CurriculumElementImpl.java b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementImpl.java index c57a7e1317b..2c363cde059 100644 --- a/src/main/java/org/olat/modules/curriculum/model/CurriculumElementImpl.java +++ b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementImpl.java @@ -91,6 +91,9 @@ public class CurriculumElementImpl implements CurriculumElement, Persistable { @Column(name="c_managed_flags", nullable=true, insertable=true, updatable=true) private String managedFlagsString; + @Column(name="c_m_path_keys", nullable=true, insertable=true, updatable=true) + private String materializedPathKeys; + @ManyToOne(targetEntity=GroupImpl.class,fetch=FetchType.LAZY,optional=false) @JoinColumn(name="fk_group", nullable=false, insertable=true, updatable=false) private Group group; @@ -140,26 +143,32 @@ public class CurriculumElementImpl implements CurriculumElement, Persistable { this.lastModified = lastModified; } + @Override public String getIdentifier() { return identifier; } + @Override public void setIdentifier(String identifier) { this.identifier = identifier; } + @Override public String getDisplayName() { return displayName; } + @Override public void setDisplayName(String displayName) { this.displayName = displayName; } + @Override public String getDescription() { return description; } + @Override public void setDescription(String description) { this.description = description; } @@ -172,18 +181,22 @@ public class CurriculumElementImpl implements CurriculumElement, Persistable { this.status = status; } + @Override public Date getBeginDate() { return beginDate; } + @Override public void setBeginDate(Date beginDate) { this.beginDate = beginDate; } + @Override public Date getEndDate() { return endDate; } + @Override public void setEndDate(Date endDate) { this.endDate = endDate; } @@ -198,6 +211,15 @@ public class CurriculumElementImpl implements CurriculumElement, Persistable { this.externalId = externalId; } + @Override + public String getMaterializedPathKeys() { + return materializedPathKeys; + } + + public void setMaterializedPathKeys(String materializedPathKeys) { + this.materializedPathKeys = materializedPathKeys; + } + public String getManagedFlagsString() { return managedFlagsString; } @@ -216,6 +238,7 @@ public class CurriculumElementImpl implements CurriculumElement, Persistable { managedFlagsString = CurriculumElementManagedFlag.toString(flags); } + @Override public Group getGroup() { return group; } @@ -224,6 +247,7 @@ public class CurriculumElementImpl implements CurriculumElement, Persistable { this.group = group; } + @Override public CurriculumElement getParent() { return parent; } diff --git a/src/main/java/org/olat/modules/curriculum/model/CurriculumElementTypeImpl.java b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementTypeImpl.java index e140bba9c1c..a9dc56fd7d8 100644 --- a/src/main/java/org/olat/modules/curriculum/model/CurriculumElementTypeImpl.java +++ b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementTypeImpl.java @@ -39,6 +39,7 @@ import javax.persistence.TemporalType; import org.olat.core.id.Persistable; import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeManagedFlag; import org.olat.modules.curriculum.CurriculumElementTypeToType; /** @@ -171,6 +172,16 @@ public class CurriculumElementTypeImpl implements Persistable, CurriculumElement this.managedFlagsString = managedFlagsString; } + @Override + public CurriculumElementTypeManagedFlag[] getManagedFlags() { + return CurriculumElementTypeManagedFlag.toEnum(managedFlagsString); + } + + public void setManagedFlagss(CurriculumElementTypeManagedFlag[] flags) { + managedFlagsString = CurriculumElementTypeManagedFlag.toString(flags); + } + + @Override public Set<CurriculumElementTypeToType> getAllowedSubTypes() { return allowedSubTypes; } diff --git a/src/main/java/org/olat/modules/curriculum/model/CurriculumElementTypeRefImpl.java b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementTypeRefImpl.java new file mode 100644 index 00000000000..938b890f2ea --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/model/CurriculumElementTypeRefImpl.java @@ -0,0 +1,40 @@ +package org.olat.modules.curriculum.model; + +import org.olat.modules.curriculum.CurriculumElementTypeRef; + +/** + * + * Initial date: 11 mai 2018<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumElementTypeRefImpl implements CurriculumElementTypeRef { + + private final Long key; + + public CurriculumElementTypeRefImpl(Long key) { + this.key = key; + } + + @Override + public Long getKey() { + return key; + } + + @Override + public int hashCode() { + return getKey() == null ? 78254 : getKey().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof CurriculumElementTypeRefImpl) { + CurriculumElementTypeRefImpl ref = (CurriculumElementTypeRefImpl)obj; + return getKey() != null && getKey().equals(ref.getKey()); + } + return super.equals(obj); + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumAdminConfigurationController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumAdminConfigurationController.java new file mode 100644 index 00000000000..455a551ef79 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumAdminConfigurationController.java @@ -0,0 +1,101 @@ +/** + * <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.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.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.modules.curriculum.CurriculumModule; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 12 févr. 2018<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumAdminConfigurationController extends FormBasicController { + + private static final String[] onKeys = new String[] { "on" }; + + private MultipleSelectionElement enableEl; + private MultipleSelectionElement curriculumMyCoursesEl; + + @Autowired + private CurriculumModule curriculumModule; + + public CurriculumAdminConfigurationController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + initForm(ureq); + update(); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormDescription("admin.description"); + + String[] onValues = new String[] { translate("on") }; + enableEl = uifactory.addCheckboxesHorizontal("curriculum.admin.enabled", formLayout, onKeys, onValues); + enableEl.addActionListener(FormEvent.ONCHANGE); + if(curriculumModule.isEnabled()) { + enableEl.select(onKeys[0], true); + } + + curriculumMyCoursesEl = uifactory.addCheckboxesHorizontal("curriculum.in.my.courses.enabled", formLayout, onKeys, onValues); + curriculumMyCoursesEl.addActionListener(FormEvent.ONCHANGE); + if(curriculumModule.isEnabled()) { + curriculumMyCoursesEl.select(onKeys[0], true); + } + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(enableEl == source) { + curriculumModule.setEnabled(enableEl.isAtLeastSelected(1)); + update(); + fireEvent(ureq, Event.CHANGED_EVENT); + } else if(curriculumMyCoursesEl == source) { + curriculumModule.setCurriculumInMyCourses(curriculumMyCoursesEl.isAtLeastSelected(1)); + } + super.formInnerEvent(ureq, source, event); + } + + private void update() { + boolean enabled = enableEl.isAtLeastSelected(1); + curriculumMyCoursesEl.setVisible(enabled); + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumAdminController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumAdminController.java index 19f3c0e4713..59a99d801ee 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/CurriculumAdminController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumAdminController.java @@ -20,28 +20,36 @@ 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.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.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.segmentedview.SegmentViewComponent; +import org.olat.core.gui.components.segmentedview.SegmentViewEvent; +import org.olat.core.gui.components.segmentedview.SegmentViewFactory; +import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.util.resource.OresHelper; import org.olat.modules.curriculum.CurriculumModule; import org.springframework.beans.factory.annotation.Autowired; /** * - * Initial date: 12 févr. 2018<br> + * Initial date: 11 mai 2018<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class CurriculumAdminController extends FormBasicController { +public class CurriculumAdminController extends BasicController { - private static final String[] onKeys = new String[] { "on" }; + private final Link configurationLink; + private final Link curriculumElementTypeListLink; + private final VelocityContainer mainVC; + private final SegmentViewComponent segmentView; - private MultipleSelectionElement enableEl; - private MultipleSelectionElement curriculumMyCoursesEl; + private CurriculumAdminConfigurationController configurationCtrl; + private CurriculumElementTypesEditController elementTypeListCtrl; @Autowired private CurriculumModule curriculumModule; @@ -49,52 +57,75 @@ public class CurriculumAdminController extends FormBasicController { public CurriculumAdminController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl); - initForm(ureq); - update(); - } - - @Override - protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - setFormTitle("admin.title"); - setFormDescription("admin.description"); + mainVC = createVelocityContainer("curriculum_admin"); - String[] onValues = new String[] { translate("on") }; - enableEl = uifactory.addCheckboxesHorizontal("curriculum.admin.enabled", formLayout, onKeys, onValues); - enableEl.addActionListener(FormEvent.ONCHANGE); + segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this); + segmentView.setDontShowSingleSegment(true); + configurationLink = LinkFactory.createLink("curriculum.configuration", mainVC, this); + segmentView.addSegment(configurationLink, true); + curriculumElementTypeListLink = LinkFactory.createLink("curriculum.element.types", mainVC, this); + doOpenConfiguration(ureq); if(curriculumModule.isEnabled()) { - enableEl.select(onKeys[0], true); + segmentView.addSegment(curriculumElementTypeListLink, false); } - curriculumMyCoursesEl = uifactory.addCheckboxesHorizontal("curriculum.in.my.courses.enabled", formLayout, onKeys, onValues); - curriculumMyCoursesEl.addActionListener(FormEvent.ONCHANGE); - if(curriculumModule.isEnabled()) { - curriculumMyCoursesEl.select(onKeys[0], true); - } + mainVC.put("segmentCmp", configurationCtrl.getInitialComponent()); + putInitialPanel(mainVC); + } @Override protected void doDispose() { // } - + @Override - protected void formOK(UserRequest ureq) { - // + protected void event(UserRequest ureq, Controller source, Event event) { + if(configurationCtrl == source) { + if(event == Event.CHANGED_EVENT) { + segmentView.removeSegment(curriculumElementTypeListLink); + if(curriculumModule.isEnabled()) { + segmentView.addSegment(curriculumElementTypeListLink, false); + } + } + } + super.event(ureq, source, event); } @Override - protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { - if(enableEl == source) { - curriculumModule.setEnabled(enableEl.isAtLeastSelected(1)); - update(); - } else if(curriculumMyCoursesEl == source) { - curriculumModule.setCurriculumInMyCourses(curriculumMyCoursesEl.isAtLeastSelected(1)); + protected void event(UserRequest ureq, Component source, Event event) { + if(source == segmentView) { + if(event instanceof SegmentViewEvent) { + SegmentViewEvent sve = (SegmentViewEvent)event; + String segmentCName = sve.getComponentName(); + Component clickedLink = mainVC.getComponent(segmentCName); + if (clickedLink == configurationLink) { + doOpenConfiguration(ureq); + } else if (clickedLink == curriculumElementTypeListLink){ + doOpenCurriculumElementTypes(ureq); + } + } } - super.formInnerEvent(ureq, source, event); } - private void update() { - boolean enabled = enableEl.isAtLeastSelected(1); - curriculumMyCoursesEl.setVisible(enabled); + private void doOpenConfiguration(UserRequest ureq) { + if(configurationCtrl == null) { + WindowControl bwControl = addToHistory(ureq, OresHelper.createOLATResourceableType("Configuration"), null); + configurationCtrl = new CurriculumAdminConfigurationController(ureq, bwControl); + listenTo(configurationCtrl); + } + addToHistory(ureq, configurationCtrl); + mainVC.put("segmentCmp", configurationCtrl.getInitialComponent()); } + + private void doOpenCurriculumElementTypes(UserRequest ureq) { + if(elementTypeListCtrl == null) { + WindowControl bwControl = addToHistory(ureq, OresHelper.createOLATResourceableType("Types"), null); + elementTypeListCtrl = new CurriculumElementTypesEditController(ureq, bwControl); + listenTo(elementTypeListCtrl); + } + addToHistory(ureq, elementTypeListCtrl); + mainVC.put("segmentCmp", elementTypeListCtrl.getInitialComponent()); + } + } diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumComposerController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumComposerController.java index 1ff6b07ed04..dfaa0d43fd3 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/CurriculumComposerController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumComposerController.java @@ -223,7 +223,7 @@ public class CurriculumComposerController extends FormBasicController implements private void doNewCurriculumElement(UserRequest ureq) { if(newElementCtrl != null) return; - newElementCtrl = new EditCurriculumElementController(ureq, getWindowControl(), curriculum); + newElementCtrl = new EditCurriculumElementController(ureq, getWindowControl(), null, curriculum); listenTo(newElementCtrl); cmc = new CloseableModalController(getWindowControl(), "close", newElementCtrl.getInitialComponent(), true, translate("add.curriculum.element")); @@ -237,7 +237,7 @@ public class CurriculumComposerController extends FormBasicController implements tableEl.reloadData(); showWarning("warning.curriculum.element.deleted"); } else { - newSubElementCtrl = new EditCurriculumElementController(ureq, getWindowControl(), curriculum); + newSubElementCtrl = new EditCurriculumElementController(ureq, getWindowControl(), parentElement, curriculum); newSubElementCtrl.setParentElement(parentElement); listenTo(newSubElementCtrl); diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypeRow.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypeRow.java new file mode 100644 index 00000000000..65317c815e7 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypeRow.java @@ -0,0 +1,65 @@ +/** + * <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.components.form.flexible.elements.FormLink; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeRef; + +/** + * + * Initial date: 11 mai 2018<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumElementTypeRow implements CurriculumElementTypeRef { + + private FormLink toolsLink; + private final CurriculumElementType type; + + public CurriculumElementTypeRow(CurriculumElementType type) { + this.type = type; + } + + @Override + public Long getKey() { + return type.getKey(); + } + + public String getIdentifier() { + return type.getIdentifier(); + } + + public String getDisplayName() { + return type.getDisplayName(); + } + + public CurriculumElementType getType() { + return type; + } + + public FormLink getToolsLink() { + return toolsLink; + } + + public void setToolsLink(FormLink toolsLink) { + this.toolsLink = toolsLink; + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesEditController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesEditController.java new file mode 100644 index 00000000000..6e6a5970caa --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesEditController.java @@ -0,0 +1,326 @@ +/** + * <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.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +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.FlexiTableElement; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +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.elements.table.DefaultFlexiColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; +import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.control.generic.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.control.generic.modal.DialogBoxController; +import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.id.context.StateEntry; +import org.olat.core.util.StringHelper; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeManagedFlag; +import org.olat.modules.curriculum.CurriculumElementTypeRef; +import org.olat.modules.curriculum.CurriculumService; +import org.olat.modules.curriculum.ui.CurriculumElementTypesTableModel.TypesCols; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 11 mai 2018<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumElementTypesEditController extends FormBasicController implements Activateable2 { + + private FormLink addRootTypeButton; + private FlexiTableElement tableEl; + private CurriculumElementTypesTableModel model; + + private ToolsController toolsCtrl; + private CloseableModalController cmc; + private DialogBoxController confirmDeleteDialog; + private EditCurriculumElementTypeController rootElementTypeCtrl; + private EditCurriculumElementTypeController editElementTypeCtrl; + protected CloseableCalloutWindowController toolsCalloutCtrl; + + private int counter = 1; + + @Autowired + private CurriculumService curriculumService; + + public CurriculumElementTypesEditController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "admin_types"); + initForm(ureq); + loadModel(); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + addRootTypeButton = uifactory.addFormLink("add.root.type", formLayout, Link.BUTTON); + addRootTypeButton.setIconLeftCSS("o_icon o_icon-fw o_icon_add"); + + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TypesCols.identifier)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TypesCols.displayName)); + DefaultFlexiColumnModel editColumn = new DefaultFlexiColumnModel("table.header.edit", -1, "edit", + new StaticFlexiCellRenderer("", "edit", "o_icon o_icon-lg o_icon_edit", translate("edit"))); + editColumn.setExportable(false); + columnsModel.addFlexiColumnModel(editColumn); + DefaultFlexiColumnModel toolsColumn = new DefaultFlexiColumnModel(TypesCols.tools); + toolsColumn.setExportable(false); + columnsModel.addFlexiColumnModel(toolsColumn); + + model = new CurriculumElementTypesTableModel(columnsModel); + tableEl = uifactory.addTableElement(getWindowControl(), "types", model, 25, false, getTranslator(), formLayout); + tableEl.setEmtpyTableMessageKey("table.type.empty"); + tableEl.setAndLoadPersistedPreferences(ureq, "cur-el-types"); + } + + private void loadModel() { + List<CurriculumElementType> types = curriculumService.getCurriculumElementTypes(); + List<CurriculumElementTypeRow> rows = types + .stream().map(t -> forgeRow(t)) + .collect(Collectors.toList()); + model.setObjects(rows); + tableEl.reset(false, true, true); + } + + private CurriculumElementTypeRow forgeRow(CurriculumElementType type) { + CurriculumElementTypeRow row = new CurriculumElementTypeRow(type); + if(isToolsEnable(type)) { + FormLink toolsLink = uifactory.addFormLink("tools_" + (++counter), "tools", "", null, null, Link.NONTRANSLATED); + toolsLink.setIconLeftCSS("o_icon o_icon_actions o_icon-lg"); + toolsLink.setUserObject(row); + row.setToolsLink(toolsLink); + } + return row; + } + + private boolean isToolsEnable(CurriculumElementType type) { + return !CurriculumElementTypeManagedFlag.isManaged(type.getManagedFlags(), CurriculumElementTypeManagedFlag.copy) + || !CurriculumElementTypeManagedFlag.isManaged(type.getManagedFlags(), CurriculumElementTypeManagedFlag.delete); + } + + @Override + protected void doDispose() { + // + } + + @Override + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { + if(entries == null || entries.isEmpty()) return; + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(rootElementTypeCtrl == source || editElementTypeCtrl == source) { + if(event == Event.DONE_EVENT) { + loadModel(); + } + cmc.deactivate(); + cleanUp(); + } else if(confirmDeleteDialog == source) { + if (DialogBoxUIFactory.isOkEvent(event) || DialogBoxUIFactory.isYesEvent(event)) { + CurriculumElementTypeRow row = (CurriculumElementTypeRow)confirmDeleteDialog.getUserObject(); + doDelete(row); + } + cleanUp(); + } else if(cmc == source) { + cleanUp(); + } + super.event(ureq, source, event); + } + + private void cleanUp() { + removeAsListenerAndDispose(rootElementTypeCtrl); + removeAsListenerAndDispose(cmc); + rootElementTypeCtrl = null; + cmc = null; + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(addRootTypeButton == source) { + doAddRootType(ureq); + } else if (source instanceof FormLink) { + FormLink link = (FormLink)source; + String cmd = link.getCmd(); + if("tools".equals(cmd)) { + CurriculumElementTypeRow row = (CurriculumElementTypeRow)link.getUserObject(); + doOpenTools(ureq, row, link); + } + } else if(tableEl == source) { + if(event instanceof SelectionEvent) { + SelectionEvent se = (SelectionEvent)event; + String cmd = se.getCommand(); + if("edit".equals(cmd)) { + CurriculumElementTypeRow row = model.getObject(se.getIndex()); + doEditCurriculElementType(ureq, row.getType()); + } + } + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + private void doOpenTools(UserRequest ureq, CurriculumElementTypeRow row, FormLink link) { + removeAsListenerAndDispose(toolsCtrl); + removeAsListenerAndDispose(toolsCalloutCtrl); + + CurriculumElementType type = curriculumService.getCurriculumElementType(row); + if(type == null) { + tableEl.reloadData(); + showWarning("warning.curriculum.element.type.deleted"); + } else { + toolsCtrl = new ToolsController(ureq, getWindowControl(), row, type); + listenTo(toolsCtrl); + + toolsCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(), + toolsCtrl.getInitialComponent(), link.getFormDispatchId(), "", true, ""); + listenTo(toolsCalloutCtrl); + toolsCalloutCtrl.activate(); + } + } + + private void doAddRootType(UserRequest ureq) { + rootElementTypeCtrl = new EditCurriculumElementTypeController(ureq, getWindowControl(), null); + listenTo(rootElementTypeCtrl); + + cmc = new CloseableModalController(getWindowControl(), "close", rootElementTypeCtrl.getInitialComponent(), true, translate("add.root.type")); + listenTo(cmc); + cmc.activate(); + } + + private void doEditCurriculElementType(UserRequest ureq, CurriculumElementTypeRef type) { + CurriculumElementType reloadedType = curriculumService.getCurriculumElementType(type); + editElementTypeCtrl = new EditCurriculumElementTypeController(ureq, getWindowControl(), reloadedType); + listenTo(editElementTypeCtrl); + + cmc = new CloseableModalController(getWindowControl(), "close", editElementTypeCtrl.getInitialComponent(), true, translate("edit")); + listenTo(cmc); + cmc.activate(); + } + + private void doCopy(CurriculumElementTypeRow row) { + curriculumService.cloneCurriculumElementType(row); + loadModel(); + showInfo("info.copy.element.type.sucessfull", row.getDisplayName()); + } + + private void doConfirmDelete(UserRequest ureq, CurriculumElementTypeRow row) { + String[] args = new String[] { StringHelper.escapeHtml(row.getDisplayName()) }; + String title = translate("confirmation.delete.type.title", args); + String text = translate("confirmation.delete.type", args); + confirmDeleteDialog = activateOkCancelDialog(ureq, title, text, confirmDeleteDialog); + confirmDeleteDialog.setUserObject(row); + } + + private void doDelete(CurriculumElementTypeRow row) { + if(curriculumService.deleteCurriculumElementType(row)) { + showInfo("confirm.delete.element.type.sucessfull", row.getDisplayName()); + loadModel(); + tableEl.reset(true, true, true); + } else { + showWarning("warning.delete.element.type", row.getDisplayName()); + } + } + + private class ToolsController extends BasicController { + + private final CurriculumElementTypeRow row; + + private final VelocityContainer mainVC; + + public ToolsController(UserRequest ureq, WindowControl wControl, CurriculumElementTypeRow row, CurriculumElementType type) { + super(ureq, wControl); + setTranslator(CurriculumElementTypesEditController.this.getTranslator()); + this.row = row; + + mainVC = createVelocityContainer("tools"); + List<String> links = new ArrayList<>(); + + if(!CurriculumElementTypeManagedFlag.isManaged(type.getManagedFlags(), CurriculumElementTypeManagedFlag.copy)) { + addLink("details.copy", "copy", "o_icon o_icon-fw o_icon_copy", links); + } + if(!CurriculumElementTypeManagedFlag.isManaged(type.getManagedFlags(), CurriculumElementTypeManagedFlag.delete)) { + addLink("details.delete", "delete", "o_icon o_icon-fw o_icon_delete_item", links); + } + + mainVC.contextPut("links", links); + putInitialPanel(mainVC); + } + + private void addLink(String name, String cmd, String iconCSS, List<String> links) { + Link link = LinkFactory.createLink(name, cmd, getTranslator(), mainVC, this, Link.LINK); + if(iconCSS != null) { + link.setIconLeftCSS(iconCSS); + } + mainVC.put(name, link); + links.add(name); + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + fireEvent(ureq, Event.DONE_EVENT); + if(source instanceof Link) { + Link link = (Link)source; + String cmd = link.getCommand(); + if("copy".equals(cmd)) { + close(); + doCopy(row); + } else if("delete".equals(cmd)) { + close(); + doConfirmDelete(ureq, row); + } + } + } + + private void close() { + toolsCalloutCtrl.deactivate(); + cleanUp(); + } + + @Override + protected void doDispose() { + // + } + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesTableModel.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesTableModel.java new file mode 100644 index 00000000000..3216d3cb034 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesTableModel.java @@ -0,0 +1,98 @@ +/** + * <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.util.List; + +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel; + +/** + * + * Initial date: 11 mai 2018<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumElementTypesTableModel extends DefaultFlexiTableDataModel<CurriculumElementTypeRow> +implements SortableFlexiTableDataModel<CurriculumElementTypeRow> { + + public CurriculumElementTypesTableModel(FlexiTableColumnModel columnsModel) { + super(columnsModel); + } + + @Override + public void sort(SortKey orderBy) { + if(orderBy != null) { + List<CurriculumElementTypeRow> views = new CurriculumElementTypesTableModelSortDelegate(orderBy, this, null).sort(); + super.setObjects(views); + } + } + + @Override + public Object getValueAt(int row, int col) { + CurriculumElementTypeRow type = getObject(row); + return getValueAt(type, col); + } + + @Override + public Object getValueAt(CurriculumElementTypeRow row, int col) { + switch(TypesCols.values()[col]) { + case identifier: return row.getIdentifier(); + case displayName: return row.getDisplayName(); + case tools: return row.getToolsLink(); + default: return null; + } + } + + @Override + public DefaultFlexiTableDataModel<CurriculumElementTypeRow> createCopyWithEmptyList() { + return new CurriculumElementTypesTableModel(getTableColumnModel()); + } + + public enum TypesCols implements FlexiSortableColumnDef { + identifier("table.header.type.identifier"), + displayName("table.header.type.displayName"), + tools("table.header.tools"); + + private final String i18nHeaderKey; + + private TypesCols(String i18nHeaderKey) { + this.i18nHeaderKey = i18nHeaderKey; + } + + @Override + public boolean sortable() { + return true; + } + + @Override + public String sortKey() { + return name(); + } + + @Override + public String i18nHeaderKey() { + return i18nHeaderKey; + } + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesTableModelSortDelegate.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesTableModelSortDelegate.java new file mode 100644 index 00000000000..a4546b12631 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementTypesTableModelSortDelegate.java @@ -0,0 +1,38 @@ +/** + * <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.util.Locale; + +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableModelDelegate; + +/** + * + * Initial date: 11 mai 2018<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CurriculumElementTypesTableModelSortDelegate extends SortableFlexiTableModelDelegate<CurriculumElementTypeRow> { + + public CurriculumElementTypesTableModelSortDelegate(SortKey orderBy, CurriculumElementTypesTableModel tableModel, Locale locale) { + super(orderBy, tableModel, locale); + } +} diff --git a/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementController.java b/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementController.java index 6e4d419b5b4..c7954aebd40 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementController.java @@ -19,9 +19,16 @@ */ package org.olat.modules.curriculum.ui; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Set; + import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.DateChooser; import org.olat.core.gui.components.form.flexible.elements.RichTextElement; +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.FormLayoutContainer; @@ -32,7 +39,10 @@ import org.olat.core.util.StringHelper; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementManagedFlag; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeToType; import org.olat.modules.curriculum.CurriculumService; +import org.olat.modules.curriculum.model.CurriculumElementTypeRefImpl; import org.springframework.beans.factory.annotation.Autowired; /** @@ -43,9 +53,14 @@ import org.springframework.beans.factory.annotation.Autowired; */ public class EditCurriculumElementController extends FormBasicController { - private RichTextElement descriptionEl; + private DateChooser endEl; + private DateChooser beginEl; private TextElement identifierEl; private TextElement displayNameEl; + private RichTextElement descriptionEl; + + + private SingleSelection curriculumElementTypeEl; private Curriculum curriculum; private CurriculumElement element; @@ -61,17 +76,19 @@ public class EditCurriculumElementController extends FormBasicController { * @param wControl The window control */ public EditCurriculumElementController(UserRequest ureq, WindowControl wControl, - Curriculum curriculum) { + CurriculumElement parentElement, Curriculum curriculum) { super(ureq, wControl); this.curriculum = curriculum; + this.parentElement = parentElement; initForm(ureq); } public EditCurriculumElementController(UserRequest ureq, WindowControl wControl, - CurriculumElement element, Curriculum curriculum) { + CurriculumElement element, CurriculumElement parentElement, Curriculum curriculum) { super(ureq, wControl); this.curriculum = curriculum; this.element = element; + this.parentElement = parentElement; initForm(ureq); } @@ -97,25 +114,96 @@ public class EditCurriculumElementController extends FormBasicController { } String identifier = element == null ? "" : element.getIdentifier(); - identifierEl = uifactory.addTextElement("curriculum.identifier", "curriculum.identifier", 255, identifier, formLayout); + identifierEl = uifactory.addTextElement("identifier", "curriculum.element.identifier", 255, identifier, formLayout); identifierEl.setEnabled(!CurriculumElementManagedFlag.isManaged(element, CurriculumElementManagedFlag.identifier)); identifierEl.setMandatory(true); String displayName = element == null ? "" : element.getDisplayName(); - displayNameEl = uifactory.addTextElement("curriculum.displayName", "curriculum.displayName", 255, displayName, formLayout); + displayNameEl = uifactory.addTextElement("displayName", "curriculum.element.displayName", 255, displayName, formLayout); displayNameEl.setEnabled(!CurriculumElementManagedFlag.isManaged(element, CurriculumElementManagedFlag.displayName)); displayNameEl.setMandatory(true); + List<CurriculumElementType> types = getTypes(); + String[] typeKeys = new String[types.size() + 1]; + String[] typeValues = new String[types.size() + 1]; + typeKeys[0] = ""; + typeValues[0] = "-"; + for(int i=types.size(); i-->0; ) { + typeKeys[i+1] = types.get(i).getKey().toString(); + typeValues[i+1] = types.get(i).getDisplayName(); + } + curriculumElementTypeEl = uifactory.addDropdownSingleselect("type", "curriculum.element.type", formLayout, typeKeys, typeValues, null); + curriculumElementTypeEl.setEnabled(!CurriculumElementManagedFlag.isManaged(element, CurriculumElementManagedFlag.type)); + boolean typeFound = false; + if(element != null && element.getType() != null) { + String selectedTypeKey = element.getType().getKey().toString(); + for(String typeKey:typeKeys) { + if(typeKey.equals(selectedTypeKey)) { + curriculumElementTypeEl.select(selectedTypeKey, true); + typeFound = true; + break; + } + } + } + if(!typeFound) { + curriculumElementTypeEl.select(typeKeys[0], true); + } + + Date begin = element == null ? null : element.getBeginDate(); + beginEl = uifactory.addDateChooser("start", "curriculum.element.begin", begin, formLayout); + beginEl.setEnabled(!CurriculumElementManagedFlag.isManaged(element, CurriculumElementManagedFlag.dates)); + + Date end = element == null ? null : element.getEndDate(); + endEl = uifactory.addDateChooser("start", "curriculum.element.end", end, formLayout); + endEl.setEnabled(!CurriculumElementManagedFlag.isManaged(element, CurriculumElementManagedFlag.dates)); + String description = element == null ? "" : element.getDescription(); descriptionEl = uifactory.addRichTextElementForStringDataCompact("curriculum.description", "curriculum.description", description, 10, 60, null, formLayout, ureq.getUserSession(), getWindowControl()); descriptionEl.setEnabled(!CurriculumElementManagedFlag.isManaged(element, CurriculumElementManagedFlag.description)); - + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); formLayout.add(buttonsCont); uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); uifactory.addFormSubmitButton("save", buttonsCont); } + + private List<CurriculumElementType> getTypes() { + List<CurriculumElementType> types; + if(element != null) { + types = getTypes(element); + } else if(parentElement != null) { + types = getTypes(parentElement); + } else { + types = new ArrayList<>(); + } + + if(types.isEmpty()) { + types.addAll(curriculumService.getCurriculumElementTypes()); + } else if(element != null && element.getType() != null && !types.contains(element.getType())) { + types.add(element.getType()); + } + return types; + } + + private List<CurriculumElementType> getTypes(CurriculumElement curriculumElement) { + List<CurriculumElementType> types = new ArrayList<>(); + List<CurriculumElement> parentLine = curriculumService.getCurriculumElementParentLine(curriculumElement); + for(int i=parentLine.size() - 1; i-->0; ) { + CurriculumElement parent = parentLine.get(i); + CurriculumElementType parentType = parent.getType(); + if(parentType != null) { + Set<CurriculumElementTypeToType> typeToTypes = parentType.getAllowedSubTypes(); + for(CurriculumElementTypeToType typeToType:typeToTypes) { + if(typeToType != null) { + types.add(typeToType.getAllowedSubType()); + } + } + break; + } + } + return types; + } @Override protected void doDispose() { @@ -124,7 +212,7 @@ public class EditCurriculumElementController extends FormBasicController { @Override protected boolean validateFormLogic(UserRequest ureq) { - boolean allOk = true; + boolean allOk = super.validateFormLogic(ureq); displayNameEl.clearError(); if(!StringHelper.containsNonWhitespace(displayNameEl.getValue())) { @@ -138,20 +226,30 @@ public class EditCurriculumElementController extends FormBasicController { allOk &= false; } - return allOk & super.validateFormLogic(ureq); + return allOk; } @Override protected void formOK(UserRequest ureq) { + CurriculumElementType elementType = null; + String selectedTypeKey = curriculumElementTypeEl.getSelectedKey(); + if(StringHelper.containsNonWhitespace(selectedTypeKey)) { + elementType = curriculumService + .getCurriculumElementType(new CurriculumElementTypeRefImpl(new Long(selectedTypeKey))); + } + if(element == null) { //create a new one - element = curriculumService - .createCurriculumElement(identifierEl.getValue(), displayNameEl.getValue(), parentElement, curriculum); + element = curriculumService.createCurriculumElement(identifierEl.getValue(), displayNameEl.getValue(), + beginEl.getDate(), endEl.getDate(), parentElement, elementType, curriculum); } else { element = curriculumService.getCurriculumElement(element); element.setIdentifier(identifierEl.getValue()); element.setDisplayName(displayNameEl.getValue()); element.setDescription(descriptionEl.getValue()); + element.setBeginDate(beginEl.getDate()); + element.setEndDate(endEl.getDate()); + element.setType(elementType); element = curriculumService.updateCurriculumElement(element); } diff --git a/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementOverviewController.java b/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementOverviewController.java index cdb1931a78b..c788ac2435f 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementOverviewController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementOverviewController.java @@ -55,7 +55,7 @@ public class EditCurriculumElementOverviewController extends BasicController { tabPane = new TabbedPane("tabs", getLocale()); tabPane.addListener(this); - metadataCtrl = new EditCurriculumElementController(ureq, getWindowControl(), element, curriculum); + metadataCtrl = new EditCurriculumElementController(ureq, getWindowControl(), element, element.getParent(), curriculum); listenTo(metadataCtrl); tabPane.addTab(translate("curriculum.element.metadata"), metadataCtrl); initTabPane(); diff --git a/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementTypeController.java b/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementTypeController.java new file mode 100644 index 00000000000..5a9ba1aedf8 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/EditCurriculumElementTypeController.java @@ -0,0 +1,164 @@ +/** + * <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.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.RichTextElement; +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.FormLayoutContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeManagedFlag; +import org.olat.modules.curriculum.CurriculumElementTypeToType; +import org.olat.modules.curriculum.CurriculumService; +import org.olat.modules.curriculum.model.CurriculumElementTypeRefImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 11 mai 2018<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class EditCurriculumElementTypeController extends FormBasicController { + + private TextElement identifierEl; + private TextElement displayNameEl; + private RichTextElement descriptionEl; + private MultipleSelectionElement allowedSubTypesEl; + + private CurriculumElementType curriculumElementType; + + @Autowired + private CurriculumService curriculumService; + + public EditCurriculumElementTypeController(UserRequest ureq, WindowControl wControl, CurriculumElementType curriculumElementType) { + super(ureq, wControl); + this.curriculumElementType = curriculumElementType; + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + String identifier = curriculumElementType == null ? "" : curriculumElementType.getIdentifier(); + identifierEl = uifactory.addTextElement("type.identifier", "type.identifier", 255, identifier, formLayout); + identifierEl.setEnabled(!CurriculumElementTypeManagedFlag.isManaged(curriculumElementType, CurriculumElementTypeManagedFlag.identifier)); + identifierEl.setMandatory(true); + if(!StringHelper.containsNonWhitespace(identifier)) { + identifierEl.setFocus(true); + } + + String displayName = curriculumElementType == null ? "" : curriculumElementType.getDisplayName(); + displayNameEl = uifactory.addTextElement("type.displayname", "type.displayname", 255, displayName, formLayout); + displayNameEl.setEnabled(!CurriculumElementTypeManagedFlag.isManaged(curriculumElementType, CurriculumElementTypeManagedFlag.displayName)); + displayNameEl.setMandatory(true); + + String description = curriculumElementType == null ? "" : curriculumElementType.getDescription(); + descriptionEl = uifactory.addRichTextElementForStringDataMinimalistic("type.description", "type.description", description, 10, 60, + formLayout, getWindowControl()); + descriptionEl.setEnabled(!CurriculumElementTypeManagedFlag.isManaged(curriculumElementType, CurriculumElementTypeManagedFlag.description)); + + List<CurriculumElementType> types = curriculumService.getCurriculumElementTypes(); + types.remove(curriculumElementType); + + String[] subTypeKeys = new String[types.size()]; + String[] subTypeValues = new String[types.size()]; + for(int i=types.size(); i-->0; ) { + subTypeKeys[i] = types.get(i).getKey().toString(); + subTypeValues[i] = types.get(i).getDisplayName(); + } + allowedSubTypesEl = uifactory.addCheckboxesVertical("type.allowed.sub.types", formLayout, subTypeKeys, subTypeValues, 2); + allowedSubTypesEl.setEnabled(!CurriculumElementTypeManagedFlag.isManaged(curriculumElementType, CurriculumElementTypeManagedFlag.subTypes)); + if(curriculumElementType != null) { + Set<CurriculumElementTypeToType> typeToTypes = curriculumElementType.getAllowedSubTypes(); + for(CurriculumElementTypeToType typeToType:typeToTypes) { + String subTypeKey = typeToType.getAllowedSubType().getKey().toString(); + allowedSubTypesEl.select(subTypeKey, true); + } + } + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + uifactory.addFormSubmitButton("save", buttonsCont); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + displayNameEl.clearError(); + if(!StringHelper.containsNonWhitespace(displayNameEl.getValue())) { + displayNameEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + + identifierEl.clearError(); + if(!StringHelper.containsNonWhitespace(identifierEl.getValue())) { + identifierEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } + + return allOk & super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + if(curriculumElementType == null) { + curriculumElementType = curriculumService.createCurriculumElementType(identifierEl.getValue(), displayNameEl.getValue(), + descriptionEl.getValue(), null); + } else { + curriculumElementType = curriculumService.getCurriculumElementType(curriculumElementType); + curriculumElementType.setIdentifier(identifierEl.getValue()); + curriculumElementType.setDisplayName(displayNameEl.getValue()); + curriculumElementType.setDescription(descriptionEl.getValue()); + } + + Collection<String> selectedAllowedSubTypeKeys = allowedSubTypesEl.getSelectedKeys(); + List<CurriculumElementType> allowedSubTypes = new ArrayList<>(); + for(String selectedAllowedSubTypeKey:selectedAllowedSubTypeKeys) { + allowedSubTypes.add(curriculumService.getCurriculumElementType(new CurriculumElementTypeRefImpl(new Long(selectedAllowedSubTypeKey)))); + } + curriculumElementType = curriculumService.updateCurriculumElementType(curriculumElementType, allowedSubTypes); + + 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/admin_types.html b/src/main/java/org/olat/modules/curriculum/ui/_content/admin_types.html new file mode 100644 index 00000000000..f2ba8c909b9 --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/_content/admin_types.html @@ -0,0 +1,6 @@ +#if($r.available("add.root.type")) +<div class="o_button_group o_button_group_right"> + $r.render("add.root.type") +</div> +#end +$r.render("types") \ No newline at end of file diff --git a/src/main/java/org/olat/modules/curriculum/ui/_content/curriculum_admin.html b/src/main/java/org/olat/modules/curriculum/ui/_content/curriculum_admin.html new file mode 100644 index 00000000000..ae882e5cd7f --- /dev/null +++ b/src/main/java/org/olat/modules/curriculum/ui/_content/curriculum_admin.html @@ -0,0 +1,7 @@ +<div class="clearfix"> + $r.render("segments") <br/> + + #if($r.available("segmentCmp")) + $r.render("segmentCmp") + #end +</div> \ 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 cb5664c558e..27148306f51 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 @@ -12,7 +12,10 @@ admin.title=$\:admin.menu.title curriculum.admin.enabled=Curriculum einschalten curriculum.element.metadata=Metadaten curriculum.element.key=ID +curriculum.element.identifier=Bezeichnung +curriculum.element.displayName=Name curriculum.element.external.id=Externe ID +curriculum.element.type=Typ curriculum.in.my.courses.enabled=Curriculum in "Meine Kurse" curriculum.identifier=Bezeichnung curriculum.displayName=Name @@ -22,7 +25,6 @@ curriculum.external.id=Externe ID move.element=Element schieben remove.memberships=Entfernen resources.add=$add.resources - resources.add.title= supervisor=Fachvorsteher (supervisor) tab.resources=Kurse @@ -33,5 +35,27 @@ table.header.identifier=Bezeichnung table.header.role=Rolle table.header.tools=<i class\='o_icon o_icon_actions o_icon-lg'> </i> table.header.username=Benutzername +table.header.type.identifier=Bezeichnung +table.header.type.displayName=Name table.curriculum.empty=Es steht kein Curriculum zur Verfügung -table.curriculum.element.empty=Curriculum ist leer \ No newline at end of file +table.curriculum.element.empty=Curriculum ist leer +type.identifier=Bezeichnung +type.displayname=Name +type.description=Beschreibung +type.allowed.sub.types=Sub types +add.root.type=Neuer Typ erstellen +curriculum.configuration=Curriculum +curriculum.element.types=Typen +table.type.empty=Es sind keine Typen vorhanden. +table.header.edit=Bearbeiten +curriculum.element.begin=Beginndatum +curriculum.element.end=Enddatum + +info.copy.element.type.sucessfull=Der Typ "{0}" wurde erfolgreich kopiert. +warning.curriculum.element.type.deleted=Dieser Typ ist nicht mehr verf\u00FCgbar. +confirmation.delete.type.title=Typ "{0}" l\u00F6schen +confirmation.delete.type=Wollen Sie wirklich den Typ "{0}" l\u00F6schen? +confirm.delete.element.type.sucessfull=Der Typ "{0}" wurde erfolgreich gel\u00F6scht. +warning.delete.element.type=Der Typ wurde nicht gel\u00F6scht. Er ist noch benutzt. +details.copy=Kopieren +details.delete=L\u00F6schen \ No newline at end of file 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 ffbfa347c8d..1e7e9c21730 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 @@ -13,6 +13,9 @@ curriculum.admin.enabled=Enable curriculum curriculum.element.key=ID curriculum.element.metadata=Metadata curriculum.element.external.id=External ID +curriculum.element.identifier=Identifier +curriculum.element.displayName=Name +curriculum.element.type=Type curriculum.in.my.courses.enabled=Curriculum in "My courses" curriculum.identifier=Identifier curriculum.displayName=Name @@ -31,5 +34,27 @@ table.header.identifier=Identifier table.header.role=Role table.header.tools=<i class\='o_icon o_icon_actions o_icon-lg'> </i> table.header.username=Username +table.header.type.identifier=Identifier +table.header.type.displayName=Name table.curriculum.empty=There are no curriculum available -table.curriculum.element.empty=Curriculum is empty \ No newline at end of file +table.curriculum.element.empty=Curriculum is empty +type.identifier=Identifier +type.displayname=Name +type.description=Description +type.allowed.sub.types=Sub types +add.root.type=Add new type +curriculum.configuration=Curriculum +curriculum.element.types=Types +table.type.empty=There isn't any type available. +table.header.edit=Edit +curriculum.element.begin=Start date +curriculum.element.end=End date + +info.copy.element.type.sucessfull=The type "{0}" was successfully copied. +warning.curriculum.element.type.deleted=This type is no longer available. +confirmation.delete.type.title=Delete type "{0}" +confirmation.delete.type=Do you really want to delete this type "{0}"? +confirm.delete.element.type.sucessfull=The type "{0}" was successfully deleted. +warning.delete.element.type=The type "{0}" was not deleted because it is still in use. +details.copy=Copy +details.delete=Delete \ No newline at end of file diff --git a/src/main/resources/database/mysql/alter_12_4_x_to_13_0_0.sql b/src/main/resources/database/mysql/alter_12_4_x_to_13_0_0.sql index f9acb5fc485..00055553e39 100644 --- a/src/main/resources/database/mysql/alter_12_4_x_to_13_0_0.sql +++ b/src/main/resources/database/mysql/alter_12_4_x_to_13_0_0.sql @@ -114,6 +114,7 @@ create table o_cur_curriculum_element ( c_begin datetime, c_end datetime, c_external_id varchar(64), + c_m_path_keys varchar(255), c_managed_flags varchar(255), fk_group bigint not null, fk_parent bigint, diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index bcdb983e542..ed230d07974 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -2470,11 +2470,12 @@ c_begin datetime, c_end datetime, c_external_id varchar(64), + c_m_path_keys varchar(255), c_managed_flags varchar(255), fk_group bigint not null, fk_parent bigint, fk_curriculum bigint not null, - fk_type bigint, + fk_type bigint, primary key (id) ); diff --git a/src/main/resources/database/oracle/alter_12_4_x_to_13_0_0.sql b/src/main/resources/database/oracle/alter_12_4_x_to_13_0_0.sql index 9f3de8b8043..3214aa43372 100644 --- a/src/main/resources/database/oracle/alter_12_4_x_to_13_0_0.sql +++ b/src/main/resources/database/oracle/alter_12_4_x_to_13_0_0.sql @@ -116,6 +116,7 @@ create table o_cur_curriculum_element ( c_begin date, c_end date, c_external_id varchar(64), + c_m_path_keys varchar(255), c_managed_flags varchar(255), fk_group number(20) not null, fk_parent number(20), diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql index 52dc3b499f0..912c16f44bd 100644 --- a/src/main/resources/database/oracle/setupDatabase.sql +++ b/src/main/resources/database/oracle/setupDatabase.sql @@ -2514,6 +2514,7 @@ create table o_cur_curriculum_element ( c_begin date, c_end date, c_external_id varchar(64), + c_m_path_keys varchar(255), c_managed_flags varchar(255), fk_group number(20) not null, fk_parent number(20), diff --git a/src/main/resources/database/postgresql/alter_12_4_x_to_13_0_0.sql b/src/main/resources/database/postgresql/alter_12_4_x_to_13_0_0.sql index 61067187a4e..93303c41768 100644 --- a/src/main/resources/database/postgresql/alter_12_4_x_to_13_0_0.sql +++ b/src/main/resources/database/postgresql/alter_12_4_x_to_13_0_0.sql @@ -116,6 +116,7 @@ create table o_cur_curriculum_element ( c_begin timestamp, c_end timestamp , c_external_id varchar(64), + c_m_path_keys varchar(255), c_managed_flags varchar(255), fk_group int8 not null, fk_parent int8, diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index 2eaaa09fc4a..9486ee57f0d 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -2467,6 +2467,7 @@ create table o_cur_curriculum_element ( c_begin timestamp, c_end timestamp , c_external_id varchar(64), + c_m_path_keys varchar(255), c_managed_flags varchar(255), fk_group int8 not null, fk_parent int8, diff --git a/src/test/java/org/olat/modules/curriculum/manager/CurriculumElementDAOTest.java b/src/test/java/org/olat/modules/curriculum/manager/CurriculumElementDAOTest.java index 529584d585d..42300f605bf 100644 --- a/src/test/java/org/olat/modules/curriculum/manager/CurriculumElementDAOTest.java +++ b/src/test/java/org/olat/modules/curriculum/manager/CurriculumElementDAOTest.java @@ -19,6 +19,7 @@ */ package org.olat.modules.curriculum.manager; +import java.util.Date; import java.util.List; import org.junit.Assert; @@ -27,6 +28,7 @@ import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementType; import org.olat.modules.curriculum.CurriculumRoles; import org.olat.modules.curriculum.CurriculumService; import org.olat.modules.curriculum.model.CurriculumElementImpl; @@ -50,12 +52,15 @@ public class CurriculumElementDAOTest extends OlatTestCase { @Autowired private CurriculumElementDAO curriculumElementDao; @Autowired + private CurriculumElementTypeDAO curriculumElementTypeDao; + @Autowired private CurriculumService curriculumService; @Test public void createCurriculumElement() { Curriculum curriculum = curriculumDao.createAndPersist("Cur-for-el-1", "Curriculum for element", "Curriculum", null); - CurriculumElement element = curriculumElementDao.createCurriculumElement("Element-1", "1. Element", null, curriculum); + CurriculumElementType type = curriculumElementTypeDao.createCurriculumElementType("typ-for-cur-el-1", "Type for", "First element", "AC-234"); + CurriculumElement element = curriculumElementDao.createCurriculumElement("Element-1", "1. Element", new Date(), new Date(), null, type, curriculum); Assert.assertNotNull(element); dbInstance.commitAndCloseSession(); @@ -63,15 +68,19 @@ public class CurriculumElementDAOTest extends OlatTestCase { Assert.assertNotNull(element.getKey()); Assert.assertNotNull(element.getCreationDate()); Assert.assertNotNull(element.getLastModified()); + Assert.assertNotNull(element.getBeginDate()); + Assert.assertNotNull(element.getEndDate()); Assert.assertEquals("Element-1", element.getIdentifier()); Assert.assertEquals("1. Element", element.getDisplayName()); Assert.assertEquals(curriculum, element.getCurriculum()); + Assert.assertEquals(type, element.getType()); } @Test public void loadByKey() { Curriculum curriculum = curriculumDao.createAndPersist("Cur-for-el-2", "Curriculum for element", "Curriculum", null); - CurriculumElement element = curriculumElementDao.createCurriculumElement("Element-2", "2. Element", null, curriculum); + CurriculumElementType type = curriculumElementTypeDao.createCurriculumElementType("typ-for-cur-el-2", "Type for", "First element", "AC-234"); + CurriculumElement element = curriculumElementDao.createCurriculumElement("Element-2", "2. Element", new Date(), new Date(), null, type, curriculum); Assert.assertNotNull(element); dbInstance.commitAndCloseSession(); @@ -83,22 +92,43 @@ public class CurriculumElementDAOTest extends OlatTestCase { Assert.assertEquals(element, reloadedElement); Assert.assertNotNull(reloadedElement.getCreationDate()); Assert.assertNotNull(reloadedElement.getLastModified()); + Assert.assertNotNull(reloadedElement.getBeginDate()); + Assert.assertNotNull(reloadedElement.getEndDate()); Assert.assertEquals("Element-2", reloadedElement.getIdentifier()); Assert.assertEquals("2. Element", reloadedElement.getDisplayName()); Assert.assertEquals(curriculum, reloadedElement.getCurriculum()); + Assert.assertEquals(type, reloadedElement.getType()); + } + + @Test + public void loadElements() { + Curriculum curriculum = curriculumDao.createAndPersist("Cur-for-el-6", "Curriculum for element", "Curriculum", null); + CurriculumElement element1 = curriculumElementDao.createCurriculumElement("Element-6", "6.1 Element", null, null, null, null, curriculum); + CurriculumElement element2 = curriculumElementDao.createCurriculumElement("Element-6", "6.1.1 Element", null, null, element1, null, curriculum); + CurriculumElement element3 = curriculumElementDao.createCurriculumElement("Element-6", "6.2 Element", null, null, null, null, curriculum); + dbInstance.commitAndCloseSession(); + + //load all elements of the curriculum + List<CurriculumElement> elements = curriculumElementDao.loadElements(curriculum); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(elements); + Assert.assertEquals(3, elements.size()); + Assert.assertTrue(elements.contains(element1)); + Assert.assertTrue(elements.contains(element2)); + Assert.assertTrue(elements.contains(element3)); } @Test public void createCurriculumElementParentChildren() { Curriculum curriculum = curriculumDao.createAndPersist("cur-for-el-3", "Curriculum for element", "Curriculum", null); - CurriculumElement parentElement = curriculumElementDao.createCurriculumElement("Element-3", "3. Element", null, curriculum); + CurriculumElement parentElement = curriculumElementDao.createCurriculumElement("Element-3", "3. Element", null, null, null, null, curriculum); dbInstance.commit(); // save 3 children - CurriculumElement element1 = curriculumElementDao.createCurriculumElement("Element-3-1", "3.1 Element", parentElement, curriculum); + CurriculumElement element1 = curriculumElementDao.createCurriculumElement("Element-3-1", "3.1 Element", null, null, parentElement, null, curriculum); dbInstance.commit(); - CurriculumElement element2 = curriculumElementDao.createCurriculumElement("Element-3-2", "3.2 Element", parentElement, curriculum); + CurriculumElement element2 = curriculumElementDao.createCurriculumElement("Element-3-2", "3.2 Element", null, null, parentElement, null, curriculum); dbInstance.commit(); - CurriculumElement element3 = curriculumElementDao.createCurriculumElement("Element-3-3", "3.3 Element", parentElement, curriculum); + CurriculumElement element3 = curriculumElementDao.createCurriculumElement("Element-3-3", "3.3 Element", null, null, parentElement, null, curriculum); dbInstance.commitAndCloseSession(); //reload parents @@ -111,11 +141,90 @@ public class CurriculumElementDAOTest extends OlatTestCase { Assert.assertEquals(element3, children.get(2)); } + @Test + public void getParentLine() { + Curriculum curriculum = curriculumDao.createAndPersist("cur-for-el-4", "Curriculum for element", "Curriculum", null); + CurriculumElement parentElement = curriculumElementDao.createCurriculumElement("Element-4", "4. Element", null, null, null, null, curriculum); + dbInstance.commit(); + // save 3 children + CurriculumElement element1 = curriculumElementDao.createCurriculumElement("Element-4-1", "4.1 Element", null, null, parentElement, null, curriculum); + dbInstance.commit(); + CurriculumElement element2 = curriculumElementDao.createCurriculumElement("Element-4-2", "4.1.1 Element", null, null, element1, null, curriculum); + dbInstance.commit(); + CurriculumElement element3 = curriculumElementDao.createCurriculumElement("Element-4-3", "4.1.1.1 Element", null, null, element2, null, curriculum); + dbInstance.commitAndCloseSession(); + + //reload parents + List<CurriculumElement> parentLine = curriculumElementDao.getParentLine(element3); + Assert.assertNotNull(parentLine); + Assert.assertEquals(4, parentLine.size()); + Assert.assertEquals(parentElement, parentLine.get(0)); + Assert.assertEquals(element1, parentLine.get(1)); + Assert.assertEquals(element2, parentLine.get(2)); + Assert.assertEquals(element3, parentLine.get(3)); + } + + @Test + public void getDescendants() { + Curriculum curriculum = curriculumDao.createAndPersist("cur-for-el-5", "Curriculum for element", "Curriculum", null); + CurriculumElement parentElement = curriculumElementDao.createCurriculumElement("Element-5", "5. Element", null, null, null, null, curriculum); + dbInstance.commit(); + // save 3 children + CurriculumElement element1 = curriculumElementDao.createCurriculumElement("Element-5-1", "5.1 Element", null, null, parentElement, null, curriculum); + dbInstance.commit(); + CurriculumElement element1_1 = curriculumElementDao.createCurriculumElement("Element-5-1-1", "5.1.1 Element", null, null, element1, null, curriculum); + dbInstance.commit(); + CurriculumElement element2 = curriculumElementDao.createCurriculumElement("Element-5-2", "5.2 Element", null, null, parentElement, null, curriculum); + dbInstance.commitAndCloseSession(); + + // load descendants of the root element + List<CurriculumElement> descendants = curriculumElementDao.getDescendants(parentElement); + Assert.assertNotNull(descendants); + Assert.assertEquals(3, descendants.size()); + Assert.assertTrue(descendants.contains(element1)); + Assert.assertTrue(descendants.contains(element1_1)); + Assert.assertTrue(descendants.contains(element2)); + } + + @Test + public void moveCurriculumElement() { + Curriculum curriculum = curriculumDao.createAndPersist("cur-for-el-7", "Curriculum for element", "Curriculum", null); + CurriculumElement rootElement = curriculumElementDao.createCurriculumElement("Element-7", "7. Element", null, null, null, null, curriculum); + CurriculumElement element1 = curriculumElementDao.createCurriculumElement("Element-7-1", "7.1 Element", null, null, rootElement, null, curriculum); + CurriculumElement element1_1 = curriculumElementDao.createCurriculumElement("Element-7-1-1", "7.1.1 Element", null, null, element1, null, curriculum); + CurriculumElement element1_1_1 = curriculumElementDao.createCurriculumElement("Element-7-1-1", "7.1.1 Element", null, null, element1_1, null, curriculum); + CurriculumElement element1_1_2 = curriculumElementDao.createCurriculumElement("Element-7-1-2", "7.1.2 Element", null, null, element1_1, null, curriculum); + CurriculumElement element2 = curriculumElementDao.createCurriculumElement("Element-7-2", "7.2 Element", null, null, rootElement, null, curriculum); + dbInstance.commitAndCloseSession(); + + // move element1_1 under element2 + curriculumElementDao.move(element1_1, element2); + dbInstance.commit(); + + // check parent line of element1_1_2 + CurriculumElement reloadElement1_1_2 = curriculumElementDao.loadByKey(element1_1_2.getKey()); + List<CurriculumElement> parentLine1_1_2 = curriculumElementDao.getParentLine(reloadElement1_1_2); + Assert.assertNotNull(parentLine1_1_2); + Assert.assertEquals(4, parentLine1_1_2.size()); + Assert.assertEquals(rootElement, parentLine1_1_2.get(0)); + Assert.assertEquals(element2, parentLine1_1_2.get(1)); + Assert.assertEquals(element1_1, parentLine1_1_2.get(2)); + Assert.assertEquals(element1_1_2, parentLine1_1_2.get(3)); + + // check descendants element1_1 + CurriculumElement reloadElement1_1 = curriculumElementDao.loadByKey(element1_1.getKey()); + List<CurriculumElement> descendants1_1 = curriculumElementDao.getDescendants(reloadElement1_1); + Assert.assertNotNull(descendants1_1); + Assert.assertEquals(2, descendants1_1.size()); + Assert.assertTrue(descendants1_1.contains(element1_1_1)); + Assert.assertTrue(descendants1_1.contains(element1_1_2)); + } + @Test public void getMembers() { Identity supervisor = JunitTestHelper.createAndPersistIdentityAsRndUser("cur-supervisor-1"); Curriculum curriculum = curriculumService.createCurriculum("cur-for-el-4", "Curriculum for element", "Curriculum", null); - CurriculumElement element = curriculumService.createCurriculumElement("Element-4", "4. Element", null, curriculum); + CurriculumElement element = curriculumService.createCurriculumElement("Element-4", "4. Element", null, null, null, null, curriculum); curriculumService.addMember(element, supervisor, CurriculumRoles.supervisor); dbInstance.commitAndCloseSession(); @@ -126,5 +235,4 @@ public class CurriculumElementDAOTest extends OlatTestCase { Assert.assertEquals(supervisor, member.getIdentity()); Assert.assertEquals(CurriculumRoles.supervisor.name(), member.getRole()); } - } diff --git a/src/test/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAOTest.java b/src/test/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAOTest.java index ff64c1a41bb..91a92fa0179 100644 --- a/src/test/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAOTest.java +++ b/src/test/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAOTest.java @@ -33,7 +33,7 @@ public class CurriculumRepositoryEntryRelationDAOTest extends OlatTestCase { @Test public void createRelation() { Curriculum curriculum = curriculumService.createCurriculum("cur-el-rel-1", "Curriculum for relation", "Curriculum", null); - CurriculumElement element = curriculumService.createCurriculumElement("Element-for-rel", "Element for relation", null, curriculum); + CurriculumElement element = curriculumService.createCurriculumElement("Element-for-rel", "Element for relation", null, null, null, null, curriculum); Identity author = JunitTestHelper.createAndPersistIdentityAsRndUser("cur-el-re-auth"); RepositoryEntry entry = JunitTestHelper.createRandomRepositoryEntry(author); dbInstance.commitAndCloseSession(); @@ -52,7 +52,7 @@ public class CurriculumRepositoryEntryRelationDAOTest extends OlatTestCase { @Test public void getRepositoryEntries() { Curriculum curriculum = curriculumService.createCurriculum("cur-el-rel-2", "Curriculum for relation", "Curriculum", null); - CurriculumElement element = curriculumService.createCurriculumElement("Element-for-rel", "Element for relation", null, curriculum); + CurriculumElement element = curriculumService.createCurriculumElement("Element-for-rel", "Element for relation", null, null, null, null, curriculum); Identity author = JunitTestHelper.createAndPersistIdentityAsRndUser("cur-el-re-auth"); RepositoryEntry entry = JunitTestHelper.createRandomRepositoryEntry(author); dbInstance.commit(); @@ -69,7 +69,7 @@ public class CurriculumRepositoryEntryRelationDAOTest extends OlatTestCase { @Test public void getCurriculumElements() { Curriculum curriculum = curriculumService.createCurriculum("cur-el-rel-2", "Curriculum for relation", "Curriculum", null); - CurriculumElement element = curriculumService.createCurriculumElement("Element-for-rel", "Element for relation", null, curriculum); + CurriculumElement element = curriculumService.createCurriculumElement("Element-for-rel", "Element for relation", null, null, null, null, curriculum); Identity author = JunitTestHelper.createAndPersistIdentityAsRndUser("cur-el-re-auth"); RepositoryEntry entry = JunitTestHelper.createRandomRepositoryEntry(author); dbInstance.commit(); -- GitLab