SEBSERV-75 implementation and fixes

This commit is contained in:
anhefti 2020-01-22 13:26:33 +01:00
parent c009ccc7e8
commit 77aae3ad54
8 changed files with 119 additions and 36 deletions

View file

@ -8,6 +8,8 @@
package ch.ethz.seb.sebserver.gui.content; package ch.ethz.seb.sebserver.gui.content;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
import java.util.function.Function; import java.util.function.Function;
@ -86,6 +88,9 @@ public class QuizDiscoveryList implements TemplateComposer {
private final static LocTextKey NO_IMPORT_OF_OUT_DATED_QUIZ = private final static LocTextKey NO_IMPORT_OF_OUT_DATED_QUIZ =
new LocTextKey("sebserver.quizdiscovery.quiz.import.out.dated"); new LocTextKey("sebserver.quizdiscovery.quiz.import.out.dated");
private final static String TEXT_KEY_ADDITIONAL_ATTR_PREFIX =
"sebserver.quizdiscovery.quiz.details.additional.";
// filter attribute models // filter attribute models
private final TableFilterAttribute institutionFilter; private final TableFilterAttribute institutionFilter;
private final TableFilterAttribute lmsFilter; private final TableFilterAttribute lmsFilter;
@ -270,6 +275,9 @@ public class QuizDiscoveryList implements TemplateComposer {
return action; return action;
} }
private static final Collection<String> ADDITIONAL_HTML_ATTRIBUTES = Arrays.asList(
"course_summary");
private void createDetailsForm( private void createDetailsForm(
final QuizData quizData, final QuizData quizData,
final PageContext pc, final PageContext pc,
@ -318,14 +326,43 @@ public class QuizDiscoveryList implements TemplateComposer {
quizData.additionalAttributes quizData.additionalAttributes
.entrySet() .entrySet()
.stream() .stream()
.forEach(entry -> formbuilder .forEach(entry -> {
.addField(FormBuilder.text( LocTextKey titleKey = new LocTextKey(TEXT_KEY_ADDITIONAL_ATTR_PREFIX + entry.getKey());
entry.getKey(), if (!this.pageService.getI18nSupport().hasText(titleKey)) {
new LocTextKey(entry.getKey()), titleKey = new LocTextKey(entry.getKey());
entry.getValue()))); }
formbuilder
.addField(FormBuilder.text(
entry.getKey(),
titleKey,
toAdditionalValue(entry.getKey(), entry.getValue()))
.asHTML(ADDITIONAL_HTML_ATTRIBUTES.contains(entry.getKey())));
});
} }
formbuilder.build(); formbuilder.build();
} }
private String toAdditionalValue(final String name, final String value) {
if ("timecreated".equals(name)) {
try {
return this.pageService
.getI18nSupport()
.formatDisplayDate(Utils.toDateTimeUTCUnix(Long.parseLong(value)));
} catch (final Exception e) {
return value;
}
} else if ("timelimit".equals(name)) {
try {
return this.pageService
.getI18nSupport()
.formatDisplayTime(Utils.toDateTimeUTCUnix(Long.parseLong(value)));
} catch (final Exception e) {
return value;
}
} else {
return value;
}
}
} }

View file

@ -14,6 +14,8 @@ import org.apache.commons.lang3.StringUtils;
import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
@ -73,6 +75,11 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
return this; return this;
} }
public FieldBuilder<?> asHTML(final boolean html) {
this.isHTML = html;
return this;
}
public TextFieldBuilder asColorbox() { public TextFieldBuilder asColorbox() {
this.isColorbox = true; this.isColorbox = true;
return this; return this;
@ -88,9 +95,10 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
final Browser browser = new Browser(fieldGrid, SWT.NONE); final Browser browser = new Browser(fieldGrid, SWT.NONE);
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true); final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true);
gridData.minimumHeight = this.areaMinHeight; gridData.minimumHeight = this.areaMinHeight;
browser.setBackground(new Color(builder.formParent.getDisplay(), new RGB(240, 240, 240)));
browser.setLayoutData(gridData); browser.setLayoutData(gridData);
if (StringUtils.isNoneBlank(this.value)) { if (StringUtils.isNoneBlank(this.value)) {
browser.setText(HTML_TEXT_BLOCK_START + this.value + HTML_TEXT_BLOCK_END); browser.setText(createHTMLText(this.value));
} else if (readonly) { } else if (readonly) {
browser.setText(Constants.EMPTY_NOTE); browser.setText(Constants.EMPTY_NOTE);
} }
@ -129,4 +137,14 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
} }
private String createHTMLText(final String text) {
return HTML_TEXT_BLOCK_START
+ text
.replace("<a", "<span")
.replace("</a", "</span")
.replace("<A", "<span")
.replace("</A", "</span")
+ HTML_TEXT_BLOCK_END;
}
} }

