mirror of
https://github.com/apache/superset.git
synced 2026-04-16 22:55:52 +00:00
fix: Badge count in folders editor (#38100)
This commit is contained in:
committed by
GitHub
parent
e12140beb6
commit
86c8fa5cd7
@@ -29,6 +29,9 @@ export const DEFAULT_METRICS_FOLDER_UUID =
|
||||
export const DEFAULT_COLUMNS_FOLDER_UUID =
|
||||
'83a7ae8f-2e8a-4f2b-a8cb-ebaebef95b9b';
|
||||
|
||||
// Number of default folders (Metrics, Columns)
|
||||
export const DEFAULT_FOLDERS_COUNT = 2;
|
||||
|
||||
// Drag & drop constants
|
||||
export const DRAG_INDENTATION_WIDTH = 64;
|
||||
export const MAX_DEPTH = 3;
|
||||
|
||||
@@ -28,8 +28,10 @@ import {
|
||||
removeChildrenOf,
|
||||
serializeForAPI,
|
||||
getProjection,
|
||||
countAllFolders,
|
||||
} from './treeUtils';
|
||||
import { FoldersEditorItemType } from '../types';
|
||||
import { DatasourceFolder } from 'src/explore/components/DatasourcePanel/types';
|
||||
|
||||
const createMetricItem = (uuid: string, name: string): TreeItem => ({
|
||||
uuid,
|
||||
@@ -667,3 +669,60 @@ test('getProjection nests item under folder when dragging down with offset', ()
|
||||
expect(projection!.depth).toBe(1);
|
||||
expect(projection!.parentId).toBe('folder1');
|
||||
});
|
||||
|
||||
test('countAllFolders returns 0 for empty array', () => {
|
||||
expect(countAllFolders([])).toBe(0);
|
||||
});
|
||||
|
||||
test('countAllFolders counts flat folders', () => {
|
||||
const folders: DatasourceFolder[] = [
|
||||
createFolderItem('f1', 'Metrics', [createMetricItem('m1', 'Metric 1')]),
|
||||
createFolderItem('f2', 'Columns', [createColumnItem('c1', 'Column 1')]),
|
||||
] as DatasourceFolder[];
|
||||
|
||||
expect(countAllFolders(folders)).toBe(2);
|
||||
});
|
||||
|
||||
test('countAllFolders counts nested folders recursively', () => {
|
||||
const folders: DatasourceFolder[] = [
|
||||
createFolderItem('metrics', 'Metrics', [
|
||||
createMetricItem('m1', 'Metric 1'),
|
||||
]),
|
||||
createFolderItem('columns', 'Columns', [
|
||||
createColumnItem('c1', 'Column 1'),
|
||||
]),
|
||||
createFolderItem('custom', 'Custom Folder', [
|
||||
createFolderItem('nested', 'Nested Folder', [
|
||||
createMetricItem('m2', 'Metric 2'),
|
||||
]),
|
||||
]),
|
||||
] as DatasourceFolder[];
|
||||
|
||||
expect(countAllFolders(folders)).toBe(4);
|
||||
});
|
||||
|
||||
test('countAllFolders counts deeply nested folders', () => {
|
||||
const folders: DatasourceFolder[] = [
|
||||
createFolderItem('level0', 'Level 0', [
|
||||
createFolderItem('level1', 'Level 1', [
|
||||
createFolderItem('level2', 'Level 2', [
|
||||
createMetricItem('m1', 'Metric 1'),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
] as DatasourceFolder[];
|
||||
|
||||
expect(countAllFolders(folders)).toBe(3);
|
||||
});
|
||||
|
||||
test('countAllFolders ignores non-folder children', () => {
|
||||
const folders: DatasourceFolder[] = [
|
||||
createFolderItem('f1', 'Folder', [
|
||||
createMetricItem('m1', 'Metric 1'),
|
||||
createColumnItem('c1', 'Column 1'),
|
||||
createMetricItem('m2', 'Metric 2'),
|
||||
]),
|
||||
] as DatasourceFolder[];
|
||||
|
||||
expect(countAllFolders(folders)).toBe(1);
|
||||
});
|
||||
|
||||
@@ -330,3 +330,22 @@ export function serializeForAPI(items: TreeItem[]): DatasourceFolder[] {
|
||||
})
|
||||
.filter((folder): folder is DatasourceFolder => folder !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively counts all folders in a DatasourceFolder array,
|
||||
* including nested sub-folders within children.
|
||||
*/
|
||||
export function countAllFolders(folders: DatasourceFolder[]): number {
|
||||
let count = 0;
|
||||
for (const folder of folders) {
|
||||
count += 1;
|
||||
if (folder.children) {
|
||||
for (const child of folder.children) {
|
||||
if ('children' in child) {
|
||||
count += countAllFolders([child as DatasourceFolder]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -91,9 +91,11 @@ import { fetchSyncedColumns, updateColumns } from '../../utils';
|
||||
import DatasetUsageTab from './components/DatasetUsageTab';
|
||||
import {
|
||||
DEFAULT_COLUMNS_FOLDER_UUID,
|
||||
DEFAULT_FOLDERS_COUNT,
|
||||
DEFAULT_METRICS_FOLDER_UUID,
|
||||
} from '../../FoldersEditor/constants';
|
||||
import { validateFolders } from '../../FoldersEditor/folderValidation';
|
||||
import { countAllFolders } from '../../FoldersEditor/treeUtils';
|
||||
import FoldersEditor from '../../FoldersEditor';
|
||||
import { DatasourceFolder } from 'src/explore/components/DatasourcePanel/types';
|
||||
|
||||
@@ -266,6 +268,7 @@ interface DatasourceEditorState {
|
||||
databaseColumns: Column[];
|
||||
calculatedColumns: Column[];
|
||||
folders: DatasourceFolder[];
|
||||
folderCount: number;
|
||||
metadataLoading: boolean;
|
||||
activeTabKey: string;
|
||||
datasourceType: string;
|
||||
@@ -284,6 +287,7 @@ interface AbortControllers {
|
||||
interface CollectionTabTitleProps {
|
||||
title: string;
|
||||
collection?: unknown[] | { length: number };
|
||||
count?: number;
|
||||
}
|
||||
|
||||
interface ColumnCollectionTableProps {
|
||||
@@ -458,6 +462,7 @@ DATASOURCE_TYPES_ARR.forEach(o => {
|
||||
function CollectionTabTitle({
|
||||
title,
|
||||
collection,
|
||||
count,
|
||||
}: CollectionTabTitleProps): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
@@ -465,7 +470,10 @@ function CollectionTabTitle({
|
||||
data-test={`collection-tab-${title}`}
|
||||
>
|
||||
{title}{' '}
|
||||
<StyledBadge count={collection ? collection.length : 0} showZero />
|
||||
<StyledBadge
|
||||
count={count ?? (collection ? collection.length : 0)}
|
||||
showZero
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -905,6 +913,8 @@ class DatasourceEditor extends PureComponent<
|
||||
col => !!col.expression,
|
||||
),
|
||||
folders: props.datasource.folders || [],
|
||||
folderCount:
|
||||
countAllFolders(props.datasource.folders || []) + DEFAULT_FOLDERS_COUNT,
|
||||
metadataLoading: false,
|
||||
activeTabKey: TABS_KEYS.SOURCE,
|
||||
datasourceType: props.datasource.sql
|
||||
@@ -988,13 +998,14 @@ class DatasourceEditor extends PureComponent<
|
||||
}
|
||||
|
||||
handleFoldersChange(folders: DatasourceFolder[]) {
|
||||
const folderCount = countAllFolders(folders);
|
||||
const userMadeFolders = folders.filter(
|
||||
f =>
|
||||
f.uuid !== DEFAULT_METRICS_FOLDER_UUID &&
|
||||
f.uuid !== DEFAULT_COLUMNS_FOLDER_UUID &&
|
||||
(f.children?.length ?? 0) > 0,
|
||||
);
|
||||
this.setState({ folders: userMadeFolders }, () => {
|
||||
this.setState({ folders: userMadeFolders, folderCount }, () => {
|
||||
this.onDatasourceChange({
|
||||
...this.state.datasource,
|
||||
folders: userMadeFolders,
|
||||
@@ -2405,7 +2416,7 @@ class DatasourceEditor extends PureComponent<
|
||||
key: TABS_KEYS.FOLDERS,
|
||||
label: (
|
||||
<CollectionTabTitle
|
||||
collection={this.state.folders}
|
||||
count={this.state.folderCount}
|
||||
title={t('Folders')}
|
||||
/>
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user