diff --git a/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml b/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml index 1c43c1649e23ddf8c30d82eb7cf272d80e785cc2..3e2e826da072353f7faea085128acc4bd53759b5 100644 --- a/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml +++ b/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml @@ -75,7 +75,9 @@ <mapping-file>org/olat/portfolio/model/notification/Notifications.hbm.xml</mapping-file> <mapping-file>org/olat/portfolio/model/restriction/CollectRestriction.hbm.xml</mapping-file> <mapping-file>org/olat/core/commons/services/commentAndRating/impl/UserCommentImpl.hbm.xml</mapping-file> + <!-- <mapping-file>org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.hbm.xml</mapping-file> + --> <mapping-file>org/olat/core/commons/services/mark/impl/MarkImpl.hbm.xml</mapping-file> <mapping-file>org/olat/core/commons/services/tagging/model/TagImpl.hbm.xml</mapping-file> <mapping-file>org/olat/core/util/mail/model/DBMail.hbm.xml</mapping-file> @@ -91,6 +93,7 @@ <class>org.olat.core.dispatcher.mapper.model.PersistedMapper</class> <class>org.olat.core.commons.services.taskexecutor.model.PersistentTask</class> <class>org.olat.core.commons.services.taskexecutor.model.PersistentTaskModifier</class> + <class>org.olat.core.commons.services.commentAndRating.impl.UserRatingImpl</class> <class>org.olat.course.assessment.model.UserCourseInfosImpl</class> <class>org.olat.group.model.ContactParticipantView</class> <class>org.olat.group.model.ContactOwnerView</class> diff --git a/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml b/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml index 4c853341d0a2d51d745dfaaaac347f135f6b1d5f..90a6bf264edbb403d05b764626ca24c2449938e0 100644 --- a/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml +++ b/src/main/java/org/olat/core/commons/services/_spring/servicesCorecontext.xml @@ -22,8 +22,8 @@ <!-- Define the manager implementation used in comment and rating service --> <bean id="userCommentsManager" class="org.olat.core.commons.services.commentAndRating.impl.UserCommentsManagerImpl" scope="prototype" /> - <bean id="userRatingsManager" - class="org.olat.core.commons.services.commentAndRating.impl.UserRatingsManagerImpl" scope="prototype" /> - - + + <bean id="userRatingsManager" class="org.olat.core.commons.services.commentAndRating.impl.UserRatingsManagerImpl" scope="prototype"> + <property name="userRatingsDAO" ref="userRatingsDAO"/> + </bean> </beans> \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.hbm.xml b/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.hbm.xml deleted file mode 100644 index 43ff0bd48893c461f0c0c6cabf86f85332771e95..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.hbm.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE hibernate-mapping PUBLIC - "-//Hibernate/Hibernate Mapping DTD//EN" - "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> -<hibernate-mapping default-lazy="false"> - <class name="org.olat.core.commons.services.commentAndRating.impl.UserRatingImpl" table="o_userrating"> - - <cache usage="transactional" /> - - <id name="key" type="long" column="rating_id" unsaved-value="null"> - <generator class="hilo"/> - </id> - - <version name="version" access="field" column="version" type="int"/> - <property name="creationDate" column="creationdate" type="timestamp" /> - - <property name="lastModified" column="lastmodified" type="timestamp" /> - - <property name="resName" type="string" > - <column name="resname" not-null="true" length="50" index="resname_idx2"/> - </property> - - <property name="resId" type="long"> - <column name="resid" not-null="true" index="id_idx4" /> - </property> - - <property name="resSubPath" type="string" > - <column name="ressubpath" length="2048" sql-type="varchar(2048)" index="subpath_idx3" not-null="false"/> - </property> - - <many-to-one name="creator" class="org.olat.basesecurity.IdentityImpl" - column="creator_id" outer-join="true" cascade="none" not-null="true"/> - - <property name="rating" unique="false" type="int" not-null="false"> - <column name="rating" /> - </property> - - </class> -</hibernate-mapping> \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.java b/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.java index a0a2f666467cee7ad13d298b485db2cd21048519..27c0dda6e4d4773376deab9272be333b7d8e3991 100644 --- a/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.java +++ b/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.java @@ -21,10 +21,24 @@ package org.olat.core.commons.services.commentAndRating.impl; import java.util.Date; -import org.olat.core.commons.persistence.PersistentObject; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +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.hibernate.annotations.GenericGenerator; +import org.olat.basesecurity.IdentityImpl; import org.olat.core.commons.services.commentAndRating.model.UserRating; +import org.olat.core.id.CreateInfo; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; +import org.olat.core.id.Persistable; /** * Description:<br> @@ -35,20 +49,44 @@ import org.olat.core.id.OLATResourceable; * * @author gnaegi */ -public class UserRatingImpl extends PersistentObject implements UserRating { +@Entity(name="userrating") +@Table(name="o_userrating") +public class UserRatingImpl implements Persistable, CreateInfo, UserRating { + + private static final long serialVersionUID = -5830951461259559219L; + + @Id + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "hilo") + @Column(name="rating_id", nullable=false, unique=true, insertable=true, updatable=false) + private Long key; + + @Column(name="version", nullable=false, insertable=true, updatable=false) + private int version = 0; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="creationdate", nullable=false, insertable=true, updatable=false) + private Date creationDate; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="lastmodified", nullable=false, insertable=true, updatable=true) + private Date modifiedDate; + + @Column(name="resname", nullable=false, insertable=true, updatable=false) private String resName; + @Column(name="resid", nullable=false, insertable=true, updatable=false) private Long resId; + @Column(name="ressubpath", nullable=true, insertable=true, updatable=false) private String resSubPath; - + + @ManyToOne(targetEntity=IdentityImpl.class,fetch=FetchType.LAZY,optional=false) + @JoinColumn(name="creator_id", nullable=false, updatable=false) private Identity creator; + @Column(name="rating", nullable=false, insertable=true, updatable=true) private Integer rating; - private Date modifiedDate; - /** - * Default constructor for hibernate, don't use this! - */ - private UserRatingImpl() { + public UserRatingImpl() { // } @@ -59,14 +97,30 @@ public class UserRatingImpl extends PersistentObject implements UserRating { * @param creator * @param ratingValue */ - UserRatingImpl(OLATResourceable ores, String subpath, Identity creator, Integer ratingValue) { + public UserRatingImpl(OLATResourceable ores, String subpath, Identity creator, Integer ratingValue) { this.creator = creator; this.resName = ores.getResourceableTypeName(); this.resId = ores.getResourceableId(); this.resSubPath = subpath; this.rating = ratingValue; + this.creationDate = new Date(); + this.modifiedDate = new Date(); } + @Override + public Long getKey() { + return key; + } + + @Override + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + /** * @see org.olat.core.commons.services.commentAndRating.model.UserComment#getCreator() */ @@ -153,5 +207,26 @@ public class UserRatingImpl extends PersistentObject implements UserRating { public void setLastModified(Date date) { modifiedDate = date; } + + @Override + public int hashCode() { + return key == null ? 13256 : key.hashCode(); + } -} + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof UserRatingImpl) { + UserRatingImpl q = (UserRatingImpl)obj; + return key != null && key.equals(q.key); + } + return false; + } + + @Override + public boolean equalsByPersistableKey(Persistable persistable) { + return equals(persistable); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingsDAO.java b/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingsDAO.java new file mode 100644 index 0000000000000000000000000000000000000000..d49d142ed0d700de1bea50a72233fe30312cb739 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingsDAO.java @@ -0,0 +1,162 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.commons.services.commentAndRating.impl; + +import java.util.Date; +import java.util.List; + +import javax.persistence.TypedQuery; + +import org.olat.core.commons.persistence.DB; +import org.olat.core.commons.services.commentAndRating.model.UserRating; +import org.olat.core.id.Identity; +import org.olat.core.id.OLATResourceable; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * + * Initial date: 31.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Service("userRatingsDAO") +public class UserRatingsDAO { + + private static final OLog log = Tracing.createLoggerFor(UserRatingsDAO.class); + + @Autowired + private DB dbInstance; + + public UserRating createRating(Identity creator, OLATResourceable ores, String resSubPath, int ratingValue) { + UserRatingImpl rating = new UserRatingImpl(); + rating.setCreator(creator); + rating.setResName(ores.getResourceableTypeName()); + rating.setResId(ores.getResourceableId()); + rating.setResSubPath(resSubPath); + rating.setCreationDate(new Date()); + rating.setLastModified(new Date()); + rating.setRating(ratingValue); + dbInstance.getCurrentEntityManager().persist(rating); + return rating; + } + + public float getRatingAverage(OLATResourceable ores, String resSubPath) { + TypedQuery<Number> query; + if (resSubPath == null) { + // special query when sub path is null + query = dbInstance.getCurrentEntityManager() + .createQuery("select avg(rating) from userrating where resName=:resname AND resId=:resId AND resSubPath is NULL", Number.class); + } else { + query = dbInstance.getCurrentEntityManager() + .createQuery("select avg(rating) from userrating where resName=:resname AND resId=:resId AND resSubPath=:resSubPath", Number.class) + .setParameter("resSubPath", resSubPath); + } + Number average = query + .setParameter("resname", ores.getResourceableTypeName()) + .setParameter("resId", ores.getResourceableId()) + .getSingleResult(); + // When no ratings are found, a null value is returned! + if (average== null) { + return 0.0f; + } + return average.floatValue(); + } + + public int countRatings(OLATResourceable ores, String resSubPath) { + TypedQuery<Number> query; + if (resSubPath == null) { + // special query when sub path is null + query = dbInstance.getCurrentEntityManager() + .createQuery("select count(*) from userrating where resName=:resname AND resId=:resId AND resSubPath is NULL", Number.class); + } else { + query = dbInstance.getCurrentEntityManager() + .createQuery("select count(*) from userrating where resName=:resname AND resId=:resId AND resSubPath=:resSubPath", Number.class) + .setParameter("resSubPath", resSubPath); + } + Number count = query.setParameter("resname", ores.getResourceableTypeName()) + .setParameter("resId", ores.getResourceableId()) + .setHint("org.hibernate.cacheable", Boolean.TRUE) + .getSingleResult(); + return count.intValue(); + } + + public UserRatingImpl getRating(Identity identity, OLATResourceable ores, String resSubPath) { + StringBuilder sb = new StringBuilder(); + sb.append("select r from userrating as r where r.creator.key=:creatorKey and r.resName=:resname and r.resId=:resId"); + TypedQuery<UserRatingImpl> query; + if (resSubPath == null) { + sb.append(" and r.resSubPath is NULL"); + query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), UserRatingImpl.class); + } else { + sb.append(" and resSubPath=:resSubPath"); + query = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), UserRatingImpl.class) + .setParameter("resSubPath", resSubPath); + } + List<UserRatingImpl> results = query + .setParameter("resname", ores.getResourceableTypeName()) + .setParameter("resId", ores.getResourceableId()) + .setParameter("creatorKey", identity.getKey()) + .setHint("org.hibernate.cacheable", Boolean.TRUE) + .getResultList(); + if (results.size() == 0) return null; + return results.get(0); + } + + public UserRating updateRating(Identity identity, OLATResourceable ores, String resSubPath, int newRatingValue) { + UserRatingImpl rating = getRating(identity, ores, resSubPath); + if (rating == null) { + return createRating(identity, ores, resSubPath, newRatingValue); + } + // Update DB entry + rating.setRating(newRatingValue); + rating.setLastModified(new Date()); + rating = dbInstance.getCurrentEntityManager().merge(rating); + return rating; + } + + public UserRating updateRating(UserRating rating, int newRatingValue) { + // First reload parent from cache to prevent stale object or cache issues + rating = reloadRating(rating); + if (rating == null) { + // Original rating has been deleted in the meantime. Don't update it + return null; + } + // Update DB entry + rating.setRating(newRatingValue); + rating.setLastModified(new Date()); + rating = dbInstance.getCurrentEntityManager().merge(rating); + return rating; + } + + public UserRating reloadRating(UserRating rating) { + try { + return (UserRating)dbInstance.loadObject(rating); + } catch (Exception e) { + // Huh, most likely the given object does not exist anymore on the + // db, probably deleted by someone else + log.warn("Tried to reload a user rating but got an exception. Probably deleted in the meantime", e); + return null; + } + } +} diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingsManagerImpl.java b/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingsManagerImpl.java index 29f6490a20440b56df5063e171391b9826e08ac3..685553a67c4bd5ade3167aa3ce9b7ee96c2a0428 100644 --- a/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingsManagerImpl.java +++ b/src/main/java/org/olat/core/commons/services/commentAndRating/impl/UserRatingsManagerImpl.java @@ -24,7 +24,6 @@ */ package org.olat.core.commons.services.commentAndRating.impl; -import java.util.Date; import java.util.List; import org.olat.core.commons.persistence.DB; @@ -51,6 +50,8 @@ import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; */ public class UserRatingsManagerImpl extends UserRatingsManager { + private UserRatingsDAO userRatingsDAO; + /** * Spring constructor. Use the getInstance method instead of calling this * constructor directly. @@ -58,13 +59,23 @@ public class UserRatingsManagerImpl extends UserRatingsManager { public UserRatingsManagerImpl() { // nothing to do } + + /** + * [used by Spring] + * @param userRatingsDAO + */ + + public void setUserRatingsDAO(UserRatingsDAO userRatingsDAO) { + this.userRatingsDAO = userRatingsDAO; + } /** * @see org.olat.core.commons.services.commentAndRating.UserRatingsManager#createRatingsManager(org.olat.core.id.OLATResourceable, java.lang.String) */ @Override protected UserRatingsManager createRatingsManager(OLATResourceable ores, String subpath) { - UserRatingsManager manager = new UserRatingsManagerImpl(); + UserRatingsManagerImpl manager = new UserRatingsManagerImpl(); + manager.userRatingsDAO = userRatingsDAO; manager.init(ores, subpath); return manager; } @@ -74,29 +85,7 @@ public class UserRatingsManagerImpl extends UserRatingsManager { */ @Override public Float calculateRatingAverage() { - DBQuery query; - if (getOLATResourceableSubPath() == null) { - // special query when sub path is null - query = DBFactory - .getInstance() - .createQuery( - "select avg(rating) from UserRatingImpl where resName=:resname AND resId=:resId AND resSubPath is NULL"); - } else { - query = DBFactory - .getInstance() - .createQuery( - "select avg(rating) from UserRatingImpl where resName=:resname AND resId=:resId AND resSubPath=:resSubPath"); - query.setString("resSubPath", getOLATResourceableSubPath()); - } - query.setString("resname", getOLATResourceable() - .getResourceableTypeName()); - query.setLong("resId", getOLATResourceable().getResourceableId()); - query.setCacheable(true); - // - Double average = (Double)query.list().get(0); - // When no ratings are found, a null value is returned! - if (average == null) return Float.valueOf(0); - else return average.floatValue(); + return userRatingsDAO.getRatingAverage(getOLATResourceable(), getOLATResourceableSubPath()); } /** @@ -104,27 +93,8 @@ public class UserRatingsManagerImpl extends UserRatingsManager { */ @Override public Long countRatings() { - DBQuery query; - if (getOLATResourceableSubPath() == null) { - // special query when sub path is null - query = DBFactory - .getInstance() - .createQuery( - "select count(*) from UserRatingImpl where resName=:resname AND resId=:resId AND resSubPath is NULL"); - } else { - query = DBFactory - .getInstance() - .createQuery( - "select count(*) from UserRatingImpl where resName=:resname AND resId=:resId AND resSubPath=:resSubPath"); - query.setString("resSubPath", getOLATResourceableSubPath()); - } - query.setString("resname", getOLATResourceable() - .getResourceableTypeName()); - query.setLong("resId", getOLATResourceable().getResourceableId()); - query.setCacheable(true); - // - Long count = (Long) query.list().get(0); - return count; + int count = userRatingsDAO.countRatings(getOLATResourceable(), getOLATResourceableSubPath()); + return new Long(count); } /** @@ -138,12 +108,12 @@ public class UserRatingsManagerImpl extends UserRatingsManager { query = DBFactory .getInstance() .createQuery( - "select rating from UserRatingImpl as rating where resName=:resname AND resId=:resId AND resSubPath is NULL"); + "select rating from userrating as rating where resName=:resname AND resId=:resId AND resSubPath is NULL"); } else { query = DBFactory .getInstance() .createQuery( - "select rating from UserRatingImpl as rating where resName=:resname AND resId=:resId AND resSubPath=:resSubPath"); + "select rating from userrating as rating where resName=:resname AND resId=:resId AND resSubPath=:resSubPath"); query.setString("resSubPath", getOLATResourceableSubPath()); } query.setString("resname", getOLATResourceable() @@ -160,9 +130,7 @@ public class UserRatingsManagerImpl extends UserRatingsManager { */ @Override public UserRating createRating(Identity creator, int ratingValue) { - UserRating rating = new UserRatingImpl(getOLATResourceable(), - getOLATResourceableSubPath(), creator, Integer.valueOf(ratingValue)); - DBFactory.getInstance().saveObject(rating); + UserRating rating = userRatingsDAO.createRating(creator, getOLATResourceable(), getOLATResourceableSubPath(), ratingValue); // do logging ThreadLocalUserActivityLogger.log(CommentAndRatingLoggingAction.RATING_CREATED, getClass(), CoreLoggingResourceable.wrap(getOLATResourceable(), OlatResourceableType.feedItem)); @@ -181,12 +149,12 @@ public class UserRatingsManagerImpl extends UserRatingsManager { query = DBFactory .getInstance() .createQuery( - "select userRating from UserRatingImpl as userRating where creator=:creator AND resName=:resname AND resId=:resId AND resSubPath is NULL "); + "select userRating from userrating as userRating where creator=:creator AND resName=:resname AND resId=:resId AND resSubPath is NULL "); } else { query = DBFactory .getInstance() .createQuery( - "select userRating from UserRatingImpl as userRating where creator=:creator AND resName=:resname AND resId=:resId AND resSubPath=:resSubPath"); + "select userRating from userrating as userRating where creator=:creator AND resName=:resname AND resId=:resId AND resSubPath=:resSubPath"); query.setString("resSubPath", getOLATResourceableSubPath()); } query.setString("resname", getOLATResourceable() @@ -231,14 +199,14 @@ public class UserRatingsManagerImpl extends UserRatingsManager { // special query when sub path is null if (getOLATResourceableSubPath() == null) { StringBuilder sb = new StringBuilder(); - sb.append("delete from ").append(UserRatingImpl.class.getName()).append(" where resName=:resName and resId=:resId and resSubPath is null"); + sb.append("delete from userrating where resName=:resName and resId=:resId and resSubPath is null"); return db.getCurrentEntityManager().createQuery(sb.toString()) .setParameter("resName", getOLATResourceable().getResourceableTypeName()) .setParameter("resId", getOLATResourceable().getResourceableId()) .executeUpdate(); } else { StringBuilder sb = new StringBuilder(); - sb.append("delete from ").append(UserRatingImpl.class.getName()).append(" where resName=:resName and resId=:resId and resSubPath=:resSubPath"); + sb.append("delete from userrating where resName=:resName and resId=:resId and resSubPath=:resSubPath"); return db.getCurrentEntityManager().createQuery(sb.toString()) .setParameter("resName", getOLATResourceable().getResourceableTypeName()) .setParameter("resId", getOLATResourceable().getResourceableId()) @@ -255,7 +223,7 @@ public class UserRatingsManagerImpl extends UserRatingsManager { public int deleteAllRatingsIgnoringSubPath() { DB db = DBFactory.getInstance(); StringBuilder sb = new StringBuilder(); - sb.append("delete from ").append(UserRatingImpl.class.getName()).append(" where resName=:resName and resId=:resId"); + sb.append("delete from userrating where resName=:resName and resId=:resId"); return db.getCurrentEntityManager().createQuery(sb.toString()) .setParameter("resName", getOLATResourceable().getResourceableTypeName()) .setParameter("resId", getOLATResourceable().getResourceableId()) @@ -267,15 +235,7 @@ public class UserRatingsManagerImpl extends UserRatingsManager { */ @Override public UserRating reloadRating(UserRating rating) { - try { - DB db = DBFactory.getInstance(); - return (UserRating) db.loadObject(rating); - } catch (Exception e) { - // Huh, most likely the given object does not exist anymore on the - // db, probably deleted by someone else - logWarn("Tried to reload a user rating but got an exception. Probably deleted in the meantime", e); - return null; - } + return userRatingsDAO.reloadRating(rating); } /** @@ -287,21 +247,7 @@ public class UserRatingsManagerImpl extends UserRatingsManager { throw new AssertException( "This user rating manager is initialized for another resource than the given comment."); } - // First reload parent from cache to prevent stale object or cache issues - rating = reloadRating(rating); - if (rating == null) { - // Original rating has been deleted in the meantime. Don't update it - return null; - } - // Update DB entry - rating.setRating(newRatingValue); - rating.setLastModified(new Date()); - DB db = DBFactory.getInstance(); - db.updateObject(rating); - // do logging - ThreadLocalUserActivityLogger.log(CommentAndRatingLoggingAction.RATING_UPDATED, getClass(), - CoreLoggingResourceable.wrap(getOLATResourceable(), OlatResourceableType.feedItem)); - return rating; + return userRatingsDAO.updateRating(rating, newRatingValue); } /** @@ -328,12 +274,11 @@ public class UserRatingsManagerImpl extends UserRatingsManager { } @Override - //fxdiff public List<OLATResourceableRating> getMostRatedResourceables(int maxResults) { StringBuilder sb = new StringBuilder(); sb.append("select new ").append(OLATResourceableRating.class.getName()).append("(") .append(" rating.resName, rating.resId, rating.resSubPath, avg(rating.rating))") - .append(" from ").append(UserRatingImpl.class.getName()).append(" as rating ") + .append(" from userrating as rating ") .append(" where rating.resName=:resName and rating.resId=:resId") .append(" group by rating.resName, rating.resId, rating.resSubPath") .append(" order by avg(rating.rating) desc"); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java index 5f2ad6b6421f79bb4ee2e674077d81008fc0acbb..f9526fa08033c05d8d06f34d2141147b0a0d398f 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java @@ -30,6 +30,7 @@ import java.util.Set; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.impl.elements.table.ExtendedFlexiTableSearchController; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType; +import org.olat.core.gui.components.velocity.VelocityContainer; /** * @@ -48,6 +49,10 @@ public interface FlexiTableElement extends FormItem { * @param rendererType */ public void setRendererType(FlexiTableRendererType rendererType); + + public void setRowRenderer(VelocityContainer renderer); + + public void addFormItem(FormItem item); /** * @return True if muli selection is enabled diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java index 6d6d4896350a4e7413972d81229b4636e96c35b0..b75de3ca03cd98ab7e8667bf6204005557c9ad2c 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java @@ -20,13 +20,13 @@ package org.olat.core.gui.components.form.flexible.impl.elements.table; import org.olat.core.gui.components.Component; -import org.olat.core.gui.components.ComponentRenderer; +import org.olat.core.gui.components.DefaultComponentRenderer; import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.form.flexible.impl.FormJSHelper; import org.olat.core.gui.components.form.flexible.impl.NameValuePair; import org.olat.core.gui.render.RenderResult; import org.olat.core.gui.render.Renderer; -import org.olat.core.gui.render.RenderingState; import org.olat.core.gui.render.StringOutput; import org.olat.core.gui.render.URLBuilder; import org.olat.core.gui.translator.Translator; @@ -37,7 +37,7 @@ import org.olat.core.gui.translator.Translator; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public abstract class AbstractFlexiTableRenderer implements ComponentRenderer { +public abstract class AbstractFlexiTableRenderer extends DefaultComponentRenderer { @Override public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, @@ -54,10 +54,11 @@ public abstract class AbstractFlexiTableRenderer implements ComponentRenderer { //render headers renderHeaders(sb, ftE, translator); //render body + sb.append("<tbody>"); renderBody(renderer, sb, ftC, ubu, translator, renderResult); - sb.append("</table>"); + sb.append("</tbody></table>"); - renderFooterButtons(renderer, sb, ftE, ubu, translator, renderResult, args); + renderFooterButtons(renderer, sb, ftC, ubu, translator, renderResult, args); sb.append("</div>"); //source @@ -90,9 +91,10 @@ public abstract class AbstractFlexiTableRenderer implements ComponentRenderer { } } - protected void renderFooterButtons(Renderer renderer, StringOutput sb, FlexiTableElementImpl ftE, URLBuilder ubu, Translator translator, + protected void renderFooterButtons(Renderer renderer, StringOutput sb, FlexiTableComponent ftC, URLBuilder ubu, Translator translator, RenderResult renderResult, String[] args) { - + + FlexiTableElementImpl ftE = ftC.getFlexiTableElement(); if(ftE.isSelectAllEnable()) { String formName = ftE.getRootForm().getFormName(); String dispatchId = ftE.getFormDispatchId(); @@ -111,6 +113,10 @@ public abstract class AbstractFlexiTableRenderer implements ComponentRenderer { sb.append("</div>"); } + + if(ftE.getRendererType() != FlexiTableRendererType.dataTables && ftE.getPageSize() > 0) { + renderPagesLinks(sb, ftC); + } } protected void renderHeaders(StringOutput target, FlexiTableElementImpl ftE, Translator translator) { @@ -132,7 +138,7 @@ public abstract class AbstractFlexiTableRenderer implements ComponentRenderer { if(ftE.isColumnModelVisible(fcm)) { renderHeader(target, fcm, col++, cols, translator); } - } + } target.append("</tr></thead>"); } @@ -152,9 +158,6 @@ public abstract class AbstractFlexiTableRenderer implements ComponentRenderer { String id = ftC.getFormDispatchId(); FlexiTableElementImpl ftE = ftC.getFlexiTableElement(); FlexiTableDataModel<?> dataModel = ftE.getTableDataModel(); - - // build rows - target.append("<tbody>"); // the really selected rowid (from the tabledatamodel) int firstRow = ftE.getFirstRow(); @@ -169,7 +172,6 @@ public abstract class AbstractFlexiTableRenderer implements ComponentRenderer { } } // end of table table - target.append("</tbody>"); } protected void renderRow(Renderer renderer, StringOutput target, FlexiTableComponent ftC, String rowIdPrefix, @@ -241,22 +243,103 @@ public abstract class AbstractFlexiTableRenderer implements ComponentRenderer { } target.append("</td>"); } + + private void renderPagesLinks(StringOutput sb, FlexiTableComponent ftC) { + FlexiTableElementImpl ftE = ftC.getFlexiTableElement(); + int pageSize = ftE.getPageSize(); + FlexiTableDataModel<?> dataModel = ftE.getTableDataModel(); + int rows = dataModel.getRowCount(); + + if(pageSize > 0 && rows > pageSize) { + sb.append("<div class='b_table_page'>"); - @Override - public void renderHeaderIncludes(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, - Translator translator, RenderingState rstate) { - // - } + int page = ftE.getPage(); + int maxPage = (int)Math.ceil(((double) rows / (double) pageSize)); + + renderPageBackLink(sb, ftC, page); + renderPageNumberLinks(sb, ftC, page, maxPage); + renderPageNextLink(sb, ftC, page, maxPage); - @Override - public void renderBodyOnLoadJSFunctionCall(Renderer renderer, StringOutput sb, Component source, - RenderingState rstate) { - // + sb.append("</div>"); + } } - + private void renderPageBackLink(StringOutput sb, FlexiTableComponent ftC, int page) { + if (page <= 0) return; + FlexiTableElementImpl ftE = ftC.getFlexiTableElement(); + Form theForm = ftE.getRootForm(); + sb.append("<a class='b_table_backward' href=\"javascript:") + .append(FormJSHelper.getXHRFnCallFor(theForm, ftC.getFormDispatchId(), 1, new NameValuePair("page", Integer.toString(page - 1)))) + .append("\">").append(" ").append("</a>"); + } + + private void renderPageNextLink(StringOutput sb, FlexiTableComponent ftC, int page, int maxPage) { + if (page == maxPage) return; + FlexiTableElementImpl ftE = ftC.getFlexiTableElement(); + Form theForm = ftE.getRootForm(); + sb.append("<a class='b_table_forward' href=\"javascript:") + .append(FormJSHelper.getXHRFnCallFor(theForm, ftC.getFormDispatchId(), 1, new NameValuePair("page", Integer.toString(page + 1)))) + .append("\">").append(" ").append("</a>"); + } + + private void renderPageNumberLinks(StringOutput sb, FlexiTableComponent ftC, int page, int maxPage) { + if (maxPage < 12) { + for (int i=0; i<maxPage; i++) { + appendPagenNumberLink(sb, ftC, page, i); + } + } else { + int powerOf10 = String.valueOf(maxPage).length() - 1; + int maxStepSize = (int) Math.pow(10, powerOf10); + int stepSize = (int) Math.pow(10, String.valueOf(page).length() - 1); + boolean isStep = false; + int useEveryStep = 3; + int stepCnt = 0; + boolean isNear = false; + int nearleft = 5; + int nearright = 5; + if (page < nearleft) { + nearleft = page; + nearright += (nearright - nearleft); + } else if (page > (maxPage - nearright)) { + nearright = maxPage - page; + nearleft += (nearleft - nearright); + } + for (int i = 1; i <= maxPage; i++) { + // adapt stepsize if needed + stepSize = adaptStepIfNeeded(page, maxStepSize, stepSize, i); + + isStep = ((i % stepSize) == 0); + if (isStep) { + stepCnt++; + isStep = isStep && (stepCnt % useEveryStep == 0); + } + isNear = (i > (page - nearleft) && i < (page + nearright)); + if (i == 1 || i == maxPage || isStep || isNear) { + appendPagenNumberLink(sb, ftC, page, i); + } + } + } + } + + private void appendPagenNumberLink(StringOutput sb, FlexiTableComponent ftC, int page, int i) { + FlexiTableElementImpl ftE = ftC.getFlexiTableElement(); + Form theForm = ftE.getRootForm(); + String cssClass = (page == i) ? "b_table_page b_table_page_active" : "b_table_page"; + sb.append("<a class='").append(cssClass).append("' href=\"javascript:") + .append(FormJSHelper.getXHRFnCallFor(theForm, ftC.getFormDispatchId(), 1, new NameValuePair("page", Integer.toString(i)))) + .append("\">").append(i+1).append("</a>"); + } + private int adaptStepIfNeeded(final int page, final int maxStepSize, final int stepSize, final int i) { + int newStepSize = stepSize; + if (i < page && stepSize > 1 && ((page - i) / stepSize == 0)) { + newStepSize = stepSize / 10; + } else if (i > page && stepSize < maxStepSize && ((i - page) / stepSize == 9)) { + newStepSize = stepSize * 10; + } + return newStepSize; + } } diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiDataTablesRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiDataTablesRenderer.java index 7f6b82ee3cbd5ddd64bdedb3b1f61621e4a2cef5..52c9cc841cb90cfc10159b075c6bbaafb44cc92e 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiDataTablesRenderer.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiDataTablesRenderer.java @@ -87,22 +87,22 @@ class FlexiDataTablesRenderer extends AbstractFlexiTableRenderer implements Comp .append("jQuery(function() {\n") .append(" var scrollHeight = ").append(scrollHeight).append(";\n") .append(" var selectedIndex =").append(selectPos).append(";\n") - .append(" jQuery('#").append(id).append("').dataTable( {\n") - .append(" 'bScrollInfinite': true,\n") - .append(" 'bScrollCollapse': true,\n") - .append(" 'bFilter': false,\n") - .append(" 'sScrollY': ").append(scrollHeight).append(",\n") - .append(" 'bProcessing': true,\n") - .append(" 'bServerSide': true,\n") - .append(" 'iDisplayLength': ").append(ftE.getPageSize()).append(",\n") - .append(" 'iDeferLoading': ").append(loadedRows).append(",\n") - .append(" 'sAjaxSource': '").append(ftE.getMapperUrl()).append("',\n") - .append(" 'oLanguage': {\n") - .append(" 'sInfo': '").append(translator.translate("table.sInfo")).append("',\n") - .append(" 'sEmptyTable': '").append(translator.translate("table.sEmptyTable")).append("'\n") - .append(" },\n") - .append(" 'asStripeClasses': ['','b_table_odd'],\n") - .append(" 'aoColumns': [\n"); + .append(" jQuery('#").append(id).append("').dataTable( {\n") + .append(" 'bScrollInfinite': true,\n") + .append(" 'bScrollCollapse': true,\n") + .append(" 'bFilter': false,\n") + .append(" 'sScrollY': ").append(scrollHeight).append(",\n") + .append(" 'bProcessing': true,\n") + .append(" 'bServerSide': true,\n") + .append(" 'iDisplayLength': ").append(ftE.getPageSize()).append(",\n") + .append(" 'iDeferLoading': ").append(loadedRows).append(",\n") + .append(" 'sAjaxSource': '").append(ftE.getMapperUrl()).append("',\n") + .append(" 'oLanguage': {\n") + .append(" 'sInfo': '").append(translator.translate("table.sInfo")).append("',\n") + .append(" 'sEmptyTable': '").append(translator.translate("table.sEmptyTable")).append("'\n") + .append(" },\n") + .append(" 'asStripeClasses': ['','b_table_odd'],\n") + .append(" 'aoColumns': [\n"); int count = 0; if(ftE.isMultiSelect()) { target.append(" {'mData':'multiSelectCol', bSortable: false }\n"); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableComponent.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableComponent.java index 1d049a872962753c3b02432ab880250977d340a6..6446a8fb0b1b57f030516c4bbbebf92a746c3606 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableComponent.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableComponent.java @@ -42,8 +42,9 @@ import org.olat.core.gui.translator.Translator; */ public class FlexiTableComponent extends FormBaseComponentImpl implements ComponentCollection { - private ComponentRenderer DATATABLES_RENDERER = new FlexiDataTablesRenderer(); - private ComponentRenderer CLASSIC_RENDERER = new FlexiTableClassicRenderer(); + private static final ComponentRenderer DATATABLES_RENDERER = new FlexiDataTablesRenderer(); + private static final ComponentRenderer CLASSIC_RENDERER = new FlexiTableClassicRenderer(); + private static final ComponentRenderer CUSTOM_RENDERER = new FlexiTableCustomRenderer(); private FlexiTableElementImpl element; @@ -100,6 +101,7 @@ public class FlexiTableComponent extends FormBaseComponentImpl implements Compon switch(element.getRendererType()) { case classic: return CLASSIC_RENDERER; case dataTables: return DATATABLES_RENDERER; + case custom: return CUSTOM_RENDERER; default: return CLASSIC_RENDERER; } } diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableCustomRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableCustomRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..e2ba56e95baa648a8f1cdefc1a2b4789a053e57b --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableCustomRenderer.java @@ -0,0 +1,110 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.gui.components.form.flexible.impl.elements.table; + + +import org.olat.core.gui.components.Component; +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.FormJSHelper; +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: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +class FlexiTableCustomRenderer extends AbstractFlexiTableRenderer implements ComponentRenderer { + + @Override + public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, + RenderResult renderResult, String[] args) { + + FlexiTableComponent ftC = (FlexiTableComponent)source; + FlexiTableElementImpl ftE = ftC.getFlexiTableElement(); + + String id = ftC.getFormDispatchId(); + sb.append("<div class=\"b_table_wrapper b_floatscrollbox\">"); + renderHeaderButtons(renderer, sb, ftE, ubu, translator, renderResult, args); + + //render body + + sb.append("<div class='b_table_row'>"); + renderBody(renderer, sb, ftC, ubu, translator, renderResult); + sb.append("</div>"); + + renderFooterButtons(renderer, sb, ftC, ubu, translator, renderResult, args); + sb.append("</div>"); + + //source + if (source.isEnabled()) { + sb.append(FormJSHelper.getJSStartWithVarDeclaration(id)); + sb.append(FormJSHelper.getSetFlexiFormDirty(ftE.getRootForm(), id)); + sb.append(FormJSHelper.getJSEnd()); + } + } + + @Override + protected void renderHeaders(StringOutput sb, FlexiTableElementImpl ftE, Translator translator) { + //do nothing + } + + @Override + protected void renderRow(Renderer renderer, StringOutput sb, FlexiTableComponent ftC, String rowIdPrefix, + int row, int rows, URLBuilder ubu, Translator translator, RenderResult renderResult) { + sb.append("<div class='b_clearfix b_table_row'>"); + + FlexiTableElementImpl ftE = ftC.getFlexiTableElement(); + FlexiTableDataModel<?> dataModel = ftE.getTableDataModel(); + VelocityContainer container = ftE.getRowRenderer(); + + Object rowObject = ftE.getTableDataModel().getObject(row); + container.contextPut("row", rowObject); + + FlexiTableColumnModel columnsModel = ftE.getTableDataModel().getTableColumnModel(); + int numOfCols = columnsModel.getColumnCount(); + //link to the table element the form elements in the data model + for (int j = 0; j<numOfCols; j++) { + FlexiColumnModel fcm = columnsModel.getColumnModel(j); + int columnIndex = fcm.getColumnIndex(); + Object cellValue = columnIndex >= 0 ? dataModel.getValueAt(row, columnIndex) : null; + if (cellValue instanceof FormItem) { + FormItem formItem = (FormItem)cellValue; + formItem.setTranslator(translator); + if(ftE.getRootForm() != formItem.getRootForm()) { + formItem.setRootForm(ftE.getRootForm()); + } + ftE.addFormItem(formItem); + container.put(formItem.getComponent().getComponentName(), formItem.getComponent()); + } + } + + container.getHTMLRendererSingleton().render(renderer, sb, container, ubu, translator, renderResult, null); + container.contextRemove("row"); + + sb.append("</div>"); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java index e7a24a76bc2a40b122430dd8accaa1af4372b771..b31c0cb9f48d433ae8ca17c39949ba059cafe760 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java @@ -47,11 +47,13 @@ import org.olat.core.gui.components.form.flexible.FormItemCollection; 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.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormItemImpl; import org.olat.core.gui.components.form.flexible.impl.elements.FormLinkImpl; import org.olat.core.gui.components.form.flexible.impl.elements.TextElementImpl; import org.olat.core.gui.components.link.Link; +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; @@ -83,6 +85,8 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle private boolean selectAllEnabled; private int columnLabelForDragAndDrop; + + private VelocityContainer rowRenderer; private FormLink customButton; private FormLink searchButton, extendedSearchButton; @@ -90,7 +94,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle private ExtendedFlexiTableSearchController extendedSearchCtrl; private final FlexiTableDataModel<?> dataModel; - private FlexiTableDataSource<?> dataSource; + private final FlexiTableDataSource<?> dataSource; private final FlexiTableComponent component; private CloseableCalloutWindowController callout; private final WindowControl wControl; @@ -168,6 +172,9 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle @Override public void setRendererType(FlexiTableRendererType rendererType) { this.rendererType = rendererType; + if(component != null) { + component.setDirty(true); + } } @Override @@ -179,8 +186,6 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle public void setMultiSelect(boolean multiSelect) { this.multiSelect = multiSelect; } - - public boolean isCustomizeColumns() { return customizeColumns; @@ -198,6 +203,14 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle this.wrapperSelector = wrapperSelector; } + public VelocityContainer getRowRenderer() { + return rowRenderer; + } + + public void setRowRenderer(VelocityContainer rowRenderer) { + this.rowRenderer = rowRenderer; + } + @Override public boolean isSearchEnabled() { return searchEnabled; @@ -301,8 +314,15 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle @Override public void setPage(int page) { - currentPage = page;//TODO - //tableModel.load(0, getPageSize()); + if(currentPage == page) return; + + currentPage = page; + if(dataSource != null) { + int firstResult = currentPage * getPageSize(); + int maxResults = getPageSize(); + dataSource.load(getSearchText(), getConditionalQueries(), firstResult, maxResults, orderBy); + } + component.setDirty(true); } public int getCurrentFirstResult() { @@ -327,7 +347,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle return components.get(name); } - protected void addFormItem(FormItem item) { + public void addFormItem(FormItem item) { components.put(item.getName(), item); } @@ -351,11 +371,16 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle setMultiSelectIndex(selectedIndexArr); } - String selectedIndex = getRootForm().getRequestParameter("rSelect"); - String dispatchuri = getRootForm().getRequestParameter("dispatchuri"); - String select = getRootForm().getRequestParameter("select"); + Form form = getRootForm(); + String selectedIndex = form.getRequestParameter("rSelect"); + String dispatchuri = form.getRequestParameter("dispatchuri"); + String select = form.getRequestParameter("select"); + String page = form.getRequestParameter("page"); if("undefined".equals(dispatchuri)) { evalSearchRequest(ureq); + } else if(StringHelper.containsNonWhitespace(page)) { + int p = Integer.parseInt(page); + setPage(p); } else if(StringHelper.containsNonWhitespace(selectedIndex)) { int index = selectedIndex.lastIndexOf('-'); if(index > 0 && index+1 < selectedIndex.length()) { @@ -482,7 +507,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle if(StringHelper.containsNonWhitespace(search)) { doSearch(search, null); } else { - doResetSearch(ureq); + doResetSearch(); } } @@ -543,7 +568,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle return Arrays.equals(orderBy , sortKeys); } - protected void doResetSearch(UserRequest ureq) { + protected void doResetSearch() { if(dataSource != null) { resetInternComponents(); dataSource.clear(); @@ -677,6 +702,9 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle } public int getFirstRow() { + if(getPageSize() > 0) { + return getPage() * getPageSize(); + } return 0; } diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableModelMapper.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableModelMapper.java index 3bd79c82058788df48dddc7f06dd69aa0ca48cac..1e995fc76764b85a3068631b14ae7d1060d96f72 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableModelMapper.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableModelMapper.java @@ -143,7 +143,7 @@ public class FlexiTableModelMapper implements Mapper { item.setRootForm(ftE.getRootForm()); } ftE.addFormItem(item); - val = renderFormItem(item, request, ftE.getTranslator()); + val = renderFormItem(item, request); } else { val = renderColumnRenderer(col, value, i, ftC, ubu, ftE.getTranslator()); } @@ -173,7 +173,7 @@ public class FlexiTableModelMapper implements Mapper { return target.toString(); } - private String renderFormItem(FormItem item, HttpServletRequest request, Translator translator) { + private String renderFormItem(FormItem item, HttpServletRequest request) { UserSession usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(request); ChiefController cc = (ChiefController)Windows.getWindows(usess).getAttribute("AUTHCHIEFCONTROLLER"); return cc.getWindow().renderComponent(item.getComponent()); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableRendererType.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableRendererType.java index b73a06b054758e8a6a0a5644587585033b367ba9..f7710585544cd94f02c884cb49dd46dccfb111fe 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableRendererType.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableRendererType.java @@ -27,5 +27,6 @@ package org.olat.core.gui.components.form.flexible.impl.elements.table; public enum FlexiTableRendererType { classic, dataTables, + custom } diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/SyntheticFormItem.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/SyntheticFormItem.java deleted file mode 100644 index a9de2218046ea196fcad9d6ea367298676a67a93..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/SyntheticFormItem.java +++ /dev/null @@ -1,275 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.core.gui.components.form.flexible.impl.elements.table; - -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.FormLayouter; -import org.olat.core.gui.components.form.flexible.impl.Form; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.translator.Translator; -import org.olat.core.util.ValidationStatus; - -/** - * - * Initial date: 06.02.2013<br> - * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com - * - */ -class SyntheticFormItem<T> implements FormItem { - - private final String name; - private final String itemId; - private final String dispatchId; - private final FlexiTableElementImpl table; - - public SyntheticFormItem(String name, String itemId, String dispatchId, FlexiTableElementImpl table) { - this.name = name; - this.itemId = itemId; - this.dispatchId = dispatchId; - this.table = table; - } - - - @Override - public String getName() { - return name; - } - - @Override - public String getFormItemId() { - return itemId; - } - - @Override - public String getFormDispatchId() { - return dispatchId; - } - - @Override - public Form getRootForm() { - return table.getRootForm(); - } - - @Override - public void evalFormRequest(UserRequest ureq) { - // - } - - @Override - public void doDispatchFormRequest(UserRequest ureq) { - // - } - - @Override - public void validate(List<ValidationStatus> validationResults) { - // - } - - @Override - public void reset() { - // - } - - @Override - public boolean hasFocus() { - return false; - } - - @Override - public void setFocus(boolean hasFocus) { - // - } - - - @Override - public String getElementCssClass() { - return null; - } - - @Override - public void setElementCssClass(String cssClass) { - // - } - - @Override - public Component getComponent() { - return null; - } - - @Override - public Component getLabelC() { - return null; - } - - @Override - public String getLabelText() { - return null; - } - - @Override - public void setLabel(String labelkey, String[] params) { - // - } - - @Override - public void setLabel(String labelkey, String[] params, boolean translate) { - // - } - - @Override - public FormItem setLabelComponent(FormItem labelComponent, FormItemContainer formLayout) { - return null; - } - - @Override - public boolean isMandatory() { - return false; - } - - @Override - public void setMandatory(boolean isMandatory) { - // - } - - @Override - public Component getErrorC() { - return null; - } - - @Override - public void setErrorKey(String errorKey, String[] params) { - // - } - - @Override - public void setErrorComponent(FormItem errorFormItem, FormLayouter container) { - // - } - - @Override - public Component getExampleC() { - return null; - } - - @Override - public String getExampleText() { - return null; - } - - @Override - public void setExampleKey(String exampleKey, String[] params) { - // - } - - @Override - public Translator getTranslator() { - return null; - } - - @Override - public void setTranslator(Translator translator) { - // - } - - @Override - public boolean isVisible() { - return false; - } - - @Override - public void setVisible(boolean isVisible) { - // - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public void setEnabled(boolean isEnabled) { - // - } - - @Override - public boolean hasError() { - return false; - } - - @Override - public boolean hasLabel() { - return false; - } - - @Override - public boolean hasExample() { - return false; - } - - @Override - public void setRootForm(Form rootForm) { - // - } - - @Override - public void showLabel(boolean show) { - // - } - - @Override - public void showError(boolean show) { - // - } - - @Override - public void clearError() { - // - } - - @Override - public void showExample(boolean show) { - // - } - - @Override - public void addActionListener(Controller listener, int events) { - // - } - - @Override - public int getAction() { - return 0; - } - - @Override - public void setUserObject(Object userObject) { - // - } - - @Override - public Object getUserObject() { - return null; - } -} \ No newline at end of file diff --git a/src/main/java/org/olat/core/gui/components/panel/MainPanel.java b/src/main/java/org/olat/core/gui/components/panel/MainPanel.java new file mode 100644 index 0000000000000000000000000000000000000000..1643e2521abd84cd854ac305eec4f8e09457efde --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/panel/MainPanel.java @@ -0,0 +1,47 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.gui.components.panel; + +import org.olat.core.gui.components.ComponentRenderer; + +/** + * + * This component wrapped the content to mimic + * the 3 columsn main controller with only + * one column. + * + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MainPanel extends Panel { + + private static final ComponentRenderer RENDERER = new MainPanelRenderer(); + + public MainPanel(String name) { + super(name); + } + + @Override + public ComponentRenderer getHTMLRendererSingleton() { + return RENDERER; + } +} diff --git a/src/main/java/org/olat/core/gui/components/panel/MainPanelRenderer.java b/src/main/java/org/olat/core/gui/components/panel/MainPanelRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..0f3e6c8f37aad634ef7b3ec13d9bef997e618f59 --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/panel/MainPanelRenderer.java @@ -0,0 +1,58 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.gui.components.panel; + +import org.olat.core.gui.components.Component; +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: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MainPanelRenderer extends PanelRenderer { + + @Override + public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, + Translator translator, RenderResult renderResult, String[] args) { + + sb.append("<div id='b_main' class='b_hidecol1 b_hidecol2'>\n") + .append("<div id='b_col3' class='split-pane'>\n") + .append("<div id='b_col3_content' class='b_clearfix'>\n") + .append("<a id='b_content' name='content'></a>\n") + .append("<div id='b_col3_content_inner' class='b_floatscrollbox'>\n") + .append("<a name='b_col3'></a>\n"); + + super.render(renderer, sb, source, ubu, translator, renderResult, args); + + sb.append("</div>\n") + .append("</div>\n") + .append("<div id='b_ie_clearing'> </div>\n") + .append("</div>\n") + .append("</div> \n"); + + } + +} diff --git a/src/main/java/org/olat/core/gui/components/rating/RatingComponent.java b/src/main/java/org/olat/core/gui/components/rating/RatingComponent.java index 1c2814447d777bc492590e4f55da72b4b6e6f15a..736e388c22c8ff98eec6de3452c784efd84d14e1 100644 --- a/src/main/java/org/olat/core/gui/components/rating/RatingComponent.java +++ b/src/main/java/org/olat/core/gui/components/rating/RatingComponent.java @@ -25,6 +25,7 @@ import java.util.List; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.ComponentRenderer; +import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.logging.AssertException; @@ -56,6 +57,7 @@ public class RatingComponent extends Component { private boolean allowUserInput; private String cssClass; private float currentRating; + private Form form; /** * Create a rating component with no title and a default explanation and hover @@ -68,7 +70,11 @@ public class RatingComponent extends Component { * @param allowUserInput */ public RatingComponent(String name, float currentRating, int maxRating, boolean allowUserInput) { - super(name); + this(null, name, currentRating, maxRating, allowUserInput, null); + } + + public RatingComponent(String id, String name, float currentRating, int maxRating, boolean allowUserInput, Form form) { + super(id, name); if (currentRating > maxRating) throw new AssertException("Current rating set to higher value::" + currentRating + " than the maxRating::" + maxRating); this.allowUserInput = allowUserInput; @@ -86,7 +92,7 @@ public class RatingComponent extends Component { else this.explanation = null; this.translateExplanation = true; this.showRatingAsText = false; - + this.form = form; } /** @@ -99,9 +105,9 @@ public class RatingComponent extends Component { log.debug("***RATING_CLICKED*** dispatchID::" + ureq.getComponentID() + " rating::" + cmd); } try { - float rating = Float.parseFloat(cmd); + float rating = Float.parseFloat(cmd); // update GUI - this.setCurrentRating(rating); + setCurrentRating(rating); // notify listeners Event event = new RatingEvent(rating); fireEvent(ureq, event); @@ -118,10 +124,14 @@ public class RatingComponent extends Component { } + // // Various getter and setter methods // - + Form getForm() { + return form; + } + // only package scope, used by renderer List<String> getRatingLabel() { return ratingLabels; diff --git a/src/main/java/org/olat/core/gui/components/rating/RatingEvent.java b/src/main/java/org/olat/core/gui/components/rating/RatingEvent.java index 418de5a222510d50ac843ee163eb5176bc93a31d..d2bc683ca3dbbedbdec8052a1f1d2a59b57dc0f9 100644 --- a/src/main/java/org/olat/core/gui/components/rating/RatingEvent.java +++ b/src/main/java/org/olat/core/gui/components/rating/RatingEvent.java @@ -29,6 +29,8 @@ import org.olat.core.gui.control.Event; * @author gnaegi */ public class RatingEvent extends Event { + + private static final long serialVersionUID = -7584762233026409541L; private static final String RATING_EVENT = "ratingEvent"; private float rating; diff --git a/src/main/java/org/olat/core/gui/components/rating/RatingFormEvent.java b/src/main/java/org/olat/core/gui/components/rating/RatingFormEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..b69463da2a05426777048c27f6bac13c7d933fbd --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/rating/RatingFormEvent.java @@ -0,0 +1,50 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.gui.components.rating; + +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; + +/** + * + * Initial date: 31.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RatingFormEvent extends FormEvent { + + private static final long serialVersionUID = -3560846420954074918L; + + private static final String RATING_EVENT = "ratingEvent"; + private float rating; + + public RatingFormEvent(FormItem source, float rating) { + super(RATING_EVENT, source, ONCLICK); + this.rating = rating; + } + + public float getRating() { + return rating; + } + + public void setRating(float rating) { + this.rating = rating; + } +} diff --git a/src/main/java/org/olat/core/gui/components/rating/RatingFormItem.java b/src/main/java/org/olat/core/gui/components/rating/RatingFormItem.java new file mode 100644 index 0000000000000000000000000000000000000000..e735bcccdeb126d7b39c350f8cef5685fa135619 --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/rating/RatingFormItem.java @@ -0,0 +1,81 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.gui.components.rating; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.impl.FormItemImpl; + +/** + * + * Initial date: 31.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RatingFormItem extends FormItemImpl { + + private float currentRating; + private int maxRating; + private boolean allowUserInput; + + private RatingComponent component; + + public RatingFormItem(String name, float currentRating, int maxRating, boolean allowUserInput) { + super(name); + + this.currentRating = currentRating; + this.maxRating = maxRating; + this.allowUserInput = allowUserInput; + } + + public float getCurrentRating() { + return currentRating; + } + + @Override + protected RatingComponent getFormItemComponent() { + return component; + } + + @Override + protected void rootFormAvailable() { + if(component == null) { + component = new RatingComponent(null, getName(), currentRating, maxRating, allowUserInput, getRootForm()); + } + } + + @Override + public void evalFormRequest(UserRequest ureq) { + // + } + + @Override + public void dispatchFormRequest(UserRequest ureq) { + component.doDispatchRequest(ureq); + currentRating = component.getCurrentRating(); + + + getRootForm().fireFormEvent(ureq, new RatingFormEvent(this, currentRating)); + } + + @Override + public void reset() { + // + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/gui/components/rating/RatingRenderer.java b/src/main/java/org/olat/core/gui/components/rating/RatingRenderer.java index f69101048043e563f87f8a3ea5705911b2b11787..099a4ecce182a3ddb96324b4dfc2524816d51899 100644 --- a/src/main/java/org/olat/core/gui/components/rating/RatingRenderer.java +++ b/src/main/java/org/olat/core/gui/components/rating/RatingRenderer.java @@ -23,12 +23,15 @@ import java.util.List; import org.apache.commons.lang.StringEscapeUtils; import org.olat.core.gui.components.Component; -import org.olat.core.gui.components.ComponentRenderer; +import org.olat.core.gui.components.DefaultComponentRenderer; +import org.olat.core.gui.components.form.flexible.FormBaseComponentIdProvider; +import org.olat.core.gui.components.form.flexible.impl.Form; +import org.olat.core.gui.components.form.flexible.impl.FormJSHelper; +import org.olat.core.gui.components.form.flexible.impl.NameValuePair; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.winmgr.AJAXFlags; import org.olat.core.gui.render.RenderResult; import org.olat.core.gui.render.Renderer; -import org.olat.core.gui.render.RenderingState; import org.olat.core.gui.render.StringOutput; import org.olat.core.gui.render.URLBuilder; import org.olat.core.gui.translator.Translator; @@ -42,7 +45,7 @@ import org.olat.core.util.Formatter; * * @author gnaegi */ -public class RatingRenderer implements ComponentRenderer { +public class RatingRenderer extends DefaultComponentRenderer { /** * @see org.olat.core.gui.components.ComponentRenderer#render(org.olat.core.gui.render.Renderer, @@ -52,8 +55,9 @@ public class RatingRenderer implements ComponentRenderer { * org.olat.core.gui.translator.Translator, * org.olat.core.gui.render.RenderResult, java.lang.String[]) */ + @Override public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, - @SuppressWarnings("unused") RenderResult renderResult, @SuppressWarnings("unused") String[] args) { + RenderResult renderResult, String[] args) { RatingComponent rating = (RatingComponent) source; sb.append("<div class='b_rating "); // Add custom css class @@ -90,17 +94,26 @@ public class RatingRenderer implements ComponentRenderer { sb.append("'"); // Add action if (rating.isAllowUserInput()) { - // Add link - sb.append(" href=\""); - ubu.buildURI(sb, new String[] { VelocityContainer.COMMAND_ID }, new String[] { (i+1) +"" }, - ajaxModeEnabled ? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL); - sb.append("\""); - // add link target - if (ajaxModeEnabled) { - ubu.appendTarget(sb); - } - // add check for olat busy - sb.append(" onclick=\"return o2cl()\" onkeypress=\"return o2cl()\""); + if(rating.getForm() == null) { + // Add link + sb.append(" href=\""); + ubu.buildURI(sb, new String[] { VelocityContainer.COMMAND_ID }, new String[] { (i+1) +"" }, + ajaxModeEnabled ? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL); + sb.append("\""); + // add link target + if (ajaxModeEnabled) { + ubu.appendTarget(sb); + } + // add check for olat busy + sb.append(" onclick=\"return o2cl()\" onkeypress=\"return o2cl()\""); + } else { + Form theForm = rating.getForm(); + String elementId = FormBaseComponentIdProvider.DISPPREFIX + rating.getDispatchID(); + sb.append("href=\"javascript:") + .append(FormJSHelper.getXHRFnCallFor(theForm, elementId, 1, + new NameValuePair(VelocityContainer.COMMAND_ID, Integer.toString(i+1)))) + .append("\" "); + } } else { // Disabled link @@ -137,28 +150,4 @@ public class RatingRenderer implements ComponentRenderer { } sb.append("</div>");//b_rating } - - /** - * @see org.olat.core.gui.components.ComponentRenderer#renderBodyOnLoadJSFunctionCall(org.olat.core.gui.render.Renderer, - * org.olat.core.gui.render.StringOutput, - * org.olat.core.gui.components.Component, - * org.olat.core.gui.render.RenderingState) - */ - public void renderBodyOnLoadJSFunctionCall(Renderer renderer, StringOutput sb, Component source, RenderingState rstate) { - // no body onload to execute - } - - /** - * @see org.olat.core.gui.components.ComponentRenderer#renderHeaderIncludes(org.olat.core.gui.render.Renderer, - * org.olat.core.gui.render.StringOutput, - * org.olat.core.gui.components.Component, - * org.olat.core.gui.render.URLBuilder, - * org.olat.core.gui.translator.Translator, - * org.olat.core.gui.render.RenderingState) - */ - public void renderHeaderIncludes(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, - RenderingState rstate) { - // no headers to load - } - } diff --git a/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageComponent.java b/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..9dc03b88acb9aa9342f4fc9c6e752912b3699c5c --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageComponent.java @@ -0,0 +1,65 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.gui.components.rating; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.ComponentEventListener; +import org.olat.core.gui.components.ComponentRenderer; +import org.olat.core.gui.control.Event; + +/** + * + * Initial date: 31.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RatingWithAverageComponent extends Component implements ComponentEventListener { + + private static final RatingWithAverageRenderer RENDERER = new RatingWithAverageRenderer(); + + private final RatingWithAverageFormItem formItem; + + public RatingWithAverageComponent(String name, RatingWithAverageFormItem formItem) { + super(name); + this.formItem = formItem; + } + + public RatingWithAverageFormItem getFormItem() { + return formItem; + } + + @Override + protected void doDispatchRequest(UserRequest ureq) { + // + } + + @Override + public ComponentRenderer getHTMLRendererSingleton() { + return RENDERER; + } + + @Override + public void dispatchEvent(UserRequest ureq, Component source, Event event) { + formItem.dispatchFormRequest(ureq); + } + + +} diff --git a/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageFormItem.java b/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageFormItem.java new file mode 100644 index 0000000000000000000000000000000000000000..7f395b87dc29b5796b07a157ebc0919aa94fcaa3 --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageFormItem.java @@ -0,0 +1,130 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.gui.components.rating; + +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.FormItemCollection; +import org.olat.core.gui.components.form.flexible.impl.FormItemImpl; + +/** + * + * Initial date: 31.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RatingWithAverageFormItem extends FormItemImpl implements FormItemCollection { + + private float userRating; + private int numOfRatings; + private float averageRating; + private int maxRating; + + private RatingFormItem userComponent; + private RatingFormItem averageComponent; + private RatingWithAverageComponent component; + + public RatingWithAverageFormItem(String name, float userRating, float averageRating, int maxRating, int numOfRatings) { + super(name); + + this.maxRating = maxRating; + this.userRating = userRating; + this.numOfRatings = numOfRatings; + this.averageRating = averageRating; + component = new RatingWithAverageComponent(name, this); + } + + protected Component getUserComponent() { + return userComponent.getComponent(); + } + + protected Component getAverageComponent() { + return averageComponent.getComponent(); + } + + @Override + protected Component getFormItemComponent() { + return component; + } + + @Override + public Iterable<FormItem> getFormItems() { + List<FormItem> items = new ArrayList<FormItem>(); + items.add(userComponent); + items.add(averageComponent); + return items; + } + + @Override + public FormItem getFormComponent(String name) { + if(userComponent.getName().equals(name)) { + return userComponent; + } else if(averageComponent.getName().equals(name)) { + return averageComponent; + } + return null; + } + + @Override + protected void rootFormAvailable() { + if(userComponent == null) { + userComponent = new RatingFormItem("rusr_" + getName(), userRating, maxRating, true); + userComponent.setRootForm(getRootForm()); + userComponent.rootFormAvailable(); + userComponent.getComponent().addListener(component); + + userComponent.getFormItemComponent().setTranslateExplanation(true); + userComponent.getFormItemComponent().setTranslateRatingLabels(false); + + averageComponent = new RatingFormItem("ravg_" + getName(), averageRating, maxRating, false); + averageComponent.setRootForm(getRootForm()); + averageComponent.rootFormAvailable(); + + String[] args = new String[]{ Integer.toString(numOfRatings)}; + String explanation = translator.translate("rating.average.explanation", args); + averageComponent.getFormItemComponent().setExplanation(explanation); + averageComponent.getFormItemComponent().setTranslateExplanation(false); + averageComponent.getFormItemComponent().setTranslateRatingLabels(false); + } + } + + @Override + public void evalFormRequest(UserRequest ureq) { + // + } + + @Override + public void dispatchFormRequest(UserRequest ureq) { + userRating = userComponent.getCurrentRating(); + getRootForm().fireFormEvent(ureq, new RatingFormEvent(this, userRating)); + component.setDirty(true); + } + + @Override + public void reset() { + // + } + + +} diff --git a/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageRenderer.java b/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..4f5e3f4a19042fa37da74c3fdb3157391d2252a8 --- /dev/null +++ b/src/main/java/org/olat/core/gui/components/rating/RatingWithAverageRenderer.java @@ -0,0 +1,71 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.gui.components.rating; + +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.DefaultComponentRenderer; +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: 31.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RatingWithAverageRenderer extends DefaultComponentRenderer { + + @Override + public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, + RenderResult renderResult, String[] args) { + + RatingWithAverageComponent ratingCmp = (RatingWithAverageComponent)source; + RatingWithAverageFormItem item = ratingCmp.getFormItem(); + + String viewIdent = item.getFormDispatchId(); + sb.append("<div id=").append(viewIdent).append(" class='b_ratings_and_comments'>") + .append("<div id='b_rating_wrapper_").append(viewIdent).append("' class='b_rating_wrapper'>") + .append("<div id='b_rating_").append(viewIdent).append("' style='display:none;'>"); + + Component userCmp = item.getUserComponent(); + userCmp.getHTMLRendererSingleton().render(renderer, sb, userCmp, ubu, translator, renderResult, args); + sb.append("</div>") + .append("<div id='b_rating_avg_").append(viewIdent).append("'>"); + Component averageCmp = item.getAverageComponent(); + averageCmp.getHTMLRendererSingleton().render(renderer, sb, averageCmp, ubu, translator, renderResult, args); + sb.append("</div>") + .append("</div>") + .append("</div>") + .append("<script type='text/javascript'>\n") + .append("/* <![CDATA[ */ \n") + .append("jQuery(function(){\n") + .append(" jQuery('#b_rating_wrapper_").append(viewIdent).append("')\n") + .append(" .hover(\n") + .append(" function(){ jQuery('#b_rating_").append(viewIdent).append("').show(); jQuery('#b_rating_avg_").append(viewIdent).append("').hide(); }, \n") + .append(" function(){ jQuery('#b_rating_").append(viewIdent).append("').hide(); jQuery('#b_rating_avg_").append(viewIdent).append("').show(); }\n") + .append(" );\n") + .append("});\n") + .append("/* ]]> */\n") + .append("</script>\n"); + } +} diff --git a/src/main/java/org/olat/gui/control/OlatTopNavController.java b/src/main/java/org/olat/gui/control/OlatTopNavController.java index 0cb351239b2639b2c8cc63cc2d34468ea49bc193..8cd845917f338b815e4a60080890f8d2df1c8c2b 100644 --- a/src/main/java/org/olat/gui/control/OlatTopNavController.java +++ b/src/main/java/org/olat/gui/control/OlatTopNavController.java @@ -1,79 +1,90 @@ /** -* OLAT - Online Learning and Training<br> -* http://www.olat.org -* <p> -* Licensed under the Apache License, Version 2.0 (the "License"); <br> -* you may not use this file except in compliance with the License.<br> -* You may obtain a copy of the License at -* <p> -* http://www.apache.org/licenses/LICENSE-2.0 -* <p> -* Unless required by applicable law or agreed to in writing,<br> -* software distributed under the License is distributed on an "AS IS" BASIS, <br> -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> -* See the License for the specific language governing permissions and <br> -* limitations under the License. -* <p> -* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> -* University of Zurich, Switzerland. -* <hr> -* <a href="http://www.openolat.org"> -* OpenOLAT - Online Learning and Training</a><br> -* This file has been modified by the OpenOLAT community. Changes are licensed -* under the Apache 2.0 license as the original file. -*/ - + * <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.gui.control; +import java.util.ArrayList; +import java.util.List; + +import org.olat.NewControllerFactory; import org.olat.basesecurity.AuthHelper; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.controllers.impressum.ImpressumMainController; import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory; import org.olat.core.dispatcher.DispatcherModule; +import org.olat.core.extensions.ExtManager; +import org.olat.core.extensions.Extension; +import org.olat.core.extensions.ExtensionElement; +import org.olat.core.extensions.action.GenericActionExtension; import org.olat.core.gui.UserRequest; import org.olat.core.gui.Windows; import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.image.ImageComponent; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.tree.GenericTreeNode; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.control.creator.ControllerCreator; +import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController; import org.olat.core.gui.control.generic.popup.PopupBrowserWindow; +import org.olat.core.gui.media.MediaResource; import org.olat.core.id.OLATResourceable; +import org.olat.core.util.StringHelper; import org.olat.core.util.event.EventBus; import org.olat.core.util.event.GenericEventListener; import org.olat.core.util.resource.OresHelper; import org.olat.course.CourseFactory; import org.olat.course.CourseModule; import org.olat.course.nodes.iq.AssessmentEvent; +import org.olat.home.HomeMainController; import org.olat.ims.qti.process.AssessmentInstance; import org.olat.instantMessaging.InstantMessagingModule; import org.olat.instantMessaging.ui.InstantMessagingMainController; import org.olat.search.SearchServiceUIFactory; import org.olat.search.SearchServiceUIFactory.DisplayOption; import org.olat.search.ui.SearchInputController; +import org.olat.user.DisplayPortraitManager; +import org.olat.user.UserManager; /** - * Description:<br> - * TODO: patrickb Class Description for OlatTopNavController - * <P> - * Initial Date: 13.06.2006 <br> * - * @author patrickb + * Initial date: 21.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * */ public class OlatTopNavController extends BasicController implements GenericEventListener { private static final String ACTION_LOGOUT = "logout"; - private VelocityContainer topNavVC; - private InstantMessagingMainController imController; private SearchInputController searchC; - private Link helpLink, loginLink, impressumLink; + private Link helpLink, loginLink, impressumLink, myMenuLink; + private VelocityContainer menuVC; + private VelocityContainer topNavVC; + private InstantMessagingMainController imController; + private CloseableCalloutWindowController calloutCtr; private EventBus singleUserEventCenter; + private final DisplayPortraitManager portraitManager; private OLATResourceable ass; public OlatTopNavController(UserRequest ureq, WindowControl wControl) { @@ -84,6 +95,7 @@ public class OlatTopNavController extends BasicController implements GenericEven super(ureq, wControl); topNavVC = createVelocityContainer("topnav"); + portraitManager = DisplayPortraitManager.getInstance(); boolean isGuest = ureq.getUserSession().getRoles().isGuestOnly(); boolean isInvitee = ureq.getUserSession().getRoles().isInvitee(); @@ -127,46 +139,152 @@ public class OlatTopNavController extends BasicController implements GenericEven ass = OresHelper.createOLATResourceableType(AssessmentEvent.class); singleUserEventCenter = ureq.getUserSession().getSingleUserEventCenter(); singleUserEventCenter.registerFor(this, getIdentity(), ass); + + UserManager userManager = CoreSpringFactory.getImpl(UserManager.class); + + myMenuLink = LinkFactory.createButton("topnav.my.menu", topNavVC, this); + myMenuLink.setCustomDisplayText(userManager.getUserDisplayName(getIdentity())); + myMenuLink.setCustomEnabledLinkCSS("o_topnav_impressum"); + myMenuLink.setElementCssClass("o_sel_my_menu_open"); + + MediaResource image = portraitManager.getSmallPortraitResource(getIdentity().getName()); + + if (image != null) { + // display only within 600x300 - everything else looks ugly + ImageComponent ic = new ImageComponent("image"); + ic.setSpanAsDomReplaceable(true); + ic.setMediaResource(image); + topNavVC.contextPut("hasPortrait", Boolean.TRUE); + topNavVC.put("portrait", ic); + } else { + topNavVC.contextPut("hasPortrait", Boolean.FALSE); + } } putInitialPanel(topNavVC); } - /** - * - * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event) - */ @Override public void event(UserRequest ureq, Component source, Event event) { - String command = event.getCommand(); - if (source == helpLink) { - ControllerCreator ctrlCreator = new ControllerCreator() { - public Controller createController(UserRequest lureq, WindowControl lwControl) { - return CourseFactory.createHelpCourseLaunchController(lureq, lwControl); - } - }; - //wrap the content controller into a full header layout - ControllerCreator layoutCtrlr = BaseFullWebappPopupLayoutFactory.createAuthMinimalPopupLayout(ureq, ctrlCreator); - //open in new browser window - openInNewBrowserWindow(ureq, layoutCtrlr); - // - } else if (source == loginLink) { - DispatcherModule.redirectToDefaultDispatcher(ureq.getHttpResp()); - } else if (source == topNavVC) { + if (source == helpLink) { + doOpenHelp(ureq) ; + } else if(source == myMenuLink) { + myMenuLink.setDirty(false); + doOpenMyMenu(ureq); + } else if(source instanceof Link && source.getComponentName().startsWith("personal.tool.")) { + doCloseMyMenu(); + doOpenPersonalTool(ureq, (Link)source); + } else if (source == loginLink) { + DispatcherModule.redirectToDefaultDispatcher(ureq.getHttpResp()); + } else if (source == menuVC) { + String command = event.getCommand(); if (command.equals(ACTION_LOGOUT)) { AuthHelper.doLogout(ureq); } - } else if (source == impressumLink) { - ControllerCreator impressumControllerCreator = new ControllerCreator() { - public Controller createController(UserRequest lureq, WindowControl lwControl) { - return new ImpressumMainController(lureq, lwControl); - } - }; - PopupBrowserWindow popupBrowserWindow = Windows.getWindows(ureq).getWindowManager().createNewPopupBrowserWindowFor(ureq, impressumControllerCreator); - popupBrowserWindow.open(ureq); + } else if (source == impressumLink) { + doOpenImpressum(ureq); + } + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if (source == calloutCtr) { + closePersonalMenu(); } } + + private void doOpenPersonalTool(UserRequest ureq, Link link) { + GenericActionExtension gAe = (GenericActionExtension)link.getUserObject(); + String navKey = gAe.getNavigationKey(); + String businessPath = "[HomeSite:" + getIdentity().getKey() + "][" + navKey + ":0]"; + NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl()); + } + + private void doCloseMyMenu() { + calloutCtr.deactivate(); + removeAsListenerAndDispose(calloutCtr); + calloutCtr = null; + } + private void doOpenMyMenu(UserRequest ureq) { + removeAsListenerAndDispose(calloutCtr); + Component menu = getMenuCmp(ureq); + calloutCtr = new CloseableCalloutWindowController(ureq, getWindowControl(), menu, myMenuLink, "", true, null); + listenTo(calloutCtr); + calloutCtr.activate(); + } + + private void closePersonalMenu() { + removeAsListenerAndDispose(calloutCtr); + calloutCtr = null; + } + + private Component getMenuCmp(UserRequest ureq) { + VelocityContainer container = createVelocityContainer("menu"); + loadPersonalTools(ureq, container); + menuVC = container; + return menuVC; + } + + private void loadPersonalTools(UserRequest ureq, VelocityContainer container) { + List<String> linksName = new ArrayList<String>(); + List<String> configLinksName = new ArrayList<String>(); + + ExtManager extm = ExtManager.getInstance(); + for (Extension anExt : extm.getExtensions()) { + // check for sites + ExtensionElement ae = anExt.getExtensionFor(HomeMainController.class.getName(), ureq); + if (ae != null && ae instanceof GenericActionExtension) { + if(anExt.isEnabled()){ + GenericActionExtension gAe = (GenericActionExtension) ae; + if(!StringHelper.containsNonWhitespace(gAe.getParentTreeNodeIdentifier())) { + GenericTreeNode node = gAe.createMenuNode(ureq); + String linkName = "personal.tool." + node.getIdent(); + Link link = LinkFactory.createLink(linkName, container, this); + link.setUserObject(gAe); + link.setCustomDisplayText(gAe.getActionText(getLocale())); + link.setCustomEnabledLinkCSS(node.getIconCssClass()); + linksName.add(linkName); + } else if("config".equals(gAe.getParentTreeNodeIdentifier())) { + GenericTreeNode node = gAe.createMenuNode(ureq); + String linkName = "personal.tool." + node.getIdent(); + Link link = LinkFactory.createLink(linkName, container, this); + link.setUserObject(gAe); + link.setCustomDisplayText(gAe.getActionText(getLocale())); + link.setCustomEnabledLinkCSS(node.getIconCssClass()); + configLinksName.add(linkName); + } + } + } + } + + container.contextPut("personalTools", linksName); + container.contextPut("configs", configLinksName); + } + + protected void doOpenHelp(UserRequest ureq) { + ControllerCreator ctrlCreator = new ControllerCreator() { + public Controller createController(UserRequest lureq, WindowControl lwControl) { + return CourseFactory.createHelpCourseLaunchController(lureq, lwControl); + } + }; + //wrap the content controller into a full header layout + ControllerCreator layoutCtrlr = BaseFullWebappPopupLayoutFactory.createAuthMinimalPopupLayout(ureq, ctrlCreator); + //open in new browser window + openInNewBrowserWindow(ureq, layoutCtrlr); + } + + protected void doOpenImpressum(UserRequest ureq) { + ControllerCreator impressumControllerCreator = new ControllerCreator() { + public Controller createController(UserRequest lureq, WindowControl lwControl) { + return new ImpressumMainController(lureq, lwControl); + } + }; + PopupBrowserWindow popupBrowserWindow = Windows.getWindows(ureq).getWindowManager().createNewPopupBrowserWindowFor(ureq, impressumControllerCreator); + popupBrowserWindow.open(ureq); + } + + @Override protected void doDispose() { //controllers are disposed by BasicController // im header controller mus be disposed last - content or navigation control @@ -199,4 +317,4 @@ public class OlatTopNavController extends BasicController implements GenericEven } } } -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/gui/control/TopNavCreator.java b/src/main/java/org/olat/gui/control/TopNavCreator.java index 973babde47178061433ec4cd3afcc46b26001751..ad140e0aa47b69f58bb3ce6ef92e45859e692610 100644 --- a/src/main/java/org/olat/gui/control/TopNavCreator.java +++ b/src/main/java/org/olat/gui/control/TopNavCreator.java @@ -28,7 +28,7 @@ import org.olat.core.gui.control.creator.AutoCreator; * * <h3>Description:</h3> * AutoCreator for the FrentixTopNavController which allow to configure - * an impressum or not, annd the search or not + * an impressum or not, and the search or not * * <p> * Initial Date: 25 nov. 2010 <br> @@ -39,7 +39,6 @@ public class TopNavCreator extends AutoCreator { private boolean impressum; private boolean search; - @Override public Controller createController(UserRequest ureq, WindowControl wControl) { return new OlatTopNavController(ureq, wControl, impressum, search); @@ -60,4 +59,4 @@ public class TopNavCreator extends AutoCreator { public void setSearch(boolean search) { this.search = search; } -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/gui/control/_content/menu.html b/src/main/java/org/olat/gui/control/_content/menu.html new file mode 100644 index 0000000000000000000000000000000000000000..41bb50eb530e2705988441a2c68d98256a34780d --- /dev/null +++ b/src/main/java/org/olat/gui/control/_content/menu.html @@ -0,0 +1,24 @@ +<div class="o_topnav_my_menu"> + <span class="o_topnav_my_submenu">$r.translate("topnav.my.menu.tools")</span> + <ul> + #foreach($personalTool in $personalTools) + <li>$r.render($personalTool)</li> + #end + </ul> + <hr/> + <span class="o_topnav_my_submenu">$r.translate("topnav.my.menu.configurations")</span> + <ul> + #foreach($config in $configs) + <li>$r.render($config)</li> + #end + </ul> + <hr/> + <ul> + <li id="o_topnav_logout"> + ## make logout link very basic without onClick handler in case javaScript is broken it is still possible to log out + ## except for the onolatunload() method which must be executed to correctly finish SCORM modules (OLAT-6255) + ## must be on one line to work with inline translation tool + <a id="b_logout" href="$r.commandURI("logout")" title="$r.translateInAttribute("topnav.logout.alt")" onclick="if (window.olatonunload) {olatonunload();}"><span class="b_logout_icon">$r.translate("topnav.logout")</span></a> + </li> + </ul> +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/gui/control/_content/topnav.html b/src/main/java/org/olat/gui/control/_content/topnav.html index 893c75705c67896ed68080d98163159ce09779fd..d2bad79f28e814990c928fc500244b94cbe03540 100644 --- a/src/main/java/org/olat/gui/control/_content/topnav.html +++ b/src/main/java/org/olat/gui/control/_content/topnav.html @@ -4,6 +4,12 @@ $r.render("topnav.impressum") </li> #end + +#if (!$inAssessment && $r.available("search_input")) + <li id="o_topnav_search"> + $r.render("search_input") + </li> +#end #if ($r.available("groupchatcontroller")) <li id="o_topnav_imgroupclient"> $r.render("groupchatcontroller") @@ -14,25 +20,14 @@ $r.render("imclient") </li> #end -#if (!$inAssessment && $r.available("search_input")) - <li id="o_topnav_search"> - $r.render("search_input") - </li> -#end - <li id="o_topnav_printview"> - <a href="javascript:b_doPrint();" title="$r.translateInAttribute("topnav.printview.alt")" >$r.translate("topnav.printview")</a> - </li> -#if ($r.available("topnav.help")) - <li id="o_topnav_help"> - $r.render("topnav.help") - </li> -#end #if (!$isGuest) - <li id="o_topnav_logout"> - ## make logout link very basic without onClick handler in case javaScript is broken it is still possible to log out - ## except for the onolatunload() method which must be executed to correctly finish SCORM modules (OLAT-6255) - ## must be on one line to work with inline translation tool - <a id="b_logout" href="$r.commandURI("logout")" title="$r.translateInAttribute("topnav.logout.alt")" onclick="if (window.olatonunload) {olatonunload();}"><span class="b_logout_icon">$r.translate("topnav.logout")</span></a> + <li id="o_topnav_my_menu_link"> + <div class="o_topnav_portrait"> + #if($hasPortrait) + $r.render("portrait") + #end + </div> + $r.render("topnav.my.menu") </li> #else <li id="o_topnav_login"> diff --git a/src/main/java/org/olat/gui/control/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/gui/control/_i18n/LocalStrings_de.properties index 75a332de9acc668b845d7e3dacf9c6bb7272af37..4d64a906b0836e09127d429442af620a3df6da09 100644 --- a/src/main/java/org/olat/gui/control/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/gui/control/_i18n/LocalStrings_de.properties @@ -22,3 +22,7 @@ topnav.printview.alt=Diese Seite drucken topnav.search=Suche topnav.search.alt=Suchen Sie innerhalb von OLAT username=Eingeloggt als <i>{0}</i> +topnav.my.menu=My menu +topnav.my.menu.tools=Persönliche Werkzeuge +topnav.my.menu.configurations=Konfiguration + diff --git a/src/main/java/org/olat/repository/RepositoryManager.java b/src/main/java/org/olat/repository/RepositoryManager.java index c62748197928a4dc6de0688a3f7ef99350cdcf77..034314ef4e421a504c2a73aeb271147813b0530f 100644 --- a/src/main/java/org/olat/repository/RepositoryManager.java +++ b/src/main/java/org/olat/repository/RepositoryManager.java @@ -1683,8 +1683,8 @@ public class RepositoryManager extends BasicManager { return results; } - public int countGenericANDQueryWithRolesRestriction(SearchRepositoryEntryParameters params, boolean orderBy) { - DBQuery dbQuery = createGenericANDQueryWithRolesRestriction(params, orderBy, true); + public int countGenericANDQueryWithRolesRestriction(SearchRepositoryEntryParameters params) { + DBQuery dbQuery = createGenericANDQueryWithRolesRestriction(params, false, true); Number count = (Number)dbQuery.uniqueResult(); return count.intValue(); } diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties index 56a12b0a6df5b1bc93c75de2482a3c910f89c975..85535e0889a3aef74f21ff9553f441a099fddfb6 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties @@ -384,6 +384,7 @@ search.home=Lernressourcen search.id.format=Nur Ziffern erlaubt search.intro=Benutzen Sie den OpenOLAT-Katalog, um zu einem Lerninhalt zu gelangen. Alternativ k\u00F6nnen Sie eine allgemeine Suche \u00FCber den Men\u00FCpunkt 'Suchmaske' starten oder Sie w\u00E4hlen eine der vordefinierten Suchen im Menu auf der linken Seite. search.limit.type=Suche einschr\u00E4nken +search.mark=Favoriten search.my=Meine Eintr\u00E4ge search.mycourses.student=Meine Kurse search.mycourses.teacher=Meine betreuten Kurse @@ -398,6 +399,12 @@ security.disabled.title=Lernressource nicht verf security.disabled.info=Diese Lernressourcen ist aus Sicherheitsgründen gesperrt. Weitere Informationen erhalten Sie von Ihrem Systemadministrator. sf.notconfigured=Kein Ressourcenordner ausgew\u00E4hlt sf.resourcetitle=Gew\u00E4hlter Ressourcenordner +start=starten +details=mehr... +ratings=Bewertung +rating.average.explanation=Basierend auf {0} Bewertungen +rating.average.title=Bewertung der anderen +rating.personal.title=Ihre Bewertung tab.accesscontrol=Access control tab.calendar=Kalender tab.chat=Kurs-Chat @@ -428,10 +435,13 @@ table.header.externalid=Ext. ID table.header.externalref=Ext. Ref. table.header.lastusage=Letzter Zugriff table.header.typeimg=Typ +table.header.mark=Favorit +table.header.key=ID table.header.lifecycle.label=Semester table.header.lifecycle.softkey=Semesterbezeichnung table.header.lifecycle.start=$\:cif.date.start table.header.lifecycle.end=$\:cif.date.end +table.header.start=Starten table.subject.addeddate=Wann hinzugef\u00FCgt table.subject.birthDay=Geburtsdatum table.subject.city=Stadt @@ -452,6 +462,8 @@ table.subject.telOffice=Telefon Gesch\u00E4ft table.subject.telPrivate=Telefon Privat table.subject.zipCode=Postleitzahl table.user.login=Benutzername +table.switch.list=Liste +table.switch.table=Table title.prefix.closed=beendet tools.add.blog=Blog tools.add.course=Kurs diff --git a/src/main/java/org/olat/repository/site/MyCoursesSite.java b/src/main/java/org/olat/repository/site/MyCoursesSite.java new file mode 100644 index 0000000000000000000000000000000000000000..7b23571b324564207b78bfe643b34b232528448c --- /dev/null +++ b/src/main/java/org/olat/repository/site/MyCoursesSite.java @@ -0,0 +1,92 @@ +/** + * <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.repository.site; + +import java.util.Locale; + +import org.olat.core.commons.chiefcontrollers.BaseChiefController; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.layout.MainLayoutController; +import org.olat.core.gui.control.navigation.AbstractSiteInstance; +import org.olat.core.gui.control.navigation.DefaultNavElement; +import org.olat.core.gui.control.navigation.NavElement; +import org.olat.core.gui.control.navigation.SiteConfiguration; +import org.olat.core.gui.control.navigation.SiteDefinition; +import org.olat.core.gui.translator.Translator; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.context.BusinessControlFactory; +import org.olat.core.id.context.StateSite; +import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; +import org.olat.core.util.Util; +import org.olat.core.util.resource.OresHelper; +import org.olat.repository.ui.list.MyCoursesMainController; +import org.olat.util.logging.activity.LoggingResourceable; + +/** + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MyCoursesSite extends AbstractSiteInstance { + + private NavElement origNavElem; + private NavElement curNavElem; + + public MyCoursesSite(SiteDefinition siteDef, Locale loc) { + super(siteDef); + Translator trans = Util.createPackageTranslator(BaseChiefController.class, loc); + origNavElem = new DefaultNavElement(trans.translate("topnav.mycourses"), trans.translate("topnav.mycourses.alt"), "o_site_repository"); + origNavElem.setAccessKey("r".charAt(0)); + curNavElem = new DefaultNavElement(origNavElem); + } + + /** + * @see org.olat.navigation.SiteInstance#getNavElement() + */ + public NavElement getNavElement() { + return curNavElem; + } + + @Override + protected MainLayoutController createController(UserRequest ureq, WindowControl wControl, SiteConfiguration config) { + OLATResourceable ores = OresHelper.createOLATResourceableInstance(MyCoursesSite.class, 0l); + ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); + WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ureq, ores, new StateSite(this), wControl, true); + MainLayoutController c = new MyCoursesMainController(ureq, bwControl); + + //MainLayoutController c2 = new LayoutMain3ColsController(ureq, bwControl, c); + return c; + } + + /** + * @see org.olat.navigation.SiteInstance#isKeepState() + */ + public boolean isKeepState() { + return true; + } + + public void reset() { + curNavElem = new DefaultNavElement(origNavElem); + } + +} + diff --git a/src/main/java/org/olat/repository/site/MyCoursesSiteDef.java b/src/main/java/org/olat/repository/site/MyCoursesSiteDef.java new file mode 100644 index 0000000000000000000000000000000000000000..0790ffe3cd6ca025863a15a8119e25f6d38bde5f --- /dev/null +++ b/src/main/java/org/olat/repository/site/MyCoursesSiteDef.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.repository.site; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.navigation.AbstractSiteDefinition; +import org.olat.core.gui.control.navigation.SiteConfiguration; +import org.olat.core.gui.control.navigation.SiteDefinition; +import org.olat.core.gui.control.navigation.SiteInstance; +import org.olat.core.util.StringHelper; + +/** + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MyCoursesSiteDef extends AbstractSiteDefinition implements SiteDefinition { + + public MyCoursesSiteDef() { + // + } + + /** + * site is open to both normal users and guest users + */ + @Override + public SiteInstance createSite(UserRequest ureq, WindowControl wControl, SiteConfiguration config) { + if(StringHelper.containsNonWhitespace(config.getSecurityCallbackBeanId())) { + return new MyCoursesSite(this, ureq.getLocale()); + } else if(!ureq.getUserSession().getRoles().isInvitee()) { + //for all excepts invitees + return new MyCoursesSite(this, ureq.getLocale()); + } + return null; + } +} + diff --git a/src/main/java/org/olat/repository/ui/list/AbstractRepositoryEntryDataSource.java b/src/main/java/org/olat/repository/ui/list/AbstractRepositoryEntryDataSource.java new file mode 100644 index 0000000000000000000000000000000000000000..f331956523b0423bc7ac8df3b79875223cf27679 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/AbstractRepositoryEntryDataSource.java @@ -0,0 +1,230 @@ +/** + * <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.repository.ui.list; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.olat.basesecurity.BaseSecurity; +import org.olat.basesecurity.SecurityGroup; +import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.persistence.ResultInfos; +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.commons.services.mark.MarkManager; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate; +import org.olat.core.id.Identity; +import org.olat.core.util.StringHelper; +import org.olat.core.util.resource.OresHelper; +import org.olat.core.util.vfs.VFSLeaf; +import org.olat.course.assessment.AssessmentHelper; +import org.olat.course.assessment.UserCourseInformations; +import org.olat.course.assessment.UserEfficiencyStatement; +import org.olat.course.assessment.manager.UserCourseInformationsManager; +import org.olat.modules.coach.manager.CoachingService; +import org.olat.modules.coach.model.EfficiencyStatementEntry; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; +import org.olat.repository.model.RepositoryEntryLifecycle; +import org.olat.repository.model.RepositoryEntryMembership; +import org.olat.repository.ui.PriceMethod; +import org.olat.resource.OLATResource; +import org.olat.resource.accesscontrol.ACService; +import org.olat.resource.accesscontrol.model.OLATResourceAccess; +import org.olat.resource.accesscontrol.model.PriceMethodBundle; +import org.olat.resource.accesscontrol.ui.PriceFormat; +import org.olat.user.UserManager; + +/** + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public abstract class AbstractRepositoryEntryDataSource implements FlexiTableDataSourceDelegate<RepositoryEntryRow> { + + private final Identity identity; + private RepositoryEntryDataSourceUIFactory uifactory; + + protected final ACService acService; + protected final MarkManager markManager; + protected final UserManager userManager; + protected final CoachingService coachService; + protected final BaseSecurity securityManager; + protected final RepositoryManager repositoryManager; + protected final UserCourseInformationsManager courseInfoManager; + + private Integer count; + + public AbstractRepositoryEntryDataSource(Identity identity, RepositoryEntryDataSourceUIFactory uifactory) { + this.identity = identity; + this.uifactory = uifactory; + + acService = CoreSpringFactory.getImpl(ACService.class); + markManager = CoreSpringFactory.getImpl(MarkManager.class); + userManager = CoreSpringFactory.getImpl(UserManager.class); + coachService = CoreSpringFactory.getImpl(CoachingService.class); + securityManager = CoreSpringFactory.getImpl(BaseSecurity.class); + repositoryManager = CoreSpringFactory.getImpl(RepositoryManager.class); + courseInfoManager = CoreSpringFactory.getImpl(UserCourseInformationsManager.class); + } + + public Identity getIdentity() { + return identity; + } + + @Override + public int getRowCount() { + if(count == null) { + count = getNumOfRepositoryEntries(); + } + return count.intValue(); + } + + protected abstract int getNumOfRepositoryEntries(); + + @Override + public List<RepositoryEntryRow> reload(List<RepositoryEntryRow> rows) { + return Collections.emptyList(); + } + + @Override + public abstract ResultInfos<RepositoryEntryRow> getRows(String query, List<String> condQueries, int firstResult, int maxResults, + SortKey... orderBy); + + protected List<RepositoryEntryRow> processModel(List<RepositoryEntry> repoEntries) { + List<OLATResource> resources = new ArrayList<OLATResource>(repoEntries.size()); + List<SecurityGroup> authorsSecGroup = new ArrayList<SecurityGroup>(repoEntries.size()); + Set<Long> markedResources = new HashSet<Long>(repoEntries.size() * 2 + 1); + for(RepositoryEntry entry:repoEntries) { + resources.add(entry.getOlatResource()); + authorsSecGroup.add(entry.getOwnerGroup()); + markedResources.add(entry.getResourceableId()); + } + + List<UserCourseInformations> courseInfos = courseInfoManager.getUserCourseInformations(identity, resources); + List<RepositoryEntryMembership> authors = repositoryManager.getOwnersMembership(repoEntries); + + Set<Long> authorKeys = new HashSet<>(); + for(RepositoryEntryMembership membership:authors) { + authorKeys.add(membership.getIdentityKey()); + } + Map<Long,String> authorNames = userManager.getUserDisplayNamesByKey(authorKeys); + markManager.filterMarks(identity, "RepositoryEntry", markedResources); + List<OLATResourceAccess> resourcesWithOffer = acService.filterRepositoryEntriesWithAC(repoEntries); + List<EfficiencyStatementEntry> statements = coachService.getEfficencyStatements(identity, repoEntries); + + List<RepositoryEntryRow> items = new ArrayList<RepositoryEntryRow>(); + for(RepositoryEntry entry:repoEntries) { + RepositoryEntryRow details = new RepositoryEntryRow(); + details.setKey(entry.getKey()); + details.setDisplayName(entry.getDisplayname()); + details.setDescription(entry.getDescription()); + details.setMarked(markedResources.contains(entry.getResourceableId())); + details.setOLATResourceable(OresHelper.clone(entry.getOlatResource())); + + RepositoryEntryLifecycle lifecycle = entry.getLifecycle(); + if(lifecycle != null) { + details.setLifecycleStart(lifecycle.getValidFrom()); + details.setLifecycleEnd(lifecycle.getValidTo()); + if(!lifecycle.isPrivateCycle()) { + details.setLifecycle(lifecycle.getLabel()); + details.setLifecycleSoftKey(lifecycle.getSoftKey()); + } + } + + uifactory.forgeMarkLink(details); + uifactory.forgeSelectLink(details); + uifactory.forgeStartLink(details); + uifactory.forgeDetailsLink(details); + uifactory.forgeRatings(details, entry); + + VFSLeaf image = repositoryManager.getImage(entry); + if(image != null) { + details.setThumbnailRelPath(uifactory.getMapperThumbnailUrl() + "/" + image.getName()); + } + + StringBuilder sb = new StringBuilder(); + for(RepositoryEntryMembership membership:authors) { + if(entry.getKey().equals(membership.getOwnerRepoKey())) { + String authorName = authorNames.get(membership.getIdentityKey()); + if(StringHelper.containsNonWhitespace(authorName)) { + if(sb.length() > 0) { + sb.append(" & "); + } + sb.append(authorName); + } + } + } + if(sb.length() > 0) { + details.setAuthor(sb.toString()); + } + + + + for(UserCourseInformations courseInfo:courseInfos) { + if(courseInfo.getResource().equals(entry.getOlatResource())) { + details.setInitialLaunch(courseInfo.getInitialLaunch()); + details.setRecentLaunch(courseInfo.getRecentLaunch()); + details.setVisit(courseInfo.getVisit()); + details.setTimeSpend(courseInfo.getTimeSpend()); + } + } + + for(EfficiencyStatementEntry statement:statements) { + if(statement.getUserEfficencyStatement() != null && statement.getCourse().equals(entry)) { + UserEfficiencyStatement userStatement = statement.getUserEfficencyStatement(); + + details.setPassed(userStatement.getPassed()); + details.setScore(AssessmentHelper.getRoundedScore(userStatement.getScore())); + } + } + + List<PriceMethod> types = new ArrayList<PriceMethod>(); + if (entry.isMembersOnly()) { + // members only always show lock icon + types.add(new PriceMethod("", "b_access_membersonly_icon")); + } else { + // collect access control method icons + OLATResource resource = entry.getOlatResource(); + for(OLATResourceAccess resourceAccess:resourcesWithOffer) { + if(resource.getKey().equals(resourceAccess.getResource().getKey())) { + for(PriceMethodBundle bundle:resourceAccess.getMethods()) { + String type = (bundle.getMethod().getMethodCssClass() + "_icon").intern(); + String price = bundle.getPrice() == null || bundle.getPrice().isEmpty() ? "" : PriceFormat.fullFormat(bundle.getPrice()); + types.add(new PriceMethod(price, type)); + } + } + } + } + + if(!types.isEmpty()) { + details.setAccessTypes(types); + } + + items.add(details); + + } + return items; + } +} diff --git a/src/main/java/org/olat/repository/ui/list/AbstractRepositoryEntryListController.java b/src/main/java/org/olat/repository/ui/list/AbstractRepositoryEntryListController.java new file mode 100644 index 0000000000000000000000000000000000000000..4b436a58f0b9bae1ea992816bc8340ae589a81e2 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/AbstractRepositoryEntryListController.java @@ -0,0 +1,234 @@ +/** + * <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.repository.ui.list; + +import org.olat.NewControllerFactory; +import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.services.commentAndRating.CommentAndRatingService; +import org.olat.core.commons.services.commentAndRating.impl.UserRatingsDAO; +import org.olat.core.commons.services.commentAndRating.model.UserRating; +import org.olat.core.commons.services.mark.MarkManager; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.rating.RatingFormEvent; +import org.olat.core.gui.components.rating.RatingWithAverageFormItem; +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.id.OLATResourceable; +import org.olat.core.util.Util; +import org.olat.core.util.resource.OresHelper; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; +import org.olat.repository.ui.RepositoryEntryImageMapper; +import org.olat.repository.ui.list.RepositoryEntryDataModel.Cols; + +/** + * + * Initial date: 20.11.2012<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public abstract class AbstractRepositoryEntryListController extends FormBasicController implements RepositoryEntryDataSourceUIFactory { + + private FormLink listLink, tableLink; + private FlexiTableElement tableEl; + private RepositoryEntryDataModel model; + private FlexiTableDataSourceDelegate<RepositoryEntryRow> dataSource; + + private final String mapperThumbnailUrl; + private final MarkManager markManager; + private final UserRatingsDAO userRatingsDao; + + public AbstractRepositoryEntryListController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "repoentry_table"); + setTranslator(Util.createPackageTranslator(RepositoryManager.class, getLocale(), getTranslator())); + markManager = CoreSpringFactory.getImpl(MarkManager.class); + userRatingsDao = CoreSpringFactory.getImpl(UserRatingsDAO.class); + mapperThumbnailUrl = registerCacheableMapper(ureq, "repositoryentryImage", new RepositoryEntryImageMapper()); + } + + public FlexiTableDataSourceDelegate<RepositoryEntryRow> getDataSource() { + return dataSource; + } + + public void setDataSource(FlexiTableDataSourceDelegate<RepositoryEntryRow> dataSource) { + this.dataSource = dataSource; + if(tableEl != null) { + model.setSource(dataSource); + tableEl.reset(); + } + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + listLink = uifactory.addFormLink("switchLayoutList", "list", "table.switch.list", null, formLayout, Link.BUTTON); + tableLink = uifactory.addFormLink("switchLayoutTable", "table", "table.switch.table", null, formLayout, Link.BUTTON); + + //add the table + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.key.i18nKey(), Cols.key.ordinal(), false, null)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.mark.i18nKey(), Cols.mark.ordinal())); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName.i18nKey(), Cols.displayName.ordinal())); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.lifecycleLabel.i18nKey(), Cols.lifecycleLabel.ordinal())); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.lifecycleSoftkey.i18nKey(), Cols.lifecycleSoftkey.ordinal())); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.lifecycleStart.i18nKey(), Cols.lifecycleStart.ordinal())); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.lifecycleEnd.i18nKey(), Cols.lifecycleEnd.ordinal())); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.select.i18nKey(), Cols.select.ordinal(), false, null)); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.details.i18nKey(), Cols.details.ordinal())); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.start.i18nKey(), Cols.start.ordinal())); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.ratings.i18nKey(), Cols.ratings.ordinal())); + + model = new RepositoryEntryDataModel(dataSource, columnsModel); + tableEl = uifactory.addTableElement(ureq, getWindowControl(), "table", model, 20, getTranslator(), formLayout); + tableEl.setRendererType(FlexiTableRendererType.custom); + + VelocityContainer row = createVelocityContainer("row_1"); + tableEl.setRowRenderer(row); + } + + @Override + public String getMapperThumbnailUrl() { + return mapperThumbnailUrl; + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == listLink) { + tableEl.setRendererType(FlexiTableRendererType.custom); + } else if(source == tableLink) { + tableEl.setRendererType(FlexiTableRendererType.classic); + } else if(source instanceof RatingWithAverageFormItem && event instanceof RatingFormEvent) { + RatingFormEvent ratingEvent = (RatingFormEvent)event; + RatingWithAverageFormItem ratingItem = (RatingWithAverageFormItem)source; + RepositoryEntryRow row = (RepositoryEntryRow)ratingItem.getUserObject(); + doRating(row, ratingEvent.getRating()); + } else if(source instanceof FormLink) { + FormLink link = (FormLink)source; + String cmd = link.getCmd(); + + if("mark".equals(cmd)) { + RepositoryEntryRow row = (RepositoryEntryRow)link.getUserObject(); + if(doMark(row)) { + link.setCustomEnabledLinkCSS("b_mark_set"); + } else { + link.setCustomEnabledLinkCSS("b_mark_not_set"); + } + link.getComponent().setDirty(true); + } else if ("select".equals(cmd) || "start".equals(cmd)){ + RepositoryEntryRow row = (RepositoryEntryRow)link.getUserObject(); + doOpen(ureq, row); + } else if ("details".equals(cmd)){ + RepositoryEntryRow row = (RepositoryEntryRow)link.getUserObject(); + doOpenDetails(ureq, row); + } + } + + super.formInnerEvent(ureq, source, event); + } + + protected void doRating(RepositoryEntryRow row, float rating) { + OLATResourceable ores = row.getOLATResourceable(); + userRatingsDao.updateRating(getIdentity(), ores, null, Math.round(rating)); + } + + protected void doOpen(UserRequest ureq, RepositoryEntryRow row) { + String businessPath = "[RepositoryEntry:" + row.getKey() + "]"; + NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl()); + } + + protected void doOpenDetails(UserRequest ureq, RepositoryEntryRow row) { + String businessPath = "[RepositoryEntry:" + row.getKey() + "][details:0]"; + NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl()); + } + + protected boolean doMark(RepositoryEntryRow row) { + OLATResourceable item = OresHelper.createOLATResourceableInstance("RepositoryEntry", row.getKey()); + if(markManager.isMarked(item, getIdentity(), null)) { + markManager.removeMark(item, getIdentity(), null); + return false; + } else { + String businessPath = "[QuestionItem:" + item.getResourceableId() + "]"; + markManager.setMark(item, getIdentity(), null, businessPath); + return true; + } + } + + @Override + public void forgeMarkLink(RepositoryEntryRow row) { + FormLink markLink = uifactory.addFormLink("mark_" + row.getKey(), "mark", " ", null, null, Link.NONTRANSLATED); + markLink.setCustomEnabledLinkCSS(row.isMarked() ? "b_mark_set" : "b_mark_not_set"); + markLink.setUserObject(row); + row.setMarkLink(markLink); + } + + @Override + public void forgeSelectLink(RepositoryEntryRow row) { + String name = row.getDisplayName(); + FormLink selectLink = uifactory.addFormLink("select_" + row.getKey(), "select", name, null, null, Link.NONTRANSLATED); + selectLink.setUserObject(row); + row.setSelectLink(selectLink); + } + + @Override + public void forgeStartLink(RepositoryEntryRow row) { + FormLink startLink = uifactory.addFormLink("start_" + row.getKey(), "start", "start", null, null, Link.LINK); + startLink.setUserObject(row); + row.setStartLink(startLink); + } + + @Override + public void forgeDetailsLink(RepositoryEntryRow row) { + FormLink detailsLink = uifactory.addFormLink("details_" + row.getKey(), "details", "details", null, null, Link.LINK); + detailsLink.setUserObject(row); + row.setDetailsLink(detailsLink); + } + + @Override + public void forgeRatings(RepositoryEntryRow row, RepositoryEntry entry) { + CommentAndRatingService commentAndRatingService = (CommentAndRatingService) CoreSpringFactory.getBean(CommentAndRatingService.class); + commentAndRatingService.init(getIdentity(), entry.getOlatResource(), null, false, false); + UserRating rating = userRatingsDao.getRating(getIdentity(), row.getOLATResourceable(), null); + float ratingValue = rating != null ? rating.getRating() : 0.0f; + RatingWithAverageFormItem ratingCmp = new RatingWithAverageFormItem("rat_" + row.getKey(), ratingValue, 4, 5, 32); + row.setRatingFormItem(ratingCmp); + ratingCmp.setUserObject(row); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/list/CatalogEntryListController.java b/src/main/java/org/olat/repository/ui/list/CatalogEntryListController.java new file mode 100644 index 0000000000000000000000000000000000000000..047eb1a82d26af9a952ef148fc3e0084640f5a80 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/CatalogEntryListController.java @@ -0,0 +1,46 @@ +/** + * <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.repository.ui.list; + +import java.util.List; + +import org.olat.catalog.CatalogEntry; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.WindowControl; + +/** + * + * Initial date: 21.11.2012<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CatalogEntryListController extends AbstractRepositoryEntryListController { + + public CatalogEntryListController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + setDataSource(new CategoriesDataSource(null, getIdentity(), this)); + initForm(ureq); + } + + public void setCatalogEntries(List<CatalogEntry> entries) { + setDataSource(new CategoriesDataSource(entries, getIdentity(), this)); + } +} diff --git a/src/main/java/org/olat/repository/ui/list/CatalogNodeController.java b/src/main/java/org/olat/repository/ui/list/CatalogNodeController.java new file mode 100644 index 0000000000000000000000000000000000000000..1560678bf43ac70e2ae425a1726f705f7fd83585 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/CatalogNodeController.java @@ -0,0 +1,313 @@ +/** + * <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.repository.ui.list; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.olat.basesecurity.BaseSecurityManager; +import org.olat.catalog.CatalogEntry; +import org.olat.catalog.CatalogManager; +import org.olat.catalog.ui.CatalogEntryComparator; +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.panel.MainPanel; +import org.olat.core.gui.components.stack.StackedController; +import org.olat.core.gui.components.stack.StackedControllerAware; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; +import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.helpers.Settings; +import org.olat.core.id.Identity; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.id.context.StateEntry; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.core.util.mail.ContactList; +import org.olat.core.util.mail.ContactMessage; +import org.olat.core.util.resource.OresHelper; +import org.olat.modules.co.ContactFormController; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; +import org.olat.repository.RepositoryTableModel; +import org.olat.repository.SearchRepositoryEntryParameters; +import org.olat.repository.controllers.RepositorySearchController; + +/** + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CatalogNodeController extends BasicController implements Activateable2, StackedControllerAware { + + private StackedController stackPanel; + private CatalogEntryListController entryListController; + + private final VelocityContainer mainVC; + private Link contactLink; + + private CloseableModalController cmc; + private ContactFormController contactCtrl; + private CatalogNodeController childNodeController; + private RepositorySearchController searchResourceCtrl; + + private CatalogEntry catalogEntry; + + private final CatalogManager cm; + private final RepositoryManager repositoryManager; + + public CatalogNodeController(UserRequest ureq, WindowControl wControl, CatalogEntry catalogEntry) { + // fallback translator to repository package to reduce redundant translations + super(ureq, wControl, Util.createPackageTranslator(RepositoryManager.class, ureq.getLocale())); + + cm = CatalogManager.getInstance(); + repositoryManager = CoreSpringFactory.getImpl(RepositoryManager.class); + + this.catalogEntry = catalogEntry; + + mainVC = createVelocityContainer("node"); + + //catalog resources + entryListController = new CatalogEntryListController(ureq, wControl); + mainVC.put("entries", entryListController.getInitialComponent()); + listenTo(entryListController); + + + MainPanel mainPanel = new MainPanel("myCoursesMainPanel"); + mainPanel.setContent(mainVC); + putInitialPanel(mainPanel); + updateContent(ureq); + } + + @Override + public void setStackedController(StackedController stackPanel) { + this.stackPanel = stackPanel; + } + + @Override + public void event(UserRequest ureq, Component source, Event event) { + if(source == contactLink) { + doContactOwners(ureq); + } else if(source instanceof Link) { + Link link = (Link)source; + if("select_node".equals(link.getCommand())) { + Long categoryNodeKey = (Long)link.getUserObject(); + CatalogEntry entry = cm.getCatalogEntryByKey(categoryNodeKey); + if(entry != null && entry.getType() == CatalogEntry.TYPE_NODE) { + removeAsListenerAndDispose(childNodeController); + childNodeController = new CatalogNodeController(ureq, getWindowControl(), entry); + listenTo(childNodeController); + childNodeController.setStackedController(stackPanel); + stackPanel.pushController(entry.getName(), childNodeController); + } + } + } + } + + /** + * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, + * org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event) + */ + @Override + public void event(UserRequest ureq, Controller source, Event event) { + if(source == searchResourceCtrl) { + if (event.getCommand().equals(RepositoryTableModel.TABLE_ACTION_SELECT_LINK)) { + addResource(searchResourceCtrl.getSelectedEntry()); + updateGUI(ureq); + } + cmc.deactivate(); + cleanUp(); + //add/remove owners + } else if(source == contactCtrl) { + cmc.deactivate(); + cleanUp(); + } else if(source == childNodeController) { + if(event == Event.DONE_EVENT) { + stackPanel.popController(childNodeController); + removeAsListenerAndDispose(childNodeController); + childNodeController = null; + updateGUI(ureq); + } else if(event == Event.CHANGED_EVENT) { + updateGUI(ureq); + } + } else if(source == entryListController) { + if(event == Event.CHANGED_EVENT) { + updateGUI(ureq); + } + } else if(source == cmc) { + cleanUp(); + } else { + super.event(ureq, source, event); + } + } + + private void cleanUp() { + removeAsListenerAndDispose(cmc); + removeAsListenerAndDispose(contactCtrl); + removeAsListenerAndDispose(searchResourceCtrl); + + cmc = null; + contactCtrl = null; + searchResourceCtrl = null; + } + + /** + * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) + */ + protected void doDispose() { + // + } + + private void doContactOwners(UserRequest ureq) { + ContactList caretaker = new ContactList(translate("contact.to.groupname.caretaker")); + List<Identity> owners = cm.getOwnersOfParentLine(catalogEntry); + caretaker.addAllIdentites(owners); + ContactMessage cmsg = new ContactMessage(getIdentity()); + cmsg.addEmailTo(caretaker); + contactCtrl = new ContactFormController(ureq, getWindowControl(), false, true, false, false, cmsg); + listenTo(contactCtrl); + + cmc = new CloseableModalController(getWindowControl(), "close", contactCtrl.getInitialComponent(), true, translate("contact.caretaker")); + listenTo(cmc); + cmc.activate(); + } + + private void addResource(RepositoryEntry re) { + CatalogEntry newCatalogEntry = cm.createCatalogEntry(); + newCatalogEntry.setName(re.getDisplayname()); + newCatalogEntry.setDescription(re.getDescription()); + newCatalogEntry.setRepositoryEntry(re); + newCatalogEntry.setType(CatalogEntry.TYPE_LEAF); + newCatalogEntry.setOwnerGroup(BaseSecurityManager.getInstance().createAndPersistSecurityGroup()); + cm.addCatalogEntry(catalogEntry, newCatalogEntry); + cm.saveCatalogEntry(newCatalogEntry); + } + + /** + * refresh content of current category for displaying + * + * @param ce + * @param ceLevel + */ + private void updateGUI(UserRequest ureq) { + updateContent(ureq); + updateHistory(ureq); + } + + private void updateContent(UserRequest ureq) { + mainVC.contextPut("catalogEntryName", catalogEntry.getName()); + if(StringHelper.containsNonWhitespace(catalogEntry.getDescription())) { + mainVC.contextPut("catalogEntryDesc", catalogEntry.getDescription()); + } + + List<CatalogEntry> childCe = cm.getChildrenOf(catalogEntry); + // Sort to fix ordering by repo entry display name. For leafs the displayed + // name is not the catalog entry name but the repo entry display name. The + // SQL query orders by catalog entry name, thus the visual ordering is + // wrong. + Collections.sort(childCe, new CatalogEntryComparator(getLocale())); + + List<Long> repositoryEntryKeys = new ArrayList<Long>(); + List<Link> subCategories = new ArrayList<Link>(); + for (CatalogEntry entry : childCe) { + if(entry.getType() == CatalogEntry.TYPE_NODE) { + String cmpId = "cat_" + entry.getKey(); + Link link = LinkFactory.createCustomLink(cmpId, "select_node", cmpId, Link.LINK + Link.NONTRANSLATED, mainVC, this); + link.setCustomDisplayText(entry.getName()); + link.setCustomEnabledLinkCSS("b_with_small_icon_left o_catalog_sub_icon"); + link.setUserObject(entry.getKey()); + subCategories.add(link); + } else if(entry.getRepositoryEntry() != null && entry.getRepositoryEntry().getOlatResource() != null) { + repositoryEntryKeys.add(entry.getRepositoryEntry().getKey()); + } + } + boolean hasEntries = subCategories.size() != childCe.size(); + mainVC.getComponent("entries").setVisible(hasEntries); + mainVC.contextPut("subCategories", subCategories); + + if(!repositoryEntryKeys.isEmpty()) { + SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters(); + params.setIdentity(getIdentity()); + params.setRoles(ureq.getUserSession().getRoles()); + params.setRepositoryEntryKeys(repositoryEntryKeys); + List<RepositoryEntry> allowedEntries = repositoryManager.genericANDQueryWithRolesRestriction(params, 0, -1, false); + + List<CatalogEntry> catalogEntriesOfRepo = new ArrayList<CatalogEntry>(childCe); + for(Iterator<CatalogEntry> it=catalogEntriesOfRepo.iterator(); it.hasNext(); ) { + RepositoryEntry catRepoEntry = it.next().getRepositoryEntry(); + if(catRepoEntry == null || !allowedEntries.contains(catRepoEntry)) { + it.remove(); + } + } + + entryListController.setCatalogEntries(catalogEntriesOfRepo); + } + + String url = Settings.getServerContextPathURI() + "/url/CatalogEntry/" + catalogEntry.getKey(); + mainVC.contextPut("guestExtLink", url + "?guest=true&lang=" + getLocale().getLanguage()); + if (!ureq.getUserSession().getRoles().isGuestOnly()) { + mainVC.contextPut("extLink", url); + } + } + + public void updateHistory(UserRequest ureq) { + if(catalogEntry != null) { + OLATResourceable ores = OresHelper.createOLATResourceableInstance(CatalogEntry.class, catalogEntry.getKey()); + addToHistory(ureq, ores, null); + } else { + addToHistory(ureq); + } + } + + @Override + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { + if(entries == null || entries.isEmpty()) return; + + } + + public class PriceMethod { + private String price; + private String type; + + public PriceMethod(String price, String type) { + this.price = price; + this.type = type; + } + + public String getPrice() { + return price; + } + + public String getType() { + return type; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/list/CategoriesDataSource.java b/src/main/java/org/olat/repository/ui/list/CategoriesDataSource.java new file mode 100644 index 0000000000000000000000000000000000000000..3e0af1cb51107994bab2cd1a349d912dae2737f3 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/CategoriesDataSource.java @@ -0,0 +1,71 @@ +/** + * <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.repository.ui.list; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.olat.catalog.CatalogEntry; +import org.olat.core.commons.persistence.DefaultResultInfos; +import org.olat.core.commons.persistence.ResultInfos; +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.id.Identity; +import org.olat.repository.RepositoryEntry; + +/** + * + * Initial date: 29.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class CategoriesDataSource extends AbstractRepositoryEntryDataSource { + + private final List<CatalogEntry> entries; + + public CategoriesDataSource(List<CatalogEntry> entries, Identity identity, + RepositoryEntryDataSourceUIFactory uifactory) { + super(identity, uifactory); + this.entries = entries; + } + + @Override + protected int getNumOfRepositoryEntries() { + return entries == null ? 0 : entries.size(); + } + + @Override + public List<RepositoryEntryRow> reload(List<RepositoryEntryRow> rows) { + return Collections.emptyList(); + } + + @Override + public ResultInfos<RepositoryEntryRow> getRows(String query, List<String> condQueries, int firstResult, int maxResults, + SortKey... orderBy) { + + List<RepositoryEntry> repoEntries = new ArrayList<>(maxResults); + for(int i=firstResult; i<maxResults && i<getNumOfRepositoryEntries(); i++) { + CatalogEntry entry = entries.get(i); + repoEntries.add(entry.getRepositoryEntry()); + } + List<RepositoryEntryRow> rows = processModel(repoEntries); + return new DefaultResultInfos<RepositoryEntryRow>(firstResult + rows.size(), -1, rows); + } +} diff --git a/src/main/java/org/olat/repository/ui/list/FavoritRepositoryEntryDataSource.java b/src/main/java/org/olat/repository/ui/list/FavoritRepositoryEntryDataSource.java new file mode 100644 index 0000000000000000000000000000000000000000..418f86e5d822c0eafff36fba1f2f8563583cbf0c --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/FavoritRepositoryEntryDataSource.java @@ -0,0 +1,70 @@ +/** + * <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.repository.ui.list; + +import java.util.Collections; +import java.util.List; + +import org.olat.core.commons.persistence.DefaultResultInfos; +import org.olat.core.commons.persistence.ResultInfos; +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.id.Identity; +import org.olat.core.id.Roles; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.SearchRepositoryEntryParameters; + +/** + * + * Initial date: 29.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class FavoritRepositoryEntryDataSource extends AbstractRepositoryEntryDataSource { + + private final Roles roles; + + public FavoritRepositoryEntryDataSource(Identity identity, Roles roles, RepositoryEntryDataSourceUIFactory uifactory) { + super(identity, uifactory); + this.roles = roles; + } + + @Override + protected int getNumOfRepositoryEntries() { + SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters(getIdentity(), roles, "CourseModule"); + params.setMarked(Boolean.TRUE); + return repositoryManager.countGenericANDQueryWithRolesRestriction(params); + } + + @Override + public List<RepositoryEntryRow> reload(List<RepositoryEntryRow> rows) { + return Collections.emptyList(); + } + + @Override + public ResultInfos<RepositoryEntryRow> getRows(String query, List<String> condQueries, int firstResult, int maxResults, + SortKey... orderBy) { + + SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters(getIdentity(), roles, "CourseModule"); + params.setMarked(Boolean.TRUE); + List<RepositoryEntry> repoEntries = repositoryManager.genericANDQueryWithRolesRestriction(params, firstResult, maxResults, true); + List<RepositoryEntryRow> rows = processModel(repoEntries); + return new DefaultResultInfos<RepositoryEntryRow>(firstResult + rows.size(), -1, rows); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/list/FavoritRepositoryEntryListController.java b/src/main/java/org/olat/repository/ui/list/FavoritRepositoryEntryListController.java new file mode 100644 index 0000000000000000000000000000000000000000..8678ef0f1def6a83ac1b5361685d22beeb0ad771 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/FavoritRepositoryEntryListController.java @@ -0,0 +1,49 @@ +/** + * <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.repository.ui.list; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.id.Roles; + +/** + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class FavoritRepositoryEntryListController extends AbstractRepositoryEntryListController { + + private final Roles roles; + + public FavoritRepositoryEntryListController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + roles = ureq.getUserSession().getRoles(); + + FavoritRepositoryEntryDataSource dataSource = new FavoritRepositoryEntryDataSource(getIdentity(), roles, this); + setDataSource(dataSource); + + initForm(ureq); + } + + protected boolean updateMarkedEntries() { + return getDataSource().getRowCount() > 0; + } +} diff --git a/src/main/java/org/olat/repository/ui/list/MyCoursesMainController.java b/src/main/java/org/olat/repository/ui/list/MyCoursesMainController.java new file mode 100644 index 0000000000000000000000000000000000000000..279990d937bc29e414811e67a6630fb42634ceb2 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/MyCoursesMainController.java @@ -0,0 +1,77 @@ +/** + * <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.repository.ui.list; + +import java.util.List; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.panel.MainPanel; +import org.olat.core.gui.components.stack.StackedController; +import org.olat.core.gui.components.stack.StackedControllerImpl; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.MainLayoutBasicController; +import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.id.context.StateEntry; + +/** + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MyCoursesMainController extends MainLayoutBasicController implements Activateable2 { + + private final MainPanel mainPanel; + private final StackedController stackPanel; + private final OverviewRepositoryListController overviewCtrl; + + public MyCoursesMainController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + mainPanel = new MainPanel("myCoursesMainPanel"); + + overviewCtrl = new OverviewRepositoryListController(ureq, wControl); + listenTo(overviewCtrl); + stackPanel = new StackedControllerImpl(getWindowControl(), getTranslator(), "o_courses_breadcrumbs"); + listenTo(stackPanel); + stackPanel.pushController("Kurse", overviewCtrl); + overviewCtrl.setStackedController(stackPanel); + mainPanel.setContent(stackPanel.getInitialComponent()); + putInitialPanel(stackPanel.getInitialComponent()); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } + + @Override + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { + overviewCtrl.activate(ureq, entries, state); + } +} diff --git a/src/main/java/org/olat/repository/ui/list/OverviewRepositoryListController.java b/src/main/java/org/olat/repository/ui/list/OverviewRepositoryListController.java new file mode 100644 index 0000000000000000000000000000000000000000..dc550bf04e976e831b42b9372791023923c0b41d --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/OverviewRepositoryListController.java @@ -0,0 +1,157 @@ +/** + * <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.repository.ui.list; + +import java.util.List; + +import org.olat.catalog.CatalogEntry; +import org.olat.catalog.CatalogManager; +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.panel.MainPanel; +import org.olat.core.gui.components.segmentedview.SegmentViewComponent; +import org.olat.core.gui.components.segmentedview.SegmentViewEvent; +import org.olat.core.gui.components.segmentedview.SegmentViewFactory; +import org.olat.core.gui.components.stack.StackedController; +import org.olat.core.gui.components.stack.StackedControllerAware; +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.control.generic.dtabs.Activateable2; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.id.context.StateEntry; +import org.olat.core.util.Util; +import org.olat.repository.RepositoryManager; + +/** + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class OverviewRepositoryListController extends BasicController implements StackedControllerAware, Activateable2 { + + private MainPanel mainPanel; + private final VelocityContainer mainVC; + private final SegmentViewComponent segmentView; + private final Link favoriteLink, myCourseLink, catalogLink; + + private FavoritRepositoryEntryListController markedCtrl; + private RepositoryEntryListController myCoursesCtrl; + private CatalogNodeController catalogCtrl; + private StackedController stackPanel; + + private CatalogManager catalogManager; + + public OverviewRepositoryListController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + setTranslator(Util.createPackageTranslator(RepositoryManager.class, getLocale(), getTranslator())); + + catalogManager = CoreSpringFactory.getImpl(CatalogManager.class); + + mainPanel = new MainPanel("myCoursesMainPanel"); + mainVC = createVelocityContainer("overview"); + mainPanel.setContent(mainVC); + + boolean hasMarkedEntries = doOpenMark(ureq); + if(!hasMarkedEntries) { + doOpenMyCourses(ureq); + } + segmentView = SegmentViewFactory.createSegmentView("segments", mainVC, this); + favoriteLink = LinkFactory.createLink("search.mark", mainVC, this); + segmentView.addSegment(favoriteLink, hasMarkedEntries); + myCourseLink = LinkFactory.createLink("search.mycourses.student", mainVC, this); + segmentView.addSegment(myCourseLink, !hasMarkedEntries); + catalogLink = LinkFactory.createLink("search.catalog", mainVC, this); + segmentView.addSegment(catalogLink, false); + + putInitialPanel(mainPanel); + } + + @Override + public void setStackedController(StackedController stackPanel) { + this.stackPanel = stackPanel; + } + + @Override + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { + // + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(source == segmentView) { + if(event instanceof SegmentViewEvent) { + SegmentViewEvent sve = (SegmentViewEvent)event; + String segmentCName = sve.getComponentName(); + Component clickedLink = mainVC.getComponent(segmentCName); + if (clickedLink == favoriteLink) { + doOpenMark(ureq); + } else if (clickedLink == myCourseLink) { + doOpenMyCourses(ureq); + } else if (clickedLink == catalogLink) { + doOpenCatalog(ureq); + } + } + } + } + + private boolean doOpenMark(UserRequest ureq) { + boolean hasMarkedEntries = true; + if(markedCtrl == null) { + markedCtrl = new FavoritRepositoryEntryListController(ureq, getWindowControl()); + hasMarkedEntries = markedCtrl.updateMarkedEntries(); + listenTo(markedCtrl); + } + mainVC.put("segmentCmp", markedCtrl.getInitialComponent()); + return hasMarkedEntries; + } + + private void doOpenMyCourses(UserRequest ureq) { + if(myCoursesCtrl == null) { + myCoursesCtrl = new RepositoryEntryListController(ureq, getWindowControl()); + listenTo(myCoursesCtrl); + } + mainVC.put("segmentCmp", myCoursesCtrl.getInitialComponent()); + } + + private void doOpenCatalog(UserRequest ureq) { + if(catalogCtrl == null) { + List<CatalogEntry> entries = catalogManager.getRootCatalogEntries(); + CatalogEntry rootEntry = null; + if(entries.size() > 0) { + rootEntry = entries.get(0); + } + catalogCtrl = new CatalogNodeController(ureq, getWindowControl(), rootEntry); + catalogCtrl.setStackedController(stackPanel); + listenTo(catalogCtrl); + } + mainVC.put("segmentCmp", catalogCtrl.getInitialComponent()); + } +} diff --git a/src/main/java/org/olat/repository/ui/list/RepositoryEntryAsParticipantDataSource.java b/src/main/java/org/olat/repository/ui/list/RepositoryEntryAsParticipantDataSource.java new file mode 100644 index 0000000000000000000000000000000000000000..754ca1a6fb82d2f5a2d5c0f5b78713769d4dc5fb --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/RepositoryEntryAsParticipantDataSource.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.repository.ui.list; + +import java.util.Collections; +import java.util.List; + +import org.olat.core.commons.persistence.DefaultResultInfos; +import org.olat.core.commons.persistence.ResultInfos; +import org.olat.core.commons.persistence.SortKey; +import org.olat.core.id.Identity; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryEntryOrder; + +/** + * + * Initial date: 29.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RepositoryEntryAsParticipantDataSource extends AbstractRepositoryEntryDataSource { + + public RepositoryEntryAsParticipantDataSource(Identity identity, RepositoryEntryDataSourceUIFactory uifactory) { + super(identity, uifactory); + } + + @Override + protected int getNumOfRepositoryEntries() { + long start = System.nanoTime(); + int n = repositoryManager.countLearningResourcesAsStudent(getIdentity()); + System.out.println("Count takes (ms): " + ((System.nanoTime() - start) / 1000000)); + return n; + } + + @Override + public List<RepositoryEntryRow> reload(List<RepositoryEntryRow> rows) { + return Collections.emptyList(); + } + + @Override + public ResultInfos<RepositoryEntryRow> getRows(String query, List<String> condQueries, + int firstResult, int maxResults, SortKey... orderBy) { + + List<RepositoryEntry> repoEntries = repositoryManager + .getLearningResourcesAsStudent(getIdentity(), firstResult, maxResults, RepositoryEntryOrder.nameDesc); + List<RepositoryEntryRow> rows = processModel(repoEntries); + return new DefaultResultInfos<RepositoryEntryRow>(firstResult + rows.size(), -1, rows); + } +} diff --git a/src/main/java/org/olat/repository/ui/list/RepositoryEntryDataModel.java b/src/main/java/org/olat/repository/ui/list/RepositoryEntryDataModel.java new file mode 100644 index 0000000000000000000000000000000000000000..81a482765f97a38d526a7901d449102bd477983e --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/RepositoryEntryDataModel.java @@ -0,0 +1,89 @@ +/** + * <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.repository.ui.list; + +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataSourceModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate; + +/** + * + * Initial date: 29.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RepositoryEntryDataModel extends DefaultFlexiTableDataSourceModel<RepositoryEntryRow> { + + public RepositoryEntryDataModel(FlexiTableDataSourceDelegate<RepositoryEntryRow> source, FlexiTableColumnModel columnModel) { + super(source, columnModel); + } + + @Override + public DefaultFlexiTableDataSourceModel<RepositoryEntryRow> createCopyWithEmptyList() { + return new RepositoryEntryDataModel(getSourceDelegate(), getTableColumnModel()); + } + + @Override + public Object getValueAt(int row, int col) { + RepositoryEntryRow item = getObject(row); + if(item == null) { + return null;//don't break here + } + + switch(Cols.values()[col]) { + case key: return item.getKey(); + case displayName: return item.getDisplayName(); + case lifecycleLabel: return item.getLifecycle(); + case lifecycleSoftkey: return item.getLifecycleSoftKey(); + case lifecycleStart: return item.getLifecycleStart(); + case lifecycleEnd: return item.getLifecycleEnd(); + case mark: return item.getMarkLink(); + case select: return item.getSelectLink(); + case start: return item.getStartLink(); + case details: return item.getDetailsLink(); + case ratings: return item.getRatingFormItem(); + } + return null; + } + + public enum Cols { + key("table.header.key"), + displayName("cif.displayname"), + lifecycleLabel("table.header.lifecycle.label"), + lifecycleSoftkey("table.header.lifecycle.softkey"), + lifecycleStart("table.header.lifecycle.start"), + lifecycleEnd("table.header.lifecycle.end"), + details("table.header.details"), + select("table.header.details"), + start("table.header.start"), + mark("table.header.mark"), + ratings("ratings"); + + private final String i18nKey; + + private Cols(String i18nKey) { + this.i18nKey = i18nKey; + } + + public String i18nKey() { + return i18nKey; + } + } +} diff --git a/src/main/java/org/olat/repository/ui/list/RepositoryEntryDataSourceUIFactory.java b/src/main/java/org/olat/repository/ui/list/RepositoryEntryDataSourceUIFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..14b62a4a837dca89b2578df6b21da8de545a9d32 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/RepositoryEntryDataSourceUIFactory.java @@ -0,0 +1,46 @@ +/** + * <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.repository.ui.list; + +import org.olat.repository.RepositoryEntry; + +/** + * + * Delegate to the controller the job of forgeing the links and the mapperUrl. + * + * Initial date: 29.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface RepositoryEntryDataSourceUIFactory { + + public String getMapperThumbnailUrl(); + + public void forgeMarkLink(RepositoryEntryRow row); + + public void forgeSelectLink(RepositoryEntryRow row); + + public void forgeStartLink(RepositoryEntryRow row); + + public void forgeDetailsLink(RepositoryEntryRow row); + + public void forgeRatings(RepositoryEntryRow row, RepositoryEntry entry); + +} diff --git a/src/main/java/org/olat/repository/ui/list/RepositoryEntryListController.java b/src/main/java/org/olat/repository/ui/list/RepositoryEntryListController.java new file mode 100644 index 0000000000000000000000000000000000000000..3e79c23b0df978024f8d5cddae39015e5a65e5a7 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/RepositoryEntryListController.java @@ -0,0 +1,41 @@ +/** + * <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.repository.ui.list; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.WindowControl; + +/** + * + * Initial date: 28.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RepositoryEntryListController extends AbstractRepositoryEntryListController { + + public RepositoryEntryListController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + RepositoryEntryAsParticipantDataSource dataSource = new RepositoryEntryAsParticipantDataSource(getIdentity(), this); + setDataSource(dataSource); + initForm(ureq); + } + +} \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/list/RepositoryEntryRow.java b/src/main/java/org/olat/repository/ui/list/RepositoryEntryRow.java new file mode 100644 index 0000000000000000000000000000000000000000..710ee0aeb7af62f8f5790f5d40d353488e254eed --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/RepositoryEntryRow.java @@ -0,0 +1,304 @@ +/** + * <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.repository.ui.list; + +import java.util.Date; +import java.util.List; + +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.rating.RatingWithAverageFormItem; +import org.olat.core.id.OLATResourceable; +import org.olat.core.util.StringHelper; +import org.olat.repository.ui.PriceMethod; + +/** + * + * Initial date: 29.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class RepositoryEntryRow { + private boolean marked; + private boolean selected; + + private Long key; + private String name; + private String author; + private String description; + private String thumbnailRelPath; + + private String score; + private Boolean passed; + + public int visit; + public long timeSpend; + public Date initialLaunch; + public Date recentLaunch; + + private String lifecycle; + private String lifecycleSoftKey; + private Date lifecycleStart; + private Date lifecycleEnd; + + private List<PriceMethod> accessTypes; + + private FormLink markLink; + private FormLink selectLink; + private FormLink startLink; + private FormLink detailsLink; + + private OLATResourceable olatResource; + private RatingWithAverageFormItem ratingFormItem; + + public RepositoryEntryRow() { + // + } + + public String getCssClass() { + return "o_CourseModule_icon"; + } + + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + public String getDisplayName() { + return name; + } + + public void setDisplayName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getLifecycle() { + return lifecycle; + } + + public void setLifecycle(String lifecycle) { + this.lifecycle = lifecycle; + } + + public String getLifecycleSoftKey() { + return lifecycleSoftKey; + } + + public void setLifecycleSoftKey(String lifecycleSoftKey) { + this.lifecycleSoftKey = lifecycleSoftKey; + } + + public Date getLifecycleStart() { + return lifecycleStart; + } + + public void setLifecycleStart(Date lifecycleStart) { + this.lifecycleStart = lifecycleStart; + } + + public Date getLifecycleEnd() { + return lifecycleEnd; + } + + public void setLifecycleEnd(Date lifecycleEnd) { + this.lifecycleEnd = lifecycleEnd; + } + + public List<PriceMethod> getAccessTypes() { + return accessTypes; + } + + public void setAccessTypes(List<PriceMethod> accessTypes) { + this.accessTypes = accessTypes; + } + + public String getSelectLinkName() { + return selectLink.getComponent().getComponentName(); + } + + public FormLink getSelectLink() { + return selectLink; + } + + public void setSelectLink(FormLink selectLink) { + this.selectLink = selectLink; + } + + public String getStartLinkName() { + return startLink.getComponent().getComponentName(); + } + + public FormLink getStartLink() { + return startLink; + } + + public void setStartLink(FormLink startLink) { + this.startLink = startLink; + } + + public String getDetailsLinkName() { + return detailsLink.getComponent().getComponentName(); + } + + public FormLink getDetailsLink() { + return detailsLink; + } + + public void setDetailsLink(FormLink detailsLink) { + this.detailsLink = detailsLink; + } + + public FormLink getMarkLink() { + return markLink; + } + + public String getMarkLinkName() { + if(markLink != null) { + return markLink.getComponent().getComponentName(); + } + return null; + } + + public void setMarkLink(FormLink markLink) { + this.markLink = markLink; + } + + public String getRatingFormItemName() { + return ratingFormItem.getComponent().getComponentName(); + } + + public RatingWithAverageFormItem getRatingFormItem() { + return ratingFormItem; + } + + public void setRatingFormItem(RatingWithAverageFormItem ratingFormItem) { + this.ratingFormItem = ratingFormItem; + } + + /** + * This is a clone of the repositoryEntry.getOLATResource(); + * @return + */ + public OLATResourceable getOLATResourceable() { + return olatResource; + } + + public void setOLATResourceable(OLATResourceable olatResource) { + this.olatResource = olatResource; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getThumbnailRelPath() { + return thumbnailRelPath; + } + + public void setThumbnailRelPath(String path) { + this.thumbnailRelPath = path; + } + + public boolean isThumbnailAvailable() { + return StringHelper.containsNonWhitespace(thumbnailRelPath); + } + + public boolean isMarked() { + return marked; + } + + public void setMarked(boolean marked) { + this.marked = marked; + } + + public boolean isSelected() { + return selected; + } + + public void setSelected(boolean selected) { + this.selected = selected; + } + + public String getScore() { + return score; + } + + public void setScore(String score) { + this.score = score; + } + + public boolean isPassed() { + return passed != null && passed.booleanValue(); + } + + public void setPassed(Boolean passed) { + this.passed = passed; + } + + public boolean isFailed() { + return passed != null && !passed.booleanValue(); + } + + public int getVisit() { + return visit; + } + + public void setVisit(int visit) { + this.visit = visit; + } + + public long getTimeSpend() { + return timeSpend; + } + + public void setTimeSpend(long timeSpend) { + this.timeSpend = timeSpend; + } + + public Date getInitialLaunch() { + return initialLaunch; + } + + public void setInitialLaunch(Date initialLaunch) { + this.initialLaunch = initialLaunch; + } + + public Date getRecentLaunch() { + return recentLaunch; + } + + public void setRecentLaunch(Date recentLaunch) { + this.recentLaunch = recentLaunch; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/list/_content/node.html b/src/main/java/org/olat/repository/ui/list/_content/node.html new file mode 100644 index 0000000000000000000000000000000000000000..3e17ae0afaad4c97b7ec44f89099ef6296ef0fc0 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/_content/node.html @@ -0,0 +1,16 @@ +<div class="o_catalog"> + <fieldset> + <legend>$catalogEntryName</legend> + #if($catalogEntryDesc) + <i>$catalogEntryDesc</i> + #end + #if($subCategories.size != 0) + <div class="o_catalog_itemlist"> + #foreach($subCategory in $subCategories) + $r.render($subCategory.componentName), + #end + </div> + #end + </fieldset> +</div> +$r.render("entries") diff --git a/src/main/java/org/olat/repository/ui/list/_content/overview.html b/src/main/java/org/olat/repository/ui/list/_content/overview.html new file mode 100644 index 0000000000000000000000000000000000000000..94c1c0ab3da2ef1d638f32497494d46e16d22b38 --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/_content/overview.html @@ -0,0 +1,4 @@ +<div class="b_clearfix"> + $r.render("segments")<br/> + $r.render("segmentCmp") +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/list/_content/repoentry_table.html b/src/main/java/org/olat/repository/ui/list/_content/repoentry_table.html new file mode 100644 index 0000000000000000000000000000000000000000..01996d44603777f601e0888ed3e2e88c68865b7f --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/_content/repoentry_table.html @@ -0,0 +1,5 @@ +<div class="o_buttons_box_right"> + $r.render("switchLayoutList") + $r.render("switchLayoutTable") +</div> +$r.render("table") \ No newline at end of file diff --git a/src/main/java/org/olat/repository/ui/list/_content/row_1.html b/src/main/java/org/olat/repository/ui/list/_content/row_1.html new file mode 100644 index 0000000000000000000000000000000000000000..fe28d778d62d31b5476dc06f31fa70e7cda65e0d --- /dev/null +++ b/src/main/java/org/olat/repository/ui/list/_content/row_1.html @@ -0,0 +1,77 @@ +<div class="b_clearfix o_table_rowline"> +<div class="f_item #if($row.selected) f_item_selected #end"> + <div class="f_metadata b_clearfix"> + <div class="f_thumbnail"> + #if($row.isThumbnailAvailable()) + <div class="f_thumbnail_inner f_thumbnail_available" style="width:280px; height:158px; float:left; background:transparent url('${row.getThumbnailRelPath()}') no-repeat 50% 50%;"> </div> + #else + <div class="f_thumbnail_inner f_thumbnail_unavailable" style=""> </div> + #end + </div> + <div class="f_metadata_text"> + <div class="f_metadata_text_inner"> + <h4>$r.render($row.getSelectLinkName())</h4> + #if($row.author) + $row.author<br/> + #end + #if($row.lifecycle || $row.lifecycleSoftKey || $row.lifecycleStart || $row.lifecycleEnd) + <div class="f_metadata_lifecycle"> + <p> + #if($row.lifecycle) $row.lifecycle #end + #if($row.lifecycleSoftKey) $row.lifecycleSoftKey #end + #if($row.lifecycleStart) $r.formatDateAndTime($row.lifecycleStart) #end + #if($row.lifecycleEnd) - $r.formatDateAndTime($row.lifecycleEnd) #end + </p> + </div> + #end + <p>$row.description</p> + + + </div> + </div> + <div class="f_metadata_additional_infos"> + <div class="f_metadata_additional_infos_inner"> + <div class="f_metadata_mark">$r.render($row.markLinkName)</div> + + #if($r.get("ac_$item.key")) + #foreach($ac_type in $r.get("ac_$item.key")) + #if($ac_type.price && $ac_type.price.length() > 0) + <span class='b_float_right b_with_small_icon_left $ac_type.type'>$ac_type.price</span> + #else + <span class='b_float_right b_small_icon $ac_type.type'></span> + #end + #end + $r.render($row.getSelectLinkName()) + #end + + #if($row.passed) + $r.translate("passed.true") + #elseif($item.failed) + $r.translate("passed.false") + #end + #if($row.score) <span>/ $row.score</span> #end + + #if($row.recentLaunch) + $r.formatDateAndTime($row.recentLaunch)<br/> + #end + + #if($row.accessTypes) + $r.translate("details.orders"): + #foreach($type in $row.accessTypes) + <span class="$type.type b_access_method"> </span> + #end + #end + + $r.render($row.ratingFormItemName) + + <div class="f_metadata_details"> + $r.render($row.getDetailsLinkName()) + </div> + <div class="f_metadata_start"> + $r.render($row.getStartLinkName()) + </div> + </div> + </div> + </div> +</div> +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml b/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml index 0db01a0526f7f674dbfe12ff40ca9235844b1c50..cfa2968de5c456b709aeb24d0d96865febee9a70 100644 --- a/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml +++ b/src/main/java/org/olat/resource/accesscontrol/_spring/acContext.xml @@ -71,13 +71,15 @@ <property name="factoryMethod" value="createOrdersController"/> </bean> </property> + <property name="navigationKey" value="booking" /> + <property name="iconCssClass" value="b_with_small_icon_left b_order_icon" /> <property name="securityCallbackClassName" value="org.olat.core.extensions.security.UserOnlyExtensionSecurityCallback" /> <property name="translationPackage" value="org.olat.home" /> <property name="i18nActionKey" value="menu.orders"/> <property name="i18nDescriptionKey" value="menu.orders.alt"/> <property name="extensionPoints"> <list> - <value>org.olat.home.HomeMainController</value> + <value>org.olat.home.HomeMainController</value> </list> </property> </bean> diff --git a/src/main/java/org/olat/restapi/repository/RepositoryEntriesResource.java b/src/main/java/org/olat/restapi/repository/RepositoryEntriesResource.java index b57024b896d66189a30e2fcae488a3d618152240..bf656934770e8af0e58d6fada71df7147549549f 100644 --- a/src/main/java/org/olat/restapi/repository/RepositoryEntriesResource.java +++ b/src/main/java/org/olat/restapi/repository/RepositoryEntriesResource.java @@ -184,7 +184,7 @@ public class RepositoryEntriesResource { } if(MediaTypeVariants.isPaged(httpRequest, request)) { - int totalCount = rm.countGenericANDQueryWithRolesRestriction(params, true); + int totalCount = rm.countGenericANDQueryWithRolesRestriction(params); List<RepositoryEntry> res = rm.genericANDQueryWithRolesRestriction(params, start, limit, true); RepositoryEntryVOes voes = new RepositoryEntryVOes(); voes.setRepositoryEntries(toArrayOfVOes(res)); diff --git a/src/main/java/org/olat/restapi/repository/course/CoursesInfosWebService.java b/src/main/java/org/olat/restapi/repository/course/CoursesInfosWebService.java index 4693d9f1e7b1bed71970c385f066513bea608a3c..7b65f8a352ede68a5bf131910da091a96bb15f43 100644 --- a/src/main/java/org/olat/restapi/repository/course/CoursesInfosWebService.java +++ b/src/main/java/org/olat/restapi/repository/course/CoursesInfosWebService.java @@ -109,7 +109,7 @@ public class CoursesInfosWebService { Identity identity = getIdentity(httpRequest); SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters(identity, roles, CourseModule.getCourseTypeName()); if(MediaTypeVariants.isPaged(httpRequest, request)) { - int totalCount = rm.countGenericANDQueryWithRolesRestriction(params, true); + int totalCount = rm.countGenericANDQueryWithRolesRestriction(params); List<RepositoryEntry> repoEntries = rm.genericANDQueryWithRolesRestriction(params, start, limit, true); List<CourseInfoVO> infos = new ArrayList<CourseInfoVO>(); diff --git a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java index 8933f13999a1f23323580b64d264ce99ae03272a..d2fdb7c9daa753074948586143368a12cb6d9ff4 100644 --- a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java +++ b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java @@ -158,7 +158,7 @@ public class CoursesWebService { } if(MediaTypeVariants.isPaged(httpRequest, request)) { - int totalCount = rm.countGenericANDQueryWithRolesRestriction(params, true); + int totalCount = rm.countGenericANDQueryWithRolesRestriction(params); List<RepositoryEntry> repoEntries = rm.genericANDQueryWithRolesRestriction(params, start, limit, true); CourseVO[] vos = toCourseVo(repoEntries); CourseVOes voes = new CourseVOes(); diff --git a/src/test/java/org/olat/core/commons/services/usercomments/UserRatingsDAOTest.java b/src/test/java/org/olat/core/commons/services/usercomments/UserRatingsDAOTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4a3633c278ff39ced0c4be939dd3f4b8d5529963 --- /dev/null +++ b/src/test/java/org/olat/core/commons/services/usercomments/UserRatingsDAOTest.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.core.commons.services.usercomments; + +import java.util.UUID; + +import junit.framework.Assert; + +import org.junit.Test; +import org.olat.core.commons.persistence.DB; +import org.olat.core.commons.services.commentAndRating.impl.UserRatingsDAO; +import org.olat.core.commons.services.commentAndRating.model.UserRating; +import org.olat.core.id.Identity; +import org.olat.core.id.OLATResourceable; +import org.olat.test.JunitTestHelper; +import org.olat.test.OlatTestCase; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Initial date: 31.01.2014<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class UserRatingsDAOTest extends OlatTestCase { + + @Autowired + private DB dbInstance; + @Autowired + private UserRatingsDAO userRatingsDao; + + @Test + public void createRating() { + OLATResourceable ores = JunitTestHelper.createRandomResource(); + Identity id = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-1-" + UUID.randomUUID().toString()); + dbInstance.commitAndCloseSession(); + + //create + UserRating newRating = userRatingsDao.createRating(id, ores, "test-1", 5); + dbInstance.commit(); + Assert.assertNotNull(newRating); + Assert.assertNotNull(newRating.getKey()); + Assert.assertNotNull(newRating.getCreationDate()); + Assert.assertNotNull(newRating.getLastModified()); + Assert.assertEquals(ores.getResourceableTypeName(), newRating.getResName()); + Assert.assertEquals(ores.getResourceableId(), newRating.getResId()); + Assert.assertEquals("test-1", newRating.getResSubPath()); + Assert.assertEquals(id, newRating.getCreator()); + Assert.assertEquals(new Integer(5), newRating.getRating()); + } + + @Test + public void createUpdateRating() { + OLATResourceable ores = JunitTestHelper.createRandomResource(); + Identity id = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-1-" + UUID.randomUUID().toString()); + dbInstance.commitAndCloseSession(); + + //create + UserRating newRating = userRatingsDao.createRating(id, ores, "test-2", 5); + dbInstance.commitAndCloseSession(); + + UserRating updatedRating = userRatingsDao.updateRating(newRating, 4); + dbInstance.commit(); + + Assert.assertNotNull(updatedRating); + Assert.assertEquals(newRating, updatedRating); + Assert.assertNotNull(updatedRating.getCreationDate()); + Assert.assertNotNull(updatedRating.getLastModified()); + Assert.assertEquals(ores.getResourceableTypeName(), updatedRating.getResName()); + Assert.assertEquals(ores.getResourceableId(), updatedRating.getResId()); + Assert.assertEquals("test-2", updatedRating.getResSubPath()); + Assert.assertEquals(id, updatedRating.getCreator()); + Assert.assertEquals(new Integer(4), updatedRating.getRating()); + } + +} diff --git a/src/test/java/org/olat/repository/RepositoryManagerQueryTest.java b/src/test/java/org/olat/repository/RepositoryManagerQueryTest.java index aceacc5ac475e1952ba02a5542c8d7c5dd29003a..c3398361dfa63e88ca8c49831a0129ec0f73ca67 100644 --- a/src/test/java/org/olat/repository/RepositoryManagerQueryTest.java +++ b/src/test/java/org/olat/repository/RepositoryManagerQueryTest.java @@ -245,7 +245,7 @@ public class RepositoryManagerQueryTest extends OlatTestCase { //test paging SearchRepositoryEntryParameters params = new SearchRepositoryEntryParameters(null, "kan", null, types, null, role4, "Volks"); List<RepositoryEntry> resultOneShootInstitut6 = rm.genericANDQueryWithRolesRestriction(params, 0, 50, true); - int resultOneShootInstitutTotal6 = rm.countGenericANDQueryWithRolesRestriction(params, true); + int resultOneShootInstitutTotal6 = rm.countGenericANDQueryWithRolesRestriction(params); assertNotNull(resultOneShootInstitut6); assertEquals(50, resultOneShootInstitut6.size()); //check diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java index d671a169be784879ddc598a56e23ff195b6d212e..f015bf8d4e0e1fa0cc579bbfbb9c76b7f745921f 100644 --- a/src/test/java/org/olat/test/AllTestsJunit4.java +++ b/src/test/java/org/olat/test/AllTestsJunit4.java @@ -150,6 +150,7 @@ import org.junit.runners.Suite; org.olat.test.SpringInitDestroyVerficationTest.class, //org.olat.course.statistic.weekly.TestWeeklyStatisticManager_fillGaps.class, don't know what it tests org.olat.core.commons.services.usercomments.UserCommentsTest.class, + org.olat.core.commons.services.usercomments.UserRatingsDAOTest.class, org.olat.core.commons.services.usercomments.UserRatingsTest.class, org.olat.course.auditing.UserNodeAuditManagerTest.class, org.olat.shibboleth.util.ShibbolethAttributeTest.class,