Repository: briefercloud/briefer (language: python)

Issue:
fix naming Y axis when there are multiple series



Discussion / hints:

Fix patch:
diff --git a/apps/api/src/python/visualizations.ts b/apps/api/src/python/visualizations.ts
index 855937cd..9883d44f 100644
--- a/apps/api/src/python/visualizations.ts
+++ b/apps/api/src/python/visualizations.ts
@@ -155,7 +155,6 @@ def _briefer_create_chart(
     color_by_type,
     number_values_format,
     show_data_labels,
-    alone_in_series,
     color
 ):
     # Append _x, _y and _color to ensure uniqueness
@@ -276,7 +275,7 @@ def _briefer_create_chart(
         x_title = x_axis_name
 
     y_title = f"{y_axis_col} ({y_axis_agg_func})" if y_axis_agg_func else y_axis_col
-    if y_axis_name and alone_in_series:
+    if y_axis_name:
         y_title = y_axis_name
 
     x_time_unit = None
@@ -789,7 +788,6 @@ def _briefer_create_visualization(
             None,
             number_values_format,
             show_data_labels,
-            True,
             color
         )
         layers.append(chart)
@@ -826,7 +824,7 @@ def _briefer_create_visualization(
                     x_axis_type,
                     x_axis_group_func,
                     x_axis_sort,
-                    y_axis['name'],
+                    serie['axisName'],
                     serie['column']['name'],
                     serie['column']['type'],
                     serie['aggregateFunction'],
@@ -834,7 +832,6 @@ def _briefer_create_visualization(
                     color_by["type"] if color_by else None,
                     number_values_format,
                     show_data_labels,
-                    len(y_axis['series']) == 1,
                     color
                 )
                 series.append(chart)
diff --git a/apps/web/src/components/v2Editor/customBlocks/python/index.tsx b/apps/web/src/components/v2Editor/customBlocks/python/index.tsx
index 51911426..0e8afc83 100644
--- a/apps/web/src/components/v2Editor/customBlocks/python/index.tsx
+++ b/apps/web/src/components/v2Editor/customBlocks/python/index.tsx
@@ -525,7 +525,7 @@ function PythonBlock(props: Props) {
 
       <div
         className={clsx(
-          'absolute h-full transition-opacity opacity-0 group-hover/block:opacity-100 pl-1.5 right-0 top-0 translate-x-full flex flex-col gap-y-1',
+          'absolute h-full transition-opacity opacity-0 group-hover/block:opacity-100 pl-1.5 right-0 top-0 translate-x-full flex flex-col gap-y-1 z-20',
           isEditorFocused || statusIsDisabled ? 'opacity-100' : 'opacity-0',
           !props.isEditable ? 'hidden' : 'block'
         )}
diff --git a/apps/web/src/components/v2Editor/customBlocks/visualization/VisualizationControls.tsx b/apps/web/src/components/v2Editor/customBlocks/visualization/VisualizationControls.tsx
index 3740f003..2bf9273e 100644
--- a/apps/web/src/components/v2Editor/customBlocks/visualization/VisualizationControls.tsx
+++ b/apps/web/src/components/v2Editor/customBlocks/visualization/VisualizationControls.tsx
@@ -197,41 +197,24 @@ function VisualizationControls(props: Props) {
     [props.onChangeXAxisName]
   )
 
-  const onChangeLeftYAxisName = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>) => {
+  const onChangeYAxisName = useCallback(
+    (
+      e: React.ChangeEvent<HTMLInputElement>,
+      axisIndex: number,
+      seriesIndex: number
+    ) => {
       if (props.yAxes.length === 0) {
         return
       }
 
       const name = e.target.value === '' ? null : e.target.value
 
-      props.onChangeYAxes([
-        {
-          series: props.yAxes[0].series,
-          name,
-        },
-        ...props.yAxes.slice(1),
-      ])
-    },
-    [props.yAxes, props.onChangeYAxes]
-  )
-
-  const onChangeRightYAxisName = useCallback(
-    (e: React.ChangeEvent<HTMLInputElement>) => {
-      if (props.yAxes.length < 2) {
-        return
-      }
-
-      const name = e.target.value === '' ? null : e.target.value
+      const targetAxis = props.yAxes[axisIndex]
+      targetAxis.series[seriesIndex].axisName = name
 
-      props.onChangeYAxes([
-        props.yAxes[0],
-        {
-          series: props.yAxes[1].series,
-          name,
-        },
-        ...props.yAxes.slice(2),
-      ])
+      props.onChangeYAxes(
+        props.yAxes.map((y, i) => (i === axisIndex ? targetAxis : y))
+      )
     },
     [props.yAxes, props.onChangeYAxes]
   )
@@ -269,9 +252,9 @@ function VisualizationControls(props: Props) {
     props.onChangeYAxes([
       ...props.yAxes,
       {
-        name: null,
         series: [
           {
+            axisName: null,
             column: null,
             aggregateFunction: null,
             colorBy: null,
@@ -340,6 +323,31 @@ function VisualizationControls(props: Props) {
     [props.dataframe?.columns]
   )
 
+  const axisNameComponents = props.yAxes.map((yAxis, yI) =>
+    yAxis.series.map((_, sI) => {
+      return (
+        <div>
+          <label
+            htmlFor={`rightYAxisName-${yI}-${sI}`}
+            className="block text-xs font-medium leading-6 text-gray-900 pb-1"
+          >
+            {yI === 0 ? 'Primary' : 'Secondary'} Y-Axis Title
+            {sI > 0 ? ` (Series ${sI + 1})` : ''}
+          </label>
+          <input
+            name={`rightYAxisName-${yI}-${sI}`}
+            type="text"
+            placeholder="My Y-Axis"
+            className="w-full border-0 rounded-md ring-1 ring-inset ring-gray-200 focus:ring-1 focus:ring-inset focus:ring-gray-300 bg-white group px-2.5 text-gray-800 text-xs placeholder:text-gray-400"
+            value={props.yAxes[yI]?.series[sI]?.axisName ?? ''}
+            onChange={(e) => onChangeYAxisName(e, yI, sI)}
+            disabled={!props.dataframe || !props.isEditable}
+          />
+        </div>
+      )
+    })
+  )
+
   return (
     <div
       className={clsx(
@@ -582,47 +590,7 @@ function VisualizationControls(props: Props) {
           )}
           {tab === 'y-axis' && (
             <div className="text-xs text-gray-500 flex flex-col space-y-8">
-              <div>
-                <label
-                  htmlFor="leftYAxisName"
-                  className="block text-xs font-medium leading-6 text-gray-900 pb-1"
-                >
-                  {props.yAxes.length > 1 &&
-                  props.chartType !== 'trend' &&
-                  props.chartType !== 'number'
-                    ? 'Left '
-                    : ''}
-                  Y-Axis Name
-                </label>
-                <input
-                  name="leftYAxisName"
-                  type="text"
-                  placeholder="My Y-Axis"
-                  className="w-full border-0 rounded-md ring-1 ring-inset ring-gray-200 focus:ring-1 focus:ring-inset focus:ring-gray-300 bg-white group px-2.5 text-gray-800 text-xs placeholder:text-gray-400"
-                  value={props.yAxes[0]?.name ?? ''}
-                  onChange={onChangeLeftYAxisName}
-                  disabled={!props.dataframe || !props.isEditable}
-                />
-              </div>
-              {props.yAxes.length > 1 && (
-                <div>
-                  <label
-                    htmlFor="rightYAxisName"
-                    className="block text-xs font-medium leading-6 text-gray-900 pb-1"
-                  >
-                    Right Y-Axis Name
-                  </label>
-                  <input
-                    name="rightYAxisName"
-                    type="text"
-                    placeholder="My Y-Axis"
-                    className="w-full border-0 rounded-md ring-1 ring-inset ring-gray-200 focus:ring-1 focus:ring-inset focus:ring-gray-300 bg-white group px-2.5 text-gray-800 text-xs placeholder:text-gray-400"
-                    value={props.yAxes[1]?.name ?? ''}
-                    onChange={onChangeRightYAxisName}
-                    disabled={!props.dataframe || !props.isEditable}
-                  />
-                </div>
-              )}
+              {axisNameComponents}
             </div>
           )}
           {tab === 'labels' && (
diff --git a/apps/web/src/components/v2Editor/customBlocks/visualization/YAxisPicker.tsx b/apps/web/src/components/v2Editor/customBlocks/visualization/YAxisPicker.tsx
index 67d37624..b622071e 100644
--- a/apps/web/src/components/v2Editor/customBlocks/visualization/YAxisPicker.tsx
+++ b/apps/web/src/components/v2Editor/customBlocks/visualization/YAxisPicker.tsx
@@ -157,6 +157,7 @@ function YAxisPicker(props: Props) {
         series: [
           ...props.yAxis.series,
           {
+            axisName: null,
             column: null,
             aggregateFunction: null,
             colorBy: null,
diff --git a/packages/editor/src/blocks/visualization.ts b/packages/editor/src/blocks/visualization.ts
index f142aa5b..ce5aef50 100644
--- a/packages/editor/src/blocks/visualization.ts
+++ b/packages/editor/src/blocks/visualization.ts
@@ -88,9 +88,9 @@ export const makeVisualizationBlock = (
     yAxisAggregateFunction: null,
     yAxes: [
       {
-        name: null,
         series: [
           {
+            axisName: null,
             column: null,
             aggregateFunction: null,
             colorBy: null,
@@ -133,9 +133,9 @@ function getYAxes(block: Y.XmlElement<VisualizationBlock>): YAxis[] {
   if (yAxis || yAxisName || yAxisAggregateFunction || colorBy) {
     yAxes = [
       {
-        name: yAxisName,
         series: [
           {
+            axisName: null,
             column: yAxis,
             aggregateFunction: yAxisAggregateFunction,
             colorBy,
@@ -158,9 +158,9 @@ function getYAxes(block: Y.XmlElement<VisualizationBlock>): YAxis[] {
   if (yAxes.length === 0) {
     yAxes = [
       {
-        name: null,
         series: [
           {
+            axisName: null,
             column: null,
             aggregateFunction: null,
             colorBy: null,
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 6f5b57b2..20502681 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -568,6 +568,7 @@ export const AggregateFunction = z.union([
 export type AggregateFunction = z.infer<typeof AggregateFunction>
 
 export type Series = {
+  axisName: string | null
   chartType: ChartType | null
   column: DataFrameColumn | null
   aggregateFunction: AggregateFunction | null
@@ -575,7 +576,6 @@ export type Series = {
 }
 
 export type YAxis = {
-  name: string | null
   series: Series[]
 }
 


Test patch:
diff --git a/apps/api/src/yjs/v2/executors/blocks/visualization.test.ts b/apps/api/src/yjs/v2/executors/blocks/visualization.test.ts
index b13fc0ec..f265af88 100644
--- a/apps/api/src/yjs/v2/executors/blocks/visualization.test.ts
+++ b/apps/api/src/yjs/v2/executors/blocks/visualization.test.ts
@@ -46,9 +46,9 @@ describe('VisualizationExecutor', () => {
     block.setAttribute('xAxis', { name: 'a', type: 'string' })
     block.setAttribute('yAxes', [
       {
-        name: null,
         series: [
           {
+            axisName: null,
             chartType: null,
             column: { name: 'b', type: 'int' },
             aggregateFunction: null,
@@ -118,9 +118,9 @@ describe('VisualizationExecutor', () => {
         'ascending',
         [
           {
-            name: null,
             series: [
               {
+                axisName: null,
                 aggregateFunction: null,
                 chartType: null,
                 colorBy: null,