From 32356fbc58796a852621de736bcb97f73a342a6d Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Fri, 19 Jul 2019 19:07:21 +0200
Subject: [PATCH] OO-4160: implement delete curriculum with confirmation

---
 .../modules/curriculum/CurriculumService.java |   3 +
 .../curriculum/manager/CurriculumDAO.java     |   8 ++
 .../manager/CurriculumServiceImpl.java        |  13 ++
 .../ui/ConfirmCurriculumDeleteController.java | 127 ++++++++++++++++++
 .../ui/CurriculumListManagerController.java   |  26 +++-
 .../_content/confirm_delete_curriculum.html   |   4 +
 .../ui/_i18n/LocalStrings_de.properties       |   4 +
 .../ui/_i18n/LocalStrings_en.properties       |   4 +
 .../ui/_i18n/LocalStrings_en.properties       |   2 +-
 9 files changed, 188 insertions(+), 3 deletions(-)
 create mode 100644 src/main/java/org/olat/modules/curriculum/ui/ConfirmCurriculumDeleteController.java
 create mode 100644 src/main/java/org/olat/modules/curriculum/ui/_content/confirm_delete_curriculum.html

diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumService.java b/src/main/java/org/olat/modules/curriculum/CurriculumService.java
index a4bcc8571e8..ff15ce66fba 100644
--- a/src/main/java/org/olat/modules/curriculum/CurriculumService.java
+++ b/src/main/java/org/olat/modules/curriculum/CurriculumService.java
@@ -66,6 +66,9 @@ public interface CurriculumService {
 	public Curriculum getCurriculum(CurriculumRef ref);
 	
 	public Curriculum updateCurriculum(Curriculum curriculum);
+
+	public void deleteCurriculum(CurriculumRef curriculum);
+	
 	
 	public List<Curriculum> getCurriculums(Collection<? extends CurriculumRef> refs);
 	
diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumDAO.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumDAO.java
index 75960f18f01..e308f50cfc3 100644
--- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumDAO.java
+++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumDAO.java
@@ -27,6 +27,7 @@ import java.util.stream.Collectors;
 
 import javax.persistence.TypedQuery;
 
+import org.olat.basesecurity.Group;
 import org.olat.basesecurity.GroupRoles;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.basesecurity.OrganisationRoles;
@@ -342,6 +343,13 @@ public class CurriculumDAO {
 		return dbInstance.getCurrentEntityManager().merge(curriculum);
 	}
 	
+	public void delete(CurriculumImpl curriculum) {
+		Group group = curriculum.getGroup();
+		groupDao.removeMemberships(group);
+		dbInstance.getCurrentEntityManager().remove(curriculum);
+		groupDao.removeGroup(group);
+	}
+	
 	public List<Identity> getMembersIdentity(CurriculumRef curriculum, String role) {
 		StringBuilder sb = new StringBuilder(256);
 		sb.append("select ident from curriculum cur")
diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
index 97969f7a7cb..af7adb3108d 100644
--- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
+++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
@@ -72,6 +72,7 @@ import org.olat.modules.curriculum.model.CurriculumElementRepositoryEntryViews;
 import org.olat.modules.curriculum.model.CurriculumElementSearchInfos;
 import org.olat.modules.curriculum.model.CurriculumElementSearchParams;
 import org.olat.modules.curriculum.model.CurriculumElementWebDAVInfos;
+import org.olat.modules.curriculum.model.CurriculumImpl;
 import org.olat.modules.curriculum.model.CurriculumInfos;
 import org.olat.modules.curriculum.model.CurriculumMember;
 import org.olat.modules.curriculum.model.CurriculumRefImpl;
@@ -141,6 +142,18 @@ public class CurriculumServiceImpl implements CurriculumService, OrganisationDat
 		return curriculumDao.update(curriculum);
 	}
 	
+	@Override
+	public void deleteCurriculum(CurriculumRef curriculumRef) {
+		CurriculumImpl curriculum = (CurriculumImpl)getCurriculum(curriculumRef);
+		for(CurriculumElement rootElement:curriculum.getRootElements()) {
+			deleteCurriculumElement(rootElement);
+		}
+		dbInstance.commit();
+		curriculum = (CurriculumImpl)getCurriculum(curriculumRef);
+		curriculumDao.delete(curriculum);
+		dbInstance.commit();
+	}
+
 	@Override
 	public List<Curriculum> getCurriculums(Collection<? extends CurriculumRef> refs) {
 		return curriculumDao.loadByKeys(refs);
diff --git a/src/main/java/org/olat/modules/curriculum/ui/ConfirmCurriculumDeleteController.java b/src/main/java/org/olat/modules/curriculum/ui/ConfirmCurriculumDeleteController.java
new file mode 100644
index 00000000000..cebd7316093
--- /dev/null
+++ b/src/main/java/org/olat/modules/curriculum/ui/ConfirmCurriculumDeleteController.java
@@ -0,0 +1,127 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.modules.curriculum.ui;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.util.StringHelper;
+import org.olat.modules.curriculum.CurriculumService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 19 juil. 2019<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ConfirmCurriculumDeleteController extends FormBasicController {
+
+	private static final String[] onKeys = new String[]{ "on" };
+	
+	private FormLink deleteButton;
+	private MultipleSelectionElement acknowledgeEl;
+	
+	private final CurriculumRow rowToDelete;
+	
+	@Autowired
+	private CurriculumService curriculumService;
+	
+	public ConfirmCurriculumDeleteController(UserRequest ureq, WindowControl wControl, CurriculumRow rowToDelete) {
+		super(ureq, wControl, "confirm_delete_curriculum");
+		this.rowToDelete = rowToDelete;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		if(formLayout instanceof FormLayoutContainer) {
+			String[] args = new String[] {
+				StringHelper.escapeHtml(rowToDelete.getDisplayName()),
+				Long.toString(rowToDelete.getNumOfElements())
+			};
+			String msg = translate("confirmation.delete.curriculum", args);
+			((FormLayoutContainer)formLayout).contextPut("msg", msg);
+		}
+		
+		FormLayoutContainer layoutCont = FormLayoutContainer.createDefaultFormLayout("confirm", getTranslator());
+		formLayout.add("confirm", layoutCont);
+		layoutCont.setRootForm(mainForm);
+		
+		uifactory.addStaticTextElement("curriculum.displayName", "curriculum.displayName",
+				StringHelper.escapeHtml(rowToDelete.getDisplayName()), layoutCont);
+		
+		String[] onValues = new String[]{ translate("delete.curriculum.acknowledge") };
+		acknowledgeEl = uifactory.addCheckboxesHorizontal("acknowledge", "confirmation", layoutCont, onKeys, onValues);
+		
+		FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
+		layoutCont.add(buttonsCont);
+		uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl());
+		deleteButton = uifactory.addFormLink("delete", buttonsCont, Link.BUTTON);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	@Override
+	protected boolean validateFormLogic(UserRequest ureq) {
+		boolean allOk = super.validateFormLogic(ureq);
+		
+		acknowledgeEl.clearError();
+		if(!acknowledgeEl.isAtLeastSelected(1)) {
+			acknowledgeEl.setErrorKey("form.legende.mandatory", null);
+			allOk &= false;
+		}
+		
+		return allOk;
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		//
+	}
+
+	@Override
+	protected void formCancelled(UserRequest ureq) {
+		fireEvent(ureq, Event.CANCELLED_EVENT);
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(deleteButton == source) {
+			if(validateFormLogic(ureq)) {
+				curriculumService.deleteCurriculum(rowToDelete);
+				fireEvent(ureq, Event.DONE_EVENT);
+			}
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+}
diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumListManagerController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumListManagerController.java
index 7aec2e708bb..de294f91f37 100644
--- a/src/main/java/org/olat/modules/curriculum/ui/CurriculumListManagerController.java
+++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumListManagerController.java
@@ -58,6 +58,7 @@ import org.olat.core.gui.media.MediaResource;
 import org.olat.core.id.Roles;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.modules.curriculum.Curriculum;
 import org.olat.modules.curriculum.CurriculumElementMembership;
@@ -93,6 +94,7 @@ public class CurriculumListManagerController extends FormBasicController impleme
 	private EditCurriculumController newCurriculumCtrl;
 	private ImportCurriculumController importCurriculumCtrl;
 	private EditCurriculumOverviewController editCurriculumCtrl;
+	private ConfirmCurriculumDeleteController deleteCurriculumCtrl;
 	private CloseableCalloutWindowController toolsCalloutCtrl;
 	
 	private int counter = 0;
@@ -254,7 +256,8 @@ public class CurriculumListManagerController extends FormBasicController impleme
 			}
 			cmc.deactivate();
 			cleanUp();
-		} else if(editCurriculumCtrl == source || importCurriculumCtrl == source) {
+		} else if(editCurriculumCtrl == source || importCurriculumCtrl == source
+				|| deleteCurriculumCtrl == source) {
 			if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
 				loadModel(tableEl.getQuickSearchString(), false);
 			}
@@ -268,9 +271,11 @@ public class CurriculumListManagerController extends FormBasicController impleme
 	
 	private void cleanUp() {
 		removeAsListenerAndDispose(importCurriculumCtrl);
+		removeAsListenerAndDispose(deleteCurriculumCtrl);
 		removeAsListenerAndDispose(newCurriculumCtrl);
 		removeAsListenerAndDispose(cmc);
 		importCurriculumCtrl = null;
+		deleteCurriculumCtrl = null;
 		newCurriculumCtrl = null;
 		cmc = null;
 	}
@@ -358,6 +363,23 @@ public class CurriculumListManagerController extends FormBasicController impleme
 		}
 	}
 	
