diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java index 03f454a6d08a955db4d98eb0b57e0bd9c6a87808..f53b3c033f962edefef66d0a60ab69301f09fcf5 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentItemEditorController.java @@ -70,6 +70,8 @@ import org.olat.ims.qti21.ui.editor.interactions.MultipleChoiceEditorController; import org.olat.ims.qti21.ui.editor.interactions.SingleChoiceEditorController; import org.olat.ims.qti21.ui.editor.interactions.TrueFalseEditorController; import org.olat.ims.qti21.ui.editor.interactions.UploadEditorController; +import org.olat.ims.qti21.ui.editor.metadata.MetadataChangedEvent; +import org.olat.ims.qti21.ui.editor.metadata.MetadataController; import org.olat.modules.assessment.AssessmentEntry; import org.olat.modules.assessment.AssessmentService; import org.olat.modules.qpool.QPoolService; @@ -211,11 +213,9 @@ public class AssessmentItemEditorController extends BasicController implements A tabbedPane.addTab(translate("form.pool"), poolEditor); } - metadataCtrl = new MetadataController(ureq, getWindowControl(), metadataBuilder); + metadataCtrl = new MetadataController(ureq, getWindowControl(), metadataBuilder, readOnly); listenTo(metadataCtrl); - if(metadataCtrl.hasMetadata()) { - tabbedPane.addTab(translate("form.metadata"), metadataCtrl); - } + tabbedPane.addTab(translate("form.metadata"), metadataCtrl); } putInitialPanel(mainVC); @@ -597,6 +597,11 @@ public class AssessmentItemEditorController extends BasicController implements A if(event instanceof DetachFromPoolEvent) { fireEvent(ureq, event); } + } else if(metadataCtrl == source) { + if(event instanceof MetadataChangedEvent) { + doBuildAndCommitMetadata(); + fireEvent(ureq, event); + } } super.event(ureq, source, event); } diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java index 9facae8af191f76f9bc2c66850cb9f3394106ded..18b7ddfdb3126cd041224b8821cedbba10ee2da4 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java @@ -121,6 +121,7 @@ import org.olat.ims.qti21.ui.editor.events.AssessmentTestPartEvent; import org.olat.ims.qti21.ui.editor.events.DetachFromPoolEvent; import org.olat.ims.qti21.ui.editor.events.SelectEvent; import org.olat.ims.qti21.ui.editor.events.SelectEvent.SelectionTarget; +import org.olat.ims.qti21.ui.editor.metadata.MetadataChangedEvent; import org.olat.ims.qti21.ui.editor.overview.AssessmentTestOverviewConfigurationController; import org.olat.imscp.xml.manifest.FileType; import org.olat.imscp.xml.manifest.ResourceType; @@ -473,6 +474,8 @@ public class AssessmentTestComposerController extends MainLayoutBasicController } else if(event instanceof DetachFromPoolEvent) { DetachFromPoolEvent dfpe = (DetachFromPoolEvent)event; doDetachItemFromPool(ureq, dfpe.getItemRef()); + } else if(event instanceof MetadataChangedEvent) { + doSaveManifest(); } else if(selectQItemCtrl == source) { cmc.deactivate(); cleanUp(); diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/MetadataController.java b/src/main/java/org/olat/ims/qti21/ui/editor/MetadataController.java deleted file mode 100644 index a66705e1d2a63f67033bb1e761e6b55993176734..0000000000000000000000000000000000000000 --- a/src/main/java/org/olat/ims/qti21/ui/editor/MetadataController.java +++ /dev/null @@ -1,100 +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.ims.qti21.ui.editor; - -import org.olat.core.gui.UserRequest; -import org.olat.core.gui.components.form.flexible.FormItemContainer; -import org.olat.core.gui.components.form.flexible.impl.FormBasicController; -import org.olat.core.gui.control.Controller; -import org.olat.core.gui.control.WindowControl; -import org.olat.core.util.StringHelper; -import org.olat.core.util.Util; -import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder; -import org.olat.modules.qpool.manager.MetadataConverterHelper; -import org.olat.modules.qpool.model.LOMDuration; -import org.olat.modules.qpool.ui.QuestionsController; - -/** - * - * Initial date: 8 janv. 2020<br> - * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com - * - */ -public class MetadataController extends FormBasicController { - - private final ManifestMetadataBuilder metadataBuilder; - - public MetadataController(UserRequest ureq, WindowControl wControl, ManifestMetadataBuilder metadataBuilder) { - super(ureq, wControl, Util.createPackageTranslator(QuestionsController.class, ureq.getLocale())); - this.metadataBuilder = metadataBuilder; - initForm(ureq); - } - - @Override - protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - String learningTime = metadataBuilder.getEducationalLearningTime(); - LOMDuration duration = MetadataConverterHelper.convertDuration(learningTime); - String formattedLearningTime = formatLearningTime(duration); - uifactory.addStaticTextElement("educational.learningTime", formattedLearningTime, formLayout); - - Integer correctionTime = metadataBuilder.getOpenOLATMetadataCorrectionTime(); - String correctionTimeStr = null; - if(correctionTime != null) { - correctionTimeStr = translate("question.correctionTime.inMinutes", new String[] { correctionTime.toString() }); - } - uifactory.addStaticTextElement("question.correctionTime", correctionTimeStr, formLayout); - } - - public boolean hasMetadata() { - return StringHelper.containsNonWhitespace(metadataBuilder.getEducationalLearningTime()) - || metadataBuilder.getOpenOLATMetadataCorrectionTime() != null; - } - - private String formatLearningTime(LOMDuration duration) { - StringBuilder sb = new StringBuilder(32); - boolean started = appendFormatLearningTime(duration.getDay(), "educational.learningTime.day", sb, false); - started |= appendFormatLearningTime(duration.getHour(), "educational.learningTime.hour", sb, started); - appendFormatLearningTime(duration.getMinute(), "educational.learningTime.minute", sb, started); - appendFormatLearningTime(duration.getSeconds(), "educational.learningTime.second", sb, false); - return sb.toString(); - } - - private boolean appendFormatLearningTime(int value, String unit, StringBuilder sb, boolean append) { - if(append || value > 0) { - if(sb.length() > 0) sb.append(" "); - sb.append(value) - .append(translate(unit)); - } - return value > 0; - } - - @Override - protected void doDispose() { - // - } - - @Override - protected void formOK(UserRequest ureq) { - // - } - - - -} diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/metadata/AssessmentItemEditorMetadataSecurityCallback.java b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/AssessmentItemEditorMetadataSecurityCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..87ad3163934830a36c2cac5fe64b6e8fd38c5a98 --- /dev/null +++ b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/AssessmentItemEditorMetadataSecurityCallback.java @@ -0,0 +1,63 @@ +/** + * <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.ims.qti21.ui.editor.metadata; + +import org.olat.modules.qpool.MetadataSecurityCallback; + +/** + * Allow to change metadata and taxonomy. + * + * Initial date: 8 janv. 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +class AssessmentItemEditorMetadataSecurityCallback implements MetadataSecurityCallback { + + private final boolean readOnly; + + AssessmentItemEditorMetadataSecurityCallback(boolean readOnly) { + this.readOnly = readOnly; + } + + @Override + public boolean canEditMetadata() { + return !readOnly; + } + + @Override + public boolean canRemoveTaxonomy() { + return !readOnly; + } + + @Override + public boolean canChangeVersion() { + return false; + } + + @Override + public boolean canEditAuthors() { + return false; + } + + @Override + public boolean canViewReviews() { + return false; + } +} diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/metadata/AssessmentItemEditorQPoolSecurityCallback.java b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/AssessmentItemEditorQPoolSecurityCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..4803aa0d80cdb6777058130008f7f1b5058dea72 --- /dev/null +++ b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/AssessmentItemEditorQPoolSecurityCallback.java @@ -0,0 +1,102 @@ +/** + * <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.ims.qti21.ui.editor.metadata; + +import org.olat.core.id.Roles; +import org.olat.modules.qpool.QPoolSecurityCallback; + +/** + * + * Initial date: 8 janv. 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class AssessmentItemEditorQPoolSecurityCallback implements QPoolSecurityCallback { + + @Override + public void setRoles(Roles roles) { + // + } + + @Override + public boolean canUseCollections() { + return false; + } + + @Override + public boolean canUsePools() { + return false; + } + + @Override + public boolean canUseGroups() { + return false; + } + + @Override + public boolean canUseReviewProcess() { + return false; + } + + @Override + public boolean canUseTaxonomy() { + return true; + } + + @Override + public boolean canUseEducationalContext() { + return true; + } + + @Override + public boolean canCreateTest() { + return false; + } + + @Override + public boolean canEditAllQuestions() { + return false; + } + + @Override + public boolean canConfigReviewProcess() { + return false; + } + + @Override + public boolean canConfigTaxonomies() { + return false; + } + + @Override + public boolean canConfigPools() { + return false; + } + + @Override + public boolean canConfigItemTypes() { + return false; + } + + @Override + public boolean canConfigEducationalContext() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/metadata/ManifestMetadataItemized.java b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/ManifestMetadataItemized.java new file mode 100644 index 0000000000000000000000000000000000000000..1228f2f63b8e6a6c6d7fabf11f0eb1017207e507 --- /dev/null +++ b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/ManifestMetadataItemized.java @@ -0,0 +1,373 @@ +/** + * <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.ims.qti21.ui.editor.metadata; + +import java.math.BigDecimal; +import java.util.Date; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.util.StringHelper; +import org.olat.ims.qti.qpool.QTIMetadataConverter; +import org.olat.ims.qti21.QTI21Constants; +import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder; +import org.olat.modules.qpool.QPoolService; +import org.olat.modules.qpool.QuestionItem; +import org.olat.modules.qpool.QuestionItemEditable; +import org.olat.modules.qpool.QuestionStatus; +import org.olat.modules.qpool.manager.QEducationalContextDAO; +import org.olat.modules.qpool.manager.QItemTypeDAO; +import org.olat.modules.qpool.model.QEducationalContext; +import org.olat.modules.qpool.model.QItemType; +import org.olat.modules.qpool.model.QLicense; +import org.olat.modules.taxonomy.TaxonomyLevel; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Manifest based implementation of QuestionItem, editable. + * + * Initial date: 8 janv. 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +class ManifestMetadataItemized implements QuestionItem, QuestionItemEditable { + + private final ManifestMetadataBuilder metadataBuilder; + + private final QTIMetadataConverter metadataConverter; + + private String lang; + private String directory; + + private QItemType itemType; + private QEducationalContext context; + private TaxonomyLevel taxonomyLevel; + + @Autowired + private QItemTypeDAO itemTypeDao; + @Autowired + private QPoolService qpoolService; + @Autowired + private QEducationalContextDAO educationalContextDao; + + + public ManifestMetadataItemized(ManifestMetadataBuilder metadataBuilder, String lang) { + CoreSpringFactory.autowireObject(this); + + this.metadataBuilder = metadataBuilder; + this.lang = lang; + metadataConverter = new QTIMetadataConverter(itemTypeDao, educationalContextDao, qpoolService); + if(StringHelper.containsNonWhitespace(metadataBuilder.getClassificationTaxonomy())) { + taxonomyLevel = metadataConverter.toTaxonomy(metadataBuilder.getClassificationTaxonomy()); + } + if(StringHelper.containsNonWhitespace(metadataBuilder.getEducationContext())) { + context = metadataConverter.toEducationalContext(metadataBuilder.getEducationContext()); + } + if(StringHelper.containsNonWhitespace(metadataBuilder.getOpenOLATMetadataQuestionType())) { + itemType = metadataConverter.toType(metadataBuilder.getOpenOLATMetadataQuestionType()); + } + } + + @Override + public Long getKey() { + return null; + } + + @Override + public String getIdentifier() { + return metadataBuilder.getOpenOLATMetadataIdentifier(); + } + + @Override + public String getMasterIdentifier() { + return metadataBuilder.getOpenOLATMetadataMasterIdentifier(); + } + + @Override + public String getTitle() { + return metadataBuilder.getTitle(); + } + + @Override + public String getLanguage() { + return lang; + } + + @Override + public String getKeywords() { + return metadataBuilder.getGeneralKeywords(); + } + + @Override + public void setKeywords(String keywords) { + metadataBuilder.setGeneralKeywords(keywords, lang); + } + + @Override + public void setLanguage(String language) { + this.lang = language; + metadataBuilder.setLanguage(language, language); + } + + @Override + public String getTaxonomyLevelName() { + if(taxonomyLevel != null) { + return taxonomyLevel.getDisplayName(); + } + return metadataBuilder.getClassificationTaxonomy(); + } + + @Override + public String getTaxonomicPath() { + if(taxonomyLevel != null) { + return taxonomyLevel.getMaterializedPathIdentifiers(); + } + return metadataBuilder.getClassificationTaxonomy(); + } + + @Override + public String getTopic() { + return metadataBuilder.getOpenOLATMetadataTopic(); + } + + @Override + public void setTopic(String topic) { + metadataBuilder.setOpenOLATMetadataTopic(topic); + } + + @Override + public String getEducationalContextLevel() { + if(context != null) { + return context.getLevel(); + } + return metadataBuilder.getEducationContext(); + } + + @Override + public String getEducationalLearningTime() { + return metadataBuilder.getEducationalLearningTime(); + } + + @Override + public void setEducationalLearningTime(String time) { + metadataBuilder.setEducationalLearningTime(time); + } + + @Override + public String getItemType() { + return metadataBuilder.getOpenOLATMetadataQuestionType(); + } + + @Override + public BigDecimal getDifficulty() { + Double val = metadataBuilder.getOpenOLATMetadataDifficulty(); + return val == null ? null : BigDecimal.valueOf(val.doubleValue()); + } + + @Override + public void setDifficulty(BigDecimal difficulty) { + metadataBuilder.setOpenOLATMetadataDifficulty(difficulty); + } + + @Override + public BigDecimal getStdevDifficulty() { + Double val = metadataBuilder.getOpenOLATMetadataStandardDeviation(); + return val == null ? null : BigDecimal.valueOf(val.doubleValue()); + } + + @Override + public void setStdevDifficulty(BigDecimal stdevDifficulty) { + metadataBuilder.setOpenOLATMetadataStandardDeviation(stdevDifficulty); + } + + @Override + public BigDecimal getDifferentiation() { + Double val = metadataBuilder.getOpenOLATMetadataDiscriminationIndex(); + return val == null ? null : BigDecimal.valueOf(val.doubleValue()); + } + + @Override + public void setDifferentiation(BigDecimal differentiation) { + metadataBuilder.setOpenOLATMetadataDiscriminationIndex(differentiation); + } + + @Override + public int getNumOfAnswerAlternatives() { + Integer val = metadataBuilder.getOpenOLATMetadataDistractors(); + return val == null ? 0 : val.intValue(); + } + + @Override + public void setNumOfAnswerAlternatives(int numOfAnswerAlternatives) { + metadataBuilder.setOpenOLATMetadataDistractors(Integer.valueOf(numOfAnswerAlternatives)); + } + + @Override + public int getUsage() { + Integer usage = metadataBuilder.getOpenOLATMetadataUsage(); + return usage == null ? 0 : usage.intValue(); + } + + @Override + public void setUsage(int numOfUsage) { + metadataBuilder.setOpenOLATMetadataUsage(Integer.valueOf(numOfUsage)); + } + + @Override + public QuestionStatus getQuestionStatus() { + return null; + } + + @Override + public Date getQuestionStatusLastModified() { + return null; + } + + @Override + public String getFormat() { + return QTI21Constants.QTI_21_FORMAT; + } + + @Override + public Integer getCorrectionTime() { + return metadataBuilder.getOpenOLATMetadataCorrectionTime(); + } + + @Override + public void setCorrectionTime(Integer timeInMinute) { + metadataBuilder.setOpenOLATMetadataCorrectionTime(timeInMinute); + } + + @Override + public Date getLastModified() { + return null; + } + + @Override + public void setLastModified(Date date) { + // + } + + @Override + public Date getCreationDate() { + return null; + } + + @Override + public String getResourceableTypeName() { + return null; + } + + @Override + public Long getResourceableId() { + return null; + } + + @Override + public String getDescription() { + return metadataBuilder.getDescription(); + } + + @Override + public String getCoverage() { + return metadataBuilder.getCoverage(); + } + + @Override + public void setCoverage(String coverage) { + metadataBuilder.setCoverage(coverage, lang); + } + + @Override + public String getAdditionalInformations() { + return metadataBuilder.getOpenOLATMetadataAdditionalInformations(); + } + + @Override + public void setAdditionalInformations(String informations) { + metadataBuilder.setOpenOLATMetadataAdditionalInformations(informations); + } + + @Override + public void setTaxonomyLevel(TaxonomyLevel taxonomyLevel) { + this.taxonomyLevel = taxonomyLevel; + metadataBuilder.setClassificationTaxonomy(getTaxonomicPath(), lang); + } + + @Override + public TaxonomyLevel getTaxonomyLevel() { + return taxonomyLevel; + } + + @Override + public QEducationalContext getEducationalContext() { + return context; + } + + @Override + public void setEducationalContext(QEducationalContext context) { + this.context = context; + metadataBuilder.setEducationalContext(context.getLevel(), lang); + } + + @Override + public QItemType getType() { + return itemType; + } + + @Override + public String getAssessmentType() { + return metadataBuilder.getOpenOLATMetadataAssessmentType(); + } + + @Override + public void setAssessmentType(String type) { + metadataBuilder.setOpenOLATMetadataAssessmentType(type); + } + + @Override + public String getItemVersion() { + return metadataBuilder.getLifecycleVersion(); + } + + @Override + public QLicense getLicense() { + return null; + } + + @Override + public String getCreator() { + return metadataBuilder.getOpenOLATMetadataCreator(); + } + + @Override + public String getEditor() { + return metadataBuilder.getQtiMetadaToolVendor(); + } + + @Override + public String getEditorVersion() { + return metadataBuilder.getQtiMetadataToolVersion(); + } + + @Override + public String getDirectory() { + return directory; + } +} diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/metadata/MetadataChangedEvent.java b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/MetadataChangedEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..418c98e857203db87f17757770969e562109b9ba --- /dev/null +++ b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/MetadataChangedEvent.java @@ -0,0 +1,39 @@ +/** + * <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.ims.qti21.ui.editor.metadata; + +import org.olat.core.gui.control.Event; + +/** + * + * Initial date: 8 janv. 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MetadataChangedEvent extends Event { + + private static final long serialVersionUID = 978018182214795733L; + private static final String METADATA_CHANGED = "metadata-changed"; + + public MetadataChangedEvent() { + super(METADATA_CHANGED); + } + +} diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/metadata/MetadataController.java b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/MetadataController.java new file mode 100644 index 0000000000000000000000000000000000000000..9f3bda553b96efc116285cf5ded6c28b5d212e4f --- /dev/null +++ b/src/main/java/org/olat/ims/qti21/ui/editor/metadata/MetadataController.java @@ -0,0 +1,83 @@ +/** + * <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.ims.qti21.ui.editor.metadata; + +import java.util.Locale; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.util.Util; +import org.olat.ims.qti21.model.xml.ManifestMetadataBuilder; +import org.olat.modules.qpool.MetadataSecurityCallback; +import org.olat.modules.qpool.QPoolSecurityCallback; +import org.olat.modules.qpool.QuestionItem; +import org.olat.modules.qpool.ui.QuestionsController; +import org.olat.modules.qpool.ui.events.QItemEdited; +import org.olat.modules.qpool.ui.metadata.MetadatasController; + +/** + * + * Initial date: 8 janv. 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class MetadataController extends BasicController { + + private MetadatasController metadataCtrl; + + + public MetadataController(UserRequest ureq, WindowControl wControl, + ManifestMetadataBuilder metadataBuilder, boolean readOnly) { + super(ureq, wControl, Util.createPackageTranslator(QuestionsController.class, ureq.getLocale())); + + Locale locale = getLocale(); + QuestionItem item = new ManifestMetadataItemized(metadataBuilder, locale.getLanguage()); + QPoolSecurityCallback qPoolSecurityCallback = new AssessmentItemEditorQPoolSecurityCallback(); + MetadataSecurityCallback metadataScurityCallback = new AssessmentItemEditorMetadataSecurityCallback(readOnly); + + metadataCtrl = new MetadatasController(ureq, wControl, qPoolSecurityCallback, item, metadataScurityCallback, false, true); + listenTo(metadataCtrl); + putInitialPanel(metadataCtrl.getInitialComponent()); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + // + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(metadataCtrl == source) { + if(event instanceof QItemEdited) { + fireEvent(ureq, new MetadataChangedEvent()); + } + } + super.event(ureq, source, event); + } +} diff --git a/src/main/java/org/olat/modules/qpool/QuestionItemEditable.java b/src/main/java/org/olat/modules/qpool/QuestionItemEditable.java new file mode 100644 index 0000000000000000000000000000000000000000..196f622ffda384abae7288509368575a8a8c20ad --- /dev/null +++ b/src/main/java/org/olat/modules/qpool/QuestionItemEditable.java @@ -0,0 +1,68 @@ +/** + * <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; + +import java.math.BigDecimal; + +import org.olat.modules.qpool.model.QEducationalContext; +import org.olat.modules.taxonomy.TaxonomyLevel; + +/** + * + * Initial date: 8 janv. 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface QuestionItemEditable { + + public void setTopic(String topic); + + public void setKeywords(String keywords); + + public void setCoverage(String coverage); + + public void setAdditionalInformations(String informations); + + public void setLanguage(String language); + + public void setAssessmentType(String type); + + public void setEducationalContext(QEducationalContext context); + + public void setTaxonomyLevel(TaxonomyLevel taxonomyLevel); + + + public void setEducationalLearningTime(String time); + + public void setCorrectionTime(Integer timeInMinutes); + + + public void setDifficulty(BigDecimal difficulty); + + public void setStdevDifficulty(BigDecimal stdevDifficulty); + + public void setDifferentiation(BigDecimal differentiation); + + public void setNumOfAnswerAlternatives(int numOfAnswerAlternatives); + + public void setUsage(int usage); + + +} diff --git a/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java b/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java index 94e8d2703c465e65c96fe6aed933107b0b66b2dd..c3762a1968232874d4e033e0cd897b2052173584 100644 --- a/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java +++ b/src/main/java/org/olat/modules/qpool/model/QuestionItemImpl.java @@ -41,6 +41,7 @@ import org.olat.basesecurity.SecurityGroup; import org.olat.basesecurity.SecurityGroupImpl; import org.olat.core.id.Persistable; import org.olat.core.util.StringHelper; +import org.olat.modules.qpool.QuestionItemEditable; import org.olat.modules.qpool.QuestionItemFull; import org.olat.modules.qpool.QuestionStatus; import org.olat.modules.taxonomy.TaxonomyLevel; @@ -54,7 +55,7 @@ import org.olat.modules.taxonomy.model.TaxonomyLevelImpl; @Entity(name="questionitem") @Table(name="o_qp_item") @NamedQuery(name="loadQuestionItemByKey", query="select item from questionitem item where item.key=:itemKey") -public class QuestionItemImpl implements QuestionItemFull, Persistable { +public class QuestionItemImpl implements QuestionItemFull, QuestionItemEditable, Persistable { private static final long serialVersionUID = 6264601750280239307L; @@ -216,6 +217,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return topic; } + @Override public void setTopic(String topic) { this.topic = topic; } @@ -234,6 +236,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return coverage; } + @Override public void setCoverage(String coverage) { this.coverage = coverage; } @@ -243,6 +246,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return additionalInformations; } + @Override public void setAdditionalInformations(String additionalInformations) { this.additionalInformations = additionalInformations; } @@ -252,6 +256,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return taxonomyLevel; } + @Override public void setTaxonomyLevel(TaxonomyLevel taxonomyLevel) { this.taxonomyLevel = taxonomyLevel; } @@ -278,6 +283,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return educationalContext; } + @Override public void setEducationalContext(QEducationalContext educationalContext) { this.educationalContext = educationalContext; } @@ -295,6 +301,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return educationalLearningTime; } + @Override public void setEducationalLearningTime(String educationalLearningTime) { this.educationalLearningTime = educationalLearningTime; } @@ -304,6 +311,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return difficulty; } + @Override public void setDifficulty(BigDecimal difficulty) { this.difficulty = difficulty; } @@ -313,6 +321,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return stdevDifficulty; } + @Override public void setStdevDifficulty(BigDecimal stdevDifficulty) { this.stdevDifficulty = stdevDifficulty; } @@ -322,6 +331,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return differentiation; } + @Override public void setDifferentiation(BigDecimal differentiation) { this.differentiation = differentiation; } @@ -331,6 +341,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return numOfAnswerAlternatives; } + @Override public void setNumOfAnswerAlternatives(int numOfAnswerAlternatives) { this.numOfAnswerAlternatives = numOfAnswerAlternatives; } @@ -340,6 +351,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return usage; } + @Override public void setUsage(int usage) { this.usage = usage; } @@ -349,6 +361,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return assessmentType; } + @Override public void setAssessmentType(String assessmentType) { this.assessmentType = assessmentType; } @@ -386,6 +399,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return language; } + @Override public void setLanguage(String language) { this.language = language; } @@ -420,6 +434,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return correctionTime; } + @Override public void setCorrectionTime(Integer correctionTime) { this.correctionTime = correctionTime; } @@ -429,6 +444,7 @@ public class QuestionItemImpl implements QuestionItemFull, Persistable { return keywords; } + @Override public void setKeywords(String keywords) { this.keywords = keywords; } 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 54635978bfd939651e4408af618419f8b7b6062d..f35a647c4c3860f5e35f28ab710249526153d181 100644 --- a/src/main/java/org/olat/modules/qpool/security/ProcesslessSecurityCallback.java +++ b/src/main/java/org/olat/modules/qpool/security/ProcesslessSecurityCallback.java @@ -19,7 +19,6 @@ */ package org.olat.modules.qpool.security; -import org.olat.modules.qpool.QPoolService; import org.olat.modules.qpool.QuestionItemSecurityCallback; import org.olat.modules.qpool.QuestionItemView; import org.olat.modules.qpool.QuestionPoolModule; @@ -45,8 +44,6 @@ public class ProcesslessSecurityCallback implements QuestionItemSecurityCallback @Autowired private QuestionPoolModule qpoolModule; - @Autowired - private QPoolService qpoolService; @Override public void setQuestionItemView(QuestionItemView itemView) { diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionItemDetailsController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionItemDetailsController.java index beedcb759a29ca9bf9f168fbe1ca101f53e77792..d2ffe82f263eb1aa847bf7deee4d1695d55656ca 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QuestionItemDetailsController.java +++ b/src/main/java/org/olat/modules/qpool/ui/QuestionItemDetailsController.java @@ -170,7 +170,7 @@ public class QuestionItemDetailsController extends BasicController implements To private void setMetadatasController(UserRequest ureq, QuestionItem item, QuestionItemSecurityCallback securityCallback) { metadatasCtrl = new MetadatasController(ureq, getWindowControl(), qPoolSecurityCallback, item, securityCallback, - itemSource.isAdminItemSource()); + itemSource.isAdminItemSource(), false); mainVC.put("metadatas", metadatasCtrl.getInitialComponent()); listenTo(metadatasCtrl); } diff --git a/src/main/java/org/olat/modules/qpool/ui/QuickViewMetadataController.java b/src/main/java/org/olat/modules/qpool/ui/QuickViewMetadataController.java index d9afe6d55dba91dbc85d6809e35067271ba5f151..a84ba6e6b358134672e08ae4d4ab5c0f81f495c3 100644 --- a/src/main/java/org/olat/modules/qpool/ui/QuickViewMetadataController.java +++ b/src/main/java/org/olat/modules/qpool/ui/QuickViewMetadataController.java @@ -60,7 +60,7 @@ public class QuickViewMetadataController extends BasicController { metadataPanel.setContent(null); } else { removeAsListenerAndDispose(metadataCtrl); - metadataCtrl = new MetadatasController(ureq, getWindowControl(), qPoolSecurityCallback, item, metadataSecurityCallback, false); + metadataCtrl = new MetadatasController(ureq, getWindowControl(), qPoolSecurityCallback, item, metadataSecurityCallback, false, false); metadataPanel.setContent(metadataCtrl.getInitialComponent()); } } diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/GeneralMetadataEditController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/GeneralMetadataEditController.java index 399917a9bb8a07dc78c5657a4410ffd33191a333..d6776d49a2a25c8573a469e0f4a6081955bf0782 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/GeneralMetadataEditController.java +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/GeneralMetadataEditController.java @@ -40,6 +40,7 @@ import org.olat.modules.qpool.QPoolService; import org.olat.modules.qpool.QuestionItem; import org.olat.modules.qpool.QuestionItemAuditLog.Action; import org.olat.modules.qpool.QuestionItemAuditLogBuilder; +import org.olat.modules.qpool.QuestionItemEditable; import org.olat.modules.qpool.model.QEducationalContext; import org.olat.modules.qpool.model.QuestionItemImpl; import org.olat.modules.qpool.ui.QuestionsController; @@ -78,8 +79,8 @@ public class GeneralMetadataEditController extends FormBasicController { public GeneralMetadataEditController(UserRequest ureq, WindowControl wControl, QPoolSecurityCallback qPoolSecurityCallback, QuestionItem item, MetadataSecurityCallback securityCallback, - boolean ignoreCompetences) { - super(ureq, wControl, LAYOUT_VERTICAL); + boolean ignoreCompetences, boolean wideLayout) { + super(ureq, wControl, wideLayout ? LAYOUT_DEFAULT : LAYOUT_VERTICAL); setTranslator(Util.createPackageTranslator(QuestionsController.class, getLocale(), getTranslator())); this.qPoolSecurityCallback = qPoolSecurityCallback; @@ -144,8 +145,8 @@ public class GeneralMetadataEditController extends FormBasicController { buttonsCont.setElementCssClass("o_sel_qpool_metadata_buttons"); buttonsCont.setRootForm(mainForm); formLayout.add(buttonsCont); - uifactory.addFormSubmitButton("ok", "ok", buttonsCont); uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + uifactory.addFormSubmitButton("ok", "ok", buttonsCont); } private void buildTaxonomyLevelEl() { @@ -153,26 +154,25 @@ public class GeneralMetadataEditController extends FormBasicController { String[] selectableKeys = qpoolTaxonomyTreeBuilder.getSelectableKeys(); String[] selectableValues = qpoolTaxonomyTreeBuilder.getSelectableValues(); taxonomyLevelEl.setKeysAndValues(selectableKeys, selectableValues, null); - if (item instanceof QuestionItemImpl) { - QuestionItemImpl itemImpl = (QuestionItemImpl) item; - TaxonomyLevel selectedTaxonomyLevel = itemImpl.getTaxonomyLevel(); - if(selectedTaxonomyLevel != null) { - String selectedTaxonomyLevelKey = String.valueOf(selectedTaxonomyLevel.getKey()); - for(String taxonomyKey: qpoolTaxonomyTreeBuilder.getSelectableKeys()) { - if(taxonomyKey.equals(selectedTaxonomyLevelKey)) { - taxonomyLevelEl.select(taxonomyKey, true); - } + + TaxonomyLevel selectedTaxonomyLevel = item.getTaxonomyLevel(); + if(selectedTaxonomyLevel != null) { + String selectedTaxonomyLevelKey = String.valueOf(selectedTaxonomyLevel.getKey()); + for(String taxonomyKey: qpoolTaxonomyTreeBuilder.getSelectableKeys()) { + if(taxonomyKey.equals(selectedTaxonomyLevelKey)) { + taxonomyLevelEl.select(taxonomyKey, true); } - if (!taxonomyLevelEl.isOneSelected() && itemImpl.getTaxonomyLevel() != null) { - if (selectableKeys.length == 0) { - selectableKeys = new String[] {"dummy"}; - selectableValues = new String[1]; - } - selectableValues[0] = itemImpl.getTaxonomyLevel().getDisplayName(); - taxonomyLevelEl.setEnabled(false); + } + if (!taxonomyLevelEl.isOneSelected() && selectedTaxonomyLevel != null) { + if (selectableKeys.length == 0) { + selectableKeys = new String[] {"dummy"}; + selectableValues = new String[1]; } + selectableValues[0] = selectedTaxonomyLevel.getDisplayName(); + taxonomyLevelEl.setEnabled(false); } } + taxonomyLevelEl.addActionListener(FormEvent.ONCHANGE); setTaxonomicPath(); } @@ -240,11 +240,13 @@ public class GeneralMetadataEditController extends FormBasicController { @Override protected void formOK(UserRequest ureq) { - if(item instanceof QuestionItemImpl) { - QuestionItemImpl itemImpl = (QuestionItemImpl)item; + if(item instanceof QuestionItemEditable) { + QuestionItemEditable itemImpl = (QuestionItemEditable)item; QuestionItemAuditLogBuilder builder = qpoolService.createAuditLogBuilder(getIdentity(), Action.UPDATE_QUESTION_ITEM_METADATA); - builder.withBefore(itemImpl); + if(item instanceof QuestionItemImpl) { + builder.withBefore(item); + } itemImpl.setTopic(topicEl.getValue()); @@ -284,9 +286,11 @@ public class GeneralMetadataEditController extends FormBasicController { String assessmentType = assessmentTypeEl.isOneSelected()? assessmentTypeEl.getSelectedKey(): null; itemImpl.setAssessmentType(assessmentType); - item = qpoolService.updateItem(item); - builder.withAfter(itemImpl); - qpoolService.persist(builder.create()); + if(item instanceof QuestionItemImpl) { + item = qpoolService.updateItem(item); + builder.withAfter(item); + qpoolService.persist(builder.create()); + } fireEvent(ureq, new QItemEdited(item)); } } diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/MetadataBulkChangeController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/MetadataBulkChangeController.java index d002777654ba3fe128c843491f66d2fd33ccd2d5..1298dcc3152c5eebab0874e5b326a631ab74c089 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/MetadataBulkChangeController.java +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/MetadataBulkChangeController.java @@ -331,7 +331,7 @@ public class MetadataBulkChangeController extends FormBasicController { @Override protected boolean validateFormLogic(UserRequest ureq) { - boolean allOk = true; + boolean allOk = super.validateFormLogic(ureq); //general allOk &= validateElementLogic(topicEl, topicEl.getMaxLength(), false, isEnabled(topicEl)); @@ -352,7 +352,7 @@ public class MetadataBulkChangeController extends FormBasicController { //rights allOk &= validateElementLogic(licensorEl, 1000, false, isEnabled(licensorEl)); - return allOk & super.validateFormLogic(ureq); + return allOk; } private boolean isEnabled(FormItem item) { diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/MetadatasController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/MetadatasController.java index 4b85f41ca352cbfcefe3451566b72e1fdd800ff9..b8ea068c1cf0fe87f6eee6c6cb291d89505c40ff 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/MetadatasController.java +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/MetadatasController.java @@ -57,7 +57,7 @@ public class MetadatasController extends BasicController { private QuestionItem item; public MetadatasController(UserRequest ureq, WindowControl wControl, QPoolSecurityCallback qPoolSecurityCallback, - QuestionItem item, MetadataSecurityCallback metadataScurityCallback, boolean ignoreCompetences) { + QuestionItem item, MetadataSecurityCallback metadataScurityCallback, boolean ignoreCompetences, boolean wideLayout) { super(ureq, wControl); setTranslator(Util.createPackageTranslator(QuestionsController.class, getLocale(), getTranslator())); @@ -65,19 +65,21 @@ public class MetadatasController extends BasicController { mainVC = createVelocityContainer("item_metadatas"); generalEditCtrl = new GeneralMetadataEditController(ureq, wControl, qPoolSecurityCallback, item, - metadataScurityCallback, ignoreCompetences); + metadataScurityCallback, ignoreCompetences, wideLayout); listenTo(generalEditCtrl); mainVC.put("details_general", generalEditCtrl.getInitialComponent()); - questionEditCtrl = new QuestionMetadataEditController(ureq, wControl, item, metadataScurityCallback); + questionEditCtrl = new QuestionMetadataEditController(ureq, wControl, item, metadataScurityCallback, wideLayout); listenTo(questionEditCtrl); mainVC.put("details_question", questionEditCtrl.getInitialComponent()); - rightsEditCtrl = new RightsMetadataEditController(ureq, wControl, item, metadataScurityCallback); - listenTo(rightsEditCtrl); - mainVC.put("details_rights", rightsEditCtrl.getInitialComponent()); + if(item.getResourceableId() != null) { + rightsEditCtrl = new RightsMetadataEditController(ureq, wControl, item, metadataScurityCallback, wideLayout); + listenTo(rightsEditCtrl); + mainVC.put("details_rights", rightsEditCtrl.getInitialComponent()); + } - technicalEditCtrl = new TechnicalMetadataEditController(ureq, wControl, item, metadataScurityCallback); + technicalEditCtrl = new TechnicalMetadataEditController(ureq, wControl, item, metadataScurityCallback, wideLayout); listenTo(technicalEditCtrl); mainVC.put("details_technical", technicalEditCtrl.getInitialComponent()); @@ -150,7 +152,9 @@ public class MetadatasController extends BasicController { this.item = item; generalEditCtrl.setItem(item, metadataSecurityCallback); questionEditCtrl.setItem(item, metadataSecurityCallback); - rightsEditCtrl.setItem(item, metadataSecurityCallback); + if(rightsEditCtrl != null) { + rightsEditCtrl.setItem(item, metadataSecurityCallback); + } technicalEditCtrl.setItem(item, metadataSecurityCallback); if (ratingMetadataCtrl != null) { ratingMetadataCtrl.setItem(item); @@ -173,14 +177,14 @@ public class MetadatasController extends BasicController { Preferences guiPrefs = ureq.getUserSession().getGuiPreferences(); String guiPref = (String) guiPrefs.get(MetadatasController.class, GUIPREF_KEY_OPEN_PANEL); String openPanel = guiPref != null? guiPrefToPanel(guiPref): "general"; - mainVC.contextRemove("inGeneral"); - mainVC.contextRemove("inQuestion"); - mainVC.contextRemove("inRights"); - mainVC.contextRemove("inTechnical"); - mainVC.contextRemove("inRatings"); - mainVC.contextRemove("inPools"); - mainVC.contextRemove("inShares"); - mainVC.contextPut("in-" + openPanel, "in"); + mainVC.contextRemove("ingeneral"); + mainVC.contextRemove("inquestion"); + mainVC.contextRemove("inrights"); + mainVC.contextRemove("intechnical"); + mainVC.contextRemove("inratings"); + mainVC.contextRemove("inpools"); + mainVC.contextRemove("inshares"); + mainVC.contextPut("in" + openPanel.toLowerCase(), "in"); } private String guiPrefToPanel(String guiPref) { diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/PoolsMetadataController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/PoolsMetadataController.java index 01e70b9c49883585bc8a1ba0d5bbcda290f0e08d..10d38a87dc38a4200ec7abd59270f37c937877ff 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/PoolsMetadataController.java +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/PoolsMetadataController.java @@ -113,7 +113,7 @@ public class PoolsMetadataController extends FormBasicController { public Object getValueAt(int row, int col) { QuestionItem2Pool info = getObject(row); if(col == 0) { - return new Boolean(info.isEditable()); + return Boolean.valueOf(info.isEditable()); } return info.getPoolName(); } diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/QuestionMetadataEditController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/QuestionMetadataEditController.java index b971e57d03cf80cdc5a0f0bb372a6d317f9ba16b..caeffb8e28f5eecc7a45f757c91b302ae1599e28 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/QuestionMetadataEditController.java +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/QuestionMetadataEditController.java @@ -45,6 +45,7 @@ import org.olat.modules.qpool.QPoolService; import org.olat.modules.qpool.QuestionItem; import org.olat.modules.qpool.QuestionItemAuditLog.Action; import org.olat.modules.qpool.QuestionItemAuditLogBuilder; +import org.olat.modules.qpool.QuestionItemEditable; import org.olat.modules.qpool.manager.MetadataConverterHelper; import org.olat.modules.qpool.model.LOMDuration; import org.olat.modules.qpool.model.QItemType; @@ -80,8 +81,8 @@ public class QuestionMetadataEditController extends FormBasicController { private QPoolService qpoolService; public QuestionMetadataEditController(UserRequest ureq, WindowControl wControl, QuestionItem item, - MetadataSecurityCallback securityCallback) { - super(ureq, wControl, LAYOUT_VERTICAL); + MetadataSecurityCallback securityCallback, boolean wideLayout) { + super(ureq, wControl, wideLayout ? LAYOUT_DEFAULT : LAYOUT_VERTICAL); setTranslator(Util.createPackageTranslator(QuestionsController.class, getLocale(), getTranslator())); this.item = item; @@ -173,8 +174,8 @@ public class QuestionMetadataEditController extends FormBasicController { buttonsCont.setElementCssClass("o_sel_qpool_metadata_buttons"); buttonsCont.setRootForm(mainForm); formLayout.add(buttonsCont); - uifactory.addFormSubmitButton("ok", "ok", buttonsCont); uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + uifactory.addFormSubmitButton("ok", "ok", buttonsCont); } private void setReadOnly(MetadataSecurityCallback securityCallback) { @@ -223,11 +224,13 @@ public class QuestionMetadataEditController extends FormBasicController { @Override protected void formOK(UserRequest ureq) { - if(item instanceof QuestionItemImpl) { - QuestionItemImpl itemImpl = (QuestionItemImpl)item; + if(item instanceof QuestionItemEditable) { + QuestionItemEditable itemImpl = (QuestionItemEditable)item; QuestionItemAuditLogBuilder builder = qpoolService.createAuditLogBuilder(getIdentity(), Action.UPDATE_QUESTION_ITEM_METADATA); - builder.withBefore(itemImpl); + if(itemImpl instanceof QuestionItemImpl) { + builder.withBefore(item); + } int day = learningTimeDayElement.getIntValue(); int hour = learningTimeHourElement.getIntValue(); @@ -256,9 +259,11 @@ public class QuestionMetadataEditController extends FormBasicController { itemImpl.setCorrectionTime(Integer.valueOf(correctionTimeMinuteElement.getValue())); } - item = qpoolService.updateItem(itemImpl); - builder.withAfter(item); - qpoolService.persist(builder.create()); + if(item instanceof QuestionItemImpl) { + item = qpoolService.updateItem(item); + builder.withAfter(item); + qpoolService.persist(builder.create()); + } fireEvent(ureq, new QItemEdited(item)); } } diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/RightsMetadataEditController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/RightsMetadataEditController.java index f6f645d17f471b44db8079e24cb3892ece06bb77..a85e123d0d2db6a6f2dd4d28d43d015e9a7cbfec 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/RightsMetadataEditController.java +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/RightsMetadataEditController.java @@ -103,8 +103,8 @@ public class RightsMetadataEditController extends FormBasicController { private QuestionPoolLicenseHandler licenseHandler; public RightsMetadataEditController(UserRequest ureq, WindowControl wControl, QuestionItem item, - MetadataSecurityCallback securityCallback) { - super(ureq, wControl, LAYOUT_VERTICAL); + MetadataSecurityCallback securityCallback, boolean wideLayout) { + super(ureq, wControl, wideLayout ? LAYOUT_DEFAULT : LAYOUT_VERTICAL); setTranslator(Util.createPackageTranslator(QuestionsController.class, getLocale(), getTranslator())); this.item = item; @@ -128,37 +128,47 @@ public class RightsMetadataEditController extends FormBasicController { authorCont.put("manage.owners", managerOwners); if (licenseModule.isEnabled(licenseHandler)) { - license = licenseService.loadOrCreateLicense(item); - - LicenseSelectionConfig licenseSelectionConfig = LicenseUIFactory - .createLicenseSelectionConfig(licenseHandler, license.getLicenseType()); - licenseEl = uifactory.addDropdownSingleselect("rights.license", formLayout, - licenseSelectionConfig.getLicenseTypeKeys(), - licenseSelectionConfig.getLicenseTypeValues(getLocale())); - licenseEl.setElementCssClass("o_sel_repo_license"); - licenseEl.setMandatory(licenseSelectionConfig.isLicenseMandatory()); - if (licenseSelectionConfig.getSelectionLicenseTypeKey() != null) { - licenseEl.select(licenseSelectionConfig.getSelectionLicenseTypeKey(), true); - } - licenseEl.addActionListener(FormEvent.ONCHANGE); + license = loadLicense(); - licensorEl = uifactory.addTextElement("rights.licensor", 1000, license.getLicensor(), formLayout); - - String freetext = licenseService.isFreetext(license.getLicenseType()) ? license.getFreetext() : ""; - licenseFreetextEl = uifactory.addTextAreaElement("rights.freetext", 4, 72, freetext, formLayout); - LicenseUIFactory.updateVisibility(licenseEl, licensorEl, licenseFreetextEl); - - licenseTextEl = uifactory.addStaticTextElement("rights.licenseText", "", "", formLayout); - updateLicenseText(); - - buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); - buttonsCont.setRootForm(mainForm); - formLayout.add(buttonsCont); - okButton = uifactory.addFormSubmitButton("ok", "ok", buttonsCont); - uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + if(license != null) { + LicenseSelectionConfig licenseSelectionConfig = LicenseUIFactory + .createLicenseSelectionConfig(licenseHandler, license.getLicenseType()); + licenseEl = uifactory.addDropdownSingleselect("rights.license", formLayout, + licenseSelectionConfig.getLicenseTypeKeys(), + licenseSelectionConfig.getLicenseTypeValues(getLocale())); + licenseEl.setElementCssClass("o_sel_repo_license"); + licenseEl.setMandatory(licenseSelectionConfig.isLicenseMandatory()); + if (licenseSelectionConfig.getSelectionLicenseTypeKey() != null) { + licenseEl.select(licenseSelectionConfig.getSelectionLicenseTypeKey(), true); + } + licenseEl.addActionListener(FormEvent.ONCHANGE); + + licensorEl = uifactory.addTextElement("rights.licensor", 1000, license.getLicensor(), formLayout); + + String freetext = licenseService.isFreetext(license.getLicenseType()) ? license.getFreetext() : ""; + licenseFreetextEl = uifactory.addTextAreaElement("rights.freetext", 4, 72, freetext, formLayout); + LicenseUIFactory.updateVisibility(licenseEl, licensorEl, licenseFreetextEl); + + licenseTextEl = uifactory.addStaticTextElement("rights.licenseText", "", "", formLayout); + updateLicenseText(); + + buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + buttonsCont.setRootForm(mainForm); + formLayout.add(buttonsCont); + uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + okButton = uifactory.addFormSubmitButton("ok", "ok", buttonsCont); + } } } + private ResourceLicense loadLicense() { + ResourceLicense resourceLicense = null; + if(item.getResourceableId() != null) { + resourceLicense = licenseService.loadOrCreateLicense(item); + } + return resourceLicense; + } + private void updateLicenseText() { if (licenseTextEl != null && licenseEl != null && licenseEl.isOneSelected()) { String selectedKey = licenseEl.getSelectedKey(); @@ -217,13 +227,15 @@ public class RightsMetadataEditController extends FormBasicController { } private void reloadAuthors() { - List<Identity> authors = qpoolService.getAuthors(item); - List<String> authorLinks = new ArrayList<>(authors.size()); - for(Identity author:authors) { - String name = userManager.getUserDisplayName(author); - authorLinks.add(name); + if(item.getKey() != null) { + List<Identity> authors = qpoolService.getAuthors(item); + List<String> authorLinks = new ArrayList<>(authors.size()); + for(Identity author:authors) { + String name = userManager.getUserDisplayName(author); + authorLinks.add(name); + } + authorCont.contextPut("authors", authorLinks); } - authorCont.contextPut("authors", authorLinks); } @Override @@ -245,8 +257,6 @@ public class RightsMetadataEditController extends FormBasicController { qpoolService.removeAuthors(list, Collections.<QuestionItemShort>singletonList(item)); } reloadAuthors(); - //cmc.deactivate(); - //cleanUp(); } else if(source == cmc) { fireEvent(ureq, new QItemEdited(item)); cleanUp(); @@ -288,7 +298,7 @@ public class RightsMetadataEditController extends FormBasicController { @Override protected boolean validateFormLogic(UserRequest ureq) { - boolean allOk = true; + boolean allOk = super.validateFormLogic(ureq); if (licenseEl != null) { licenseEl.clearError(); @@ -298,7 +308,7 @@ public class RightsMetadataEditController extends FormBasicController { } } - return allOk &= super.validateFormLogic(ureq); + return allOk; } @Override diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/TechnicalMetadataEditController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/TechnicalMetadataEditController.java index 5fdde6273a3054fdde85f6cf2e8683a6d373d4e6..2e17ff342a8df1aadefa6f90dfbedb5d883c5cd7 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/TechnicalMetadataEditController.java +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/TechnicalMetadataEditController.java @@ -31,6 +31,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.util.Formatter; +import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.modules.qpool.MetadataSecurityCallback; import org.olat.modules.qpool.QPoolService; @@ -55,7 +56,7 @@ public class TechnicalMetadataEditController extends FormBasicController { private StaticTextElement formatEl; private StaticTextElement editorVersionEl; private StaticTextElement lastModifiedEl; - private StaticTextElement statusLastMdifiedEl; + private StaticTextElement statusLastModifiedEl; private TextElement versionEl; private FormLayoutContainer buttonsCont; @@ -65,8 +66,8 @@ public class TechnicalMetadataEditController extends FormBasicController { private QPoolService qpoolService; public TechnicalMetadataEditController(UserRequest ureq, WindowControl wControl, QuestionItem item, - MetadataSecurityCallback securityCallback) { - super(ureq, wControl, LAYOUT_VERTICAL); + MetadataSecurityCallback securityCallback, boolean wideLayout) { + super(ureq, wControl, wideLayout ? LAYOUT_DEFAULT : LAYOUT_VERTICAL); setTranslator(Util.createPackageTranslator(QuestionsController.class, getLocale(), getTranslator())); this.item = item; @@ -89,19 +90,21 @@ public class TechnicalMetadataEditController extends FormBasicController { Formatter formatter = Formatter.getInstance(getLocale()); String creationDate = formatter.formatDateAndTime(item.getCreationDate()); - uifactory.addStaticTextElement("technical.creation", creationDate, formLayout); + if(StringHelper.containsNonWhitespace(creationDate)) { + uifactory.addStaticTextElement("technical.creation", creationDate, formLayout); + } lastModifiedEl = uifactory.addStaticTextElement("technical.lastModified", "", formLayout); versionEl = uifactory.addTextElement("lifecycle.version", "lifecycle.version", 50, "", formLayout); - statusLastMdifiedEl = uifactory.addStaticTextElement("technical.statusLastModified", "", formLayout); + statusLastModifiedEl = uifactory.addStaticTextElement("technical.statusLastModified", "", formLayout); buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); buttonsCont.setRootForm(mainForm); formLayout.add(buttonsCont); - uifactory.addFormSubmitButton("ok", "ok", buttonsCont); uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + uifactory.addFormSubmitButton("ok", "ok", buttonsCont); } private void setReadOnly(MetadataSecurityCallback securityCallback) { @@ -124,12 +127,14 @@ public class TechnicalMetadataEditController extends FormBasicController { String lastModified = formatter.formatDateAndTime(item.getLastModified()); lastModifiedEl.setValue(lastModified); + lastModifiedEl.setVisible(StringHelper.containsNonWhitespace(lastModified)); versionEl.setValue(item.getItemVersion()); String statusLastModified = formatter.formatDateAndTime(item.getQuestionStatusLastModified()); - statusLastModified = statusLastModified != null? statusLastModified: ""; - statusLastMdifiedEl.setValue(statusLastModified); + statusLastModified = statusLastModified != null ? statusLastModified: ""; + statusLastModifiedEl.setValue(statusLastModified); + statusLastModifiedEl.setVisible(StringHelper.containsNonWhitespace(statusLastModified)); } public void setItem(QuestionItem item, MetadataSecurityCallback securityCallback) { diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/_content/item_metadatas.html b/src/main/java/org/olat/modules/qpool/ui/metadata/_content/item_metadatas.html index d794cd318c15388b8fff2f8c0593ed074421cc30..9eb5ac9bd5b7727e92ba35cb7333482cadc0089c 100644 --- a/src/main/java/org/olat/modules/qpool/ui/metadata/_content/item_metadatas.html +++ b/src/main/java/org/olat/modules/qpool/ui/metadata/_content/item_metadatas.html @@ -2,11 +2,11 @@ <div class="panel panel-default o_sel_qpool_metadata_general"> <div class="panel-heading"> <h4 class="panel-title"> - <i id="collapseGeneralToggler" class="o_icon o_icon-fw #if($inGeneral) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> + <i id="collapseGeneralToggler" class="o_icon o_icon-fw #if($ingeneral) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> <a data-toggle="collapse" data-parent="#accordion" href="#general">$r.translate("general")</a> </h4> </div> - <div id="general" class="panel-collapse collapse $!inGeneral"> + <div id="general" class="panel-collapse collapse $!ingeneral"> <div class="panel-body"> $r.render("details_general") </div> @@ -24,11 +24,11 @@ <div class="panel panel-default o_sel_qpool_metadata_item_analyse"> <div class="panel-heading"> <h4 class="panel-title"> - <i id="collapseQuestionToggler" class="o_icon o_icon-fw #if($inQuestion) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> + <i id="collapseQuestionToggler" class="o_icon o_icon-fw #if($inquestion) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> <a data-toggle="collapse" data-parent="#accordion" href="#question">$r.translate("question")</a> </h4> </div> - <div id="question" class="panel-collapse collapse $!inQuestion"> + <div id="question" class="panel-collapse collapse $!inquestion"> <div class="panel-body"> $r.render("details_question") </div> @@ -43,42 +43,42 @@ }) </script> </div> + #if($r.available("details_rights")) <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title"> - <i id="collapseRightsToggler" class="o_icon o_icon-fw #if($inRights) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> + <i id="collapseRightsToggler" class="o_icon o_icon-fw #if($inrights) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> <a data-toggle="collapse" data-parent="#accordion" href="#rights"> $r.translate("rights") </a> </h4> </div> - <div id="rights" class="panel-collapse collapse $!inRights"> + <div id="rights" class="panel-collapse collapse $!inrights"> <div class="panel-body"> $r.render("details_rights") </div> </div> <script> - /* <![CDATA[ */ - jQuery('#rights').on('hide.bs.collapse', function () { - jQuery('#collapseRightsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox'); - }) - jQuery('#rights').on('show.bs.collapse', function () { - jQuery('#collapseRightsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox'); - $r.backgroundCommand("show","panel","rights") - }) - /* ]]> */ + jQuery('#rights').on('hide.bs.collapse', function () { + jQuery('#collapseRightsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox'); + }) + jQuery('#rights').on('show.bs.collapse', function () { + jQuery('#collapseRightsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox'); + $r.backgroundCommand("show","panel","rights") + }) </script> </div> + #end <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title"> - <i id="collapseTechnicalToggler" class="o_icon o_icon-fw #if($inTechnical) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> + <i id="collapseTechnicalToggler" class="o_icon o_icon-fw #if($intechnical) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> <a data-toggle="collapse" data-parent="#accordion" href="#technical"> $r.translate("technical") </a> </h4> </div> - <div id="technical" class="panel-collapse collapse $!inTechnical"> + <div id="technical" class="panel-collapse collapse $!intechnical"> <div class="panel-body"> $r.render("details_technical") </div> @@ -99,27 +99,25 @@ <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title"> - <i id="collapsRatingsToggler" class="o_icon o_icon-fw #if($inRatings) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> + <i id="collapsRatingsToggler" class="o_icon o_icon-fw #if($inratings) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> <a data-toggle="collapse" data-parent="#accordion" href="#ratings"> $r.translate("menu.ratings") </a> </h4> </div> - <div id="ratings" class="panel-collapse collapse $!inRatings"> + <div id="ratings" class="panel-collapse collapse $!inratings"> <div class="panel-body"> $r.render("details_ratings") </div> </div> <script> - /* <![CDATA[ */ - jQuery('#ratings').on('hide.bs.collapse', function () { - jQuery('#collapsRatingsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox'); - }) - jQuery('#ratings').on('show.bs.collapse', function () { - jQuery('#collapsRatingsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox'); - $r.backgroundCommand("show","panel","ratings") - }) - /* ]]> */ + jQuery('#ratings').on('hide.bs.collapse', function () { + jQuery('#collapsRatingsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox'); + }) + jQuery('#ratings').on('show.bs.collapse', function () { + jQuery('#collapsRatingsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox'); + $r.backgroundCommand("show","panel","ratings") + }) </script> </div> #end @@ -127,27 +125,25 @@ <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title"> - <i id="collapsePoolsToggler" class="o_icon o_icon-fw #if($inPools) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> + <i id="collapsePoolsToggler" class="o_icon o_icon-fw #if($inpools) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> <a data-toggle="collapse" data-parent="#accordion" href="#pools"> $r.translate("menu.pools") </a> </h4> </div> - <div id="pools" class="panel-collapse collapse $!inPools"> + <div id="pools" class="panel-collapse collapse $!inpools"> <div class="panel-body"> $r.render("details_pools") </div> </div> <script> - /* <![CDATA[ */ - jQuery('#pools').on('hide.bs.collapse', function () { - jQuery('#collapsePoolsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox'); - }) - jQuery('#pools').on('show.bs.collapse', function () { - jQuery('#collapsePoolsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox'); - $r.backgroundCommand("show","panel","pools") - }) - /* ]]> */ + jQuery('#pools').on('hide.bs.collapse', function () { + jQuery('#collapsePoolsToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox'); + }) + jQuery('#pools').on('show.bs.collapse', function () { + jQuery('#collapsePoolsToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox'); + $r.backgroundCommand("show","panel","pools") + }) </script> </div> #end @@ -155,27 +151,25 @@ <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title"> - <i id="collapseSharesToggler" class="o_icon o_icon-fw #if($inShares) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> + <i id="collapseSharesToggler" class="o_icon o_icon-fw #if($inshares) o_icon_close_togglebox #else o_icon_open_togglebox #end"> </i> <a data-toggle="collapse" data-parent="#accordion" href="#shares"> $r.translate("sharing.shares") </a> </h4> </div> - <div id="shares" class="panel-collapse collapse $!inShares"> + <div id="shares" class="panel-collapse collapse $!inshares"> <div class="panel-body"> $r.render("details_shares") </div> </div> <script> - /* <![CDATA[ */ - jQuery('#shares').on('hide.bs.collapse', function () { - jQuery('#collapseSharesToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox'); - }) - jQuery('#shares').on('show.bs.collapse', function () { - jQuery('#collapseSharesToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox'); - $r.backgroundCommand("show","panel","shares") - }) - /* ]]> */ + jQuery('#shares').on('hide.bs.collapse', function () { + jQuery('#collapseSharesToggler').removeClass('o_icon_close_togglebox').addClass('o_icon_open_togglebox'); + }) + jQuery('#shares').on('show.bs.collapse', function () { + jQuery('#collapseSharesToggler').removeClass('o_icon_open_togglebox').addClass('o_icon_close_togglebox'); + $r.backgroundCommand("show","panel","shares") + }) </script> </div> #end diff --git a/src/test/java/org/olat/selenium/page/qpool/QuestionMetadataPage.java b/src/test/java/org/olat/selenium/page/qpool/QuestionMetadataPage.java index 77f6aa86fd39625b326fe9cb7dc261e09bee62fd..9ab8225d65c34cd11cea8f712222eda05e0c1b62 100644 --- a/src/test/java/org/olat/selenium/page/qpool/QuestionMetadataPage.java +++ b/src/test/java/org/olat/selenium/page/qpool/QuestionMetadataPage.java @@ -19,6 +19,8 @@ */ package org.olat.selenium.page.qpool; +import java.util.List; + import org.olat.selenium.page.graphene.OOGraphene; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; @@ -54,11 +56,17 @@ public class QuestionMetadataPage { private QuestionMetadataPage openMetadata(String panelClass) { By hrefBy = By.cssSelector("div." + panelClass + ">div>h4>a"); OOGraphene.waitElement(hrefBy, browser); - browser.findElement(hrefBy).click(); - OOGraphene.waitingALittleLonger();// wait the accordion opens up - By generalMetadata = By.cssSelector("div." + panelClass + " div.panel-body fieldset.o_form"); - OOGraphene.waitElement(generalMetadata, browser); + By panelInBy = By.cssSelector("div." + panelClass + " div.panel-collapse.collapse.in"); + List<WebElement> panelInEls = browser.findElements(panelInBy); + if(panelInEls.isEmpty()) { + browser.findElement(hrefBy).click(); + OOGraphene.waitElement(panelInBy, browser); + OOGraphene.waitingALittleLonger();// wait the accordion opens up + } + + By formBy = By.cssSelector("div." + panelClass + " div.panel-body fieldset.o_form"); + OOGraphene.waitElement(formBy, browser); return this; }