From ac884020888a7103f5d0e6e2764b061902a1e381 Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Thu, 20 Mar 2025 16:20:31 -0700 Subject: [PATCH 1/3] Migrate remaining renderInputHtml() overrides --- .../api/data/AbstractExcelDisplayColumn.java | 6 - api/src/org/labkey/api/data/DataColumn.java | 174 +++++++++--------- .../org/labkey/api/data/DisplayColumn.java | 21 +-- .../org/labkey/api/data/MVDisplayColumn.java | 62 ++----- .../labkey/api/data/SimpleDisplayColumn.java | 6 - .../api/query/PropertiesDisplayColumn.java | 2 +- .../api/study/actions/StudyPickerColumn.java | 42 ++--- .../org/labkey/api/util/element/Input.java | 33 ++++ .../org/labkey/api/util/element/Select.java | 2 + .../api/view/ColorPickerDisplayColumn.java | 30 +-- .../view/TypeAheadSelectDisplayColumn.java | 23 ++- .../plate/PlateSampleFilePropertyHelper.java | 146 ++++++++------- .../lineage/LineageDisplayColumn.java | 2 +- .../issue/query/IssuesListDefTable.java | 37 ++-- .../mothership/AssignedToDisplayColumn.java | 36 ++-- .../labkey/mothership/MothershipManager.java | 5 - .../labkey/api/study/InsertUpdateAction.java | 26 ++- 17 files changed, 313 insertions(+), 340 deletions(-) diff --git a/api/src/org/labkey/api/data/AbstractExcelDisplayColumn.java b/api/src/org/labkey/api/data/AbstractExcelDisplayColumn.java index e28d35d3e59..292275d42ea 100644 --- a/api/src/org/labkey/api/data/AbstractExcelDisplayColumn.java +++ b/api/src/org/labkey/api/data/AbstractExcelDisplayColumn.java @@ -56,12 +56,6 @@ public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) throw new UnsupportedOperationException("This is for excel only."); } - @Override - protected void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException - { - throw new UnsupportedOperationException("This is for excel only."); - } - @Override public HtmlString getTitle(RenderContext ctx) { diff --git a/api/src/org/labkey/api/data/DataColumn.java b/api/src/org/labkey/api/data/DataColumn.java index 1c4cf1d1ca9..8c74486913e 100644 --- a/api/src/org/labkey/api/data/DataColumn.java +++ b/api/src/org/labkey/api/data/DataColumn.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.labkey.api.action.SpringActionController; +import org.labkey.api.collections.LabKeyCollectors; import org.labkey.api.collections.NamedObject; import org.labkey.api.collections.NamedObjectList; import org.labkey.api.exp.property.IPropertyValidator; @@ -33,6 +34,7 @@ import org.labkey.api.settings.OptionalFeatureService; import org.labkey.api.stats.AnalyticsProviderRegistry; import org.labkey.api.stats.ColumnAnalyticsProvider; +import org.labkey.api.util.DOM.Renderable; import org.labkey.api.util.HtmlString; import org.labkey.api.util.HtmlStringBuilder; import org.labkey.api.util.JavaScriptFragment; @@ -65,6 +67,12 @@ import java.util.Objects; import java.util.Set; +import static org.labkey.api.util.DOM.DIV; +import static org.labkey.api.util.DOM.SPAN; +import static org.labkey.api.util.DOM.TD; +import static org.labkey.api.util.DOM.cl; +import static org.labkey.api.util.DOM.id; + /** Subclass that wraps a ColumnInfo to pull values from the database */ public class DataColumn extends DisplayColumn { @@ -313,13 +321,13 @@ public Object getJsonValue(RenderContext ctx) } @Override - public Class getValueClass() + public Class getValueClass() { return _boundColumn.getJavaClass(); } @Override - public Class getDisplayValueClass() + public Class getDisplayValueClass() { return _displayColumn.getJavaClass(); } @@ -633,7 +641,7 @@ protected String getStringValue(Object value, boolean disabledInput) } @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { if (_boundColumn.isVersionColumn() || _inputType.equalsIgnoreCase("none")) return; @@ -647,12 +655,12 @@ public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, renderHiddenFormInput(out, formFieldName, value); if (null != value) { - oldWriter.write(PageFlowUtil.filter(strVal)); + out.write(strVal); } } else if (_inputType.toLowerCase().startsWith("disabled")) { - renderTextFormInput(oldWriter, formFieldName, value, strVal, true); + renderTextFormInput(out, formFieldName, value, strVal, true); } else if (_inputType.toLowerCase().startsWith("select")) { @@ -662,42 +670,43 @@ else if (_inputType.toLowerCase().startsWith("select")) displayColumn.renderInputHtml(ctx, out, value); } else - renderSelectFormInputFromFk(ctx, oldWriter, formFieldName, value, strVal, disabledInput); + renderSelectFormInputFromFk(ctx, out, formFieldName, value, strVal, disabledInput); } else if (_inputType.equalsIgnoreCase("textarea")) { - renderTextAreaFormInput(oldWriter, formFieldName, value, strVal, disabledInput); + renderTextAreaFormInput(out, formFieldName, value, strVal, disabledInput); } else if (_inputType.equalsIgnoreCase("file")) { - renderFileFormInput(oldWriter, formFieldName, value, strVal, disabledInput); + renderFileFormInput(out, formFieldName, value, strVal, disabledInput); } else if (_inputType.equalsIgnoreCase("checkbox")) { - renderCheckboxFormInput(oldWriter, formFieldName, value, strVal, disabledInput); + renderCheckboxFormInput(out, formFieldName, value, strVal, disabledInput); } else { if (getAutoCompleteURLPrefix() != null) { - renderAutoCompleteFormInput(ctx, oldWriter, formFieldName, value, strVal, disabledInput, getAutoCompleteURLPrefix()); + renderAutoCompleteFormInput(ctx, out, formFieldName, value, strVal, disabledInput, getAutoCompleteURLPrefix()); } else { IPropertyValidator textChoiceValidator = PropertyService.get().getValidatorForColumn(_boundColumn, PropertyValidatorType.TextChoice); if (textChoiceValidator != null) - renderTextChoiceFormInput(oldWriter, formFieldName, value, strVal, disabledInput, textChoiceValidator); + renderTextChoiceFormInput(out, formFieldName, value, strVal, disabledInput, textChoiceValidator); else - renderTextFormInput(oldWriter, formFieldName, value, strVal, disabledInput); + renderTextFormInput(out, formFieldName, value, strVal, disabledInput); } } HtmlString errors = getErrors(ctx); - if (!StringUtils.isEmpty(errors.toString())) + if (!errors.isEmpty()) { - oldWriter.write(""); - oldWriter.write(errors.toString()); - oldWriter.write(""); + SPAN( + cl("help-block form-text"), + errors + ).appendTo(out); } } @@ -710,10 +719,7 @@ else if (_inputType.equalsIgnoreCase("checkbox")) return ctx.getForm() == null || col == null ? HtmlString.EMPTY_STRING : ctx.getErrors(col); } - private void renderSelectFormInput( - Writer out, String formFieldName, Object value, String strVal, - boolean disabledInput, NamedObjectList entryList - ) throws IOException + private void renderSelectFormInput(HtmlWriter out, String formFieldName, Object value, String strVal, boolean disabledInput, NamedObjectList entryList) { Select.SelectBuilder select = new Select.SelectBuilder() .disabled(disabledInput) @@ -738,15 +744,14 @@ private void renderSelectFormInput( options.add(option.build()); } - out.write(select.addOptions(options).toString()); + out.write(select.addOptions(options)); // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(HtmlWriter.of(out), formFieldName, value); + renderHiddenFormInput(out, formFieldName, value); } - private void renderTextChoiceFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput, IPropertyValidator textChoiceValidator) - throws IOException + private void renderTextChoiceFormInput(HtmlWriter out, String formFieldName, Object value, String strVal, boolean disabledInput, IPropertyValidator textChoiceValidator) { NamedObjectList options = new NamedObjectList(); List choices = PropertyService.get().getTextChoiceValidatorOptions(textChoiceValidator); @@ -764,8 +769,7 @@ private void renderTextChoiceFormInput(Writer out, String formFieldName, Object renderSelectFormInput(out, formFieldName, value, strVal, disabledInput, options); } - protected void renderSelectFormInputFromFk(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) - throws IOException + protected void renderSelectFormInputFromFk(RenderContext ctx, HtmlWriter out, String formFieldName, Object value, String strVal, boolean disabledInput) { ForeignKey boundColumnFK = _boundColumn.getFk(); NamedObjectList entryList = boundColumnFK.getSelectList(ctx); @@ -791,8 +795,7 @@ protected void renderSelectFormInputFromFk(RenderContext ctx, Writer out, String } } - protected void renderFileFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) - throws IOException + protected void renderFileFormInput(HtmlWriter out, String formFieldName, Object value, String strVal, boolean disabledInput) { var input = new Input.InputBuilder<>() .type("file") @@ -800,11 +803,10 @@ protected void renderFileFormInput(Writer out, String formFieldName, Object valu .disabled(disabledInput) .needsWrapping(false); - out.write(input.build().toString()); + out.write(input); } - protected void renderCheckboxFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) - throws IOException + protected void renderCheckboxFormInput(HtmlWriter out, String formFieldName, Object value, String strVal, boolean disabledInput) { boolean checked = ColumnInfo.booleanFromObj(ConvertUtils.convert(value)); @@ -816,7 +818,7 @@ protected void renderCheckboxFormInput(Writer out, String formFieldName, Object .checked(checked) .needsWrapping(false); - out.write(input.build().toString()); + out.write(input); /* * Checkboxes are weird. If set to FALSE they don't post at all, so it's impossible to tell @@ -826,17 +828,17 @@ protected void renderCheckboxFormInput(Writer out, String formFieldName, Object * To fix this, each checkbox posts a hidden field named @columnName. Spring parameter * binding uses these special fields to set all unposted checkbox values to false. */ - out.write(""); + out.write(new Input.InputBuilder<>() + .type("hidden") + .name(SpringActionController.FIELD_MARKER + formFieldName) + .value(1)); + // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(HtmlWriter.of(out), formFieldName, checked ? "1" : ""); + renderHiddenFormInput(out, formFieldName, checked ? "1" : ""); } - protected void renderTextAreaFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) - throws IOException + protected void renderTextAreaFormInput(HtmlWriter out, String formFieldName, Object value, String strVal, boolean disabledInput) { TextArea.TextAreaBuilder input = new TextArea.TextAreaBuilder() .columns(_inputLength) @@ -845,15 +847,14 @@ protected void renderTextAreaFormInput(Writer out, String formFieldName, Object .disabled(disabledInput) .value(strVal); - out.write(input.build().toString()); + out.write(input); // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(HtmlWriter.of(out), formFieldName, value); + renderHiddenFormInput(out, formFieldName, value); } - protected void renderTextFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) - throws IOException + protected void renderTextFormInput(HtmlWriter out, String formFieldName, Object value, String strVal, boolean disabledInput) { var input = new Input.InputBuilder<>() .name(formFieldName) @@ -862,18 +863,20 @@ protected void renderTextFormInput(Writer out, String formFieldName, Object valu .value(strVal) .needsWrapping(false); - out.write(input.build().toString()); + out.write(input); // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(HtmlWriter.of(out), formFieldName, value); + renderHiddenFormInput(out, formFieldName, value); } - protected void renderAutoCompleteFormInput(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput, @NotNull ActionURL autoCompleteURLPrefix) - throws IOException + protected void renderAutoCompleteFormInput(RenderContext ctx, HtmlWriter out, String formFieldName, Object value, String strVal, boolean disabledInput, @NotNull ActionURL autoCompleteURLPrefix) { String renderId = "auto-complete-div-" + UniqueID.getRequestScopedUID(ctx.getRequest()); - out.write("
"); + DIV( + id(renderId) + ).appendTo(out); + String initScript = "Ext4.onReady(function(){\n" + " Ext4.create('LABKEY.element.AutoCompletionField', {\n" + @@ -941,57 +944,44 @@ public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullabl if (null == _caption) return; - Writer oldWriter = out.unwrap(); - try - { - oldWriter.write(""); - - HtmlString title = getTitle(ctx); - if (title != null) - oldWriter.write(title.toString()); - if (ctx.getMode() == DataRegion.MODE_DETAILS) - oldWriter.write(":"); - int mode = ctx.getMode(); - if ((mode == DataRegion.MODE_INSERT || mode == DataRegion.MODE_UPDATE) && isEditable()) - { - if (_boundColumn != null) + TD( + cl(cls != null, cls, "lk-form-label"), + getTitle(ctx), + ctx.getMode() == DataRegion.MODE_DETAILS ? ":" : null, + (Renderable) ret -> { + + int mode = ctx.getMode(); + if ((mode == DataRegion.MODE_INSERT || mode == DataRegion.MODE_UPDATE) && isEditable()) { - List helpLines = new LinkedList<>() + if (_boundColumn != null) { - @Override - public boolean add(String s) + List helpLines = new LinkedList<>(); + if (_boundColumn.getFriendlyTypeName() != null && !_inputType.toLowerCase().startsWith("select")) { - return super.add(PageFlowUtil.filter(s)); + helpLines.add(HtmlString.of("Type: " + _boundColumn.getFriendlyTypeName())); + } + if (_boundColumn.getDescription() != null) + { + helpLines.add(HtmlString.of("Description: " + _boundColumn.getDescription())); + } + for (IPropertyValidator validator : _boundColumn.getValidators()) + helpLines.add(HtmlString.of("Validator: " + validator)); + if (renderRequiredIndicators() && _boundColumn.isRequired() && !_boundColumn.isBooleanType()) + { + out.write(" *"); + helpLines.add(HtmlString.of("This field is required.")); + } + if (!helpLines.isEmpty()) + { + HtmlString helpHtml = helpLines.stream().collect(LabKeyCollectors.joining(HtmlString.BR)); + out.write(PageFlowUtil.popupHelp(helpHtml, _boundColumn.getLabel())); } - }; - if (_boundColumn.getFriendlyTypeName() != null && !_inputType.toLowerCase().startsWith("select")) - { - helpLines.add("Type: " + _boundColumn.getFriendlyTypeName()); - } - if (_boundColumn.getDescription() != null) - { - helpLines.add("Description: " + _boundColumn.getDescription()); - } - for (IPropertyValidator validator : _boundColumn.getValidators()) - helpLines.add("Validator: " + validator); - if (renderRequiredIndicators() && _boundColumn.isRequired() && !_boundColumn.isBooleanType()) - { - oldWriter.write(" *"); - helpLines.add("This field is required."); - } - if (!helpLines.isEmpty()) - { - HtmlString helpHtml = HtmlString.unsafe(StringUtils.join(helpLines, "
")); - PageFlowUtil.popupHelp(helpHtml, _boundColumn.getLabel()).appendTo(oldWriter); } } + + return ret; } - oldWriter.write("\n"); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + ).appendTo(out); } protected boolean renderRequiredIndicators() diff --git a/api/src/org/labkey/api/data/DisplayColumn.java b/api/src/org/labkey/api/data/DisplayColumn.java index af574b493bb..51ed7070157 100644 --- a/api/src/org/labkey/api/data/DisplayColumn.java +++ b/api/src/org/labkey/api/data/DisplayColumn.java @@ -144,7 +144,7 @@ public boolean shouldRenderInCurrentRow(RenderContext ctx) /* Note: DataRegion plus its subclasses and the vast majority of DisplayColumn (and subclasses) have been rewritten to use HtmlWriter, DOM, and builders instead of String-based HTML generation. They also no longer throw - IOException. The three deprecated methods below that take both Writer and HtmlWriter are temporary, present only + IOException. The two deprecated methods below that take both Writer and HtmlWriter are temporary, present only until their overrides are migrated to use HtmlWriter, DOM, and builders, and adjusted to override the corresponding non-Writer variant. Once migrated, the deprecated methods will be removed and the non-deprecated variants will be made abstract. @@ -188,24 +188,7 @@ protected void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, Ht throw new IllegalStateException("Must override renderDetailsCellContents()"); } - public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) - { - try - { - renderInputHtml(ctx, out.unwrap(), out, value); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - // No callers (other than just above) - @Deprecated - protected void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException - { - throw new IllegalStateException("Must override renderInputHtml()"); - } + public abstract void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value); public @Nullable HtmlString getTitle(RenderContext ctx) { diff --git a/api/src/org/labkey/api/data/MVDisplayColumn.java b/api/src/org/labkey/api/data/MVDisplayColumn.java index 19d0aa512bc..7a0dc19471a 100644 --- a/api/src/org/labkey/api/data/MVDisplayColumn.java +++ b/api/src/org/labkey/api/data/MVDisplayColumn.java @@ -20,10 +20,9 @@ import org.labkey.api.util.HtmlString; import org.labkey.api.util.HtmlStringBuilder; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.element.Select.SelectBuilder; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Set; import static org.labkey.api.util.DOM.Attribute.style; @@ -180,57 +179,34 @@ public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { DIV(at(style,"margin-top:5px")).appendTo(out); super.renderInputHtml(ctx, out, value); - try - { - renderMVPicker(ctx, out); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + renderMVPicker(ctx, out); } - private void renderMVPicker(RenderContext ctx, HtmlWriter out) throws IOException + private void renderMVPicker(RenderContext ctx, HtmlWriter out) { - Writer oldWriter = out.unwrap(); String formFieldName = ctx.getForm().getFormFieldName(mvIndicatorColumn); String selectedMvIndicator = getMvIndicator(ctx); Set mvIndicators = MvUtil.getMvIndicators(ctx.getContainer()); - oldWriter.write("Missing Value Indicator: "); - oldWriter.write(""); - // disabled inputs are not posted with the form, so we output a hidden form element: - //if (isDisabledInput()) - // renderHiddenFormInput(ctx, out, formFieldName, value); - } - - private void outputName(RenderContext ctx, Writer out, String formFieldName) throws IOException - { - out.write(" name=\""); - out.write(PageFlowUtil.filter(formFieldName)); - out.write("\""); - String setFocusId = (String)ctx.get("setFocusId"); if (null != setFocusId) { - out.write(" id=\"" + PageFlowUtil.filter(setFocusId) + "\""); ctx.remove("setFocusId"); } + + out.write("Missing Value Indicator:"); + out.write(HtmlString.NBSP); + + new SelectBuilder() + .addStyle("margin-bottom:5px; margin-top:2px") + .name(formFieldName) + .id(setFocusId) + .disabled(isDisabledInput()) + .addOption("") + .addOptions(mvIndicators) + .selected(selectedMvIndicator); + + // disabled inputs are not posted with the form, so we output a hidden form element: + //if (isDisabledInput()) + // renderHiddenFormInput(ctx, out, formFieldName, value); } } diff --git a/api/src/org/labkey/api/data/SimpleDisplayColumn.java b/api/src/org/labkey/api/data/SimpleDisplayColumn.java index d64f56277ba..68901da61ea 100644 --- a/api/src/org/labkey/api/data/SimpleDisplayColumn.java +++ b/api/src/org/labkey/api/data/SimpleDisplayColumn.java @@ -167,12 +167,6 @@ public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) throw new UnsupportedOperationException("Non Bound columns not editable for " + this); } - @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException - { - throw new UnsupportedOperationException("Non Bound columns not editable for " + this); - } - @Override public @NotNull HtmlString getTitle(RenderContext ctx) { diff --git a/api/src/org/labkey/api/query/PropertiesDisplayColumn.java b/api/src/org/labkey/api/query/PropertiesDisplayColumn.java index 76d27bf07ad..a87089063ac 100644 --- a/api/src/org/labkey/api/query/PropertiesDisplayColumn.java +++ b/api/src/org/labkey/api/query/PropertiesDisplayColumn.java @@ -279,7 +279,7 @@ public boolean isEditable() } @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { // no-op } diff --git a/api/src/org/labkey/api/study/actions/StudyPickerColumn.java b/api/src/org/labkey/api/study/actions/StudyPickerColumn.java index 67a5b5768db..1cd82aad728 100644 --- a/api/src/org/labkey/api/study/actions/StudyPickerColumn.java +++ b/api/src/org/labkey/api/study/actions/StudyPickerColumn.java @@ -26,6 +26,7 @@ import org.labkey.api.security.permissions.ReadPermission; import org.labkey.api.study.Study; import org.labkey.api.study.publish.StudyPublishService; +import org.labkey.api.util.DOM.Renderable; import org.labkey.api.util.HtmlString; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.element.Input; @@ -33,10 +34,11 @@ import org.labkey.api.util.element.Select.SelectBuilder; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Set; +import static org.labkey.api.util.DOM.TD; +import static org.labkey.api.util.DOM.cl; + public class StudyPickerColumn extends UploadWizardAction.InputDisplayColumn { ColumnInfo _colInfo; @@ -69,29 +71,25 @@ public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullabl if (null == _caption) return; - Writer oldWriter = out.unwrap(); - try - { - oldWriter.write(""); - oldWriter.write(getTitle(ctx).toString()); - int mode = ctx.getMode(); - if (mode == DataRegion.MODE_INSERT || mode == DataRegion.MODE_UPDATE) - { - if (_colInfo != null) + TD( + cl(cls != null ? cls : "lk-form-label"), + getTitle(ctx), + (Renderable) ret -> { + int mode = ctx.getMode(); + if (mode == DataRegion.MODE_INSERT || mode == DataRegion.MODE_UPDATE) { - String helpPopupText = ((_colInfo.getFriendlyTypeName() != null) ? "Type: " + _colInfo.getFriendlyTypeName() + "\n" : "") + - ((_colInfo.getDescription() != null) ? "Description: " + _colInfo.getDescription() + "\n" : ""); - PageFlowUtil.popupHelp(HtmlString.of(helpPopupText), _colInfo.getName()); - if (!_colInfo.isNullable()) - oldWriter.write(" *"); + if (_colInfo != null) + { + String helpPopupText = ((_colInfo.getFriendlyTypeName() != null) ? "Type: " + _colInfo.getFriendlyTypeName() + "\n" : "") + + ((_colInfo.getDescription() != null) ? "Description: " + _colInfo.getDescription() + "\n" : ""); + out.write(PageFlowUtil.popupHelp(HtmlString.of(helpPopupText), _colInfo.getName())); + if (!_colInfo.isNullable()) + out.write(" *"); + } } + return ret; } - oldWriter.write(""); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + ).appendTo(out); } protected boolean isDisabledInput() diff --git a/api/src/org/labkey/api/util/element/Input.java b/api/src/org/labkey/api/util/element/Input.java index 1d89218b78d..a5db642b100 100644 --- a/api/src/org/labkey/api/util/element/Input.java +++ b/api/src/org/labkey/api/util/element/Input.java @@ -16,6 +16,7 @@ package org.labkey.api.util.element; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.labkey.api.data.RenderContext; import org.labkey.api.util.HasHtmlString; @@ -122,6 +123,7 @@ public static State get(String stateName) private final @Nullable HtmlString _value; private final Integer _tabIndex; private final List _styles; + private final List _dataAttributes; protected Input(InputBuilder builder) { @@ -169,6 +171,7 @@ protected Input(InputBuilder builder) _needsWrapping = builder._needsWrapping == null || builder._needsWrapping; _tabIndex = builder._tabIndex; _styles = builder._styles; + _dataAttributes = builder._dataAttributes; } public String getAutoComplete() @@ -406,6 +409,11 @@ public List getStyles() return _styles; } + private List getDataAttributes() + { + return _dataAttributes; + } + @Override public void render(RenderContext ctx, Writer out) throws IOException { @@ -566,6 +574,7 @@ protected void doInput(Appendable sb) throws IOException sb.append(" tabIndex=\"").append(h(_tabIndex)).append("\""); doStyles(sb); + doDataAttributes(sb); if (!HtmlString.isBlank(getValue())) sb.append(" value=\"").append(h(getValue())).append("\""); doInputEvents(id); @@ -610,6 +619,20 @@ protected void doStyles(Appendable sb) throws IOException } } + protected void doDataAttributes(Appendable sb) + { + getDataAttributes().forEach(attr -> { + try + { + sb.append(" data-").append(attr.name()).append("=\"").append(h(attr.value())).append("\""); + } + catch (IOException io) + { + UnexpectedException.rethrow(io); + } + }); + } + protected void doInputEvents(String id) { var pageConfig = HttpView.currentPageConfig(); @@ -760,6 +783,9 @@ public static class InputBuilder> implements HasHtmlSt private Integer _tabIndex; private final List _styles = new LinkedList<>(); + private final List _dataAttributes = new LinkedList<>(); + + private record DataAttribute(String name, String value) {} public InputBuilder() { @@ -1061,6 +1087,13 @@ public T addStyles(List styles) return (T)this; } + // Add an arbitrary "data-" attribute. Name should not include "data-"... the builder will add prefix. + public T addDataAttribute(@NotNull String name, @NotNull String value) + { + _dataAttributes.add(new DataAttribute(name, value)); + return (T)this; + } + public Input build() { return new Input(this); diff --git a/api/src/org/labkey/api/util/element/Select.java b/api/src/org/labkey/api/util/element/Select.java index 38d3bb94ba9..e42b8c80b52 100644 --- a/api/src/org/labkey/api/util/element/Select.java +++ b/api/src/org/labkey/api/util/element/Select.java @@ -71,6 +71,8 @@ protected void doInput(Appendable sb) throws IOException doStyles(sb); + doDataAttributes(sb); + doInputEvents(id); if (isDisabled()) diff --git a/api/src/org/labkey/api/view/ColorPickerDisplayColumn.java b/api/src/org/labkey/api/view/ColorPickerDisplayColumn.java index be7cd445224..b6fa6a6c79e 100644 --- a/api/src/org/labkey/api/view/ColorPickerDisplayColumn.java +++ b/api/src/org/labkey/api/view/ColorPickerDisplayColumn.java @@ -18,12 +18,15 @@ import org.labkey.api.data.ColumnInfo; import org.labkey.api.data.DataColumn; import org.labkey.api.data.RenderContext; +import org.labkey.api.util.JavaScriptFragment; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.UniqueID; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; +import static org.labkey.api.util.DOM.Attribute.style; +import static org.labkey.api.util.DOM.DIV; +import static org.labkey.api.util.DOM.SCRIPT; +import static org.labkey.api.util.DOM.at; /** * {@link org.labkey.api.data.DisplayColumn} that shows an ExtJS-based color picker component for insert/update forms @@ -37,29 +40,31 @@ public ColorPickerDisplayColumn(ColumnInfo col) } @Override - public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { Object value = getValue(ctx); if (value != null) { - oldWriter.write("
"); + DIV( + at(style, "height: 20px; width: 20px; background: #" + value) + ).appendTo(out); } } @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { String name = getFormFieldName(ctx); renderHiddenFormInput(out, name, value); String renderId = "color-picker-div-" + UniqueID.getRequestScopedUID(ctx.getRequest()); - oldWriter.write(""); - oldWriter.write("
"); + " });\n") + ).appendTo(out); + + DIV(renderId).appendTo(out); } } diff --git a/api/src/org/labkey/api/view/TypeAheadSelectDisplayColumn.java b/api/src/org/labkey/api/view/TypeAheadSelectDisplayColumn.java index 91398c2f446..9dd53bcbebb 100644 --- a/api/src/org/labkey/api/view/TypeAheadSelectDisplayColumn.java +++ b/api/src/org/labkey/api/view/TypeAheadSelectDisplayColumn.java @@ -22,15 +22,18 @@ import org.labkey.api.data.DisplayColumnFactory; import org.labkey.api.data.ForeignKey; import org.labkey.api.data.RenderContext; +import org.labkey.api.util.JavaScriptFragment; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.UniqueID; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Collection; import java.util.Collections; +import static org.labkey.api.util.DOM.DIV; +import static org.labkey.api.util.DOM.SCRIPT; +import static org.labkey.api.util.DOM.id; + /** * {@link DisplayColumn} that use a React QuerySelect component input to allow for type-ahead search/filter * for a select input that has too many options for a user to meaningfully scroll through. @@ -47,13 +50,13 @@ public TypeAheadSelectDisplayColumn(ColumnInfo col, Integer maxRows) } @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { ForeignKey fk = getBoundColumn().getFk(); // currently only supported for lookup columns with a defined schema/query if (fk == null) { - oldWriter.write("TypeAheadSelectDisplayColumn can only be used with a lookup column."); + out.write("TypeAheadSelectDisplayColumn can only be used with a lookup column."); return; } @@ -63,7 +66,6 @@ public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, String renderId = "query-select-div-" + UniqueID.getRequestScopedUID(ctx.getRequest()); StringBuilder sb = new StringBuilder(); - sb.append("\n"); - sb.append("
"); - oldWriter.write(sb.toString()); + + SCRIPT( + JavaScriptFragment.unsafe(sb.toString()) + ).appendTo(out); + + DIV( + id(renderId) + ).appendTo(out); // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) diff --git a/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java b/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java index e795e7b6b50..8fc1b23943d 100644 --- a/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java +++ b/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java @@ -39,7 +39,9 @@ import org.labkey.api.security.User; import org.labkey.api.study.assay.SampleMetadataInputFormat; import org.labkey.api.util.HtmlString; +import org.labkey.api.util.JavaScriptFragment; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.element.Input.InputBuilder; import org.labkey.api.view.HttpView; import org.labkey.api.view.InsertView; import org.labkey.api.view.template.PageConfig; @@ -53,7 +55,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.Writer; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -61,6 +62,15 @@ import java.util.Objects; import java.util.Set; +import static org.labkey.api.util.DOM.Attribute.style; +import static org.labkey.api.util.DOM.DIV; +import static org.labkey.api.util.DOM.SCRIPT; +import static org.labkey.api.util.DOM.TABLE; +import static org.labkey.api.util.DOM.TD; +import static org.labkey.api.util.DOM.TR; +import static org.labkey.api.util.DOM.cl; +import static org.labkey.api.util.DOM.id; + public class PlateSampleFilePropertyHelper extends PlateSamplePropertyHelper { private static final String SAMPLE_FILE_INPUT_NAME = "__sampleMetadataFile__"; @@ -320,7 +330,6 @@ public boolean isEditable() @Override public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullable String cls) { - if (_metadataInputFormat == SampleMetadataInputFormat.FILE_BASED) { String nounV1 = includesViruses ? "Sample/Virus" : "Sample"; @@ -330,75 +339,88 @@ public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullabl ". This information is used to determine data processing and to map " + nounV2.toLowerCase() + " values to plate locations."), nounV1 + " Metadata"); - Writer oldWriter = out.unwrap(); - try - { - oldWriter.write(""); - oldWriter.write(nounV1 + " Metadata"); - builder.appendTo(oldWriter); - oldWriter.write(" *"); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + TD( + cl(cls != null ? cls : "lk-form-label"), + nounV1 + " Metadata", + builder, + " *" + ).appendTo(out); } } @Override public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { - Writer oldWriter = out.unwrap(); - try + if (_metadataInputFormat == SampleMetadataInputFormat.FILE_BASED) { - if (_metadataInputFormat == SampleMetadataInputFormat.FILE_BASED) + String nounV1 = includesViruses ? "Sample/Virus" : "Sample"; + String nounV2 = includesViruses ? "Sample and virus" : "Sample"; + + out.write(nounV2 + " metadata should be uploaded in a TSV, CSV or Excel file with one row per " + nounV1.toLowerCase() + ". "); + out.write(PageFlowUtil.link("Download template", PageFlowUtil.urlProvider(NabUrls.class).getSampleXLSTemplateURL(_container, _protocol))); + out.write(HtmlString.BR); + + if (reshowFile != null) { - String nounV1 = includesViruses ? "Sample/Virus" : "Sample"; - String nounV2 = includesViruses ? "Sample and virus" : "Sample"; - - oldWriter.write(nounV2 + " metadata should be uploaded in a TSV, CSV or Excel file with one row per " + nounV1.toLowerCase() + ". "); - PageFlowUtil.link("Download template", PageFlowUtil.urlProvider(NabUrls.class).getSampleXLSTemplateURL(_container, _protocol)).appendTo(oldWriter); - oldWriter.write("
"); - if (reshowFile != null) - { - PageConfig pageConfig = HttpView.currentPageConfig(); - PipeRoot pipelineRoot = PipelineService.get().findPipelineRoot(ctx.getContainer()); - String filePath = PageFlowUtil.filter(pipelineRoot.relativePath(reshowFile).replace('\\', '/')); - String updateInputFn = ""; - oldWriter.write(updateInputFn); - oldWriter.write("\n"); - oldWriter.write("\n"); - pageConfig.addHandler("optionPrevUpload", "change", "showMetadataPicker(!this.checked);"); - oldWriter.write("\n"); - oldWriter.write("\n"); - oldWriter.write("\n"); - oldWriter.write("\n"); - oldWriter.write("\n"); - pageConfig.addHandler("optionNewUpload", "change", "showMetadataPicker(this.checked);"); - oldWriter.write("\n"); - oldWriter.write("\n"); - oldWriter.write("\n"); - oldWriter.write("\n
Use the metadata that was already uploaded to the server
" + PageFlowUtil.filter(reshowFile.getName()) + "
"); - oldWriter.write("\nUpload a data file
"); - } - else - { - oldWriter.write("
" + - "" + - "" + - "
"); - } + PageConfig pageConfig = HttpView.currentPageConfig(); + PipeRoot pipelineRoot = PipelineService.get().findPipelineRoot(ctx.getContainer()); + String filePath = PageFlowUtil.filter(pipelineRoot.relativePath(reshowFile).replace('\\', '/')); + + SCRIPT( + JavaScriptFragment.unsafe(""" + function showMetadataPicker(showFilePicker) { + document.getElementById('previousMetadataFileName').style.display = (showFilePicker ? 'none' : 'block'); + document.getElementById('newMetadataFileName').style.display = (!showFilePicker ? 'none' : 'block'); + }""") + ).appendTo(out); + + TABLE( + TR( + TD(new InputBuilder<>().type("radio").id("optionPrevUpload").name(METADATA_PROVIDER_INPUT_NAME).value(METADATA_PROVIDER_OPTION_PREVUPLOAD).checked(true)), + TD("Use the metadata that was already uploaded to the server") + ), + TR( + TD(), + TD( + DIV( + id("previousMetadataFileName").at(style, "display:block"), + reshowFile.getName() + ) + ) + ), + TR( + TD( + new InputBuilder<>().type("hidden").name(METADATA_PREVUPLOAD_LOCATION).value(filePath), + new InputBuilder<>().type("radio").id("optionNewUpload").name(METADATA_PROVIDER_INPUT_NAME).value(METADATA_PROVIDER_OPTION_NEWUPLOAD) + ), + TD("Upload a data file") + ), + TR( + TD(), + TD( + DIV( + id("newMetadataFileName").at(style, "display:none"), + new InputBuilder<>().type("file").id(SAMPLE_FILE_INPUT_NAME).name(SAMPLE_FILE_INPUT_NAME).size(40).addStyle("border: none") + ) + ) + ) + ).appendTo(out); + + pageConfig.addHandler("optionPrevUpload", "change", "showMetadataPicker(!this.checked);"); + pageConfig.addHandler("optionNewUpload", "change", "showMetadataPicker(this.checked);"); + } + else + { + TABLE( + TR( + TD(), + TD( + new InputBuilder<>().type("hidden").name(METADATA_PROVIDER_INPUT_NAME).value(METADATA_PROVIDER_OPTION_NEWUPLOAD), + new InputBuilder<>().type("file").name(SAMPLE_FILE_INPUT_NAME).size(40).addStyle("border: none") + ) + ) + ).appendTo(out); } - } - catch (IOException e) - { - throw new RuntimeException(e); } } }); diff --git a/experiment/src/org/labkey/experiment/lineage/LineageDisplayColumn.java b/experiment/src/org/labkey/experiment/lineage/LineageDisplayColumn.java index b594fc0b1de..e74b3303da5 100644 --- a/experiment/src/org/labkey/experiment/lineage/LineageDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/lineage/LineageDisplayColumn.java @@ -235,7 +235,7 @@ public boolean isEditable() } @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { } diff --git a/issues/src/org/labkey/issue/query/IssuesListDefTable.java b/issues/src/org/labkey/issue/query/IssuesListDefTable.java index 11987c828a9..c7bc870a484 100644 --- a/issues/src/org/labkey/issue/query/IssuesListDefTable.java +++ b/issues/src/org/labkey/issue/query/IssuesListDefTable.java @@ -51,8 +51,9 @@ import org.labkey.api.security.permissions.Permission; import org.labkey.api.security.permissions.ReadPermission; import org.labkey.api.util.Link; -import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.Pair; +import org.labkey.api.util.element.Option.OptionBuilder; +import org.labkey.api.util.element.Select.SelectBuilder; import org.labkey.api.view.ActionURL; import org.labkey.api.writer.HtmlWriter; import org.labkey.issue.IssuesController; @@ -61,13 +62,12 @@ import org.labkey.issue.model.IssueListDef; import org.labkey.issue.model.IssueManager; -import java.io.IOException; -import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Stream; public class IssuesListDefTable extends FilteredTable { @@ -338,30 +338,19 @@ public MultiValueInputColumn(ColumnInfo col, @NotNull List> } @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object val) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object val) { String formFieldName = ctx.getForm().getFormFieldName(getColumnInfo()); - oldWriter.write("\n"); + new SelectBuilder() + .name(formFieldName) + .addOptions( + _values.isEmpty() ? + Stream.of("") : + _values.stream() + .map(pair -> new OptionBuilder(pair.second, pair.first)) + ) + .appendTo(out); } @Override diff --git a/mothership/src/org/labkey/mothership/AssignedToDisplayColumn.java b/mothership/src/org/labkey/mothership/AssignedToDisplayColumn.java index 3cc560f5672..80f9c1a26b4 100644 --- a/mothership/src/org/labkey/mothership/AssignedToDisplayColumn.java +++ b/mothership/src/org/labkey/mothership/AssignedToDisplayColumn.java @@ -21,11 +21,10 @@ import org.labkey.api.data.DataColumn; import org.labkey.api.data.RenderContext; import org.labkey.api.security.User; -import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.element.Option.OptionBuilder; +import org.labkey.api.util.element.Select.SelectBuilder; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.List; public class AssignedToDisplayColumn extends DataColumn @@ -40,29 +39,18 @@ public AssignedToDisplayColumn(ColumnInfo col, Container c) } @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { List list = MothershipManager.get().getAssignedToList(_container); - oldWriter.write(""); + new SelectBuilder() + .name(getColumnInfo().getPropertyName()) + .addOption("") + .addOptions( + list.stream() + .map(user -> new OptionBuilder(user.getDisplayName(ctx.getViewContext().getUser()), user.getUserId())) + ) + .selected(value) + .appendTo(out); } } diff --git a/mothership/src/org/labkey/mothership/MothershipManager.java b/mothership/src/org/labkey/mothership/MothershipManager.java index e85a0076073..f5a9c22f104 100644 --- a/mothership/src/org/labkey/mothership/MothershipManager.java +++ b/mothership/src/org/labkey/mothership/MothershipManager.java @@ -17,7 +17,6 @@ package org.labkey.mothership; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -54,10 +53,6 @@ import static org.labkey.api.security.UserManager.USER_DISPLAY_NAME_COMPARATOR; -/** - * User: jeckels - * Date: Apr 20, 2006 - */ public class MothershipManager { private static final MothershipManager INSTANCE = new MothershipManager(); diff --git a/study/api-src/org/labkey/api/study/InsertUpdateAction.java b/study/api-src/org/labkey/api/study/InsertUpdateAction.java index def29455e7f..00554a6f2f9 100644 --- a/study/api-src/org/labkey/api/study/InsertUpdateAction.java +++ b/study/api-src/org/labkey/api/study/InsertUpdateAction.java @@ -52,6 +52,7 @@ import org.labkey.api.study.model.CohortService; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.URLHelper; +import org.labkey.api.util.element.Select.SelectBuilder; import org.labkey.api.view.ActionURL; import org.labkey.api.view.DataView; import org.labkey.api.view.InsertView; @@ -66,8 +67,6 @@ import org.springframework.validation.Errors; import org.springframework.web.servlet.ModelAndView; -import java.io.IOException; -import java.io.Writer; import java.sql.SQLException; import java.util.Collection; import java.util.Collections; @@ -142,23 +141,22 @@ public ModelAndView getView(Form form, boolean reshow, BindException errors) thr cohortCol.setDisplayColumnFactory(colInfo -> new DataColumn(colInfo) { @Override - public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { boolean disabledInput = isDisabledInput(); String formFieldName = ctx.getForm().getFormFieldName(getBoundColumn()); - oldWriter.write(""); + builder.addOption(""); + + builder.addOptions(cohorts.stream().map(StudyEntity::getLabel)) + .selected(value) + .appendTo(out); } }); } From fa5f93a028bad8e5b54bf0ad20722a368c202222 Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Fri, 21 Mar 2025 00:30:18 -0700 Subject: [PATCH 2/3] Fix MV select styling --- api/src/org/labkey/api/data/MVDisplayColumn.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/src/org/labkey/api/data/MVDisplayColumn.java b/api/src/org/labkey/api/data/MVDisplayColumn.java index 7a0dc19471a..d3fa3aef0aa 100644 --- a/api/src/org/labkey/api/data/MVDisplayColumn.java +++ b/api/src/org/labkey/api/data/MVDisplayColumn.java @@ -197,13 +197,16 @@ private void renderMVPicker(RenderContext ctx, HtmlWriter out) out.write(HtmlString.NBSP); new SelectBuilder() - .addStyle("margin-bottom:5px; margin-top:2px") + .addStyle("margin-bottom:5px") + .addStyle("margin-top:2px") + .className(null) .name(formFieldName) .id(setFocusId) .disabled(isDisabledInput()) .addOption("") .addOptions(mvIndicators) - .selected(selectedMvIndicator); + .selected(selectedMvIndicator) + .appendTo(out); // disabled inputs are not posted with the form, so we output a hidden form element: //if (isDisabledInput()) From 34d7f6e813bfc64d127576c910cc91b3ea984bfc Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Fri, 21 Mar 2025 09:14:09 -0700 Subject: [PATCH 3/3] Migrate remaining renderDetailsCellContents() overrides --- .../api/data/AbstractExcelDisplayColumn.java | 7 - api/src/org/labkey/api/data/DataColumn.java | 2 +- .../org/labkey/api/data/DisplayColumn.java | 27 +--- .../labkey/api/data/SimpleDisplayColumn.java | 4 +- .../experiment/DataFileURLDisplayColumn.java | 74 ---------- .../ExperimentRunDisplayColumn.java | 15 +- .../experiment/LineageGraphDisplayColumn.java | 24 ++-- .../ProtocolApplicationDisplayColumn.java | 16 +-- .../experiment/ProtocolDisplayColumn.java | 18 +-- .../experiment/SampleTypeDisplayColumn.java | 15 +- .../mothership/CreateIssueDisplayColumn.java | 8 +- .../pipeline/status/FileDisplayColumn.java | 29 ++-- .../pipeline/status/JobDisplayColumn.java | 130 ------------------ 13 files changed, 54 insertions(+), 315 deletions(-) delete mode 100644 experiment/src/org/labkey/experiment/DataFileURLDisplayColumn.java delete mode 100644 pipeline/src/org/labkey/pipeline/status/JobDisplayColumn.java diff --git a/api/src/org/labkey/api/data/AbstractExcelDisplayColumn.java b/api/src/org/labkey/api/data/AbstractExcelDisplayColumn.java index 292275d42ea..94fa421e31f 100644 --- a/api/src/org/labkey/api/data/AbstractExcelDisplayColumn.java +++ b/api/src/org/labkey/api/data/AbstractExcelDisplayColumn.java @@ -4,7 +4,6 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; import java.io.Writer; public abstract class AbstractExcelDisplayColumn extends DisplayColumn @@ -44,12 +43,6 @@ public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) throw new UnsupportedOperationException("This is for excel only."); } - @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) - { - throw new UnsupportedOperationException("This is for excel only."); - } - @Override public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { diff --git a/api/src/org/labkey/api/data/DataColumn.java b/api/src/org/labkey/api/data/DataColumn.java index 8c74486913e..4adbefe90dc 100644 --- a/api/src/org/labkey/api/data/DataColumn.java +++ b/api/src/org/labkey/api/data/DataColumn.java @@ -333,7 +333,7 @@ public Class getDisplayValueClass() } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { // By default, use the same rendering for both the details and grid views renderGridCellContents(ctx, out); diff --git a/api/src/org/labkey/api/data/DisplayColumn.java b/api/src/org/labkey/api/data/DisplayColumn.java index 51ed7070157..ac64180b7b5 100644 --- a/api/src/org/labkey/api/data/DisplayColumn.java +++ b/api/src/org/labkey/api/data/DisplayColumn.java @@ -144,10 +144,10 @@ public boolean shouldRenderInCurrentRow(RenderContext ctx) /* Note: DataRegion plus its subclasses and the vast majority of DisplayColumn (and subclasses) have been rewritten to use HtmlWriter, DOM, and builders instead of String-based HTML generation. They also no longer throw - IOException. The two deprecated methods below that take both Writer and HtmlWriter are temporary, present only - until their overrides are migrated to use HtmlWriter, DOM, and builders, and adjusted to override the - corresponding non-Writer variant. Once migrated, the deprecated methods will be removed and the non-deprecated - variants will be made abstract. + IOException. The deprecated renderGridCellContents() variant below that take both Writer and HtmlWriter is + temporary, present only until its overrides are migrated to use HtmlWriter, DOM, and builders, and adjusted to + override the corresponding non-Writer variant. Once migrated, the deprecated method will be removed and the + non-deprecated variant will be made abstract. */ public void renderGridCellContents(RenderContext ctx, HtmlWriter out) @@ -169,24 +169,7 @@ protected void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlW throw new IllegalStateException("Must override renderGridCellContents()"); } - public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) - { - try - { - renderDetailsCellContents(ctx, out.unwrap(), out); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - // No callers (other than just above) - @Deprecated - protected void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException - { - throw new IllegalStateException("Must override renderDetailsCellContents()"); - } + public abstract void renderDetailsCellContents(RenderContext ctx, HtmlWriter out); public abstract void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value); diff --git a/api/src/org/labkey/api/data/SimpleDisplayColumn.java b/api/src/org/labkey/api/data/SimpleDisplayColumn.java index 68901da61ea..d9733aca1c2 100644 --- a/api/src/org/labkey/api/data/SimpleDisplayColumn.java +++ b/api/src/org/labkey/api/data/SimpleDisplayColumn.java @@ -110,11 +110,11 @@ public Object getValue(RenderContext ctx) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { Object value = getValue(ctx); if (value != null) - oldWriter.write(value.toString()); + out.write(value.toString()); } @Override diff --git a/experiment/src/org/labkey/experiment/DataFileURLDisplayColumn.java b/experiment/src/org/labkey/experiment/DataFileURLDisplayColumn.java deleted file mode 100644 index d18d867c42d..00000000000 --- a/experiment/src/org/labkey/experiment/DataFileURLDisplayColumn.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2008-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.experiment; - -import org.labkey.api.data.RenderContext; -import org.labkey.api.data.SimpleDisplayColumn; -import org.labkey.api.exp.api.ExpData; -import org.labkey.api.util.PageFlowUtil; -import org.labkey.api.view.ActionURL; -import org.labkey.api.writer.HtmlWriter; -import org.labkey.experiment.controllers.exp.ExperimentController; - -import java.io.IOException; -import java.io.Writer; - -/** - * User: jeckels - * Date: Sep 29, 2005 - */ -public class DataFileURLDisplayColumn extends SimpleDisplayColumn -{ - private final ExpData _data; - - public DataFileURLDisplayColumn(ExpData data) - { - super(); - setCaption("Data File"); - _data = data; - } - - @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException - { - String dataFileURL = _data.getDataFileUrl(); - if (dataFileURL == null || dataFileURL.trim().isEmpty()) - { - oldWriter.write("(Unknown)
\n"); - return; - } - - ActionURL contentURL = _data.findDataHandler().getContentURL(_data); - if (contentURL == null && _data.isFileOnDisk()) - { - contentURL = ExperimentController.ExperimentUrlsImpl.get().getShowFileURL(_data, false); - } - - if (contentURL != null) - { - oldWriter.write(""); - } - oldWriter.write(PageFlowUtil.filter(dataFileURL)); - oldWriter.write(""); - - if (!_data.isFileOnDisk()) - { - oldWriter.write(" (Not available on disk)\n"); - } - } -} diff --git a/experiment/src/org/labkey/experiment/ExperimentRunDisplayColumn.java b/experiment/src/org/labkey/experiment/ExperimentRunDisplayColumn.java index c770ce20303..c83554283d2 100644 --- a/experiment/src/org/labkey/experiment/ExperimentRunDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/ExperimentRunDisplayColumn.java @@ -18,17 +18,11 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.exp.api.ExpRun; +import org.labkey.api.util.Link.LinkBuilder; import org.labkey.api.view.ActionURL; import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; -import java.io.IOException; -import java.io.Writer; - -/** - * User: jeckels - * Date: Oct 19, 2005 - */ public class ExperimentRunDisplayColumn extends SimpleDisplayColumn { private ExpRun _run; @@ -45,16 +39,17 @@ public ExperimentRunDisplayColumn(ExpRun run, String name) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { if (_run == null) { - oldWriter.write("(Unknown)"); + out.write("(Unknown)"); } else { ActionURL url = ExperimentController.getRunGraphURL(ctx.getContainer(), _run.getRowId()); - oldWriter.write("" + _run.getName() + ""); + + out.write(new LinkBuilder(_run.getName()).href(url).clearClasses()); } } } diff --git a/experiment/src/org/labkey/experiment/LineageGraphDisplayColumn.java b/experiment/src/org/labkey/experiment/LineageGraphDisplayColumn.java index 9965240d6f7..a3e7f30fb0f 100644 --- a/experiment/src/org/labkey/experiment/LineageGraphDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/LineageGraphDisplayColumn.java @@ -22,22 +22,16 @@ import org.labkey.api.exp.api.ExpObject; import org.labkey.api.exp.api.ExpProtocolApplication; import org.labkey.api.exp.api.ExpRun; +import org.labkey.api.util.Link.LinkBuilder; import org.labkey.api.view.ActionURL; import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; -import java.io.IOException; -import java.io.Writer; - -/** - * User: jeckels - * Date: Oct 19, 2005 - */ public class LineageGraphDisplayColumn extends SimpleDisplayColumn { - private Integer _runId; - private String _focus; - private String _linkText; + private final Integer _runId; + private final String _focus; + private final String _linkText; public LineageGraphDisplayColumn(ExpMaterial material, ExpRun run) { @@ -56,20 +50,19 @@ public LineageGraphDisplayColumn(ExpProtocolApplication app, ExpRun run) private LineageGraphDisplayColumn(String typeCode, ExpObject object, ExpRun run) { - _linkText = "Lineage for "; _focus = typeCode + object.getRowId(); - _linkText += object.getName(); + _linkText = "Lineage for " + object.getName(); _runId = run == null ? null : run.getRowId(); setCaption("Lineage Graph"); } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { if (_runId == null || _focus == null) { - oldWriter.write("(Unknown)"); + out.write("(Unknown)"); } else { @@ -77,7 +70,8 @@ public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlW url.addParameter("rowId", Integer.toString(_runId)); url.addParameter("detail", "true"); url.addParameter("focus", _focus); - oldWriter.write("" + _linkText + ""); + + out.write(new LinkBuilder(_linkText).href(url).clearClasses()); } } } diff --git a/experiment/src/org/labkey/experiment/ProtocolApplicationDisplayColumn.java b/experiment/src/org/labkey/experiment/ProtocolApplicationDisplayColumn.java index f94f32d7c50..d3ef28dfa23 100644 --- a/experiment/src/org/labkey/experiment/ProtocolApplicationDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/ProtocolApplicationDisplayColumn.java @@ -18,20 +18,14 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.exp.api.ExpProtocolApplication; +import org.labkey.api.util.Link.LinkBuilder; import org.labkey.api.view.ActionURL; import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; -import java.io.IOException; -import java.io.Writer; - -/** - * User: jeckels - * Date: Oct 19, 2005 - */ public class ProtocolApplicationDisplayColumn extends SimpleDisplayColumn { - private ExpProtocolApplication _protocolApplication; + private final ExpProtocolApplication _protocolApplication; public ProtocolApplicationDisplayColumn(ExpProtocolApplication protocolApplication) { @@ -45,16 +39,16 @@ public ProtocolApplicationDisplayColumn(ExpProtocolApplication protocolApplicati } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { if (_protocolApplication == null) { - oldWriter.write("(Unknown)"); + out.write("(Unknown)"); } else { ActionURL url = ExperimentController.getShowApplicationURL(ctx.getContainer(), _protocolApplication.getRowId()); - oldWriter.write("" + _protocolApplication.getName() + ""); + out.write(new LinkBuilder(_protocolApplication.getName()).href(url).clearClasses()); } } } diff --git a/experiment/src/org/labkey/experiment/ProtocolDisplayColumn.java b/experiment/src/org/labkey/experiment/ProtocolDisplayColumn.java index da593a22259..456cfa4b503 100644 --- a/experiment/src/org/labkey/experiment/ProtocolDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/ProtocolDisplayColumn.java @@ -18,20 +18,14 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.exp.api.ExpProtocol; +import org.labkey.api.util.Link.LinkBuilder; import org.labkey.api.view.ActionURL; import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; -import java.io.IOException; -import java.io.Writer; - -/** - * User: jeckels - * Date: Oct 19, 2005 - */ public class ProtocolDisplayColumn extends SimpleDisplayColumn { - private ExpProtocol _protocol; + private final ExpProtocol _protocol; public ProtocolDisplayColumn(ExpProtocol protocol) { @@ -45,18 +39,18 @@ public ProtocolDisplayColumn(ExpProtocol protocol, String name) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { if (_protocol == null) { - oldWriter.write("(Unknown)"); + out.write("(Unknown)"); } else { ActionURL url = new ActionURL(ExperimentController.ProtocolDetailsAction.class, ctx.getContainer()); url.addParameter("rowId", Integer.toString(_protocol.getRowId())); - oldWriter.write("" + _protocol.getName() + ""); + + out.write(new LinkBuilder(_protocol.getName()).href(url).clearClasses()); } } - } diff --git a/experiment/src/org/labkey/experiment/SampleTypeDisplayColumn.java b/experiment/src/org/labkey/experiment/SampleTypeDisplayColumn.java index 6ecba386f62..2ee12c8e77a 100644 --- a/experiment/src/org/labkey/experiment/SampleTypeDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/SampleTypeDisplayColumn.java @@ -20,18 +20,11 @@ import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.exp.api.ExpMaterial; import org.labkey.api.exp.api.ExpSampleType; -import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.Link.LinkBuilder; import org.labkey.api.view.ActionURL; import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; -import java.io.IOException; -import java.io.Writer; - -/** - * User: jeckels - * Date: Oct 4, 2007 - */ public class SampleTypeDisplayColumn extends SimpleDisplayColumn { private final ExpMaterial _material; @@ -43,19 +36,19 @@ public SampleTypeDisplayColumn(ExpMaterial material) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { ExpSampleType st = _material.getSampleType(); if (st == null) { - oldWriter.write("Not a member of a sample type"); + out.write("Not a member of a sample type"); } else { ActionURL url = new ActionURL(ExperimentController.ShowSampleTypeAction.class, st.getContainer()); url.addParameter("rowId", Integer.toString(st.getRowId())); - oldWriter.write("" + PageFlowUtil.filter(st.getName()) + ""); + out.write(new LinkBuilder(st.getName()).href(url).clearClasses()); } } } diff --git a/mothership/src/org/labkey/mothership/CreateIssueDisplayColumn.java b/mothership/src/org/labkey/mothership/CreateIssueDisplayColumn.java index d78c9e14e46..d46e8acccc2 100644 --- a/mothership/src/org/labkey/mothership/CreateIssueDisplayColumn.java +++ b/mothership/src/org/labkey/mothership/CreateIssueDisplayColumn.java @@ -39,14 +39,14 @@ public CreateIssueDisplayColumn(ColumnInfo column, ActionButton saveButton) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { - _saveButton.render(ctx, oldWriter); - oldWriter.write("\t"); + _saveButton.render(ctx, out); + out.write("\t"); PageFlowUtil.button("Create Issue") .onClick("document.forms.CreateIssue.elements['assignedTo'].value = document.forms[" + PageFlowUtil.jsString(ctx.getCurrentRegion().getFormId()) + "].elements['assignedTo'].value; document.forms.CreateIssue.submit();") - .appendTo(oldWriter); + .appendTo(out); } } diff --git a/pipeline/src/org/labkey/pipeline/status/FileDisplayColumn.java b/pipeline/src/org/labkey/pipeline/status/FileDisplayColumn.java index e9af8481f6b..2a4269e7ae0 100644 --- a/pipeline/src/org/labkey/pipeline/status/FileDisplayColumn.java +++ b/pipeline/src/org/labkey/pipeline/status/FileDisplayColumn.java @@ -23,12 +23,12 @@ import org.labkey.api.pipeline.PipelineProvider; import org.labkey.api.pipeline.PipelineService; import org.labkey.api.util.FileUtil; +import org.labkey.api.util.HtmlString; import org.labkey.api.util.NetworkDrive; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.writer.HtmlWriter; import java.io.IOException; -import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; @@ -42,12 +42,11 @@ public class FileDisplayColumn extends SimpleDisplayColumn { public FileDisplayColumn() { - super(); setCaption("Files"); } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { List files = null; @@ -67,7 +66,7 @@ public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlW if (files == null || files.isEmpty()) { - oldWriter.write(" "); + out.write(HtmlString.NBSP); } else { @@ -75,24 +74,22 @@ public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlW { // make sure the files can be open for read String fileName = file.getFileName().toString(); + if (Files.isReadable(file)) { - oldWriter.write(""); - oldWriter.write(PageFlowUtil.filter(fileName)); - oldWriter.write("\n"); - - oldWriter.write("  "); - PageFlowUtil.link("view").href(StatusController.urlShowFile(ctx.getContainer(), rowIdI.intValue(), fileName, false)).appendTo(oldWriter); - PageFlowUtil.link("download").href(StatusController.urlShowFile(ctx.getContainer(), rowIdI.intValue(), fileName, true)).appendTo(oldWriter); - oldWriter.write("
\n"); + out.write(PageFlowUtil.link(fileName).href(StatusController.urlShowFile(ctx.getContainer(), rowIdI.intValue(), fileName, false))); + out.write(HtmlString.NBSP); + out.write(HtmlString.NBSP); + out.write(PageFlowUtil.link("view").href(StatusController.urlShowFile(ctx.getContainer(), rowIdI.intValue(), fileName, false))); + out.write(PageFlowUtil.link("download").href(StatusController.urlShowFile(ctx.getContainer(), rowIdI.intValue(), fileName, true))); } else { - oldWriter.write(PageFlowUtil.filter(fileName)); - oldWriter.write("
\n"); + out.write(fileName); } + + out.write(HtmlString.BR); + out.write("\n"); } } } diff --git a/pipeline/src/org/labkey/pipeline/status/JobDisplayColumn.java b/pipeline/src/org/labkey/pipeline/status/JobDisplayColumn.java deleted file mode 100644 index 5c6351ec42f..00000000000 --- a/pipeline/src/org/labkey/pipeline/status/JobDisplayColumn.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2008-2019 LabKey Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.labkey.pipeline.status; - -import org.labkey.api.data.RenderContext; -import org.labkey.api.data.SimpleDisplayColumn; -import org.labkey.api.pipeline.PipelineStatusFile; -import org.labkey.api.util.PageFlowUtil; -import org.labkey.api.writer.HtmlWriter; -import org.labkey.pipeline.api.PipelineStatusFileImpl; - -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import static org.labkey.pipeline.api.PipelineStatusManager.getJobStatusFile; -import static org.labkey.pipeline.api.PipelineStatusManager.getSplitStatusFiles; - -/** - * SplitDisplayColumn class - *

- * Created: Oct 25, 2005 - * - * @author bmaclean - */ -public class JobDisplayColumn extends SimpleDisplayColumn -{ - private boolean _split; - private List _jobStatus; - - public JobDisplayColumn(boolean split) - { - super(); - _split = split; - if (_split) - setCaption("Split jobs"); - else - setCaption("Join job"); - } - - @Override - public boolean isVisible(RenderContext ctx) - { - return !getJobStatus(ctx).isEmpty(); - } - - @Override - public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException - { - if (_jobStatus == null || _jobStatus.isEmpty()) - oldWriter.write(" "); - else - { - int rowIndex = 0; - oldWriter.write("\n" + - "\n" + - "\n" + - " \n" + - " \n" + - ""); - for (PipelineStatusFile sf : _jobStatus) - { - if (rowIndex++ % 2 == 0) - oldWriter.write(""); - else - oldWriter.write(""); - - oldWriter.write(""); - oldWriter.write(""); - oldWriter.write("\n"); - } - oldWriter.write("
Status
Description
"); - oldWriter.write(PageFlowUtil.filter(sf.getStatus())); - oldWriter.write(""); - oldWriter.write(PageFlowUtil.filter(sf.getDescription())); - oldWriter.write("
\n"); - } - } - - public List getJobStatus(RenderContext ctx) - { - if (_jobStatus == null) - { - if (_split) - { - String jobId = (String) ctx.get("Job"); - if (jobId != null) - { - // If we're being rendered from the Admin Console, we won't be in the right container, - // so don't specify one - _jobStatus = getSplitStatusFiles(jobId); - } - } - else if (ctx.get("JobParent") != null) - { - PipelineStatusFileImpl parent = getJobStatusFile((String) ctx.get("JobParent")); - if (parent != null) - { - _jobStatus = Collections.singletonList(parent); - } - } - if (_jobStatus == null) - _jobStatus = Collections.emptyList(); - // Make a copy of the immutable list so we can sort as needed - _jobStatus = new ArrayList<>(_jobStatus); - - _jobStatus.sort(Comparator.comparing(PipelineStatusFile::getDescription, String.CASE_INSENSITIVE_ORDER)); - } - - return _jobStatus; - } -}