mirror of
https://github.com/datahub-project/datahub.git
synced 2025-08-17 21:56:56 +00:00
feat(ui): Adding Search Bar to all List Views (groups, users, domains, policies, ingestion) (#4919)
This commit is contained in:
parent
a0e7262b00
commit
f18f619a2c
@ -1,6 +1,5 @@
|
||||
package com.linkedin.datahub.graphql.resolvers.domain;
|
||||
|
||||
import com.linkedin.common.UrnArray;
|
||||
import com.linkedin.common.urn.Urn;
|
||||
import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
|
||||
@ -11,13 +10,15 @@ import com.linkedin.datahub.graphql.generated.ListDomainsInput;
|
||||
import com.linkedin.datahub.graphql.generated.ListDomainsResult;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.metadata.Constants;
|
||||
import com.linkedin.metadata.query.ListResult;
|
||||
import com.linkedin.metadata.search.SearchEntity;
|
||||
import com.linkedin.metadata.search.SearchResult;
|
||||
import graphql.schema.DataFetcher;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.*;
|
||||
|
||||
@ -29,6 +30,7 @@ public class ListDomainsResolver implements DataFetcher<CompletableFuture<ListDo
|
||||
|
||||
private static final Integer DEFAULT_START = 0;
|
||||
private static final Integer DEFAULT_COUNT = 20;
|
||||
private static final String DEFAULT_QUERY = "";
|
||||
|
||||
private final EntityClient _entityClient;
|
||||
|
||||
@ -47,11 +49,13 @@ public class ListDomainsResolver implements DataFetcher<CompletableFuture<ListDo
|
||||
final ListDomainsInput input = bindArgument(environment.getArgument("input"), ListDomainsInput.class);
|
||||
final Integer start = input.getStart() == null ? DEFAULT_START : input.getStart();
|
||||
final Integer count = input.getCount() == null ? DEFAULT_COUNT : input.getCount();
|
||||
final String query = input.getQuery() == null ? DEFAULT_QUERY : input.getQuery();
|
||||
|
||||
try {
|
||||
// First, get all group Urns.
|
||||
final ListResult gmsResult = _entityClient.list(
|
||||
final SearchResult gmsResult = _entityClient.search(
|
||||
Constants.DOMAIN_ENTITY_NAME,
|
||||
query,
|
||||
Collections.emptyMap(),
|
||||
start,
|
||||
count,
|
||||
@ -59,10 +63,12 @@ public class ListDomainsResolver implements DataFetcher<CompletableFuture<ListDo
|
||||
|
||||
// Now that we have entities we can bind this to a result.
|
||||
final ListDomainsResult result = new ListDomainsResult();
|
||||
result.setStart(gmsResult.getStart());
|
||||
result.setCount(gmsResult.getCount());
|
||||
result.setTotal(gmsResult.getTotal());
|
||||
result.setDomains(mapUnresolvedDomains(gmsResult.getEntities()));
|
||||
result.setStart(gmsResult.getFrom());
|
||||
result.setCount(gmsResult.getPageSize());
|
||||
result.setTotal(gmsResult.getNumEntities());
|
||||
result.setDomains(mapUnresolvedDomains(gmsResult.getEntities().stream()
|
||||
.map(SearchEntity::getEntity)
|
||||
.collect(Collectors.toList())));
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to list domains", e);
|
||||
@ -73,7 +79,7 @@ public class ListDomainsResolver implements DataFetcher<CompletableFuture<ListDo
|
||||
}
|
||||
|
||||
// This method maps urns returned from the list endpoint into Partial Domain objects which will be resolved be a separate Batch resolver.
|
||||
private List<Domain> mapUnresolvedDomains(final UrnArray entityUrns) {
|
||||
private List<Domain> mapUnresolvedDomains(final List<Urn> entityUrns) {
|
||||
final List<Domain> results = new ArrayList<>();
|
||||
for (final Urn urn : entityUrns) {
|
||||
final Domain unresolvedDomain = new Domain();
|
||||
|
@ -10,7 +10,8 @@ import com.linkedin.datahub.graphql.generated.ListGroupsResult;
|
||||
import com.linkedin.datahub.graphql.types.corpgroup.mappers.CorpGroupMapper;
|
||||
import com.linkedin.entity.EntityResponse;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.metadata.query.ListResult;
|
||||
import com.linkedin.metadata.search.SearchEntity;
|
||||
import com.linkedin.metadata.search.SearchResult;
|
||||
import graphql.schema.DataFetcher;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import java.util.Collection;
|
||||
@ -29,6 +30,7 @@ public class ListGroupsResolver implements DataFetcher<CompletableFuture<ListGro
|
||||
|
||||
private static final Integer DEFAULT_START = 0;
|
||||
private static final Integer DEFAULT_COUNT = 20;
|
||||
private static final String DEFAULT_QUERY = "";
|
||||
|
||||
private final EntityClient _entityClient;
|
||||
|
||||
@ -45,22 +47,25 @@ public class ListGroupsResolver implements DataFetcher<CompletableFuture<ListGro
|
||||
final ListGroupsInput input = bindArgument(environment.getArgument("input"), ListGroupsInput.class);
|
||||
final Integer start = input.getStart() == null ? DEFAULT_START : input.getStart();
|
||||
final Integer count = input.getCount() == null ? DEFAULT_COUNT : input.getCount();
|
||||
final String query = input.getQuery() == null ? DEFAULT_QUERY : input.getQuery();
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
// First, get all group Urns.
|
||||
final ListResult gmsResult =
|
||||
_entityClient.list(CORP_GROUP_ENTITY_NAME, Collections.emptyMap(), start, count, context.getAuthentication());
|
||||
final SearchResult gmsResult =
|
||||
_entityClient.search(CORP_GROUP_ENTITY_NAME, query, Collections.emptyMap(), start, count, context.getAuthentication());
|
||||
|
||||
// Then, get hydrate all groups.
|
||||
final Map<Urn, EntityResponse> entities = _entityClient.batchGetV2(CORP_GROUP_ENTITY_NAME,
|
||||
new HashSet<>(gmsResult.getEntities()), null, context.getAuthentication());
|
||||
new HashSet<>(gmsResult.getEntities().stream()
|
||||
.map(SearchEntity::getEntity)
|
||||
.collect(Collectors.toList())), null, context.getAuthentication());
|
||||
|
||||
// Now that we have entities we can bind this to a result.
|
||||
final ListGroupsResult result = new ListGroupsResult();
|
||||
result.setStart(gmsResult.getStart());
|
||||
result.setCount(gmsResult.getCount());
|
||||
result.setTotal(gmsResult.getTotal());
|
||||
result.setStart(gmsResult.getFrom());
|
||||
result.setCount(gmsResult.getPageSize());
|
||||
result.setTotal(gmsResult.getNumEntities());
|
||||
result.setGroups(mapEntities(entities.values()));
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
|
@ -14,7 +14,8 @@ import com.linkedin.entity.EnvelopedAspect;
|
||||
import com.linkedin.entity.EnvelopedAspectMap;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.metadata.Constants;
|
||||
import com.linkedin.metadata.query.ListResult;
|
||||
import com.linkedin.metadata.search.SearchEntity;
|
||||
import com.linkedin.metadata.search.SearchResult;
|
||||
import com.linkedin.secret.DataHubSecretValue;
|
||||
import graphql.schema.DataFetcher;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
@ -25,6 +26,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.*;
|
||||
@ -38,6 +40,7 @@ public class ListSecretsResolver implements DataFetcher<CompletableFuture<ListSe
|
||||
|
||||
private static final Integer DEFAULT_START = 0;
|
||||
private static final Integer DEFAULT_COUNT = 20;
|
||||
private static final String DEFAULT_QUERY = "";
|
||||
|
||||
private final EntityClient _entityClient;
|
||||
|
||||
@ -54,24 +57,28 @@ public class ListSecretsResolver implements DataFetcher<CompletableFuture<ListSe
|
||||
final ListSecretsInput input = bindArgument(environment.getArgument("input"), ListSecretsInput.class);
|
||||
final Integer start = input.getStart() == null ? DEFAULT_START : input.getStart();
|
||||
final Integer count = input.getCount() == null ? DEFAULT_COUNT : input.getCount();
|
||||
final String query = input.getQuery() == null ? DEFAULT_QUERY : input.getQuery();
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
// First, get all secrets
|
||||
final ListResult gmsResult = _entityClient.list(Constants.SECRETS_ENTITY_NAME, Collections.emptyMap(), start, count, context.getAuthentication());
|
||||
final SearchResult
|
||||
gmsResult = _entityClient.search(Constants.SECRETS_ENTITY_NAME, query, Collections.emptyMap(), start, count, context.getAuthentication());
|
||||
|
||||
// Then, resolve all secrets
|
||||
final Map<Urn, EntityResponse> entities = _entityClient.batchGetV2(
|
||||
Constants.SECRETS_ENTITY_NAME,
|
||||
new HashSet<>(gmsResult.getEntities()),
|
||||
new HashSet<>(gmsResult.getEntities().stream()
|
||||
.map(SearchEntity::getEntity)
|
||||
.collect(Collectors.toList())),
|
||||
ImmutableSet.of(Constants.SECRET_VALUE_ASPECT_NAME),
|
||||
context.getAuthentication());
|
||||
|
||||
// Now that we have entities we can bind this to a result.
|
||||
final ListSecretsResult result = new ListSecretsResult();
|
||||
result.setStart(gmsResult.getStart());
|
||||
result.setCount(gmsResult.getCount());
|
||||
result.setTotal(gmsResult.getTotal());
|
||||
result.setStart(gmsResult.getFrom());
|
||||
result.setCount(gmsResult.getPageSize());
|
||||
result.setTotal(gmsResult.getNumEntities());
|
||||
result.setSecrets(mapEntities(entities.values()));
|
||||
return result;
|
||||
|
||||
|
@ -11,13 +11,15 @@ import com.linkedin.datahub.graphql.resolvers.ingest.IngestionResolverUtils;
|
||||
import com.linkedin.entity.EntityResponse;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.metadata.Constants;
|
||||
import com.linkedin.metadata.query.ListResult;
|
||||
import com.linkedin.metadata.search.SearchEntity;
|
||||
import com.linkedin.metadata.search.SearchResult;
|
||||
import graphql.schema.DataFetcher;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.*;
|
||||
|
||||
@ -28,6 +30,7 @@ public class ListIngestionSourcesResolver implements DataFetcher<CompletableFutu
|
||||
|
||||
private static final Integer DEFAULT_START = 0;
|
||||
private static final Integer DEFAULT_COUNT = 20;
|
||||
private static final String DEFAULT_QUERY = "";
|
||||
|
||||
private final EntityClient _entityClient;
|
||||
|
||||
@ -44,12 +47,14 @@ public class ListIngestionSourcesResolver implements DataFetcher<CompletableFutu
|
||||
final ListIngestionSourcesInput input = bindArgument(environment.getArgument("input"), ListIngestionSourcesInput.class);
|
||||
final Integer start = input.getStart() == null ? DEFAULT_START : input.getStart();
|
||||
final Integer count = input.getCount() == null ? DEFAULT_COUNT : input.getCount();
|
||||
final String query = input.getQuery() == null ? DEFAULT_QUERY : input.getQuery();
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
// First, get all ingestion sources Urns.
|
||||
final ListResult gmsResult = _entityClient.list(
|
||||
final SearchResult gmsResult = _entityClient.search(
|
||||
Constants.INGESTION_SOURCE_ENTITY_NAME,
|
||||
query,
|
||||
Collections.emptyMap(),
|
||||
start,
|
||||
count,
|
||||
@ -58,15 +63,17 @@ public class ListIngestionSourcesResolver implements DataFetcher<CompletableFutu
|
||||
// Then, resolve all ingestion sources
|
||||
final Map<Urn, EntityResponse> entities = _entityClient.batchGetV2(
|
||||
Constants.INGESTION_SOURCE_ENTITY_NAME,
|
||||
new HashSet<>(gmsResult.getEntities()),
|
||||
new HashSet<>(gmsResult.getEntities().stream()
|
||||
.map(SearchEntity::getEntity)
|
||||
.collect(Collectors.toList())),
|
||||
ImmutableSet.of(Constants.INGESTION_INFO_ASPECT_NAME),
|
||||
context.getAuthentication());
|
||||
|
||||
// Now that we have entities we can bind this to a result.
|
||||
final ListIngestionSourcesResult result = new ListIngestionSourcesResult();
|
||||
result.setStart(gmsResult.getStart());
|
||||
result.setCount(gmsResult.getCount());
|
||||
result.setTotal(gmsResult.getTotal());
|
||||
result.setStart(gmsResult.getFrom());
|
||||
result.setCount(gmsResult.getPageSize());
|
||||
result.setTotal(gmsResult.getNumEntities());
|
||||
result.setIngestionSources(IngestionResolverUtils.mapIngestionSources(entities.values()));
|
||||
return result;
|
||||
|
||||
|
@ -21,6 +21,7 @@ public class ListPoliciesResolver implements DataFetcher<CompletableFuture<ListP
|
||||
|
||||
private static final Integer DEFAULT_START = 0;
|
||||
private static final Integer DEFAULT_COUNT = 20;
|
||||
private static final String DEFAULT_QUERY = "";
|
||||
|
||||
private final PolicyFetcher _policyFetcher;
|
||||
|
||||
@ -37,12 +38,13 @@ public class ListPoliciesResolver implements DataFetcher<CompletableFuture<ListP
|
||||
final ListPoliciesInput input = bindArgument(environment.getArgument("input"), ListPoliciesInput.class);
|
||||
final Integer start = input.getStart() == null ? DEFAULT_START : input.getStart();
|
||||
final Integer count = input.getCount() == null ? DEFAULT_COUNT : input.getCount();
|
||||
final String query = input.getQuery() == null ? DEFAULT_QUERY : input.getQuery();
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
// First, get all policy Urns.
|
||||
final PolicyFetcher.PolicyFetchResult policyFetchResult =
|
||||
_policyFetcher.fetchPolicies(start, count, context.getAuthentication());
|
||||
_policyFetcher.fetchPolicies(start, count, query, context.getAuthentication());
|
||||
|
||||
// Now that we have entities we can bind this to a result.
|
||||
final ListPoliciesResult result = new ListPoliciesResult();
|
||||
|
@ -10,7 +10,8 @@ import com.linkedin.datahub.graphql.generated.ListUsersResult;
|
||||
import com.linkedin.datahub.graphql.types.corpuser.mappers.CorpUserMapper;
|
||||
import com.linkedin.entity.EntityResponse;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.metadata.query.ListResult;
|
||||
import com.linkedin.metadata.search.SearchEntity;
|
||||
import com.linkedin.metadata.search.SearchResult;
|
||||
import graphql.schema.DataFetcher;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import java.util.Collection;
|
||||
@ -29,6 +30,7 @@ public class ListUsersResolver implements DataFetcher<CompletableFuture<ListUser
|
||||
|
||||
private static final Integer DEFAULT_START = 0;
|
||||
private static final Integer DEFAULT_COUNT = 20;
|
||||
private static final String DEFAULT_QUERY = "";
|
||||
|
||||
private final EntityClient _entityClient;
|
||||
|
||||
@ -45,22 +47,26 @@ public class ListUsersResolver implements DataFetcher<CompletableFuture<ListUser
|
||||
final ListUsersInput input = bindArgument(environment.getArgument("input"), ListUsersInput.class);
|
||||
final Integer start = input.getStart() == null ? DEFAULT_START : input.getStart();
|
||||
final Integer count = input.getCount() == null ? DEFAULT_COUNT : input.getCount();
|
||||
final String query = input.getQuery() == null ? DEFAULT_QUERY : input.getQuery();
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
// First, get all policy Urns.
|
||||
final ListResult gmsResult =
|
||||
_entityClient.list(CORP_USER_ENTITY_NAME, Collections.emptyMap(), start, count, context.getAuthentication());
|
||||
final SearchResult gmsResult =
|
||||
_entityClient.search(CORP_USER_ENTITY_NAME, query, Collections.emptyMap(), start, count, context.getAuthentication());
|
||||
|
||||
// Then, get hydrate all users.
|
||||
final Map<Urn, EntityResponse> entities = _entityClient.batchGetV2(CORP_USER_ENTITY_NAME,
|
||||
new HashSet<>(gmsResult.getEntities()), null, context.getAuthentication());
|
||||
new HashSet<>(gmsResult.getEntities().stream()
|
||||
.map(SearchEntity::getEntity)
|
||||
.collect(Collectors.toList())
|
||||
), null, context.getAuthentication());
|
||||
|
||||
// Now that we have entities we can bind this to a result.
|
||||
final ListUsersResult result = new ListUsersResult();
|
||||
result.setStart(gmsResult.getStart());
|
||||
result.setCount(gmsResult.getCount());
|
||||
result.setTotal(gmsResult.getTotal());
|
||||
result.setStart(gmsResult.getFrom());
|
||||
result.setCount(gmsResult.getPageSize());
|
||||
result.setTotal(gmsResult.getNumEntities());
|
||||
result.setUsers(mapEntities(entities.values()));
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
|
@ -6336,6 +6336,11 @@ input ListPoliciesInput {
|
||||
The maximum number of Policies to be returned in the result set
|
||||
"""
|
||||
count: Int
|
||||
|
||||
"""
|
||||
Optional search query
|
||||
"""
|
||||
query: String
|
||||
}
|
||||
|
||||
"""
|
||||
@ -6416,6 +6421,11 @@ input ListUsersInput {
|
||||
The maximum number of Policies to be returned in the result set
|
||||
"""
|
||||
count: Int
|
||||
|
||||
"""
|
||||
Optional search query
|
||||
"""
|
||||
query: String
|
||||
}
|
||||
|
||||
"""
|
||||
@ -6456,6 +6466,11 @@ input ListGroupsInput {
|
||||
The maximum number of Policies to be returned in the result set
|
||||
"""
|
||||
count: Int
|
||||
|
||||
"""
|
||||
Optional search query
|
||||
"""
|
||||
query: String
|
||||
}
|
||||
|
||||
type EntityCountResults {
|
||||
@ -7577,6 +7592,11 @@ input ListDomainsInput {
|
||||
The maximum number of Domains to be returned in the result set
|
||||
"""
|
||||
count: Int
|
||||
|
||||
"""
|
||||
Optional search query
|
||||
"""
|
||||
query: String
|
||||
}
|
||||
|
||||
"""
|
||||
|
@ -188,6 +188,11 @@ input ListSecretsInput {
|
||||
The number of results to be returned
|
||||
"""
|
||||
count: Int
|
||||
|
||||
"""
|
||||
An optional search query
|
||||
"""
|
||||
query: String
|
||||
}
|
||||
|
||||
"""
|
||||
@ -354,6 +359,11 @@ input ListIngestionSourcesInput {
|
||||
The number of results to be returned
|
||||
"""
|
||||
count: Int
|
||||
|
||||
"""
|
||||
An optional search query
|
||||
"""
|
||||
query: String
|
||||
}
|
||||
|
||||
"""
|
||||
|
@ -2,13 +2,14 @@ package com.linkedin.datahub.graphql.resolvers.domain;
|
||||
|
||||
import com.datahub.authentication.Authentication;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.linkedin.common.UrnArray;
|
||||
import com.linkedin.common.urn.Urn;
|
||||
import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.generated.ListDomainsInput;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.metadata.Constants;
|
||||
import com.linkedin.metadata.query.ListResult;
|
||||
import com.linkedin.metadata.search.SearchEntity;
|
||||
import com.linkedin.metadata.search.SearchEntityArray;
|
||||
import com.linkedin.metadata.search.SearchResult;
|
||||
import com.linkedin.r2.RemoteInvocationException;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import java.util.Collections;
|
||||
@ -25,7 +26,7 @@ public class ListDomainsResolverTest {
|
||||
private static final Urn TEST_DOMAIN_URN = Urn.createFromTuple("domain", "test-id");
|
||||
|
||||
private static final ListDomainsInput TEST_INPUT = new ListDomainsInput(
|
||||
0, 20
|
||||
0, 20, null
|
||||
);
|
||||
|
||||
@Test
|
||||
@ -33,18 +34,19 @@ public class ListDomainsResolverTest {
|
||||
// Create resolver
|
||||
EntityClient mockClient = Mockito.mock(EntityClient.class);
|
||||
|
||||
Mockito.when(mockClient.list(
|
||||
Mockito.when(mockClient.search(
|
||||
Mockito.eq(Constants.DOMAIN_ENTITY_NAME),
|
||||
Mockito.eq(""),
|
||||
Mockito.eq(Collections.emptyMap()),
|
||||
Mockito.eq(0),
|
||||
Mockito.eq(20),
|
||||
Mockito.any(Authentication.class)
|
||||
)).thenReturn(
|
||||
new ListResult()
|
||||
.setStart(0)
|
||||
.setCount(1)
|
||||
.setTotal(1)
|
||||
.setEntities(new UrnArray(ImmutableSet.of(TEST_DOMAIN_URN)))
|
||||
new SearchResult()
|
||||
.setFrom(0)
|
||||
.setPageSize(1)
|
||||
.setNumEntities(1)
|
||||
.setEntities(new SearchEntityArray(ImmutableSet.of(new SearchEntity().setEntity(TEST_DOMAIN_URN))))
|
||||
);
|
||||
|
||||
ListDomainsResolver resolver = new ListDomainsResolver(mockClient);
|
||||
@ -77,8 +79,9 @@ public class ListDomainsResolverTest {
|
||||
Mockito.when(mockEnv.getContext()).thenReturn(mockContext);
|
||||
|
||||
assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join());
|
||||
Mockito.verify(mockClient, Mockito.times(0)).list(
|
||||
Mockito.verify(mockClient, Mockito.times(0)).search(
|
||||
Mockito.any(),
|
||||
Mockito.eq("*"),
|
||||
Mockito.anyMap(),
|
||||
Mockito.anyInt(),
|
||||
Mockito.anyInt(),
|
||||
@ -89,8 +92,9 @@ public class ListDomainsResolverTest {
|
||||
public void testGetEntityClientException() throws Exception {
|
||||
// Create resolver
|
||||
EntityClient mockClient = Mockito.mock(EntityClient.class);
|
||||
Mockito.doThrow(RemoteInvocationException.class).when(mockClient).list(
|
||||
Mockito.doThrow(RemoteInvocationException.class).when(mockClient).search(
|
||||
Mockito.any(),
|
||||
Mockito.eq(""),
|
||||
Mockito.anyMap(),
|
||||
Mockito.anyInt(),
|
||||
Mockito.anyInt(),
|
||||
|
@ -3,7 +3,6 @@ package com.linkedin.datahub.graphql.resolvers.ingest.secret;
|
||||
import com.datahub.authentication.Authentication;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.linkedin.common.UrnArray;
|
||||
import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.generated.ListSecretsInput;
|
||||
import com.linkedin.entity.Aspect;
|
||||
@ -12,7 +11,9 @@ import com.linkedin.entity.EnvelopedAspect;
|
||||
import com.linkedin.entity.EnvelopedAspectMap;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.metadata.Constants;
|
||||
import com.linkedin.metadata.query.ListResult;
|
||||
import com.linkedin.metadata.search.SearchEntity;
|
||||
import com.linkedin.metadata.search.SearchEntityArray;
|
||||
import com.linkedin.metadata.search.SearchResult;
|
||||
import com.linkedin.r2.RemoteInvocationException;
|
||||
import com.linkedin.secret.DataHubSecretValue;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
@ -28,7 +29,7 @@ import static org.testng.Assert.*;
|
||||
public class ListSecretsResolverTest {
|
||||
|
||||
private static final ListSecretsInput TEST_INPUT = new ListSecretsInput(
|
||||
0, 20
|
||||
0, 20, null
|
||||
);
|
||||
|
||||
@Test
|
||||
@ -38,18 +39,19 @@ public class ListSecretsResolverTest {
|
||||
|
||||
DataHubSecretValue returnedValue = getTestSecretValue();
|
||||
|
||||
Mockito.when(mockClient.list(
|
||||
Mockito.when(mockClient.search(
|
||||
Mockito.eq(Constants.SECRETS_ENTITY_NAME),
|
||||
Mockito.eq(""),
|
||||
Mockito.eq(Collections.emptyMap()),
|
||||
Mockito.eq(0),
|
||||
Mockito.eq(20),
|
||||
Mockito.any(Authentication.class)
|
||||
)).thenReturn(
|
||||
new ListResult()
|
||||
.setStart(0)
|
||||
.setCount(1)
|
||||
.setTotal(1)
|
||||
.setEntities(new UrnArray(ImmutableSet.of(TEST_SECRET_URN)))
|
||||
new SearchResult()
|
||||
.setFrom(0)
|
||||
.setPageSize(1)
|
||||
.setNumEntities(1)
|
||||
.setEntities(new SearchEntityArray(ImmutableSet.of(new SearchEntity().setEntity(TEST_SECRET_URN))))
|
||||
);
|
||||
|
||||
Mockito.when(mockClient.batchGetV2(
|
||||
@ -104,8 +106,9 @@ public class ListSecretsResolverTest {
|
||||
Mockito.anySet(),
|
||||
Mockito.anySet(),
|
||||
Mockito.any(Authentication.class));
|
||||
Mockito.verify(mockClient, Mockito.times(0)).list(
|
||||
Mockito.verify(mockClient, Mockito.times(0)).search(
|
||||
Mockito.any(),
|
||||
Mockito.eq(""),
|
||||
Mockito.anyMap(),
|
||||
Mockito.anyInt(),
|
||||
Mockito.anyInt(),
|
||||
|
@ -3,7 +3,6 @@ package com.linkedin.datahub.graphql.resolvers.ingest.source;
|
||||
import com.datahub.authentication.Authentication;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.linkedin.common.UrnArray;
|
||||
import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.generated.ListIngestionSourcesInput;
|
||||
import com.linkedin.entity.Aspect;
|
||||
@ -13,7 +12,9 @@ import com.linkedin.entity.EnvelopedAspectMap;
|
||||
import com.linkedin.entity.client.EntityClient;
|
||||
import com.linkedin.ingestion.DataHubIngestionSourceInfo;
|
||||
import com.linkedin.metadata.Constants;
|
||||
import com.linkedin.metadata.query.ListResult;
|
||||
import com.linkedin.metadata.search.SearchEntity;
|
||||
import com.linkedin.metadata.search.SearchEntityArray;
|
||||
import com.linkedin.metadata.search.SearchResult;
|
||||
import com.linkedin.r2.RemoteInvocationException;
|
||||
import graphql.schema.DataFetchingEnvironment;
|
||||
import java.util.Collections;
|
||||
@ -27,7 +28,7 @@ import static org.testng.Assert.*;
|
||||
|
||||
public class ListIngestionSourceResolverTest {
|
||||
|
||||
private static final ListIngestionSourcesInput TEST_INPUT = new ListIngestionSourcesInput(0, 20);
|
||||
private static final ListIngestionSourcesInput TEST_INPUT = new ListIngestionSourcesInput(0, 20, null);
|
||||
|
||||
@Test
|
||||
public void testGetSuccess() throws Exception {
|
||||
@ -36,18 +37,19 @@ public class ListIngestionSourceResolverTest {
|
||||
|
||||
DataHubIngestionSourceInfo returnedInfo = getTestIngestionSourceInfo();
|
||||
|
||||
Mockito.when(mockClient.list(
|
||||
Mockito.when(mockClient.search(
|
||||
Mockito.eq(Constants.INGESTION_SOURCE_ENTITY_NAME),
|
||||
Mockito.eq(""),
|
||||
Mockito.eq(Collections.emptyMap()),
|
||||
Mockito.eq(0),
|
||||
Mockito.eq(20),
|
||||
Mockito.any(Authentication.class)
|
||||
)).thenReturn(
|
||||
new ListResult()
|
||||
.setStart(0)
|
||||
.setCount(1)
|
||||
.setTotal(1)
|
||||
.setEntities(new UrnArray(ImmutableSet.of(TEST_INGESTION_SOURCE_URN)))
|
||||
new SearchResult()
|
||||
.setFrom(0)
|
||||
.setPageSize(1)
|
||||
.setNumEntities(1)
|
||||
.setEntities(new SearchEntityArray(ImmutableSet.of(new SearchEntity().setEntity(TEST_INGESTION_SOURCE_URN))))
|
||||
);
|
||||
|
||||
Mockito.when(mockClient.batchGetV2(
|
||||
@ -102,8 +104,9 @@ public class ListIngestionSourceResolverTest {
|
||||
Mockito.anySet(),
|
||||
Mockito.anySet(),
|
||||
Mockito.any(Authentication.class));
|
||||
Mockito.verify(mockClient, Mockito.times(0)).list(
|
||||
Mockito.verify(mockClient, Mockito.times(0)).search(
|
||||
Mockito.any(),
|
||||
Mockito.eq(""),
|
||||
Mockito.anyMap(),
|
||||
Mockito.anyInt(),
|
||||
Mockito.anyInt(),
|
||||
|
@ -1,6 +1,8 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Empty, List, message, Pagination, Typography } from 'antd';
|
||||
import { useLocation } from 'react-router';
|
||||
import styled from 'styled-components';
|
||||
import * as QueryString from 'query-string';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Domain } from '../../types.generated';
|
||||
import { useListDomainsQuery } from '../../graphql/domain.generated';
|
||||
@ -8,6 +10,8 @@ import CreateDomainModal from './CreateDomainModal';
|
||||
import { Message } from '../shared/Message';
|
||||
import TabToolbar from '../entity/shared/components/styled/TabToolbar';
|
||||
import DomainListItem from './DomainListItem';
|
||||
import { SearchBar } from '../search/SearchBar';
|
||||
import { useEntityRegistry } from '../useEntityRegistry';
|
||||
|
||||
const DomainsContainer = styled.div``;
|
||||
|
||||
@ -37,6 +41,13 @@ const PaginationInfo = styled(Typography.Text)`
|
||||
const DEFAULT_PAGE_SIZE = 25;
|
||||
|
||||
export const DomainsList = () => {
|
||||
const entityRegistry = useEntityRegistry();
|
||||
const location = useLocation();
|
||||
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });
|
||||
const paramsQuery = (params?.query as string) || undefined;
|
||||
const [query, setQuery] = useState<undefined | string>(undefined);
|
||||
useEffect(() => setQuery(paramsQuery), [paramsQuery]);
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
const [isCreatingDomain, setIsCreatingDomain] = useState(false);
|
||||
|
||||
@ -48,6 +59,7 @@ export const DomainsList = () => {
|
||||
input: {
|
||||
start,
|
||||
count: pageSize,
|
||||
query,
|
||||
},
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
@ -76,6 +88,22 @@ export const DomainsList = () => {
|
||||
<PlusOutlined /> New Domain
|
||||
</Button>
|
||||
</div>
|
||||
<SearchBar
|
||||
initialQuery={query || ''}
|
||||
placeholderText="Search domains..."
|
||||
suggestions={[]}
|
||||
style={{
|
||||
maxWidth: 220,
|
||||
padding: 0,
|
||||
}}
|
||||
inputStyle={{
|
||||
height: 32,
|
||||
fontSize: 12,
|
||||
}}
|
||||
onSearch={() => null}
|
||||
onQueryChange={(q) => setQuery(q)}
|
||||
entityRegistry={entityRegistry}
|
||||
/>
|
||||
</TabToolbar>
|
||||
<DomainsStyledList
|
||||
bordered
|
||||
|
@ -1,6 +1,8 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Empty, List, message, Pagination } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import { useLocation } from 'react-router';
|
||||
import * as QueryString from 'query-string';
|
||||
import { UsergroupAddOutlined } from '@ant-design/icons';
|
||||
import { CorpGroup } from '../../../types.generated';
|
||||
import { Message } from '../../shared/Message';
|
||||
@ -8,6 +10,8 @@ import { useListGroupsQuery } from '../../../graphql/group.generated';
|
||||
import GroupListItem from './GroupListItem';
|
||||
import TabToolbar from '../../entity/shared/components/styled/TabToolbar';
|
||||
import CreateGroupModal from './CreateGroupModal';
|
||||
import { SearchBar } from '../../search/SearchBar';
|
||||
import { useEntityRegistry } from '../../useEntityRegistry';
|
||||
|
||||
const GroupContainer = styled.div``;
|
||||
|
||||
@ -26,6 +30,13 @@ const GroupPaginationContainer = styled.div`
|
||||
const DEFAULT_PAGE_SIZE = 25;
|
||||
|
||||
export const GroupList = () => {
|
||||
const entityRegistry = useEntityRegistry();
|
||||
const location = useLocation();
|
||||
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });
|
||||
const paramsQuery = (params?.query as string) || undefined;
|
||||
const [query, setQuery] = useState<undefined | string>(undefined);
|
||||
useEffect(() => setQuery(paramsQuery), [paramsQuery]);
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
const [isCreatingGroup, setIsCreatingGroup] = useState(false);
|
||||
const [removedUrns, setRemovedUrns] = useState<string[]>([]);
|
||||
@ -39,6 +50,7 @@ export const GroupList = () => {
|
||||
input: {
|
||||
start,
|
||||
count: pageSize,
|
||||
query,
|
||||
},
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
@ -72,6 +84,22 @@ export const GroupList = () => {
|
||||
<UsergroupAddOutlined /> Create group
|
||||
</Button>
|
||||
</div>
|
||||
<SearchBar
|
||||
initialQuery={query || ''}
|
||||
placeholderText="Search groups..."
|
||||
suggestions={[]}
|
||||
style={{
|
||||
maxWidth: 220,
|
||||
padding: 0,
|
||||
}}
|
||||
inputStyle={{
|
||||
height: 32,
|
||||
fontSize: 12,
|
||||
}}
|
||||
onSearch={() => null}
|
||||
onQueryChange={(q) => setQuery(q)}
|
||||
entityRegistry={entityRegistry}
|
||||
/>
|
||||
</TabToolbar>
|
||||
<GroupStyledList
|
||||
bordered
|
||||
|
@ -1,10 +1,15 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Empty, List, message, Pagination } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import * as QueryString from 'query-string';
|
||||
import { useLocation } from 'react-router';
|
||||
import UserListItem from './UserListItem';
|
||||
import { Message } from '../../shared/Message';
|
||||
import { useListUsersQuery } from '../../../graphql/user.generated';
|
||||
import { CorpUser } from '../../../types.generated';
|
||||
import TabToolbar from '../../entity/shared/components/styled/TabToolbar';
|
||||
import { SearchBar } from '../../search/SearchBar';
|
||||
import { useEntityRegistry } from '../../useEntityRegistry';
|
||||
|
||||
const UserContainer = styled.div``;
|
||||
|
||||
@ -23,6 +28,13 @@ const UserPaginationContainer = styled.div`
|
||||
const DEFAULT_PAGE_SIZE = 25;
|
||||
|
||||
export const UserList = () => {
|
||||
const entityRegistry = useEntityRegistry();
|
||||
const location = useLocation();
|
||||
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });
|
||||
const paramsQuery = (params?.query as string) || undefined;
|
||||
const [query, setQuery] = useState<undefined | string>(undefined);
|
||||
useEffect(() => setQuery(paramsQuery), [paramsQuery]);
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
const [removedUrns, setRemovedUrns] = useState<string[]>([]);
|
||||
|
||||
@ -34,6 +46,7 @@ export const UserList = () => {
|
||||
input: {
|
||||
start,
|
||||
count: pageSize,
|
||||
query,
|
||||
},
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
@ -61,6 +74,27 @@ export const UserList = () => {
|
||||
{!data && loading && <Message type="loading" content="Loading users..." />}
|
||||
{error && message.error('Failed to load users :(')}
|
||||
<UserContainer>
|
||||
<TabToolbar>
|
||||
<div>
|
||||
<></>
|
||||
</div>
|
||||
<SearchBar
|
||||
initialQuery={query || ''}
|
||||
placeholderText="Search users..."
|
||||
suggestions={[]}
|
||||
style={{
|
||||
maxWidth: 220,
|
||||
padding: 0,
|
||||
}}
|
||||
inputStyle={{
|
||||
height: 32,
|
||||
fontSize: 12,
|
||||
}}
|
||||
onSearch={() => null}
|
||||
onQueryChange={(q) => setQuery(q)}
|
||||
entityRegistry={entityRegistry}
|
||||
/>
|
||||
</TabToolbar>
|
||||
<UserStyledList
|
||||
bordered
|
||||
locale={{
|
||||
|
@ -1,6 +1,8 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Empty, message, Modal, Pagination, Typography } from 'antd';
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import * as QueryString from 'query-string';
|
||||
import { useLocation } from 'react-router';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
useCreateSecretMutation,
|
||||
@ -12,6 +14,8 @@ import TabToolbar from '../../entity/shared/components/styled/TabToolbar';
|
||||
import { SecretBuilderModal } from './SecretBuilderModal';
|
||||
import { SecretBuilderState } from './types';
|
||||
import { StyledTable } from '../../entity/shared/components/styled/StyledTable';
|
||||
import { SearchBar } from '../../search/SearchBar';
|
||||
import { useEntityRegistry } from '../../useEntityRegistry';
|
||||
|
||||
const DeleteButtonContainer = styled.div`
|
||||
display: flex;
|
||||
@ -26,6 +30,13 @@ const SourcePaginationContainer = styled.div`
|
||||
const DEFAULT_PAGE_SIZE = 25;
|
||||
|
||||
export const SecretsList = () => {
|
||||
const entityRegistry = useEntityRegistry();
|
||||
const location = useLocation();
|
||||
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });
|
||||
const paramsQuery = (params?.query as string) || undefined;
|
||||
const [query, setQuery] = useState<undefined | string>(undefined);
|
||||
useEffect(() => setQuery(paramsQuery), [paramsQuery]);
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
const pageSize = DEFAULT_PAGE_SIZE;
|
||||
@ -42,6 +53,7 @@ export const SecretsList = () => {
|
||||
input: {
|
||||
start,
|
||||
count: pageSize,
|
||||
query,
|
||||
},
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
@ -163,6 +175,22 @@ export const SecretsList = () => {
|
||||
<PlusOutlined /> Create new secret
|
||||
</Button>
|
||||
</div>
|
||||
<SearchBar
|
||||
initialQuery={query || ''}
|
||||
placeholderText="Search secrets..."
|
||||
suggestions={[]}
|
||||
style={{
|
||||
maxWidth: 220,
|
||||
padding: 0,
|
||||
}}
|
||||
inputStyle={{
|
||||
height: 32,
|
||||
fontSize: 12,
|
||||
}}
|
||||
onSearch={() => null}
|
||||
onQueryChange={(q) => setQuery(q)}
|
||||
entityRegistry={entityRegistry}
|
||||
/>
|
||||
</TabToolbar>
|
||||
<StyledTable
|
||||
columns={tableColumns}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { CopyOutlined, DeleteOutlined, PlusOutlined, RedoOutlined } from '@ant-design/icons';
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import * as QueryString from 'query-string';
|
||||
import { useLocation } from 'react-router';
|
||||
import { Button, Empty, Image, message, Modal, Pagination, Tooltip, Typography } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import cronstrue from 'cronstrue';
|
||||
@ -24,6 +26,8 @@ import {
|
||||
import { DEFAULT_EXECUTOR_ID, SourceBuilderState } from './builder/types';
|
||||
import { UpdateIngestionSourceInput } from '../../../types.generated';
|
||||
import { capitalizeFirstLetter } from '../../shared/textUtil';
|
||||
import { SearchBar } from '../../search/SearchBar';
|
||||
import { useEntityRegistry } from '../../useEntityRegistry';
|
||||
|
||||
const SourceContainer = styled.div``;
|
||||
|
||||
@ -66,6 +70,13 @@ const removeExecutionsFromIngestionSource = (source) => {
|
||||
};
|
||||
|
||||
export const IngestionSourceList = () => {
|
||||
const entityRegistry = useEntityRegistry();
|
||||
const location = useLocation();
|
||||
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });
|
||||
const paramsQuery = (params?.query as string) || undefined;
|
||||
const [query, setQuery] = useState<undefined | string>(undefined);
|
||||
useEffect(() => setQuery(paramsQuery), [paramsQuery]);
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
const pageSize = DEFAULT_PAGE_SIZE;
|
||||
@ -83,6 +94,7 @@ export const IngestionSourceList = () => {
|
||||
input: {
|
||||
start,
|
||||
count: pageSize,
|
||||
query,
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -404,6 +416,22 @@ export const IngestionSourceList = () => {
|
||||
<RedoOutlined /> Refresh
|
||||
</Button>
|
||||
</div>
|
||||
<SearchBar
|
||||
initialQuery={query || ''}
|
||||
placeholderText="Search sources..."
|
||||
suggestions={[]}
|
||||
style={{
|
||||
maxWidth: 220,
|
||||
padding: 0,
|
||||
}}
|
||||
inputStyle={{
|
||||
height: 32,
|
||||
fontSize: 12,
|
||||
}}
|
||||
onSearch={() => null}
|
||||
onQueryChange={(q) => setQuery(q)}
|
||||
entityRegistry={entityRegistry}
|
||||
/>
|
||||
</TabToolbar>
|
||||
<StyledTable
|
||||
columns={tableColumns}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { Button, Empty, message, Modal, Pagination, Tag, Typography } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import * as QueryString from 'query-string';
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { useLocation } from 'react-router';
|
||||
|
||||
import { SearchablePage } from '../search/SearchablePage';
|
||||
import PolicyBuilderModal from './PolicyBuilderModal';
|
||||
@ -31,6 +33,7 @@ import { StyledTable } from '../entity/shared/components/styled/StyledTable';
|
||||
import AvatarsGroup from './AvatarsGroup';
|
||||
import { useEntityRegistry } from '../useEntityRegistry';
|
||||
import { ANTD_GRAY } from '../entity/shared/constants';
|
||||
import { SearchBar } from '../search/SearchBar';
|
||||
|
||||
const PoliciesContainer = styled.div`
|
||||
padding-top: 20px;
|
||||
@ -138,6 +141,12 @@ const toPolicyInput = (policy: Omit<Policy, 'urn'>): PolicyUpdateInput => {
|
||||
// TODO: Cleanup the styling.
|
||||
export const PoliciesPage = () => {
|
||||
const entityRegistry = useEntityRegistry();
|
||||
const location = useLocation();
|
||||
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });
|
||||
const paramsQuery = (params?.query as string) || undefined;
|
||||
const [query, setQuery] = useState<undefined | string>(undefined);
|
||||
useEffect(() => setQuery(paramsQuery), [paramsQuery]);
|
||||
|
||||
const {
|
||||
config: { policiesConfig },
|
||||
} = useAppConfig();
|
||||
@ -166,7 +175,13 @@ export const PoliciesPage = () => {
|
||||
refetch: policiesRefetch,
|
||||
} = useListPoliciesQuery({
|
||||
fetchPolicy: 'no-cache',
|
||||
variables: { input: { start, count: pageSize } },
|
||||
variables: {
|
||||
input: {
|
||||
start,
|
||||
count: pageSize,
|
||||
query,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Any time a policy is removed, edited, or created, refetch the list.
|
||||
@ -402,7 +417,9 @@ export const PoliciesPage = () => {
|
||||
|
||||
return (
|
||||
<SearchablePage>
|
||||
{policiesLoading && <Message type="loading" content="Loading policies..." style={{ marginTop: '10%' }} />}
|
||||
{policiesLoading && !policiesData && (
|
||||
<Message type="loading" content="Loading policies..." style={{ marginTop: '10%' }} />
|
||||
)}
|
||||
{policiesError && message.error('Failed to load policies :(')}
|
||||
{updateError && message.error('Failed to update the Policy :(')}
|
||||
<PoliciesContainer>
|
||||
@ -420,6 +437,22 @@ export const PoliciesPage = () => {
|
||||
<PlusOutlined /> Create new policy
|
||||
</Button>
|
||||
</div>
|
||||
<SearchBar
|
||||
initialQuery={query || ''}
|
||||
placeholderText="Search policies..."
|
||||
suggestions={[]}
|
||||
style={{
|
||||
maxWidth: 220,
|
||||
padding: 0,
|
||||
}}
|
||||
inputStyle={{
|
||||
height: 32,
|
||||
fontSize: 12,
|
||||
}}
|
||||
onSearch={() => null}
|
||||
onQueryChange={(q) => setQuery(q)}
|
||||
entityRegistry={entityRegistry}
|
||||
/>
|
||||
</TabToolbar>
|
||||
<StyledTable
|
||||
columns={tableColumns}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { Input, AutoComplete, Image, Typography } from 'antd';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import styled from 'styled-components';
|
||||
@ -185,6 +185,7 @@ export const SearchBar = ({
|
||||
const history = useHistory();
|
||||
const [searchQuery, setSearchQuery] = useState<string>();
|
||||
const [selected, setSelected] = useState<string>();
|
||||
useEffect(() => setSelected(initialQuery), [initialQuery]);
|
||||
const searchEntityTypes = entityRegistry.getSearchEntityTypes();
|
||||
const userUrn = useGetAuthenticatedUserUrn();
|
||||
const { data } = useListRecommendationsQuery({
|
||||
|
@ -12,13 +12,16 @@ record DataHubPolicyInfo {
|
||||
* Display name of the Policy
|
||||
*/
|
||||
@Searchable = {
|
||||
"fieldType": "KEYWORD"
|
||||
"fieldType": "TEXT_PARTIAL"
|
||||
}
|
||||
displayName: string
|
||||
|
||||
/**
|
||||
* Description of the Policy
|
||||
*/
|
||||
@Searchable = {
|
||||
"fieldType": "TEXT"
|
||||
}
|
||||
description: string
|
||||
|
||||
/**
|
||||
|
@ -39,10 +39,15 @@ public class PolicyFetcher {
|
||||
|
||||
public PolicyFetchResult fetchPolicies(int start, int count, Authentication authentication)
|
||||
throws RemoteInvocationException, URISyntaxException {
|
||||
return fetchPolicies(start, count, "", authentication);
|
||||
}
|
||||
|
||||
public PolicyFetchResult fetchPolicies(int start, int count, String query, Authentication authentication)
|
||||
throws RemoteInvocationException, URISyntaxException {
|
||||
log.debug(String.format("Batch fetching policies. start: %s, count: %s ", start, count));
|
||||
// First fetch all policy urns from start - start + count
|
||||
SearchResult result =
|
||||
_entityClient.search(POLICY_ENTITY_NAME, "*", null, POLICY_SORT_CRITERION, start, count, authentication);
|
||||
_entityClient.search(POLICY_ENTITY_NAME, query, null, POLICY_SORT_CRITERION, start, count, authentication);
|
||||
List<Urn> policyUrns = result.getEntities().stream().map(SearchEntity::getEntity).collect(Collectors.toList());
|
||||
|
||||
if (policyUrns.isEmpty()) {
|
||||
|
@ -75,7 +75,7 @@ public class DataHubAuthorizerTest {
|
||||
policySearchResult.setEntities(new SearchEntityArray(ImmutableList.of(new SearchEntity().setEntity(activePolicyUrn),
|
||||
new SearchEntity().setEntity(inactivePolicyUrn))));
|
||||
|
||||
when(_entityClient.search(eq("dataHubPolicy"), eq("*"), isNull(), any(), anyInt(), anyInt(), any())).thenReturn(
|
||||
when(_entityClient.search(eq("dataHubPolicy"), eq(""), isNull(), any(), anyInt(), anyInt(), any())).thenReturn(
|
||||
policySearchResult);
|
||||
when(_entityClient.batchGetV2(eq(POLICY_ENTITY_NAME),
|
||||
eq(ImmutableSet.of(activePolicyUrn, inactivePolicyUrn)), eq(null), any())).thenReturn(
|
||||
@ -192,7 +192,7 @@ public class DataHubAuthorizerTest {
|
||||
emptyResult.setNumEntities(0);
|
||||
emptyResult.setEntities(new SearchEntityArray());
|
||||
|
||||
when(_entityClient.search(eq("dataHubPolicy"), eq("*"), isNull(), any(), anyInt(), anyInt(), any())).thenReturn(
|
||||
when(_entityClient.search(eq("dataHubPolicy"), eq(""), isNull(), any(), anyInt(), anyInt(), any())).thenReturn(
|
||||
emptyResult);
|
||||
when(_entityClient.batchGetV2(eq(POLICY_ENTITY_NAME), eq(Collections.emptySet()), eq(null), any())).thenReturn(
|
||||
Collections.emptyMap());
|
||||
|
Loading…
x
Reference in New Issue
Block a user