Skip to content
Snippets Groups Projects
Commit 79274216 authored by uhensler's avatar uhensler
Browse files

OO-3304: First filters in the quality analysis tool

parent f6c03c44
No related branches found
No related tags found
No related merge requests found
Showing
with 1131 additions and 11 deletions
......@@ -196,7 +196,7 @@ public interface CurriculumService {
public CurriculumElement getCurriculumElement(CurriculumElementRef element);
public List<CurriculumElement> getCurriculumElements(Collection<CurriculumElementRef> elementRefs);
public void deleteCurriculumElement(CurriculumElementRef element);
......@@ -210,6 +210,8 @@ public interface CurriculumService {
*/
public List<CurriculumElement> getCurriculumElements(CurriculumRef curriculum, CurriculumElementStatus[] status);
public List<CurriculumElement> getCurriculumElementsByCurriculums(Collection<? extends CurriculumRef> curriculumRefs);
/**
* Return all the elements of a curriculum, flat, with additional informations
* like the number of resources linked to the elements. List element in state
......
......@@ -19,6 +19,8 @@
*/
package org.olat.modules.curriculum.manager;
import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
......@@ -251,6 +253,21 @@ public class CurriculumElementDAO {
.setParameter("entryKey", entry.getKey())
.getResultList();
}
public List<CurriculumElement> loadElementsByCurriculums(Collection<? extends CurriculumRef> curriculumRefs) {
QueryBuilder sb = new QueryBuilder();
sb.append("select el");
sb.append(" from curriculumelement el");
sb.append(" inner join fetch el.curriculum curriculum");
sb.append(" left join el.parent parentEl");
sb.and().append("el.curriculum.key in :curriculumKeys");
List<Long> curriculumKeys = curriculumRefs.stream().map(CurriculumRef::getKey).collect(toList());
return dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), CurriculumElement.class)
.setParameter("curriculumKeys", curriculumKeys)
.getResultList();
}
public List<CurriculumElement> searchElements(String externalId, String identifier, Long key) {
StringBuilder sb = new StringBuilder(256);
......@@ -474,4 +491,5 @@ public class CurriculumElementDAO {
return len1 - len2;
}
}
}
......@@ -326,6 +326,11 @@ public class CurriculumServiceImpl implements CurriculumService {
return curriculumElementDao.getChildren(parentElement);
}
@Override
public List<CurriculumElement> getCurriculumElementsByCurriculums(Collection<? extends CurriculumRef> curriculumRefs) {
return curriculumElementDao.loadElementsByCurriculums(curriculumRefs);
}
@Override
public List<CurriculumElement> searchCurriculumElements(String externalId, String identifier, Long key) {
return curriculumElementDao.searchElements(externalId, identifier, key);
......
......@@ -19,7 +19,6 @@
*/
package org.olat.modules.forms.model.jpa;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
......@@ -113,9 +112,9 @@ public class RubricStatisticImpl implements RubricStatistic {
}
private Long getValue(List<CalculatedLong> calculatedLongs, String identifier, int step) {
String subidentifier = BigDecimal.valueOf((double)step).toPlainString();
for (CalculatedLong calculatedLong: calculatedLongs) {
if (calculatedLong.getIdentifier().equals(identifier) && calculatedLong.getSubIdentifier().equals(subidentifier)) {
int calculatedStep = Double.valueOf(calculatedLong.getSubIdentifier()).intValue();
if (calculatedLong.getIdentifier().equals(identifier) && calculatedStep == step) {
return calculatedLong.getValue();
}
}
......
/**
* <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.analysis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.olat.core.id.OrganisationRef;
import org.olat.modules.curriculum.CurriculumElementRef;
import org.olat.modules.curriculum.CurriculumRef;
import org.olat.repository.RepositoryEntryRef;
/**
*
* Initial date: 04.09.2018<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class AnalysisSearchParameter {
private RepositoryEntryRef formEntryRef;
private Date dateRangeFrom;
private Date dateRangeTo;
private List<? extends OrganisationRef> organisationRefs;
private Collection<? extends CurriculumRef> curriculumRefs;
private List<? extends CurriculumElementRef> curriculumElementRefs;
public RepositoryEntryRef getFormEntryRef() {
return formEntryRef;
}
public void setFormEntryRef(RepositoryEntryRef formEntryRef) {
this.formEntryRef = formEntryRef;
}
public Date getDateRangeFrom() {
return dateRangeFrom;
}
public void setDateRangeFrom(Date dateRangeFrom) {
this.dateRangeFrom = dateRangeFrom;
}
public Date getDateRangeTo() {
return dateRangeTo;
}
public void setDateRangeTo(Date dateRangeTo) {
this.dateRangeTo = dateRangeTo;
}
public List<? extends OrganisationRef> getOrganisationRefs() {
return organisationRefs;
}
public void setOrganisationRefs(List<? extends OrganisationRef> organisationRefs) {
this.organisationRefs = organisationRefs;
}
public Collection<? extends CurriculumRef> getCurriculumRefs() {
return curriculumRefs;
}
public void setCurriculumRefs(Collection<? extends CurriculumRef> curriculumRefs) {
this.curriculumRefs = curriculumRefs;
}
public List<? extends CurriculumElementRef> getCurriculumElementRefs() {
return curriculumElementRefs;
}
public void setCurriculumElementRefs(List<? extends CurriculumElementRef> curriculumElementRefs) {
this.curriculumElementRefs = curriculumElementRefs;
}
@Override
public AnalysisSearchParameter clone() {
AnalysisSearchParameter clone = new AnalysisSearchParameter();
clone.formEntryRef = this.formEntryRef;
clone.dateRangeFrom = this.dateRangeFrom;
clone.organisationRefs = this.organisationRefs != null? new ArrayList<>(this.organisationRefs): null;
clone.curriculumRefs = this.curriculumRefs != null? new ArrayList<>(this.curriculumRefs): null;
clone.curriculumElementRefs = this.curriculumElementRefs != null? new ArrayList<>(this.curriculumElementRefs): null;
return clone;
}
}
......@@ -21,14 +21,18 @@ package org.olat.modules.quality.analysis;
import java.util.Date;
import org.olat.core.id.OLATResourceable;
/**
*
* Initial date: 03.09.2018<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public interface EvaluationFormView {
public interface EvaluationFormView extends OLATResourceable {
public String RESOURCEABLE_TYPE = "form";
public Long getFormEntryKey();
public Date getFormCreatedDate();
......
......@@ -21,6 +21,10 @@ package org.olat.modules.quality.analysis;
import java.util.List;
import org.olat.core.id.Organisation;
import org.olat.modules.curriculum.Curriculum;
import org.olat.modules.curriculum.CurriculumElement;
/**
*
* Initial date: 03.09.2018<br>
......@@ -30,5 +34,13 @@ import java.util.List;
public interface QualityAnalysisService {
public List<EvaluationFormView> loadEvaluationForms(EvaluationFormViewSearchParams searchParams);
public List<Organisation> loadFilterOrganisations(AnalysisSearchParameter searchParams);
public List<Curriculum> loadFilterCurriculums(AnalysisSearchParameter searchParams);
public List<CurriculumElement> loadFilterCurriculumElements(AnalysisSearchParameter searchParams);
public Long loadFilterDataCollectionCount(AnalysisSearchParameter searchParams);
}
/**
* <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.analysis.manager;
import static java.util.stream.Collectors.toList;
import java.util.List;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import org.olat.core.commons.persistence.DB;
import org.olat.core.commons.persistence.QueryBuilder;
import org.olat.core.id.Organisation;
import org.olat.modules.curriculum.Curriculum;
import org.olat.modules.curriculum.CurriculumRef;
import org.olat.modules.quality.QualityDataCollectionLight;
import org.olat.modules.quality.QualityDataCollectionStatus;
import org.olat.modules.quality.analysis.AnalysisSearchParameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*
* Initial date: 05.09.2018<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
@Service
public class AnalysisFilterDAO {
@Autowired
private DB dbInstance;
List<Organisation> loadOrganisations(AnalysisSearchParameter searchParams) {
QueryBuilder sb = new QueryBuilder();
sb.append("select distinct organisation");
appendFrom(sb);
appendWhere(sb, searchParams);
sb.and().append("organisation.key is not null");
TypedQuery<Organisation> query = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), Organisation.class);
appendParameters(query, searchParams);
return query.getResultList();
}
List<Curriculum> loadCurriculums(AnalysisSearchParameter searchParams) {
QueryBuilder sb = new QueryBuilder();
sb.append("select distinct curriculum");
appendFrom(sb);
appendWhere(sb, searchParams);
sb.and().append("curriculum.key is not null");
TypedQuery<Curriculum> query = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), Curriculum.class);
appendParameters(query, searchParams);
return query.getResultList();
}
List<String> loadCurriculumElementPathes(AnalysisSearchParameter searchParams) {
QueryBuilder sb = new QueryBuilder();
sb.append("select distinct curriculumElement.materializedPathKeys");
appendFrom(sb);
appendWhere(sb, searchParams);
sb.and().append("curriculumElement.key is not null");
TypedQuery<String> query = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), String.class);
appendParameters(query, searchParams);
return query.getResultList();
}
public Long loadFilterDataCollectionCount(AnalysisSearchParameter searchParams) {
QueryBuilder sb = new QueryBuilder();
sb.append("select count(distinct collection.key)");
appendFrom(sb);
appendWhere(sb, searchParams);
TypedQuery<Long> query = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), Long.class);
appendParameters(query, searchParams);
return query.getResultList().get(0);
}
private void appendFrom(QueryBuilder sb) {
sb.append(" from qualitydatacollection collection");
sb.append(" inner join evaluationformsurvey survey");
sb.append(" on survey.resName = '").append(QualityDataCollectionLight.RESOURCEABLE_TYPE_NAME).append("'");
sb.append(" and survey.resId = collection.key");
sb.append(" left join qualitycontext context");
sb.append(" on context.dataCollection.key = collection.key");
sb.append(" left join contexttocurriculum contextToCurriculum");
sb.append(" on contextToCurriculum.context.key = context.key");
sb.append(" left join curriculum curriculum");
sb.append(" on contextToCurriculum.curriculum.key = curriculum.key");
sb.append(" left join contexttocurriculumelement contextToCurriculumElement");
sb.append(" on contextToCurriculumElement.context.key = context.key");
sb.append(" left join curriculumelement curriculumElement");
sb.append(" on contextToCurriculumElement.curriculumElement.key = curriculumElement.key");
sb.append(" left join contexttoorganisation contextToOrganisation");
sb.append(" on contextToOrganisation.context.key = context.key");
sb.append(" left join organisation organisation");
sb.append(" on contextToOrganisation.organisation.key = organisation.key");
}
private void appendWhere(QueryBuilder sb, AnalysisSearchParameter searchParams) {
sb.and().append("collection.status = '").append(QualityDataCollectionStatus.FINISHED).append("'");
if (searchParams.getFormEntryRef() != null) {
sb.and().append("survey.formEntry.key = :formEntryKey");
}
if (searchParams.getDateRangeFrom() != null) {
sb.and().append("collection.deadline >= :dateRangeFrom");
}
if (searchParams.getDateRangeTo() != null) {
sb.and().append("collection.deadline <= :dateRangeTo");
}
if (searchParams.getOrganisationRefs() != null) {
sb.and();
for (int i = 0; i < searchParams.getOrganisationRefs().size(); i++) {
if (i == 0) {
sb.append("(");
} else {
sb.append(" or ");
}
sb.append("organisation.materializedPathKeys like :orgPath").append(i);
if (i == searchParams.getOrganisationRefs().size() - 1) {
sb.append(")");
}
}
}
if (searchParams.getCurriculumRefs() != null) {
sb.and().append("curriculum.key in :curriculumKeys");
}
if (searchParams.getCurriculumElementRefs() != null) {
sb.and();
for (int i = 0; i < searchParams.getCurriculumElementRefs().size(); i++) {
if (i == 0) {
sb.append("(");
} else {
sb.append(" or ");
}
sb.append("curriculumElement.materializedPathKeys like :elePath").append(i);
if (i == searchParams.getCurriculumElementRefs().size() - 1) {
sb.append(")");
}
}
}
}
private void appendParameters(Query query, AnalysisSearchParameter searchParams) {
if (searchParams.getFormEntryRef() != null) {
query.setParameter("formEntryKey", searchParams.getFormEntryRef().getKey());
}
if (searchParams.getDateRangeFrom() != null) {
query.setParameter("dateRangeFrom", searchParams.getDateRangeFrom());
}
if (searchParams.getDateRangeTo() != null) {
query.setParameter("dateRangeTo", searchParams.getDateRangeTo());
}
if (searchParams.getOrganisationRefs() != null) {
for (int i = 0; i < searchParams.getOrganisationRefs().size(); i++) {
String parameter = new StringBuilder(12).append("orgPath").append(i).toString();
Long key = searchParams.getOrganisationRefs().get(i).getKey();
String value = new StringBuilder(32).append("%/").append(key).append("/%").toString();
query.setParameter(parameter, value);
}
}
if (searchParams.getCurriculumRefs() != null) {
List<Long> curriculumKeys = searchParams.getCurriculumRefs().stream().map(CurriculumRef::getKey).collect(toList());
query.setParameter("curriculumKeys", curriculumKeys);
}
if (searchParams.getCurriculumElementRefs() != null) {
for (int i = 0; i < searchParams.getCurriculumElementRefs().size(); i++) {
String parameter = new StringBuilder(12).append("elePath").append(i).toString();
Long key = searchParams.getCurriculumElementRefs().get(i).getKey();
String value = new StringBuilder(32).append("%/").append(key).append("/%").toString();
query.setParameter(parameter, value);
}
}
}
}
......@@ -19,8 +19,14 @@
*/
package org.olat.modules.quality.analysis.manager;
import java.util.ArrayList;
import java.util.List;
import org.olat.core.id.Organisation;
import org.olat.modules.curriculum.Curriculum;
import org.olat.modules.curriculum.CurriculumElement;
import org.olat.modules.curriculum.CurriculumService;
import org.olat.modules.quality.analysis.AnalysisSearchParameter;
import org.olat.modules.quality.analysis.EvaluationFormView;
import org.olat.modules.quality.analysis.EvaluationFormViewSearchParams;
import org.olat.modules.quality.analysis.QualityAnalysisService;
......@@ -36,11 +42,52 @@ import org.springframework.stereotype.Service;
@Service
public class QualityAnalysisServiceImpl implements QualityAnalysisService {
@Autowired
private AnalysisFilterDAO filterDao;
@Autowired
private EvaluationFormDAO evaluationFromDao;
@Autowired
private CurriculumService curriculumService;
@Override
public List<EvaluationFormView> loadEvaluationForms(EvaluationFormViewSearchParams searchParams) {
return evaluationFromDao.load(searchParams);
}
@Override
public List<Organisation> loadFilterOrganisations(AnalysisSearchParameter searchParams) {
return filterDao.loadOrganisations(searchParams);
}
@Override
public List<Curriculum> loadFilterCurriculums(AnalysisSearchParameter searchParams) {
return filterDao.loadCurriculums(searchParams);
}
@Override
public List<CurriculumElement> loadFilterCurriculumElements(AnalysisSearchParameter searchParams) {
if (searchParams == null || searchParams.getCurriculumRefs() == null) {
return new ArrayList<>(0);
}
List<CurriculumElement> elementsOfCurriculums = curriculumService
.getCurriculumElementsByCurriculums(searchParams.getCurriculumRefs());
List<String> pathes = filterDao.loadCurriculumElementPathes(searchParams);
elementsOfCurriculums.removeIf(e -> isUnusedLeaf(e, pathes));
return elementsOfCurriculums;
}
private boolean isUnusedLeaf(CurriculumElement e, List<String> pathsOfContexts) {
for (String path : pathsOfContexts) {
if (path.contains(e.getMaterializedPathKeys())) {
return false;
}
}
return true;
}
@Override
public Long loadFilterDataCollectionCount(AnalysisSearchParameter searchParams) {
return filterDao.loadFilterDataCollectionCount(searchParams);
}
}
......@@ -50,6 +50,16 @@ public class EvaluationFormViewImpl implements EvaluationFormView {
this.numberParticipationsDone = numberParticipationsDone;
}
@Override
public String getResourceableTypeName() {
return EvaluationFormView.RESOURCEABLE_TYPE;
}
@Override
public Long getResourceableId() {
return formEntryKey;
}
@Override
public Long getFormEntryKey() {
return formEntryKey;
......
/**
* <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.analysis.ui;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.controller.BlankController;
import org.olat.modules.quality.QualitySecurityCallback;
import org.olat.modules.quality.analysis.AnalysisSearchParameter;
import org.olat.modules.quality.analysis.EvaluationFormView;
/**
*
* Initial date: 04.09.2018<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class AnalysisController extends BasicController {
enum Presentation {REPORT, HEAT_MAP};
private VelocityContainer mainVC;
private Controller filterCtrl;
private Controller presentationCtrl;
private final QualitySecurityCallback secCallback;
private final TooledStackedPanel stackPanel;
private final EvaluationFormView formView;
protected AnalysisController(UserRequest ureq, WindowControl wControl, QualitySecurityCallback secCallback,
TooledStackedPanel stackPanel, EvaluationFormView formView) {
super(ureq, wControl);
this.secCallback = secCallback;
this.stackPanel = stackPanel;
this.formView = formView;
mainVC = createVelocityContainer("analysis");
putInitialPanel(mainVC);
AnalysisSearchParameter searchParams = new AnalysisSearchParameter();
searchParams.setFormEntryRef(() -> formView.getFormEntryKey());
filterCtrl= new FilterController(ureq, wControl, searchParams);
listenTo(filterCtrl);
mainVC.put("filter", filterCtrl.getInitialComponent());
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
//TODO uh if click on breadcrumb shows blankcontroller
}
@Override
protected void doDispose() {
removeAsListenerAndDispose(presentationCtrl);
removeAsListenerAndDispose(filterCtrl);
presentationCtrl = null;
filterCtrl = null;
}
public void setPresentation(UserRequest ureq, Presentation presentation) {
removeAsListenerAndDispose(presentationCtrl);
presentationCtrl = null;
switch (presentation) {
case REPORT:
presentationCtrl = new AnalysisReportController(ureq, getWindowControl(), secCallback, stackPanel);
break;
case HEAT_MAP:
presentationCtrl = new HeatMapController(ureq, getWindowControl(), secCallback, stackPanel);
break;
default:
presentationCtrl = new BlankController(ureq, getWindowControl());
break;
}
listenTo(presentationCtrl);
mainVC.put("presentation", presentationCtrl.getInitialComponent());
mainVC.setDirty(true);
}
}
......@@ -27,10 +27,12 @@ import org.olat.basesecurity.OrganisationRoles;
import org.olat.basesecurity.OrganisationService;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.form.flexible.FormItem;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement;
import org.olat.core.gui.components.form.flexible.elements.FormLink;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableCssDelegate;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnModel;
......@@ -38,6 +40,7 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponentDelegate;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType;
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.stack.TooledStackedPanel;
import org.olat.core.gui.components.velocity.VelocityContainer;
......@@ -75,6 +78,7 @@ public class AnalysisListController extends FormBasicController implements Flexi
private QualityAnalysisService analysisService;
@Autowired
private OrganisationService organisationService;
private AnalysisSegmentsController analysisCtrl;
public AnalysisListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
QualitySecurityCallback secCallback) {
......@@ -137,7 +141,7 @@ public class AnalysisListController extends FormBasicController implements Flexi
private AnalysisRow forgeRow(EvaluationFormView form) {
String openLinkId = "open_" + (++counter);
FormLink openLink = uifactory.addFormLink(openLinkId, "analysis.table.open", "analysis.table.open", null, flc, Link.LINK);
FormLink openLink = uifactory.addFormLink(openLinkId, CMD_OPEN, "analysis.table.open", null, flc, Link.LINK);
openLink.setElementCssClass("o_qual_ana_open_link");
openLink.setIconRightCSS("o_icon o_icon_start");
......@@ -155,6 +159,34 @@ public class AnalysisListController extends FormBasicController implements Flexi
}
return components;
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (source == tableEl && event instanceof SelectionEvent) {
SelectionEvent se = (SelectionEvent)event;
String cmd = se.getCommand();
AnalysisRow row = dataModel.getObject(se.getIndex());
if (CMD_OPEN.equals(cmd)) {
doOpenAnalysis(ureq, row);
}
} else if (source instanceof FormLink) {
FormLink link = (FormLink)source;
if(CMD_OPEN.equals(link.getCmd())) {
doOpenAnalysis(ureq, (AnalysisRow)link.getUserObject());
}
}
super.formInnerEvent(ureq, source, event);
}
private void doOpenAnalysis(UserRequest ureq, EvaluationFormView formView) {
WindowControl bwControl = addToHistory(ureq, formView, null);
analysisCtrl = new AnalysisSegmentsController(ureq, bwControl, secCallback, stackPanel, formView);
listenTo(analysisCtrl);
String title = formView.getFormTitle();
stackPanel.pushController(title, analysisCtrl);
analysisCtrl.activate(ureq, null, null);
}
@Override
protected void formOK(UserRequest ureq) {
......
/**
* <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.analysis.ui;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.modules.quality.QualitySecurityCallback;
/**
*
* Initial date: 04.09.2018<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class AnalysisReportController extends FormBasicController {
private final QualitySecurityCallback secCallback;
private final TooledStackedPanel stackPanel;
public AnalysisReportController(UserRequest ureq, WindowControl wControl, QualitySecurityCallback secCallback,
TooledStackedPanel stackPanel) {
super(ureq, wControl);
this.secCallback = secCallback;
this.stackPanel = stackPanel;
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
uifactory.addStaticExampleText("re3", "", "Report, report, report,..", formLayout);
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
super.event(ureq, source, event);
}
@Override
protected void formOK(UserRequest ureq) {
//
}
@Override
protected void doDispose() {
//
}
}
......@@ -30,7 +30,7 @@ import org.olat.modules.quality.analysis.EvaluationFormView;
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class AnalysisRow {
public class AnalysisRow implements EvaluationFormView {
private final EvaluationFormView formView;
private final FormLink openLink;
......@@ -39,31 +39,48 @@ public class AnalysisRow {
this.formView = formView;
this.openLink = openLink;
}
@Override
public String getResourceableTypeName() {
return formView.getResourceableTypeName();
}
@Override
public Long getResourceableId() {
return formView.getResourceableId();
}
@Override
public Long getFormEntryKey() {
return formView.getFormEntryKey();
}
@Override
public Date getFormCreatedDate() {
return formView.getFormCreatedDate();
}
@Override
public String getFormTitle() {
return formView.getFormTitle();
}
@Override
public Long getNumberDataCollections() {
return formView.getNumberDataCollections();
}
@Override
public Date getSoonestDataCollectionDate() {
return formView.getSoonestDataCollectionDate();
}
@Override
public Date getLatestDataCollectionDate() {
return formView.getLatestDataCollectionDate();
}
@Override
public Long getNumberParticipationsDone() {
return formView.getNumberParticipationsDone();
}
......
/**
* <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.analysis.ui;
import java.util.List;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.panel.Panel;
import org.olat.core.gui.components.panel.SimpleStackedPanel;
import org.olat.core.gui.components.panel.StackedPanel;
import org.olat.core.gui.components.stack.ButtonGroupComponent;
import org.olat.core.gui.components.stack.PopEvent;
import org.olat.core.gui.components.stack.TooledController;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry;
import org.olat.modules.quality.QualitySecurityCallback;
import org.olat.modules.quality.analysis.EvaluationFormView;
/**
*
* Initial date: 04.09.2018<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class AnalysisSegmentsController extends BasicController implements TooledController, Activateable2 {
private final TooledStackedPanel stackPanel;
private final StackedPanel mainPanel;
private final ButtonGroupComponent segmentButtonsCmp;
private Link reportLink;
private Link heatMapLink;
private AnalysisController analysisCtrl;
private final QualitySecurityCallback secCallback;
private final EvaluationFormView formView;
//TODO uh Wo wird das StackPanel und das SecCallback benätigt
public AnalysisSegmentsController(UserRequest ureq, WindowControl wControl, QualitySecurityCallback secCallback,
TooledStackedPanel stackPanel, EvaluationFormView formView) {
super(ureq, wControl);
this.secCallback = secCallback;
this.stackPanel = stackPanel;
stackPanel.addListener(this);
this.formView = formView;
segmentButtonsCmp = new ButtonGroupComponent("segments");
reportLink = LinkFactory.createLink("segments.report.link", getTranslator(), this);
segmentButtonsCmp.addButton(reportLink, false);
heatMapLink = LinkFactory.createLink("segments.heatmap.link", getTranslator(), this);
segmentButtonsCmp.addButton(heatMapLink, false);
mainPanel = putInitialPanel(new SimpleStackedPanel("analysisSegments"));
mainPanel.setContent(new Panel("empty"));
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
doOpenReport(ureq);
}
@Override
public void initTools() {
stackPanel.addTool(segmentButtonsCmp, true);
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
if (reportLink == source) {
doOpenReport(ureq);
} else if(heatMapLink == source) {
doOpenHeatMap(ureq);
} else if (stackPanel == source && stackPanel.getLastController() == this && event instanceof PopEvent) {
PopEvent popEvent = (PopEvent) event;
if (popEvent.isClose()) {
stackPanel.popController(this);
} else {
doOpenReport(ureq);
}
}
}
private void doOpenAnalysis(UserRequest ureq) {
if (analysisCtrl == null) {
analysisCtrl = new AnalysisController(ureq, getWindowControl(), secCallback, stackPanel, formView);
listenTo(analysisCtrl);
stackPanel.pushController("segments.report.breadcrumb", analysisCtrl);
}
}
private void doOpenReport(UserRequest ureq) {
doOpenAnalysis(ureq);
analysisCtrl.setPresentation(ureq, AnalysisController.Presentation.REPORT);
stackPanel.changeDisplayname(translate("segments.report.breadcrumb"));
segmentButtonsCmp.setSelectedButton(reportLink);
}
private void doOpenHeatMap(UserRequest ureq) {
doOpenAnalysis(ureq);
analysisCtrl.setPresentation(ureq, AnalysisController.Presentation.HEAT_MAP);
stackPanel.changeDisplayname(translate("segments.heatmap.breadcrumb"));
segmentButtonsCmp.setSelectedButton(heatMapLink);
}
@Override
protected void doDispose() {
if(stackPanel != null) {
stackPanel.removeListener(this);
}
}
}
/**
* <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.analysis.ui;
import static java.util.stream.Collectors.toList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.olat.basesecurity.OrganisationModule;
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.MultipleSelectionElement;
import org.olat.core.gui.components.form.flexible.elements.StaticTextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.id.Organisation;
import org.olat.core.id.OrganisationRef;
import org.olat.modules.curriculum.Curriculum;
import org.olat.modules.curriculum.CurriculumElement;
import org.olat.modules.curriculum.CurriculumElementRef;
import org.olat.modules.curriculum.CurriculumModule;
import org.olat.modules.curriculum.CurriculumRef;
import org.olat.modules.curriculum.ui.CurriculumTreeModel;
import org.olat.modules.quality.analysis.AnalysisSearchParameter;
import org.olat.modules.quality.analysis.QualityAnalysisService;
import org.olat.modules.quality.ui.QualityUIFactory;
import org.olat.modules.quality.ui.QualityUIFactory.KeysValues;
import org.olat.user.ui.organisation.OrganisationTreeModel;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 04.09.2018<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class FilterController extends FormBasicController {
private DateChooser dateRangeFromEl;
private DateChooser dateRangeToEl;
private MultipleSelectionElement organisationEl;
private MultipleSelectionElement curriculumEl;
private MultipleSelectionElement curriculumElementEl;
private StaticTextElement countFilteredEl;
private final AnalysisSearchParameter searchParams;
@Autowired
private QualityAnalysisService analysisService;
@Autowired
private OrganisationModule organisationModule;
@Autowired
private CurriculumModule curriculumModule;
public FilterController(UserRequest ureq, WindowControl wControl, AnalysisSearchParameter searchParams) {
super(ureq, wControl);
this.searchParams = searchParams;
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
dateRangeFromEl = uifactory.addDateChooser("filter.date.range.from", null, formLayout);
dateRangeFromEl.addActionListener(FormEvent.ONCHANGE);
dateRangeToEl = uifactory.addDateChooser("filter.date.range.to", null, formLayout);
dateRangeToEl.addActionListener(FormEvent.ONCHANGE);
organisationEl = uifactory.addCheckboxesDropdown("filter.organisations", formLayout);
organisationEl.addActionListener(FormEvent.ONCLICK);
curriculumEl = uifactory.addCheckboxesDropdown("filter.curriculums", formLayout);
curriculumEl.addActionListener(FormEvent.ONCLICK);
curriculumElementEl = uifactory.addCheckboxesDropdown("filter.curriculum.elements", formLayout);
curriculumElementEl.addActionListener(FormEvent.ONCLICK);
countFilteredEl = uifactory.addStaticTextElement("filter.count", "", formLayout);
setSelectionValues();
}
private void setSelectionValues() {
setOrganisationValues();
setCurriculumValues();
setCurriculumElementValues();
setCountFiltered();
}
private void setOrganisationValues() {
if (!organisationModule.isEnabled()) {
organisationEl.setVisible(false);
return;
}
Collection<String> selectedKeys = organisationEl.getSelectedKeys();
AnalysisSearchParameter orgSearchParams = new AnalysisSearchParameter();
orgSearchParams.setFormEntryRef(searchParams.getFormEntryRef());
List<Organisation> organisations = analysisService.loadFilterOrganisations(orgSearchParams);
OrganisationTreeModel organisationModel = new OrganisationTreeModel();
organisationModel.loadTreeModel(organisations);
KeysValues keysValues = QualityUIFactory.getTopicOrganisationKeysValues(organisationModel, null);
organisationEl.setKeysAndValues(keysValues.getKeys(), keysValues.getValues());
for (String key: selectedKeys) {
organisationEl.select(key, true);
}
}
private void setCurriculumValues() {
if (!curriculumModule.isEnabled()) {
curriculumEl.setVisible(false);
return;
}
Collection<String> selectedKeys = curriculumEl.getSelectedKeys();
AnalysisSearchParameter curriculumSearchParams = searchParams.clone();
curriculumSearchParams.setCurriculumRefs(null);
curriculumSearchParams.setCurriculumElementRefs(null);
List<Curriculum> curriculums = analysisService.loadFilterCurriculums(curriculumSearchParams);
KeysValues keysValues = QualityUIFactory.getCurriculumKeysValues(curriculums, null);
curriculumEl.setKeysAndValues(keysValues.getKeys(), keysValues.getValues());
for (String key: selectedKeys) {
curriculumEl.select(key, true);
}
}
private void setCurriculumElementValues() {
if (!curriculumModule.isEnabled()) {
curriculumElementEl.setVisible(false);
return;
}
Collection<String> selectedKeys = curriculumEl.getSelectedKeys();
AnalysisSearchParameter curriculumElementSearchParams = searchParams.clone();
Collection<String> curriculumKeys = curriculumEl.isAtLeastSelected(1)
? curriculumEl.getSelectedKeys()
: curriculumEl.getKeys();
List<? extends CurriculumRef> curriculumRefs = curriculumKeys.stream()
.map(key -> QualityUIFactory.getCurriculumRef(key))
.collect(toList());
curriculumElementSearchParams.setCurriculumRefs(curriculumRefs);
curriculumElementSearchParams.setCurriculumElementRefs(null);
List<CurriculumElement> curriculumElements = analysisService.loadFilterCurriculumElements(curriculumElementSearchParams);
CurriculumTreeModel curriculumTreeModel = new CurriculumTreeModel();
curriculumTreeModel.loadTreeModel(curriculumElements);
KeysValues keysValues = QualityUIFactory.getCurriculumElementKeysValues(curriculumTreeModel, null);
curriculumElementEl.setKeysAndValues(keysValues.getKeys(), keysValues.getValues());
for (String key: selectedKeys) {
curriculumElementEl.select(key, true);
}
}
private void setCountFiltered() {
Long count = analysisService.loadFilterDataCollectionCount(searchParams);
countFilteredEl.setValue(count.toString());
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (source == dateRangeFromEl) {
doFiltered();
} else if (source == dateRangeToEl) {
doFiltered();
} else if (source == organisationEl) {
doFiltered();
} else if (source == curriculumEl) {
doFiltered();
} else if (source == curriculumElementEl) {
doFiltered();
}
super.formInnerEvent(ureq, source, event);
}
private void doFiltered() {
getSearchParams();
setSelectionValues();
//TODO uh filter presentation -> fireEvent
}
private void getSearchParams() {
getSearchParamOrganisations();
getSearchParamCurriculums();
getSearchParamCurriculumElements();
getSearchParamDateRangeFrom();
getSearchParamDateRangeTo();
}
private void getSearchParamOrganisations() {
if (organisationModule.isEnabled() && organisationEl.isAtLeastSelected(1)) {
List<OrganisationRef> organisationRefs = organisationEl.getSelectedKeys().stream()
.map(key -> QualityUIFactory.getOrganisationRef(key))
.collect(toList());
searchParams.setOrganisationRefs(organisationRefs);
} else {
searchParams.setOrganisationRefs(null);
}
}
private void getSearchParamCurriculums() {
if (curriculumEl.isEnabled() && curriculumEl.isAtLeastSelected(1)) {
Collection<CurriculumRef> curriculumRefs = curriculumEl.getSelectedKeys().stream()
.map(key -> QualityUIFactory.getCurriculumRef(key))
.collect(toList());
searchParams.setCurriculumRefs(curriculumRefs);
} else {
searchParams.setCurriculumRefs(null);
}
}
private void getSearchParamCurriculumElements() {
if (curriculumEl.isEnabled() && curriculumElementEl.isAtLeastSelected(1)) {
List<CurriculumElementRef> curriculumElementRefs = curriculumElementEl.getSelectedKeys().stream()
.map(key -> QualityUIFactory.getCurriculumElementRef(key))
.collect(toList());
searchParams.setCurriculumElementRefs(curriculumElementRefs);
} else {
searchParams.setCurriculumElementRefs(null);
}
}
private void getSearchParamDateRangeFrom() {
Date dateRangeFrom = dateRangeFromEl.getDate();
searchParams.setDateRangeFrom(dateRangeFrom);
}
private void getSearchParamDateRangeTo() {
Date dateRangeTo = dateRangeToEl.getDate();
searchParams.setDateRangeTo(dateRangeTo);
}
@Override
protected void formOK(UserRequest ureq) {
//
}
@Override
protected void doDispose() {
//
}
}
/**
* <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.analysis.ui;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.modules.quality.QualitySecurityCallback;
/**
*
* Initial date: 04.09.2018<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public class HeatMapController extends FormBasicController {
private final QualitySecurityCallback secCallback;
private final TooledStackedPanel stackPanel;
public HeatMapController(UserRequest ureq, WindowControl wControl, QualitySecurityCallback secCallback,
TooledStackedPanel stackPanel) {
super(ureq, wControl);
this.secCallback = secCallback;
this.stackPanel = stackPanel;
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
uifactory.addStaticExampleText("hm", "", "HEAT MAP", formLayout);
}
@Override
protected void formOK(UserRequest ureq) {
//
}
@Override
protected void doDispose() {
//
}
}
$r.render("filter")
#if($r.available("presentation"))
$r.render("presentation")
#end
......@@ -2,8 +2,18 @@ analysis.table.data.collections.latest=Letzte Datenerhebung
analysis.table.data.collections.number=Datenerhebungen
analysis.table.data.collections.soonest=Erste Datenerhebung
analysis.table.empty=Diese Tabelle enth\u00e4hlt keine Daten.
analysis.table.form.created=Erstellt
analysis.table.form.created.on=Erstellt am {0}
analysis.table.form.created=Erstellt
analysis.table.form.title=Fragebogen
analysis.table.participations.number=Teilnahmen
analysis.table.open=\u00d6ffnen
analysis.table.participations.number=Teilnahmen
filter.count=Anzahl Datenerhebungen
filter.curriculum.elements=Curriculumelement
filter.curriculums=Curriculum
filter.date.range.from=Datenerhebungen von
filter.date.range.to=Datenerhebungen to
filter.organisations=Organisationen
segments.heatmap.breadcrumb=Heatmap
segments.heatmap.link=Heatmap
segments.report.breadcrumb=Report
segments.report.link=Report
......@@ -2,8 +2,18 @@ analysis.table.data.collections.latest=Latest data collection
analysis.table.data.collections.number=Data collections
analysis.table.data.collections.soonest=Soonest data collection
analysis.table.empty=This table contains no data.
analysis.table.form.created=Created
analysis.table.form.created.on=Created on {0}
analysis.table.form.created=Created
analysis.table.form.title=Questionnaire
analysis.table.participations.number=Participations
analysis.table.open=Open
analysis.table.participations.number=Participations
filter.count=Number of data collections
filter.curriculum.elements=Curriculumelement
filter.curriculums=Curriculum
filter.date.range.from=Data collections from
filter.date.range.to=Data collections to
filter.organisations=Organisations
segments.heatmap.breadcrumb=Heat map
segments.heatmap.link=Heat map
segments.report.breadcrumb=Report
segments.report.link=Report
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment