@lightdash/cli 2.245.2 → 2.247.0

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.
@@ -121,7 +121,9 @@ order, `sortBy` describes result ordering, `totalColumnCount` exposes truncation
121
121
  view (headline, summary, limitations, anomalies) plus `analyse()`;
122
122
  `useInsights(result)` narrows to one chart and adds `matches(row)` so flagged
123
123
  points can be marked, with `investigate(id)` / `continueInAskAi(id)` for the
124
- action menu. Render a summary block and markers; render nothing when
124
+ action menu. Render a summary block and markers (only `high`, `medium`,
125
+ `positive`; never `info`); on line charts the marker must also be the
126
+ `activeDot` so hover does not cover it. Render nothing when
125
127
  `status === 'unavailable'`. Full contract in `/app/references/ai-analysis.md`.
126
128
  - `ai-prompt`: `useAiPrompt()` returns `{ available, ask, loading, text, error }`;
127
129
  `ask({ prompt, sources: [{ result, label }], focus?: { row } })` sends an
@@ -149,11 +149,15 @@ Each anomaly:
149
149
  }
150
150
  ```
151
151
 
152
- Mark the flagged rows on the chart. `matches(row)` takes the raw result row, so call it per datum:
152
+ Mark the flagged rows on the chart. `matches(row)` takes the raw result row, so call it per datum. Only `high`, `medium` and `positive` earn a marker; `info` is context for the summary (a gap, a partial period), so never paint it on the chart:
153
153
 
154
154
  ```tsx
155
155
  import { Bar, BarChart, Cell } from 'recharts';
156
156
 
157
+ const MARKED = new Set(['high', 'medium', 'positive']);
158
+ const marker = (insights, row) =>
159
+ insights.matches(row).find((a) => MARKED.has(a.severity)) ?? null;
160
+
157
161
  function OrdersByStatus() {
158
162
  const orders = useLightdash(ordersQuery);
159
163
  const insights = useInsights(orders);
@@ -162,7 +166,7 @@ function OrdersByStatus() {
162
166
  <BarChart data={orders.data}>
163
167
  <Bar dataKey="orders_count">
164
168
  {orders.data.map((row) => {
165
- const flagged = insights.matches(row).length > 0;
169
+ const flagged = marker(insights, row) !== null;
166
170
  return (
167
171
  <Cell
168
172
  key={row.orders_status}
@@ -177,7 +181,46 @@ function OrdersByStatus() {
177
181
  }
178
182
  ```
179
183
 
180
- Keep the marker subtle (an outline, a dot, a badge in the tooltip), and show the anomaly `text` on hover so the viewer learns why the point is marked.
184
+ Keep the marker subtle (an outline, a dot, a badge in the tooltip), and show the anomaly `text` on hover so the viewer learns why the point is marked. Tint by severity: `positive` is not a warning.
185
+
186
+ ### Markers on line and area charts must stay clickable on hover
187
+
188
+ Recharts draws `activeDot` on top of `dot` while the cursor is over a point. With the default `activeDot={{ r: 5 }}` the hover dot covers the marker and takes the click, so the action menu only opens from a one-pixel rim. Render the same marker component for both, with the same click handler, or turn the hover dot off:
189
+
190
+ ```tsx
191
+ // Recharts clones the dot element and merges cx, cy and payload into its
192
+ // props, so extra props like insights and onOpenMenu pass straight through.
193
+ const Marker = ({ cx, cy, payload, insights, onOpenMenu }) => {
194
+ const anomaly = marker(insights, payload);
195
+ return (
196
+ <circle
197
+ cx={cx}
198
+ cy={cy}
199
+ r={anomaly ? 5 : 3}
200
+ fill={anomaly ? 'var(--destructive)' : 'var(--chart-1)'}
201
+ style={{ cursor: 'pointer' }}
202
+ onClick={(e) => onOpenMenu(payload, e)}
203
+ />
204
+ );
205
+ };
206
+
207
+ function OrdersOverTime() {
208
+ const orders = useLightdash(ordersQuery);
209
+ const insights = useInsights(orders);
210
+ const [menu, setMenu] = useState(null);
211
+ const openMenu = (row, e) => setMenu({ row, x: e.clientX, y: e.clientY });
212
+ const dot = <Marker insights={insights} onOpenMenu={openMenu} />;
213
+
214
+ return (
215
+ <LineChart data={orders.data}>
216
+ <Line dataKey="orders_count" dot={dot} activeDot={dot} />
217
+ {/* or: activeDot={false} */}
218
+ </LineChart>
219
+ );
220
+ }
221
+ ```
222
+
223
+ Whatever element carries the click handler must be the topmost one at that position: render markers after the series, never under a hover overlay or a tooltip cursor.
181
224
 
182
225
  ## Investigate from the action menu
183
226
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "2.245.2",
3
+ "version": "2.247.0",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -22,8 +22,8 @@
22
22
  "@actions/core": "1.11.1",
23
23
  "@aws-sdk/credential-providers": "3.995.0",
24
24
  "@casl/ability": "6.8.0",
25
- "@lightdash/common": "2.245.2",
26
- "@lightdash/warehouses": "2.245.2",
25
+ "@lightdash/common": "2.247.0",
26
+ "@lightdash/warehouses": "2.247.0",
27
27
  "@sidvind/better-ajv-errors": "7.0.0",
28
28
  "@types/columnify": "1.5.1",
29
29
  "ajv": "8.18.0",