bito-code-review[bot] commented on code in PR #39760:
URL: https://github.com/apache/superset/pull/39760#discussion_r3291583595


##########
superset-frontend/src/explore/components/controls/LayerConfigsControl/LayerTreeItem.tsx:
##########
@@ -18,7 +18,6 @@
  */
 import { Icons } from '@superset-ui/core/components/Icons';
 import { Button } from '@superset-ui/core/components';
-import { Tag } from 'src/components';
 import { FC } from 'react';

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>CWE-N/A: Missing Unit Test Coverage</b></div>
   <div id="fix">
   
   The LayerTreeItem component lacks unit test coverage. BITO.md rule [6262] 
requires tests to verify actual behavior (click handlers, rendering structure), 
not just that components render. Without tests, this refactoring removing the 
Tag wrapper creates regression risk that could go undetected.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #c40662</i></small>
   </div><div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Tag component functionality removed</b></div>
   <div id="fix">
   
   Replacing `<Tag>` with `<div>` removes non-cosmetic functionality from 
`src/components/Tag/index.tsx`: (1) Tooltip wrapping around children, (2) 
styled top/bottom margins via `theme.sizeUnit`, (3) `data-test="tag"` attribute 
for testing, and (4) conditional link rendering when `id` prop is present. The 
`className` prop is passed through to StyledTag and applied to the AntdTag 
element, so removing the Tag wrapper changes observable behavior beyond 
styling. Either restore the Tag wrapper or explicitly remove the features via 
component props.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #5c3657</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/plugins/plugin-chart-cartodiagram/src/util/layerUtil.tsx:
##########
@@ -152,8 +196,71 @@ export const createLayer = async (layerConf: LayerConf) => 
{
     layer = await createWfsLayer(layerConf);
   } else if (isXyzLayerConf(layerConf)) {
     layer = createXyzLayer(layerConf);
+  } else if (isDataLayerConf(layerConf)) {
+    layer = await createDataLayer(layerConf);
   } else {
     console.warn('Provided layerconfig is not recognized');
   }
   return layer;
 };
