feature (console): add a feature flag to enable BigQuery in the nav tree

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7566
GitOrigin-RevId: 72b7ac1775efaae40686bc8b91fe7d07d6de7513
This commit is contained in:
Vijay Prasanna 2023-01-18 21:52:23 +05:30 committed by hasura-bot
parent 40bcd5545b
commit 200f2bab7a
4 changed files with 109 additions and 75 deletions

View File

@ -23,6 +23,10 @@ import { Button } from '@/new-components/Button';
import styles from '../../Common/Layout/LeftSubSidebar/LeftSubSidebar.module.scss';
import Spinner from '../../Common/Spinner/Spinner';
import { useGDCTreeItemClick } from './GDCTree/hooks/useGDCTreeItemClick';
import {
availableFeatureFlagIds,
useIsFeatureFlagEnabled,
} from '@/features/FeatureFlags';
const DATA_SIDEBAR_SET_LOADING = 'dataSidebar/DATA_SIDEBAR_SET_LOADING';
@ -83,6 +87,9 @@ const DataSubSidebar = props => {
const [schemaLoading, setSchemaLoading] = useState(false);
const [isFetching, setIsFetching] = useState(false);
const [preLoadState, setPreLoadState] = useState(true);
const { enabled: isBigQueryEnabled } = useIsFeatureFlagEnabled(
availableFeatureFlagIds.enabledNewUIForBigQuery
);
const onDatabaseChange = newSourceName => {
if (newSourceName === currentDataSource) {
@ -122,82 +129,84 @@ const DataSubSidebar = props => {
const getItems = (schemaInfo = null) => {
let sourceItems = [];
sources.forEach(source => {
if (isInconsistentSource(source.name, inconsistentObjects)) return;
sources
.filter(source => !isBigQueryEnabled || source.kind !== 'bigquery')
.forEach(source => {
if (isInconsistentSource(source.name, inconsistentObjects)) return;
const sourceItem = { name: source.name, type: 'database' };
const sourceTables = !source.tables
? []
: source.tables.map(data => {
const is_enum = data.is_enum ? true : false;
return {
name: data.table.name,
schema: data.table.schema,
type: 'table',
is_enum: is_enum,
};
});
const sourceFunctions = !source.functions
? []
: source.functions.map(data => ({
name: data.function.name,
schema: data.function.schema,
type: 'function',
}));
const schemaGroups = groupByKey(
[...sourceTables, ...sourceFunctions],
'schema'
);
// Find out the difference between schemas from metadata and SchemaList from state
const schemasFromMetadata = Array.from(
new Set([
...sourceTables.map(i => i.schema),
...sourceFunctions.map(i => i.schema),
])
);
const missingSchemas = schemaList.filter(
x => !schemasFromMetadata.includes(x)
);
let schemaItems = [];
Object.keys(schemaGroups).forEach(schema => {
const schemaItem = { name: schema, type: 'schema' };
const tableItems = [];
schemaGroups[schema].forEach(table => {
const is_view =
schemaInfo?.[source.name]?.[schema]?.[table.name]?.table_type ===
'view' ||
schemaInfo?.[source.name]?.[schema]?.[table.name]?.table_type ===
'materialized_view';
let type = table.type;
if (is_view) type = 'view';
if (table.is_enum) type = 'enum';
tableItems.push({
name: table.name,
type: type,
const sourceItem = { name: source.name, type: 'database' };
const sourceTables = !source.tables
? []
: source.tables.map(data => {
const is_enum = data.is_enum ? true : false;
return {
name: data.table.name,
schema: data.table.schema,
type: 'table',
is_enum: is_enum,
};
});
const sourceFunctions = !source.functions
? []
: source.functions.map(data => ({
name: data.function.name,
schema: data.function.schema,
type: 'function',
}));
const schemaGroups = groupByKey(
[...sourceTables, ...sourceFunctions],
'schema'
);
// Find out the difference between schemas from metadata and SchemaList from state
const schemasFromMetadata = Array.from(
new Set([
...sourceTables.map(i => i.schema),
...sourceFunctions.map(i => i.schema),
])
);
const missingSchemas = schemaList.filter(
x => !schemasFromMetadata.includes(x)
);
let schemaItems = [];
Object.keys(schemaGroups).forEach(schema => {
const schemaItem = { name: schema, type: 'schema' };
const tableItems = [];
schemaGroups[schema].forEach(table => {
const is_view =
schemaInfo?.[source.name]?.[schema]?.[table.name]?.table_type ===
'view' ||
schemaInfo?.[source.name]?.[schema]?.[table.name]?.table_type ===
'materialized_view';
let type = table.type;
if (is_view) type = 'view';
if (table.is_enum) type = 'enum';
tableItems.push({
name: table.name,
type: type,
});
});
schemaItem.children = tableItems;
schemaItems = [...schemaItems, schemaItem];
});
schemaItem.children = tableItems;
schemaItems = [...schemaItems, schemaItem];
sourceItem.children = schemaItems;
if (source.name === currentDataSource) {
sourceItem.children = [
...missingSchemas.map(schemaName => ({
name: schemaName,
type: 'schema',
children: [],
})),
...sourceItem.children,
];
}
sourceItems = [...sourceItems, sourceItem];
});
sourceItem.children = schemaItems;
if (source.name === currentDataSource) {
sourceItem.children = [
...missingSchemas.map(schemaName => ({
name: schemaName,
type: 'schema',
children: [],
})),
...sourceItem.children,
];
}
sourceItems = [...sourceItems, sourceItem];
});
return sourceItems;
};

View File

@ -1,5 +1,9 @@
import { DEFAULT_STALE_TIME } from '@/features/DatabaseRelationships';
import { DataSource, nativeDrivers } from '@/features/DataSource';
import {
availableFeatureFlagIds,
useIsFeatureFlagEnabled,
} from '@/features/FeatureFlags';
import { useMetadata } from '@/features/hasura-metadata-api';
import { useHttpClient } from '@/features/Network';
import { DataNode } from 'antd/lib/tree';
@ -11,6 +15,8 @@ const isValueDataNode = (value: DataNode | null): value is DataNode =>
export const useTreeData = () => {
const httpClient = useHttpClient();
const { data: metadata, isFetching } = useMetadata();
const { enabled: isBigQueryEnabled, isLoading: isFeatureFlagsLoading } =
useIsFeatureFlagEnabled(availableFeatureFlagIds.enabledNewUIForBigQuery);
return useQuery({
queryKey: ['treeview'],
@ -21,7 +27,11 @@ export const useTreeData = () => {
/**
* NOTE: this filter prevents native drivers from being part of the new tree
*/
.filter(source => !nativeDrivers.includes(source.kind))
.filter(
source =>
!nativeDrivers.includes(source.kind) ||
(isBigQueryEnabled && source.kind === 'bigquery')
)
.map(async source => {
const tablesAsTree = await DataSource(
httpClient
@ -35,7 +45,7 @@ export const useTreeData = () => {
return filteredResult;
},
enabled: !isFetching,
enabled: !isFetching && !isFeatureFlagsLoading,
refetchOnWindowFocus: false,
staleTime: DEFAULT_STALE_TIME,
});

View File

@ -412,6 +412,10 @@ const TreeView: React.FC<TreeViewProps> = ({
availableFeatureFlagIds.gdcId
);
const { enabled: isBigQueryEnabled } = useIsFeatureFlagEnabled(
availableFeatureFlagIds.enabledNewUIForBigQuery
);
if (items.length === 0 && !isGDCTreeViewEnabled) {
return preLoadState ? (
<div className={styles.treeNav}>
@ -456,7 +460,7 @@ const TreeView: React.FC<TreeViewProps> = ({
schemaLoading={schemaLoading}
/>
))}
{isGDCTreeViewEnabled ? (
{isGDCTreeViewEnabled || isBigQueryEnabled ? (
<div id="tree-container" className="inline-block">
<GDCTree onSelect={gdcItemClick} />
</div>

View File

@ -4,11 +4,13 @@ import { FeatureFlagDefinition } from './types';
const relationshipTabTablesId = '0bea35ff-d3e9-45e9-af1b-59923bf82fa9';
const gdcId = '88436c32-2798-11ed-a261-0242ac120002';
const importActionFromOpenApiId = '12e5aaf4-c794-4b8f-b762-5fda0bff946a';
const enabledNewUIForBigQuery = 'e2d790ba-96fb-11ed-a8fc-0242ac120002';
export const availableFeatureFlagIds = {
relationshipTabTablesId,
gdcId,
importActionFromOpenApiId,
enabledNewUIForBigQuery,
};
const importActionFromOpenApi: FeatureFlagDefinition = {
@ -43,6 +45,15 @@ export const availableFeatureFlags: FeatureFlagDefinition[] = [
defaultValue: false,
discussionUrl: '',
},
{
id: enabledNewUIForBigQuery,
title: 'Enable the revamped UI for BigQuery',
description: 'Try out the new UI experience for BigQuery.',
section: 'data',
status: 'experimental',
defaultValue: false,
discussionUrl: '',
},
// eslint-disable-next-line no-underscore-dangle
...(isProConsole(window.__env) ? [importActionFromOpenApi] : []),
];