/**
* <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.portfolio.ui;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.olat.NewControllerFactory;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.form.flexible.FormItem;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.FormLink;
import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
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.components.link.LinkFactory;
import org.olat.core.gui.components.stack.TooledController;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.components.stack.TooledStackedPanel.Align;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.gui.control.generic.modal.DialogBoxController;
import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry;
import org.olat.core.util.Formatter;
import org.olat.core.util.StringHelper;
import org.olat.modules.portfolio.Category;
import org.olat.modules.portfolio.Media;
import org.olat.modules.portfolio.MediaHandler;
import org.olat.modules.portfolio.PageStatus;
import org.olat.modules.portfolio.PortfolioService;
import org.olat.modules.portfolio.manager.MetadataXStream;
import org.olat.modules.portfolio.model.BinderPageUsage;
import org.olat.modules.portfolio.ui.event.MediaEvent;
import org.olat.user.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 20.06.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class MediaDetailsController extends FormBasicController implements Activateable2, TooledController {
private Link editLink, deleteLink;
private final TooledStackedPanel stackPanel;
private Controller mediaCtrl;
private Controller mediaEditCtrl;
private CloseableModalController cmc;
private DialogBoxController confirmDeleteMediaCtrl;
private int counter;
private Media media;
private boolean editable = true;
private final MediaHandler handler;
private final List<BinderPageUsage> usedInList;
@Autowired
private UserManager userManager;
@Autowired
private PortfolioService portfolioService;
public MediaDetailsController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, Media media) {
super(ureq, wControl, "media_details");
this.media = media;
this.stackPanel = stackPanel;
handler = portfolioService.getMediaHandler(media.getType());
usedInList = portfolioService.getUsedInBinders(media);
for(BinderPageUsage binder:usedInList) {
if(binder.getPageStatus() == PageStatus.closed || binder.getPageStatus() == PageStatus.published) {
editable = false;
}
}
initForm(ureq);
}
@Override
public void initTools() {
if(editable) {
editLink = LinkFactory.createToolLink("edit", translate("edit"), this);
editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_edit");
stackPanel.addTool(editLink, Align.left);
}
if(usedInList.isEmpty()) {
deleteLink = LinkFactory.createToolLink("delete", translate("delete"), this);
deleteLink.setIconLeftCSS("o_icon o_icon-lg o_icon_delete_item");
stackPanel.addTool(deleteLink, Align.left);
}
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
if(formLayout instanceof FormLayoutContainer) {
FormLayoutContainer layoutCont = (FormLayoutContainer)formLayout;
layoutCont.contextPut("title", StringHelper.escapeHtml(media.getTitle()));
layoutCont.contextPut("description", StringHelper.xssScan(media.getDescription()));
layoutCont.contextPut("iconCssClass", handler.getIconCssClass(media));
mediaCtrl = handler.getMediaController(ureq, getWindowControl(), media);
if(mediaCtrl != null) {
listenTo(mediaCtrl);
layoutCont.put("media", mediaCtrl.getInitialComponent());
}
layoutCont.contextPut("media", media);
String author = userManager.getUserDisplayName(media.getAuthor());
layoutCont.contextPut("author", author);
if(media.getCollectionDate() != null) {
String collectionDate = Formatter.getInstance(getLocale()).formatDate(media.getCollectionDate());
layoutCont.contextPut("collectionDate", collectionDate);
}
if(StringHelper.containsNonWhitespace(media.getMetadataXml())) {
Object metadata = MetadataXStream.get().fromXML(media.getMetadataXml());
layoutCont.contextPut("metadata", metadata);
}
List<Category> categories = portfolioService.getCategories(media);
if(categories != null && categories.size() > 0) {
Map<String,String> categoriesMap = categories.stream()
.collect(Collectors.toMap(c -> c.getName(), c -> c.getName()));
TextBoxListElement categoriesEl = uifactory.addTextBoxListElement("categories", "categories", "categories.hint", categoriesMap, formLayout, getTranslator());
categoriesEl.setHelpText(translate("categories.hint"));
categoriesEl.setElementCssClass("o_sel_ep_tagsinput");
categoriesEl.setEnabled(false);
}
List<FormLink> binderLinks = new ArrayList<>(usedInList.size());
Set<Long> binderUniqueKeys = new HashSet<>();
for(BinderPageUsage binder:usedInList) {
if(binderUniqueKeys.contains(binder.getBinderKey())) continue;
FormLink link;
if(binder.getBinderKey() == null) {
link = uifactory.addFormLink("binder_" + (++counter), "page", binder.getPageTitle(), null, layoutCont, Link.LINK | Link.NONTRANSLATED);
binderUniqueKeys.add(binder.getPageKey());
} else {
link = uifactory.addFormLink("binder_" + (++counter), "binder", binder.getBinderTitle(), null, layoutCont, Link.LINK | Link.NONTRANSLATED);
binderUniqueKeys.add(binder.getBinderKey());
}
link.setUserObject(binder);
binderLinks.add(link);
}
layoutCont.contextPut("binderLinks", binderLinks);
}
}
private void reload(UserRequest ureq) {
initForm(flc, this, ureq);
}
@Override
protected void doDispose() {
//
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
//
}
@Override
protected void formOK(UserRequest ureq) {
//
}
@Override
public void event(UserRequest ureq, Component source, Event event) {
if(editLink == source) {
doEdit(ureq);
} else if(deleteLink == source) {
doConfirmDelete(ureq);
}
super.event(ureq, source, event);
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(mediaEditCtrl == source) {
if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
reload(ureq);
fireEvent(ureq, Event.CHANGED_EVENT);
}
cmc.deactivate();
cleanUp();
} else if(confirmDeleteMediaCtrl == source) {
if(DialogBoxUIFactory.isYesEvent(event)) {
doDelete();
fireEvent(ureq, new MediaEvent(MediaEvent.DELETED));
}
} else if(cmc == source) {
cleanUp();
}
super.event(ureq, source, event);
}
private void cleanUp() {
removeAsListenerAndDispose(mediaEditCtrl);
removeAsListenerAndDispose(cmc);
mediaEditCtrl = null;
cmc = null;
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if(source instanceof FormLink) {
FormLink link = (FormLink)source;
String cmd = link.getCmd();
Object uobject = link.getUserObject();
if("binder".equals(cmd)) {
if(uobject instanceof BinderPageUsage) {
String businessPath = "[Binder:" + ((BinderPageUsage)uobject).getBinderKey() + "]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
} else if("page".equals(cmd)) {
if(uobject instanceof BinderPageUsage) {
//http://localhost:8081/auth/HomeSite/720898/PortfolioV2/0/MyPages/0/Entry/89
String businessPath = "[HomeSite:" + getIdentity().getKey() + "][PortfolioV2:0][MyPages:0][Entry:" + ((BinderPageUsage)uobject).getPageKey() + "]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
}
}
}
super.formInnerEvent(ureq, source, event);
}
private void doEdit(UserRequest ureq) {
if(mediaEditCtrl != null) return;
mediaEditCtrl = handler.getEditMediaController(ureq, getWindowControl(), media);
listenTo(mediaEditCtrl);
String title = translate("edit");
cmc = new CloseableModalController(getWindowControl(), null, mediaEditCtrl.getInitialComponent(), true, title, true);
listenTo(cmc);
cmc.activate();
}
private void doConfirmDelete(UserRequest ureq) {
String title = translate("delete.media.confirm.title");
String text = translate("delete.media.confirm.descr", new String[]{ StringHelper.escapeHtml(media.getTitle()) });
confirmDeleteMediaCtrl = activateYesNoDialog(ureq, title, text, confirmDeleteMediaCtrl);
confirmDeleteMediaCtrl.setUserObject(media);
}
private void doDelete() {
portfolioService.deleteMedia(media);
}
}