diff --git a/src/main/java/de/bps/onyx/plugin/wsserver/ReturnWSService.java b/src/main/java/de/bps/onyx/plugin/wsserver/ReturnWSService.java index 18d8cf4390544951e7c0cd0ef41bb76c7a2800a2..10f9e672195c1a6ea5be4667692e3835bdd371c2 100644 --- a/src/main/java/de/bps/onyx/plugin/wsserver/ReturnWSService.java +++ b/src/main/java/de/bps/onyx/plugin/wsserver/ReturnWSService.java @@ -41,9 +41,9 @@ import org.olat.core.util.FileUtils; import org.olat.core.util.WebappHelper; import org.olat.course.CourseFactory; import org.olat.course.ICourse; -import org.olat.course.assessment.NewCachePersistingAssessmentManager; +import org.olat.course.assessment.AssessmentManager; +import org.olat.course.assessment.manager.CourseAssessmentManagerImpl; import org.olat.course.nodes.CourseNode; -import org.olat.course.properties.CoursePropertyManager; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironmentImpl; @@ -204,9 +204,8 @@ public class ReturnWSService { ICourse course = CourseFactory.loadCourse(resourceId); CourseNode courseNode = course.getRunStructure().getNode(qtiResultSet.getOlatResourceDetail()); - NewCachePersistingAssessmentManager am = (NewCachePersistingAssessmentManager) NewCachePersistingAssessmentManager.getInstance(course); + AssessmentManager am = new CourseAssessmentManagerImpl(course.getCourseEnvironment().getCourseGroupManager().getCourseEntry()); - CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager(); // create an identenv with no roles, no // attributes, no locale IdentityEnvironment ienv = new IdentityEnvironment(); @@ -215,7 +214,8 @@ public class ReturnWSService { ScoreEvaluation scoreEvaluation = new ScoreEvaluation(qtiResultSet.getScore(), qtiResultSet.getIsPassed(), qtiResultSet.getFullyAssessed(), qtiResultSet.getAssessmentID()); - am.syncAndsaveScoreEvaluation(courseNode, assessedIdentity, assessedIdentity, scoreEvaluation, false, userCourseEnvironment, cpm); + am.saveScoreEvaluation(courseNode, null, assessedIdentity, scoreEvaluation, userCourseEnvironment, false); + } } else { if (log.isDebug()) { diff --git a/src/main/java/org/olat/admin/landingpages/ui/LandingPagesAdminController.java b/src/main/java/org/olat/admin/landingpages/ui/LandingPagesAdminController.java index 12d19100fc3d6e775d9380b28315c3d88ba76731..2d3c16c7826a8de3c8a3d452e76b3cbc8e29671c 100644 --- a/src/main/java/org/olat/admin/landingpages/ui/LandingPagesAdminController.java +++ b/src/main/java/org/olat/admin/landingpages/ui/LandingPagesAdminController.java @@ -53,7 +53,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.velocity.VelocityContainer; @@ -139,12 +138,12 @@ public class LandingPagesAdminController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RCols.landingPage.i18nKey(), RCols.landingPage.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RCols.landingPageChooser.i18nKey(), RCols.landingPageChooser.ordinal())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("up", -1, "up", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("up", -1, "up", new StaticFlexiCellRenderer("", "up", "o_icon o_icon-lg o_icon_move_up",translate("up")))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("down", -1, "down", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("down", -1, "down", new StaticFlexiCellRenderer("", "down", "o_icon o_icon-lg o_icon_move_down", translate("down")))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("add", translate("add"), "add")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", translate("delete"), "delete")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("add", translate("add"), "add")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", translate("delete"), "delete")); //pack the rules Rules rules = lpModule.getRules(); diff --git a/src/main/java/org/olat/admin/site/ui/SitesConfigurationController.java b/src/main/java/org/olat/admin/site/ui/SitesConfigurationController.java index 757d9244041515f5694928f01e9b877d8817e800..4674ca9959f5e3cff8200be166120935a3730006 100644 --- a/src/main/java/org/olat/admin/site/ui/SitesConfigurationController.java +++ b/src/main/java/org/olat/admin/site/ui/SitesConfigurationController.java @@ -41,7 +41,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.navigation.SiteAlternativeControllerCreator; @@ -136,9 +135,9 @@ public class SitesConfigurationController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SiteCols.altController.i18nKey(), SiteCols.altController.ordinal())); } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, SiteCols.defaultOrder.i18nKey(), SiteCols.defaultOrder.ordinal(), false, null)); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("up", SiteCols.up.ordinal(), "up", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("up", SiteCols.up.ordinal(), "up", new StaticFlexiCellRenderer("", "up", "o_icon o_icon-lg o_icon_move_up", translate("up")))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("down", SiteCols.down.ordinal(), "down", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("down", SiteCols.down.ordinal(), "down", new StaticFlexiCellRenderer("", "down", "o_icon o_icon-lg o_icon_move_down", translate("down")))); model = new SiteDefModel(columnsModel); diff --git a/src/main/java/org/olat/admin/user/UserSearchFlexiController.java b/src/main/java/org/olat/admin/user/UserSearchFlexiController.java index 0af9923e07732f5fd9e460e28f544500f479015c..69ca37a8ab984a500a6b56c3bda4fac8d07dc5eb 100644 --- a/src/main/java/org/olat/admin/user/UserSearchFlexiController.java +++ b/src/main/java/org/olat/admin/user/UserSearchFlexiController.java @@ -44,7 +44,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFle import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -213,7 +212,7 @@ public class UserSearchFlexiController extends FlexiAutoCompleterController { tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colPos++)); } } - tableColumnModel.addFlexiColumnModel(new StaticFlexiColumnModel("select", translate("select"), "select")); + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("select", translate("select"), "select")); Translator myTrans = userManager.getPropertyHandlerTranslator(getTranslator()); userTableModel = new UserSearchFlexiTableModel(Collections.<Identity>emptyList(), resultingPropertyHandlers, isAdministrativeUser, getLocale(), tableColumnModel); diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java index 4cf7cea7cc09baa2f57d1bb691fb05e86180d8a9..55b19a06a64f2fe1852caa104259387832ebabf4 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java @@ -108,8 +108,8 @@ import org.olat.core.util.resource.OresHelper; import org.olat.course.assessment.AssessmentMode.Status; import org.olat.course.assessment.AssessmentModeNotificationEvent; import org.olat.course.assessment.model.TransientAssessmentMode; -import org.olat.course.assessment.ui.AssessmentModeGuardController; -import org.olat.course.assessment.ui.ChooseAssessmentModeEvent; +import org.olat.course.assessment.ui.mode.AssessmentModeGuardController; +import org.olat.course.assessment.ui.mode.ChooseAssessmentModeEvent; import org.olat.gui.control.UserToolsMenuController; import org.olat.home.HomeSite; import org.olat.login.AfterLoginInterceptionController; diff --git a/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml b/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml index e4f0bb7550b6386cf65e8bffe83d2f4420660007..b94733d852e7a9d885475effc04d4d3c2fee4c1b 100644 --- a/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml +++ b/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml @@ -131,6 +131,7 @@ <class>org.olat.ims.qti.statistics.model.QTIStatisticResult</class> <class>org.olat.ims.qti.statistics.model.QTIStatisticResultSet</class> <class>org.olat.ims.qti21.model.jpa.UserTestSessionImpl</class> + <class>org.olat.modules.assessment.model.AssessmentEntryImpl</class> <class>org.olat.modules.qpool.model.PoolImpl</class> <class>org.olat.modules.qpool.model.PoolToItem</class> <class>org.olat.modules.qpool.model.PoolItemShortView</class> diff --git a/src/main/java/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml b/src/main/java/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml index 84b11a62c11011109b3b87847edada3d520b7d7f..4db7eeb0244441f092fdb7fd39d31a350c6f0460 100644 --- a/src/main/java/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml +++ b/src/main/java/org/olat/core/commons/services/notifications/_spring/notificationsContext.xml @@ -7,7 +7,6 @@ <!-- List of notifications handlers --> <bean id="org.olat.modules.fo.ForumNotificationsHandler" class="org.olat.modules.fo.ForumNotificationsHandler" /> - <bean id="org.olat.course.assessment.AssessmentNotificationsHandler" class="org.olat.course.assessment.AssessmentNotificationsHandler" /> <bean id="org.olat.core.commons.modules.bc.FolderNotificationsHandler" class="org.olat.core.commons.modules.bc.notifications.FolderNotificationsHandler" /> <bean id="org.olat.modules.dialog.FileUploadNotificationHandler" class="org.olat.modules.dialog.FileUploadNotificationHandler" /> <bean id="org.olat.course.nodes.ta.DropboxFileUploadNotificationHandler" class="org.olat.course.nodes.ta.DropboxFileUploadNotificationHandler" /> diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiColumnModel.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiColumnModel.java deleted file mode 100644 index 3516227520efeeb1e11fec8d4b1946c7c8eefb1c..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiColumnModel.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.core.gui.components.form.flexible.impl.elements.table; - -/** - * - * Initial date: 15.02.2013<br> - * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com - * - */ -public abstract class AbstractFlexiColumnModel implements FlexiColumnModel { - - private int alignment; - private String headerKey; - private String headerLabel; - private String columnKey; - private boolean sortable; - private boolean exportable = true; - private String sortedKey; - private int columnIndex; - private FlexiCellRenderer cellRenderer; - - public AbstractFlexiColumnModel(String headerKey, int columnIndex, int alignment, FlexiCellRenderer cellRenderer) { - this(headerKey, columnIndex, alignment, false, null, cellRenderer); - } - - public AbstractFlexiColumnModel(String headerKey, int columnIndex, int alignment, - boolean sortable, String sortedKey, FlexiCellRenderer cellRenderer) { - this.headerKey = headerKey; - this.columnIndex = columnIndex; - this.columnKey = headerKey.replace(".", "").toLowerCase(); - this.sortable = sortable; - this.sortedKey = sortedKey; - this.alignment = alignment; - this.cellRenderer = cellRenderer; - } - - @Override - public String getAction() { - return null; - } - - public String getHeaderKey() { - return headerKey; - } - - @Override - public String getHeaderLabel() { - return headerLabel; - } - - public void setHeaderLabel(String headerLabel) { - this.headerLabel = headerLabel; - } - - @Override - public String getColumnKey() { - return columnKey; - } - - @Override - public int getColumnIndex() { - return columnIndex; - } - - @Override - public boolean isSortable() { - return sortable; - } - - @Override - public void setSortable(boolean sortable) { - this.sortable = sortable; - } - - @Override - public boolean isExportable() { - return exportable; - } - - @Override - public void setExportable(boolean exportable) { - this.exportable = exportable; - } - - @Override - public boolean isDefaultVisible() { - return true; - } - - @Override - public String getSortKey() { - return sortedKey; - } - - @Override - public void setSortKey(String sortedKey) { - this.sortedKey = sortedKey; - } - - public int getAlignment() { - return alignment; - } - - public void setAlignment(int alignment) { - this.alignment = alignment; - } - - public void setCellRenderer(FlexiCellRenderer cellRenderer) { - this.cellRenderer = cellRenderer; - } - - public FlexiCellRenderer getCellRenderer() { - return cellRenderer; - } -} \ No newline at end of file diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiColumnModel.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiColumnModel.java index ead0aa3f6862bcca2f4c26f531ffc3d94e8b97e3..4c1369fb0fbdeec4bbe3c8a909f24e1a62103ad4 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiColumnModel.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiColumnModel.java @@ -43,31 +43,99 @@ public class DefaultFlexiColumnModel implements FlexiColumnModel { private String sortedKey; private boolean defaultVisible; + private boolean alwaysVisible; private int alignment; + + private final String action; + private FlexiCellRenderer cellRenderer; + + public DefaultFlexiColumnModel(FlexiColumnDef def) { + this(def.i18nHeaderKey(), def.ordinal(), false, null); + } + + public DefaultFlexiColumnModel(FlexiColumnDef def, String action) { + this(true, false, def.i18nHeaderKey(), def.ordinal(), action, false, null, FlexiColumnModel.ALIGNMENT_LEFT, + new StaticFlexiCellRenderer(action, new TextFlexiCellRenderer())); + } + /** + * + * @param headerKey + * @param columnIndex + */ public DefaultFlexiColumnModel(String headerKey, int columnIndex) { this(headerKey, columnIndex, false, null); } + /** + * Always visible + * @param headerKey + * @param label + * @param action + */ + public DefaultFlexiColumnModel(String headerKey, String label, String action) { + this(true, true, headerKey, -1, action, false, null, FlexiColumnModel.ALIGNMENT_LEFT, new StaticFlexiCellRenderer(label, action)); + } + public DefaultFlexiColumnModel(String headerKey, int columnIndex, boolean sortable, String sortKey) { - this(true, headerKey, columnIndex, sortable, sortKey, FlexiColumnModel.ALIGNMENT_LEFT, new TextFlexiCellRenderer()); + this(true, false, headerKey, columnIndex, null, sortable, sortKey, FlexiColumnModel.ALIGNMENT_LEFT, new TextFlexiCellRenderer()); + } + + public DefaultFlexiColumnModel(FlexiColumnDef def, FlexiCellRenderer renderer) { + this(true, false, def.i18nHeaderKey(), def.ordinal(), null, false, null, FlexiColumnModel.ALIGNMENT_LEFT, renderer); } public DefaultFlexiColumnModel(String headerKey, int columnIndex, FlexiCellRenderer renderer) { - this(true, headerKey, columnIndex, false, null, FlexiColumnModel.ALIGNMENT_LEFT, renderer); + this(true, false, headerKey, columnIndex, null, false, null, FlexiColumnModel.ALIGNMENT_LEFT, renderer); + } + + /** + * Always visible + * @param headerKey + * @param columnIndex + * @param action + * @param renderer + */ + public DefaultFlexiColumnModel(String headerKey, int columnIndex, String action, FlexiCellRenderer renderer) { + this(true, true, headerKey, columnIndex, action, false, null, FlexiColumnModel.ALIGNMENT_LEFT, renderer); } public DefaultFlexiColumnModel(String headerKey, int columnIndex, boolean sortable, String sortKey, FlexiCellRenderer renderer) { - this(true, headerKey, columnIndex, sortable, sortKey, FlexiColumnModel.ALIGNMENT_LEFT, renderer); + this(true, false, headerKey, columnIndex, null, sortable, sortKey, FlexiColumnModel.ALIGNMENT_LEFT, renderer); } public DefaultFlexiColumnModel(boolean defVisible, String headerKey, int columnIndex, boolean sortable, String sortKey) { - this(defVisible, headerKey, columnIndex, sortable, sortKey, FlexiColumnModel.ALIGNMENT_LEFT, new TextFlexiCellRenderer()); + this(defVisible, false, headerKey, columnIndex, null, sortable, sortKey, FlexiColumnModel.ALIGNMENT_LEFT, + new TextFlexiCellRenderer()); + } + + public DefaultFlexiColumnModel(boolean defVisible, String headerKey, int columnIndex, String action, boolean sortable, String sortKey) { + this(defVisible, false, headerKey, columnIndex, action, sortable, sortKey, FlexiColumnModel.ALIGNMENT_LEFT, + new StaticFlexiCellRenderer(action, new TextFlexiCellRenderer())); + } + + /** + * Always visible + * @param headerKey + * @param columnIndex + * @param action + * @param sortable + * @param sortedKey + * @param renderer + */ + public DefaultFlexiColumnModel(String headerKey, int columnIndex, String action, boolean sortable, String sortedKey, FlexiCellRenderer renderer) { + this(true, true, headerKey, columnIndex, action, sortable, sortedKey, FlexiColumnModel.ALIGNMENT_LEFT, renderer); } public DefaultFlexiColumnModel(boolean defVisible, String headerKey, int columnIndex, boolean sortable, String sortKey, int alignment, FlexiCellRenderer cellRenderer) { + this(defVisible, false, headerKey, columnIndex, null, sortable, sortKey, alignment, cellRenderer); + } + + public DefaultFlexiColumnModel(boolean defVisible, boolean alwaysVisible, String headerKey, int columnIndex, String action, + boolean sortable, String sortKey, int alignment, FlexiCellRenderer cellRenderer) { this.defaultVisible = defVisible; + this.alwaysVisible = alwaysVisible; this.sortable = sortable; this.sortedKey = sortKey; this.headerKey = headerKey; @@ -75,16 +143,17 @@ public class DefaultFlexiColumnModel implements FlexiColumnModel { this.columnKey = headerKey.replace(".", "").toLowerCase(); this.alignment = alignment; this.cellRenderer = cellRenderer; + this.action = action; } @Override public boolean isAlwaysVisible() { - return false; + return alwaysVisible; } @Override public String getAction() { - return null; + return action; } @Override diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiColumnDef.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiColumnDef.java new file mode 100644 index 0000000000000000000000000000000000000000..6aa159b81dc56353ec15856bdaeee8c4b6b40e77 --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiColumnDef.java @@ -0,0 +1,34 @@ +/** + * <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.core.gui.components.form.flexible.impl.elements.table; + +/** + * + * Initial date: 22.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface FlexiColumnDef { + + public int ordinal(); + + public String i18nHeaderKey(); + +} diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiSortableColumnDef.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiSortableColumnDef.java new file mode 100644 index 0000000000000000000000000000000000000000..41220754517fe8f34d5d6b4358d276bca3295f1e --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiSortableColumnDef.java @@ -0,0 +1,34 @@ +/** + * <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.core.gui.components.form.flexible.impl.elements.table; + +/** + * + * Initial date: 22.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface FlexiSortableColumnDef extends FlexiColumnDef { + + public boolean sortable(); + + public String sortKey(); + +} diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/StaticFlexiColumnModel.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/StaticFlexiColumnModel.java deleted file mode 100644 index d6a6b9e863c3c2afb5ded834e6d89a7be8937060..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/StaticFlexiColumnModel.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.core.gui.components.form.flexible.impl.elements.table; - -/** - * - * Initial date: 15.02.2013<br> - * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com - * - */ -public class StaticFlexiColumnModel extends AbstractFlexiColumnModel { - - private final String action; - - /** - * Used the standard renderer - * @param headerKey - * @param label - * @param action - */ - public StaticFlexiColumnModel(String headerKey, String label, String action) { - super(headerKey, -1, FlexiColumnModel.ALIGNMENT_LEFT, new StaticFlexiCellRenderer(label, action)); - this.action = action; - } - - /** - * Use a custom renderer - * @param headerKey - * @param columnIndex - * @param action - * @param renderer - */ - public StaticFlexiColumnModel(String headerKey, int columnIndex, String action, FlexiCellRenderer renderer) { - super(headerKey, columnIndex, FlexiColumnModel.ALIGNMENT_LEFT, renderer); - this.action = action; - } - - public StaticFlexiColumnModel(String headerKey, int columnIndex, String action, boolean sortable, String sortedKey, FlexiCellRenderer renderer) { - super(headerKey, columnIndex, FlexiColumnModel.ALIGNMENT_LEFT, sortable, sortedKey, renderer); - this.action = action; - } - - @Override - public boolean isAlwaysVisible() { - return true; - } - - @Override - public String getAction() { - return action; - } -} diff --git a/src/main/java/org/olat/course/assessment/AssessmentHelper.java b/src/main/java/org/olat/course/assessment/AssessmentHelper.java index 14aff5c5d15cb0016c88b6284a1810eaf7d5da3e..e2de2a74b674386194a128589bc00191cf322b95 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentHelper.java +++ b/src/main/java/org/olat/course/assessment/AssessmentHelper.java @@ -25,6 +25,7 @@ package org.olat.course.assessment; +import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.ParseException; @@ -243,12 +244,18 @@ public class AssessmentHelper { return nodes; } + + public static String getRoundedScore(BigDecimal score) { + if (score == null) return null; + + Float fscore = score.floatValue(); + return getRoundedScore(fscore); + } /** * @param score The score to be rounded * @return The rounded score for GUI presentation */ - //fxdiff VCRP-4: assessment overview with max score public static String getRoundedScore(Float score) { if (score == null) return null; @@ -256,7 +263,6 @@ public class AssessmentHelper { synchronized(scoreFormat) { return scoreFormat.format(score); } - //return Formatter.roundToString(score.floatValue(), 3); } public static Float getRoundedScore(String score) { diff --git a/src/main/java/org/olat/course/assessment/AssessmentMainController.java b/src/main/java/org/olat/course/assessment/AssessmentMainController.java index 374806d854636a23277678fea8f50960df3e6fef..d702acd669bf446df9a096bf7c34fa0b2ed12ee1 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentMainController.java +++ b/src/main/java/org/olat/course/assessment/AssessmentMainController.java @@ -96,6 +96,7 @@ import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.course.assessment.NodeTableDataModel.Cols; import org.olat.course.assessment.bulk.BulkAssessmentOverviewController; +import org.olat.course.assessment.manager.AssessmentNotificationsHandler; import org.olat.course.assessment.manager.UserCourseInformationsManager; import org.olat.course.certificate.CertificateEvent; import org.olat.course.certificate.CertificateLight; @@ -234,6 +235,8 @@ public class AssessmentMainController extends MainLayoutBasicController implemen private BusinessGroupService businessGroupService; @Autowired private CertificatesManager certificatesManager; + @Autowired + private AssessmentNotificationsHandler assessmentNotificationsHandler; /** * Constructor for the assessment tool controller. @@ -284,10 +287,11 @@ public class AssessmentMainController extends MainLayoutBasicController implemen if (hasAssessableNodes) { index.contextPut("hasAssessableNodes", new Boolean(hasAssessableNodes)); - - // --- assessment notification subscription --- - csc = AssessmentUIFactory.createContextualSubscriptionController(ureq, wControl, course); - if (csc != null) { + + SubscriptionContext subsContext = assessmentNotificationsHandler.getAssessmentSubscriptionContext(ureq.getIdentity(), course); + if (subsContext != null) { + PublisherData pData = assessmentNotificationsHandler.getAssessmentPublisherData(course, wControl.getBusinessControl().getAsString()); + csc = new ContextualSubscriptionController(ureq, wControl, subsContext, pData); listenTo(csc); // cleanup on dispose index.put("assessmentSubscription", csc.getInitialComponent()); } diff --git a/src/main/java/org/olat/course/assessment/AssessmentManager.java b/src/main/java/org/olat/course/assessment/AssessmentManager.java index 313408bfb3a89afb737fa09548f920f366f0c904..3a01ddc8098c2c4e14b4c41227d7b46cdb47035e 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentManager.java +++ b/src/main/java/org/olat/course/assessment/AssessmentManager.java @@ -34,6 +34,7 @@ import org.olat.core.util.event.GenericEventListener; import org.olat.course.nodes.CourseNode; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.modules.assessment.AssessmentEntry; /** * Description:<BR> @@ -52,6 +53,7 @@ import org.olat.course.run.userview.UserCourseEnvironment; public interface AssessmentManager { // Names used to save user data in the properties table + /* public static final String SCORE = "SCORE"; public static final String PASSED = "PASSED"; public static final String ATTEMPTS = "ATTEMPTS"; @@ -60,6 +62,7 @@ public interface AssessmentManager { public static final String ASSESSMENT_ID = "ASSESSMENT_ID"; public final static String FULLY_ASSESSED = "FULLY_ASSESSED"; + */ /** * Load all persisted assessment data into a local cache if such a cache is available @@ -208,4 +211,5 @@ public interface AssessmentManager { */ public Boolean getNodeFullyAssessed(CourseNode courseNode, Identity identity); + public List<AssessmentEntry> getAssessmentData(CourseNode courseNode); } \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/AssessmentToolManager.java b/src/main/java/org/olat/course/assessment/AssessmentToolManager.java new file mode 100644 index 0000000000000000000000000000000000000000..4408a90122b81b98c65092312ffb52a0f4cb80e1 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/AssessmentToolManager.java @@ -0,0 +1,39 @@ +/** + * <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.course.assessment; + +import java.util.List; + +import org.olat.core.id.Identity; +import org.olat.course.assessment.model.SearchAssessedIdentityParams; + +/** + * The manager taylored for the assessment tool. + * + * + * Initial date: 22.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface AssessmentToolManager { + + public List<Identity> getAssessedIdentityWithCertificates(SearchAssessedIdentityParams params); + +} diff --git a/src/main/java/org/olat/course/assessment/AssessmentUIFactory.java b/src/main/java/org/olat/course/assessment/AssessmentUIFactory.java deleted file mode 100644 index 42f0be22fd3d145cd776cb36309fb5dd065c9b83..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/course/assessment/AssessmentUIFactory.java +++ /dev/null @@ -1,61 +0,0 @@ -/** -* OLAT - Online Learning and Training<br> -* http://www.olat.org -* <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 -* <p> -* http://www.apache.org/licenses/LICENSE-2.0 -* <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> -* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> -* University of Zurich, Switzerland. -* <hr> -* <a href="http://www.openolat.org"> -* OpenOLAT - Online Learning and Training</a><br> -* This file has been modified by the OpenOLAT community. Changes are licensed -* under the Apache 2.0 license as the original file. -*/ -package org.olat.course.assessment; - -import org.olat.core.commons.services.notifications.PublisherData; -import org.olat.core.commons.services.notifications.SubscriptionContext; -import org.olat.core.commons.services.notifications.ui.ContextualSubscriptionController; -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.WindowControl; -import org.olat.course.ICourse; - -/** - * Description:<br> - * TODO: patrickb Class Description for AssessmentUIFactory - * - * <P> - * Initial Date: 29.06.2010 <br> - * @author patrickb - */ -public class AssessmentUIFactory { - - /** - * - * @param ureq - * @param wControl - * @param course - * @return null if no contextualSubscriptionController is available - */ - public static Controller createContextualSubscriptionController(UserRequest ureq, WindowControl wControl, ICourse course){ - AssessmentNotificationsHandler anh = AssessmentNotificationsHandler.getInstance(); - SubscriptionContext subsContext = anh.getAssessmentSubscriptionContext(ureq.getIdentity(), course); - if (subsContext != null) { - PublisherData pData = anh.getAssessmentPublisherData(course, wControl.getBusinessControl().getAsString()); - return new ContextualSubscriptionController(ureq, wControl, subsContext, pData); - } - return null; - } -} diff --git a/src/main/java/org/olat/course/assessment/EfficiencyStatementManager.java b/src/main/java/org/olat/course/assessment/EfficiencyStatementManager.java index eaf931ac397090878857a08e476d38faacd64edc..14be0f81eea0b479bf65238b284e1ac5b8decbf0 100644 --- a/src/main/java/org/olat/course/assessment/EfficiencyStatementManager.java +++ b/src/main/java/org/olat/course/assessment/EfficiencyStatementManager.java @@ -128,7 +128,7 @@ public class EfficiencyStatementManager extends BasicManager implements UserData * Called in AssessmentManager in a <code>doInSync</code> block, toghether with the saveScore. * @param userCourseEnv */ - protected void updateUserEfficiencyStatement(UserCourseEnvironment userCourseEnv) { + public void updateUserEfficiencyStatement(UserCourseEnvironment userCourseEnv) { Long courseResId = userCourseEnv.getCourseEnvironment().getCourseResourceableId(); OLATResourceable courseOres = OresHelper.createOLATResourceableInstance(CourseModule.class, courseResId); RepositoryEntry re = repositoryManager.lookupRepositoryEntry(courseOres, false); diff --git a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml index c94ace250abcf9cc98301d5234e7a931c3485a4c..3d1a18c13dd43a9134b2a9dcd1778e99a5505188 100644 --- a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml +++ b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml @@ -31,13 +31,13 @@ <property name="order" value="8206" /> <property name="actionController"> <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> - <property name="className" value="org.olat.course.assessment.ui.AssessmentModeAdminController"/> + <property name="className" value="org.olat.course.assessment.ui.mode.AssessmentModeAdminController"/> </bean> </property> <property name="navigationKey" value="certificates" /> <property name="i18nActionKey" value="admin.menu.title"/> <property name="i18nDescriptionKey" value="admin.menu.title.alt"/> - <property name="translationPackage" value="org.olat.course.assessment.ui"/> + <property name="translationPackage" value="org.olat.course.assessment.ui.mode"/> <property name="parentTreeNodeIdentifier" value="modulesParent" /> <property name="extensionPoints"> <list> diff --git a/src/main/java/org/olat/course/assessment/bulk/BulkAssessmentOverviewController.java b/src/main/java/org/olat/course/assessment/bulk/BulkAssessmentOverviewController.java index d158e3c2d3e9583c218b6868dbfafd67f3fe8716..041ac112fd651a5eedc277acf24b9e3f94f131cd 100644 --- a/src/main/java/org/olat/course/assessment/bulk/BulkAssessmentOverviewController.java +++ b/src/main/java/org/olat/course/assessment/bulk/BulkAssessmentOverviewController.java @@ -42,7 +42,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; @@ -118,11 +117,11 @@ public class BulkAssessmentOverviewController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.numOfAssessedUsers", Cols.numOfAssessedUsers.ordinal())); FlexiCellRenderer renderer = new StaticFlexiCellRenderer("select-owner", new TextFlexiCellRenderer()); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.owner", Cols.owner.ordinal(), "select-owner", renderer)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.owner", Cols.owner.ordinal(), "select-owner", renderer)); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit", translate("edit"), "edit")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", translate("delete"), "delete")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("edit", translate("edit"), "edit")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", translate("delete"), "delete")); taskModel = new TaskDataModel(Collections.<TaskData>emptyList(), columnsModel); taskListEl = uifactory.addTableElement(getWindowControl(), "taskList", taskModel, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/assessment/bulk/SelectCourseNodeStepForm.java b/src/main/java/org/olat/course/assessment/bulk/SelectCourseNodeStepForm.java index 04c8d88683dfc5d58f5fd127ef8683c6934889a3..55b69fbdd7516e1e4e29e0daef685168126c0023 100644 --- a/src/main/java/org/olat/course/assessment/bulk/SelectCourseNodeStepForm.java +++ b/src/main/java/org/olat/course/assessment/bulk/SelectCourseNodeStepForm.java @@ -36,7 +36,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.table.DefaultTableDataModel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -80,7 +79,7 @@ public class SelectCourseNodeStepForm extends StepFormBasicController { FlexiTableColumnModel tableColumnModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, "table.header.node", Cols.node.ordinal(), false, null, FlexiColumnModel.ALIGNMENT_LEFT, new CourseNodeRenderer())); - tableColumnModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.action.select", + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.action.select", Cols.assessable.ordinal(), "select", new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("table.action.select"), "select"), null))); tableModel.setTableColumnModel(tableColumnModel); diff --git a/src/main/java/org/olat/course/assessment/AssessmentNotificationsHandler.java b/src/main/java/org/olat/course/assessment/manager/AssessmentNotificationsHandler.java similarity index 77% rename from src/main/java/org/olat/course/assessment/AssessmentNotificationsHandler.java rename to src/main/java/org/olat/course/assessment/manager/AssessmentNotificationsHandler.java index 6c4d7355c9e700eeba36aa9e9922a7320826f705..ead32f35b68ad0448e011bb666e3a91e8a41a7fc 100644 --- a/src/main/java/org/olat/course/assessment/AssessmentNotificationsHandler.java +++ b/src/main/java/org/olat/course/assessment/manager/AssessmentNotificationsHandler.java @@ -23,20 +23,19 @@ * under the Apache 2.0 license as the original file. */ -package org.olat.course.assessment; +package org.olat.course.assessment.manager; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Map; +import java.util.Set; -import org.olat.basesecurity.BaseSecurityManager; +import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.Constants; import org.olat.basesecurity.GroupRoles; -import org.olat.core.CoreSpringFactory; -import org.olat.core.commons.persistence.PersistenceHelper; import org.olat.core.commons.services.notifications.NotificationHelper; import org.olat.core.commons.services.notifications.NotificationsHandler; import org.olat.core.commons.services.notifications.NotificationsManager; @@ -60,6 +59,7 @@ import org.olat.course.CourseFactory; import org.olat.course.CourseModule; import org.olat.course.ICourse; import org.olat.course.Structure; +import org.olat.course.assessment.AssessmentHelper; import org.olat.course.groupsandrights.CourseGroupManager; import org.olat.course.groupsandrights.CourseRights; import org.olat.course.nodes.AssessableCourseNode; @@ -67,13 +67,14 @@ import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.CourseNodeFactory; import org.olat.course.nodes.STCourseNode; import org.olat.course.nodes.ScormCourseNode; -import org.olat.course.properties.CoursePropertyManager; -import org.olat.course.run.environment.CourseEnvironment; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.manager.AssessmentEntryDAO; import org.olat.modules.scorm.assessment.ScormAssessmentManager; -import org.olat.properties.Property; import org.olat.repository.RepositoryManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; /** * Description:<br> @@ -84,26 +85,23 @@ import org.olat.repository.RepositoryManager; * * @author Roberto Bagnoli */ +@Service public class AssessmentNotificationsHandler implements NotificationsHandler { private static final OLog log = Tracing.createLoggerFor(AssessmentNotificationsHandler.class); private static final String CSS_CLASS_USER_ICON = "o_icon_user"; - private static AssessmentNotificationsHandler INSTANCE; - private Map<Long,SubscriptionContext> subsContexts = new HashMap<Long,SubscriptionContext>(); - /** - * Don't use this! Always use the getInstance() method. This is only used once by Spring! - */ - public AssessmentNotificationsHandler() { - INSTANCE = this; - } + @Autowired + private BaseSecurity securityManager; + @Autowired + private RepositoryManager repositoryManager; + @Autowired + private NotificationsManager notificationsManager; + @Autowired + private BusinessGroupService businessGroupService; + @Autowired + private AssessmentEntryDAO courseNodeAssessmentDao; - /** - * @return the singleton instance - */ - public static AssessmentNotificationsHandler getInstance() { - return INSTANCE; - } /** * Returns the <code>SubscriptionContext</code> to use for assessment @@ -122,27 +120,18 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { * identity associated to the request is not allowed to be notified * @see #canSubscribeForAssessmentNotification(Identity, ICourse) */ - protected SubscriptionContext getAssessmentSubscriptionContext(Identity ident, ICourse course) { + public SubscriptionContext getAssessmentSubscriptionContext(Identity ident, ICourse course) { SubscriptionContext sctx = null; - if (ident == null || canSubscribeForAssessmentNotification(ident, course)) { // Creates a new SubscriptionContext only if not found into cache - Long courseId = course.getResourceableId(); - synchronized (subsContexts) { //o_clusterOK by:ld - no problem to have independent subsContexts caches for each cluster node - sctx = subsContexts.get(courseId); - if (sctx == null) { - // a subscription context showing to the root node (the course's root - // node is started when clicking such a notification) - CourseNode cn = course.getRunStructure().getRootNode(); - CourseEnvironment ce = course.getCourseEnvironment(); - //FIXME:fg:b little problem is that the assessment tool and the course are not "the same" anymore, that is you can open the same course twice in the - // dynamic tabs by a) klicking e.g. via repo, and b via notifications link to the assementtool - sctx = new SubscriptionContext(CourseModule.ORES_COURSE_ASSESSMENT, ce.getCourseResourceableId(), cn.getIdent()); - subsContexts.put(courseId, sctx); - } + if (sctx == null) { + // a subscription context showing to the root node (the course's root + // node is started when clicking such a notification) + CourseNode cn = course.getRunStructure().getRootNode(); + Long resourceableId = course.getResourceableId(); + sctx = new SubscriptionContext(CourseModule.ORES_COURSE_ASSESSMENT, resourceableId, cn.getIdent()); } } - return sctx; } @@ -208,7 +197,7 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { private void markPublisherNews(Identity ident, ICourse course) { SubscriptionContext subsContext = getAssessmentSubscriptionContext(course); if (subsContext != null) { - NotificationsManager.getInstance().markPublisherNews(subsContext, ident, true); + notificationsManager.markPublisherNews(subsContext, ident, true); } } @@ -233,7 +222,7 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { CourseGroupManager grpMan = course.getCourseEnvironment().getCourseGroupManager(); - boolean isInstitutionalResourceManager = BaseSecurityManager.getInstance().isIdentityInSecurityGroup(ident, BaseSecurityManager.getInstance().findSecurityGroupByName(Constants.GROUP_INST_ORES_MANAGER)); + boolean isInstitutionalResourceManager = securityManager.isIdentityInSecurityGroup(ident, securityManager.findSecurityGroupByName(Constants.GROUP_INST_ORES_MANAGER)); return isInstitutionalResourceManager || grpMan.isIdentityCourseAdministrator(ident) || grpMan.isIdentityCourseCoach(ident) || grpMan.hasRight(ident, CourseRights.RIGHT_ASSESSMENT); } @@ -307,8 +296,8 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { Publisher p = subscriber.getPublisher(); if(!NotificationsUpgradeHelper.checkCourse(p)) { //course don't exist anymore - NotificationsManager.getInstance().deactivate(p); - return NotificationsManager.getInstance().getNoSubscriptionInfo(); + notificationsManager.deactivate(p); + return notificationsManager.getNoSubscriptionInfo(); } try { @@ -318,7 +307,7 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { // do not try to create a subscription info if state is deleted - results in // exceptions, course // can't be loaded when already deleted - if (NotificationsManager.getInstance().isPublisherValid(p) && compareDate.before(latestNews)) { + if (notificationsManager.isPublisherValid(p) && compareDate.before(latestNews)) { Long courseId = new Long(p.getData()); final ICourse course = loadCourseFromId(courseId); if (course != null) { @@ -327,37 +316,23 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager(); final boolean hasFullAccess = (cgm.isIdentityCourseAdministrator(identity) ? true : cgm.hasRight(identity, CourseRights.RIGHT_ASSESSMENT)); - final List<Identity> coachedUsers = new ArrayList<Identity>(); + final Set<Identity> coachedUsers = new HashSet<Identity>(); if (!hasFullAccess) { // initialize list of users, only when user has not full access List<BusinessGroup> coachedGroups = cgm.getOwnedBusinessGroups(identity); - BusinessGroupService businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class); List<Identity> coachedIdentites = businessGroupService.getMembers(coachedGroups, GroupRoles.participant.name()); coachedUsers.addAll(coachedIdentites); } List<AssessableCourseNode> testNodes = getCourseTestNodes(course); Translator translator = Util.createPackageTranslator(AssessmentNotificationsHandler.class, locale); - - for (AssessableCourseNode test:testNodes) { - final CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager(); - - List<Property> scoreProperties = cpm.listCourseNodeProperties(test, null, null, AssessmentManager.SCORE); - List<Property> attemptProperties = cpm.listCourseNodeProperties(test, null, null, AssessmentManager.ATTEMPTS); - - for(Property attemptProperty:attemptProperties) { - Date modDate = attemptProperty.getLastModified(); - Identity assessedIdentity = attemptProperty.getIdentity(); - if (modDate.after(compareDate) && (hasFullAccess || PersistenceHelper.listContainsObjectByKey(coachedUsers, assessedIdentity))) { - String score = null; - for(Property scoreProperty:scoreProperties) { - if(scoreProperty.getIdentity().equalsByPersistableKey(assessedIdentity) ) { - score = scoreProperty.getFloatValue().toString(); - break; - } - } - + List<AssessmentEntry> assessments = courseNodeAssessmentDao.loadAssessmentEntryBySubIdent(cgm.getCourseEntry(), test.getIdent()); + for(AssessmentEntry assessment:assessments) { + Date modDate = assessment.getLastModified(); + Identity assessedIdentity = assessment.getIdentity(); + if (modDate.after(compareDate) && (hasFullAccess || coachedUsers.contains(assessedIdentity))) { + BigDecimal score = assessment.getScore(); if(test instanceof ScormCourseNode) { ScormCourseNode scormTest = (ScormCourseNode)test; //check if completed or passed @@ -373,8 +348,9 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { desc = translator.translate("notifications.entry.attempt", new String[] { test.getShortTitle(), NotificationHelper.getFormatedName(assessedIdentity), type }); } else { + String scoreStr =AssessmentHelper.getRoundedScore(score); desc = translator.translate("notifications.entry", new String[] { test.getShortTitle(), - NotificationHelper.getFormatedName(assessedIdentity), score, type }); + NotificationHelper.getFormatedName(assessedIdentity), scoreStr, type }); } String urlToSend = null; @@ -397,13 +373,13 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { } } if(si == null) { - si = NotificationsManager.getInstance().getNoSubscriptionInfo(); + si = notificationsManager.getNoSubscriptionInfo(); } return si; } catch (Exception e) { log.error("Error while creating assessment notifications", e); checkPublisher(p); - return NotificationsManager.getInstance().getNoSubscriptionInfo(); + return notificationsManager.getNoSubscriptionInfo(); } } @@ -411,7 +387,7 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { try { if(!NotificationsUpgradeHelper.checkCourse(p)) { log.info("deactivating publisher with key; " + p.getKey(), null); - NotificationsManager.getInstance().deactivate(p); + notificationsManager.deactivate(p); } } catch (Exception e) { log.error("", e); @@ -422,10 +398,9 @@ public class AssessmentNotificationsHandler implements NotificationsHandler { public String createTitleInfo(Subscriber subscriber, Locale locale) { try { Long resId = subscriber.getPublisher().getResId(); - String displayName = RepositoryManager.getInstance().lookupDisplayNameByOLATResourceableId(resId); + String displayName = repositoryManager.lookupDisplayNameByOLATResourceableId(resId); Translator trans = Util.createPackageTranslator(AssessmentNotificationsHandler.class, locale); - String title = trans.translate("notifications.title", new String[]{ displayName }); - return title; + return trans.translate("notifications.title", new String[]{ displayName }); } catch (Exception e) { log.error("Error while creating assessment notifications for subscriber: " + subscriber.getKey(), e); checkPublisher(subscriber.getPublisher()); diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..a17ee2c257484454d31f8e520854b6eef62c330b --- /dev/null +++ b/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java @@ -0,0 +1,73 @@ +/** + * <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.course.assessment.manager; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.olat.basesecurity.GroupRoles; +import org.olat.basesecurity.IdentityImpl; +import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; +import org.olat.course.assessment.AssessmentToolManager; +import org.olat.course.assessment.model.AssessedIdentityWithCertificate; +import org.olat.course.assessment.model.SearchAssessedIdentityParams; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * Work with the datas for the assessment tool + * + * + * Initial date: 21.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class AssessmentToolManagerImpl implements AssessmentToolManager{ + + @Autowired + private DB dbInstance; + + @Override + public List<Identity> getAssessedIdentityWithCertificates(SearchAssessedIdentityParams params) { + StringBuilder sb = new StringBuilder(); + sb.append("select ident") + .append(" from ").append(IdentityImpl.class.getName()).append(" as ident ") + .append(" where exists (") + .append(" select infos from usercourseinfos infos where infos.identity=ident") + .append(" and infos.resource.key=:resourceKey") + .append(" ) or exists (select rel from repoentrytogroup as rel, bgroup as baseGroup, bgroupmember as membership") + .append(" where rel.entry.key=:courseEntryKey and rel.group=baseGroup and membership.group=baseGroup and membership.identity=ident") + .append(" and membership.role='").append(GroupRoles.participant.name()).append("'") + .append(" )"); + + List<Identity> list = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Identity.class) + .setParameter("courseEntryKey", params.getCourseEntry().getKey()) + .setParameter("resourceKey", params.getCourseEntry().getOlatResource().getKey()) + .getResultList(); + return list; + } + + + +} diff --git a/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..2dc48da9ec9a12300b7b085bbf25e8f76ceb030f --- /dev/null +++ b/src/main/java/org/olat/course/assessment/manager/CourseAssessmentManagerImpl.java @@ -0,0 +1,340 @@ +/** + * <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.course.assessment.manager; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.id.Identity; +import org.olat.core.id.OLATResourceable; +import org.olat.core.logging.activity.StringResourceableType; +import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; +import org.olat.core.util.StringHelper; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.event.GenericEventListener; +import org.olat.core.util.mail.MailerResult; +import org.olat.core.util.resource.OresHelper; +import org.olat.course.CourseFactory; +import org.olat.course.ICourse; +import org.olat.course.assessment.AssessmentChangedEvent; +import org.olat.course.assessment.AssessmentLoggingAction; +import org.olat.course.assessment.AssessmentManager; +import org.olat.course.assessment.EfficiencyStatementManager; +import org.olat.course.auditing.UserNodeAuditManager; +import org.olat.course.certificate.CertificateTemplate; +import org.olat.course.certificate.CertificatesManager; +import org.olat.course.certificate.model.CertificateInfos; +import org.olat.course.nodes.AssessableCourseNode; +import org.olat.course.nodes.CourseNode; +import org.olat.course.run.scoring.ScoreEvaluation; +import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.manager.AssessmentEntryDAO; +import org.olat.repository.RepositoryEntry; +import org.olat.util.logging.activity.LoggingResourceable; + +/** + * + * Initial date: 20.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CourseAssessmentManagerImpl implements AssessmentManager { + + private static final Float FLOAT_ZERO = new Float(0); + private static final Integer INTEGER_ZERO = new Integer(0); + + private final RepositoryEntry courseEntry; + private final CertificatesManager certificatesManager; + private final AssessmentEntryDAO courseNodeAssessmentDao; + private final EfficiencyStatementManager efficiencyStatementManager; + + public CourseAssessmentManagerImpl(RepositoryEntry courseEntry) { + this.courseEntry = courseEntry; + certificatesManager = CoreSpringFactory.getImpl(CertificatesManager.class); + courseNodeAssessmentDao = CoreSpringFactory.getImpl(AssessmentEntryDAO.class); + efficiencyStatementManager = CoreSpringFactory.getImpl(EfficiencyStatementManager.class); + } + + private AssessmentEntry getOrCreate(Identity assessedIdentity, CourseNode courseNode) { + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(assessedIdentity, courseEntry, courseNode.getIdent()); + if(nodeAssessment == null) { + nodeAssessment = courseNodeAssessmentDao + .createCourseNodeAssessment(assessedIdentity, courseEntry, + courseNode.getIdent(), courseNode.getReferencedRepositoryEntry()); + } + return nodeAssessment; + } + + @Override + public List<AssessmentEntry> getAssessmentData(CourseNode courseNode) { + return courseNodeAssessmentDao.loadAssessmentEntryBySubIdent(courseEntry, courseNode.getIdent()); + } + + @Override + public void saveNodeAttempts(CourseNode courseNode, Identity identity, Identity assessedIdentity, Integer attempts) { + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + + AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); + nodeAssessment.setAttempts(attempts); + courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + + //node log + UserNodeAuditManager am = course.getCourseEnvironment().getAuditManager(); + am.appendToUserNodeLog(courseNode, identity, assessedIdentity, "ATTEMPTS set to: " + String.valueOf(attempts)); + + // notify about changes + AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_ATTEMPTS_CHANGED, assessedIdentity); + CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, course); + + // user activity logging + ThreadLocalUserActivityLogger.log(AssessmentLoggingAction.ASSESSMENT_ATTEMPTS_UPDATED, + getClass(), + LoggingResourceable.wrap(assessedIdentity), + LoggingResourceable.wrapNonOlatResource(StringResourceableType.qtiAttempts, "", String.valueOf(attempts))); + } + + @Override + public void saveNodeComment(CourseNode courseNode, Identity identity, Identity assessedIdentity, String comment) { + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + + AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); + nodeAssessment.setComment(comment); + courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + + // node log + UserNodeAuditManager am = course.getCourseEnvironment().getAuditManager(); + am.appendToUserNodeLog(courseNode, identity, assessedIdentity, "COMMENT set to: " + comment); + + // notify about changes + AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_USER_COMMENT_CHANGED, assessedIdentity); + CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, course); + + // user activity logging + ThreadLocalUserActivityLogger.log(AssessmentLoggingAction.ASSESSMENT_USERCOMMENT_UPDATED, + getClass(), + LoggingResourceable.wrap(assessedIdentity), + LoggingResourceable.wrapNonOlatResource(StringResourceableType.qtiUserComment, "", StringHelper.stripLineBreaks(comment))); + } + + @Override + public void saveNodeCoachComment(CourseNode courseNode, Identity assessedIdentity, String comment) { + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + + AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); + nodeAssessment.setCoachComment(comment); + courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + + // notify about changes + AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_COACH_COMMENT_CHANGED, assessedIdentity); + CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, course); + + // user activity logging + ThreadLocalUserActivityLogger.log(AssessmentLoggingAction.ASSESSMENT_COACHCOMMENT_UPDATED, + getClass(), + LoggingResourceable.wrap(assessedIdentity), + LoggingResourceable.wrapNonOlatResource(StringResourceableType.qtiCoachComment, "", StringHelper.stripLineBreaks(comment))); + } + + @Override + public void incrementNodeAttempts(CourseNode courseNode, Identity assessedIdentity, UserCourseEnvironment userCourseEnv) { + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + + AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); + int attempts = nodeAssessment.getAttempts() == null ? 1 :nodeAssessment.getAttempts().intValue() + 1; + nodeAssessment.setAttempts(attempts); + courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + if(courseNode instanceof AssessableCourseNode) { + // Update users efficiency statement + efficiencyStatementManager.updateUserEfficiencyStatement(userCourseEnv); + } + + // notify about changes + AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_ATTEMPTS_CHANGED, assessedIdentity); + CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, course); + + // user activity logging + ThreadLocalUserActivityLogger.log(AssessmentLoggingAction.ASSESSMENT_ATTEMPTS_UPDATED, + getClass(), + LoggingResourceable.wrap(assessedIdentity), + LoggingResourceable.wrapNonOlatResource(StringResourceableType.qtiAttempts, "", String.valueOf(attempts))); + } + + @Override + public void incrementNodeAttemptsInBackground(CourseNode courseNode, Identity assessedIdentity, UserCourseEnvironment userCourseEnv) { + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + + AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); + int attempts = nodeAssessment.getAttempts() == null ? 1 :nodeAssessment.getAttempts().intValue() + 1; + nodeAssessment.setAttempts(attempts); + courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + if(courseNode instanceof AssessableCourseNode) { + // Update users efficiency statement + efficiencyStatementManager.updateUserEfficiencyStatement(userCourseEnv); + } + + // notify about changes + AssessmentChangedEvent ace = new AssessmentChangedEvent(AssessmentChangedEvent.TYPE_ATTEMPTS_CHANGED, assessedIdentity); + CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(ace, course); + } + + @Override + public void saveScoreEvaluation(CourseNode courseNode, Identity identity, Identity assessedIdentity, + ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnv, + boolean incrementUserAttempts) { + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + + Float score = scoreEvaluation.getScore(); + Boolean passed = scoreEvaluation.getPassed(); + Long assessmentId = scoreEvaluation.getAssessmentID(); + + AssessmentEntry nodeAssessment = getOrCreate(assessedIdentity, courseNode); + if(score == null) { + nodeAssessment.setScore(null); + } else { + nodeAssessment.setScore(new BigDecimal(Float.toString(score))); + } + nodeAssessment.setPassed(passed); + nodeAssessment.setFullyAssessed(scoreEvaluation.getFullyAssessed()); + nodeAssessment.setAssessmentId(assessmentId); + if(incrementUserAttempts) { + int attempts = nodeAssessment.getAttempts() == null ? 1 :nodeAssessment.getAttempts().intValue() + 1; + nodeAssessment.setAttempts(attempts); + } + nodeAssessment = courseNodeAssessmentDao.updateCourseNodeAssessment(nodeAssessment); + + + if(courseNode instanceof AssessableCourseNode) { + // Update users efficiency statement + efficiencyStatementManager.updateUserEfficiencyStatement(userCourseEnv); + } + + if(passed != null && passed.booleanValue() && course.getCourseConfig().isAutomaticCertificationEnabled()) { + if(certificatesManager.isRecertificationAllowed(assessedIdentity, courseEntry)) { + CertificateTemplate template = null; + Long templateId = course.getCourseConfig().getCertificateTemplate(); + if(templateId != null) { + template = certificatesManager.getTemplateById(templateId); + } + CertificateInfos certificateInfos = new CertificateInfos(assessedIdentity, score, passed); + MailerResult result = new MailerResult(); + certificatesManager.generateCertificate(certificateInfos, courseEntry, template, result); + } + } + } + + @Override + public Float getNodeScore(CourseNode courseNode, Identity identity) { + if (courseNode == null) { + return FLOAT_ZERO; // return default value + } + + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + if(nodeAssessment != null && nodeAssessment.getScore() != null) { + return nodeAssessment.getScore().floatValue(); + } + return FLOAT_ZERO; + } + + @Override + public String getNodeComment(CourseNode courseNode, Identity identity) { + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + return nodeAssessment == null ? null : nodeAssessment.getComment(); + } + + @Override + public String getNodeCoachComment(CourseNode courseNode, Identity identity) { + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + return nodeAssessment == null ? null : nodeAssessment.getCoachComment(); + } + + @Override + public Boolean getNodePassed(CourseNode courseNode, Identity identity) { + if (courseNode == null) { + return Boolean.FALSE; // return default value + } + + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + return nodeAssessment == null ? null : nodeAssessment.getPassed(); + } + + @Override + public Integer getNodeAttempts(CourseNode courseNode, Identity identity) { + if(courseNode == null) return INTEGER_ZERO; + + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + return nodeAssessment == null ? INTEGER_ZERO : nodeAssessment.getAttempts(); + } + + @Override + public Long getAssessmentID(CourseNode courseNode, Identity identity) { + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + return nodeAssessment == null ? null : nodeAssessment.getAssessmentId(); + } + + @Override + public Date getScoreLastModifiedDate(CourseNode courseNode, Identity identity) { + if(courseNode == null) return null; + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + return nodeAssessment == null ? null : nodeAssessment.getLastModified(); + } + + @Override + public Boolean getNodeFullyAssessed(CourseNode courseNode, Identity identity) { + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(identity, courseEntry, courseNode.getIdent()); + return nodeAssessment == null ? null : nodeAssessment.getFullyAssessed(); + } + + @Override + public OLATResourceable createOLATResourceableForLocking(Identity assessedIdentity) { + return OresHelper.createOLATResourceableInstance("AssessmentManager::Identity", assessedIdentity.getKey()); + } + + @Override + public void registerForAssessmentChangeEvents(GenericEventListener gel, Identity identity) { + CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(gel, identity, courseEntry.getOlatResource()); + } + + @Override + public void deregisterFromAssessmentChangeEvents(GenericEventListener gel) { + CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(gel, courseEntry.getOlatResource()); + } + + @Override + public void preloadCache(Identity identity) { + // + } + + @Override + public void preloadCache(List<Identity> identities) { + // + } +} diff --git a/src/main/java/org/olat/course/assessment/model/AssessedIdentityWithCertificate.java b/src/main/java/org/olat/course/assessment/model/AssessedIdentityWithCertificate.java new file mode 100644 index 0000000000000000000000000000000000000000..f85bbb43f571ecfd6e617e18428ae2fd4803dbf8 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/model/AssessedIdentityWithCertificate.java @@ -0,0 +1,56 @@ +/** + * <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.course.assessment.model; + +import org.olat.core.id.Identity; +import org.olat.course.certificate.CertificateLight; + +/** + * + * Initial date: 21.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessedIdentityWithCertificate { + + private Identity identity; + private CertificateLight certificate; + + public AssessedIdentityWithCertificate() { + // + } + + public AssessedIdentityWithCertificate(Identity identity, CertificateLight certificate) { + this.identity = identity; + this.certificate = certificate; + } + + public Identity getIdentity() { + return identity; + } + + public void setIdentity(Identity identity) { + this.identity = identity; + } + + public CertificateLight getCertificate() { + return certificate; + } +} diff --git a/src/main/java/org/olat/course/assessment/model/SearchAssessedIdentityParams.java b/src/main/java/org/olat/course/assessment/model/SearchAssessedIdentityParams.java new file mode 100644 index 0000000000000000000000000000000000000000..3370dd4cba1dc3a819f14e7cda076918896797be --- /dev/null +++ b/src/main/java/org/olat/course/assessment/model/SearchAssessedIdentityParams.java @@ -0,0 +1,66 @@ +/** + * <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.course.assessment.model; + +import java.util.List; + +import org.olat.group.BusinessGroupRef; +import org.olat.repository.RepositoryEntry; + +/** + * + * Initial date: 21.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class SearchAssessedIdentityParams { + + private final RepositoryEntry courseEntry; + private boolean withCertificates; + private List<? extends BusinessGroupRef> businessGroups; + + public SearchAssessedIdentityParams(RepositoryEntry courseEntry) { + this.courseEntry = courseEntry; + } + + public RepositoryEntry getCourseEntry() { + return courseEntry; + } + + + public List<? extends BusinessGroupRef> getBusinessGroups() { + return businessGroups; + } + + public void setBusinessGroups(List<? extends BusinessGroupRef> businessGroups) { + this.businessGroups = businessGroups; + } + + public boolean isWithCertificates() { + return withCertificates; + } + + public void setWithCertificates(boolean withCertificates) { + this.withCertificates = withCertificates; + } + + + +} diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminController.java b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminController.java similarity index 97% rename from src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminController.java rename to src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminController.java index 66f61723515463e6cdf3dcc1c259ef64a5ccbd36..1e6f6a4f10efc5afc210906698465bbf5c505081 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminController.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminController.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminListController.java b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminListController.java similarity index 96% rename from src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminListController.java rename to src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminListController.java index 66b4b0534c8f1ebc5af645dd9e9c4319bbb15a19..20cd083d368a7b8826b9142a7e7590812a308620 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminListController.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminListController.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.List; @@ -38,7 +38,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; @@ -48,7 +47,7 @@ import org.olat.course.assessment.AssessmentMode; import org.olat.course.assessment.AssessmentModeCoordinationService; import org.olat.course.assessment.AssessmentModeManager; import org.olat.course.assessment.model.SearchAssessmentModeParams; -import org.olat.course.assessment.ui.AssessmentModeListModel.Cols; +import org.olat.course.assessment.ui.mode.AssessmentModeListModel.Cols; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; @@ -105,7 +104,7 @@ public class AssessmentModeAdminListController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.status.i18nKey(), Cols.status.ordinal(), true, Cols.status.name(), new ModeStatusCellRenderer())); FlexiCellRenderer renderer = new StaticFlexiCellRenderer("select", new TextFlexiCellRenderer()); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.course.i18nKey(), Cols.course.ordinal(), "select", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.course.i18nKey(), Cols.course.ordinal(), "select", true, Cols.course.name(), renderer)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.externalId.i18nKey(), Cols.externalId.ordinal(), true, Cols.externalId.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.externalRef.i18nKey(), Cols.externalRef.ordinal(), true, Cols.externalRef.name())); diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminSettingsController.java b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminSettingsController.java similarity index 98% rename from src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminSettingsController.java rename to src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminSettingsController.java index 7b604ae5501a6af2ed849c040ed836a622bef815..3ff922c4b17447aee9c45f217e3ee6efb9201135 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeAdminSettingsController.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeAdminSettingsController.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeEditController.java similarity index 99% rename from src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java rename to src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeEditController.java index a6f79530026ed821db3946802a85e8d9c7367717..c04e9e9ad1aa3f90e951c2fc3b1567a8c1f6ae1c 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeEditController.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.ArrayList; import java.util.Date; diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeGuardController.java b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeGuardController.java similarity index 99% rename from src/main/java/org/olat/course/assessment/ui/AssessmentModeGuardController.java rename to src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeGuardController.java index 992f391b5f3740aa6b42093e6d19d4d18fec1c3e..bb6bba6169e974c14862fb19c1888382e75bb6d6 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeGuardController.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeGuardController.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.ArrayList; import java.util.Date; diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListController.java similarity index 96% rename from src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java rename to src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListController.java index 42cef7938f59f8698bce6efd3ff7f4c6887f629a..67083d899b53ba0e6b7f8611f5d09e5e27e201ec 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListController.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.ArrayList; import java.util.List; @@ -37,7 +37,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.stack.PopEvent; import org.olat.core.gui.components.stack.TooledStackedPanel; @@ -55,7 +54,7 @@ import org.olat.course.assessment.AssessmentModeCoordinationService; import org.olat.course.assessment.AssessmentModeManager; import org.olat.course.assessment.AssessmentModeNotificationEvent; import org.olat.course.assessment.model.TransientAssessmentMode; -import org.olat.course.assessment.ui.AssessmentModeListModel.Cols; +import org.olat.course.assessment.ui.mode.AssessmentModeListModel.Cols; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; @@ -127,11 +126,11 @@ public class AssessmentModeListController extends FormBasicController implements true, Cols.followupTime.name(), new TimeCellRenderer(getTranslator()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.target.i18nKey(), Cols.target.ordinal(), true, Cols.target.name(), new TargetAudienceCellRenderer(getTranslator()))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("start", Cols.start.ordinal(), "start", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("start", Cols.start.ordinal(), "start", new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("start"), "start"), null))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("stop", Cols.stop.ordinal(), "stop", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("stop", Cols.stop.ordinal(), "stop", new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("stop"), "stop"), null))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit", translate("edit"), "edit")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("edit", translate("edit"), "edit")); model = new AssessmentModeListModel(columnsModel, getTranslator(), assessmentModeCoordinationService); tableEl = uifactory.addTableElement(getWindowControl(), "table", model, 20, false, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListModel.java b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListModel.java similarity index 99% rename from src/main/java/org/olat/course/assessment/ui/AssessmentModeListModel.java rename to src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListModel.java index b6fe0b6be18b1eb8360682dd5ccb387074ec2fda..4399978e62e767e9cc50876edba16e0b6ed75925 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListModel.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListModel.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListModelSort.java b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListModelSort.java similarity index 95% rename from src/main/java/org/olat/course/assessment/ui/AssessmentModeListModelSort.java rename to src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListModelSort.java index 1e30ade2a26e2c583f2a5f4ca20ce4b7884f4b2e..52b0de2ddfd04dd54facb59901cd18712bad54c0 100644 --- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListModelSort.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/AssessmentModeListModelSort.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.Collections; import java.util.Comparator; @@ -29,7 +29,7 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFl import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableModelDelegate; import org.olat.course.assessment.AssessmentMode; import org.olat.course.assessment.AssessmentMode.Status; -import org.olat.course.assessment.ui.AssessmentModeListModel.Cols; +import org.olat.course.assessment.ui.mode.AssessmentModeListModel.Cols; /** * diff --git a/src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.java b/src/main/java/org/olat/course/assessment/ui/mode/ChooseAssessmentModeEvent.java similarity index 97% rename from src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.java rename to src/main/java/org/olat/course/assessment/ui/mode/ChooseAssessmentModeEvent.java index bc39d2bf801b87d49f5804cee91df794981bda76..da2af55f78c4b812fd49518a3ec2a2f12ebe7b07 100644 --- a/src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/ChooseAssessmentModeEvent.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import org.olat.core.gui.control.Event; import org.olat.course.assessment.model.TransientAssessmentMode; diff --git a/src/main/java/org/olat/course/assessment/ui/ChooseElementsController.java b/src/main/java/org/olat/course/assessment/ui/mode/ChooseElementsController.java similarity index 98% rename from src/main/java/org/olat/course/assessment/ui/ChooseElementsController.java rename to src/main/java/org/olat/course/assessment/ui/mode/ChooseElementsController.java index 882f4cbe052b341cc94f88b9926449b6842bd388..52426a072469420d839d82f8765894ccb93d788e 100644 --- a/src/main/java/org/olat/course/assessment/ui/ChooseElementsController.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/ChooseElementsController.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/olat/course/assessment/ui/ChooseStartElementController.java b/src/main/java/org/olat/course/assessment/ui/mode/ChooseStartElementController.java similarity index 98% rename from src/main/java/org/olat/course/assessment/ui/ChooseStartElementController.java rename to src/main/java/org/olat/course/assessment/ui/mode/ChooseStartElementController.java index 7391a04c21afeedbdf4f102000070c3cadc2de47..9cfaacbe0c008185a6b33f08c555f9f5d1c6acc7 100644 --- a/src/main/java/org/olat/course/assessment/ui/ChooseStartElementController.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/ChooseStartElementController.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/olat/course/assessment/ui/CourseNodeSelectionTreeModel.java b/src/main/java/org/olat/course/assessment/ui/mode/CourseNodeSelectionTreeModel.java similarity index 97% rename from src/main/java/org/olat/course/assessment/ui/CourseNodeSelectionTreeModel.java rename to src/main/java/org/olat/course/assessment/ui/mode/CourseNodeSelectionTreeModel.java index b3ce1b3f80e87de76f2cfa4e0e8516fa57869e4a..23bd46203547959425e89b8f36477ebe3c1fc924 100644 --- a/src/main/java/org/olat/course/assessment/ui/CourseNodeSelectionTreeModel.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/CourseNodeSelectionTreeModel.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import org.olat.core.gui.components.tree.GenericTreeModel; import org.olat.core.gui.components.tree.GenericTreeNode; diff --git a/src/main/java/org/olat/course/assessment/ui/ModeStatusCellRenderer.java b/src/main/java/org/olat/course/assessment/ui/mode/ModeStatusCellRenderer.java similarity index 98% rename from src/main/java/org/olat/course/assessment/ui/ModeStatusCellRenderer.java rename to src/main/java/org/olat/course/assessment/ui/mode/ModeStatusCellRenderer.java index fe5f1ce4ade81f1ee96ceb9652568b0707792241..b0b2943106eb83a59fd1fbe8d11dd367f776b4df 100644 --- a/src/main/java/org/olat/course/assessment/ui/ModeStatusCellRenderer.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/ModeStatusCellRenderer.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import java.util.List; diff --git a/src/main/java/org/olat/course/assessment/ui/TargetAudienceCellRenderer.java b/src/main/java/org/olat/course/assessment/ui/mode/TargetAudienceCellRenderer.java similarity index 97% rename from src/main/java/org/olat/course/assessment/ui/TargetAudienceCellRenderer.java rename to src/main/java/org/olat/course/assessment/ui/mode/TargetAudienceCellRenderer.java index 91e970a14b9e13e81a83797d322a15beb4b859d3..6b535c3b7b3ebe6a8cf325d619f42711956f4ee7 100644 --- a/src/main/java/org/olat/course/assessment/ui/TargetAudienceCellRenderer.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/TargetAudienceCellRenderer.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent; diff --git a/src/main/java/org/olat/course/assessment/ui/TimeCellRenderer.java b/src/main/java/org/olat/course/assessment/ui/mode/TimeCellRenderer.java similarity index 97% rename from src/main/java/org/olat/course/assessment/ui/TimeCellRenderer.java rename to src/main/java/org/olat/course/assessment/ui/mode/TimeCellRenderer.java index d14e8195632262c56325094458787697b1fb9b82..6fedbdce2bc5a794010363735809f2f618a8db30 100644 --- a/src/main/java/org/olat/course/assessment/ui/TimeCellRenderer.java +++ b/src/main/java/org/olat/course/assessment/ui/mode/TimeCellRenderer.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment.ui; +package org.olat.course.assessment.ui.mode; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent; diff --git a/src/main/java/org/olat/course/assessment/ui/_content/admin.html b/src/main/java/org/olat/course/assessment/ui/mode/_content/admin.html similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_content/admin.html rename to src/main/java/org/olat/course/assessment/ui/mode/_content/admin.html diff --git a/src/main/java/org/olat/course/assessment/ui/_content/admin_search.html b/src/main/java/org/olat/course/assessment/ui/mode/_content/admin_search.html similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_content/admin_search.html rename to src/main/java/org/olat/course/assessment/ui/mode/_content/admin_search.html diff --git a/src/main/java/org/olat/course/assessment/ui/_content/choose_elements.html b/src/main/java/org/olat/course/assessment/ui/mode/_content/choose_elements.html similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_content/choose_elements.html rename to src/main/java/org/olat/course/assessment/ui/mode/_content/choose_elements.html diff --git a/src/main/java/org/olat/course/assessment/ui/_content/choose_groups.html b/src/main/java/org/olat/course/assessment/ui/mode/_content/choose_groups.html similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_content/choose_groups.html rename to src/main/java/org/olat/course/assessment/ui/mode/_content/choose_groups.html diff --git a/src/main/java/org/olat/course/assessment/ui/_content/choose_mode.html b/src/main/java/org/olat/course/assessment/ui/mode/_content/choose_mode.html similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_content/choose_mode.html rename to src/main/java/org/olat/course/assessment/ui/mode/_content/choose_mode.html diff --git a/src/main/java/org/olat/course/assessment/ui/_content/course_element.html b/src/main/java/org/olat/course/assessment/ui/mode/_content/course_element.html similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_content/course_element.html rename to src/main/java/org/olat/course/assessment/ui/mode/_content/course_element.html diff --git a/src/main/java/org/olat/course/assessment/ui/_content/course_elements.html b/src/main/java/org/olat/course/assessment/ui/mode/_content/course_elements.html similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_content/course_elements.html rename to src/main/java/org/olat/course/assessment/ui/mode/_content/course_elements.html diff --git a/src/main/java/org/olat/course/assessment/ui/_content/mode_list.html b/src/main/java/org/olat/course/assessment/ui/mode/_content/mode_list.html similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_content/mode_list.html rename to src/main/java/org/olat/course/assessment/ui/mode/_content/mode_list.html diff --git a/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/assessment/ui/mode/_i18n/LocalStrings_de.properties similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties rename to src/main/java/org/olat/course/assessment/ui/mode/_i18n/LocalStrings_de.properties diff --git a/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/assessment/ui/mode/_i18n/LocalStrings_en.properties similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_en.properties rename to src/main/java/org/olat/course/assessment/ui/mode/_i18n/LocalStrings_en.properties diff --git a/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/assessment/ui/mode/_i18n/LocalStrings_fr.properties similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_fr.properties rename to src/main/java/org/olat/course/assessment/ui/mode/_i18n/LocalStrings_fr.properties diff --git a/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/course/assessment/ui/mode/_i18n/LocalStrings_pt_BR.properties similarity index 100% rename from src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_pt_BR.properties rename to src/main/java/org/olat/course/assessment/ui/mode/_i18n/LocalStrings_pt_BR.properties diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityController.java new file mode 100644 index 0000000000000000000000000000000000000000..e1dee132bc920aef8cc5866159ce2f8ff2dd0f39 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityController.java @@ -0,0 +1,59 @@ +/** + * <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.course.assessment.ui.tool; + +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.control.Controller; +import org.olat.core.gui.control.WindowControl; + +/** + * + * Initial date: 22.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessedIdentityController extends FormBasicController { + + public AssessedIdentityController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + // + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + + +} diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityListController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityListController.java new file mode 100644 index 0000000000000000000000000000000000000000..4fbc651345f289c6d228950c025af73ce059b8a6 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityListController.java @@ -0,0 +1,281 @@ +/** + * <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.course.assessment.ui.tool; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.olat.basesecurity.BaseSecurity; +import org.olat.basesecurity.BaseSecurityModule; +import org.olat.core.commons.persistence.SortKey; +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.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.DefaultFlexiTableDataModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnDef; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel; +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.core.id.Identity; +import org.olat.core.util.Util; +import org.olat.core.util.coordinate.CoordinatorManager; +import org.olat.core.util.event.GenericEventListener; +import org.olat.course.CourseFactory; +import org.olat.course.ICourse; +import org.olat.course.assessment.AssessedIdentitiesTableDataModel; +import org.olat.course.assessment.AssessmentMainController; +import org.olat.course.assessment.AssessmentToolManager; +import org.olat.course.assessment.IAssessmentCallback; +import org.olat.course.assessment.IdentityAssessmentEditController; +import org.olat.course.assessment.model.SearchAssessedIdentityParams; +import org.olat.course.certificate.CertificateEvent; +import org.olat.course.certificate.CertificateLight; +import org.olat.course.certificate.CertificatesManager; +import org.olat.course.certificate.ui.DownloadCertificateCellRenderer; +import org.olat.repository.RepositoryEntry; +import org.olat.user.UserManager; +import org.olat.user.propertyhandlers.UserPropertyHandler; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 21.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessedIdentityListController extends FormBasicController implements GenericEventListener { + + public static final int USER_PROPS_OFFSET = 500; + public static final String usageIdentifyer = AssessedIdentitiesTableDataModel.usageIdentifyer; + + private FlexiTableElement tableEl; + private AssessedUserTableModel usersTableModel; + private final List<UserPropertyHandler> userPropertyHandlers; + private final TooledStackedPanel stackPanel; + + private RepositoryEntry courseEntry; + private final boolean isAdministrativeUser; + private final IAssessmentCallback assessmentCallback; + + @Autowired + private UserManager userManager; + @Autowired + private BaseSecurity securityManager; + @Autowired + private BaseSecurityModule securityModule; + @Autowired + private CertificatesManager certificatesManager; + @Autowired + private AssessmentToolManager assessmentToolManager; + + + public AssessedIdentityListController(UserRequest ureq, WindowControl wControl, + TooledStackedPanel stackPanel, RepositoryEntry courseEntry, IAssessmentCallback assessmentCallback) { + super(ureq, wControl, "identities"); + setTranslator(Util.createPackageTranslator(AssessmentMainController.class, getLocale(), getTranslator())); + setTranslator(userManager.getPropertyHandlerTranslator(getTranslator())); + + this.stackPanel = stackPanel; + this.courseEntry = courseEntry; + this.assessmentCallback = assessmentCallback; + isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles()); + userPropertyHandlers = UserManager.getInstance().getUserPropertyHandlersFor(usageIdentifyer, isAdministrativeUser); + + initForm(ureq); + updateModel(); + + // Register for assessment changed events + CoordinatorManager.getInstance().getCoordinator().getEventBus() + .registerFor(this, getIdentity(), CertificatesManager.ORES_CERTIFICATE_EVENT); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + //add the table + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(UserCols.username, "select")); + + int colIndex = USER_PROPS_OFFSET; + List<UserPropertyHandler> userPropertyHandlers = userManager.getUserPropertyHandlersFor(usageIdentifyer, isAdministrativeUser); + for (int i = 0; i < userPropertyHandlers.size(); i++) { + UserPropertyHandler userPropertyHandler = userPropertyHandlers.get(i); + boolean visible = UserManager.getInstance().isMandatoryUserProperty(usageIdentifyer , userPropertyHandler); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(visible, userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex++, "select", false, null)); + } + + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(UserCols.certificate, new DownloadCertificateCellRenderer())); + + usersTableModel = new AssessedUserTableModel(columnsModel); + tableEl = uifactory.addTableElement(getWindowControl(), "identities", usersTableModel, getTranslator(), formLayout); + tableEl.setExportEnabled(true); + } + + private void updateModel() { + SearchAssessedIdentityParams params = new SearchAssessedIdentityParams(courseEntry); + params.setWithCertificates(true); + List<Identity> assessedIdentities = assessmentToolManager.getAssessedIdentityWithCertificates(params); + List<AssessedIdentityRow> rows = new ArrayList<>(assessedIdentities.size()); + for(Identity assessedIdentity:assessedIdentities) { + rows.add(new AssessedIdentityRow(assessedIdentity, userPropertyHandlers, getLocale())); + } + usersTableModel.setObjects(rows); + + ConcurrentMap<Long, CertificateLight> certificates = new ConcurrentHashMap<>(); + List<CertificateLight> certificateList = certificatesManager.getLastCertificates(courseEntry.getOlatResource()); + for(CertificateLight certificate:certificateList) { + CertificateLight currentCertificate = certificates.get(certificate.getIdentityKey()); + if(currentCertificate == null || currentCertificate.getCreationDate().before(certificate.getCreationDate())) { + certificates.put(certificate.getIdentityKey(), certificate); + } + } + usersTableModel.setCertificates(certificates); + } + + private void updateCertificate(Long certificateKey) { + CertificateLight certificate = certificatesManager.getCertificateLightById(certificateKey); + usersTableModel.putCertificate(certificate); + tableEl.getComponent().setDirty(true); + } + + @Override + protected void doDispose() { + // + } + + @Override + public void event(Event event) { + if(event instanceof CertificateEvent) { + CertificateEvent ce = (CertificateEvent)event; + if(courseEntry.getOlatResource().getKey().equals(ce.getResourceKey())) { + updateCertificate(ce.getCertificateKey()); + } + } + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(tableEl == source) { + if(event instanceof SelectionEvent) { + SelectionEvent se = (SelectionEvent)event; + String cmd = se.getCommand(); + AssessedIdentityRow selectedRow = usersTableModel.getObject(se.getIndex()); + if("select".equals(cmd)) { + doSelectUser(ureq, selectedRow); + } + } + } else if(source instanceof FormLink) { + FormLink link = (FormLink)source; + if("download-cert".equals(link.getCmd())) { + + } + } + super.formInnerEvent(ureq, source, event); + } + + private void doSelectUser(UserRequest ureq, AssessedIdentityRow row) { + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + Identity assessedIdentity = securityManager.loadIdentityByKey(row.getIdentityKey()); + IdentityAssessmentEditController userController = new IdentityAssessmentEditController(getWindowControl(), ureq, + stackPanel, assessedIdentity, course, true, false, true); + listenTo(userController); + String fullname = userManager.getUserDisplayName(assessedIdentity); + stackPanel.pushController(fullname, userController); + } + + public static class AssessedUserTableModel extends DefaultFlexiTableDataModel<AssessedIdentityRow> implements SortableFlexiTableDataModel<AssessedIdentityRow> { + + private ConcurrentMap<Long, CertificateLight> certificates; + + public AssessedUserTableModel(FlexiTableColumnModel columnModel) { + super(columnModel); + } + + public void setCertificates(ConcurrentMap<Long, CertificateLight> certificates) { + this.certificates = certificates; + } + + public void putCertificate(CertificateLight certificate) { + if(certificates != null) { + certificates.put(certificate.getIdentityKey(), certificate); + } + } + + @Override + public void sort(SortKey sortKey) { + // + } + + @Override + public Object getValueAt(int row, int col) { + AssessedIdentityRow identityRow = getObject(row); + return getValueAt(identityRow, col); + } + + @Override + public Object getValueAt(AssessedIdentityRow row, int col) { + if(col >= 0 && col < UserCols.values().length) { + switch(UserCols.values()[col]) { + case username: return row.getIdentityName(); + case certificate: return certificates.get(row.getIdentityKey()); + } + } + int propPos = col - USER_PROPS_OFFSET; + return row.getIdentityProp(propPos); + } + + @Override + public DefaultFlexiTableDataModel<AssessedIdentityRow> createCopyWithEmptyList() { + return new AssessedUserTableModel(getTableColumnModel()); + } + } + + public enum UserCols implements FlexiColumnDef { + + username("table.header.name"), + certificate("table.header.certificate"); + + private final String i18nKey; + + private UserCols(String i18nKey) { + this.i18nKey = i18nKey; + } + + public String i18nHeaderKey() { + return i18nKey; + } + } +} diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityRow.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityRow.java new file mode 100644 index 0000000000000000000000000000000000000000..ea7aa45ea18a418f06e204f460d6fc29dd0b2394 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessedIdentityRow.java @@ -0,0 +1,44 @@ +/** + * <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.course.assessment.ui.tool; + +import java.util.List; +import java.util.Locale; + +import org.olat.core.id.Identity; +import org.olat.user.UserPropertiesRow; +import org.olat.user.propertyhandlers.UserPropertyHandler; + +/** + * + * Initial date: 21.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessedIdentityRow extends UserPropertiesRow { + + + public AssessedIdentityRow(Identity identity, List<UserPropertyHandler> userPropertyHandlers, Locale locale) { + super(identity, userPropertyHandlers, locale); + } + + + +} diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentOverviewController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentOverviewController.java new file mode 100644 index 0000000000000000000000000000000000000000..6a011297e6a61887f1d359137592aa4ef406d30d --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentOverviewController.java @@ -0,0 +1,173 @@ +/** + * <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.course.assessment.ui.tool; + +import java.util.List; + +import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.panel.Panel; +import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.components.tree.GenericTreeModel; +import org.olat.core.gui.components.tree.GenericTreeNode; +import org.olat.core.gui.components.tree.MenuTree; +import org.olat.core.gui.components.tree.TreeModel; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.MainLayoutBasicController; +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.core.util.Util; +import org.olat.course.CourseFactory; +import org.olat.course.ICourse; +import org.olat.course.assessment.AssessmentMainController; +import org.olat.course.assessment.IAssessmentCallback; +import org.olat.repository.RepositoryEntry; + +/** + * + * Initial date: 21.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessmentOverviewController extends MainLayoutBasicController implements Activateable2 { + + private MenuTree menuTree; + private final Panel mainPanel; + private TooledStackedPanel stackPanel; + + private boolean hasAssessableNodes; + private RepositoryEntry courseEntry; + private IAssessmentCallback assessmentCallback; + + public AssessmentOverviewController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, + RepositoryEntry courseEntry, IAssessmentCallback assessmentCallback) { + super(ureq, wControl); + setTranslator(Util.createPackageTranslator(AssessmentMainController.class, getLocale(), getTranslator())); + this.courseEntry = courseEntry; + this.stackPanel = stackPanel; + this.assessmentCallback = assessmentCallback; + + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + + hasAssessableNodes = course.hasAssessableNodes(); + boolean hasCertificates = course.getCourseConfig().isAutomaticCertificationEnabled() + || course.getCourseConfig().isManualCertificationEnabled(); + + mainPanel = new Panel("assessmentToolv2"); + + // Navigation menu + menuTree = new MenuTree("menuTree"); + TreeModel tm = buildTreeModel(hasAssessableNodes, hasCertificates); + menuTree.setTreeModel(tm); + menuTree.setSelectedNodeId(tm.getRootNode().getIdent()); + menuTree.addListener(this); + + LayoutMain3ColsController columLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), menuTree, mainPanel, "course" + course.getResourceableId()); + listenTo(columLayoutCtr); // cleanup on dispose + putInitialPanel(columLayoutCtr.getInitialComponent()); + } + + private TreeModel buildTreeModel(boolean assessableNodes, boolean certificate) { + GenericTreeNode root, gtn; + + GenericTreeModel gtm = new GenericTreeModel(); + root = new GenericTreeNode(); + root.setTitle(translate("menu.index")); + root.setUserObject("index"); + root.setAltText(translate("menu.index.alt")); + gtm.setRootNode(root); + + // show real menu only when there are some assessable nodes + /* + if (assessableNodes) { + gtn = new GenericTreeNode(); + gtn.setTitle(translate("menu.groupfocus")); + gtn.setUserObject("groups"); + gtn.setAltText(translate("menu.groupfocus.alt")); + gtn.setCssClass("o_sel_assessment_tool_groups"); + root.addChild(gtn); + + gtn = new GenericTreeNode(); + gtn.setTitle(translate("menu.nodefocus")); + gtn.setUserObject("courseNodes"); + gtn.setAltText(translate("menu.nodefocus.alt")); + gtn.setCssClass("o_sel_assessment_tool_nodes"); + root.addChild(gtn); + } + */ + + if (assessableNodes || certificate) { + gtn = new GenericTreeNode(); + gtn.setTitle(translate("menu.userfocus")); + gtn.setUserObject("users"); + gtn.setAltText(translate("menu.userfocus.alt")); + gtn.setCssClass("o_sel_assessment_tool_users"); + root.addChild(gtn); + } + + return gtm; + } + + @Override + protected void doDispose() { + // + } + + @Override + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if (source == menuTree) { + if (event.getCommand().equals(MenuTree.COMMAND_TREENODE_CLICKED)) { + Object uo = menuTree.getSelectedNode().getUserObject(); + if("groups".equals(uo)) { + doSelectGroupView(); + } else if("courseNodes".equals(uo)) { + doSelectCourseNodesView(); + } else if("users".equals(uo)) { + doSelectUsersView(ureq); + } + } + } + } + + private void doSelectGroupView() { + + } + + private void doSelectCourseNodesView() { + + } + + private void doSelectUsersView(UserRequest ureq) { + AssessedIdentityListController listController = new AssessedIdentityListController(ureq, getWindowControl(), stackPanel, + courseEntry, assessmentCallback); + listenTo(listController); + mainPanel.setContent(listController.getInitialComponent()); + } + + +} diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_content/identities.html b/src/main/java/org/olat/course/assessment/ui/tool/_content/identities.html new file mode 100644 index 0000000000000000000000000000000000000000..42a472edfd4b53b23f921ce1e1734d813c08e393 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/_content/identities.html @@ -0,0 +1 @@ +$r.render("identities") \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_content/overview.html b/src/main/java/org/olat/course/assessment/ui/tool/_content/overview.html new file mode 100644 index 0000000000000000000000000000000000000000..3b2634d5414ce45796a9da01b6f1fde618d9e34a --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/_content/overview.html @@ -0,0 +1 @@ +<h1>Hello</h1> \ No newline at end of file diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties new file mode 100644 index 0000000000000000000000000000000000000000..88cd94609c457d55e0bd694399d70ada03acb762 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties @@ -0,0 +1 @@ +#Mon Mar 02 09:54:04 CET 2009 diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_en.properties new file mode 100644 index 0000000000000000000000000000000000000000..ec501f9f433fed1a8bde1ac9922be1c4d209298e --- /dev/null +++ b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_en.properties @@ -0,0 +1 @@ +#Fri Feb 06 10:03:07 CET 2015 diff --git a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java index 99a377a4b56cb533aac4bbe9a73df2eaee6ec964..baac00e0fda18fafca2f679aa5fb41dda92831e0 100644 --- a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java +++ b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.stack.BreadcrumbPanel; import org.olat.core.gui.components.stack.BreadcrumbPanelAware; @@ -176,20 +175,20 @@ public class CertificateAndEfficiencyStatementListController extends FormBasicCo tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.score.i18n(), Cols.score.ordinal())); tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.passed.i18n(), Cols.passed.ordinal(), new PassedCellRenderer())); - tableColumnModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.show", + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.show", translate("table.header.show"), CMD_SHOW)); tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.lastModified.i18n(), Cols.lastModified.ordinal())); tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.certificate.i18n(), Cols.certificate.ordinal(), new DownloadCertificateCellRenderer(assessedIdentity))); - tableColumnModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.launchcourse", + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.launchcourse", translate("table.header.launchcourse"), CMD_LAUNCH_COURSE)); - tableColumnModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.delete", + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.delete", translate("table.action.delete"), CMD_DELETE)); //delete EPArtefactHandler<?> artHandler = portfolioModule.getArtefactHandler(EfficiencyStatementArtefact.ARTEFACT_TYPE); if(portfolioModule.isEnabled() && artHandler != null && artHandler.isEnabled() && assessedIdentity.equals(getIdentity())) { - tableColumnModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.artefact", + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.artefact", Cols.efficiencyStatement.ordinal(), CMD_ARTEFACT, new StaticFlexiCellRenderer(CMD_ARTEFACT, new AsArtefactCellRenderer()))); } diff --git a/src/main/java/org/olat/course/certificate/ui/CertificatesAdminController.java b/src/main/java/org/olat/course/certificate/ui/CertificatesAdminController.java index 526ba9ac2a70b07b1bec293730115651ebad1172..32fe7d4f8bd906227124c998dea055667c2ea5aa 100644 --- a/src/main/java/org/olat/course/certificate/ui/CertificatesAdminController.java +++ b/src/main/java/org/olat/course/certificate/ui/CertificatesAdminController.java @@ -33,7 +33,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFle import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -75,8 +74,8 @@ public class CertificatesAdminController extends FormBasicController { FlexiTableColumnModel tableColumnModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal())); - tableColumnModel.addFlexiColumnModel(new StaticFlexiColumnModel("replace", translate("replace"), "replace")); - tableColumnModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", translate("delete"), "delete")); + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("replace", translate("replace"), "replace")); + tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", translate("delete"), "delete")); tableModel = new TemplatesDataModel(tableColumnModel); tableEl = uifactory.addTableElement(getWindowControl(), "templates", tableModel, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/certificate/ui/DownloadCertificateCellRenderer.java b/src/main/java/org/olat/course/certificate/ui/DownloadCertificateCellRenderer.java index 03477dcebe1b034ec214262a86ba2aaec7afbf0c..09c89054f9ff300e5e25d368e32c35d155e9b3de 100644 --- a/src/main/java/org/olat/course/certificate/ui/DownloadCertificateCellRenderer.java +++ b/src/main/java/org/olat/course/certificate/ui/DownloadCertificateCellRenderer.java @@ -21,6 +21,8 @@ package org.olat.course.certificate.ui; import java.util.Locale; +import org.olat.basesecurity.IdentityRef; +import org.olat.basesecurity.model.IdentityRefImpl; import org.olat.core.CoreSpringFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent; @@ -71,15 +73,20 @@ public class DownloadCertificateCellRenderer implements CustomCellRenderer, Flex public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source, URLBuilder ubu, Translator translator) { if(cellValue instanceof CertificateLight) { - render(target, (CertificateLight)cellValue, assessedIdentity, translator.getLocale()); + CertificateLight certificate = (CertificateLight)cellValue; + if(assessedIdentity == null) { + IdentityRef idRef = new IdentityRefImpl(certificate.getIdentityKey()); + render(target, certificate, idRef, translator.getLocale()); + } else { + render(target, certificate, assessedIdentity, translator.getLocale()); + } } else if(cellValue instanceof CertificateLightPack) { CertificateLightPack pack = (CertificateLightPack)cellValue; render(target, pack.getCertificate(), pack.getIdentity(), translator.getLocale()); } } - - private void render(StringOutput sb, CertificateLight certificate, Identity identity, Locale locale) { + private void render(StringOutput sb, CertificateLight certificate, IdentityRef identity, Locale locale) { String name = Formatter.getInstance(locale).formatDate(certificate.getCreationDate()); if(CertificateStatus.pending.equals(certificate.getStatus())) { sb.append("<span><i class='o_icon o_icon_pending o_icon-spin'> </i> ").append(name).append(".pdf").append("</span>"); @@ -101,7 +108,7 @@ public class DownloadCertificateCellRenderer implements CustomCellRenderer, Flex return finalName + ".pdf"; } - public static String getName(CertificateLight certificate, Identity identity) { + public static String getName(CertificateLight certificate, IdentityRef identity) { StringBuilder sb = new StringBuilder(100); String fullName = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(identity); String date = Formatter.formatShortDateFilesystem(certificate.getCreationDate()); @@ -110,7 +117,7 @@ public class DownloadCertificateCellRenderer implements CustomCellRenderer, Flex return finalName + ".pdf"; } - public static String getUrl(CertificateLight certificate, Identity identity) { + public static String getUrl(CertificateLight certificate, IdentityRef identity) { StringBuilder sb = new StringBuilder(100); sb.append(Settings.getServerContextPath()).append("/certificate/") .append(certificate.getUuid()).append("/").append(getName(certificate, identity)); diff --git a/src/main/java/org/olat/course/member/CourseBusinessGroupListController.java b/src/main/java/org/olat/course/member/CourseBusinessGroupListController.java index f9215f4b81994fa06c9c788446ce039b87db5877..2d7f8bd09c8f562e1fbaef524c185990b15e6bdf 100644 --- a/src/main/java/org/olat/course/member/CourseBusinessGroupListController.java +++ b/src/main/java/org/olat/course/member/CourseBusinessGroupListController.java @@ -35,7 +35,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; @@ -119,7 +118,7 @@ public class CourseBusinessGroupListController extends AbstractBusinessGroupList FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); //group name - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal(), TABLE_ACTION_LAUNCH, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal(), TABLE_ACTION_LAUNCH, true, Cols.name.name(), new StaticFlexiCellRenderer(TABLE_ACTION_LAUNCH, new BusinessGroupNameCellRenderer()))); //id and reference columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.key.i18n(), Cols.key.ordinal(), true, Cols.key.name())); @@ -146,10 +145,10 @@ public class CourseBusinessGroupListController extends AbstractBusinessGroupList columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.accessTypes.i18n(), Cols.accessTypes.ordinal(), true, Cols.accessTypes.name(), FlexiColumnModel.ALIGNMENT_LEFT, new BGAccessControlledCellRenderer())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.edit", translate("table.header.edit"), TABLE_ACTION_EDIT)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.edit", translate("table.header.edit"), TABLE_ACTION_EDIT)); if(!managed) { - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.remove", Cols.unlink.ordinal(), TABLE_ACTION_UNLINK, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.remove", Cols.unlink.ordinal(), TABLE_ACTION_UNLINK, new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("table.header.remove"), TABLE_ACTION_UNLINK), null))); } return columnsModel; diff --git a/src/main/java/org/olat/course/nodes/MSCourseNode.java b/src/main/java/org/olat/course/nodes/MSCourseNode.java index e9d698808d2ca14189fb71d345ce1b6523af914c..e106fde2c3a7f3801dd98085dc43a5bac309c331 100644 --- a/src/main/java/org/olat/course/nodes/MSCourseNode.java +++ b/src/main/java/org/olat/course/nodes/MSCourseNode.java @@ -441,11 +441,9 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Assess return tools; } - /** - * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListView(org.olat.course.run.userview.UserCourseEnvironment) - */ + @Override public String getDetailsListView(UserCourseEnvironment userCourseEnvironment) { - throw new OLATRuntimeException(MSCourseNode.class, "Details not available in MS nodes", null); + return null; } /** diff --git a/src/main/java/org/olat/course/nodes/STCourseNode.java b/src/main/java/org/olat/course/nodes/STCourseNode.java index 1dd4cc8b9f4a5e893ca9f3fd868d4e299d12cfc7..af2cd168fb9dec595f27ae4a2d1b0caef8e8def4 100644 --- a/src/main/java/org/olat/course/nodes/STCourseNode.java +++ b/src/main/java/org/olat/course/nodes/STCourseNode.java @@ -532,11 +532,9 @@ public class STCourseNode extends AbstractAccessableCourseNode implements Assess throw new OLATRuntimeException(STCourseNode.class, "Details controler not available in ST nodes", null); } - /** - * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListView(org.olat.course.run.userview.UserCourseEnvironment) - */ + @Override public String getDetailsListView(UserCourseEnvironment userCourseEnvironment) { - throw new OLATRuntimeException(STCourseNode.class, "Details not available in ST nodes", null); + return null; } /** diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java index b326bb7b12d19934998ef5fde66527e788c7271d..f32905a624d8eb882aa0e0d888c553ffd8f3e49b 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckListAssessmentController.java @@ -57,7 +57,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; @@ -214,7 +213,7 @@ public class CheckListAssessmentController extends FormBasicController implement FlexiColumnModel col; if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new StaticFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex, userPropertyHandler.getName(), true, propName, new StaticFlexiCellRenderer(userPropertyHandler.getName(), new TextFlexiCellRenderer())); } else { @@ -238,7 +237,7 @@ public class CheckListAssessmentController extends FormBasicController implement if(withScore) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.totalPoints.i18nKey(), Cols.totalPoints.ordinal(), true, "points")); } - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.edit.checkbox", translate("table.header.edit.checkbox"), "edit")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.edit.checkbox", translate("table.header.edit.checkbox"), "edit")); List<CheckListAssessmentRow> datas = loadDatas(); model = new CheckListAssessmentDataModel(checkboxList, datas, columnsModel); diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckListBoxListEditController.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckListBoxListEditController.java index e7660d4c389e8e94fb384dba08c84c1c150368ea..77ad3ef1824d76a065ff8df987084996214b762c 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckListBoxListEditController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckListBoxListEditController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -125,12 +124,12 @@ public class CheckListBoxListEditController extends FormBasicController { columnsModel.addFlexiColumnModel(pointColModel); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.release.i18nKey(), Cols.release.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.file.i18nKey(), Cols.file.ordinal())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit", translate("edit"), "edit")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("up", Cols.up.ordinal(), "up", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("edit", translate("edit"), "edit")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("up", Cols.up.ordinal(), "up", new BooleanCellRenderer( new StaticFlexiCellRenderer("", "up", "o_icon o_icon-lg o_icon_move_up", translate("up")), null))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("down", Cols.down.ordinal(), "down", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("down", Cols.down.ordinal(), "down", new BooleanCellRenderer( new StaticFlexiCellRenderer("", "down", "o_icon o_icon-lg o_icon_move_down", translate("down")), null))); diff --git a/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentController.java b/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentController.java index 48a780dfbfc59c76aa8fc3ad7848958e962dd83c..ff7a10886b2fd98f0e9cee82bca8f8d6f87d8828 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/CheckboxAssessmentController.java @@ -46,7 +46,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColum 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.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; @@ -150,7 +149,7 @@ public class CheckboxAssessmentController extends FormBasicController { FlexiColumnModel col; if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new StaticFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex, userPropertyHandler.getName(), true, propName, new StaticFlexiCellRenderer(userPropertyHandler.getName(), new TextFlexiCellRenderer())); } else { diff --git a/src/main/java/org/olat/course/nodes/cl/ui/wizard/CheckboxListStepController.java b/src/main/java/org/olat/course/nodes/cl/ui/wizard/CheckboxListStepController.java index d731f2bbcf317737636777ebfe294c0c5076e441..bbf52fc31d7359867ee100d217916d4542b0c60c 100644 --- a/src/main/java/org/olat/course/nodes/cl/ui/wizard/CheckboxListStepController.java +++ b/src/main/java/org/olat/course/nodes/cl/ui/wizard/CheckboxListStepController.java @@ -36,7 +36,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFle import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -99,7 +98,7 @@ public class CheckboxListStepController extends StepFormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.points.i18nKey(), Cols.points.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.release.i18nKey(), Cols.release.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.file.i18nKey(), Cols.file.ordinal())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit.checkbox", translate("edit.checkbox"), "edit")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("edit.checkbox", translate("edit.checkbox"), "edit")); model = new CheckboxConfigDataModel(getTranslator(), columnsModel); boxTable = uifactory.addTableElement(getWindowControl(), "checkbox-list", model, getTranslator(), tableCont); diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTAAssignmentEditController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTAAssignmentEditController.java index 898f5c98443593843c651367ff8200c2780d4416..b92e1e4ba0766dd13bc18821ada292bf113b231c 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/GTAAssignmentEditController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/GTAAssignmentEditController.java @@ -41,7 +41,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -143,11 +142,11 @@ public class GTAAssignmentEditController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TDCols.title.i18nKey(), TDCols.title.ordinal())); fileExistsRenderer = new WarningFlexiCellRenderer(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TDCols.file.i18nKey(), TDCols.file.ordinal(), fileExistsRenderer)); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.edit", TDCols.edit.ordinal(), "edit", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.edit", TDCols.edit.ordinal(), "edit", new BooleanCellRenderer( new StaticFlexiCellRenderer(translate("edit"), "edit"), new StaticFlexiCellRenderer(translate("replace"), "edit")))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.edit", translate("delete"), "delete")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.edit", translate("delete"), "delete")); taskModel = new TaskDefinitionTableModel(columnsModel); taskDefTableEl = uifactory.addTableElement(getWindowControl(), "taskTable", taskModel, getTranslator(), tasksCont); diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTAAvailableTaskController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTAAvailableTaskController.java index 4b881ff69e882b5c4df0ec44c68aedc13072b69c..d43cdf0f4f3cd870da2353bc059457ed8b3a0484 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/GTAAvailableTaskController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/GTAAvailableTaskController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Controller; @@ -124,7 +123,7 @@ public class GTAAvailableTaskController extends FormBasicController { if(preview) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ATDCols.preview.i18nKey(), ATDCols.preview.ordinal())); } - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("select", -1, "select", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("select", -1, "select", new StaticFlexiCellRenderer(translate("select"), "select", "btn btn-primary", "o_icon o_icon_submit"))); taskModel = new AvailableTaskTableModel(columnsModel); diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupGradingController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupGradingController.java index 44aa5be753f75a9c88c166504bcfb38b5de12755..4fec641c6dade62ba20e1bfa1385e3bbd51d5322 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupGradingController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupGradingController.java @@ -37,7 +37,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColum 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.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.velocity.VelocityContainer; @@ -164,7 +163,7 @@ public class GTACoachedGroupGradingController extends FormBasicController { FlexiColumnModel col; if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new StaticFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex, userPropertyHandler.getName(), true, propName, new StaticFlexiCellRenderer(userPropertyHandler.getName(), new TextFlexiCellRenderer())); } else { diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupListController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupListController.java index a0dc1b45666a168c291e1d4fc8f89b9e6544c327..0cb2d3be87ecdaa795f36e4a5ffa0598583062b0 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupListController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupListController.java @@ -34,7 +34,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFle import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.course.nodes.GTACourseNode; @@ -87,7 +86,7 @@ public class GTACoachedGroupListController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CGCols.taskStatus.i18nKey(), CGCols.taskStatus.ordinal(), true, CGCols.taskStatus.name(), new TaskStatusCellRenderer(getTranslator()))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("select", translate("select"), "select")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("select", translate("select"), "select")); tableModel = new CoachGroupsTableModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "entries", tableModel, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedParticipantListController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedParticipantListController.java index 0606b194d45c0c2ae0c851ea1c281d1fc0d56ea7..8ac1e0b1c7b9c203f6f6aef10a2de2c0cbae97f5 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedParticipantListController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedParticipantListController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -157,7 +156,7 @@ public class GTACoachedParticipantListController extends FormBasicController { FlexiColumnModel col; if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new StaticFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex, userPropertyHandler.getName(), true, propName, new StaticFlexiCellRenderer(userPropertyHandler.getName(), new TextFlexiCellRenderer())); } else { @@ -174,7 +173,7 @@ public class GTACoachedParticipantListController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CGCols.taskStatus.i18nKey(), CGCols.taskStatus.ordinal(), true, CGCols.taskStatus.name(), new TaskStatusCellRenderer(getTranslator()))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("select", translate("select"), "select")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("select", translate("select"), "select")); tableModel = new CoachParticipantsTableModel(userPropertyHandlers, getLocale(), columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "entries", tableModel, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTASampleSolutionsEditController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTASampleSolutionsEditController.java index e7a09109ccdacbb5696af6d0f322b832b731b0eb..6cf002930ce7c32d7f11761ad9c9987bfaeb66a9 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/GTASampleSolutionsEditController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/GTASampleSolutionsEditController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -111,11 +110,11 @@ public class GTASampleSolutionsEditController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SolCols.title.i18nKey(), SolCols.title.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SolCols.file.i18nKey(), SolCols.file.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SolCols.author.i18nKey(), SolCols.author.ordinal())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.edit", SolCols.edit.ordinal(), "edit", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.edit", SolCols.edit.ordinal(), "edit", new BooleanCellRenderer( new StaticFlexiCellRenderer(translate("edit"), "edit"), new StaticFlexiCellRenderer(translate("replace"), "edit")))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("table.header.edit", translate("delete"), "delete")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("table.header.edit", translate("delete"), "delete")); solutionModel = new SolutionTableModel(columnsModel); solutionTable = uifactory.addTableElement(getWindowControl(), "table", solutionModel, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GroupAssessmentController.java b/src/main/java/org/olat/course/nodes/gta/ui/GroupAssessmentController.java index 3e63b2346e5a7db2ec9399a9627bf6a6417f4c37..8c07ff08e076669a6f2af6134786c944179648ec 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/GroupAssessmentController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/GroupAssessmentController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColum 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.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; @@ -183,7 +182,7 @@ public class GroupAssessmentController extends FormBasicController { FlexiColumnModel col; if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new StaticFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex, userPropertyHandler.getName(), true, propName, new StaticFlexiCellRenderer(userPropertyHandler.getName(), new TextFlexiCellRenderer())); } else { diff --git a/src/main/java/org/olat/course/nodes/gta/ui/SubmitDocumentsController.java b/src/main/java/org/olat/course/nodes/gta/ui/SubmitDocumentsController.java index ea6ae71da20db6903c056cc4153f2795d7ccb097..995f70c145d36df61d1d9cd98fca85ae1c8c5457 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/SubmitDocumentsController.java +++ b/src/main/java/org/olat/course/nodes/gta/ui/SubmitDocumentsController.java @@ -47,7 +47,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -136,11 +135,11 @@ class SubmitDocumentsController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(docI18nKey, DocCols.document.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(DocCols.date.i18nKey(), DocCols.date.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(DocCols.uploadedBy.i18nKey(), DocCols.uploadedBy.ordinal())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit", DocCols.edit.ordinal(), "edit", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("edit", DocCols.edit.ordinal(), "edit", new BooleanCellRenderer( new StaticFlexiCellRenderer(translate("edit"), "edit"), new StaticFlexiCellRenderer(translate("replace"), "edit")))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", translate("delete"), "delete")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", translate("delete"), "delete")); model = new DocumentTableModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "table", model, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/nodes/iq/IQRunController.java b/src/main/java/org/olat/course/nodes/iq/IQRunController.java index f716c37f0447566e798d16277bc0a995b48cebf0..f9231f5baa9b36d7b174b94077b97ad61b769cba 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQRunController.java +++ b/src/main/java/org/olat/course/nodes/iq/IQRunController.java @@ -67,7 +67,7 @@ import org.olat.course.DisposedCourseRestartController; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentHelper; import org.olat.course.assessment.AssessmentManager; -import org.olat.course.assessment.AssessmentNotificationsHandler; +import org.olat.course.assessment.manager.AssessmentNotificationsHandler; import org.olat.course.auditing.UserNodeAuditManager; import org.olat.course.nodes.AssessableCourseNode; import org.olat.course.nodes.CourseNode; @@ -92,6 +92,7 @@ import org.olat.modules.iq.IQSubmittedEvent; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; import org.olat.util.logging.activity.LoggingResourceable; +import org.springframework.beans.factory.annotation.Autowired; /** * Description:<BR> @@ -128,7 +129,10 @@ public class IQRunController extends BasicController implements GenericEventList private OLATResourceable assessmentInstanceOres; - private final IQManager iqManager; + @Autowired + private IQManager iqManager; + @Autowired + private AssessmentNotificationsHandler assessmentNotificationsHandler; /** * Constructor for a test run controller @@ -152,7 +156,6 @@ public class IQRunController extends BasicController implements GenericEventList this.assessmentInstanceOres = OresHelper.createOLATResourceableType(AssessmentInstance.class); this.userSession = ureq.getUserSession(); - iqManager = CoreSpringFactory.getImpl(IQManager.class); addLoggingResourceable(LoggingResourceable.wrap(courseNode)); @@ -469,9 +472,8 @@ public class IQRunController extends BasicController implements GenericEventList acn.updateUserScoreEvaluation(sceval, userCourseEnv, getIdentity(), incrementUserAttempts); // Mark publisher for notifications - AssessmentNotificationsHandler anh = AssessmentNotificationsHandler.getInstance(); Long courseId = userCourseEnv.getCourseEnvironment().getCourseResourceableId(); - anh.markPublisherNews(getIdentity(), courseId); + assessmentNotificationsHandler.markPublisherNews(getIdentity(), courseId); if(!assessmentStopped) { assessmentStopped = true; AssessmentEvent assessmentStoppedEvent = new AssessmentEvent(AssessmentEvent.TYPE.STOPPED, userSession); diff --git a/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentDetailsController.java b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentDetailsController.java index 1711070cd9f1d277406c0e3937a76857f7ed6ec3..6642523c2b91db3105071165f8ef06ce8cbdcceb 100644 --- a/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentDetailsController.java +++ b/src/main/java/org/olat/course/nodes/iq/QTI21AssessmentDetailsController.java @@ -33,7 +33,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; @@ -85,7 +84,7 @@ public class QTI21AssessmentDetailsController extends FormBasicController { protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TSCols.lastModified.i18nKey(), TSCols.lastModified.ordinal())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(TSCols.results.i18nKey(), TSCols.results.ordinal(), "result", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TSCols.results.i18nKey(), TSCols.results.ordinal(), "result", new BooleanCellRenderer(new StaticFlexiCellRenderer(translate(TSCols.results.i18nKey()), "result"), null))); tableModel = new QTI21TestSessionTableModel(columnsModel); diff --git a/src/main/java/org/olat/course/nodes/ta/ConvertToGTACourseNode.java b/src/main/java/org/olat/course/nodes/ta/ConvertToGTACourseNode.java index c82fdc1e2a8d5a038770338253eefa414b0eaa90..cd73d218a1bc02a3822dbd11a6fb2b0ff5791dc2 100644 --- a/src/main/java/org/olat/course/nodes/ta/ConvertToGTACourseNode.java +++ b/src/main/java/org/olat/course/nodes/ta/ConvertToGTACourseNode.java @@ -63,6 +63,7 @@ import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentEntry; import org.olat.properties.Property; /** @@ -217,55 +218,24 @@ public class ConvertToGTACourseNode { CourseEnvironment courseEnv = course.getCourseEnvironment(); CoursePropertyManager propertyMgr = courseEnv.getCoursePropertyManager(); - Map<Long,AssessmentDatas> datas = new HashMap<>(); - List<Property> properties = propertyMgr.listCourseNodeProperties(sourceNode, null, null, null); - for(Property property:properties) { - String name = property.getName(); - if(AssessmentManager.SCORE.equals(name) || AssessmentManager.PASSED.equals(name) - || AssessmentManager.ATTEMPTS.equals(name) || AssessmentManager.COMMENT.equals(name) - || AssessmentManager.COACH_COMMENT.equals(name)) { - - Identity identity = property.getIdentity(); - AssessmentDatas assessmentDatas; - if(datas.containsKey(identity.getKey())) { - assessmentDatas = datas.get(identity.getKey()); - } else { - assessmentDatas = new AssessmentDatas(identity); - datas.put(identity.getKey(), assessmentDatas); - } - - switch(name) { - case AssessmentManager.SCORE: - assessmentDatas.setScore(property.getFloatValue()); - break; - case AssessmentManager.PASSED: - String pass = property.getStringValue(); - if(StringHelper.containsNonWhitespace(pass)) { - assessmentDatas.setPassed("true".equals(pass)); - } - break; - case AssessmentManager.ATTEMPTS: - assessmentDatas.setAttempts(property.getLongValue()); - break; - case AssessmentManager.COMMENT: - assessmentDatas.setComment(property.getTextValue()); - break; - case AssessmentManager.COACH_COMMENT: - assessmentDatas.setCoachComment(property.getTextValue()); - break; - } - } + Map<Long,AssessmentEntry> datas = new HashMap<>(); + List<AssessmentEntry> properties = courseEnv.getAssessmentManager().getAssessmentData(sourceNode); + + for(AssessmentEntry property:properties) { + Identity identity = property.getIdentity(); + datas.put(identity.getKey(), property); } properties = null; DBFactory.getInstance().getCurrentEntityManager().clear(); AssessmentManager assessmentMgr = courseEnv.getAssessmentManager(); - for(AssessmentDatas assessmentDatas:datas.values()) { - Identity assessedIdentity = securityManager.loadIdentityByKey(assessmentDatas.getIdentity().getKey()); + for(AssessmentEntry assessmentData:datas.values()) { + Identity assessedIdentity = securityManager.loadIdentityByKey(assessmentData.getIdentity().getKey()); - if(assessmentDatas.getPassed() != null || assessmentDatas.getScore() != null) { + if(assessmentData.getPassed() != null || assessmentData.getScore() != null) { UserCourseEnvironment userCourseEnv = AssessmentHelper.createAndInitUserCourseEnvironment(assessedIdentity, course); - ScoreEvaluation scoreEval = new ScoreEvaluation(assessmentDatas.getScore(), assessmentDatas.getPassed()); + Float score = assessmentData.getScore() == null ? null : assessmentData.getScore().floatValue(); + ScoreEvaluation scoreEval = new ScoreEvaluation(score, assessmentData.getPassed()); assessmentMgr.saveScoreEvaluation(gtaNode, null, assessedIdentity, scoreEval, userCourseEnv, false); //set graded @@ -277,16 +247,16 @@ public class ConvertToGTACourseNode { } } - if(assessmentDatas.getAttempts() != null) { - assessmentMgr.saveNodeAttempts(gtaNode, null, assessedIdentity, assessmentDatas.getAttempts().intValue()); + if(assessmentData.getAttempts() != null) { + assessmentMgr.saveNodeAttempts(gtaNode, null, assessedIdentity, assessmentData.getAttempts().intValue()); } - if(StringHelper.containsNonWhitespace(assessmentDatas.getCoachComment())) { - assessmentMgr.saveNodeCoachComment(gtaNode, assessedIdentity, assessmentDatas.getCoachComment()); + if(StringHelper.containsNonWhitespace(assessmentData.getCoachComment())) { + assessmentMgr.saveNodeCoachComment(gtaNode, assessedIdentity, assessmentData.getCoachComment()); } - if(StringHelper.containsNonWhitespace(assessmentDatas.getComment())) { - assessmentMgr.saveNodeComment(gtaNode, null, assessedIdentity, assessmentDatas.getComment()); + if(StringHelper.containsNonWhitespace(assessmentData.getComment())) { + assessmentMgr.saveNodeComment(gtaNode, null, assessedIdentity, assessmentData.getComment()); } } @@ -426,62 +396,4 @@ public class ConvertToGTACourseNode { } } } - - private static class AssessmentDatas { - - private final Identity identity; - private Boolean passed; - private Float score; - private String comment; - private String coachComment; - private Long attempts; - - public AssessmentDatas(Identity identity) { - this.identity = identity; - } - - public Boolean getPassed() { - return passed; - } - - public void setPassed(Boolean passed) { - this.passed = passed; - } - - public Float getScore() { - return score; - } - - public void setScore(Float score) { - this.score = score; - } - - public String getComment() { - return comment; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public String getCoachComment() { - return coachComment; - } - - public void setCoachComment(String coachComment) { - this.coachComment = coachComment; - } - - public Long getAttempts() { - return attempts; - } - - public void setAttempts(Long attempts) { - this.attempts = attempts; - } - - public Identity getIdentity() { - return identity; - } - } } diff --git a/src/main/java/org/olat/course/properties/PersistingCoursePropertyManager.java b/src/main/java/org/olat/course/properties/PersistingCoursePropertyManager.java index 82f3b8aaf801cfccf7a10109a09d0f39107fccfd..8ff2a49428423295c807e188dfe6792152806900 100644 --- a/src/main/java/org/olat/course/properties/PersistingCoursePropertyManager.java +++ b/src/main/java/org/olat/course/properties/PersistingCoursePropertyManager.java @@ -25,24 +25,22 @@ package org.olat.course.properties; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; -import javax.persistence.TypedQuery; - -import org.olat.basesecurity.IdentityImpl; -import org.olat.core.commons.persistence.DBFactory; +import org.olat.core.CoreSpringFactory; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.logging.AssertException; import org.olat.core.manager.BasicManager; -import org.olat.course.assessment.AssessmentManager; +import org.olat.course.CourseFactory; +import org.olat.course.ICourse; import org.olat.course.nodes.CourseNode; import org.olat.group.BusinessGroup; +import org.olat.modules.assessment.manager.AssessmentEntryDAO; import org.olat.properties.NarrowedPropertyManager; import org.olat.properties.Property; import org.olat.resource.OLATResource; @@ -225,34 +223,8 @@ public class PersistingCoursePropertyManager extends BasicManager implements Cou */ @Override public List<Identity> getAllIdentitiesWithCourseAssessmentData(Collection<Identity> excludeIdentities) { - StringBuilder query = new StringBuilder(); - query.append("select distinct i from ") - .append(IdentityImpl.class.getName()).append(" as i,") - .append(Property.class.getName()).append(" as p") - .append(" where i = p.identity and p.resourceTypeName = :resname") - .append(" and p.resourceTypeId = :resid") - .append(" and p.identity is not null") - .append(" and p.name in ('").append(AssessmentManager.SCORE).append("','").append(AssessmentManager.PASSED).append("')"); - - if(excludeIdentities != null && !excludeIdentities.isEmpty()) { - query.append(" and p.identity.key not in (:excludeIdentities) "); - } - - TypedQuery<Identity> db = DBFactory.getInstance().getCurrentEntityManager() - .createQuery(query.toString(), Identity.class) - .setParameter("resid", ores.getResourceableId()) - .setParameter("resname", ores.getResourceableTypeName()); - if(excludeIdentities != null && !excludeIdentities.isEmpty()) { - List<Long> excludeKeys = new ArrayList<Long>(); - for(Identity identity:excludeIdentities) { - excludeKeys.add(identity.getKey()); - } - //limit because Oracle and Hibernate doesn't like more than 1000 - if(excludeKeys.size() > 900) { - excludeKeys = excludeKeys.subList(0, 900); - } - db.setParameter("excludeIdentities", excludeKeys); - } - return db.getResultList(); + ICourse course = CourseFactory.loadCourse(ores); + AssessmentEntryDAO courseNodeAssessmentDao = CoreSpringFactory.getImpl(AssessmentEntryDAO.class); + return courseNodeAssessmentDao.getAllIdentitiesWithAssessmentData(course.getCourseEnvironment().getCourseGroupManager().getCourseEntry()); } } \ No newline at end of file diff --git a/src/main/java/org/olat/course/reminder/manager/ReminderRuleDAO.java b/src/main/java/org/olat/course/reminder/manager/ReminderRuleDAO.java index 00ec90da967bd3223b1c57817284f1c4fcc38519..7bf5024389d5277a1630ae35d1e83ed1c6149883 100644 --- a/src/main/java/org/olat/course/reminder/manager/ReminderRuleDAO.java +++ b/src/main/java/org/olat/course/reminder/manager/ReminderRuleDAO.java @@ -33,6 +33,7 @@ import org.olat.core.commons.persistence.PersistenceHelper; import org.olat.core.id.Identity; import org.olat.course.assessment.AssessmentManager; import org.olat.course.nodes.CourseNode; +import org.olat.repository.RepositoryEntryRef; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -48,33 +49,28 @@ public class ReminderRuleDAO { @Autowired private DB dbInstance; - public Map<Long,Float> getScores(Long courseResourceId, CourseNode node, List<Identity> identities) { + + public Map<Long,Float> getScores(RepositoryEntryRef entry, CourseNode node, List<Identity> identities) { if(identities == null || identities.isEmpty()) { return new HashMap<Long,Float>(); } - List<Long> identityKeys = PersistenceHelper.toKeys(identities); - - StringBuilder sb = new StringBuilder(); - sb.append("select p.identity.key, p.floatValue from org.olat.properties.Property as p") - .append(" where p.resourceTypeId = :resId and p.resourceTypeName='CourseModule'") - .append(" and p.name='").append(AssessmentManager.SCORE).append("'") - .append(" and p.category=:category"); - Set<Long> identityKeySet = null; - if(identityKeys.size() < 100) { - sb.append(" and p.identity.key in (:identityKeys)"); - } else { - identityKeySet = new HashSet<Long>(identityKeys); + StringBuilder sb = new StringBuilder(); + sb.append("select nodeassessment.identity.key, nodeassessment.score from coursenodeassessment nodeassessment") + .append(" where nodeassessment.courseEntry.key=:courseEntryKey and nodeassessment.courseNodeIdent=:courseNodeIdent"); + if(identities.size() < 50) { + sb.append(" and nodeassessment.identity.key in (:identityKeys)"); } - String myCategory = buildCourseNodePropertyCategory(node); TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Object[].class) - .setParameter("resId", courseResourceId) - .setParameter("category", myCategory); - if(identityKeys.size() < 100) { - query.setParameter("identityKeys", identityKeys); + .setParameter("courseEntryKey", entry.getKey()) + .setParameter("courseNodeIdent", node.getIdent()); + if(identities.size() < 50) { + query.setParameter("identityKeys", PersistenceHelper.toKeys(identities)); + } else { + identityKeySet = new HashSet<>(PersistenceHelper.toKeys(identities)); } List<Object[]> infoList = query.getResultList(); @@ -82,40 +78,34 @@ public class ReminderRuleDAO { for(Object[] infos:infoList) { Long identityKey = (Long)infos[0]; if(identityKeySet == null || identityKeySet.contains(identityKey)) { - Float score = (Float)infos[1]; - dateMap.put(identityKey, score); + Number score = (Number)infos[1]; + dateMap.put(identityKey, score.floatValue()); } } return dateMap; } - public Map<Long,Integer> getAttempts(Long courseResourceId, CourseNode node, List<Identity> identities) { + public Map<Long,Integer> getAttempts(RepositoryEntryRef entry, CourseNode node, List<Identity> identities) { if(identities == null || identities.isEmpty()) { return new HashMap<Long,Integer>(); } - List<Long> identityKeys = PersistenceHelper.toKeys(identities); - - StringBuilder sb = new StringBuilder(); - sb.append("select p.identity.key, p.longValue from org.olat.properties.Property as p") - .append(" where p.resourceTypeId = :resId and p.resourceTypeName='CourseModule'") - .append(" and p.name='").append(AssessmentManager.ATTEMPTS).append("'") - .append(" and p.category=:category"); - Set<Long> identityKeySet = null; - if(identityKeys.size() < 100) { - sb.append(" and p.identity.key in (:identityKeys)"); - } else { - identityKeySet = new HashSet<Long>(identityKeys); + StringBuilder sb = new StringBuilder(); + sb.append("select nodeassessment.identity.key, nodeassessment.attempts from coursenodeassessment nodeassessment") + .append(" where nodeassessment.courseEntry.key=:courseEntryKey and nodeassessment.courseNodeIdent=:courseNodeIdent"); + if(identities.size() < 50) { + sb.append(" and nodeassessment.identity.key in (:identityKeys)"); } - String myCategory = buildCourseNodePropertyCategory(node); TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Object[].class) - .setParameter("resId", courseResourceId) - .setParameter("category", myCategory); - if(identityKeys.size() < 100) { - query.setParameter("identityKeys", identityKeys); + .setParameter("courseEntryKey", entry.getKey()) + .setParameter("courseNodeIdent", node.getIdent()); + if(identities.size() < 50) { + query.setParameter("identityKeys", PersistenceHelper.toKeys(identities)); + } else { + identityKeySet = new HashSet<>(PersistenceHelper.toKeys(identities)); } List<Object[]> infoList = query.getResultList(); @@ -130,33 +120,27 @@ public class ReminderRuleDAO { return dateMap; } - public Map<Long,Date> getInitialAttemptDates(Long courseResourceId, CourseNode node, List<Identity> identities) { + public Map<Long,Date> getInitialAttemptDates(RepositoryEntryRef entry, CourseNode node, List<Identity> identities) { if(identities == null || identities.isEmpty()) { return new HashMap<Long,Date>(); } - List<Long> identityKeys = PersistenceHelper.toKeys(identities); - - StringBuilder sb = new StringBuilder(); - sb.append("select p.identity.key, p.creationDate from org.olat.properties.Property as p") - .append(" where p.resourceTypeId = :resId and p.resourceTypeName='CourseModule'") - .append(" and p.name='").append(AssessmentManager.ATTEMPTS).append("'") - .append(" and p.category=:category"); - Set<Long> identityKeySet = null; - if(identityKeys.size() < 100) { - sb.append(" and p.identity.key in (:identityKeys)"); - } else { - identityKeySet = new HashSet<Long>(identityKeys); + StringBuilder sb = new StringBuilder(); + sb.append("select nodeassessment.identity.key, nodeassessment.creationDate from coursenodeassessment nodeassessment") + .append(" where nodeassessment.courseEntry.key=:courseEntryKey and nodeassessment.courseNodeIdent=:courseNodeIdent"); + if(identities.size() < 50) { + sb.append(" and nodeassessment.identity.key in (:identityKeys)"); } - String myCategory = buildCourseNodePropertyCategory(node); TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Object[].class) - .setParameter("resId", courseResourceId) - .setParameter("category", myCategory); - if(identityKeys.size() < 100) { - query.setParameter("identityKeys", identityKeys); + .setParameter("courseEntryKey", entry.getKey()) + .setParameter("courseNodeIdent", node.getIdent()); + if(identities.size() < 50) { + query.setParameter("identityKeys", PersistenceHelper.toKeys(identities)); + } else { + identityKeySet = new HashSet<>(PersistenceHelper.toKeys(identities)); } List<Object[]> infoList = query.getResultList(); @@ -171,33 +155,27 @@ public class ReminderRuleDAO { return dateMap; } - public Map<Long,Boolean> getPassed(Long courseResourceId, CourseNode node, List<Identity> identities) { + public Map<Long,Boolean> getPassed(RepositoryEntryRef entry, CourseNode node, List<Identity> identities) { if(identities == null || identities.isEmpty()) { return new HashMap<Long,Boolean>(); } - List<Long> identityKeys = PersistenceHelper.toKeys(identities); - - StringBuilder sb = new StringBuilder(); - sb.append("select p.identity.key, p.stringValue from org.olat.properties.Property as p") - .append(" where p.resourceTypeId = :resId and p.resourceTypeName='CourseModule'") - .append(" and p.name='").append(AssessmentManager.PASSED).append("'") - .append(" and p.category=:category"); - Set<Long> identityKeySet = null; - if(identityKeys.size() < 100) { - sb.append(" and p.identity.key in (:identityKeys)"); - } else { - identityKeySet = new HashSet<Long>(identityKeys); + StringBuilder sb = new StringBuilder(); + sb.append("select nodeassessment.identity.key, nodeassessment.passed from coursenodeassessment nodeassessment") + .append(" where nodeassessment.courseEntry.key=:courseEntryKey and nodeassessment.courseNodeIdent=:courseNodeIdent"); + if(identities.size() < 50) { + sb.append(" and nodeassessment.identity.key in (:identityKeys)"); } - String myCategory = buildCourseNodePropertyCategory(node); TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Object[].class) - .setParameter("resId", courseResourceId) - .setParameter("category", myCategory); - if(identityKeys.size() < 100) { - query.setParameter("identityKeys", identityKeys); + .setParameter("courseEntryKey", entry.getKey()) + .setParameter("courseNodeIdent", node.getIdent()); + if(identities.size() < 50) { + query.setParameter("identityKeys", PersistenceHelper.toKeys(identities)); + } else { + identityKeySet = new HashSet<>(PersistenceHelper.toKeys(identities)); } List<Object[]> infoList = query.getResultList(); @@ -211,10 +189,4 @@ public class ReminderRuleDAO { } return dateMap; } - - private String buildCourseNodePropertyCategory(CourseNode node) { - String type = (node.getType().length() > 4 ? node.getType().substring(0, 4) : node.getType()); - return ("NID:" + type + "::" + node.getIdent()); - } - -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/reminder/rule/AttemptsRuleSPI.java b/src/main/java/org/olat/course/reminder/rule/AttemptsRuleSPI.java index d204cc5d8fd1a1ccb7ebca266621307cc651703a..a630bcca0fbc5a56fd74948787117fd4d3344168 100644 --- a/src/main/java/org/olat/course/reminder/rule/AttemptsRuleSPI.java +++ b/src/main/java/org/olat/course/reminder/rule/AttemptsRuleSPI.java @@ -82,7 +82,7 @@ public class AttemptsRuleSPI implements FilterRuleSPI { ICourse course = CourseFactory.loadCourse(entry.getOlatResource()); CourseNode courseNode = course.getRunStructure().getNode(nodeIdent); - Map<Long, Integer> attempts = helperDao.getAttempts(entry.getOlatResource().getResourceableId(), courseNode, identities); + Map<Long, Integer> attempts = helperDao.getAttempts(entry, courseNode, identities); for(Iterator<Identity> identityIt=identities.iterator(); identityIt.hasNext(); ) { Identity identity = identityIt.next(); diff --git a/src/main/java/org/olat/course/reminder/rule/InitialAttemptsRuleSPI.java b/src/main/java/org/olat/course/reminder/rule/InitialAttemptsRuleSPI.java index eb8c5e1640c093454899af23267a1fa761d60b9d..2fee1ec95040a5738ac5525ec8a08989dea42dab 100644 --- a/src/main/java/org/olat/course/reminder/rule/InitialAttemptsRuleSPI.java +++ b/src/main/java/org/olat/course/reminder/rule/InitialAttemptsRuleSPI.java @@ -80,7 +80,7 @@ public class InitialAttemptsRuleSPI extends AbstractLaunchDateRuleSPI { ICourse course = CourseFactory.loadCourse(courseResourceId); CourseNode courseNode = course.getRunStructure().getNode(nodeIdent); - return helperDao.getInitialAttemptDates(courseResourceId, courseNode, identities); + return helperDao.getInitialAttemptDates(entry, courseNode, identities); } else { return null; } diff --git a/src/main/java/org/olat/course/reminder/rule/PassedRuleSPI.java b/src/main/java/org/olat/course/reminder/rule/PassedRuleSPI.java index d365bbe40e0a5a475e85b5d2e59fb47abbb059f6..20363103622faf520423e21ac146cb2190b8f197 100644 --- a/src/main/java/org/olat/course/reminder/rule/PassedRuleSPI.java +++ b/src/main/java/org/olat/course/reminder/rule/PassedRuleSPI.java @@ -80,7 +80,7 @@ public class PassedRuleSPI implements FilterRuleSPI { ICourse course = CourseFactory.loadCourse(entry.getOlatResource()); CourseNode courseNode = course.getRunStructure().getNode(nodeIdent); - Map<Long, Boolean> passeds = helperDao.getPassed(entry.getOlatResource().getResourceableId(), courseNode, identities); + Map<Long, Boolean> passeds = helperDao.getPassed(entry, courseNode, identities); if("passed".equals(status)) { for(Iterator<Identity> identityIt=identities.iterator(); identityIt.hasNext(); ) { diff --git a/src/main/java/org/olat/course/reminder/rule/ScoreRuleSPI.java b/src/main/java/org/olat/course/reminder/rule/ScoreRuleSPI.java index bf1290ccefd13c1e0e022c84ef900d4a9ce21249..4280160e7888004193e078993d8c14b98bdf1093 100644 --- a/src/main/java/org/olat/course/reminder/rule/ScoreRuleSPI.java +++ b/src/main/java/org/olat/course/reminder/rule/ScoreRuleSPI.java @@ -83,7 +83,7 @@ public class ScoreRuleSPI implements FilterRuleSPI { ICourse course = CourseFactory.loadCourse(entry.getOlatResource()); CourseNode courseNode = course.getRunStructure().getNode(nodeIdent); - Map<Long, Float> scores = helperDao.getScores(entry.getOlatResource().getResourceableId(), courseNode, identities); + Map<Long, Float> scores = helperDao.getScores(entry, courseNode, identities); for(Iterator<Identity> identityIt=identities.iterator(); identityIt.hasNext(); ) { Identity identity = identityIt.next(); diff --git a/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java b/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java index c122e8bf8e41b62cdfaea488873c54f7324c2e45..fb217c13a7a8b716236f4d85651faa8061239173 100644 --- a/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java +++ b/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java @@ -36,7 +36,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; @@ -110,7 +109,7 @@ public class CourseReminderListController extends FormBasicController implements FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, ReminderCols.id.i18nKey(), ReminderCols.id.ordinal(), true, ReminderCols.id.name())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(ReminderCols.description.i18nKey(), ReminderCols.description.ordinal(), + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ReminderCols.description.i18nKey(), ReminderCols.description.ordinal(), "edit", true, ReminderCols.description.name(), new StaticFlexiCellRenderer("edit", new TextFlexiCellRenderer()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ReminderCols.creator.i18nKey(), ReminderCols.creator.ordinal(), true, ReminderCols.creator.name())); diff --git a/src/main/java/org/olat/course/reminder/ui/CourseReminderLogsController.java b/src/main/java/org/olat/course/reminder/ui/CourseReminderLogsController.java index 0f8c9b539ae3d215ecc02fd5d1f3221c265392fb..e6ca4dadd2efd023cd4fea36efe1938738303014 100644 --- a/src/main/java/org/olat/course/reminder/ui/CourseReminderLogsController.java +++ b/src/main/java/org/olat/course/reminder/ui/CourseReminderLogsController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.stack.TooledStackedPanel; import org.olat.core.gui.control.Controller; @@ -107,7 +106,7 @@ public class CourseReminderLogsController extends FormBasicController { FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SendCols.status.i18nKey(), SendCols.status.ordinal(), true, SendCols.status.name(), new StatusCellRenderer())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(SendCols.reminder.i18nKey(), SendCols.reminder.ordinal(), + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SendCols.reminder.i18nKey(), SendCols.reminder.ordinal(), "reminder", true, SendCols.reminder.name(), new StaticFlexiCellRenderer("reminder", new TextFlexiCellRenderer()))); if(isAdministrativeUser) { @@ -126,7 +125,7 @@ public class CourseReminderLogsController extends FormBasicController { FlexiColumnModel col; if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new StaticFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex, userPropertyHandler.getName(), true, propName, new StaticFlexiCellRenderer(userPropertyHandler.getName(), new TextFlexiCellRenderer())); } else { @@ -138,7 +137,7 @@ public class CourseReminderLogsController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SendCols.sendTime.i18nKey(), SendCols.sendTime.ordinal(), true, SendCols.sendTime.name())); //user properties - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("resend", translate("resend"), "resend")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("resend", translate("resend"), "resend")); tableModel = new CourseSendReminderTableModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, false, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/reminder/ui/CourseSendReminderListController.java b/src/main/java/org/olat/course/reminder/ui/CourseSendReminderListController.java index b54d9c1d343e3db9f19dff12d43fbf6af659c228..7e43e1381e39134021abac3e9573031d55055d5b 100644 --- a/src/main/java/org/olat/course/reminder/ui/CourseSendReminderListController.java +++ b/src/main/java/org/olat/course/reminder/ui/CourseSendReminderListController.java @@ -38,7 +38,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -117,7 +116,7 @@ public class CourseSendReminderListController extends FormBasicController { FlexiColumnModel col; if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new StaticFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex, userPropertyHandler.getName(), true, propName, new StaticFlexiCellRenderer(userPropertyHandler.getName(), new TextFlexiCellRenderer())); } else { @@ -126,7 +125,7 @@ public class CourseSendReminderListController extends FormBasicController { columnsModel.addFlexiColumnModel(col); } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SendCols.sendTime.i18nKey(), SendCols.sendTime.ordinal(), true, SendCols.sendTime.name())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("resend", translate("resend"), "resend")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("resend", translate("resend"), "resend")); tableModel = new CourseSendReminderTableModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, false, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java index c58980fe134e744695a8111f2a5824d419187f7e..1454540efd1fac3ce605d9831194d02fdd24bf5a 100644 --- a/src/main/java/org/olat/course/run/CourseRuntimeController.java +++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java @@ -90,7 +90,8 @@ import org.olat.course.assessment.AssessmentMainController; import org.olat.course.assessment.AssessmentModule; import org.olat.course.assessment.CoachingGroupAccessAssessmentCallback; import org.olat.course.assessment.FullAccessAssessmentCallback; -import org.olat.course.assessment.ui.AssessmentModeListController; +import org.olat.course.assessment.ui.mode.AssessmentModeListController; +import org.olat.course.assessment.ui.tool.AssessmentOverviewController; import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementController; import org.olat.course.certificate.ui.CertificatesOptionsController; import org.olat.course.config.CourseConfig; @@ -148,7 +149,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im private Delayed delayedClose; //tools private Link folderLink, - assessmentLink, archiverLink, + assessmentLink, assessment_v2_Link, archiverLink, courseStatisticLink, surveyStatisticLink, testStatisticLink, areaLink, dbLink, //settings @@ -169,6 +170,7 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im private CourseOptionsController optionsToolCtr; private CourseRemindersController remindersCtrl; private AssessmentMainController assessmentToolCtr; + private AssessmentOverviewController assessmentTool_v2_Ctr; private MembersManagementMainController membersCtrl; private StatisticCourseNodesController statsToolCtr; private AssessmentModeListController assessmentModeCtrl; @@ -391,6 +393,11 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im assessmentLink = LinkFactory.createToolLink("assessment",translate("command.openassessment"), this, "o_icon_assessment_tool"); assessmentLink.setElementCssClass("o_sel_course_assessment_tool"); tools.addComponent(assessmentLink); + + assessment_v2_Link = LinkFactory.createToolLink("assessment", translate("command.openassessment") + " v2", this, "o_icon_rocket"); + assessment_v2_Link.setElementCssClass("o_sel_course_assessment_tool"); + tools.addComponent(assessment_v2_Link); + } if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_ARCHIVING)) { archiverLink = LinkFactory.createToolLink("archiver", translate("command.openarchiver"), this, "o_icon_archive_tool"); @@ -718,6 +725,8 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im doAssessmentSurveyStatistics(ureq); } else if(assessmentLink == source) { doAssessmentTool(ureq); + } else if(assessment_v2_Link == source) { + doAssessmentTool_v2(ureq); } else if(calendarLink == source) { launchCalendar(ureq); } else if(chatLink == source) { @@ -1277,6 +1286,42 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im return null; } + private Activateable2 doAssessmentTool_v2(UserRequest ureq) { + if(delayedClose == Delayed.assessmentTool || requestForClose(ureq)) { + OLATResourceable ores = OresHelper.createOLATResourceableType("assessmentTool"); + ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); + WindowControl swControl = addToHistory(ureq, ores, null); + + // 1) course admins and users with tool right: full access + if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_ASSESSMENT)) { + removeCustomCSS(ureq); + AssessmentOverviewController ctrl = new AssessmentOverviewController(ureq, swControl, toolbarPanel, + getRepositoryEntry(), new FullAccessAssessmentCallback(reSecurity.isEntryAdmin())); + ctrl.activate(ureq, null, null); + listenTo(ctrl); + assessmentTool_v2_Ctr = pushController(ureq, translate("command.openassessment"), ctrl); + currentToolCtr = assessmentTool_v2_Ctr; + setActiveTool(assessmentLink); + return assessmentToolCtr; + } + // 2) users with coach right: limited access to coached groups + if (reSecurity.isCourseCoach() || reSecurity.isGroupCoach()) { + removeCustomCSS(ureq); + AssessmentOverviewController ctrl = new AssessmentOverviewController(ureq, swControl, toolbarPanel, + getRepositoryEntry(), new CoachingGroupAccessAssessmentCallback()); + ctrl.activate(ureq, null, null); + listenTo(ctrl); + assessmentTool_v2_Ctr = pushController(ureq, translate("command.openassessment"), ctrl); + currentToolCtr = assessmentTool_v2_Ctr; + setActiveTool(assessmentLink); + return assessmentToolCtr; + } + } else { + delayedClose = Delayed.assessmentTool; + } + return null; + } + private void doEfficiencyStatements(UserRequest ureq) { if(delayedClose == Delayed.efficiencyStatements || requestForClose(ureq)) { // will not be disposed on course run dispose, popus up as new browserwindow diff --git a/src/main/java/org/olat/course/run/environment/CourseEnvironmentImpl.java b/src/main/java/org/olat/course/run/environment/CourseEnvironmentImpl.java index a7dad723660cadc2e2812fee04d40c44ecfc07f8..e76f292de1d075bb0a6b6e55ea8990c2033cb179 100644 --- a/src/main/java/org/olat/course/run/environment/CourseEnvironmentImpl.java +++ b/src/main/java/org/olat/course/run/environment/CourseEnvironmentImpl.java @@ -31,7 +31,7 @@ import org.olat.core.util.vfs.VFSContainer; import org.olat.course.PersistingCourseImpl; import org.olat.course.Structure; import org.olat.course.assessment.AssessmentManager; -import org.olat.course.assessment.NewCachePersistingAssessmentManager; +import org.olat.course.assessment.manager.CourseAssessmentManagerImpl; import org.olat.course.auditing.UserNodeAuditManager; import org.olat.course.auditing.UserNodeAuditManagerImpl; import org.olat.course.config.CourseConfig; @@ -106,7 +106,7 @@ public class CourseEnvironmentImpl implements CourseEnvironment { if(assessmentManager == null) { synchronized(this) { if(assessmentManager == null) { - assessmentManager = NewCachePersistingAssessmentManager.getInstance(course); + assessmentManager = new CourseAssessmentManagerImpl(cgm.getCourseEntry()); } } } diff --git a/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java b/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java index c81d8d846db3b8c4c173e48b0ef6fa024001e1a6..242f9ece90590a615b496b446d01ab3313ac6ca5 100644 --- a/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java +++ b/src/main/java/org/olat/course/run/preview/PreviewAssessmentManager.java @@ -25,6 +25,7 @@ package org.olat.course.run.preview; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -39,6 +40,7 @@ import org.olat.course.assessment.AssessmentManager; import org.olat.course.nodes.CourseNode; import org.olat.course.run.scoring.ScoreEvaluation; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.modules.assessment.AssessmentEntry; /** * Initial Date: 08.02.2005 @@ -58,6 +60,11 @@ final class PreviewAssessmentManager extends BasicManager implements AssessmentM nodeScores.put(courseNode.getIdent(), score); } + @Override + public List<AssessmentEntry> getAssessmentData(CourseNode courseNode) { + return Collections.emptyList(); + } + /** * @see org.olat.course.assessment.AssessmentManager#saveNodeAttempts(org.olat.course.nodes.CourseNode, org.olat.core.id.Identity, org.olat.core.id.Identity, java.lang.Integer) */ diff --git a/src/main/java/org/olat/course/site/ui/CourseSiteAdminController.java b/src/main/java/org/olat/course/site/ui/CourseSiteAdminController.java index 298db11e9d5b26eb64bb3a16726d0608ee75bdbe..2abee7c14f99e0e4d614948b12174db91dcd752c 100644 --- a/src/main/java/org/olat/course/site/ui/CourseSiteAdminController.java +++ b/src/main/java/org/olat/course/site/ui/CourseSiteAdminController.java @@ -44,7 +44,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; @@ -109,9 +108,9 @@ public class CourseSiteAdminController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CSCols.title.i18nKey(), CSCols.title.ordinal())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, CSCols.courseId.i18nKey(), CSCols.courseId.ordinal(), false, null)); FlexiCellRenderer renderer = new StaticFlexiCellRenderer("openre", new TextFlexiCellRenderer()); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(CSCols.courseTitle.i18nKey(), CSCols.courseTitle.ordinal(), "openre", renderer)); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("select", translate("select"), "select")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("remove", translate("remove"), "remove")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CSCols.courseTitle.i18nKey(), CSCols.courseTitle.ordinal(), "openre", renderer)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("select", translate("select"), "select")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("remove", translate("remove"), "remove")); String page = velocity_root + "/lang_options.html"; tableLayout = FormLayoutContainer.createCustomFormLayout("site.options.lang", getTranslator(), page); diff --git a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java index be661066c35668eadeb29e26b34ff2adb8700828..4379802ce3a5e0b8cd91ba0742a3cfd6ecf0493a 100644 --- a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java +++ b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java @@ -51,7 +51,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; @@ -258,7 +257,7 @@ public abstract class AbstractMemberListController extends FormBasicController i } if(isAdministrativeUser) { FlexiCellRenderer renderer = new StaticFlexiCellRenderer(TABLE_ACTION_EDIT, new TextFlexiCellRenderer()); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.username.i18n(), Cols.username.ordinal(), TABLE_ACTION_EDIT, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.username.i18n(), Cols.username.ordinal(), TABLE_ACTION_EDIT, true, Cols.username.name(), renderer)); } @@ -272,7 +271,7 @@ public abstract class AbstractMemberListController extends FormBasicController i FlexiColumnModel col; if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new StaticFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colPos++, TABLE_ACTION_EDIT, true, propName, new StaticFlexiCellRenderer(TABLE_ACTION_EDIT, new TextFlexiCellRenderer())); } else { diff --git a/src/main/java/org/olat/group/ui/main/BusinessGroupFlexiTableModel.java b/src/main/java/org/olat/group/ui/main/BusinessGroupFlexiTableModel.java index 478f03eec83f4b847f834c39871d3a10d3348ea0..a4226ec335d0b0f670925860eb6c51ea20a1111c 100644 --- a/src/main/java/org/olat/group/ui/main/BusinessGroupFlexiTableModel.java +++ b/src/main/java/org/olat/group/ui/main/BusinessGroupFlexiTableModel.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.translator.Translator; import org.olat.core.util.Formatter; @@ -74,7 +73,7 @@ public class BusinessGroupFlexiTableModel extends DefaultFlexiTableDataModel<BGT columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.mark.i18n(), Cols.mark.ordinal(), true, Cols.mark.name())); //group name - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal(), TABLE_ACTION_LAUNCH, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal(), TABLE_ACTION_LAUNCH, true, Cols.name.name(), new StaticFlexiCellRenderer(TABLE_ACTION_LAUNCH, new BusinessGroupNameCellRenderer()))); //id and reference columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.key.i18n(), Cols.key.ordinal(), true, Cols.key.name())); @@ -103,10 +102,10 @@ public class BusinessGroupFlexiTableModel extends DefaultFlexiTableDataModel<BGT true, Cols.role.name(), FlexiColumnModel.ALIGNMENT_LEFT, new BGRoleCellRenderer(translator.getLocale()))); //actions - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.allowLeave.i18n(), Cols.allowLeave.ordinal(), TABLE_ACTION_LEAVE, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.allowLeave.i18n(), Cols.allowLeave.ordinal(), TABLE_ACTION_LEAVE, new BooleanCellRenderer(new StaticFlexiCellRenderer(translator.translate("table.header.leave"), TABLE_ACTION_LEAVE), null))); if(delete) { - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.allowDelete.i18n(), Cols.allowDelete.ordinal(), TABLE_ACTION_DELETE, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.allowDelete.i18n(), Cols.allowDelete.ordinal(), TABLE_ACTION_DELETE, new BooleanCellRenderer(new StaticFlexiCellRenderer(translator.translate("table.header.delete"), TABLE_ACTION_DELETE), null))); } @@ -119,7 +118,7 @@ public class BusinessGroupFlexiTableModel extends DefaultFlexiTableDataModel<BGT columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.mark.i18n(), Cols.mark.ordinal(), true, Cols.mark.name())); //group name - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal(), TABLE_ACTION_LAUNCH, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal(), TABLE_ACTION_LAUNCH, true, Cols.name.name(), new StaticFlexiCellRenderer(TABLE_ACTION_LAUNCH, new BusinessGroupNameCellRenderer()))); //id and reference columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.key.i18n(), Cols.key.ordinal(), true, Cols.key.name())); @@ -145,7 +144,7 @@ public class BusinessGroupFlexiTableModel extends DefaultFlexiTableDataModel<BGT true, Cols.waitingListCount.name())); //actions - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("select", translator.translate("select"), TABLE_ACTION_SELECT)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("select", translator.translate("select"), TABLE_ACTION_SELECT)); return columnsModel; } diff --git a/src/main/java/org/olat/group/ui/main/OpenBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/OpenBusinessGroupListController.java index 0bc11b54d49f58b4d37cc498b8d7f33ab442491a..322b297c9284f8066926bf71b8d88c9b27d1e21c 100644 --- a/src/main/java/org/olat/group/ui/main/OpenBusinessGroupListController.java +++ b/src/main/java/org/olat/group/ui/main/OpenBusinessGroupListController.java @@ -28,7 +28,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColum 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.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.control.WindowControl; import org.olat.group.BusinessGroup; @@ -54,7 +53,7 @@ public class OpenBusinessGroupListController extends AbstractBusinessGroupListCo protected FlexiTableColumnModel initColumnModel() { FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal(), TABLE_ACTION_LAUNCH, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18n(), Cols.name.ordinal(), TABLE_ACTION_LAUNCH, true, Cols.name.name(), new StaticFlexiCellRenderer(TABLE_ACTION_LAUNCH, new BusinessGroupNameCellRenderer()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.key.i18n(), Cols.key.ordinal(), true, Cols.key.name())); @@ -66,7 +65,7 @@ public class OpenBusinessGroupListController extends AbstractBusinessGroupListCo false, null, FlexiColumnModel.ALIGNMENT_LEFT, new TextFlexiCellRenderer(EscapeMode.antisamy))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.resources.i18n(), Cols.resources.ordinal(), true, Cols.resources.name(), FlexiColumnModel.ALIGNMENT_LEFT, new BGResourcesCellRenderer(flc))); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.freePlaces.i18n(), Cols.freePlaces.ordinal(), TABLE_ACTION_LAUNCH, + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.freePlaces.i18n(), Cols.freePlaces.ordinal(), TABLE_ACTION_LAUNCH, true, Cols.freePlaces.name(), new TextFlexiCellRenderer(EscapeMode.none))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.accessTypes.i18n(), Cols.accessTypes.ordinal(), true, Cols.accessTypes.name(), FlexiColumnModel.ALIGNMENT_LEFT, new BGAccessControlledCellRenderer())); diff --git a/src/main/java/org/olat/ims/_spring/imsContext.xml b/src/main/java/org/olat/ims/_spring/imsContext.xml index fc16b9ae262cccfb21409bfd7394718e9ea192f2..142f2764eabd0cfbc566588dbfa0a67d5188f795 100644 --- a/src/main/java/org/olat/ims/_spring/imsContext.xml +++ b/src/main/java/org/olat/ims/_spring/imsContext.xml @@ -8,10 +8,9 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> - <context:component-scan base-package="org.olat.ims.lti.manager,org.olat.ims.qti" /> + <context:component-scan base-package="org.olat.ims.lti.manager,org.olat.ims.qti,org.olat.ims.qti21,uk.ac.ed.ph.jqtiplus" /> <import resource="classpath:/org/olat/ims/qti/_spring/qtiContext.xml"/> - <import resource="classpath:/org/olat/ims/qti21/_spring/qti21Context.xml"/> <bean id="org.olat.ims.cp.CPManager" class="org.olat.ims.cp.CPManagerImpl"/> diff --git a/src/main/java/org/olat/ims/qti/statistics/manager/QTIStatisticsManagerImpl.java b/src/main/java/org/olat/ims/qti/statistics/manager/QTIStatisticsManagerImpl.java index 89be6c9e50332cea9389c1d18720e0a53c073af5..9decbec61d89f6a00374747d8e1a6aa42b7c1a41 100644 --- a/src/main/java/org/olat/ims/qti/statistics/manager/QTIStatisticsManagerImpl.java +++ b/src/main/java/org/olat/ims/qti/statistics/manager/QTIStatisticsManagerImpl.java @@ -30,7 +30,6 @@ import java.util.Map; import javax.persistence.TypedQuery; import org.olat.core.commons.persistence.DB; -import org.olat.course.assessment.AssessmentManager; import org.olat.ims.qti.QTIResultManager; import org.olat.ims.qti.editor.beecom.objects.FIBResponse; import org.olat.ims.qti.editor.beecom.objects.Item; @@ -48,7 +47,6 @@ import org.olat.ims.qti.statistics.model.StatisticKPrimOption; import org.olat.ims.qti.statistics.model.StatisticSurveyItem; import org.olat.ims.qti.statistics.model.StatisticSurveyItemResponse; import org.olat.ims.qti.statistics.model.StatisticsItem; -import org.olat.properties.Property; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -76,9 +74,8 @@ public class QTIStatisticsManagerImpl implements QTIStatisticsManager { } if(searchParams.isMayViewAllUsersAssessments()) { - sb.append(" and rset.identityKey in ( select p.identity.key from ").append(Property.class.getName()).append(" p ") - .append(" where p.resourceTypeId=:resourceId and p.resourceTypeName='CourseModule'") - .append(" and p.name in ('").append(AssessmentManager.SCORE).append("','").append(AssessmentManager.PASSED).append("')") + sb.append(" and rset.identityKey in (select nodeassessment.identity.key from coursenodeassessment nodeassessment ") + .append(" where nodeassessment.courseEntry.key=rset.repositoryEntryKey and nodeassessment.courseNodeIdent=rset.olatResourceDetail") .append(" )"); } return sb; diff --git a/src/main/java/org/olat/ims/qti/statistics/model/QTIStatisticResultSet.java b/src/main/java/org/olat/ims/qti/statistics/model/QTIStatisticResultSet.java index 5a091120721d407bc457e8469397f61d57b365ae..7a316b0209685a9cf235ab23d13f716567027eed 100644 --- a/src/main/java/org/olat/ims/qti/statistics/model/QTIStatisticResultSet.java +++ b/src/main/java/org/olat/ims/qti/statistics/model/QTIStatisticResultSet.java @@ -58,6 +58,8 @@ public class QTIStatisticResultSet implements CreateInfo, Persistable { @Column(name="lastmodified", nullable=false, insertable=true, updatable=false) private Date lastModified; + @Column(name="repositoryref_fk", nullable=false, insertable=true, updatable=false) + private Long repositoryEntryKey; @Column(name="olatresource_fk", nullable=false, insertable=true, updatable=false) private Long olatResource; @Column(name="olatresourcedetail", nullable=false, insertable=true, updatable=false) @@ -103,6 +105,13 @@ public class QTIStatisticResultSet implements CreateInfo, Persistable { this.identityKey = identityKey; } + public Long getRepositoryEntryKey() { + return repositoryEntryKey; + } + + public void setRepositoryEntryKey(Long repositoryEntryKey) { + this.repositoryEntryKey = repositoryEntryKey; + } public Long getOlatResource() { return olatResource; diff --git a/src/main/java/org/olat/ims/qti21/_spring/qti21Context.xml b/src/main/java/org/olat/ims/qti21/_spring/qti21Context.xml deleted file mode 100644 index 1cbe50ad4b1cb43ccb4cc0b46737a6787af0d731..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/ims/qti21/_spring/qti21Context.xml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation=" - http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context.xsd"> - - <context:component-scan base-package="org.olat.ims.qti21,uk.ac.ed.ph.jqtiplus" /> - - -</beans> \ No newline at end of file diff --git a/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java b/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java index e79ec405ebd25a66c6ecde85e160c34f2c9815f2..a8bfb7bbc94f5bdadac26b8b29f51ea1d0964b33 100644 --- a/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java +++ b/src/main/java/org/olat/ims/qti21/manager/QTI21ServiceImpl.java @@ -37,7 +37,6 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.olat.basesecurity.IdentityRef; -import org.olat.core.commons.persistence.DB; import org.olat.core.gui.components.form.flexible.impl.MultipartFileInfos; import org.olat.core.id.Identity; import org.olat.core.logging.OLATRuntimeException; @@ -101,8 +100,6 @@ public class QTI21ServiceImpl implements QTI21Service { private static final OLog log = Tracing.createLoggerFor(QTI21ServiceImpl.class); - @Autowired - private DB dbInstance; @Autowired private EventDAO eventDao; @Autowired diff --git a/src/main/java/org/olat/modules/assessment/AssessmentEntry.java b/src/main/java/org/olat/modules/assessment/AssessmentEntry.java new file mode 100644 index 0000000000000000000000000000000000000000..373fcd6dbd507fffe0adafa618071bad86beaaf2 --- /dev/null +++ b/src/main/java/org/olat/modules/assessment/AssessmentEntry.java @@ -0,0 +1,86 @@ +/** + * <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.assessment; + +import java.math.BigDecimal; +import java.util.Date; + +import org.olat.core.id.Identity; +import org.olat.repository.RepositoryEntry; + +/** + * + * Initial date: 20.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface AssessmentEntry { + + public Long getKey(); + + public Date getCreationDate(); + + public Date getLastModified(); + + public Long getAssessmentId(); + + public void setAssessmentId(Long assessmentId); + + public Integer getAttempts(); + + public void setAttempts(Integer attempts); + + public BigDecimal getScore(); + + public void setScore(BigDecimal score); + + public Boolean getPassed(); + + public void setPassed(Boolean passed); + + public Boolean getFullyAssessed(); + + public void setFullyAssessed(Boolean fullyAssessed); + + public Double getCompletion(); + + public void setCompletion(Double completion); + + public String getComment(); + + public void setComment(String comment); + + public String getCoachComment(); + + public void setCoachComment(String coachComment); + + public RepositoryEntry getRepositoryEntry(); + + public String getSubIdent(); + + /** + * + * @return + */ + public RepositoryEntry getReferenceEntry(); + + public Identity getIdentity(); + +} diff --git a/src/main/java/org/olat/modules/assessment/AssessmentService.java b/src/main/java/org/olat/modules/assessment/AssessmentService.java new file mode 100644 index 0000000000000000000000000000000000000000..6715ccdec598682cc7fea21b89e5dd7b9388445f --- /dev/null +++ b/src/main/java/org/olat/modules/assessment/AssessmentService.java @@ -0,0 +1,30 @@ +/** + * <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.assessment; + +/** + * + * Initial date: 22.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface AssessmentService { + +} diff --git a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java new file mode 100644 index 0000000000000000000000000000000000000000..9bc23b903cfb2f12cfb0e7b82d2d810ae4a242ca --- /dev/null +++ b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java @@ -0,0 +1,107 @@ +/** + * <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.assessment.manager; + +import java.util.Date; +import java.util.List; + +import org.olat.basesecurity.IdentityRef; +import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.model.AssessmentEntryImpl; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryRef; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 20.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class AssessmentEntryDAO { + + @Autowired + private DB dbInstance; + + public AssessmentEntry createCourseNodeAssessment(Identity assessedIdentity, + RepositoryEntry entry, String subIdent, RepositoryEntry referenceEntry) { + + AssessmentEntryImpl data = new AssessmentEntryImpl(); + data.setCreationDate(new Date()); + data.setLastModified(data.getCreationDate()); + data.setIdentity(assessedIdentity); + data.setRepositoryEntry(entry); + data.setSubIdent(subIdent); + data.setReferenceEntry(referenceEntry); + dbInstance.getCurrentEntityManager().persist(data); + return data; + } + + public AssessmentEntry loadAssessmentEntryById(Long id) { + List<AssessmentEntry> nodeAssessment = dbInstance.getCurrentEntityManager() + .createNamedQuery("loadAssessmentEntryById", AssessmentEntry.class) + .setParameter("key", id) + .getResultList(); + return nodeAssessment.isEmpty() ? null : nodeAssessment.get(0); + } + + public AssessmentEntry loadAssessmentEntry(IdentityRef assessedIdentity, RepositoryEntryRef entry, + String subIdent) { + + List<AssessmentEntry> nodeAssessment = dbInstance.getCurrentEntityManager() + .createNamedQuery("loadAssessmentEntryByRepositoryEntryAndUser", AssessmentEntry.class) + .setParameter("repositoryEntryKey", entry.getKey()) + .setParameter("identityKey", assessedIdentity.getKey()) + .setParameter("subIdent", subIdent) + .getResultList(); + return nodeAssessment.isEmpty() ? null : nodeAssessment.get(0); + } + + public AssessmentEntry updateCourseNodeAssessment(AssessmentEntry nodeAssessment) { + ((AssessmentEntryImpl)nodeAssessment).setLastModified(new Date()); + return dbInstance.getCurrentEntityManager().merge(nodeAssessment); + } + + public List<AssessmentEntry> loadAssessmentEntryBySubIdent(RepositoryEntryRef entry, String subIdent) { + return dbInstance.getCurrentEntityManager() + .createNamedQuery("loadAssessmentEntryByRepositoryEntryAndSubIdent", AssessmentEntry.class) + .setParameter("repositoryEntryKey", entry.getKey()) + .setParameter("subIdent", subIdent) + .getResultList(); + } + + public List<Identity> getAllIdentitiesWithAssessmentData(RepositoryEntryRef courseEntry) { + StringBuilder sb = new StringBuilder(); + sb.append("select distinct data.identity from assessmententry data where data.repositoryEntry.key=:repositoryEntryKey"); + return dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Identity.class) + .setParameter("repositoryEntryKey", courseEntry.getKey()) + .getResultList(); + } + + + + + +} diff --git a/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..ca5d5c3da9d4d700f3f6edb74ffe8fadd4e07400 --- /dev/null +++ b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryImpl.java @@ -0,0 +1,257 @@ +/** + * <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.assessment.model; + +import java.math.BigDecimal; +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.olat.basesecurity.IdentityImpl; +import org.olat.core.id.CreateInfo; +import org.olat.core.id.Identity; +import org.olat.core.id.ModifiedInfo; +import org.olat.core.id.Persistable; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.repository.RepositoryEntry; + +/** + * + * Initial date: 20.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Entity(name="assessmententry") +@Table(name="o_as_entry") +@NamedQueries({ + @NamedQuery(name="loadAssessmentEntryById", query="select data from assessmententry data where data.key=:key"), + @NamedQuery(name="loadAssessmentEntryByRepositoryEntryAndUser", query="select data from assessmententry data where data.repositoryEntry.key=:repositoryEntryKey and data.identity.key=:identityKey and data.subIdent=:subIdent"), + @NamedQuery(name="loadAssessmentEntryByRepositoryEntryAndSubIdent", query="select data from assessmententry data where data.repositoryEntry.key=:repositoryEntryKey and data.subIdent=:subIdent") + + +}) +public class AssessmentEntryImpl implements Persistable, ModifiedInfo, CreateInfo, AssessmentEntry { + + private static final long serialVersionUID = 2934783777645549412L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id", nullable=false, unique=true, insertable=true, updatable=false) + private Long key; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="creationdate", nullable=false, insertable=true, updatable=false) + private Date creationDate; + @Temporal(TemporalType.TIMESTAMP) + @Column(name="lastmodified", nullable=false, insertable=true, updatable=true) + private Date lastModified; + + @Column(name="a_attemtps", nullable=true, insertable=true, updatable=true) + private Integer attempts; + @Column(name="a_score", nullable=true, insertable=true, updatable=true) + private BigDecimal score; + @Column(name="a_passed", nullable=true, insertable=true, updatable=true) + private Boolean passed; + + @Column(name="a_completion", nullable=true, insertable=true, updatable=true) + private Double completion; + + @Column(name="a_comment", nullable=true, insertable=true, updatable=true) + private String comment; + @Column(name="a_coach_comment", nullable=true, insertable=true, updatable=true) + private String coachComment; + + // fully passed and assessment id are only for onyx + @Column(name="a_fully_assessed", nullable=true, insertable=true, updatable=true) + private Boolean fullyAssessed; + @Column(name="a_assessment_id", nullable=true, insertable=true, updatable=true) + private Long assessmentId; + + @ManyToOne(targetEntity=RepositoryEntry.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="fk_entry", nullable=false, insertable=true, updatable=false) + private RepositoryEntry repositoryEntry; + + @Column(name="a_subident", nullable=true, insertable=true, updatable=false) + private String subIdent; + + @ManyToOne(targetEntity=RepositoryEntry.class,fetch=FetchType.LAZY,optional=true) + @JoinColumn(name="fk_reference_entry", nullable=true, insertable=true, updatable=false) + private RepositoryEntry referenceEntry; + + @ManyToOne(targetEntity=IdentityImpl.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="fk_identity", nullable=false, insertable=true, updatable=false) + private Identity identity; + + + @Override + public Long getKey() { + return key; + } + + @Override + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + + @Override + public Date getLastModified() { + return lastModified; + } + + public void setLastModified(Date lastModified) { + this.lastModified = lastModified; + } + + public Integer getAttempts() { + return attempts; + } + + public void setAttempts(Integer attempts) { + this.attempts = attempts; + } + + public BigDecimal getScore() { + return score; + } + + public void setScore(BigDecimal score) { + this.score = score; + } + + public Boolean getPassed() { + return passed; + } + + public void setPassed(Boolean passed) { + this.passed = passed; + } + + public Boolean getFullyAssessed() { + return fullyAssessed; + } + + public void setFullyAssessed(Boolean fullyAssessed) { + this.fullyAssessed = fullyAssessed; + } + + public Double getCompletion() { + return completion; + } + + public void setCompletion(Double completion) { + this.completion = completion; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getCoachComment() { + return coachComment; + } + + public void setCoachComment(String coachComment) { + this.coachComment = coachComment; + } + + public Long getAssessmentId() { + return assessmentId; + } + + public void setAssessmentId(Long assessmentId) { + this.assessmentId = assessmentId; + } + + @Override + public RepositoryEntry getRepositoryEntry() { + return repositoryEntry; + } + + public void setRepositoryEntry(RepositoryEntry entry) { + this.repositoryEntry = entry; + } + + @Override + public String getSubIdent() { + return subIdent; + } + + public void setSubIdent(String subIdent) { + this.subIdent = subIdent; + } + + public RepositoryEntry getReferenceEntry() { + return referenceEntry; + } + + public void setReferenceEntry(RepositoryEntry referenceEntry) { + this.referenceEntry = referenceEntry; + } + + public Identity getIdentity() { + return identity; + } + + public void setIdentity(Identity identity) { + this.identity = identity; + } + + @Override + public int hashCode() { + return key == null ? -864687 : key.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof AssessmentEntryImpl) { + AssessmentEntryImpl session = (AssessmentEntryImpl)obj; + return getKey() != null && getKey().equals(session.getKey()); + } + return false; + } + + @Override + public boolean equalsByPersistableKey(Persistable persistable) { + return equals(persistable); + } +} diff --git a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java index a44508ae67f21d38bdd12eb178cc281ee3c8dccf..484b7b5056b7bb5443db752f313d237f476ab281 100644 --- a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java +++ b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java @@ -49,7 +49,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Controller; @@ -122,7 +121,7 @@ public abstract class AbstractItemListController extends FormBasicController protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { //add the table FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("quickview", "<i class='o_icon o_icon_quickview'> </i>", "quick-view")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("quickview", "<i class='o_icon o_icon_quickview'> </i>", "quick-view")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.mark.i18nKey(), Cols.mark.ordinal(), true, OrderBy.marks.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.editable.i18nKey(), Cols.editable.ordinal(), false, null, FlexiColumnModel.ALIGNMENT_LEFT, @@ -149,7 +148,7 @@ public abstract class AbstractItemListController extends FormBasicController columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.rating.i18nKey(), Cols.rating.ordinal(), true, OrderBy.rating.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.itemVersion.i18nKey(), Cols.itemVersion.ordinal(), true, OrderBy.itemVersion.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.status.i18nKey(), Cols.status.ordinal(), true, OrderBy.status.name())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("details", translate("details"), "select-item")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("details", translate("details"), "select-item")); model = new QuestionItemDataModel(columnsModel, this, getTranslator()); itemsTable = uifactory.addTableElement(getWindowControl(), "items", model, 50, true, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/modules/qpool/ui/CollectionListController.java b/src/main/java/org/olat/modules/qpool/ui/CollectionListController.java index 4db0cb289f73c6a0c9a879b9ba59891061a258d3..e55689651a93d404109858ac71e7984873b504de 100644 --- a/src/main/java/org/olat/modules/qpool/ui/CollectionListController.java +++ b/src/main/java/org/olat/modules/qpool/ui/CollectionListController.java @@ -39,7 +39,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -87,7 +86,7 @@ public class CollectionListController extends FormBasicController { FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("collection.name", 0)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("collection.creationDate", 1)); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("select", translate("select"), "select-coll")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("select", translate("select"), "select-coll")); model = new CollectionsDataModel(colls, columnsModel); collectionsTable = uifactory.addTableElement(getWindowControl(), "collections", model, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/modules/qpool/ui/PoolsController.java b/src/main/java/org/olat/modules/qpool/ui/PoolsController.java index f56cdcaf7506d14fa363bb4447277792b348968a..e43344b9e7651b5fb7abce5fa6652255eb3c149f 100644 --- a/src/main/java/org/olat/modules/qpool/ui/PoolsController.java +++ b/src/main/java/org/olat/modules/qpool/ui/PoolsController.java @@ -43,7 +43,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.table.TableDataModel; import org.olat.core.gui.control.Controller; @@ -109,7 +108,7 @@ public class PoolsController extends FormBasicController { new CSSIconFlexiCellRenderer("o_private")) )); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18nKey(), Cols.name.ordinal(), true, "name")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("select", translate("select"), "select-pool")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("select", translate("select"), "select-pool")); model = new PoolDataModel(columnsModel, getTranslator()); poolTable = uifactory.addTableElement(getWindowControl(), "pools", model, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/PoolsAdminController.java b/src/main/java/org/olat/modules/qpool/ui/admin/PoolsAdminController.java index 7449b12bf5bbcc8942ca1fb4609c0aa9f1226671..8964277fc05c9759df73bbbc72c94fce6c75362b 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/PoolsAdminController.java +++ b/src/main/java/org/olat/modules/qpool/ui/admin/PoolsAdminController.java @@ -44,7 +44,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.table.TableDataModel; import org.olat.core.gui.control.Controller; @@ -108,9 +107,9 @@ public class PoolsAdminController extends FormBasicController { new CSSIconFlexiCellRenderer("o_icon_pool_private")) )); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.name.i18nKey(), Cols.name.ordinal(), true, "name")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit", translate("edit"), "edit-pool")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("pool.owners", translate("pool.owners"), "owners-pool")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", translate("delete"), "delete-pool")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("edit", translate("edit"), "edit-pool")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("pool.owners", translate("pool.owners"), "owners-pool")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", translate("delete"), "delete-pool")); model = new PoolDataModel(columnsModel, getTranslator()); poolTable = uifactory.addTableElement(getWindowControl(), "pools", model, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/QEducationalContextsAdminController.java b/src/main/java/org/olat/modules/qpool/ui/admin/QEducationalContextsAdminController.java index dd8314430bd377a03639cc10f828f97c5f9914c2..abd77fd2dac1e6ca4ef127f7e85a22357d79b444 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/QEducationalContextsAdminController.java +++ b/src/main/java/org/olat/modules/qpool/ui/admin/QEducationalContextsAdminController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.table.TableDataModel; @@ -100,9 +99,9 @@ public class QEducationalContextsAdminController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.id.i18nKey(), Cols.id.ordinal(), true, "key")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.level.i18nKey(), Cols.level.ordinal(), true, "level")); FlexiCellRenderer renderer = new StaticFlexiCellRenderer("translate", new TextFlexiCellRenderer()); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.levelI18n.i18nKey(), Cols.levelI18n.ordinal(), "translate", renderer)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.levelI18n.i18nKey(), Cols.levelI18n.ordinal(), "translate", renderer)); FlexiCellRenderer delRenderer = new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("delete"), "delete-level"), null); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", Cols.deletable.ordinal(), "delete-level", delRenderer)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", Cols.deletable.ordinal(), "delete-level", delRenderer)); model = new LevelDataModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "levels", model, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java b/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java index e13ba5480d78f0fd2b126b3056059542537a9f34..642f79fda562daf1438017ead6024a7789309bb4 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java +++ b/src/main/java/org/olat/modules/qpool/ui/admin/QItemTypesAdminController.java @@ -40,7 +40,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.table.TableDataModel; @@ -100,9 +99,9 @@ public class QItemTypesAdminController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.id.i18nKey(), Cols.id.ordinal(), true, "key")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.type.i18nKey(), Cols.type.ordinal(), true, "name")); FlexiCellRenderer renderer = new StaticFlexiCellRenderer("translate", new TextFlexiCellRenderer()); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.typeI18n.i18nKey(), Cols.typeI18n.ordinal(), "translate", renderer)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.typeI18n.i18nKey(), Cols.typeI18n.ordinal(), "translate", renderer)); FlexiCellRenderer delRenderer = new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("delete"), "delete-type"), null); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", Cols.deletable.ordinal(), "delete-type", delRenderer)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", Cols.deletable.ordinal(), "delete-type", delRenderer)); model = new QItemTypeDataModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "types", model, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/QLicensesAdminController.java b/src/main/java/org/olat/modules/qpool/ui/admin/QLicensesAdminController.java index 1041d9cd247edbc7e49361175d6653c3213fd819..b6066fe115b34b79b265a9bac9402ab71c700653 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/QLicensesAdminController.java +++ b/src/main/java/org/olat/modules/qpool/ui/admin/QLicensesAdminController.java @@ -39,7 +39,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.table.TableDataModel; import org.olat.core.gui.control.Controller; @@ -94,7 +93,7 @@ public class QLicensesAdminController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.id.i18nKey(), Cols.id.ordinal(), true, "key")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.licenseKey.i18nKey(), Cols.licenseKey.ordinal(), true, "licenseKey")); FlexiCellRenderer delRenderer = new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("delete"), "delete-license"), null); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", Cols.deletable.ordinal(), "delete-license", delRenderer)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", Cols.deletable.ordinal(), "delete-license", delRenderer)); model = new QItemTypeDataModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "licenses", model, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/portfolio/manager/EPFrontendManager.java b/src/main/java/org/olat/portfolio/manager/EPFrontendManager.java index 4021208046e37fbf669e9cf821cee9c9a24434fc..888e40f279ad3e2d5ef2443970686f159cd1965f 100755 --- a/src/main/java/org/olat/portfolio/manager/EPFrontendManager.java +++ b/src/main/java/org/olat/portfolio/manager/EPFrontendManager.java @@ -46,7 +46,7 @@ import org.olat.core.util.vfs.VFSContainer; import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentManager; -import org.olat.course.assessment.AssessmentNotificationsHandler; +import org.olat.course.assessment.manager.AssessmentNotificationsHandler; import org.olat.course.nodes.CourseNode; import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironmentImpl; diff --git a/src/main/java/org/olat/repository/ui/LifecycleAdminController.java b/src/main/java/org/olat/repository/ui/LifecycleAdminController.java index c805505595fd3037d9015b0b4b0dbe4978710114..df3515949583419c846826ae06d5531be7bccee1 100644 --- a/src/main/java/org/olat/repository/ui/LifecycleAdminController.java +++ b/src/main/java/org/olat/repository/ui/LifecycleAdminController.java @@ -37,7 +37,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable 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.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -89,8 +88,8 @@ public class LifecycleAdminController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(LCCols.validTo.i18nKey(), LCCols.validTo.ordinal())); FlexiCellRenderer delRenderer = new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("delete"), "delete-cycle"), null); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("delete", LCCols.delete.ordinal(), "delete-cycle", delRenderer)); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("edit", translate(LCCols.edit.i18nKey()), "edit-lifecycle")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("delete", LCCols.delete.ordinal(), "delete-cycle", delRenderer)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("edit", translate(LCCols.edit.i18nKey()), "edit-lifecycle")); model = new LifecycleDataModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "cycles", model, getTranslator(), formLayout); diff --git a/src/main/java/org/olat/repository/ui/author/AuthorListController.java b/src/main/java/org/olat/repository/ui/author/AuthorListController.java index 86dc47a69d3e8ca562ea7a185cbef4a92b2d3f8f..b2e9853672cf97d569daeb55bbb15c6e2fea58e4 100644 --- a/src/main/java/org/olat/repository/ui/author/AuthorListController.java +++ b/src/main/java/org/olat/repository/ui/author/AuthorListController.java @@ -55,7 +55,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; @@ -246,7 +245,7 @@ public class AuthorListController extends FormBasicController implements Activat columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.type.i18nKey(), Cols.type.ordinal(), true, OrderBy.type.name(), FlexiColumnModel.ALIGNMENT_LEFT, new TypeRenderer())); FlexiCellRenderer renderer = new StaticFlexiCellRenderer("select", new TextFlexiCellRenderer()); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.displayName.i18nKey(), Cols.displayName.ordinal(), "select", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName.i18nKey(), Cols.displayName.ordinal(), "select", true, OrderBy.displayname.name(), renderer)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.authors.i18nKey(), Cols.authors.ordinal(), true, OrderBy.authors.name())); @@ -274,10 +273,10 @@ public class AuthorListController extends FormBasicController implements Activat true, OrderBy.creationDate.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.lastUsage.i18nKey(), Cols.lastUsage.ordinal(), true, OrderBy.lastUsage.name())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.detailsSupported.i18nKey(), Cols.detailsSupported.ordinal(), "details", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.detailsSupported.i18nKey(), Cols.detailsSupported.ordinal(), "details", new StaticFlexiCellRenderer("", "details", "o_icon o_icon-lg o_icon_details", translate("details")))); if(hasAuthorRight) { - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.editionSupported.i18nKey(), Cols.editionSupported.ordinal(), "edit", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.editionSupported.i18nKey(), Cols.editionSupported.ordinal(), "edit", new BooleanCellRenderer(new StaticFlexiCellRenderer("", "edit", "o_icon o_icon-lg o_icon_edit", translate("edit")), null))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.tools.i18nKey(), Cols.tools.ordinal())); } diff --git a/src/main/java/org/olat/repository/ui/author/CatalogSettingsController.java b/src/main/java/org/olat/repository/ui/author/CatalogSettingsController.java index 53759b6edf5b8a4b356d1f9b585c20ec276c9b83..fa051cb5a532b8da234fb641f1ca6a6886f14dbb 100644 --- a/src/main/java/org/olat/repository/ui/author/CatalogSettingsController.java +++ b/src/main/java/org/olat/repository/ui/author/CatalogSettingsController.java @@ -34,7 +34,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFle import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.stack.TooledStackedPanel; @@ -94,7 +93,7 @@ public class CatalogSettingsController extends FormBasicController { protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("catalog.path", 0)); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel("remove", translate("remove"), "remove")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("remove", translate("remove"), "remove")); List<CatalogEntry> catalogEntries = catalogManager.getCatalogCategoriesFor(entry); model = new CategoriesListModel(catalogEntries, columnsModel); diff --git a/src/main/java/org/olat/repository/ui/catalog/CatalogNodeManagerController.java b/src/main/java/org/olat/repository/ui/catalog/CatalogNodeManagerController.java index 09df1e365dadc4e846ebc10842253c40663f9d05..759291a975e7a94dc7ebac2b40014b802cacf6c7 100644 --- a/src/main/java/org/olat/repository/ui/catalog/CatalogNodeManagerController.java +++ b/src/main/java/org/olat/repository/ui/catalog/CatalogNodeManagerController.java @@ -47,7 +47,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; -import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; @@ -221,7 +220,7 @@ public class CatalogNodeManagerController extends FormBasicController implements columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.type.i18nKey(), Cols.type.ordinal(), true, OrderBy.type.name(), FlexiColumnModel.ALIGNMENT_LEFT, new TypeRenderer())); FlexiCellRenderer renderer = new StaticFlexiCellRenderer("select", new TextFlexiCellRenderer()); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.displayName.i18nKey(), Cols.displayName.ordinal(), "select", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName.i18nKey(), Cols.displayName.ordinal(), "select", true, OrderBy.displayname.name(), renderer)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.authors.i18nKey(), Cols.authors.ordinal(), true, OrderBy.authors.name())); @@ -245,9 +244,9 @@ public class CatalogNodeManagerController extends FormBasicController implements true, OrderBy.ac.name(), FlexiColumnModel.ALIGNMENT_LEFT, new ACRenderer())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.creationDate.i18nKey(), Cols.creationDate.ordinal(), true, OrderBy.creationDate.name())); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.delete.i18nKey(), translate(Cols.delete.i18nKey()), "delete")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.move.i18nKey(), translate(Cols.move.i18nKey()), "move")); - columnsModel.addFlexiColumnModel(new StaticFlexiColumnModel(Cols.detailsSupported.i18nKey(), Cols.detailsSupported.ordinal(), "details", + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.delete.i18nKey(), translate(Cols.delete.i18nKey()), "delete")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.move.i18nKey(), translate(Cols.move.i18nKey()), "move")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.detailsSupported.i18nKey(), Cols.detailsSupported.ordinal(), "details", new StaticFlexiCellRenderer("", "details", "o_icon o_icon-lg o_icon_details", translate("details")))); entriesModel = new CatalogEntryRowModel(columnsModel); diff --git a/src/main/java/org/olat/restapi/repository/course/CourseAssessmentWebService.java b/src/main/java/org/olat/restapi/repository/course/CourseAssessmentWebService.java index 80634f5b536e608feb0ef2376943a9923c12de97..179c2290e97df3d6e8e5cac796176015e8d9838f 100644 --- a/src/main/java/org/olat/restapi/repository/course/CourseAssessmentWebService.java +++ b/src/main/java/org/olat/restapi/repository/course/CourseAssessmentWebService.java @@ -50,7 +50,6 @@ import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityManager; import org.olat.basesecurity.GroupRoles; import org.olat.core.CoreSpringFactory; -import org.olat.core.commons.persistence.DBFactory; import org.olat.core.id.Identity; import org.olat.core.id.IdentityEnvironment; import org.olat.core.logging.OLog; @@ -61,7 +60,6 @@ import org.olat.course.assessment.AssessmentManager; import org.olat.course.nodes.AssessableCourseNode; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.IQTESTCourseNode; -import org.olat.course.properties.CoursePropertyManager; import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.scoring.ScoreAccounting; import org.olat.course.run.scoring.ScoreEvaluation; @@ -83,7 +81,6 @@ import org.olat.ims.qti.process.AssessmentFactory; import org.olat.ims.qti.process.AssessmentInstance; import org.olat.modules.ModuleConfiguration; import org.olat.modules.iq.IQManager; -import org.olat.properties.Property; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; import org.olat.repository.RepositoryService; @@ -555,30 +552,8 @@ public class CourseAssessmentWebService { } private Date getLastModificationDate(Identity assessedIdentity, ICourse course, CourseNode courseNode) { - //try to load the exact score prpoerty saved on the DB - - final CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager(); - Property scoreProperty = cpm.findCourseNodeProperty(courseNode, assessedIdentity, null, AssessmentManager.SCORE); - if(scoreProperty != null) { - return scoreProperty.getLastModified(); - } - - //last change in course - StringBuilder sb = new StringBuilder(); - sb.append("select max(p.lastModified) from ").append(Property.class.getName()).append(" as p where") - .append(" p.resourceTypeName = :restypename and p.resourceTypeId = :restypeid") - .append(" and p.name = '").append(AssessmentManager.SCORE).append("'") - .append(" and p.identity = :id"); - List<Date> properties = DBFactory.getInstance().getCurrentEntityManager() - .createQuery(sb.toString(), Date.class) - .setParameter("restypename", course.getResourceableTypeName()) - .setParameter("restypeid", course.getResourceableId().longValue()) - .setParameter("id", assessedIdentity) - .getResultList(); - if(!properties.isEmpty()) { - return properties.get(0); - } - return null; + AssessmentManager am = course.getCourseEnvironment().getAssessmentManager(); + return am.getScoreLastModifiedDate(courseNode, assessedIdentity); } private List<Identity> loadUsers(ICourse course) { diff --git a/src/main/java/org/olat/upgrade/OLATUpgrade_11_0_0.java b/src/main/java/org/olat/upgrade/OLATUpgrade_11_0_0.java new file mode 100644 index 0000000000000000000000000000000000000000..f3ebb73a8985ebc2120daa63599a0e4514c708a0 --- /dev/null +++ b/src/main/java/org/olat/upgrade/OLATUpgrade_11_0_0.java @@ -0,0 +1,595 @@ +/** + * <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.upgrade; + +import static org.olat.upgrade.legacy.NewCachePersistingAssessmentManager.ASSESSMENT_ID; +import static org.olat.upgrade.legacy.NewCachePersistingAssessmentManager.ATTEMPTS; +import static org.olat.upgrade.legacy.NewCachePersistingAssessmentManager.COACH_COMMENT; +import static org.olat.upgrade.legacy.NewCachePersistingAssessmentManager.COMMENT; +import static org.olat.upgrade.legacy.NewCachePersistingAssessmentManager.FULLY_ASSESSED; +import static org.olat.upgrade.legacy.NewCachePersistingAssessmentManager.PASSED; +import static org.olat.upgrade.legacy.NewCachePersistingAssessmentManager.SCORE; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.olat.basesecurity.GroupRoles; +import org.olat.core.commons.persistence.DB; +import org.olat.core.commons.persistence.DBFactory; +import org.olat.core.id.Identity; +import org.olat.core.id.Roles; +import org.olat.core.util.StringHelper; +import org.olat.core.util.cache.CacheWrapper; +import org.olat.course.CourseFactory; +import org.olat.course.ICourse; +import org.olat.course.nodes.CourseNode; +import org.olat.course.tree.CourseEditorTreeNode; +import org.olat.group.BusinessGroup; +import org.olat.group.BusinessGroupService; +import org.olat.group.model.SearchBusinessGroupParams; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.model.AssessmentEntryImpl; +import org.olat.properties.Property; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; +import org.olat.repository.RepositoryService; +import org.olat.repository.model.SearchRepositoryEntryParameters; +import org.olat.upgrade.legacy.NewCacheKey; +import org.olat.upgrade.legacy.NewCachePersistingAssessmentManager; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 27.03.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class OLATUpgrade_11_0_0 extends OLATUpgrade { + + private static final int BATCH_SIZE = 50; + private static final String ASSESSMENT_DATAS = "ASSESSMENT PROPERTY TABLE"; + private static final String VERSION = "OLAT_11.0.0"; + + @Autowired + private DB dbInstance; + @Autowired + private RepositoryManager repositoryManager; + @Autowired + private BusinessGroupService businessGroupService; + @Autowired + private RepositoryService repositoryService; + + public OLATUpgrade_11_0_0() { + super(); + } + + @Override + public String getVersion() { + return VERSION; + } + + @Override + public boolean doPreSystemInitUpgrade(UpgradeManager upgradeManager) { + return false; + } + + @Override + public boolean doPostSystemInitUpgrade(UpgradeManager upgradeManager) { + UpgradeHistoryData uhd = upgradeManager.getUpgradesHistory(VERSION); + if (uhd == null) { + // has never been called, initialize + uhd = new UpgradeHistoryData(); + } else if (uhd.isInstallationComplete()) { + return false; + } + + boolean allOk = true; + allOk &= upgradeAssessmentPropertyTable(upgradeManager, uhd); + + uhd.setInstallationComplete(allOk); + upgradeManager.setUpgradesHistory(uhd, VERSION); + if(allOk) { + log.audit("Finished OLATUpgrade_11_0_0 successfully!"); + } else { + log.audit("OLATUpgrade_11_0_0 not finished, try to restart OpenOLAT!"); + } + return allOk; + } + + private boolean upgradeAssessmentPropertyTable(UpgradeManager upgradeManager, UpgradeHistoryData uhd) { + boolean allOk = true; + if (!uhd.getBooleanDataValue(ASSESSMENT_DATAS)) { + int counter = 0; + final Roles roles = new Roles(true, true, true, true, false, true, false); + final SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters(); + params.setRoles(roles); + params.setResourceTypes(Collections.singletonList("CourseModule")); + + List<RepositoryEntry> courses; + do { + courses = repositoryManager.genericANDQueryWithRolesRestriction(params, counter, 50, true); + for(RepositoryEntry course:courses) { + allOk &= processCourseAssessmentData(course); + } + counter += courses.size(); + log.audit("Assessment data migration processed: " + courses.size() + ", total processed (" + counter + ")"); + dbInstance.commitAndCloseSession(); + } while(courses.size() == BATCH_SIZE); + uhd.setBooleanDataValue(ASSESSMENT_DATAS, allOk); + upgradeManager.setUpgradesHistory(uhd, VERSION); + } + return allOk; + } + + // select count(*) from o_property where name in ('SCORE','PASSED','ATTEMPTS','COMMENT','COACH_COMMENT','ASSESSMENT_ID','FULLY_ASSESSED'); + private boolean processCourseAssessmentData(RepositoryEntry courseEntry) { + Long courseResourceId = courseEntry.getOlatResource().getResourceableId(); + + //load already migrated data + List<AssessmentEntryImpl> currentNodeAssessmentList = loadAssessmentEntries(courseEntry); + Map<AssessmentDataKey,AssessmentEntryImpl> curentNodeAssessmentMap = new HashMap<>(); + for(AssessmentEntryImpl currentNodeAssessment:currentNodeAssessmentList) { + AssessmentDataKey key = new AssessmentDataKey(currentNodeAssessment.getIdentity(), courseResourceId, currentNodeAssessment.getSubIdent()); + curentNodeAssessmentMap.put(key, currentNodeAssessment); + } + + Map<AssessmentDataKey,AssessmentEntryImpl> nodeAssessmentMap = new HashMap<>(); + + List<Property> courseProperties = loadAssessmentProperties(courseEntry); + for(Property property:courseProperties) { + String propertyCategory = property.getCategory(); + if(StringHelper.containsNonWhitespace(propertyCategory)) { + int nodeIdentIndex = propertyCategory.indexOf("::"); + if(nodeIdentIndex > 0) { + String nodeIdent = propertyCategory.substring(propertyCategory.indexOf("::") + 2); + AssessmentDataKey key = new AssessmentDataKey(property.getIdentity(), property.getResourceTypeId(), nodeIdent); + if(curentNodeAssessmentMap.containsKey(key)) { + continue; + } + + AssessmentEntryImpl nodeAssessment; + if(nodeAssessmentMap.containsKey(key)) { + nodeAssessment = nodeAssessmentMap.get(key); + if(nodeAssessment.getCreationDate().after(property.getCreationDate())) { + nodeAssessment.setCreationDate(property.getCreationDate()); + } + + if(nodeAssessment.getLastModified().before(property.getLastModified())) { + nodeAssessment.setLastModified(property.getLastModified()); + } + } else { + nodeAssessment = createAssessmentEntry(property, courseEntry, nodeIdent, courseEntry); + } + copyAssessmentProperty(property, nodeAssessment); + nodeAssessmentMap.put(key, nodeAssessment); + } + } + } + + int count = 0; + for(AssessmentEntryImpl courseNodeAssessment:nodeAssessmentMap.values()) { + dbInstance.getCurrentEntityManager().persist(courseNodeAssessment); + if(++count % 50 == 0) { + dbInstance.commit(); + } + } + dbInstance.commitAndCloseSession(); + + return verifyCourseAssessmentData(courseEntry); + } + + /** + * The method compare the content of the cache used in assessment tool + * with the migrated values and vice versa. + * + * @param courseEntry + * @return + */ + private boolean verifyCourseAssessmentData(RepositoryEntry courseEntry) { + //load the cache and fill it with the same amount of datas as in assessment tool + ICourse course = CourseFactory.loadCourse(courseEntry.getOlatResource()); + StaticCacheWrapper cache = new StaticCacheWrapper(); + NewCachePersistingAssessmentManager assessmentManager = new NewCachePersistingAssessmentManager(course, cache); + List<Identity> assessableIdentities = getAllAssessableIdentities(courseEntry); + assessmentManager.preloadCache(assessableIdentities); + dbInstance.commitAndCloseSession(); + + Set<Identity> assessableIdentitySet = new HashSet<>(assessableIdentities); + List<AssessmentEntryImpl> nodeAssessments = loadAssessmentEntries(courseEntry); + Map<AssessmentDataKey, AssessmentEntryImpl> nodeAssessmentMap = new HashMap<>(); + for(AssessmentEntryImpl nodeAssessment:nodeAssessments) { + if(!assessableIdentitySet.contains(nodeAssessment.getIdentity())) { + assessmentManager.preloadCache(nodeAssessment.getIdentity()); + } + if(nodeAssessment.getIdentity() != null && nodeAssessment.getRepositoryEntry() != null + && nodeAssessment.getRepositoryEntry().getOlatResource() != null) { + nodeAssessmentMap.put(new AssessmentDataKey(nodeAssessment), nodeAssessment); + } + } + dbInstance.commitAndCloseSession(); + + //compare the value in CourseNodeAssessment with the content of the cache + boolean allOk = true; + for(AssessmentEntryImpl nodeAssessment:nodeAssessments) { + allOk &= compareCourseNodeAssessment(nodeAssessment, assessmentManager, course, courseEntry); + } + dbInstance.commitAndCloseSession(); + + //compare the content of the cache with the CourseNodeAssessments + for(NewCacheKey cacheKey:cache.getKeys()) { + Map<String,Serializable> dataMap = cache.get(cacheKey); + Long identityKey = cacheKey.getIdentityKey(); + for(Map.Entry<String, Serializable> data:dataMap.entrySet()) { + String key = data.getKey(); + int index = key.indexOf("_"); + if(index > 0 && !key.equals("LAST_MODIFIED")) { + String nodeIdent = key.substring(0, index); + String dataType = key.substring(index + 1); + + AssessmentDataKey assessmentDataKey = new AssessmentDataKey(identityKey, course.getResourceableId(), nodeIdent); + AssessmentEntryImpl nodeAssessment = nodeAssessmentMap.get(assessmentDataKey); + allOk &= compareProperty(dataType, data.getValue(), nodeAssessment, courseEntry, nodeIdent, identityKey); + } + } + } + dbInstance.commitAndCloseSession(); + + if(!allOk) { + log.error("Critical error during course verification: " + courseEntry.getDisplayname() + "(" + courseEntry.getKey() + ")"); + } + return allOk; + } + + private boolean compareProperty(String dataType, Serializable value, AssessmentEntryImpl nodeAssessment, RepositoryEntry courseEntry, String nodeIdent, Long identityKey) { + boolean allOk = true; + if(nodeAssessment == null) { + log.audit("ERROR nodeAssessment not found: " + getErrorAt(courseEntry, nodeIdent, identityKey)); + allOk = false; + } else if(ATTEMPTS.equals(dataType)) { + if((value == null && nodeAssessment.getAttempts() == null) || + (value != null && nodeAssessment.getAttempts() != null && value.equals(nodeAssessment.getAttempts()))) { + //ok + } else { + log.audit("ERROR number of attempts: " + value + " / " + nodeAssessment.getAttempts() + getErrorAt(courseEntry, nodeIdent, identityKey)); + allOk &= false; + } + } else if(PASSED.equals(dataType)) { + if((value == null && nodeAssessment.getPassed() == null) || + (value != null && nodeAssessment.getPassed() != null && value.equals(nodeAssessment.getPassed()))) { + //ok + } else { + log.audit("ERROR passed: " + value + " / " + nodeAssessment.getPassed() + getErrorAt(courseEntry, nodeIdent, identityKey)); + allOk &= false; + } + } else if(FULLY_ASSESSED.equals(dataType)) { + if((value == null && nodeAssessment.getFullyAssessed() == null) || + (value != null && nodeAssessment.getFullyAssessed() != null && value.equals(nodeAssessment.getFullyAssessed()))) { + //ok + } else { + log.audit("ERROR fullyAssessed: " + value + " / " + nodeAssessment.getFullyAssessed() + getErrorAt(courseEntry, nodeIdent, identityKey)); + allOk &= false; + } + } else if(SCORE.equals(dataType)) { + if((value == null && nodeAssessment.getScore() == null) || + (value instanceof Float && nodeAssessment.getScore() != null && Math.abs(((Float)value).floatValue() - nodeAssessment.getScore().floatValue()) < 0.00001f)) { + //ok + } else { + log.audit("ERROR score: " + value + " / " + nodeAssessment.getScore() + getErrorAt(courseEntry, nodeIdent, identityKey)); + allOk &= false; + } + } + return allOk; + } + + private String getErrorAt(RepositoryEntry courseEntry, String nodeIdent, Long identityKey) { + return " at course : " + courseEntry.getDisplayname() + " (" + courseEntry.getKey() + ")" + + " at node: " + nodeIdent + " for identity: " + identityKey; + } + + private boolean compareCourseNodeAssessment(AssessmentEntryImpl entry, NewCachePersistingAssessmentManager assessmentManager, + ICourse course, RepositoryEntry courseEntry) { + CourseNode node = course.getRunStructure().getNode(entry.getSubIdent()); + if(node == null) { + CourseEditorTreeNode editorNode = course.getEditorTreeModel().getCourseEditorNodeById(entry.getSubIdent()); + if(editorNode != null) { + node = editorNode.getCourseNode(); + } + } + + boolean allOk = true; + if(node != null) { + Identity assessedIdentity = entry.getIdentity(); + + Integer attempts = assessmentManager.getNodeAttempts(node, assessedIdentity); + if((attempts == null && entry.getAttempts() == null) || + (attempts != null && entry.getAttempts() != null && attempts.equals(entry.getAttempts()))) { + //ok + } else { + log.audit("ERROR number of attempts: " + attempts + " / " + entry.getAttempts() + getErrorAt(courseEntry, node)); + allOk &= false; + } + + Boolean passed = assessmentManager.getNodePassed(node, assessedIdentity); + if((passed == null && entry.getPassed() == null) || + (passed != null && entry.getPassed() != null && passed.equals(entry.getPassed()))) { + //ok + } else { + log.audit("ERROR passed: " + passed + " / " + entry.getPassed() + getErrorAt(courseEntry, node)); + allOk &= false; + } + + Boolean fullyAssessed = assessmentManager.getNodeFullyAssessed(node, assessedIdentity); + if((fullyAssessed == null && entry.getFullyAssessed() == null) || + (fullyAssessed != null && entry.getFullyAssessed() != null && fullyAssessed.equals(entry.getFullyAssessed()))) { + //ok + } else { + log.audit("ERROR fullyAssessed: " + fullyAssessed + " / " + entry.getFullyAssessed() + getErrorAt(courseEntry, node)); + allOk &= false; + } + + Float score = assessmentManager.getNodeScore(node, assessedIdentity); + if((score == null && entry.getScore() == null) || + (score != null && entry.getScore() != null && Math.abs(score.floatValue() - entry.getScore().floatValue()) < 0.00001f)) { + //ok + } else { + log.audit("ERROR score: " + score + " / " + entry.getScore() + getErrorAt(courseEntry, node)); + allOk &= false; + } + } + return allOk; + } + + private String getErrorAt(RepositoryEntry courseEntry, CourseNode courseNode) { + return " at course : " + courseEntry.getDisplayname() + " (" + courseEntry.getKey() + ")" + + " at node: " + courseNode.getShortTitle() + " (" + courseNode.getIdent() + ")"; + } + + /** + * Return the same amount of user as in the assessment tool. + * @param entry + * @return + */ + private List<Identity> getAllAssessableIdentities(RepositoryEntry entry) { + Set<Identity> duplicateKiller = new HashSet<>(); + List<Identity> assessableIdentities = new ArrayList<>(); + + SearchBusinessGroupParams params = new SearchBusinessGroupParams(); + List<BusinessGroup> coachedGroups = businessGroupService.findBusinessGroups(params, entry, 0, -1); + + List<Identity> participants = businessGroupService.getMembers(coachedGroups, GroupRoles.participant.name()); + for(Identity participant:participants) { + if(!duplicateKiller.contains(participant)) { + assessableIdentities.add(participant); + duplicateKiller.add(participant); + } + } + + + List<Identity> courseParticipants = repositoryService.getMembers(entry, GroupRoles.participant.name()); + for(Identity participant:courseParticipants) { + if(!duplicateKiller.contains(participant)) { + assessableIdentities.add(participant); + duplicateKiller.add(participant); + } + } + + ICourse course = CourseFactory.loadCourse(entry.getOlatResource()); + List<Identity> assessedUsers = getAllIdentitiesWithCourseAssessmentData(course.getResourceableId()); + for(Identity assessedUser:assessedUsers) { + if(!duplicateKiller.contains(assessedUser)) { + assessableIdentities.add(assessedUser); + duplicateKiller.add(assessedUser); + } + } + + return assessableIdentities; + } + + private List<Identity> getAllIdentitiesWithCourseAssessmentData(Long resourceId) { + StringBuilder query = new StringBuilder(); + query.append("select p.identity from ") + .append(Property.class.getName()).append(" as p") + .append(" where p.resourceTypeName = 'CourseModule'") + .append(" and p.resourceTypeId = :resid") + .append(" and p.identity is not null") + .append(" and p.name in ('").append(SCORE).append("','").append(PASSED).append("')"); + + return DBFactory.getInstance().getCurrentEntityManager() + .createQuery(query.toString(), Identity.class) + .setParameter("resid", resourceId) + .getResultList(); + } + + private AssessmentEntryImpl createAssessmentEntry(Property property, RepositoryEntry courseEntry, + String nodeIdent, RepositoryEntry referenceEntry) { + AssessmentEntryImpl entry = new AssessmentEntryImpl(); + entry.setCreationDate(property.getCreationDate()); + entry.setLastModified(property.getLastModified()); + entry.setIdentity(property.getIdentity()); + entry.setRepositoryEntry(courseEntry); + entry.setSubIdent(nodeIdent); + entry.setReferenceEntry(referenceEntry); + return entry; + } + + private void copyAssessmentProperty(Property property, AssessmentEntry nodeAssessment) { + String propertyName = property.getName(); + if (propertyName.equals(ATTEMPTS)) { + if(property.getLongValue() != null) { + nodeAssessment.setAttempts(property.getLongValue().intValue()); + } + } else if (propertyName.equals(SCORE)) { + if(property.getFloatValue() != null) { + BigDecimal score = new BigDecimal(Float.toString(property.getFloatValue().floatValue())); + nodeAssessment.setScore(score); + } + } else if (propertyName.equals(PASSED)) { + if(StringHelper.containsNonWhitespace(property.getStringValue())) { + nodeAssessment.setPassed(new Boolean(property.getStringValue())); + } + } else if(propertyName.equals(FULLY_ASSESSED)) { + if(StringHelper.containsNonWhitespace(property.getStringValue())) { + nodeAssessment.setFullyAssessed(new Boolean(property.getStringValue())); + } + } else if (propertyName.equals(ASSESSMENT_ID)) { + nodeAssessment.setAssessmentId(property.getLongValue()); + } else if (propertyName.equals(COMMENT)) { + nodeAssessment.setComment(property.getTextValue()); + } else if(propertyName.equals(COACH_COMMENT)) { + nodeAssessment.setCoachComment(property.getTextValue()); + } + } + + private List<AssessmentEntryImpl> loadAssessmentEntries(RepositoryEntry courseEntry) { + String sb = "select data from assessmententry data where data.repositoryEntry.key=:courseEntryKey"; + return dbInstance.getCurrentEntityManager() + .createQuery(sb, AssessmentEntryImpl.class) + .setParameter("courseEntryKey", courseEntry.getKey()) + .getResultList(); + } + + private List<Property> loadAssessmentProperties(RepositoryEntry course) { + StringBuilder sb = new StringBuilder(); + sb.append("from org.olat.properties.Property as p") + .append(" inner join fetch p.identity as ident ") + .append(" inner join fetch ident.user as user ") + .append(" where p.resourceTypeId = :restypeid and p.resourceTypeName = :restypename") + .append(" and p.name in ('") + .append(ATTEMPTS).append("','") + .append(SCORE).append("','") + .append(FULLY_ASSESSED).append("','") + .append(PASSED).append("','") + .append(ASSESSMENT_ID).append("','") + .append(COMMENT).append("','") + .append(COACH_COMMENT) + .append("')"); + + return dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Property.class) + .setParameter("restypename", course.getOlatResource().getResourceableTypeName()) + .setParameter("restypeid", course.getOlatResource().getResourceableId()) + .getResultList(); + } + + private static class AssessmentDataKey { + + private final Long courseId; + private final Long identityKey; + private final String courseNodeIdent; + + public AssessmentDataKey(Identity identity, Long courseOresId, String courseNodeIdent) { + this.courseId = courseOresId; + this.identityKey = identity.getKey(); + this.courseNodeIdent = courseNodeIdent; + } + + public AssessmentDataKey(Long identityKey, Long courseOresId, String courseNodeIdent) { + this.courseId = courseOresId; + this.identityKey = identityKey; + this.courseNodeIdent = courseNodeIdent; + } + + public AssessmentDataKey(AssessmentEntry nodeAssessment) { + this.courseId = nodeAssessment.getRepositoryEntry().getOlatResource().getResourceableId(); + this.identityKey = nodeAssessment.getIdentity().getKey(); + this.courseNodeIdent = nodeAssessment.getSubIdent(); + } + + @Override + public int hashCode() { + return (courseId == null ? 32876 : courseId.hashCode()) + + (identityKey == null ? 7525 : identityKey.hashCode()) + + (courseNodeIdent == null ? 39841 : courseNodeIdent.hashCode()); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof AssessmentDataKey) { + AssessmentDataKey key = (AssessmentDataKey)obj; + return courseId != null && courseId.equals(key.courseId) + && identityKey != null && identityKey.equals(key.identityKey) + && courseNodeIdent != null && courseNodeIdent.equals(key.courseNodeIdent); + } + return false; + } + } + + private static class StaticCacheWrapper implements CacheWrapper<NewCacheKey,HashMap<String, Serializable>> { + + private ConcurrentHashMap<NewCacheKey,HashMap<String, Serializable>> map = new ConcurrentHashMap<>(); + + @Override + public boolean containsKey(NewCacheKey key) { + return map.containsKey(key); + } + + @Override + public HashMap<String, Serializable> get(NewCacheKey key) { + return map.get(key); + } + + @Override + public HashMap<String, Serializable> update(NewCacheKey key, HashMap<String, Serializable> value) { + return map.put(key, value); + } + + @Override + public HashMap<String, Serializable> put(NewCacheKey key, HashMap<String, Serializable> value) { + return map.put(key, value); + } + + @Override + public HashMap<String, Serializable> putIfAbsent(NewCacheKey key, HashMap<String, Serializable> value) { + return map.putIfAbsent(key, value); + } + + @Override + public List<NewCacheKey> getKeys() { + return new ArrayList<>(map.keySet()); + } + + @Override + public HashMap<String, Serializable> remove(NewCacheKey key) { + return map.remove(key); + } + + @Override + public int size() { + return map.size(); + } + + @Override + public Iterator<NewCacheKey> iterateKeys() { + return map.keySet().iterator(); + } + } +} diff --git a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml index 52fdefa2e8b22db8991d2fd271d27cc97e964ca7..d216c12061a06da2c7e2a326e7708edd5a6337d7 100644 --- a/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml +++ b/src/main/java/org/olat/upgrade/_spring/upgradeContext.xml @@ -44,6 +44,7 @@ <bean id="upgrade_10_0_3" class="org.olat.upgrade.OLATUpgrade_10_0_3"/> <bean id="upgrade_10_1_0" class="org.olat.upgrade.OLATUpgrade_10_1_0"/> <bean id="upgrade_10_3_0" class="org.olat.upgrade.OLATUpgrade_10_3_0"/> + <bean id="upgrade_11_0_0" class="org.olat.upgrade.OLATUpgrade_11_0_0"/> </list> </property> </bean> diff --git a/src/main/java/org/olat/course/assessment/NewCacheKey.java b/src/main/java/org/olat/upgrade/legacy/NewCacheKey.java similarity index 98% rename from src/main/java/org/olat/course/assessment/NewCacheKey.java rename to src/main/java/org/olat/upgrade/legacy/NewCacheKey.java index 30b8f2c33080fb6bc7776997a855107071302e11..cdaa56a697952d124f56c5cce4c0cef09da70504 100644 --- a/src/main/java/org/olat/course/assessment/NewCacheKey.java +++ b/src/main/java/org/olat/upgrade/legacy/NewCacheKey.java @@ -17,7 +17,7 @@ * frentix GmbH, http://www.frentix.com * <p> */ -package org.olat.course.assessment; +package org.olat.upgrade.legacy; import java.io.Serializable; diff --git a/src/main/java/org/olat/course/assessment/NewCachePersistingAssessmentManager.java b/src/main/java/org/olat/upgrade/legacy/NewCachePersistingAssessmentManager.java similarity index 97% rename from src/main/java/org/olat/course/assessment/NewCachePersistingAssessmentManager.java rename to src/main/java/org/olat/upgrade/legacy/NewCachePersistingAssessmentManager.java index 89609755385339918ddfa3217ac4d20ae660e84d..472f747e5c1cc6b3e360689c25eb822b07e1baca 100644 --- a/src/main/java/org/olat/course/assessment/NewCachePersistingAssessmentManager.java +++ b/src/main/java/org/olat/upgrade/legacy/NewCachePersistingAssessmentManager.java @@ -23,7 +23,7 @@ * under the Apache 2.0 license as the original file. */ -package org.olat.course.assessment; +package org.olat.upgrade.legacy; import java.io.Serializable; import java.util.ArrayList; @@ -45,7 +45,6 @@ import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.logging.activity.StringResourceableType; import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; -import org.olat.core.manager.BasicManager; import org.olat.core.util.StringHelper; import org.olat.core.util.cache.CacheWrapper; import org.olat.core.util.coordinate.CoordinatorManager; @@ -56,6 +55,10 @@ import org.olat.core.util.mail.MailerResult; import org.olat.core.util.resource.OresHelper; import org.olat.course.CourseFactory; import org.olat.course.ICourse; +import org.olat.course.assessment.AssessmentChangedEvent; +import org.olat.course.assessment.AssessmentLoggingAction; +import org.olat.course.assessment.AssessmentManager; +import org.olat.course.assessment.EfficiencyStatementManager; import org.olat.course.auditing.UserNodeAuditManager; import org.olat.course.certificate.CertificateTemplate; import org.olat.course.certificate.CertificatesManager; @@ -106,9 +109,18 @@ import org.olat.util.logging.activity.LoggingResourceable; * * @author Felix Jost */ -public class NewCachePersistingAssessmentManager extends BasicManager implements AssessmentManager { +public class NewCachePersistingAssessmentManager { private static final OLog log = Tracing.createLoggerFor(NewCachePersistingAssessmentManager.class); + + public static final String SCORE = "SCORE"; + public static final String PASSED = "PASSED"; + public static final String ATTEMPTS = "ATTEMPTS"; + public static final String COMMENT = "COMMENT"; + public static final String COACH_COMMENT = "COACH_COMMENT"; + public static final String ASSESSMENT_ID = "ASSESSMENT_ID"; + + public final static String FULLY_ASSESSED = "FULLY_ASSESSED"; /** * the key under which a hashmap is stored in a cachewrapper. we only use one key so that either all values of a user are there or none are there. @@ -126,32 +138,21 @@ public class NewCachePersistingAssessmentManager extends BasicManager implements private CacheWrapper<NewCacheKey,HashMap<String, Serializable>> courseCache; private OLATResourceable ores; - - // we cannot store the ref to cpm here, since at the time where the assessmentManager is initialized, the given course is not fully initialized yet. - //does not work: final CoursePropertyManager cpm; - - /** - * Get an instance of the persisting assessment manager. This will use the - * course property manager to persist assessment data. THIS METHOD MUST ONLY - * BE USED WITHIN THE COURSE CONSTRUCTOR. Use course.getAssessmentManager() to - * use the assessment manager during runtime! - * - * @param course - * @return The assessment manager for this course - */ - public static AssessmentManager getInstance(ICourse course) { - return new NewCachePersistingAssessmentManager(course); - } - /** * Private since singleton */ - private NewCachePersistingAssessmentManager(ICourse course) { + public NewCachePersistingAssessmentManager(ICourse course) { this.ores = course; //String cacheName = "Course@" + course.getResourceableId(); courseCache = CoordinatorManager.getInstance().getCoordinator().getCacher() .getCache(AssessmentManager.class.getSimpleName(), "newpersisting"); } + + public NewCachePersistingAssessmentManager(ICourse course, CacheWrapper<NewCacheKey,HashMap<String, Serializable>> cache) { + this.ores = course; + //String cacheName = "Course@" + course.getResourceableId(); + courseCache = cache; + } /** * @param identity the identity for which to properties are to be loaded. * if null, the properties of all identities (=all properties of this course) @@ -191,13 +192,11 @@ public class NewCachePersistingAssessmentManager extends BasicManager implements /** * @see org.olat.course.assessment.AssessmentManager#preloadCache(org.olat.core.id.Identity) */ - @Override public void preloadCache(Identity identity) { // triggers loading of data of the given user. getOrLoadScorePassedAttemptsMap(identity, null, false); } - @Override public void preloadCache(List<Identity> identities) { int count = 0; int batch = 200; @@ -573,7 +572,6 @@ public class NewCachePersistingAssessmentManager extends BasicManager implements * @see org.olat.course.assessment.AssessmentManager#incrementNodeAttemptsInBackground(org.olat.course.nodes.CourseNode, * org.olat.core.id.Identity, org.olat.course.run.userview.UserCourseEnvironment) */ - @Override public void incrementNodeAttemptsInBackground(CourseNode courseNode, Identity identity, UserCourseEnvironment userCourseEnv) { incrementNodeAttempts(courseNode, identity, userCourseEnv, false); } @@ -720,7 +718,6 @@ public class NewCachePersistingAssessmentManager extends BasicManager implements } } - @Override public Boolean getNodeFullyAssessed(CourseNode courseNode, Identity identity) { Boolean fullyAssessed = null; if (courseNode != null) { @@ -835,7 +832,6 @@ public class NewCachePersistingAssessmentManager extends BasicManager implements } } - @Override public Date getScoreLastModifiedDate(CourseNode courseNode, Identity identity) { if (courseNode == null) { return null; // return default value diff --git a/src/main/java/org/olat/user/UserManager.java b/src/main/java/org/olat/user/UserManager.java index 9aa14e10455301b54831307fb7afcb7fcf9fcf9e..b198f11d88e89820ce0f6b0a75b43b1b999578bb 100644 --- a/src/main/java/org/olat/user/UserManager.java +++ b/src/main/java/org/olat/user/UserManager.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import org.olat.basesecurity.IdentityNames; +import org.olat.basesecurity.IdentityRef; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; import org.olat.core.id.User; @@ -262,6 +263,8 @@ public abstract class UserManager extends BasicManager { */ public abstract String getUserDisplayName(Identity identity); + public abstract String getUserDisplayName(IdentityRef identity); + /** * * @param identityKeys diff --git a/src/main/java/org/olat/user/UserManagerImpl.java b/src/main/java/org/olat/user/UserManagerImpl.java index b29af80ff6a91656397eed8c5c91e8d81c75f322..8b0847beb9e827e897851b12f2159d1cce2877c8 100644 --- a/src/main/java/org/olat/user/UserManagerImpl.java +++ b/src/main/java/org/olat/user/UserManagerImpl.java @@ -36,6 +36,7 @@ import javax.persistence.TypedQuery; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.IdentityImpl; import org.olat.basesecurity.IdentityNames; +import org.olat.basesecurity.IdentityRef; import org.olat.basesecurity.IdentityShort; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.DBFactory; @@ -534,6 +535,14 @@ public class UserManagerImpl extends UserManager { return fullNames; } + @Override + public String getUserDisplayName(IdentityRef identity) { + if(identity instanceof Identity) { + return getUserDisplayName((Identity)identity); + } + return getUserDisplayName(identity.getKey()); + } + @Override public String getUserDisplayName(Identity identity) { if (userDisplayNameCreator == null || identity == null) return ""; diff --git a/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql b/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql index ba04f9ce30e30836d1108475cd15a49f1619ce88..e4b4f1bbab4225a718388d92f789f33faa7f4e00 100644 --- a/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql +++ b/src/main/resources/database/mysql/alter_10_x_0_to_11_0_0.sql @@ -20,3 +20,30 @@ alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx alter table o_qti_assessment_session add constraint qti_sess_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); + +create table o_as_entry ( + id bigint not null auto_increment, + creationdate datetime not null, + lastmodified datetime not null, + a_attemtps bigint default null, + a_score float(65,30) default null, + a_passed bit default null, + a_fully_assessed bit default null, + a_assessment_id bigint default null, + a_completion float(65,30), + a_comment text, + a_coach_comment text, + fk_entry bigint not null, + a_subident varchar(64), + fk_reference_entry bigint not null, + fk_identity bigint not null, + primary key (id), + unique (fk_identity, fk_entry, a_subident) +); +alter table o_as_entry ENGINE = InnoDB; + +alter table o_as_entry add constraint as_entry_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +alter table o_as_entry add constraint as_entry_to_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); +alter table o_as_entry add constraint as_entry_to_refentry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); + +create index idx_as_entry_to_id_idx on o_as_entry (a_assessment_id); diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index d3bcd0b99c1f345c4603a65c844a2cd231c1ca6b..1988ee14ff9c289254731249acc37ca49a22d864 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -1064,6 +1064,26 @@ create table o_as_user_course_infos ( primary key (id) ); +create table o_as_entry ( + id bigint not null auto_increment, + creationdate datetime not null, + lastmodified datetime not null, + a_attemtps bigint default null, + a_score float(65,30) default null, + a_passed bit default null, + a_fully_assessed bit default null, + a_assessment_id bigint default null, + a_completion float(65,30), + a_comment text, + a_coach_comment text, + fk_entry bigint not null, + a_subident varchar(64), + fk_reference_entry bigint not null, + fk_identity bigint not null, + primary key (id), + unique (fk_identity, fk_entry, a_subident) +); + create table o_as_mode_course ( id bigint not null, creationdate datetime not null, @@ -1750,7 +1770,7 @@ alter table o_ac_paypal_transaction ENGINE = InnoDB; alter table o_as_eff_statement ENGINE = InnoDB; alter table o_as_user_course_infos ENGINE = InnoDB; alter table o_as_mode_course ENGINE = InnoDB; -alter table o_as_mode_course ENGINE = InnoDB; +alter table o_as_entry ENGINE = InnoDB; alter table o_as_mode_course_to_area ENGINE = InnoDB; alter table o_mapper ENGINE = InnoDB; alter table o_qti_assessment_session ENGINE = InnoDB; @@ -2074,6 +2094,12 @@ alter table o_as_user_course_infos add index user_course_infos_id_cstr (fk_ident alter table o_as_user_course_infos add index user_course_infos_res_cstr (fk_resource_id), add constraint user_course_infos_res_cstr foreign key (fk_resource_id) references o_olatresource (resource_id); alter table o_as_user_course_infos add unique (fk_identity, fk_resource_id); +alter table o_as_entry add constraint as_entry_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +alter table o_as_entry add constraint as_entry_to_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); +alter table o_as_entry add constraint as_entry_to_refentry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); + +create index idx_as_entry_to_id_idx on o_as_entry (a_assessment_id); + -- mapper create index o_mapper_uuid_idx on o_mapper (mapper_uuid); diff --git a/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql b/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql index acf7795ad120bfd94a9a913266f16b2e3ee25523..ec896e6017d9be197ece2df257a91ad29eba1bda 100644 --- a/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql +++ b/src/main/resources/database/postgresql/alter_10_x_0_to_11_0_0.sql @@ -19,4 +19,37 @@ create index idx_testess_to_repo_entry_idx on o_qti_assessment_session (fk_entry alter table o_qti_assessment_session add constraint qti_sess_to_course_entry_idx foreign key (fk_course) references o_repositoryentry (repositoryentry_id); create index idx_qti_sess_to_course_entry_idx on o_qti_assessment_session (fk_course); alter table o_qti_assessment_session add constraint qti_sess_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); -create index idx_qti_sess_to_identity_idx on o_qti_assessment_session (fk_identity); \ No newline at end of file +create index idx_qti_sess_to_identity_idx on o_qti_assessment_session (fk_identity); + + + +create table o_as_entry ( + id bigserial, + creationdate timestamp not null, + lastmodified timestamp not null, + a_attemtps int8 default null, + a_score decimal default null, + a_passed bool default null, + a_fully_assessed bool default null, + a_assessment_id int8 default null, + a_completion float(24), + a_comment text, + a_coach_comment text, + fk_entry int8 not null, + a_subident varchar(64), + fk_reference_entry int8 not null, + fk_identity int8 not null, + primary key (id), + unique(fk_identity, fk_entry, a_subident) +); + +alter table o_as_entry add constraint as_entry_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index idx_as_entry_to_ident_idx on o_as_entry (fk_identity); +alter table o_as_entry add constraint as_entry_to_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); +create index idx_as_entry_to_entry_idx on o_as_entry (fk_entry); +alter table o_as_entry add constraint as_entry_to_refentry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); +create index idx_as_entry_to_refentry_idx on o_as_entry (fk_reference_entry); + +create index idx_as_entry_to_id_idx on o_as_entry (a_assessment_id); + + diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index d0567fc794d6524817a11818f9a9386c83d93513..3cbe71a6ab2acb59f679422d96a303742ab75473 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -1065,6 +1065,26 @@ create table o_as_user_course_infos ( primary key (id) ); +create table o_as_entry ( + id bigserial, + creationdate timestamp not null, + lastmodified timestamp not null, + a_attemtps int8 default null, + a_score decimal default null, + a_passed bool default null, + a_fully_assessed bool default null, + a_assessment_id int8 default null, + a_completion float(24), + a_comment text, + a_coach_comment text, + fk_entry int8 not null, + a_subident varchar(64), + fk_reference_entry int8 not null, + fk_identity int8 not null, + primary key (id), + unique(fk_identity, fk_entry, a_subident) +); + create table o_as_mode_course ( id int8 not null, creationdate timestamp not null, @@ -2073,6 +2093,15 @@ alter table o_as_user_course_infos add constraint user_course_infos_res_cstr for create index idx_ucourseinfos_rsrc_idx on o_as_user_course_infos (fk_resource_id); alter table o_as_user_course_infos add unique (fk_identity, fk_resource_id); +alter table o_as_entry add constraint as_entry_to_identity_idx foreign key (fk_identity) references o_bs_identity (id); +create index idx_as_entry_to_ident_idx on o_as_entry (fk_identity); +alter table o_as_entry add constraint as_entry_to_entry_idx foreign key (fk_entry) references o_repositoryentry (repositoryentry_id); +create index idx_as_entry_to_entry_idx on o_as_entry (fk_entry); +alter table o_as_entry add constraint as_entry_to_refentry_idx foreign key (fk_reference_entry) references o_repositoryentry (repositoryentry_id); +create index idx_as_entry_to_refentry_idx on o_as_entry (fk_reference_entry); + +create index idx_as_entry_to_id_idx on o_as_entry (a_assessment_id); + -- mapper create index o_mapper_uuid_idx on o_mapper (mapper_uuid); diff --git a/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java b/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8e0a33470d3cda87aee04beefda625873b695eb2 --- /dev/null +++ b/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java @@ -0,0 +1,104 @@ +/** + * <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.assessment.manager; + +import java.util.UUID; + +import org.junit.Assert; +import org.junit.Test; +import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; +import org.olat.modules.assessment.AssessmentEntry; +import org.olat.modules.assessment.manager.AssessmentEntryDAO; +import org.olat.repository.RepositoryEntry; +import org.olat.test.JunitTestHelper; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; + + +/** + * + * Initial date: 20.07.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessmentEntryDAOTest extends OlatTestCase { + + @Autowired + private DB dbInstance; + @Autowired + private AssessmentEntryDAO courseNodeAssessmentDao; + + @Test + public void createCourseNodeAssessment() { + Identity assessedIdentity = JunitTestHelper.createAndPersistIdentityAsRndUser("as-node-1"); + RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry(); + String courseNodeIdent = "39485349759"; + + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .createCourseNodeAssessment(assessedIdentity, entry, courseNodeIdent, entry); + Assert.assertNotNull(nodeAssessment); + dbInstance.commitAndCloseSession(); + + //check values + Assert.assertNotNull(nodeAssessment.getKey()); + Assert.assertNotNull(nodeAssessment.getCreationDate()); + Assert.assertNotNull(nodeAssessment.getLastModified()); + Assert.assertEquals(assessedIdentity, nodeAssessment.getIdentity()); + Assert.assertEquals(entry, nodeAssessment.getRepositoryEntry()); + Assert.assertEquals(courseNodeIdent, nodeAssessment.getSubIdent()); + } + + @Test + public void loadCourseNodeAssessmentById() { + Identity assessedIdentity = JunitTestHelper.createAndPersistIdentityAsRndUser("as-node-2"); + RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry(); + String courseNodeIdent = UUID.randomUUID().toString(); + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .createCourseNodeAssessment(assessedIdentity, entry, courseNodeIdent, entry); + dbInstance.commitAndCloseSession(); + + AssessmentEntry reloadedAssessment = courseNodeAssessmentDao.loadAssessmentEntryById(nodeAssessment.getKey()); + Assert.assertEquals(nodeAssessment.getKey(), reloadedAssessment.getKey()); + Assert.assertEquals(nodeAssessment, reloadedAssessment); + Assert.assertEquals(assessedIdentity, reloadedAssessment.getIdentity()); + Assert.assertEquals(entry, reloadedAssessment.getRepositoryEntry()); + Assert.assertEquals(courseNodeIdent, reloadedAssessment.getSubIdent()); + } + + @Test + public void loadCourseNodeAssessment() { + Identity assessedIdentity = JunitTestHelper.createAndPersistIdentityAsRndUser("as-node-3"); + RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry(); + String courseNodeIdent = UUID.randomUUID().toString(); + AssessmentEntry nodeAssessment = courseNodeAssessmentDao + .createCourseNodeAssessment(assessedIdentity, entry, courseNodeIdent, entry); + dbInstance.commitAndCloseSession(); + + AssessmentEntry reloadedAssessment = courseNodeAssessmentDao + .loadAssessmentEntry(assessedIdentity, entry, courseNodeIdent); + Assert.assertEquals(nodeAssessment.getKey(), reloadedAssessment.getKey()); + Assert.assertEquals(nodeAssessment, reloadedAssessment); + Assert.assertEquals(assessedIdentity, reloadedAssessment.getIdentity()); + Assert.assertEquals(entry, reloadedAssessment.getRepositoryEntry()); + Assert.assertEquals(courseNodeIdent, reloadedAssessment.getSubIdent()); + } + +} diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index d4e5cb2ec82550665513f44d017e699b2349c036..985fcbc9d53c839cfb94a640d2267302ae71890a 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -129,6 +129,7 @@ import org.junit.runners.Suite; org.olat.course.assessment.AssessmentManagerTest.class, org.olat.course.assessment.manager.UserCourseInformationsManagerTest.class, org.olat.course.assessment.manager.AssessmentModeManagerTest.class, + org.olat.modules.assessment.manager.AssessmentEntryDAOTest.class, org.olat.course.certificate.manager.CertificatesManagerTest.class, org.olat.course.config.CourseConfigManagerImplTest.class, org.olat.course.groupsandrights.CourseGroupManagementTest.class,