feat(react): dynamically hide entity types that haven't been ingested (#3419)

This commit is contained in:
Gabe Lyons 2021-10-19 22:20:31 -07:00 committed by GitHub
parent a74ce1961d
commit 4c1c3b2377
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 121 additions and 6 deletions

View File

@ -40,6 +40,7 @@ import com.linkedin.datahub.graphql.generated.MLPrimaryKeyProperties;
import com.linkedin.datahub.graphql.resolvers.MeResolver;
import com.linkedin.datahub.graphql.resolvers.group.AddGroupMembersResolver;
import com.linkedin.datahub.graphql.resolvers.group.CreateGroupResolver;
import com.linkedin.datahub.graphql.resolvers.group.EntityCountsResolver;
import com.linkedin.datahub.graphql.resolvers.group.ListGroupsResolver;
import com.linkedin.datahub.graphql.resolvers.group.RemoveGroupMembersResolver;
import com.linkedin.datahub.graphql.resolvers.group.RemoveGroupResolver;
@ -422,6 +423,8 @@ public class GmsGraphQLEngine {
new ListUsersResolver(GmsClientFactory.getEntitiesClient()))
.dataFetcher("listGroups",
new ListGroupsResolver(GmsClientFactory.getEntitiesClient()))
.dataFetcher("getEntityCounts",
new EntityCountsResolver(GmsClientFactory.getEntitiesClient()))
);
}

View File

