diff --git a/src/ui/src/core_components/content/CoreDataframe.vue b/src/ui/src/core_components/content/CoreDataframe.vue
index 89f34c426..2d613db63 100644
--- a/src/ui/src/core_components/content/CoreDataframe.vue
+++ b/src/ui/src/core_components/content/CoreDataframe.vue
@@ -87,11 +87,22 @@
:key="columnName"
class="cell"
>
- {{ row[columnName] }}
+
+
+
+ {{ row[columnName] }}
+
-
+
@@ -112,6 +123,7 @@ import { ComputedRef } from "vue";
import { onUnmounted } from "vue";
import WdsTextInput from "../../wds/WdsTextInput.vue";
import WdsControl from "../../wds/WdsControl.vue";
+import BaseMarkdown from "../base/BaseMarkdown.vue";
const description = "A component to display Pandas DataFrames.";
const defaultDataframe = `data:application/vnd.apache.arrow.file;base64,QVJST1cxAAD/////iAMAABAAAAAAAAoADgAGAAUACAAKAAAAAAEEABAAAAAAAAoADAAAAAQACAAKAAAAlAIAAAQAAAABAAAADAAAAAgADAAEAAgACAAAAGwCAAAEAAAAXwIAAHsiaW5kZXhfY29sdW1ucyI6IFsiX19pbmRleF9sZXZlbF8wX18iXSwgImNvbHVtbl9pbmRleGVzIjogW3sibmFtZSI6IG51bGwsICJmaWVsZF9uYW1lIjogbnVsbCwgInBhbmRhc190eXBlIjogInVuaWNvZGUiLCAibnVtcHlfdHlwZSI6ICJvYmplY3QiLCAibWV0YWRhdGEiOiB7ImVuY29kaW5nIjogIlVURi04In19XSwgImNvbHVtbnMiOiBbeyJuYW1lIjogImNvbF9hIiwgImZpZWxkX25hbWUiOiAiY29sX2EiLCAicGFuZGFzX3R5cGUiOiAiaW50NjQiLCAibnVtcHlfdHlwZSI6ICJpbnQ2NCIsICJtZXRhZGF0YSI6IG51bGx9LCB7Im5hbWUiOiAiY29sX2IiLCAiZmllbGRfbmFtZSI6ICJjb2xfYiIsICJwYW5kYXNfdHlwZSI6ICJpbnQ2NCIsICJudW1weV90eXBlIjogImludDY0IiwgIm1ldGFkYXRhIjogbnVsbH0sIHsibmFtZSI6IG51bGwsICJmaWVsZF9uYW1lIjogIl9faW5kZXhfbGV2ZWxfMF9fIiwgInBhbmRhc190eXBlIjogImludDY0IiwgIm51bXB5X3R5cGUiOiAiaW50NjQiLCAibWV0YWRhdGEiOiBudWxsfV0sICJjcmVhdG9yIjogeyJsaWJyYXJ5IjogInB5YXJyb3ciLCAidmVyc2lvbiI6ICIxMi4wLjAifSwgInBhbmRhc192ZXJzaW9uIjogIjEuNS4zIn0ABgAAAHBhbmRhcwAAAwAAAIgAAABEAAAABAAAAJT///8AAAECEAAAACQAAAAEAAAAAAAAABEAAABfX2luZGV4X2xldmVsXzBfXwAAAJD///8AAAABQAAAAND///8AAAECEAAAABgAAAAEAAAAAAAAAAUAAABjb2xfYgAAAMD///8AAAABQAAAABAAFAAIAAYABwAMAAAAEAAQAAAAAAABAhAAAAAgAAAABAAAAAAAAAAFAAAAY29sX2EAAAAIAAwACAAHAAgAAAAAAAABQAAAAAAAAAD/////6AAAABQAAAAAAAAADAAWAAYABQAIAAwADAAAAAADBAAYAAAAMAAAAAAAAAAAAAoAGAAMAAQACAAKAAAAfAAAABAAAAACAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAAAAAAAAAAAAAMAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAwAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAD/////AAAAABAAAAAMABQABgAIAAwAEAAMAAAAAAAEADwAAAAoAAAABAAAAAEAAACYAwAAAAAAAPAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAACgAMAAAABAAIAAoAAACUAgAABAAAAAEAAAAMAAAACAAMAAQACAAIAAAAbAIAAAQAAABfAgAAeyJpbmRleF9jb2x1bW5zIjogWyJfX2luZGV4X2xldmVsXzBfXyJdLCAiY29sdW1uX2luZGV4ZXMiOiBbeyJuYW1lIjogbnVsbCwgImZpZWxkX25hbWUiOiBudWxsLCAicGFuZGFzX3R5cGUiOiAidW5pY29kZSIsICJudW1weV90eXBlIjogIm9iamVjdCIsICJtZXRhZGF0YSI6IHsiZW5jb2RpbmciOiAiVVRGLTgifX1dLCAiY29sdW1ucyI6IFt7Im5hbWUiOiAiY29sX2EiLCAiZmllbGRfbmFtZSI6ICJjb2xfYSIsICJwYW5kYXNfdHlwZSI6ICJpbnQ2NCIsICJudW1weV90eXBlIjogImludDY0IiwgIm1ldGFkYXRhIjogbnVsbH0sIHsibmFtZSI6ICJjb2xfYiIsICJmaWVsZF9uYW1lIjogImNvbF9iIiwgInBhbmRhc190eXBlIjogImludDY0IiwgIm51bXB5X3R5cGUiOiAiaW50NjQiLCAibWV0YWRhdGEiOiBudWxsfSwgeyJuYW1lIjogbnVsbCwgImZpZWxkX25hbWUiOiAiX19pbmRleF9sZXZlbF8wX18iLCAicGFuZGFzX3R5cGUiOiAiaW50NjQiLCAibnVtcHlfdHlwZSI6ICJpbnQ2NCIsICJtZXRhZGF0YSI6IG51bGx9XSwgImNyZWF0b3IiOiB7ImxpYnJhcnkiOiAicHlhcnJvdyIsICJ2ZXJzaW9uIjogIjEyLjAuMCJ9LCAicGFuZGFzX3ZlcnNpb24iOiAiMS41LjMifQAGAAAAcGFuZGFzAAADAAAAiAAAAEQAAAAEAAAAlP///wAAAQIQAAAAJAAAAAQAAAAAAAAAEQAAAF9faW5kZXhfbGV2ZWxfMF9fAAAAkP///wAAAAFAAAAA0P///wAAAQIQAAAAGAAAAAQAAAAAAAAABQAAAGNvbF9iAAAAwP///wAAAAFAAAAAEAAUAAgABgAHAAwAAAAQABAAAAAAAAECEAAAACAAAAAEAAAAAAAAAAUAAABjb2xfYQAAAAgADAAIAAcACAAAAAAAAAFAAAAAsAMAAEFSUk9XMQ==`;
@@ -157,6 +169,16 @@ export default {
no: "no",
},
},
+ useMarkdown: {
+ name: "Use Markdown",
+ type: FieldType.Text,
+ desc: "If active, the output will be sanitized; unsafe elements will be removed.",
+ options: {
+ yes: "yes",
+ no: "no",
+ },
+ default: "no",
+ },
displayRowCount: {
name: "Display row count",
desc: "Specifies how many rows to show simultaneously.",
@@ -206,9 +228,10 @@ import type * as aq from "arquero";
import type { Table } from "apache-arrow";
/**
- * Only a certain amount of rows is rendered at a time (MAX_ROWS_RENDERED),
+ * If the table is massive, only a certain amount of rows is rendered at a time,
* to prevent filling the DOM with unnecessary rows.
*/
+const MASSIVE_ROW_COUNT = 1000;
const ROW_HEIGHT_PX = 36; // Must match CSS
const MIN_COLUMN_WIDTH_PX = 80;
const MAX_COLUMN_AUTO_WIDTH_PX = 300;
@@ -254,6 +277,7 @@ const columnCount = computed(
() => (isIndexShown.value ? 1 : 0) + shownColumnNames.value.length,
);
const rowCount = computed(() => table.value?.numRows() ?? 0);
+const isRowCountMassive = computed(() => rowCount.value > MASSIVE_ROW_COUNT);
const displayRowCount = computed(() =>
Math.min(fields.displayRowCount.value, rowCount.value),
);
@@ -273,9 +297,13 @@ const rowOffset = computed(() => {
const slicedTable = computed(() => {
if (!table.value) return null;
+ const offset = isRowCountMassive.value ? rowOffset.value : 0;
+ const limit = isRowCountMassive.value
+ ? displayRowCount.value
+ : MASSIVE_ROW_COUNT;
const data = table.value.objects({
- offset: rowOffset.value,
- limit: displayRowCount.value,
+ offset,
+ limit,
});
const indices = table.value
.indices()
@@ -401,7 +429,11 @@ async function loadData() {
function download() {
const csv = table.value.toCSV();
const el = document.createElement("a");
- el.href = "data:text/plain;base64," + window.btoa(csv);
+
+ // btoa only supports ASCII
+
+ const s = String.fromCharCode(...new TextEncoder().encode(csv));
+ el.href = "data:text/plain;base64," + window.btoa(s);
el.download = "data.csv";
el.click();
}
@@ -545,7 +577,7 @@ onUnmounted(() => {
.grid {
margin-bottom: -1px;
- position: sticky;
+ position: v-bind("isRowCountMassive ? 'sticky': 'unset'");
top: 0;
display: grid;
}
@@ -557,9 +589,10 @@ onUnmounted(() => {
color: var(--primaryTextColor);
border-bottom: 1px solid var(--separatorColor);
display: flex;
- align-items: center;
+ align-items: start;
white-space: nowrap;
font-size: 0.75rem;
+ text-overflow: ellipsis;
}
.grid.wrapText .cell {
@@ -575,6 +608,8 @@ onUnmounted(() => {
font-weight: 400;
margin-bottom: 12px;
border-bottom: none;
+ top: 0;
+ z-index: 1;
}
.grid.scrolled .cell.headerCell {
@@ -615,5 +650,6 @@ onUnmounted(() => {
position: absolute;
height: 1px;
width: 1px;
+ background: red;
}