korbit-ai[bot] commented on code in PR #32548:
URL: https://github.com/apache/superset/pull/32548#discussion_r2040019022
##########
superset-frontend/src/explore/components/DatasourcePanel/index.tsx:
##########
@@ -137,7 +143,7 @@ export default function DataSourcePanel({
width,
}: Props) {
const [dropzones] = useContext(DropzoneContext);
Review Comment:
### Missing Context Provider Error Handling <sub></sub>
<details>
<summary>Tell me more</summary>
###### What is the issue?
No error handling or fallback for when DropzoneContext is undefined.
###### Why this matters
If the component is rendered outside of a DropzoneContext provider, it will
crash when trying to destructure undefined.
###### Suggested change ∙ *Feature Preview*
Add a check for context availability:
```typescript
const dropzoneContext = useContext(DropzoneContext);
if (!dropzoneContext) {
return <div>Error: DropzoneContext not found</div>;
}
const [dropzones] = dropzoneContext;
```
###### Provide feedback to improve future suggestions
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/00715585-6a11-436c-accc-f0639ff34a59/upvote)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/00715585-6a11-436c-accc-f0639ff34a59?what_not_true=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/00715585-6a11-436c-accc-f0639ff34a59?what_out_of_scope=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/00715585-6a11-436c-accc-f0639ff34a59?what_not_in_standard=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/00715585-6a11-436c-accc-f0639ff34a59)
</details>
<sub>
💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>
<!--- korbi internal id:73b5bd94-a7fd-4c0d-8dc5-6ebc8cf40d64 -->
[](73b5bd94-a7fd-4c0d-8dc5-6ebc8cf40d64)
##########
superset-frontend/packages/superset-ui-core/src/query/types/Datasource.ts:
##########
@@ -58,6 +59,7 @@ export const DEFAULT_METRICS: Metric[] = [
{
metric_name: 'COUNT(*)',
expression: 'COUNT(*)',
+ uuid: nanoid(),
Review Comment:
### Dynamic UUID Generation in Static Constants <sub></sub>
<details>
<summary>Tell me more</summary>
###### What is the issue?
Generating UUIDs in DEFAULT_METRICS using nanoid() will create new IDs on
every import of the module
###### Why this matters
This causes unnecessary memory allocation and computation on every module
import, even when the DEFAULT_METRICS array is not used. For static default
values, the UUID should be a constant.
###### Suggested change ∙ *Feature Preview*
Use a hardcoded UUID string instead of generating it dynamically:
```typescript
uuid: 'DEFAULT_COUNT_METRIC_UUID', // or any other constant UUID string
```
###### Provide feedback to improve future suggestions
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b49d7f80-0ebb-4563-ac0f-2b47fbfc1949/upvote)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b49d7f80-0ebb-4563-ac0f-2b47fbfc1949?what_not_true=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b49d7f80-0ebb-4563-ac0f-2b47fbfc1949?what_out_of_scope=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b49d7f80-0ebb-4563-ac0f-2b47fbfc1949?what_not_in_standard=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/b49d7f80-0ebb-4563-ac0f-2b47fbfc1949)
</details>
<sub>
💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>
<!--- korbi internal id:db6be6f1-9c30-4670-99ba-f8bbe2c2445d -->
[](db6be6f1-9c30-4670-99ba-f8bbe2c2445d)
##########
superset-frontend/src/explore/components/DatasourcePanel/DatasourceItems.tsx:
##########
@@ -0,0 +1,151 @@
+/**
+ * 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 { useCallback, useEffect, useMemo, useState } from 'react';
+import { VariableSizeList as List } from 'react-window';
+import { cloneDeep } from 'lodash';
+import { FlattenedItem, Folder } from './types';
+import DatasourcePanelItem from './DatasourcePanelItem';
+
+const BORDER_WIDTH = 2;
+const HEADER_ITEM_HEIGHT = 50;
+const METRIC_OR_COLUMN_ITEM_HEIGHT = 32;
+const DIVIDER_ITEM_HEIGHT = 16;
+
+const flattenFolderStructure = (
+ folders: Folder[],
+ depth = 0,
+ folderMap: Map<string, Folder> = new Map(),
+): { flattenedItems: FlattenedItem[]; folderMap: Map<string, Folder> } => {
+ const flattenedItems: FlattenedItem[] = [];
+
+ folders.forEach((folder, idx) => {
+ folderMap.set(folder.id, folder);
+
+ flattenedItems.push({
+ type: 'header',
+ folderId: folder.id,
+ depth,
+ height: HEADER_ITEM_HEIGHT,
+ });
+
+ if (!folder.isCollapsed) {
+ folder.items.forEach(item => {
+ flattenedItems.push({
+ type: 'item',
+ folderId: folder.id,
+ depth,
+ item,
+ height: METRIC_OR_COLUMN_ITEM_HEIGHT,
+ });
+ });
+
+ if (folder.subFolders && folder.subFolders.length > 0) {
+ const { flattenedItems: subItems } = flattenFolderStructure(
+ folder.subFolders,
+ depth + 1,
+ folderMap,
+ );
+
+ flattenedItems.push(...subItems);
+ }
+ }
+ if (depth === 0 && idx !== folders.length - 1) {
+ flattenedItems.push({
+ type: 'divider',
+ folderId: folder.id,
+ depth,
+ height: DIVIDER_ITEM_HEIGHT,
+ });
+ }
+ });
+
+ return { flattenedItems, folderMap };
+};
+
+interface DatasourceItemsProps {
+ width: number;
+ height: number;
+ folders: Folder[];
+}
+export const DatasourceItems = ({
+ width,
+ height,
+ folders,
+}: DatasourceItemsProps) => {
+ const [folderStructure, setFolderStructure] = useState<Folder[]>(folders);
+
+ useEffect(() => {
+ setFolderStructure(prev => (prev !== folders ? folders : prev));
+ }, [folders]);
+
+ const { flattenedItems, folderMap } = useMemo(
+ () => flattenFolderStructure(folderStructure),
+ [folderStructure],
+ );
+
+ const handleToggleCollapse = useCallback((folderId: string) => {
+ setFolderStructure(prevFolders => {
+ const updatedFolders = cloneDeep(prevFolders);
Review Comment:
### Inefficient Deep Cloning in State Updates <sub></sub>
<details>
<summary>Tell me more</summary>
###### What is the issue?
Using lodash's cloneDeep for folder state updates creates unnecessary deep
cloning of the entire folder structure.
###### Why this matters
Deep cloning large data structures is computationally expensive and can
impact performance, especially when the folder structure is large or when
frequent collapse/expand operations occur.
###### Suggested change ∙ *Feature Preview*
Implement selective immutable updates using spread operators or immer to
only clone the path to the modified folder. Example:
```typescript
const updateFolder = (folders: Folder[]): Folder[] => {
return folders.map(folder => {
if (folder.id === folderId) {
return { ...folder, isCollapsed: !folder.isCollapsed };
}
if (folder.subFolders) {
return { ...folder, subFolders: updateFolder(folder.subFolders) };
}
return folder;
});
};
```
###### Provide feedback to improve future suggestions
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/293a74f6-cd27-40b4-9043-824576cf09e8/upvote)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/293a74f6-cd27-40b4-9043-824576cf09e8?what_not_true=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/293a74f6-cd27-40b4-9043-824576cf09e8?what_out_of_scope=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/293a74f6-cd27-40b4-9043-824576cf09e8?what_not_in_standard=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/293a74f6-cd27-40b4-9043-824576cf09e8)
</details>
<sub>
💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>
<!--- korbi internal id:7d3e0c5a-6e6d-475d-aa7c-a5cf8a69f4f8 -->
[](7d3e0c5a-6e6d-475d-aa7c-a5cf8a69f4f8)
##########
superset-frontend/src/explore/components/DatasourcePanel/transformDatasourceFolders.ts:
##########
@@ -0,0 +1,155 @@
+/**
+ * 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 { Metric, t } from '@superset-ui/core';
+import {
+ ColumnItem,
+ DatasourceFolder,
+ DatasourcePanelColumn,
+ Folder,
+ MetricItem,
+} from './types';
+
+const transformToFolderStructure = (
+ metrics: MetricItem[],
+ columns: ColumnItem[],
+ folderConfig: DatasourceFolder[] | undefined,
+): Folder[] => {
+ const metricsMap = new Map<string, MetricItem>();
+ const columnsMap = new Map<string, ColumnItem>();
+
+ const assignedMetricUuids = new Set<string>();
+ const assignedColumnUuids = new Set<string>();
+
+ metrics.forEach(metric => {
+ metricsMap.set(metric.uuid, metric);
+ });
+
+ columns.forEach(column => {
+ columnsMap.set(column.uuid, column);
+ });
+
+ const processFolder = (
+ datasourceFolder: DatasourceFolder,
+ parentId?: string,
+ ): Folder => {
+ const folder: Folder = {
+ id: datasourceFolder.uuid,
+ name: datasourceFolder.name,
+ description: datasourceFolder.description,
+ isCollapsed: false,
+ items: [],
+ parentId,
+ };
+
+ if (datasourceFolder.children && datasourceFolder.children.length > 0) {
+ if (!folder.subFolders) {
+ folder.subFolders = [];
+ }
+
+ datasourceFolder.children.forEach(child => {
+ if (child.type === 'folder') {
+ folder.subFolders!.push(
+ processFolder(child as DatasourceFolder, folder.id),
+ );
+ } else if (child.type === 'metric') {
+ const metric = metricsMap.get(child.uuid);
+ if (metric) {
+ folder.items.push(metric);
+ assignedMetricUuids.add(metric.uuid);
+ }
+ } else if (child.type === 'column') {
+ const column = columnsMap.get(child.uuid);
+ if (column) {
+ folder.items.push(column);
+ assignedColumnUuids.add(column.uuid);
+ }
+ }
Review Comment:
### Simplify child type handling logic <sub></sub>
<details>
<summary>Tell me more</summary>
###### What is the issue?
The nested if-else chain handling different child types has repetitive
patterns and could be simplified using a map or switch statement.
###### Why this matters
The current structure makes it harder to add new types and increases
cognitive load when reading the code. Similar operations are repeated for
metrics and columns.
###### Suggested change ∙ *Feature Preview*
```typescript
const typeHandlers = {
folder: (child: DatasourceFolder) => {
folder.subFolders!.push(processFolder(child, folder.id));
},
metric: (child: { uuid: string }) => {
const item = metricsMap.get(child.uuid);
if (item) {
folder.items.push(item);
assignedMetricUuids.add(item.uuid);
}
},
column: (child: { uuid: string }) => {
const item = columnsMap.get(child.uuid);
if (item) {
folder.items.push(item);
assignedColumnUuids.add(item.uuid);
}
},
};
datasourceFolder.children.forEach(child => {
const handler = typeHandlers[child.type];
if (handler) {
handler(child as any);
}
});
```
###### Provide feedback to improve future suggestions
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/ab36e2a9-3948-44ff-90c5-6e36c50f13d3/upvote)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/ab36e2a9-3948-44ff-90c5-6e36c50f13d3?what_not_true=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/ab36e2a9-3948-44ff-90c5-6e36c50f13d3?what_out_of_scope=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/ab36e2a9-3948-44ff-90c5-6e36c50f13d3?what_not_in_standard=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/ab36e2a9-3948-44ff-90c5-6e36c50f13d3)
</details>
<sub>
💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>
<!--- korbi internal id:cad26b98-73c2-4e12-adca-b12a769370f2 -->
[](cad26b98-73c2-4e12-adca-b12a769370f2)
##########
superset-frontend/src/explore/components/DatasourcePanel/transformDatasourceFolders.ts:
##########
@@ -0,0 +1,155 @@
+/**
+ * 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 { Metric, t } from '@superset-ui/core';
+import {
+ ColumnItem,
+ DatasourceFolder,
+ DatasourcePanelColumn,
+ Folder,
+ MetricItem,
+} from './types';
+
+const transformToFolderStructure = (
+ metrics: MetricItem[],
+ columns: ColumnItem[],
+ folderConfig: DatasourceFolder[] | undefined,
+): Folder[] => {
+ const metricsMap = new Map<string, MetricItem>();
+ const columnsMap = new Map<string, ColumnItem>();
+
+ const assignedMetricUuids = new Set<string>();
+ const assignedColumnUuids = new Set<string>();
+
+ metrics.forEach(metric => {
+ metricsMap.set(metric.uuid, metric);
+ });
+
+ columns.forEach(column => {
+ columnsMap.set(column.uuid, column);
+ });
+
+ const processFolder = (
+ datasourceFolder: DatasourceFolder,
+ parentId?: string,
+ ): Folder => {
+ const folder: Folder = {
+ id: datasourceFolder.uuid,
+ name: datasourceFolder.name,
+ description: datasourceFolder.description,
+ isCollapsed: false,
+ items: [],
+ parentId,
+ };
+
+ if (datasourceFolder.children && datasourceFolder.children.length > 0) {
+ if (!folder.subFolders) {
+ folder.subFolders = [];
+ }
+
+ datasourceFolder.children.forEach(child => {
+ if (child.type === 'folder') {
+ folder.subFolders!.push(
+ processFolder(child as DatasourceFolder, folder.id),
+ );
+ } else if (child.type === 'metric') {
+ const metric = metricsMap.get(child.uuid);
+ if (metric) {
+ folder.items.push(metric);
+ assignedMetricUuids.add(metric.uuid);
+ }
Review Comment:
### Silent failure on missing metric reference <sub></sub>
<details>
<summary>Tell me more</summary>
###### What is the issue?
Silent handling of missing metrics in the metricsMap when processing folder
structure.
###### Why this matters
If a metric UUID referenced in the folder structure doesn't exist in the
metricsMap, the code silently skips it without logging or error reporting,
making it difficult to debug misconfigurations or data inconsistencies.
###### Suggested change ∙ *Feature Preview*
Add logging or error collection for missing metric references:
```typescript
const metric = metricsMap.get(child.uuid);
if (metric) {
folder.items.push(metric);
assignedMetricUuids.add(metric.uuid);
} else {
console.warn(`Referenced metric ${child.uuid} not found in metrics map`);
}
```
###### Provide feedback to improve future suggestions
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/12a108f9-3ef6-462b-9406-c1220cb3e130/upvote)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/12a108f9-3ef6-462b-9406-c1220cb3e130?what_not_true=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/12a108f9-3ef6-462b-9406-c1220cb3e130?what_out_of_scope=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/12a108f9-3ef6-462b-9406-c1220cb3e130?what_not_in_standard=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/12a108f9-3ef6-462b-9406-c1220cb3e130)
</details>
<sub>
💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>
<!--- korbi internal id:542ed542-fc55-44be-8c3f-8ea5a379edc2 -->
[](542ed542-fc55-44be-8c3f-8ea5a379edc2)
##########
superset-frontend/src/explore/components/DatasourcePanel/DatasourceItems.tsx:
##########
@@ -0,0 +1,151 @@
+/**
+ * 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 { useCallback, useEffect, useMemo, useState } from 'react';
+import { VariableSizeList as List } from 'react-window';
+import { cloneDeep } from 'lodash';
+import { FlattenedItem, Folder } from './types';
+import DatasourcePanelItem from './DatasourcePanelItem';
+
+const BORDER_WIDTH = 2;
+const HEADER_ITEM_HEIGHT = 50;
+const METRIC_OR_COLUMN_ITEM_HEIGHT = 32;
+const DIVIDER_ITEM_HEIGHT = 16;
+
+const flattenFolderStructure = (
+ folders: Folder[],
+ depth = 0,
+ folderMap: Map<string, Folder> = new Map(),
+): { flattenedItems: FlattenedItem[]; folderMap: Map<string, Folder> } => {
+ const flattenedItems: FlattenedItem[] = [];
+
+ folders.forEach((folder, idx) => {
+ folderMap.set(folder.id, folder);
+
+ flattenedItems.push({
+ type: 'header',
+ folderId: folder.id,
+ depth,
+ height: HEADER_ITEM_HEIGHT,
+ });
+
+ if (!folder.isCollapsed) {
+ folder.items.forEach(item => {
+ flattenedItems.push({
+ type: 'item',
+ folderId: folder.id,
+ depth,
+ item,
+ height: METRIC_OR_COLUMN_ITEM_HEIGHT,
+ });
+ });
+
+ if (folder.subFolders && folder.subFolders.length > 0) {
+ const { flattenedItems: subItems } = flattenFolderStructure(
+ folder.subFolders,
+ depth + 1,
+ folderMap,
+ );
+
+ flattenedItems.push(...subItems);
+ }
+ }
+ if (depth === 0 && idx !== folders.length - 1) {
+ flattenedItems.push({
+ type: 'divider',
+ folderId: folder.id,
+ depth,
+ height: DIVIDER_ITEM_HEIGHT,
+ });
+ }
+ });
+
+ return { flattenedItems, folderMap };
+};
+
+interface DatasourceItemsProps {
+ width: number;
+ height: number;
+ folders: Folder[];
+}
+export const DatasourceItems = ({
+ width,
+ height,
+ folders,
+}: DatasourceItemsProps) => {
+ const [folderStructure, setFolderStructure] = useState<Folder[]>(folders);
+
+ useEffect(() => {
+ setFolderStructure(prev => (prev !== folders ? folders : prev));
+ }, [folders]);
+
+ const { flattenedItems, folderMap } = useMemo(
+ () => flattenFolderStructure(folderStructure),
+ [folderStructure],
+ );
+
+ const handleToggleCollapse = useCallback((folderId: string) => {
+ setFolderStructure(prevFolders => {
+ const updatedFolders = cloneDeep(prevFolders);
+
+ const updateFolder = (folders: Folder[] | undefined): boolean => {
+ if (!folders) {
+ return false;
+ }
+ for (let i = 0; i < folders.length; i += 1) {
+ if (folders[i].id === folderId) {
+ // eslint-disable-next-line no-param-reassign
+ folders[i].isCollapsed = !folders[i].isCollapsed;
+ return true;
+ }
+
+ if (folders[i].subFolders && updateFolder(folders[i].subFolders)) {
+ return true;
+ }
+ }
+ return false;
+ };
Review Comment:
### Complex imperative folder update logic <sub></sub>
<details>
<summary>Tell me more</summary>
###### What is the issue?
The updateFolder function is using a nested imperative approach with
mutation, making it harder to follow the logic flow.
###### Why this matters
Complex nested loops with mutations are harder to debug and reason about. A
recursive functional approach would be clearer.
###### Suggested change ∙ *Feature Preview*
```typescript
const updateFolder = (folders: Folder[] | undefined): Folder[] | undefined
=> {
if (!folders) return undefined;
return folders.map(folder => ({
...folder,
isCollapsed: folder.id === folderId ? !folder.isCollapsed :
folder.isCollapsed,
subFolders: updateFolder(folder.subFolders)
}));
};
```
###### Provide feedback to improve future suggestions
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/dcfcd9cc-2e66-415b-8669-d9334ae2a49a/upvote)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/dcfcd9cc-2e66-415b-8669-d9334ae2a49a?what_not_true=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/dcfcd9cc-2e66-415b-8669-d9334ae2a49a?what_out_of_scope=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/dcfcd9cc-2e66-415b-8669-d9334ae2a49a?what_not_in_standard=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/dcfcd9cc-2e66-415b-8669-d9334ae2a49a)
</details>
<sub>
💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>
<!--- korbi internal id:4e3a431c-b1d9-4628-a2b6-c98bbdfaee93 -->
[](4e3a431c-b1d9-4628-a2b6-c98bbdfaee93)
--
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]