diff --git a/src/main/java/org/olat/admin/user/UserAdminController.java b/src/main/java/org/olat/admin/user/UserAdminController.java index ecf45ca8bb6158c2efae34df0d4b8b183b3466b9..a94167f43108c85d116aaca3cd59d84e3a969416 100644 --- a/src/main/java/org/olat/admin/user/UserAdminController.java +++ b/src/main/java/org/olat/admin/user/UserAdminController.java @@ -64,6 +64,8 @@ import org.olat.core.util.vfs.QuotaManager; import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementListController; import org.olat.ldap.LDAPLoginManager; import org.olat.ldap.LDAPLoginModule; +import org.olat.modules.curriculum.CurriculumModule; +import org.olat.modules.curriculum.ui.CurriculumListController; import org.olat.modules.lecture.LectureModule; import org.olat.modules.lecture.ui.ParticipantLecturesOverviewController; import org.olat.modules.taxonomy.TaxonomyModule; @@ -100,7 +102,7 @@ public class UserAdminController extends BasicController implements Activateable private static final String NLS_FOUND_PROPERTY = "found.property"; private static final String NLS_EDIT_UPROFILE = "edit.uprofile"; private static final String NLS_EDIT_UPREFS = "edit.uprefs"; - private static final String NLS_EDIT_UPCRED = "edit.upwd"; + private static final String NLS_EDIT_UPCRED = "edit.upwd"; private static final String NLS_EDIT_UAUTH = "edit.uauth"; private static final String NLS_EDIT_UPROP = "edit.uprop"; private static final String NLS_EDIT_UROLES = "edit.uroles"; @@ -112,7 +114,8 @@ public class UserAdminController extends BasicController implements Activateable private static final String NLS_VIEW_EFF_STATEMENTS = "view.effStatements"; private static final String NLS_VIEW_SUBSCRIPTIONS = "view.subscriptions"; private static final String NLS_VIEW_LECTURES = "view.lectures"; - private static final String NLS_VIEW_COMPETENCES = "view.competences"; + private static final String NLS_VIEW_COMPETENCES = "view.competences"; + private static final String NLS_VIEW_CURRICULUM = "view.curriculum"; private VelocityContainer myContent; private final TooledStackedPanel stackPanel; @@ -126,6 +129,7 @@ public class UserAdminController extends BasicController implements Activateable // controllers used in tabbed pane private TabbedPane userTabP; private Controller prefsCtr, propertiesCtr, pwdCtr, quotaCtr, rolesCtr, userShortDescrCtr; + private CurriculumListController curriculumCtr; private UserRelationsController relationsCtrl; private DisplayPortraitController portraitCtr; private UserAuthenticationsEditorController authenticationsCtr; @@ -156,6 +160,8 @@ public class UserAdminController extends BasicController implements Activateable @Autowired private TaxonomyModule taxonomyModule; @Autowired + private CurriculumModule curriculumModule; + @Autowired private QuotaManager quotaManager; @Autowired private OrganisationService organisationService; @@ -491,6 +497,18 @@ public class UserAdminController extends BasicController implements Activateable return competencePanel; }); } + + if(curriculumModule.isEnabled() && (isUserManagerOf || isRolesManagerOf || isAdminOf || isPrincipalOf)) { + userTabP.addTab(translate(NLS_VIEW_CURRICULUM), uureq -> { + curriculumCtr = new CurriculumListController(uureq, getWindowControl(), identity); + listenTo(curriculumCtr); + BreadcrumbedStackedPanel competencePanel = new BreadcrumbedStackedPanel("curriculums", getTranslator(), curriculumCtr); + competencePanel.pushController(translate(NLS_VIEW_CURRICULUM), curriculumCtr); + curriculumCtr.setBreadcrumbPanel(competencePanel); + competencePanel.setInvisibleCrumb(1); + return competencePanel; + }); + } // now push to velocity myContent.put("userTabP", userTabP); diff --git a/src/main/java/org/olat/admin/user/_content/udispatcher.html b/src/main/java/org/olat/admin/user/_content/udispatcher.html index 1bee7b63589bcaa2296a653d79abd572c7dc5f40..c7430ae63812b6281579b382be6e9f20a67b8e06 100644 --- a/src/main/java/org/olat/admin/user/_content/udispatcher.html +++ b/src/main/java/org/olat/admin/user/_content/udispatcher.html @@ -4,7 +4,7 @@ #if($r.isTrue($showTitle)) <h4>$r.translate("content.usermgmt.userfound")</h4> #end -<div class="o_user_infos"> +<div class="o_user_infos row"> <div class="o_user_portrait">$r.render("portrait")</div> <div class="o_user_infos_inner"> $r.render("userShortDescription") diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_de.properties index e00e3a65c581c33436f84e1ed8e93538e696f538..823b0f9907e85c179a122ee1100f33658d5da0c5 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_de.properties @@ -207,6 +207,7 @@ usermanagers=Benutzerverwalter view.access=Buchungen view.competences=Kompetenzen view.courses=Lernressourcen +view.curriculum=Curriculum view.effStatements=Statements view.groups=Gruppen view.lectures=Lektionen diff --git a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties index 44270949b2ae823e9e34c65202d02af88e1ef4ce..2772dd8d09bef62ec16ab535205dfb46fafff17b 100644 --- a/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/admin/user/_i18n/LocalStrings_en.properties @@ -205,6 +205,7 @@ usermanagers=User manager view.access=Bookings view.competences=Competences view.courses=Learning resources +view.curriculum=Curriculum view.effStatements=Statements view.groups=Groups view.lectures=Lectures diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumSecurityCallbackFactory.java b/src/main/java/org/olat/modules/curriculum/CurriculumSecurityCallbackFactory.java index 4f58624415fb80912f0e972f353335d63dac06ff..bcff4452fc8257ce16f5d2c462c5d3b74d579779 100644 --- a/src/main/java/org/olat/modules/curriculum/CurriculumSecurityCallbackFactory.java +++ b/src/main/java/org/olat/modules/curriculum/CurriculumSecurityCallbackFactory.java @@ -45,6 +45,14 @@ public class CurriculumSecurityCallbackFactory { return new DefaultCurriculumSecurityCallback(false, Collections.emptyList()); } + /** + * @return A security callback without any administration permissions + * but view calendars and lectures. + */ + public static final CurriculumSecurityCallback userLookCallback() { + return new UserLookCurriculumSecurityCallback(); + } + public static final CurriculumSecurityCallback createCallback(Roles roles) { boolean admin = roles.isCurriculumManager() || roles.isAdministrator(); return new DefaultCurriculumSecurityCallback(admin, Collections.emptyList()); @@ -54,6 +62,23 @@ public class CurriculumSecurityCallbackFactory { return new DefaultCurriculumSecurityCallback(canManage, ownedRefs); } + private static class UserLookCurriculumSecurityCallback extends DefaultCurriculumSecurityCallback { + + public UserLookCurriculumSecurityCallback() { + super(false, Collections.emptyList()); + } + + @Override + public boolean canViewAllCalendars() { + return true; + } + + @Override + public boolean canViewAllLectures() { + return true; + } + } + private static class DefaultCurriculumSecurityCallback implements CurriculumSecurityCallback { private final boolean admin; diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementListController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementListController.java index ea530c0e69bd27d657035b26c90b98b45f89b9a0..119a6da008fdbf7fb268fb5ae24cf8ef9d505dca 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementListController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumElementListController.java @@ -58,6 +58,7 @@ 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.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.id.Roles; import org.olat.core.id.context.BusinessControlFactory; @@ -70,7 +71,7 @@ import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementMembership; import org.olat.modules.curriculum.CurriculumElementWithView; import org.olat.modules.curriculum.CurriculumRef; -import org.olat.modules.curriculum.CurriculumSecurityCallbackFactory; +import org.olat.modules.curriculum.CurriculumSecurityCallback; import org.olat.modules.curriculum.CurriculumService; import org.olat.modules.curriculum.model.CurriculumElementRefImpl; import org.olat.modules.curriculum.model.CurriculumElementRepositoryEntryViews; @@ -117,6 +118,8 @@ public class CurriculumElementListController extends FormBasicController impleme private final boolean guestOnly; private final CurriculumRef curriculum; private final MapperKey mapperThumbnailKey; + private final Identity assessedIdentity; + private final CurriculumSecurityCallback secCallback; private RepositoryEntryDetailsController detailsCtrl; private CurriculumElementCalendarController calendarsCtrl; @@ -136,10 +139,13 @@ public class CurriculumElementListController extends FormBasicController impleme @Autowired private RepositoryManager repositoryManager; - public CurriculumElementListController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, CurriculumRef curriculum) { + public CurriculumElementListController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, + Identity assessedIdentity, CurriculumRef curriculum, CurriculumSecurityCallback secCallback) { super(ureq, wControl, "curriculum_element_list", Util.createPackageTranslator(RepositoryService.class, ureq.getLocale())); this.curriculum = curriculum; this.stackPanel = stackPanel; + this.secCallback = secCallback; + this.assessedIdentity = assessedIdentity; guestOnly = ureq.getUserSession().getRoles().isGuestOnly(); mapperThumbnailKey = mapperService.register(null, "repositoryentryImage", new RepositoryEntryImageMapper()); @@ -161,7 +167,9 @@ public class CurriculumElementListController extends FormBasicController impleme elementIdentifierCol.setCellRenderer(new CurriculumElementCompositeRenderer("select", new TextFlexiCellRenderer())); columnsModel.addFlexiColumnModel(elementIdentifierCol); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, ElementViewCols.select)); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.mark)); + if(assessedIdentity.equals(getIdentity())) { + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.mark)); + } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.details)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.calendars)); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.start)); @@ -169,7 +177,11 @@ public class CurriculumElementListController extends FormBasicController impleme tableModel = new CurriculumElementWithViewsDataModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 50, false, getTranslator(), formLayout); tableEl.setAvailableRendererTypes(FlexiTableRendererType.custom, FlexiTableRendererType.classic); - tableEl.setRendererType(FlexiTableRendererType.custom); + if(assessedIdentity.equals(getIdentity())) { + tableEl.setRendererType(FlexiTableRendererType.custom); + } else { + tableEl.setRendererType(FlexiTableRendererType.classic); + } tableEl.setElementCssClass("o_curriculumtable"); tableEl.setCustomizeColumns(true); tableEl.setEmtpyTableMessageKey("table.curriculum.empty"); @@ -181,7 +193,8 @@ public class CurriculumElementListController extends FormBasicController impleme row.setDomReplacementWrapperRequired(false); // sets its own DOM id in velocity container tableEl.setRowRenderer(row, this); - tableEl.setAndLoadPersistedPreferences(ureq, "my-curriculum-elements-v3-" + curriculum.getKey()); + tableEl.setAndLoadPersistedPreferences(ureq, "my-curriculum-elements-v3-" + + (assessedIdentity.equals(getIdentity()) ? "" : "look-") + curriculum.getKey()); } private List<FlexiTableFilter> getFilters() { @@ -243,7 +256,7 @@ public class CurriculumElementListController extends FormBasicController impleme private void loadModel(UserRequest ureq) { Roles roles = ureq.getUserSession().getRoles(); List<CurriculumRef> curriculumList = Collections.singletonList(curriculum); - List<CurriculumElementRepositoryEntryViews> elementsWithViews = curriculumService.getCurriculumElements(getIdentity(), roles, curriculumList); + List<CurriculumElementRepositoryEntryViews> elementsWithViews = curriculumService.getCurriculumElements(assessedIdentity, roles, curriculumList); Set<Long> repoKeys = new HashSet<>(elementsWithViews.size() * 3); List<OLATResource> resourcesWithAC = new ArrayList<>(elementsWithViews.size() * 3); @@ -256,7 +269,7 @@ public class CurriculumElementListController extends FormBasicController impleme } } List<OLATResourceAccess> resourcesWithOffer = acService.filterResourceWithAC(resourcesWithAC); - repositoryService.filterMembership(getIdentity(), repoKeys); + repositoryService.filterMembership(assessedIdentity, repoKeys); List<CurriculumElementWithViewsRow> rows = new ArrayList<>(elementsWithViews.size() * 3); for(CurriculumElementRepositoryEntryViews elementWithViews:elementsWithViews) { @@ -559,9 +572,9 @@ public class CurriculumElementListController extends FormBasicController impleme } } + List<RepositoryEntry> entries = repositoryService.loadByKeys(entryKeys); - calendarsCtrl = new CurriculumElementCalendarController(ureq, bwControl, element, entries, - CurriculumSecurityCallbackFactory.createDefaultCallback()); + calendarsCtrl = new CurriculumElementCalendarController(ureq, bwControl, element, entries, secCallback); listenTo(calendarsCtrl); stackPanel.pushController(translate("calendars"), calendarsCtrl); } diff --git a/src/main/java/org/olat/modules/curriculum/ui/CurriculumListController.java b/src/main/java/org/olat/modules/curriculum/ui/CurriculumListController.java index 3acaeadb333330750a0f36902e957b32db67be86..abac7c542a285d865e81ccbaf4ab5becb6b6a32e 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/CurriculumListController.java +++ b/src/main/java/org/olat/modules/curriculum/ui/CurriculumListController.java @@ -38,12 +38,15 @@ import org.olat.core.gui.components.stack.BreadcrumbedStackedPanel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.id.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.resource.OresHelper; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumRef; +import org.olat.modules.curriculum.CurriculumSecurityCallback; +import org.olat.modules.curriculum.CurriculumSecurityCallbackFactory; import org.olat.modules.curriculum.CurriculumService; import org.olat.modules.curriculum.ui.CurriculumManagerDataModel.CurriculumCols; import org.olat.modules.curriculum.ui.component.CurriculumActiveCellRenderer; @@ -62,16 +65,44 @@ public class CurriculumListController extends FormBasicController implements Act private FlexiTableElement tableEl; private CurriculumManagerDataModel tableModel; - private final BreadcrumbedStackedPanel stackPanel; + private BreadcrumbedStackedPanel stackPanel; + private CurriculumSecurityCallback secCallback; private CurriculumElementListController elementListCtrl; + private Identity assessedIdentity; + @Autowired private CurriculumService curriculumService; + /** + * This opens the list of the curriculum of the loged in user with standard permissions. + * + * @param ureq The user request + * @param wControl The window control + * @param stackPanel The bread crumb panel + */ public CurriculumListController(UserRequest ureq, WindowControl wControl, BreadcrumbedStackedPanel stackPanel) { super(ureq, wControl, "curriculum_list"); this.stackPanel = stackPanel; + assessedIdentity = getIdentity(); + secCallback = CurriculumSecurityCallbackFactory.createDefaultCallback(); + + initForm(ureq); + loadModel(); + } + + /** + * This opens the list of curriculums of the specified user. + * + * @param ureq The user request + * @param wControl The window control + * @param assessedIdentity The identity to look at the curriculums + */ + public CurriculumListController(UserRequest ureq, WindowControl wControl, Identity assessedIdentity) { + super(ureq, wControl, "curriculum_list"); + this.assessedIdentity = assessedIdentity; + secCallback = CurriculumSecurityCallbackFactory.userLookCallback(); initForm(ureq); loadModel(); @@ -80,6 +111,10 @@ public class CurriculumListController extends FormBasicController implements Act public String getName() { return "curriculum"; } + + public void setBreadcrumbPanel(BreadcrumbedStackedPanel stackPanel) { + this.stackPanel = stackPanel; + } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { @@ -88,17 +123,15 @@ public class CurriculumListController extends FormBasicController implements Act columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CurriculumCols.active, new CurriculumActiveCellRenderer(getTranslator()))); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CurriculumCols.displayName, "select")); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(CurriculumCols.identifier, "select")); - DefaultFlexiColumnModel toolsCol = new DefaultFlexiColumnModel(CurriculumCols.tools); - toolsCol.setExportable(false); - toolsCol.setAlwaysVisible(true); - columnsModel.addFlexiColumnModel(toolsCol); tableModel = new CurriculumManagerDataModel(columnsModel, getLocale()); tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, false, getTranslator(), formLayout); tableEl.setCustomizeColumns(true); tableEl.setEmtpyTableMessageKey("table.curriculum.empty"); tableEl.setFilters("activity", getFilters(), false); - tableEl.setSelectedFilterKey("active"); + if(assessedIdentity.equals(getIdentity())) { + tableEl.setSelectedFilterKey("active"); + } tableEl.setAndLoadPersistedPreferences(ureq, "cur-curriculum-list-v2"); } @@ -112,8 +145,8 @@ public class CurriculumListController extends FormBasicController implements Act } private void loadModel() { - List<Curriculum> curriculums = curriculumService.getMyCurriculums(getIdentity()); - List<CurriculumRef> activeRefs = curriculumService.getMyActiveCurriculumRefs(getIdentity()); + List<Curriculum> curriculums = curriculumService.getMyCurriculums(assessedIdentity); + List<CurriculumRef> activeRefs = curriculumService.getMyActiveCurriculumRefs(assessedIdentity); List<Long> activeKeys = activeRefs.stream().map(CurriculumRef::getKey).collect(Collectors.toList()); List<CurriculumRow> rows = curriculums.stream() .map(c -> new CurriculumRow(c, activeKeys.contains(c.getKey()))) @@ -176,7 +209,8 @@ public class CurriculumListController extends FormBasicController implements Act OLATResourceable ores = OresHelper.createOLATResourceableInstance("Curriculum", row.getKey()); WindowControl swControl = addToHistory(ureq, ores, null); - elementListCtrl = new CurriculumElementListController(ureq, swControl, stackPanel, row); + elementListCtrl = new CurriculumElementListController(ureq, swControl, stackPanel, + assessedIdentity, row, secCallback); listenTo(elementListCtrl); stackPanel.pushController(row.getDisplayName(), elementListCtrl); }