mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-10-05 06:18:04 +03:00
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:
parent
40bcd5545b
commit
200f2bab7a
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
});
|
||||
|
@ -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>
|
||||
|
@ -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] : []),
|
||||
];
|
||||
|
Loading…
Reference in New Issue
Block a user