From 7487e9290bc57359fac55ce1abbec14a81937c93 Mon Sep 17 00:00:00 2001 From: uhensler <urs.hensler@frentix.com> Date: Wed, 27 May 2020 10:51:20 +0200 Subject: [PATCH] OO-4708: Black lists in quality generators --- .../generator/QualityGeneratorProvider.java | 10 +- .../generator/QualityGeneratorService.java | 9 +- .../manager/QualityGeneratorServiceImpl.java | 20 +- .../provider/course/CourseProvider.java | 23 +- .../course/manager/CourseProviderDAO.java | 17 +- .../course/manager/SearchParameters.java | 47 ++- .../CourseLecturesFollowUpProvider.java | 16 +- .../CourseLecturesProvider.java | 19 +- .../manager/CourseLecturesProviderDAO.java | 40 ++- .../manager/SearchParameters.java | 28 +- .../CurriculumElementProvider.java | 23 +- .../manager/CurriculumElementProviderDAO.java | 18 +- .../manager/SearchParameters.java | 29 +- .../provider/fallback/FallbackProvider.java | 16 +- .../CurriculumElementBlackListController.java | 65 ++++ .../ui/CurriculumElementListController.java | 289 +++++++++++++++++ ...va => CurriculumElementListDataModel.java} | 6 +- .../CurriculumElementWhiteListController.java | 247 +-------------- .../generator/ui/GeneratorController.java | 19 +- .../ui/GeneratorWhiteListController.java | 32 -- .../RepositoryEntryBlackListController.java | 63 ++++ .../ui/RepositoryEntryListController.java | 291 ++++++++++++++++++ ...java => RepositoryEntryListDataModel.java} | 6 +- .../RepositoryEntryWhiteListController.java | 245 +-------------- .../ui/_i18n/LocalStrings_de.properties | 1 + .../ui/_i18n/LocalStrings_en.properties | 1 + .../course/manager/CourseProviderDAOTest.java | 20 +- .../CourseLecturesProviderDAOTest.java | 39 ++- .../CurriculumElementProviderTest.java | 4 +- .../CurriculumElementProviderDAOTest.java | 32 +- 30 files changed, 1090 insertions(+), 585 deletions(-) create mode 100644 src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementBlackListController.java create mode 100644 src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementListController.java rename src/main/java/org/olat/modules/quality/generator/ui/{CurriculumElementWhiteListDataModel.java => CurriculumElementListDataModel.java} (92%) delete mode 100644 src/main/java/org/olat/modules/quality/generator/ui/GeneratorWhiteListController.java create mode 100644 src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryBlackListController.java create mode 100644 src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryListController.java rename src/main/java/org/olat/modules/quality/generator/ui/{RepositoryEntryWhiteListDataModel.java => RepositoryEntryListDataModel.java} (92%) diff --git a/src/main/java/org/olat/modules/quality/generator/QualityGeneratorProvider.java b/src/main/java/org/olat/modules/quality/generator/QualityGeneratorProvider.java index ffd0b973642..85cce02502d 100644 --- a/src/main/java/org/olat/modules/quality/generator/QualityGeneratorProvider.java +++ b/src/main/java/org/olat/modules/quality/generator/QualityGeneratorProvider.java @@ -26,9 +26,9 @@ import java.util.Locale; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.modules.quality.QualityDataCollection; -import org.olat.modules.quality.generator.ui.GeneratorWhiteListController; import org.olat.modules.quality.generator.ui.ProviderConfigController; import org.olat.modules.quality.ui.security.GeneratorSecurityCallback; @@ -52,7 +52,13 @@ public interface QualityGeneratorProvider { public boolean hasWhiteListController(); - public GeneratorWhiteListController getWhiteListController(UserRequest ureq, WindowControl wControl, + public Controller getWhiteListController(UserRequest ureq, WindowControl wControl, + GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, + QualityGeneratorConfigs configs); + + public boolean hasBlackListController(); + + public Controller getBlackListController(UserRequest ureq, WindowControl wControl, GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, QualityGeneratorConfigs configs); diff --git a/src/main/java/org/olat/modules/quality/generator/QualityGeneratorService.java b/src/main/java/org/olat/modules/quality/generator/QualityGeneratorService.java index b0467eeb65d..0319f2a8f76 100644 --- a/src/main/java/org/olat/modules/quality/generator/QualityGeneratorService.java +++ b/src/main/java/org/olat/modules/quality/generator/QualityGeneratorService.java @@ -27,10 +27,10 @@ import java.util.Locale; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Organisation; import org.olat.modules.quality.QualityGeneratorProviderReferenceable; -import org.olat.modules.quality.generator.ui.GeneratorWhiteListController; import org.olat.modules.quality.generator.ui.ProviderConfigController; import org.olat.modules.quality.ui.security.GeneratorSecurityCallback; @@ -69,7 +69,12 @@ public interface QualityGeneratorService { public boolean hasWhiteListController(QualityGenerator generator); - public GeneratorWhiteListController getWhiteListController(UserRequest ureq, WindowControl wControl, + public Controller getWhiteListController(UserRequest ureq, WindowControl wControl, + GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator); + + public boolean hasBlackListController(QualityGenerator generator); + + public Controller getBlackListController(UserRequest ureq, WindowControl wControl, GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator); public void generateDataCollections(); diff --git a/src/main/java/org/olat/modules/quality/generator/manager/QualityGeneratorServiceImpl.java b/src/main/java/org/olat/modules/quality/generator/manager/QualityGeneratorServiceImpl.java index 114de2f24d7..6a41bed7af9 100644 --- a/src/main/java/org/olat/modules/quality/generator/manager/QualityGeneratorServiceImpl.java +++ b/src/main/java/org/olat/modules/quality/generator/manager/QualityGeneratorServiceImpl.java @@ -30,12 +30,13 @@ import java.util.List; import java.util.Locale; import java.util.Set; +import org.apache.logging.log4j.Logger; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Organisation; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.modules.quality.QualityDataCollection; import org.olat.modules.quality.QualityGeneratorProviderReferenceable; @@ -50,7 +51,6 @@ import org.olat.modules.quality.generator.QualityGeneratorSearchParams; import org.olat.modules.quality.generator.QualityGeneratorService; import org.olat.modules.quality.generator.QualityGeneratorToOrganisation; import org.olat.modules.quality.generator.QualityGeneratorView; -import org.olat.modules.quality.generator.ui.GeneratorWhiteListController; import org.olat.modules.quality.generator.ui.ProviderConfigController; import org.olat.modules.quality.ui.security.GeneratorSecurityCallback; import org.springframework.beans.factory.annotation.Autowired; @@ -177,13 +177,27 @@ public class QualityGeneratorServiceImpl implements QualityGeneratorService { } @Override - public GeneratorWhiteListController getWhiteListController(UserRequest ureq, WindowControl wControl, + public Controller getWhiteListController(UserRequest ureq, WindowControl wControl, GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator) { QualityGeneratorProvider provider = providerFactory.getProvider(generator.getType()); QualityGeneratorConfigsImpl configs = new QualityGeneratorConfigsImpl(generator); return provider.getWhiteListController(ureq, wControl, secCallback, stackPanel, generator, configs); } + @Override + public boolean hasBlackListController(QualityGenerator generator) { + QualityGeneratorProvider provider = providerFactory.getProvider(generator.getType()); + return provider.hasBlackListController(); + } + + @Override + public Controller getBlackListController(UserRequest ureq, WindowControl wControl, + GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator) { + QualityGeneratorProvider provider = providerFactory.getProvider(generator.getType()); + QualityGeneratorConfigsImpl configs = new QualityGeneratorConfigsImpl(generator); + return provider.getBlackListController(ureq, wControl, secCallback, stackPanel, generator, configs); + } + @Override public void generateDataCollections() { List<QualityGenerator> generators = generatorDao.loadEnabledGenerators(); diff --git a/src/main/java/org/olat/modules/quality/generator/provider/course/CourseProvider.java b/src/main/java/org/olat/modules/quality/generator/provider/course/CourseProvider.java index 9ad85b0346a..7c843b9d1bb 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/course/CourseProvider.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/course/CourseProvider.java @@ -39,6 +39,7 @@ import org.olat.basesecurity.GroupRoles; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; @@ -62,8 +63,8 @@ import org.olat.modules.quality.generator.TitleCreator; import org.olat.modules.quality.generator.provider.course.manager.CourseProviderDAO; import org.olat.modules.quality.generator.provider.course.manager.SearchParameters; import org.olat.modules.quality.generator.provider.course.ui.CourseProviderConfigController; -import org.olat.modules.quality.generator.ui.GeneratorWhiteListController; import org.olat.modules.quality.generator.ui.ProviderConfigController; +import org.olat.modules.quality.generator.ui.RepositoryEntryBlackListController; import org.olat.modules.quality.generator.ui.RepositoryEntryWhiteListController; import org.olat.modules.quality.ui.security.GeneratorSecurityCallback; import org.olat.repository.RepositoryEntry; @@ -162,12 +163,24 @@ public class CourseProvider implements QualityGeneratorProvider { } @Override - public GeneratorWhiteListController getWhiteListController(UserRequest ureq, WindowControl wControl, + public Controller getWhiteListController(UserRequest ureq, WindowControl wControl, GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, QualityGeneratorConfigs configs) { return new RepositoryEntryWhiteListController(ureq, wControl, stackPanel, configs); } + @Override + public boolean hasBlackListController() { + return true; + } + + @Override + public Controller getBlackListController(UserRequest ureq, WindowControl wControl, + GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, + QualityGeneratorConfigs configs) { + return new RepositoryEntryBlackListController(ureq, wControl, stackPanel, configs); + } + @Override public List<QualityDataCollection> generate(QualityGenerator generator, QualityGeneratorConfigs configs, Date fromDate, Date toDate) { List<Organisation> organisations = generatorService.loadGeneratorOrganisations(generator); @@ -344,8 +357,10 @@ public class CourseProvider implements QualityGeneratorProvider { SearchParameters searchParams = new SearchParameters(); searchParams.setGeneratorRef(generator); searchParams.setOrganisationRefs(organisations); - List<RepositoryEntryRef> repositoryEntryRefs = RepositoryEntryWhiteListController.getRepositoryEntryRefs(configs); - searchParams.setRepositoryEntryRefs(repositoryEntryRefs); + List<RepositoryEntryRef> whiteListRefs = RepositoryEntryWhiteListController.getRepositoryEntryRefs(configs); + searchParams.setWhiteListRefs(whiteListRefs); + List<RepositoryEntryRef> blackListRefs = RepositoryEntryBlackListController.getRepositoryEntryRefs(configs); + searchParams.setBlackListRefs(blackListRefs); return searchParams; } diff --git a/src/main/java/org/olat/modules/quality/generator/provider/course/manager/CourseProviderDAO.java b/src/main/java/org/olat/modules/quality/generator/provider/course/manager/CourseProviderDAO.java index 82e14f80773..b4f60660abb 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/course/manager/CourseProviderDAO.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/course/manager/CourseProviderDAO.java @@ -119,8 +119,11 @@ public class CourseProviderDAO { sb.and(); sb.append("(lifecycle.validTo >= :validAt or lifecycle.validTo is null)"); } - if (searchParams.getRepositoryEntryRefs() != null && !searchParams.getRepositoryEntryRefs().isEmpty()) { - sb.and().append("entry.key in :repositoryKeys"); + if (searchParams.getWhiteListRefs() != null && !searchParams.getWhiteListRefs().isEmpty()) { + sb.and().append("entry.key in (:whiteListKeys)"); + } + if (searchParams.getBlackListRefs() != null && !searchParams.getBlackListRefs().isEmpty()) { + sb.and().append("entry.key not in (:blackListKeys)"); } } @@ -154,9 +157,13 @@ public class CourseProviderDAO { if (searchParams.getLifecycleValidAt() != null) { query.setParameter("validAt", searchParams.getLifecycleValidAt()); } - if (searchParams.getRepositoryEntryRefs() != null && !searchParams.getRepositoryEntryRefs().isEmpty()) { - List<Long> keys = searchParams.getRepositoryEntryRefs().stream().map(RepositoryEntryRef::getKey).collect(toList()); - query.setParameter("repositoryKeys", keys); + if (searchParams.getWhiteListRefs() != null && !searchParams.getWhiteListRefs().isEmpty()) { + List<Long> keys = searchParams.getWhiteListRefs().stream().map(RepositoryEntryRef::getKey).collect(toList()); + query.setParameter("whiteListKeys", keys); + } + if (searchParams.getBlackListRefs() != null && !searchParams.getBlackListRefs().isEmpty()) { + List<Long> keys = searchParams.getBlackListRefs().stream().map(RepositoryEntryRef::getKey).collect(toList()); + query.setParameter("blackListKeys", keys); } } diff --git a/src/main/java/org/olat/modules/quality/generator/provider/course/manager/SearchParameters.java b/src/main/java/org/olat/modules/quality/generator/provider/course/manager/SearchParameters.java index f29cb519ee6..bb67c0e4837 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/course/manager/SearchParameters.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/course/manager/SearchParameters.java @@ -44,7 +44,8 @@ public class SearchParameters { private Date endFrom; private Date endTo; private Date lifecycleValidAt; - private Collection<? extends RepositoryEntryRef> repositoryEntryRefs; + private Collection<? extends RepositoryEntryRef> whiteListRefs; + private Collection<? extends RepositoryEntryRef> blackListRefs; public QualityGeneratorRef getGeneratorRef() { return generatorRef; @@ -53,6 +54,14 @@ public class SearchParameters { public void setGeneratorRef(QualityGeneratorRef generatorRef) { this.generatorRef = generatorRef; } + + public Date getGeneratorDataCollectionStart() { + return generatorDataCollectionStart; + } + + public void setGeneratorDataCollectionStart(Date generatorDataCollectionStart) { + this.generatorDataCollectionStart = generatorDataCollectionStart; + } public List<? extends OrganisationRef> getOrganisationRefs() { return organisationRefs; @@ -101,23 +110,23 @@ public class SearchParameters { public void setLifecycleValidAt(Date lifecycleValidAt) { this.lifecycleValidAt = lifecycleValidAt; } - - public Collection<? extends RepositoryEntryRef> getRepositoryEntryRefs() { - return repositoryEntryRefs; + + public Collection<? extends RepositoryEntryRef> getWhiteListRefs() { + return whiteListRefs; } - public void setRepositoryEntryRefs(Collection<? extends RepositoryEntryRef> repositoryEntryRefs) { - this.repositoryEntryRefs = repositoryEntryRefs; + public void setWhiteListRefs(Collection<? extends RepositoryEntryRef> whiteListRefs) { + this.whiteListRefs = whiteListRefs; } - public Date getGeneratorDataCollectionStart() { - return generatorDataCollectionStart; + public Collection<? extends RepositoryEntryRef> getBlackListRefs() { + return blackListRefs; } - - public void setGeneratorDataCollectionStart(Date generatorDataCollectionStart) { - this.generatorDataCollectionStart = generatorDataCollectionStart; + + public void setBlackListRefs(Collection<? extends RepositoryEntryRef> blackListRefs) { + this.blackListRefs = blackListRefs; } - + @Override public String toString() { StringBuilder builder = new StringBuilder(); @@ -137,8 +146,18 @@ public class SearchParameters { builder.append(endFrom); builder.append(", endTo="); builder.append(endTo); - builder.append(", repositoryEntryRefs="); - builder.append(repositoryEntryRefs); + builder.append(", whiteListRefs (keys)=["); + builder.append(whiteListRefs.stream() + .map(RepositoryEntryRef::getKey) + .map(r -> r.toString()) + .collect(Collectors.joining(", "))); + builder.append("]"); + builder.append(", blackListRefs (keys)=["); + builder.append(blackListRefs.stream() + .map(RepositoryEntryRef::getKey) + .map(r -> r.toString()) + .collect(Collectors.joining(", "))); + builder.append("]"); builder.append(", generatorDataCollectionStart="); builder.append(generatorDataCollectionStart); builder.append("]"); diff --git a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesFollowUpProvider.java b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesFollowUpProvider.java index 0f5a3370776..7b39cecea07 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesFollowUpProvider.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesFollowUpProvider.java @@ -37,6 +37,7 @@ import org.olat.basesecurity.GroupRoles; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; @@ -70,7 +71,6 @@ import org.olat.modules.quality.generator.provider.courselectures.manager.Course import org.olat.modules.quality.generator.provider.courselectures.manager.LectureBlockInfo; import org.olat.modules.quality.generator.provider.courselectures.manager.SearchParameters; import org.olat.modules.quality.generator.provider.courselectures.ui.CourseLectureFollowUpProviderConfigController; -import org.olat.modules.quality.generator.ui.GeneratorWhiteListController; import org.olat.modules.quality.generator.ui.ProviderConfigController; import org.olat.modules.quality.ui.security.GeneratorSecurityCallback; import org.olat.repository.RepositoryEntry; @@ -161,7 +161,19 @@ public class CourseLecturesFollowUpProvider implements QualityGeneratorProvider } @Override - public GeneratorWhiteListController getWhiteListController(UserRequest ureq, WindowControl wControl, + public Controller getWhiteListController(UserRequest ureq, WindowControl wControl, + GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, + QualityGeneratorConfigs configs) { + return null; + } + + @Override + public boolean hasBlackListController() { + return false; + } + + @Override + public Controller getBlackListController(UserRequest ureq, WindowControl wControl, GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, QualityGeneratorConfigs configs) { return null; diff --git a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProvider.java b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProvider.java index 787136f4491..6bca758878f 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProvider.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/CourseLecturesProvider.java @@ -37,6 +37,7 @@ import org.olat.basesecurity.GroupRoles; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; @@ -61,8 +62,8 @@ import org.olat.modules.quality.generator.provider.courselectures.manager.Course import org.olat.modules.quality.generator.provider.courselectures.manager.LectureBlockInfo; import org.olat.modules.quality.generator.provider.courselectures.manager.SearchParameters; import org.olat.modules.quality.generator.provider.courselectures.ui.CourseLectureProviderConfigController; +import org.olat.modules.quality.generator.ui.CurriculumElementBlackListController; import org.olat.modules.quality.generator.ui.CurriculumElementWhiteListController; -import org.olat.modules.quality.generator.ui.GeneratorWhiteListController; import org.olat.modules.quality.generator.ui.ProviderConfigController; import org.olat.modules.quality.ui.security.GeneratorSecurityCallback; import org.olat.repository.RepositoryEntry; @@ -159,12 +160,24 @@ public class CourseLecturesProvider implements QualityGeneratorProvider { } @Override - public GeneratorWhiteListController getWhiteListController(UserRequest ureq, WindowControl wControl, + public Controller getWhiteListController(UserRequest ureq, WindowControl wControl, GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, QualityGeneratorConfigs configs) { return new CurriculumElementWhiteListController(ureq, wControl, stackPanel, generator, configs); } + @Override + public boolean hasBlackListController() { + return true; + } + + @Override + public Controller getBlackListController(UserRequest ureq, WindowControl wControl, + GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, + QualityGeneratorConfigs configs) { + return new CurriculumElementBlackListController(ureq, wControl, stackPanel, generator, configs); + } + @Override public List<QualityDataCollection> generate(QualityGenerator generator, QualityGeneratorConfigs configs, Date fromDate, Date toDate) { @@ -311,7 +324,7 @@ public class CourseLecturesProvider implements QualityGeneratorProvider { searchParams.setTo(to); Collection<CurriculumElementRef> curriculumElementRefs = CurriculumElementWhiteListController.getCurriculumElementRefs(configs); - searchParams.setCurriculumElementRefs(curriculumElementRefs); + searchParams.setWhiteListRefs(curriculumElementRefs); String minLectures = configs.getValue(CONFIG_KEY_TOTAL_LECTURES_MIN); if (StringHelper.containsNonWhitespace(minLectures)) { diff --git a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAO.java b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAO.java index 5c19db727b8..1e5187d1638 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAO.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAO.java @@ -165,7 +165,7 @@ public class CourseLecturesProviderDAO { if (!searchParams.getCourseRefs().isEmpty()) { sb.and().append("lb.fk_entry in :courseKeys"); } - if (!searchParams.getCurriculumElementRefs().isEmpty()) { + if (!searchParams.getWhiteListRefs().isEmpty()) { sb.and(); sb.append("lb.fk_entry in ("); sb.append(" select distinct v.repositoryentry_id"); @@ -174,7 +174,19 @@ public class CourseLecturesProviderDAO { sb.append(" on rel.fk_entry_id = v.repositoryentry_id"); sb.append(" inner join o_cur_curriculum_element el"); sb.append(" on el.fk_group = rel.fk_group_id"); - sb.append(" where el.id in :curriculumElementKeys"); + sb.append(" where el.id in (:whiteListKeys)"); + sb.append(" )"); + } + if (!searchParams.getBlackListRefs().isEmpty()) { + sb.and(); + sb.append("lb.fk_entry not in ("); + sb.append(" select distinct v.repositoryentry_id"); + sb.append(" from o_repositoryentry v"); + sb.append(" inner join o_re_to_group rel"); + sb.append(" on rel.fk_entry_id = v.repositoryentry_id"); + sb.append(" inner join o_cur_curriculum_element el"); + sb.append(" on el.fk_group = rel.fk_group_id"); + sb.append(" where el.id in (:blackListKeys)"); sb.append(" )"); } if (searchParams.getFinishedDataCollectionForGeneratorAndTopicIdentityRef() != null) { @@ -386,14 +398,24 @@ public class CourseLecturesProviderDAO { if (!searchParams.getCourseRefs().isEmpty()) { sb.and().append("course.key in :courseKeys"); } - if (!searchParams.getCurriculumElementRefs().isEmpty()) { + if (!searchParams.getWhiteListRefs().isEmpty()) { sb.and(); sb.append("course.key in ("); sb.append(" select distinct v.key"); sb.append(" from repositoryentry as v"); sb.append(" inner join v.groups as rel"); sb.append(" inner join curriculumelement as el on (el.group.key=rel.group.key)"); - sb.append(" where el.key in :curriculumElementKeys"); + sb.append(" where el.key in (:whiteListKeys)"); + sb.append(" )"); + } + if (!searchParams.getBlackListRefs().isEmpty()) { + sb.and(); + sb.append("course.key not in ("); + sb.append(" select distinct v.key"); + sb.append(" from repositoryentry as v"); + sb.append(" inner join v.groups as rel"); + sb.append(" inner join curriculumelement as el on (el.group.key=rel.group.key)"); + sb.append(" where el.key in (:blackListKeys)"); sb.append(" )"); } if (!searchParams.getOrganisationRefs().isEmpty()) { @@ -443,9 +465,13 @@ public class CourseLecturesProviderDAO { List<Long> courseKeys = searchParams.getCourseRefs().stream().map(RepositoryEntryRef::getKey).collect(Collectors.toList()); query.setParameter("courseKeys", courseKeys); } - if (!searchParams.getCurriculumElementRefs().isEmpty()) { - List<Long> curriculumElementKeys = searchParams.getCurriculumElementRefs().stream().map(CurriculumElementRef::getKey).collect(Collectors.toList()); - query.setParameter("curriculumElementKeys", curriculumElementKeys); + if (!searchParams.getWhiteListRefs().isEmpty()) { + List<Long> curriculumElementKeys = searchParams.getWhiteListRefs().stream().map(CurriculumElementRef::getKey).collect(Collectors.toList()); + query.setParameter("whiteListKeys", curriculumElementKeys); + } + if (!searchParams.getBlackListRefs().isEmpty()) { + List<Long> curriculumElementKeys = searchParams.getBlackListRefs().stream().map(CurriculumElementRef::getKey).collect(Collectors.toList()); + query.setParameter("blackListKeys", curriculumElementKeys); } if (!searchParams.getOrganisationRefs().isEmpty()) { for (int i = 0; i < searchParams.getOrganisationRefs().size(); i++) { diff --git a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/manager/SearchParameters.java b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/manager/SearchParameters.java index 1cca0393d98..f4db3dc9e10 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/courselectures/manager/SearchParameters.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/courselectures/manager/SearchParameters.java @@ -50,7 +50,8 @@ public class SearchParameters { private QualityGeneratorRef excludeGeneratorAndTopicRepositoryRef; private IdentityRef teacherRef; private Collection<? extends RepositoryEntryRef> courseRefs; - private Collection<? extends CurriculumElementRef> curriculumElementRefs; + private Collection<? extends CurriculumElementRef> whiteListRefs; + private Collection<? extends CurriculumElementRef> blackListRefs; private List<? extends OrganisationRef> organisationRefs; private Date from; private Date to; @@ -138,15 +139,26 @@ public class SearchParameters { this.courseRefs = courseRefs; } - public Collection<? extends CurriculumElementRef> getCurriculumElementRefs() { - if (curriculumElementRefs == null) { - curriculumElementRefs = Collections.emptyList(); + public Collection<? extends CurriculumElementRef> getWhiteListRefs() { + if (whiteListRefs == null) { + whiteListRefs = Collections.emptyList(); } - return curriculumElementRefs; + return whiteListRefs; } - public void setCurriculumElementRefs(Collection<? extends CurriculumElementRef> curriculumElementRefs) { - this.curriculumElementRefs = curriculumElementRefs; + public void setWhiteListRefs(Collection<? extends CurriculumElementRef> whiteListRefs) { + this.whiteListRefs = whiteListRefs; + } + + public Collection<? extends CurriculumElementRef> getBlackListRefs() { + if (blackListRefs == null) { + blackListRefs = Collections.emptyList(); + } + return blackListRefs; + } + + public void setBlackListRefs(Collection<? extends CurriculumElementRef> blackListRefs) { + this.blackListRefs = blackListRefs; } public List<? extends OrganisationRef> getOrganisationRefs() { @@ -200,7 +212,7 @@ public class SearchParameters { builder.append(", courseRefs="); builder.append(courseRefs); builder.append(", curriculumElementRefs={"); - builder.append(curriculumElementRefs.stream() + builder.append(whiteListRefs.stream() .map(CurriculumElementRef::getKey) .map(k -> k.toString()) .collect(Collectors.joining(", "))); diff --git a/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/CurriculumElementProvider.java b/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/CurriculumElementProvider.java index ade5a38b510..acf4381ed3d 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/CurriculumElementProvider.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/CurriculumElementProvider.java @@ -33,6 +33,7 @@ import org.apache.logging.log4j.Logger; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; @@ -58,8 +59,8 @@ import org.olat.modules.quality.generator.TitleCreator; import org.olat.modules.quality.generator.provider.curriculumelement.manager.CurriculumElementProviderDAO; import org.olat.modules.quality.generator.provider.curriculumelement.manager.SearchParameters; import org.olat.modules.quality.generator.provider.curriculumelement.ui.CurriculumElementProviderConfigController; +import org.olat.modules.quality.generator.ui.CurriculumElementBlackListController; import org.olat.modules.quality.generator.ui.CurriculumElementWhiteListController; -import org.olat.modules.quality.generator.ui.GeneratorWhiteListController; import org.olat.modules.quality.generator.ui.ProviderConfigController; import org.olat.modules.quality.ui.security.GeneratorSecurityCallback; import org.olat.repository.RepositoryEntry; @@ -136,12 +137,24 @@ public class CurriculumElementProvider implements QualityGeneratorProvider { } @Override - public GeneratorWhiteListController getWhiteListController(UserRequest ureq, WindowControl wControl, + public Controller getWhiteListController(UserRequest ureq, WindowControl wControl, GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, QualityGeneratorConfigs configs) { return new CurriculumElementWhiteListController(ureq, wControl, stackPanel, generator, configs); } + @Override + public boolean hasBlackListController() { + return true; + } + + @Override + public Controller getBlackListController(UserRequest ureq, WindowControl wControl, + GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, + QualityGeneratorConfigs configs) { + return new CurriculumElementBlackListController(ureq, wControl, stackPanel, generator, configs); + } + @Override public List<QualityDataCollection> generate(QualityGenerator generator, QualityGeneratorConfigs configs, Date fromDate, Date toDate) { @@ -255,8 +268,10 @@ public class CurriculumElementProvider implements QualityGeneratorProvider { searchParams.setStartDate(false); } - List<CurriculumElementRef> curriculumElementRefs = CurriculumElementWhiteListController.getCurriculumElementRefs(configs); - searchParams.setCurriculumElementRefs(curriculumElementRefs); + List<CurriculumElementRef> whiteListRefs = CurriculumElementWhiteListController.getCurriculumElementRefs(configs); + searchParams.setWhiteListRefs(whiteListRefs); + List<CurriculumElementRef> blackListRefs = CurriculumElementBlackListController.getCurriculumElementRefs(configs); + searchParams.setBlackListRefs(blackListRefs); return searchParams; } diff --git a/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/CurriculumElementProviderDAO.java b/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/CurriculumElementProviderDAO.java index e20c2a209d8..cffcef81e34 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/CurriculumElementProviderDAO.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/CurriculumElementProviderDAO.java @@ -98,8 +98,11 @@ public class CurriculumElementProviderDAO { } } } - if (searchParams.getCurriculumElementRefs() != null && !searchParams.getCurriculumElementRefs().isEmpty()) { - sb.and().append("curEle.key in :curEleKeys"); + if (searchParams.getWhiteListRefs() != null && !searchParams.getWhiteListRefs().isEmpty()) { + sb.and().append("curEle.key in (:whiteListKeys)"); + } + if (searchParams.getBlackListRefs() != null && !searchParams.getBlackListRefs().isEmpty()) { + sb.and().append("curEle.key not in (:blackListKeys)"); } } @@ -130,10 +133,15 @@ public class CurriculumElementProviderDAO { query.setParameter(parameter, value); } } - if (searchParams.getCurriculumElementRefs() != null && !searchParams.getCurriculumElementRefs().isEmpty()) { - List<Long> curEleKeys = searchParams.getCurriculumElementRefs().stream().map(CurriculumElementRef::getKey).collect(toList()); - query.setParameter("curEleKeys", curEleKeys); + if (searchParams.getWhiteListRefs() != null && !searchParams.getWhiteListRefs().isEmpty()) { + List<Long> curEleKeys = searchParams.getWhiteListRefs().stream().map(CurriculumElementRef::getKey).collect(toList()); + query.setParameter("whiteListKeys", curEleKeys); + } + if (searchParams.getBlackListRefs() != null && !searchParams.getBlackListRefs().isEmpty()) { + List<Long> curEleKeys = searchParams.getBlackListRefs().stream().map(CurriculumElementRef::getKey).collect(toList()); + query.setParameter("blackListKeys", curEleKeys); } + } } diff --git a/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/SearchParameters.java b/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/SearchParameters.java index 3bf4a96d8fb..454367a7e82 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/SearchParameters.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/SearchParameters.java @@ -39,7 +39,8 @@ public class SearchParameters { private QualityGeneratorRef generatorRef; private List<? extends OrganisationRef> organisationRefs; private Long ceTypeKey; - private Collection<? extends CurriculumElementRef> curriculumElementRefs; + private Collection<? extends CurriculumElementRef> whiteListRefs; + private Collection<? extends CurriculumElementRef> blackListRefs; private Date from; private Date to; private boolean startDate; @@ -60,12 +61,20 @@ public class SearchParameters { this.organisationRefs = organisations; } - public Collection<? extends CurriculumElementRef> getCurriculumElementRefs() { - return curriculumElementRefs; + public Collection<? extends CurriculumElementRef> getWhiteListRefs() { + return whiteListRefs; } - public void setCurriculumElementRefs(Collection<? extends CurriculumElementRef> curriculumElementRefs) { - this.curriculumElementRefs = curriculumElementRefs; + public void setWhiteListRefs(Collection<? extends CurriculumElementRef> whiteListRefs) { + this.whiteListRefs = whiteListRefs; + } + + public Collection<? extends CurriculumElementRef> getBlackListRefs() { + return blackListRefs; + } + + public void setBlackListRefs(Collection<? extends CurriculumElementRef> blackListRefs) { + this.blackListRefs = blackListRefs; } public Long getCeTypeKey() { @@ -111,8 +120,14 @@ public class SearchParameters { builder.append("]"); builder.append(", ceTypeKey="); builder.append(ceTypeKey); - builder.append(", curriculumElementRefs="); - builder.append(curriculumElementRefs); + builder.append(", whiteListRefs (keys)=["); + builder.append(whiteListRefs.stream().map(CurriculumElementRef::getKey).map(ce -> ce.toString()) + .collect(Collectors.joining(", "))); + builder.append("]"); + builder.append(", blackListRefs (keys)=["); + builder.append(blackListRefs.stream().map(CurriculumElementRef::getKey).map(ce -> ce.toString()) + .collect(Collectors.joining(", "))); + builder.append("]"); builder.append(", from="); builder.append(from); builder.append(", to="); diff --git a/src/main/java/org/olat/modules/quality/generator/provider/fallback/FallbackProvider.java b/src/main/java/org/olat/modules/quality/generator/provider/fallback/FallbackProvider.java index 77930dc1f39..67ab7bef5dd 100644 --- a/src/main/java/org/olat/modules/quality/generator/provider/fallback/FallbackProvider.java +++ b/src/main/java/org/olat/modules/quality/generator/provider/fallback/FallbackProvider.java @@ -27,6 +27,7 @@ import java.util.Locale; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.translator.Translator; import org.olat.core.util.Util; @@ -35,7 +36,6 @@ import org.olat.modules.quality.generator.QualityGenerator; import org.olat.modules.quality.generator.QualityGeneratorConfigs; import org.olat.modules.quality.generator.QualityGeneratorProvider; import org.olat.modules.quality.generator.ui.GeneratorListController; -import org.olat.modules.quality.generator.ui.GeneratorWhiteListController; import org.olat.modules.quality.generator.ui.ProviderConfigController; import org.olat.modules.quality.ui.security.GeneratorSecurityCallback; import org.springframework.stereotype.Service; @@ -79,7 +79,19 @@ public class FallbackProvider implements QualityGeneratorProvider { } @Override - public GeneratorWhiteListController getWhiteListController(UserRequest ureq, WindowControl wControl, + public Controller getWhiteListController(UserRequest ureq, WindowControl wControl, + GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, + QualityGeneratorConfigs configs) { + return null; + } + + @Override + public boolean hasBlackListController() { + return false; + } + + @Override + public Controller getBlackListController(UserRequest ureq, WindowControl wControl, GeneratorSecurityCallback secCallback, TooledStackedPanel stackPanel, QualityGenerator generator, QualityGeneratorConfigs configs) { return null; diff --git a/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementBlackListController.java b/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementBlackListController.java new file mode 100644 index 00000000000..71e4392b541 --- /dev/null +++ b/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementBlackListController.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.quality.generator.ui; + +import java.util.List; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.WindowControl; +import org.olat.modules.curriculum.CurriculumElementRef; +import org.olat.modules.quality.generator.QualityGenerator; +import org.olat.modules.quality.generator.QualityGeneratorConfigs; + +/** + * + * Initial date: 27 May 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class CurriculumElementBlackListController extends CurriculumElementListController { + + private static final String CONFIG_KEY = "curriculum.element.black.list"; + + public CurriculumElementBlackListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, + QualityGenerator generator, QualityGeneratorConfigs configs) { + super(ureq, wControl, stackPanel, generator, configs); + } + + @Override + protected String getConfigKey() { + return CONFIG_KEY; + } + + @Override + protected String getTablePrefsKey() { + return "quality-ce-black-list"; + } + + public static List<CurriculumElementRef> getCurriculumElementRefs(QualityGeneratorConfigs generatorConfigs) { + return CurriculumElementListController.getCurriculumElementRefs(generatorConfigs, CONFIG_KEY); + } + + public static void setCurriculumElementRefs(QualityGeneratorConfigs generatorConfigs, + List<? extends CurriculumElementRef> elements) { + CurriculumElementListController.setCurriculumElementRefs(generatorConfigs, elements, CONFIG_KEY); + } + +} diff --git a/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementListController.java b/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementListController.java new file mode 100644 index 00000000000..2065f9abf32 --- /dev/null +++ b/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementListController.java @@ -0,0 +1,289 @@ +/** + * <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.quality.generator.ui; + +import static java.util.stream.Collectors.joining; + +import java.util.Arrays; +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.FormLayoutContainer; +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.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.stack.TooledController; +import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.components.stack.TooledStackedPanel.Align; +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.generic.closablewrapper.CloseableModalController; +import org.olat.core.id.Organisation; +import org.olat.core.util.StringHelper; +import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementRef; +import org.olat.modules.curriculum.CurriculumService; +import org.olat.modules.curriculum.model.CurriculumElementRefImpl; +import org.olat.modules.quality.generator.QualityGenerator; +import org.olat.modules.quality.generator.QualityGeneratorConfigs; +import org.olat.modules.quality.generator.QualityGeneratorService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 27 May 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public abstract class CurriculumElementListController extends FormBasicController implements TooledController { + + private static final String KEY_DELIMITER = ","; + + private FlexiTableElement tableEl; + private CurriculumElementListDataModel tableModel; + private Link addLink; + private FormLink removeLink; + + private CloseableModalController cmc; + private CurriculumElementSelectionController selectCtrl; + private CurriculumElementRemoveConfirmationController removeConfirmationCtrl; + + private final TooledStackedPanel stackPanel; + private final QualityGenerator generator; + private final QualityGeneratorConfigs configs; + + @Autowired + private QualityGeneratorService generatorService; + @Autowired + private CurriculumService curriculumService; + + public CurriculumElementListController(UserRequest ureq, WindowControl wControl, + TooledStackedPanel stackPanel, QualityGenerator generator, QualityGeneratorConfigs configs) { + super(ureq, wControl, LAYOUT_BAREBONE); + this.stackPanel = stackPanel; + this.generator = generator; + this.configs = configs; + initForm(ureq); + } + + protected abstract String getConfigKey(); + + protected abstract String getTablePrefsKey(); + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CurriculumElementListDataModel.Cols.displayName)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CurriculumElementListDataModel.Cols.identifier)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CurriculumElementListDataModel.Cols.typeName)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CurriculumElementListDataModel.Cols.begin)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CurriculumElementListDataModel.Cols.end)); + + tableModel = new CurriculumElementListDataModel(columnsModel, getLocale()); + tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, true, getTranslator(), formLayout); + tableEl.setEmtpyTableMessageKey("curriculum.element.empty.table"); + tableEl.setAndLoadPersistedPreferences(ureq, getTablePrefsKey()); + tableEl.setMultiSelect(true); + tableEl.setSelectAllEnable(true); + + FormLayoutContainer buttons = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add("buttons", buttons); + buttons.setElementCssClass("o_button_group"); + removeLink = uifactory.addFormLink("curriculum.element.remove", buttons, Link.BUTTON); + + loadModel(); + } + + @Override + public void initTools() { + addLink = LinkFactory.createToolLink("curriculum.element.add", translate("curriculum.element.add"), this); + addLink.setIconLeftCSS("o_icon o_icon-fw o_icon_qual_gen_ce_add"); + stackPanel.addTool(addLink, Align.right); + } + + private void loadModel() { + List<CurriculumElementRef> elementRefs = getCurriculumElementRefs(configs, getConfigKey()); + List<CurriculumElement> curriculumElements = curriculumService.getCurriculumElements(elementRefs); + tableModel.setObjects(curriculumElements); + tableEl.reset(true, true, true); + + removeLink.setVisible(!curriculumElements.isEmpty()); + flc.setDirty(true); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if (source == removeLink) { + List<CurriculumElement> elements = getSelectedCurriculumElements(); + doConfirmRemove(ureq, elements); + } + } + + private List<CurriculumElement> getSelectedCurriculumElements() { + return tableEl.getMultiSelectedIndex().stream() + .map(index -> tableModel.getObject(index.intValue())) + .collect(Collectors.toList()); + } + + @Override + public void event(UserRequest ureq, Component source, Event event) { + if (source == addLink) { + doSelectCurriculumElement(ureq); + } + super.event(ureq, source, event); + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if (source == selectCtrl) { + if (Event.DONE_EVENT.equals(event)) { + String elementKey = selectCtrl.getCurriculumElementKey(); + doAddCurriculumElement(elementKey); + } + cmc.deactivate(); + cleanUp(); + } else if (source == removeConfirmationCtrl) { + if (Event.DONE_EVENT.equals(event)) { + List<CurriculumElement> elements = removeConfirmationCtrl.getCurriculumElements(); + doRemove(elements); + } + cmc.deactivate(); + cleanUp(); + } else if (source == cmc) { + cleanUp(); + } + super.event(ureq, source, event); + } + + private void cleanUp() { + removeAsListenerAndDispose(removeConfirmationCtrl); + removeAsListenerAndDispose(selectCtrl); + removeAsListenerAndDispose(cmc); + removeConfirmationCtrl = null; + selectCtrl = null; + cmc = null; + } + + protected static List<CurriculumElementRef> getCurriculumElementRefs(QualityGeneratorConfigs generatorConfigs, + String configKey) { + String whiteListConfig = generatorConfigs.getValue(configKey); + String[] keys = StringHelper.containsNonWhitespace(whiteListConfig) + ? whiteListConfig.split(KEY_DELIMITER) + : new String[0]; + List<CurriculumElementRef> elementRefs = Arrays.stream(keys) + .map(Long::valueOf) + .map(CurriculumElementRefImpl::new) + .collect(Collectors.toList()); + return elementRefs; + } + + public static void setCurriculumElementRefs(QualityGeneratorConfigs generatorConfigs, + List<? extends CurriculumElementRef> elements, String configKey) { + for (CurriculumElementRef element : elements) { + doAddCurriculumElement(generatorConfigs, element.getKey().toString(), configKey); + } + } + + private static void doAddCurriculumElement(QualityGeneratorConfigs generatorConfigs, String elementKey, String configKey) { + if (StringHelper.containsNonWhitespace(elementKey)) { + String whiteListConfig = generatorConfigs.getValue(configKey); + if (StringHelper.containsNonWhitespace(whiteListConfig)) { + String[] keys = whiteListConfig.split(KEY_DELIMITER); + if (!Arrays.asList(keys).contains(elementKey)) { + whiteListConfig += KEY_DELIMITER + elementKey; + } + } else { + whiteListConfig = elementKey; + } + generatorConfigs.setValue(configKey, whiteListConfig); + } + } + + private void doSelectCurriculumElement(UserRequest ureq) { + List<Organisation> organisations = generatorService.loadGeneratorOrganisations(generator); + + selectCtrl = new CurriculumElementSelectionController(ureq, getWindowControl(), organisations); + listenTo(selectCtrl); + + cmc = new CloseableModalController(getWindowControl(), translate("close"), + selectCtrl.getInitialComponent(), true, translate("curriculum.element.select.title")); + cmc.activate(); + listenTo(cmc); + } + + private void doAddCurriculumElement(String elementKey) { + doAddCurriculumElement(configs, elementKey, getConfigKey()); + loadModel(); + } + + private void doConfirmRemove(UserRequest ureq, List<CurriculumElement> elements) { + if (elements.isEmpty()) { + showWarning("curriculum.element.none.selected"); + } else { + removeConfirmationCtrl = new CurriculumElementRemoveConfirmationController(ureq, getWindowControl(), elements); + listenTo(removeConfirmationCtrl); + + cmc = new CloseableModalController(getWindowControl(), translate("close"), + removeConfirmationCtrl.getInitialComponent(), true, translate("curriculum.element.remove.confirm.title")); + cmc.activate(); + listenTo(cmc); + } + } + + private void doRemove(List<CurriculumElement> elements) { + List<String> keysToRemove = elements.stream() + .map(CurriculumElementRef::getKey) + .map(String::valueOf) + .collect(Collectors.toList()); + + String whiteListConfig = configs.getValue(getConfigKey()); + String[] splittedKeys = StringHelper.containsNonWhitespace(whiteListConfig) + ? whiteListConfig.split(KEY_DELIMITER) + : new String[0]; + List<String> currentKeys = Arrays.stream(splittedKeys).collect(Collectors.toList()); + currentKeys.removeAll(keysToRemove); + + String keys = currentKeys.stream().collect(joining(KEY_DELIMITER)); + configs.setValue(getConfigKey(), keys); + loadModel(); + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void doDispose() { + // + } + +} diff --git a/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementWhiteListDataModel.java b/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementListDataModel.java similarity index 92% rename from src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementWhiteListDataModel.java rename to src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementListDataModel.java index ffc98cb2f2b..36815adb8b2 100644 --- a/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementWhiteListDataModel.java +++ b/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementListDataModel.java @@ -37,12 +37,12 @@ import org.olat.modules.curriculum.CurriculumElementType; * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com * */ -class CurriculumElementWhiteListDataModel extends DefaultFlexiTableDataModel<CurriculumElement> +class CurriculumElementListDataModel extends DefaultFlexiTableDataModel<CurriculumElement> implements SortableFlexiTableDataModel<CurriculumElement> { private final Locale locale; - CurriculumElementWhiteListDataModel(FlexiTableColumnModel columnsModel, Locale locale) { + CurriculumElementListDataModel(FlexiTableColumnModel columnsModel, Locale locale) { super(columnsModel); this.locale = locale; } @@ -76,7 +76,7 @@ class CurriculumElementWhiteListDataModel extends DefaultFlexiTableDataModel<Cur @Override public DefaultFlexiTableDataModel<CurriculumElement> createCopyWithEmptyList() { - return new CurriculumElementWhiteListDataModel(getTableColumnModel(), locale); + return new CurriculumElementListDataModel(getTableColumnModel(), locale); } public enum Cols implements FlexiSortableColumnDef { diff --git a/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementWhiteListController.java b/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementWhiteListController.java index 645050389de..3338df6c205 100644 --- a/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementWhiteListController.java +++ b/src/main/java/org/olat/modules/quality/generator/ui/CurriculumElementWhiteListController.java @@ -19,44 +19,14 @@ */ package org.olat.modules.quality.generator.ui; -import static java.util.stream.Collectors.joining; - -import java.util.Arrays; 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.FormLayoutContainer; -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.link.Link; -import org.olat.core.gui.components.link.LinkFactory; -import org.olat.core.gui.components.stack.TooledController; import org.olat.core.gui.components.stack.TooledStackedPanel; -import org.olat.core.gui.components.stack.TooledStackedPanel.Align; -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.generic.closablewrapper.CloseableModalController; -import org.olat.core.id.Organisation; -import org.olat.core.util.StringHelper; -import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementRef; -import org.olat.modules.curriculum.CurriculumService; -import org.olat.modules.curriculum.model.CurriculumElementRefImpl; import org.olat.modules.quality.generator.QualityGenerator; import org.olat.modules.quality.generator.QualityGeneratorConfigs; -import org.olat.modules.quality.generator.QualityGeneratorService; -import org.olat.modules.quality.generator.ui.CurriculumElementWhiteListDataModel.Cols; -import org.springframework.beans.factory.annotation.Autowired; /** * @@ -64,223 +34,32 @@ import org.springframework.beans.factory.annotation.Autowired; * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com * */ -public class CurriculumElementWhiteListController extends FormBasicController -implements GeneratorWhiteListController, TooledController { +public class CurriculumElementWhiteListController extends CurriculumElementListController { - private static final String CURRICULUM_ELEMENT_WHITE_LIST = "curriculum.element.white.list"; - private static final String KEY_DELIMITER = ","; - - private FlexiTableElement tableEl; - private CurriculumElementWhiteListDataModel tableModel; - private Link addLink; - private FormLink removeLink; - - private CloseableModalController cmc; - private CurriculumElementSelectionController selectCtrl; - private CurriculumElementRemoveConfirmationController removeConfirmationCtrl; - - private final TooledStackedPanel stackPanel; - private final QualityGenerator generator; - private final QualityGeneratorConfigs configs; - - @Autowired - private QualityGeneratorService generatorService; - @Autowired - private CurriculumService curriculumService; + private static final String CONFIG_KEY = "curriculum.element.white.list"; - public CurriculumElementWhiteListController(UserRequest ureq, WindowControl wControl, - TooledStackedPanel stackPanel, QualityGenerator generator, QualityGeneratorConfigs configs) { - super(ureq, wControl, LAYOUT_BAREBONE); - this.stackPanel = stackPanel; - this.generator = generator; - this.configs = configs; - initForm(ureq); + public CurriculumElementWhiteListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, + QualityGenerator generator, QualityGeneratorConfigs configs) { + super(ureq, wControl, stackPanel, generator, configs); } @Override - protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.identifier)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.typeName)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.begin)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.end)); - - tableModel = new CurriculumElementWhiteListDataModel(columnsModel, getLocale()); - tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, true, getTranslator(), formLayout); - tableEl.setEmtpyTableMessageKey("curriculum.element.empty.table"); - tableEl.setAndLoadPersistedPreferences(ureq, "quality-ce-white-list"); - tableEl.setMultiSelect(true); - tableEl.setSelectAllEnable(true); - - FormLayoutContainer buttons = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); - formLayout.add("buttons", buttons); - buttons.setElementCssClass("o_button_group"); - removeLink = uifactory.addFormLink("curriculum.element.remove", buttons, Link.BUTTON); - - loadModel(); - } - - @Override - public void initTools() { - addLink = LinkFactory.createToolLink("curriculum.element.add", translate("curriculum.element.add"), this); - addLink.setIconLeftCSS("o_icon o_icon-fw o_icon_qual_gen_ce_add"); - stackPanel.addTool(addLink, Align.right); + protected String getConfigKey() { + return CONFIG_KEY; } - private void loadModel() { - List<CurriculumElementRef> elementRefs = getCurriculumElementRefs(configs); - List<CurriculumElement> curriculumElements = curriculumService.getCurriculumElements(elementRefs); - tableModel.setObjects(curriculumElements); - tableEl.reset(true, true, true); - - removeLink.setVisible(!curriculumElements.isEmpty()); - flc.setDirty(true); - } - - @Override - protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { - if (source == removeLink) { - List<CurriculumElement> elements = getSelectedCurriculumElements(); - doConfirmRemove(ureq, elements); - } - } - - private List<CurriculumElement> getSelectedCurriculumElements() { - return tableEl.getMultiSelectedIndex().stream() - .map(index -> tableModel.getObject(index.intValue())) - .collect(Collectors.toList()); - } - - @Override - public void event(UserRequest ureq, Component source, Event event) { - if (source == addLink) { - doSelectCurriculumElement(ureq); - } - super.event(ureq, source, event); - } - @Override - protected void event(UserRequest ureq, Controller source, Event event) { - if (source == selectCtrl) { - if (Event.DONE_EVENT.equals(event)) { - String elementKey = selectCtrl.getCurriculumElementKey(); - doAddCurriculumElement(elementKey); - } - cmc.deactivate(); - cleanUp(); - } else if (source == removeConfirmationCtrl) { - if (Event.DONE_EVENT.equals(event)) { - List<CurriculumElement> elements = removeConfirmationCtrl.getCurriculumElements(); - doRemove(elements); - } - cmc.deactivate(); - cleanUp(); - } else if (source == cmc) { - cleanUp(); - } - super.event(ureq, source, event); + protected String getTablePrefsKey() { + return "quality-ce-white-list"; } - private void cleanUp() { - removeAsListenerAndDispose(removeConfirmationCtrl); - removeAsListenerAndDispose(selectCtrl); - removeAsListenerAndDispose(cmc); - removeConfirmationCtrl = null; - selectCtrl = null; - cmc = null; - } - public static List<CurriculumElementRef> getCurriculumElementRefs(QualityGeneratorConfigs generatorConfigs) { - String whiteListConfig = generatorConfigs.getValue(CURRICULUM_ELEMENT_WHITE_LIST); - String[] keys = StringHelper.containsNonWhitespace(whiteListConfig) - ? whiteListConfig.split(KEY_DELIMITER) - : new String[0]; - List<CurriculumElementRef> elementRefs = Arrays.stream(keys) - .map(Long::valueOf) - .map(CurriculumElementRefImpl::new) - .collect(Collectors.toList()); - return elementRefs; + return CurriculumElementListController.getCurriculumElementRefs(generatorConfigs, CONFIG_KEY); } - public static void setCurriculumElementRefs(QualityGeneratorConfigs generatorConfigs, List<? extends CurriculumElementRef> elements) { - for (CurriculumElementRef element : elements) { - doAddCurriculumElement(generatorConfigs, element.getKey().toString()); - } - } - - private static void doAddCurriculumElement(QualityGeneratorConfigs generatorConfigs, String elementKey) { - if (StringHelper.containsNonWhitespace(elementKey)) { - String whiteListConfig = generatorConfigs.getValue(CURRICULUM_ELEMENT_WHITE_LIST); - if (StringHelper.containsNonWhitespace(whiteListConfig)) { - String[] keys = whiteListConfig.split(KEY_DELIMITER); - if (!Arrays.asList(keys).contains(elementKey)) { - whiteListConfig += KEY_DELIMITER + elementKey; - } - } else { - whiteListConfig = elementKey; - } - generatorConfigs.setValue(CURRICULUM_ELEMENT_WHITE_LIST, whiteListConfig); - } - } - - private void doSelectCurriculumElement(UserRequest ureq) { - List<Organisation> organisations = generatorService.loadGeneratorOrganisations(generator); - - selectCtrl = new CurriculumElementSelectionController(ureq, getWindowControl(), organisations); - listenTo(selectCtrl); - - cmc = new CloseableModalController(getWindowControl(), translate("close"), - selectCtrl.getInitialComponent(), true, translate("curriculum.element.select.title")); - cmc.activate(); - listenTo(cmc); - } - - private void doAddCurriculumElement(String elementKey) { - doAddCurriculumElement(configs, elementKey); - loadModel(); - } - - private void doConfirmRemove(UserRequest ureq, List<CurriculumElement> elements) { - if (elements.isEmpty()) { - showWarning("curriculum.element.none.selected"); - } else { - removeConfirmationCtrl = new CurriculumElementRemoveConfirmationController(ureq, getWindowControl(), elements); - listenTo(removeConfirmationCtrl); - - cmc = new CloseableModalController(getWindowControl(), translate("close"), - removeConfirmationCtrl.getInitialComponent(), true, translate("curriculum.element.remove.confirm.title")); - cmc.activate(); - listenTo(cmc); - } - } - - private void doRemove(List<CurriculumElement> elements) { - List<String> keysToRemove = elements.stream() - .map(CurriculumElementRef::getKey) - .map(String::valueOf) - .collect(Collectors.toList()); - - String whiteListConfig = configs.getValue(CURRICULUM_ELEMENT_WHITE_LIST); - String[] splittedKeys = StringHelper.containsNonWhitespace(whiteListConfig) - ? whiteListConfig.split(KEY_DELIMITER) - : new String[0]; - List<String> currentKeys = Arrays.stream(splittedKeys).collect(Collectors.toList()); - currentKeys.removeAll(keysToRemove); - - String keys = currentKeys.stream().collect(joining(KEY_DELIMITER)); - configs.setValue(CURRICULUM_ELEMENT_WHITE_LIST, keys); - loadModel(); - } - - @Override - protected void formOK(UserRequest ureq) { - // - } - - @Override - protected void doDispose() { - // + public static void setCurriculumElementRefs(QualityGeneratorConfigs generatorConfigs, + List<? extends CurriculumElementRef> elements) { + CurriculumElementListController.setCurriculumElementRefs(generatorConfigs, elements, CONFIG_KEY); } } diff --git a/src/main/java/org/olat/modules/quality/generator/ui/GeneratorController.java b/src/main/java/org/olat/modules/quality/generator/ui/GeneratorController.java index 15b04d01690..e5ff1659143 100644 --- a/src/main/java/org/olat/modules/quality/generator/ui/GeneratorController.java +++ b/src/main/java/org/olat/modules/quality/generator/ui/GeneratorController.java @@ -67,13 +67,15 @@ public class GeneratorController extends BasicController implements TooledContro private Link configurationLink; private Link reportAccessLink; private Link whiteListLink; + private Link blackListLink; private final ButtonGroupComponent segmentButtonsCmp; private final TooledStackedPanel stackPanel; private final StackedPanel mainPanel; private GeneratorEditController configCtrl; private GeneratorReportAccessController reportAccessCtrl; - private GeneratorWhiteListController whiteListCtrl; + private Controller whiteListCtrl; + private Controller blackListCtrl; private CloseableModalController cmc; private GeneratorEnableConfirmationController enableConfirmationCtrl; private GeneratorDisableConfirmationController disableConfirmationCtrl; @@ -104,6 +106,10 @@ public class GeneratorController extends BasicController implements TooledContro whiteListLink = LinkFactory.createLink("generator.white.list", getTranslator(), this); segmentButtonsCmp.addButton(whiteListLink, false); } + if (generatorService.hasBlackListController(generator)) { + blackListLink = LinkFactory.createLink("generator.black.list", getTranslator(), this); + segmentButtonsCmp.addButton(blackListLink, false); + } mainPanel = putInitialPanel(new SimpleStackedPanel("dataCollectionSegments")); mainPanel.setContent(new Panel("empty")); @@ -165,6 +171,8 @@ public class GeneratorController extends BasicController implements TooledContro doOpenReportAccess(ureq); } else if(whiteListLink == source) { doOpenWhiteList(ureq); + } else if(blackListLink == source) { + doOpenBlackList(ureq); } else if (stackPanel == source && stackPanel.getLastController() == this && event instanceof PopEvent) { PopEvent popEvent = (PopEvent) event; if (popEvent.isClose()) { @@ -243,6 +251,15 @@ public class GeneratorController extends BasicController implements TooledContro stackPanel.pushController(translate("generator.white.list"), whiteListCtrl); segmentButtonsCmp.setSelectedButton(whiteListLink); } + + private void doOpenBlackList(UserRequest ureq) { + blackListCtrl = generatorService.getBlackListController(ureq, getWindowControl(), secCallback, stackPanel, + generator); + listenTo(blackListCtrl); + stackPanel.popUpToController(this); + stackPanel.pushController(translate("generator.black.list"), blackListCtrl); + segmentButtonsCmp.setSelectedButton(blackListLink); + } private void doConfirmEnableGenerator(UserRequest ureq) { if (configCtrl.validateBeforeActivation(ureq)) { diff --git a/src/main/java/org/olat/modules/quality/generator/ui/GeneratorWhiteListController.java b/src/main/java/org/olat/modules/quality/generator/ui/GeneratorWhiteListController.java deleted file mode 100644 index 64dca8fbe36..00000000000 --- a/src/main/java/org/olat/modules/quality/generator/ui/GeneratorWhiteListController.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.modules.quality.generator.ui; - -import org.olat.core.gui.control.Controller; - -/** - * - * Initial date: 03.11.2018<br> - * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com - * - */ -public interface GeneratorWhiteListController extends Controller { - -} diff --git a/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryBlackListController.java b/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryBlackListController.java new file mode 100644 index 00000000000..c423f9651c6 --- /dev/null +++ b/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryBlackListController.java @@ -0,0 +1,63 @@ +/** + * <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.quality.generator.ui; + +import java.util.List; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.control.WindowControl; +import org.olat.modules.quality.generator.QualityGeneratorConfigs; +import org.olat.repository.RepositoryEntryRef; + +/** + * + * Initial date: 27 May 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class RepositoryEntryBlackListController extends RepositoryEntryListController { + + private static final String CONFIG_KEY = "course.black.list"; + + public RepositoryEntryBlackListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, + QualityGeneratorConfigs configs) { + super(ureq, wControl, stackPanel, configs); + } + + @Override + protected String getConfigKey() { + return CONFIG_KEY; + } + + @Override + protected String getTablePrefKey() { + return "quality-re-black-list"; + } + + public static List<RepositoryEntryRef> getRepositoryEntryRefs(QualityGeneratorConfigs generatorConfigs) { + return RepositoryEntryListController.getRepositoryEntryRefs(generatorConfigs, CONFIG_KEY); + } + + public static void setRepositoryEntryRefs(QualityGeneratorConfigs generatorConfigs, List<? extends RepositoryEntryRef> entries) { + RepositoryEntryListController.setRepositoryEntryRefs(generatorConfigs, entries, CONFIG_KEY); + } + +} diff --git a/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryListController.java b/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryListController.java new file mode 100644 index 00000000000..886d57396f0 --- /dev/null +++ b/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryListController.java @@ -0,0 +1,291 @@ +/** + * <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.quality.generator.ui; + +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toList; + +import java.util.Arrays; +import java.util.Collections; +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.FormLayoutContainer; +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.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.stack.TooledController; +import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.components.stack.TooledStackedPanel.Align; +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.generic.closablewrapper.CloseableModalController; +import org.olat.core.util.StringHelper; +import org.olat.course.CourseModule; +import org.olat.modules.quality.generator.QualityGeneratorConfigs; +import org.olat.modules.quality.generator.ui.RepositoryEntryListDataModel.Cols; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryRef; +import org.olat.repository.RepositoryService; +import org.olat.repository.controllers.ReferencableEntriesSearchController; +import org.olat.repository.model.RepositoryEntryRefImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 27 May 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public abstract class RepositoryEntryListController extends FormBasicController implements TooledController { + + private static final String KEY_DELIMITER = ","; + + private FlexiTableElement tableEl; + private RepositoryEntryListDataModel tableModel; + private Link addLink; + private FormLink removeLink; + + private CloseableModalController cmc; + private ReferencableEntriesSearchController selectCtrl; + private RepositoryEntryRemoveConfirmationController removeConfirmationCtrl; + + private final TooledStackedPanel stackPanel; + private final QualityGeneratorConfigs configs; + + @Autowired + private RepositoryService repositoryService; + + public RepositoryEntryListController(UserRequest ureq, WindowControl wControl, + TooledStackedPanel stackPanel, QualityGeneratorConfigs configs) { + super(ureq, wControl, LAYOUT_BAREBONE); + this.stackPanel = stackPanel; + this.configs = configs; + initForm(ureq); + } + + protected abstract String getConfigKey(); + + protected abstract String getTablePrefKey(); + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.id)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.identifier)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.begin)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.end)); + + tableModel = new RepositoryEntryListDataModel(columnsModel, getLocale()); + tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, true, getTranslator(), formLayout); + tableEl.setEmtpyTableMessageKey("repository.entry.empty.table"); + tableEl.setAndLoadPersistedPreferences(ureq, getTablePrefKey()); + tableEl.setMultiSelect(true); + tableEl.setSelectAllEnable(true); + + FormLayoutContainer buttons = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add("buttons", buttons); + buttons.setElementCssClass("o_button_group"); + removeLink = uifactory.addFormLink("repository.entry.remove", buttons, Link.BUTTON); + + loadModel(); + } + + @Override + public void initTools() { + addLink = LinkFactory.createToolLink("repository.entry.select", translate("repository.entry.select"), this); + addLink.setIconLeftCSS("o_icon o_icon-fw o_icon_qual_gen_re_add"); + stackPanel.addTool(addLink, Align.right); + } + + private void loadModel() { + List<Long> entryKeys = getRepositoryEntryRefs(configs, getConfigKey()).stream() + .map(RepositoryEntryRef::getKey) + .collect(toList()); + List<RepositoryEntry> entries = repositoryService.loadByKeys(entryKeys); + tableModel.setObjects(entries); + tableEl.reset(true, true, true); + + removeLink.setVisible(!entries.isEmpty()); + flc.setDirty(true); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if (source == removeLink) { + List<RepositoryEntry> entries = getSelectedRepositoryEntries(); + doConfirmRemove(ureq, entries); + } + } + + private List<RepositoryEntry> getSelectedRepositoryEntries() { + return tableEl.getMultiSelectedIndex().stream() + .map(index -> tableModel.getObject(index.intValue())) + .collect(Collectors.toList()); + } + + @Override + public void event(UserRequest ureq, Component source, Event event) { + if (source == addLink) { + doSelectRepositoryEntry(ureq); + } + super.event(ureq, source, event); + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if (source == selectCtrl) { + List<RepositoryEntry> selectedEntries = Collections.emptyList(); + if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) { + selectedEntries = Collections.singletonList(selectCtrl.getSelectedEntry()); + } else if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRIES_SELECTED) { + selectedEntries = selectCtrl.getSelectedEntries(); + } + doAddRepositoryEntries(selectedEntries); + cmc.deactivate(); + cleanUp(); + } else if (source == removeConfirmationCtrl) { + if (Event.DONE_EVENT.equals(event)) { + List<RepositoryEntry> entries = removeConfirmationCtrl.getRepositoryEntrys(); + doRemove(entries); + } + cmc.deactivate(); + cleanUp(); + } else if (source == cmc) { + cleanUp(); + } + super.event(ureq, source, event); + } + + private void cleanUp() { + removeAsListenerAndDispose(removeConfirmationCtrl); + removeAsListenerAndDispose(selectCtrl); + removeAsListenerAndDispose(cmc); + removeConfirmationCtrl = null; + selectCtrl = null; + cmc = null; + } + + protected static List<RepositoryEntryRef> getRepositoryEntryRefs(QualityGeneratorConfigs generatorConfigs, String configKey) { + String whiteListConfig = generatorConfigs.getValue(configKey); + String[] keys = StringHelper.containsNonWhitespace(whiteListConfig) + ? whiteListConfig.split(KEY_DELIMITER) + : new String[0]; + List<RepositoryEntryRef> elementRefs = Arrays.stream(keys) + .map(Long::valueOf) + .map(RepositoryEntryRefImpl::new) + .collect(toList()); + return elementRefs; + } + + public static void setRepositoryEntryRefs(QualityGeneratorConfigs generatorConfigs, + List<? extends RepositoryEntryRef> entries, String configKey) { + for (RepositoryEntryRef entry : entries) { + doAddRepositoryEntry(generatorConfigs, entry.getKey().toString(), configKey); + } + } + + private static void doAddRepositoryEntry(QualityGeneratorConfigs generatorConfigs, String entryKey, String configKey) { + if (StringHelper.containsNonWhitespace(entryKey)) { + String whiteListConfig = generatorConfigs.getValue(configKey); + if (StringHelper.containsNonWhitespace(whiteListConfig)) { + String[] keys = whiteListConfig.split(KEY_DELIMITER); + if (!Arrays.asList(keys).contains(entryKey)) { + whiteListConfig += KEY_DELIMITER + entryKey; + } + } else { + whiteListConfig = entryKey; + } + generatorConfigs.setValue(configKey, whiteListConfig); + } + } + + private void doSelectRepositoryEntry(UserRequest ureq) { + selectCtrl = new ReferencableEntriesSearchController(getWindowControl(), ureq, + new String[] { CourseModule.getCourseTypeName() }, translate("repository.entry.select.title"), + false, false, true, false, true); + listenTo(selectCtrl); + + cmc = new CloseableModalController(getWindowControl(), translate("close"), + selectCtrl.getInitialComponent(), true, translate("repository.entry.select.title")); + cmc.activate(); + listenTo(cmc); + } + + private void doAddRepositoryEntries(List<RepositoryEntry> selectedEntries) { + setRepositoryEntryRefs(configs, selectedEntries, getConfigKey()); + loadModel(); + } + + private void doConfirmRemove(UserRequest ureq, List<RepositoryEntry> entries) { + if (entries.isEmpty()) { + showWarning("repository.entry.none.selected"); + } else { + removeConfirmationCtrl = new RepositoryEntryRemoveConfirmationController(ureq, getWindowControl(), entries); + listenTo(removeConfirmationCtrl); + + cmc = new CloseableModalController(getWindowControl(), translate("close"), + removeConfirmationCtrl.getInitialComponent(), true, translate("repository.entry.remove.confirm.title")); + cmc.activate(); + listenTo(cmc); + } + } + + private void doRemove(List<RepositoryEntry> entries) { + List<String> keysToRemove = entries.stream() + .map(RepositoryEntryRef::getKey) + .map(String::valueOf) + .collect(Collectors.toList()); + + String whiteListConfig = configs.getValue(getConfigKey()); + String[] splittedKeys = StringHelper.containsNonWhitespace(whiteListConfig) + ? whiteListConfig.split(KEY_DELIMITER) + : new String[0]; + List<String> currentKeys = Arrays.stream(splittedKeys).collect(Collectors.toList()); + currentKeys.removeAll(keysToRemove); + + String keys = currentKeys.stream().collect(joining(KEY_DELIMITER)); + configs.setValue(getConfigKey(), keys); + loadModel(); + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void doDispose() { + // + } + +} diff --git a/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryWhiteListDataModel.java b/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryListDataModel.java similarity index 92% rename from src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryWhiteListDataModel.java rename to src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryListDataModel.java index ec6a941cae7..f3f9b10117e 100644 --- a/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryWhiteListDataModel.java +++ b/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryListDataModel.java @@ -37,12 +37,12 @@ import org.olat.repository.model.RepositoryEntryLifecycle; * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com * */ -class RepositoryEntryWhiteListDataModel extends DefaultFlexiTableDataModel<RepositoryEntry> +class RepositoryEntryListDataModel extends DefaultFlexiTableDataModel<RepositoryEntry> implements SortableFlexiTableDataModel<RepositoryEntry> { private final Locale locale; - RepositoryEntryWhiteListDataModel(FlexiTableColumnModel columnsModel, Locale locale) { + RepositoryEntryListDataModel(FlexiTableColumnModel columnsModel, Locale locale) { super(columnsModel); this.locale = locale; } @@ -79,7 +79,7 @@ class RepositoryEntryWhiteListDataModel extends DefaultFlexiTableDataModel<Repos @Override public DefaultFlexiTableDataModel<RepositoryEntry> createCopyWithEmptyList() { - return new RepositoryEntryWhiteListDataModel(getTableColumnModel(), locale); + return new RepositoryEntryListDataModel(getTableColumnModel(), locale); } public enum Cols implements FlexiSortableColumnDef { diff --git a/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryWhiteListController.java b/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryWhiteListController.java index 34352c020ec..edb4d32afc8 100644 --- a/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryWhiteListController.java +++ b/src/main/java/org/olat/modules/quality/generator/ui/RepositoryEntryWhiteListController.java @@ -19,45 +19,13 @@ */ package org.olat.modules.quality.generator.ui; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; - -import java.util.Arrays; -import java.util.Collections; 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.FormLayoutContainer; -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.link.Link; -import org.olat.core.gui.components.link.LinkFactory; -import org.olat.core.gui.components.stack.TooledController; import org.olat.core.gui.components.stack.TooledStackedPanel; -import org.olat.core.gui.components.stack.TooledStackedPanel.Align; -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.generic.closablewrapper.CloseableModalController; -import org.olat.core.util.StringHelper; -import org.olat.course.CourseModule; import org.olat.modules.quality.generator.QualityGeneratorConfigs; -import org.olat.modules.quality.generator.ui.RepositoryEntryWhiteListDataModel.Cols; -import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; -import org.olat.repository.RepositoryService; -import org.olat.repository.controllers.ReferencableEntriesSearchController; -import org.olat.repository.model.RepositoryEntryRefImpl; -import org.springframework.beans.factory.annotation.Autowired; /** * @@ -65,222 +33,31 @@ import org.springframework.beans.factory.annotation.Autowired; * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com * */ -public class RepositoryEntryWhiteListController extends FormBasicController - implements GeneratorWhiteListController, TooledController { +public class RepositoryEntryWhiteListController extends RepositoryEntryListController { - private static final String COURSE_WHITE_LIST = "course.white.list"; - private static final String KEY_DELIMITER = ","; - - private FlexiTableElement tableEl; - private RepositoryEntryWhiteListDataModel tableModel; - private Link addLink; - private FormLink removeLink; - - private CloseableModalController cmc; - private ReferencableEntriesSearchController selectCtrl; - private RepositoryEntryRemoveConfirmationController removeConfirmationCtrl; - - private final TooledStackedPanel stackPanel; - private final QualityGeneratorConfigs configs; - - @Autowired - private RepositoryService repositoryService; + private static final String CONFIG_KEY = "course.white.list"; - public RepositoryEntryWhiteListController(UserRequest ureq, WindowControl wControl, - TooledStackedPanel stackPanel, QualityGeneratorConfigs configs) { - super(ureq, wControl, LAYOUT_BAREBONE); - this.stackPanel = stackPanel; - this.configs = configs; - initForm(ureq); + public RepositoryEntryWhiteListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, + QualityGeneratorConfigs configs) { + super(ureq, wControl, stackPanel, configs); } @Override - protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.id)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.identifier)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.begin)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.end)); - - tableModel = new RepositoryEntryWhiteListDataModel(columnsModel, getLocale()); - tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, true, getTranslator(), formLayout); - tableEl.setEmtpyTableMessageKey("repository.entry.empty.table"); - tableEl.setAndLoadPersistedPreferences(ureq, "quality-re-white-list"); - tableEl.setMultiSelect(true); - tableEl.setSelectAllEnable(true); - - FormLayoutContainer buttons = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); - formLayout.add("buttons", buttons); - buttons.setElementCssClass("o_button_group"); - removeLink = uifactory.addFormLink("repository.entry.remove", buttons, Link.BUTTON); - - loadModel(); - } - - @Override - public void initTools() { - addLink = LinkFactory.createToolLink("repository.entry.select", translate("repository.entry.select"), this); - addLink.setIconLeftCSS("o_icon o_icon-fw o_icon_qual_gen_re_add"); - stackPanel.addTool(addLink, Align.right); + protected String getConfigKey() { + return CONFIG_KEY; } - private void loadModel() { - List<Long> entryKeys = getRepositoryEntryRefs(configs).stream().map(RepositoryEntryRef::getKey).collect(toList()); - List<RepositoryEntry> entries = repositoryService.loadByKeys(entryKeys); - tableModel.setObjects(entries); - tableEl.reset(true, true, true); - - removeLink.setVisible(!entries.isEmpty()); - flc.setDirty(true); - } - - @Override - protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { - if (source == removeLink) { - List<RepositoryEntry> entries = getSelectedRepositoryEntries(); - doConfirmRemove(ureq, entries); - } - } - - private List<RepositoryEntry> getSelectedRepositoryEntries() { - return tableEl.getMultiSelectedIndex().stream() - .map(index -> tableModel.getObject(index.intValue())) - .collect(Collectors.toList()); - } - - @Override - public void event(UserRequest ureq, Component source, Event event) { - if (source == addLink) { - doSelectRepositoryEntry(ureq); - } - super.event(ureq, source, event); - } - @Override - protected void event(UserRequest ureq, Controller source, Event event) { - if (source == selectCtrl) { - List<RepositoryEntry> selectedEntries = Collections.emptyList(); - if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) { - selectedEntries = Collections.singletonList(selectCtrl.getSelectedEntry()); - } else if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRIES_SELECTED) { - selectedEntries = selectCtrl.getSelectedEntries(); - } - doAddRepositoryEntries(selectedEntries); - cmc.deactivate(); - cleanUp(); - } else if (source == removeConfirmationCtrl) { - if (Event.DONE_EVENT.equals(event)) { - List<RepositoryEntry> entries = removeConfirmationCtrl.getRepositoryEntrys(); - doRemove(entries); - } - cmc.deactivate(); - cleanUp(); - } else if (source == cmc) { - cleanUp(); - } - super.event(ureq, source, event); + protected String getTablePrefKey() { + return "quality-re-white-list"; } - private void cleanUp() { - removeAsListenerAndDispose(removeConfirmationCtrl); - removeAsListenerAndDispose(selectCtrl); - removeAsListenerAndDispose(cmc); - removeConfirmationCtrl = null; - selectCtrl = null; - cmc = null; - } - public static List<RepositoryEntryRef> getRepositoryEntryRefs(QualityGeneratorConfigs generatorConfigs) { - String whiteListConfig = generatorConfigs.getValue(COURSE_WHITE_LIST); - String[] keys = StringHelper.containsNonWhitespace(whiteListConfig) - ? whiteListConfig.split(KEY_DELIMITER) - : new String[0]; - List<RepositoryEntryRef> elementRefs = Arrays.stream(keys) - .map(Long::valueOf) - .map(RepositoryEntryRefImpl::new) - .collect(toList()); - return elementRefs; + return RepositoryEntryListController.getRepositoryEntryRefs(generatorConfigs, CONFIG_KEY); } public static void setRepositoryEntryRefs(QualityGeneratorConfigs generatorConfigs, List<? extends RepositoryEntryRef> entries) { - for (RepositoryEntryRef entry : entries) { - doAddRepositoryEntry(generatorConfigs, entry.getKey().toString()); - } - } - - private static void doAddRepositoryEntry(QualityGeneratorConfigs generatorConfigs, String entryKey) { - if (StringHelper.containsNonWhitespace(entryKey)) { - String whiteListConfig = generatorConfigs.getValue(COURSE_WHITE_LIST); - if (StringHelper.containsNonWhitespace(whiteListConfig)) { - String[] keys = whiteListConfig.split(KEY_DELIMITER); - if (!Arrays.asList(keys).contains(entryKey)) { - whiteListConfig += KEY_DELIMITER + entryKey; - } - } else { - whiteListConfig = entryKey; - } - generatorConfigs.setValue(COURSE_WHITE_LIST, whiteListConfig); - } - } - - private void doSelectRepositoryEntry(UserRequest ureq) { - selectCtrl = new ReferencableEntriesSearchController(getWindowControl(), ureq, - new String[] { CourseModule.getCourseTypeName() }, translate("repository.entry.select.title"), - false, false, true, false, true); - listenTo(selectCtrl); - - cmc = new CloseableModalController(getWindowControl(), translate("close"), - selectCtrl.getInitialComponent(), true, translate("repository.entry.select.title")); - cmc.activate(); - listenTo(cmc); - } - - private void doAddRepositoryEntries(List<RepositoryEntry> selectedEntries) { - setRepositoryEntryRefs(configs, selectedEntries); - loadModel(); - } - - private void doConfirmRemove(UserRequest ureq, List<RepositoryEntry> entries) { - if (entries.isEmpty()) { - showWarning("repository.entry.none.selected"); - } else { - removeConfirmationCtrl = new RepositoryEntryRemoveConfirmationController(ureq, getWindowControl(), entries); - listenTo(removeConfirmationCtrl); - - cmc = new CloseableModalController(getWindowControl(), translate("close"), - removeConfirmationCtrl.getInitialComponent(), true, translate("repository.entry.remove.confirm.title")); - cmc.activate(); - listenTo(cmc); - } - } - - private void doRemove(List<RepositoryEntry> entries) { - List<String> keysToRemove = entries.stream() - .map(RepositoryEntryRef::getKey) - .map(String::valueOf) - .collect(Collectors.toList()); - - String whiteListConfig = configs.getValue(COURSE_WHITE_LIST); - String[] splittedKeys = StringHelper.containsNonWhitespace(whiteListConfig) - ? whiteListConfig.split(KEY_DELIMITER) - : new String[0]; - List<String> currentKeys = Arrays.stream(splittedKeys).collect(Collectors.toList()); - currentKeys.removeAll(keysToRemove); - - String keys = currentKeys.stream().collect(joining(KEY_DELIMITER)); - configs.setValue(COURSE_WHITE_LIST, keys); - loadModel(); - } - - @Override - protected void formOK(UserRequest ureq) { - // - } - - @Override - protected void doDispose() { - // + RepositoryEntryListController.setRepositoryEntryRefs(generatorConfigs, entries, CONFIG_KEY); } } diff --git a/src/main/java/org/olat/modules/quality/generator/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/quality/generator/ui/_i18n/LocalStrings_de.properties index 42e2b335382..bb51f1efc89 100644 --- a/src/main/java/org/olat/modules/quality/generator/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/quality/generator/ui/_i18n/LocalStrings_de.properties @@ -16,6 +16,7 @@ curriculum.element.select.curriculum.element=Curriculumelement curriculum.element.select.title=Curriculumelement hinzuf\u00FCgen curriculum.element.type.name=Typ details.delete.error.quality.form.entry=Lernressource "{0}" kann nicht gel\u00F6scht werden. Es wird von einen Datenerhebungen ben\u00FCtzt. +generator.black.list=Negativliste generator.configuration=Konfiguration generator.create=Generator erstellen generator.create.button=Erstellen diff --git a/src/main/java/org/olat/modules/quality/generator/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/quality/generator/ui/_i18n/LocalStrings_en.properties index 9ab67696d14..5ce7f846be2 100644 --- a/src/main/java/org/olat/modules/quality/generator/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/quality/generator/ui/_i18n/LocalStrings_en.properties @@ -17,6 +17,7 @@ curriculum.element.select.curriculum=Curriculum curriculum.element.select.title=Add curriculum element curriculum.element.type.name=Type details.delete.error.quality.form.entry=This learning resource "{0}" cannot be deleted. There are data collections which need it. +generator.black.list=Black list generator.configuration=Configuration generator.create.button=Create generator.create.create=Create diff --git a/src/test/java/org/olat/modules/quality/generator/provider/course/manager/CourseProviderDAOTest.java b/src/test/java/org/olat/modules/quality/generator/provider/course/manager/CourseProviderDAOTest.java index 5fbfc2fd7a9..b5bce19395d 100644 --- a/src/test/java/org/olat/modules/quality/generator/provider/course/manager/CourseProviderDAOTest.java +++ b/src/test/java/org/olat/modules/quality/generator/provider/course/manager/CourseProviderDAOTest.java @@ -239,14 +239,14 @@ public class CourseProviderDAOTest extends OlatTestCase { } @Test - public void shouldFilterByRepositoryEntryRefs() { + public void shouldFilterByWhiteListRefs() { RepositoryEntry course1 = createEntry(null, null, null); RepositoryEntry course2 = createEntry(null, null, null); RepositoryEntry other = createEntry(null, null, null); dbInstance.commitAndCloseSession(); SearchParameters seachParameters = new SearchParameters(); - seachParameters.setRepositoryEntryRefs(asList(course1, course2)); + seachParameters.setWhiteListRefs(asList(course1, course2)); List<RepositoryEntry> courses = sut.loadCourses(seachParameters); assertThat(courses) @@ -254,6 +254,22 @@ public class CourseProviderDAOTest extends OlatTestCase { .doesNotContain(other); } + @Test + public void shouldFilterByBlackListRefs() { + RepositoryEntry course1 = createEntry(null, null, null); + RepositoryEntry course2 = createEntry(null, null, null); + RepositoryEntry blackList = createEntry(null, null, null); + dbInstance.commitAndCloseSession(); + + SearchParameters seachParameters = new SearchParameters(); + seachParameters.setBlackListRefs(asList(blackList)); + List<RepositoryEntry> courses = sut.loadCourses(seachParameters); + + assertThat(courses) + .contains(course1, course2) + .doesNotContain(blackList); + } + @Test public void shouldFilterByGeneratorDataCollectionStart() { Date start = nextHour(); diff --git a/src/test/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAOTest.java b/src/test/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAOTest.java index 44da5408c1e..aa30cacb39c 100644 --- a/src/test/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAOTest.java +++ b/src/test/java/org/olat/modules/quality/generator/provider/courselectures/manager/CourseLecturesProviderDAOTest.java @@ -203,7 +203,7 @@ public class CourseLecturesProviderDAOTest extends OlatTestCase { } @Test - public void shouldFilterLectureBlockInfosByCurriculumElements() { + public void shouldFilterLectureBlockInfosByWhiteList() { Identity teacher = JunitTestHelper.createAndPersistIdentityAsRndUser(""); Organisation organisation = organisationService.createOrganisation("org", "Org", null, null, null); Curriculum curriculum = curriculumService.createCurriculum("Curriculum", "Curriculum", null, organisation); @@ -226,14 +226,45 @@ public class CourseLecturesProviderDAOTest extends OlatTestCase { SearchParameters searchParams = new SearchParameters(); searchParams.setTeacherRef(teacher); - searchParams.setCurriculumElementRefs(Arrays.asList(element)); + searchParams.setWhiteListRefs(Arrays.asList(element)); List<LectureBlockInfo> infos = sut.loadLectureBlockInfo(searchParams); assertThat(infos).extracting(LectureBlockInfo::getCourseRepoKey) .containsExactlyInAnyOrder(course1.getKey(), course2.getKey()) .doesNotContain(otherCourse.getKey()); } + + @Test + public void shouldFilterLectureBlockInfosByBlackList() { + Identity teacher = JunitTestHelper.createAndPersistIdentityAsRndUser(""); + Organisation organisation = organisationService.createOrganisation("org", "Org", null, null, null); + Curriculum curriculum = curriculumService.createCurriculum("Curriculum", "Curriculum", null, organisation); + CurriculumElement element = curriculumService.createCurriculumElement("Element", "Element", + CurriculumElementStatus.active, null, null, null, null, CurriculumCalendars.disabled, + CurriculumLectures.disabled, CurriculumLearningProgress.disabled, curriculum); + CurriculumElement otherElement = curriculumService.createCurriculumElement("Element", "Element", + CurriculumElementStatus.active, null, null, null, null, CurriculumCalendars.disabled, + CurriculumLectures.disabled, CurriculumLearningProgress.disabled, curriculum); + RepositoryEntry course1 = JunitTestHelper.createAndPersistRepositoryEntry(); + RepositoryEntry course2 = JunitTestHelper.createAndPersistRepositoryEntry(); + RepositoryEntry otherCourse = JunitTestHelper.createAndPersistRepositoryEntry(); + createLectureBlock(course1, teacher, 1); + createLectureBlock(course2, teacher, 1); + createLectureBlock(otherCourse, teacher, 1); + curriculumService.addRepositoryEntry(element, course1, false); + curriculumService.addRepositoryEntry(element, course2, false); + curriculumService.addRepositoryEntry(otherElement, otherCourse, false); + dbInstance.commitAndCloseSession(); + + SearchParameters searchParams = new SearchParameters(); + searchParams.setTeacherRef(teacher); + searchParams.setBlackListRefs(Arrays.asList(otherElement)); + List<LectureBlockInfo> infos = sut.loadLectureBlockInfo(searchParams); + assertThat(infos).extracting(LectureBlockInfo::getCourseRepoKey) + .containsExactlyInAnyOrder(course1.getKey(), course2.getKey()) + .doesNotContain(otherCourse.getKey()); + } @Test public void shouldFilterLectureBlockInfosByEndDate() { @@ -581,11 +612,11 @@ public class CourseLecturesProviderDAOTest extends OlatTestCase { assertThat(count).isEqualTo(2); } - public LectureBlock createLectureBlock(RepositoryEntry course, Identity teacher, int numLectures) { + private LectureBlock createLectureBlock(RepositoryEntry course, Identity teacher, int numLectures) { return createLectureBlock(course, teacher, numLectures, nextHour(), nextHour()); } - public LectureBlock createLectureBlock(RepositoryEntry course, Identity teacher, int numLectures, Date start, Date end) { + private LectureBlock createLectureBlock(RepositoryEntry course, Identity teacher, int numLectures, Date start, Date end) { LectureBlock lectureBlock = lectureService.createLectureBlock(course); lectureBlock.setStartDate(start); lectureBlock.setEndDate(end); diff --git a/src/test/java/org/olat/modules/quality/generator/provider/curriculumelement/CurriculumElementProviderTest.java b/src/test/java/org/olat/modules/quality/generator/provider/curriculumelement/CurriculumElementProviderTest.java index c77d260e585..26a6124251a 100644 --- a/src/test/java/org/olat/modules/quality/generator/provider/curriculumelement/CurriculumElementProviderTest.java +++ b/src/test/java/org/olat/modules/quality/generator/provider/curriculumelement/CurriculumElementProviderTest.java @@ -84,7 +84,7 @@ public class CurriculumElementProviderTest extends OlatTestCase { QualityGenerator generator = createGeneratorInDefaultOrganisation(); String durationDays = "10"; - QualityGeneratorConfigs configs = createAfterSecondLectureConfigs(generator, durationDays, curriculumElement); + QualityGeneratorConfigs configs = createZeroDaysAfterBeginConfigs(generator, durationDays, curriculumElement); Date lastRun = new GregorianCalendar(2010, 6, 1).getTime(); Date now = new GregorianCalendar(2010, 6, 13).getTime(); @@ -99,7 +99,7 @@ public class CurriculumElementProviderTest extends OlatTestCase { .doesNotContain(defaultOrganisation); } - private QualityGeneratorConfigs createAfterSecondLectureConfigs(QualityGenerator generator, String durationDays, + private QualityGeneratorConfigs createZeroDaysAfterBeginConfigs(QualityGenerator generator, String durationDays, CurriculumElementRef curriculumElementRef) { QualityGeneratorConfigs configs = new QualityGeneratorConfigsImpl(generator); configs.setValue(CurriculumElementProvider.CONFIG_KEY_TITLE, "DATA_COLLECTION_TITLE"); diff --git a/src/test/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/CurriculumElementProviderDAOTest.java b/src/test/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/CurriculumElementProviderDAOTest.java index a85a1aab578..ea7a965c0df 100644 --- a/src/test/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/CurriculumElementProviderDAOTest.java +++ b/src/test/java/org/olat/modules/quality/generator/provider/curriculumelement/manager/CurriculumElementProviderDAOTest.java @@ -175,7 +175,7 @@ public class CurriculumElementProviderDAOTest extends OlatTestCase { } @Test - public void shouldFilterByCurriculumElement() { + public void shouldFilterByWhiteList() { Organisation organisation = organisationService.createOrganisation(random(), random(), null, null, null); Curriculum curriculum = curriculumService.createCurriculum(random(), random(), null, organisation); dbInstance.commitAndCloseSession(); @@ -192,7 +192,35 @@ public class CurriculumElementProviderDAOTest extends OlatTestCase { dbInstance.commitAndCloseSession(); SearchParameters searchParams = new SearchParameters(); - searchParams.setCurriculumElementRefs(asList(curriculumElement1, curriculumElement2)); + searchParams.setWhiteListRefs(asList(curriculumElement1, curriculumElement2)); + List<CurriculumElement> pending = sut.loadPending(searchParams); + + assertThat(pending) + .containsExactlyInAnyOrder(curriculumElement1, curriculumElement2) + .doesNotContain(otherCurriculumElement); + } + + @Test + public void shouldFilterByBlackList() { + Organisation organisation = organisationService.createOrganisation(random(), random(), null, null, null); + Curriculum curriculum = curriculumService.createCurriculum(random(), random(), null, organisation); + CurriculumElementType type = curriculumService.createCurriculumElementType(random(), random(), random(), null); + dbInstance.commitAndCloseSession(); + + CurriculumElement curriculumElement1 = curriculumService.createCurriculumElement(random(), random(), + CurriculumElementStatus.active, oneDayAgo(), inOneDay(), null, type, CurriculumCalendars.disabled, + CurriculumLectures.disabled, CurriculumLearningProgress.disabled, curriculum); + CurriculumElement curriculumElement2 = curriculumService.createCurriculumElement(random(), random(), + CurriculumElementStatus.active, oneDayAgo(), inOneDay(), null, type, CurriculumCalendars.disabled, + CurriculumLectures.disabled, CurriculumLearningProgress.disabled, curriculum); + CurriculumElement otherCurriculumElement = curriculumService.createCurriculumElement(random(), random(), + CurriculumElementStatus.active, oneDayAgo(), inOneDay(), null, type, CurriculumCalendars.disabled, + CurriculumLectures.disabled, CurriculumLearningProgress.disabled, curriculum); + dbInstance.commitAndCloseSession(); + + SearchParameters searchParams = new SearchParameters(); + searchParams.setCeTypeKey(type.getKey()); + searchParams.setBlackListRefs(asList(otherCurriculumElement)); List<CurriculumElement> pending = sut.loadPending(searchParams); assertThat(pending) -- GitLab