diff --git a/app/gui/src/project-view/components/visualizations/ScatterplotVisualization.vue b/app/gui/src/project-view/components/visualizations/ScatterplotVisualization.vue index 632c3ae42a05..b1ade0c8e3e1 100644 --- a/app/gui/src/project-view/components/visualizations/ScatterplotVisualization.vue +++ b/app/gui/src/project-view/components/visualizations/ScatterplotVisualization.vue @@ -7,6 +7,7 @@ import { Pattern } from '@/util/ast/match' import { getTextWidthBySizeAndFamily } from '@/util/measurement' import { defineKeybinds } from '@/util/visualizationBuiltins' import { computed, ref, watch, watchEffect, watchPostEffect } from 'vue' +import { ToolbarItem } from './toolbar' export const name = 'Scatter Plot' export const icon = 'points' @@ -707,12 +708,12 @@ watchPostEffect(() => { const yScale_ = yScale.value const plotData = getPlotData(data.value) as Point[] const series = Object.keys(data.value.axis).filter((s) => s != 'x') - const colorScale = (d: string) => { + const colorScale = (d: Point) => { const color = d3.scaleOrdinal(d3.schemeCategory10).domain(series) if (data.value.is_multi_series) { - return color(d) + return color(d.series ?? '') } - return DEFAULT_FILL_COLOR + return d.color ?? DEFAULT_FILL_COLOR } d3Points.value .selectAll('path') @@ -730,7 +731,7 @@ watchPostEffect(() => { 'd', symbol.type(matchShape).size((d) => (d.size ?? 0.15) * SIZE_SCALE_MULTIPLER), ) - .style('fill', (d) => colorScale(d.series || '')) + .style('fill', (d) => colorScale(d)) .attr('transform', (d) => `translate(${xScale_(Number(d.x))}, ${yScale_(d.y)})`) if (data.value.points.labels === VISIBLE_POINTS) { d3Points.value @@ -865,42 +866,49 @@ const makeSeriesLabelOptions = () => { return seriesOptions } -config.setToolbar([ - { - icon: 'select', - title: 'Enable Selection', - toggle: selectionEnabled, - }, - { - icon: 'show_all', - title: 'Fit All', - onClick: () => zoomToSelected(false), - }, - { - icon: 'zoom', - title: 'Zoom to Selected', - disabled: () => brushExtent.value == null, - onClick: zoomToSelected, - }, - { - icon: 'add_to_graph_editor', - title: 'Create component of selected points', - disabled: () => !createNewFilterNodeEnabled.value, - onClick: createNewFilterNode, - }, - { - type: 'textSelectionMenu', - selectedTextOption: yAxisSelected, - title: 'Choose Y Axis Label', - heading: 'Y Axis Label: ', - options: { - none: { - label: 'No Label', - }, - ...makeSeriesLabelOptions(), +const createTextSelectionButton = (): ToolbarItem => ({ + type: 'textSelectionMenu', + selectedTextOption: yAxisSelected, + title: 'Choose Y Axis Label', + heading: 'Y Axis Label: ', + options: { + none: { + label: 'No Label', }, + ...makeSeriesLabelOptions(), }, -]) +}) + +function useScatterplotVizToolbar() { + const textSelectionButton = createTextSelectionButton() + return computed(() => [ + { + icon: 'select', + title: 'Enable Selection', + toggle: selectionEnabled, + }, + { + icon: 'show_all', + title: 'Fit All', + onClick: () => zoomToSelected(false), + }, + { + icon: 'zoom', + title: 'Zoom to Selected', + disabled: () => brushExtent.value == null, + onClick: zoomToSelected, + }, + { + icon: 'add_to_graph_editor', + title: 'Create component of selected points', + disabled: () => !createNewFilterNodeEnabled.value, + onClick: createNewFilterNode, + }, + ...(data.value.is_multi_series ? [textSelectionButton] : []), + ]) +} + +config.setToolbar(useScatterplotVizToolbar())