@ -12,7 +12,7 @@ import javax.annotation.Nonnull;
*/
public class EntityTypeMapper {
private static final Map<EntityType, String> ENTITY_TYPE_TO_NAME =
static final Map<EntityType, String> ENTITY_TYPE_TO_NAME =
ImmutableMap.<EntityType, String>builder().put(EntityType.DATASET, "dataset")
.put(EntityType.CORP_USER, "corpuser")
.put(EntityType.CORP_GROUP, "corpGroup")

View File

@ -0,0 +1,55 @@
package com.linkedin.datahub.graphql.resolvers.group;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.generated.EntityCountInput;
import com.linkedin.datahub.graphql.generated.EntityCountResult;
import com.linkedin.datahub.graphql.generated.EntityCountResults;
import com.linkedin.datahub.graphql.resolvers.EntityTypeMapper;
import com.linkedin.entity.client.EntityClient;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.*;
public class EntityCountsResolver implements DataFetcher<CompletableFuture<EntityCountResults>> {
private final EntityClient _entityClient;
public EntityCountsResolver(final EntityClient entityClient) {
_entityClient = entityClient;
}
@Override
public CompletableFuture<EntityCountResults> get(final DataFetchingEnvironment environment) throws Exception {
final QueryContext context = environment.getContext();
final EntityCountInput input = bindArgument(environment.getArgument("input"), EntityCountInput.class);
final EntityCountResults results = new EntityCountResults();
return CompletableFuture.supplyAsync(() -> {
try {
// First, get all counts
Map<String, Long> gmsResult = _entityClient.batchGetTotalEntityCount(
input.getTypes().stream().map(type -> EntityTypeMapper.getName(type)).collect(Collectors.toList()), context.getActor());
// bind to a result.
List<EntityCountResult> resultList = gmsResult.entrySet().stream().map(entry -> {
EntityCountResult result = new EntityCountResult();
result.setCount(Math.toIntExact(entry.getValue()));
result.setEntityType(EntityTypeMapper.getType(entry.getKey()));
return result;
}).collect(Collectors.toList());
results.setCounts(resultList);
return results;
} catch (Exception e) {
throw new RuntimeException("Failed to get entity counts", e);
}
});
}
}

View File

@ -98,6 +98,11 @@ type Query {
List all DataHub Groups
"""
listGroups(input: ListGroupsInput!): ListGroupsResult
"""
Fetches the number of entities ingested by type
"""
getEntityCounts(input: EntityCountInput): EntityCountResults
}
"""
@ -326,6 +331,13 @@ enum EntityType {
MLPRIMARY_KEY
}
"""
Input for the get entity counts endpoint
"""
input EntityCountInput {
types: [EntityType!]
}
"""
Input for the list relationships field of an Entity
"""
@ -4261,6 +4273,15 @@ input ListGroupsInput {
count: Int
}
type EntityCountResults {
counts: [EntityCountResult!]
}
type EntityCountResult {
entityType: EntityType!
count: Int!
}
"""
The result obtained when listing DataHub Groups
"""

View File

@ -4,6 +4,8 @@ import styled from 'styled-components';
import { useEntityRegistry } from '../useEntityRegistry';
import { BrowseEntityCard } from '../search/BrowseEntityCard';
import { useGetEntityCountsQuery } from '../../graphql/app.generated';
import { EntityType } from '../../types.generated';
const Title = styled(Typography.Text)`
&& {
@ -23,8 +25,25 @@ const BodyContainer = styled.div`
background-color: ${(props) => props.theme.styles['homepage-background-lower-fade']};
`;
// TODO: Make this list config-driven
const PERMANENT_ENTITY_TYPES = [EntityType.Dataset, EntityType.Chart, EntityType.Dashboard];
export const HomePageBody = () => {
const entityRegistry = useEntityRegistry();
const browseEntityList = entityRegistry.getBrowseEntityTypes();
const { data: entityCountData } = useGetEntityCountsQuery({
variables: {
input: {
types: browseEntityList,
},
},
});
const orderedEntityCounts =
entityCountData?.getEntityCounts?.counts?.sort((a, b) => {
return browseEntityList.indexOf(a.entityType) - browseEntityList.indexOf(b.entityType);
}) || PERMANENT_ENTITY_TYPES.map((entityType) => ({ count: 0, entityType }));
return (
<BodyContainer>
@ -32,11 +51,15 @@ export const HomePageBody = () => {
<b>Explore</b> your data
</Title>
<EntityGridRow gutter={[16, 24]}>
{entityRegistry.getBrowseEntityTypes().map((entityType) => (
<Col xs={24} sm={24} md={8} key={entityType}>
<BrowseEntityCard entityType={entityType} />
</Col>
))}
{orderedEntityCounts.map(
(entityCount) =>
entityCount &&
(entityCount.count !== 0 || PERMANENT_ENTITY_TYPES.indexOf(entityCount.entityType) !== -1) && (
<Col xs={24} sm={24} md={8} key={entityCount.entityType}>
<BrowseEntityCard entityType={entityCount.entityType} />
</Col>
),
)}
</EntityGridRow>
</BodyContainer>
);

View File

@ -26,3 +26,12 @@ query appConfig {
}
}
}
query getEntityCounts($input: EntityCountInput) {
getEntityCounts(input: $input) {
counts {
entityType
count
}
}
}

View File

@ -17,6 +17,8 @@ import { GlossaryTermEntity } from '../../app/entity/glossaryTerm/GlossaryTermEn
import { MLFeatureTableEntity } from '../../app/entity/mlFeatureTable/MLFeatureTableEntity';
import { MLModelEntity } from '../../app/entity/mlModel/MLModelEntity';
import { MLModelGroupEntity } from '../../app/entity/mlModelGroup/MLModelGroupEntity';
import { ChartEntity } from '../../app/entity/chart/ChartEntity';
import { DashboardEntity } from '../../app/entity/dashboard/DashboardEntity';
type Props = {
children: React.ReactNode;
@ -26,6 +28,8 @@ type Props = {
export function getTestEntityRegistry() {
const entityRegistry = new EntityRegistry();
entityRegistry.register(new DatasetEntity());
entityRegistry.register(new ChartEntity());
entityRegistry.register(new DashboardEntity());
entityRegistry.register(new UserEntity());
entityRegistry.register(new GroupEntity());
entityRegistry.register(new TagEntity());