mirror of
https://github.com/datahub-project/datahub.git
synced 2025-08-30 12:06:00 +00:00
feat(customSearchCards): add descriptions (#14472)
Co-authored-by: Chris Collins <chriscollins3456@gmail.com>
This commit is contained in:
parent
b1d96ab3bb
commit
3fe39bf149
@ -314,15 +314,7 @@ import com.linkedin.datahub.graphql.types.view.DataHubViewType;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.entity.client.SystemEntityClient;
|
||||
import com.linkedin.metadata.client.UsageStatsJavaClient;
|
||||
import com.linkedin.metadata.config.ChromeExtensionConfiguration;
|
||||
import com.linkedin.metadata.config.DataHubConfiguration;
|
||||
import com.linkedin.metadata.config.GraphQLConfiguration;
|
||||
import com.linkedin.metadata.config.HomePageConfiguration;
|
||||
import com.linkedin.metadata.config.IngestionConfiguration;
|
||||
import com.linkedin.metadata.config.SearchBarConfiguration;
|
||||
import com.linkedin.metadata.config.TestsConfiguration;
|
||||
import com.linkedin.metadata.config.ViewsConfiguration;
|
||||
import com.linkedin.metadata.config.VisualConfiguration;
|
||||
import com.linkedin.metadata.config.*;
|
||||
import com.linkedin.metadata.config.telemetry.TelemetryConfiguration;
|
||||
import com.linkedin.metadata.connection.ConnectionService;
|
||||
import com.linkedin.metadata.entity.EntityService;
|
||||
@ -433,6 +425,7 @@ public class GmsGraphQLEngine {
|
||||
private final DataHubConfiguration datahubConfiguration;
|
||||
private final ViewsConfiguration viewsConfiguration;
|
||||
private final SearchBarConfiguration searchBarConfiguration;
|
||||
private final SearchCardConfiguration searchCardConfiguration;
|
||||
private final HomePageConfiguration homePageConfiguration;
|
||||
private final ChromeExtensionConfiguration chromeExtensionConfiguration;
|
||||
|
||||
@ -567,6 +560,7 @@ public class GmsGraphQLEngine {
|
||||
this.datahubConfiguration = args.datahubConfiguration;
|
||||
this.viewsConfiguration = args.viewsConfiguration;
|
||||
this.searchBarConfiguration = args.searchBarConfiguration;
|
||||
this.searchCardConfiguration = args.searchCardConfiguration;
|
||||
this.homePageConfiguration = args.homePageConfiguration;
|
||||
this.featureFlags = args.featureFlags;
|
||||
this.chromeExtensionConfiguration = args.chromeExtensionConfiguration;
|
||||
@ -972,6 +966,7 @@ public class GmsGraphQLEngine {
|
||||
this.datahubConfiguration,
|
||||
this.viewsConfiguration,
|
||||
this.searchBarConfiguration,
|
||||
this.searchCardConfiguration,
|
||||
this.homePageConfiguration,
|
||||
this.featureFlags,
|
||||
this.chromeExtensionConfiguration,
|
||||
|
@ -13,15 +13,7 @@ import com.linkedin.datahub.graphql.featureflags.FeatureFlags;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.entity.client.SystemEntityClient;
|
||||
import com.linkedin.metadata.client.UsageStatsJavaClient;
|
||||
import com.linkedin.metadata.config.ChromeExtensionConfiguration;
|
||||
import com.linkedin.metadata.config.DataHubConfiguration;
|
||||
import com.linkedin.metadata.config.GraphQLConfiguration;
|
||||
import com.linkedin.metadata.config.HomePageConfiguration;
|
||||
import com.linkedin.metadata.config.IngestionConfiguration;
|
||||
import com.linkedin.metadata.config.SearchBarConfiguration;
|
||||
import com.linkedin.metadata.config.TestsConfiguration;
|
||||
import com.linkedin.metadata.config.ViewsConfiguration;
|
||||
import com.linkedin.metadata.config.VisualConfiguration;
|
||||
import com.linkedin.metadata.config.*;
|
||||
import com.linkedin.metadata.config.telemetry.TelemetryConfiguration;
|
||||
import com.linkedin.metadata.connection.ConnectionService;
|
||||
import com.linkedin.metadata.entity.EntityService;
|
||||
@ -77,6 +69,7 @@ public class GmsGraphQLEngineArgs {
|
||||
DataHubConfiguration datahubConfiguration;
|
||||
ViewsConfiguration viewsConfiguration;
|
||||
SearchBarConfiguration searchBarConfiguration;
|
||||
SearchCardConfiguration searchCardConfiguration;
|
||||
HomePageConfiguration homePageConfiguration;
|
||||
SiblingGraphService siblingGraphService;
|
||||
GroupService groupService;
|
||||
|
@ -4,40 +4,11 @@ import com.datahub.authentication.AuthenticationConfiguration;
|
||||
import com.datahub.authorization.AuthorizationConfiguration;
|
||||
import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.featureflags.FeatureFlags;
|
||||
import com.linkedin.datahub.graphql.generated.AnalyticsConfig;
|
||||
import com.linkedin.datahub.graphql.generated.AppConfig;
|
||||
import com.linkedin.datahub.graphql.generated.*;
|
||||
import com.linkedin.datahub.graphql.generated.ApplicationConfig;
|
||||
import com.linkedin.datahub.graphql.generated.AuthConfig;
|
||||
import com.linkedin.datahub.graphql.generated.ChromeExtensionConfig;
|
||||
import com.linkedin.datahub.graphql.generated.EntityProfileConfig;
|
||||
import com.linkedin.datahub.graphql.generated.EntityProfilesConfig;
|
||||
import com.linkedin.datahub.graphql.generated.EntityType;
|
||||
import com.linkedin.datahub.graphql.generated.FeatureFlagsConfig;
|
||||
import com.linkedin.datahub.graphql.generated.HomePageConfig;
|
||||
import com.linkedin.datahub.graphql.generated.IdentityManagementConfig;
|
||||
import com.linkedin.datahub.graphql.generated.LineageConfig;
|
||||
import com.linkedin.datahub.graphql.generated.ManagedIngestionConfig;
|
||||
import com.linkedin.datahub.graphql.generated.PersonalSidebarSection;
|
||||
import com.linkedin.datahub.graphql.generated.PoliciesConfig;
|
||||
import com.linkedin.datahub.graphql.generated.Privilege;
|
||||
import com.linkedin.datahub.graphql.generated.QueriesTabConfig;
|
||||
import com.linkedin.datahub.graphql.generated.ResourcePrivileges;
|
||||
import com.linkedin.datahub.graphql.generated.SearchBarAPI;
|
||||
import com.linkedin.datahub.graphql.generated.SearchBarConfig;
|
||||
import com.linkedin.datahub.graphql.generated.SearchResultsVisualConfig;
|
||||
import com.linkedin.datahub.graphql.generated.TelemetryConfig;
|
||||
import com.linkedin.datahub.graphql.generated.TestsConfig;
|
||||
import com.linkedin.datahub.graphql.generated.ThemeConfig;
|
||||
import com.linkedin.datahub.graphql.generated.ViewsConfig;
|
||||
import com.linkedin.datahub.graphql.generated.VisualConfig;
|
||||
import com.linkedin.metadata.config.ChromeExtensionConfiguration;
|
||||
import com.linkedin.metadata.config.DataHubConfiguration;
|
||||
import com.linkedin.metadata.config.HomePageConfiguration;
|
||||
import com.linkedin.metadata.config.IngestionConfiguration;
|
||||
import com.linkedin.metadata.config.SearchBarConfiguration;
|
||||
import com.linkedin.metadata.config.TestsConfiguration;
|
||||
import com.linkedin.metadata.config.ViewsConfiguration;
|
||||
import com.linkedin.metadata.config.VisualConfiguration;
|
||||
import com.linkedin.metadata.config.*;
|
||||
import com.linkedin.metadata.config.telemetry.TelemetryConfiguration;
|
||||
import com.linkedin.metadata.service.SettingsService;
|
||||
import com.linkedin.metadata.version.GitVersion;
|
||||
@ -64,6 +35,7 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
|
||||
private final DataHubConfiguration _datahubConfiguration;
|
||||
private final ViewsConfiguration _viewsConfiguration;
|
||||
private final SearchBarConfiguration _searchBarConfig;
|
||||
private final SearchCardConfiguration _searchCardConfig;
|
||||
private final HomePageConfiguration _homePageConfig;
|
||||
private final FeatureFlags _featureFlags;
|
||||
private final ChromeExtensionConfiguration _chromeExtensionConfiguration;
|
||||
@ -82,6 +54,7 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
|
||||
final DataHubConfiguration datahubConfiguration,
|
||||
final ViewsConfiguration viewsConfiguration,
|
||||
final SearchBarConfiguration searchBarConfig,
|
||||
final SearchCardConfiguration searchCardConfig,
|
||||
final HomePageConfiguration homePageConfig,
|
||||
final FeatureFlags featureFlags,
|
||||
final ChromeExtensionConfiguration chromeExtensionConfiguration,
|
||||
@ -98,6 +71,7 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
|
||||
_datahubConfiguration = datahubConfiguration;
|
||||
_viewsConfiguration = viewsConfiguration;
|
||||
_searchBarConfig = searchBarConfig;
|
||||
_searchCardConfig = searchCardConfig;
|
||||
_homePageConfig = homePageConfig;
|
||||
_featureFlags = featureFlags;
|
||||
_chromeExtensionConfiguration = chromeExtensionConfiguration;
|
||||
@ -233,6 +207,10 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
|
||||
}
|
||||
appConfig.setSearchBarConfig(searchBarConfig);
|
||||
|
||||
final SearchCardConfig searchCardConfig = new SearchCardConfig();
|
||||
searchCardConfig.setShowDescription(_searchCardConfig.getShowDescription());
|
||||
appConfig.setSearchCardConfig(searchCardConfig);
|
||||
|
||||
final HomePageConfig homePageConfig = new HomePageConfig();
|
||||
try {
|
||||
homePageConfig.setFirstInPersonalSidebar(
|
||||
|
@ -217,6 +217,16 @@ type SearchBarConfig {
|
||||
apiVariant: SearchBarAPI!
|
||||
}
|
||||
|
||||
"""
|
||||
Configurations related to the Search card
|
||||
"""
|
||||
type SearchCardConfig {
|
||||
"""
|
||||
Whether the search card should show description
|
||||
"""
|
||||
showDescription: Boolean!
|
||||
}
|
||||
|
||||
"""
|
||||
Variants of APIs used in the Search bar to get data
|
||||
"""
|
||||
@ -318,6 +328,11 @@ type AppConfig {
|
||||
"""
|
||||
searchBarConfig: SearchBarConfig!
|
||||
|
||||
"""
|
||||
Configurations related to the Search card
|
||||
"""
|
||||
searchCardConfig: SearchCardConfig!
|
||||
|
||||
"""
|
||||
Feature flags telling the UI whether a feature is enabled or not
|
||||
"""
|
||||
|
@ -0,0 +1,411 @@
|
||||
package com.linkedin.datahub.graphql.resolvers.config;
|
||||
|
||||
import static com.linkedin.datahub.graphql.TestUtils.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import com.datahub.authentication.AuthenticationConfiguration;
|
||||
import com.datahub.authorization.AuthorizationConfiguration;
|
||||
import com.datahub.authorization.DefaultAuthorizerConfiguration;
|
||||
import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.featureflags.FeatureFlags;
|
||||
import com.linkedin.datahub.graphql.generated.AppConfig;
|
||||
import com.linkedin.datahub.graphql.generated.PersonalSidebarSection;
|
||||
import com.linkedin.datahub.graphql.generated.SearchBarAPI;
|
||||
import com.linkedin.metadata.config.*;
|
||||
import com.linkedin.metadata.config.telemetry.TelemetryConfiguration;
|
||||
import com.linkedin.metadata.service.SettingsService;
|
||||
import com.linkedin.metadata.version.GitVersion;
|
||||
import com.linkedin.settings.global.ApplicationsSettings;
|
||||
import com.linkedin.settings.global.GlobalSettingsInfo;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class AppConfigResolverTest {
|
||||
|
||||
@Mock private GitVersion mockGitVersion;
|
||||
@Mock private IngestionConfiguration mockIngestionConfiguration;
|
||||
@Mock private AuthenticationConfiguration mockAuthenticationConfiguration;
|
||||
@Mock private AuthorizationConfiguration mockAuthorizationConfiguration;
|
||||
@Mock private DefaultAuthorizerConfiguration mockDefaultAuthorizer;
|
||||
@Mock private VisualConfiguration mockVisualConfiguration;
|
||||
@Mock private TelemetryConfiguration mockTelemetryConfiguration;
|
||||
@Mock private TestsConfiguration mockTestsConfiguration;
|
||||
@Mock private DataHubConfiguration mockDatahubConfiguration;
|
||||
@Mock private ViewsConfiguration mockViewsConfiguration;
|
||||
@Mock private SearchBarConfiguration mockSearchBarConfiguration;
|
||||
@Mock private SearchCardConfiguration mockSearchCardConfiguration;
|
||||
@Mock private HomePageConfiguration mockHomePageConfiguration;
|
||||
@Mock private FeatureFlags mockFeatureFlags;
|
||||
@Mock private ChromeExtensionConfiguration mockChromeExtensionConfiguration;
|
||||
@Mock private SettingsService mockSettingsService;
|
||||
@Mock private DataFetchingEnvironment mockDataFetchingEnvironment;
|
||||
@Mock private GlobalSettingsInfo mockGlobalSettingsInfo;
|
||||
|
||||
private AppConfigResolver resolver;
|
||||
private QueryContext mockContext;
|
||||
|
||||
@BeforeMethod
|
||||
public void setupTest() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
|
||||
mockContext = getMockAllowContext();
|
||||
when(mockDataFetchingEnvironment.getContext()).thenReturn(mockContext);
|
||||
|
||||
// Setup basic mock responses
|
||||
when(mockGitVersion.getVersion()).thenReturn("1.0.0");
|
||||
when(mockIngestionConfiguration.isEnabled()).thenReturn(true);
|
||||
when(mockAuthenticationConfiguration.isEnabled()).thenReturn(true);
|
||||
when(mockAuthorizationConfiguration.getDefaultAuthorizer()).thenReturn(mockDefaultAuthorizer);
|
||||
when(mockDefaultAuthorizer.isEnabled()).thenReturn(true);
|
||||
when(mockTelemetryConfiguration.isEnableThirdPartyLogging()).thenReturn(false);
|
||||
when(mockTestsConfiguration.isEnabled()).thenReturn(true);
|
||||
when(mockViewsConfiguration.isEnabled()).thenReturn(true);
|
||||
when(mockSearchBarConfiguration.getApiVariant()).thenReturn("AUTOCOMPLETE_FOR_MULTIPLE");
|
||||
when(mockSearchCardConfiguration.getShowDescription()).thenReturn(true);
|
||||
when(mockHomePageConfiguration.getFirstInPersonalSidebar()).thenReturn("YOUR_ASSETS");
|
||||
when(mockChromeExtensionConfiguration.isEnabled()).thenReturn(false);
|
||||
when(mockChromeExtensionConfiguration.isLineageEnabled()).thenReturn(false);
|
||||
|
||||
// Setup feature flags
|
||||
setupFeatureFlags();
|
||||
|
||||
resolver =
|
||||
new AppConfigResolver(
|
||||
mockGitVersion,
|
||||
true, // isAnalyticsEnabled
|
||||
mockIngestionConfiguration,
|
||||
mockAuthenticationConfiguration,
|
||||
mockAuthorizationConfiguration,
|
||||
true, // supportsImpactAnalysis
|
||||
mockVisualConfiguration,
|
||||
mockTelemetryConfiguration,
|
||||
mockTestsConfiguration,
|
||||
mockDatahubConfiguration,
|
||||
mockViewsConfiguration,
|
||||
mockSearchBarConfiguration,
|
||||
mockSearchCardConfiguration,
|
||||
mockHomePageConfiguration,
|
||||
mockFeatureFlags,
|
||||
mockChromeExtensionConfiguration,
|
||||
mockSettingsService);
|
||||
}
|
||||
|
||||
private void setupFeatureFlags() {
|
||||
when(mockFeatureFlags.isShowSearchFiltersV2()).thenReturn(false);
|
||||
when(mockFeatureFlags.isBusinessAttributeEntityEnabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isReadOnlyModeEnabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowBrowseV2()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowAcrylInfo()).thenReturn(false);
|
||||
when(mockFeatureFlags.isErModelRelationshipFeatureEnabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowAccessManagement()).thenReturn(false);
|
||||
when(mockFeatureFlags.isNestedDomainsEnabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isPlatformBrowseV2()).thenReturn(false);
|
||||
when(mockFeatureFlags.isDataContractsEnabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isEditableDatasetNameEnabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isThemeV2Enabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isThemeV2Default()).thenReturn(false);
|
||||
when(mockFeatureFlags.isThemeV2Toggleable()).thenReturn(false);
|
||||
when(mockFeatureFlags.isLineageGraphV2()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowSeparateSiblings()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowManageStructuredProperties()).thenReturn(false);
|
||||
when(mockFeatureFlags.isSchemaFieldCLLEnabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isHideDbtSourceInLineage()).thenReturn(false);
|
||||
when(mockFeatureFlags.isSchemaFieldLineageIgnoreStatus()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowNavBarRedesign()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowAutoCompleteResults()).thenReturn(false);
|
||||
when(mockFeatureFlags.isEntityVersioning()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowHasSiblingsFilter()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowSearchBarAutocompleteRedesign()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowManageTags()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowIntroducePage()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowIngestionPageRedesign()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowLineageExpandMore()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowStatsTabRedesign()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowHomePageRedesign()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowProductUpdates()).thenReturn(false);
|
||||
when(mockFeatureFlags.isLineageGraphV3()).thenReturn(false);
|
||||
when(mockFeatureFlags.isLogicalModelsEnabled()).thenReturn(false);
|
||||
when(mockFeatureFlags.isShowHomepageUserRole()).thenReturn(false);
|
||||
when(mockFeatureFlags.isAssetSummaryPageV1()).thenReturn(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBasicConfig() throws Exception {
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(result.getAppVersion(), "1.0.0");
|
||||
assertNotNull(result.getLineageConfig());
|
||||
assertTrue(result.getLineageConfig().getSupportsImpactAnalysis());
|
||||
assertNotNull(result.getAnalyticsConfig());
|
||||
assertTrue(result.getAnalyticsConfig().getEnabled());
|
||||
assertNotNull(result.getAuthConfig());
|
||||
assertTrue(result.getAuthConfig().getTokenAuthEnabled());
|
||||
assertNotNull(result.getPoliciesConfig());
|
||||
assertTrue(result.getPoliciesConfig().getEnabled());
|
||||
assertNotNull(result.getIdentityManagementConfig());
|
||||
assertTrue(result.getIdentityManagementConfig().getEnabled());
|
||||
assertNotNull(result.getManagedIngestionConfig());
|
||||
assertTrue(result.getManagedIngestionConfig().getEnabled());
|
||||
assertNotNull(result.getTelemetryConfig());
|
||||
assertFalse(result.getTelemetryConfig().getEnableThirdPartyLogging());
|
||||
assertNotNull(result.getTestsConfig());
|
||||
assertTrue(result.getTestsConfig().getEnabled());
|
||||
assertNotNull(result.getViewsConfig());
|
||||
assertTrue(result.getViewsConfig().getEnabled());
|
||||
assertNotNull(result.getSearchBarConfig());
|
||||
assertEquals(
|
||||
result.getSearchBarConfig().getApiVariant(), SearchBarAPI.AUTOCOMPLETE_FOR_MULTIPLE);
|
||||
assertNotNull(result.getSearchCardConfig());
|
||||
assertTrue(result.getSearchCardConfig().getShowDescription());
|
||||
assertNotNull(result.getHomePageConfig());
|
||||
assertEquals(
|
||||
result.getHomePageConfig().getFirstInPersonalSidebar(), PersonalSidebarSection.YOUR_ASSETS);
|
||||
assertNotNull(result.getFeatureFlags());
|
||||
assertNotNull(result.getChromeExtensionConfig());
|
||||
assertFalse(result.getChromeExtensionConfig().getEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithAnalyticsDisabled() throws Exception {
|
||||
resolver =
|
||||
new AppConfigResolver(
|
||||
mockGitVersion,
|
||||
false, // isAnalyticsEnabled
|
||||
mockIngestionConfiguration,
|
||||
mockAuthenticationConfiguration,
|
||||
mockAuthorizationConfiguration,
|
||||
true,
|
||||
mockVisualConfiguration,
|
||||
mockTelemetryConfiguration,
|
||||
mockTestsConfiguration,
|
||||
mockDatahubConfiguration,
|
||||
mockViewsConfiguration,
|
||||
mockSearchBarConfiguration,
|
||||
mockSearchCardConfiguration,
|
||||
mockHomePageConfiguration,
|
||||
mockFeatureFlags,
|
||||
mockChromeExtensionConfiguration,
|
||||
mockSettingsService);
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getAnalyticsConfig());
|
||||
assertFalse(result.getAnalyticsConfig().getEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithVisualConfiguration() throws Exception {
|
||||
AssetsConfiguration mockAssets = mock(AssetsConfiguration.class);
|
||||
QueriesTabConfig mockQueriesTab = mock(QueriesTabConfig.class);
|
||||
EntityProfileConfig mockEntityProfile = mock(EntityProfileConfig.class);
|
||||
SearchResultVisualConfig mockSearchResult = mock(SearchResultVisualConfig.class);
|
||||
ThemeConfiguration mockTheme = mock(ThemeConfiguration.class);
|
||||
|
||||
when(mockVisualConfiguration.getAssets()).thenReturn(mockAssets);
|
||||
when(mockAssets.getLogoUrl()).thenReturn("https://example.com/logo.png");
|
||||
when(mockAssets.getFaviconUrl()).thenReturn("https://example.com/favicon.ico");
|
||||
when(mockVisualConfiguration.getAppTitle()).thenReturn("Custom DataHub");
|
||||
when(mockVisualConfiguration.isHideGlossary()).thenReturn(true);
|
||||
when(mockVisualConfiguration.isShowFullTitleInLineage()).thenReturn(true);
|
||||
when(mockVisualConfiguration.getQueriesTab()).thenReturn(mockQueriesTab);
|
||||
when(mockQueriesTab.getQueriesTabResultSize()).thenReturn(20);
|
||||
when(mockVisualConfiguration.getEntityProfile()).thenReturn(mockEntityProfile);
|
||||
when(mockEntityProfile.getDomainDefaultTab()).thenReturn("DOCUMENTATION");
|
||||
when(mockVisualConfiguration.getSearchResult()).thenReturn(mockSearchResult);
|
||||
when(mockSearchResult.getEnableNameHighlight()).thenReturn(true);
|
||||
when(mockVisualConfiguration.getTheme()).thenReturn(mockTheme);
|
||||
when(mockTheme.getThemeId()).thenReturn("dark");
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getVisualConfig());
|
||||
assertEquals(result.getVisualConfig().getLogoUrl(), "https://example.com/logo.png");
|
||||
assertEquals(result.getVisualConfig().getFaviconUrl(), "https://example.com/favicon.ico");
|
||||
assertEquals(result.getVisualConfig().getAppTitle(), "Custom DataHub");
|
||||
assertTrue(result.getVisualConfig().getHideGlossary());
|
||||
assertTrue(result.getVisualConfig().getShowFullTitleInLineage());
|
||||
assertNotNull(result.getVisualConfig().getQueriesTab());
|
||||
assertEquals(
|
||||
result.getVisualConfig().getQueriesTab().getQueriesTabResultSize(), Integer.valueOf(20));
|
||||
assertNotNull(result.getVisualConfig().getEntityProfiles());
|
||||
assertNotNull(result.getVisualConfig().getEntityProfiles().getDomain());
|
||||
assertEquals(
|
||||
result.getVisualConfig().getEntityProfiles().getDomain().getDefaultTab(), "DOCUMENTATION");
|
||||
assertNotNull(result.getVisualConfig().getSearchResult());
|
||||
assertTrue(result.getVisualConfig().getSearchResult().getEnableNameHighlight());
|
||||
assertNotNull(result.getVisualConfig().getTheme());
|
||||
assertEquals(result.getVisualConfig().getTheme().getThemeId(), "dark");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithApplicationsEnabled() throws Exception {
|
||||
ApplicationsSettings mockApplications = mock(ApplicationsSettings.class);
|
||||
when(mockGlobalSettingsInfo.hasApplications()).thenReturn(true);
|
||||
when(mockGlobalSettingsInfo.getApplications()).thenReturn(mockApplications);
|
||||
when(mockApplications.hasEnabled()).thenReturn(true);
|
||||
when(mockApplications.isEnabled()).thenReturn(true);
|
||||
when(mockSettingsService.getGlobalSettings(any())).thenReturn(mockGlobalSettingsInfo);
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getVisualConfig());
|
||||
assertNotNull(result.getVisualConfig().getApplication());
|
||||
assertTrue(result.getVisualConfig().getApplication().getShowApplicationInNavigation());
|
||||
assertTrue(result.getVisualConfig().getApplication().getShowSidebarSectionWhenEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithApplicationsDisabled() throws Exception {
|
||||
ApplicationsSettings mockApplications = mock(ApplicationsSettings.class);
|
||||
when(mockGlobalSettingsInfo.hasApplications()).thenReturn(true);
|
||||
when(mockGlobalSettingsInfo.getApplications()).thenReturn(mockApplications);
|
||||
when(mockApplications.hasEnabled()).thenReturn(true);
|
||||
when(mockApplications.isEnabled()).thenReturn(false);
|
||||
when(mockSettingsService.getGlobalSettings(any())).thenReturn(mockGlobalSettingsInfo);
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getVisualConfig());
|
||||
assertNotNull(result.getVisualConfig().getApplication());
|
||||
assertFalse(result.getVisualConfig().getApplication().getShowApplicationInNavigation());
|
||||
assertFalse(result.getVisualConfig().getApplication().getShowSidebarSectionWhenEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithNullGlobalSettings() throws Exception {
|
||||
when(mockSettingsService.getGlobalSettings(any())).thenReturn(null);
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getVisualConfig());
|
||||
assertNotNull(result.getVisualConfig().getApplication());
|
||||
assertFalse(result.getVisualConfig().getApplication().getShowApplicationInNavigation());
|
||||
assertFalse(result.getVisualConfig().getApplication().getShowSidebarSectionWhenEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithSearchCardDescriptionDisabled() throws Exception {
|
||||
when(mockSearchCardConfiguration.getShowDescription()).thenReturn(false);
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getSearchCardConfig());
|
||||
assertFalse(result.getSearchCardConfig().getShowDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithFeatureFlagsEnabled() throws Exception {
|
||||
// Enable some feature flags
|
||||
when(mockFeatureFlags.isShowSearchFiltersV2()).thenReturn(true);
|
||||
when(mockFeatureFlags.isBusinessAttributeEntityEnabled()).thenReturn(true);
|
||||
when(mockFeatureFlags.isReadOnlyModeEnabled()).thenReturn(true);
|
||||
when(mockFeatureFlags.isThemeV2Enabled()).thenReturn(true);
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getFeatureFlags());
|
||||
assertTrue(result.getFeatureFlags().getShowSearchFiltersV2());
|
||||
assertTrue(result.getFeatureFlags().getBusinessAttributeEntityEnabled());
|
||||
assertTrue(result.getFeatureFlags().getReadOnlyModeEnabled());
|
||||
assertTrue(result.getFeatureFlags().getThemeV2Enabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithInvalidSearchBarAPI() throws Exception {
|
||||
when(mockSearchBarConfiguration.getApiVariant()).thenReturn("INVALID_API");
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getSearchBarConfig());
|
||||
assertEquals(
|
||||
result.getSearchBarConfig().getApiVariant(), SearchBarAPI.AUTOCOMPLETE_FOR_MULTIPLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithInvalidPersonalSidebarSection() throws Exception {
|
||||
when(mockHomePageConfiguration.getFirstInPersonalSidebar()).thenReturn("INVALID_SECTION");
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getHomePageConfig());
|
||||
assertEquals(
|
||||
result.getHomePageConfig().getFirstInPersonalSidebar(), PersonalSidebarSection.YOUR_ASSETS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithNullSettingsService() throws Exception {
|
||||
resolver =
|
||||
new AppConfigResolver(
|
||||
mockGitVersion,
|
||||
true,
|
||||
mockIngestionConfiguration,
|
||||
mockAuthenticationConfiguration,
|
||||
mockAuthorizationConfiguration,
|
||||
true,
|
||||
mockVisualConfiguration,
|
||||
mockTelemetryConfiguration,
|
||||
mockTestsConfiguration,
|
||||
mockDatahubConfiguration,
|
||||
mockViewsConfiguration,
|
||||
mockSearchBarConfiguration,
|
||||
mockSearchCardConfiguration,
|
||||
mockHomePageConfiguration,
|
||||
mockFeatureFlags,
|
||||
mockChromeExtensionConfiguration,
|
||||
null // null settings service
|
||||
);
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.getVisualConfig());
|
||||
// Should not crash and should handle null settings service gracefully
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConfigWithNullVisualConfiguration() throws Exception {
|
||||
resolver =
|
||||
new AppConfigResolver(
|
||||
mockGitVersion,
|
||||
true,
|
||||
mockIngestionConfiguration,
|
||||
mockAuthenticationConfiguration,
|
||||
mockAuthorizationConfiguration,
|
||||
true,
|
||||
null, // null visual configuration
|
||||
mockTelemetryConfiguration,
|
||||
mockTestsConfiguration,
|
||||
mockDatahubConfiguration,
|
||||
mockViewsConfiguration,
|
||||
mockSearchBarConfiguration,
|
||||
mockSearchCardConfiguration,
|
||||
mockHomePageConfiguration,
|
||||
mockFeatureFlags,
|
||||
mockChromeExtensionConfiguration,
|
||||
mockSettingsService);
|
||||
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result);
|
||||
assertNotNull(result.getVisualConfig());
|
||||
// Should handle null visual configuration gracefully
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPoliciesConfigMapping() throws Exception {
|
||||
AppConfig result = resolver.get(mockDataFetchingEnvironment).get();
|
||||
|
||||
assertNotNull(result.getPoliciesConfig());
|
||||
assertNotNull(result.getPoliciesConfig().getPlatformPrivileges());
|
||||
assertNotNull(result.getPoliciesConfig().getResourcePrivileges());
|
||||
// Verify that the privileges lists are populated (they come from static config)
|
||||
assertFalse(result.getPoliciesConfig().getPlatformPrivileges().isEmpty());
|
||||
assertFalse(result.getPoliciesConfig().getResourcePrivileges().isEmpty());
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
import { Text } from '@components';
|
||||
import React, { useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { removeMarkdown } from '@app/entity/shared/components/styled/StripMarkdownText';
|
||||
|
||||
const StyledText = styled(Text)`
|
||||
text-wrap: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export type Props = {
|
||||
content: string;
|
||||
clearMarkdown?: boolean;
|
||||
};
|
||||
|
||||
export default function ShortMarkdownViewer({ content, clearMarkdown }: Props) {
|
||||
const processedContent = useMemo(() => {
|
||||
let processingContent = content;
|
||||
|
||||
if (clearMarkdown) {
|
||||
processingContent = removeMarkdown(processingContent);
|
||||
}
|
||||
|
||||
return processingContent;
|
||||
}, [content, clearMarkdown]);
|
||||
|
||||
return (
|
||||
<StyledText color="gray" colorLevel={1700} type="div">
|
||||
{processedContent}
|
||||
</StyledText>
|
||||
);
|
||||
}
|
@ -4,6 +4,7 @@ import React, { ReactNode } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useEntityContext, useEntityData } from '@app/entity/shared/EntityContext';
|
||||
import { removeMarkdown } from '@app/entity/shared/components/styled/StripMarkdownText';
|
||||
import { GenericEntityProperties } from '@app/entity/shared/types';
|
||||
import { EntityMenuActions, PreviewType } from '@app/entityV2/Entity';
|
||||
import { EntityMenuItems } from '@app/entityV2/shared/EntityDropdown/EntityMenuActions';
|
||||
@ -15,6 +16,7 @@ import { GlossaryPreviewCardDecoration } from '@app/entityV2/shared/containers/p
|
||||
import { PopularityTier } from '@app/entityV2/shared/containers/profile/sidebar/shared/utils';
|
||||
import ViewInPlatform from '@app/entityV2/shared/externalUrl/ViewInPlatform';
|
||||
import CompactMarkdownViewer from '@app/entityV2/shared/tabs/Documentation/components/CompactMarkdownViewer';
|
||||
import ShortMarkdownViewer from '@app/entityV2/shared/tabs/Documentation/components/ShortMarkdownViewer';
|
||||
import { DashboardLastUpdatedMs, DatasetLastUpdatedMs } from '@app/entityV2/shared/utils';
|
||||
import ColoredBackgroundPlatformIconGroup from '@app/previewV2/ColoredBackgroundPlatformIconGroup';
|
||||
import { CompactView } from '@app/previewV2/CompactView';
|
||||
@ -24,6 +26,7 @@ import EntityHeader from '@app/previewV2/EntityHeader';
|
||||
import { ActionsAndStatusSection } from '@app/previewV2/shared';
|
||||
import { useRemoveDataProductAssets, useRemoveDomainAssets, useRemoveGlossaryTermAssets } from '@app/previewV2/utils';
|
||||
import { useSearchContext } from '@app/search/context/SearchContext';
|
||||
import { useAppConfig } from '@app/useAppConfig';
|
||||
import { useEntityRegistryV2 } from '@app/useEntityRegistry';
|
||||
import DataProcessInstanceInfo from '@src/app/preview/DataProcessInstanceInfo';
|
||||
|
||||
@ -105,8 +108,15 @@ const InsightIconContainer = styled.span`
|
||||
margin-right: 4px;
|
||||
`;
|
||||
|
||||
const Documentation = styled.div`
|
||||
const DocumentationTopMarginWrapper = styled.div`
|
||||
margin-top: 8px;
|
||||
`;
|
||||
|
||||
const ShortDocumentation = styled(DocumentationTopMarginWrapper)`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const Documentation = styled(DocumentationTopMarginWrapper)`
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
`;
|
||||
@ -218,6 +228,15 @@ export default function DefaultPreviewCard({
|
||||
}: Props) {
|
||||
const entityRegistry = useEntityRegistryV2();
|
||||
const supportedCapabilities = entityRegistry.getSupportedEntityCapabilities(entityType);
|
||||
const { config } = useAppConfig();
|
||||
|
||||
const shouldShowRedesignedDescription = config.searchCardConfig.showDescription;
|
||||
const shouldShowDescriptionsForSearch =
|
||||
previewType === PreviewType.SEARCH && config.searchCardConfig.showDescription;
|
||||
const shouldShowDescription =
|
||||
previewType === PreviewType.HOVER_CARD ||
|
||||
ENTITY_TYPES_WITH_DESCRIPTION_PREVIEW.has(entityType) ||
|
||||
shouldShowDescriptionsForSearch;
|
||||
|
||||
// sometimes these lists will be rendered inside an entity container (for example, in the case of impact analysis)
|
||||
// in those cases, we may want to enrich the preview w/ context about the container entity
|
||||
@ -311,13 +330,17 @@ export default function DefaultPreviewCard({
|
||||
entityTitleWidth={previewType === PreviewType.HOVER_CARD ? 150 : 200}
|
||||
/>
|
||||
</RowContainer>
|
||||
{(previewType === PreviewType.HOVER_CARD ||
|
||||
ENTITY_TYPES_WITH_DESCRIPTION_PREVIEW.has(entityType)) &&
|
||||
description ? (
|
||||
<Documentation>
|
||||
<CompactMarkdownViewer content={description} />
|
||||
</Documentation>
|
||||
) : null}
|
||||
{shouldShowDescription &&
|
||||
!!description &&
|
||||
(shouldShowRedesignedDescription ? (
|
||||
<ShortDocumentation>
|
||||
<ShortMarkdownViewer content={description} clearMarkdown />
|
||||
</ShortDocumentation>
|
||||
) : (
|
||||
<Documentation>
|
||||
<CompactMarkdownViewer content={removeMarkdown(description)} />
|
||||
</Documentation>
|
||||
))}
|
||||
{shouldShowDPIinfo && (
|
||||
<RowContainer style={{ marginTop: 8, justifyContent: 'flex-end' }}>
|
||||
<DataProcessInstanceInfo {...lastRunEvent} />
|
||||
|
@ -47,6 +47,9 @@ export const DEFAULT_APP_CONFIG = {
|
||||
searchBarConfig: {
|
||||
apiVariant: SearchBarApi.AutocompleteForMultiple,
|
||||
},
|
||||
searchCardConfig: {
|
||||
showDescription: false,
|
||||
},
|
||||
homePageConfig: {
|
||||
firstInPersonalSidebar: PersonalSidebarSection.YourAssets,
|
||||
},
|
||||
|
@ -69,6 +69,9 @@ query appConfig {
|
||||
searchBarConfig {
|
||||
apiVariant
|
||||
}
|
||||
searchCardConfig {
|
||||
showDescription
|
||||
}
|
||||
homePageConfig {
|
||||
firstInPersonalSidebar
|
||||
}
|
||||
|
@ -751,6 +751,7 @@ public class PropertiesCollectorConfigurationTest extends AbstractTestNGSpringCo
|
||||
"platformAnalytics.usageExport.usageEventTypes",
|
||||
"platformAnalytics.usageExport.userFilters",
|
||||
"searchBar.apiVariant",
|
||||
"searchCard.showDescription",
|
||||
"searchService.cache.hazelcast.serviceName",
|
||||
"searchService.cache.hazelcast.service-dns-timeout",
|
||||
"searchService.cache.hazelcast.kubernetes-api-retries",
|
||||
|
@ -37,6 +37,9 @@ public class DataHubAppConfiguration {
|
||||
/** Search bar related configs */
|
||||
private SearchBarConfiguration searchBar;
|
||||
|
||||
/** Search card related configs */
|
||||
private SearchCardConfiguration searchCard;
|
||||
|
||||
/** Home page related configs */
|
||||
private HomePageConfiguration homePage;
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
package com.linkedin.metadata.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/** POJO representing the "searchCard" configuration block in application.yaml.on.yml */
|
||||
@Data
|
||||
public class SearchCardConfiguration {
|
||||
/** If turned on, show the description in search card */
|
||||
public Boolean showDescription;
|
||||
}
|
@ -744,6 +744,9 @@ views:
|
||||
searchBar:
|
||||
apiVariant: ${SEARCH_BAR_API_VARIANT:AUTOCOMPLETE_FOR_MULTIPLE}
|
||||
|
||||
searchCard:
|
||||
showDescription: ${SEARCH_CARD_SHOW_DESCRIPTION:false}
|
||||
|
||||
homePage:
|
||||
firstInPersonalSidebar: ${FIRST_IN_PERSONAL_SIDEBAR:YOUR_ASSETS}
|
||||
|
||||
|
@ -257,6 +257,7 @@ public class GraphQLEngineFactory {
|
||||
args.setDatahubConfiguration(configProvider.getDatahub());
|
||||
args.setViewsConfiguration(configProvider.getViews());
|
||||
args.setSearchBarConfiguration(configProvider.getSearchBar());
|
||||
args.setSearchCardConfiguration(configProvider.getSearchCard());
|
||||
args.setHomePageConfiguration(configProvider.getHomePage());
|
||||
args.setSiblingGraphService(siblingGraphService);
|
||||
args.setGroupService(groupService);
|
||||
|
Loading…
x
Reference in New Issue
Block a user