@graphenedata/cli 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -0
- package/dist/cli/bigQuery-OQUNH3VT.js +75 -0
- package/dist/cli/bigQuery-OQUNH3VT.js.map +7 -0
- package/dist/cli/chunk-56K2FF57.js +53 -0
- package/dist/cli/chunk-56K2FF57.js.map +7 -0
- package/dist/cli/chunk-TZTTALAV.js +12868 -0
- package/dist/cli/chunk-TZTTALAV.js.map +7 -0
- package/dist/cli/cli.js +260 -11196
- package/dist/cli/clickhouse-S3BJSKND.js +65 -0
- package/dist/cli/clickhouse-S3BJSKND.js.map +7 -0
- package/dist/cli/duckdb-TKVMONRK.js +87 -0
- package/dist/cli/duckdb-TKVMONRK.js.map +7 -0
- package/dist/cli/serve2-S2LL4D4D.js +448 -0
- package/dist/cli/serve2-S2LL4D4D.js.map +7 -0
- package/dist/cli/snowflake-3VPDEYYP.js +128 -0
- package/dist/cli/snowflake-3VPDEYYP.js.map +7 -0
- package/dist/index.d.ts +63 -0
- package/dist/lang/index.d.ts +63 -0
- package/dist/skills/graphene/SKILL.md +156 -95
- package/dist/skills/graphene/references/big-value.md +6 -41
- package/dist/skills/graphene/references/date-range.md +64 -0
- package/dist/skills/graphene/references/dropdown.md +3 -4
- package/dist/skills/graphene/references/echarts.md +162 -0
- package/dist/skills/graphene/references/gsql.md +55 -25
- package/dist/skills/graphene/references/model-gsql.md +70 -0
- package/dist/skills/graphene/references/table.md +13 -14
- package/dist/skills/graphene/references/text-input.md +2 -1
- package/dist/ui/app.css +239 -340
- package/dist/ui/component-utilities/dataShaping.ts +484 -0
- package/dist/ui/component-utilities/dataSummary.ts +57 -0
- package/dist/ui/component-utilities/enrich.ts +793 -0
- package/dist/ui/component-utilities/format.ts +177 -0
- package/dist/ui/component-utilities/inputUtils.ts +44 -8
- package/dist/ui/component-utilities/theme.ts +200 -0
- package/dist/ui/component-utilities/themeStores.ts +21 -8
- package/dist/ui/component-utilities/types.ts +70 -0
- package/dist/ui/components/AreaChart.svelte +57 -105
- package/dist/ui/components/BarChart.svelte +71 -129
- package/dist/ui/components/BigValue.svelte +24 -40
- package/dist/ui/components/Column.svelte +10 -18
- package/dist/ui/components/DateRange.svelte +54 -21
- package/dist/ui/components/Dropdown.svelte +47 -26
- package/dist/ui/components/DropdownOption.svelte +1 -2
- package/dist/ui/components/ECharts.svelte +181 -67
- package/dist/ui/components/InlineDelta.svelte +50 -31
- package/dist/ui/components/LineChart.svelte +54 -125
- package/dist/ui/components/PieChart.svelte +27 -37
- package/dist/ui/components/QueryLoad.svelte +77 -45
- package/dist/ui/components/Row.svelte +2 -1
- package/dist/ui/components/ScatterPlot.svelte +52 -0
- package/dist/ui/components/Skeleton.svelte +32 -0
- package/dist/ui/components/Table.svelte +3 -2
- package/dist/ui/components/TableGroupRow.svelte +28 -36
- package/dist/ui/components/TableHarness.svelte +32 -0
- package/dist/ui/components/TableHeader.svelte +34 -59
- package/dist/ui/components/TableRow.svelte +14 -38
- package/dist/ui/components/TableSubtotalRow.svelte +18 -21
- package/dist/ui/components/TableTotalRow.svelte +27 -37
- package/dist/ui/components/TextInput.svelte +13 -12
- package/dist/ui/components/Value.svelte +25 -0
- package/dist/ui/components/_Table.svelte +72 -70
- package/dist/ui/internal/ChartGallery.svelte +527 -0
- package/dist/ui/internal/ErrorDisplay.svelte +22 -97
- package/dist/ui/internal/LocalApp.svelte +84 -19
- package/dist/ui/internal/PageNavGroup.svelte +269 -0
- package/dist/ui/internal/Sidebar.svelte +178 -0
- package/dist/ui/internal/SidebarToggle.svelte +47 -0
- package/dist/ui/internal/StyleGallery.svelte +244 -0
- package/dist/ui/internal/clientCache.ts +2 -2
- package/dist/ui/internal/pageInputs.svelte.js +292 -0
- package/dist/ui/internal/queryEngine.ts +112 -129
- package/dist/ui/internal/runSocket.ts +31 -14
- package/dist/ui/internal/sidebar.svelte.js +18 -0
- package/dist/ui/internal/telemetry.ts +51 -16
- package/dist/ui/internal/types.d.ts +7 -0
- package/dist/ui/web.js +30 -11
- package/package.json +40 -38
- package/dist/skills/graphene/references/area-chart.md +0 -95
- package/dist/skills/graphene/references/bar-chart.md +0 -112
- package/dist/skills/graphene/references/line-chart.md +0 -108
- package/dist/skills/graphene/references/pie-chart.md +0 -29
- package/dist/skills/graphene/references/value-formats.md +0 -104
- package/dist/ui/component-utilities/autoFormatting.js +0 -280
- package/dist/ui/component-utilities/builtInFormats.js +0 -481
- package/dist/ui/component-utilities/chartContext.js +0 -12
- package/dist/ui/component-utilities/chartWindowDebug.js +0 -21
- package/dist/ui/component-utilities/checkInputs.js +0 -84
- package/dist/ui/component-utilities/convert.js +0 -15
- package/dist/ui/component-utilities/dateParsing.js +0 -56
- package/dist/ui/component-utilities/dropdownContext.ts +0 -1
- package/dist/ui/component-utilities/echarts.js +0 -252
- package/dist/ui/component-utilities/echartsThemes.js +0 -443
- package/dist/ui/component-utilities/formatTitle.js +0 -24
- package/dist/ui/component-utilities/formatting.js +0 -241
- package/dist/ui/component-utilities/getColumnExtents.js +0 -79
- package/dist/ui/component-utilities/getColumnSummary.js +0 -62
- package/dist/ui/component-utilities/getCompletedData.js +0 -122
- package/dist/ui/component-utilities/getDistinctCount.js +0 -7
- package/dist/ui/component-utilities/getDistinctValues.js +0 -15
- package/dist/ui/component-utilities/getSeriesConfig.js +0 -231
- package/dist/ui/component-utilities/getSortedData.js +0 -9
- package/dist/ui/component-utilities/getStackPercentages.js +0 -45
- package/dist/ui/component-utilities/getStackedData.js +0 -19
- package/dist/ui/component-utilities/getYAxisIndex.js +0 -15
- package/dist/ui/component-utilities/globalContexts.js +0 -1
- package/dist/ui/component-utilities/helpers/getCompletedData.helpers.js +0 -119
- package/dist/ui/component-utilities/replaceNulls.js +0 -16
- package/dist/ui/component-utilities/tableUtils.ts +0 -107
- package/dist/ui/component-utilities/tidyWithTypes.js +0 -9
- package/dist/ui/components/Area.svelte +0 -214
- package/dist/ui/components/Bar.svelte +0 -347
- package/dist/ui/components/Chart.svelte +0 -995
- package/dist/ui/components/Line.svelte +0 -227
- package/dist/ui/internal/NavSidebar.svelte +0 -396
- package/dist/ui/internal/theme.ts +0 -60
- package/dist/ui/public/inter-latin-ext.woff2 +0 -0
- package/dist/ui/public/inter-latin.woff2 +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type {Snippet} from 'svelte'
|
|
3
|
+
import type {QueryResult} from '../component-utilities/types.ts'
|
|
3
4
|
import QueryLoad from './QueryLoad.svelte'
|
|
4
5
|
import TableInner from './_Table.svelte'
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
|
-
data: string
|
|
8
|
+
data: string | QueryResult
|
|
8
9
|
children?: Snippet
|
|
9
10
|
[key: string]: unknown
|
|
10
11
|
}
|
|
@@ -14,7 +15,7 @@
|
|
|
14
15
|
let spreadProps = $derived(Object.fromEntries(Object.entries(restProps).filter(([, value]) => value !== undefined)))
|
|
15
16
|
</script>
|
|
16
17
|
|
|
17
|
-
{#snippet tableContent(loaded:
|
|
18
|
+
{#snippet tableContent(loaded: QueryResult)}
|
|
18
19
|
{#if children}
|
|
19
20
|
<TableInner {...spreadProps} data={loaded} {children} />
|
|
20
21
|
{:else}
|
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
import TableCell from './TableCell.svelte'
|
|
3
3
|
import TableGroupToggle from './TableGroupToggle.svelte'
|
|
4
4
|
import InlineDelta from './InlineDelta.svelte'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {toBoolean} from '../component-utilities/
|
|
5
|
+
import {summarizeColumn, type SummaryMetric} from '../component-utilities/dataSummary.ts'
|
|
6
|
+
import {formatFromField} from '../component-utilities/format.ts'
|
|
7
|
+
import {toBoolean} from '../component-utilities/inputUtils'
|
|
8
8
|
|
|
9
9
|
interface Props {
|
|
10
10
|
groupName: string
|
|
11
11
|
currentGroupData?: any[]
|
|
12
12
|
toggled?: boolean
|
|
13
|
-
columnSummary?: any[]
|
|
14
13
|
rowNumbers?: boolean | string
|
|
15
14
|
rowColor?: string
|
|
16
15
|
subtotals?: boolean | string
|
|
@@ -20,7 +19,7 @@
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
let {
|
|
23
|
-
groupName, currentGroupData = [], toggled = true,
|
|
22
|
+
groupName, currentGroupData = [], toggled = true,
|
|
24
23
|
rowNumbers: rowNumbersProp = undefined, rowColor = undefined, subtotals: subtotalsProp = true,
|
|
25
24
|
orderedColumns = [], compact: compactProp = undefined, onToggle,
|
|
26
25
|
}: Props = $props()
|
|
@@ -29,6 +28,16 @@
|
|
|
29
28
|
let subtotals = $derived(toBoolean(subtotalsProp) ?? true)
|
|
30
29
|
let compact = $derived(toBoolean(compactProp))
|
|
31
30
|
|
|
31
|
+
const SUPPORTED_METRICS: SummaryMetric[] = ['sum', 'mean', 'median', 'min', 'max', 'count', 'countDistinct']
|
|
32
|
+
|
|
33
|
+
const getAggregateValue = (rows: Record<string, unknown>[], column: any) => {
|
|
34
|
+
let metric = column?.totalAgg as SummaryMetric | undefined
|
|
35
|
+
if (!metric && String(column?.type || '').toLowerCase() === 'number') metric = 'sum'
|
|
36
|
+
if (!metric || !SUPPORTED_METRICS.includes(metric)) return '-'
|
|
37
|
+
let summary = summarizeColumn(rows, column.field ?? {name: column.id, type: column.type}, [metric])
|
|
38
|
+
return summary[metric] ?? null
|
|
39
|
+
}
|
|
40
|
+
|
|
32
41
|
const toggleGroup = () => onToggle?.({groupName})
|
|
33
42
|
|
|
34
43
|
const handleKeydown = (event: KeyboardEvent) => {
|
|
@@ -38,12 +47,6 @@
|
|
|
38
47
|
}
|
|
39
48
|
}
|
|
40
49
|
|
|
41
|
-
const resolveFormat = (column: any, summary: any) => {
|
|
42
|
-
if (column.subtotalFmt) return getFormatObjectFromString(column.subtotalFmt)
|
|
43
|
-
if (column.totalFmt) return getFormatObjectFromString(column.totalFmt)
|
|
44
|
-
if (column.fmt) return getFormatObjectFromString(column.fmt, summary.format?.valueType)
|
|
45
|
-
return summary.format
|
|
46
|
-
}
|
|
47
50
|
</script>
|
|
48
51
|
|
|
49
52
|
<tr
|
|
@@ -63,8 +66,6 @@
|
|
|
63
66
|
{/if}
|
|
64
67
|
|
|
65
68
|
{#each orderedColumns as column, index (index)}
|
|
66
|
-
{@const summary = safeExtractColumn(column, columnSummary)}
|
|
67
|
-
{@const format = resolveFormat(column, summary)}
|
|
68
69
|
{#if index === 0}
|
|
69
70
|
{#if rowNumbers}
|
|
70
71
|
<!-- Covered by the row-number label cell -->
|
|
@@ -77,30 +78,21 @@
|
|
|
77
78
|
</TableCell>
|
|
78
79
|
{/if}
|
|
79
80
|
{:else if subtotals}
|
|
80
|
-
<TableCell class={
|
|
81
|
-
{#if
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
chip={column.chip}
|
|
94
|
-
/>
|
|
95
|
-
{:else}
|
|
96
|
-
{formatValue(
|
|
97
|
-
aggregateColumn(currentGroupData, column.id, column.totalAgg, summary.type, column.weightCol),
|
|
98
|
-
format,
|
|
99
|
-
summary.columnUnitSummary,
|
|
100
|
-
)}
|
|
101
|
-
{/if}
|
|
81
|
+
<TableCell class={column.type} {compact} align={column.align}>
|
|
82
|
+
{#if column.contentType === 'delta'}
|
|
83
|
+
<InlineDelta
|
|
84
|
+
value={getAggregateValue(currentGroupData, column)}
|
|
85
|
+
downIsGood={column.downIsGood}
|
|
86
|
+
field={column.field}
|
|
87
|
+
showValue={column.showValue}
|
|
88
|
+
showSymbol={column.deltaSymbol}
|
|
89
|
+
align={column.align}
|
|
90
|
+
neutralMin={column.neutralMin ?? 0}
|
|
91
|
+
neutralMax={column.neutralMax ?? 0}
|
|
92
|
+
chip={column.chip}
|
|
93
|
+
/>
|
|
102
94
|
{:else}
|
|
103
|
-
{column.
|
|
95
|
+
{formatFromField(column.field, getAggregateValue(currentGroupData, column))}
|
|
104
96
|
{/if}
|
|
105
97
|
</TableCell>
|
|
106
98
|
{:else}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Column from './Column.svelte'
|
|
3
|
+
import Table from './Table.svelte'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
data: any
|
|
7
|
+
tableProps?: Record<string, unknown>
|
|
8
|
+
columns?: Record<string, unknown>[]
|
|
9
|
+
width?: number | string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let {data, tableProps = {}, columns = [], width = 880}: Props = $props()
|
|
13
|
+
let wrapperWidth = $derived(typeof width === 'number' ? `${width}px` : width)
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class="table-harness" style:width={wrapperWidth}>
|
|
17
|
+
{#if columns.length > 0}
|
|
18
|
+
<Table data={data} {...tableProps}>
|
|
19
|
+
{#each columns as column, index (index)}
|
|
20
|
+
<Column {...column} />
|
|
21
|
+
{/each}
|
|
22
|
+
</Table>
|
|
23
|
+
{:else}
|
|
24
|
+
<Table data={data} {...tableProps} />
|
|
25
|
+
{/if}
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<style>
|
|
29
|
+
.table-harness {
|
|
30
|
+
max-width: 100%;
|
|
31
|
+
}
|
|
32
|
+
</style>
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import SortIcon from './SortIcon.svelte'
|
|
3
|
-
import {
|
|
4
|
-
import {toBoolean} from '../component-utilities/convert'
|
|
3
|
+
import {toBoolean} from '../component-utilities/inputUtils'
|
|
5
4
|
|
|
6
5
|
interface Props {
|
|
7
6
|
rowNumbers?: boolean | string
|
|
8
7
|
headerColor?: string
|
|
9
8
|
headerFontColor?: string
|
|
10
9
|
orderedColumns?: any[]
|
|
11
|
-
columnSummary?: any[]
|
|
12
10
|
sortable?: boolean | string
|
|
13
11
|
sortClick?: (columnId: string) => () => void
|
|
14
12
|
formatColumnTitles?: boolean | string
|
|
@@ -20,7 +18,7 @@
|
|
|
20
18
|
|
|
21
19
|
let {
|
|
22
20
|
rowNumbers: rowNumbersProp = false, headerColor = undefined, headerFontColor = undefined,
|
|
23
|
-
orderedColumns = [],
|
|
21
|
+
orderedColumns = [], sortable: sortableProp = true, sortClick = () => () => {},
|
|
24
22
|
formatColumnTitles: formatColumnTitlesProp = true, sortObj = {col: null, ascending: null},
|
|
25
23
|
wrapTitles: wrapTitlesProp = false, compact: compactProp = false, link = undefined,
|
|
26
24
|
}: Props = $props()
|
|
@@ -31,12 +29,11 @@
|
|
|
31
29
|
let wrapTitles = $derived(toBoolean(wrapTitlesProp) ?? false)
|
|
32
30
|
let compact = $derived(toBoolean(compactProp) ?? false)
|
|
33
31
|
|
|
34
|
-
const
|
|
35
|
-
if (column.align
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return 'header-title--align-start'
|
|
32
|
+
const getHeaderAlignment = (column: any) => {
|
|
33
|
+
if (column.align) return column.align
|
|
34
|
+
if (['sparkline', 'sparkbar', 'sparkarea', 'bar'].includes(column.contentType)) return 'center'
|
|
35
|
+
if (column.type === 'number') return 'right'
|
|
36
|
+
return 'left'
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
const computeGroupSpans = (columns: any[]) => {
|
|
@@ -55,10 +52,10 @@
|
|
|
55
52
|
return sortObj.ascending ? 'ascending' : 'descending'
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
const resolveHeaderTitle = (column: any
|
|
55
|
+
const resolveHeaderTitle = (column: any) => {
|
|
59
56
|
if (column.title) return column.title
|
|
60
|
-
if (formatColumnTitles) return
|
|
61
|
-
return
|
|
57
|
+
if (formatColumnTitles) return column.defaultTitle ?? column.id
|
|
58
|
+
return column.id
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
let columnsWithGroupSpan = $derived(computeGroupSpans(orderedColumns))
|
|
@@ -71,7 +68,7 @@
|
|
|
71
68
|
{#if rowNumbers}
|
|
72
69
|
<th class={`header-index ${compact ? 'header-index--compact' : ''}`} style:background-color={headerColor}></th>
|
|
73
70
|
{/if}
|
|
74
|
-
{#each columnsWithGroupSpan as column (column.id)}
|
|
71
|
+
{#each columnsWithGroupSpan as column (column.identifier ?? column.id)}
|
|
75
72
|
{#if column.colGroup && column.isNewGroup}
|
|
76
73
|
<th class="header-group" colspan={column.span}>
|
|
77
74
|
<div class="header-group__label">{column.colGroup}</div>
|
|
@@ -95,33 +92,28 @@
|
|
|
95
92
|
style:color={headerFontColor}
|
|
96
93
|
></th>
|
|
97
94
|
{/if}
|
|
98
|
-
{#each orderedColumns as column (column.id)}
|
|
99
|
-
{@const summary = safeExtractColumn(column, columnSummary)}
|
|
95
|
+
{#each orderedColumns as column (column.identifier ?? column.id)}
|
|
100
96
|
<th
|
|
101
97
|
role="columnheader"
|
|
102
|
-
class={`header-cell ${
|
|
98
|
+
class={`header-cell ${column.type ?? ''} ${compact ? 'header-cell--compact' : ''}`}
|
|
103
99
|
style:color={headerFontColor}
|
|
104
100
|
style:background={headerColor}
|
|
105
|
-
style:text-align={
|
|
101
|
+
style:text-align={getHeaderAlignment(column)}
|
|
106
102
|
style:cursor={sortable ? 'pointer' : 'auto'}
|
|
107
103
|
onclick={sortable ? sortClick(column.id) : undefined}
|
|
108
104
|
aria-sort={getAriaSortValue(column.id)}
|
|
109
105
|
>
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
{
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
106
|
+
<span class={`header-title__text ${wrapTitles || column.wrapTitle ? 'header-title__text--wrap' : ''}`}>
|
|
107
|
+
{resolveHeaderTitle(column)}
|
|
108
|
+
{#if column.description}
|
|
109
|
+
<span class="header-title__info" title={column.description}>ⓘ</span>
|
|
110
|
+
{/if}
|
|
111
|
+
</span>
|
|
112
|
+
{#if sortObj.col === column.id}
|
|
117
113
|
<span class="header-sort-indicator">
|
|
118
|
-
{
|
|
119
|
-
<SortIcon ascending={sortObj.ascending ?? undefined} />
|
|
120
|
-
{:else}
|
|
121
|
-
<span class="header-sort-placeholder"><SortIcon ascending /></span>
|
|
122
|
-
{/if}
|
|
114
|
+
<SortIcon ascending={sortObj.ascending ?? undefined} />
|
|
123
115
|
</span>
|
|
124
|
-
|
|
116
|
+
{/if}
|
|
125
117
|
</th>
|
|
126
118
|
{/each}
|
|
127
119
|
{#if link}
|
|
@@ -178,40 +170,24 @@
|
|
|
178
170
|
}
|
|
179
171
|
|
|
180
172
|
.header-cell {
|
|
173
|
+
position: relative;
|
|
181
174
|
padding: 2px 13px 2px 6px;
|
|
182
175
|
vertical-align: bottom;
|
|
183
176
|
}
|
|
184
177
|
|
|
185
|
-
.header-cell
|
|
186
|
-
padding:
|
|
187
|
-
font-size: 12px;
|
|
178
|
+
.header-cell:first-child {
|
|
179
|
+
padding-left: 3px;
|
|
188
180
|
}
|
|
189
181
|
|
|
190
|
-
.header-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
justify-content: space-between;
|
|
194
|
-
gap: 4px;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.header-title--wrap {
|
|
198
|
-
align-items: stretch;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.header-title--align-end {
|
|
202
|
-
justify-content: flex-end;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
.header-title--align-center {
|
|
206
|
-
justify-content: center;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
.header-title--align-start {
|
|
210
|
-
justify-content: flex-start;
|
|
182
|
+
.header-cell--compact {
|
|
183
|
+
padding: 1px 16.5px 1px 1px;
|
|
184
|
+
font-size: 12px;
|
|
211
185
|
}
|
|
212
186
|
|
|
213
187
|
.header-title__text {
|
|
214
188
|
display: inline-block;
|
|
189
|
+
max-width: 100%;
|
|
190
|
+
text-align: inherit;
|
|
215
191
|
letter-spacing: -0.015em;
|
|
216
192
|
}
|
|
217
193
|
|
|
@@ -227,14 +203,13 @@
|
|
|
227
203
|
}
|
|
228
204
|
|
|
229
205
|
.header-sort-indicator {
|
|
206
|
+
position: absolute;
|
|
207
|
+
right: 1px;
|
|
208
|
+
bottom: 4px;
|
|
230
209
|
display: inline-flex;
|
|
231
210
|
align-items: center;
|
|
232
211
|
}
|
|
233
212
|
|
|
234
|
-
.header-sort-placeholder {
|
|
235
|
-
visibility: hidden;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
213
|
.header-link-cell {
|
|
239
214
|
width: 24px;
|
|
240
215
|
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
import chroma from 'chroma-js'
|
|
3
3
|
import InlineDelta from './InlineDelta.svelte'
|
|
4
4
|
import TableCell from './TableCell.svelte'
|
|
5
|
-
import {
|
|
6
|
-
import {formatValue, getFormatObjectFromString} from '../component-utilities/formatting.js'
|
|
5
|
+
import {formatFromField} from '../component-utilities/format.ts'
|
|
7
6
|
import {getThemeStores} from '../component-utilities/themeStores'
|
|
8
7
|
|
|
9
8
|
interface Props {
|
|
@@ -13,7 +12,7 @@
|
|
|
13
12
|
rowNumbers?: boolean | string
|
|
14
13
|
rowLines?: boolean | string
|
|
15
14
|
index?: number
|
|
16
|
-
|
|
15
|
+
columnLookup?: Record<string, any>
|
|
17
16
|
grouped?: boolean
|
|
18
17
|
groupType?: 'accordion' | 'section'
|
|
19
18
|
groupColumn?: string
|
|
@@ -26,7 +25,7 @@
|
|
|
26
25
|
let {
|
|
27
26
|
displayedData = [], rowShading: rowShadingProp = undefined, link = undefined,
|
|
28
27
|
rowNumbers: rowNumbersProp = undefined, rowLines: rowLinesProp = undefined, index = 0,
|
|
29
|
-
|
|
28
|
+
columnLookup = {}, grouped = false, groupType = undefined, groupColumn = undefined,
|
|
30
29
|
rowSpan = 1, groupNamePosition = 'middle', orderedColumns = [], compact: compactProp = undefined,
|
|
31
30
|
}: Props = $props()
|
|
32
31
|
|
|
@@ -124,10 +123,9 @@
|
|
|
124
123
|
{/if}
|
|
125
124
|
|
|
126
125
|
{#each orderedColumns as column, k (k)}
|
|
127
|
-
{@const
|
|
128
|
-
{@const
|
|
129
|
-
{@const
|
|
130
|
-
{@const columnMax = column.colorMax ?? scaleSummary?.columnUnitSummary?.max}
|
|
126
|
+
{@const scaleSummary = column.scaleColumn ? columnLookup[column.scaleColumn] : column}
|
|
127
|
+
{@const columnMin = column.colorMin ?? scaleSummary?.stats?.min}
|
|
128
|
+
{@const columnMax = column.colorMax ?? scaleSummary?.stats?.max}
|
|
131
129
|
{@const colorScale = column.contentType === 'colorscale'
|
|
132
130
|
? computeColorScale(column, columnMin, columnMax)
|
|
133
131
|
: undefined}
|
|
@@ -145,21 +143,15 @@
|
|
|
145
143
|
if (contentContrast < backgroundContrast) return $theme.colors['base-100']
|
|
146
144
|
return $theme.colors['base-content']
|
|
147
145
|
})()}
|
|
148
|
-
{@const columnFormat = (() => {
|
|
149
|
-
if (column.fmt) return getFormatObjectFromString(column.fmt, summary.format?.valueType)
|
|
150
|
-
if (column.fmtColumn && row[column.fmtColumn]) {
|
|
151
|
-
return getFormatObjectFromString(row[column.fmtColumn], summary.format?.valueType)
|
|
152
|
-
}
|
|
153
|
-
return summary.format
|
|
154
|
-
})()}
|
|
155
146
|
{@const paddingLeft = k === 0 && grouped && groupType === 'accordion' && !rowNumbers ? '28px' : undefined}
|
|
156
|
-
{@const shouldShow = !(groupType === 'section' && groupColumn ===
|
|
147
|
+
{@const shouldShow = !(groupType === 'section' && groupColumn === column.id && i !== 0)}
|
|
157
148
|
<TableCell
|
|
158
|
-
class={
|
|
149
|
+
class={column?.type}
|
|
159
150
|
{compact}
|
|
160
151
|
verticalAlign={groupType === 'section' ? groupNamePosition : undefined}
|
|
161
|
-
rowSpan={groupType === 'section' && groupColumn ===
|
|
152
|
+
rowSpan={groupType === 'section' && groupColumn === column.id && i === 0 ? rowSpan : 1}
|
|
162
153
|
{paddingLeft}
|
|
154
|
+
align={column.align}
|
|
163
155
|
wrap={column.wrap}
|
|
164
156
|
cellColor={formattedColor}
|
|
165
157
|
fontColor={fontColor}
|
|
@@ -185,21 +177,12 @@
|
|
|
185
177
|
>
|
|
186
178
|
{#if column.linkLabel != undefined}
|
|
187
179
|
{#if row[column.linkLabel] != undefined}
|
|
188
|
-
{
|
|
189
|
-
{formatValue(
|
|
190
|
-
row[column.linkLabel],
|
|
191
|
-
column.fmt ? getFormatObjectFromString(column.fmt, labelSummary.format?.valueType) : labelSummary.format,
|
|
192
|
-
labelSummary.columnUnitSummary,
|
|
193
|
-
)}
|
|
180
|
+
{formatFromField(columnLookup[column.linkLabel]?.field, row[column.linkLabel])}
|
|
194
181
|
{:else}
|
|
195
182
|
{column.linkLabel}
|
|
196
183
|
{/if}
|
|
197
184
|
{:else}
|
|
198
|
-
{
|
|
199
|
-
row[column.id],
|
|
200
|
-
column.fmt ? getFormatObjectFromString(column.fmt, summary.format?.valueType) : summary.format,
|
|
201
|
-
summary.columnUnitSummary,
|
|
202
|
-
)}
|
|
185
|
+
{formatFromField(column.field, row[column.id])}
|
|
203
186
|
{/if}
|
|
204
187
|
</a>
|
|
205
188
|
{/if}
|
|
@@ -207,8 +190,7 @@
|
|
|
207
190
|
<InlineDelta
|
|
208
191
|
value={row[column.id]}
|
|
209
192
|
downIsGood={column.downIsGood}
|
|
210
|
-
|
|
211
|
-
columnUnitSummary={summary.columnUnitSummary}
|
|
193
|
+
field={column.field}
|
|
212
194
|
showValue={column.showValue}
|
|
213
195
|
showSymbol={column.deltaSymbol}
|
|
214
196
|
align={column.align}
|
|
@@ -217,13 +199,7 @@
|
|
|
217
199
|
chip={column.chip}
|
|
218
200
|
/>
|
|
219
201
|
{:else}
|
|
220
|
-
{
|
|
221
|
-
–
|
|
222
|
-
{:else if summary.type === 'number'}
|
|
223
|
-
{formatValue(row[column.id], columnFormat, summary.columnUnitSummary)}
|
|
224
|
-
{:else}
|
|
225
|
-
{formatValue(row[column.id], columnFormat, summary.columnUnitSummary)}
|
|
226
|
-
{/if}
|
|
202
|
+
{formatFromField(column.field, row[column.id])}
|
|
227
203
|
{/if}
|
|
228
204
|
</TableCell>
|
|
229
205
|
{/each}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import InlineDelta from './InlineDelta.svelte'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import {summarizeColumn, type SummaryMetric} from '../component-utilities/dataSummary.ts'
|
|
4
|
+
import {formatFromField} from '../component-utilities/format.ts'
|
|
5
5
|
import TableCell from './TableCell.svelte'
|
|
6
|
-
import {toBoolean} from '../component-utilities/
|
|
6
|
+
import {toBoolean} from '../component-utilities/inputUtils'
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
9
9
|
groupName?: string
|
|
10
10
|
currentGroupData?: any[]
|
|
11
|
-
columnSummary?: any[]
|
|
12
11
|
rowColor?: string
|
|
13
12
|
groupBy?: string
|
|
14
13
|
groupType?: 'accordion' | 'section'
|
|
@@ -19,12 +18,22 @@
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
let {
|
|
22
|
-
groupName = undefined, currentGroupData = [],
|
|
21
|
+
groupName = undefined, currentGroupData = [], rowColor = undefined,
|
|
23
22
|
groupBy = undefined, groupType = undefined, rowNumbers: rowNumbersProp = undefined,
|
|
24
23
|
fontColor = undefined, orderedColumns = [], compact = undefined,
|
|
25
24
|
}: Props = $props()
|
|
26
25
|
|
|
27
26
|
let rowNumbers = $derived(toBoolean(rowNumbersProp) ?? false)
|
|
27
|
+
|
|
28
|
+
const SUPPORTED_METRICS: SummaryMetric[] = ['sum', 'mean', 'median', 'min', 'max', 'count', 'countDistinct']
|
|
29
|
+
|
|
30
|
+
const getAggregateValue = (rows: Record<string, unknown>[], column: any) => {
|
|
31
|
+
let metric = column?.totalAgg as SummaryMetric | undefined
|
|
32
|
+
if (!metric && String(column?.type || '').toLowerCase() === 'number') metric = 'sum'
|
|
33
|
+
if (!metric || !SUPPORTED_METRICS.includes(metric)) return '-'
|
|
34
|
+
let summary = summarizeColumn(rows, column.field ?? {name: column.id, type: column.type}, [metric])
|
|
35
|
+
return summary[metric] ?? null
|
|
36
|
+
}
|
|
28
37
|
</script>
|
|
29
38
|
|
|
30
39
|
<tr class="subtotal-row" style:background-color={rowColor} style:color={fontColor}>
|
|
@@ -32,21 +41,13 @@
|
|
|
32
41
|
<TableCell class="index" {compact}></TableCell>
|
|
33
42
|
{/if}
|
|
34
43
|
{#each orderedColumns as column (column.id)}
|
|
35
|
-
{
|
|
36
|
-
{@const baseFormat = column.fmt ? getFormatObjectFromString(column.fmt, summary.format?.valueType) : summary.format}
|
|
37
|
-
{@const format = (() => {
|
|
38
|
-
if (column.subtotalFmt) return getFormatObjectFromString(column.subtotalFmt)
|
|
39
|
-
if (column.totalFmt) return getFormatObjectFromString(column.totalFmt)
|
|
40
|
-
return baseFormat
|
|
41
|
-
})()}
|
|
42
|
-
<TableCell class={summary.type} {compact} align={column.align}>
|
|
44
|
+
<TableCell class={column.type} {compact} align={column.align}>
|
|
43
45
|
{#if column.id !== groupBy}
|
|
44
46
|
{#if column.contentType === 'delta'}
|
|
45
47
|
<InlineDelta
|
|
46
|
-
value={
|
|
48
|
+
value={getAggregateValue(currentGroupData, column)}
|
|
47
49
|
downIsGood={column.downIsGood}
|
|
48
|
-
|
|
49
|
-
columnUnitSummary={summary.columnUnitSummary}
|
|
50
|
+
field={column.field}
|
|
50
51
|
showValue={column.showValue}
|
|
51
52
|
showSymbol={column.deltaSymbol}
|
|
52
53
|
align={column.align}
|
|
@@ -55,11 +56,7 @@
|
|
|
55
56
|
chip={column.chip}
|
|
56
57
|
/>
|
|
57
58
|
{:else}
|
|
58
|
-
{
|
|
59
|
-
aggregateColumn(currentGroupData, column.id, column.totalAgg, summary.type, column.weightCol),
|
|
60
|
-
format,
|
|
61
|
-
summary.columnUnitSummary,
|
|
62
|
-
)}
|
|
59
|
+
{formatFromField(column.field, getAggregateValue(currentGroupData, column))}
|
|
63
60
|
{/if}
|
|
64
61
|
{:else if groupType === 'section'}
|
|
65
62
|
{groupName}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import InlineDelta from './InlineDelta.svelte'
|
|
3
3
|
import TableCell from './TableCell.svelte'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import {summarizeColumn, type SummaryMetric} from '../component-utilities/dataSummary.ts'
|
|
5
|
+
import {formatFromField} from '../component-utilities/format.ts'
|
|
6
6
|
|
|
7
7
|
interface Props {
|
|
8
8
|
data?: any[]
|
|
9
9
|
rowNumbers?: boolean | string
|
|
10
|
-
columnSummary?: any[]
|
|
11
10
|
rowColor?: string
|
|
12
11
|
fontColor?: string
|
|
13
12
|
groupType?: 'accordion' | 'section'
|
|
@@ -16,7 +15,7 @@
|
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
let {
|
|
19
|
-
data = [], rowNumbers: rowNumbersProp = undefined,
|
|
18
|
+
data = [], rowNumbers: rowNumbersProp = undefined, rowColor = undefined,
|
|
20
19
|
fontColor = undefined, groupType = undefined, orderedColumns = [], compact: compactProp = undefined,
|
|
21
20
|
}: Props = $props()
|
|
22
21
|
|
|
@@ -32,6 +31,16 @@
|
|
|
32
31
|
|
|
33
32
|
let rowNumbers = $derived(toBool(rowNumbersProp))
|
|
34
33
|
let compact = $derived(toBool(compactProp))
|
|
34
|
+
|
|
35
|
+
const SUPPORTED_METRICS: SummaryMetric[] = ['sum', 'mean', 'median', 'min', 'max', 'count', 'countDistinct']
|
|
36
|
+
|
|
37
|
+
const getAggregateValue = (rows: Record<string, unknown>[], column: any, aggType: string | undefined) => {
|
|
38
|
+
let metric = aggType as SummaryMetric | undefined
|
|
39
|
+
if (!metric && String(column?.type || '').toLowerCase() === 'number') metric = 'sum'
|
|
40
|
+
if (!metric || !SUPPORTED_METRICS.includes(metric)) return '-'
|
|
41
|
+
let summary = summarizeColumn(rows, column.field ?? {name: column.id, type: column.type}, [metric])
|
|
42
|
+
return summary[metric] ?? null
|
|
43
|
+
}
|
|
35
44
|
</script>
|
|
36
45
|
|
|
37
46
|
<tr class="total-row" style:background-color={rowColor} style:color={fontColor}>
|
|
@@ -40,49 +49,30 @@
|
|
|
40
49
|
{/if}
|
|
41
50
|
|
|
42
51
|
{#each orderedColumns as column (column.id)}
|
|
43
|
-
{@const summary = safeExtractColumn(column, columnSummary)}
|
|
44
|
-
{@const format = (() => {
|
|
45
|
-
if (column.totalFmt) return getFormatObjectFromString(column.totalFmt)
|
|
46
|
-
if (column.fmt) return getFormatObjectFromString(column.fmt, summary.format?.valueType)
|
|
47
|
-
return summary.format
|
|
48
|
-
})()}
|
|
49
52
|
{@const totalAgg = column.totalAgg ?? 'sum'}
|
|
50
53
|
<TableCell
|
|
51
54
|
{compact}
|
|
52
|
-
dataType={
|
|
55
|
+
dataType={column.type}
|
|
53
56
|
align={column.align}
|
|
54
57
|
height={column.height}
|
|
55
58
|
width={column.width}
|
|
56
59
|
wrap={column.wrap}
|
|
57
60
|
topBorder="1px solid rgba(107, 114, 128, 0.5)"
|
|
58
61
|
>
|
|
59
|
-
{#if
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
chip={column.chip}
|
|
72
|
-
/>
|
|
73
|
-
{:else}
|
|
74
|
-
{formatValue(
|
|
75
|
-
totalAgg === 'weightedMean' ? weightedMean(data, column.id, column.weightCol) : summary.columnUnitSummary?.[totalAgg],
|
|
76
|
-
format,
|
|
77
|
-
summary.columnUnitSummary,
|
|
78
|
-
)}
|
|
79
|
-
{/if}
|
|
62
|
+
{#if column.contentType === 'delta'}
|
|
63
|
+
<InlineDelta
|
|
64
|
+
value={getAggregateValue(data, column, totalAgg)}
|
|
65
|
+
downIsGood={column.downIsGood}
|
|
66
|
+
field={column.field}
|
|
67
|
+
showValue={column.showValue}
|
|
68
|
+
showSymbol={column.deltaSymbol}
|
|
69
|
+
align={column.align}
|
|
70
|
+
neutralMin={column.neutralMin ?? 0}
|
|
71
|
+
neutralMax={column.neutralMax ?? 0}
|
|
72
|
+
chip={column.chip}
|
|
73
|
+
/>
|
|
80
74
|
{:else}
|
|
81
|
-
{
|
|
82
|
-
{formatValue(totalAgg, format, summary.columnUnitSummary)}
|
|
83
|
-
{:else}
|
|
84
|
-
{totalAgg}
|
|
85
|
-
{/if}
|
|
75
|
+
{formatFromField(column.field, getAggregateValue(data, column, totalAgg))}
|
|
86
76
|
{/if}
|
|
87
77
|
</TableCell>
|
|
88
78
|
{/each}
|