/** * <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.List; import org.olat.NewControllerFactory; import org.olat.core.commons.persistence.SortKey; import org.olat.core.commons.services.commentAndRating.CommentAndRatingDefaultSecurityCallback; import org.olat.core.commons.services.commentAndRating.CommentAndRatingSecurityCallback; import org.olat.core.commons.services.commentAndRating.manager.UserRatingsDAO; import org.olat.core.commons.services.commentAndRating.ui.UserCommentsController; import org.olat.core.commons.services.mark.Mark; import org.olat.core.commons.services.mark.MarkManager; import org.olat.core.dispatcher.mapper.MapperService; import org.olat.core.dispatcher.mapper.manager.MapperKey; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter; import org.olat.core.gui.components.form.flexible.elements.FlexiTableSort; import org.olat.core.gui.components.form.flexible.elements.FlexiTableSortOptions; 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.DateFlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponentDelegate; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableSearchEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.rating.RatingFormEvent; import org.olat.core.gui.components.rating.RatingFormItem; import org.olat.core.gui.components.rating.RatingWithAverageFormItem; import org.olat.core.gui.components.stack.BreadcrumbPanel; 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.generic.closablewrapper.CloseableModalController; import org.olat.core.gui.control.generic.dtabs.Activateable2; 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.ContextEntry; import org.olat.core.id.context.StateEntry; import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.resource.OresHelper; import org.olat.course.CorruptedCourseException; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; import org.olat.repository.RepositoryModule; import org.olat.repository.RepositoryService; import org.olat.repository.controllers.EntryChangedEvent; import org.olat.repository.controllers.EntryChangedEvent.Change; import org.olat.repository.model.SearchMyRepositoryEntryViewParams; import org.olat.repository.model.SearchMyRepositoryEntryViewParams.Filter; import org.olat.repository.model.SearchMyRepositoryEntryViewParams.OrderBy; import org.olat.repository.ui.RepositoryEntryImageMapper; import org.olat.repository.ui.list.RepositoryEntryDataModel.Cols; import org.olat.util.logging.activity.LoggingResourceable; import org.springframework.beans.factory.annotation.Autowired; /** * * Initial date: 20.11.2012<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ public class RepositoryEntryListController extends FormBasicController implements Activateable2, RepositoryEntryDataSourceUIFactory, FlexiTableComponentDelegate { private final List<Link> filterLinks = new ArrayList<>(); private final List<Link> orderByLinks = new ArrayList<>(); private boolean withSearch; private final String name; private FlexiTableElement tableEl; private RepositoryEntryDataModel model; private DefaultRepositoryEntryDataSource dataSource; private SearchMyRepositoryEntryViewParams searchParams; private CloseableModalController cmc; private UserCommentsController commentsCtrl; private final BreadcrumbPanel stackPanel; private RepositoryEntryDetailsController detailsCtrl; private RepositoryEntrySearchController searchCtrl; private final MapperKey mapperThumbnailKey; @Autowired private MarkManager markManager; @Autowired private UserRatingsDAO userRatingsDao; @Autowired private MapperService mapperService; @Autowired private RepositoryModule repositoryModule; @Autowired private RepositoryService repositoryService; private final boolean guestOnly; public RepositoryEntryListController(UserRequest ureq, WindowControl wControl, SearchMyRepositoryEntryViewParams searchParams, boolean load, boolean withSearch, String name, BreadcrumbPanel stackPanel) { super(ureq, wControl, "repoentry_table"); setTranslator(Util.createPackageTranslator(RepositoryManager.class, getLocale(), getTranslator())); mapperThumbnailKey = mapperService.register(null, "repositoryentryImage", new RepositoryEntryImageMapper()); this.name = name; this.stackPanel = stackPanel; this.withSearch = withSearch; guestOnly = ureq.getUserSession().getRoles().isGuestOnly(); OLATResourceable ores = OresHelper.createOLATResourceableType("MyCoursesSite"); ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); this.searchParams = searchParams; dataSource = new DefaultRepositoryEntryDataSource(searchParams, this); initForm(ureq); if(load) { tableEl.reloadData(); } } public boolean isEmpty() { return dataSource.getRowCount() == 0; } public String getName() { return name; } public void reloadRows() { tableEl.reloadData(); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { if(withSearch) { setFormDescription("table.search.mycourses.desc"); searchCtrl = new RepositoryEntrySearchController(ureq, getWindowControl(), true, mainForm); searchCtrl.setEnabled(false); listenTo(searchCtrl); } FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.key.i18nKey(), Cols.key.ordinal(), true, OrderBy.key.name())); if(!guestOnly) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.mark.i18nKey(), Cols.mark.ordinal(), true, OrderBy.favorit.name())); } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.displayName.i18nKey(), Cols.select.ordinal(), true, OrderBy.displayname.name())); if(repositoryModule.isManagedRepositoryEntries()) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.externalId.i18nKey(), Cols.externalId.ordinal(), true, OrderBy.externalId.name())); } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.externalRef.i18nKey(), Cols.externalRef.ordinal(), true, OrderBy.externalRef.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.lifecycleLabel.i18nKey(), Cols.lifecycleLabel.ordinal(), true, OrderBy.lifecycleLabel.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.lifecycleSoftkey.i18nKey(), Cols.lifecycleSoftkey.ordinal(), true, OrderBy.lifecycleSoftkey.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.lifecycleStart.i18nKey(), Cols.lifecycleStart.ordinal(), true, OrderBy.lifecycleStart.name(), FlexiColumnModel.ALIGNMENT_LEFT, new DateFlexiCellRenderer(getLocale()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(true, Cols.lifecycleEnd.i18nKey(), Cols.lifecycleEnd.ordinal(), true, OrderBy.lifecycleEnd.name(), FlexiColumnModel.ALIGNMENT_LEFT, new DateFlexiCellRenderer(getLocale()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.location.i18nKey(), Cols.location.ordinal(), true, OrderBy.location.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.details.i18nKey(), Cols.details.ordinal(), false, null)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.start.i18nKey(), Cols.start.ordinal())); if(repositoryModule.isRatingEnabled()) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.ratings.i18nKey(), Cols.ratings.ordinal(), true, OrderBy.rating.name())); } if(repositoryModule.isCommentEnabled()) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.comments.i18nKey(), Cols.comments.ordinal())); } model = new RepositoryEntryDataModel(dataSource, columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "table", model, 20, false, getTranslator(), formLayout); tableEl.setAvailableRendererTypes(FlexiTableRendererType.custom, FlexiTableRendererType.classic); tableEl.setRendererType(FlexiTableRendererType.custom); tableEl.setSearchEnabled(withSearch); tableEl.setExtendedSearch(searchCtrl); tableEl.setCustomizeColumns(true); tableEl.setElementCssClass("o_coursetable"); tableEl.setEmtpyTableMessageKey("table.sEmptyTable"); VelocityContainer row = createVelocityContainer("row_1"); row.setDomReplacementWrapperRequired(false); // sets its own DOM id in velocity container tableEl.setRowRenderer(row, this); initFilters(tableEl); initSorters(tableEl); tableEl.setAndLoadPersistedPreferences(ureq, "re-list-" + name); } private void initFilters(FlexiTableElement tableElement) { List<FlexiTableFilter> filters = new ArrayList<>(16); filters.add(new FlexiTableFilter(translate("filter.show.all"), Filter.showAll.name(), true)); filters.add(FlexiTableFilter.SPACER); filters.add(new FlexiTableFilter(translate("filter.current.courses"), Filter.currentCourses.name())); filters.add(new FlexiTableFilter(translate("filter.upcoming.courses"), Filter.upcomingCourses.name())); filters.add(new FlexiTableFilter(translate("filter.old.courses"), Filter.oldCourses.name())); filters.add(FlexiTableFilter.SPACER); filters.add(new FlexiTableFilter(translate("filter.booked.participant"), Filter.asParticipant.name())); filters.add(new FlexiTableFilter(translate("filter.booked.coach"), Filter.asCoach.name())); filters.add(new FlexiTableFilter(translate("filter.booked.author"), Filter.asAuthor.name())); if(!searchParams.isMembershipMandatory()) { filters.add(new FlexiTableFilter(translate("filter.not.booked"), Filter.notBooked.name())); } filters.add(FlexiTableFilter.SPACER); filters.add(new FlexiTableFilter(translate("filter.passed"), Filter.passed.name())); filters.add(new FlexiTableFilter(translate("filter.not.passed"), Filter.notPassed.name())); filters.add(new FlexiTableFilter(translate("filter.without.passed.infos"), Filter.withoutPassedInfos.name())); tableElement.setFilters(null, filters, false); } private void initSorters(FlexiTableElement tableElement) { List<FlexiTableSort> sorters = new ArrayList<>(14); sorters.add(new FlexiTableSort(translate("orderby.automatic"), OrderBy.automatic.name())); sorters.add(new FlexiTableSort(translate("orderby.favorit"), OrderBy.favorit.name())); sorters.add(new FlexiTableSort(translate("orderby.lastVisited"), OrderBy.lastVisited.name())); sorters.add(new FlexiTableSort(translate("orderby.score"), OrderBy.score.name())); sorters.add(new FlexiTableSort(translate("orderby.passed"), OrderBy.passed.name())); sorters.add(FlexiTableSort.SPACER); sorters.add(new FlexiTableSort(translate("orderby.title"), OrderBy.title.name())); sorters.add(new FlexiTableSort(translate("orderby.lifecycle"), OrderBy.lifecycle.name())); sorters.add(new FlexiTableSort(translate("orderby.author"), OrderBy.author.name())); sorters.add(new FlexiTableSort(translate("orderby.creationDate"), OrderBy.creationDate.name())); sorters.add(new FlexiTableSort(translate("orderby.lastModified"), OrderBy.lastModified.name())); if(repositoryModule.isRatingEnabled()) { sorters.add(new FlexiTableSort(translate("orderby.rating"), OrderBy.rating.name())); } FlexiTableSortOptions options = new FlexiTableSortOptions(sorters); options.setDefaultOrderBy(new SortKey(OrderBy.title.name(), true)); tableElement.setSortSettings(options); } @Override public String getMapperThumbnailUrl() { return mapperThumbnailKey.getUrl(); } @Override protected void doDispose() { // } @Override public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { if(state instanceof RepositoryEntryListState) { RepositoryEntryListState se = (RepositoryEntryListState)state; if(se.getTableState() != null) { tableEl.setStateEntry(ureq, se.getTableState()); } if(se.getSearchEvent() != null) { searchCtrl.update(se.getSearchEvent()); doSearch(ureq, se.getSearchEvent()); } } } @Override protected void formOK(UserRequest ureq) { // } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { 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(); boolean marked = doMark(ureq, row); link.setIconLeftCSS(marked ? "o_icon o_icon_bookmark o_icon-lg" : "o_icon o_icon_bookmark_add o_icon-lg"); link.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark")); link.getComponent().setDirty(true); row.setMarked(marked); } else if ("start".equals(cmd)){ RepositoryEntryRow row = (RepositoryEntryRow)link.getUserObject(); doOpen(ureq, row, null); } else if ("details".equals(cmd)){ RepositoryEntryRow row = (RepositoryEntryRow)link.getUserObject(); doOpenDetails(ureq, row); } else if ("select".equals(cmd)) { RepositoryEntryRow row = (RepositoryEntryRow)link.getUserObject(); if (row.isMember()) { doOpen(ureq, row, null); } else { doOpenDetails(ureq, row); } } else if ("comments".equals(cmd)){ RepositoryEntryRow row = (RepositoryEntryRow)link.getUserObject(); doOpenComments(ureq, row); } } else if(source == tableEl) { if(event instanceof SelectionEvent) { SelectionEvent se = (SelectionEvent)event; String cmd = se.getCommand(); RepositoryEntryRow row = model.getObject(se.getIndex()); if("select".equals(cmd)) { if (row.isMember()) { doOpen(ureq, row, null); } else { doOpenDetails(ureq, row); } } } else if(event instanceof FlexiTableSearchEvent) { RepositoryEntryListState state = new RepositoryEntryListState(); state.setTableState(tableEl.getStateEntry()); addToHistory(ureq, state); } } super.formInnerEvent(ureq, source, event); } @Override public void event(UserRequest ureq, Component source, Event event) { if(source instanceof Link) { Link link = (Link)source; Object uo = link.getUserObject(); if(uo instanceof OrderBy) { OrderBy sort = (OrderBy)uo; for(Link order:orderByLinks) { removeCheck(order); } toggleCheck(link); doOrderBy(sort); flc.setDirty(true); } else if(uo instanceof Filter) { toggleCheck(link); List<Filter> selectedFilters = new ArrayList<>(); for(Link filter:filterLinks) { String iconCss = filter.getIconLeftCSS(); if(StringHelper.containsNonWhitespace(iconCss)) { selectedFilters.add((Filter)filter.getUserObject()); } } doFilter(selectedFilters); flc.setDirty(true); } } else if(source == mainForm.getInitialComponent()) { if("ONCLICK".equals(event.getCommand())) { String rowKeyStr = ureq.getParameter("select_row"); if(StringHelper.isLong(rowKeyStr)) { try { Long rowKey = new Long(rowKeyStr); List<RepositoryEntryRow> rows = model.getObjects(); for(RepositoryEntryRow row:rows) { if(row != null && row.getKey().equals(rowKey)) { if (row.isMember()) { doOpen(ureq, row, null); } else { doOpenDetails(ureq, row); } } } } catch (NumberFormatException e) { logWarn("Not a valid long: " + rowKeyStr, e); } } } } super.event(ureq, source, event); } private void toggleCheck(Link link) { String iconCss = link.getIconLeftCSS(); if(StringHelper.containsNonWhitespace(iconCss)) { link.setIconLeftCSS(null); } else { link.setIconLeftCSS("o_icon o_icon_check o_icon-fw"); } } private void removeCheck(Link link) { String iconCss = link.getIconLeftCSS(); if(StringHelper.containsNonWhitespace(iconCss)) { link.setIconLeftCSS(null); } } @Override protected void event(UserRequest ureq, Controller source, Event event) { if(cmc == source) { if(commentsCtrl != null) { RepositoryEntryRow row = (RepositoryEntryRow)commentsCtrl.getUserObject(); long numOfComments = commentsCtrl.getCommentsCount(); String css = numOfComments > 0 ? "o_icon o_icon_comments o_icon-lg" : "o_icon o_icon_comments_none o_icon-lg"; row.getCommentsLink().setCustomEnabledLinkCSS("o_comments"); row.getCommentsLink().setIconLeftCSS(css); String title = "(" + numOfComments + ")"; row.getCommentsLink().setI18nKey(title); row.getCommentsLink().getComponent().setDirty(true); } cleanUp(); } else if(commentsCtrl == source) { if(event == Event.CANCELLED_EVENT) { cmc.deactivate(); cleanUp(); } } else if(searchCtrl == source) { if(event instanceof SearchEvent) { SearchEvent se = (SearchEvent)event; doSearch(ureq, se); } else if(event == Event.CANCELLED_EVENT) { searchParams.setIdAndRefs(null); searchParams.setAuthor(null); searchParams.setText(null); } } else if(detailsCtrl == source) { if(event instanceof LeavingEvent) { stackPanel.popUpToController(this); tableEl.reset(); } } super.event(ureq, source, event); } @Override protected void propagateDirtinessToContainer(FormItem fiSrc, FormEvent event) { //do not update the } private void cleanUp() { removeAsListenerAndDispose(cmc); removeAsListenerAndDispose(commentsCtrl); commentsCtrl = null; cmc = null; } private void doSearch(UserRequest ureq, SearchEvent se) { searchParams.setIdAndRefs(se.getId()); searchParams.setAuthor(se.getAuthor()); searchParams.setText(se.getDisplayname()); searchParams.setMembershipMandatory(se.isMembershipMandatory()); tableEl.reset(true, true, true); RepositoryEntryListState state = new RepositoryEntryListState(); state.setTableState(tableEl.getStateEntry()); state.setSearchEvent(se); addToHistory(ureq, state); } protected void doFilter(List<Filter> filters) { dataSource.setFilters(filters); tableEl.reset(); } protected void doOrderBy(OrderBy orderBy) { dataSource.setOrderBy(orderBy); tableEl.reset(); } protected void doRating(RepositoryEntryRow row, float rating) { OLATResourceable ores = row.getRepositoryEntryResourceable(); userRatingsDao.updateRating(getIdentity(), ores, null, Math.round(rating)); } protected void doOpen(UserRequest ureq, RepositoryEntryRow row, String subPath) { try { String businessPath = "[RepositoryEntry:" + row.getKey() + "]"; if (subPath != null) { businessPath += subPath; } NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl()); } catch (CorruptedCourseException e) { logError("Course corrupted: " + row.getKey() + " (" + row.getOLATResourceable().getResourceableId() + ")", e); showError("cif.error.corrupted"); } } protected void doOpenDetails(UserRequest ureq, RepositoryEntryRow row) { // to be more consistent: course members see info page within the course, non-course members see it outside the course if (row.isMember()) { doOpen(ureq, row, "[Infos:0]"); } else { removeAsListenerAndDispose(detailsCtrl); OLATResourceable ores = OresHelper.createOLATResourceableInstance("Infos", 0l); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); RepositoryEntry entry = repositoryService.loadByKey(row.getKey()); if(entry == null) { showWarning("repositoryentry.not.existing"); } else { detailsCtrl = new RepositoryEntryDetailsController(ureq, bwControl, entry, row, false); listenTo(detailsCtrl); addToHistory(ureq, detailsCtrl); String displayName = row.getDisplayName(); stackPanel.pushController(displayName, detailsCtrl); } } } protected void doOpenComments(UserRequest ureq, RepositoryEntryRow row) { if(commentsCtrl != null) return; boolean anonym = ureq.getUserSession().getRoles().isGuestOnly(); CommentAndRatingSecurityCallback secCallback = new CommentAndRatingDefaultSecurityCallback(getIdentity(), false, anonym); commentsCtrl = new UserCommentsController(ureq, getWindowControl(), row.getRepositoryEntryResourceable(), null, secCallback); commentsCtrl.setUserObject(row); listenTo(commentsCtrl); cmc = new CloseableModalController(getWindowControl(), "close", commentsCtrl.getInitialComponent(), true, translate("comments")); listenTo(cmc); cmc.activate(); } protected boolean doMark(UserRequest ureq, RepositoryEntryRow row) { OLATResourceable item = OresHelper.createOLATResourceableInstance("RepositoryEntry", row.getKey()); if(markManager.isMarked(item, getIdentity(), null)) { markManager.removeMark(item, getIdentity(), null); EntryChangedEvent e = new EntryChangedEvent(row, getIdentity(), Change.removeBookmark, name); ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES); return false; } else { String businessPath = "[RepositoryEntry:" + item.getResourceableId() + "]"; markManager.setMark(item, getIdentity(), null, businessPath); EntryChangedEvent e = new EntryChangedEvent(row, getIdentity(), Change.addBookmark, name); ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES); return true; } } @Override public void forgeMarkLink(RepositoryEntryRow row) { if(!guestOnly) { FormLink markLink = uifactory.addFormLink("mark_" + row.getKey(), "mark", "", null, null, Link.NONTRANSLATED); markLink.setIconLeftCSS(row.isMarked() ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE); markLink.setTitle(translate(row.isMarked() ? "details.bookmark.remove" : "details.bookmark")); markLink.setUserObject(row); row.setMarkLink(markLink); } } @Override public void forgeSelectLink(RepositoryEntryRow row) { String displayName = StringHelper.escapeHtml(row.getDisplayName()); FormLink selectLink = uifactory.addFormLink("select_" + row.getKey(), "select", displayName, null, null, Link.NONTRANSLATED); if(row.isClosed()) { selectLink.setIconLeftCSS("o_icon o_CourseModule_icon_closed"); } selectLink.setUserObject(row); row.setSelectLink(selectLink); } @Override public void forgeStartLink(RepositoryEntryRow row) { String label; boolean isStart = true; if(!row.isMembersOnly() && row.getAccessTypes() != null && !row.getAccessTypes().isEmpty() && !row.isMember()) { if(guestOnly) { if(row.getAccess() == RepositoryEntry.ACC_USERS_GUESTS) { label = "start"; } else { return; } } else { label = "book"; isStart = false; } } else { label = "start"; } FormLink startLink = uifactory.addFormLink("start_" + row.getKey(), "start", label, null, null, Link.LINK); startLink.setUserObject(row); startLink.setCustomEnabledLinkCSS(isStart ? "o_start btn-block" : "o_book btn-block"); startLink.setIconRightCSS("o_icon o_icon_start"); row.setStartLink(startLink); } @Override public void forgeDetails(RepositoryEntryRow row) { FormLink detailsLink = uifactory.addFormLink("details_" + row.getKey(), "details", "details", null, null, Link.LINK); detailsLink.setCustomEnabledLinkCSS("o_details"); detailsLink.setUserObject(row); row.setDetailsLink(detailsLink); } @Override public Iterable<Component> getComponents(int row, Object rowObject) { return null; } @Override public void forgeRatings(RepositoryEntryRow row) { if(repositoryModule.isRatingEnabled()) { if(guestOnly) { Double averageRating = row.getAverageRating(); float averageRatingValue = averageRating == null ? 0f : averageRating.floatValue(); RatingFormItem ratingCmp = new RatingFormItem("rat_" + row.getKey(), averageRatingValue, 5, false); row.setRatingFormItem(ratingCmp); ratingCmp.setUserObject(row); } else { Integer myRating = row.getMyRating(); Double averageRating = row.getAverageRating(); long numOfRatings = row.getNumOfRatings(); float ratingValue = myRating == null ? 0f : myRating.floatValue(); float averageRatingValue = averageRating == null ? 0f : averageRating.floatValue(); RatingWithAverageFormItem ratingCmp = new RatingWithAverageFormItem("rat_" + row.getKey(), ratingValue, averageRatingValue, 5, numOfRatings); row.setRatingFormItem(ratingCmp); ratingCmp.setUserObject(row); } } } @Override public void forgeComments(RepositoryEntryRow row) { if(repositoryModule.isCommentEnabled()) { long numOfComments = row.getNumOfComments(); String title = "(" + numOfComments + ")"; FormLink commentsLink = uifactory.addFormLink("comments_" + row.getKey(), "comments", title, null, null, Link.NONTRANSLATED); commentsLink.setUserObject(row); String css = numOfComments > 0 ? "o_icon o_icon_comments o_icon-lg" : "o_icon o_icon_comments_none o_icon-lg"; commentsLink.setCustomEnabledLinkCSS("o_comments"); commentsLink.setIconLeftCSS(css); row.setCommentsLink(commentsLink); } } @Override public Translator getTranslator() { return super.getTranslator(); } }