Skip to content

Commit

Permalink
Improve Table Viz handling of Numbers (#9793)
Browse files Browse the repository at this point in the history
- Added support for NaN, Infinity and -Infinity in the Table viz.
- Simplified the logic so all the formatting in a single place in the Table viz.
- Sorted Number formatting for BigInt and < 10000.

![image](https://github.com/enso-org/enso/assets/4699705/1486eb7e-df87-4516-90d0-75fda1e9743d)

![image](https://github.com/enso-org/enso/assets/4699705/e55c0e6b-bd3c-4dcf-a65f-41f8516568a6)
  • Loading branch information
jdunkerley committed Apr 26, 2024
1 parent cb31bca commit c517930
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 23 deletions.
48 changes: 26 additions & 22 deletions app/gui2/src/components/visualizations/TableVisualization.vue
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ const selectableRowLimits = computed(() => {
})
const wasAutomaticallyAutosized = ref(false)
const numberFormat = new Intl.NumberFormat(undefined, {
style: 'decimal',
maximumFractionDigits: 12,
useGrouping: 'min2' as any,
})
function setRowLimit(newRowLimit: number) {
if (newRowLimit !== rowLimit.value) {
rowLimit.value = newRowLimit
Expand All @@ -158,12 +164,29 @@ function escapeHTML(str: string) {
}
function cellRenderer(params: ICellRendererParams) {
// Convert's the value into a display string.
if (params.value === null) return '<span style="color:grey; font-style: italic;">Nothing</span>'
else if (params.value === undefined) return ''
else if (params.value === '') return '<span style="color:grey; font-style: italic;">Empty</span>'
else if (typeof params.value === 'number')
return params.value.toLocaleString(undefined, { maximumFractionDigits: 12 })
else return escapeHTML(params.value.toString())
else if (typeof params.value === 'number') return numberFormat.format(params.value)
else if (Array.isArray(params.value)) {
const content = params.value
if (isMatrix({ json: content })) {
return `[Vector ${content.length} rows x ${content[0].length} cols]`
} else if (isObjectMatrix({ json: content })) {
return `[Table ${content.length} rows x ${Object.keys(content[0]).length} cols]`
} else {
return `[Vector ${content.length} items]`
}
} else if (typeof params.value === 'object') {
const valueType = params.value?.type
if (valueType === 'BigInt') return numberFormat.format(BigInt(params.value?.value))
else if (valueType === 'Float')
return `<span style="color:grey; font-style: italic;">${params.value?.value ?? 'Unknown'}</span>`
else if ('_display_text_' in params.value && params.value['_display_text_'])
return String(params.value['_display_text_'])
else return `{ ${valueType} Object }`
} else return escapeHTML(params.value.toString())
}
function addRowIndex(data: object[]): object[] {
Expand Down Expand Up @@ -217,25 +240,6 @@ function indexField(): ColDef {
/** Return a human-readable representation of an object. */
function toRender(content: unknown) {
if (Array.isArray(content)) {
if (isMatrix({ json: content })) {
return `[Vector ${content.length} rows x ${content[0].length} cols]`
} else if (isObjectMatrix({ json: content })) {
return `[Table ${content.length} rows x ${Object.keys(content[0]).length} cols]`
} else {
return `[Vector ${content.length} items]`
}
}
if (typeof content === 'object' && content != null) {
const type = 'type' in content ? content.type : undefined
if ('_display_text_' in content && content['_display_text_']) {
return String(content['_display_text_'])
} else {
return `{ ${type} Object }`
}
}
return content
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ prepare_visualization y max_rows=1000 =
pairs = [['_display_text_', '[Function '+x.to_text+']']]
value = JS_Object.from_pairs pairs
JS_Object.from_pairs [["json", value]]
_ : Number ->
JS_Object.from_pairs [["json", make_json_for_value x]]
_ ->
js_value = x.to_js_object
value = if js_value.is_a JS_Object . not then js_value else
Expand Down Expand Up @@ -167,7 +169,7 @@ make_json_for_value val level=0 = case val of
Nothing -> Nothing
_ : Text -> val
_ : Number ->
js_version = val.to_js_object
js_version = if val.is_finite then val.to_js_object else JS_Object.from_pairs [["type", "Float"], ["value", val.to_text]]
if js_version.is_a JS_Object . not then js_version else
pairs = [['_display_text_', val.to_display_text]] + js_version.field_names.map f-> [f, js_version.get f]
JS_Object.from_pairs pairs
Expand Down

0 comments on commit c517930

Please sign in to comment.