mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-26 01:18:20 +00:00
feat(home) Get correct home page template and render rows/modules (#13978)
This commit is contained in:
parent
8fdee30d5f
commit
b9b97e4bfe
@ -202,6 +202,7 @@ import com.linkedin.datahub.graphql.resolvers.search.SearchResolver;
|
||||
import com.linkedin.datahub.graphql.resolvers.settings.applications.UpdateApplicationsSettingsResolver;
|
||||
import com.linkedin.datahub.graphql.resolvers.settings.docPropagation.DocPropagationSettingsResolver;
|
||||
import com.linkedin.datahub.graphql.resolvers.settings.docPropagation.UpdateDocPropagationSettingsResolver;
|
||||
import com.linkedin.datahub.graphql.resolvers.settings.homePage.GlobalHomePageSettingsResolver;
|
||||
import com.linkedin.datahub.graphql.resolvers.settings.user.UpdateCorpUserViewsSettingsResolver;
|
||||
import com.linkedin.datahub.graphql.resolvers.settings.user.UpdateUserHomePageSettingsResolver;
|
||||
import com.linkedin.datahub.graphql.resolvers.settings.view.GlobalViewsSettingsResolver;
|
||||
@ -771,6 +772,8 @@ public class GmsGraphQLEngine {
|
||||
configureMetadataAttributionResolver(builder);
|
||||
configureVersionPropertiesResolvers(builder);
|
||||
configureVersionSetResolvers(builder);
|
||||
configureGlobalHomePageSettingsResolvers(builder);
|
||||
configurePageTemplateRowResolvers(builder);
|
||||
}
|
||||
|
||||
private void configureOrganisationRoleResolvers(RuntimeWiring.Builder builder) {
|
||||
@ -1088,7 +1091,10 @@ public class GmsGraphQLEngine {
|
||||
"listBusinessAttributes", new ListBusinessAttributesResolver(this.entityClient))
|
||||
.dataFetcher(
|
||||
"docPropagationSettings",
|
||||
new DocPropagationSettingsResolver(this.settingsService)));
|
||||
new DocPropagationSettingsResolver(this.settingsService))
|
||||
.dataFetcher(
|
||||
"globalHomePageSettings",
|
||||
new GlobalHomePageSettingsResolver(this.settingsService)));
|
||||
}
|
||||
|
||||
private DataFetcher getEntitiesResolver() {
|
||||
@ -3498,4 +3504,35 @@ public class GmsGraphQLEngine {
|
||||
"versionsSearch",
|
||||
new VersionsSearchResolver(this.entityClient, this.viewService)));
|
||||
}
|
||||
|
||||
private void configureGlobalHomePageSettingsResolvers(final RuntimeWiring.Builder builder) {
|
||||
builder.type(
|
||||
"GlobalHomePageSettings",
|
||||
typeWiring ->
|
||||
typeWiring.dataFetcher(
|
||||
"defaultTemplate",
|
||||
new LoadableTypeResolver<>(
|
||||
dataHubPageTemplateType,
|
||||
(env) -> {
|
||||
final GlobalHomePageSettings homePageSettings = env.getSource();
|
||||
return homePageSettings.getDefaultTemplate() != null
|
||||
? homePageSettings.getDefaultTemplate().getUrn()
|
||||
: null;
|
||||
})));
|
||||
}
|
||||
|
||||
private void configurePageTemplateRowResolvers(final RuntimeWiring.Builder builder) {
|
||||
builder.type(
|
||||
"DataHubPageTemplateRow",
|
||||
typeWiring ->
|
||||
typeWiring.dataFetcher(
|
||||
"modules",
|
||||
new LoadableTypeBatchResolver<>(
|
||||
dataHubPageModuleType,
|
||||
(env) ->
|
||||
((DataHubPageTemplateRow) env.getSource())
|
||||
.getModules().stream()
|
||||
.map(DataHubPageModule::getUrn)
|
||||
.collect(Collectors.toList()))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
package com.linkedin.datahub.graphql.resolvers.settings.homePage;
|
||||
|
||||
import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
|
||||
import com.linkedin.datahub.graphql.generated.DataHubPageTemplate;
|
||||
import com.linkedin.datahub.graphql.generated.EntityType;
|
||||
import com.linkedin.datahub.graphql.generated.GlobalHomePageSettings;
|
||||
import com.linkedin.metadata.service.SettingsService;
|
||||
import com.linkedin.settings.global.GlobalSettingsInfo;
|
||||
import graphql.schema.DataFetcher;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import javax.annotation.Nonnull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/** Retrieves the Global Settings related to the Home Page feature. */
|
||||
@Slf4j
|
||||
public class GlobalHomePageSettingsResolver
|
||||
implements DataFetcher<CompletableFuture<GlobalHomePageSettings>> {
|
||||
|
||||
private final SettingsService _settingsService;
|
||||
|
||||
public GlobalHomePageSettingsResolver(final SettingsService settingsService) {
|
||||
_settingsService = Objects.requireNonNull(settingsService, "settingsService must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<GlobalHomePageSettings> get(final DataFetchingEnvironment environment)
|
||||
throws Exception {
|
||||
final QueryContext context = environment.getContext();
|
||||
return GraphQLConcurrencyUtils.supplyAsync(
|
||||
() -> {
|
||||
try {
|
||||
final GlobalSettingsInfo globalSettings =
|
||||
_settingsService.getGlobalSettings(context.getOperationContext());
|
||||
final GlobalHomePageSettings defaultSettings = new GlobalHomePageSettings();
|
||||
return globalSettings != null && globalSettings.hasHomePage()
|
||||
? mapGlobalHomePageSettings(globalSettings.getHomePage())
|
||||
: defaultSettings;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to retrieve Global Home Page Settings", e);
|
||||
}
|
||||
},
|
||||
this.getClass().getSimpleName(),
|
||||
"get");
|
||||
}
|
||||
|
||||
private static GlobalHomePageSettings mapGlobalHomePageSettings(
|
||||
@Nonnull final com.linkedin.settings.global.GlobalHomePageSettings settings) {
|
||||
final GlobalHomePageSettings result = new GlobalHomePageSettings();
|
||||
|
||||
// Map defaultTemplate settings field
|
||||
if (settings.hasDefaultTemplate()) {
|
||||
DataHubPageTemplate template = new DataHubPageTemplate();
|
||||
template.setUrn(settings.getDefaultTemplate().toString());
|
||||
template.setType(EntityType.DATAHUB_PAGE_TEMPLATE);
|
||||
result.setDefaultTemplate(template);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
package com.linkedin.datahub.graphql.resolvers.settings.homePage;
|
||||
|
||||
import static com.linkedin.datahub.graphql.TestUtils.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import com.linkedin.common.urn.Urn;
|
||||
import com.linkedin.common.urn.UrnUtils;
|
||||
import com.linkedin.data.template.SetMode;
|
||||
import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.generated.DataHubPageTemplate;
|
||||
import com.linkedin.datahub.graphql.generated.EntityType;
|
||||
import com.linkedin.metadata.service.SettingsService;
|
||||
import com.linkedin.settings.global.GlobalHomePageSettings;
|
||||
import com.linkedin.settings.global.GlobalSettingsInfo;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import org.mockito.Mockito;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class GlobalHomePageSettingsResolverTest {
|
||||
|
||||
private static final Urn TEST_TEMPLATE_URN =
|
||||
UrnUtils.getUrn("urn:li:dataHubPageTemplate:test-template");
|
||||
private static final Urn TEST_USER_URN = UrnUtils.getUrn("urn:li:corpuser:test");
|
||||
|
||||
@Test
|
||||
public void testGetSuccessNullSettings() throws Exception {
|
||||
SettingsService mockService = initSettingsService(null);
|
||||
GlobalHomePageSettingsResolver resolver = new GlobalHomePageSettingsResolver(mockService);
|
||||
|
||||
QueryContext mockContext = getMockAllowContext(TEST_USER_URN.toString());
|
||||
DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class);
|
||||
Mockito.when(mockEnv.getContext()).thenReturn(mockContext);
|
||||
|
||||
com.linkedin.datahub.graphql.generated.GlobalHomePageSettings result =
|
||||
resolver.get(mockEnv).get();
|
||||
|
||||
Assert.assertNotNull(result); // Empty settings
|
||||
Assert.assertNull(result.getDefaultTemplate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSuccessEmptySettings() throws Exception {
|
||||
SettingsService mockService = initSettingsService(new GlobalHomePageSettings());
|
||||
GlobalHomePageSettingsResolver resolver = new GlobalHomePageSettingsResolver(mockService);
|
||||
|
||||
QueryContext mockContext = getMockAllowContext(TEST_USER_URN.toString());
|
||||
DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class);
|
||||
Mockito.when(mockEnv.getContext()).thenReturn(mockContext);
|
||||
|
||||
com.linkedin.datahub.graphql.generated.GlobalHomePageSettings result =
|
||||
resolver.get(mockEnv).get();
|
||||
|
||||
Assert.assertNull(result.getDefaultTemplate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSuccessExistingSettings() throws Exception {
|
||||
SettingsService mockService =
|
||||
initSettingsService(new GlobalHomePageSettings().setDefaultTemplate(TEST_TEMPLATE_URN));
|
||||
GlobalHomePageSettingsResolver resolver = new GlobalHomePageSettingsResolver(mockService);
|
||||
|
||||
QueryContext mockContext = getMockAllowContext(TEST_USER_URN.toString());
|
||||
DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class);
|
||||
Mockito.when(mockEnv.getContext()).thenReturn(mockContext);
|
||||
|
||||
com.linkedin.datahub.graphql.generated.GlobalHomePageSettings result =
|
||||
resolver.get(mockEnv).get();
|
||||
|
||||
Assert.assertNotNull(result.getDefaultTemplate());
|
||||
DataHubPageTemplate template = result.getDefaultTemplate();
|
||||
Assert.assertEquals(template.getUrn(), TEST_TEMPLATE_URN.toString());
|
||||
Assert.assertEquals(template.getType(), EntityType.DATAHUB_PAGE_TEMPLATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSuccessSettingsWithoutDefaultTemplate() throws Exception {
|
||||
SettingsService mockService = initSettingsService(new GlobalHomePageSettings());
|
||||
GlobalHomePageSettingsResolver resolver = new GlobalHomePageSettingsResolver(mockService);
|
||||
|
||||
QueryContext mockContext = getMockAllowContext(TEST_USER_URN.toString());
|
||||
DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class);
|
||||
Mockito.when(mockEnv.getContext()).thenReturn(mockContext);
|
||||
|
||||
com.linkedin.datahub.graphql.generated.GlobalHomePageSettings result =
|
||||
resolver.get(mockEnv).get();
|
||||
|
||||
Assert.assertNull(result.getDefaultTemplate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetException() throws Exception {
|
||||
SettingsService mockService = Mockito.mock(SettingsService.class);
|
||||
Mockito.doThrow(RuntimeException.class).when(mockService).getGlobalSettings(any());
|
||||
|
||||
GlobalHomePageSettingsResolver resolver = new GlobalHomePageSettingsResolver(mockService);
|
||||
|
||||
DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class);
|
||||
QueryContext mockContext = getMockAllowContext(TEST_USER_URN.toString());
|
||||
Mockito.when(mockEnv.getContext()).thenReturn(mockContext);
|
||||
|
||||
assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join());
|
||||
}
|
||||
|
||||
private static SettingsService initSettingsService(
|
||||
GlobalHomePageSettings existingHomePageSettings) {
|
||||
SettingsService mockService = Mockito.mock(SettingsService.class);
|
||||
|
||||
Mockito.when(mockService.getGlobalSettings(any()))
|
||||
.thenReturn(
|
||||
new GlobalSettingsInfo().setHomePage(existingHomePageSettings, SetMode.IGNORE_NULL));
|
||||
|
||||
return mockService;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import EntityRegistryProvider from '@app/EntityRegistryProvider';
|
||||
import GlobalSettingsProvider from '@app/context/GlobalSettingsProvider';
|
||||
import UserContextProvider from '@app/context/UserContextProvider';
|
||||
import { NavBarProvider } from '@app/homeV2/layout/navBarRedesign/NavBarContext';
|
||||
import SearchContextProvider from '@app/search/context/SearchContextProvider';
|
||||
@ -16,19 +17,21 @@ interface Props {
|
||||
export default function AppProviders({ children }: Props) {
|
||||
return (
|
||||
<AppConfigProvider>
|
||||
<UserContextProvider>
|
||||
<EntityRegistryProvider>
|
||||
<BrowserTitleProvider>
|
||||
<EducationStepsProvider>
|
||||
<QuickFiltersProvider>
|
||||
<SearchContextProvider>
|
||||
<NavBarProvider>{children}</NavBarProvider>
|
||||
</SearchContextProvider>
|
||||
</QuickFiltersProvider>
|
||||
</EducationStepsProvider>
|
||||
</BrowserTitleProvider>
|
||||
</EntityRegistryProvider>
|
||||
</UserContextProvider>
|
||||
<GlobalSettingsProvider>
|
||||
<UserContextProvider>
|
||||
<EntityRegistryProvider>
|
||||
<BrowserTitleProvider>
|
||||
<EducationStepsProvider>
|
||||
<QuickFiltersProvider>
|
||||
<SearchContextProvider>
|
||||
<NavBarProvider>{children}</NavBarProvider>
|
||||
</SearchContextProvider>
|
||||
</QuickFiltersProvider>
|
||||
</EducationStepsProvider>
|
||||
</BrowserTitleProvider>
|
||||
</EntityRegistryProvider>
|
||||
</UserContextProvider>
|
||||
</GlobalSettingsProvider>
|
||||
</AppConfigProvider>
|
||||
);
|
||||
}
|
||||
|
||||
18
datahub-web-react/src/app/context/GlobalSettingsContext.tsx
Normal file
18
datahub-web-react/src/app/context/GlobalSettingsContext.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import React, { useContext } from 'react';
|
||||
|
||||
import { GetHomePageSettingsQuery } from '@graphql/app.generated';
|
||||
|
||||
export const DEFAULT_GLOBAL_SETTINGS = {
|
||||
globalHomePageSettings: {
|
||||
defaultTemplate: null,
|
||||
},
|
||||
};
|
||||
|
||||
export const GlobalSettingsContext = React.createContext<{
|
||||
settings: GetHomePageSettingsQuery;
|
||||
loaded: boolean;
|
||||
}>({ settings: DEFAULT_GLOBAL_SETTINGS, loaded: false });
|
||||
|
||||
export function useGlobalSettings() {
|
||||
return useContext(GlobalSettingsContext);
|
||||
}
|
||||
20
datahub-web-react/src/app/context/GlobalSettingsProvider.tsx
Normal file
20
datahub-web-react/src/app/context/GlobalSettingsProvider.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
import { DEFAULT_GLOBAL_SETTINGS, GlobalSettingsContext } from '@app/context/GlobalSettingsContext';
|
||||
|
||||
import { useGetHomePageSettingsQuery } from '@graphql/app.generated';
|
||||
|
||||
export default function GlobalSettingsProvider({ children }: { children: React.ReactNode }) {
|
||||
const { data } = useGetHomePageSettingsQuery();
|
||||
|
||||
return (
|
||||
<GlobalSettingsContext.Provider
|
||||
value={{
|
||||
settings: data || DEFAULT_GLOBAL_SETTINGS,
|
||||
loaded: !!data,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</GlobalSettingsContext.Provider>
|
||||
);
|
||||
}
|
||||
@ -10,7 +10,11 @@ const MAX_ASSETS_TO_FETCH = 50;
|
||||
export const useGetAssetsYouOwn = (user?: CorpUser | null, count = MAX_ASSETS_TO_FETCH) => {
|
||||
const { groupUrns, loading: groupDataLoading } = useGetUserGroupUrns(user?.urn);
|
||||
|
||||
const { loading, data, error } = useGetSearchResultsForMultipleQuery({
|
||||
const {
|
||||
loading: searchLoading,
|
||||
data,
|
||||
error,
|
||||
} = useGetSearchResultsForMultipleQuery({
|
||||
variables: {
|
||||
input: {
|
||||
query: '*',
|
||||
@ -38,6 +42,7 @@ export const useGetAssetsYouOwn = (user?: CorpUser | null, count = MAX_ASSETS_TO
|
||||
const entities =
|
||||
originEntities.map((entity) => entityRegistry.getGenericEntityProperties(entity.type, entity)) || [];
|
||||
const total = data?.searchAcrossEntities?.total || 0;
|
||||
const loading = searchLoading || groupDataLoading || !data;
|
||||
|
||||
return { originEntities, entities, loading: loading || groupDataLoading, error, total };
|
||||
return { originEntities, entities, loading, error, total };
|
||||
};
|
||||
|
||||
@ -1,34 +1,26 @@
|
||||
import React from 'react';
|
||||
|
||||
import { useGlobalSettings } from '@app/context/GlobalSettingsContext';
|
||||
import { useUserContext } from '@app/context/useUserContext';
|
||||
import { Announcements } from '@app/homeV3/announcements/Announcements';
|
||||
import Module from '@app/homeV3/module/Module';
|
||||
import { ModuleProps } from '@app/homeV3/module/types';
|
||||
import { CenteredContainer, ContentContainer, ContentDiv } from '@app/homeV3/styledComponents';
|
||||
|
||||
const SAMPLE_MODULES: ModuleProps[] = [
|
||||
{
|
||||
name: 'Your Assets',
|
||||
description: 'These are assets you are the owner',
|
||||
type: 'yourAssets',
|
||||
visibility: 'personal',
|
||||
},
|
||||
{
|
||||
name: 'Sample large module',
|
||||
description: 'Description of the sample module',
|
||||
type: 'sampleLarge',
|
||||
visibility: 'global',
|
||||
},
|
||||
];
|
||||
import TemplateRow from '@app/homeV3/templateRow/TemplateRow';
|
||||
|
||||
const HomePageContent = () => {
|
||||
const { settings } = useGlobalSettings();
|
||||
const { user } = useUserContext();
|
||||
|
||||
const template = user?.settings?.homePage?.pageTemplate || settings.globalHomePageSettings?.defaultTemplate;
|
||||
|
||||
return (
|
||||
<ContentContainer>
|
||||
<CenteredContainer>
|
||||
<ContentDiv>
|
||||
<Announcements />
|
||||
{SAMPLE_MODULES.map((sampleModule) => (
|
||||
<Module {...sampleModule} key={sampleModule.name} />
|
||||
))}
|
||||
{template?.properties.rows.map((row, i) => {
|
||||
const key = `templateRow-${i}`;
|
||||
return <TemplateRow key={key} row={row} />;
|
||||
})}
|
||||
</ContentDiv>
|
||||
</CenteredContainer>
|
||||
</ContentContainer>
|
||||
|
||||
@ -4,13 +4,16 @@ import { ModuleProps } from '@app/homeV3/module/types';
|
||||
import SampleLargeModule from '@app/homeV3/modules/SampleLargeModule';
|
||||
import YourAssetsModule from '@app/homeV3/modules/YourAssetsModule';
|
||||
|
||||
export default function Module(props: ModuleProps) {
|
||||
const Component = useMemo(() => {
|
||||
// TODO: implement logic to map props.type to component
|
||||
if (props.type === 'sampleLarge') return SampleLargeModule;
|
||||
if (props.type === 'yourAssets') return YourAssetsModule;
|
||||
return SampleLargeModule;
|
||||
}, [props.type]);
|
||||
import { DataHubPageModuleType } from '@types';
|
||||
|
||||
return <Component {...props} />;
|
||||
export default function Module(props: ModuleProps) {
|
||||
const { module } = props;
|
||||
const Component = useMemo(() => {
|
||||
if (module.properties.type === DataHubPageModuleType.OwnedAssets) return YourAssetsModule;
|
||||
// TODO: remove the sample large module once we have other modules to fill this out
|
||||
console.error(`Issue finding module with type ${module.properties.type}`);
|
||||
return SampleLargeModule;
|
||||
}, [module.properties.type]);
|
||||
|
||||
return <Component module={module} />;
|
||||
}
|
||||
|
||||
@ -3,10 +3,8 @@ import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import ModuleContainer from '@app/homeV3/module/components/ModuleContainer';
|
||||
import ModuleDescription from '@app/homeV3/module/components/ModuleDescription';
|
||||
import ModuleMenu from '@app/homeV3/module/components/ModuleMenu';
|
||||
import ModuleName from '@app/homeV3/module/components/ModuleName';
|
||||
import PublicModuleBadge from '@app/homeV3/module/components/PublicModuleBadge';
|
||||
import { ModuleProps } from '@app/homeV3/module/types';
|
||||
|
||||
const ModuleHeader = styled.div`
|
||||
@ -51,20 +49,15 @@ interface Props extends ModuleProps {
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export default function LargeModule({
|
||||
children,
|
||||
name,
|
||||
description,
|
||||
visibility,
|
||||
loading,
|
||||
}: React.PropsWithChildren<Props>) {
|
||||
export default function LargeModule({ children, module, loading }: React.PropsWithChildren<Props>) {
|
||||
const { name } = module.properties;
|
||||
return (
|
||||
<ModuleContainer $height="316px">
|
||||
<ModuleHeader>
|
||||
<ModuleName text={name} />
|
||||
<ModuleDescription text={description} />
|
||||
{/* TODO: implement description for modules CH-548 */}
|
||||
{/* <ModuleDescription text={description} /> */}
|
||||
<FloatingRightHeaderSection>
|
||||
<PublicModuleBadge isPublic={visibility === 'global'} />
|
||||
<ModuleMenu />
|
||||
</FloatingRightHeaderSection>
|
||||
</ModuleHeader>
|
||||
|
||||
@ -5,6 +5,7 @@ const ModuleContainer = styled.div<{ $height: string }>`
|
||||
background: ${colors.white};
|
||||
border: ${borders['1px']} ${colors.gray[100]};
|
||||
border-radius: ${radius.lg};
|
||||
flex: 1;
|
||||
|
||||
height: ${(props) => props.$height};
|
||||
box-shadow:
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
// TODO: adapt to DataHubPageModuleProperties
|
||||
import { PageModuleFragment } from '@graphql/template.generated';
|
||||
|
||||
// the current props are just to draft some components
|
||||
export interface ModuleProps {
|
||||
name: string;
|
||||
type: string;
|
||||
visibility: 'personal' | 'global';
|
||||
description?: string;
|
||||
isPublic?: boolean;
|
||||
module: PageModuleFragment;
|
||||
}
|
||||
|
||||
27
datahub-web-react/src/app/homeV3/templateRow/TemplateRow.tsx
Normal file
27
datahub-web-react/src/app/homeV3/templateRow/TemplateRow.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import Module from '@app/homeV3/module/Module';
|
||||
|
||||
import { PageTemplateRowFragment } from '@graphql/template.generated';
|
||||
|
||||
const RowWrapper = styled.div`
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
row: PageTemplateRowFragment;
|
||||
}
|
||||
|
||||
export default function TemplateRow({ row }: Props) {
|
||||
return (
|
||||
<RowWrapper>
|
||||
{row.modules.map((module) => (
|
||||
<Module key={module.urn} module={module} />
|
||||
))}
|
||||
</RowWrapper>
|
||||
);
|
||||
}
|
||||
@ -132,6 +132,14 @@ query getDocPropagationSettings {
|
||||
}
|
||||
}
|
||||
|
||||
query getHomePageSettings {
|
||||
globalHomePageSettings {
|
||||
defaultTemplate {
|
||||
...pageTemplateFields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation updateGlobalViewsSettings($input: UpdateGlobalViewsSettingsInput!) {
|
||||
updateGlobalViewsSettings(input: $input)
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ query getMe {
|
||||
}
|
||||
homePage {
|
||||
pageTemplate {
|
||||
urn
|
||||
...pageTemplateFields
|
||||
}
|
||||
dismissedAnnouncementUrns
|
||||
}
|
||||
|
||||
33
datahub-web-react/src/graphql/template.graphql
Normal file
33
datahub-web-react/src/graphql/template.graphql
Normal file
@ -0,0 +1,33 @@
|
||||
fragment pageTemplateFields on DataHubPageTemplate {
|
||||
urn
|
||||
type
|
||||
properties {
|
||||
rows {
|
||||
...PageTemplateRow
|
||||
}
|
||||
surface {
|
||||
surfaceType
|
||||
}
|
||||
visibility {
|
||||
scope
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment PageTemplateRow on DataHubPageTemplateRow {
|
||||
modules {
|
||||
...PageModule
|
||||
}
|
||||
}
|
||||
|
||||
fragment PageModule on DataHubPageModule {
|
||||
urn
|
||||
type
|
||||
properties {
|
||||
name
|
||||
type
|
||||
visibility {
|
||||
scope
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user