+
+export const removeSelectionLayer = (olMap: Map) => {
+  const selectionLayer = olMap
+    .getLayers()
+    .getArray()
+    .filter(l => l.get(LAYER_NAME_PROP) === SELECTION_LAYER_NAME)
+    .pop();
+  if (selectionLayer) {
+    olMap.removeLayer(selectionLayer);
+  }
+};
+
+export const getSelectedFeatures = (
+  dataLayers: VectorLayer<VectorSource>[],
+  filterState: FilterState,
+  crossFilterColumn: string,
+) => {
+  let selectedFeatures: Feature[] = [];
+  if (
+    filterState.selectedValues !== null &&
+    filterState.selectedValues !== undefined &&
+    dataLayers
+  ) {
+    selectedFeatures = dataLayers.flatMap(dataLayer =>
+      dataLayer
+        .getSource()!
+        .getFeatures()
+        .filter(f =>
+          filterState.selectedValues.includes(f.get(crossFilterColumn)),
+        ),
+    );
+  }
+  return selectedFeatures;
+};
+
+export const setSelectionBackgroundOpacity = (
+  dataLayers: VectorLayer<VectorSource>[],
+  opacity: number,
+) => {
+  dataLayers.forEach(dataLayer => {
+    dataLayer.setOpacity(opacity);
+  });
+};
+
+export const createSelectionLayer = (
+  dataLayers: VectorLayer<VectorSource>[],
+  features: Feature[],
+) => {
+  const selectionLayer = new VectorLayer({
+    source: new VectorSource({
+      features,
+    }),
+  });
+  selectionLayer.set(LAYER_NAME_PROP, SELECTION_LAYER_NAME);
+  // TODO how can we handle multiple data layers?

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>TODO acknowledges incomplete logic</b></div>
   <div id="fix">
   
   TODO comment at line 260 acknowledges incomplete handling of multiple data 
layers in `createSelectionLayer`. The function currently only uses the style 
from `dataLayers[0]`, which may not be appropriate when multiple layers have 
different styles.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #5c3657</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/plugins/plugin-chart-cartodiagram/src/util/geometryUtil.ts:
##########
@@ -58,3 +59,13 @@ export const getExtentFromFeatures = (features: Feature[]) 
=> {
   source.addFeatures(features);
   return source.getExtent();
 };
+
+/**
+ * Generates a padding array for the map extent.
+ * @param mapExtentPadding The selected map extent padding value
+ * @returns An array with the padding values or undefined
+ */
+export const getMapExtentPadding = (
+  mapExtentPadding?: number,
+): FitOptions['padding'] | undefined =>
+  mapExtentPadding !== undefined ? Array(4).fill(mapExtentPadding) : undefined;

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Missing unit tests for new function</b></div>
   <div id="fix">
   
   The new `getMapExtentPadding` function lacks unit tests. Per project 
guidelines, new utility functions should have dedicated tests covering success 
paths and edge cases. The existing test file at 
`test/util/geometryUtil.test.ts` only tests 
`getProjectedCoordinateFromPointGeoJson` and `getExtentFromFeatures`.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #5c3657</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/src/explore/components/controls/LayerConfigsControl/LayerConfigsPopoverContent.tsx:
##########
@@ -273,29 +345,47 @@ export const LayerConfigsPopoverContent: FC<
       conf = {
         ...baseConfs,
         type: currentLayerConf.type,
+        url: currentLayerConf.url,
       };
-    } else {
+    } else if (isWfsLayerConf(currentLayerConf)) {
       conf = {
         ...baseConfs,
         type: currentLayerConf.type,
+        url: currentLayerConf.url,
         version: currentLayerConf.version,
         typeName: currentLayerConf.typeName,
         maxFeatures: currentLayerConf.maxFeatures,
         style: currentLayerConf.style,
       };
+    } else {
+      conf = {
+        ...baseConfs,
+        type: currentLayerConf.type,

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Redundant type assignment</b></div>
   <div id="fix">
   
   The `type: currentLayerConf.type` property is set in `baseConfs` (line 331) 
and then redundantly reassigned in each branch conf object at lines 341, 347, 
353, and 363. The spread operator `...baseConfs` already propagates this value, 
making the per-branch assignments dead code within the diff.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #5c3657</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/src/explore/components/controls/LayerConfigsControl/geoStylerUtil.ts:
##########
@@ -0,0 +1,183 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { FeatureCollection, GeoJsonGeometryTypes } from 'geojson';
+import { VectorData } from 'geostyler-data';
+import { GeoStylerContextInterface, GeoStylerLocale, locale } from 'geostyler';
+
+import { Style, Symbolizer } from 'geostyler-style';
+import { ColTypeMapping } from './types';
+import { SupersetTheme } from '@apache-superset/core/theme';
+
+/**
+ * Map Superset column type to GeoStyler column type.
+ * @param colType The Superset columntype
+ * @returns The GeoStyler column type.
+ */
+export const colTypeToGeoStylerType = (colType: string) => {
+  // TODO add missing types
+  switch (colType) {
+    case 'LONGINTEGER':
+    case 'INTEGER':
+      return 'integer';
+    case 'STRING':
+      return 'string';
+    case 'DATETIME':
+    case 'DATE':
+    case 'FLOAT':
+    case 'DECIMAL':
+      return 'number';
+    default:
+      return colType;
+  }
+};
+
+/**
+ * Map Superset column types to GeoStyler data.
+ * @param colTypes The superset column types.
+ * @returns A geotyler-data object.
+ */
+export const colTypesToGeoStylerData = (
+  colTypes: ColTypeMapping,
+  dataFeatureCollection: FeatureCollection = {
+    type: 'FeatureCollection',
+    features: [],
+  },
+) => {
+  const data: VectorData = {
+    schema: {
+      type: 'object',
+      properties: Object.keys(colTypes).reduce(
+        (prev, cur) => ({
+          ...prev,
+          [cur]: {
+            type: colTypeToGeoStylerType(colTypes[cur]),
+          },
+        }),
+        {},
+      ),
+    },
+    exampleFeatures: dataFeatureCollection,
+  };
+  return data;
+};
+
+/**
+ * Create a GeoStylerContext.
+ *
+ * Sets the locales, GsData, and enables and disables certain features
+ * depending on given data and their geometries.
+ *
+ * @param gsLocale The locales of the active language.
+ * @param data The GeoStyler Data.
+ * @param geomTypes List of distinct geometry types.
+ * @returns The GeoStylerContext.
+ */
+export const createGeoStylerContext = (
+  gsLocale: GeoStylerLocale,
+  data: VectorData | undefined,
+  composition: GeoStylerContextInterface['composition'],
+) => {
+  const context: GeoStylerContextInterface = {
+    locale: gsLocale,
+    composition: composition ?? {},
+  };
+
+  if (data) {
+    context.data = data;
+  }
+
+  if (!context.composition!.Rules) {
+    context.composition!.Rules = {};
+  }
+  context.composition!.Rules.disableClassification =
+    !data?.exampleFeatures.features.length;
+
+  return context;
+};
+
+/**
+ * Get the GeoStylerLocale derived from the application locale.
+ * @param appLocale The application locale.
+ * @returns The matching GeoStylerLocale.
+ */
+export const getGeoStylerLocale = (appLocale: string) => {
+  let gsLocale = (locale as Record<string, GeoStylerLocale>)[appLocale];
+  if (!gsLocale) {
+    const localeKeys = Object.keys(locale);
+    const localeKey = localeKeys.find(
+      l => l.split('_')[0].toLowerCase() === appLocale.toLowerCase(),
+    );
+    gsLocale = localeKey
+      ? (locale as Record<string, GeoStylerLocale>)[localeKey]
+      : locale.en_US;
+  }
+  return gsLocale;
+};
+
+/**
+ * Get the default style depending on given geometry types.
+ * @param geomTypes List of distinct geometry types.
+ * @param styleName Name of the style.
+ * @param ruleName Name of the rule.
+ * @returns GeoStylerStyle.
+ */
+export const getDefaultStyle = (
+  geomTypes: GeoJsonGeometryTypes[] = [],
+  styleName: string,
+  ruleName: string,
+  theme: SupersetTheme,
+) => {
+  const symbolizers: Symbolizer[] = [];
+  if (geomTypes.includes('Polygon') || geomTypes.includes('MultiPolygon')) {
+    symbolizers.push({
+      kind: 'Fill',
+      // eslint-disable-next-line theme-colors/no-literal-colors
+      color: theme.colorTextBase,
+    });
+  }
+  if (
+    geomTypes.includes('LineString') ||
+    geomTypes.includes('MultiLineString')
+  ) {
+    symbolizers.push({
+      kind: 'Line',
+      // eslint-disable-next-line theme-colors/no-literal-colors
+      color: theme.colorTextBase,
+      width: 2,
+    });
+  }
+  if (geomTypes.includes('Point') || geomTypes.includes('MultiPoint')) {
+    symbolizers.push({
+      kind: 'Mark',
+      wellKnownName: 'circle',
+      // eslint-disable-next-line theme-colors/no-literal-colors
+      color: theme.colorTextBase,
+    });
+  }
+  const style: Style = {
+    name: styleName,
+    rules: [
+      {
+        name: ruleName,
+        symbolizers,
+      },
+    ],
+  };
+  return style;
+};

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Missing unit tests for new utilities</b></div>
   <div id="fix">
   
   Add comprehensive unit tests for this new utility module covering: type 
mapping logic, data transformation, context creation with various inputs, 
locale fallback behavior, and default style generation for different geometry 
types.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #5c3657</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/src/explore/components/controls/LayerConfigsControl/LayerConfigsPopoverContent.tsx:
##########
@@ -482,25 +642,74 @@ export const LayerConfigsPopoverContent: FC<
             {
               key: LAYER_CONFIG_TABS.GEOSTYLER,
               label: styleTabLabel,
-              disabled: !isWfsLayerConf(currentLayerConf),
-              children: isWfsLayerConf(currentLayerConf) && (
-                <StyledGeoStyler
-                  style={currentLayerConf.style}
-                  onStyleChange={onStyleChange}
-                  data={geostylerData}
-                />
+              disabled:
+                !isWfsLayerConf(currentLayerConf) &&
+                !isDataLayerConf(currentLayerConf),
+              children: (isWfsLayerConf(currentLayerConf) ||
+                isDataLayerConf(currentLayerConf)) && (
+                <>
+                  <StyledUploadButtonContainer>
+                    <div>
+                      <StyledFeedbackMessage success={!!feedback.success}>
+                        {feedback.message}
+                      </StyledFeedbackMessage>
+                    </div>
+                    <Upload
+                      beforeUpload={beforeUpload}
+                      showUploadList={false}
+                      accept=".sld"
+                    >
+                      <Button
+                        buttonSize="small"
+                        buttonStyle="secondary"
+                        icon={
+                          feedback.success !== null ? (
+                            feedback.success ? (
+                              <CheckOutlined
+                                style={{ color: theme.colorSuccess }}
+                              />
+                            ) : (
+                              <CloseOutlined
+                                style={{ color: theme.colorError }}
+                              />
+                            )
+                          ) : (
+                            <UploadOutlined />
+                          )
+                        }
+                        style={{ float: 'right' }}
+                      >
+                        {t('Import SLD')}
+                      </Button>
+                    </Upload>
+                  </StyledUploadButtonContainer>
+                  <GeoStylerContext.Provider value={geoStylerContext}>
+                    <StyledGeoStyler
+                      style={currentLayerConf.style}
+                      onStyleChange={onStyleChange}
+                    />

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Missing `data` prop in GeoStyler</b></div>
   <div id="fix">
   
   The `data` prop was present in the old GeoStyler usage (line 490) but is 
missing in the new code. This prop provides parsed geo data for the style 
editor to display feature information.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #5c3657</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/plugins/plugin-chart-cartodiagram/src/util/transformPropsUtil.ts:
##########
@@ -55,6 +70,55 @@ export const getGeojsonColumns = (columns: string[]) =>
     return [...prev, idx];
   }, []);
 
+export const getWkbColumns = (columns: string[]) =>
+  columns.reduce((prev, current, idx) => {
+    let isWkb;
+
+    try {
+      new WKB().readFeature(current);

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>WKB parser reuse</b></div>
   <div id="fix">
   
   Move the `new WKB()` instantiation outside of the `reduce` callback into a 
block-bodied arrow function so that the same parser instance is reused for each 
column.
   </div>
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #5c3657</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to