diff --git a/src/components/timeline/LayerLine.svelte b/src/components/timeline/LayerLine.svelte index 0e05edb2c3..dd407fd110 100644 --- a/src/components/timeline/LayerLine.svelte +++ b/src/components/timeline/LayerLine.svelte @@ -2,12 +2,13 @@ diff --git a/src/components/timeline/form/TimelineEditorLayerSettings.svelte b/src/components/timeline/form/TimelineEditorLayerSettings.svelte index 6c5607a62a..b724a2444b 100644 --- a/src/components/timeline/form/TimelineEditorLayerSettings.svelte +++ b/src/components/timeline/form/TimelineEditorLayerSettings.svelte @@ -159,6 +159,17 @@ on:input={onInput} /> + + Show As Line Plot + + {/if} Layer ID diff --git a/src/schemas/ui-view-schema.json b/src/schemas/ui-view-schema.json index 44c80bce68..03842bad0c 100644 --- a/src/schemas/ui-view-schema.json +++ b/src/schemas/ui-view-schema.json @@ -405,6 +405,9 @@ "opacity": { "type": "number" }, + "showAsLinePlot": { + "type": "boolean" + }, "yAxisId": { "$ref": "#/definitions/yAxisId" } diff --git a/src/types/timeline.ts b/src/types/timeline.ts index b6177ed9b5..2f7a007c8f 100644 --- a/src/types/timeline.ts +++ b/src/types/timeline.ts @@ -196,6 +196,7 @@ export type XRangeLayerColorScheme = export interface XRangeLayer extends Layer { colorScheme: XRangeLayerColorScheme; opacity: number; + showAsLinePlot: boolean; } export interface XRangePoint extends Point { diff --git a/src/utilities/generic.ts b/src/utilities/generic.ts index a8eaeaa0bc..0da48e8336 100644 --- a/src/utilities/generic.ts +++ b/src/utilities/generic.ts @@ -95,10 +95,21 @@ export function getTarget(event: Event) { if (target.tagName === 'INPUT') { const input = target as HTMLInputElement; - const { name, type, value: valueAsString, valueAsNumber } = input; - const value = type === 'number' ? valueAsNumber : valueAsString; + const { name, type, value: valueAsString, valueAsNumber, checked } = input; + let convertedValue; + + switch (type) { + case 'number': + convertedValue = valueAsNumber; + break; + case 'checkbox': + convertedValue = checked; + break; + default: + convertedValue = valueAsString; + } - return { name, value }; + return { name, value: convertedValue }; } else if (target.tagName === 'SELECT') { const select = target as HTMLSelectElement; const type = select.getAttribute('data-type') ?? 'text'; diff --git a/src/utilities/timeline.ts b/src/utilities/timeline.ts index 93091b3128..cf917994ef 100644 --- a/src/utilities/timeline.ts +++ b/src/utilities/timeline.ts @@ -1,6 +1,6 @@ import { bisector, tickStep } from 'd3-array'; import type { Quadtree, QuadtreeInternalNode, QuadtreeLeaf } from 'd3-quadtree'; -import { scaleLinear, scaleTime, type ScaleLinear, type ScaleTime } from 'd3-scale'; +import { scaleLinear, scalePoint, scaleTime, type ScaleLinear, type ScalePoint, type ScaleTime } from 'd3-scale'; import { timeHour, timeInterval, @@ -139,12 +139,22 @@ export function getXScale(domain: Date[], width: number): ScaleTime { + return scalePoint() + .domain(domain as string[]) + .range([height - CANVAS_PADDING_Y, CANVAS_PADDING_Y]); +} + export function getYScale(domain: (number | null)[], height: number): ScaleLinear { return scaleLinear() .domain(domain.filter(filterEmpty)) .range([height - CANVAS_PADDING_Y, CANVAS_PADDING_Y]); } +export function isXRangeLayer(layer: Layer): layer is XRangeLayer { + return layer.chartType === 'x-range'; +} + function isQuadtreeLeaf(node?: QuadtreeInternalNode | QuadtreeLeaf): node is QuadtreeLeaf { if (node && node.length === undefined) { return true; @@ -355,7 +365,11 @@ export function createHorizontalGuide( if (firstAxis.scaleDomain.length === 2) { if (firstAxis.scaleDomain[0] !== null && firstAxis.scaleDomain[1] !== null) { // Default y value to the middle of the domain - y = (firstAxis.scaleDomain[1] + firstAxis.scaleDomain[0]) / 2; + if (typeof firstAxis.scaleDomain[0] === 'number' && typeof firstAxis.scaleDomain[1] === 'number') { + y = (firstAxis.scaleDomain[1] + firstAxis.scaleDomain[0]) / 2; + } else { + // TODO: Figure out how to place a horizontal guide on a categorical axis + } } } } @@ -494,6 +508,7 @@ export function createTimelineXRangeLayer( id, name: '', opacity: 0.8, + showAsLinePlot: false, yAxisId, ...args, };