diff --git a/src/main/java/org/olat/modules/quality/QualityDataCollectionViewSearchParams.java b/src/main/java/org/olat/modules/quality/QualityDataCollectionViewSearchParams.java index af33ef4cfb755423ec6a4f663a58926498a17b14..aaec48959ee25a93299b38d02f7e97fbff58a76f 100644 --- a/src/main/java/org/olat/modules/quality/QualityDataCollectionViewSearchParams.java +++ b/src/main/java/org/olat/modules/quality/QualityDataCollectionViewSearchParams.java @@ -20,9 +20,13 @@ package org.olat.modules.quality; import java.util.Collection; +import java.util.Date; +import java.util.List; import org.olat.basesecurity.IdentityRef; import org.olat.core.id.OrganisationRef; +import org.olat.modules.quality.generator.QualityGeneratorRef; +import org.olat.repository.RepositoryEntryRef; /** * @@ -32,51 +36,150 @@ import org.olat.core.id.OrganisationRef; */ public class QualityDataCollectionViewSearchParams { - private QualityDataCollectionRef dataCollectionRef; private Collection<? extends OrganisationRef> organsationRefs; private IdentityRef reportAccessIdentity; private Collection<? extends OrganisationRef> learnResourceManagerOrganisationRefs; private boolean ignoreReportAccessRelationRole; - - public QualityDataCollectionRef getDataCollectionRef() { - return dataCollectionRef; - } - - public void setDataCollectionRef(QualityDataCollectionRef dataCollectionRef) { - this.dataCollectionRef = dataCollectionRef; - } - + private String searchString; + private String title; + private String topic; + private Date startAfter; + private Date startBefore; + private Date deadlineAfter; + private Date deadlineBefore; + private QualityDataCollectionRef dataCollectionRef; + private List<? extends QualityGeneratorRef> generatorRefs; + private List<? extends RepositoryEntryRef> formEntryRefs; + private List<QualityDataCollectionTopicType> topicTypes; + private List<QualityDataCollectionStatus> status; + public Collection<? extends OrganisationRef> getOrgansationRefs() { return organsationRefs; } - + public void setOrgansationRefs(Collection<? extends OrganisationRef> organsationRefs) { this.organsationRefs = organsationRefs; } - + public IdentityRef getReportAccessIdentity() { return reportAccessIdentity; } - - public void setReportAccessIdentity(IdentityRef identityRef) { - this.reportAccessIdentity = identityRef; + + public void setReportAccessIdentity(IdentityRef reportAccessIdentity) { + this.reportAccessIdentity = reportAccessIdentity; } - + public Collection<? extends OrganisationRef> getLearnResourceManagerOrganisationRefs() { return learnResourceManagerOrganisationRefs; } - + public void setLearnResourceManagerOrganisationRefs( Collection<? extends OrganisationRef> learnResourceManagerOrganisationRefs) { this.learnResourceManagerOrganisationRefs = learnResourceManagerOrganisationRefs; } - + public boolean isIgnoreReportAccessRelationRole() { return ignoreReportAccessRelationRole; } - + public void setIgnoreReportAccessRelationRole(boolean ignoreReportAccessRelationRole) { this.ignoreReportAccessRelationRole = ignoreReportAccessRelationRole; } + + public String getSearchString() { + return searchString; + } + + public void setSearchString(String searchString) { + this.searchString = searchString; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public Date getStartAfter() { + return startAfter; + } + + public void setStartAfter(Date startAfter) { + this.startAfter = startAfter; + } + + public Date getStartBefore() { + return startBefore; + } + + public void setStartBefore(Date startBefore) { + this.startBefore = startBefore; + } + + public Date getDeadlineAfter() { + return deadlineAfter; + } + + public void setDeadlineAfter(Date deadlineAfter) { + this.deadlineAfter = deadlineAfter; + } + + public Date getDeadlineBefore() { + return deadlineBefore; + } + + public void setDeadlineBefore(Date deadlineBefore) { + this.deadlineBefore = deadlineBefore; + } + + public QualityDataCollectionRef getDataCollectionRef() { + return dataCollectionRef; + } + + public void setDataCollectionRef(QualityDataCollectionRef dataCollectionRef) { + this.dataCollectionRef = dataCollectionRef; + } + + public List<? extends QualityGeneratorRef> getGeneratorRefs() { + return generatorRefs; + } + + public void setGeneratorRefs(List<? extends QualityGeneratorRef> generatorRefs) { + this.generatorRefs = generatorRefs; + } + + public List<? extends RepositoryEntryRef> getFormEntryRefs() { + return formEntryRefs; + } + + public void setFormEntryRefs(List<? extends RepositoryEntryRef> formEntryRefs) { + this.formEntryRefs = formEntryRefs; + } + + public List<QualityDataCollectionTopicType> getTopicTypes() { + return topicTypes; + } + + public void setTopicTypes(List<QualityDataCollectionTopicType> topicTypes) { + this.topicTypes = topicTypes; + } + + public List<QualityDataCollectionStatus> getStatus() { + return status; + } + + public void setStatus(List<QualityDataCollectionStatus> status) { + this.status = status; + } } diff --git a/src/main/java/org/olat/modules/quality/QualityService.java b/src/main/java/org/olat/modules/quality/QualityService.java index ce8c46a97a1a173742ed4c46c4f7bc47a942a9e0..1ad263424f7022fb925b1c992d784ad7bf818e9e 100644 --- a/src/main/java/org/olat/modules/quality/QualityService.java +++ b/src/main/java/org/olat/modules/quality/QualityService.java @@ -91,6 +91,10 @@ public interface QualityService { * @param until the date to evaluate if a deadline has passed */ public void startDataCollection(Date until); + + public List<QualityGenerator> getGenerators(QualityDataCollectionViewSearchParams searchParams); + + public List<RepositoryEntry> getFormEntries(QualityDataCollectionViewSearchParams searchParams); public int getDataCollectionCount(QualityDataCollectionViewSearchParams searchParams); diff --git a/src/main/java/org/olat/modules/quality/generator/QualityGeneratorRef.java b/src/main/java/org/olat/modules/quality/generator/QualityGeneratorRef.java index 75fae98d7cf6cf27b288616db25be1c541d05fea..0258f1566223653f83c053ae18520d4df43c33cb 100644 --- a/src/main/java/org/olat/modules/quality/generator/QualityGeneratorRef.java +++ b/src/main/java/org/olat/modules/quality/generator/QualityGeneratorRef.java @@ -30,5 +30,10 @@ public interface QualityGeneratorRef { public String RESOURCEABLE_TYPE_NAME = "generator"; public Long getKey(); + + public static QualityGeneratorRef of(String keyString) { + Long key = Long.valueOf(keyString); + return () -> key; + } } 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 1e2b37e91f6f898005fb9c8bb4f0715da88504b9..1f7aabdc27fe0e896a0b3c693f958f6c372abc05 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 @@ -148,7 +148,7 @@ public class CourseLecturesFollowUpProvider implements QualityGeneratorProvider List<Organisation> organisations = generatorService.loadGeneratorOrganisations(generator); String previousGeneratorKey = configs.getValue(CONFIG_KEY_PREVIOUS_GENERATOR_KEY); - QualityGeneratorRef previousGeneratorRef = getQualityGeneratorRef(previousGeneratorKey); + QualityGeneratorRef previousGeneratorRef = QualityGeneratorRef.of(previousGeneratorKey); QualityGeneratorConfigs previosGeneratorConfigs = getPreviosGeneratorConfigs(previousGeneratorRef); SearchParameters searchParams = getSeachParameters(generator, configs, organisations, fromDate, toDate, @@ -190,7 +190,7 @@ public class CourseLecturesFollowUpProvider implements QualityGeneratorProvider List<Organisation> organisations = generatorService.loadGeneratorOrganisations(generator); String previousGeneratorKey = configs.getValue(CONFIG_KEY_PREVIOUS_GENERATOR_KEY); - QualityGeneratorRef previousGeneratorRef = getQualityGeneratorRef(previousGeneratorKey); + QualityGeneratorRef previousGeneratorRef = QualityGeneratorRef.of(previousGeneratorKey); QualityGeneratorConfigs previosGeneratorConfigs = getPreviosGeneratorConfigs(previousGeneratorRef); SearchParameters searchParams = getSeachParameters(generator, configs, organisations, fromDate, toDate, @@ -449,10 +449,5 @@ public class CourseLecturesFollowUpProvider implements QualityGeneratorProvider QualityGenerator generator = generatorService.loadGenerator(generatorRef); return generatorService.loadGeneratorConfigs(generator); } - - private QualityGeneratorRef getQualityGeneratorRef(String keyString) { - Long key = Long.valueOf(keyString); - return () -> key; - } } diff --git a/src/main/java/org/olat/modules/quality/manager/QualityDataCollectionDAO.java b/src/main/java/org/olat/modules/quality/manager/QualityDataCollectionDAO.java index e0cbe6eca383211896e929e83968165a36b7c475..13835959f5c17505023ab7a672b0d1b9d7d8a265 100644 --- a/src/main/java/org/olat/modules/quality/manager/QualityDataCollectionDAO.java +++ b/src/main/java/org/olat/modules/quality/manager/QualityDataCollectionDAO.java @@ -33,10 +33,12 @@ import java.util.stream.Collectors; import javax.persistence.TypedQuery; import org.olat.core.commons.persistence.DB; +import org.olat.core.commons.persistence.PersistenceHelper; import org.olat.core.commons.persistence.QueryBuilder; import org.olat.core.commons.persistence.SortKey; import org.olat.core.gui.translator.Translator; import org.olat.core.id.OrganisationRef; +import org.olat.core.util.StringHelper; import org.olat.modules.curriculum.CurriculumElementRef; import org.olat.modules.curriculum.CurriculumRef; import org.olat.modules.quality.QualityDataCollection; @@ -50,8 +52,10 @@ import org.olat.modules.quality.QualityDataCollectionViewSearchParams; import org.olat.modules.quality.QualityReportAccess; import org.olat.modules.quality.QualityReportAccessRightProvider; import org.olat.modules.quality.generator.QualityGenerator; +import org.olat.modules.quality.generator.QualityGeneratorRef; import org.olat.modules.quality.model.QualityDataCollectionImpl; import org.olat.modules.taxonomy.TaxonomyLevelRef; +import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -344,9 +348,38 @@ public class QualityDataCollectionDAO { .getResultList(); return keys != null && !keys.isEmpty() && keys.get(0) != null; } - + + List<QualityGenerator> loadGenerators(QualityDataCollectionViewSearchParams searchParams) { + QueryBuilder sb = new QueryBuilder(); + sb.append("select distinct(collection.generator)"); + sb.append(" from qualitydatacollection as collection"); + appendWhereClause(sb, searchParams); + + TypedQuery<QualityGenerator> query = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), QualityGenerator.class); + appendParameter(query, searchParams); + + return query.getResultList(); + } + + public List<RepositoryEntry> loadFormEntries(QualityDataCollectionViewSearchParams searchParams) { + QueryBuilder sb = new QueryBuilder(); + sb.append("select distinct(form)"); + sb.append(" from qualitydatacollection as collection"); + sb.append(" join evaluationformsurvey survey on survey.resName = '").append(QualityDataCollectionLight.RESOURCEABLE_TYPE_NAME).append("'"); + sb.append(" and survey.resId = collection.key"); + sb.append(" join survey.formEntry as form"); + appendWhereClause(sb, searchParams); + + TypedQuery<RepositoryEntry> query = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), RepositoryEntry.class); + appendParameter(query, searchParams); + + return query.getResultList(); + } + int getDataCollectionCount(QualityDataCollectionViewSearchParams searchParams) { - QueryBuilder sb = new QueryBuilder(256); + QueryBuilder sb = new QueryBuilder(); sb.append("select count(collection)"); sb.append(" from qualitydatacollection as collection"); appendWhereClause(sb, searchParams); @@ -436,6 +469,48 @@ public class QualityDataCollectionDAO { if (searchParams.getDataCollectionRef() != null && searchParams.getDataCollectionRef().getKey() != null) { sb.and().append("collection.key = :collectionKey"); } + if (searchParams.getFormEntryRefs() != null) { + sb.and().append("form.key in (:formKeys)"); + } + if (StringHelper.containsNonWhitespace(searchParams.getTitle())) { + sb.and().append("lower(collection.title) like :title"); + } + if (searchParams.getStartAfter() != null) { + sb.and().append("collection.start >= :startAfter"); + } + if (searchParams.getStartBefore() != null) { + sb.and().append("collection.start <= :startBefore"); + } + if (searchParams.getDeadlineAfter() != null) { + sb.and().append("collection.deadline >= :deadlineAfter"); + } + if (searchParams.getDeadlineBefore() != null) { + sb.and().append("collection.deadline <= :deadlineBefore"); + } + if (StringHelper.containsNonWhitespace(searchParams.getTopic()) + || StringHelper.containsNonWhitespace(searchParams.getSearchString())) { + sb.and().append("("); + sb.append("lower(collection.topicCustom) like :topic"); + sb.append(" or lower(user.lastName) like :topic"); + sb.append(" or lower(user.firstName) like :topic"); + sb.append(" or lower(organisation.displayName) like :topic"); + sb.append(" or lower(curriculum.displayName) like :topic"); + sb.append(" or lower(curriculumElement.displayName) like :topic"); + sb.append(" or lower(repository.displayname) like :topic"); + if (StringHelper.containsNonWhitespace(searchParams.getSearchString())) { + sb.append(" or lower(collection.title) like :topic"); + } + sb.append(")"); + } + if (searchParams.getTopicTypes() != null) { + sb.and().append("collection.topicType in (:topicTypes)"); + } + if (searchParams.getGeneratorRefs() != null) { + sb.and().append("collection.generator.key in (:generatorKeys)"); + } + if (searchParams.getStatus() != null) { + sb.and().append("collection.status in (:status)"); + } // (searchParams.getOrgansationRefs() == null): show all data collections if (searchParams.getOrgansationRefs() != null) { sb.and().append("("); @@ -562,6 +637,41 @@ public class QualityDataCollectionDAO { if (searchParams.getDataCollectionRef() != null && searchParams.getDataCollectionRef().getKey() != null) { query.setParameter("collectionKey", searchParams.getDataCollectionRef().getKey()); } + if (searchParams.getFormEntryRefs() != null) { + List<Long> generatorKeys = searchParams.getFormEntryRefs().stream().map(RepositoryEntryRef::getKey).collect(toList()); + query.setParameter("formKeys", generatorKeys); + } + if (StringHelper.containsNonWhitespace(searchParams.getTitle())) { + query.setParameter("title", PersistenceHelper.makeFuzzyQueryString(searchParams.getTitle().toLowerCase())); + } + if (searchParams.getStartAfter() != null) { + query.setParameter("startAfter", searchParams.getStartAfter()); + } + if (searchParams.getStartBefore() != null) { + query.setParameter("startBefore", searchParams.getStartBefore()); + } + if (searchParams.getDeadlineAfter() != null) { + query.setParameter("deadlineAfter", searchParams.getDeadlineAfter()); + } + if (searchParams.getDeadlineBefore() != null) { + query.setParameter("deadlineBefore", searchParams.getDeadlineBefore()); + } + if (StringHelper.containsNonWhitespace(searchParams.getTopic())) { + query.setParameter("topic", PersistenceHelper.makeFuzzyQueryString(searchParams.getTopic().toLowerCase())); + } + if (StringHelper.containsNonWhitespace(searchParams.getSearchString())) { + query.setParameter("topic", PersistenceHelper.makeFuzzyQueryString(searchParams.getSearchString().toLowerCase())); + } + if (searchParams.getTopicTypes() != null) { + query.setParameter("topicTypes", searchParams.getTopicTypes()); + } + if (searchParams.getGeneratorRefs() != null) { + List<Long> generatorKeys = searchParams.getGeneratorRefs().stream().map(QualityGeneratorRef::getKey).collect(toList()); + query.setParameter("generatorKeys", generatorKeys); + } + if (searchParams.getStatus() != null) { + query.setParameter("status", searchParams.getStatus()); + } // (searchParams.getOrgansationRefs() == null): show all data collections if (searchParams.getOrgansationRefs() != null) { List<Long> organiationKeys = searchParams.getOrgansationRefs().stream().map(OrganisationRef::getKey).collect(toList()); @@ -600,4 +710,5 @@ public class QualityDataCollectionDAO { } return sb; } + } diff --git a/src/main/java/org/olat/modules/quality/manager/QualityServiceImpl.java b/src/main/java/org/olat/modules/quality/manager/QualityServiceImpl.java index 6e9100a401f98b825c7722e237ef8bb48d263250..263a2ee4198ba83fe569cde2de54a1b641b67f88 100644 --- a/src/main/java/org/olat/modules/quality/manager/QualityServiceImpl.java +++ b/src/main/java/org/olat/modules/quality/manager/QualityServiceImpl.java @@ -364,6 +364,16 @@ public class QualityServiceImpl } return statistics; } + + @Override + public List<QualityGenerator> getGenerators(QualityDataCollectionViewSearchParams searchParams) { + return dataCollectionDao.loadGenerators(searchParams); + } + + @Override + public List<RepositoryEntry> getFormEntries(QualityDataCollectionViewSearchParams searchParams) { + return dataCollectionDao.loadFormEntries(searchParams); + } @Override public int getDataCollectionCount(QualityDataCollectionViewSearchParams searchParams) { diff --git a/src/main/java/org/olat/modules/quality/ui/DataCollectionDataModel.java b/src/main/java/org/olat/modules/quality/ui/DataCollectionDataModel.java index c09778b3c042550f08a6e157f92a9c8c6dea9c22..f5f37549cecacc39aa544a4f85ec3e683894f586 100644 --- a/src/main/java/org/olat/modules/quality/ui/DataCollectionDataModel.java +++ b/src/main/java/org/olat/modules/quality/ui/DataCollectionDataModel.java @@ -27,7 +27,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate; import org.olat.core.gui.translator.Translator; import org.olat.core.util.StringHelper; -import org.olat.modules.quality.ui.security.MainSecurityCallback; /** * @@ -38,13 +37,11 @@ import org.olat.modules.quality.ui.security.MainSecurityCallback; public class DataCollectionDataModel extends DefaultFlexiTableDataSourceModel<DataCollectionRow> { private final Translator translator; - private final MainSecurityCallback secCallback; public DataCollectionDataModel(FlexiTableDataSourceDelegate<DataCollectionRow> dataSource, - FlexiTableColumnModel columnsModel, Translator translator, MainSecurityCallback secCallback) { + FlexiTableColumnModel columnsModel, Translator translator) { super(dataSource, columnsModel); this.translator = translator; - this.secCallback = secCallback; } public DataCollectionRow getObjectByKey(Long key) { @@ -61,6 +58,7 @@ public class DataCollectionDataModel extends DefaultFlexiTableDataSourceModel<Da public Object getValueAt(int row, int col) { DataCollectionRow dataCollectionRow = getObject(row); switch (DataCollectionCols.values()[col]) { + case key: return dataCollectionRow.getKey(); case status: return dataCollectionRow.getStatus(); case title: { String title = dataCollectionRow.getTitle(); @@ -82,10 +80,11 @@ public class DataCollectionDataModel extends DefaultFlexiTableDataSourceModel<Da @Override public DefaultFlexiTableDataSourceModel<DataCollectionRow> createCopyWithEmptyList() { - return new DataCollectionDataModel(getSourceDelegate(), getTableColumnModel(), translator, secCallback); + return new DataCollectionDataModel(getSourceDelegate(), getTableColumnModel(), translator); } public enum DataCollectionCols implements FlexiSortableColumnDef { + key("data.collection.id"), status("data.collection.status"), title("data.collection.title"), start("data.collection.start"), diff --git a/src/main/java/org/olat/modules/quality/ui/DataCollectionDataSource.java b/src/main/java/org/olat/modules/quality/ui/DataCollectionDataSource.java index 5b150c917a7236a8d696e7bbede96cf3af78a61d..579ca0532e6889998eca9cd01b8f5837a6253e6a 100644 --- a/src/main/java/org/olat/modules/quality/ui/DataCollectionDataSource.java +++ b/src/main/java/org/olat/modules/quality/ui/DataCollectionDataSource.java @@ -20,12 +20,9 @@ package org.olat.modules.quality.ui; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; -import org.olat.basesecurity.BaseSecurityModule; -import org.olat.basesecurity.IdentityRef; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DefaultResultInfos; import org.olat.core.commons.persistence.ResultInfos; @@ -33,7 +30,6 @@ import org.olat.core.commons.persistence.SortKey; import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate; import org.olat.core.gui.translator.Translator; -import org.olat.core.id.OrganisationRef; import org.olat.modules.quality.QualityDataCollectionView; import org.olat.modules.quality.QualityDataCollectionViewSearchParams; import org.olat.modules.quality.QualityService; @@ -48,22 +44,25 @@ import org.springframework.beans.factory.annotation.Autowired; public class DataCollectionDataSource implements FlexiTableDataSourceDelegate<DataCollectionRow> { private final Translator translator; - private final QualityDataCollectionViewSearchParams searchParams; + private final QualityDataCollectionViewSearchParams defaultSearchParams; + private QualityDataCollectionViewSearchParams searchParams; @Autowired private QualityService qualityService; - @Autowired - private BaseSecurityModule securityModule; - public DataCollectionDataSource(Translator translator, Collection<? extends OrganisationRef> organsationRefs, - IdentityRef identityRef, Collection<? extends OrganisationRef> learnResourceManagerOrganisationRefs) { + public DataCollectionDataSource(Translator translator, QualityDataCollectionViewSearchParams defaultSearchParams) { this.translator = translator; + this.defaultSearchParams = defaultSearchParams; + CoreSpringFactory.autowireObject(this); - searchParams = new QualityDataCollectionViewSearchParams(); - searchParams.setOrgansationRefs(organsationRefs); - searchParams.setReportAccessIdentity(identityRef); - searchParams.setLearnResourceManagerOrganisationRefs(learnResourceManagerOrganisationRefs); - searchParams.setIgnoreReportAccessRelationRole(!securityModule.isRelationRoleEnabled()); + } + + public void setSearchParams(QualityDataCollectionViewSearchParams searchParams) { + this.searchParams = searchParams; + this.searchParams.setOrgansationRefs(defaultSearchParams.getOrgansationRefs()); + this.searchParams.setReportAccessIdentity(defaultSearchParams.getReportAccessIdentity()); + this.searchParams.setLearnResourceManagerOrganisationRefs(defaultSearchParams.getLearnResourceManagerOrganisationRefs()); + this.searchParams.setIgnoreReportAccessRelationRole(defaultSearchParams.isIgnoreReportAccessRelationRole()); } @Override diff --git a/src/main/java/org/olat/modules/quality/ui/DataCollectionListController.java b/src/main/java/org/olat/modules/quality/ui/DataCollectionListController.java index 51ef37963ff89f5c9dfdaa1e0ef395dab10ff4ef..09a18a9481c02005ca60c54cbdfb9d192701a45e 100644 --- a/src/main/java/org/olat/modules/quality/ui/DataCollectionListController.java +++ b/src/main/java/org/olat/modules/quality/ui/DataCollectionListController.java @@ -21,6 +21,7 @@ package org.olat.modules.quality.ui; import java.util.List; +import org.olat.basesecurity.BaseSecurityModule; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.form.flexible.FormItem; @@ -32,6 +33,7 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFle import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableSearchEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; @@ -53,6 +55,7 @@ import org.olat.modules.forms.handler.EvaluationFormResource; import org.olat.modules.quality.QualityDataCollection; import org.olat.modules.quality.QualityDataCollectionLight; import org.olat.modules.quality.QualityDataCollectionView; +import org.olat.modules.quality.QualityDataCollectionViewSearchParams; import org.olat.modules.quality.QualityService; import org.olat.modules.quality.ui.DataCollectionDataModel.DataCollectionCols; import org.olat.modules.quality.ui.event.DataCollectionEvent; @@ -79,13 +82,17 @@ public class DataCollectionListController extends FormBasicController implements private CloseableModalController cmc; private DataCollectionController dataCollectionCtrl; + private DataCollectionSearchController searchCtrl; private ReferencableEntriesSearchController formSearchCtrl; private DataCollectionDeleteConfirmationController deleteConfirmationCtrl; private final MainSecurityCallback secCallback; + private final DataCollectionDataSource dataSource; @Autowired private QualityService qualityService; + @Autowired + private BaseSecurityModule securityModule; public DataCollectionListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, MainSecurityCallback secCallback) { @@ -94,12 +101,24 @@ public class DataCollectionListController extends FormBasicController implements stackPanel.addListener(this); this.secCallback = secCallback; + QualityDataCollectionViewSearchParams defaultSearchParams = new QualityDataCollectionViewSearchParams(); + defaultSearchParams.setOrgansationRefs(secCallback.getViewDataCollectionOrganisationRefs()); + defaultSearchParams.setReportAccessIdentity(getIdentity()); + defaultSearchParams.setLearnResourceManagerOrganisationRefs(secCallback.getLearnResourceManagerOrganisationRefs()); + defaultSearchParams.setIgnoreReportAccessRelationRole(!securityModule.isRelationRoleEnabled()); + dataSource = new DataCollectionDataSource(getTranslator(), defaultSearchParams); + + searchCtrl = new DataCollectionSearchController(ureq, getWindowControl(), mainForm, defaultSearchParams); + searchCtrl.setEnabled(false); + listenTo(searchCtrl); + initForm(ureq); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, DataCollectionCols.key)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(DataCollectionCols.status, new DataCollectionStatusCellRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(DataCollectionCols.title, CMD_EDIT)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(DataCollectionCols.start)); @@ -114,14 +133,13 @@ public class DataCollectionListController extends FormBasicController implements columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, DataCollectionCols.creationDate)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, DataCollectionCols.generatorTitle)); - DataCollectionDataSource dataSource = new DataCollectionDataSource(getTranslator(), - secCallback.getViewDataCollectionOrganisationRefs(), getIdentity(), - secCallback.getLearnResourceManagerOrganisationRefs()); - dataModel = new DataCollectionDataModel(dataSource, columnsModel, getTranslator(), secCallback); + dataModel = new DataCollectionDataModel(dataSource, columnsModel, getTranslator()); tableEl = uifactory.addTableElement(getWindowControl(), "dataCollections", dataModel, 25, true, getTranslator(), formLayout); tableEl.setElementCssClass("o_qual_dc_list"); tableEl.setAndLoadPersistedPreferences(ureq, "quality-data-collection"); tableEl.setEmtpyTableMessageKey("data.collection.empty.table"); + tableEl.setSearchEnabled(true); //TODO uh search and advanced search + tableEl.setExtendedSearch(searchCtrl); } @Override @@ -140,6 +158,7 @@ public class DataCollectionListController extends FormBasicController implements ContextEntry entry = entries.get(0); String type = entry.getOLATResourceable().getResourceableTypeName(); if (QualityDataCollectionLight.RESOURCEABLE_TYPE_NAME.equals(type)) { + doResetExtendedSearch(ureq); Long key = entry.getOLATResourceable().getResourceableId(); DataCollectionRow row = dataModel.getObjectByKey(key); if (row == null) { @@ -182,6 +201,9 @@ public class DataCollectionListController extends FormBasicController implements if (CMD_EDIT.equals(cmd)) { doEditDataCollection(ureq, row.getDataCollection()); } + } else if(event instanceof FlexiTableSearchEvent) { + FlexiTableSearchEvent ftse = (FlexiTableSearchEvent)event; + doSearch(ftse.getSearch()); } super.formInnerEvent(ureq, source, event); } @@ -205,6 +227,13 @@ public class DataCollectionListController extends FormBasicController implements QualityDataCollection dataCollectionToDelete = dccEvent.getDataCollection(); doConfirmDeleteDataCollection(ureq, dataCollectionToDelete); } + }else if (searchCtrl == source) { + if (event instanceof SearchEvent) { + SearchEvent se = (SearchEvent)event; + doExtendedSearch(se); + } else if (event == Event.CANCELLED_EVENT) { + doResetExtendedSearch(ureq); + } } else if (source == formSearchCtrl) { if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) { RepositoryEntry formEntry = formSearchCtrl.getSelectedEntry(); @@ -276,6 +305,37 @@ public class DataCollectionListController extends FormBasicController implements tableEl.reset(true, false, true); stackPanel.popUpToController(this); } + private void doSearch(String search) { + QualityDataCollectionViewSearchParams params = new QualityDataCollectionViewSearchParams(); + params.setSearchString(search); + doSearch(params); + } + + private void doExtendedSearch(SearchEvent se) { + QualityDataCollectionViewSearchParams params = new QualityDataCollectionViewSearchParams(); + params.setTitle(se.getTitle()); + params.setTopic(se.getTopic()); + params.setStartAfter(se.getStartAfter()); + params.setStartBefore(se.getStartBefore()); + params.setDeadlineAfter(se.getDeadlineAfter()); + params.setDeadlineBefore(se.getDeadlineBefore()); + params.setDataCollectionRef(se.getDataCollectionRef()); + params.setGeneratorRefs(se.getGeneratorRefs()); + params.setFormEntryRefs(se.getFormEntryRefs()); + params.setTopicTypes(se.getTopicTypes()); + params.setStatus(se.getStatus()); + doSearch(params); + } + + private void doSearch(QualityDataCollectionViewSearchParams params) { + dataSource.setSearchParams(params); + tableEl.reset(true, true, true); + } + + private void doResetExtendedSearch(UserRequest ureq) { + dataSource.setSearchParams(new QualityDataCollectionViewSearchParams()); + tableEl.resetSearch(ureq); + } @Override protected void formOK(UserRequest ureq) { diff --git a/src/main/java/org/olat/modules/quality/ui/DataCollectionSearchController.java b/src/main/java/org/olat/modules/quality/ui/DataCollectionSearchController.java new file mode 100644 index 0000000000000000000000000000000000000000..4a24b51033ee43d7839deb31b46ea5a8fc7cb72b --- /dev/null +++ b/src/main/java/org/olat/modules/quality/ui/DataCollectionSearchController.java @@ -0,0 +1,262 @@ +/** + * <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.ui; + +import static org.olat.core.gui.components.util.KeyValues.entry; + +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.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.DateChooser; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.Form; +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.ExtendedFlexiTableSearchController; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.util.KeyValues; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.olat.modules.quality.QualityDataCollectionStatus; +import org.olat.modules.quality.QualityDataCollectionTopicType; +import org.olat.modules.quality.QualityDataCollectionViewSearchParams; +import org.olat.modules.quality.QualityService; +import org.olat.modules.quality.generator.QualityGenerator; +import org.olat.modules.quality.generator.QualityGeneratorRef; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.model.RepositoryEntryRefImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 28 Aug 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class DataCollectionSearchController extends FormBasicController implements ExtendedFlexiTableSearchController { + + private MultipleSelectionElement fromEntriesEl; + private TextElement titleEl; + private MultipleSelectionElement topicTypeEl; + private TextElement topicEl; + private TextElement keyEl; + private MultipleSelectionElement generatorsEl; + private DateChooser startAfterEl; + private DateChooser startBeforeEl; + private DateChooser deadlineAfterEl; + private DateChooser deadlineBeforeEl; + private MultipleSelectionElement statusEl; + private FormLink searchButton; + + private final QualityDataCollectionViewSearchParams defaultSearchParams; + private boolean enabled = true; + + @Autowired + private QualityService qualityService; + + public DataCollectionSearchController(UserRequest ureq, WindowControl wControl, Form mainForm, + QualityDataCollectionViewSearchParams defaultSearchParams) { + super(ureq, wControl, LAYOUT_CUSTOM, "data_collection_search", mainForm); + this.defaultSearchParams = defaultSearchParams; + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + FormLayoutContainer leftContainer = FormLayoutContainer.createDefaultFormLayout("left_1", getTranslator()); + leftContainer.setRootForm(mainForm); + formLayout.add(leftContainer); + + // LEFT part of form + List<RepositoryEntry> formEntries = qualityService.getFormEntries(defaultSearchParams); + KeyValues formEntriesKV = new KeyValues(); + formEntries.forEach(formEntry -> formEntriesKV.add(entry(formEntry.getKey().toString(), formEntry.getDisplayname()))); + formEntriesKV.sort(KeyValues.VALUE_ASC); + fromEntriesEl = uifactory.addCheckboxesDropdown("data.collection.form", "data.collection.form", + leftContainer, formEntriesKV.keys(), formEntriesKV.values()); + fromEntriesEl.setNonSelectedText(translate("search.show.all")); + + titleEl = uifactory.addTextElement("data.collection.title", "data.collection.title", 255, "", leftContainer); + titleEl.setFocus(true); + + KeyValues topicTypeKV = new KeyValues(); + Arrays.stream(QualityDataCollectionTopicType.values()) + .forEach(type -> topicTypeKV.add(entry(type.name(), translate(type.getI18nKey())))); + topicTypeEl = uifactory.addCheckboxesDropdown("data.collection.topic.type", "data.collection.topic.type", + leftContainer, topicTypeKV.keys(), topicTypeKV.values()); + topicTypeEl.setNonSelectedText(translate("search.show.all")); + + topicEl = uifactory.addTextElement("data.collection.topic", "data.collection.topic", 255, "", leftContainer); + + keyEl = uifactory.addTextElement("data.collection.id", "data.collection.id", 64, "", leftContainer); + + List<QualityGenerator> generators = qualityService.getGenerators(defaultSearchParams); + if (!generators.isEmpty()) { + KeyValues generatorsKV = new KeyValues(); + generators.forEach(generator -> generatorsKV.add(entry(generator.getKey().toString(), generator.getTitle()))); + generatorsKV.sort(KeyValues.VALUE_ASC); + generatorsEl = uifactory.addCheckboxesDropdown("data.collection.generator.title", + "data.collection.generator.title", leftContainer, generatorsKV.keys(), generatorsKV.values()); + } + + // RIGHT part of form + FormLayoutContainer rightContainer = FormLayoutContainer.createDefaultFormLayout("right_1", getTranslator()); + rightContainer.setRootForm(mainForm); + formLayout.add(rightContainer); + + startAfterEl = uifactory.addDateChooser("data.collection.start.after", null, rightContainer); + startAfterEl.setDateChooserTimeEnabled(true); + + startBeforeEl = uifactory.addDateChooser("data.collection.start.before", null, rightContainer); + startBeforeEl.setDateChooserTimeEnabled(true); + + deadlineAfterEl = uifactory.addDateChooser("data.collection.deadline.after", null, rightContainer); + deadlineAfterEl.setDateChooserTimeEnabled(true); + + deadlineBeforeEl = uifactory.addDateChooser("data.collection.deadline.before", null, rightContainer); + deadlineBeforeEl.setDateChooserTimeEnabled(true); + + KeyValues statusKV = new KeyValues(); + statusKV.add(entry(QualityDataCollectionStatus.PREPARATION.name(), translate("data.collection.status.preparation"))); + statusKV.add(entry(QualityDataCollectionStatus.READY.name(), translate("data.collection.status.ready"))); + statusKV.add(entry(QualityDataCollectionStatus.RUNNING.name(), translate("data.collection.status.running"))); + statusKV.add(entry(QualityDataCollectionStatus.FINISHED.name(), translate("data.collection.status.finished"))); + statusEl = uifactory.addCheckboxesHorizontal("data.collection.status", rightContainer, statusKV.keys(), statusKV.values()); + + + FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); + formLayout.add(buttonLayout); + uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl()); + searchButton = uifactory.addFormLink("search", buttonLayout, Link.BUTTON); + searchButton.setCustomEnabledLinkCSS("btn btn-primary"); + } + + @Override + public void setEnabled(boolean enable) { + this.enabled = enable; + } + + @Override + public List<String> getConditionalQueries() { + return Collections.emptyList(); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(enabled && source == searchButton) { + fireSearchEvent(ureq); + } + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + if(!enabled) return true; + + boolean allOk = super.validateFormLogic(ureq); + + allOk &= QualityUIFactory.validateLong(keyEl, 0, Long.MAX_VALUE); + + return allOk; + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + + @Override + protected void formOK(UserRequest ureq) { + if (enabled) { + fireSearchEvent(ureq); + } + } + + private void fireSearchEvent(UserRequest ureq) { + SearchEvent se = new SearchEvent(); + + if (fromEntriesEl.isAtLeastSelected(1)) { + List<RepositoryEntryRefImpl> formEntryRefs = fromEntriesEl.getSelectedKeys().stream() + .map(Long::valueOf) + .map(RepositoryEntryRefImpl::new) + .collect(Collectors.toList()); + se.setFormEntryRefs(formEntryRefs); + } + + String title = titleEl.getValue(); + if (StringHelper.containsNonWhitespace(title)) { + se.setTitle(title); + } + + if (topicTypeEl.isAtLeastSelected(1)) { + List<QualityDataCollectionTopicType> topicTypes = topicTypeEl.getSelectedKeys().stream() + .map(QualityDataCollectionTopicType::valueOf) + .collect(Collectors.toList()); + se.setTopicTypes(topicTypes); + } + + String topic = topicEl.getValue(); + if (StringHelper.containsNonWhitespace(topic)) { + se.setTopic(topic); + } + + if (generatorsEl != null && generatorsEl.isAtLeastSelected(1)) { + List<? extends QualityGeneratorRef> generatorRefs = generatorsEl.getSelectedKeys().stream() + .map(QualityGeneratorRef::of) + .collect(Collectors.toList()); + se.setGeneratorRefs(generatorRefs); + } + + if (statusEl.isAtLeastSelected(1)) { + List<QualityDataCollectionStatus> status = statusEl.getSelectedKeys().stream() + .map(QualityDataCollectionStatus::valueOf) + .collect(Collectors.toList()); + se.setStatus(status); + } + + String keyValue = keyEl.getValue(); + if (StringHelper.containsNonWhitespace(keyValue)) { + Long key = Long.valueOf(keyValue); + se.setDataCollectionRef(() -> key); + } + + se.setStartAfter(startAfterEl.getDate()); + se.setStartBefore(startBeforeEl.getDate()); + se.setDeadlineAfter(deadlineAfterEl.getDate()); + se.setDeadlineBefore(deadlineBeforeEl.getDate()); + + fireEvent(ureq, se); + } + + @Override + protected void doDispose() { + // + } + +} diff --git a/src/main/java/org/olat/modules/quality/ui/QualityUIFactory.java b/src/main/java/org/olat/modules/quality/ui/QualityUIFactory.java index a01745069906453c0502bd766a065bdd03f57d8b..f624d682b096ddd3fc1c0f0ad5eec2f810a96ad0 100644 --- a/src/main/java/org/olat/modules/quality/ui/QualityUIFactory.java +++ b/src/main/java/org/olat/modules/quality/ui/QualityUIFactory.java @@ -582,6 +582,31 @@ public class QualityUIFactory { return allOk; } + public static boolean validateLong(TextElement el, long min, long max) { + boolean allOk = true; + el.clearError(); + if(el.isEnabled() && el.isVisible()) { + String val = el.getValue(); + if(StringHelper.containsNonWhitespace(val)) { + + try { + long value = Long.parseLong(val); + if(min > value) { + el.setErrorKey("error.number.greater", new String[] {String.valueOf(min)}); + allOk = false; + } else if(max < value) { + el.setErrorKey("error.number.lower", new String[] {String.valueOf(max)}); + allOk = false; + } + } catch (NumberFormatException e) { + el.setErrorKey("error.wrong.number", null); + allOk = false; + } + } + } + return allOk; + } + public static boolean validateDouble(TextElement el, int min, int max) { boolean allOk = true; el.clearError(); diff --git a/src/main/java/org/olat/modules/quality/ui/SearchEvent.java b/src/main/java/org/olat/modules/quality/ui/SearchEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..0c8cfdc94dc96cae52d0d3c68eba46e95279caf9 --- /dev/null +++ b/src/main/java/org/olat/modules/quality/ui/SearchEvent.java @@ -0,0 +1,155 @@ +/** + * <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.ui; + +import java.util.Date; +import java.util.List; + +import org.olat.core.gui.control.Event; +import org.olat.modules.quality.QualityDataCollectionRef; +import org.olat.modules.quality.QualityDataCollectionStatus; +import org.olat.modules.quality.QualityDataCollectionTopicType; +import org.olat.modules.quality.generator.QualityGeneratorRef; +import org.olat.repository.RepositoryEntryRef; + +/** + * + * Initial date: 28 Aug 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class SearchEvent extends Event { + + private static final long serialVersionUID = -8809079365428887946L; + + private String searchString; + private String title; + private String topic; + private Date startAfter; + private Date startBefore; + private Date deadlineAfter; + private Date deadlineBefore; + private QualityDataCollectionRef dataCollectionRef; + private List<? extends QualityGeneratorRef> generatorRefs; + private List<? extends RepositoryEntryRef> formEntryRefs; + private List<QualityDataCollectionTopicType> topicTypes; + private List<QualityDataCollectionStatus> status; + + public SearchEvent() { + super("qulity-dc-search"); + } + + public String getSearchString() { + return searchString; + } + + public void setSearchString(String searchString) { + this.searchString = searchString; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public Date getStartAfter() { + return startAfter; + } + + public void setStartAfter(Date startAfter) { + this.startAfter = startAfter; + } + + public Date getStartBefore() { + return startBefore; + } + + public void setStartBefore(Date startBefore) { + this.startBefore = startBefore; + } + + public Date getDeadlineAfter() { + return deadlineAfter; + } + + public void setDeadlineAfter(Date deadlineAfter) { + this.deadlineAfter = deadlineAfter; + } + + public Date getDeadlineBefore() { + return deadlineBefore; + } + + public void setDeadlineBefore(Date deadlineBefore) { + this.deadlineBefore = deadlineBefore; + } + + public QualityDataCollectionRef getDataCollectionRef() { + return dataCollectionRef; + } + + public void setDataCollectionRef(QualityDataCollectionRef dataCollectionRef) { + this.dataCollectionRef = dataCollectionRef; + } + + public List<? extends QualityGeneratorRef> getGeneratorRefs() { + return generatorRefs; + } + + public void setGeneratorRefs(List<? extends QualityGeneratorRef> generatorRefs) { + this.generatorRefs = generatorRefs; + } + + public List<? extends RepositoryEntryRef> getFormEntryRefs() { + return formEntryRefs; + } + + public void setFormEntryRefs(List<? extends RepositoryEntryRef> formEntryRefs) { + this.formEntryRefs = formEntryRefs; + } + + public List<QualityDataCollectionTopicType> getTopicTypes() { + return topicTypes; + } + + public void setTopicTypes(List<QualityDataCollectionTopicType> topicTypes) { + this.topicTypes = topicTypes; + } + + public List<QualityDataCollectionStatus> getStatus() { + return status; + } + + public void setStatus(List<QualityDataCollectionStatus> status) { + this.status = status; + } + +} diff --git a/src/main/java/org/olat/modules/quality/ui/_content/data_collection_search.html b/src/main/java/org/olat/modules/quality/ui/_content/data_collection_search.html new file mode 100644 index 0000000000000000000000000000000000000000..d204118c125f59c8d7d1e6a7c46bbfe860c9666b --- /dev/null +++ b/src/main/java/org/olat/modules/quality/ui/_content/data_collection_search.html @@ -0,0 +1,13 @@ +<div class="row"> + <div class="col-md-6"> + $r.render("left_1") + </div> + <div class="col-md-6"> + $r.render("right_1") + </div> +</div> +<div class="row"> + <div class="col-md-offset-3 col-md-9"> + $r.render("button_layout") + </div> +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/modules/quality/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/quality/ui/_i18n/LocalStrings_de.properties index d7c5f38dd2ce30205bbb2957276d68abb1777aba..43072ca35766214808bd9c7d15a2d63c27db555f 100644 --- a/src/main/java/org/olat/modules/quality/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/quality/ui/_i18n/LocalStrings_de.properties @@ -1,12 +1,12 @@ #Wed Dec 19 17:17:44 CET 2018 -admin.config.title=Einstellungen Qualit\u00E4tsmanagement -admin.enabled=Qualit\u00E4tsmanagement +admin.config.title=Einstellungen Qualit\u00e4tsmanagement +admin.enabled=Qualit\u00e4tsmanagement admin.from.email=Absender Email-Adresse -admin.from.email.help=Hier k\u00F6nnen Sie optional eine spezielle Email-Adresse f\u00FCr Emails des Qualit\u00E4tsmanagement konfigurieren (Einladungen, Erinnerungen, ...). +admin.from.email.help=Hier k\u00f6nnen Sie optional eine spezielle Email-Adresse f\u00fcr Emails des Qualit\u00e4tsmanagement konfigurieren (Einladungen, Erinnerungen, ...). admin.from.name=Absender Name -admin.menu.title=Qualit\u00E4tsmanagement +admin.menu.title=Qualit\u00e4tsmanagement admin.menu.title.alt=$\:admin.menu.title -admin.suggestion.email.addresses=Empf\u00E4nger Email-Adressen +admin.suggestion.email.addresses=Empf\u00e4nger Email-Adressen admin.suggestion.email.body=Email Nachricht (Vorlage) admin.suggestion.email.subject=Email Betreff (Vorlage) admin.suggestion.enabled=Verbesserungsvorschlag @@ -15,17 +15,19 @@ breadcrumb.analysis=$\:goto.analysis.title breadcrumb.data.collections=$\:goto.data.collection.title breadcrumb.executor.participations=$\:goto.executor.participation.title breadcrumb.generators=$\:goto.generator.title -breadcrumb.root=Qualit\u00E4tsmanagement +breadcrumb.root=Qualit\u00e4tsmanagement breadcrumb.suggestion=$\:goto.suggestion.title data.collection.configuration=Konfiguration data.collection.create=Datenerhebung erstellen data.collection.creation.date=Erstellt data.collection.deadline=Bis -data.collection.delete=L\u00F6schen -data.collection.delete.button=L\u00F6schen -data.collection.delete.confirm=Wollen sie die Datenerhebung "{0}" wirklich l\u00F6schen? -data.collection.delete.title=Datenerhebung l\u00F6schen -data.collection.empty.table=Diese Tabelle enth\u00E4hlt keine Daten. +data.collection.deadline.after="Bis" nach +data.collection.deadline.before="Bis" vor +data.collection.delete=L\u00f6schen +data.collection.delete.button=L\u00f6schen +data.collection.delete.confirm=Wollen sie die Datenerhebung "{0}" wirklich l\u00f6schen? +data.collection.delete.title=Datenerhebung l\u00f6schen +data.collection.empty.table=Diese Tabelle enth\u00e4hlt keine Daten. data.collection.figures.period=Erhebungszeitraum data.collection.figures.previous.title=Erstbefragung data.collection.figures.title=Titel @@ -39,8 +41,9 @@ data.collection.form.edit=Bearbeiten data.collection.form.preview= data.collection.form.preview.title=Vorschau data.collection.form.replace=Ersetzen -data.collection.form.select=Fragebogen ausw\u00E4hlen +data.collection.form.select=Fragebogen ausw\u00e4hlen data.collection.generator.title=Generator +data.collection.id=ID data.collection.number.of.participants=Teilnehmer data.collection.organisations=Organisationen data.collection.participations=Teilnehmer @@ -50,14 +53,16 @@ data.collection.report.access=Berechtigungen Report data.collection.report.followup=Zweitbefragung data.collection.report.previous=Erstbefragung data.collection.start=Von -data.collection.start.confirm=Wollen Sie diese Datenerhebung wirklich jetzt starten? Das Startdatum wird auf das heutige Datum gesetzt. Die Konfiguration kann anschliessend nicht mehr ge\u00E4ndert werden. +data.collection.start.after="Von" nach +data.collection.start.before="Von" vor +data.collection.start.confirm=Wollen Sie diese Datenerhebung wirklich jetzt starten? Das Startdatum wird auf das heutige Datum gesetzt. Die Konfiguration kann anschliessend nicht mehr ge\u00e4ndert werden. data.collection.start.confirm.button=Start data.collection.start.confirm.title=Datenerhebung jetzt starten data.collection.status=Status data.collection.status.finished=Abgeschlossen data.collection.status.preparation=Vorbereitung data.collection.status.ready=Vorbereitet -data.collection.status.running=Durchf\u00FChrung +data.collection.status.running=Durchf\u00fchrung data.collection.title=Titel data.collection.title.empty=(Ohne Titel) data.collection.topic=Gegenstand @@ -67,36 +72,36 @@ data.collection.topic.custom=weiteres data.collection.topic.custom.text=Gegenstand data.collection.topic.identity=Betreuer data.collection.topic.identity.name=Betreuer -data.collection.topic.identity.none=Kein Betreuer ausgew\u00E4lt +data.collection.topic.identity.none=Kein Betreuer ausgew\u00e4lt data.collection.topic.identity.select=Select data.collection.topic.organisation=Organisation data.collection.topic.repository=Kurs data.collection.topic.repository.name=Kurs -data.collection.topic.repository.none=Kein Kurs ausgew\u00E4lt +data.collection.topic.repository.none=Kein Kurs ausgew\u00e4lt data.collection.topic.repository.select=Select data.collection.topic.title=Beurteilungsgegenstand data.collection.topic.type=Gegenstandsart data.collection.topic.type.select=Gegenstandsart data.collections=Datenerhebungen -error.deadline.before.start=Der Endtermin muss sp\u00E4ter sein als der Starttermin. -error.email.invalid=Email-Adresse ung\u00FCltig. -error.input.toolong=Der eingegebene Text ist mit {1} Zeichen zu lang. Bitte beschr\u00E4nken Sie sich auf maximal {0} Zeichen. -error.number.greater=Die Zahl muss gr\u00F6sser oder gleich {0} sein. +error.deadline.before.start=Der Endtermin muss sp\u00e4ter sein als der Starttermin. +error.email.invalid=Email-Adresse ung\u00fcltig. +error.input.toolong=Der eingegebene Text ist mit {1} Zeichen zu lang. Bitte beschr\u00e4nken Sie sich auf maximal {0} Zeichen. +error.number.greater=Die Zahl muss gr\u00f6sser oder gleich {0} sein. error.number.lower=Die Zahl muss kleiner oder gleich {0} sein. -error.email.name.no.address=Sie k\u00F6nnen den Namen nur angeben, wenn Sie auch eine Email-Adresse angeben. -error.repo.entry.missing=Der Fragebogen, welchen Sie anzeigen m\u00F6chten, wurde in der Zwischenzeit aus der Ablage der Lernressourcen gel\u00F6scht. -error.repo.entry.not.replaceable=Der Fragebogen kann nicht mehr ge\u00E4ndert werden. -error.wrong.number=Ung\u00FCltiges Zahlenfomat. +error.email.name.no.address=Sie k\u00f6nnen den Namen nur angeben, wenn Sie auch eine Email-Adresse angeben. +error.repo.entry.missing=Der Fragebogen, welchen Sie anzeigen m\u00f6chten, wurde in der Zwischenzeit aus der Ablage der Lernressourcen gel\u00f6scht. +error.repo.entry.not.replaceable=Der Fragebogen kann nicht mehr ge\u00e4ndert werden. +error.wrong.number=Ung\u00fcltiges Zahlenfomat. executor.participation.already.done=Sie haben bereits an der Umfrage "{0}" teilgenommen. Vielen Dank\! executor.participation.coach=$\:participation.role.coach executor.participation.curriculum.element=Curriculumelement executor.participation.deadline=$\:data.collection.deadline -executor.participation.empty.table=Es sind keine Umfragen vorhanden, an welchen Sie teilnehmen k\u00F6nnen. -executor.participation.execute=Ausf\u00FCllen +executor.participation.empty.table=Es sind keine Umfragen vorhanden, an welchen Sie teilnehmen k\u00f6nnen. +executor.participation.execute=Ausf\u00fcllen executor.participation.forbidden=Sie haben keinen Zugriff auf diese Umfrage\! executor.participation.future=Die Umfrage "{0}" ist noch nicht gestartet. -executor.participation.future.done.message=Vielen Dank f\u00FCr Ihre Teilnahme an der Umfrage. -executor.participation.over=Die Umfrage "{0}" ist bereits beendet. Sie k\u00F6nnen nicht mehr teilnehmen. +executor.participation.future.done.message=Vielen Dank f\u00fcr Ihre Teilnahme an der Umfrage. +executor.participation.over=Die Umfrage "{0}" ist bereits beendet. Sie k\u00f6nnen nicht mehr teilnehmen. executor.participation.owner=$\:participation.role.owner executor.participation.participant=$\:participation.role.participant executor.participation.previous.title=$\:data.collection.figures.previous.title @@ -114,17 +119,17 @@ executor.participation.title=$\:data.collection.title executor.participation.topic=$\:data.collection.topic executor.participation.topic.title=Beurteilungsgegenstand executor.participation.topic.type=$\:data.collection.topic.type -goto.analysis.help=\u00D6ffnen Sie das Analyse-Werkzeug, um die Antworten der Datenerhebungen zu filtern, zu visualisieren und zu analysieren oder \u00F6ffnen Sie eine vordefinierte Ansicht. -goto.analysis.link=Analyse-Werkzeug \u00F6ffnen +goto.analysis.help=\u00d6ffnen Sie das Analyse-Werkzeug, um die Antworten der Datenerhebungen zu filtern, zu visualisieren und zu analysieren oder \u00f6ffnen Sie eine vordefinierte Ansicht. +goto.analysis.link=Analyse-Werkzeug \u00f6ffnen goto.analysis.title=Analyse goto.data.collection.help=Erstellen und bearbeiten Sie einzelne Datenerhebungen. -goto.data.collection.link=Datenerhebungen \u00F6ffnen +goto.data.collection.link=Datenerhebungen \u00f6ffnen goto.data.collection.title=Datenerhebungen goto.executor.participation.help=Beantworten Sie Ihre offenen Umfragen. -goto.executor.participation.link=Meine Umfragen \u00F6ffnen +goto.executor.participation.link=Meine Umfragen \u00f6ffnen goto.executor.participation.title=Meine Umfragen goto.generator.help=Erstellen und bearbeiten Sie Generatoren zur automatischen Erzeugung von Datenerhebungen. -goto.generator.link=Datenerhebungsgeneratoren \u00F6ffnen +goto.generator.link=Datenerhebungsgeneratoren \u00f6ffnen goto.generator.title=Datenerhebungsgeneratoren goto.suggestion.help=Erstellen Sie einen Verbesserungsvorschlag und senden Sie ihn an uns. goto.suggestion.link=Verbesserungsvorschlag erstellen @@ -134,71 +139,71 @@ participation.email=Email participation.empty.table=Es sind keine Teilnehmer vorhanden. participation.firstname=Vorname participation.lastname=Nachname -participation.none.selected=Es sind keine Teilnehmer ausgew\u00E4lt. +participation.none.selected=Es sind keine Teilnehmer ausgew\u00e4lt. participation.remove=Entfernen -participation.remove.confirm=Wollen Sie die {0} ausgew\u00E4lten Teilnehmer wirklich entfernen? +participation.remove.confirm=Wollen Sie die {0} ausgew\u00e4lten Teilnehmer wirklich entfernen? participation.remove.confirm.button=Entfernen participation.repository.entry=Kurs participation.role=Rolle participation.role.coach=Betreuer participation.role.owner=Besitzer participation.role.participant=Teilnehmer -participation.user.add=Hinzuf\u00FCgen -participation.user.add.choose.title=Benutzer ausw\u00E4hlen -participation.user.add.confirm.title=Best\u00E4tigen -participation.user.add.course=Hinzuf\u00FCgen von Kurs -participation.user.add.curele=Hinzuf\u00FCgen von Curriculumelement -participation.user.add.title=Teilnehmer hinzuf\u00FCgen -participation.user.confirm.add.confirm.title=Best\u00E4tigen -participation.user.course.add.choose=Ausw\u00E4hlen -participation.user.course.add.choose.course.title=Kurs ausw\u00E4hlen -participation.user.course.add.choose.roles.title=Rollen ausw\u00E4hlen -participation.user.course.add.confirm.title=Best\u00E4tigen +participation.user.add=Hinzuf\u00fcgen +participation.user.add.choose.title=Benutzer ausw\u00e4hlen +participation.user.add.confirm.title=Best\u00e4tigen +participation.user.add.course=Hinzuf\u00fcgen von Kurs +participation.user.add.curele=Hinzuf\u00fcgen von Curriculumelement +participation.user.add.title=Teilnehmer hinzuf\u00fcgen +participation.user.confirm.add.confirm.title=Best\u00e4tigen +participation.user.course.add.choose=Ausw\u00e4hlen +participation.user.course.add.choose.course.title=Kurs ausw\u00e4hlen +participation.user.course.add.choose.roles.title=Rollen ausw\u00e4hlen +participation.user.course.add.confirm.title=Best\u00e4tigen participation.user.course.add.role.coach=$\:participation.role.coach participation.user.course.add.role.owner=$\:participation.role.owner participation.user.course.add.role.participant=$\:participation.role.participant participation.user.course.add.roles=Rollen -participation.user.course.add.title=Teinehmer hinzuf\u00FCgen -participation.user.curele.add.choose.curele.title=Curriculumelement ausw\u00E4hlen +participation.user.course.add.title=Teinehmer hinzuf\u00fcgen +participation.user.curele.add.choose.curele.title=Curriculumelement ausw\u00e4hlen participation.user.curele.add.choose.curriculum=Curriculum participation.user.curele.add.choose.curriculum.element=Curriculumelement -participation.user.curele.add.choose.roles.title=Rollen ausw\u00E4hlen +participation.user.curele.add.choose.roles.title=Rollen ausw\u00e4hlen participation.user.curele.add.curele.curriculum=Curriculum participation.user.curele.add.curele.curriculum.element=Curriculumelement participation.user.curele.add.role.coach=$\:participation.role.coach participation.user.curele.add.role.owner=$\:participation.role.owner participation.user.curele.add.role.participant=$\:participation.role.participant participation.user.curele.add.roles=Rollen -participation.user.curele.add.title=Teinehmer hinzuf\u00FCgen -relation.right.selectableQualityReportAccess=Zugriff Qualit\u00E4tsmanagementreport -reminder.announcement.coach.context.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Gerne informieren wir Sie, dass am $start Ihre Beurteilung Ihrer Klasse ansteht. Wir bitten Sie, sich f\u00FCr diese Befragung Zeit einzuplanen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Besten Dank f\u00FCr Ihre Mitarbeit und einen sch\u00F6nen Tag.<br/><br/>Freundliche Gr\u00FCsse<br/>Ihr QM Officer -reminder.announcement.coach.context.date=Versanddatum Ank\u00FCndigung -reminder.announcement.coach.context.subject=Ank\u00FCndigung Datenerhebung: $title -reminder.announcement.coach.topic.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Gerne informieren wir Sie, dass am $start die Beurteilung Ihrer Klasse \u00FCber Ihren Unterricht ansteht. Wir bitten Sie, sich f\u00FCr diese Befragung Zeit einzuplanen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Besten Dank f\u00FCr Ihre Mitarbeit und einen sch\u00F6nen Tag.<br/><br/>Freundliche Gr\u00FCsse<br/>Ihr QM Officer -reminder.announcement.coach.topic.date=Versanddatum Ank\u00FCndigung -reminder.announcement.coach.topic.subject=Ank\u00FCndigung Datenerhebung: $title -reminder.invitation.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Hiermit laden wir Sie ein, an der Befragung "$title" teilzunehmen.<br/><br/><div class\="o_email_button_group"><a class\="o_email_button" href\="$url">Umfrage \u00F6ffnen</a></div><br/><br/>Mit Ihren Antworten helfen Sie uns, dass wir unser Angebot als Bildungseinrichtung stetig verbessern k\u00F6nnen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Die Umfrage endet am <strong>$deadline</strong>. Nach diesem Zeitpunkt kann nicht mehr an der Befragung teilgenommen werden.<br/><br/>Besten Dank\!<br/><br/>Freundliche Gr\u00FCsse<br/>Ihr QM Officer +participation.user.curele.add.title=Teinehmer hinzuf\u00fcgen +relation.right.selectableQualityReportAccess=Zugriff Qualit\u00e4tsmanagementreport +reminder.announcement.coach.context.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Gerne informieren wir Sie, dass am $start Ihre Beurteilung Ihrer Klasse ansteht. Wir bitten Sie, sich f\u00fcr diese Befragung Zeit einzuplanen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Besten Dank f\u00fcr Ihre Mitarbeit und einen sch\u00f6nen Tag.<br/><br/>Freundliche Gr\u00fcsse<br/>Ihr QM Officer +reminder.announcement.coach.context.date=Versanddatum Ank\u00fcndigung +reminder.announcement.coach.context.subject=Ank\u00fcndigung Datenerhebung: $title +reminder.announcement.coach.topic.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Gerne informieren wir Sie, dass am $start die Beurteilung Ihrer Klasse \u00fcber Ihren Unterricht ansteht. Wir bitten Sie, sich f\u00fcr diese Befragung Zeit einzuplanen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Besten Dank f\u00fcr Ihre Mitarbeit und einen sch\u00f6nen Tag.<br/><br/>Freundliche Gr\u00fcsse<br/>Ihr QM Officer +reminder.announcement.coach.topic.date=Versanddatum Ank\u00fcndigung +reminder.announcement.coach.topic.subject=Ank\u00fcndigung Datenerhebung: $title +reminder.invitation.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Hiermit laden wir Sie ein, an der Befragung "$title" teilzunehmen.<br/><br/><div class\="o_email_button_group"><a class\="o_email_button" href\="$url">Umfrage \u00f6ffnen</a></div><br/><br/>Mit Ihren Antworten helfen Sie uns, dass wir unser Angebot als Bildungseinrichtung stetig verbessern k\u00f6nnen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Die Umfrage endet am <strong>$deadline</strong>. Nach diesem Zeitpunkt kann nicht mehr an der Befragung teilgenommen werden.<br/><br/>Besten Dank\!<br/><br/>Freundliche Gr\u00fcsse<br/>Ihr QM Officer reminder.invitation.date=Versanddatum Einladung reminder.invitation.subject=$title\: $topictype $topic -reminder.reminder1.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Hiermit laden wir Sie ein, an der Befragung "$title" teilzunehmen.<br/><br/><div class\="o_email_button_group"><a class\="o_email_button" href\="$url">Umfrage \u00F6ffnen</a></div><br/><br/>Wir haben Sie am <b>$invitation</b> h\u00F6flich eingeladen, an der an Sie versandten Befragung teilzunehmen. Leider sind Ihre Antworten bis dato nicht bei uns eingegangen. Bitte nehmen Sie sich die Zeit und f\u00FCllen den Fragebogen aus. Sie helfen uns damit, dass wir unser Angebot als Bildungseinrichtung stetig verbessern k\u00F6nnen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Die Umfrage endet am <strong>$deadline</strong>. Nach diesem Zeitpunkt kann nicht mehr an der Befragung teilgenommen werden.<br/><br/>Besten Dank\!<br/><br/>Freundliche Gr\u00FCsse<br/>Ihr QM Officer +reminder.reminder1.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Hiermit laden wir Sie ein, an der Befragung "$title" teilzunehmen.<br/><br/><div class\="o_email_button_group"><a class\="o_email_button" href\="$url">Umfrage \u00f6ffnen</a></div><br/><br/>Wir haben Sie am <b>$invitation</b> h\u00f6flich eingeladen, an der an Sie versandten Befragung teilzunehmen. Leider sind Ihre Antworten bis dato nicht bei uns eingegangen. Bitte nehmen Sie sich die Zeit und f\u00fcllen den Fragebogen aus. Sie helfen uns damit, dass wir unser Angebot als Bildungseinrichtung stetig verbessern k\u00f6nnen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Die Umfrage endet am <strong>$deadline</strong>. Nach diesem Zeitpunkt kann nicht mehr an der Befragung teilgenommen werden.<br/><br/>Besten Dank\!<br/><br/>Freundliche Gr\u00fcsse<br/>Ihr QM Officer reminder.reminder1.date=Versanddatum Erinnerung 1 reminder.reminder1.subject=$title\: $topictype $topic -reminder.reminder2.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Hiermit laden wir Sie ein, an der Befragung "$title" teilzunehmen.<br/><br/><div class\="o_email_button_group"><a class\="o_email_button" href\="$url">Umfrage \u00F6ffnen</a></div><br/><br/>Wir haben Sie am <b>$invitation</b> h\u00F6flich eingeladen, an der an Sie versandten Befragung teilzunehmen. Leider sind Ihre Antworten bis dato nicht bei uns eingegangen. Bitte nehmen Sie sich umgehend Zeit und f\u00FCllen den Fragebogen aus. Sie helfen uns mit Ihrer R\u00FCckmeldung, dass wir unser Angebot als Bildungseinrichtung stetig verbessern k\u00F6nnen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Die Umfrage endet am <strong>$deadline</strong>. Nach diesem Zeitpunkt kann nicht mehr an der Befragung teilgenommen werden.<br/><br/>Besten Dank\!<br/><br/>Freundliche Gr\u00FCsse<br/>Ihr QM Officer +reminder.reminder2.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Hiermit laden wir Sie ein, an der Befragung "$title" teilzunehmen.<br/><br/><div class\="o_email_button_group"><a class\="o_email_button" href\="$url">Umfrage \u00f6ffnen</a></div><br/><br/>Wir haben Sie am <b>$invitation</b> h\u00f6flich eingeladen, an der an Sie versandten Befragung teilzunehmen. Leider sind Ihre Antworten bis dato nicht bei uns eingegangen. Bitte nehmen Sie sich umgehend Zeit und f\u00fcllen den Fragebogen aus. Sie helfen uns mit Ihrer R\u00fcckmeldung, dass wir unser Angebot als Bildungseinrichtung stetig verbessern k\u00f6nnen.<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong>$context<br/><br/>Die Umfrage endet am <strong>$deadline</strong>. Nach diesem Zeitpunkt kann nicht mehr an der Befragung teilgenommen werden.<br/><br/>Besten Dank\!<br/><br/>Freundliche Gr\u00fcsse<br/>Ihr QM Officer reminder.reminder2.date=Versanddatum Erinnerung 2 reminder.reminder2.subject=$title\: $topictype $topic reminder.serie.followup=Nachbefragung reminder.serie.primary=Erstbefragung -report.access.email.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Die Umfrage "$title" wurde soeben abgeschlossen. Die detaillierten Umfrageresultate liegen in OpenOlat f\u00FCr Sie bereit.<br/><br/><div class\="o_email_button_group"><a class\="o_email_button" href\="$url">Resultate \u00F6ffnen</a></div><br/>Es handelt sich um eine Umfrage mit den folgenden Kennwerten\:<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong><br/>$result$context<br/><br/>Freundliche Gr\u00FCsse<br/>Ihr QM Officer<br/> +report.access.email.body=<h1>$title</h1>Liebe/r $firstname $lastname<br/><br/>Die Umfrage "$title" wurde soeben abgeschlossen. Die detaillierten Umfrageresultate liegen in OpenOlat f\u00fcr Sie bereit.<br/><br/><div class\="o_email_button_group"><a class\="o_email_button" href\="$url">Resultate \u00f6ffnen</a></div><br/>Es handelt sich um eine Umfrage mit den folgenden Kennwerten\:<br/><br/><strong>Beurteilungsgegenstand\: $topictype $topic</strong><br/>$result$context<br/><br/>Freundliche Gr\u00fcsse<br/>Ihr QM Officer<br/> report.access.email.rubric.index={0} report.access.email.rubric.index.name={0} ({1}) report.access.email.rubric.rating=Rubric {0}\: {1} ({2}) report.access.email.subject=Datenerhebung "$title" beendet report.access.email.trigger=Email report.access.email.trigger.always=Immer -report.access.email.trigger.insufficient=Ungen\u00FCgend -report.access.email.trigger.insufficientNeutral=Ungen\u00FCgend oder neutral +report.access.email.trigger.insufficient=Ungen\u00fcgend +report.access.email.trigger.insufficientNeutral=Ungen\u00fcgend oder neutral report.access.email.trigger.never=Nie -report.access.empty.table=Es k\u00F6nnen keine Zugangsberechtigungen konfiguriert werden. +report.access.empty.table=Es k\u00f6nnen keine Zugangsberechtigungen konfiguriert werden. report.access.name=Rolle report.access.name.members=Einzelne Benutzer report.access.name.participants.all=Eingeladene Benutzer @@ -209,21 +214,22 @@ report.access.name.repo.owner=Kurs Besitzer report.access.name.topic.identity=Beurteilter Betreuer report.access.name.topic.identity.name=Beurteilter Betreuer ({0}) report.access.online=Online -report.access.rating.insufficient=ungen\u00FCgend +report.access.rating.insufficient=ungen\u00fcgend report.access.rating.neutral=neutral report.access.rating.not.rated=nicht bewertet -report.access.rating.sufficient=gen\u00FCgend -report.member.add=Hinzuf\u00FCgen -report.member.add.title=Einzelne Benutzer hinzuf\u00FCgen -report.member.empty.table=Diese Tabelle enth\u00E4hlt keine Daten. +report.access.rating.sufficient=gen\u00fcgend +report.member.add=Hinzuf\u00fcgen +report.member.add.title=Einzelne Benutzer hinzuf\u00fcgen +report.member.empty.table=Diese Tabelle enth\u00e4hlt keine Daten. report.member.remove=Entfernen report.member.remove.confirm.text=Wollen Sie diese Benutzer wirklich entfernen? report.member.remove.confirm.title=Benutzer entfernen report.member.title=Einzelne Benutzer report.member.username=Benutzername -report.member.warning.atleastone=Sie m\u00FCssen mindestens einen Benutzer ausw\u00E4hlen. -site.title=Qualit\u00E4tsmanagement -site.title.alt=Qualit\u00E4tsmanagement -suggestion.description=Gerne nehmen wir Ihr Feedback zur kontinuierlichen Verbesserung entgegen.<br>Einfach dieses Formular ausf\u00FCllen und abschicken - wir k\u00FCmmern uns gerne um Ihr Anliegen. +report.member.warning.atleastone=Sie m\u00fcssen mindestens einen Benutzer ausw\u00e4hlen. +search.show.all=Alle anzeigen +site.title=Qualit\u00e4tsmanagement +site.title.alt=Qualit\u00e4tsmanagement +suggestion.description=Gerne nehmen wir Ihr Feedback zur kontinuierlichen Verbesserung entgegen.<br>Einfach dieses Formular ausf\u00fcllen und abschicken - wir k\u00fcmmern uns gerne um Ihr Anliegen. suggestion.title=Verbesserungsvorschlag -suggstion.recipients=Qualit\u00E4tsverantwortliche +suggstion.recipients=Qualit\u00e4tsverantwortliche diff --git a/src/main/java/org/olat/modules/quality/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/quality/ui/_i18n/LocalStrings_en.properties index 0579528bdfbc0bc3df1c1ea81743ae7b7dfed85d..51f3a3ee7ddf3a6b932dd4ddfa2356f5dff64780 100644 --- a/src/main/java/org/olat/modules/quality/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/quality/ui/_i18n/LocalStrings_en.properties @@ -21,6 +21,8 @@ data.collection.configuration=Configuration data.collection.create=Create data collection data.collection.creation.date=Created data.collection.deadline=To +data.collection.deadline.after="To" after +data.collection.deadline.before="To" before data.collection.delete=Delete data.collection.delete.button=Delete data.collection.delete.confirm=Do you really want to delete the data collection "{0}"? @@ -41,6 +43,7 @@ data.collection.form.preview.title=Preview data.collection.form.replace=Replace data.collection.form.select=Select questionnaire data.collection.generator.title=Generator +data.collection.id=ID data.collection.number.of.participants=Participants data.collection.organisations=Organisations data.collection.participations=Participants @@ -50,6 +53,8 @@ data.collection.report.access=Report access data.collection.report.followup=Follow-up data.collection.report.previous=Previous data.collection.start=From +data.collection.start.after="From" after +data.collection.start.before="From" before data.collection.start.confirm=Do you really want to start the data collection now? The "from" date will be changed to today. Afterwards you can not change the configuration anymore. data.collection.start.confirm.button=Start data.collection.start.confirm.title=Start data collection now @@ -222,6 +227,7 @@ report.member.remove.confirm.title=Remove user report.member.title=Individual users report.member.username=Username report.member.warning.atleastone=You need to choose at least one user. +search.show.all=Show all site.title=Quality management site.title.alt=Quality management suggestion.description=We are happy to receive your feedback.<br/>Simply fill out this form and send it off - we will be happy to take care of your suggestion. diff --git a/src/test/java/org/olat/modules/quality/manager/QualityDataCollectionDAOTest.java b/src/test/java/org/olat/modules/quality/manager/QualityDataCollectionDAOTest.java index a3933d1eb5ab3b06e2f8298a80ee918855bc8543..008e6ea9e58895af41caaec5174b0f7914c73225 100644 --- a/src/test/java/org/olat/modules/quality/manager/QualityDataCollectionDAOTest.java +++ b/src/test/java/org/olat/modules/quality/manager/QualityDataCollectionDAOTest.java @@ -36,11 +36,13 @@ import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; +import java.util.UUID; import org.junit.Before; import org.junit.Test; import org.olat.basesecurity.GroupRoles; import org.olat.basesecurity.IdentityRelationshipService; +import org.olat.basesecurity.OrganisationService; import org.olat.basesecurity.RelationRight; import org.olat.basesecurity.RelationRole; import org.olat.core.commons.persistence.DB; @@ -49,7 +51,11 @@ import org.olat.core.id.Identity; import org.olat.core.id.Organisation; import org.olat.course.certificate.CertificateEmailRightProvider; import org.olat.modules.curriculum.Curriculum; +import org.olat.modules.curriculum.CurriculumCalendars; import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementStatus; +import org.olat.modules.curriculum.CurriculumLearningProgress; +import org.olat.modules.curriculum.CurriculumLectures; import org.olat.modules.curriculum.CurriculumRoles; import org.olat.modules.curriculum.CurriculumService; import org.olat.modules.forms.EvaluationFormManager; @@ -98,6 +104,8 @@ public class QualityDataCollectionDAOTest extends OlatTestCase { private CurriculumService curriculumService; @Autowired private IdentityRelationshipService identityRelationshipService; + @Autowired + private OrganisationService organisationService; @Autowired private QualityDataCollectionDAO sut; @@ -479,7 +487,47 @@ public class QualityDataCollectionDAOTest extends OlatTestCase { .containsExactlyInAnyOrder(dataCollection1, dataCollection2) .doesNotContain(dataCollectionOtherKey, dataCollectionNoKey); } - + + @Test + public void shouldLoadGenerators() { + String title = JunitTestHelper.random(); + QualityGenerator generator1 = qualityTestHelper.createGenerator(); + QualityGenerator generator2 = qualityTestHelper.createGenerator(); + QualityDataCollection dataCollection11 = sut.createDataCollection(generator1, 123l); + dataCollection11.setTitle(title); + dataCollection11 = sut.updateDataCollection(dataCollection11); + QualityDataCollection dataCollection12 = sut.createDataCollection(generator1, 124l); + dataCollection12.setTitle(title); + dataCollection12 = sut.updateDataCollection(dataCollection12); + QualityDataCollection dataCollection21 = sut.createDataCollection(generator2, 123l); + dataCollection21.setTitle(title); + dataCollection21 = sut.updateDataCollection(dataCollection21); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setTitle(title); + List<QualityGenerator> generators = sut.loadGenerators(searchParams); + + assertThat(generators).containsExactlyInAnyOrder(generator1, generator2); + } + + @Test + public void shouldLoadFormEntries() { + RepositoryEntry formEntry1 = JunitTestHelper.createAndPersistRepositoryEntry(); + RepositoryEntry formEntry2 = JunitTestHelper.createAndPersistRepositoryEntry(); + Organisation organisation = qualityTestHelper.createOrganisation(); + qualityTestHelper.createDataCollection(organisation, formEntry1); + qualityTestHelper.createDataCollection(organisation, formEntry1); + qualityTestHelper.createDataCollection(organisation, formEntry2); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + List<RepositoryEntry> formEntries = sut.loadFormEntries(searchParams); + + assertThat(formEntries).containsExactlyInAnyOrder(formEntry1, formEntry2); + } + @Test public void shouldGetDataCollectionCount() { int numberOfDataCollections = 3; @@ -970,6 +1018,370 @@ public class QualityDataCollectionDAOTest extends OlatTestCase { ); } + @Test + public void shouldFilterDataCollectionsByFormEntries() { + RepositoryEntry formEntry1 = JunitTestHelper.createAndPersistRepositoryEntry(); + RepositoryEntry formEntry2 = JunitTestHelper.createAndPersistRepositoryEntry(); + RepositoryEntry formEntryOther = JunitTestHelper.createAndPersistRepositoryEntry(); + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollection1 = qualityTestHelper.createDataCollection(organisation, formEntry1); + QualityDataCollection dataCollection2 = qualityTestHelper.createDataCollection(organisation, formEntry1); + QualityDataCollection dataCollection3 = qualityTestHelper.createDataCollection(organisation, formEntry2); + QualityDataCollection dataCollectionOther = qualityTestHelper.createDataCollection(organisation, formEntryOther); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setFormEntryRefs(Arrays.asList(formEntry1, formEntry2)); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection1.getKey(), + dataCollection2.getKey(), + dataCollection3.getKey()) + .doesNotContain( + dataCollectionOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsBySearchString() { + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollectionTitle = qualityTestHelper.createDataCollection(organisation); + dataCollectionTitle.setTitle("Are lions evil?"); + dataCollectionTitle = sut.updateDataCollection(dataCollectionTitle); + QualityDataCollection dataCollectionCustom = qualityTestHelper.createDataCollection(organisation); + dataCollectionCustom.setTopicCustom("liOn"); + dataCollectionCustom = sut.updateDataCollection(dataCollectionCustom); + QualityDataCollection dataCollectionCustomOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionCustomOther.setTopicCustom("cat"); + dataCollectionCustomOther = sut.updateDataCollection(dataCollectionCustomOther); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setSearchString("lion"); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollectionTitle.getKey(), + dataCollectionCustom.getKey()) + .doesNotContain( + dataCollectionCustomOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByTitle() { + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollection1 = qualityTestHelper.createDataCollection(organisation); + dataCollection1.setTitle("lion"); + dataCollection1 = sut.updateDataCollection(dataCollection1); + QualityDataCollection dataCollection2 = qualityTestHelper.createDataCollection(organisation); + dataCollection2.setTitle("Lion King"); + dataCollection2 = sut.updateDataCollection(dataCollection2); + QualityDataCollection dataCollection3 = qualityTestHelper.createDataCollection(organisation); + dataCollection3.setTitle("My lion is the king"); + dataCollection3 = sut.updateDataCollection(dataCollection3); + QualityDataCollection dataCollectionOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionOther.setTitle("tiger"); + dataCollectionOther = sut.updateDataCollection(dataCollectionOther); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setTitle("lion"); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection1.getKey(), + dataCollection2.getKey(), + dataCollection3.getKey()) + .doesNotContain( + dataCollectionOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByStartAfter() { + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollection1 = qualityTestHelper.createDataCollection(organisation); + dataCollection1.setStart(qualityTestHelper.getDateInFuture()); + qualityService.updateDataCollection(dataCollection1); + QualityDataCollection dataCollection2 = qualityTestHelper.createDataCollection(organisation); + dataCollection2.setStart(qualityTestHelper.getDateInFuture()); + qualityService.updateDataCollection(dataCollection2); + QualityDataCollection dataCollectionOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionOther.setStart(qualityTestHelper.getDateInPast()); + qualityService.updateDataCollection(dataCollectionOther); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setStartAfter(new Date()); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection1.getKey(), + dataCollection2.getKey()) + .doesNotContain( + dataCollectionOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByStartBefore() { + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollection1 = qualityTestHelper.createDataCollection(organisation); + dataCollection1.setStart(qualityTestHelper.getDateInPast()); + qualityService.updateDataCollection(dataCollection1); + QualityDataCollection dataCollection2 = qualityTestHelper.createDataCollection(organisation); + dataCollection2.setStart(qualityTestHelper.getDateInPast()); + qualityService.updateDataCollection(dataCollection2); + QualityDataCollection dataCollectionOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionOther.setStart(qualityTestHelper.getDateInFuture()); + qualityService.updateDataCollection(dataCollectionOther); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setStartBefore(new Date()); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection1.getKey(), + dataCollection2.getKey()) + .doesNotContain( + dataCollectionOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByDeadlineAfter() { + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollection1 = qualityTestHelper.createDataCollection(organisation); + dataCollection1.setDeadline(qualityTestHelper.getDateInFuture()); + qualityService.updateDataCollection(dataCollection1); + QualityDataCollection dataCollection2 = qualityTestHelper.createDataCollection(organisation); + dataCollection2.setDeadline(qualityTestHelper.getDateInFuture()); + qualityService.updateDataCollection(dataCollection2); + QualityDataCollection dataCollectionOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionOther.setDeadline(qualityTestHelper.getDateInPast()); + qualityService.updateDataCollection(dataCollectionOther); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setDeadlineAfter(new Date()); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection1.getKey(), + dataCollection2.getKey()) + .doesNotContain( + dataCollectionOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByDeadlineBefore() { + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollection1 = qualityTestHelper.createDataCollection(organisation); + dataCollection1.setDeadline(qualityTestHelper.getDateInPast()); + qualityService.updateDataCollection(dataCollection1); + QualityDataCollection dataCollection2 = qualityTestHelper.createDataCollection(organisation); + dataCollection2.setDeadline(qualityTestHelper.getDateInPast()); + qualityService.updateDataCollection(dataCollection2); + QualityDataCollection dataCollectionOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionOther.setDeadline(qualityTestHelper.getDateInFuture()); + qualityService.updateDataCollection(dataCollectionOther); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setDeadlineBefore(new Date()); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection1.getKey(), + dataCollection2.getKey()) + .doesNotContain( + dataCollectionOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByTopicType() { + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollection1 = qualityTestHelper.createDataCollection(organisation); + dataCollection1.setTopicType(QualityDataCollectionTopicType.CUSTOM); + dataCollection1 = sut.updateDataCollection(dataCollection1); + QualityDataCollection dataCollection2 = qualityTestHelper.createDataCollection(organisation); + dataCollection2.setTopicType(QualityDataCollectionTopicType.CUSTOM); + dataCollection2 = sut.updateDataCollection(dataCollection2); + QualityDataCollection dataCollection3 = qualityTestHelper.createDataCollection(organisation); + dataCollection3.setTopicType(QualityDataCollectionTopicType.CURRICULUM); + dataCollection3 = sut.updateDataCollection(dataCollection3); + QualityDataCollection dataCollectionOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionOther.setTopicType(QualityDataCollectionTopicType.IDENTIY); + dataCollectionOther = sut.updateDataCollection(dataCollectionOther); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setTopicTypes(Arrays.asList(QualityDataCollectionTopicType.CUSTOM, QualityDataCollectionTopicType.CURRICULUM)); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection1.getKey(), + dataCollection2.getKey(), + dataCollection3.getKey()) + .doesNotContain( + dataCollectionOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByTopic() { + Organisation organisation = qualityTestHelper.createOrganisation(); + + // Custom + QualityDataCollection dataCollectionCustom = qualityTestHelper.createDataCollection(organisation); + dataCollectionCustom.setTopicCustom("liOn"); + dataCollectionCustom = sut.updateDataCollection(dataCollectionCustom); + + QualityDataCollection dataCollectionCustomOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionCustomOther.setTopicCustom("cat"); + dataCollectionCustomOther = sut.updateDataCollection(dataCollectionCustomOther); + + // Identity + Identity identity = JunitTestHelper.createAndPersistIdentityAsUser("LION"); + QualityDataCollection dataCollectionIdentity = qualityTestHelper.createDataCollection(organisation); + dataCollectionIdentity.setTopicIdentity(identity); + dataCollectionIdentity = sut.updateDataCollection(dataCollectionIdentity); + + // Organisation + Organisation topicOrganisation = organisationService.createOrganisation("The lions cage", UUID.randomUUID().toString(), null, null, null); + QualityDataCollection dataCollectionOrganisation = qualityTestHelper.createDataCollection(organisation); + dataCollectionOrganisation.setTopicOrganisation(topicOrganisation); + dataCollectionOrganisation = sut.updateDataCollection(dataCollectionOrganisation); + + // Curriculum + Curriculum curriculum = curriculumService.createCurriculum("i", "Lions training", "d", organisation);; + QualityDataCollection dataCollectionCurriculum = qualityTestHelper.createDataCollection(organisation); + dataCollectionCurriculum.setTopicCurriculum(curriculum); + dataCollectionCurriculum = sut.updateDataCollection(dataCollectionCurriculum); + + // CurriculumElement + Curriculum curriculumCE = curriculumService.createCurriculum("i", "d", "d", organisation);; + CurriculumElement curriculumElement = curriculumService.createCurriculumElement("ident", "LIONS Physiognomy", CurriculumElementStatus.active, null, null, null, + null, CurriculumCalendars.disabled, CurriculumLectures.disabled, CurriculumLearningProgress.disabled, + curriculumCE); + QualityDataCollection dataCollectionCurElement = qualityTestHelper.createDataCollection(organisation); + dataCollectionCurElement.setTopicCurriculumElement(curriculumElement); + dataCollectionCurElement = sut.updateDataCollection(dataCollectionCurElement); + + // RepositoryEntry + RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry(); + entry.setDisplayname("Course with Lions"); + entry = repositoryService.update(entry); + QualityDataCollection dataCollectionRepoEntry = qualityTestHelper.createDataCollection(organisation); + dataCollectionRepoEntry.setTopicRepositoryEntry(entry); + dataCollectionRepoEntry = sut.updateDataCollection(dataCollectionRepoEntry); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setTopic("lion"); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollectionCustom.getKey(), + dataCollectionIdentity.getKey(), + dataCollectionOrganisation.getKey(), + dataCollectionCurriculum.getKey(), + dataCollectionCurElement.getKey(), + dataCollectionRepoEntry.getKey()) + .doesNotContain( + dataCollectionCustomOther.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByGeneratorRefs() { + Collection<Organisation> organisations = Collections.singletonList(qualityTestHelper.createOrganisation()); + RepositoryEntry formEntry = JunitTestHelper.createAndPersistRepositoryEntry(); + String title = JunitTestHelper.random(); + QualityGenerator generator1 = qualityTestHelper.createGenerator(); + QualityGenerator generator2 = qualityTestHelper.createGenerator(); + QualityGenerator generatorOther = qualityTestHelper.createGenerator(); + QualityDataCollection dataCollection11 = qualityService.createDataCollection(organisations, formEntry, generator1, 123l); + dataCollection11.setTitle(title); + dataCollection11 = sut.updateDataCollection(dataCollection11); + QualityDataCollection dataCollection12 = qualityService.createDataCollection(organisations, formEntry, generator1, 124l); + dataCollection12.setTitle(title); + dataCollection12 = sut.updateDataCollection(dataCollection12); + QualityDataCollection dataCollection21 = qualityService.createDataCollection(organisations, formEntry, generator2, 123l); + dataCollection21.setTitle(title); + dataCollection21 = sut.updateDataCollection(dataCollection21); + QualityDataCollection dataCollectionOther = qualityService.createDataCollection(organisations, formEntry, generatorOther, 123l); + dataCollectionOther.setTitle(title); + dataCollectionOther = sut.updateDataCollection(dataCollectionOther); + QualityDataCollection dataCollectionNoGenerator = sut.createDataCollection(); + dataCollectionNoGenerator.setTitle(title); + dataCollectionNoGenerator = sut.updateDataCollection(dataCollectionNoGenerator); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setTitle(title); + searchParams.setGeneratorRefs(Arrays.asList(generator1, generator2)); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection11.getKey(), + dataCollection12.getKey(), + dataCollection21.getKey()) + .doesNotContain( + dataCollectionOther.getKey(), + dataCollectionNoGenerator.getKey()); + } + + @Test + public void shouldFilterDataCollectionsByStatus() { + Organisation organisation = qualityTestHelper.createOrganisation(); + QualityDataCollection dataCollection1 = qualityTestHelper.createDataCollection(organisation); + dataCollection1 = sut.updateDataCollectionStatus(dataCollection1, READY); + QualityDataCollection dataCollection2 = qualityTestHelper.createDataCollection(organisation); + dataCollection2 = sut.updateDataCollectionStatus(dataCollection2, READY); + QualityDataCollection dataCollection3 = qualityTestHelper.createDataCollection(organisation); + dataCollection3 = sut.updateDataCollectionStatus(dataCollection3, FINISHED); + QualityDataCollection dataCollectionOther = qualityTestHelper.createDataCollection(organisation); + dataCollectionOther = sut.updateDataCollectionStatus(dataCollectionOther, PREPARATION); + dbInstance.commitAndCloseSession(); + + QualityDataCollectionViewSearchParams searchParams = new QualityDataCollectionViewSearchParams(); + searchParams.setOrgansationRefs(Collections.singletonList(organisation)); + searchParams.setStatus(Arrays.asList(READY, FINISHED)); + List<QualityDataCollectionView> dataCollections = sut.loadDataCollections(TRANSLATOR, searchParams, 0, -1); + + assertThat(dataCollections) + .extracting(QualityDataCollectionView::getKey) + .containsExactlyInAnyOrder( + dataCollection1.getKey(), + dataCollection2.getKey(), + dataCollection3.getKey()) + .doesNotContain( + dataCollectionOther.getKey()); + } + @Test public void shouldFilterDataCollectionsByReportMembers() { Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("p1"); diff --git a/src/test/java/org/olat/modules/quality/manager/QualityTestHelper.java b/src/test/java/org/olat/modules/quality/manager/QualityTestHelper.java index 3df1caf16cd0d89ff010bd752dcc926ed9f616d9..92a7334920149cd9d9bb2297344eba681fd53086 100644 --- a/src/test/java/org/olat/modules/quality/manager/QualityTestHelper.java +++ b/src/test/java/org/olat/modules/quality/manager/QualityTestHelper.java @@ -177,13 +177,13 @@ public class QualityTestHelper { return dataCollection; } - private Date getDateInPast() { + public Date getDateInPast() { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.YEAR, -1); return calendar.getTime(); } - private Date getDateInFuture() { + public Date getDateInFuture() { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.YEAR, 1); return calendar.getTime();