+	private void doDeleteCurriculum(UserRequest ureq, CurriculumRow row) {
+		removeAsListenerAndDispose(deleteCurriculumCtrl);
+		
+		Curriculum curriculum = curriculumService.getCurriculum(row);
+		if(curriculum == null) {
+			showWarning("warning.curriculum.deleted");
+		} else {
+			deleteCurriculumCtrl = new ConfirmCurriculumDeleteController(ureq, getWindowControl(), row);
+			listenTo(deleteCurriculumCtrl);
+			
+			String title = translate("delete.curriculum.title", new String[] { StringHelper.escapeHtml(row.getDisplayName()) });
+			cmc = new CloseableModalController(getWindowControl(), "close", deleteCurriculumCtrl.getInitialComponent(), true, title);
+			listenTo(cmc);
+			cmc.activate();
+		}
+	}
+	
 	private void doExportCurriculum(UserRequest ureq, CurriculumRow row) {
 		Curriculum curriculum = curriculumService.getCurriculum(row);
 		MediaResource mr = new ExportCurriculumMediaResource(curriculum);
@@ -453,7 +475,7 @@ public class CurriculumListManagerController extends FormBasicController impleme
 				doEditCurriculum(ureq, row);
 			} else if(deleteLink == source) {
 				close();
-				showWarning("Not implemented");
+				doDeleteCurriculum(ureq, row);
 			} else if(exportLink == source) {
 				close();
 				doExportCurriculum(ureq, row);
diff --git a/src/main/java/org/olat/modules/curriculum/ui/_content/confirm_delete_curriculum.html b/src/main/java/org/olat/modules/curriculum/ui/_content/confirm_delete_curriculum.html
new file mode 100644
index 00000000000..2e8fdedae59
--- /dev/null
+++ b/src/main/java/org/olat/modules/curriculum/ui/_content/confirm_delete_curriculum.html
@@ -0,0 +1,4 @@
+<div class="o_error">
+	<p><i class="o_icon o_icon-lg o_icon_important"> </i> $msg</p>
+</div>
+$r.render("confirm")
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties
index ca81e116e4d..c0b4bf63024 100644
--- a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties
@@ -16,9 +16,11 @@ confirm.remove.member.title=Mitglieder entfernen
 confirm.remove.member.text=Wollen Sie wirklich diese Mitglieder entfernen?
 confirm.remove.resource.title=Lernresourcen entfernen
 confirm.remove.resource.text=Wollen Sie wirklich diese Lernresourcen entfernen?
+confirmation=Best\u00E4tigung
 confirmation.delete.type=Wollen Sie wirklich den Typ "{0}" l\u00F6schen?
 confirmation.delete.type.title=Typ "{0}" l\u00F6schen
 confirmation.delete.element=Wollen Sie wirklich dieses Curriculum Element "{0}" l\u00F6schen?
+confirmation.delete.curriculum=Wollen Sie wirklich dieses Curriculum "{0}" l\u00F6schen? Er enth\u00E4lt <strong>{1} Elementen</strong>.
 confirmation.delete.element.title=Curriculum Element "{0}" l\u00F6schen
 copy.element=Element kopieren
 copy.element.title=Element "{0}" kopieren
@@ -53,6 +55,8 @@ curriculum.key=ID
 curriculum.metadata=Metadaten
 curriculum.organisation=Organisation
 curriculum.search=Suchen
+delete.curriculum.acknowledge=Ich verstehe, dass das Curriculum und alle seine Elementen werden definitive gel\u00F6scht.
+delete.curriculum.title=Curriculum "{0}" l\u00F6schen
 details=Infoseite
 details.copy=Kopieren
 details.delete=L\u00F6schen
diff --git a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties
index fdad3d3de55..543913620d4 100644
--- a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties
@@ -16,6 +16,8 @@ confirm.remove.member.text=Do you really want to remove this member(s)?
 confirm.remove.member.title=Remove member
 confirm.remove.resource.text=Do you really want to remove this learn resource(s)?
 confirm.remove.resource.title=Remove learn resources
+confirmation=Confirmation
+confirmation.delete.curriculum=Do you really want to delete this curriculum "{0}"? It contains <strong>{1} elements</strong>.
 confirmation.delete.element=Do you really want to delete this curriculum element "{0}"?
 confirmation.delete.element.title=Delete curriculum element "{0}"
 confirmation.delete.type=Do you really want to delete this type "{0}"?
@@ -53,6 +55,8 @@ curriculum.key=ID
 curriculum.metadata=Metadata
 curriculum.organisation=Organisation
 curriculum.search=Search
+delete.binder.acknowledge=I understand that the curriculum and all its elements will be definitely deleted.
+delete.curriculum.title=Delete curriculum "{0}"
 details=Info page
 details.copy=Copy
 details.delete=Delete
diff --git a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
index 7bf718c0d54..f40e2186857 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
@@ -144,7 +144,7 @@ delete.assignment.in.use.confirm.descr=$\:delete.assignment.confirm.descr <div c
 delete.assignment.template.confirm.descr=Do you really want to delete this template "{0}"?
 delete.assignment.template.confirm.title=Delete template
 delete.binder=Delete binder
-delete.binder.acknowledge=I understand that the binder and all its entries will be definetly deleted.
+delete.binder.acknowledge=I understand that the binder and all its entries will be definitely deleted.
 delete.binder.acknowledge.2=I understand that the binder cannot be restored again.
 delete.binder.success=Binder is successfully deleted.
 delete.binder.warning=Do you really want to delete the binder "{0}"? It contains <strong>{1}</strong> sections, <strong>{2}</strong> entries and <strong>{3}</strong> comments.
-- 
GitLab