View file

@ -37,6 +37,7 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute; import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
import ch.ethz.seb.sebserver.gui.widget.Selection; import ch.ethz.seb.sebserver.gui.widget.Selection;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
public class TableFilter<ROW extends Entity> { public class TableFilter<ROW extends Entity> {
@ -418,10 +419,7 @@ public class TableFilter<ROW extends Entity> {
@Override @Override
FilterComponent build(final Composite parent) { FilterComponent build(final Composite parent) {
final Composite innerComposite = createInnerComposite(parent); final Composite innerComposite = createInnerComposite(parent);
final GridData gridData = new GridData(SWT.FILL, SWT.END, true, true); this.selector = TableFilter.this.entityTable.widgetFactory.dateSelector(innerComposite);
this.selector = new DateTime(innerComposite, SWT.DATE | SWT.BORDER);
this.selector.setLayoutData(gridData);
return this; return this;
} }
@ -478,7 +476,7 @@ public class TableFilter<ROW extends Entity> {
private class DateRange extends FilterComponent { private class DateRange extends FilterComponent {
private Composite innerComposite; private Composite innerComposite;
private final GridData rw1 = new GridData(SWT.FILL, SWT.FILL, true, true); //private final GridData rw1 = new GridData(SWT.FILL, SWT.FILL, true, true);
private DateTime fromDateSelector; private DateTime fromDateSelector;
private DateTime toDateSelector; private DateTime toDateSelector;
private DateTime fromTimeSelector; private DateTime fromTimeSelector;
@ -505,26 +503,17 @@ public class TableFilter<ROW extends Entity> {
this.innerComposite.setLayout(gridLayout); this.innerComposite.setLayout(gridLayout);
this.innerComposite.setLayoutData(this.rowData); this.innerComposite.setLayoutData(this.rowData);
TableFilter.this.entityTable.widgetFactory final WidgetFactory wf = TableFilter.this.entityTable.widgetFactory;
.labelLocalized(this.innerComposite, DATE_FROM_TEXT); wf.labelLocalized(this.innerComposite, DATE_FROM_TEXT);
this.fromDateSelector = this.fromDateSelector = wf.dateSelector(this.innerComposite);
new DateTime(this.innerComposite, SWT.DATE | SWT.BORDER);
this.fromDateSelector.setLayoutData(this.rw1);
if (this.withTime) { if (this.withTime) {
this.fromTimeSelector = this.fromTimeSelector = wf.timeSelector(this.innerComposite);
new DateTime(this.innerComposite, SWT.TIME | SWT.BORDER);
this.fromTimeSelector.setLayoutData(this.rw1);
} }
TableFilter.this.entityTable.widgetFactory wf.labelLocalized(this.innerComposite, DATE_TO_TEXT);
.labelLocalized(this.innerComposite, DATE_TO_TEXT); this.toDateSelector = wf.dateSelector(this.innerComposite);
this.toDateSelector =
new DateTime(this.innerComposite, SWT.DATE | SWT.BORDER);
this.toDateSelector.setLayoutData(this.rw1);
if (this.withTime) { if (this.withTime) {
this.toTimeSelector = this.toTimeSelector = wf.timeSelector(this.innerComposite);
new DateTime(this.innerComposite, SWT.TIME | SWT.BORDER);
this.toTimeSelector.setLayoutData(this.rw1);
} }
return this; return this;

View file

@ -25,6 +25,7 @@ import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Listener;
@ -617,6 +618,27 @@ public class WidgetFactory {
return selection; return selection;
} }
public DateTime dateSelector(final Composite parent) {
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
final DateTime dateTime = new DateTime(parent, SWT.DATE | SWT.BORDER | SWT.DROP_DOWN);
dateTime.setLayoutData(gridData);
return dateTime;
}
public DateTime timeSelector(final Composite parent) {
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
final DateTime dateTime = new DateTime(parent, SWT.TIME | SWT.BORDER | SWT.SHORT);
dateTime.setLayoutData(gridData);
return dateTime;
}
public DateTime timeSelectorWithSeconds(final Composite parent) {
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
final DateTime dateTime = new DateTime(parent, SWT.TIME | SWT.BORDER | SWT.MEDIUM);
dateTime.setLayoutData(gridData);
return dateTime;
}
public ThresholdList thresholdList( public ThresholdList thresholdList(
final Composite parent, final Composite parent,
final Composite updateAnchor, final Composite updateAnchor,

View file

@ -183,7 +183,6 @@ public class MoodleCourseAccess extends CourseAccess {
.stream() .stream()
.map(courseQuizData -> { .map(courseQuizData -> {
final String startURI = uriPrefix + courseData.id; final String startURI = uriPrefix + courseData.id;
additionalAttrs.put("coursemodule", courseQuizData.coursemodule);
additionalAttrs.put("timelimit", String.valueOf(courseQuizData.timelimit)); additionalAttrs.put("timelimit", String.valueOf(courseQuizData.timelimit));
return new QuizData( return new QuizData(
courseQuizData.id, courseQuizData.id,

View file

@ -275,14 +275,6 @@ final class MoodleRestTemplateFactory {
functionReqEntity = new HttpEntity<>(null); functionReqEntity = new HttpEntity<>(null);
} }
// // NOTE: The interpretation of a multi-value GET parameter on a URL quesry part
// // seems to be very PHP specific. It must have the form of:
// // ... &param[]=x&param[]=y& ...
// // And the square bracket must not be escaped on the URL like: %5B%5D
// String urlString = queryParam.toUriString()
// .replaceAll("%5B", "[")
// .replaceAll("%5D", "]");
final ResponseEntity<String> response = super.exchange( final ResponseEntity<String> response = super.exchange(
queryParam.toUriString(), queryParam.toUriString(),
usePOST ? HttpMethod.POST : HttpMethod.GET, usePOST ? HttpMethod.POST : HttpMethod.GET,

View file

@ -285,6 +285,12 @@ sebserver.quizdiscovery.quiz.details.description=Description
sebserver.quizdiscovery.quiz.details.starttime=Start Time sebserver.quizdiscovery.quiz.details.starttime=Start Time
sebserver.quizdiscovery.quiz.details.endtime=End Time sebserver.quizdiscovery.quiz.details.endtime=End Time
sebserver.quizdiscovery.quiz.details.url=Start URL sebserver.quizdiscovery.quiz.details.url=Start URL
sebserver.quizdiscovery.quiz.details.additional.timecreated=Creation Time
sebserver.quizdiscovery.quiz.details.additional.course_shortname=Short Name
sebserver.quizdiscovery.quiz.details.additional.course_fullname=Full Name
sebserver.quizdiscovery.quiz.details.additional.course_displayname=Display Name
sebserver.quizdiscovery.quiz.details.additional.course_summary=Summary
sebserver.quizdiscovery.quiz.details.additional.timelimit=Time Limit
################################ ################################
# Exam # Exam

View file

@ -398,6 +398,26 @@ DateTime-DropDownButton {
width: 30px; width: 30px;
} }
DateTime-Calendar-Navbar {
border: none;
border-radius: 0;
background-color: #1F407A;
background-image: gradient(linear, left top, left bottom, from(#1F407A), to(#1F407A));
color: white;
font: 12px Arial, Helvetica, sans-serif;
text-shadow: none;
}
DateTime-Field:selected, DateTime-Calendar-Day:selected {
background-color: #1F407A;
color: #ffffff;
}
DateTime-Calendar-Day:selected:hover {
background-color: #1F407A;
color: #ffffff;
}
/* Message titlebar */ /* Message titlebar */
Shell.message { Shell.message {
font: 12px Arial, Helvetica, sans-serif; font: 12px Arial, Helvetica, sans-serif;