diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java index e76a7fcb60e1d8c07436e04e6a0e616d30375b94..f99713e078f87184f6dd61103632cc19e907df7b 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java @@ -57,7 +57,9 @@ class RichTextElementComponent extends FormBaseComponentImpl { private static final ComponentRenderer RENDERER = new RichTextElementRenderer(); private final RichTextElementImpl element; - private int cols, rows; + private int cols; + private int rows; + private Integer currentHeight; private TextMode currentTextMode; /** @@ -82,9 +84,6 @@ class RichTextElementComponent extends FormBaseComponentImpl { return element; } - /** - * @see org.olat.core.gui.components.Component#getHTMLRendererSingleton() - */ @Override public ComponentRenderer getHTMLRendererSingleton() { return RENDERER; @@ -105,6 +104,14 @@ class RichTextElementComponent extends FormBaseComponentImpl { public void setRows(int rows) { this.rows = rows; } + + protected Integer getCurrentHeight() { + return currentHeight; + } + + protected void setCurrentHeight(Integer currentHeight) { + this.currentHeight = currentHeight; + } protected TextMode getCurrentTextMode() { return currentTextMode; diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementImpl.java index 5842130b40bccb7592f5b0f53de689957088f39d..ec50cef3cbda8735338c0578d16fd852b406a264 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementImpl.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementImpl.java @@ -198,6 +198,9 @@ public class RichTextElementImpl extends AbstractTextElement implements String paramId = component.getFormDispatchId(); String cmd = getRootForm().getRequestParameter("cmd"); String submitValue = getRootForm().getRequestParameter(paramId); + String sizeParamId = "rtinye_".concat(paramId); + String size = getRootForm().getRequestParameter(sizeParamId); + if(StringHelper.containsNonWhitespace(submitValue)) { if(renderingMode == TextMode.oneLine) { submitValue = TextMode.fromOneLine(submitValue); @@ -206,6 +209,10 @@ public class RichTextElementImpl extends AbstractTextElement implements } } + if(StringHelper.containsNonWhitespace(size)) { + setCurrentHeight(size); + } + String dispatchUri = getRootForm().getRequestParameter("dispatchuri"); if("saveinlinedtiny".equals(cmd)) { if(submitValue != null) { @@ -259,6 +266,15 @@ public class RichTextElementImpl extends AbstractTextElement implements configuration = null; } } + + private void setCurrentHeight(String size) { + try { + int height = Double.valueOf(size).intValue(); + component.setCurrentHeight(height); + } catch (NumberFormatException e) { + //can happen, don't make a drama of it + } + } @Override public void setNewOriginalValue(String value) { diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementRenderer.java index 763279dade4d9ed1a4a64fe358a101df5a3f2918..9e4c59258ca23884bf021ba991a0011bae5d5ef1 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementRenderer.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementRenderer.java @@ -213,6 +213,9 @@ class RichTextElementRenderer extends DefaultComponentRenderer { configurations.append("maxSize:").append(te.getMaxLength()).append("\n"); } + Integer currentHeight = teC.getCurrentHeight(); + + sb.append("<input type='hidden' id='rtinye_").append(teC.getFormDispatchId()).append("' name='rtinye_").append(teC.getFormDispatchId()).append("' value='' />"); sb.append("<script type='text/javascript'>/* <![CDATA[ */\n"); //file browser url sb.append(" BTinyHelper.editorMediaUris.put('").append(domID).append("','"); @@ -220,13 +223,21 @@ class RichTextElementRenderer extends DefaultComponentRenderer { sb.append("');\n"); sb.append(" setTimeout(function() { jQuery('#").append(domID).append("').tinymce({\n")//delay for firefox + tinymce 4.5 + jQuery 3.3.1 .append(" selector: '#").append(domID).append("',\n") - .append(" script_url: '").append(baseUrl.toString()).append("',\n") - .append(" setup: function(ed){\n") + .append(" script_url: '").append(baseUrl.toString()).append("',\n"); + if(currentHeight != null && currentHeight.intValue() > 20) { + sb.append(" height: ").append(currentHeight).append(",\n"); + } + sb.append(" setup: function(ed){\n") .append(" ed.on('init', function(e) {\n") .append(" ").append(onInit.get(0).replace(".curry(", "(")).append(";\n") .append(" });\n") .append(" ed.on('change', function(e) {\n") .append(" BTinyHelper.triggerOnChange('").append(domID).append("');\n") + .append(" });\n") + .append(" ed.on('ResizeEditor', function(e) {\n") + .append(" try {\n") + .append(" jQuery('#rtinye_").append(teC.getFormDispatchId()).append("').val(ed.contentAreaContainer.clientHeight);\n") + .append(" } catch(e) { }\n") .append(" });\n"); if(config.isSendOnBlur()) { sb.append(" ed.on('blur', function(e) {\n") diff --git a/src/main/java/org/olat/core/util/vfs/restapi/VFSWebservice.java b/src/main/java/org/olat/core/util/vfs/restapi/VFSWebservice.java index ea62ecabb1b7560ed46e8874c32c2fafddb9886f..7debe5390c91fd8001a5f87f8c4ff4a62da0eca9 100644 --- a/src/main/java/org/olat/core/util/vfs/restapi/VFSWebservice.java +++ b/src/main/java/org/olat/core/util/vfs/restapi/VFSWebservice.java @@ -525,7 +525,7 @@ public class VFSWebservice { for(PathSegment seg:path) { String segPath = seg.getPath(); for(VFSItem item : directory.getItems(new SystemItemFilter())) { - if(normalize(item.getName()).equals(segPath)) { + if(item.getName().equals(segPath) || normalize(item.getName()).equals(segPath)) { if(item instanceof VFSLeaf) { if(path.get(path.size() - 1) == seg) { resolvedItem = item; diff --git a/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java b/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java index fb217c13a7a8b716236f4d85651faa8061239173..cda034927d19a60254628922bb86ed01c5508d22 100644 --- a/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java +++ b/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java @@ -119,11 +119,15 @@ public class CourseReminderListController extends FormBasicController implements true, ReminderCols.lastModified.name())); columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ReminderCols.send.i18nKey(), ReminderCols.send.ordinal(), true, ReminderCols.send.name())); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ReminderCols.tools.i18nKey(), ReminderCols.tools.ordinal())); + DefaultFlexiColumnModel toolsCol = new DefaultFlexiColumnModel(ReminderCols.tools.i18nKey(), ReminderCols.tools.ordinal()); + toolsCol.setAlwaysVisible(true); + toolsCol.setExportable(false); + columnsModel.addFlexiColumnModel(toolsCol); tableModel = new CourseReminderTableModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, false, getTranslator(), formLayout); updateModel(); + tableEl.setAndLoadPersistedPreferences(ureq, "course-reminder-list"); } private void updateModel() { @@ -142,7 +146,7 @@ public class CourseReminderListController extends FormBasicController implements } tableModel.setObjects(rows); tableEl.reset(); - tableEl.setVisible(rows.size() > 0); + tableEl.setVisible(!rows.isEmpty()); } @Override diff --git a/src/main/java/org/olat/course/reminder/ui/CourseReminderLogsController.java b/src/main/java/org/olat/course/reminder/ui/CourseReminderLogsController.java index ac952facba430fbe5269978237aec0e673170aa0..586e8c5658dd4cd871a919bf6d3d9e04d6da5785 100644 --- a/src/main/java/org/olat/course/reminder/ui/CourseReminderLogsController.java +++ b/src/main/java/org/olat/course/reminder/ui/CourseReminderLogsController.java @@ -136,12 +136,16 @@ public class CourseReminderLogsController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(SendCols.sendTime.i18nKey(), SendCols.sendTime.ordinal(), true, SendCols.sendTime.name())); - //user properties - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel("resend", translate("resend"), "resend")); + + DefaultFlexiColumnModel resendCol = new DefaultFlexiColumnModel("resend", translate("resend"), "resend"); + resendCol.setAlwaysVisible(true); + resendCol.setExportable(false); + columnsModel.addFlexiColumnModel(resendCol); tableModel = new CourseSendReminderTableModel(columnsModel); tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 20, false, getTranslator(), formLayout); tableEl.setElementCssClass("o_sel_course_sent_reminder_log_list"); + tableEl.setAndLoadPersistedPreferences(ureq, "course-reminders-logs"); updateModel(); } diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/BackgroundSize.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/BackgroundSize.java new file mode 100644 index 0000000000000000000000000000000000000000..5900972da9cbc3bb47bd2242198f1875d706ccad --- /dev/null +++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/BackgroundSize.java @@ -0,0 +1,43 @@ +/** + * <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.interactions; + +/** + * + * Initial date: 4 mars 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public enum BackgroundSize { + + s1024(1024), + s800(800), + s480(480); + + private final int size; + + private BackgroundSize(int size) { + this.size = size; + } + + public int size() { + return size; + } +} diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/DrawingEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/DrawingEditorController.java index 337753345f3d11b10c786f86d9714cd31baed413..63e4776ef40dc1294dcda9230ee2b595c3e3946f 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/DrawingEditorController.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/DrawingEditorController.java @@ -34,6 +34,7 @@ import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FileElement; import org.olat.core.gui.components.form.flexible.elements.RichTextElement; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; import org.olat.core.gui.components.form.flexible.elements.TextElement; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; @@ -42,6 +43,7 @@ import org.olat.core.gui.components.form.flexible.impl.elements.FileElementEvent import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.util.CodeHelper; +import org.olat.core.util.FileUtils; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.ValidationStatus; @@ -74,6 +76,7 @@ public class DrawingEditorController extends FormBasicController { private TextElement titleEl; private RichTextElement textEl; + private SingleSelection resizeEl; private FileElement backgroundEl; private final File itemFile; @@ -144,6 +147,15 @@ public class DrawingEditorController extends FormBasicController { backgroundEl.setDeleteEnabled(true); backgroundEl.limitToMimeType(mimeTypes, "error.mimetype", new String[]{ mimeTypes.toString() }); + String[] resizeKeys = new String[] { "no" }; + String[] resizeValues = new String[] { translate("form.imd.background.resize.no") }; + resizeEl = uifactory.addRadiosHorizontal("form.imd.background.resize", formLayout, resizeKeys, resizeValues); + resizeEl.setVisible(false); + resizeEl.setEnabled(!readOnly); + if(initialBackgroundImage != null) { + Size size = imageService.getSize(new LocalFileImpl(initialBackgroundImage), null); + optimizeResizeEl(size, false); + } // Submit Button FormLayoutContainer buttonsContainer = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); @@ -222,6 +234,8 @@ public class DrawingEditorController extends FormBasicController { backgroundEl.setUploadFileName(uniqueFilename); backgroundImage = backgroundEl.moveUploadFileTo(itemFile.getParentFile()); backgroundEl.setInitialFile(backgroundImage); + Size size = imageService.getSize(new LocalFileImpl(backgroundImage), null); + optimizeResizeEl(size, true); } } } @@ -244,7 +258,18 @@ public class DrawingEditorController extends FormBasicController { if(objectImg != null) { String filename = objectImg.getName(); String mimeType = WebappHelper.getMimeType(filename); - Size size = imageService.getSize(new LocalFileImpl(objectImg), null); + Size currentSize = imageService.getSize(new LocalFileImpl(objectImg), null); + + Size size = currentSize; + if(resizeEl.isVisible() && !resizeEl.isSelected(0)) { + int maxSize = Integer.parseInt(resizeEl.getSelectedKey()); + if(maxSize < currentSize.getHeight() || maxSize < currentSize.getWidth()) { + String extension = FileUtils.getFileSuffix(filename); + size = imageService.scaleImage(objectImg, extension, objectImg, maxSize, maxSize, false); + optimizeResizeEl(size, false); + } + } + int height = -1; int width = -1; if(size != null) { @@ -260,4 +285,42 @@ public class DrawingEditorController extends FormBasicController { fireEvent(ureq, new AssessmentItemEvent(AssessmentItemEvent.ASSESSMENT_ITEM_CHANGED, itemBuilder.getAssessmentItem(), QTI21QuestionType.drawing)); } + + private void optimizeResizeEl(Size size, boolean selectSize) { + List<String> keys = new ArrayList<>(); + List<String> values = new ArrayList<>(); + + String selectedSize = null; + for(BackgroundSize availableSize:BackgroundSize.values()) { + int proposedSize = availableSize.size(); + if(proposedSize <= size.getHeight() || proposedSize <= size.getWidth()) { + String s = Integer.toString(availableSize.size()); + keys.add(s); + values.add(s + " x " + s); + if((proposedSize == size.getHeight() && proposedSize >= size.getWidth()) + || (proposedSize == size.getWidth() && proposedSize >= size.getHeight())) { + selectedSize = s; + } + } + } + if(selectedSize == null) { + keys.add(0, "no"); + values.add(0, translate("form.imd.background.resize.no")); + } + resizeEl.setKeysAndValues(keys.toArray(new String[keys.size()]), values.toArray(new String[values.size()]), null); + + if(keys.size() == 1) { + resizeEl.select(keys.get(0), true); + resizeEl.setVisible(false); + } else { + if(selectedSize != null) { + resizeEl.select(selectedSize, true); + } else if(selectSize && keys.size() > 1 && keys.get(1).equals(Integer.toString(BackgroundSize.s1024.size()))) { + resizeEl.select(Integer.toString(BackgroundSize.s1024.size()), true); + } else { + resizeEl.select(keys.get(0), true); + } + resizeEl.setVisible(true); + } + } } \ No newline at end of file diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java index 446c02193beaadcbc45fc33b53d7c9de38a6cdc6..779bf90b2df6c03714ab5c6c20668bb86232f451 100644 --- a/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java +++ b/src/main/java/org/olat/ims/qti21/ui/editor/interactions/HotspotEditorController.java @@ -598,8 +598,8 @@ public class HotspotEditorController extends FormBasicController { } else { if(selectedSize != null) { resizeEl.select(selectedSize, true); - } else if(selectSize && keys.size() > 1 && keys.get(1).equals(Integer.toString(BackgroundSize.s1024.size))) { - resizeEl.select(Integer.toString(BackgroundSize.s1024.size), true); + } else if(selectSize && keys.size() > 1 && keys.get(1).equals(Integer.toString(BackgroundSize.s1024.size()))) { + resizeEl.select(Integer.toString(BackgroundSize.s1024.size()), true); } else { resizeEl.select(keys.get(0), true); } @@ -779,20 +779,4 @@ public class HotspotEditorController extends FormBasicController { coords.set(3, (bottomY - translateY)); } } - - public enum BackgroundSize { - s1024(1024), - s800(800), - s480(480); - - private final int size; - - private BackgroundSize(int size) { - this.size = size; - } - - public int size() { - return size; - } - } } diff --git a/src/test/java/org/olat/restapi/FolderTest.java b/src/test/java/org/olat/restapi/FolderTest.java index 41aaa25b0a24da130426e194001a44705cd91514..63e08bdab9fb78c2d5438b92335b8449a514b318 100644 --- a/src/test/java/org/olat/restapi/FolderTest.java +++ b/src/test/java/org/olat/restapi/FolderTest.java @@ -20,9 +20,15 @@ package org.olat.restapi; import static org.junit.Assert.assertEquals; -import static org.olat.core.util.vfs.restapi.VFSWebservice.normalize; + +import java.util.Arrays; +import java.util.Collection; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.olat.core.util.vfs.restapi.VFSWebservice; /** * * <h3>Description:</h3> @@ -30,13 +36,30 @@ import org.junit.Test; * Initial Date: 28 jan. 2011 <br> * @author srosse, stephane.rosse@frentix.com, www.frentix.com */ +@RunWith(Parameterized.class) public class FolderTest { + + @Parameters + public static Collection<Object[]> data() { + return Arrays.asList(new Object[][] { + { "HASTDJUR", "HÄSTDJUR" }, + { "HASTDJUR", "HÄSTDJÜR" }, + { "HAST_DJUR", "HÄST_DJUR" }, + { "This_is_a_funky_String", "TĥïŠĩš â fůňķŷ ŠťŕÄńġ" } + }); + } + + private String expected; + private String string; + + public FolderTest(String expected, String string) { + this.expected = expected; + this.string = string; + } @Test public void testNormalizer() { - assertEquals("HASTDJUR", normalize("HÄSTDJUR")); - assertEquals("HASTDJUR", normalize("HÄSTDJÜR")); - assertEquals("HAST_DJUR", normalize("HÄST_DJUR")); - assertEquals("This_is_a_funky_String", normalize("TĥïŠĩš â fůňķŷ ŠťŕÄńġ")); + String normalized = VFSWebservice.normalize(string); + assertEquals(expected, normalized); } }