diff --git a/announcements/src/org/labkey/announcements/query/ToursTable.java b/announcements/src/org/labkey/announcements/query/ToursTable.java index 018645a1f01..bb97b2f42d7 100644 --- a/announcements/src/org/labkey/announcements/query/ToursTable.java +++ b/announcements/src/org/labkey/announcements/query/ToursTable.java @@ -26,7 +26,6 @@ import org.labkey.api.data.ColumnInfo; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerFilter; -import org.labkey.api.data.ContainerForeignKey; import org.labkey.api.data.ContainerManager; import org.labkey.api.data.DataColumn; import org.labkey.api.data.DisplayColumn; @@ -36,12 +35,12 @@ import org.labkey.api.query.DetailsURL; import org.labkey.api.query.FilteredTable; import org.labkey.api.query.QueryUpdateService; -import org.labkey.api.query.UserIdQueryForeignKey; import org.labkey.api.security.User; import org.labkey.api.security.UserPrincipal; import org.labkey.api.security.permissions.Permission; import org.labkey.api.security.permissions.PlatformDeveloperPermission; import org.labkey.api.security.permissions.ReadPermission; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -118,14 +117,14 @@ public DisplayColumn createRenderer(final ColumnInfo colInfo) DataColumn dc = new DataColumn(colInfo) { @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object value = getValue(ctx); Modes m = Modes.fromValue((Integer)value); if(null != m) - out.write(m.toString()); + oldWriter.write(m.toString()); else - out.write(value.toString()); + oldWriter.write(value.toString()); } }; diff --git a/api/src/org/labkey/api/assay/AssayDataCollectorDisplayColumn.java b/api/src/org/labkey/api/assay/AssayDataCollectorDisplayColumn.java index 8fba1568077..1156a6b5236 100644 --- a/api/src/org/labkey/api/assay/AssayDataCollectorDisplayColumn.java +++ b/api/src/org/labkey/api/assay/AssayDataCollectorDisplayColumn.java @@ -16,21 +16,18 @@ package org.labkey.api.assay; +import org.jetbrains.annotations.NotNull; import org.labkey.api.assay.actions.AssayRunUploadForm; import org.labkey.api.data.BaseColumnInfo; import org.labkey.api.data.ColumnInfo; import org.labkey.api.data.RenderContext; import org.labkey.api.data.SimpleDisplayColumn; +import org.labkey.api.util.HtmlString; +import org.labkey.api.util.HtmlStringBuilder; import org.labkey.api.view.HttpView; import org.labkey.api.view.JspView; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; - -/** - * User: jeckels - * Date: Aug 3, 2007 - */ public class AssayDataCollectorDisplayColumn extends SimpleDisplayColumn { private final AssayRunUploadForm _form; @@ -40,16 +37,15 @@ public AssayDataCollectorDisplayColumn(AssayRunUploadForm form) { _form = form; setCaption("Run Data"); - var col = new BaseColumnInfo("Run Data"); + var col = new BaseColumnInfo("Run Data"); col.setInputType("file"); _col = col; } @Override - public void renderTitle(RenderContext ctx, Writer out) throws IOException + public @NotNull HtmlString getTitle(RenderContext ctx) { - super.renderTitle(ctx, out); - out.write(" *"); + return HtmlStringBuilder.of(super.getTitle(ctx)).append(" *").getHtmlString(); } @Override @@ -65,7 +61,7 @@ public ColumnInfo getColumnInfo() } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { HttpView descriptionView = _form.getProvider().getDataDescriptionView(_form); JspView view = new JspView<>("/org/labkey/assay/view/dataUpload.jsp", _form); @@ -79,7 +75,7 @@ public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws } catch (Exception e) { - throw (IOException)new IOException().initCause(e); + throw new RuntimeException(e); } } } diff --git a/api/src/org/labkey/api/assay/AssayQCFlagColumn.java b/api/src/org/labkey/api/assay/AssayQCFlagColumn.java index 12488b577fc..d4f39807530 100644 --- a/api/src/org/labkey/api/assay/AssayQCFlagColumn.java +++ b/api/src/org/labkey/api/assay/AssayQCFlagColumn.java @@ -36,6 +36,7 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.Pair; import org.labkey.api.view.template.ClientDependency; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -87,7 +88,7 @@ public Set getClientDependencies() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { String strValue = (String)getValue(ctx); if (isNotBlank(strValue)) @@ -100,11 +101,11 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep // users with update perm will be able to change enabled state and edit comment, others will only be able to read flag details Link.LinkBuilder linkBuilder = new Link.LinkBuilder(getCollapsedQCFlagOutput(values, enabled)) .onClick("showQCFlagToggleWindow(" + jsString(_schemaName) + ", " + runId + "," + _editable + "); return false;"); - out.write(linkBuilder.toString()); + oldWriter.write(linkBuilder.toString()); } else { - out.write(" "); + oldWriter.write(" "); } } diff --git a/api/src/org/labkey/api/assay/actions/BulkPropertiesDisplayColumn.java b/api/src/org/labkey/api/assay/actions/BulkPropertiesDisplayColumn.java index ce7a7127de3..811bd79718a 100644 --- a/api/src/org/labkey/api/assay/actions/BulkPropertiesDisplayColumn.java +++ b/api/src/org/labkey/api/assay/actions/BulkPropertiesDisplayColumn.java @@ -20,21 +20,16 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.view.JspView; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; - -/** - * User: jeckels - * Date: Jan 30, 2009 - */ public class BulkPropertiesDisplayColumn extends SimpleDisplayColumn { - private BulkPropertiesUploadForm _form; - private ColumnInfo _col; public static final String PROPERTIES_FIELD_NAME = "__bulkProperties"; public static final String ENABLED_FIELD_NAME = "__enableBulkProperties"; + private BulkPropertiesUploadForm _form; + private final ColumnInfo _col; + public BulkPropertiesDisplayColumn(BulkPropertiesUploadForm form) { _form = form; @@ -58,7 +53,7 @@ public ColumnInfo getColumnInfo() } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { JspView view = new JspView<>("/org/labkey/api/assay/bulkPropertiesInput.jsp", _form); try @@ -67,7 +62,7 @@ public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws } catch (Exception e) { - throw (IOException)new IOException().initCause(e); + throw new RuntimeException(e); } } } \ No newline at end of file diff --git a/api/src/org/labkey/api/assay/actions/UploadWizardAction.java b/api/src/org/labkey/api/assay/actions/UploadWizardAction.java index 796a066545f..f96c9ed1268 100644 --- a/api/src/org/labkey/api/assay/actions/UploadWizardAction.java +++ b/api/src/org/labkey/api/assay/actions/UploadWizardAction.java @@ -75,10 +75,12 @@ import org.labkey.api.study.publish.StudyPublishService; import org.labkey.api.util.HtmlString; import org.labkey.api.util.HtmlStringBuilder; +import org.labkey.api.util.JavaScriptFragment; import org.labkey.api.util.Link; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.Pair; import org.labkey.api.util.URLHelper; +import org.labkey.api.util.element.Input; import org.labkey.api.view.ActionURL; import org.labkey.api.view.HtmlView; import org.labkey.api.view.HttpView; @@ -92,6 +94,7 @@ import org.labkey.api.view.ViewServlet; import org.labkey.api.view.template.ClientDependency; import org.labkey.api.writer.ContainerUser; +import org.labkey.api.writer.HtmlWriter; import org.springframework.context.MessageSourceResolvable; import org.springframework.validation.BindException; import org.springframework.validation.Errors; @@ -99,8 +102,6 @@ import org.springframework.validation.ObjectError; import org.springframework.web.servlet.ModelAndView; -import java.io.IOException; -import java.io.Writer; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; @@ -115,6 +116,7 @@ import static org.labkey.api.util.DOM.BR; import static org.labkey.api.util.DOM.DIV; import static org.labkey.api.util.DOM.FONT; +import static org.labkey.api.util.DOM.SCRIPT; import static org.labkey.api.util.DOM.cl; import static org.labkey.api.util.DOM.createHtml; @@ -898,9 +900,9 @@ public boolean isEditable() } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { - out.write(""); + out.write(new Input.InputBuilder<>().type("text").name(_inputName).value(value == null ? null : value.toString())); } @Override @@ -1128,31 +1130,33 @@ public UploadWizardInsertView(DataRegion dataRegion, ViewContext context, BindEx } @Override - protected void _renderDataRegion(RenderContext ctx, Writer out) throws IOException + protected void _renderDataRegion(RenderContext ctx, HtmlWriter out) { // may want to just put this in a js file and include it in all the wizard pages - out.write("\n"); + String script =""" + function uploadWizard_showPopup(elem, txtTitle, txtMsg) + { + var win = new Ext.Window({ + title: txtTitle, + border: false, + constrain: true, + html: txtMsg, + closeAction:'close', + autoScroll: true, + modal: true, + buttons: [{ + text: 'Close', + id: 'btn_cancel', + handler: function(){win.close();} + }] + }); + win.show(elem); + } + """; + + SCRIPT( + JavaScriptFragment.unsafe(script) + ).appendTo(out); super._renderDataRegion(ctx, out); } @@ -1178,7 +1182,7 @@ public HtmlString getErrors(String paramName) list = errors.getGlobalErrors(); else list = errors.getFieldErrors(paramName); - if (list == null || list.size() == 0) + if (list == null || list.isEmpty()) return HtmlString.EMPTY_STRING; Set uniqueErrorStrs = new TreeSet<>(); @@ -1217,12 +1221,16 @@ public HtmlString getErrors(String paramName) else if (errors != null && "main".equals(paramName) && errors.getFieldError("transform") != null) { return createHtml( - DIV( - FONT(cl("labkey-error"), - DIV("Transform Script Error"), - BR(), - DIV(HtmlString.unsafe(errors.getFieldError("transform").getDefaultMessage()))), - BR())); + DIV( + FONT( + cl("labkey-error"), + DIV("Transform Script Error"), + BR(), + DIV(HtmlString.unsafe(errors.getFieldError("transform").getDefaultMessage())) + ), + BR() + ) + ); } else diff --git a/api/src/org/labkey/api/audit/data/ExperimentAuditColumn.java b/api/src/org/labkey/api/audit/data/ExperimentAuditColumn.java index 604b14ceb9c..7af2ca18b95 100644 --- a/api/src/org/labkey/api/audit/data/ExperimentAuditColumn.java +++ b/api/src/org/labkey/api/audit/data/ExperimentAuditColumn.java @@ -25,6 +25,7 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.Pair; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -103,22 +104,22 @@ public boolean isFilterable() protected abstract String extractFromKey3(RenderContext ctx); @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Pair value = getExpValue(ctx); if (value != null && value.second != null) { - out.write("" + PageFlowUtil.filter(value.first.getName()) + ""); + oldWriter.write("" + PageFlowUtil.filter(value.first.getName()) + ""); return; } if (_defaultName != null) { String extracted = extractFromKey3(ctx); - out.write(extracted != null ? PageFlowUtil.filter(extracted) : " "); + oldWriter.write(extracted != null ? PageFlowUtil.filter(extracted) : " "); } else - out.write(" "); + oldWriter.write(" "); } } diff --git a/api/src/org/labkey/api/audit/provider/GroupAuditProvider.java b/api/src/org/labkey/api/audit/provider/GroupAuditProvider.java index b90e197946c..9e33fff8ad4 100644 --- a/api/src/org/labkey/api/audit/provider/GroupAuditProvider.java +++ b/api/src/org/labkey/api/audit/provider/GroupAuditProvider.java @@ -51,6 +51,7 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; import org.labkey.api.view.ViewContext; +import org.labkey.api.writer.HtmlWriter; import org.springframework.validation.BindException; import java.io.IOException; @@ -336,7 +337,7 @@ public String getName() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Integer id = (Integer)getBoundColumn().getValue(ctx); if (id != null) @@ -358,15 +359,15 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep String groupName = g.isProjectGroup() && groupContainer != null ? groupContainer.getPath() + "/" + g.getName() : g.getName(); ActionURL url = PageFlowUtil.urlProvider(SecurityUrls.class).getManageGroupURL(groupContainer, groupName); - out.write(""); - out.write(displayText); - out.write(""); + oldWriter.write(""); + oldWriter.write(displayText); + oldWriter.write(""); } else { - out.write(displayText); + oldWriter.write(displayText); } return; } @@ -384,23 +385,23 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep ActionURL url = UserManager.getUserDetailsURL(ctx.getContainer(), loggedInUser, id); if (url != null) { - out.write(""); - out.write(displayText); - out.write(""); + oldWriter.write(""); + oldWriter.write(displayText); + oldWriter.write(""); } else - out.write(displayText); + oldWriter.write(displayText); } else { - out.write(p.getName()); + oldWriter.write(p.getName()); } } } } - out.write(" "); + oldWriter.write(" "); } @Override diff --git a/api/src/org/labkey/api/data/AJAXDetailsDisplayColumn.java b/api/src/org/labkey/api/data/AJAXDetailsDisplayColumn.java index acd6b71fc80..c750658316f 100644 --- a/api/src/org/labkey/api/data/AJAXDetailsDisplayColumn.java +++ b/api/src/org/labkey/api/data/AJAXDetailsDisplayColumn.java @@ -21,27 +21,26 @@ import org.labkey.api.query.DetailsURL; import org.labkey.api.query.FieldKey; import org.labkey.api.util.ContainerContext; +import org.labkey.api.util.DOM; import org.labkey.api.util.GUID; import org.labkey.api.util.JavaScriptFragment; import org.labkey.api.util.StringExpression; import org.labkey.api.view.ActionURL; import org.labkey.api.view.HttpView; import org.labkey.api.view.template.ClientDependency; -import org.labkey.api.view.template.PageConfig; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import static org.labkey.api.util.DOM.SPAN; +import static org.labkey.api.util.DOM.id; + /** * Uses LABKEY.Ext.CalloutTip to provide additional details, summoned via AJAX - * - * User: jeckels - * Date: May 14, 2012 */ public class AJAXDetailsDisplayColumn extends DataColumn { @@ -79,7 +78,7 @@ public AJAXDetailsDisplayColumn(@NotNull ColumnInfo col, @Nullable ActionURL url } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { String evaluatedURL = null; if (_detailsURL != null) @@ -106,9 +105,13 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep props.put("autoLoad", autoLoadProp); props.put("target", divId); - out.write(""); - super.renderGridCellContents(ctx, out); - out.write(""); + SPAN( + id(divId), + (DOM.Renderable) ret -> { + super.renderGridCellContents(ctx, out); + return ret; + } + ).appendTo(out); HttpView.currentPageConfig().addDocumentLoadHandler(JavaScriptFragment.unsafe( " Ext.onReady(function () { \n" + " var config = " + props.toString(0) + ";\n" + diff --git a/api/src/org/labkey/api/data/AbstractFileDisplayColumn.java b/api/src/org/labkey/api/data/AbstractFileDisplayColumn.java index 4fd3d7036ec..55ec297375b 100644 --- a/api/src/org/labkey/api/data/AbstractFileDisplayColumn.java +++ b/api/src/org/labkey/api/data/AbstractFileDisplayColumn.java @@ -23,8 +23,9 @@ import org.labkey.api.util.MimeMap; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.StringExpression; -import org.labkey.api.util.element.Input; +import org.labkey.api.util.element.Input.InputBuilder; import org.labkey.api.view.HttpView; +import org.labkey.api.writer.HtmlWriter; import java.io.File; import java.io.FileNotFoundException; @@ -48,13 +49,13 @@ public AbstractFileDisplayColumn(ColumnInfo col) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { renderIconAndFilename(ctx, out, (String)getValue(ctx), true, true); } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { renderIconAndFilename(ctx, out, (String)getValue(ctx), true, true); } @@ -69,7 +70,7 @@ protected String getFileName(RenderContext ctx, Object value, boolean isDisplay) protected abstract InputStream getFileContents(RenderContext ctx, Object value) throws FileNotFoundException; - protected void renderIconAndFilename(RenderContext ctx, Writer out, String filename, boolean link, boolean thumbnail) throws IOException + protected void renderIconAndFilename(RenderContext ctx, HtmlWriter out, String filename, boolean link, boolean thumbnail) { renderIconAndFilename(ctx, out, filename, null, null, link, thumbnail); } @@ -82,67 +83,75 @@ protected boolean isImage(String filename) || filename.toLowerCase().endsWith(".gif"); } - protected void renderIconAndFilename(RenderContext ctx, Writer out, String filename, @Nullable String fileIconUrl, @Nullable String popupIconUrl, boolean link, boolean thumbnail) throws IOException + protected void renderIconAndFilename(RenderContext ctx, HtmlWriter out, String filename, @Nullable String fileIconUrl, @Nullable String popupIconUrl, boolean link, boolean thumbnail) { - if (null != filename && !StringUtils.isEmpty(filename)) + Writer oldWriter = out.unwrap(); + try { - // equivalent of DisplayColumn.renderURL. - // Don't want to call renderUrl (DataColumn.renderUrl) to skip unnecessary displayValue check - StringExpression s = compileExpression(ctx.getViewContext()); - String url = null == s ? null : s.eval(ctx); - - if (link) + if (null != filename && !StringUtils.isEmpty(filename)) { - if (null != url) + // equivalent of DisplayColumn.renderURL. + // Don't want to call renderUrl (DataColumn.renderUrl) to skip unnecessary displayValue check + StringExpression s = compileExpression(ctx.getViewContext()); + String url = null == s ? null : s.eval(ctx); + + if (link) { - out.write(""); } - out.write(" href=\""); - out.write(PageFlowUtil.filter(url)); - out.write("\">"); } - } - String displayName = getFileName(ctx, filename, true); - boolean isImage = isImage(filename); + String displayName = getFileName(ctx, filename, true); + boolean isImage = isImage(filename); - FileImageRenderHelper renderHelper = createRenderHelper(ctx, url, filename, displayName, fileIconUrl, popupIconUrl, thumbnail, isImage); + FileImageRenderHelper renderHelper = createRenderHelper(ctx, url, filename, displayName, fileIconUrl, popupIconUrl, thumbnail, isImage); - if ((url != null || fileIconUrl != null) && thumbnail && isImage) - { - // controls whether to render a popup image on hover, otherwise just render an image with a click handler - // to navigate to the url - if (renderHelper.renderPopupImage()) - PageFlowUtil.popupHelp(HtmlString.unsafe(renderHelper.createPopupImage()), displayName).link(HtmlString.unsafe(renderHelper.createThumbnailImage())).width(310).script(renderHelper.createClickScript()).appendTo(out); - else - PageFlowUtil.popupHelp(displayName).link(HtmlString.unsafe(renderHelper.createThumbnailImage())).width(310).script(renderHelper.createClickScript()).appendTo(out); - } - else - { - if (url != null && thumbnail && MimeMap.DEFAULT.isInlineImageFor(new File(filename)) ) + if ((url != null || fileIconUrl != null) && thumbnail && isImage) { + // controls whether to render a popup image on hover, otherwise just render an image with a click handler + // to navigate to the url if (renderHelper.renderPopupImage()) - PageFlowUtil.popupHelp(HtmlString.unsafe(renderHelper.createPopupImage()), displayName).link(HtmlString.unsafe(renderHelper.createThumbnailImage())).width(310).script(renderHelper.createClickScript()).appendTo(out); + PageFlowUtil.popupHelp(HtmlString.unsafe(renderHelper.createPopupImage()), displayName).link(HtmlString.unsafe(renderHelper.createThumbnailImage())).width(310).script(renderHelper.createClickScript()).appendTo(oldWriter); else - PageFlowUtil.popupHelp(displayName).link(HtmlString.unsafe(renderHelper.createThumbnailImage())).width(310).script(renderHelper.createClickScript()).appendTo(out); + PageFlowUtil.popupHelp(displayName).link(HtmlString.unsafe(renderHelper.createThumbnailImage())).width(310).script(renderHelper.createClickScript()).appendTo(oldWriter); } else - out.write(renderHelper.createThumbnailImage()); - } + { + if (url != null && thumbnail && MimeMap.DEFAULT.isInlineImageFor(new File(filename)) ) + { + if (renderHelper.renderPopupImage()) + PageFlowUtil.popupHelp(HtmlString.unsafe(renderHelper.createPopupImage()), displayName).link(HtmlString.unsafe(renderHelper.createThumbnailImage())).width(310).script(renderHelper.createClickScript()).appendTo(oldWriter); + else + PageFlowUtil.popupHelp(displayName).link(HtmlString.unsafe(renderHelper.createThumbnailImage())).width(310).script(renderHelper.createClickScript()).appendTo(oldWriter); + } + else + oldWriter.write(renderHelper.createThumbnailImage()); + } - if (link && null != url) + if (link && null != url) + { + oldWriter.write(""); + } + } + else { - out.write(""); + oldWriter.write(" "); } } - else + catch (IOException e) { - out.write(" "); + throw new RuntimeException(e); } } @@ -257,14 +266,14 @@ protected boolean hasFileInputHtml() } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { if (hasFileInputHtml()) { String filename = getFileName(ctx, value); String formFieldName = ctx.getForm().getFormFieldName(getBoundColumn()); - Input.InputBuilder input = new Input.InputBuilder() + InputBuilder input = new InputBuilder<>() .type("file") .name(formFieldName) .disabled(isDisabledInput(ctx)) @@ -294,15 +303,24 @@ protected String getRemovalWarningText(String filename) return "Previous file " + filename + " will be removed."; } - private void renderThumbnailAndRemoveLink(Writer out, RenderContext ctx, String filename, String filePicker) throws IOException + // TODO: filePicker should be a builder or HtmlString or something sensible like that + private void renderThumbnailAndRemoveLink(HtmlWriter out, RenderContext ctx, String filename, String filePicker) { String divId = GUID.makeGUID(); String linkId = "remove" + divId; - out.write("
"); - renderIconAndFilename(ctx, out, filename, false, false); - out.write(" [remove]"); - out.write("
\n"); + Writer oldWriter = out.unwrap(); + try + { + oldWriter.write("
"); + renderIconAndFilename(ctx, out, filename, false, false); + oldWriter.write(" [remove]"); + oldWriter.write("
\n"); + } + catch (IOException e) + { + throw new RuntimeException(e); + } String innerHtml = filePicker + "" + getRemovalWarningText(filename) + ""; HttpView.currentPageConfig().addHandler(linkId, "click", "document.getElementById(" + jsString(divId) + ").innerHTML = " + jsString(innerHtml)); } diff --git a/api/src/org/labkey/api/data/AbstractValueTransformingDisplayColumn.java b/api/src/org/labkey/api/data/AbstractValueTransformingDisplayColumn.java index 6c314cfae4f..adef6a588e3 100644 --- a/api/src/org/labkey/api/data/AbstractValueTransformingDisplayColumn.java +++ b/api/src/org/labkey/api/data/AbstractValueTransformingDisplayColumn.java @@ -17,13 +17,11 @@ import org.jetbrains.annotations.NotNull; import org.labkey.api.util.HtmlString; -import org.labkey.api.util.PageFlowUtil; /** * Base class for transforming a raw DB column into a completely transformed value. An example is wrapping a RowId * column in the real table and showing a value that's calculated in Java code instead based on looking up other * data. Provides one simple method to implement to handle returning that value in HTML, exports, client API requests, etc. - * Created by Josh on 5/17/2017. */ public abstract class AbstractValueTransformingDisplayColumn extends DataColumn { diff --git a/api/src/org/labkey/api/data/ArrayExcelWriter.java b/api/src/org/labkey/api/data/ArrayExcelWriter.java index 3be33610144..d308c717ac4 100644 --- a/api/src/org/labkey/api/data/ArrayExcelWriter.java +++ b/api/src/org/labkey/api/data/ArrayExcelWriter.java @@ -2,7 +2,9 @@ import org.apache.poi.ss.usermodel.Sheet; import org.labkey.api.reader.ColumnDescriptor; +import org.labkey.api.util.HtmlString; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import java.io.Writer; import java.util.ArrayList; @@ -45,15 +47,15 @@ public void renderGrid(RenderContext ctx, Sheet sheet, List visible public class ArrayDisplayColumn extends DisplayColumn { - Class valueClass; + Class valueClass; int position; - public ArrayDisplayColumn(String name, Class valueClass, int position) + public ArrayDisplayColumn(String name, Class valueClass, int position) { this(name, name, valueClass, position); } - public ArrayDisplayColumn(String name, String caption, Class valueClass, int position) + public ArrayDisplayColumn(String name, String caption, Class valueClass, int position) { setName(name); setCaption(caption); @@ -68,27 +70,26 @@ public Object getValue(RenderContext ctx) } @Override - public Class getValueClass() + public Class getValueClass() { return valueClass; } - //NOTE: Methods beyond here are unimplemented, just abstract in base class @Override - public void renderGridCellContents(RenderContext ctx, Writer out) + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) { throw new UnsupportedOperationException("This is for excel only."); } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) { throw new UnsupportedOperationException("This is for excel only."); } @Override - public void renderTitle(RenderContext ctx, Writer out) + public HtmlString getTitle(RenderContext ctx) { throw new UnsupportedOperationException("This is for excel only."); } @@ -112,13 +113,13 @@ public boolean isEditable() } @Override - public void renderFilterOnClick(RenderContext ctx, Writer out) + public String getFilterOnClick(RenderContext ctx) { throw new UnsupportedOperationException("This is for excel only."); } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { throw new UnsupportedOperationException("This is for excel only."); } @@ -160,7 +161,7 @@ public ColumnInfo getColumnInfo() } @Override - public void render(RenderContext ctx, Writer out) + public void render(RenderContext ctx, HtmlWriter out) { throw new UnsupportedOperationException("This is for excel only."); } diff --git a/api/src/org/labkey/api/data/AttachmentDisplayColumn.java b/api/src/org/labkey/api/data/AttachmentDisplayColumn.java index 7cc97bf6224..a27a6c60f78 100644 --- a/api/src/org/labkey/api/data/AttachmentDisplayColumn.java +++ b/api/src/org/labkey/api/data/AttachmentDisplayColumn.java @@ -27,9 +27,6 @@ import java.util.Set; /** - * User: adam - * Date: Feb 12, 2008 - * * Renders attachment popup and download link using the underlying ColumnInfo's URL. */ public class AttachmentDisplayColumn extends AbstractFileDisplayColumn @@ -59,7 +56,7 @@ else if (value instanceof String) } @Override - public Class getDisplayValueClass() + public Class getDisplayValueClass() { ColumnInfo displayColumn = getDisplayColumn(); if (displayColumn.getPropertyType() != null) diff --git a/api/src/org/labkey/api/data/BaseColumnInfo.java b/api/src/org/labkey/api/data/BaseColumnInfo.java index 81a35776899..53f6c1e0176 100644 --- a/api/src/org/labkey/api/data/BaseColumnInfo.java +++ b/api/src/org/labkey/api/data/BaseColumnInfo.java @@ -51,6 +51,7 @@ import org.labkey.api.util.StringExpressionFactory; import org.labkey.api.util.StringExpressionFactory.FieldKeyStringExpression; import org.labkey.api.util.logging.LogHelper; +import org.labkey.api.writer.HtmlWriter; import org.labkey.data.xml.ColumnType; import org.labkey.data.xml.DbSequenceType; import org.labkey.data.xml.PropertiesType; @@ -1301,9 +1302,9 @@ else if (xmlCol.isSetKeyVariable()) return new SimpleDisplayColumn() { @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { - out.write(PageFlowUtil.filter("Error: " + message)); + oldWriter.write(PageFlowUtil.filter("Error: " + message)); } }; }; diff --git a/api/src/org/labkey/api/data/CrosstabDataRegion.java b/api/src/org/labkey/api/data/CrosstabDataRegion.java index 16dc0bd5950..c8fda5034d4 100644 --- a/api/src/org/labkey/api/data/CrosstabDataRegion.java +++ b/api/src/org/labkey/api/data/CrosstabDataRegion.java @@ -17,16 +17,22 @@ import org.apache.commons.lang3.StringUtils; import org.labkey.api.query.CrosstabView; -import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.DOM.Renderable; +import org.labkey.api.util.HtmlString; +import org.labkey.api.util.Link; import org.labkey.api.util.Pair; -import org.labkey.api.util.UnexpectedException; +import org.labkey.api.util.SafeToRender; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.sql.SQLException; import java.util.List; +import static org.labkey.api.util.DOM.Attribute.colspan; +import static org.labkey.api.util.DOM.TH; +import static org.labkey.api.util.DOM.THEAD; +import static org.labkey.api.util.DOM.TR; +import static org.labkey.api.util.DOM.at; + /** * Used in conjunction with the CrosstabView class to override rendering of the column headers. */ @@ -51,70 +57,71 @@ protected void renderGridHeaderColumns(RenderContext ctx, HtmlWriter out, boolea { if (_numMemberMeasures > 0) { - Writer oldWriter = out.unwrap(); - - try - { //add a row for the column axis label if there is one - oldWriter.write(""); - renderColumnGroupHeader(_numRowAxisCols + (showRecordSelectors ? 1 : 0), _settings.getRowAxis().getCaption(), oldWriter, false); - renderColumnGroupHeader(renderers.size() - _numRowAxisCols, _settings.getColumnAxis().getCaption(), oldWriter, false); - oldWriter.write(""); + THEAD( + TR( + (Renderable) ret -> { + renderColumnGroupHeader(_numRowAxisCols + (showRecordSelectors ? 1 : 0), HtmlString.of(_settings.getRowAxis().getCaption()), out, false); + renderColumnGroupHeader(renderers.size() - _numRowAxisCols, HtmlString.of(_settings.getColumnAxis().getCaption()), out, false); - //add an extra row for the column dimension members - oldWriter.write(""); - renderColumnGroupHeader(_numRowAxisCols + (showRecordSelectors ? 1 : 0), _settings.getRowAxis().getCaption(), oldWriter, false); - - List>> groupedByMember = CrosstabView.columnsByMember(renderers); - - // Output a group header for each column's crosstab member. - CrosstabDimension colDim = _settings.getColumnAxis().getDimensions().get(0); - boolean alternate = true; - for (Pair> group : groupedByMember) - { - CrosstabMember currentMember = group.first; - List memberColumns = group.second; - if (memberColumns.isEmpty()) - continue; - - alternate = !alternate; - - if (currentMember != null) - { - if (_numMeasures != _numMemberMeasures || colDim.getMemberUrl(currentMember) != null) - { - renderColumnGroupHeader(memberColumns.size(), getMemberCaptionWithUrl(colDim, currentMember), oldWriter, alternate); + return ret; } - } - - for (DisplayColumn renderer : memberColumns) - { - if (alternate) - renderer.addDisplayClass("labkey-alternate-col"); - if (currentMember != null && _numMeasures != _numMemberMeasures) - { - String memberCaption = currentMember.getCaption(); - String innerCaption = renderer.getCaption(ctx); - if (StringUtils.startsWith(innerCaption, memberCaption)) - renderer.setCaption(StringUtils.trim(innerCaption.substring(memberCaption.length()))); + ) + ).appendTo(out); + + //add an extra row for the column dimension members + THEAD( + TR( + (Renderable) ret -> { + renderColumnGroupHeader(_numRowAxisCols + (showRecordSelectors ? 1 : 0), HtmlString.of(_settings.getRowAxis().getCaption()), out, false); + + List>> groupedByMember = CrosstabView.columnsByMember(renderers); + + // Output a group header for each column's crosstab member. + CrosstabDimension colDim = _settings.getColumnAxis().getDimensions().get(0); + boolean alternate = true; + for (Pair> group : groupedByMember) + { + CrosstabMember currentMember = group.first; + List memberColumns = group.second; + if (memberColumns.isEmpty()) + continue; + + alternate = !alternate; + + if (currentMember != null) + { + if (_numMeasures != _numMemberMeasures || colDim.getMemberUrl(currentMember) != null) + { + renderColumnGroupHeader(memberColumns.size(), getMemberCaptionWithUrl(colDim, currentMember), out, alternate); + } + } + + for (DisplayColumn renderer : memberColumns) + { + if (alternate) + renderer.addDisplayClass("labkey-alternate-col"); + if (currentMember != null && _numMeasures != _numMemberMeasures) + { + String memberCaption = currentMember.getCaption(); + String innerCaption = renderer.getCaption(ctx); + if (StringUtils.startsWith(innerCaption, memberCaption)) + renderer.setCaption(StringUtils.trim(innerCaption.substring(memberCaption.length()))); + } + } + } + + return ret; } - } - } - - //end the col dimension member header row - oldWriter.write(""); - } - catch (IOException e) - { - throw UnexpectedException.wrap(e); - } + ) + ).appendTo(out); } //call the base class to finish rendering the headers super.renderGridHeaderColumns(ctx, out, showRecordSelectors, renderers); } - protected String getMemberCaptionWithUrl(CrosstabDimension dimension, CrosstabMember member) + protected SafeToRender getMemberCaptionWithUrl(CrosstabDimension dimension, CrosstabMember member) { String url = null; if (null != dimension.getUrl()) @@ -123,37 +130,27 @@ protected String getMemberCaptionWithUrl(CrosstabDimension dimension, CrosstabMe return getMemberCaptionWithUrl(member.getCaption(), url); } - protected String getMemberCaptionWithUrl(String caption, String url) + protected SafeToRender getMemberCaptionWithUrl(String caption, String url) { if (url != null) { - StringBuilder ret = new StringBuilder(); - ret.append(""); - ret.append(PageFlowUtil.filter(caption)); - ret.append(""); - return ret.toString(); + return new Link.LinkBuilder(caption).href(url); } - return PageFlowUtil.filter(caption); + return HtmlString.of(caption); } - protected void renderColumnGroupHeader(int groupWidth, String caption, Writer out, boolean alternate) throws IOException + protected void renderColumnGroupHeader(int groupWidth, SafeToRender caption, HtmlWriter out, boolean alternate) { if (groupWidth <= 0) return; - out.write("\n"); - out.write(caption == null ? "" : caption); - out.write("\n"); + TH( + at(colspan, groupWidth). + cl("labkey-data-region labkey-pivot labkey-group-column-header"). + cl(alternate,"labkey-alternate-col"). + cl(isShowBorders(), "labkey-show-borders"), + caption + ).appendTo(out); } } diff --git a/api/src/org/labkey/api/data/DataColumn.java b/api/src/org/labkey/api/data/DataColumn.java index 5d4bd22ecac..1c4cf1d1ca9 100644 --- a/api/src/org/labkey/api/data/DataColumn.java +++ b/api/src/org/labkey/api/data/DataColumn.java @@ -52,6 +52,7 @@ import org.labkey.api.view.HttpView; import org.labkey.api.view.TypeAheadSelectDisplayColumn; import org.labkey.api.view.template.ClientDependency; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -324,7 +325,7 @@ public Class getDisplayValueClass() } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { // By default, use the same rendering for both the details and grid views renderGridCellContents(ctx, out); @@ -341,14 +342,15 @@ public FieldKey getFilterKey() } @Override - public void renderFilterOnClick(RenderContext ctx, Writer out) throws IOException + public String getFilterOnClick(RenderContext ctx) { if (_filterColumn == null) - return; + return ""; String regionName = ctx.getCurrentRegion().getName(); String columnName = PageFlowUtil.jsString(_boundColumn.getFieldKey().toString()); - out.write(DataRegion.getJavaScriptObjectReference(regionName) + "._openFilter(" + columnName + ");"); + + return DataRegion.getJavaScriptObjectReference(regionName) + "._openFilter(" + columnName + ");"; } @Override @@ -371,7 +373,7 @@ public String getClearSortScript(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object o = getValue(ctx); @@ -415,15 +417,15 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep link.style(css); } - link.build().appendTo(out); + link.build().appendTo(oldWriter); } else { - formattedValue.appendTo(out); + formattedValue.appendTo(oldWriter); } } else - out.write(" "); + oldWriter.write(" "); } protected String renderURLorValueURL(RenderContext ctx) @@ -631,7 +633,7 @@ protected String getStringValue(Object value, boolean disabledInput) } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException { if (_boundColumn.isVersionColumn() || _inputType.equalsIgnoreCase("none")) return; @@ -642,15 +644,15 @@ public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws if (_boundColumn.isAutoIncrement()) { - renderHiddenFormInput(ctx, out, formFieldName, value); + renderHiddenFormInput(out, formFieldName, value); if (null != value) { - out.write(PageFlowUtil.filter(strVal)); + oldWriter.write(PageFlowUtil.filter(strVal)); } } else if (_inputType.toLowerCase().startsWith("disabled")) { - renderTextFormInput(ctx, out, formFieldName, value, strVal, true); + renderTextFormInput(oldWriter, formFieldName, value, strVal, true); } else if (_inputType.toLowerCase().startsWith("select")) { @@ -660,42 +662,42 @@ else if (_inputType.toLowerCase().startsWith("select")) displayColumn.renderInputHtml(ctx, out, value); } else - renderSelectFormInputFromFk(ctx, out, formFieldName, value, strVal, disabledInput); + renderSelectFormInputFromFk(ctx, oldWriter, formFieldName, value, strVal, disabledInput); } else if (_inputType.equalsIgnoreCase("textarea")) { - renderTextAreaFormInput(ctx, out, formFieldName, value, strVal, disabledInput); + renderTextAreaFormInput(oldWriter, formFieldName, value, strVal, disabledInput); } else if (_inputType.equalsIgnoreCase("file")) { - renderFileFormInput(ctx, out, formFieldName, value, strVal, disabledInput); + renderFileFormInput(oldWriter, formFieldName, value, strVal, disabledInput); } else if (_inputType.equalsIgnoreCase("checkbox")) { - renderCheckboxFormInput(ctx, out, formFieldName, value, strVal, disabledInput); + renderCheckboxFormInput(oldWriter, formFieldName, value, strVal, disabledInput); } else { if (getAutoCompleteURLPrefix() != null) { - renderAutoCompleteFormInput(ctx, out, formFieldName, value, strVal, disabledInput, getAutoCompleteURLPrefix()); + renderAutoCompleteFormInput(ctx, oldWriter, formFieldName, value, strVal, disabledInput, getAutoCompleteURLPrefix()); } else { IPropertyValidator textChoiceValidator = PropertyService.get().getValidatorForColumn(_boundColumn, PropertyValidatorType.TextChoice); if (textChoiceValidator != null) - renderTextChoiceFormInput(ctx, out, formFieldName, value, strVal, disabledInput, textChoiceValidator); + renderTextChoiceFormInput(oldWriter, formFieldName, value, strVal, disabledInput, textChoiceValidator); else - renderTextFormInput(ctx, out, formFieldName, value, strVal, disabledInput); + renderTextFormInput(oldWriter, formFieldName, value, strVal, disabledInput); } } HtmlString errors = getErrors(ctx); if (!StringUtils.isEmpty(errors.toString())) { - out.write(""); - out.write(errors.toString()); - out.write(""); + oldWriter.write(""); + oldWriter.write(errors.toString()); + oldWriter.write(""); } } @@ -709,7 +711,7 @@ else if (_inputType.equalsIgnoreCase("checkbox")) } private void renderSelectFormInput( - RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, + Writer out, String formFieldName, Object value, String strVal, boolean disabledInput, NamedObjectList entryList ) throws IOException { @@ -727,8 +729,8 @@ private void renderSelectFormInput( { String entryName = entry.getName(); OptionBuilder option = new OptionBuilder() - .selected(isSelectInputSelected(entryName, value, strVal)) - .value(entryName); + .selected(isSelectInputSelected(entryName, value, strVal)) + .value(entryName); if (null != entry.getObject()) option.label(getSelectInputDisplayValue(entry)); @@ -740,10 +742,10 @@ private void renderSelectFormInput( // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(ctx, out, formFieldName, value); + renderHiddenFormInput(HtmlWriter.of(out), formFieldName, value); } - private void renderTextChoiceFormInput(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput, IPropertyValidator textChoiceValidator) + private void renderTextChoiceFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput, IPropertyValidator textChoiceValidator) throws IOException { NamedObjectList options = new NamedObjectList(); @@ -759,7 +761,7 @@ private void renderTextChoiceFormInput(RenderContext ctx, Writer out, String for for (String choice : choices) options.put(new SimpleNamedObject(choice, choice)); - renderSelectFormInput(ctx, out, formFieldName, value, strVal, disabledInput, options); + renderSelectFormInput(out, formFieldName, value, strVal, disabledInput, options); } protected void renderSelectFormInputFromFk(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) @@ -781,15 +783,15 @@ protected void renderSelectFormInputFromFk(RenderContext ctx, Writer out, String displayValue = getDisplayValue(ctx); String textInputValue = Objects.toString(displayValue, strVal); - renderTextFormInput(ctx, out, formFieldName, value, textInputValue, disabledInput); + renderTextFormInput(out, formFieldName, value, textInputValue, disabledInput); } else { - renderSelectFormInput(ctx, out, formFieldName, value, strVal, disabledInput, entryList); + renderSelectFormInput(out, formFieldName, value, strVal, disabledInput, entryList); } } - protected void renderFileFormInput(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) + protected void renderFileFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) throws IOException { var input = new Input.InputBuilder<>() @@ -801,7 +803,7 @@ protected void renderFileFormInput(RenderContext ctx, Writer out, String formFie out.write(input.build().toString()); } - protected void renderCheckboxFormInput(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) + protected void renderCheckboxFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) throws IOException { boolean checked = ColumnInfo.booleanFromObj(ConvertUtils.convert(value)); @@ -830,10 +832,10 @@ protected void renderCheckboxFormInput(RenderContext ctx, Writer out, String for out.write("\" value=\"1\">"); // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(ctx, out, formFieldName, checked ? "1" : ""); + renderHiddenFormInput(HtmlWriter.of(out), formFieldName, checked ? "1" : ""); } - protected void renderTextAreaFormInput(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) + protected void renderTextAreaFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) throws IOException { TextArea.TextAreaBuilder input = new TextArea.TextAreaBuilder() @@ -847,10 +849,10 @@ protected void renderTextAreaFormInput(RenderContext ctx, Writer out, String for // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(ctx, out, formFieldName, value); + renderHiddenFormInput(HtmlWriter.of(out), formFieldName, value); } - protected void renderTextFormInput(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) + protected void renderTextFormInput(Writer out, String formFieldName, Object value, String strVal, boolean disabledInput) throws IOException { var input = new Input.InputBuilder<>() @@ -864,7 +866,7 @@ protected void renderTextFormInput(RenderContext ctx, Writer out, String formFie // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(ctx, out, formFieldName, value); + renderHiddenFormInput(HtmlWriter.of(out), formFieldName, value); } protected void renderAutoCompleteFormInput(RenderContext ctx, Writer out, String formFieldName, Object value, String strVal, boolean disabledInput, @NotNull ActionURL autoCompleteURLPrefix) @@ -924,71 +926,72 @@ public String getSortHandler(RenderContext ctx, Sort.SortDirection sort) } @Override - public void renderTitle(RenderContext ctx, Writer out) throws IOException - { - String title = PageFlowUtil.filter(getTitle(ctx)); - if (title.isEmpty()) - { - title = " "; - } - out.write(title); - } - - @Override - public String getTitle(RenderContext ctx) + public @Nullable HtmlString getTitle(RenderContext ctx) { + // TODO: Treat null and empty the same instead? if (_caption == null) return null; - return _caption.eval(ctx); + String title = _caption.eval(ctx); + return title.isEmpty() ? HtmlString.NBSP : HtmlString.of(title); } @Override - public void renderDetailsCaptionCell(RenderContext ctx, Writer out, @Nullable String cls) throws IOException + public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullable String cls) { if (null == _caption) return; - out.write(""); - - renderTitle(ctx, out); - if (ctx.getMode() == DataRegion.MODE_DETAILS) - out.write(":"); - int mode = ctx.getMode(); - if ((mode == DataRegion.MODE_INSERT || mode == DataRegion.MODE_UPDATE) && isEditable()) + Writer oldWriter = out.unwrap(); + try { - if (_boundColumn != null) + 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()) { - List helpLines = new LinkedList<>() + if (_boundColumn != null) { - @Override - public boolean add(String s) + List helpLines = new LinkedList<>() { - return super.add(PageFlowUtil.filter(s)); + @Override + public boolean add(String s) + { + return super.add(PageFlowUtil.filter(s)); + } + }; + 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); } - }; - 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()) - { - out.write(" *"); - helpLines.add("This field is required."); - } - if (!helpLines.isEmpty()) - { - HtmlString helpHtml = HtmlString.unsafe(StringUtils.join(helpLines, "
")); - PageFlowUtil.popupHelp(helpHtml, _boundColumn.getLabel()).appendTo(out); } } + oldWriter.write("\n"); + } + catch (IOException e) + { + throw new RuntimeException(e); } - out.write("\n"); } protected boolean renderRequiredIndicators() @@ -1008,7 +1011,7 @@ public void setEditable(boolean b) } @Override - public void render(RenderContext ctx, Writer out) throws IOException + public void render(RenderContext ctx, HtmlWriter out) { if (ctx.getMode() == DataRegion.MODE_INSERT || ctx.getMode() == DataRegion.MODE_UPDATE) renderInputHtml(ctx, out, getInputValue(ctx)); diff --git a/api/src/org/labkey/api/data/DataRegion.java b/api/src/org/labkey/api/data/DataRegion.java index 092cc93f9a8..4c418c3259a 100644 --- a/api/src/org/labkey/api/data/DataRegion.java +++ b/api/src/org/labkey/api/data/DataRegion.java @@ -53,7 +53,6 @@ import org.labkey.api.util.DOM; 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; import org.labkey.api.util.JunitUtil; import org.labkey.api.util.PageFlowUtil; @@ -961,12 +960,9 @@ protected void renderHeaderScript(RenderContext ctx, HtmlWriter out, Map\n"); - - out.write(builder); + SCRIPT( + JavaScriptFragment.unsafe("LABKEY.DataRegion.create(" + dataRegionJSON.toString(2) + ");\n") + ).appendTo(out); } protected void renderTable(RenderContext ctx, HtmlWriter out) throws SQLException @@ -1805,19 +1801,19 @@ protected void renderFormBegin(RenderContext ctx, HtmlWriter out, int mode) protected void renderHiddenFormFields(RenderContext ctx, HtmlWriter out, int mode) { if (mode == MODE_GRID) - out.write(new InputBuilder().type("hidden").name(DataRegionSelection.DATA_REGION_SELECTION_KEY).value(getSelectionKey())); + out.write(new InputBuilder<>().type("hidden").name(DataRegionSelection.DATA_REGION_SELECTION_KEY).value(getSelectionKey())); out.write(new CsrfInput(ctx.getViewContext())); for (FormField field : _hiddenFormFields) { - out.write(new InputBuilder().type("hidden").name(field.name()).value(field.value())); + out.write(new InputBuilder<>().type("hidden").name(field.name()).value(field.value())); } if (mode == MODE_UPDATE_MULTIPLE) { - out.write(new InputBuilder().type("hidden").name(TableViewForm.DATA_SUBMIT_NAME).value("true")); - out.write(new InputBuilder().type("hidden").name(TableViewForm.BULK_UPDATE_NAME).value("true")); + out.write(new InputBuilder<>().type("hidden").name(TableViewForm.DATA_SUBMIT_NAME).value("true")); + out.write(new InputBuilder<>().type("hidden").name(TableViewForm.BULK_UPDATE_NAME).value("true")); } } @@ -1842,7 +1838,7 @@ private void renderRecordSelector(RenderContext ctx, HtmlWriter out) boolean enabled = isRecordSelectorEnabled(ctx); boolean checked = isRecordSelectorChecked(ctx, checkboxValue); - new InputBuilder() + new InputBuilder<>() .type("checkbox") .title("Select/unselect row") .name(getRecordSelectorName(ctx)) @@ -1991,9 +1987,7 @@ private void renderDetails(RenderContext ctx, HtmlWriter out) throws SQLExceptio TR( (Renderable) rend -> { renderer.renderDetailsCaptionCell(ctx, out, null); - renderer.renderInputWrapperBegin(out); - renderer.renderDetailsData(ctx, out); - renderer.renderInputWrapperEnd(out); + renderer.renderDetailsCell(ctx, out); return rend; } ).appendTo(out); @@ -2196,9 +2190,7 @@ private void renderFormField(RenderContext ctx, HtmlWriter out, DisplayColumn re } else { - renderer.renderInputWrapperBegin(out); - renderer.renderDetailsData(ctx, out); - renderer.renderInputWrapperEnd(out); + renderer.renderDetailsCell(ctx, out); } return ret; } @@ -2316,7 +2308,7 @@ private void renderForm(RenderContext ctx, HtmlWriter out) if (null != pkVal) { out.write( - new InputBuilder() + new InputBuilder<>() .type("hidden") .name(viewForm != null ? viewForm.getFormFieldName(pkCol) : pkColName) .value(pkVal.toString()) @@ -2462,8 +2454,6 @@ private void renderForm(RenderContext ctx, HtmlWriter out) } } - out.write(HtmlStringBuilder.of(HttpView.currentPageConfig().getScriptTagStart())); - StringWriter sw = new StringWriter(); for (DisplayColumnGroup group : groups) { @@ -2477,8 +2467,9 @@ private void renderForm(RenderContext ctx, HtmlWriter out) } } - out.write(JavaScriptFragment.unsafe(sw.toString())); - out.writeElementEnd(DOM.Element.script); + SCRIPT( + JavaScriptFragment.unsafe(sw.toString()) + ).appendTo(out); } return app; @@ -2503,7 +2494,7 @@ private HtmlWriter writeSameHeader(RenderContext ctx, HtmlWriter out, List() .type("checkbox") .id(madeId) .name("~~SELECTALL~~") @@ -2835,8 +2826,8 @@ private ContextAction createFilterAction(RenderContext ctx, List _clientDependencies = new LinkedHashSet<>(); // for URL generation private String _url; private StringExpression _urlExpression; private StringExpression _urlCompiled; + private StringExpression _textExpression = null; + private StringExpression _textExpressionCompiled = null; private StringExpression _urlTitle = null; private StringExpression _urlTitleCompiled = null; + private RowSpanner _rowSpanner = DEFAULT_ROW_SPANNER; + private String _description = null; + private String _displayClass; - protected Set _clientDependencies = new LinkedHashSet<>(); private final List _analyticsProviders = new ArrayList<>(); /** Handles spanning multiple rows in a grid. A separate interface to allow for easier mixing and matching with DisplayColumn implementations. */ @@ -128,16 +141,73 @@ public boolean shouldRenderInCurrentRow(RenderContext ctx) } }; - private RowSpanner _rowSpanner = DEFAULT_ROW_SPANNER; + /* + 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 + 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. + */ - public abstract void renderGridCellContents(RenderContext ctx, Writer out) throws IOException; + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) + { + try + { + renderGridCellContents(ctx, out.unwrap(), out); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } - public abstract void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException; + // No callers (other than just above) + @Deprecated + protected void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + { + 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 - public abstract void renderTitle(RenderContext ctx, Writer out) throws IOException; + protected void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException + { + throw new IllegalStateException("Must override renderDetailsCellContents()"); + } - public String getTitle(RenderContext ctx) + 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 @Nullable HtmlString getTitle(RenderContext ctx) { return null; } @@ -150,15 +220,6 @@ public String getTitle(RenderContext ctx) public abstract boolean isEditable(); - public abstract void renderFilterOnClick(RenderContext ctx, Writer out) throws IOException; - - public abstract void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException; - - // Do nothing by default - public void renderGridEnd(RenderContext ctx, Writer out) throws IOException - { - } - public String renderURL(RenderContext ctx) { StringExpression s = compileExpression(ctx.getViewContext()); @@ -193,7 +254,6 @@ public void setURLExpression(StringExpression se) _urlCompiled = null; } - public StringExpression getURLExpression() { return _urlExpression; @@ -263,7 +323,6 @@ protected void addAnalyticsProvider(@NotNull ColumnAnalyticsProvider analyticsP public abstract boolean isQueryColumn(); - /** return a set of FieldKeys that this DisplayColumn depends on */ public void addQueryFieldKeys(Set keys) { @@ -318,7 +377,7 @@ public ColumnInfo getDisplayColumnInfo() public abstract Object getValue(RenderContext ctx); - public abstract Class getValueClass(); + public abstract Class getValueClass(); public Object getJsonValue(RenderContext ctx) { @@ -629,7 +688,7 @@ public Object getDisplayValue(RenderContext ctx) return getValue(ctx); } - public Class getDisplayValueClass() + public Class getDisplayValueClass() { return getValueClass(); } @@ -671,18 +730,6 @@ public String getDefaultHeaderStyle() return ""; } - public void renderGridHeaderCell(RenderContext ctx, HtmlWriter out) - { - try - { - renderGridHeaderCell(ctx, out.unwrap(), null); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - public boolean hasFilterKey(FieldKey fieldKey) { FieldKey fk = getFilterKey(); @@ -711,7 +758,12 @@ private Sort.SortField getSortColumn(Sort sort) return null; } - public void renderGridHeaderCell(RenderContext ctx, Writer out, String headerClass) throws IOException + public void renderGridHeaderCell(RenderContext ctx, HtmlWriter out) + { + renderGridHeaderCell(ctx, out, null); + } + + public void renderGridHeaderCell(RenderContext ctx, HtmlWriter out, String headerClass) { Sort sort = getSort(ctx); Sort.SortField sortField = getSortColumn(sort); @@ -723,33 +775,6 @@ public void renderGridHeaderCell(RenderContext ctx, Writer out, String headerCla NavTree navTree = getPopupNavTree(ctx, baseId, sort, filtered); boolean hasMenu = navTree != null; - out.write(""); - String style = getDefaultHeaderStyle(); if (style == null) style = ""; // 34871: Support for column display width if (!isBlank(getWidth())) - style += ";width:" + getWidth() + "px;"; - - out.write("
"); - - renderTitle(ctx, out); - - out.write(""); - out.write(""); - out.write(""); - - if (hasMenu) - { - out.write(""); - - // 31304: click target should fill the entire cell - out.write("
"); - out.write("
    "); - PopupMenuView.renderTree(navTree, out); - out.write("
"); - } - - out.write("
"); - out.write(""); + style += "; width:" + getWidth() + "px;"; + + TH( + cl("labkey-column-header " + getGridHeaderClass()). + cl(hasMenu, "dropdown dropdown-rollup"). + cl(sortField != null, () -> "labkey-sort-" + (sortField.getSortDirection() == Sort.SortDirection.ASC ? "asc" : "desc")). + cl(filtered, "labkey-filtered"). + cl(headerClass). + cl(_displayClass). + cl(isPhiProtected(), "labkey-phi-protected"). + at(!tooltip.isEmpty(), title, tooltip). + data("column-name", ctx.getCurrentRegion().getName() + ":" + columnName), + + DIV( + at(!style.isEmpty(), DOM.Attribute.style, style), + getTitle(ctx), + SPAN(cl("fa fa-filter")), + SPAN(cl("fa fa-up")), + SPAN(cl("fa fa-down")), + (DOM.Renderable) ret -> { + if (hasMenu) + { + SPAN( + cl("fa fa-chevron-circle-down") + ).appendTo(out); + DIV( + cl("dropdown-toggle").data("toggle", "dropdown") + ).appendTo(out); + UL( + cl("dropdown-menu").at(!tooltip.isEmpty(), title, ""), + (DOM.Renderable) rend -> PopupMenuView.renderTree(navTree, out) + ).appendTo(out); + } + return ret; + } + ) + ).appendTo(out); } private Sort getSort(RenderContext ctx) @@ -889,9 +907,9 @@ private boolean isFiltered(RenderContext ctx) } return (null != this.getColumnInfo() && - (filteredColSet.contains(this.getColumnInfo().getFieldKey())) || - (this.getColumnInfo().getDisplayField() != null && - filteredColSet.contains(this.getColumnInfo().getDisplayField().getFieldKey()))); + (filteredColSet.contains(this.getColumnInfo().getFieldKey())) || + (this.getColumnInfo().getDisplayField() != null && + filteredColSet.contains(this.getColumnInfo().getDisplayField().getFieldKey()))); } return false; } @@ -1029,78 +1047,40 @@ public boolean isUserSort(RenderContext ctx) return null != getSortColumn(userSort); } - public String getGridDataCell(RenderContext ctx) - { - StringWriter writer = new StringWriter(); - try - { - renderGridDataCell(ctx, writer); - } - catch (Exception e) - { - writer.write(e.getMessage()); - } - return writer.toString(); - } - - boolean foundHoverContent = false; + private boolean foundHoverContent = false; public void renderGridDataCell(RenderContext ctx, HtmlWriter out) - { - try - { - renderGridDataCell(ctx, out.unwrap()); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - public void renderGridDataCell(RenderContext ctx, Writer out) throws IOException { if (!_rowSpanner.shouldRenderInCurrentRow(ctx)) { // An earlier row has covered this cell with a rowspan so no need to render any HTML return; } - out.write(" 1) - { - out.write(" rowspan=\"" + rowSpan + "\""); - } - if (hoverContent != null) - { - out.write(" data-columntiptitle=\"" + PageFlowUtil.filter(getHoverTitle(ctx)) + "\""); - out.write(" data-columntipcontent=\"" + PageFlowUtil.filter(hoverContent) + "\""); - if (!foundHoverContent) - { - foundHoverContent=true; - HttpView.currentPageConfig().addHandlerForQuerySelector("TD.lk-column-tt", "mouseover", - "showHelpDivDelay(this, this.dataset['columntiptitle'], this.dataset['columntipcontent'], null, 1000);"); - HttpView.currentPageConfig().addHandlerForQuerySelector("TD.lk-column-tt", "mouseout", "return hideHelpDivDelay();"); + + TD( + cl(!isBlank(displayClass) || !isBlank(hoverContent), trimToEmpty(displayClass) + (!isBlank(hoverContent) ? " lk-column-tt" : "")). + at(align, _textAlign).at(!style.isEmpty(), DOM.Attribute.style, style).at(rowSpan > 1, rowspan, rowSpan). + data(hoverContent != null, "columntiptitle", getHoverTitle(ctx)). + data(hoverContent != null, "columntipcontent", hoverContent), + (DOM.Renderable) ret -> { + renderGridCellContents(ctx, out); + return ret; } + ).appendTo(out); + + if (hoverContent != null && !foundHoverContent) + { + PageConfig pageConfig = HttpView.currentPageConfig(); + pageConfig.addHandlerForQuerySelector("TD.lk-column-tt", "mouseover", + "showHelpDivDelay(this, this.dataset['columntiptitle'], this.dataset['columntipcontent'], null, 1000);"); + pageConfig.addHandlerForQuerySelector("TD.lk-column-tt", "mouseout", "return hideHelpDivDelay();"); + foundHoverContent = true; } - out.write(">"); - renderGridCellContents(ctx, out); - out.write(""); } protected String getHoverContent(RenderContext ctx) @@ -1153,7 +1133,9 @@ public String getCaption(RenderContext ctx, boolean htmlEncode) StringWriter writer = new StringWriter(); try { - renderTitle(ctx, writer); + HtmlString title = getTitle(ctx); + if (title != null) + writer.write(title.toString()); } catch (Exception e) { @@ -1171,86 +1153,15 @@ public String getCaption(RenderContext ctx, boolean htmlEncode) return _caption.getSource(); } - - public String getDetailsCaptionCell(RenderContext ctx) - { - StringWriter writer = new StringWriter(); - try - { - renderDetailsCaptionCell(ctx, writer, null); - } - catch (Exception e) - { - writer.write(e.getMessage()); - } - return writer.toString(); - } - public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullable String cls) - { - try - { - renderDetailsCaptionCell(ctx, out.unwrap(), cls); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - public void renderDetailsCaptionCell(RenderContext ctx, Writer out, @Nullable String cls) throws IOException { if (null == _caption) return; - out.write(""); - renderTitle(ctx, out); - out.write(""); - } - - public String getDetailsData(RenderContext ctx) - { - StringWriter writer = new StringWriter(); - try - { - renderDetailsData(ctx, writer); - } - catch (Exception e) - { - writer.write(e.getMessage()); - } - return writer.toString(); - } - - public void renderDetailsData(RenderContext ctx, HtmlWriter out) - { - try - { - renderDetailsData(ctx, out.unwrap()); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - public void renderDetailsData(RenderContext ctx, Writer out) throws IOException - { - renderDetailsCellContents(ctx, out); - } - - public String getInputCell(RenderContext ctx) - { - StringWriter writer = new StringWriter(); - try - { - renderInputCell(ctx, writer); - } - catch (Exception e) - { - writer.write(e.getMessage()); - } - return writer.toString(); + TD( + cl("lk-form-label"), + getTitle(ctx) + ).appendTo(out); } /** Get typed value or string value if form type conversion failed. */ @@ -1284,85 +1195,39 @@ public String getFormFieldName(RenderContext ctx) return getName(); } - protected 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"); - } - } - - public void renderHiddenFormInput(RenderContext ctx, Writer out) throws IOException + protected void renderHiddenFormInput(HtmlWriter out, String formFieldName, Object value) { - renderHiddenFormInput(ctx, out, getFormFieldName(ctx), getInputValue(ctx)); - } - - protected void renderHiddenFormInput(RenderContext ctx, Writer out, String formFieldName, Object value) throws IOException - { - out.write(new Input.InputBuilder() + out.write(new InputBuilder<>() .name(formFieldName) .type("hidden") - .value(null != value ? value.toString() : null) - .toString()); - } - - public void renderInputWrapperBegin(HtmlWriter out) - { - try - { - renderInputWrapperBegin(out.unwrap()); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - public void renderInputWrapperBegin(Writer out) throws IOException - { - out.write(""); - } - - public void renderInputWrapperEnd(HtmlWriter out) - { - try - { - renderInputWrapperEnd(out.unwrap()); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + .value(null != value ? value.toString() : null)); } - public void renderInputWrapperEnd(Writer out) throws IOException + public DOM._Attributes getInputAttributes() { - out.write(""); + return at(); } public void renderInputCell(RenderContext ctx, HtmlWriter out) { - try - { - renderInputCell(ctx, out.unwrap()); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + TD( + getInputAttributes(), + (DOM.Renderable) ret -> { + renderInputHtml(ctx, out, getInputValue(ctx)); + return ret; + } + ).appendTo(out); } - public void renderInputCell(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCell(RenderContext ctx, HtmlWriter out) { - renderInputWrapperBegin(out); - renderInputHtml(ctx, out, getInputValue(ctx)); - renderInputWrapperEnd(out); + TD( + getInputAttributes(), + (DOM.Renderable) ret -> { + renderDetailsCellContents(ctx, out); + return ret; + } + ).appendTo(out); } public String getSortHandler(RenderContext ctx, Sort.SortDirection sort) @@ -1370,19 +1235,7 @@ public String getSortHandler(RenderContext ctx, Sort.SortDirection sort) return ""; } - public String getFilterOnClick(RenderContext ctx) - { - StringWriter writer = new StringWriter(); - try - { - renderFilterOnClick(ctx, writer); - } - catch (Exception e) - { - writer.write(e.getMessage()); - } - return writer.toString(); - } + public abstract String getFilterOnClick(RenderContext ctx); public String getClearFilter(RenderContext ctx) { @@ -1394,21 +1247,6 @@ public String getClearSortScript(RenderContext ctx) return ""; } - public String getInputHtml(RenderContext ctx) - { - Object value = getInputValue(ctx); - StringWriter writer = new StringWriter(); - try - { - renderInputHtml(ctx, writer, value); - } - catch (Exception e) - { - writer.write(e.getMessage()); - } - return writer.toString(); - } - public boolean getRequiresHtmlFiltering() { return _requiresHtmlFiltering; diff --git a/api/src/org/labkey/api/data/DisplayColumnDecorator.java b/api/src/org/labkey/api/data/DisplayColumnDecorator.java index 5719934c467..a72477f17e6 100644 --- a/api/src/org/labkey/api/data/DisplayColumnDecorator.java +++ b/api/src/org/labkey/api/data/DisplayColumnDecorator.java @@ -16,6 +16,8 @@ package org.labkey.api.data; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.labkey.api.query.FieldKey; @@ -25,9 +27,6 @@ import org.labkey.api.util.StringExpression; import org.labkey.api.view.ActionURL; import org.labkey.api.view.ViewContext; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import org.labkey.api.writer.HtmlWriter; import java.io.IOException; @@ -36,10 +35,6 @@ import java.util.Map; import java.util.Set; -/** - * User: kevink - * Date: Nov 20, 2008 4:25:54 PM - */ public class DisplayColumnDecorator extends DisplayColumn { protected DisplayColumn _column; @@ -50,35 +45,23 @@ public DisplayColumnDecorator(DisplayColumn column) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { _column.renderGridCellContents(ctx, out); } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { _column.renderDetailsCellContents(ctx, out); } @Override - public void renderTitle(RenderContext ctx, Writer out) throws IOException - { - _column.renderTitle(ctx, out); - } - - @Override - public String getTitle(RenderContext ctx) + public HtmlString getTitle(RenderContext ctx) { return _column.getTitle(ctx); } - @Override - public void renderGridEnd(RenderContext ctx, Writer out) throws IOException - { - _column.renderGridEnd(ctx, out); - } - @Override public boolean isSortable() { @@ -98,13 +81,7 @@ public boolean isEditable() } @Override - public void renderFilterOnClick(RenderContext ctx, Writer out) throws IOException - { - _column.renderFilterOnClick(ctx, out); - } - - @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { _column.renderInputHtml(ctx, out, value); } @@ -319,7 +296,7 @@ public Object getDisplayValue(RenderContext ctx) } @Override - public Class getDisplayValueClass() + public Class getDisplayValueClass() { return _column.getDisplayValueClass(); } @@ -379,7 +356,7 @@ public void renderGridHeaderCell(RenderContext ctx, HtmlWriter out) } @Override - public void renderGridHeaderCell(RenderContext ctx, Writer out, String headerClass) throws IOException + public void renderGridHeaderCell(RenderContext ctx, HtmlWriter out, String headerClass) { _column.renderGridHeaderCell(ctx, out, headerClass); } @@ -390,12 +367,6 @@ public boolean isUserSort(RenderContext ctx) return _column.isUserSort(ctx); } - @Override - public String getGridDataCell(RenderContext ctx) - { - return _column.getGridDataCell(ctx); - } - @NotNull @Override public String getCssStyle(RenderContext ctx) @@ -422,35 +393,11 @@ public String getCaption(RenderContext ctx, boolean htmlEncode) } @Override - public String getDetailsCaptionCell(RenderContext ctx) - { - return _column.getDetailsCaptionCell(ctx); - } - - @Override - public void renderDetailsCaptionCell(RenderContext ctx, Writer out, @Nullable String cls) throws IOException + public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullable String cls) { _column.renderDetailsCaptionCell(ctx, out, cls); } - @Override - public String getDetailsData(RenderContext ctx) - { - return _column.getDetailsData(ctx); - } - - @Override - public void renderDetailsData(RenderContext ctx, Writer out) throws IOException - { - _column.renderDetailsData(ctx, out); - } - - @Override - public String getInputCell(RenderContext ctx) - { - return _column.getInputCell(ctx); - } - @Override protected Object getInputValue(RenderContext ctx) { @@ -464,27 +411,21 @@ public String getFormFieldName(RenderContext ctx) } @Override - protected void outputName(RenderContext ctx, Writer out, String formFieldName) throws IOException - { - _column.outputName(ctx, out, formFieldName); - } - - @Override - public void renderHiddenFormInput(RenderContext ctx, Writer out) throws IOException + protected void renderHiddenFormInput(HtmlWriter out, String formFieldName, Object value) { - _column.renderHiddenFormInput(ctx, out); + _column.renderHiddenFormInput(out, formFieldName, value); } @Override - protected void renderHiddenFormInput(RenderContext ctx, Writer out, String formFieldName, Object value) throws IOException + public void renderInputCell(RenderContext ctx, HtmlWriter out) { - _column.renderHiddenFormInput(ctx, out, formFieldName, value); + _column.renderInputCell(ctx, out); } @Override - public void renderInputCell(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCell(RenderContext ctx, HtmlWriter out) { - _column.renderInputCell(ctx, out); + _column.renderDetailsCell(ctx, out); } @Override @@ -511,12 +452,6 @@ public String getClearSortScript(RenderContext ctx) return _column.getClearSortScript(ctx); } - @Override - public String getInputHtml(RenderContext ctx) - { - return _column.getInputHtml(ctx); - } - @Override public boolean getRequiresHtmlFiltering() { diff --git a/api/src/org/labkey/api/data/DisplayColumnGroup.java b/api/src/org/labkey/api/data/DisplayColumnGroup.java index 796b72fe7fb..251f8be7f03 100644 --- a/api/src/org/labkey/api/data/DisplayColumnGroup.java +++ b/api/src/org/labkey/api/data/DisplayColumnGroup.java @@ -16,6 +16,8 @@ package org.labkey.api.data; +import org.labkey.api.util.DOM; +import org.labkey.api.util.element.Input.InputBuilder; import org.labkey.api.view.HttpView; import org.labkey.api.writer.HtmlWriter; @@ -23,6 +25,8 @@ import java.io.Writer; import java.util.List; +import static org.labkey.api.util.DOM.TD; + public class DisplayColumnGroup { private final List _columns; @@ -53,41 +57,33 @@ public boolean isCopyable() public void writeSameCheckboxCell(RenderContext ctx, HtmlWriter out) { - try - { - writeSameCheckboxCell(ctx, out.unwrap()); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } + TD( + isCopyable() ? (DOM.Renderable) ret -> { - public void writeSameCheckboxCell(RenderContext ctx, Writer out) throws IOException - { - out.write(""); - if (isCopyable()) - { - String id = getGroupFormFieldName(ctx) + "CheckBox"; - out.write(""); - StringBuilder onChange = new StringBuilder("b = this.checked;"); - for (int i = 1; i < getColumns().size(); i++) - { - DisplayColumn col = getColumns().get(i); - ColumnInfo colInfo = col.getColumnInfo(); - if (colInfo != null) - { - onChange.append("document.getElementsByName('") - .append(col.getFormFieldName(ctx)) - .append("')[0].style.display = b ? 'none' : 'block';\n"); - } - } - onChange.append(" if (b) { ") - .append(getGroupFormFieldName(ctx)) - .append("Updated(); }"); - HttpView.currentPageConfig().addHandler(id, "change", onChange.toString()); - } - out.write(""); + String id = getGroupFormFieldName(ctx) + "CheckBox"; + new InputBuilder<>().type("checkbox").name(id).id(id).appendTo(out); + StringBuilder onChange = new StringBuilder("b = this.checked;"); + + getColumns().forEach(col -> { + ColumnInfo colInfo = col.getColumnInfo(); + if (colInfo != null) + { + onChange.append("document.getElementsByName('") + .append(col.getFormFieldName(ctx)) + .append("')[0].style.display = b ? 'none' : 'block';\n"); + } + }); + + onChange.append(" if (b) { ") + .append(getGroupFormFieldName(ctx)) + .append("Updated(); }"); + + HttpView.currentPageConfig().addHandler(id, "change", onChange.toString()); + + return ret; + } : + null + ).appendTo(out); } private String getGroupFormFieldName(RenderContext ctx) diff --git a/api/src/org/labkey/api/data/HighlightingDisplayColumn.java b/api/src/org/labkey/api/data/HighlightingDisplayColumn.java index 21d65614eec..880c621db81 100644 --- a/api/src/org/labkey/api/data/HighlightingDisplayColumn.java +++ b/api/src/org/labkey/api/data/HighlightingDisplayColumn.java @@ -17,6 +17,7 @@ package org.labkey.api.data; import org.labkey.api.query.FieldKey; +import org.labkey.api.util.DOM; import org.labkey.api.util.UniqueID; import org.labkey.api.view.HttpView; import org.labkey.api.view.template.PageConfig; @@ -28,11 +29,9 @@ import java.util.LinkedHashMap; import java.util.List; -/* -* User: adam -* Date: Dec 19, 2010 -* Time: 8:38:17 PM -*/ +import static org.labkey.api.util.DOM.SPAN; +import static org.labkey.api.util.DOM.cl; + public class HighlightingDisplayColumn extends DisplayColumnDecorator { private final LinkedHashMap, String> _distinctValuesToClass = new LinkedHashMap<>(); @@ -115,7 +114,7 @@ public void renderGridHeaderCell(RenderContext ctx, HtmlWriter out) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { if (!handlersAdded) { @@ -131,16 +130,19 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep } String styleClass = getStyleClass(ctx); - out.write(""); - super.renderGridCellContents(ctx, out); - out.write(""); + SPAN( + cl(styleClass, _cssEventSelector), + (DOM.Renderable) ret -> { + super.renderGridCellContents(ctx, out); + return ret; + } + ).appendTo(out); } - @Override + // Note: Nobody calls this method! It must have been orphaned in DisplayColumn / DataColumn a while back. + // I'm leaving the code in place in case we want to restore it... public void renderGridEnd(RenderContext ctx, Writer out) throws IOException { - super.renderGridEnd(ctx, out); - String styleMapName = "styleMap" + _uid; String lockedStylesName = "lockedStyles" + _uid; diff --git a/api/src/org/labkey/api/data/IconDisplayColumn.java b/api/src/org/labkey/api/data/IconDisplayColumn.java index 7f784edf6d1..5c6eef07992 100644 --- a/api/src/org/labkey/api/data/IconDisplayColumn.java +++ b/api/src/org/labkey/api/data/IconDisplayColumn.java @@ -19,6 +19,7 @@ import org.jetbrains.annotations.NotNull; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -70,14 +71,14 @@ public boolean isSortable() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { ActionURL linkURL = _linkURL.clone(); Object value = ctx.getRow().get(getColumnInfo().getAlias()); if (value != null) { linkURL.addParameter(_parameterName, value.toString()); - out.write(""); + oldWriter.write(""); } } } diff --git a/api/src/org/labkey/api/data/InputColumn.java b/api/src/org/labkey/api/data/InputColumn.java index 7718a99a0ce..2e9cad2f146 100644 --- a/api/src/org/labkey/api/data/InputColumn.java +++ b/api/src/org/labkey/api/data/InputColumn.java @@ -15,14 +15,13 @@ */ package org.labkey.api.data; +import org.labkey.api.writer.HtmlWriter; + import java.io.IOException; import java.io.Writer; /** * Renders a bound ColumnInfo as an HTML form input in a grid view. - * - * User: kevink - * Date: 10/21/12 */ public class InputColumn extends DataColumn { @@ -32,13 +31,13 @@ public InputColumn(ColumnInfo col) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { renderInputHtml(ctx, out, getInputValue(ctx)); } @Override - public void render(RenderContext ctx, Writer out) throws IOException + public void render(RenderContext ctx, HtmlWriter out) { renderInputHtml(ctx, out, getInputValue(ctx)); } diff --git a/api/src/org/labkey/api/data/JavaScriptDisplayColumn.java b/api/src/org/labkey/api/data/JavaScriptDisplayColumn.java index 420a5c2bdb6..6df2c612cc7 100644 --- a/api/src/org/labkey/api/data/JavaScriptDisplayColumn.java +++ b/api/src/org/labkey/api/data/JavaScriptDisplayColumn.java @@ -23,6 +23,7 @@ import org.labkey.api.util.Link.LinkBuilder; import org.labkey.api.util.StringExpressionFactory; import org.labkey.api.view.template.ClientDependency; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -63,7 +64,7 @@ public JavaScriptDisplayColumn(ColumnInfo col, @Nullable Collection depe } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object o = getValue(ctx); @@ -74,10 +75,10 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep if (_onClickExpression != null) onClick = StringUtils.trim(_onClickExpression.eval(ctx)); - renderLink(out, getFormattedHtml(ctx), onClick, _linkClassName); + renderLink(oldWriter, getFormattedHtml(ctx), onClick, _linkClassName); } else - out.write(" "); + oldWriter.write(" "); } protected void renderLink(Writer out, HtmlString html, @Nullable String onClick, @Nullable String linkClassName) diff --git a/api/src/org/labkey/api/data/MVDisplayColumn.java b/api/src/org/labkey/api/data/MVDisplayColumn.java index 66c744df087..19d0aa512bc 100644 --- a/api/src/org/labkey/api/data/MVDisplayColumn.java +++ b/api/src/org/labkey/api/data/MVDisplayColumn.java @@ -20,11 +20,18 @@ import org.labkey.api.util.HtmlString; import org.labkey.api.util.HtmlStringBuilder; import org.labkey.api.util.PageFlowUtil; +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; +import static org.labkey.api.util.DOM.DIV; +import static org.labkey.api.util.DOM.FONT; +import static org.labkey.api.util.DOM.at; +import static org.labkey.api.util.DOM.cl; + /** * Column type that renders an indicator if there is an associated missing value indicator to accompany the normal * value. There is a discrete, configured list of allowable indicators, on a per-container basis. See {@link MvUtil}. @@ -64,7 +71,7 @@ public Object getRawValue(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { String mvIndicator = getMvIndicator(ctx); if (mvIndicator != null) @@ -78,9 +85,10 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep .append(value) .unsafeAppend("'.

"); - out.write(""); - PageFlowUtil.popupHelp(popupText, "Missing Value Indicator: " + mvIndicator).link(HtmlString.of(mvIndicator)).appendTo(out); - out.write(""); + FONT( + cl("labkey-mv"), + PageFlowUtil.popupHelp(popupText, "Missing Value Indicator: " + mvIndicator).link(HtmlString.of(mvIndicator)) + ).appendTo(out); } else { @@ -114,8 +122,8 @@ public Object getValue(RenderContext ctx) @Override public Object getDisplayValue(RenderContext ctx) { - // For non-mv-aware clients, we need to return null - // if we have an mv indicator + // For non-MV-aware clients, we need to return null + // if we have an MV indicator if (getMvIndicator(ctx) != null) { return null; @@ -168,39 +176,61 @@ else if (ctx.getRow() != null) } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { - out.write("
"); + DIV(at(style,"margin-top:5px")).appendTo(out); super.renderInputHtml(ctx, out, value); - renderMVPicker(ctx, out); + try + { + renderMVPicker(ctx, out); + } + catch (IOException e) + { + throw new RuntimeException(e); + } } - private void renderMVPicker(RenderContext ctx, Writer out) throws IOException + private void renderMVPicker(RenderContext ctx, HtmlWriter out) throws IOException { + Writer oldWriter = out.unwrap(); String formFieldName = ctx.getForm().getFormFieldName(mvIndicatorColumn); String selectedMvIndicator = getMvIndicator(ctx); Set mvIndicators = MvUtil.getMvIndicators(ctx.getContainer()); - out.write("Missing Value Indicator: "); - out.write(""); + 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"); + } + } } diff --git a/api/src/org/labkey/api/data/MultiValuedDisplayColumn.java b/api/src/org/labkey/api/data/MultiValuedDisplayColumn.java index 5051786a67f..e6a79a4d1e9 100644 --- a/api/src/org/labkey/api/data/MultiValuedDisplayColumn.java +++ b/api/src/org/labkey/api/data/MultiValuedDisplayColumn.java @@ -18,9 +18,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.labkey.api.query.FieldKey; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -32,9 +31,6 @@ /** * Wraps any DisplayColumn and causes it to render each value separately. Often used in conjunction with * MultiValuedLookupColumn - * - * User: adam - * Date: Sep 14, 2010 */ public class MultiValuedDisplayColumn extends DisplayColumnDecorator implements IMultiValuedDisplayColumn { @@ -125,7 +121,7 @@ public List renderURLs(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { try { @@ -139,7 +135,7 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep Object o = getValue(mvCtx); if (o != null) { - out.append(sep); + out.write(sep); super.renderGridCellContents(mvCtx, out); sep = ", "; } @@ -155,13 +151,7 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep } @Override - public void renderDetailsData(RenderContext ctx, Writer out) throws IOException - { - renderGridCellContents(ctx, out); - } - - @Override - public Class getDisplayValueClass() + public Class getDisplayValueClass() { return String.class; } @@ -208,14 +198,6 @@ public List getJsonValues(RenderContext ctx) return values(ctx, _column::getJsonValue); } - @Override - public void renderInputCell(RenderContext ctx, Writer out) throws IOException - { - renderInputWrapperBegin(out); - renderInputHtml(ctx, out, getInputValue(ctx)); - renderInputWrapperEnd(out); - } - @Override public Object getInputValue(RenderContext ctx) { diff --git a/api/src/org/labkey/api/data/NestableDataRegion.java b/api/src/org/labkey/api/data/NestableDataRegion.java index a0a704a72a6..9580e222828 100644 --- a/api/src/org/labkey/api/data/NestableDataRegion.java +++ b/api/src/org/labkey/api/data/NestableDataRegion.java @@ -21,7 +21,6 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; diff --git a/api/src/org/labkey/api/data/SimpleDisplayColumn.java b/api/src/org/labkey/api/data/SimpleDisplayColumn.java index 8515a370efb..d64f56277ba 100644 --- a/api/src/org/labkey/api/data/SimpleDisplayColumn.java +++ b/api/src/org/labkey/api/data/SimpleDisplayColumn.java @@ -16,10 +16,13 @@ package org.labkey.api.data; +import org.jetbrains.annotations.NotNull; import org.labkey.api.query.FieldKey; +import org.labkey.api.util.HtmlString; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.StringExpression; import org.labkey.api.util.StringExpressionFactory; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -95,7 +98,7 @@ public boolean isSortable() } @Override - public Class getValueClass() + public Class getValueClass() { return String.class; } @@ -107,70 +110,73 @@ public Object getValue(RenderContext ctx) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object value = getValue(ctx); if (value != null) - out.write(value.toString()); + oldWriter.write(value.toString()); } @Override - public void renderFilterOnClick(RenderContext ctx, Writer out) + public String getFilterOnClick(RenderContext ctx) { throw new UnsupportedOperationException("Non Bound columns not filterable"); } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { String url = renderURL(ctx); if (null != url) { - out.write(""); + oldWriter.write("'>"); } Object value = getDisplayValue(ctx); if (value == null) - out.write(""); + oldWriter.write(""); else if (null == _format) - out.write(getDisplayValue(ctx).toString()); + oldWriter.write(getDisplayValue(ctx).toString()); else - out.write(_format.format(getDisplayValue(ctx))); + oldWriter.write(_format.format(getDisplayValue(ctx))); if (null != url) - out.write(""); + oldWriter.write(""); } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { - throw new UnsupportedOperationException("Non Bound columns not editable"); + throw new UnsupportedOperationException("Non Bound columns not editable for " + this); } @Override - public void renderTitle(RenderContext ctx, Writer out) throws IOException + public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException { - if (null != _caption) - _caption.render(out, ctx); - else - out.write(" "); + throw new UnsupportedOperationException("Non Bound columns not editable for " + this); + } + + @Override + public @NotNull HtmlString getTitle(RenderContext ctx) + { + return null != _caption ? HtmlString.of(_caption) : HtmlString.NBSP; } @Override @@ -180,9 +186,9 @@ public boolean isEditable() } @Override - public void render(RenderContext ctx, Writer out) throws IOException + public void render(RenderContext ctx, HtmlWriter out) { - renderTitle(ctx, out); + out.write(getTitle(ctx)); if (null != _caption) out.write(" "); renderDetailsCellContents(ctx, out); diff --git a/api/src/org/labkey/api/data/URLDisplayColumn.java b/api/src/org/labkey/api/data/URLDisplayColumn.java index 88df0f7781f..40c191a79b7 100644 --- a/api/src/org/labkey/api/data/URLDisplayColumn.java +++ b/api/src/org/labkey/api/data/URLDisplayColumn.java @@ -21,10 +21,9 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.StringExpression; import org.labkey.api.util.StringExpressionFactory; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; import java.io.InputStream; -import java.io.Writer; /** * URLDisplayColumn allows for a grid cell to render a thumbnail image and/or a popup tooltip image, both via @@ -109,7 +108,7 @@ protected InputStream getFileContents(RenderContext ctx, Object value) } @Override - protected void renderIconAndFilename(RenderContext ctx, Writer out, String filename, boolean link, boolean thumbnail) throws IOException + protected void renderIconAndFilename(RenderContext ctx, HtmlWriter out, String filename, boolean link, boolean thumbnail) { Object value = getValue(ctx); String url = renderURL(ctx); diff --git a/api/src/org/labkey/api/data/UrlColumn.java b/api/src/org/labkey/api/data/UrlColumn.java index f0b1a7a11b7..e25fa8d6181 100644 --- a/api/src/org/labkey/api/data/UrlColumn.java +++ b/api/src/org/labkey/api/data/UrlColumn.java @@ -19,6 +19,7 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.StringExpression; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -39,12 +40,12 @@ public UrlColumn(ActionURL url, String text) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object value = getValue(ctx); String url = renderURL(ctx); if (value != null && url != null) - out.write(PageFlowUtil.link(value.toString()).href(url).target(_linkTarget).toString()); + oldWriter.write(PageFlowUtil.link(value.toString()).href(url).target(_linkTarget).toString()); } } diff --git a/api/src/org/labkey/api/defaults/SetDefaultValuesAction.java b/api/src/org/labkey/api/defaults/SetDefaultValuesAction.java index 05c063b963c..16e172d26f9 100644 --- a/api/src/org/labkey/api/defaults/SetDefaultValuesAction.java +++ b/api/src/org/labkey/api/defaults/SetDefaultValuesAction.java @@ -36,6 +36,7 @@ import org.labkey.api.portal.ProjectUrls; import org.labkey.api.security.RequiresPermission; import org.labkey.api.security.permissions.AdminPermission; +import org.labkey.api.util.DOM.Renderable; import org.labkey.api.util.HtmlString; import org.labkey.api.util.HtmlStringBuilder; import org.labkey.api.util.PageFlowUtil; @@ -52,11 +53,17 @@ import java.io.File; import java.io.IOException; -import java.io.Writer; import java.util.HashMap; import java.util.List; import java.util.Map; +import static org.labkey.api.util.DOM.Attribute.style; +import static org.labkey.api.util.DOM.LABEL; +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; + @RequiresPermission(AdminPermission.class) public class SetDefaultValuesAction extends DefaultValuesAction { @@ -111,53 +118,113 @@ protected static class DefaultValueDataRegion extends DataRegion @Override public void render(RenderContext ctx, HtmlWriter out) { - Writer oldWriter = out.unwrap(); - - try - { - renderFormBegin(ctx, out, MODE_INSERT); - renderMainErrors(ctx, out); - oldWriter.write(""); - oldWriter.write("" + - "" + - "" + - "" + - ""); - for (DisplayColumn renderer : getDisplayColumns()) - { - if (!shouldRender(renderer, ctx) || !(renderer instanceof DefaultableDisplayColumn)) - continue; - boolean isFile = ((DefaultableDisplayColumn) renderer).getJavaType() == File.class; - oldWriter.write(""); - - renderer.renderDetailsCaptionCell(ctx, oldWriter, "control-label lk-form-row-label"); - - if (isFile) - oldWriter.write(""); // No input for file - else - renderer.renderInputCell(ctx, oldWriter); - - oldWriter.write(""); - oldWriter.write(""); + return app; } - oldWriter.write("
"); - if (isFile) - oldWriter.write("Defaults cannot be set for file fields."); - else + renderFormBegin(ctx, out, MODE_INSERT); + renderMainErrors(ctx, out); + + TABLE( + cl("lk-fields-table"), + (Renderable) app -> { + TR( + TD( + cl("lk-form-label lk-form-col-label"), + LABEL("Field") + ), + TD( + cl("lk-form-label lk-form-col-label").at(style, "text-align: left;"), + LABEL("Initial/Default Value") + ), + TD( + cl("lk-form-label lk-form-col-label"), + LABEL("Default type") + ) + ).appendTo(out); + + for (DisplayColumn renderer : getDisplayColumns()) { - DefaultValueType defaultType = ((DefaultableDisplayColumn) renderer).getDefaultValueType(); - if (defaultType == null) - defaultType = DefaultValueType.FIXED_EDITABLE; - oldWriter.write(PageFlowUtil.filter(defaultType.getLabel())); - PageFlowUtil.popupHelp(HtmlString.of(defaultType.getHelpText()), "Default Value Type: " + defaultType.getLabel()).appendTo(oldWriter); + if (!shouldRender(renderer, ctx) || !(renderer instanceof DefaultableDisplayColumn)) + continue; + boolean isFile = ((DefaultableDisplayColumn) renderer).getJavaType() == File.class; + TR( + (Renderable) ret -> { + renderer.renderDetailsCaptionCell(ctx, out, "control-label lk-form-row-label"); + + if (isFile) + TD().appendTo(out); // No input for file + else + renderer.renderInputCell(ctx, out); + + TD( + (Renderable) rend -> { + if (isFile) + { + out.write("Defaults cannot be set for file fields."); + } + else + { + DefaultValueType defaultType = ((DefaultableDisplayColumn) renderer).getDefaultValueType(); + if (defaultType == null) + defaultType = DefaultValueType.FIXED_EDITABLE; + out.write(defaultType.getLabel()); + out.write(PageFlowUtil.popupHelp(HtmlString.of(defaultType.getHelpText()), "Default Value Type: " + defaultType.getLabel())); + } + return rend; + } + ).appendTo(out); + + return ret; + } + ).appendTo(out); } - oldWriter.write("
"); - } - catch (IOException e) - { - throw new RuntimeException(e); - } + ).appendTo(out); +// oldWriter.write(""); + + +// renderer.renderDetailsCaptionCell(ctx, out, "control-label lk-form-row-label"); +// +// if (isFile) +// TD().appendTo(out); // No input for file +// else +// renderer.renderInputCell(ctx, out); +// +// TD( +// (Renderable) ret -> { +// if (isFile) +// { +// out.write("Defaults cannot be set for file fields."); +// } +// else +// { +// DefaultValueType defaultType = ((DefaultableDisplayColumn) renderer).getDefaultValueType(); +// if (defaultType == null) +// defaultType = DefaultValueType.FIXED_EDITABLE; +// out.write(defaultType.getLabel()); +// out.write(PageFlowUtil.popupHelp(HtmlString.of(defaultType.getHelpText()), "Default Value Type: " + defaultType.getLabel())); +// } +// return ret; +// } +// ).appendTo(out); +// oldWriter.write(""); + +// oldWriter.write(""); +// } +// oldWriter.write("
"); +// if (isFile) +// { +// out.write("Defaults cannot be set for file fields."); +// } +// else +// { +// DefaultValueType defaultType = ((DefaultableDisplayColumn) renderer).getDefaultValueType(); +// if (defaultType == null) +// defaultType = DefaultValueType.FIXED_EDITABLE; +// out.write(defaultType.getLabel()); +// out.write(PageFlowUtil.popupHelp(HtmlString.of(defaultType.getHelpText()), "Default Value Type: " + defaultType.getLabel())); +// } +// oldWriter.write("
"); + ButtonBar bbar = getButtonBar(MODE_INSERT); bbar.setStyle(ButtonBar.Style.separateButtons); diff --git a/api/src/org/labkey/api/exp/flag/FlagColumnRenderer.java b/api/src/org/labkey/api/exp/flag/FlagColumnRenderer.java index 7e718bec4ec..2a2f11eb7be 100644 --- a/api/src/org/labkey/api/exp/flag/FlagColumnRenderer.java +++ b/api/src/org/labkey/api/exp/flag/FlagColumnRenderer.java @@ -26,6 +26,7 @@ import org.labkey.api.util.UnexpectedException; import org.labkey.api.util.UniqueID; import org.labkey.api.view.HttpView; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -154,9 +155,9 @@ public static String flagDisabledCls() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { - renderFlag(ctx, out); + renderFlag(ctx, oldWriter); } @Override diff --git a/api/src/org/labkey/api/exp/property/DomainAuditProvider.java b/api/src/org/labkey/api/exp/property/DomainAuditProvider.java index 7c526e3f594..65ad2b74cbb 100644 --- a/api/src/org/labkey/api/exp/property/DomainAuditProvider.java +++ b/api/src/org/labkey/api/exp/property/DomainAuditProvider.java @@ -35,6 +35,7 @@ import org.labkey.api.query.UserSchema; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.writer.DefaultContainerUser; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -250,7 +251,7 @@ public String getName() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { String uri = (String)getBoundColumn().getValue(ctx); String cId = ctx.get(getContainerFieldKey(), String.class); @@ -265,15 +266,15 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep { DomainKind kind = PropertyService.get().getDomainKind(domain.getTypeURI()); if (kind != null) - out.write("" + PageFlowUtil.filter(domain.getName()) + ""); + oldWriter.write("" + PageFlowUtil.filter(domain.getName()) + ""); else - out.write(PageFlowUtil.filter(domain.getName())); + oldWriter.write(PageFlowUtil.filter(domain.getName())); return; } } } - out.write(Objects.toString(PageFlowUtil.filter(ctx.get(getDefaultNameFieldKey())), " ")); + oldWriter.write(Objects.toString(PageFlowUtil.filter(ctx.get(getDefaultNameFieldKey())), " ")); } @Override diff --git a/api/src/org/labkey/api/jsp/JspBase.java b/api/src/org/labkey/api/jsp/JspBase.java index 2357cc8fdf0..c4998da621b 100644 --- a/api/src/org/labkey/api/jsp/JspBase.java +++ b/api/src/org/labkey/api/jsp/JspBase.java @@ -475,7 +475,7 @@ public LinkBuilder link(Renderable html, @NotNull URLHelper url) public InputBuilder input() { - return new InputBuilder(); + return new InputBuilder<>(); } public HtmlString generateBackButton() diff --git a/api/src/org/labkey/api/jsp/taglib/CheckboxTag.java b/api/src/org/labkey/api/jsp/taglib/CheckboxTag.java index 6ed6ef17911..d7ac14fd025 100644 --- a/api/src/org/labkey/api/jsp/taglib/CheckboxTag.java +++ b/api/src/org/labkey/api/jsp/taglib/CheckboxTag.java @@ -35,7 +35,7 @@ public class CheckboxTag extends SimpleTagBase public void doTag() throws IOException { // TODO: We need a CheckBoxBuilder - InputBuilder checkbox = new InputBuilder() + InputBuilder checkbox = new InputBuilder<>() .type("checkbox") .id(_id) .name(_name) @@ -52,7 +52,7 @@ public void doTag() throws IOException getOut().print(checkbox); - InputBuilder springMarker = new InputBuilder() + InputBuilder springMarker = new InputBuilder<>() .type("hidden") .name(SpringActionController.FIELD_MARKER + _name); diff --git a/api/src/org/labkey/api/jsp/taglib/InputTag.java b/api/src/org/labkey/api/jsp/taglib/InputTag.java index 283026505da..16b7537b4ee 100644 --- a/api/src/org/labkey/api/jsp/taglib/InputTag.java +++ b/api/src/org/labkey/api/jsp/taglib/InputTag.java @@ -286,7 +286,7 @@ public void doTag() throws IOException else if ("displayfield".equalsIgnoreCase(type)) input = new DisplayField.DisplayFieldBuilder(); else - input = new Input.InputBuilder().type(type); + input = new Input.InputBuilder<>().type(type); if (null == forceSmallContext) forceSmallContext = false; diff --git a/api/src/org/labkey/api/query/PropertiesDisplayColumn.java b/api/src/org/labkey/api/query/PropertiesDisplayColumn.java index 3c8f199d10d..76d27bf07ad 100644 --- a/api/src/org/labkey/api/query/PropertiesDisplayColumn.java +++ b/api/src/org/labkey/api/query/PropertiesDisplayColumn.java @@ -186,32 +186,32 @@ public Object getJsonValue(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { updateInnerContext(ctx); if (innerCtxLsid != null && !innerCtxCols.isEmpty()) { - out.write(""); - out.write("
"); - out.write(""); - out.write(""); + oldWriter.write("
"); + oldWriter.write("
"); + oldWriter.write(""); + oldWriter.write(""); for (var pair : innerCtxCols) { - pair.second.renderGridHeaderCell(innerCtx, HtmlWriter.of(out)); + pair.second.renderGridHeaderCell(innerCtx, out); } - out.write(""); - out.write(""); + oldWriter.write(""); + oldWriter.write(""); - out.write(""); - out.write(""); + oldWriter.write(""); + oldWriter.write(""); for (var pair : innerCtxCols) { - pair.second.renderGridDataCell(innerCtx, HtmlWriter.of(out)); + pair.second.renderGridDataCell(innerCtx, out); } - out.write(""); - out.write(""); - out.write("
"); + oldWriter.write(""); + oldWriter.write(""); + oldWriter.write(""); } } @@ -279,7 +279,7 @@ public boolean isEditable() } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) + public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) { // no-op } diff --git a/api/src/org/labkey/api/query/QueryView.java b/api/src/org/labkey/api/query/QueryView.java index 87b32448ff4..d2ba88766a3 100644 --- a/api/src/org/labkey/api/query/QueryView.java +++ b/api/src/org/labkey/api/query/QueryView.java @@ -2315,7 +2315,7 @@ protected void renderDataRegion(PrintWriter out) throws Exception // make sure table has been instantiated getTable(); List errors = getParseErrors(); - if (errors.size() != 0) + if (!errors.isEmpty()) { renderErrors(out, "Query '" + getQueryDef().getName() + "' has errors", errors); return; diff --git a/api/src/org/labkey/api/study/actions/ParticipantVisitResolverChooser.java b/api/src/org/labkey/api/study/actions/ParticipantVisitResolverChooser.java index a3d7b0be3b3..94300211079 100644 --- a/api/src/org/labkey/api/study/actions/ParticipantVisitResolverChooser.java +++ b/api/src/org/labkey/api/study/actions/ParticipantVisitResolverChooser.java @@ -24,20 +24,17 @@ import org.labkey.api.study.assay.ParticipantVisitResolverType; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.HttpView; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; import java.util.List; -/** - * User: jeckels - * Date: Sep 20, 2007 - */ public class ParticipantVisitResolverChooser extends SimpleDisplayColumn { - private List _resolvers; - private String _typeInputName; - private ColumnInfo _boundColumn; + private final List _resolvers; + private final String _typeInputName; + private final ColumnInfo _boundColumn; public ParticipantVisitResolverChooser(String typeInputName, List resolvers, ColumnInfo boundColumn) { @@ -59,100 +56,108 @@ protected boolean isDisabledInput() } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { - if (_resolvers.isEmpty()) - { - out.write("None available
"); - return; - } - - boolean disabledInput = isDisabledInput(); - ParticipantVisitResolverType selected = null; - for (ParticipantVisitResolverType resolver : _resolvers) + Writer oldWriter = out.unwrap(); + try { - if (resolver.getName().equals(value)) + if (_resolvers.isEmpty()) { - selected = resolver; - break; + oldWriter.write("None available
"); + return; } - } - if (selected == null) - { - selected = _resolvers.get(0); - } - // Keep track of listeners that want to know when the resolver selection has changed - out.write(""); - - if (_resolvers.size() < 2) - { - out.write("" + PageFlowUtil.filter(selected.getDescription()) + "
"); - try + boolean disabledInput = isDisabledInput(); + ParticipantVisitResolverType selected = null; + for (ParticipantVisitResolverType resolver : _resolvers) { - selected.render(ctx); + if (resolver.getName().equals(value)) + { + selected = resolver; + break; + } } - catch (Exception e) + if (selected == null) { - throw new IOException(e); + selected = _resolvers.get(0); } - } - else - { - out.write("\n"); - out.write(""); - for (ParticipantVisitResolverType resolver : _resolvers) + // Keep track of listeners that want to know when the resolver selection has changed + oldWriter.write(""); + + if (_resolvers.size() < 2) { - String script = "typeElements = document.getElementsByName(" + PageFlowUtil.jsString(_typeInputName)+ "); " + - "for (i = 0; i < typeElements.length; i++) " + - "{ var resolverSubSectionDiv = document.getElementById('ResolverDiv-' + typeElements[i].value); " + - " if (resolverSubSectionDiv != null) resolverSubSectionDiv.style.display='none'; } "; - - RenderSubSelectors renderSubs = renderResolverSubSelectors(resolver); - if (renderSubs != RenderSubSelectors.NONE) - script += "document.getElementById('ResolverDiv-' + this.value).style.display='block';"; - - // Notify listeners that the selection has changed - script += "for (i = 0; i < participantVisitResolverSelectionListeners.length; i++) { participantVisitResolverSelectionListeners[i].call(this); } "; - HttpView.currentPageConfig().addHandler("RadioBtn-" + resolver.getName(), "click", script); - - out.write(""); - - if (renderSubs != RenderSubSelectors.NONE) + oldWriter.write("" + PageFlowUtil.filter(selected.getDescription()) + "
"); + try + { + selected.render(ctx); + } + catch (Exception e) { + throw new IOException(e); + } + } + else + { + oldWriter.write("
My data is identified by:
"); - out.write(""); - - out.write(""); - out.write(PageFlowUtil.filter(resolver.getDescription())); - out.write("
\n"); + oldWriter.write(""); - out.write(""); + + if (renderSubs != RenderSubSelectors.NONE) { - throw (IOException)new IOException().initCause(e); + + oldWriter.write(""); } - out.write(""); - if (disabledInput) - out.write(""); - out.write(""); } + oldWriter.write("
My data is identified by:
"); - out.write("
"); - try - { - ctx.put(RenderSubSelectors.class.getSimpleName(), renderSubs); - resolver.render(ctx); - } - catch (Exception e) + for (ParticipantVisitResolverType resolver : _resolvers) + { + String script = "typeElements = document.getElementsByName(" + PageFlowUtil.jsString(_typeInputName)+ "); " + + "for (i = 0; i < typeElements.length; i++) " + + "{ var resolverSubSectionDiv = document.getElementById('ResolverDiv-' + typeElements[i].value); " + + " if (resolverSubSectionDiv != null) resolverSubSectionDiv.style.display='none'; } "; + + RenderSubSelectors renderSubs = renderResolverSubSelectors(resolver); + if (renderSubs != RenderSubSelectors.NONE) + script += "document.getElementById('ResolverDiv-' + this.value).style.display='block';"; + + // Notify listeners that the selection has changed + script += "for (i = 0; i < participantVisitResolverSelectionListeners.length; i++) { participantVisitResolverSelectionListeners[i].call(this); } "; + HttpView.currentPageConfig().addHandler("RadioBtn-" + resolver.getName(), "click", script); + + oldWriter.write("
"); + oldWriter.write(""); + + oldWriter.write(""); + oldWriter.write(PageFlowUtil.filter(resolver.getDescription())); + oldWriter.write("
"); + oldWriter.write("
"); + try + { + ctx.put(RenderSubSelectors.class.getSimpleName(), renderSubs); + resolver.render(ctx); + } + catch (Exception e) + { + throw (IOException)new IOException().initCause(e); + } + oldWriter.write("
"); + if (disabledInput) + oldWriter.write(""); + oldWriter.write("
"); } - out.write(""); + } + catch (IOException e) + { + throw new RuntimeException(e); } } @@ -160,7 +165,7 @@ public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws * Rather than a boolean to render subselectors for the resolver type, there are cases where * some, but not all, of the resolver's subselection options are to be displayed. */ - public static enum RenderSubSelectors + public enum RenderSubSelectors { ALL, NONE, diff --git a/api/src/org/labkey/api/study/actions/StudyPickerColumn.java b/api/src/org/labkey/api/study/actions/StudyPickerColumn.java index e868814067a..67a5b5768db 100644 --- a/api/src/org/labkey/api/study/actions/StudyPickerColumn.java +++ b/api/src/org/labkey/api/study/actions/StudyPickerColumn.java @@ -28,17 +28,15 @@ import org.labkey.api.study.publish.StudyPublishService; import org.labkey.api.util.HtmlString; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.element.Input; 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.Set; -/** -* User: jeckels -* Date: Aug 30, 2010 -*/ public class StudyPickerColumn extends UploadWizardAction.InputDisplayColumn { ColumnInfo _colInfo; @@ -66,26 +64,34 @@ public Object getValue(RenderContext ctx) } @Override - public void renderDetailsCaptionCell(RenderContext ctx, Writer out, @Nullable String cls) throws IOException + public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullable String cls) { if (null == _caption) return; - out.write(""); - renderTitle(ctx, out); - int mode = ctx.getMode(); - if (mode == DataRegion.MODE_INSERT || mode == DataRegion.MODE_UPDATE) + Writer oldWriter = out.unwrap(); + try { - if (_colInfo != null) + oldWriter.write(""); + oldWriter.write(getTitle(ctx).toString()); + 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()) - out.write(" *"); + if (_colInfo != null) + { + 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(" *"); + } } + oldWriter.write(""); + } + catch (IOException e) + { + throw new RuntimeException(e); } - out.write(""); } protected boolean isDisabledInput() @@ -94,13 +100,13 @@ protected boolean isDisabledInput() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { this.renderInputHtml(ctx, out, getValue(ctx)); } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { Set studies = StudyPublishService.get().getValidPublishTargets(ctx.getViewContext().getUser(), ReadPermission.class); @@ -119,10 +125,11 @@ public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws .selected(container.getId().equals(value)) ); } - out.write(select.toString()); - + + out.write(select); + if (disabled) - out.write(""); + out.write(new Input.InputBuilder<>().type("hidden").name(_inputName).value(HtmlString.of(value))); } @Override diff --git a/api/src/org/labkey/api/study/assay/FileLinkDisplayColumn.java b/api/src/org/labkey/api/study/assay/FileLinkDisplayColumn.java index 93cb8198b44..06a38c4e5e7 100644 --- a/api/src/org/labkey/api/study/assay/FileLinkDisplayColumn.java +++ b/api/src/org/labkey/api/study/assay/FileLinkDisplayColumn.java @@ -47,6 +47,7 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.webdav.WebdavResource; import org.labkey.api.webdav.WebdavService; +import org.labkey.api.writer.HtmlWriter; import java.io.File; import java.io.FileInputStream; @@ -360,7 +361,7 @@ protected InputStream getFileContents(RenderContext ctx, Object ignore) throws F } @Override - protected void renderIconAndFilename(RenderContext ctx, Writer out, String filename, boolean link, boolean thumbnail) throws IOException + protected void renderIconAndFilename(RenderContext ctx, HtmlWriter out, String filename, boolean link, boolean thumbnail) { Object value = getValue(ctx); String s = value == null ? null : StringUtils.trimToNull(value.toString()); diff --git a/api/src/org/labkey/api/study/query/PublishResultsQueryView.java b/api/src/org/labkey/api/study/query/PublishResultsQueryView.java index c7801a0dafd..c58469a5688 100644 --- a/api/src/org/labkey/api/study/query/PublishResultsQueryView.java +++ b/api/src/org/labkey/api/study/query/PublishResultsQueryView.java @@ -72,6 +72,7 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.view.DataView; import org.labkey.api.view.HttpView; +import org.labkey.api.writer.HtmlWriter; import org.springframework.validation.BindException; import java.io.IOException; @@ -798,7 +799,7 @@ public void addQueryColumns(Set set) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { if (_editable) { @@ -808,8 +809,8 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep if (ctx.get(RENDERED_REQUIRES_COMPLETION) == null) { // TODO: Use the same code as AutoCompleteTag.java - out.write(""); + oldWriter.write(""); ctx.put(RENDERED_REQUIRES_COMPLETION, true); } @@ -854,17 +855,17 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep // the div we will lazily wire up completions to (needs to be a sibling to the input) sb.append("
"); - out.write(sb.toString()); + oldWriter.write(sb.toString()); } else { - out.write(""); } } else { - out.write(""); } } @@ -956,7 +957,7 @@ public TimepointPreviewColumn(ParticipantIDDataInputColumn participantColumn, Vi } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object visitObject = _visitColumn.calculateValue(ctx); Object dateObject = _dateColumn.calculateValue(ctx); @@ -981,7 +982,7 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep visit = study == null ? null : study.getVisit(participantID, visitDouble, dateDate, true); - out.write(visit == null ? "" : visit.getDisplayString()); + oldWriter.write(visit == null ? "" : visit.getDisplayString()); } } diff --git a/api/src/org/labkey/api/study/query/SourceDataLinkDisplayColumn.java b/api/src/org/labkey/api/study/query/SourceDataLinkDisplayColumn.java index 6b91768212d..59d2beac785 100644 --- a/api/src/org/labkey/api/study/query/SourceDataLinkDisplayColumn.java +++ b/api/src/org/labkey/api/study/query/SourceDataLinkDisplayColumn.java @@ -24,15 +24,12 @@ import org.labkey.api.study.Dataset; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Set; /** * Serves the dual purpose of adding a hidden element for the object id and showing a link to the originating source - * User: jgarms - * Date: Dec 19, 2008 */ public class SourceDataLinkDisplayColumn extends DataInputColumn { @@ -58,7 +55,7 @@ protected Object calculateValue(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { if (null != _objectIdCol) super.renderGridCellContents(ctx, out); @@ -70,7 +67,7 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep case Assay -> { ActionURL runURL = new ActionURL(AssayDetailRedirectAction.class, ctx.getContainer()); runURL.addParameter("runId", sourceId); - out.write(PageFlowUtil.link("View Run").href(runURL).toString()); + out.write(PageFlowUtil.link("View Run").href(runURL)); } case SampleType -> { ExpObject expObject = _publishSource.resolvePublishSource(sourceId); @@ -80,7 +77,7 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep // by default the container is where the sample definition lives, use the current container instead so // the user is returned to the original folder that the link was attempted from. url.setContainer(ctx.getContainer()); - out.write(PageFlowUtil.link("View Sample Type").href(url).toString()); + out.write(PageFlowUtil.link("View Sample Type").href(url)); } } } diff --git a/api/src/org/labkey/api/study/query/ValidParticipantVisitDisplayColumn.java b/api/src/org/labkey/api/study/query/ValidParticipantVisitDisplayColumn.java index a8292420422..8301fbfe606 100644 --- a/api/src/org/labkey/api/study/query/ValidParticipantVisitDisplayColumn.java +++ b/api/src/org/labkey/api/study/query/ValidParticipantVisitDisplayColumn.java @@ -22,6 +22,7 @@ import org.labkey.api.util.HtmlString; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.Pair; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -45,7 +46,7 @@ public ValidParticipantVisitDisplayColumn(PublishResultsQueryView.ResolverHelper } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Pair matchStatus; @@ -58,13 +59,13 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep HtmlString message = matchStatus.second; if (match) { - out.write(""); - PageFlowUtil.popupHelp(message, "Match").appendTo(out); + oldWriter.write(""); + PageFlowUtil.popupHelp(message, "Match").appendTo(oldWriter); } else { - out.write(""); - PageFlowUtil.popupHelp(message, "No match").appendTo(out); + oldWriter.write(""); + PageFlowUtil.popupHelp(message, "No match").appendTo(oldWriter); } } } diff --git a/api/src/org/labkey/api/util/DOM.java b/api/src/org/labkey/api/util/DOM.java index f85ac2a446f..80b10cb01ca 100644 --- a/api/src/org/labkey/api/util/DOM.java +++ b/api/src/org/labkey/api/util/DOM.java @@ -28,8 +28,10 @@ import java.util.Objects; import java.util.Set; import java.util.TreeSet; +import java.util.function.Supplier; import java.util.stream.Stream; +import static org.labkey.api.util.DOM.Element.script; import static org.labkey.api.util.HtmlString.unsafe; import static org.labkey.api.util.PageFlowUtil.filter; @@ -524,6 +526,14 @@ public _Attributes cl(boolean test, String className) classes.add(className); return this; } + // Calculates the className only if test is true + public _Attributes cl(boolean test, Supplier classNameSupplier) + { + String className; + if (test && null != (className = classNameSupplier.get())) + classes.add(className); + return this; + } public _Attributes cl(boolean test, String trueName, String falseName) { if (test && null != trueName) @@ -626,8 +636,17 @@ public static _Attributes at(Attributes attrsIn) public static _Attributes at(Attribute firstKey, Object firstValue, Object... keyvalues) { - var ret = new _Attributes(firstKey,firstValue,keyvalues); - return ret; + return new _Attributes(firstKey,firstValue,keyvalues); + } + + public static _Attributes at(boolean test, Attribute key, Object value) + { + return new _Attributes().at(test, key, value); + } + + public static _Attributes at(boolean test, Attribute key, Object ifValue, Object elseValue) + { + return new _Attributes().at(test, key, ifValue, elseValue); } public static _Attributes cl(boolean f, String className) @@ -750,7 +769,6 @@ public static Renderable FORM(Attributes attrs, Object... body) public static Renderable ERRORS(PageContext pageContext) { - int count=0; Enumeration e = pageContext.getAttributeNamesInScope(PageContext.REQUEST_SCOPE); List list = new ArrayList<>(); while (e.hasMoreElements()) @@ -777,7 +795,7 @@ public static Renderable ERRORS(BindingResult errors) public static Renderable ERRORS(List z) { if (null == z || z.isEmpty()) - return HtmlString.unsafe(""); + return HtmlString.EMPTY_STRING; final ViewContext context = HttpView.getRootContext(); return DIV(cl("labkey-error"), z.stream().map(error -> @@ -801,11 +819,6 @@ public static Renderable ERRORS(List z) } } - @Deprecated /* use LK */ - public static class X extends LK - { - } - private static Appendable appendAttribute(Appendable html, String key, Object value) throws IOException { if (null==value) @@ -1703,11 +1716,11 @@ public static Renderable SAMP(Object... body) } public static Renderable SCRIPT(Iterable> attrs, Object... body) { - return (html) -> Element.script.render(html, attrs, body); + return (html) -> script.render(html, attrs, body); } public static Renderable SCRIPT(Object... body) { - return (html) -> Element.script.render(html, at(Attribute.type,"text/javascript", Attribute.nonce, HttpView.currentPageConfig().getScriptNonce()), body); + return (html) -> script.render(html, at(Attribute.type,"text/javascript", Attribute.nonce, HttpView.currentPageConfig().getScriptNonce()), body); } public static Renderable SECTION(Iterable> attrs, Object... body) { diff --git a/api/src/org/labkey/api/util/JavaScriptFragment.java b/api/src/org/labkey/api/util/JavaScriptFragment.java index 76e4cc4e87b..90bff8176a3 100644 --- a/api/src/org/labkey/api/util/JavaScriptFragment.java +++ b/api/src/org/labkey/api/util/JavaScriptFragment.java @@ -11,6 +11,7 @@ import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; +import java.io.IOException; import java.io.StringReader; import java.util.Collections; import java.util.Set; @@ -19,7 +20,7 @@ * Used to assert that a character sequence is valid, properly encoded JavaScript. Similar to HtmlString, though this class * is just a simple wrapper; it doesn't (yet) provide filtering, a builder, or other useful mechanisms of HtmlString. */ -public class JavaScriptFragment implements SafeToRender +public class JavaScriptFragment implements SafeToRender, DOM.Renderable { public static final JavaScriptFragment EMPTY = new JavaScriptFragment(""); public static final JavaScriptFragment EMPTY_STRING = JavaScriptFragment.unsafe("''"); @@ -141,4 +142,17 @@ public String toString() { return _s; } + + @Override + public Appendable appendTo(Appendable sb) + { + try + { + return sb.append(toString()); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } } diff --git a/api/src/org/labkey/api/util/element/CsrfInput.java b/api/src/org/labkey/api/util/element/CsrfInput.java index 80bf67e20a3..c27d20a4930 100644 --- a/api/src/org/labkey/api/util/element/CsrfInput.java +++ b/api/src/org/labkey/api/util/element/CsrfInput.java @@ -1,5 +1,6 @@ package org.labkey.api.util.element; +import jakarta.servlet.jsp.JspContext; import org.labkey.api.util.CSRFUtil; import org.labkey.api.util.HasHtmlString; import org.labkey.api.util.HtmlString; @@ -7,8 +8,6 @@ import org.labkey.api.util.element.Input.InputBuilder; import org.labkey.api.view.ViewContext; -import jakarta.servlet.jsp.JspContext; - public class CsrfInput implements HasHtmlString, SafeToRender { private final String _expectedToken; @@ -26,7 +25,7 @@ public CsrfInput(JspContext context) @Override public HtmlString getHtmlString() { - return new InputBuilder().type("hidden").name(CSRFUtil.csrfName).value(_expectedToken).getHtmlString(); + return new InputBuilder<>().type("hidden").name(CSRFUtil.csrfName).value(_expectedToken).getHtmlString(); } @Override diff --git a/api/src/org/labkey/api/view/ColorPickerDisplayColumn.java b/api/src/org/labkey/api/view/ColorPickerDisplayColumn.java index 814bd6c6c0f..be7cd445224 100644 --- a/api/src/org/labkey/api/view/ColorPickerDisplayColumn.java +++ b/api/src/org/labkey/api/view/ColorPickerDisplayColumn.java @@ -20,6 +20,7 @@ import org.labkey.api.data.RenderContext; 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; @@ -27,8 +28,6 @@ /** * {@link org.labkey.api.data.DisplayColumn} that shows an ExtJS-based color picker component for insert/update forms * and a small square of the color in grid views. - * User: jeckels - * Date: 12/23/2014 */ public class ColorPickerDisplayColumn extends DataColumn { @@ -38,25 +37,25 @@ public ColorPickerDisplayColumn(ColumnInfo col) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object value = getValue(ctx); if (value != null) { - out.write("
"); + oldWriter.write("
"); } } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException { String name = getFormFieldName(ctx); - renderHiddenFormInput(ctx, out, name, value); + renderHiddenFormInput(out, name, value); String renderId = "color-picker-div-" + UniqueID.getRequestScopedUID(ctx.getRequest()); - out.write(""); - out.write("
"); + oldWriter.write(""); + oldWriter.write("
"); } } diff --git a/api/src/org/labkey/api/view/DataView.java b/api/src/org/labkey/api/view/DataView.java index 1b837d9c6d3..e5dcf16cb7b 100644 --- a/api/src/org/labkey/api/view/DataView.java +++ b/api/src/org/labkey/api/view/DataView.java @@ -36,13 +36,13 @@ import org.labkey.api.util.ExceptionUtil; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.template.ClientDependency; +import org.labkey.api.writer.HtmlWriter; import org.springframework.dao.DataAccessException; import org.springframework.validation.Errors; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.io.Writer; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; @@ -202,13 +202,13 @@ else if (null != getRenderContext().getForm()) } - protected abstract void _renderDataRegion(RenderContext ctx, Writer out) throws IOException; + protected abstract void _renderDataRegion(RenderContext ctx, HtmlWriter out); @Override public void renderView(RenderContext model, PrintWriter out) throws IOException { - _renderDataRegion(getRenderContext(), out); + _renderDataRegion(getRenderContext(), HtmlWriter.of(out)); } public String createVerifySelectedScript(ActionURL url, String objectsDescription) diff --git a/api/src/org/labkey/api/view/DetailsView.java b/api/src/org/labkey/api/view/DetailsView.java index ab4d99efe6f..7d13105ec5a 100644 --- a/api/src/org/labkey/api/view/DetailsView.java +++ b/api/src/org/labkey/api/view/DetailsView.java @@ -24,10 +24,9 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.data.TableViewForm; import org.labkey.api.view.template.ClientDependency; +import org.labkey.api.writer.HtmlWriter; import org.springframework.validation.BindException; -import java.io.IOException; -import java.io.Writer; import java.util.LinkedHashSet; import java.util.List; @@ -63,7 +62,7 @@ protected boolean isColumnIncluded(ColumnInfo col) } @Override - protected void _renderDataRegion(RenderContext ctx, Writer out) throws IOException + protected void _renderDataRegion(RenderContext ctx, HtmlWriter out) { ctx.setMode(DataRegion.MODE_DETAILS); if (ctx.getResults() == null) diff --git a/api/src/org/labkey/api/view/GridView.java b/api/src/org/labkey/api/view/GridView.java index 718fb838743..47b074159d4 100644 --- a/api/src/org/labkey/api/view/GridView.java +++ b/api/src/org/labkey/api/view/GridView.java @@ -20,6 +20,7 @@ import org.labkey.api.data.Filter; import org.labkey.api.data.RenderContext; import org.labkey.api.data.Sort; +import org.labkey.api.writer.HtmlWriter; import org.springframework.validation.Errors; import java.io.IOException; @@ -59,7 +60,7 @@ public void setSort(Sort sort) } @Override - protected void _renderDataRegion(RenderContext ctx, Writer out) throws IOException + protected void _renderDataRegion(RenderContext ctx, HtmlWriter out) { ctx.setMode(DataRegion.MODE_GRID); //Force through bottleneck diff --git a/api/src/org/labkey/api/view/InsertView.java b/api/src/org/labkey/api/view/InsertView.java index e1005757af6..a16e1e81e6b 100644 --- a/api/src/org/labkey/api/view/InsertView.java +++ b/api/src/org/labkey/api/view/InsertView.java @@ -24,10 +24,9 @@ import org.labkey.api.exp.property.Domain; import org.labkey.api.exp.property.DomainProperty; import org.labkey.api.query.FieldKey; +import org.labkey.api.writer.HtmlWriter; import org.springframework.validation.BindException; -import java.io.IOException; -import java.io.Writer; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -91,7 +90,7 @@ public void setInitialValue(String inputName, Object value) } @Override - protected void _renderDataRegion(RenderContext ctx, Writer out) throws IOException + protected void _renderDataRegion(RenderContext ctx, HtmlWriter out) { TableInfo tableInfo = getTable(); diff --git a/api/src/org/labkey/api/view/PopupMenuView.java b/api/src/org/labkey/api/view/PopupMenuView.java index b46678db211..ce55e6fce1b 100644 --- a/api/src/org/labkey/api/view/PopupMenuView.java +++ b/api/src/org/labkey/api/view/PopupMenuView.java @@ -86,9 +86,10 @@ public boolean hasChildren() } @SneakyThrows - public static void renderTree(NavTree tree, HtmlWriter out) + public static HtmlWriter renderTree(NavTree tree, HtmlWriter out) { renderTree(tree, out.unwrap()); + return out; } public static void renderTree(NavTree tree, Writer out) throws IOException diff --git a/api/src/org/labkey/api/view/TypeAheadSelectDisplayColumn.java b/api/src/org/labkey/api/view/TypeAheadSelectDisplayColumn.java index c184db54c73..91398c2f446 100644 --- a/api/src/org/labkey/api/view/TypeAheadSelectDisplayColumn.java +++ b/api/src/org/labkey/api/view/TypeAheadSelectDisplayColumn.java @@ -24,6 +24,7 @@ import org.labkey.api.data.RenderContext; 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; @@ -46,13 +47,13 @@ public TypeAheadSelectDisplayColumn(ColumnInfo col, Integer maxRows) } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException { ForeignKey fk = getBoundColumn().getFk(); // currently only supported for lookup columns with a defined schema/query if (fk == null) { - out.write("TypeAheadSelectDisplayColumn can only be used with a lookup column."); + oldWriter.write("TypeAheadSelectDisplayColumn can only be used with a lookup column."); return; } @@ -79,11 +80,11 @@ public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws sb.append("});\n"); sb.append("\n"); sb.append("
"); - out.write(sb.toString()); + oldWriter.write(sb.toString()); // disabled inputs are not posted with the form, so we output a hidden form element: if (disabledInput) - renderHiddenFormInput(ctx, out, formFieldName, value); + renderHiddenFormInput(out, formFieldName, value); } public static class Factory implements DisplayColumnFactory diff --git a/api/src/org/labkey/api/view/UpdateView.java b/api/src/org/labkey/api/view/UpdateView.java index 947e7b019a7..6f89462c8e8 100644 --- a/api/src/org/labkey/api/view/UpdateView.java +++ b/api/src/org/labkey/api/view/UpdateView.java @@ -21,10 +21,10 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.data.TableViewForm; import org.labkey.api.util.logging.LogHelper; +import org.labkey.api.writer.HtmlWriter; import org.springframework.validation.BindException; import java.io.IOException; -import java.io.Writer; /** * Provides a view to update a single row from a {@link DataRegion} in a simple HTML form. @@ -50,7 +50,7 @@ protected boolean isColumnIncluded(ColumnInfo col) } @Override - protected void _renderDataRegion(RenderContext ctx, Writer out) throws IOException + protected void _renderDataRegion(RenderContext ctx, HtmlWriter out) { if (null != getRenderContext().getForm()) { @@ -60,7 +60,7 @@ protected void _renderDataRegion(RenderContext ctx, Writer out) throws IOExcepti else { out.write("No values to _render"); - _log.info("No values or pk specified for data region " + getDataRegion().getName()); + _log.info("No values or pk specified for data region {}", getDataRegion().getName()); } } } diff --git a/api/src/org/labkey/api/view/tabstrip.jsp b/api/src/org/labkey/api/view/tabstrip.jsp index 2617600792a..ace7929638c 100644 --- a/api/src/org/labkey/api/view/tabstrip.jsp +++ b/api/src/org/labkey/api/view/tabstrip.jsp @@ -34,7 +34,7 @@ <% for (NavTree tab : tabs) { - if (null != tab.getText() && tab.getText().length() > 0) + if (null != tab.getText() && !tab.getText().isEmpty()) { %>
  • " id="<%=h(view._prefix + "tab" + tab.getId())%>"><% diff --git a/api/src/org/labkey/api/writer/HtmlWriter.java b/api/src/org/labkey/api/writer/HtmlWriter.java index 8572af13cc0..aff5983c792 100644 --- a/api/src/org/labkey/api/writer/HtmlWriter.java +++ b/api/src/org/labkey/api/writer/HtmlWriter.java @@ -46,24 +46,52 @@ public void write(SafeToRender safeToRender) } } - public void write(Number number) throws IOException + public void write(Number number) { - _writer.write(number.toString()); + try + { + _writer.write(number.toString()); + } + catch (IOException e) + { + throw new RuntimeException(e); + } } - public void write(boolean b) throws IOException + public void write(boolean b) { - _writer.write(Boolean.toString(b)); + try + { + _writer.write(Boolean.toString(b)); + } + catch (IOException e) + { + throw new RuntimeException(e); + } } - public void write(JSONObject json) throws IOException + public void write(JSONObject json) { - _writer.write(json.toString()); + try + { + _writer.write(json.toString()); + } + catch (IOException e) + { + throw new RuntimeException(e); + } } - public void write(JSONArray array) throws IOException + public void write(JSONArray array) { - _writer.write(array.toString()); + try + { + _writer.write(array.toString()); + } + catch (IOException e) + { + throw new RuntimeException(e); + } } // Outputs an HTML encoded version of the input string diff --git a/assay/api-src/org/labkey/api/assay/AssayDataLinkDisplayColumn.java b/assay/api-src/org/labkey/api/assay/AssayDataLinkDisplayColumn.java index 6ffecc482ed..729134acb7d 100644 --- a/assay/api-src/org/labkey/api/assay/AssayDataLinkDisplayColumn.java +++ b/assay/api-src/org/labkey/api/assay/AssayDataLinkDisplayColumn.java @@ -30,6 +30,7 @@ import org.labkey.api.query.QueryService; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -57,7 +58,7 @@ public AssayDataLinkDisplayColumn(ColumnInfo colInfo, ContainerFilter containerF } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { // RunId and ProtocolId may not be available if we are in a custom query Number runId = _runIdColumnInfo == null ? null : (Number)_runIdColumnInfo.getValue(ctx); @@ -76,17 +77,17 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep { ActionURL url = PageFlowUtil.urlProvider(AssayUrls.class).getAssayResultsURL(container, protocol, _containerFilter, runId.intValue()); - out.write("" + + oldWriter.write("" + PageFlowUtil.filter(getDisplayColumn().getValue(ctx)) + ""); } else { - out.write(PageFlowUtil.filter(getDisplayColumn().getValue(ctx))); + oldWriter.write(PageFlowUtil.filter(getDisplayColumn().getValue(ctx))); } } else { - out.write(PageFlowUtil.filter(getDisplayColumn().getValue(ctx))); + oldWriter.write(PageFlowUtil.filter(getDisplayColumn().getValue(ctx))); } } 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 018c565f52e..e795e7b6b50 100644 --- a/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java +++ b/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java @@ -15,6 +15,7 @@ */ package org.labkey.api.assay.plate; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.Nullable; import org.labkey.api.assay.AssayDataCollector; @@ -42,11 +43,11 @@ import org.labkey.api.view.HttpView; import org.labkey.api.view.InsertView; import org.labkey.api.view.template.PageConfig; +import org.labkey.api.writer.HtmlWriter; import org.labkey.vfs.FileLike; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; -import jakarta.servlet.http.HttpServletRequest; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -317,8 +318,9 @@ public boolean isEditable() } @Override - public void renderDetailsCaptionCell(RenderContext ctx, Writer out, @Nullable String cls) throws IOException + public void renderDetailsCaptionCell(RenderContext ctx, HtmlWriter out, @Nullable String cls) { + if (_metadataInputFormat == SampleMetadataInputFormat.FILE_BASED) { String nounV1 = includesViruses ? "Sample/Virus" : "Sample"; @@ -328,60 +330,76 @@ public void renderDetailsCaptionCell(RenderContext ctx, Writer out, @Nullable St ". This information is used to determine data processing and to map " + nounV2.toLowerCase() + " values to plate locations."), nounV1 + " Metadata"); - out.write(""); - out.write(nounV1 + " Metadata"); - builder.appendTo(out); - out.write(" *"); + Writer oldWriter = out.unwrap(); + try + { + oldWriter.write(""); + oldWriter.write(nounV1 + " Metadata"); + builder.appendTo(oldWriter); + oldWriter.write(" *"); + } + catch (IOException e) + { + throw new RuntimeException(e); + } } } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { - if (_metadataInputFormat == SampleMetadataInputFormat.FILE_BASED) + Writer oldWriter = out.unwrap(); + try { - 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() + ". "); - PageFlowUtil.link("Download template", PageFlowUtil.urlProvider(NabUrls.class).getSampleXLSTemplateURL(_container, _protocol)).appendTo(out); - out.write("
    "); - if (reshowFile != null) + if (_metadataInputFormat == SampleMetadataInputFormat.FILE_BASED) { - PageConfig pageConfig = HttpView.currentPageConfig(); - PipeRoot pipelineRoot = PipelineService.get().findPipelineRoot(ctx.getContainer()); - String filePath = PageFlowUtil.filter(pipelineRoot.relativePath(reshowFile).replace('\\', '/')); - String updateInputFn = ""; - out.write(updateInputFn); - out.write("\n"); - out.write("\n"); - pageConfig.addHandler("optionPrevUpload", "change", "showMetadataPicker(!this.checked);"); - out.write("\n"); - out.write("\n"); - out.write("\n"); - out.write("\n"); - out.write("\n"); - pageConfig.addHandler("optionNewUpload", "change", "showMetadataPicker(this.checked);"); - out.write("\n"); - out.write("\n"); - out.write("\n"); - out.write("\n
    Use the metadata that was already uploaded to the server
    " + PageFlowUtil.filter(reshowFile.getName()) + "
    "); - out.write("\nUpload a data file
    "); - } - else - { - out.write("
    " + - "" + - "" + - "
    "); + 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("
    " + + "" + + "" + + "
    "); + } } } + catch (IOException e) + { + throw new RuntimeException(e); + } } }); } diff --git a/assay/src/org/labkey/assay/query/TypeDisplayColumn.java b/assay/src/org/labkey/assay/query/TypeDisplayColumn.java index 326f18a471d..47060d376cf 100644 --- a/assay/src/org/labkey/assay/query/TypeDisplayColumn.java +++ b/assay/src/org/labkey/assay/query/TypeDisplayColumn.java @@ -31,9 +31,8 @@ import org.labkey.api.query.FieldKey; import org.labkey.api.security.permissions.DeletePermission; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Set; /** @@ -59,7 +58,7 @@ public void addQueryFieldKeys(Set keys) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { String providerName = (String)getColumnInfo().getValue(ctx); if (providerName != null) @@ -78,25 +77,25 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep AssayProvider provider = AssayService.get().getProvider(protocol); if (provider != null) { - LOG.warn("Failed to match AssayProvider '" + provider.getName() + "' using pattern '" + provider.getProtocolPattern() + "' for LSID: " + lsid); - out.write(PageFlowUtil.filter(provider.getName())); + LOG.warn("Failed to match AssayProvider '{}' using pattern '{}' for LSID: {}", provider.getName(), provider.getProtocolPattern(), lsid); + out.write(provider.getName()); return; } else if (protocol != null) { - out.write(PageFlowUtil.filter("")); + out.write(""); // We won't be showing our normal UI that lets an admin delete the design, so let the user do it directly // from here if (protocol.getContainer().hasPermissions(ctx.getViewContext().getUser(), Set.of(DesignAssayPermission.class, DeletePermission.class))) { out.write(" "); - PageFlowUtil.link("Delete Assay Design", PageFlowUtil.urlProvider(ExperimentUrls.class).getDeleteProtocolURL(protocol, PageFlowUtil.urlProvider(AssayUrls.class).getAssayListURL(ctx.getContainer()))).appendTo(out); + out.write(PageFlowUtil.link("Delete Assay Design", PageFlowUtil.urlProvider(ExperimentUrls.class).getDeleteProtocolURL(protocol, PageFlowUtil.urlProvider(AssayUrls.class).getAssayListURL(ctx.getContainer())))); } return; } } } - out.write(PageFlowUtil.filter("")); + out.write(""); } } diff --git a/core/src/org/labkey/core/admin/AdminController.java b/core/src/org/labkey/core/admin/AdminController.java index a4f26a16c4f..8c0055f5fde 100644 --- a/core/src/org/labkey/core/admin/AdminController.java +++ b/core/src/org/labkey/core/admin/AdminController.java @@ -310,6 +310,7 @@ import org.labkey.api.wiki.WikiRendererType; import org.labkey.api.wiki.WikiRenderingService; import org.labkey.api.writer.FileSystemFile; +import org.labkey.api.writer.HtmlWriter; import org.labkey.api.writer.ZipFile; import org.labkey.api.writer.ZipUtil; import org.labkey.bootstrap.ExplodedModuleService; @@ -6855,7 +6856,7 @@ public FolderGroupColumn(Set assignmentSet, ColumnInfo col) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { String value = (String)ctx.get(getBoundColumn().getDisplayField().getFieldKey()); @@ -6873,7 +6874,7 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep delim = ",
    "; } } - out.write(sb.toString()); + oldWriter.write(sb.toString()); } } } diff --git a/core/src/org/labkey/core/admin/MenuViewFactory.java b/core/src/org/labkey/core/admin/MenuViewFactory.java index 7cca7771cbb..56e8942d18b 100644 --- a/core/src/org/labkey/core/admin/MenuViewFactory.java +++ b/core/src/org/labkey/core/admin/MenuViewFactory.java @@ -39,6 +39,7 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.view.ViewContext; import org.labkey.api.view.WebPartView; +import org.labkey.api.writer.HtmlWriter; import java.io.PrintWriter; import java.sql.ResultSet; @@ -134,7 +135,7 @@ protected String renderURLorValueURL(RenderContext renderContext) cellStrings.add(stringBuilder); StringBuilderWriter writer = new StringBuilderWriter(stringBuilder); renderContext.setRow(factory.getRowMap(rs)); - dataColumn.renderGridCellContents(renderContext, writer); + dataColumn.renderGridCellContents(renderContext, HtmlWriter.of(writer)); seenAtLeastOne = true; } diff --git a/core/src/org/labkey/core/query/ModulesTableInfo.java b/core/src/org/labkey/core/query/ModulesTableInfo.java index ef049602b16..2fed361a774 100644 --- a/core/src/org/labkey/core/query/ModulesTableInfo.java +++ b/core/src/org/labkey/core/query/ModulesTableInfo.java @@ -34,9 +34,8 @@ import org.labkey.api.query.FieldKey; import org.labkey.api.query.SimpleUserSchema; import org.labkey.api.util.StringExpressionFactory; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.List; /** @@ -263,7 +262,7 @@ public DisplayColumn createRenderer(ColumnInfo colInfo) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { Object o = getValue(ctx); diff --git a/core/src/org/labkey/core/query/PostgresStatActivityTable.java b/core/src/org/labkey/core/query/PostgresStatActivityTable.java index d6e183de28a..5097a283b94 100644 --- a/core/src/org/labkey/core/query/PostgresStatActivityTable.java +++ b/core/src/org/labkey/core/query/PostgresStatActivityTable.java @@ -32,6 +32,7 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.logging.LogHelper; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.core.admin.AdminController; import java.io.IOException; @@ -218,7 +219,7 @@ public boolean isFilterable() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Integer pid = ctx.get(getBoundColumn().getFieldKey(), Integer.class); List threads = new ArrayList<>(); @@ -235,10 +236,10 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep String separator = ""; for (Thread thread : threads) { - out.write(separator); + oldWriter.write(separator); ActionURL url = new ActionURL(AdminController.ShowThreadsAction.class, ContainerManager.getRoot()); url.setFragment(thread.getName()); - out.write(new Link.LinkBuilder(thread.getName()).href(url).target("_blank").renderToString()); + oldWriter.write(new Link.LinkBuilder(thread.getName()).href(url).target("_blank").renderToString()); separator = "\n
    "; // Check for HTTP threads and their async counterparts to tie queries to the request that spawned them @@ -249,8 +250,8 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep } if (request != null) { - out.write(separator); - out.write( PageFlowUtil.filter(request)); + oldWriter.write(separator); + oldWriter.write( PageFlowUtil.filter(request)); } } } diff --git a/core/src/org/labkey/core/query/ShortUrlTableInfo.java b/core/src/org/labkey/core/query/ShortUrlTableInfo.java index 2c3a425741a..32d361fd007 100644 --- a/core/src/org/labkey/core/query/ShortUrlTableInfo.java +++ b/core/src/org/labkey/core/query/ShortUrlTableInfo.java @@ -29,10 +29,9 @@ import org.labkey.api.view.ShortURLRecord; import org.labkey.api.view.ShortURLService; import org.labkey.api.view.template.ClientDependency; +import org.labkey.api.writer.HtmlWriter; import org.labkey.core.admin.AdminController; -import java.io.IOException; -import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -95,7 +94,7 @@ public String renderURL(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { String shortUrl = (String) getValue(ctx); Integer rowId = ctx.get(FieldKey.fromParts(ROWID_COL), Integer.class); @@ -103,10 +102,10 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep { var elementId = "copyToClipboardId" + rowId; PageFlowUtil.iconLink("fa fa-clipboard", "copy to clipboard") - .onClick("return false;") - .id(elementId) - .attributes(Collections.singletonMap("data-clipboard-text", ShortURLRecord.renderShortURL(shortUrl))) - .appendTo(out); + .onClick("return false;") + .id(elementId) + .attributes(Collections.singletonMap("data-clipboard-text", ShortURLRecord.renderShortURL(shortUrl))) + .appendTo(out); DOM.SCRIPT(HtmlString.unsafe("new Clipboard('#" + elementId + "');")).appendTo(out); } else diff --git a/core/src/org/labkey/core/query/UserAvatarDisplayColumnFactory.java b/core/src/org/labkey/core/query/UserAvatarDisplayColumnFactory.java index 7bac83b9970..74ef0961bbe 100644 --- a/core/src/org/labkey/core/query/UserAvatarDisplayColumnFactory.java +++ b/core/src/org/labkey/core/query/UserAvatarDisplayColumnFactory.java @@ -23,10 +23,15 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.security.User; import org.labkey.api.security.UserManager; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; import java.io.InputStream; -import java.io.Writer; + +import static org.labkey.api.util.DOM.Attribute.height; +import static org.labkey.api.util.DOM.Attribute.src; +import static org.labkey.api.util.DOM.Attribute.width; +import static org.labkey.api.util.DOM.IMG; +import static org.labkey.api.util.DOM.at; public class UserAvatarDisplayColumnFactory implements DisplayColumnFactory { @@ -57,27 +62,19 @@ public String renderURL(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { - String renderUrl = renderURL(ctx); - if (renderUrl != null) - { - out.write(getImageTagStr(renderUrl, 32)); - } + renderImageTag(out, ctx, 32); } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { - String renderUrl = renderURL(ctx); - if (renderUrl != null) - { - out.write(getImageTagStr(renderUrl, null)); - } + renderImageTag(out, ctx, null); } @Override - protected void renderIconAndFilename(RenderContext ctx, Writer out, String filename, @Nullable String fileIconUrl, @Nullable String popupIconUrl, boolean link, boolean thumbnail) throws IOException + protected void renderIconAndFilename(RenderContext ctx, HtmlWriter out, String filename, @Nullable String fileIconUrl, @Nullable String popupIconUrl, boolean link, boolean thumbnail) { renderDetailsCellContents(ctx, out); } @@ -95,9 +92,15 @@ protected InputStream getFileContents(RenderContext ctx, Object value) return null; } - private String getImageTagStr(String renderUrl, Integer size) + private void renderImageTag(HtmlWriter out, RenderContext ctx, Integer size) { - return ""; + String renderUrl = renderURL(ctx); + if (renderUrl != null) + { + IMG( + at(src, renderUrl).at(size != null, height, size).at(size != null, width, size) + ).appendTo(out); + } } @Nullable diff --git a/core/src/org/labkey/core/query/UsersMsgPrefTable.java b/core/src/org/labkey/core/query/UsersMsgPrefTable.java index acdd05f1a9d..3dbbed716fe 100644 --- a/core/src/org/labkey/core/query/UsersMsgPrefTable.java +++ b/core/src/org/labkey/core/query/UsersMsgPrefTable.java @@ -32,22 +32,16 @@ import org.labkey.api.security.User; import org.labkey.api.security.UserManager; import org.labkey.api.security.permissions.ReadPermission; +import org.labkey.api.util.HtmlString; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.Map; -/* - User: klum - Date: Feb 2, 2011 - Time: 1:38:38 PM - */ - /** * Table of users and their associated messaging preferences. This may not be the best place for this table - * its here because it contains all of the columns of the users table plus columns for messaging preferences. + * its here because it contains all the columns of the users table plus columns for messaging preferences. * * Only exposes folder-level user settings, not subforum subscriptions. */ @@ -171,12 +165,12 @@ public NotificationSettingColumn(ColumnInfo column) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { Object value = getValue(ctx); if (value == null) - out.write("<folder default>"); + out.write(HtmlString.unsafe("<folder default>")); else super.renderGridCellContents(ctx, out); } diff --git a/experiment/src/org/labkey/experiment/DataFileSizeDisplayColumn.java b/experiment/src/org/labkey/experiment/DataFileSizeDisplayColumn.java deleted file mode 100644 index 6d16e1d1b65..00000000000 --- a/experiment/src/org/labkey/experiment/DataFileSizeDisplayColumn.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2012-2013 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.apache.commons.io.FileUtils; -import org.labkey.api.data.RenderContext; -import org.labkey.api.data.SimpleDisplayColumn; -import org.labkey.api.exp.api.ExpData; - -import java.io.IOException; -import java.io.Writer; - -/** - * User: bbimber - * Date: 7/3/12 - * Time: 7:09 AM - */ -public class DataFileSizeDisplayColumn extends SimpleDisplayColumn -{ - private ExpData _data; - - public DataFileSizeDisplayColumn(ExpData data, String name) - { - _data = data; - setCaption(name); - } - - @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException - { - if (_data == null) - { - out.write(""); - } - else if (_data.getFile() == null || !_data.getFile().exists()) - { - out.write("File not found"); - } - else - { - long size = _data.getFile().length(); - out.write(FileUtils.byteCountToDisplaySize(size)); - } - } - -} diff --git a/experiment/src/org/labkey/experiment/DataFileURLDisplayColumn.java b/experiment/src/org/labkey/experiment/DataFileURLDisplayColumn.java index 5a58b148db2..d18d867c42d 100644 --- a/experiment/src/org/labkey/experiment/DataFileURLDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/DataFileURLDisplayColumn.java @@ -20,6 +20,7 @@ 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; @@ -31,7 +32,7 @@ */ public class DataFileURLDisplayColumn extends SimpleDisplayColumn { - private ExpData _data; + private final ExpData _data; public DataFileURLDisplayColumn(ExpData data) { @@ -41,12 +42,12 @@ public DataFileURLDisplayColumn(ExpData data) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { String dataFileURL = _data.getDataFileUrl(); - if (dataFileURL == null || dataFileURL.trim().length() == 0) + if (dataFileURL == null || dataFileURL.trim().isEmpty()) { - out.write("(Unknown)
    \n"); + oldWriter.write("(Unknown)
    \n"); return; } @@ -58,16 +59,16 @@ public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOEx if (contentURL != null) { - out.write(""); + oldWriter.write(""); } - out.write(PageFlowUtil.filter(dataFileURL)); - out.write(""); + oldWriter.write(PageFlowUtil.filter(dataFileURL)); + oldWriter.write(""); if (!_data.isFileOnDisk()) { - out.write(" (Not available on disk)\n"); + 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 aefeb6f2323..c770ce20303 100644 --- a/experiment/src/org/labkey/experiment/ExperimentRunDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/ExperimentRunDisplayColumn.java @@ -19,6 +19,7 @@ import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.exp.api.ExpRun; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; import java.io.IOException; @@ -44,16 +45,16 @@ public ExperimentRunDisplayColumn(ExpRun run, String name) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { if (_run == null) { - out.write("(Unknown)"); + oldWriter.write("(Unknown)"); } else { ActionURL url = ExperimentController.getRunGraphURL(ctx.getContainer(), _run.getRowId()); - out.write("" + _run.getName() + ""); + oldWriter.write("" + _run.getName() + ""); } } } diff --git a/experiment/src/org/labkey/experiment/LineageGraphDisplayColumn.java b/experiment/src/org/labkey/experiment/LineageGraphDisplayColumn.java index 7e321050d8d..9965240d6f7 100644 --- a/experiment/src/org/labkey/experiment/LineageGraphDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/LineageGraphDisplayColumn.java @@ -23,6 +23,7 @@ import org.labkey.api.exp.api.ExpProtocolApplication; import org.labkey.api.exp.api.ExpRun; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; import java.io.IOException; @@ -64,11 +65,11 @@ private LineageGraphDisplayColumn(String typeCode, ExpObject object, ExpRun run) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { if (_runId == null || _focus == null) { - out.write("(Unknown)"); + oldWriter.write("(Unknown)"); } else { @@ -76,7 +77,7 @@ public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOEx url.addParameter("rowId", Integer.toString(_runId)); url.addParameter("detail", "true"); url.addParameter("focus", _focus); - out.write("" + _linkText + ""); + oldWriter.write("" + _linkText + ""); } } } diff --git a/experiment/src/org/labkey/experiment/ProtocolApplicationDisplayColumn.java b/experiment/src/org/labkey/experiment/ProtocolApplicationDisplayColumn.java index 7ccdefcc556..f94f32d7c50 100644 --- a/experiment/src/org/labkey/experiment/ProtocolApplicationDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/ProtocolApplicationDisplayColumn.java @@ -19,6 +19,7 @@ import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.exp.api.ExpProtocolApplication; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; import java.io.IOException; @@ -44,16 +45,16 @@ public ProtocolApplicationDisplayColumn(ExpProtocolApplication protocolApplicati } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { if (_protocolApplication == null) { - out.write("(Unknown)"); + oldWriter.write("(Unknown)"); } else { ActionURL url = ExperimentController.getShowApplicationURL(ctx.getContainer(), _protocolApplication.getRowId()); - out.write("" + _protocolApplication.getName() + ""); + oldWriter.write("" + _protocolApplication.getName() + ""); } } } diff --git a/experiment/src/org/labkey/experiment/ProtocolDisplayColumn.java b/experiment/src/org/labkey/experiment/ProtocolDisplayColumn.java index c01f4dfb6fb..da593a22259 100644 --- a/experiment/src/org/labkey/experiment/ProtocolDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/ProtocolDisplayColumn.java @@ -19,6 +19,7 @@ import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.exp.api.ExpProtocol; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; import java.io.IOException; @@ -44,17 +45,17 @@ public ProtocolDisplayColumn(ExpProtocol protocol, String name) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { if (_protocol == null) { - out.write("(Unknown)"); + oldWriter.write("(Unknown)"); } else { ActionURL url = new ActionURL(ExperimentController.ProtocolDetailsAction.class, ctx.getContainer()); url.addParameter("rowId", Integer.toString(_protocol.getRowId())); - out.write("" + _protocol.getName() + ""); + oldWriter.write("" + _protocol.getName() + ""); } } diff --git a/experiment/src/org/labkey/experiment/SampleTypeDisplayColumn.java b/experiment/src/org/labkey/experiment/SampleTypeDisplayColumn.java index 5db419af986..6ecba386f62 100644 --- a/experiment/src/org/labkey/experiment/SampleTypeDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/SampleTypeDisplayColumn.java @@ -22,6 +22,7 @@ import org.labkey.api.exp.api.ExpSampleType; 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; @@ -42,19 +43,19 @@ public SampleTypeDisplayColumn(ExpMaterial material) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { ExpSampleType st = _material.getSampleType(); if (st == null) { - out.write("Not a member of a sample type"); + oldWriter.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())); - out.write("" + PageFlowUtil.filter(st.getName()) + ""); + oldWriter.write("" + PageFlowUtil.filter(st.getName()) + ""); } } } diff --git a/experiment/src/org/labkey/experiment/api/DataLinkColumn.java b/experiment/src/org/labkey/experiment/api/DataLinkColumn.java index 1f49d3e9563..d2c8621423a 100644 --- a/experiment/src/org/labkey/experiment/api/DataLinkColumn.java +++ b/experiment/src/org/labkey/experiment/api/DataLinkColumn.java @@ -24,6 +24,7 @@ import org.labkey.api.util.HtmlString; 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; @@ -42,13 +43,13 @@ public DataLinkColumn(ColumnInfo col) protected abstract ActionURL getURL(ExpData data); @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { ExpData data = getData(ctx); if (data != null) { - renderData(out, data); + renderData(oldWriter, data); } } diff --git a/experiment/src/org/labkey/experiment/api/ExpDataFileColumn.java b/experiment/src/org/labkey/experiment/api/ExpDataFileColumn.java index 54bf1b61d41..df8b21710e9 100644 --- a/experiment/src/org/labkey/experiment/api/ExpDataFileColumn.java +++ b/experiment/src/org/labkey/experiment/api/ExpDataFileColumn.java @@ -20,6 +20,7 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.exp.api.ExpData; import org.labkey.api.exp.api.ExperimentService; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -58,13 +59,13 @@ protected ExpData getData(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { ExpData data = getData(ctx); if (data != null) { - renderData(out, data); + renderData(oldWriter, data); } } diff --git a/experiment/src/org/labkey/experiment/api/ExpDataImpl.java b/experiment/src/org/labkey/experiment/api/ExpDataImpl.java index f8da3024e54..c69b0a3ca6d 100644 --- a/experiment/src/org/labkey/experiment/api/ExpDataImpl.java +++ b/experiment/src/org/labkey/experiment/api/ExpDataImpl.java @@ -1075,7 +1075,7 @@ public HtmlString getHiddenInputsHtml(ViewContext ctx) String dataclass = ctx.getActionURL().getParameter(PROPERTY); if (dataclass != null) { - return new InputBuilder().type("hidden").id("search-type").name(PROPERTY).value(dataclass).getHtmlString(); + return new InputBuilder<>().type("hidden").id("search-type").name(PROPERTY).value(dataclass).getHtmlString(); } return null; diff --git a/experiment/src/org/labkey/experiment/api/ExpDataTableImpl.java b/experiment/src/org/labkey/experiment/api/ExpDataTableImpl.java index c248bb01d20..e89d9cdc2b7 100644 --- a/experiment/src/org/labkey/experiment/api/ExpDataTableImpl.java +++ b/experiment/src/org/labkey/experiment/api/ExpDataTableImpl.java @@ -80,6 +80,7 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.TestContext; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.api.writer.MemoryVirtualFile; import org.labkey.api.writer.VirtualFile; import org.labkey.experiment.controllers.exp.ExperimentController; @@ -748,20 +749,20 @@ protected ActionURL getURL(ExpData data) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { ExpData data = getData(ctx); if (data != null) { if (data.isFileOnDisk()) { - PageFlowUtil.link("View File").href(ExperimentController.ExperimentUrlsImpl.get().getShowFileURL(data, true)).appendTo(out); - out.write("
    "); - PageFlowUtil.link("Download").href(ExperimentController.ExperimentUrlsImpl.get().getShowFileURL(data, false)).appendTo(out); + PageFlowUtil.link("View File").href(ExperimentController.ExperimentUrlsImpl.get().getShowFileURL(data, true)).appendTo(oldWriter); + oldWriter.write("
    "); + PageFlowUtil.link("Download").href(ExperimentController.ExperimentUrlsImpl.get().getShowFileURL(data, false)).appendTo(oldWriter); } else { - out.write("File not available"); + oldWriter.write("File not available"); } } } diff --git a/experiment/src/org/labkey/experiment/api/ExpFilesTableImpl.java b/experiment/src/org/labkey/experiment/api/ExpFilesTableImpl.java index 4995ef58759..87acc302daf 100644 --- a/experiment/src/org/labkey/experiment/api/ExpFilesTableImpl.java +++ b/experiment/src/org/labkey/experiment/api/ExpFilesTableImpl.java @@ -37,7 +37,9 @@ import org.labkey.api.security.UserPrincipal; import org.labkey.api.security.permissions.InsertPermission; import org.labkey.api.security.permissions.Permission; +import org.labkey.api.util.element.Input; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; import java.io.IOException; @@ -146,47 +148,39 @@ private MutableColumnInfo getAbsolutePathColumn() var result = wrapColumn("AbsoluteFilePath", _rootTable.getColumn("RowId")); result.setTextAlign("left"); result.setJdbcType(JdbcType.VARCHAR); - result.setDisplayColumnFactory(new DisplayColumnFactory() + result.setDisplayColumnFactory(colInfo -> new ExpDataFileColumn(colInfo) { @Override - public DisplayColumn createRenderer(ColumnInfo colInfo) + protected void renderData(Writer out, ExpData data) throws IOException { - return new ExpDataFileColumn(colInfo) - { - @Override - protected void renderData(Writer out, ExpData data) throws IOException - { - String val = ((String)getJsonValue(data)); - if (val != null) - out.write(val); - } - - @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException - { - out.write(""); - } + String val = ((String)getJsonValue(data)); + if (val != null) + out.write(val); + } - @Override - protected Object getJsonValue(ExpData data) - { - String val; - if (data == null || data.getFile() == null || !data.getFile().exists()) - val = ""; - else - { - val = data.getFile().getAbsolutePath(); - } - return val; - } + @Override + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) + { + out.write(new Input.InputBuilder<>().type("text").className("form-control").name("quf_AbsoluteFilePath").size(40)); + } - @Override - public boolean isEditable() - { - return true; - } + @Override + protected Object getJsonValue(ExpData data) + { + String val; + if (data == null || data.getFile() == null || !data.getFile().exists()) + val = ""; + else + { + val = data.getFile().getAbsolutePath(); + } + return val; + } - }; + @Override + public boolean isEditable() + { + return true; } }); result.setDescription("The absolute file path of the file record."); diff --git a/experiment/src/org/labkey/experiment/api/ExpRunTableImpl.java b/experiment/src/org/labkey/experiment/api/ExpRunTableImpl.java index 0cc05b84519..5c17686677f 100644 --- a/experiment/src/org/labkey/experiment/api/ExpRunTableImpl.java +++ b/experiment/src/org/labkey/experiment/api/ExpRunTableImpl.java @@ -70,6 +70,7 @@ import org.labkey.api.util.StringExpression; import org.labkey.api.view.ActionURL; import org.labkey.api.view.UnauthorizedException; +import org.labkey.api.writer.HtmlWriter; import org.labkey.experiment.controllers.exp.ExperimentController; import org.labkey.experiment.controllers.exp.ExperimentMembershipDisplayColumnFactory; import org.springframework.web.multipart.MultipartFile; @@ -700,7 +701,7 @@ public String getDisplayValue(RenderContext ctx) // Issue 10481: convince ExcelColumn.setSimpleType() that we are actually a string. @Override - public Class getDisplayValueClass() + public Class getDisplayValueClass() { return String.class; } @@ -722,9 +723,9 @@ public String getCssStyle(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { - out.write(buildString(ctx, true)); + oldWriter.write(buildString(ctx, true)); } @Override @@ -760,13 +761,13 @@ public boolean isSortable() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object rowId = getColumnInfo().getValue(ctx); if (rowId != null) { ActionURL graphURL = PageFlowUtil.urlProvider(ExperimentUrls.class).getRunGraphURL(ctx.getContainer(), ((Number)rowId).intValue()); - out.write(""); + oldWriter.write(""); } } } diff --git a/experiment/src/org/labkey/experiment/controllers/exp/ExperimentMembershipDisplayColumnFactory.java b/experiment/src/org/labkey/experiment/controllers/exp/ExperimentMembershipDisplayColumnFactory.java index d145be0a965..67dcdb302bd 100644 --- a/experiment/src/org/labkey/experiment/controllers/exp/ExperimentMembershipDisplayColumnFactory.java +++ b/experiment/src/org/labkey/experiment/controllers/exp/ExperimentMembershipDisplayColumnFactory.java @@ -30,6 +30,7 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; import org.labkey.api.view.HttpView; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -105,13 +106,13 @@ public void addQueryColumns(Set queryCols) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { if (!_renderedFunction) { ActionURL url = new ActionURL(ExperimentController.ToggleRunExperimentMembershipAction.class, ctx.getContainer()); - out.write(""); + oldWriter.write(""); _renderedFunction = true; } String id = HttpView.currentPageConfig().makeId("checkbox"); - out.write(""); + oldWriter.write("/>"); } private int getExpId(RenderContext ctx) diff --git a/experiment/src/org/labkey/experiment/lineage/LineageDisplayColumn.java b/experiment/src/org/labkey/experiment/lineage/LineageDisplayColumn.java index 10a68574a84..b594fc0b1de 100644 --- a/experiment/src/org/labkey/experiment/lineage/LineageDisplayColumn.java +++ b/experiment/src/org/labkey/experiment/lineage/LineageDisplayColumn.java @@ -27,8 +27,9 @@ import org.labkey.api.query.ReexecutableDataregion; import org.labkey.api.query.ReexecutableRenderContext; import org.labkey.api.query.UserSchema; +import org.labkey.api.util.HtmlString; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; import java.io.Writer; import java.sql.SQLException; import java.util.Collection; @@ -143,13 +144,13 @@ private void updateInnerContext(RenderContext outerCtx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { if (null == innerDisplayColumn) { Object v = getValue(ctx); if (null != v) - out.write("<" + filter(v) + ">"); + out.write(HtmlString.unsafe("<" + filter(v) + ">")); return; } updateInnerContext(ctx); @@ -234,12 +235,12 @@ public boolean isEditable() } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) + public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) { } @Override - public Class getDisplayValueClass() + public Class getDisplayValueClass() { if (null == innerDisplayColumn) return String.class; @@ -247,7 +248,7 @@ public Class getDisplayValueClass() } @Override - public Class getValueClass() + public Class getValueClass() { if (null == innerDisplayColumn) return String.class; diff --git a/issues/src/org/labkey/issue/IssuesController.java b/issues/src/org/labkey/issue/IssuesController.java index e360979042e..1e74c2eae6c 100644 --- a/issues/src/org/labkey/issue/IssuesController.java +++ b/issues/src/org/labkey/issue/IssuesController.java @@ -1988,7 +1988,7 @@ public HtmlString getHiddenInputsHtml(ViewContext ctx) String status = ctx.getActionURL().getParameter("status"); if (status != null) { - return new InputBuilder().type("hidden").id("search-type").name("status").value(status).getHtmlString(); + return new InputBuilder<>().type("hidden").id("search-type").name("status").value(status).getHtmlString(); } return null; diff --git a/issues/src/org/labkey/issue/model/IssuePage.java b/issues/src/org/labkey/issue/model/IssuePage.java index 5953bd957f6..5825ebc6beb 100644 --- a/issues/src/org/labkey/issue/model/IssuePage.java +++ b/issues/src/org/labkey/issue/model/IssuePage.java @@ -58,6 +58,7 @@ import org.labkey.api.util.element.Input; import org.labkey.api.view.ActionURL; import org.labkey.api.view.ViewContext; +import org.labkey.api.writer.HtmlWriter; import org.labkey.issue.CustomColumnConfiguration; import org.labkey.issue.IssuesController; import org.labkey.issue.model.IssueObject.CommentObject; @@ -76,21 +77,16 @@ import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; import static org.labkey.api.util.PageFlowUtil.filter; - -/** - * User: Karl Lum - * Date: Aug 31, 2006 - * Time: 1:07:36 PM - */ public class IssuePage implements DataRegionSelection.DataSelectionKeyForm { private final Container _c; private final User _user; + private final Map _renderContextDefaultValues = new CaseInsensitiveHashMap<>(); + private IssueObject _issue; private IssueObject _prevIssue; private Set _issueIds = Collections.emptySet(); @@ -111,7 +107,6 @@ public class IssuePage implements DataRegionSelection.DataSelectionKeyForm private IssueListDef _issueListDef; private Map _renderContextRow; - private Map _renderContextDefaultValues = new CaseInsensitiveHashMap<>(); private TableInfo _tableInfo; private int _mode = DataRegion.MODE_DETAILS; @@ -358,8 +353,8 @@ private RenderContext getRenderContext(ViewContext context, boolean readOnly) if (table != null) { List displayColumns = table.getColumns().stream() - .map(ColumnInfo::getRenderer) - .collect(Collectors.toUnmodifiableList()); + .map(ColumnInfo::getRenderer) + .toList(); List selectCols = RenderContext.getSelectColumns(displayColumns, table); SimpleFilter filter = new SimpleFilter(FieldKey.fromParts("IssueId"), _issue.getIssueId()); @@ -453,7 +448,7 @@ public HtmlString renderLabel(DomainProperty prop, ViewContext context) throws I try (Writer writer = new StringWriter()) { - dc.renderDetailsCaptionCell(renderContext, writer, "lk-form-label"); + dc.renderDetailsCaptionCell(renderContext, HtmlWriter.of(writer), "lk-form-label"); sb.append(writer); } return HtmlString.unsafe(sb.toString()); @@ -530,12 +525,12 @@ public HtmlString writeInput(String field, String value, int tabIndex) return writeInput(field, value, builder->builder.tabIndex(tabIndex)); } - public HtmlString writeInput(String field, String value, Consumer builderModifier) + public HtmlString writeInput(String field, String value, Consumer> builderModifier) { if (!isVisible(field)) return HtmlString.unsafe(filter(value, false, true)); - Input.InputBuilder builder = new Input.InputBuilder() + Input.InputBuilder builder = new Input.InputBuilder<>() .name(field) .value(value) .onChange("LABKEY.setDirty(true);return true;") diff --git a/issues/src/org/labkey/issue/query/IssuesListDefTable.java b/issues/src/org/labkey/issue/query/IssuesListDefTable.java index f1bd54df6ae..11987c828a9 100644 --- a/issues/src/org/labkey/issue/query/IssuesListDefTable.java +++ b/issues/src/org/labkey/issue/query/IssuesListDefTable.java @@ -17,8 +17,6 @@ import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.labkey.api.collections.CaseInsensitiveHashMap; @@ -52,9 +50,11 @@ import org.labkey.api.security.permissions.InsertPermission; 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.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.issue.IssuesController; import org.labkey.issue.actions.DeleteIssueListAction; import org.labkey.issue.actions.InsertIssueDefAction; @@ -69,14 +69,10 @@ import java.util.Map; import java.util.Set; -/** - * Created by klum on 4/10/16. - */ public class IssuesListDefTable extends FilteredTable { - private static final Logger LOG = LogManager.getLogger(IssuesListDefTable.class); - private final static Set _AUTOPOPULATED_COLUMN_NAMES; + static { Set autoPopulatedCols = new CaseInsensitiveHashSet(Table.AUTOPOPULATED_COLUMN_NAMES); @@ -188,24 +184,24 @@ public void addQueryFieldKeys(Set keys) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { Container c = getContainer(ctx); if (c != null) { if (c.hasPermission(getUserSchema().getUser(), ReadPermission.class)) { - out.write(""); - out.write(PageFlowUtil.filter(c.getName())); - out.write(""); + out.write(new Link.LinkBuilder(c.getName()).href(c.getStartURL(getUserSchema().getUser())).clearClasses()); } else - out.write(PageFlowUtil.filter(c.getName())); + { + out.write(c.getName()); + } } else + { super.renderGridCellContents(ctx, out); + } } }; } @@ -331,7 +327,7 @@ protected void _delete(Container c, Map row) throws InvalidKeyEx } } - public class MultiValueInputColumn extends DataColumn + public static class MultiValueInputColumn extends DataColumn { private final List> _values; @@ -342,30 +338,30 @@ public MultiValueInputColumn(ColumnInfo col, @NotNull List> } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object val) throws IOException + public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object val) throws IOException { String formFieldName = ctx.getForm().getFormFieldName(getColumnInfo()); - out.write("\n"); - if (_values.size() > 0) + if (!_values.isEmpty()) { for (Pair value : _values) { - out.write("\n"); + oldWriter.write("\n"); } } else { - out.write("\n"); } - out.write(""); + oldWriter.write(""); } } diff --git a/mothership/src/org/labkey/mothership/CreateIssueDisplayColumn.java b/mothership/src/org/labkey/mothership/CreateIssueDisplayColumn.java index bde9ff2a9cd..d78c9e14e46 100644 --- a/mothership/src/org/labkey/mothership/CreateIssueDisplayColumn.java +++ b/mothership/src/org/labkey/mothership/CreateIssueDisplayColumn.java @@ -21,6 +21,7 @@ import org.labkey.api.data.DataColumn; import org.labkey.api.data.RenderContext; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -38,14 +39,14 @@ public CreateIssueDisplayColumn(ColumnInfo column, ActionButton saveButton) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { - _saveButton.render(ctx, out); - out.write("\t"); + _saveButton.render(ctx, oldWriter); + oldWriter.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(out); + .appendTo(oldWriter); } } diff --git a/mothership/src/org/labkey/mothership/StackTraceDisplayColumn.java b/mothership/src/org/labkey/mothership/StackTraceDisplayColumn.java index 2da5e714cb0..8a2db01e953 100644 --- a/mothership/src/org/labkey/mothership/StackTraceDisplayColumn.java +++ b/mothership/src/org/labkey/mothership/StackTraceDisplayColumn.java @@ -19,24 +19,24 @@ import org.labkey.api.data.ColumnInfo; import org.labkey.api.data.DataColumn; import org.labkey.api.data.RenderContext; -import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.DOM; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.LineNumberReader; import java.io.StringReader; -import java.io.Writer; import java.util.ArrayList; import java.util.List; -/** - * User: jeckels - * Date: Apr 24, 2006 - */ +import static org.labkey.api.util.DOM.Attribute.style; +import static org.labkey.api.util.DOM.PRE; +import static org.labkey.api.util.DOM.at; + public class StackTraceDisplayColumn extends DataColumn { private static final int MAX_LINES_TO_SHOW = 10; - //Careful, a renderer without a resultset is only good for input forms + //Careful, a renderer without a ResultSet is only good for input forms public StackTraceDisplayColumn(ColumnInfo col) { super(col); @@ -44,52 +44,59 @@ public StackTraceDisplayColumn(ColumnInfo col) } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { renderContents(ctx, out, Integer.MAX_VALUE); } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, HtmlWriter out) { renderContents(ctx, out, Integer.MAX_VALUE); } - private void renderContents(RenderContext ctx, Writer out, int maxLines) throws IOException + @Override + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) + { + renderContents(ctx, out, MAX_LINES_TO_SHOW); + } + + private void renderContents(RenderContext ctx, HtmlWriter out, int maxLines) { String stackTrace = (String)getValue(ctx); - out.write("
    ");
    -        StringBuilder sb = new StringBuilder();
             LineNumberReader reader = new LineNumberReader(new StringReader(stackTrace));
             List lines = new ArrayList<>();
    -        String line;
    -        while ((line = reader.readLine()) != null)
    -        {
    -            lines.add(line);
    -        }
    -
    -        for (int i = 0; i < lines.size(); i++)
    +        try
             {
    -            if (i < maxLines)
    +            String line;
    +            while ((line = reader.readLine()) != null)
                 {
    -                sb.append(lines.get(i));
    -                sb.append("\n");
    +                lines.add(line);
                 }
             }
    -
    -        if (reader.getLineNumber() >= maxLines)
    +        catch (IOException e)
             {
    -            sb.append("... (");
    -            sb.append(reader.getLineNumber());
    -            sb.append(" lines total)");
    +            throw new RuntimeException(e);
             }
    -        out.write(PageFlowUtil.filter(sb.toString()));
    -        out.write("
    "); - } - @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException - { - renderContents(ctx, out, MAX_LINES_TO_SHOW); + PRE( + at(style, "margin: 4px 0px"), + (DOM.Renderable) ret -> { + for (int i = 0; i < lines.size(); i++) + { + if (i < maxLines) + { + out.write(lines.get(i) + "\n"); + } + } + + if (reader.getLineNumber() >= maxLines) + { + out.write("... (" + reader.getLineNumber() + " lines total)"); + } + + return ret; + } + ).appendTo(out); } } diff --git a/pipeline/src/org/labkey/pipeline/analysis/ProtocolManagementWebPart.java b/pipeline/src/org/labkey/pipeline/analysis/ProtocolManagementWebPart.java index a0da6b5695b..fa544a5c272 100644 --- a/pipeline/src/org/labkey/pipeline/analysis/ProtocolManagementWebPart.java +++ b/pipeline/src/org/labkey/pipeline/analysis/ProtocolManagementWebPart.java @@ -37,6 +37,7 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.view.GridView; import org.labkey.api.view.ViewContext; +import org.labkey.api.writer.HtmlWriter; import org.springframework.validation.BindException; import java.io.IOException; @@ -170,11 +171,11 @@ public ArchivedDisplayColumn() } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { if ((boolean)ctx.getRow().get("archived")) { - out.write(""); // html checkmark + oldWriter.write(""); // html checkmark } } } diff --git a/pipeline/src/org/labkey/pipeline/status/DescriptionDisplayColumn.java b/pipeline/src/org/labkey/pipeline/status/DescriptionDisplayColumn.java index 1bffd7e12dc..290bcec4d5b 100644 --- a/pipeline/src/org/labkey/pipeline/status/DescriptionDisplayColumn.java +++ b/pipeline/src/org/labkey/pipeline/status/DescriptionDisplayColumn.java @@ -18,6 +18,7 @@ import org.labkey.api.data.RenderContext; import org.labkey.api.data.SimpleDisplayColumn; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.writer.HtmlWriter; import java.io.File; import java.io.IOException; @@ -47,7 +48,7 @@ public DescriptionDisplayColumn(URI uriRoot) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Map cols = ctx.getRow(); String description = (String) cols.get("description"); @@ -70,6 +71,6 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep description = filePath; } - out.write(PageFlowUtil.filter(description)); + oldWriter.write(PageFlowUtil.filter(description)); } } diff --git a/pipeline/src/org/labkey/pipeline/status/FileDisplayColumn.java b/pipeline/src/org/labkey/pipeline/status/FileDisplayColumn.java index 86374699d18..e9af8481f6b 100644 --- a/pipeline/src/org/labkey/pipeline/status/FileDisplayColumn.java +++ b/pipeline/src/org/labkey/pipeline/status/FileDisplayColumn.java @@ -25,6 +25,7 @@ import org.labkey.api.util.FileUtil; 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; @@ -46,7 +47,7 @@ public FileDisplayColumn() } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { List files = null; @@ -66,7 +67,7 @@ public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOEx if (files == null || files.isEmpty()) { - out.write(" "); + oldWriter.write(" "); } else { @@ -76,21 +77,21 @@ public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOEx String fileName = file.getFileName().toString(); if (Files.isReadable(file)) { - out.write(""); - out.write(PageFlowUtil.filter(fileName)); - out.write("\n"); + oldWriter.write(""); + oldWriter.write(PageFlowUtil.filter(fileName)); + oldWriter.write("\n"); - out.write("  "); - PageFlowUtil.link("view").href(StatusController.urlShowFile(ctx.getContainer(), rowIdI.intValue(), fileName, false)).appendTo(out); - PageFlowUtil.link("download").href(StatusController.urlShowFile(ctx.getContainer(), rowIdI.intValue(), fileName, true)).appendTo(out); - out.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"); } else { - out.write(PageFlowUtil.filter(fileName)); - out.write("
    \n"); + oldWriter.write(PageFlowUtil.filter(fileName)); + oldWriter.write("
    \n"); } } } diff --git a/pipeline/src/org/labkey/pipeline/status/JobDisplayColumn.java b/pipeline/src/org/labkey/pipeline/status/JobDisplayColumn.java index 4e225a09d99..5c6351ec42f 100644 --- a/pipeline/src/org/labkey/pipeline/status/JobDisplayColumn.java +++ b/pipeline/src/org/labkey/pipeline/status/JobDisplayColumn.java @@ -19,6 +19,7 @@ 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; @@ -60,14 +61,14 @@ public boolean isVisible(RenderContext ctx) } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOException + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { if (_jobStatus == null || _jobStatus.isEmpty()) - out.write(" "); + oldWriter.write(" "); else { int rowIndex = 0; - out.write("\n" + + oldWriter.write("
    \n" + "\n" + "\n" + " \n" + @@ -76,21 +77,21 @@ public void renderDetailsCellContents(RenderContext ctx, Writer out) throws IOEx for (PipelineStatusFile sf : _jobStatus) { if (rowIndex++ % 2 == 0) - out.write(""); + oldWriter.write(""); else - out.write(""); + oldWriter.write(""); - out.write(""); - out.write(""); - out.write("\n"); + oldWriter.write(""); + oldWriter.write(""); + oldWriter.write("\n"); } - out.write("
    Status
    "); - out.write(PageFlowUtil.filter(sf.getStatus())); - out.write(""); - out.write(PageFlowUtil.filter(sf.getDescription())); - out.write("
    "); + oldWriter.write(PageFlowUtil.filter(sf.getStatus())); + oldWriter.write(""); + oldWriter.write(PageFlowUtil.filter(sf.getDescription())); + oldWriter.write("
    \n"); + oldWriter.write("\n"); } } diff --git a/pipeline/src/org/labkey/pipeline/status/StatusDataRegion.java b/pipeline/src/org/labkey/pipeline/status/StatusDataRegion.java index 2b17c8259ce..5c2e056f6e8 100644 --- a/pipeline/src/org/labkey/pipeline/status/StatusDataRegion.java +++ b/pipeline/src/org/labkey/pipeline/status/StatusDataRegion.java @@ -20,18 +20,29 @@ import org.labkey.api.data.CompareType; import org.labkey.api.data.DataRegion; import org.labkey.api.data.RenderContext; +import org.labkey.api.data.RuntimeSQLException; import org.labkey.api.data.SimpleFilter; import org.labkey.api.pipeline.PipelineJob; +import org.labkey.api.util.DOM; +import org.labkey.api.util.HtmlString; +import org.labkey.api.util.JavaScriptFragment; +import org.labkey.api.util.Link; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; -import org.labkey.api.view.HttpView; -import org.labkey.api.view.template.PageConfig; import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.sql.SQLException; +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.at; +import static org.labkey.api.util.DOM.cl; +import static org.labkey.api.util.DOM.id; + public class StatusDataRegion extends DataRegion { private final Class> _apiAction; @@ -46,18 +57,16 @@ public StatusDataRegion(Class> apiAction, ActionU _returnUrl.deleteParameter(ActionURL.Param.returnUrl); } - private void renderTab(Writer out, String text, ActionURL url, boolean selected) throws IOException + private void renderTab(HtmlWriter out, String text, ActionURL url, boolean selected) { - String selectStyle = ""; - if (selected) - selectStyle = " class=\"labkey-frame\""; - out.write("  "); - out.write(text); - out.write("  \n"); + TD( + cl(selected, "labkey-frame"), + HtmlString.NBSP, + HtmlString.NBSP, + new Link.LinkBuilder(text).href(url), + HtmlString.NBSP, + HtmlString.NBSP + ).appendTo(out); } @Override @@ -71,67 +80,76 @@ protected void renderTable(RenderContext ctx, HtmlWriter out) throws SQLExceptio String controller = SpringActionController.getControllerName(_apiAction); String action = SpringActionController.getActionName(_apiAction); - PageConfig config = HttpView.currentPageConfig(); - - Writer oldWriter = out.unwrap(); - try - { - oldWriter.write("\n"); + SCRIPT(JavaScriptFragment.unsafe( + "LABKEY.requiresExt4Sandbox(function() {\n" + + " LABKEY.requiresScript('pipeline/StatusUpdate.js', function(){\n" + + " if (!LABKEY.pipeline.statusUpdateInstance)\n" + + " LABKEY.pipeline.statusUpdateInstance = new LABKEY.pipeline.StatusUpdate(" + PageFlowUtil.jsString(controller) + "," + PageFlowUtil.jsString(action) + "," + PageFlowUtil.jsString(_returnUrl.toString()) + ");\n" + + " LABKEY.pipeline.statusUpdateInstance.start();\n" + + " });\n" + + "});\n") + ).appendTo(out); ActionURL url = StatusController.urlShowList(ctx.getContainer(), false); ActionURL urlFilter = ctx.getSortFilterURLHelper(); SimpleFilter filters = new SimpleFilter(urlFilter, getName()); - oldWriter.write(""); - oldWriter.write(""); - - String name = "StatusFiles.Status~" + CompareType.NOT_IN.getPreferredUrlKey(); - String value = PipelineJob.TaskStatus.complete.toString() + ";" + PipelineJob.TaskStatus.cancelled.toString() + ";" + PipelineJob.TaskStatus.error.toString(); - url.deleteParameters(); - url.addParameter(name, value); - boolean selected = value.equals(urlFilter.getParameter(name)) || PipelineQueryView.createCompletedFilter().equals(ctx.getBaseFilter()); - renderTab(oldWriter, "Running", url, selected); - boolean selSeen = selected; - - name = "StatusFiles.Status~eq"; - value = PipelineJob.TaskStatus.error.toString(); - url.deleteParameters(); - url.addParameter(name, value); - selected = !selSeen && value.equals(urlFilter.getParameter(name)); - renderTab(oldWriter, "Errors", url, selected); - - name = "StatusFiles.Status~eq"; - value = PipelineJob.TaskStatus.cancelled.toString(); - url.deleteParameters(); - url.addParameter(name, value); - selected = !selSeen && value.equals(urlFilter.getParameter(name)); - renderTab(oldWriter, "Cancelled", url, selected); - - selSeen = selSeen || selected; - url.deleteParameters(); - renderTab(oldWriter, "All", url, filters.getClauses().isEmpty() && !selSeen); - - oldWriter.write("
    Show:
    \n"); - oldWriter.write("
    "); - oldWriter.write("
    "); - - super.renderTable(ctx, out); - - oldWriter.write("
    "); - } - catch(IOException e) - { - throw new RuntimeException(e); - } + TABLE( + at(style, "margin-bottom:10px;"), + TR( + TD("Show:"), + (DOM.Renderable) ret -> { + String name = "StatusFiles.Status~" + CompareType.NOT_IN.getPreferredUrlKey(); + String value = PipelineJob.TaskStatus.complete + ";" + PipelineJob.TaskStatus.cancelled + ";" + PipelineJob.TaskStatus.error; + url.deleteParameters(); + url.addParameter(name, value); + boolean selected = value.equals(urlFilter.getParameter(name)) || PipelineQueryView.createCompletedFilter().equals(ctx.getBaseFilter()); + renderTab(out, "Running", url, selected); + boolean selSeen = selected; + + name = "StatusFiles.Status~eq"; + value = PipelineJob.TaskStatus.error.toString(); + url.deleteParameters(); + url.addParameter(name, value); + selected = !selSeen && value.equals(urlFilter.getParameter(name)); + renderTab(out, "Errors", url, selected); + + name = "StatusFiles.Status~eq"; + value = PipelineJob.TaskStatus.cancelled.toString(); + url.deleteParameters(); + url.addParameter(name, value); + selected = !selSeen && value.equals(urlFilter.getParameter(name)); + renderTab(out, "Cancelled", url, selected); + + selSeen = selSeen || selected; + url.deleteParameters(); + renderTab(out, "All", url, filters.getClauses().isEmpty() && !selSeen); + + return ret; + } + ) + ).appendTo(out); + + DIV( + id("statusFailureDiv"). + cl("labkey-error"). + at(style, "display: none") + ).appendTo(out); + + DIV( + id("statusRegionDiv"), + (DOM.Renderable) ret -> { + try + { + super.renderTable(ctx, out); + } + catch (SQLException e) + { + throw new RuntimeSQLException(e); + } + return ret; + } + ).appendTo(out); } } diff --git a/specimen/src/org/labkey/specimen/SpecimenCommentAuditProvider.java b/specimen/src/org/labkey/specimen/SpecimenCommentAuditProvider.java index d5a56268d0a..638d46cb849 100644 --- a/specimen/src/org/labkey/specimen/SpecimenCommentAuditProvider.java +++ b/specimen/src/org/labkey/specimen/SpecimenCommentAuditProvider.java @@ -33,6 +33,7 @@ import org.labkey.api.query.UserSchema; import org.labkey.api.util.Link; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import org.labkey.specimen.actions.SpecimenController; import java.io.IOException; @@ -125,7 +126,7 @@ public void addQueryColumns(Set columns) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object containerId = containerColumn.getValue(ctx); String globalUniqueId = (String) getValue(ctx); @@ -135,12 +136,12 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep Container container = ContainerManager.getForId(containerId.toString()); if (container == null) { - out.write(globalUniqueId); + oldWriter.write(globalUniqueId); return; } ActionURL url = SpecimenController.getCommentURL(container, globalUniqueId); - out.write(new Link.LinkBuilder(globalUniqueId).href(url).clearClasses().toString()); + oldWriter.write(new Link.LinkBuilder(globalUniqueId).href(url).clearClasses().toString()); } }; } diff --git a/specimen/src/org/labkey/specimen/actions/SpecimenController.java b/specimen/src/org/labkey/specimen/actions/SpecimenController.java index fdcecd3649c..b894b54ce0f 100644 --- a/specimen/src/org/labkey/specimen/actions/SpecimenController.java +++ b/specimen/src/org/labkey/specimen/actions/SpecimenController.java @@ -3305,7 +3305,7 @@ public AttachmentDisplayColumn(HttpServletRequest request) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Map cols = ctx.getRow(); SpecimenRequestEvent event = ObjectFactory.Registry.getFactory(SpecimenRequestEvent.class).fromMap(cols); @@ -3315,14 +3315,14 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep { for (Attachment attachment : attachments) { - out.write(""); - out.write(""); - out.write(PageFlowUtil.filter(attachment.getName())); - out.write("
    "); + oldWriter.write(""); + oldWriter.write(""); + oldWriter.write(PageFlowUtil.filter(attachment.getName())); + oldWriter.write("
    "); } } else - out.write(" "); + oldWriter.write(" "); } } diff --git a/specimen/src/org/labkey/specimen/query/SpecimenRequestDisplayColumn.java b/specimen/src/org/labkey/specimen/query/SpecimenRequestDisplayColumn.java index 531ba316634..8776891782e 100644 --- a/specimen/src/org/labkey/specimen/query/SpecimenRequestDisplayColumn.java +++ b/specimen/src/org/labkey/specimen/query/SpecimenRequestDisplayColumn.java @@ -22,6 +22,7 @@ import org.labkey.api.study.StudyUtils; import org.labkey.api.util.HtmlString; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -46,7 +47,7 @@ public SpecimenRequestDisplayColumn(SpecimenQueryView specimenQueryView, TableIn } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { String hash = (String) ctx.getRow().get("SpecimenHash"); String globalUniqueId = (String) ctx.getRow().get("GlobalUniqueId"); @@ -66,33 +67,33 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep boolean available = (!vialView && count > 0) || (vialView && StudyUtils.isFieldTrue(ctx, "Available")); boolean showCart = _showCartLinks && available; String script = null; - out.write("
    "); + oldWriter.write("
    "); if (showCart) { script = globalUniqueId == null ? "requestByHash('" + hash + "'); return false;" : "requestByGlobalUniqueId('" + globalUniqueId + "'); return false;"; - out.write(""); + oldWriter.write(""); } if (_showOneVialIndicator && count == 1) { - out.write(getVialCountHtml(ctx, "", + oldWriter.write(getVialCountHtml(ctx, "", "One Vial Available", "Only one vial of this primary specimen is available.", script)); } else if (_showZeroVialIndicator && count == 0) { - out.write(getVialCountHtml(ctx, "", + oldWriter.write(getVialCountHtml(ctx, "", "Zero Vials Available", "No vials of this primary specimen are currently available for request.", null)); } else { - out.write(getVialCountHtml(ctx, "
    " + String.valueOf(count) + "
    ", + oldWriter.write(getVialCountHtml(ctx, "
    " + String.valueOf(count) + "
    ", count + " Vials Available", count + " vials of this primary specimen are currently available for new requests.", script)); } if (showCart) - out.write("
    "); - out.write("
    "); + oldWriter.write(""); + oldWriter.write("
    "); } private String getVialCountHtml(RenderContext ctx, String cellHtml, String popupTitle, String popupBody, String requestScript) diff --git a/specimen/src/org/labkey/specimen/query/SpecimenRequestQueryView.java b/specimen/src/org/labkey/specimen/query/SpecimenRequestQueryView.java index 8384b1bb3ce..bb29e12a3f5 100644 --- a/specimen/src/org/labkey/specimen/query/SpecimenRequestQueryView.java +++ b/specimen/src/org/labkey/specimen/query/SpecimenRequestQueryView.java @@ -38,6 +38,7 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.view.NavTree; import org.labkey.api.view.ViewContext; +import org.labkey.api.writer.HtmlWriter; import org.labkey.specimen.SpecimenRequestManager; import org.labkey.specimen.SpecimenRequestStatus; import org.labkey.specimen.actions.SpecimenController.DeleteRequestAction; @@ -45,15 +46,8 @@ import org.labkey.specimen.actions.SpecimenController.SubmitRequestAction; import org.labkey.specimen.security.permissions.ManageRequestsPermission; -import java.io.IOException; -import java.io.Writer; import java.util.Set; -/** - * User: brittp - * Date: Apr 20, 2007 - * Time: 2:49:42 PM - */ public class SpecimenRequestQueryView extends BaseSpecimenQueryView { private NavTree[] _extraLinks; @@ -97,7 +91,7 @@ public void addQueryColumns(Set set) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { StringBuilder content = new StringBuilder(); // Use a div to set spacing around the buttons- otherwise they overlap the edges of their data grid cells: diff --git a/specimen/src/org/labkey/specimen/report/specimentype/TypeCohortReportFactory.java b/specimen/src/org/labkey/specimen/report/specimentype/TypeCohortReportFactory.java index bc4ca6a181d..d3e54beecf5 100644 --- a/specimen/src/org/labkey/specimen/report/specimentype/TypeCohortReportFactory.java +++ b/specimen/src/org/labkey/specimen/report/specimentype/TypeCohortReportFactory.java @@ -65,7 +65,7 @@ public List> getAdditionalFormInputHtml(User user) if (study.isAdvancedCohorts()) { CohortFilter.Type currentType = getCohortFilter() != null ? getCohortFilter().getType() : CohortFilter.Type.DATA_COLLECTION; - Input.InputBuilder input = new Input.InputBuilder() + Input.InputBuilder input = new Input.InputBuilder<>() .type("hidden") .value("0") .name(Params.cohortId.name()); diff --git a/study/api-src/org/labkey/api/study/InsertUpdateAction.java b/study/api-src/org/labkey/api/study/InsertUpdateAction.java index fc1f09ece97..def29455e7f 100644 --- a/study/api-src/org/labkey/api/study/InsertUpdateAction.java +++ b/study/api-src/org/labkey/api/study/InsertUpdateAction.java @@ -61,6 +61,7 @@ import org.labkey.api.view.UnauthorizedException; import org.labkey.api.view.UpdateView; import org.labkey.api.view.template.ClientDependency; +import org.labkey.api.writer.HtmlWriter; import org.springframework.validation.BindException; import org.springframework.validation.Errors; import org.springframework.web.servlet.ModelAndView; @@ -141,23 +142,23 @@ public ModelAndView getView(Form form, boolean reshow, BindException errors) thr cohortCol.setDisplayColumnFactory(colInfo -> new DataColumn(colInfo) { @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) throws IOException + public void renderInputHtml(RenderContext ctx, Writer oldWriter, HtmlWriter out, Object value) throws IOException { boolean disabledInput = isDisabledInput(); String formFieldName = ctx.getForm().getFormFieldName(getBoundColumn()); - out.write("\n"); if (getBoundColumn().isNullable()) - out.write("\t\n"); + oldWriter.write(PageFlowUtil.filter(cohort.getLabel())); + oldWriter.write("\n"); } - out.write(""); + oldWriter.write(""); } }); } diff --git a/study/api-src/org/labkey/api/study/MapArrayExcelWriter.java b/study/api-src/org/labkey/api/study/MapArrayExcelWriter.java index 8bfc477e685..e763e12042a 100644 --- a/study/api-src/org/labkey/api/study/MapArrayExcelWriter.java +++ b/study/api-src/org/labkey/api/study/MapArrayExcelWriter.java @@ -23,18 +23,15 @@ import org.labkey.api.data.ExcelWriter; import org.labkey.api.data.RenderContext; import org.labkey.api.reader.ColumnDescriptor; +import org.labkey.api.util.HtmlString; import org.labkey.api.view.ActionURL; +import org.labkey.api.writer.HtmlWriter; import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.Map; -/** - * User: Mark Igra - * Date: May 4, 2007 - * Time: 3:08:34 PM - */ public class MapArrayExcelWriter extends ExcelWriter { private final List> maps; @@ -62,14 +59,14 @@ public void renderGrid(RenderContext ctx, Sheet sheet, List visible public class MapArrayDisplayColumn extends DisplayColumn { - Class valueClass; + Class valueClass; - public MapArrayDisplayColumn(String name, Class valueClass) + public MapArrayDisplayColumn(String name, Class valueClass) { this(name, name, valueClass); } - public MapArrayDisplayColumn(String name, String caption, Class valueClass) + public MapArrayDisplayColumn(String name, String caption, Class valueClass) { setName(name); setCaption(caption); @@ -84,7 +81,7 @@ public Object getValue(RenderContext ctx) } @Override - public Class getValueClass() + public Class getValueClass() { return valueClass; } @@ -92,19 +89,19 @@ public Class getValueClass() //NOTE: Methods beyond here are unimplemented, just abstract in base class! @Override - public void renderGridCellContents(RenderContext ctx, Writer out) + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) { throw new UnsupportedOperationException("This is for excel only."); } @Override - public void renderDetailsCellContents(RenderContext ctx, Writer out) + public void renderDetailsCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) { throw new UnsupportedOperationException("This is for excel only."); } @Override - public void renderTitle(RenderContext ctx, Writer out) + public HtmlString getTitle(RenderContext ctx) { throw new UnsupportedOperationException("This is for excel only."); } @@ -128,13 +125,13 @@ public boolean isEditable() } @Override - public void renderFilterOnClick(RenderContext ctx, Writer out) + public String getFilterOnClick(RenderContext ctx) { throw new UnsupportedOperationException("This is for excel only."); } @Override - public void renderInputHtml(RenderContext ctx, Writer out, Object value) + public void renderInputHtml(RenderContext ctx, HtmlWriter out, Object value) { throw new UnsupportedOperationException("This is for excel only."); } @@ -176,7 +173,7 @@ public ColumnInfo getColumnInfo() } @Override - public void render(RenderContext ctx, Writer out) + public void render(RenderContext ctx, HtmlWriter out) { throw new UnsupportedOperationException("This is for excel only."); } diff --git a/study/src/org/labkey/study/controllers/StudyController.java b/study/src/org/labkey/study/controllers/StudyController.java index 97986639d3c..640a8c5c3c2 100644 --- a/study/src/org/labkey/study/controllers/StudyController.java +++ b/study/src/org/labkey/study/controllers/StudyController.java @@ -220,6 +220,7 @@ import org.labkey.api.view.WebPartView; import org.labkey.api.view.template.PageConfig; import org.labkey.api.writer.FileSystemFile; +import org.labkey.api.writer.HtmlWriter; import org.labkey.api.writer.VirtualFile; import org.labkey.study.CohortFilterFactory; import org.labkey.study.MasterPatientIndexMaintenanceTask; @@ -2836,10 +2837,10 @@ public ModelAndView getView(IdForm form, BindException errors) GridView gv = new GridView(dr, errors); DisplayColumn dc = new SimpleDisplayColumn(null) { @Override - public void renderGridCellContents(RenderContext ctx, Writer out) + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) { ActionURL url = new ActionURL(DownloadTsvAction.class, ctx.getContainer()).addParameter("id", String.valueOf(ctx.get("RowId"))); - PageFlowUtil.link("Download Data File").href(url).appendTo(out); + PageFlowUtil.link("Download Data File").href(url).appendTo(oldWriter); } }; dr.addDisplayColumn(dc); diff --git a/study/src/org/labkey/study/query/BaseStudyTable.java b/study/src/org/labkey/study/query/BaseStudyTable.java index 5b1e559a02a..c5230de9428 100644 --- a/study/src/org/labkey/study/query/BaseStudyTable.java +++ b/study/src/org/labkey/study/query/BaseStudyTable.java @@ -58,6 +58,7 @@ import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.Pair; import org.labkey.api.util.StringExpression; +import org.labkey.api.writer.HtmlWriter; import org.labkey.study.StudySchema; import org.labkey.study.model.DatasetDefinition; import org.labkey.study.model.ParticipantGroupManager; @@ -711,11 +712,11 @@ public Object getDisplayValue(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object value = getDisplayColumn().getValue(ctx); if (value instanceof String s) - out.write(s); + oldWriter.write(s); } } diff --git a/study/src/org/labkey/study/query/CohortQueryView.java b/study/src/org/labkey/study/query/CohortQueryView.java index 78e9652f664..f3317d735a3 100644 --- a/study/src/org/labkey/study/query/CohortQueryView.java +++ b/study/src/org/labkey/study/query/CohortQueryView.java @@ -29,6 +29,7 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.view.DataView; import org.labkey.api.view.ViewContext; +import org.labkey.api.writer.HtmlWriter; import org.labkey.study.controllers.CohortController; import org.labkey.study.controllers.StudyDefinitionController; import org.labkey.study.model.CohortImpl; @@ -121,7 +122,7 @@ public CohortDeleteColumn(ColumnInfo rowIdColumn, ColumnInfo folderColumn) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Integer rowId = (Integer)rowIdColumn.getValue(ctx); Container folder = ContainerManager.getForId((String) folderColumn.getValue(ctx)); @@ -136,11 +137,11 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep ActionURL actionURL = new ActionURL(CohortController.DeleteCohortAction.class, folder); actionURL.addParameter("rowId", rowId.toString()); - out.write(new LinkBuilder("delete").href(actionURL).usePost().toString()); + oldWriter.write(new LinkBuilder("delete").href(actionURL).usePost().toString()); } else { - out.write("in use"); + oldWriter.write("in use"); } } } diff --git a/study/src/org/labkey/study/query/DatasetQueryView.java b/study/src/org/labkey/study/query/DatasetQueryView.java index 813d0ecfda9..9486ac4abc7 100644 --- a/study/src/org/labkey/study/query/DatasetQueryView.java +++ b/study/src/org/labkey/study/query/DatasetQueryView.java @@ -85,6 +85,7 @@ import org.labkey.api.view.NavTree; import org.labkey.api.view.NotFoundException; import org.labkey.api.view.ViewContext; +import org.labkey.api.writer.HtmlWriter; import org.labkey.study.CohortFilterFactory; import org.labkey.study.StudySchema; import org.labkey.study.controllers.StudyController; @@ -335,7 +336,7 @@ public DatasetDetailsColumn(ColumnInfo sourceLsidCol, User user) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object lsid = ctx.get(_sourceLsidColumn.getName()); if (lsid != null) @@ -344,11 +345,11 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep { ActionURL dataURL = new ActionURL(StudyController.DatasetItemDetailsAction.class, getContainer()); dataURL.addParameter("sourceLsid", lsid.toString()); - PageFlowUtil.link("assay").href(dataURL).appendTo(out); + PageFlowUtil.link("assay").href(dataURL).appendTo(oldWriter); return; } } - out.write(" "); + oldWriter.write(" "); } @Override diff --git a/study/src/org/labkey/study/query/LocationQueryView.java b/study/src/org/labkey/study/query/LocationQueryView.java index 40031f45a97..83ac4446e37 100644 --- a/study/src/org/labkey/study/query/LocationQueryView.java +++ b/study/src/org/labkey/study/query/LocationQueryView.java @@ -32,19 +32,16 @@ import org.labkey.api.query.QueryView; import org.labkey.api.query.UserSchema; import org.labkey.api.security.permissions.AdminPermission; +import org.labkey.api.util.HtmlString; import org.labkey.api.util.StringExpression; import org.labkey.api.view.ActionURL; import org.labkey.api.view.DataView; +import org.labkey.api.writer.HtmlWriter; import org.labkey.study.controllers.StudyController; import org.springframework.validation.Errors; -import java.io.IOException; -import java.io.Writer; import java.util.List; -/** - * Created by Joe on 9/8/2014. - */ public class LocationQueryView extends QueryView { public LocationQueryView(UserSchema schema, QuerySettings settings, @Nullable Errors errors) @@ -103,13 +100,13 @@ protected void addDetailsAndUpdateColumns(List ret, TableInfo tab { var update = new UpdateColumn.Impl(urlUpdate) { @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { Container c = ContainerManager.getForId((String)ctx.get("container")); if (c.hasPermission(getUser(), AdminPermission.class)) super.renderGridCellContents(ctx, out); else - out.write(" "); + out.write(HtmlString.NBSP); } }; ret.add(0, update); diff --git a/study/src/org/labkey/study/query/SpecimenDetailTable.java b/study/src/org/labkey/study/query/SpecimenDetailTable.java index c8b08be5889..e2033cd5c28 100644 --- a/study/src/org/labkey/study/query/SpecimenDetailTable.java +++ b/study/src/org/labkey/study/query/SpecimenDetailTable.java @@ -45,6 +45,7 @@ import org.labkey.api.specimen.model.SpecimenTablesProvider; import org.labkey.api.specimen.settings.SettingsManager; import org.labkey.api.study.StudyService; +import org.labkey.api.writer.HtmlWriter; import org.labkey.study.CohortForeignKey; import org.labkey.study.StudySchema; import org.labkey.study.model.StudyManager; @@ -325,7 +326,7 @@ public Object getDisplayValue(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { Object value = getBoundColumn().getValue(ctx); if (value == null) diff --git a/study/src/org/labkey/study/query/SpecimenSummaryTable.java b/study/src/org/labkey/study/query/SpecimenSummaryTable.java index 2814b41d98f..e3beb1b3b8f 100644 --- a/study/src/org/labkey/study/query/SpecimenSummaryTable.java +++ b/study/src/org/labkey/study/query/SpecimenSummaryTable.java @@ -42,6 +42,7 @@ import org.labkey.api.specimen.settings.SettingsManager; import org.labkey.api.study.StudyService; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.writer.HtmlWriter; import java.io.IOException; import java.io.Writer; @@ -385,9 +386,9 @@ public Object getDisplayValue(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { - out.write(getDisplayText(ctx, true)); + oldWriter.write(getDisplayText(ctx, true)); } } } diff --git a/study/src/org/labkey/study/query/StudyPropertiesQueryView.java b/study/src/org/labkey/study/query/StudyPropertiesQueryView.java index 043c6420967..3d314245cdc 100644 --- a/study/src/org/labkey/study/query/StudyPropertiesQueryView.java +++ b/study/src/org/labkey/study/query/StudyPropertiesQueryView.java @@ -24,11 +24,11 @@ import org.labkey.api.view.ActionURL; import org.labkey.api.view.DataView; import org.labkey.api.view.ViewContext; +import org.labkey.api.writer.HtmlWriter; import org.labkey.study.controllers.StudyPropertiesController; import org.labkey.study.model.ExtensibleStudyEntity; import org.labkey.study.model.StudyImpl; -import java.io.IOException; import java.io.Writer; /** @@ -80,10 +80,10 @@ public EditColumn(Container container) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) { ActionURL actionURL = new ActionURL(StudyPropertiesController.UpdateAction.class, container); - PageFlowUtil.link("edit").href(actionURL).appendTo(out); + PageFlowUtil.link("edit").href(actionURL).appendTo(oldWriter); } } } diff --git a/study/src/org/labkey/study/query/StudySnapshotTable.java b/study/src/org/labkey/study/query/StudySnapshotTable.java index 6d66bc559ed..643b405ec04 100644 --- a/study/src/org/labkey/study/query/StudySnapshotTable.java +++ b/study/src/org/labkey/study/query/StudySnapshotTable.java @@ -37,6 +37,7 @@ import org.labkey.api.util.HtmlString; import org.labkey.api.util.JsonUtil; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.writer.HtmlWriter; import org.labkey.study.StudySchema; import java.io.IOException; @@ -96,12 +97,12 @@ public String renderURL(RenderContext ctx) settingsColumn.setDisplayColumnFactory(colInfo -> new DataColumn(colInfo){ @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, Writer oldWriter, HtmlWriter out) throws IOException { Object value = getValue(ctx); Object jsonValue = JsonUtil.DEFAULT_MAPPER.readValue(String.valueOf(value), Object.class); - out.write(PageFlowUtil.filter(JsonUtil.DEFAULT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(jsonValue), true, true)); + oldWriter.write(PageFlowUtil.filter(JsonUtil.DEFAULT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(jsonValue), true, true)); } }); @@ -129,9 +130,9 @@ public HtmlString getFormattedHtml(RenderContext ctx) } @Override - public void renderTitle(RenderContext ctx, Writer out) + public HtmlString getTitle(RenderContext ctx) { - // no title + return null; // no title } @Override diff --git a/wiki/src/org/labkey/wiki/query/PathDisplayColumn.java b/wiki/src/org/labkey/wiki/query/PathDisplayColumn.java index 80ef006336e..a7fe4f4de4b 100644 --- a/wiki/src/org/labkey/wiki/query/PathDisplayColumn.java +++ b/wiki/src/org/labkey/wiki/query/PathDisplayColumn.java @@ -24,17 +24,14 @@ import org.labkey.api.data.RemappingDisplayColumnFactory; import org.labkey.api.data.RenderContext; import org.labkey.api.query.FieldKey; -import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.HtmlString; +import org.labkey.api.util.Link; import org.labkey.api.util.StringExpression; +import org.labkey.api.writer.HtmlWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Map; /** - * User: kevink - * Date: 7/2/15 - * * Renders the wiki "Path" column as a set of '/' parts with links to the wiki * page for each part. Since '/' is a legal character in wiki names, we split * the "PathParts" column value using an unlikely value delimiter and use it @@ -108,7 +105,7 @@ private String[] getPathParts(RenderContext ctx) } @Override - public void renderGridCellContents(RenderContext ctx, Writer out) throws IOException + public void renderGridCellContents(RenderContext ctx, HtmlWriter out) { if (!_hasPathPartsDisplayCol) { @@ -119,14 +116,14 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep String[] parts = getPathParts(ctx); if (parts == null) { - out.write(" "); + out.write(HtmlString.NBSP); return; } StringExpression s = compileExpression(ctx.getViewContext()); if (s == null) { - out.write(" "); + out.write(HtmlString.NBSP); return; } @@ -145,15 +142,11 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep String url = s.eval(newRow); if (url != null) { - out.write(""); - out.write(PageFlowUtil.filter(part)); - out.write(""); + out.write(new Link.LinkBuilder(part).href(url).clearClasses()); } else { - out.write(PageFlowUtil.filter(part)); + out.write(part); } } }