diff --git a/src/main/java/org/olat/modules/fo/manager/ForumManager.java b/src/main/java/org/olat/modules/fo/manager/ForumManager.java index 744bbd0e2b88466a4979f95b068bba55a4097cd7..0b1cd251ecdd747031011c2b3b060f13b703f4cf 100644 --- a/src/main/java/org/olat/modules/fo/manager/ForumManager.java +++ b/src/main/java/org/olat/modules/fo/manager/ForumManager.java @@ -25,6 +25,7 @@ package org.olat.modules.fo.manager; +import java.io.File; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -39,6 +40,7 @@ import javax.persistence.TemporalType; import javax.persistence.TypedQuery; import org.olat.basesecurity.IdentityRef; +import org.olat.core.commons.modules.bc.FolderConfig; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.services.mark.MarkingService; @@ -809,6 +811,15 @@ public class ForumManager { return null; } + public File getMessageDirectory(Long forumKey, Long messageKey, boolean create) { + File forumDir = getForumDirectory(forumKey); + File messageDir = new File(forumDir, messageKey.toString()); + if(create && !messageDir.exists()) { + messageDir.mkdirs(); + } + return messageDir; + } + private void moveMessageContainer(Long fromForumKey, Long fromMessageKey, Long toForumKey, Long toMessageKey) { // copy message container VFSContainer toMessageContainer = getMessageContainer(toForumKey, toMessageKey); @@ -840,6 +851,15 @@ public class ForumManager { return null; } + public File getForumDirectory(Long forumKey) { + File forumsDir = new File(FolderConfig.getCanonicalRoot(), "forum"); + File forumDir = new File(forumsDir,forumKey.toString()); + if(!forumDir.exists()) { + forumDir.mkdirs(); + } + return forumDir; + } + /** * Splits the current thread starting from the current message. * It updates the messages of the selected subthread by setting the Parent and the Threadtop. diff --git a/src/main/java/org/olat/modules/fo/portfolio/ForumMediaHandler.java b/src/main/java/org/olat/modules/fo/portfolio/ForumMediaHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..7f075e510ff1da21060ec7ab443583424f1cd5dd --- /dev/null +++ b/src/main/java/org/olat/modules/fo/portfolio/ForumMediaHandler.java @@ -0,0 +1,103 @@ +/** + * <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.fo.portfolio; + +import java.io.File; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.id.Identity; +import org.olat.core.util.FileUtils; +import org.olat.core.util.resource.OresHelper; +import org.olat.modules.fo.Forum; +import org.olat.modules.fo.Message; +import org.olat.modules.fo.MessageLight; +import org.olat.modules.fo.manager.ForumManager; +import org.olat.modules.portfolio.Media; +import org.olat.modules.portfolio.handler.AbstractMediaHandler; +import org.olat.modules.portfolio.manager.MediaDAO; +import org.olat.modules.portfolio.manager.PortfolioFileStorage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 20.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class ForumMediaHandler extends AbstractMediaHandler { + + public static final String FORUM_HANDLER = OresHelper.calculateTypeName(Forum.class); + + @Autowired + private MediaDAO mediaDao; + @Autowired + private ForumManager forumManager; + @Autowired + private PortfolioFileStorage fileStorage; + + public ForumMediaHandler() { + super(FORUM_HANDLER); + } + + @Override + public String getIconCssClass() { + return "o_fo_icon"; + } + + @Override + public Media createMedia(String title, String description, Object mediaObject, String businessPath, Identity author) { + Message message = null; + if(mediaObject instanceof Message) { + message = (Message)mediaObject; + } else if(mediaObject instanceof MessageLight) { + MessageLight messageLight = (MessageLight)mediaObject; + message = forumManager.loadMessage(messageLight.getKey()); + } + + String content = message.getBody(); + Media media = mediaDao.createMedia(title, description, content, FORUM_HANDLER, businessPath, 70, author); + + File messageDir = forumManager.getMessageDirectory(message.getForum().getKey(), message.getKey(), false); + if (messageDir != null && messageDir.exists()) { + File[] attachments = messageDir.listFiles(); + if (attachments.length > 0) { + File mediaDir = fileStorage.generateMediaSubDirectory(media); + for(File attachment:attachments) { + FileUtils.copyFileToDir(attachment, mediaDir, "Forum media"); + } + String storagePath = fileStorage.getRelativePath(mediaDir); + media = mediaDao.updateStoragePath(media, storagePath); + } + } + + return media; + } + + @Override + public Controller getMediaController(UserRequest ureq, WindowControl wControl, Media media) { + return new ForumMessageMediaController(ureq, wControl, media); + } + + +} diff --git a/src/main/java/org/olat/modules/fo/portfolio/ForumMessageMediaController.java b/src/main/java/org/olat/modules/fo/portfolio/ForumMessageMediaController.java new file mode 100644 index 0000000000000000000000000000000000000000..cd04f4135b0826f23c0dae08398c7d4ee6ef7a3c --- /dev/null +++ b/src/main/java/org/olat/modules/fo/portfolio/ForumMessageMediaController.java @@ -0,0 +1,84 @@ +/** + * <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.fo.portfolio; + +import java.util.List; + +import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.download.DownloadComponent; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.util.CSSHelper; +import org.olat.core.util.StringHelper; +import org.olat.core.util.vfs.VFSContainer; +import org.olat.core.util.vfs.VFSItem; +import org.olat.core.util.vfs.VFSLeaf; +import org.olat.core.util.vfs.restapi.SystemItemFilter; +import org.olat.modules.portfolio.Media; + +/** + * + * Initial date: 20.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ForumMessageMediaController extends BasicController { + + public ForumMessageMediaController(UserRequest ureq, WindowControl wControl, Media media) { + super(ureq, wControl); + + VelocityContainer mainVC = createVelocityContainer("messageDetails"); + mainVC.contextPut("text", media.getContent()); + if (StringHelper.containsNonWhitespace(media.getStoragePath())) { + VFSContainer attachmentsContainer = new OlatRootFolderImpl("/" + media.getStoragePath(), null); + List<VFSItem> attachments = attachmentsContainer.getItems(new SystemItemFilter()); + int i=1; //vc-shift! + for (VFSItem attachment : attachments) { + if(attachment instanceof VFSLeaf) { + VFSLeaf file = (VFSLeaf)attachment; + DownloadComponent downlC = new DownloadComponent("download"+i, file, true, + file.getName() + " (" + String.valueOf(file.getSize() / 1024) + " KB)", null, + CSSHelper.createFiletypeIconCssClassFor(file.getName())); + mainVC.put("download"+i, downlC); + i++; + } + } + mainVC.contextPut("attachments", attachments); + mainVC.contextPut("hasAttachments", true); + } + + putInitialPanel(mainVC); + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } + + @Override + protected void doDispose() { + // + } +} + diff --git a/src/main/java/org/olat/modules/fo/ui/MessageListController.java b/src/main/java/org/olat/modules/fo/ui/MessageListController.java index 2cfddeb97745336b85a84bd51d2f972af91b5595..ed415bc9125dedcd05b9312c082e1d0ac4469eb2 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageListController.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageListController.java @@ -84,11 +84,14 @@ import org.olat.modules.fo.MessageRef; import org.olat.modules.fo.Status; import org.olat.modules.fo.archiver.formatters.ForumDownloadResource; import org.olat.modules.fo.manager.ForumManager; +import org.olat.modules.fo.portfolio.ForumMediaHandler; import org.olat.modules.fo.ui.MessageEditController.EditMode; import org.olat.modules.fo.ui.events.DeleteMessageEvent; import org.olat.modules.fo.ui.events.DeleteThreadEvent; import org.olat.modules.fo.ui.events.ErrorEditMessage; import org.olat.modules.fo.ui.events.SelectMessageEvent; +import org.olat.modules.portfolio.PortfolioV2Module; +import org.olat.modules.portfolio.ui.component.MediaCollectorComponent; import org.olat.portfolio.EPUIFactory; import org.olat.portfolio.manager.EPFrontendManager; import org.olat.user.DisplayPortraitController; @@ -153,6 +156,10 @@ public class MessageListController extends BasicController implements GenericEve private BaseSecurityModule securityModule; @Autowired private EPFrontendManager epMgr; + @Autowired + private PortfolioV2Module portfolioModule; + @Autowired + private ForumMediaHandler forumMediaHandler; public MessageListController(UserRequest ureq, WindowControl wControl, Forum forum, ForumCallback foCallback) { @@ -673,11 +680,17 @@ public class MessageListController extends BasicController implements GenericEve + "[Message:" + m.getKey() + "]"; Long artefact = artefactStats.get(businessPath); int numOfArtefact = artefact == null ? 0 : artefact.intValue(); - Controller ePFCollCtrl = EPUIFactory - .createArtefactCollectWizzardController(ureq, getWindowControl(), numOfArtefact, messageOres, businessPath); - if (ePFCollCtrl != null) { - messageView.setArtefact(ePFCollCtrl); - mainVC.put("eportfolio_" + keyString, ePFCollCtrl.getInitialComponent()); + if(portfolioModule.isEnabled()) { + String collectorId = "eportfolio_" + keyString; + Component collectorCmp = new MediaCollectorComponent(collectorId, getWindowControl(), m, forumMediaHandler, businessPath); + mainVC.put(collectorId, collectorCmp); + } else { + Controller ePFCollCtrl = EPUIFactory + .createArtefactCollectWizzardController(ureq, getWindowControl(), numOfArtefact, messageOres, businessPath); + if (ePFCollCtrl != null) { + messageView.setArtefact(ePFCollCtrl); + mainVC.put("eportfolio_" + keyString, ePFCollCtrl.getInitialComponent()); + } } } } diff --git a/src/main/java/org/olat/modules/portfolio/Media.java b/src/main/java/org/olat/modules/portfolio/Media.java new file mode 100644 index 0000000000000000000000000000000000000000..e9150061d9b944cb23bfc084842b56922887fe96 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/Media.java @@ -0,0 +1,54 @@ +/** + * <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; + +import java.util.Date; + +import org.olat.core.id.Identity; + +/** + * + * Initial date: 17.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface Media { + + public Long getKey(); + + public Date getCreationDate(); + + public Date getCollectionDate(); + + public String getStoragePath(); + + public String getType(); + + public String getTitle(); + + public String getDescription(); + + public String getContent(); + + public String getBusinessPath(); + + public Identity getAuthor(); + +} diff --git a/src/main/java/org/olat/modules/portfolio/MediaHandler.java b/src/main/java/org/olat/modules/portfolio/MediaHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..8b0ccc0f4fc39c5e8b6aea49a6dddc269491df18 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/MediaHandler.java @@ -0,0 +1,43 @@ +/** + * <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; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.id.Identity; + +/** + * + * Initial date: 20.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface MediaHandler { + + public String getType(); + + public String getIconCssClass(); + + public Media createMedia(String title, String description, Object mediaObject, String businessPath, Identity author); + + public Controller getMediaController(UserRequest ureq, WindowControl wControl, Media media); + +} diff --git a/src/main/java/org/olat/modules/portfolio/PortfolioService.java b/src/main/java/org/olat/modules/portfolio/PortfolioService.java index 905fbbe86f5b7c7b670049e5d18785bb34f12ad7..3c3c0f27cf0ee816e452c3556a76ae0f72ec9283 100644 --- a/src/main/java/org/olat/modules/portfolio/PortfolioService.java +++ b/src/main/java/org/olat/modules/portfolio/PortfolioService.java @@ -100,7 +100,14 @@ public interface PortfolioService { public List<Binder> getBinders(Identity owner, RepositoryEntryRef courseEntry, String subIdent); - public boolean isTemplateInUse(Binder binder, RepositoryEntry courseEntry, String subIdent); + /** + * Check if this template is used, has some copies. + * @param template + * @param courseEntry + * @param subIdent + * @return + */ + public boolean isTemplateInUse(Binder template, RepositoryEntry courseEntry, String subIdent); public Binder assignBinder(Identity owner, BinderRef templateBinder, RepositoryEntry courseEntry, String subIdent, Date deadline); @@ -200,5 +207,14 @@ public interface PortfolioService { * @return */ public PagePart updatePart(PagePart part); + + public MediaHandler getMediaHandler(String type); + + public Media getMediaByKey(Long key); + + public List<Media> searchOwnedMedias(IdentityRef author); + + public void updateCategories(Media media, List<String> categories); + } diff --git a/src/main/java/org/olat/modules/portfolio/handler/AbstractMediaHandler.java b/src/main/java/org/olat/modules/portfolio/handler/AbstractMediaHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..f4168dac37ee039019034ce16ae41e9aba11b625 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/handler/AbstractMediaHandler.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.modules.portfolio.handler; + +import org.olat.modules.portfolio.MediaHandler; + +/** + * + * Initial date: 20.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public abstract class AbstractMediaHandler implements MediaHandler { + + private final String type; + + public AbstractMediaHandler(String type) { + this.type = type; + } + + @Override + public String getType() { + return type; + } + + +} diff --git a/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java b/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java index ef13c17c89b5e9adb2209d24dbd3f36595d80fe1..489c80795bc73d494f66d1005391b5308a33029d 100644 --- a/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java +++ b/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java @@ -474,7 +474,8 @@ public class BinderDAO { StringBuilder sb = new StringBuilder(); sb.append("select section from pfsection as section") .append(" inner join fetch section.baseGroup as baseGroup") - .append(" where section.binder.key=:binderKey"); + .append(" where section.binder.key=:binderKey") + .append(" order by section.pos"); return dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Section.class) diff --git a/src/main/java/org/olat/modules/portfolio/manager/MediaDAO.java b/src/main/java/org/olat/modules/portfolio/manager/MediaDAO.java new file mode 100644 index 0000000000000000000000000000000000000000..98b1dd892a52f29afa46f1f99317c97b5ffa6094 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/manager/MediaDAO.java @@ -0,0 +1,93 @@ +/** + * <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.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.portfolio.Media; +import org.olat.modules.portfolio.model.MediaImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 17.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service +public class MediaDAO { + + @Autowired + private DB dbInstance; + + public Media createMedia(String title, String description, String content, String type, String businessPath, int signature, Identity author) { + MediaImpl media = new MediaImpl(); + media.setCreationDate(new Date()); + media.setCollectionDate(media.getCreationDate()); + media.setType(type); + + media.setTitle(title); + media.setDescription(description); + media.setContent(content); + media.setSignature(signature); + media.setBusinessPath(businessPath); + + media.setAuthor(author); + dbInstance.getCurrentEntityManager().persist(media); + return media; + } + + public Media updateStoragePath(Media media, String storagePath) { + ((MediaImpl)media).setStoragePath(storagePath); + return dbInstance.getCurrentEntityManager().merge(media); + } + + public Media loadByKey(Long key) { + StringBuilder sb = new StringBuilder(); + sb.append("select media from pfmedia as media") + .append(" inner join fetch media.author as author") + .append(" where media.key=:mediaKey"); + + List<Media> medias = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Media.class) + .setParameter("mediaKey", key) + .getResultList(); + return medias == null || medias.isEmpty() ? null : medias.get(0); + } + + public List<Media> loadByAuthor(IdentityRef author) { + StringBuilder sb = new StringBuilder(); + sb.append("select media from pfmedia as media") + .append(" inner join fetch media.author as author") + .append(" where author.key=:authorKey"); + + List<Media> medias = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Media.class) + .setParameter("authorKey", author.getKey()) + .getResultList(); + return medias; + } + +} diff --git a/src/main/java/org/olat/modules/portfolio/manager/PortfolioFileStorage.java b/src/main/java/org/olat/modules/portfolio/manager/PortfolioFileStorage.java index f0ecefe814590ee4a26ef7acaa3bdfdea4d34924..d0c76eafd22d28a1c8c426e6d2ab393e58f05146 100644 --- a/src/main/java/org/olat/modules/portfolio/manager/PortfolioFileStorage.java +++ b/src/main/java/org/olat/modules/portfolio/manager/PortfolioFileStorage.java @@ -24,6 +24,7 @@ import java.nio.file.Path; import java.util.UUID; import org.olat.core.commons.modules.bc.FolderConfig; +import org.olat.modules.portfolio.Media; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Service; @@ -37,7 +38,7 @@ import org.springframework.stereotype.Service; public class PortfolioFileStorage implements InitializingBean { private File rootDirectory, bcrootDirectory; - private File pagesPostersDirectory, binderPostersDirectory; + private File pagesPostersDirectory, binderPostersDirectory, mediaDirectory; @Override public void afterPropertiesSet() { @@ -50,13 +51,14 @@ public class PortfolioFileStorage implements InitializingBean { File postersDirectory = new File(rootDirectory, "posters"); binderPostersDirectory = new File(postersDirectory, "binders"); pagesPostersDirectory = new File(postersDirectory, "pages"); + mediaDirectory = new File(rootDirectory, "artefacts"); } protected File getRootDirectory() { return bcrootDirectory; } - protected String getRelativePath(File file) { + public String getRelativePath(File file) { Path relPath = bcrootDirectory.toPath().relativize(file.toPath()); return relPath.toString(); } @@ -80,4 +82,19 @@ public class PortfolioFileStorage implements InitializingBean { } return dir; } + + public File generateMediaSubDirectory(Media media) { + File subDirectory = generateMediaSubDirectory(); + return new File(subDirectory, media.getKey().toString()); + } + + protected File generateMediaSubDirectory() { + String cleanUuid = UUID.randomUUID().toString().replace("-", ""); + String firstToken = cleanUuid.substring(0, 2).toLowerCase(); + File dir = new File(mediaDirectory, firstToken); + if(!dir.exists()) { + dir.mkdirs(); + } + return dir; + } } diff --git a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java index f5713dc8ac830714fef54621934852897acb336f..b05c0cbb5fdaad7d6f3b8463a428db9ef9bb6d6f 100644 --- a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java +++ b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java @@ -41,6 +41,8 @@ import org.olat.core.util.resource.OresHelper; import org.olat.modules.portfolio.Binder; import org.olat.modules.portfolio.BinderRef; import org.olat.modules.portfolio.Category; +import org.olat.modules.portfolio.Media; +import org.olat.modules.portfolio.MediaHandler; import org.olat.modules.portfolio.Page; import org.olat.modules.portfolio.PageBody; import org.olat.modules.portfolio.PagePart; @@ -75,6 +77,8 @@ public class PortfolioServiceImpl implements PortfolioService { @Autowired private GroupDAO groupDao; @Autowired + private MediaDAO mediaDao; + @Autowired private BinderDAO binderDao; @Autowired private CategoryDAO categoryDao; @@ -87,6 +91,9 @@ public class PortfolioServiceImpl implements PortfolioService { @Autowired private PortfolioFileStorage portfolioFileStorage; + @Autowired + private List<MediaHandler> mediaHandlers; + @Override public Binder createNewBinder(String title, String summary, String imagePath, Identity owner) { BinderImpl portfolio = binderDao.createAndPersist(title, summary, imagePath, null); @@ -275,7 +282,11 @@ public class PortfolioServiceImpl implements PortfolioService { @Override public void updateCategories(Binder binder, List<String> categories) { OLATResourceable ores = OresHelper.createOLATResourceableInstance(Binder.class, binder.getKey()); - List<Category> currentCategories = categoryDao.getCategories(ores); + updateCategories(ores, categories); + } + + private void updateCategories(OLATResourceable oresource, List<String> categories) { + List<Category> currentCategories = categoryDao.getCategories(oresource); Map<String,Category> currentCategoryMap = new HashMap<>(); for(Category category:currentCategories) { currentCategoryMap.put(category.getName(), category); @@ -285,14 +296,14 @@ public class PortfolioServiceImpl implements PortfolioService { for(String newCategory:newCategories) { if(!currentCategoryMap.containsKey(newCategory)) { Category category = categoryDao.createAndPersistCategory(newCategory); - categoryDao.appendRelation(ores, category); + categoryDao.appendRelation(oresource, category); } } for(Category currentCategory:currentCategories) { String name = currentCategory.getName(); if(!newCategories.contains(name)) { - categoryDao.removeRelation(ores, currentCategory); + categoryDao.removeRelation(oresource, currentCategory); } } } @@ -405,8 +416,33 @@ public class PortfolioServiceImpl implements PortfolioService { public PagePart updatePart(PagePart part) { return pageDao.merge(part); } - - - - + + @Override + public MediaHandler getMediaHandler(String type) { + if(this.mediaHandlers != null) { + for(MediaHandler handler:mediaHandlers) { + if(type.equals(handler.getType())) { + return handler; + } + } + } + return null; + } + + @Override + public void updateCategories(Media media, List<String> categories) { + OLATResourceable ores = OresHelper.createOLATResourceableInstance(Media.class, media.getKey()); + updateCategories(ores, categories); + } + + @Override + public List<Media> searchOwnedMedias(IdentityRef author) { + return mediaDao.loadByAuthor(author); + } + + @Override + public Media getMediaByKey(Long key) { + return mediaDao.loadByKey(key); + } + } diff --git a/src/main/java/org/olat/modules/portfolio/model/MediaImpl.java b/src/main/java/org/olat/modules/portfolio/model/MediaImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..dba896956074c4a564335f4cfad784733eb1090c --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/model/MediaImpl.java @@ -0,0 +1,202 @@ +/** + * <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.model; + +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.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.Persistable; +import org.olat.modules.portfolio.Media; + +/** + * + * Initial date: 17.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Entity(name="pfmedia") +@Table(name="o_pf_media") +public class MediaImpl implements Persistable, CreateInfo, Media { + + private static final long serialVersionUID = -8066676191014353560L; + + @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="p_collection_date", nullable=false, insertable=true, updatable=false) + private Date collectionDate; + @Column(name="p_type", nullable=false, insertable=true, updatable=false) + private String type; + @Column(name="p_storage_path", nullable=true, insertable=true, updatable=true) + private String storagePath; + + @Column(name="p_title", nullable=false, insertable=true, updatable=true) + private String title; + @Column(name="p_description", nullable=true, insertable=true, updatable=true) + private String description; + @Column(name="p_content", nullable=true, insertable=true, updatable=true) + private String content; + @Column(name="p_signature", nullable=false, insertable=true, updatable=true) + private int signature; + @Column(name="p_business_path", nullable=false, insertable=true, updatable=true) + private String businessPath; + + @ManyToOne(targetEntity=IdentityImpl.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="fk_author_id", nullable=false, insertable=true, updatable=false) + private Identity author; + + @Override + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + @Override + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + + @Override + public Date getCollectionDate() { + return collectionDate; + } + + public void setCollectionDate(Date collectionDate) { + this.collectionDate = collectionDate; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getStoragePath() { + return storagePath; + } + + public void setStoragePath(String storagePath) { + this.storagePath = storagePath; + } + + @Override + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Override + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public int getSignature() { + return signature; + } + + public void setSignature(int signature) { + this.signature = signature; + } + + @Override + public String getBusinessPath() { + return businessPath; + } + + public void setBusinessPath(String businessPath) { + this.businessPath = businessPath; + } + + @Override + public Identity getAuthor() { + return author; + } + + public void setAuthor(Identity author) { + this.author = author; + } + + @Override + public int hashCode() { + return key == null ? 459537 : key.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(obj == this) { + return true; + } + if(obj instanceof MediaImpl) { + MediaImpl media = (MediaImpl)obj; + return key != null && key.equals(media.getKey()); + } + return false; + } + + @Override + public boolean equalsByPersistableKey(Persistable persistable) { + return equals(persistable); + } +} diff --git a/src/main/java/org/olat/modules/portfolio/model/MediaPart.java b/src/main/java/org/olat/modules/portfolio/model/MediaPart.java new file mode 100644 index 0000000000000000000000000000000000000000..c06b3a33698c3152915eb2801982b20d2b58e288 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/model/MediaPart.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.modules.portfolio.model; + +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import org.olat.modules.portfolio.Media; + +/** + * + * Initial date: 17.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Entity(name="pfmediapart") +@DiscriminatorColumn +public class MediaPart extends AbstractPart { + + private static final long serialVersionUID = -5902348088983758191L; + + @ManyToOne(targetEntity=MediaImpl.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="fk_media_id", nullable=false, insertable=true, updatable=false) + private Media media; + + public Media getMedia() { + return media; + } + + public void setMedia(Media media) { + this.media = media; + } + + + +} diff --git a/src/main/java/org/olat/modules/portfolio/model/MediaRow.java b/src/main/java/org/olat/modules/portfolio/model/MediaRow.java new file mode 100644 index 0000000000000000000000000000000000000000..5eb0a27dad93e88d6d94af4ceacc57e005a58bc8 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/model/MediaRow.java @@ -0,0 +1,57 @@ +/** + * <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.model; + +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.modules.portfolio.Media; + +/** + * + * Initial date: 20.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MediaRow { + + private Media media; + + private FormLink openFormLink; + + public MediaRow(Media media) { + this.media = media; + } + + public Long getKey() { + return media.getKey(); + } + + public String getTitle() { + return media.getTitle(); + } + + public FormLink getOpenFormItem() { + return openFormLink; + } + + public String getOpenFormItemName() { + return openFormLink == null ? null : openFormLink.getComponent().getComponentName(); + } + +} diff --git a/src/main/java/org/olat/modules/portfolio/ui/BinderRuntimeController.java b/src/main/java/org/olat/modules/portfolio/ui/BinderRuntimeController.java index 8a80cc32d8464bbcec30ec03ef3a17f5d13c5dbe..9f3c836377a3ea72f19a91def941232123596843 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/BinderRuntimeController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/BinderRuntimeController.java @@ -1,3 +1,22 @@ +/** + * <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 org.olat.core.gui.UserRequest; diff --git a/src/main/java/org/olat/modules/portfolio/ui/MediaCenterController.java b/src/main/java/org/olat/modules/portfolio/ui/MediaCenterController.java index aa665dffcc6a3c11b15e83ffd9eba5c26a7967c9..1270218e738628a314ba8df3a43d968509a0dd9c 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/MediaCenterController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/MediaCenterController.java @@ -19,12 +19,36 @@ */ package org.olat.modules.portfolio.ui; +import java.util.ArrayList; +import java.util.List; + import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; +import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponentDelegate; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRowCssDelegate; +import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.stack.TooledStackedPanel; +import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.util.StringHelper; +import org.olat.modules.portfolio.Media; +import org.olat.modules.portfolio.PortfolioService; +import org.olat.modules.portfolio.model.MediaRow; +import org.olat.modules.portfolio.ui.BindersDataModel.PortfolioCols; +import org.olat.modules.portfolio.ui.event.MediaSelectionEvent; +import org.springframework.beans.factory.annotation.Autowired; /** * @@ -32,34 +56,132 @@ import org.olat.core.gui.control.WindowControl; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class MediaCenterController extends FormBasicController { +public class MediaCenterController extends FormBasicController implements FlexiTableComponentDelegate, FlexiTableRowCssDelegate { + + private MediaDataModel model; + private FlexiTableElement tableEl; + private final boolean select; private final TooledStackedPanel stackPanel; + + private MediaDetailsController detailsCtrl; + + @Autowired + private PortfolioService portfolioService; + public MediaCenterController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "medias"); + this.stackPanel = null; + this.select = true; + + initForm(ureq); + loadModel(); + } + public MediaCenterController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel) { - super(ureq, wControl); + super(ureq, wControl, "medias"); this.stackPanel = stackPanel; + this.select = false; initForm(ureq); + loadModel(); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - setFormTitle("media.center"); + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, PortfolioCols.key, "select")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(PortfolioCols.title, "select")); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(PortfolioCols.open)); + + model = new MediaDataModel(columnsModel); + tableEl = uifactory.addTableElement(getWindowControl(), "table", model, 20, false, getTranslator(), formLayout); + tableEl.setAvailableRendererTypes(FlexiTableRendererType.custom, FlexiTableRendererType.classic); + tableEl.setRendererType(FlexiTableRendererType.custom); + tableEl.setSearchEnabled(true); + tableEl.setCustomizeColumns(true); + tableEl.setElementCssClass("o_binder_page_listing"); + tableEl.setEmtpyTableMessageKey("table.sEmptyTable"); + tableEl.setPageSize(24); + VelocityContainer row = createVelocityContainer("media_row"); + row.setDomReplacementWrapperRequired(false); // sets its own DOM id in velocity container + tableEl.setRowRenderer(row, this); + tableEl.setRowCssDelegate(this); + tableEl.setAndLoadPersistedPreferences(ureq, "media-list"); + } + + @Override + public String getRowCssClass(int pos) { + return null; + } + + @Override + public Iterable<Component> getComponents(int row, Object rowObject) { + return null; } + private void loadModel() { + List<Media> medias = portfolioService.searchOwnedMedias(getIdentity()); + List<MediaRow> rows = new ArrayList<>(medias.size()); + for(Media media:medias) { + MediaRow row = new MediaRow(media); + rows.add(row); + } + model.setObjects(rows); + } + @Override protected void doDispose() { // } + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == tableEl) { + if(event instanceof SelectionEvent) { + SelectionEvent se = (SelectionEvent)event; + String cmd = se.getCommand(); + MediaRow row = model.getObject(se.getIndex()); + if("select".equals(cmd)) { + if(select) { + doSelect(ureq, row.getKey()); + } else { + doOpenMedia(ureq, row.getKey()); + } + } + } + } else if(source instanceof FormLink) { + FormLink link = (FormLink)source; + String cmd = link.getCmd(); + if("open".equals(cmd)) { + MediaRow row = (MediaRow)link.getUserObject(); + Activateable2 activateable = doOpenMedia(ureq, row.getKey()); + if(activateable != null) { + activateable.activate(ureq, null, null); + } + } + } + super.formInnerEvent(ureq, source, event); + } + @Override protected void formOK(UserRequest ureq) { // } + - - - - + private void doSelect(UserRequest ureq, Long mediaKey) { + Media media = portfolioService.getMediaByKey(mediaKey); + fireEvent(ureq, new MediaSelectionEvent(media)); + } + + private Activateable2 doOpenMedia(UserRequest ureq, Long mediaKey) { + Media media = portfolioService.getMediaByKey(mediaKey); + detailsCtrl = new MediaDetailsController(ureq, getWindowControl(), media); + listenTo(detailsCtrl); + + String displayName = StringHelper.escapeHtml(media.getTitle()); + stackPanel.pushController(displayName, detailsCtrl); + return detailsCtrl; + } } diff --git a/src/main/java/org/olat/modules/portfolio/ui/MediaDataModel.java b/src/main/java/org/olat/modules/portfolio/ui/MediaDataModel.java new file mode 100644 index 0000000000000000000000000000000000000000..4bbebd81b8a7654117d1d6c7ddc5469dd421b7e3 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/MediaDataModel.java @@ -0,0 +1,82 @@ +/** + * <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 org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.modules.portfolio.model.MediaRow; +import org.olat.modules.portfolio.ui.PageListDataModel.PageCols; + +/** + * + * Initial date: 20.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MediaDataModel extends DefaultFlexiTableDataModel<MediaRow> { + + public MediaDataModel(FlexiTableColumnModel columnsModel) { + super(columnsModel); + } + + @Override + public Object getValueAt(int row, int col) { + MediaRow page = getObject(row); + switch(PageCols.values()[col]) { + case key: return page.getKey(); + case title: return page.getTitle(); + case open: return page.getOpenFormItem(); + } + return null; + } + + @Override + public DefaultFlexiTableDataModel<MediaRow> createCopyWithEmptyList() { + return new MediaDataModel(getTableColumnModel()); + } + + public enum MediaCols implements FlexiSortableColumnDef { + key("table.header.key"), + title("table.header.title"), + open("table.header.open"); + + private final String i18nKey; + + private MediaCols(String i18nKey) { + this.i18nKey = i18nKey; + } + + @Override + public String i18nHeaderKey() { + return i18nKey; + } + + @Override + public boolean sortable() { + return true; + } + + @Override + public String sortKey() { + return name(); + } + } +} diff --git a/src/main/java/org/olat/modules/portfolio/ui/MediaDetailsController.java b/src/main/java/org/olat/modules/portfolio/ui/MediaDetailsController.java new file mode 100644 index 0000000000000000000000000000000000000000..03ca20399722374b4713d262f2fa82ba60a0e2dc --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/MediaDetailsController.java @@ -0,0 +1,94 @@ +/** + * <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.List; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +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.StringHelper; +import org.olat.modules.portfolio.Media; +import org.olat.modules.portfolio.MediaHandler; +import org.olat.modules.portfolio.PortfolioService; +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 { + + private Media media; + private MediaHandler handler; + + private Controller mediaCtrl; + + @Autowired + private PortfolioService portfolioService; + + public MediaDetailsController(UserRequest ureq, WindowControl wControl, Media media) { + super(ureq, wControl, "media_details"); + this.media = media; + handler = portfolioService.getMediaHandler(media.getType()); + + initForm(ureq); + } + + @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()); + + mediaCtrl = handler.getMediaController(ureq, getWindowControl(), media); + if(mediaCtrl != null) { + listenTo(mediaCtrl); + layoutCont.put("media", mediaCtrl.getInitialComponent()); + } + } + } + + @Override + protected void doDispose() { + // + } + + @Override + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { + // + } + + @Override + protected void formOK(UserRequest ureq) { + // + } +} diff --git a/src/main/java/org/olat/modules/portfolio/ui/PageController.java b/src/main/java/org/olat/modules/portfolio/ui/PageController.java index 436ab3a7238ee7fe6c3d08fa49889fd0c423f40f..c8023c39db70be8105df7126f59b3e3bb0484ad0 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/PageController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/PageController.java @@ -32,17 +32,22 @@ 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.components.text.TextComponent; +import org.olat.core.gui.components.text.TextFactory; 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.util.CodeHelper; import org.olat.modules.portfolio.Binder; import org.olat.modules.portfolio.BinderSecurityCallback; +import org.olat.modules.portfolio.MediaHandler; import org.olat.modules.portfolio.Page; import org.olat.modules.portfolio.PagePart; import org.olat.modules.portfolio.PortfolioService; import org.olat.modules.portfolio.Section; import org.olat.modules.portfolio.model.HTMLPart; +import org.olat.modules.portfolio.model.MediaPart; import org.olat.modules.portfolio.ui.editor.PageEditorController; import org.springframework.beans.factory.annotation.Autowired; @@ -56,12 +61,13 @@ public class PageController extends FormBasicController implements TooledControl private Link editLink, editMetadataLink; protected final TooledStackedPanel stackPanel; - private List<HTMLFragment> fragments = new ArrayList<>(); + private List<FragmentWrapper> fragments = new ArrayList<>(); private CloseableModalController cmc; private PageEditorController editCtrl; private PageMetadataEditController editMetadataCtrl; + private int counter; private Page page; private final BinderSecurityCallback secCallback; @@ -76,7 +82,7 @@ public class PageController extends FormBasicController implements TooledControl this.secCallback = secCallback; initForm(ureq); - loadModel(); + loadModel(ureq); } @Override @@ -102,15 +108,17 @@ public class PageController extends FormBasicController implements TooledControl } } - private void loadModel() { + private void loadModel(UserRequest ureq) { flc.getFormItemComponent().contextPut("pageTitle", page.getTitle()); List<PagePart> parts = portfolioService.getPageParts(page); - List<HTMLFragment> newFragments = new ArrayList<>(parts.size()); + List<FragmentWrapper> newFragments = new ArrayList<>(parts.size()); for(PagePart part:parts) { - HTMLFragment fragment = createFragment(part); + Fragment fragment = createFragment(ureq, part); if(fragment != null) { - newFragments.add(fragment); + String cmpId = "cpt-" + (++counter); + newFragments.add(new FragmentWrapper(cmpId, fragment.getContent())); + flc.getFormItemComponent().put(cmpId, fragment.getContent()); } } fragments = newFragments; @@ -126,10 +134,10 @@ public class PageController extends FormBasicController implements TooledControl public void event(UserRequest ureq, Controller source, Event event) { if(editCtrl == source) { stackPanel.popUpToController(this); - loadModel(); + loadModel(ureq); } else if(editMetadataCtrl == source) { if(event == Event.DONE_EVENT) { - loadModel(); + loadModel(ureq); } cmc.deactivate(); cleanUp(); @@ -191,34 +199,82 @@ public class PageController extends FormBasicController implements TooledControl stackPanel.pushController("Edit", editCtrl); } - private HTMLFragment createFragment(PagePart part) { + private Fragment createFragment(UserRequest ureq, PagePart part) { if(part instanceof HTMLPart) { HTMLPart htmlPart = (HTMLPart)part; HTMLFragment editorFragment = new HTMLFragment(htmlPart); return editorFragment; + } else if(part instanceof MediaPart) { + MediaPart htmlPart = (MediaPart)part; + MediaFragment editorFragment = new MediaFragment(htmlPart, ureq); + return editorFragment; } return null; - } - public static class HTMLFragment { + public class MediaFragment implements Fragment { - private PagePart part; + private final PagePart part; + private Controller controller; - public HTMLFragment(HTMLPart part) { + public MediaFragment(MediaPart part, UserRequest ureq) { this.part = part; + MediaHandler handler = portfolioService.getMediaHandler(part.getMedia().getType()); + controller = handler.getMediaController(ureq, getWindowControl(), part.getMedia()); } - public String getContent() { - return part.getContent(); + @Override + public Component getContent() { + return controller.getInitialComponent(); } public PagePart getPart() { return part; } + } + + public static class HTMLFragment implements Fragment { + + private final PagePart part; + private TextComponent component; - public void setPart(PagePart part) { + public HTMLFragment(HTMLPart part) { this.part = part; + component = TextFactory.createTextComponentFromString("cmp" + CodeHelper.getRAMUniqueID(), part.getContent(), null, false, null); + } + + @Override + public Component getContent() { + return component; + } + + public PagePart getPart() { + return part; + } + } + + public interface Fragment { + + public Component getContent(); + + } + + public static final class FragmentWrapper { + + private final String componentName; + private final Component component; + + public FragmentWrapper(String componentName, Component component) { + this.componentName = componentName; + this.component = component; + } + + public String getComponentName() { + return componentName; + } + + public Component getComponent() { + return component; } } } diff --git a/src/main/java/org/olat/modules/portfolio/ui/_content/media_details.html b/src/main/java/org/olat/modules/portfolio/ui/_content/media_details.html new file mode 100644 index 0000000000000000000000000000000000000000..faf960c0f61bfe76306c34d08eaec10a8a7727e3 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/_content/media_details.html @@ -0,0 +1,5 @@ +<h2><i class="o_icon o_icon-lg $iconCssClass"> </i> $title</h2> + +<div class="clearfix"> +$r.render("media") +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/modules/portfolio/ui/_content/media_row.html b/src/main/java/org/olat/modules/portfolio/ui/_content/media_row.html new file mode 100644 index 0000000000000000000000000000000000000000..5ab2f8a4323abafb10abb68657d9d39f1a775057 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/_content/media_row.html @@ -0,0 +1 @@ +Hello \ No newline at end of file diff --git a/src/main/java/org/olat/modules/portfolio/ui/_content/medias.html b/src/main/java/org/olat/modules/portfolio/ui/_content/medias.html new file mode 100644 index 0000000000000000000000000000000000000000..bade9402acda206e8171adcb2d85adb1b884ea54 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/_content/medias.html @@ -0,0 +1 @@ +$r.render("table") \ No newline at end of file diff --git a/src/main/java/org/olat/modules/portfolio/ui/_content/page_content.html b/src/main/java/org/olat/modules/portfolio/ui/_content/page_content.html index c298d097debad73fe54e7d4d4d18f6133850c8b8..eb31c305035b8997ac658b5ac6b273d20c2f88c2 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/_content/page_content.html +++ b/src/main/java/org/olat/modules/portfolio/ui/_content/page_content.html @@ -1,4 +1,4 @@ <h1>$pageTitle</h1> #foreach($fragment in $fragments) - <div class="">$fragment.content</div> + <div class="">$r.render($fragment.componentName)</div> #end \ No newline at end of file diff --git a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties index 828105f4907387556d985c58188e1ba367107f84..8b6f5e97ba23fa303bbfd0513f9c99b6b04f57a4 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties @@ -3,6 +3,11 @@ access.rights.owner.long=als Besitzer (lesen / schreiben) access.rights.coach.long=als Betreuer (lesen / kommentieren / bewerten) access.rights.reviewer.long=als Reviewer (lesen / kommentieren) +artefact.collect.date=Datum + +artefact.descr=Beschreibung +artefact.title=Titel +artefact.source=Quelle meta.last.modified=zuletzt bearbeitet am {0} portfolio.personal.menu.title=Portfolio 2.0 portfolio.personal.menu.title.alt=$\:portfolio.personal.menu.title 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 1270d43dedb646801ef7a39e4047122e15a10d9c..8fa1662f6bfc589ccff444fb43622be014393eab 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 @@ -15,8 +15,14 @@ access.rights.date=Date access.rights.owner.long=as owner (read / write) access.rights.coach.long=as coach (read / comment / assess) access.rights.reviewer.long=as reviewer (read / comment) -add.html=HTML +add.html=Add HTML +add.media=Add media add.member=Add member +artefact.collect.date=Date +artefact.collect.link=Link +artefact.descr=Description +artefact.title=Title +artefact.source=Source begin.date=Begin binder.by=by {0} categories=Categories diff --git a/src/main/java/org/olat/modules/portfolio/ui/component/MediaCollectorComponent.java b/src/main/java/org/olat/modules/portfolio/ui/component/MediaCollectorComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..f1af63f6d6dfd0010923364bbe7b63b98b67b97d --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/component/MediaCollectorComponent.java @@ -0,0 +1,112 @@ +/** + * <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.component; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.ComponentRenderer; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.impl.FormBaseComponentImpl; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.ControllerEventListener; +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.modules.portfolio.MediaHandler; +import org.olat.modules.portfolio.ui.wizard.CollectArtefactController; + +/** + * + * Initial date: 17.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MediaCollectorComponent extends FormBaseComponentImpl implements ControllerEventListener { + + private CloseableModalController cmc; + private CollectArtefactController collectorCtrl; + + private static final ComponentRenderer RENDERER = new MediaCollectorComponentRenderer(); + + private FormItem item; + private final WindowControl wControl; + + private final Object media; + private final String businessPath; + private final MediaHandler handler; + + public MediaCollectorComponent(String name, WindowControl wControl, Object media, MediaHandler handler, String businessPath) { + super(name); + this.wControl = wControl; + this.media = media; + this.handler = handler; + this.businessPath = businessPath; + } + + public FormItem getItem() { + return item; + } + + @Override + protected void doDispatchRequest(UserRequest ureq) { + String cmd = ureq.getParameter(VelocityContainer.COMMAND_ID); + if("pfcollect".equalsIgnoreCase(cmd)) { + doOpenCollector(ureq); + } + } + + @Override + public void dispatchEvent(UserRequest ureq, Controller source, Event event) { + if(collectorCtrl == source) { + + cmc.deactivate(); + cleanUp(); + } else if(cmc == source) { + cleanUp(); + } + } + + private void cleanUp() { + if(collectorCtrl != null) { + //collectorCtrl.addControllerListener(el); + collectorCtrl = null; + } + if(cmc != null) { + cmc = null; + } + + } + + private void doOpenCollector(UserRequest ureq) { + collectorCtrl = new CollectArtefactController(ureq, wControl, media, handler, businessPath); + collectorCtrl.addControllerListener(this); + + String title = "Media"; + cmc = new CloseableModalController(wControl, null, collectorCtrl.getInitialComponent(), true, title, true); + cmc.addControllerListener(this); + cmc.activate(); + + } + + @Override + public ComponentRenderer getHTMLRendererSingleton() { + return RENDERER; + } +} diff --git a/src/main/java/org/olat/modules/portfolio/ui/component/MediaCollectorComponentRenderer.java b/src/main/java/org/olat/modules/portfolio/ui/component/MediaCollectorComponentRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..03a4ae529d3bed286ef28f777a2c1e7edb660139 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/component/MediaCollectorComponentRenderer.java @@ -0,0 +1,57 @@ +/** + * <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.component; + +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.DefaultComponentRenderer; +import org.olat.core.gui.components.form.flexible.impl.NameValuePair; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.render.RenderResult; +import org.olat.core.gui.render.Renderer; +import org.olat.core.gui.render.StringOutput; +import org.olat.core.gui.render.URLBuilder; +import org.olat.core.gui.translator.Translator; + +/** + * + * Initial date: 17.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MediaCollectorComponentRenderer extends DefaultComponentRenderer { + + @Override + public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, + RenderResult renderResult, String[] args) { + MediaCollectorComponent cmp = (MediaCollectorComponent)source; + sb.append("<a class='o_portfolio_collector' "); + + if(cmp.getItem() == null) { + ubu.buildHrefAndOnclick(sb, null, true, false, true, + new NameValuePair(VelocityContainer.COMMAND_ID, "pfcollect")); + } + + + + sb.append("><i class='o_icon o_icon-lg o_icon_eportfolio_add'> </i></a>"); + } + + +} diff --git a/src/main/java/org/olat/modules/portfolio/ui/editor/PageEditorController.java b/src/main/java/org/olat/modules/portfolio/ui/editor/PageEditorController.java index 963c96e4e8f69e6fd1ca35a4c337bf2fc5ec4bd0..d1027af1b30a52a5e3a2b6080bbdfd226aa61f97 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/editor/PageEditorController.java +++ b/src/main/java/org/olat/modules/portfolio/ui/editor/PageEditorController.java @@ -34,14 +34,19 @@ 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.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.util.StringHelper; -import org.olat.core.util.UserSession; import org.olat.core.util.Util; +import org.olat.modules.portfolio.Media; +import org.olat.modules.portfolio.MediaHandler; import org.olat.modules.portfolio.Page; import org.olat.modules.portfolio.PagePart; import org.olat.modules.portfolio.PortfolioService; import org.olat.modules.portfolio.model.HTMLPart; +import org.olat.modules.portfolio.model.MediaPart; +import org.olat.modules.portfolio.ui.MediaCenterController; import org.olat.modules.portfolio.ui.PageController; +import org.olat.modules.portfolio.ui.event.MediaSelectionEvent; import org.springframework.beans.factory.annotation.Autowired; /** @@ -52,9 +57,12 @@ import org.springframework.beans.factory.annotation.Autowired; */ public class PageEditorController extends FormBasicController { - private FormLink addHtmlLink; - private List<HTMLEditorFragment> fragments = new ArrayList<>(); + private FormLink addHtmlLink, addMediaLink; + private List<EditorFragment> fragments = new ArrayList<>(); + private CloseableModalController cmc; + private MediaCenterController mediaListCtrl; + private Page page; private int counter = 0; @@ -74,6 +82,9 @@ public class PageEditorController extends FormBasicController { protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { addHtmlLink = uifactory.addFormLink("add.html", "add.html", "add.html", null, formLayout, Link.BUTTON); addHtmlLink.setIconLeftCSS("o_icon o_icon_add_html"); + + addMediaLink = uifactory.addFormLink("add.media", "add.media", "add.media", null, formLayout, Link.BUTTON); + addMediaLink.setIconLeftCSS("o_icon o_icon_portfolio"); uifactory.addFormSubmitButton("save", formLayout); @@ -84,11 +95,10 @@ public class PageEditorController extends FormBasicController { } private void loadModel(UserRequest ureq) { - UserSession usess = ureq.getUserSession(); List<PagePart> parts = portfolioService.getPageParts(page); - List<HTMLEditorFragment> newFragments = new ArrayList<>(parts.size()); + List<EditorFragment> newFragments = new ArrayList<>(parts.size()); for(PagePart part:parts) { - HTMLEditorFragment fragment = createFragment(part, usess); + EditorFragment fragment = createFragment(ureq, part); if(fragment != null) { newFragments.add(fragment); } @@ -106,6 +116,8 @@ public class PageEditorController extends FormBasicController { protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(addHtmlLink == source) { doAddHTMLFragment(ureq); + } else if(addMediaLink == source) { + doOpenMediaBrowser(ureq); } else if(source.getUserObject() instanceof HTMLEditorFragment) { HTMLEditorFragment fragment = (HTMLEditorFragment)source.getUserObject(); if(fragment.getFormItem() == source) { @@ -127,48 +139,104 @@ public class PageEditorController extends FormBasicController { @Override protected void formOK(UserRequest ureq) { - for(HTMLEditorFragment fragment:fragments) { - String htmlVal = fragment.getFormItem().getValue(); - String currentHtmlVal = fragment.getPart().getContent(); - - if((currentHtmlVal == null && StringHelper.containsNonWhitespace(htmlVal)) - || (htmlVal == null && StringHelper.containsNonWhitespace(currentHtmlVal)) - || (currentHtmlVal != null && !currentHtmlVal.equals(htmlVal))) { - PagePart part = fragment.getPart(); - part.setContent(htmlVal); - fragment.setPart(portfolioService.updatePart(part)); + for(EditorFragment fragment:fragments) { + if(fragment instanceof HTMLEditorFragment) { + HTMLEditorFragment htmlFragment = (HTMLEditorFragment)fragment; + String htmlVal = htmlFragment.getFormItem().getValue(); + String currentHtmlVal = fragment.getPart().getContent(); + + if((currentHtmlVal == null && StringHelper.containsNonWhitespace(htmlVal)) + || (htmlVal == null && StringHelper.containsNonWhitespace(currentHtmlVal)) + || (currentHtmlVal != null && !currentHtmlVal.equals(htmlVal))) { + PagePart part = fragment.getPart(); + part.setContent(htmlVal); + htmlFragment.setPart(portfolioService.updatePart(part)); + } } } fireEvent(ureq, Event.DONE_EVENT); } + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(mediaListCtrl == source) { + if(event instanceof MediaSelectionEvent) { + MediaSelectionEvent mse = (MediaSelectionEvent)event; + if(mse.getMedia() != null) { + doAddMedia(ureq, mse.getMedia()); + } + } + cmc.deactivate(); + cleanUp(); + } else if(cmc == source) { + cleanUp(); + } + super.event(ureq, source, event); + } + + private void cleanUp() { + removeAsListenerAndDispose(mediaListCtrl); + removeAsListenerAndDispose(cmc); + mediaListCtrl = null; + cmc = null; + } + + private void doOpenMediaBrowser(UserRequest ureq) { + if(mediaListCtrl != null) return; + + mediaListCtrl = new MediaCenterController(ureq, getWindowControl()); + listenTo(mediaListCtrl); + + String title = translate("add.media"); + cmc = new CloseableModalController(getWindowControl(), null, mediaListCtrl.getInitialComponent(), true, title, true); + listenTo(cmc); + cmc.activate(); + } + + private void doAddMedia(UserRequest ureq, Media media) { + MediaPart part = new MediaPart(); + part.setMedia(media); + part = portfolioService.appendNewPagePart(page, part); + EditorFragment fragment = createFragment(ureq, part); + fragments.add(fragment); + flc.setDirty(true); + } + private void doAddHTMLFragment(UserRequest ureq) { String content = "<p>Hello world</p>"; HTMLPart htmlPart = new HTMLPart(); htmlPart.setContent(content); htmlPart = portfolioService.appendNewPagePart(page, htmlPart); - HTMLEditorFragment fragment = createFragment(htmlPart, ureq.getUserSession()); + EditorFragment fragment = createFragment(ureq, htmlPart); fragments.add(fragment); flc.setDirty(true); } - private HTMLEditorFragment createFragment(PagePart part, UserSession usess) { + private EditorFragment createFragment(UserRequest ureq, PagePart part) { if(part instanceof HTMLPart) { HTMLPart htmlPart = (HTMLPart)part; HTMLEditorFragment editorFragment = new HTMLEditorFragment(htmlPart); String cmpId = "html-" + (++counter); String content = htmlPart.getContent(); - RichTextElement htmlItem = uifactory.addRichTextElementForStringDataCompact(cmpId, null, content, 25, 80, null, flc, usess, getWindowControl()); + RichTextElement htmlItem = uifactory.addRichTextElementForStringDataCompact(cmpId, null, content, 25, 80, null, flc, ureq.getUserSession(), getWindowControl()); //htmlItem.getEditorConfiguration().setInline(true); editorFragment.setFormItem(htmlItem); return editorFragment; + } else if (part instanceof MediaPart) { + MediaPart mediaPart = (MediaPart)part; + MediaHandler handler = portfolioService.getMediaHandler(mediaPart.getMedia().getType()); + String cmpId = "media-" + (++counter); + Controller mediaCtrl = handler.getMediaController(ureq, getWindowControl(), mediaPart.getMedia()); + MediaEditorFragment fragment = new MediaEditorFragment(mediaPart, cmpId, mediaCtrl); + flc.getFormItemComponent().put(cmpId, mediaCtrl.getInitialComponent()); + return fragment; } return null; } - public static class HTMLEditorFragment { + public static class HTMLEditorFragment implements EditorFragment { private PagePart part; private RichTextElement formItem; @@ -177,6 +245,7 @@ public class PageEditorController extends FormBasicController { this.part = part; } + @Override public PagePart getPart() { return part; } @@ -193,9 +262,46 @@ public class PageEditorController extends FormBasicController { this.formItem = formItem; formItem.setUserObject(this); } - + + @Override public String getComponentName() { return formItem.getComponent().getComponentName(); } } + + public static class MediaEditorFragment implements EditorFragment { + + private PagePart part; + private String cmpName; + private Controller controller; + + public MediaEditorFragment(MediaPart part, String cmpName, Controller controller) { + this.part = part; + this.cmpName = cmpName; + this.controller = controller; + } + + @Override + public PagePart getPart() { + return part; + } + + public void setPart(PagePart part) { + this.part = part; + } + + @Override + public String getComponentName() { + return cmpName; + } + } + + public interface EditorFragment { + + public PagePart getPart(); + + public void setPart(PagePart part); + + public String getComponentName(); + } } diff --git a/src/main/java/org/olat/modules/portfolio/ui/editor/_content/page_editor.html b/src/main/java/org/olat/modules/portfolio/ui/editor/_content/page_editor.html index 281a62fb4bbd2ccbffa79ddaf92006b87d3f70b8..e2a30f54c072282bf0bd30013ee258c7a5def460 100644 --- a/src/main/java/org/olat/modules/portfolio/ui/editor/_content/page_editor.html +++ b/src/main/java/org/olat/modules/portfolio/ui/editor/_content/page_editor.html @@ -1,6 +1,6 @@ <h1>$pageTitle</h1> <div class="o_button_group o_button_group_left"> -$r.render("save") $r.render("add.html") +$r.render("save") $r.render("add.html") $r.render("add.media") </div> #foreach($fragment in $fragments) diff --git a/src/main/java/org/olat/modules/portfolio/ui/event/MediaSelectionEvent.java b/src/main/java/org/olat/modules/portfolio/ui/event/MediaSelectionEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..20b8aaadd47998ed0d54ff9c74ee4b8e4c03f55e --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/event/MediaSelectionEvent.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.modules.portfolio.ui.event; + +import org.olat.core.gui.control.Event; +import org.olat.modules.portfolio.Media; + +/** + * + * Initial date: 20.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MediaSelectionEvent extends Event { + + private static final long serialVersionUID = -7111363042350387554L; + private Media media; + + public MediaSelectionEvent(Media media) { + super("pf-media-select"); + this.media = media; + } + + public Media getMedia() { + return media; + } +} diff --git a/src/main/java/org/olat/modules/portfolio/ui/wizard/CollectArtefactController.java b/src/main/java/org/olat/modules/portfolio/ui/wizard/CollectArtefactController.java new file mode 100644 index 0000000000000000000000000000000000000000..d8bc46d70509bafe8f7beaf039969067ee1f64a6 --- /dev/null +++ b/src/main/java/org/olat/modules/portfolio/ui/wizard/CollectArtefactController.java @@ -0,0 +1,139 @@ +/** + * <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.wizard; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.StaticTextElement; +import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +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.context.BusinessControlFactory; +import org.olat.core.util.Formatter; +import org.olat.core.util.Util; +import org.olat.modules.portfolio.Media; +import org.olat.modules.portfolio.MediaHandler; +import org.olat.modules.portfolio.PortfolioService; +import org.olat.modules.portfolio.ui.PortfolioHomeController; +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 CollectArtefactController extends FormBasicController { + + private TextElement titleEl; + private TextElement descriptionEl; + private TextBoxListElement categoriesEl; + + private StaticTextElement sourceEl; + private StaticTextElement dateEl; + private StaticTextElement linkEl; + + private Media mediaReference; + private final Object mediaObject; + private final MediaHandler handler; + private Map<String,String> categories = new HashMap<>(); + + private final String businessPath; + + @Autowired + private PortfolioService portfolioService; + + public CollectArtefactController(UserRequest ureq, WindowControl wControl, Object mediaObject, MediaHandler handler, String businessPath) { + super(ureq, wControl); + setTranslator(Util.createPackageTranslator(PortfolioHomeController.class, getLocale(), getTranslator())); + this.handler = handler; + this.mediaObject = mediaObject; + this.businessPath = businessPath; + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + titleEl = uifactory.addTextElement("artefact.title", "artefact.title", 255, "", formLayout); + titleEl.setMandatory(true); + + descriptionEl = uifactory.addRichTextElementForStringData("artefact.descr", "artefact.descr", "", 8, 6, false, null, null, formLayout, ureq.getUserSession(), getWindowControl()); + + categoriesEl = uifactory.addTextBoxListElement("categories", "categories", "categories.hint", categories, formLayout, getTranslator()); + categoriesEl.setElementCssClass("o_sel_ep_tagsinput"); + categoriesEl.setAllowDuplicates(false); + + String source = "Forum"; + uifactory.addStaticTextElement("artefact.source", "artefact.source", source, formLayout); + String date = Formatter.getInstance(getLocale()).formatDate(new Date()); + uifactory.addStaticTextElement("artefact.collect.date", "artefact.collect.date", date, formLayout); + + String link = BusinessControlFactory.getInstance().getURLFromBusinessPathString(businessPath); + uifactory.addStaticTextElement("artefact.collect.link", "artefact.collect.link", link, formLayout); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("save", "save", buttonsCont); + uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = true; + + return allOk & super.validateFormLogic(ureq); + } + + @Override + protected void formOK(UserRequest ureq) { + if(mediaReference == null) { + String title = titleEl.getValue(); + String description = descriptionEl.getValue(); + mediaReference = handler.createMedia(title, description, mediaObject, businessPath, getIdentity()); + } else { + //TODO + } + + List<String> updatedCategories = categoriesEl.getValueList(); + portfolioService.updateCategories(mediaReference, updatedCategories); + + fireEvent(ureq, Event.DONE_EVENT); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } +} diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 16ae4e66012842a2c5d18d8a0b4cae1daa4ea7ae..3c1a751688fd649439e2ca3e58b63d748fd032f8 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -160,7 +160,9 @@ <class>org.olat.modules.portfolio.model.PageImpl</class> <class>org.olat.modules.portfolio.model.PageBodyImpl</class> <class>org.olat.modules.portfolio.model.AbstractPart</class> + <class>org.olat.modules.portfolio.model.MediaImpl</class> <class>org.olat.modules.portfolio.model.HTMLPart</class> + <class>org.olat.modules.portfolio.model.MediaPart</class> <class>org.olat.modules.portfolio.model.CategoryImpl</class> <class>org.olat.modules.portfolio.model.CategoryToElementImpl</class> <class>org.olat.modules.qpool.model.PoolImpl</class> 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 b7b2df2a9f21eee3d8ea0a4ba91b96170fe1ec91..a9f1e41084a8178ea57eaaea17e62be3f91aac6b 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 @@ -190,6 +190,26 @@ alter table o_pf_page_body ENGINE = InnoDB; alter table o_pf_page add constraint pf_page_body_idx foreign key (fk_body_id) references o_pf_page_body (id); +create table o_pf_media ( + id bigint not null auto_increment, + creationdate datetime not null, + p_collection_date datetime not null, + p_type varchar(64) not null, + p_storage_path varchar(255), + p_title varchar(255) not null, + p_description mediumtext, + p_content mediumtext, + p_signature bigint not null default 0, + p_business_path varchar(255) not null, + fk_author_id bigint not null, + primary key (id) +); +alter table o_pf_media ENGINE = InnoDB; + +alter table o_pf_media add constraint pf_media_author_idx foreign key (fk_author_id) references o_bs_identity (id); +create index idx_media_storage_path_idx on o_pf_media (p_business_path); + + create table o_pf_page_part ( id bigint not null auto_increment, creationdate datetime not null, @@ -197,12 +217,14 @@ create table o_pf_page_part ( pos bigint default null, dtype varchar(32), p_content mediumtext, + fk_media_id bigint, fk_page_body_id bigint, primary key (id) ); alter table o_pf_page_part ENGINE = InnoDB; alter table o_pf_page_part add constraint pf_page_page_body_idx foreign key (fk_page_body_id) references o_pf_page_body (id); +alter table o_pf_page_part add constraint pf_page_media_idx foreign key (fk_media_id) references o_pf_media (id); create table o_pf_category ( diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql index 053a4944084764ebe84b67fa013747a778c798c1..d9808b1dee2c9647af5f41314eb93e98947c801f 100644 --- a/src/main/resources/database/mysql/setupDatabase.sql +++ b/src/main/resources/database/mysql/setupDatabase.sql @@ -1603,7 +1603,6 @@ create table o_pf_binder ( primary key (id) ); - create table o_pf_section ( id bigint not null auto_increment, creationdate datetime not null, @@ -1620,7 +1619,6 @@ create table o_pf_section ( primary key (id) ); - create table o_pf_page ( id bigint not null auto_increment, creationdate datetime not null, @@ -1646,6 +1644,20 @@ create table o_pf_page_body ( primary key (id) ); +create table o_pf_media ( + id bigint not null auto_increment, + creationdate datetime not null, + p_collection_date datetime not null, + p_type varchar(64) not null, + p_storage_path varchar(255), + p_title varchar(255) not null, + p_description mediumtext, + p_content mediumtext, + p_signature bigint not null default 0, + p_business_path varchar(255) not null, + fk_author_id bigint not null, + primary key (id) +); create table o_pf_page_part ( id bigint not null auto_increment, @@ -1654,11 +1666,11 @@ create table o_pf_page_part ( pos bigint default null, dtype varchar(32), p_content mediumtext, + fk_media_id bigint, fk_page_body_id bigint, primary key (id) ); - create table o_pf_category ( id bigint not null auto_increment, creationdate datetime not null, @@ -1666,8 +1678,6 @@ create table o_pf_category ( primary key (id) ); - - create table o_pf_category_relation ( id bigint not null auto_increment, creationdate datetime not null, @@ -1677,11 +1687,7 @@ create table o_pf_category_relation ( primary key (id) ); - - - - - +-- lti create table o_lti_outcome ( id bigint not null, creationdate datetime not null, @@ -2105,6 +2111,7 @@ alter table o_goto_registrant ENGINE = InnoDB; alter table o_vid_transcoding ENGINE = InnoDB; alter table o_pf_category_relation ENGINE = InnoDB; alter table o_pf_category ENGINE = InnoDB; +alter table o_pf_media ENGINE = InnoDB; alter table o_pf_page_part ENGINE = InnoDB; alter table o_pf_section ENGINE = InnoDB; alter table o_pf_page_body ENGINE = InnoDB; @@ -2472,7 +2479,11 @@ alter table o_pf_page add constraint pf_page_section_idx foreign key (fk_section alter table o_pf_page add constraint pf_page_body_idx foreign key (fk_body_id) references o_pf_page_body (id); +alter table o_pf_media add constraint pf_media_author_idx foreign key (fk_author_id) references o_bs_identity (id); +create index idx_category_rel_resid_idx on o_pf_media (p_business_path); + alter table o_pf_page_part add constraint pf_page_page_body_idx foreign key (fk_page_body_id) references o_pf_page_body (id); +alter table o_pf_page_part add constraint pf_page_media_idx foreign key (fk_media_id) references o_pf_media (id); create index idx_category_name_idx on o_pf_category (p_name); 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 3bb549ecb4bfd8a4e172021db4cb953400013d18..a1de946280e5adce4236255c6b3b5d2d59bad8d3 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 @@ -211,12 +211,34 @@ create table o_pf_page_part ( pos int8 default null, dtype varchar(32), p_content text, + fk_media_id int8, fk_page_body_id int8, primary key (id) ); alter table o_pf_page_part add constraint pf_page_page_body_idx foreign key (fk_page_body_id) references o_pf_page_body (id); create index idx_pf_page_page_body_idx on o_pf_page_part (fk_page_body_id); +alter table o_pf_page_part add constraint pf_page_media_idx foreign key (fk_media_id) references o_pf_media (id); +create index idx_pf_page_media_idx on o_pf_page_part (fk_media_id); + +create table o_pf_media ( + id bigserial, + creationdate timestamp not null, + p_collection_date timestamp not null, + p_type varchar(64) not null, + p_storage_path varchar(255), + p_title varchar(255) not null, + p_description text, + p_content text, + p_signature int8 not null default 0, + p_business_path varchar(255) not null, + fk_author_id int8 not null, + primary key (id) +); + +alter table o_pf_media add constraint pf_media_author_idx foreign key (fk_author_id) references o_bs_identity (id); +create index idx_pf_media_author_idx on o_pf_media (fk_author_id); +create index idx_media_storage_path_idx on o_pf_media (p_business_path); create table o_pf_category ( diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql index 4193afac0e22ec586945f26e91c0c6510e04a3f5..ade89b3b4df49682aba24fa9b7eadb325e946221 100644 --- a/src/main/resources/database/postgresql/setupDatabase.sql +++ b/src/main/resources/database/postgresql/setupDatabase.sql @@ -1533,10 +1533,26 @@ create table o_pf_page_part ( pos int8 default null, dtype varchar(32), p_content text, + fk_media_id int8, fk_page_body_id int8, primary key (id) ); +create table o_pf_media ( + id bigserial, + creationdate timestamp not null, + p_collection_date timestamp not null, + p_type varchar(64) not null, + p_storage_path varchar(255), + p_title varchar(255) not null, + p_description text, + p_content text, + p_signature int8 not null default 0, + p_business_path varchar(255) not null, + fk_author_id int8 not null, + primary key (id) +); + create table o_pf_category ( id bigserial, creationdate timestamp not null, @@ -2480,6 +2496,12 @@ create index idx_pf_page_body_idx on o_pf_page (fk_body_id); alter table o_pf_page_part add constraint pf_page_page_body_idx foreign key (fk_page_body_id) references o_pf_page_body (id); create index idx_pf_page_page_body_idx on o_pf_page_part (fk_page_body_id); +alter table o_pf_page_part add constraint pf_page_media_idx foreign key (fk_media_id) references o_pf_media (id); +create index idx_pf_page_media_idx on o_pf_page_part (fk_media_id); + +alter table o_pf_media add constraint pf_media_author_idx foreign key (fk_author_id) references o_bs_identity (id); +create index idx_pf_media_author_idx on o_pf_media (fk_author_id); +create index idx_media_storage_path_idx on o_pf_media (p_business_path); create index idx_category_name_idx on o_pf_category (p_name); diff --git a/src/test/java/org/olat/modules/portfolio/manager/MediaDAOTest.java b/src/test/java/org/olat/modules/portfolio/manager/MediaDAOTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a1b31f31650bbd0ea1951a3d8ebf3d79112c0311 --- /dev/null +++ b/src/test/java/org/olat/modules/portfolio/manager/MediaDAOTest.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.modules.portfolio.manager; + +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.portfolio.Media; +import org.olat.test.JunitTestHelper; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 17.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MediaDAOTest extends OlatTestCase { + + @Autowired + private DB dbInstance; + @Autowired + private MediaDAO mediaDao; + + @Test + public void createMedia() { + Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("pf-media-1"); + Media media = mediaDao.createMedia("Media", "Media description", "Media content", "Forum", "[Media:0]", 10, id); + dbInstance.commit(); + + Assert.assertNotNull(media); + Assert.assertNotNull(media.getKey()); + Assert.assertNotNull(media.getCreationDate()); + Assert.assertNotNull(media.getCollectionDate()); + Assert.assertEquals(id, media.getAuthor()); + + Media reloadedMedia = mediaDao.loadByKey(media.getKey()); + Assert.assertNotNull(reloadedMedia); + Assert.assertEquals(media, reloadedMedia); + Assert.assertEquals(id, reloadedMedia.getAuthor()); + Assert.assertEquals("Media", reloadedMedia.getTitle()); + Assert.assertEquals("Media description", reloadedMedia.getDescription()); + Assert.assertEquals("[Media:0]", reloadedMedia.getBusinessPath()); + Assert.assertEquals(id, reloadedMedia.getAuthor()); + } + +} diff --git a/src/test/java/org/olat/selenium/PortfolioTest.java b/src/test/java/org/olat/selenium/PortfolioTest.java index 6068c4e4c12655232234eabff70973929e0a5924..db70fbd2689c74e3449c3fce72bd81bfd8e36881 100644 --- a/src/test/java/org/olat/selenium/PortfolioTest.java +++ b/src/test/java/org/olat/selenium/PortfolioTest.java @@ -23,6 +23,8 @@ import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import org.jboss.arquillian.container.test.api.Deployment; @@ -58,13 +60,22 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; - +/** + * + * Suite of test for the e-Portfolio version 1.0 + * + * Initial date: 20.06.2016<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ @RunWith(Arquillian.class) public class PortfolioTest { @Deployment(testable = false) public static WebArchive createDeployment() { - return ArquillianDeployments.createDeployment(); + Map<String,String> propertyPortfolioV1 = new HashMap<>(); + propertyPortfolioV1.put("portfoliov2.enabled", "false"); + return ArquillianDeployments.createDeployment(propertyPortfolioV1); } @Drone diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index 47c3141a931eef663337b9cf152ed0e18598b263..7ff15aca7cb145e830a7618e06eba1ef6bb9f814 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -155,6 +155,9 @@ import org.junit.runners.Suite; org.olat.modules.gotomeeting.manager.GoToRegistrantDAOTest.class, org.olat.modules.gotomeeting.GoToTimezoneIDsTest.class, org.olat.modules.portfolio.manager.BinderDAOTest.class, + org.olat.modules.portfolio.manager.CategoryDAOTest.class, + org.olat.modules.portfolio.manager.MediaDAOTest.class, + org.olat.modules.portfolio.manager.PageDAOTest.class, org.olat.modules.portfolio.manager.PortfolioServiceTest.class, org.olat.modules.reminder.ReminderModuleTest.class, org.olat.modules.reminder.manager.ReminderDAOTest.class, diff --git a/src/test/java/org/olat/test/ArquillianDeployments.java b/src/test/java/org/olat/test/ArquillianDeployments.java index 4e8182139cca8a1a6d5ca1c1f36dc5b686334ada..91db31a743f4b8f75f8234d67f517c6b59ad4a7a 100644 --- a/src/test/java/org/olat/test/ArquillianDeployments.java +++ b/src/test/java/org/olat/test/ArquillianDeployments.java @@ -26,7 +26,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import org.jboss.shrinkwrap.api.ArchivePath; @@ -47,13 +49,15 @@ public class ArquillianDeployments { public static final String TEST_RSRC = "src/test/resources"; public static final String LIB_DIR = "target/openolat-lms-11.0-SNAPSHOT/WEB-INF/lib"; - public static WebArchive createDeployment() { - return createDeployment("openolat.war"); + return createDeployment("openolat.war", new HashMap<String,String>()); } - + + public static WebArchive createDeployment(Map<String,String> overrideProperties) { + return createDeployment("openolat.war", overrideProperties); + } - public static WebArchive createDeployment(String name) { + public static WebArchive createDeployment(String name, Map<String,String> overrideProperties) { WebArchive archive = ShrinkWrap.create(WebArchive.class, name); addClasses(archive); @@ -62,12 +66,12 @@ public class ArquillianDeployments { addResourceRecursive(new File(MAIN_JAVA), null, new JavaResourcesFilter(), archive); addResourceRecursive(new File(MAIN_RSRC), null, new AllFileFilter(), archive); addWebResourceRecursive(new File(WEBAPP), "static", new StaticFileFilter(), archive); - addOlatLocalProperties(archive); + addOlatLocalProperties(archive, overrideProperties); archive.setWebXML(new File(WEBINF_TOMCAT, "web.xml")); return archive; } - public static WebArchive addOlatLocalProperties(WebArchive archive) { + public static WebArchive addOlatLocalProperties(WebArchive archive, Map<String,String> overrideProperties) { String profile = System.getProperty("profile"); if(profile == null || profile.isEmpty()) { profile = "mysql"; @@ -90,6 +94,10 @@ public class ArquillianDeployments { updatedProperties.setProperty(name, replacedValue); } + for(Map.Entry<String, String> entryToOverride:overrideProperties.entrySet()) { + updatedProperties.setProperty(entryToOverride.getKey(), entryToOverride.getValue()); + } + StringWriter writer = new StringWriter(); updatedProperties.store(writer, "Replaced for Arquillian deployements"); propertiesAsset = new StringAsset(writer.toString());