From c25464a506327163ede0f31210ba0729b18f450e Mon Sep 17 00:00:00 2001 From: uhensler <none@none> Date: Wed, 10 Jan 2018 08:04:16 +0100 Subject: [PATCH] OO-3113: Configuration of the pool manager rights --- .../modules/qpool/QPoolSecurityCallback.java | 18 ++- .../qpool/QuestionItemSecurityCallback.java | 2 + .../modules/qpool/QuestionPoolModule.java | 131 ++++++++++++++++++ .../security/ProcesslessSecurityCallback.java | 61 ++++++-- .../QPoolSecurityCallbackFactory.java | 16 +-- ...ck.java => QPoolSecurityCallbackImpl.java} | 50 ++++++- .../RegularQPoolSecurityCallback.java | 66 --------- .../ReviewProcessSecurityCallback.java | 35 +++-- .../qpool/ui/AbstractItemListController.java | 9 +- .../qpool/ui/_content/item_list_overview.html | 2 +- .../qpool/ui/_i18n/LocalStrings_de.properties | 1 + .../qpool/ui/_i18n/LocalStrings_en.properties | 1 + ...stionPoolAdminConfigurationController.java | 88 ++++++++++-- .../qpool/ui/admin/_content/admin_config.html | 3 + .../ui/admin/_i18n/LocalStrings_de.properties | 10 ++ .../ui/admin/_i18n/LocalStrings_en.properties | 10 ++ .../ui/metadata/ExtendedSearchController.java | 1 + .../ui/tree/QuestionPoolMenuTreeModel.java | 54 +++++--- .../ui/tree/ReviewProcessAdminTreeNode.java | 59 ++++++++ 19 files changed, 477 insertions(+), 140 deletions(-) rename src/main/java/org/olat/modules/qpool/security/{AdministratorQPoolSecurityCallback.java => QPoolSecurityCallbackImpl.java} (57%) delete mode 100644 src/main/java/org/olat/modules/qpool/security/RegularQPoolSecurityCallback.java create mode 100644 src/main/java/org/olat/modules/qpool/ui/admin/_content/admin_config.html create mode 100644 src/main/java/org/olat/modules/qpool/ui/tree/ReviewProcessAdminTreeNode.java diff --git a/src/main/java/org/olat/modules/qpool/QPoolSecurityCallback.java b/src/main/java/org/olat/modules/qpool/QPoolSecurityCallback.java index 7072a7f0a2a..4bae90c1f72 100644 --- a/src/main/java/org/olat/modules/qpool/QPoolSecurityCallback.java +++ b/src/main/java/org/olat/modules/qpool/QPoolSecurityCallback.java @@ -26,6 +26,10 @@ package org.olat.modules.qpool; * */ public interface QPoolSecurityCallback { + + public void setAdmin(boolean admin); + + public void setPoolAdmin(boolean poolAdmin); boolean canUseCollections(); @@ -35,6 +39,18 @@ public interface QPoolSecurityCallback { boolean canUseReviewProcess(); - boolean canAdmin(); + boolean canEditAllQuestions(); + + boolean canConfigReviewProcess(); + + boolean canConfigTaxonomies(); + + boolean canConfigPools(); + + boolean canConfigItemTypes(); + + boolean canConfigEducationalContext(); + + boolean canConfigLicences(); } diff --git a/src/main/java/org/olat/modules/qpool/QuestionItemSecurityCallback.java b/src/main/java/org/olat/modules/qpool/QuestionItemSecurityCallback.java index 2454fd8c64c..4771c2c6007 100644 --- a/src/main/java/org/olat/modules/qpool/QuestionItemSecurityCallback.java +++ b/src/main/java/org/olat/modules/qpool/QuestionItemSecurityCallback.java @@ -35,6 +35,8 @@ public interface QuestionItemSecurityCallback { public void setAdmin(boolean admin); + public void setPoolAdmin(boolean poolAdmin); + public boolean canEditQuestion(); public boolean canEditMetadata(); diff --git a/src/main/java/org/olat/modules/qpool/QuestionPoolModule.java b/src/main/java/org/olat/modules/qpool/QuestionPoolModule.java index 6e546128f50..7acd6c6f342 100644 --- a/src/main/java/org/olat/modules/qpool/QuestionPoolModule.java +++ b/src/main/java/org/olat/modules/qpool/QuestionPoolModule.java @@ -61,6 +61,14 @@ public class QuestionPoolModule extends AbstractSpringModule implements ConfigOn private static final String FINAL_VISIBLE_TEACH = "final.visible.teach"; private static final String TAXONOMY_QPOOL_KEY = "taxonomy.qpool.key"; public static final String DEFAULT_TAXONOMY_QPOOL_IDENTIFIER = "QPOOL"; + private static final String POOL_ADMIN_METADATA = "pool.admin.metadata"; + private static final String POOL_ADMIN_STATUS = "pool.admin.status"; + private static final String POOL_ADMIN_REVIEW_PROCESS = "pool.admin.review.process"; + private static final String POOL_ADMIN_TAXONOMY = "pool.admin.taxonomy"; + private static final String POOL_ADMIN_POOLS = "pool.admin.pools"; + private static final String POOL_ADMIN_ITEM_TYPES = "pool.admin.item.types"; + private static final String POOL_ADMIN_EDUCATIONAL_CONTEXT = "pool.admin.educational.context"; + private static final String POOL_ADMIN_LICENSES = "pool.admin.licenses"; private boolean collectionsEnabled = true; private boolean poolsEnabled = true; @@ -70,6 +78,15 @@ public class QuestionPoolModule extends AbstractSpringModule implements ConfigOn private boolean finalVisibleTeach = false; private String taxonomyQPoolKey; + private boolean poolAdminAllowedToEditMetadata = false; + private boolean poolAdminAllowedToEditStatus = false; + private boolean poolAdminAllowedToConfigReviewProcess = true; + private boolean poolAdminAllowedToConfigTaxonomy = true; + private boolean poolAdminAllowedToConfigPools = true; + private boolean poolAdminAllowedToConfigItemTypes = true; + private boolean poolAdminAllowedToConfigEducationalContext = true; + private boolean poolAdminAllowedToConfigLicenses = true; + @Autowired private DB dbInstance; @Autowired @@ -154,6 +171,47 @@ public class QuestionPoolModule extends AbstractSpringModule implements ConfigOn if(StringHelper.containsNonWhitespace(taxonomyQPoolKeyObj)) { taxonomyQPoolKey = taxonomyQPoolKeyObj; } + + String poolAdminAllowedToEditMetadataObj = getStringPropertyValue(POOL_ADMIN_METADATA, true); + if(StringHelper.containsNonWhitespace(poolAdminAllowedToEditMetadataObj)) { + poolAdminAllowedToEditMetadata = "true".equals(poolAdminAllowedToEditMetadataObj); + } + + String poolAdminAllowedToEditStatusObj = getStringPropertyValue(POOL_ADMIN_STATUS, true); + if(StringHelper.containsNonWhitespace(poolAdminAllowedToEditStatusObj)) { + poolAdminAllowedToEditStatus = "true".equals(poolAdminAllowedToEditStatusObj); + } + + String poolAdminAllowedToConfigReviewProcessObj = getStringPropertyValue(POOL_ADMIN_REVIEW_PROCESS, true); + if(StringHelper.containsNonWhitespace(poolAdminAllowedToConfigReviewProcessObj)) { + poolAdminAllowedToConfigReviewProcess = "true".equals(poolAdminAllowedToConfigReviewProcessObj); + } + + String poolAdminAllowedToConfigTaxonomyObj = getStringPropertyValue(POOL_ADMIN_TAXONOMY, true); + if(StringHelper.containsNonWhitespace(poolAdminAllowedToConfigTaxonomyObj)) { + poolAdminAllowedToConfigTaxonomy = "true".equals(poolAdminAllowedToConfigTaxonomyObj); + } + + String poolAdminAllowedToConfigPoolsObj = getStringPropertyValue(POOL_ADMIN_POOLS, true); + if(StringHelper.containsNonWhitespace(poolAdminAllowedToConfigPoolsObj)) { + poolAdminAllowedToConfigPools = "true".equals(poolAdminAllowedToConfigPoolsObj); + } + + String poolAdminAllowedToConfigItemTypesObj = getStringPropertyValue(POOL_ADMIN_ITEM_TYPES, true); + if(StringHelper.containsNonWhitespace(poolAdminAllowedToConfigItemTypesObj)) { + poolAdminAllowedToConfigItemTypes = "true".equals(poolAdminAllowedToConfigItemTypesObj); + } + + String poolAdminAllowedToConfigEducationalContextObj = getStringPropertyValue(POOL_ADMIN_EDUCATIONAL_CONTEXT, true); + if(StringHelper.containsNonWhitespace(poolAdminAllowedToConfigEducationalContextObj)) { + poolAdminAllowedToConfigEducationalContext = "true".equals(poolAdminAllowedToConfigEducationalContextObj); + } + + String poolAdminAllowedToConfigLicensesObj = getStringPropertyValue(POOL_ADMIN_LICENSES, true); + if(StringHelper.containsNonWhitespace(poolAdminAllowedToConfigLicensesObj)) { + poolAdminAllowedToConfigLicenses = "true".equals(poolAdminAllowedToConfigLicensesObj); + } + } @Override @@ -270,4 +328,77 @@ public class QuestionPoolModule extends AbstractSpringModule implements ConfigOn setStringProperty(TAXONOMY_QPOOL_KEY, taxonomyQPoolKey, true); } + public boolean isPoolAdminAllowedToEditMetadata() { + return poolAdminAllowedToEditMetadata; + } + + public void setPoolAdminAllowedToEditMetadata(boolean poolAdminAllowedToEditMetadata) { + this.poolAdminAllowedToEditMetadata = poolAdminAllowedToEditMetadata; + setStringProperty(POOL_ADMIN_METADATA, Boolean.toString(poolAdminAllowedToEditMetadata), true); + } + + public boolean isPoolAdminAllowedToEditStatus() { + return poolAdminAllowedToEditStatus; + } + + public void setPoolAdminAllowedToEditStatus(boolean poolAdminAllowedToEditStatus) { + this.poolAdminAllowedToEditStatus = poolAdminAllowedToEditStatus; + setStringProperty(POOL_ADMIN_STATUS, Boolean.toString(poolAdminAllowedToEditStatus), true); + } + + + public boolean isPoolAdminAllowedToConfigReviewProcess() { + return poolAdminAllowedToConfigReviewProcess; + } + + public void setPoolAdminAllowedToConfigReviewProcess(boolean poolAdminAllowedToConfigReviewProcess) { + this.poolAdminAllowedToConfigReviewProcess = poolAdminAllowedToConfigReviewProcess; + setStringProperty(POOL_ADMIN_REVIEW_PROCESS, Boolean.toString(poolAdminAllowedToConfigReviewProcess), true); + } + + public boolean isPoolAdminAllowedToConfigTaxonomy() { + return poolAdminAllowedToConfigTaxonomy; + } + + public void setPoolAdminAllowedToConfigTaxonomy(boolean poolAdminAllowedToConfigTaxonomy) { + this.poolAdminAllowedToConfigTaxonomy = poolAdminAllowedToConfigTaxonomy; + setStringProperty(POOL_ADMIN_TAXONOMY, Boolean.toString(poolAdminAllowedToConfigTaxonomy), true); + } + + public boolean isPoolAdminAllowedToConfigPools() { + return poolAdminAllowedToConfigPools; + } + + public void setPoolAdminAllowedToConfigPools(boolean poolAdminAllowedToConfigPools) { + this.poolAdminAllowedToConfigPools = poolAdminAllowedToConfigPools; + setStringProperty(POOL_ADMIN_POOLS, Boolean.toString(poolAdminAllowedToConfigPools), true); + } + + public boolean isPoolAdminAllowedToConfigItemTypes() { + return poolAdminAllowedToConfigItemTypes; + } + + public void setPoolAdminAllowedToConfigItemTypes(boolean poolAdminAllowedToConfigItemTypes) { + this.poolAdminAllowedToConfigItemTypes = poolAdminAllowedToConfigItemTypes; + setStringProperty(POOL_ADMIN_ITEM_TYPES, Boolean.toString(poolAdminAllowedToConfigItemTypes), true); + } + + public boolean isPoolAdminAllowedToConfigEducationalContext() { + return poolAdminAllowedToConfigEducationalContext; + } + + public void setPoolAdminAllowedToConfigEducationalContext(boolean poolAdminAllowedToConfigEducationalContext) { + this.poolAdminAllowedToConfigEducationalContext = poolAdminAllowedToConfigEducationalContext; + setStringProperty(POOL_ADMIN_EDUCATIONAL_CONTEXT, Boolean.toString(poolAdminAllowedToConfigEducationalContext), true); + } + + public boolean isPoolAdminAllowedToConfigLicenses() { + return poolAdminAllowedToConfigLicenses; + } + + public void setPoolAdminAllowedToConfigLicenses(boolean poolAdminAllowedToConfigLicenses) { + this.poolAdminAllowedToConfigLicenses = poolAdminAllowedToConfigLicenses; + setStringProperty(POOL_ADMIN_LICENSES, Boolean.toString(poolAdminAllowedToConfigLicenses), true); + } + } diff --git a/src/main/java/org/olat/modules/qpool/security/ProcesslessSecurityCallback.java b/src/main/java/org/olat/modules/qpool/security/ProcesslessSecurityCallback.java index c52e2f0b3f3..e338252e59e 100644 --- a/src/main/java/org/olat/modules/qpool/security/ProcesslessSecurityCallback.java +++ b/src/main/java/org/olat/modules/qpool/security/ProcesslessSecurityCallback.java @@ -21,7 +21,9 @@ package org.olat.modules.qpool.security; import org.olat.modules.qpool.QuestionItemSecurityCallback; import org.olat.modules.qpool.QuestionItemView; +import org.olat.modules.qpool.QuestionPoolModule; import org.olat.modules.qpool.ui.QuestionItemsSource; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -37,8 +39,12 @@ public class ProcesslessSecurityCallback implements QuestionItemSecurityCallback private QuestionItemView itemView; private QuestionItemsSource questionItemSource; - private boolean isAdmin = false; + private boolean admin = false; + private boolean poolAdmin = false; + @Autowired + private QuestionPoolModule qpoolModule; + @Override public void setQuestionItemView(QuestionItemView itemView) { this.itemView = itemView; @@ -51,22 +57,31 @@ public class ProcesslessSecurityCallback implements QuestionItemSecurityCallback @Override public void setAdmin(boolean admin) { - this.isAdmin = admin; + this.admin = admin; + } + + @Override + public void setPoolAdmin(boolean poolAdmin) { + this.poolAdmin = poolAdmin; } @Override public boolean canEditQuestion() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); } @Override public boolean canEditMetadata() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin + || itemView.isAuthor() + || itemView.isEditableInPool() + || itemView.isEditableInShare() + || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditMetadata()); } @Override public boolean canRemoveTaxonomy() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); } @Override @@ -86,38 +101,58 @@ public class ProcesslessSecurityCallback implements QuestionItemSecurityCallback @Override public boolean canSetDraft() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin + || itemView.isAuthor() + || itemView.isEditableInPool() + || itemView.isEditableInShare() + || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditStatus()); } @Override public boolean canSetRevised() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin + || itemView.isAuthor() + || itemView.isEditableInPool() + || itemView.isEditableInShare() + || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditStatus()); } @Override public boolean canSetReview() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin + || itemView.isAuthor() + || itemView.isEditableInPool() + || itemView.isEditableInShare() + || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditStatus()); } @Override public boolean canSetFinal() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin + || itemView.isAuthor() + || itemView.isEditableInPool() + || itemView.isEditableInShare() + || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditStatus()); } @Override public boolean canSetEndOfLife() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin + || itemView.isAuthor() + || itemView.isEditableInPool() + || itemView.isEditableInShare() + || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditStatus()); } @Override public boolean canDelete() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); } @Override public boolean canRemove() { return questionItemSource.isRemoveEnabled() - && (isAdmin || itemView.isAuthor()); + && (admin || itemView.isAuthor()); } @Override @@ -127,7 +162,7 @@ public class ProcesslessSecurityCallback implements QuestionItemSecurityCallback @Override public boolean canChangeVersion() { - return isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); + return admin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare(); } } diff --git a/src/main/java/org/olat/modules/qpool/security/QPoolSecurityCallbackFactory.java b/src/main/java/org/olat/modules/qpool/security/QPoolSecurityCallbackFactory.java index 3f775f9e078..9c1aaded4cc 100644 --- a/src/main/java/org/olat/modules/qpool/security/QPoolSecurityCallbackFactory.java +++ b/src/main/java/org/olat/modules/qpool/security/QPoolSecurityCallbackFactory.java @@ -42,8 +42,8 @@ public class QPoolSecurityCallbackFactory { @Autowired private QuestionPoolModule qpoolModule; - public QuestionItemSecurityCallback createQuestionItemSecurityCallback(QuestionItemView itemView, QuestionItemsSource questionItemSource, - boolean isOLATAdmin) { + public QuestionItemSecurityCallback createQuestionItemSecurityCallback(QuestionItemView itemView, + QuestionItemsSource questionItemSource, Roles roles) { QuestionItemSecurityCallback securityCallback; if (qpoolModule.isReviewProcessEnabled()) { securityCallback = CoreSpringFactory.getImpl(ReviewProcessSecurityCallback.class); @@ -52,17 +52,15 @@ public class QPoolSecurityCallbackFactory { } securityCallback.setQuestionItemView(itemView); securityCallback.setQuestionItemSource(questionItemSource); - securityCallback.setAdmin(isOLATAdmin); + securityCallback.setAdmin(roles.isOLATAdmin()); + securityCallback.setPoolAdmin(roles.isPoolAdmin()); return securityCallback; } public QPoolSecurityCallback createQPoolSecurityCallback(Roles roles) { - QPoolSecurityCallback securityCallback; - if (roles.isOLATAdmin()) { - securityCallback = CoreSpringFactory.getImpl(AdministratorQPoolSecurityCallback.class); - } else { - securityCallback = CoreSpringFactory.getImpl(RegularQPoolSecurityCallback.class); - } + QPoolSecurityCallback securityCallback = CoreSpringFactory.getImpl(QPoolSecurityCallbackImpl.class); + securityCallback.setAdmin(roles.isOLATAdmin()); + securityCallback.setPoolAdmin(roles.isPoolAdmin()); return securityCallback; } diff --git a/src/main/java/org/olat/modules/qpool/security/AdministratorQPoolSecurityCallback.java b/src/main/java/org/olat/modules/qpool/security/QPoolSecurityCallbackImpl.java similarity index 57% rename from src/main/java/org/olat/modules/qpool/security/AdministratorQPoolSecurityCallback.java rename to src/main/java/org/olat/modules/qpool/security/QPoolSecurityCallbackImpl.java index 7c5d33c8cad..bde9a0c40a3 100644 --- a/src/main/java/org/olat/modules/qpool/security/AdministratorQPoolSecurityCallback.java +++ b/src/main/java/org/olat/modules/qpool/security/QPoolSecurityCallbackImpl.java @@ -33,11 +33,24 @@ import org.springframework.stereotype.Component; */ @Component @Scope("prototype") -public class AdministratorQPoolSecurityCallback implements QPoolSecurityCallback { +public class QPoolSecurityCallbackImpl implements QPoolSecurityCallback { + private boolean admin = false; + private boolean poolAdmin = false; + @Autowired private QuestionPoolModule qpoolModule; - + + @Override + public void setAdmin(boolean admin) { + this.admin = admin; + } + + @Override + public void setPoolAdmin(boolean poolAdmin) { + this.poolAdmin = poolAdmin; + } + @Override public boolean canUseCollections() { return qpoolModule.isCollectionsEnabled(); @@ -59,9 +72,38 @@ public class AdministratorQPoolSecurityCallback implements QPoolSecurityCallback } @Override - public boolean canAdmin() { - return true; + public boolean canEditAllQuestions() { + return admin || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditMetadata()); + } + + @Override + public boolean canConfigReviewProcess() { + return admin || (poolAdmin && qpoolModule.isPoolAdminAllowedToConfigReviewProcess()); + } + + @Override + public boolean canConfigTaxonomies() { + return admin || (poolAdmin && qpoolModule.isPoolAdminAllowedToConfigTaxonomy()); } + @Override + public boolean canConfigPools() { + return admin || (poolAdmin && qpoolModule.isPoolAdminAllowedToConfigPools()); + } + + @Override + public boolean canConfigItemTypes() { + return admin || (poolAdmin && qpoolModule.isPoolAdminAllowedToConfigItemTypes()); + } + + @Override + public boolean canConfigEducationalContext() { + return admin || (poolAdmin && qpoolModule.isPoolAdminAllowedToConfigEducationalContext()); + } + + @Override + public boolean canConfigLicences() { + return admin || (poolAdmin && qpoolModule.isPoolAdminAllowedToConfigLicenses()); + } } diff --git a/src/main/java/org/olat/modules/qpool/security/RegularQPoolSecurityCallback.java b/src/main/java/org/olat/modules/qpool/security/RegularQPoolSecurityCallback.java deleted file mode 100644 index dd5bac65a24..00000000000 --- a/src/main/java/org/olat/modules/qpool/security/RegularQPoolSecurityCallback.java +++ /dev/null @@ -1,66 +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.modules.qpool.security; - -import org.olat.modules.qpool.QPoolSecurityCallback; -import org.olat.modules.qpool.QuestionPoolModule; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -/** - * - * Initial date: 05.12.2017<br> - * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com - * - */ -@Component -@Scope("prototype") -public class RegularQPoolSecurityCallback implements QPoolSecurityCallback { - - @Autowired - private QuestionPoolModule qpoolModule; - - @Override - public boolean canUseCollections() { - return qpoolModule.isCollectionsEnabled(); - } - - @Override - public boolean canUsePools() { - return qpoolModule.isPoolsEnabled(); - } - - @Override - public boolean canUseGroups() { - return qpoolModule.isSharesEnabled(); - } - - @Override - public boolean canUseReviewProcess() { - return qpoolModule.isReviewProcessEnabled(); - } - - @Override - public boolean canAdmin() { - return false; - } - -} diff --git a/src/main/java/org/olat/modules/qpool/security/ReviewProcessSecurityCallback.java b/src/main/java/org/olat/modules/qpool/security/ReviewProcessSecurityCallback.java index 6d95b93abb5..b5bcc7f8675 100644 --- a/src/main/java/org/olat/modules/qpool/security/ReviewProcessSecurityCallback.java +++ b/src/main/java/org/olat/modules/qpool/security/ReviewProcessSecurityCallback.java @@ -24,6 +24,7 @@ import java.util.Collection; import org.olat.modules.qpool.QuestionItemSecurityCallback; import org.olat.modules.qpool.QuestionItemView; +import org.olat.modules.qpool.QuestionPoolModule; import org.olat.modules.qpool.QuestionStatus; import org.olat.modules.qpool.ReviewService; import org.olat.modules.qpool.ui.QuestionItemsSource; @@ -49,8 +50,11 @@ public class ReviewProcessSecurityCallback implements QuestionItemSecurityCallba private QuestionItemView itemView; private QuestionItemsSource questionItemSource; - private boolean isAdmin = false; + private boolean admin = false; + private boolean poolAdmin = false; + @Autowired + private QuestionPoolModule qpoolModule; @Autowired private ReviewService reviewService; @@ -66,38 +70,43 @@ public class ReviewProcessSecurityCallback implements QuestionItemSecurityCallba @Override public void setAdmin(boolean admin) { - this.isAdmin = admin; + this.admin = admin; + } + + @Override + public void setPoolAdmin(boolean poolAdmin) { + this.poolAdmin = poolAdmin; } @Override public boolean canEditQuestion() { return reviewService.isEditableQuestionStatus(itemView.getQuestionStatus()) - && (isAdmin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare()) ; + && (admin || itemView.isAuthor() || itemView.isEditableInPool() || itemView.isEditableInShare()) ; } @Override public boolean canEditMetadata() { - return isAdmin || itemView.isAuthor() || itemView.isManager(); + return admin || itemView.isAuthor() || itemView.isManager() || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditMetadata()); } @Override public boolean canRemoveTaxonomy() { return QuestionStatus.draft.equals(itemView.getQuestionStatus()) - && (isAdmin || itemView.isAuthor() || itemView.isManager()); + && (admin || itemView.isAuthor() || itemView.isManager()); } @Override public boolean canStartReview() { return itemView.isReviewableFormat() && reviewService.isEditableQuestionStatus(itemView.getQuestionStatus()) - && (isAdmin || itemView.isAuthor()); + && (admin || itemView.isAuthor()); } @Override public boolean canReviewNotStartable() { return !itemView.isReviewableFormat() && reviewService.isEditableQuestionStatus(itemView.getQuestionStatus()) - && (isAdmin || itemView.isAuthor()); + && (admin || itemView.isAuthor()); } @Override @@ -109,13 +118,13 @@ public class ReviewProcessSecurityCallback implements QuestionItemSecurityCallba @Override public boolean canSetDraft() { - return isAdmin; + return admin; } @Override public boolean canSetRevised() { return itemView.isReviewableFormat() - && (isAdmin || itemView.isManager()); + && (admin || itemView.isManager() || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditStatus())); } @Override @@ -126,24 +135,24 @@ public class ReviewProcessSecurityCallback implements QuestionItemSecurityCallba @Override public boolean canSetFinal() { return itemView.isReviewableFormat() - && (isAdmin || itemView.isManager()); + && (admin || itemView.isManager() || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditStatus())); } @Override public boolean canSetEndOfLife() { - return isAdmin || itemView.isManager(); + return admin || itemView.isManager() || (poolAdmin && qpoolModule.isPoolAdminAllowedToEditStatus()); } @Override public boolean canDelete() { return DELETABLE_STATES.contains(itemView.getQuestionStatus()) - && (isAdmin || itemView.isManager()); + && (admin || itemView.isManager()); } @Override public boolean canRemove() { return questionItemSource.isRemoveEnabled() - && (isAdmin || itemView.isAuthor()); + && (admin || itemView.isAuthor()); } @Override diff --git a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java index c479afa648a..3c01421d8f4 100644 --- a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java +++ b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java @@ -57,6 +57,7 @@ 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.OLATResourceable; +import org.olat.core.id.Roles; import org.olat.core.util.StringHelper; import org.olat.core.util.event.EventBus; import org.olat.core.util.event.GenericEventListener; @@ -105,7 +106,7 @@ public abstract class AbstractItemListController extends FormBasicController private EventBus eventBus; private QuestionItemsSource itemsSource; - private final boolean isOLATAdmin; + private final Roles roles; public AbstractItemListController(UserRequest ureq, WindowControl wControl, QPoolSecurityCallback securityCallback, QuestionItemsSource source, String key) { @@ -129,7 +130,7 @@ public abstract class AbstractItemListController extends FormBasicController this.securityCallback = securityCallback; this.prefsKey = key; this.itemsSource = source; - this.isOLATAdmin = ureq.getUserSession().getRoles().isOLATAdmin(); + this.roles = ureq.getUserSession().getRoles(); this.restrictToFormat = restrictToFormat; eventBus = ureq.getUserSession().getSingleUserEventCenter(); @@ -456,7 +457,7 @@ public abstract class AbstractItemListController extends FormBasicController protected ItemRow forgeRow(QuestionItemView item) { boolean marked = item.isMarked(); QuestionItemSecurityCallback securityCallback = qpoolSecurityCallbackFactory - .createQuestionItemSecurityCallback(item, getSource(), isOLATAdmin); + .createQuestionItemSecurityCallback(item, getSource(), roles); ItemRow row = new ItemRow(item, securityCallback); FormLink markLink = uifactory.addFormLink("mark_" + row.getKey(), "mark", " ", null, null, Link.NONTRANSLATED); markLink.setIconLeftCSS(marked ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE); @@ -469,7 +470,7 @@ public abstract class AbstractItemListController extends FormBasicController protected ItemRow wrapNewItem(QuestionItem item) { ItemWrapper itemWrapper = ItemWrapper.builder(item).setAuthor(true).create(); QuestionItemSecurityCallback securityCallback = qpoolSecurityCallbackFactory - .createQuestionItemSecurityCallback(itemWrapper, getSource(), isOLATAdmin); + .createQuestionItemSecurityCallback(itemWrapper, getSource(), roles); return new ItemRow(itemWrapper, securityCallback); } } diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/item_list_overview.html b/src/main/java/org/olat/modules/qpool/ui/_content/item_list_overview.html index 033fc058937..29f9eee1ab3 100644 --- a/src/main/java/org/olat/modules/qpool/ui/_content/item_list_overview.html +++ b/src/main/java/org/olat/modules/qpool/ui/_content/item_list_overview.html @@ -1,5 +1,5 @@ <h4> - <i class="o_icon o_icon-fw o_icon_qpool"> </i> + <i class="o_icon o_icon-fw o_icon_qpool"> </i> $r.translate("menu.pools.main") </h4> <div class="clearfix"> diff --git a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties index a48d80bb09d..62d0db743aa 100644 --- a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_de.properties @@ -108,6 +108,7 @@ menu.admin.levels.alt=Stufe menu.admin.licenses=Lizenz menu.admin.licenses.alt=Lizenz menu.admin.pools=Pool-Verwaltung +menu.admin.review.process=Beurteilungsprozess menu.admin.studyfields=Fachbereich menu.admin.studyfields.alt=Fachbereich menu.admin.types=Fragetyp diff --git a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_en.properties index c700b6eebd5..a3eff9954f2 100644 --- a/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/qpool/ui/_i18n/LocalStrings_en.properties @@ -108,6 +108,7 @@ menu.admin.levels.alt=Level menu.admin.licenses=License menu.admin.licenses.alt=License menu.admin.pools=Pool administration +menu.admin.review.process=Review Process menu.admin.studyfields=Subject menu.admin.studyfields.alt=Subject menu.admin.types=Type diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/QuestionPoolAdminConfigurationController.java b/src/main/java/org/olat/modules/qpool/ui/admin/QuestionPoolAdminConfigurationController.java index f510b2d15c9..714abd69476 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/QuestionPoolAdminConfigurationController.java +++ b/src/main/java/org/olat/modules/qpool/ui/admin/QuestionPoolAdminConfigurationController.java @@ -19,7 +19,9 @@ */ package org.olat.modules.qpool.ui.admin; +import java.util.Collection; import java.util.List; +import java.util.stream.Stream; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; @@ -48,12 +50,31 @@ import org.springframework.beans.factory.annotation.Autowired; */ public class QuestionPoolAdminConfigurationController extends FormBasicController { - private static final String[] onKeys = new String[] { "on" }; + private static final String[] onKeys = { "on" }; + private static final String POOL_MANAGER_EDIT_METADATA = "pool.manager.edit.matadata"; + private static final String POOL_MANAGER_EDIT_STATUS = "pool.manager.edit.status"; + private static final String POOL_MANAGER_REVIEW_PROCESS = "pool.manager.review.process"; + private static final String POOL_MANAGER_TAXONOMY = "pool.manager.taxonomy"; + private static final String POOL_MANAGER_POOLS = "pool.manager.pools"; + private static final String POOL_MANAGER_ITEM_TYPES = "pool.manager.item.types"; + private static final String POOL_MANAGER_EDUCATIONAL_CONTEXT = "pool.manager.educational.context"; + private static final String POOL_MANAGER_LICENSES = "pool.manager.licenses"; + private static final String[] POOL_MANAGER_RIGHTS_KEYS = { + POOL_MANAGER_EDIT_METADATA, + POOL_MANAGER_EDIT_STATUS, + POOL_MANAGER_REVIEW_PROCESS, + POOL_MANAGER_TAXONOMY, + POOL_MANAGER_POOLS, + POOL_MANAGER_ITEM_TYPES, + POOL_MANAGER_EDUCATIONAL_CONTEXT, + POOL_MANAGER_LICENSES + }; private MultipleSelectionElement reviewProcessEnabledEl; private MultipleSelectionElement collectionsEnabledEl; private MultipleSelectionElement poolsEnabledEl; private MultipleSelectionElement sharesEnabledEl; + private MultipleSelectionElement poolManagerRightsEl; private SingleSelection taxonomyTreeEl; private CloseableModalController closeableModalCtrl; @@ -69,36 +90,36 @@ public class QuestionPoolAdminConfigurationController extends FormBasicControlle private QPoolService qpoolService; public QuestionPoolAdminConfigurationController(UserRequest ureq, WindowControl wControl) { - super(ureq, wControl); + super(ureq, wControl, "admin_config"); initForm(ureq); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - setFormTitle("admin.configuration.title"); + FormLayoutContainer moduleCont = FormLayoutContainer.createDefaultFormLayout("module", getTranslator()); + moduleCont.setFormTitle(translate("admin.configuration.title")); + moduleCont.setRootForm(mainForm); + formLayout.add("module", moduleCont); String[] onValues = new String[] { translate("on") }; - reviewProcessEnabledEl = uifactory.addCheckboxesHorizontal("review.process.enabled", formLayout, onKeys, onValues); + reviewProcessEnabledEl = uifactory.addCheckboxesHorizontal("review.process.enabled", moduleCont, onKeys, onValues); reviewProcessEnabledEl.addActionListener(FormEvent.ONCHANGE); if (qpoolModule.isReviewProcessEnabled()) { reviewProcessEnabledEl.select(onKeys[0], true); } - collectionsEnabledEl = uifactory.addCheckboxesHorizontal("collections.enabled", formLayout, onKeys, onValues); - collectionsEnabledEl.addActionListener(FormEvent.ONCHANGE); + collectionsEnabledEl = uifactory.addCheckboxesHorizontal("collections.enabled", moduleCont, onKeys, onValues); if (qpoolModule.isCollectionsEnabled()) { collectionsEnabledEl.select(onKeys[0], true); } - poolsEnabledEl = uifactory.addCheckboxesHorizontal("pools.enabled", formLayout, onKeys, onValues); - poolsEnabledEl.addActionListener(FormEvent.ONCHANGE); + poolsEnabledEl = uifactory.addCheckboxesHorizontal("pools.enabled", moduleCont, onKeys, onValues); if (qpoolModule.isPoolsEnabled()) { poolsEnabledEl.select(onKeys[0], true); } - sharesEnabledEl = uifactory.addCheckboxesHorizontal("shares.enabled", formLayout, onKeys, onValues); - sharesEnabledEl.addActionListener(FormEvent.ONCHANGE); + sharesEnabledEl = uifactory.addCheckboxesHorizontal("shares.enabled", moduleCont, onKeys, onValues); if (qpoolModule.isSharesEnabled()) { sharesEnabledEl.select(onKeys[0], true); } @@ -115,7 +136,7 @@ public class QuestionPoolAdminConfigurationController extends FormBasicControlle } String selectedTaxonomyQPoolKey = qpoolModule.getTaxonomyQPoolKey(); - taxonomyTreeEl = uifactory.addDropdownSingleselect("selected.taxonomy.tree", formLayout, taxonomyKeys, taxonomyValues, null); + taxonomyTreeEl = uifactory.addDropdownSingleselect("selected.taxonomy.tree", moduleCont, taxonomyKeys, taxonomyValues, null); taxonomyTreeEl.setEnabled(false); if(StringHelper.containsNonWhitespace(selectedTaxonomyQPoolKey)) { for(String taxonomyKey:taxonomyKeys) { @@ -125,11 +146,36 @@ public class QuestionPoolAdminConfigurationController extends FormBasicControlle } } + FormLayoutContainer poolManagerRightsCont = FormLayoutContainer.createDefaultFormLayout("poolManagerRights", getTranslator()); + poolManagerRightsCont.setFormTitle(translate("admin.pool.manager.title")); + poolManagerRightsCont.setRootForm(mainForm); + formLayout.add("poolManagerRights", poolManagerRightsCont); + + poolManagerRightsEl = uifactory.addCheckboxesVertical("pool.manager.allowed", poolManagerRightsCont, + POOL_MANAGER_RIGHTS_KEYS, translateKeys(POOL_MANAGER_RIGHTS_KEYS), 1); + poolManagerRightsEl.select(POOL_MANAGER_EDIT_METADATA, qpoolModule.isPoolAdminAllowedToEditMetadata()); + poolManagerRightsEl.select(POOL_MANAGER_EDIT_STATUS, qpoolModule.isPoolAdminAllowedToEditStatus()); + poolManagerRightsEl.select(POOL_MANAGER_REVIEW_PROCESS, qpoolModule.isPoolAdminAllowedToConfigReviewProcess()); + poolManagerRightsEl.select(POOL_MANAGER_TAXONOMY, qpoolModule.isPoolAdminAllowedToConfigTaxonomy()); + poolManagerRightsEl.select(POOL_MANAGER_POOLS, qpoolModule.isPoolAdminAllowedToConfigPools()); + poolManagerRightsEl.select(POOL_MANAGER_ITEM_TYPES, qpoolModule.isPoolAdminAllowedToConfigItemTypes()); + poolManagerRightsEl.select(POOL_MANAGER_EDUCATIONAL_CONTEXT, qpoolModule.isPoolAdminAllowedToConfigEducationalContext()); + poolManagerRightsEl.select(POOL_MANAGER_LICENSES, qpoolModule.isPoolAdminAllowedToConfigLicenses()); + + FormLayoutContainer buttonsWrapperCont = FormLayoutContainer.createDefaultFormLayout("global", getTranslator()); + buttonsWrapperCont.setRootForm(mainForm); + formLayout.add("buttonsWrapper", buttonsWrapperCont); FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); - formLayout.add(buttonsCont); + buttonsWrapperCont.add(buttonsCont); uifactory.addFormSubmitButton("save", buttonsCont); } + private String[] translateKeys(String[] keys) { + return Stream.of(keys) + .map(key -> getTranslator().translate(key)) + .toArray(String[]::new); + } + @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if (reviewProcessEnabledEl == source) { @@ -192,6 +238,24 @@ public class QuestionPoolAdminConfigurationController extends FormBasicControlle String selectedTaxonomyQPoolKey = taxonomyTreeEl.getSelectedKey(); qpoolModule.setTaxonomyQPoolKey(selectedTaxonomyQPoolKey); + + Collection<String> selectedPoolManagerRights = poolManagerRightsEl.getSelectedKeys(); + boolean poolAdminAllowedToEditMetadata = selectedPoolManagerRights.contains(POOL_MANAGER_EDIT_METADATA); + qpoolModule.setPoolAdminAllowedToEditMetadata(poolAdminAllowedToEditMetadata); + boolean poolAdminAllowedToEditStatus = selectedPoolManagerRights.contains(POOL_MANAGER_EDIT_STATUS); + qpoolModule.setPoolAdminAllowedToEditStatus(poolAdminAllowedToEditStatus); + boolean poolAdminAllowedToConfigReviewProcess = selectedPoolManagerRights.contains(POOL_MANAGER_REVIEW_PROCESS); + qpoolModule.setPoolAdminAllowedToConfigReviewProcess(poolAdminAllowedToConfigReviewProcess ); + boolean poolAdminAllowedToConfigTaxonomy = selectedPoolManagerRights.contains(POOL_MANAGER_TAXONOMY); + qpoolModule.setPoolAdminAllowedToConfigTaxonomy(poolAdminAllowedToConfigTaxonomy); + boolean poolAdminAllowedToConfigPools = selectedPoolManagerRights.contains(POOL_MANAGER_POOLS); + qpoolModule.setPoolAdminAllowedToConfigPools(poolAdminAllowedToConfigPools); + boolean poolAdminAllowedToConfigItemTypes = selectedPoolManagerRights.contains(POOL_MANAGER_ITEM_TYPES); + qpoolModule.setPoolAdminAllowedToConfigItemTypes(poolAdminAllowedToConfigItemTypes); + boolean poolAdminAllowedToConfigEducationalContext = selectedPoolManagerRights.contains(POOL_MANAGER_EDUCATIONAL_CONTEXT); + qpoolModule.setPoolAdminAllowedToConfigEducationalContext(poolAdminAllowedToConfigEducationalContext); + boolean poolAdminAllowedToConfigLicenses = selectedPoolManagerRights.contains(POOL_MANAGER_LICENSES); + qpoolModule.setPoolAdminAllowedToConfigLicenses(poolAdminAllowedToConfigLicenses); } @Override diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/_content/admin_config.html b/src/main/java/org/olat/modules/qpool/ui/admin/_content/admin_config.html new file mode 100644 index 00000000000..52ad99a8004 --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/admin/_content/admin_config.html @@ -0,0 +1,3 @@ +$r.render("module") +$r.render("poolManagerRights") +$r.render("buttonsWrapper") \ No newline at end of file diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties index cd9572d6d12..88dfd21e4d3 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_de.properties @@ -3,6 +3,7 @@ add.taxonomyLevel=Fachbereich erstellen admin.configuration.title=Fragenpool admin.levels.intro=Erstellen Sie die verf\u00FCgbaren Stufen die f\u00FCr Ihr Ausbildungslevel Sinn machen. Beispiele f\u00FCr Stufen im schulischen Kontext sind\: Unterstufe, Oberstufe, Gymnasium, Bachelor, Master. In einem Unternehmenskontext k\u00F6nnten Stufen so aussehen\: ohne Berufsausbildung, mit Berufsausbildung, F\u00FChrungsfunktion, Administration, Kader, Management admin.licenses.intro=Erstellen Sie zus\u00E4tzliche Lizenztypen wenn die Standard Lizenztypen von OpenOLAT nicht gen\u00FCgen. Die Standard Lizenztypen k\u00F6nnen nicht gel\u00F6scht werden. +admin.pool.manager.title=Rechte Poolverwalter admin.pools.intro=Erstellen Sie einen oder mehrere Fragenpools. Ein Fragenpool ist eine Fragendatenbank die allen Autoren des Systems f\u00FCr den Austausch von Fragen zur Verf\u00FCgung steht (\u00D6ffentlich). Optional l\u00E4sst sich ein Fragenpool auch auf einige wenige Autoren einschr\u00E4nken, z.B. die Mitarbeiter einer Abteilung (Nicht \u00F6ffentlich). admin.review.process.decision.type=Beurteilungsmethode admin.review.process.title=Beurteilungsprozess @@ -43,6 +44,15 @@ license.key=Lizenz lower.limit=Untergrenze f\u00FCr positive Beurteilung lower.limit.provider.name=Untergrenze number.of.ratings=Anzahl Beurteilungen pro Frage +pool.manager.allowed=Der Poolverwalter darf +pool.manager.edit.matadata=alle Fragen sehen und die Metadaten bearbeiten +pool.manager.edit.status=den Status einer Frage beliebig \u00E4ndern +pool.manager.educational.context=die Einstellungen "$:\segment.educational.context" bearbeiten +pool.manager.licenses=die Einstellungen "$:\segment.licenses" bearbeiten +pool.manager.item.types=die Einstellungen "$:\segment.item.types" bearbeiten +pool.manager.pools=die Einstellungen "$:\segment.pools" bearbeiten +pool.manager.review.process=die Einstellungen "$:\segment.review.process" bearbeiten +pool.manager.taxonomy=die Einstellungen "$:\segment.taxonomy" bearbeiten pools.enabled=Pools reset.status=Alle Fragen in den Status "draft" zur\u00FCcksetzen. review.process.confirm.enable.button=Einschalten diff --git a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_en.properties index b1813d49432..dc4a4e4e2bf 100644 --- a/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/qpool/ui/admin/_i18n/LocalStrings_en.properties @@ -3,6 +3,7 @@ add.taxonomyLevel=Create subject admin.configuration.title=Question bank admin.levels.intro=Create those levels that apply to your organisations educational level. Examples for levels in an academic context could be elementary school, middle school, high school, bachelor, master. Within a corporation context, levels could be the following\: without apprenticeship, with vocational training, administration, middle management, CO admin.licenses.intro=You can create more license types if the default license types are not sufficient. Please note that the default licenses cannot be deleted. +admin.pool.manager.title=Rights pool manager admin.pools.intro=Create one or more question pools. A pool is an question bank that allows all users with author rights the exchange of question items (public access). You can also opt for a pool with only a select few authors, e.g. a departments' staff (private access). admin.review.process.decision.type=Decision method admin.review.process.title=Review process @@ -42,6 +43,15 @@ license.id=ID license.key=License lower.limit=Lower limit for positive decision number.of.ratings=Number of ratings per question +pool.manager.allowed=The pool manager is allowed to +pool.manager.edit.matadata=see all questions and edit the metadata +pool.manager.edit.status=change the status of a question +pool.manager.educational.context=edit the settings "$:\segment.educational.context" +pool.manager.licenses=edit the settings "$:\segment.licenses" +pool.manager.item.types=edit the settings "$:\segment.item.types" +pool.manager.pools=edit the settings "$:\segment.pools" +pool.manager.review.process=edit the settings "$:\segment.review.process" +pool.manager.taxonomy=edit the settings "$:\segment.taxonomy" pools.enabled=Pools reset.status=Reset all questions to state "draft". review.process.confirm.enable.button=Enable diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/ExtendedSearchController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/ExtendedSearchController.java index 4a1c9da9455..7db4e1da0ef 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/ExtendedSearchController.java +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/ExtendedSearchController.java @@ -68,6 +68,7 @@ public class ExtendedSearchController extends FormBasicController implements Ext private ExtendedSearchPrefs prefs; private boolean enabled = true; + @Autowired private QPoolService qpoolService; @Autowired diff --git a/src/main/java/org/olat/modules/qpool/ui/tree/QuestionPoolMenuTreeModel.java b/src/main/java/org/olat/modules/qpool/ui/tree/QuestionPoolMenuTreeModel.java index beab2655ca0..602a8ded935 100644 --- a/src/main/java/org/olat/modules/qpool/ui/tree/QuestionPoolMenuTreeModel.java +++ b/src/main/java/org/olat/modules/qpool/ui/tree/QuestionPoolMenuTreeModel.java @@ -231,11 +231,14 @@ public class QuestionPoolMenuTreeModel extends GenericTreeModel implements DnDTr } //administration - if(securityCallback.canAdmin()) { - TreeNode adminNode = new AdministrationTreeNode(translator.translate("menu.admin")); - rootNode.addChild(adminNode); - buildAdminSubTreeModel(adminNode); + TreeNode adminNode = new AdministrationTreeNode(translator.translate("menu.admin")); + rootNode.addChild(adminNode); + buildAdminSubTreeModel(adminNode); + if (adminNode.getChildCount() > 0) { setFirstChildAsDelegate(adminNode); + } else { + // Admin tree node should not be visible if user has no particular admin rights. + rootNode.remove(adminNode); } } @@ -343,23 +346,40 @@ public class QuestionPoolMenuTreeModel extends GenericTreeModel implements DnDTr private void buildAdminSubTreeModel(TreeNode adminNode) { adminNode.removeAllChildren(); - TreeNode node = new AllQuestionsTreeNode(stackPanel, securityCallback, translator.translate("menu.all.questions")); - adminNode.addChild(node); - - node = new TaxonomyAdminTreeNode(translator.translate("menu.admin.studyfields")); - adminNode.addChild(node); + if (securityCallback.canEditAllQuestions()) { + TreeNode node = new AllQuestionsTreeNode(stackPanel, securityCallback, translator.translate("menu.all.questions")); + adminNode.addChild(node); + } - node = new PoolsAdminTreeNode(translator.translate("menu.admin.pools")); - adminNode.addChild(node); + if (securityCallback.canConfigReviewProcess()) { + TreeNode node = new ReviewProcessAdminTreeNode(translator.translate("menu.admin.review.process")); + adminNode.addChild(node); + } - node = new QItemTypesAdminTreeNode(translator.translate("menu.admin.types")); - adminNode.addChild(node); + if (securityCallback.canConfigTaxonomies()) { + TreeNode node = new TaxonomyAdminTreeNode(translator.translate("menu.admin.studyfields")); + adminNode.addChild(node); + } - node = new QEducationalContextsAdminTreeNode(translator.translate("menu.admin.levels")); - adminNode.addChild(node); + if (securityCallback.canConfigPools()) { + TreeNode node = new PoolsAdminTreeNode(translator.translate("menu.admin.pools")); + adminNode.addChild(node); + } + + if (securityCallback.canConfigItemTypes()) { + TreeNode node = new QItemTypesAdminTreeNode(translator.translate("menu.admin.types")); + adminNode.addChild(node); + } + + if (securityCallback.canConfigEducationalContext()) { + TreeNode node = new QEducationalContextsAdminTreeNode(translator.translate("menu.admin.levels")); + adminNode.addChild(node); + } - node = new QLicensesAdminTreeNode(translator.translate("menu.admin.licenses")); - adminNode.addChild(node); + if (securityCallback.canConfigLicences()) { + TreeNode node = new QLicensesAdminTreeNode(translator.translate("menu.admin.licenses")); + adminNode.addChild(node); + } } private void setFirstChildAsDelegate(INode node) { diff --git a/src/main/java/org/olat/modules/qpool/ui/tree/ReviewProcessAdminTreeNode.java b/src/main/java/org/olat/modules/qpool/ui/tree/ReviewProcessAdminTreeNode.java new file mode 100644 index 00000000000..65cecc2f51b --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/ui/tree/ReviewProcessAdminTreeNode.java @@ -0,0 +1,59 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.qpool.ui.tree; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.tree.GenericTreeNode; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.context.BusinessControlFactory; +import org.olat.core.util.resource.OresHelper; +import org.olat.modules.qpool.ui.admin.ReviewProcessAdminController; + +/** + * + * Initial date: 09.01.2018<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class ReviewProcessAdminTreeNode extends GenericTreeNode implements ControllerTreeNode { + + private static final long serialVersionUID = -2738148565868342086L; + + public static final OLATResourceable ORES = OresHelper.createOLATResourceableType("ReviewProcess"); + + private ReviewProcessAdminController controller; + + public ReviewProcessAdminTreeNode(String title) { + super(); + this.setTitle(title); + } + + @Override + public Controller getController(UserRequest ureq, WindowControl wControl) { + if(controller == null) { + WindowControl swControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ureq, ORES, null, + wControl, true); + controller = new ReviewProcessAdminController(ureq, swControl); + } + return controller; + } +} -- GitLab