diff --git a/.github/workflows/docker-unified.yml b/.github/workflows/docker-unified.yml index 075da20cdd11cc..9e9a0ed9884b46 100644 --- a/.github/workflows/docker-unified.yml +++ b/.github/workflows/docker-unified.yml @@ -990,7 +990,7 @@ jobs: DATAHUB_VERSION: ${{ needs.setup.outputs.unique_tag }} DATAHUB_ACTIONS_IMAGE: ${{ env.DATAHUB_INGESTION_IMAGE }} ACTIONS_VERSION: ${{ needs.datahub_ingestion_slim_build.outputs.tag || 'head-slim' }} - ACTIONS_EXTRA_PACKAGES: "acryl-datahub-actions[executor]==0.0.13 acryl-datahub-actions==0.0.13 acryl-datahub==0.10.5" + ACTIONS_EXTRA_PACKAGES: "acryl-datahub-actions[executor] acryl-datahub-actions" ACTIONS_CONFIG: "https://raw.githubusercontent.com/acryldata/datahub-actions/main/docker/config/executor.yaml" run: | ./smoke-test/run-quickstart.sh diff --git a/build.gradle b/build.gradle index fbced335ddc2e7..07ca1f09e813c3 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ buildscript { ext.hadoop3Version = '3.3.6' ext.kafkaVersion = '5.5.15' ext.hazelcastVersion = '5.3.6' - ext.ebeanVersion = '12.16.1' + ext.ebeanVersion = '15.5.2' ext.googleJavaFormatVersion = '1.18.1' ext.openLineageVersion = '1.19.0' ext.logbackClassicJava8 = '1.2.12' @@ -104,8 +104,8 @@ project.ext.spec = [ project.ext.externalDependency = [ 'akkaHttp': 'com.typesafe.akka:akka-http-core_2.12:10.2.10', - 'antlr4Runtime': 'org.antlr:antlr4-runtime:4.7.2', - 'antlr4': 'org.antlr:antlr4:4.7.2', + 'antlr4Runtime': 'org.antlr:antlr4-runtime:4.9.3', + 'antlr4': 'org.antlr:antlr4:4.9.3', 'assertJ': 'org.assertj:assertj-core:3.11.1', 'avro': 'org.apache.avro:avro:1.11.3', 'avroCompiler': 'org.apache.avro:avro-compiler:1.11.3', @@ -129,8 +129,10 @@ project.ext.externalDependency = [ 'dropwizardMetricsCore': 'io.dropwizard.metrics:metrics-core:4.2.3', 'dropwizardMetricsJmx': 'io.dropwizard.metrics:metrics-jmx:4.2.3', 'ebean': 'io.ebean:ebean:' + ebeanVersion, + 'ebeanTest': 'io.ebean:ebean-test:' + ebeanVersion, 'ebeanAgent': 'io.ebean:ebean-agent:' + ebeanVersion, 'ebeanDdl': 'io.ebean:ebean-ddl-generator:' + ebeanVersion, + 'ebeanQueryBean': 'io.ebean:querybean-generator:' + ebeanVersion, 'elasticSearchRest': 'org.opensearch.client:opensearch-rest-high-level-client:' + elasticsearchVersion, 'elasticSearchJava': 'org.opensearch.client:opensearch-java:2.6.0', 'findbugsAnnotations': 'com.google.code.findbugs:annotations:3.0.1', @@ -359,6 +361,9 @@ configure(subprojects.findAll {! it.name.startsWith('spark-lineage')}) { exclude group: "org.slf4j", module: "slf4j-log4j12" exclude group: "org.slf4j", module: "slf4j-nop" exclude group: "org.slf4j", module: "slf4j-ext" + + resolutionStrategy.force externalDependency.antlr4Runtime + resolutionStrategy.force externalDependency.antlr4 } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java index de77ff9444c6e7..d38c1030b61be8 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java @@ -293,6 +293,7 @@ import com.linkedin.datahub.graphql.resolvers.step.BatchGetStepStatesResolver; import com.linkedin.datahub.graphql.resolvers.step.BatchUpdateStepStatesResolver; import com.linkedin.datahub.graphql.resolvers.structuredproperties.CreateStructuredPropertyResolver; +import com.linkedin.datahub.graphql.resolvers.structuredproperties.DeleteStructuredPropertyResolver; import com.linkedin.datahub.graphql.resolvers.structuredproperties.RemoveStructuredPropertiesResolver; import com.linkedin.datahub.graphql.resolvers.structuredproperties.UpdateStructuredPropertyResolver; import com.linkedin.datahub.graphql.resolvers.structuredproperties.UpsertStructuredPropertiesResolver; @@ -1034,6 +1035,7 @@ private void configureQueryResolvers(final RuntimeWiring.Builder builder) { .dataFetcher("assertion", getResolver(assertionType)) .dataFetcher("form", getResolver(formType)) .dataFetcher("view", getResolver(dataHubViewType)) + .dataFetcher("structuredProperty", getResolver(structuredPropertyType)) .dataFetcher("listPolicies", new ListPoliciesResolver(this.entityClient)) .dataFetcher("getGrantedPrivileges", new GetGrantedPrivilegesResolver()) .dataFetcher("listUsers", new ListUsersResolver(this.entityClient)) @@ -1343,6 +1345,9 @@ private void configureMutationResolvers(final RuntimeWiring.Builder builder) { .dataFetcher( "updateStructuredProperty", new UpdateStructuredPropertyResolver(this.entityClient)) + .dataFetcher( + "deleteStructuredProperty", + new DeleteStructuredPropertyResolver(this.entityClient)) .dataFetcher("raiseIncident", new RaiseIncidentResolver(this.entityClient)) .dataFetcher( "updateIncidentStatus", @@ -2116,6 +2121,9 @@ private void configureStructuredPropertyResolvers(final RuntimeWiring.Builder bu .getAllowedTypes().stream() .map(entityTypeType.getKeyProvider()) .collect(Collectors.toList())))); + builder.type( + "StructuredPropertyEntity", + typeWiring -> typeWiring.dataFetcher("exists", new EntityExistsResolver(entityService))); } /** diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ResolverUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ResolverUtils.java index d34fd9f32d322e..5f873b4bebab32 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ResolverUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ResolverUtils.java @@ -6,7 +6,6 @@ import com.datahub.authentication.Authentication; import com.fasterxml.jackson.core.StreamReadConstraints; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableSet; import com.linkedin.common.urn.UrnUtils; import com.linkedin.data.template.StringArray; import com.linkedin.datahub.graphql.QueryContext; @@ -14,14 +13,12 @@ import com.linkedin.datahub.graphql.generated.AndFilterInput; import com.linkedin.datahub.graphql.generated.FacetFilterInput; import com.linkedin.datahub.graphql.resolvers.search.SearchUtils; -import com.linkedin.metadata.aspect.AspectRetriever; import com.linkedin.metadata.query.filter.Condition; import com.linkedin.metadata.query.filter.ConjunctiveCriterion; import com.linkedin.metadata.query.filter.ConjunctiveCriterionArray; import com.linkedin.metadata.query.filter.Criterion; import com.linkedin.metadata.query.filter.CriterionArray; import com.linkedin.metadata.query.filter.Filter; -import com.linkedin.metadata.search.utils.ESUtils; import com.linkedin.metadata.service.ViewService; import com.linkedin.view.DataHubViewInfo; import graphql.schema.DataFetchingEnvironment; @@ -39,8 +36,6 @@ public class ResolverUtils { - private static final Set KEYWORD_EXCLUDED_FILTERS = - ImmutableSet.of("runId", "_entityType"); private static final ObjectMapper MAPPER = new ObjectMapper(); static { @@ -111,11 +106,10 @@ public static Map buildFacetFilters( return facetFilters; } - public static List criterionListFromAndFilter( - List andFilters, @Nullable AspectRetriever aspectRetriever) { + public static List criterionListFromAndFilter(List andFilters) { return andFilters != null && !andFilters.isEmpty() ? andFilters.stream() - .map(filter -> criterionFromFilter(filter, aspectRetriever)) + .map(filter -> criterionFromFilter(filter)) .collect(Collectors.toList()) : Collections.emptyList(); } @@ -124,14 +118,13 @@ public static List criterionListFromAndFilter( // conjunctive criterion // arrays, rather than just one for the AND case. public static ConjunctiveCriterionArray buildConjunctiveCriterionArrayWithOr( - @Nonnull List orFilters, @Nullable AspectRetriever aspectRetriever) { + @Nonnull List orFilters) { return new ConjunctiveCriterionArray( orFilters.stream() .map( orFilter -> { CriterionArray andCriterionForOr = - new CriterionArray( - criterionListFromAndFilter(orFilter.getAnd(), aspectRetriever)); + new CriterionArray(criterionListFromAndFilter(orFilter.getAnd())); return new ConjunctiveCriterion().setAnd(andCriterionForOr); }) .collect(Collectors.toList())); @@ -139,9 +132,7 @@ public static ConjunctiveCriterionArray buildConjunctiveCriterionArrayWithOr( @Nullable public static Filter buildFilter( - @Nullable List andFilters, - @Nullable List orFilters, - @Nullable AspectRetriever aspectRetriever) { + @Nullable List andFilters, @Nullable List orFilters) { if ((andFilters == null || andFilters.isEmpty()) && (orFilters == null || orFilters.isEmpty())) { return null; @@ -150,34 +141,21 @@ public static Filter buildFilter( // Or filters are the new default. We will check them first. // If we have OR filters, we need to build a series of CriterionArrays if (orFilters != null && !orFilters.isEmpty()) { - return new Filter().setOr(buildConjunctiveCriterionArrayWithOr(orFilters, aspectRetriever)); + return new Filter().setOr(buildConjunctiveCriterionArrayWithOr(orFilters)); } // If or filters are not set, someone may be using the legacy and filters - final List andCriterions = criterionListFromAndFilter(andFilters, aspectRetriever); + final List andCriterions = criterionListFromAndFilter(andFilters); return new Filter() .setOr( new ConjunctiveCriterionArray( new ConjunctiveCriterion().setAnd(new CriterionArray(andCriterions)))); } - public static Criterion criterionFromFilter( - final FacetFilterInput filter, @Nullable AspectRetriever aspectRetriever) { - return criterionFromFilter(filter, false, aspectRetriever); - } - // Translates a FacetFilterInput (graphql input class) into Criterion (our internal model) - public static Criterion criterionFromFilter( - final FacetFilterInput filter, - final Boolean skipKeywordSuffix, - @Nullable AspectRetriever aspectRetriever) { + public static Criterion criterionFromFilter(final FacetFilterInput filter) { Criterion result = new Criterion(); - - if (skipKeywordSuffix) { - result.setField(filter.getField()); - } else { - result.setField(getFilterField(filter.getField(), skipKeywordSuffix, aspectRetriever)); - } + result.setField(filter.getField()); // `value` is deprecated in place of `values`- this is to support old query patterns. If values // is provided, @@ -210,16 +188,6 @@ public static Criterion criterionFromFilter( return result; } - private static String getFilterField( - final String originalField, - final boolean skipKeywordSuffix, - @Nullable AspectRetriever aspectRetriever) { - if (KEYWORD_EXCLUDED_FILTERS.contains(originalField)) { - return originalField; - } - return ESUtils.toKeywordField(originalField, skipKeywordSuffix, aspectRetriever); - } - public static Filter viewFilter( OperationContext opContext, ViewService viewService, String viewUrn) { if (viewUrn == null) { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/assertion/AssertionRunEventResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/assertion/AssertionRunEventResolver.java index 0e9d2cea611416..f7e86f1f2f3452 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/assertion/AssertionRunEventResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/assertion/AssertionRunEventResolver.java @@ -12,6 +12,7 @@ import com.linkedin.datahub.graphql.generated.AssertionRunStatus; import com.linkedin.datahub.graphql.generated.FacetFilterInput; import com.linkedin.datahub.graphql.generated.FilterInput; +import com.linkedin.datahub.graphql.resolvers.ResolverUtils; import com.linkedin.datahub.graphql.types.dataset.mappers.AssertionRunEventMapper; import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; @@ -147,7 +148,7 @@ public static Filter buildFilter( .setAnd( new CriterionArray( facetFilters.stream() - .map(filter -> criterionFromFilter(filter, true, aspectRetriever)) + .map(ResolverUtils::criterionFromFilter) .collect(Collectors.toList()))))); } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/auth/ListAccessTokensResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/auth/ListAccessTokensResolver.java index e0ecebbbc7bc2e..29d44b526692f5 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/auth/ListAccessTokensResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/auth/ListAccessTokensResolver.java @@ -71,10 +71,7 @@ public CompletableFuture get(DataFetchingEnvironment envi .withSearchFlags(flags -> flags.setFulltext(true)), Constants.ACCESS_TOKEN_ENTITY_NAME, "", - buildFilter( - filters, - Collections.emptyList(), - context.getOperationContext().getAspectRetriever()), + buildFilter(filters, Collections.emptyList()), sortCriteria, start, count); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/chart/BrowseV2Resolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/chart/BrowseV2Resolver.java index b54ca398aef980..18ee5f595ce582 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/chart/BrowseV2Resolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/chart/BrowseV2Resolver.java @@ -74,9 +74,7 @@ public CompletableFuture get(DataFetchingEnvironment environmen ? BROWSE_PATH_V2_DELIMITER + String.join(BROWSE_PATH_V2_DELIMITER, input.getPath()) : ""; - final Filter inputFilter = - ResolverUtils.buildFilter( - null, input.getOrFilters(), context.getOperationContext().getAspectRetriever()); + final Filter inputFilter = ResolverUtils.buildFilter(null, input.getOrFilters()); BrowseResultV2 browseResults = _entityClient.browseV2( diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/dataproduct/ListDataProductAssetsResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/dataproduct/ListDataProductAssetsResolver.java index 5c43fafb678c5c..e59f7b3116acdb 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/dataproduct/ListDataProductAssetsResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/dataproduct/ListDataProductAssetsResolver.java @@ -151,11 +151,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) filters.removeIf(f -> f.getField().equals(OUTPUT_PORTS_FILTER_FIELD)); } // add urns from the aspect to our filters - final Filter baseFilter = - ResolverUtils.buildFilter( - filters, - input.getOrFilters(), - context.getOperationContext().getAspectRetriever()); + final Filter baseFilter = ResolverUtils.buildFilter(filters, input.getOrFilters()); final Filter finalFilter = buildFilterWithUrns( context.getDataHubAppConfig(), new HashSet<>(urnsToFilterOn), baseFilter); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DomainEntitiesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DomainEntitiesResolver.java index 6a880503802cb4..c6265380fb2fd0 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DomainEntitiesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DomainEntitiesResolver.java @@ -79,9 +79,7 @@ public CompletableFuture get(final DataFetchingEnvironment enviro .getFilters() .forEach( filter -> { - criteria.add( - criterionFromFilter( - filter, true, context.getOperationContext().getAspectRetriever())); + criteria.add(criterionFromFilter(filter)); }); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/form/CreateDynamicFormAssignmentResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/form/CreateDynamicFormAssignmentResolver.java index 3cf4d9175d45bf..b9d74f8af660e8 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/form/CreateDynamicFormAssignmentResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/form/CreateDynamicFormAssignmentResolver.java @@ -33,9 +33,7 @@ public CompletableFuture get(final DataFetchingEnvironment environment) final CreateDynamicFormAssignmentInput input = bindArgument(environment.getArgument("input"), CreateDynamicFormAssignmentInput.class); final Urn formUrn = UrnUtils.getUrn(input.getFormUrn()); - final DynamicFormAssignment formAssignment = - FormUtils.mapDynamicFormAssignment( - input, context.getOperationContext().getAspectRetriever()); + final DynamicFormAssignment formAssignment = FormUtils.mapDynamicFormAssignment(input); return GraphQLConcurrencyUtils.supplyAsync( () -> { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ingest/source/ListIngestionSourcesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ingest/source/ListIngestionSourcesResolver.java index 1a2806224e4a92..8ead47aa65ceb0 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ingest/source/ListIngestionSourcesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ingest/source/ListIngestionSourcesResolver.java @@ -68,10 +68,7 @@ public CompletableFuture get( .withSearchFlags(flags -> flags.setFulltext(true)), Constants.INGESTION_SOURCE_ENTITY_NAME, query, - buildFilter( - filters, - Collections.emptyList(), - context.getOperationContext().getAspectRetriever()), + buildFilter(filters, Collections.emptyList()), null, start, count); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/load/TimeSeriesAspectResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/load/TimeSeriesAspectResolver.java index 4d4b898618bf9c..0f4f0b2645e425 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/load/TimeSeriesAspectResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/load/TimeSeriesAspectResolver.java @@ -9,9 +9,9 @@ import com.linkedin.datahub.graphql.generated.Entity; import com.linkedin.datahub.graphql.generated.FilterInput; import com.linkedin.datahub.graphql.generated.TimeSeriesAspect; +import com.linkedin.datahub.graphql.resolvers.ResolverUtils; import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; -import com.linkedin.metadata.aspect.AspectRetriever; import com.linkedin.metadata.aspect.EnvelopedAspect; import com.linkedin.metadata.authorization.PoliciesConfig; import com.linkedin.metadata.query.filter.ConjunctiveCriterion; @@ -120,7 +120,7 @@ public CompletableFuture> get(DataFetchingEnvironment env maybeStartTimeMillis, maybeEndTimeMillis, maybeLimit, - buildFilters(maybeFilters, context.getOperationContext().getAspectRetriever()), + buildFilters(maybeFilters), maybeSort); // Step 2: Bind profiles into GraphQL strong types. @@ -135,8 +135,7 @@ public CompletableFuture> get(DataFetchingEnvironment env "get"); } - private Filter buildFilters( - @Nullable FilterInput maybeFilters, @Nullable AspectRetriever aspectRetriever) { + private Filter buildFilters(@Nullable FilterInput maybeFilters) { if (maybeFilters == null) { return null; } @@ -147,7 +146,7 @@ private Filter buildFilters( .setAnd( new CriterionArray( maybeFilters.getAnd().stream() - .map(filter -> criterionFromFilter(filter, true, aspectRetriever)) + .map(ResolverUtils::criterionFromFilter) .collect(Collectors.toList()))))); } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/FormUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/FormUtils.java index d118c04d19393d..cac0cca2682e84 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/FormUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/FormUtils.java @@ -18,7 +18,6 @@ import com.linkedin.form.FormPromptType; import com.linkedin.form.FormType; import com.linkedin.form.StructuredPropertyParams; -import com.linkedin.metadata.aspect.AspectRetriever; import com.linkedin.metadata.query.filter.Condition; import com.linkedin.metadata.query.filter.ConjunctiveCriterion; import com.linkedin.metadata.query.filter.ConjunctiveCriterionArray; @@ -31,7 +30,6 @@ import java.util.UUID; import java.util.stream.Collectors; import javax.annotation.Nonnull; -import javax.annotation.Nullable; public class FormUtils { @@ -61,16 +59,13 @@ public static PrimitivePropertyValueArray getStructuredPropertyValuesFromInput( /** Map a GraphQL CreateDynamicFormAssignmentInput to the GMS DynamicFormAssignment aspect */ @Nonnull public static DynamicFormAssignment mapDynamicFormAssignment( - @Nonnull final CreateDynamicFormAssignmentInput input, - @Nullable AspectRetriever aspectRetriever) { + @Nonnull final CreateDynamicFormAssignmentInput input) { Objects.requireNonNull(input, "input must not be null"); final DynamicFormAssignment result = new DynamicFormAssignment(); final Filter filter = new Filter() - .setOr( - ResolverUtils.buildConjunctiveCriterionArrayWithOr( - input.getOrFilters(), aspectRetriever)); + .setOr(ResolverUtils.buildConjunctiveCriterionArrayWithOr(input.getOrFilters())); result.setFilter(filter); return result; } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ownership/ListOwnershipTypesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ownership/ListOwnershipTypesResolver.java index da0d5dd07a94f0..05fc540e39de4c 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ownership/ListOwnershipTypesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/ownership/ListOwnershipTypesResolver.java @@ -63,10 +63,7 @@ public CompletableFuture get(DataFetchingEnvironment e context.getOperationContext().withSearchFlags(flags -> flags.setFulltext(true)), Constants.OWNERSHIP_TYPE_ENTITY_NAME, query, - buildFilter( - filters, - Collections.emptyList(), - context.getOperationContext().getAspectRetriever()), + buildFilter(filters, Collections.emptyList()), Collections.singletonList(DEFAULT_SORT_CRITERION), start, count); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/ListPoliciesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/ListPoliciesResolver.java index ce11451aa1913f..4120401e0150f9 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/ListPoliciesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/ListPoliciesResolver.java @@ -59,11 +59,7 @@ public CompletableFuture get(final DataFetchingEnvironment e log.debug( "User {} listing policies with filters {}", context.getActorUrn(), filters.toString()); - final Filter filter = - ResolverUtils.buildFilter( - facetFilters, - Collections.emptyList(), - context.getOperationContext().getAspectRetriever()); + final Filter filter = ResolverUtils.buildFilter(facetFilters, Collections.emptyList()); return _policyFetcher .fetchPolicies(context.getOperationContext(), start, query, count, filter) diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/query/ListQueriesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/query/ListQueriesResolver.java index aa411f019a4c08..3c84884bedbae8 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/query/ListQueriesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/query/ListQueriesResolver.java @@ -15,7 +15,6 @@ import com.linkedin.datahub.graphql.generated.ListQueriesResult; import com.linkedin.datahub.graphql.generated.QueryEntity; import com.linkedin.entity.client.EntityClient; -import com.linkedin.metadata.aspect.AspectRetriever; import com.linkedin.metadata.query.filter.Filter; import com.linkedin.metadata.query.filter.SortCriterion; import com.linkedin.metadata.query.filter.SortOrder; @@ -74,7 +73,7 @@ public CompletableFuture get(final DataFetchingEnvironment en flags -> flags.setFulltext(true).setSkipHighlighting(true)), QUERY_ENTITY_NAME, query, - buildFilters(input, context.getOperationContext().getAspectRetriever()), + buildFilters(input), sortCriteria, start, count); @@ -111,8 +110,7 @@ private List mapUnresolvedQueries(final List queryUrns) { } @Nullable - private Filter buildFilters( - @Nonnull final ListQueriesInput input, @Nullable AspectRetriever aspectRetriever) { + private Filter buildFilters(@Nonnull final ListQueriesInput input) { final AndFilterInput criteria = new AndFilterInput(); List andConditions = new ArrayList<>(); @@ -139,6 +137,6 @@ private Filter buildFilters( } criteria.setAnd(andConditions); - return buildFilter(Collections.emptyList(), ImmutableList.of(criteria), aspectRetriever); + return buildFilter(Collections.emptyList(), ImmutableList.of(criteria)); } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/recommendation/ListRecommendationsResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/recommendation/ListRecommendationsResolver.java index 01818778643905..28334b2c0af9a4 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/recommendation/ListRecommendationsResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/recommendation/ListRecommendationsResolver.java @@ -17,6 +17,7 @@ import com.linkedin.datahub.graphql.generated.RecommendationRenderType; import com.linkedin.datahub.graphql.generated.RecommendationRequestContext; import com.linkedin.datahub.graphql.generated.SearchParams; +import com.linkedin.datahub.graphql.resolvers.ResolverUtils; import com.linkedin.datahub.graphql.types.common.mappers.UrnToEntityMapper; import com.linkedin.datahub.graphql.types.entitytype.EntityTypeMapper; import com.linkedin.metadata.query.filter.CriterionArray; @@ -105,9 +106,7 @@ private com.linkedin.metadata.recommendation.RecommendationRequestContext mapReq searchRequestContext.setFilters( new CriterionArray( requestContext.getSearchRequestContext().getFilters().stream() - .map( - facetField -> - criterionFromFilter(facetField, opContext.getAspectRetriever())) + .map(ResolverUtils::criterionFromFilter) .collect(Collectors.toList()))); } mappedRequestContext.setSearchRequestContext(searchRequestContext); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AggregateAcrossEntitiesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AggregateAcrossEntitiesResolver.java index 19bccaf2650866..29b71d95ad9749 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AggregateAcrossEntitiesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AggregateAcrossEntitiesResolver.java @@ -64,9 +64,7 @@ public CompletableFuture get(DataFetchingEnvironment environme UrnUtils.getUrn(input.getViewUrn())) : null; - final Filter inputFilter = - ResolverUtils.buildFilter( - null, input.getOrFilters(), context.getOperationContext().getAspectRetriever()); + final Filter inputFilter = ResolverUtils.buildFilter(null, input.getOrFilters()); final SearchFlags searchFlags = mapInputFlags(context, input.getSearchFlags()); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AutoCompleteResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AutoCompleteResolver.java index 79792940ef27f7..5e4f56dbfff980 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AutoCompleteResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AutoCompleteResolver.java @@ -51,11 +51,7 @@ public CompletableFuture get(DataFetchingEnvironment enviro throw new ValidationException("'query' parameter can not be null or empty"); } - final Filter filter = - ResolverUtils.buildFilter( - input.getFilters(), - input.getOrFilters(), - context.getOperationContext().getRetrieverContext().orElseThrow().getAspectRetriever()); + final Filter filter = ResolverUtils.buildFilter(input.getFilters(), input.getOrFilters()); final int limit = input.getLimit() != null ? input.getLimit() : DEFAULT_LIMIT; return GraphQLConcurrencyUtils.supplyAsync( () -> { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AutocompleteUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AutocompleteUtils.java index 5b5888b89b241b..c28b18acf195b8 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AutocompleteUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/AutocompleteUtils.java @@ -43,10 +43,7 @@ public static CompletableFuture batchGetAutocomplet GraphQLConcurrencyUtils.supplyAsync( () -> { final Filter filter = - ResolverUtils.buildFilter( - input.getFilters(), - input.getOrFilters(), - context.getOperationContext().getAspectRetriever()); + ResolverUtils.buildFilter(input.getFilters(), input.getOrFilters()); final Filter finalFilter = view != null ? SearchUtils.combineFilters( diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/ScrollAcrossEntitiesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/ScrollAcrossEntitiesResolver.java index 8b8b93353bc6e8..77eef1b9a25c69 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/ScrollAcrossEntitiesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/ScrollAcrossEntitiesResolver.java @@ -72,9 +72,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) UrnUtils.getUrn(input.getViewUrn())) : null; - final Filter baseFilter = - ResolverUtils.buildFilter( - null, input.getOrFilters(), context.getOperationContext().getAspectRetriever()); + final Filter baseFilter = ResolverUtils.buildFilter(null, input.getOrFilters()); final SearchFlags searchFlags; com.linkedin.datahub.graphql.generated.SearchFlags inputFlags = input.getSearchFlags(); if (inputFlags != null) { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/ScrollAcrossLineageResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/ScrollAcrossLineageResolver.java index 1b719b6f786205..2c058eb60a7ee3 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/ScrollAcrossLineageResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/ScrollAcrossLineageResolver.java @@ -130,10 +130,7 @@ public CompletableFuture get(DataFetchingEnvironment entityNames, sanitizedQuery, maxHops, - ResolverUtils.buildFilter( - facetFilters, - input.getOrFilters(), - context.getOperationContext().getAspectRetriever()), + ResolverUtils.buildFilter(facetFilters, input.getOrFilters()), null, scrollId, keepAlive, diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossEntitiesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossEntitiesResolver.java index 0dbed92b7d58e7..d103704146d399 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossEntitiesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossEntitiesResolver.java @@ -61,10 +61,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) : null; final Filter baseFilter = - ResolverUtils.buildFilter( - input.getFilters(), - input.getOrFilters(), - context.getOperationContext().getAspectRetriever()); + ResolverUtils.buildFilter(input.getFilters(), input.getOrFilters()); SearchFlags searchFlags = mapInputFlags(context, input.getSearchFlags()); List sortCriteria; diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossLineageResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossLineageResolver.java index dc3a1fc17e4ec9..c90be924ac69f5 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossLineageResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossLineageResolver.java @@ -139,10 +139,7 @@ public CompletableFuture get(DataFetchingEnvironment count); final Filter filter = - ResolverUtils.buildFilter( - input.getFilters(), - input.getOrFilters(), - context.getOperationContext().getAspectRetriever()); + ResolverUtils.buildFilter(input.getFilters(), input.getOrFilters()); final SearchFlags searchFlags; com.linkedin.datahub.graphql.generated.SearchFlags inputFlags = input.getSearchFlags(); if (inputFlags != null) { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchResolver.java index 7a48e305dbfe49..45751fc6eb8cb2 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchResolver.java @@ -86,10 +86,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) context.getOperationContext().withSearchFlags(flags -> searchFlags), entityName, sanitizedQuery, - ResolverUtils.buildFilter( - input.getFilters(), - input.getOrFilters(), - context.getOperationContext().getAspectRetriever()), + ResolverUtils.buildFilter(input.getFilters(), input.getOrFilters()), Collections.emptyList(), start, count)); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/CreateStructuredPropertyResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/CreateStructuredPropertyResolver.java index 3be7ea505abbf3..328f63b893d06f 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/CreateStructuredPropertyResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/CreateStructuredPropertyResolver.java @@ -83,6 +83,8 @@ public CompletableFuture get(final DataFetchingEnviron builder.setCardinality( PropertyCardinality.valueOf(input.getCardinality().toString())); } + builder.setCreated(context.getOperationContext().getAuditStamp()); + builder.setLastModified(context.getOperationContext().getAuditStamp()); MetadataChangeProposal mcp = builder.build(); _entityClient.ingestProposal(context.getOperationContext(), mcp, false); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/DeleteStructuredPropertyResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/DeleteStructuredPropertyResolver.java new file mode 100644 index 00000000000000..e7d59494654fdd --- /dev/null +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/DeleteStructuredPropertyResolver.java @@ -0,0 +1,52 @@ +package com.linkedin.datahub.graphql.resolvers.structuredproperties; + +import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.bindArgument; + +import com.linkedin.common.urn.Urn; +import com.linkedin.common.urn.UrnUtils; +import com.linkedin.datahub.graphql.QueryContext; +import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; +import com.linkedin.datahub.graphql.exception.AuthorizationException; +import com.linkedin.datahub.graphql.generated.DeleteStructuredPropertyInput; +import com.linkedin.entity.client.EntityClient; +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; + +@Slf4j +public class DeleteStructuredPropertyResolver implements DataFetcher> { + + private final EntityClient _entityClient; + + public DeleteStructuredPropertyResolver(@Nonnull final EntityClient entityClient) { + _entityClient = Objects.requireNonNull(entityClient, "entityClient must not be null"); + } + + @Override + public CompletableFuture get(final DataFetchingEnvironment environment) + throws Exception { + final QueryContext context = environment.getContext(); + + final DeleteStructuredPropertyInput input = + bindArgument(environment.getArgument("input"), DeleteStructuredPropertyInput.class); + final Urn propertyUrn = UrnUtils.getUrn(input.getUrn()); + + return CompletableFuture.supplyAsync( + () -> { + try { + if (!AuthorizationUtils.canManageStructuredProperties(context)) { + throw new AuthorizationException( + "Unable to delete structured property. Please contact your admin."); + } + _entityClient.deleteEntity(context.getOperationContext(), propertyUrn); + return true; + } catch (Exception e) { + throw new RuntimeException( + String.format("Failed to perform update against input %s", input), e); + } + }); + } +} diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/UpdateStructuredPropertyResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/UpdateStructuredPropertyResolver.java index 2549f303bacd95..c432281ec16848 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/UpdateStructuredPropertyResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/structuredproperties/UpdateStructuredPropertyResolver.java @@ -76,6 +76,7 @@ public CompletableFuture get(final DataFetchingEnviron if (input.getNewEntityTypes() != null) { input.getNewEntityTypes().forEach(builder::addEntityType); } + builder.setLastModified(context.getOperationContext().getAuditStamp()); MetadataChangeProposal mcp = builder.build(); _entityClient.ingestProposal(context.getOperationContext(), mcp, false); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ListGlobalViewsResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ListGlobalViewsResolver.java index 265f4d5f5d56e2..bda950ef3eb581 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ListGlobalViewsResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ListGlobalViewsResolver.java @@ -16,7 +16,6 @@ import com.linkedin.datahub.graphql.generated.ListViewsResult; import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; -import com.linkedin.metadata.aspect.AspectRetriever; import com.linkedin.metadata.query.filter.Filter; import com.linkedin.metadata.query.filter.SortCriterion; import com.linkedin.metadata.query.filter.SortOrder; @@ -31,7 +30,6 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import lombok.extern.slf4j.Slf4j; /** Resolver used for listing global DataHub Views. */ @@ -73,7 +71,7 @@ public CompletableFuture get(final DataFetchingEnvironment envi context.getOperationContext().withSearchFlags(flags -> flags.setFulltext(true)), Constants.DATAHUB_VIEW_ENTITY_NAME, query, - buildFilters(context.getOperationContext().getAspectRetriever()), + buildFilters(), Collections.singletonList(DEFAULT_SORT_CRITERION), start, count); @@ -109,7 +107,7 @@ private List mapUnresolvedViews(final List entityUrns) { return results; } - private Filter buildFilters(@Nullable AspectRetriever aspectRetriever) { + private Filter buildFilters() { final AndFilterInput globalCriteria = new AndFilterInput(); List andConditions = new ArrayList<>(); andConditions.add( @@ -120,6 +118,6 @@ private Filter buildFilters(@Nullable AspectRetriever aspectRetriever) { false, FilterOperator.EQUAL)); globalCriteria.setAnd(andConditions); - return buildFilter(Collections.emptyList(), ImmutableList.of(globalCriteria), aspectRetriever); + return buildFilter(Collections.emptyList(), ImmutableList.of(globalCriteria)); } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ListMyViewsResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ListMyViewsResolver.java index abfdeb2d608693..53a7c92bbe8ec3 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ListMyViewsResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ListMyViewsResolver.java @@ -132,6 +132,6 @@ private Filter buildFilters( filterCriteria.setAnd(andConditions); // Currently, there is no way to fetch the views belonging to another user. - return buildFilter(Collections.emptyList(), ImmutableList.of(filterCriteria), aspectRetriever); + return buildFilter(Collections.emptyList(), ImmutableList.of(filterCriteria)); } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ViewUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ViewUtils.java index 70a5ced4bfbf10..aa41a1e4876517 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ViewUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/view/ViewUtils.java @@ -141,7 +141,7 @@ private static Filter buildAndFilter( .setAnd( new CriterionArray( input.stream() - .map(f -> ResolverUtils.criterionFromFilter(f, aspectRetriever)) + .map(ResolverUtils::criterionFromFilter) .collect(Collectors.toList())))))); return result; } @@ -157,9 +157,7 @@ private static Filter buildOrFilter( new ConjunctiveCriterion() .setAnd( new CriterionArray( - ImmutableList.of( - ResolverUtils.criterionFromFilter( - filter, aspectRetriever))))) + ImmutableList.of(ResolverUtils.criterionFromFilter(filter))))) .collect(Collectors.toList()))); return result; } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/MapperUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/MapperUtils.java index 0eb74210971d9f..0d69e62c621a60 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/MapperUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/MapperUtils.java @@ -3,15 +3,18 @@ import static com.linkedin.datahub.graphql.util.SearchInsightsUtil.*; import static com.linkedin.metadata.utils.SearchUtil.*; +import com.linkedin.common.AuditStamp; import com.linkedin.common.UrnArray; import com.linkedin.common.urn.Urn; import com.linkedin.data.template.StringMap; import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.generated.AggregationMetadata; +import com.linkedin.datahub.graphql.generated.CorpUser; import com.linkedin.datahub.graphql.generated.EntityPath; import com.linkedin.datahub.graphql.generated.ExtraProperty; import com.linkedin.datahub.graphql.generated.FacetMetadata; import com.linkedin.datahub.graphql.generated.MatchedField; +import com.linkedin.datahub.graphql.generated.ResolvedAuditStamp; import com.linkedin.datahub.graphql.generated.SearchResult; import com.linkedin.datahub.graphql.generated.SearchSuggestion; import com.linkedin.datahub.graphql.types.common.mappers.UrnToEntityMapper; @@ -132,4 +135,13 @@ public static EntityPath mapPath(@Nullable final QueryContext context, UrnArray path.stream().map(p -> UrnToEntityMapper.map(context, p)).collect(Collectors.toList())); return entityPath; } + + public static ResolvedAuditStamp createResolvedAuditStamp(AuditStamp auditStamp) { + final ResolvedAuditStamp resolvedAuditStamp = new ResolvedAuditStamp(); + final CorpUser emptyCreatedUser = new CorpUser(); + emptyCreatedUser.setUrn(auditStamp.getActor().toString()); + resolvedAuditStamp.setActor(emptyCreatedUser); + resolvedAuditStamp.setTime(auditStamp.getTime()); + return resolvedAuditStamp; + } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/structuredproperty/StructuredPropertyMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/structuredproperty/StructuredPropertyMapper.java index ff54131506a7cc..c539c65118ac6d 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/structuredproperty/StructuredPropertyMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/structuredproperty/StructuredPropertyMapper.java @@ -2,7 +2,9 @@ import static com.linkedin.metadata.Constants.*; +import com.google.common.collect.ImmutableList; import com.linkedin.common.urn.Urn; +import com.linkedin.common.urn.UrnUtils; import com.linkedin.data.DataMap; import com.linkedin.data.template.StringArrayMap; import com.linkedin.datahub.graphql.QueryContext; @@ -17,6 +19,7 @@ import com.linkedin.datahub.graphql.generated.StructuredPropertyEntity; import com.linkedin.datahub.graphql.generated.TypeQualifier; import com.linkedin.datahub.graphql.types.common.mappers.util.MappingHelper; +import com.linkedin.datahub.graphql.types.mappers.MapperUtils; import com.linkedin.datahub.graphql.types.mappers.ModelMapper; import com.linkedin.entity.EntityResponse; import com.linkedin.entity.EnvelopedAspectMap; @@ -45,6 +48,9 @@ public StructuredPropertyEntity apply( final StructuredPropertyEntity result = new StructuredPropertyEntity(); result.setUrn(entityResponse.getUrn().toString()); result.setType(EntityType.STRUCTURED_PROPERTY); + // set the default required values for a structured property in case references are still being + // cleaned up + setDefaultProperty(result); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); mappingHelper.mapToResult( @@ -74,6 +80,13 @@ private void mapStructuredPropertyDefinition( if (gmsDefinition.hasTypeQualifier()) { definition.setTypeQualifier(mapTypeQualifier(gmsDefinition.getTypeQualifier())); } + if (gmsDefinition.getCreated() != null) { + definition.setCreated(MapperUtils.createResolvedAuditStamp(gmsDefinition.getCreated())); + } + if (gmsDefinition.getLastModified() != null) { + definition.setLastModified( + MapperUtils.createResolvedAuditStamp(gmsDefinition.getLastModified())); + } definition.setEntityTypes( gmsDefinition.getEntityTypes().stream() .map(this::createEntityTypeEntity) @@ -126,4 +139,22 @@ private EntityTypeEntity createEntityTypeEntity(final String entityTypeUrnStr) { entityType.setType(EntityType.ENTITY_TYPE); return entityType; } + + /* + * In the case that a property is deleted and the references haven't been cleaned up yet (this process is async) + * set a default property to prevent APIs breaking. The UI queries for whether the entity exists and it will + * be filtered out. + */ + private void setDefaultProperty(final StructuredPropertyEntity result) { + StructuredPropertyDefinition definition = new StructuredPropertyDefinition(); + definition.setQualifiedName(""); + definition.setCardinality(PropertyCardinality.SINGLE); + definition.setImmutable(true); + definition.setValueType( + createDataTypeEntity(UrnUtils.getUrn("urn:li:dataType:datahub.string"))); + definition.setEntityTypes( + ImmutableList.of( + createEntityTypeEntity(UrnUtils.getUrn("urn:li:entityType:datahub.dataset")))); + result.setDefinition(definition); + } } diff --git a/datahub-graphql-core/src/main/resources/entity.graphql b/datahub-graphql-core/src/main/resources/entity.graphql index 52e81f8094dea6..a2e2fe9163f536 100644 --- a/datahub-graphql-core/src/main/resources/entity.graphql +++ b/datahub-graphql-core/src/main/resources/entity.graphql @@ -84,6 +84,11 @@ type Query { """ role(urn: String!): Role + """ + Fetch a Structured Property by primary key (urn) + """ + structuredProperty(urn: String!): StructuredPropertyEntity + """ Fetch a ERModelRelationship by primary key (urn) """ diff --git a/datahub-graphql-core/src/main/resources/properties.graphql b/datahub-graphql-core/src/main/resources/properties.graphql index dfe84686456814..292381d064f362 100644 --- a/datahub-graphql-core/src/main/resources/properties.graphql +++ b/datahub-graphql-core/src/main/resources/properties.graphql @@ -18,6 +18,11 @@ extend type Mutation { Update an existing structured property """ updateStructuredProperty(input: UpdateStructuredPropertyInput!): StructuredPropertyEntity! + + """ + Delete an existing structured property + """ + deleteStructuredProperty(input: DeleteStructuredPropertyInput!): Boolean! } """ @@ -34,6 +39,11 @@ type StructuredPropertyEntity implements Entity { """ type: EntityType! + """ + Whether or not this entity exists on DataHub + """ + exists: Boolean + """ Definition of this structured property including its name """ @@ -95,6 +105,16 @@ type StructuredPropertyDefinition { Whether or not this structured property is immutable """ immutable: Boolean! + + """ + Audit stamp for when this structured property was created + """ + created: ResolvedAuditStamp + + """ + Audit stamp for when this structured property was last modified + """ + lastModified: ResolvedAuditStamp } """ @@ -447,3 +467,13 @@ input UpdateTypeQualifierInput { """ newAllowedTypes: [String!] } + +""" +Input for deleting a form +""" +input DeleteStructuredPropertyInput { + """ + The urn of the structured properties that is being deleted + """ + urn: String! +} diff --git a/datahub-graphql-core/src/main/resources/search.graphql b/datahub-graphql-core/src/main/resources/search.graphql index 9c4375e70d9baa..32d73845e1ae40 100644 --- a/datahub-graphql-core/src/main/resources/search.graphql +++ b/datahub-graphql-core/src/main/resources/search.graphql @@ -551,6 +551,16 @@ enum FilterOperator { """ LESS_THAN_OR_EQUAL_TO + """ + Represent the relation: String field starts with value, e.g. name starts with PageView + """ + START_WITH + + """ + Represent the relation: String field ends with value, e.g. name ends with Event + """ + END_WITH + """ Represent the relation: URN field any nested children in addition to the given URN """ diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/ResolverUtilsTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/ResolverUtilsTest.java index b01aacaaab65ca..2950b50bec8f18 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/ResolverUtilsTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/ResolverUtilsTest.java @@ -13,7 +13,6 @@ import com.linkedin.datahub.graphql.TestUtils; import com.linkedin.datahub.graphql.generated.FacetFilterInput; import com.linkedin.datahub.graphql.generated.FilterOperator; -import com.linkedin.metadata.aspect.AspectRetriever; import com.linkedin.metadata.config.DataHubAppConfiguration; import com.linkedin.metadata.config.MetadataChangeProposalConfig; import com.linkedin.metadata.query.filter.Condition; @@ -45,8 +44,7 @@ public void testCriterionFromFilter() throws Exception { null, ImmutableList.of("urn:li:tag:abc", "urn:li:tag:def"), false, - FilterOperator.EQUAL), - mock(AspectRetriever.class)); + FilterOperator.EQUAL)); assertEquals( valuesCriterion, new Criterion() @@ -54,13 +52,12 @@ public void testCriterionFromFilter() throws Exception { .setValues(new StringArray(ImmutableList.of("urn:li:tag:abc", "urn:li:tag:def"))) .setNegated(false) .setCondition(Condition.EQUAL) - .setField("tags.keyword")); + .setField("tags")); // this is the legacy pathway Criterion valueCriterion = criterionFromFilter( - new FacetFilterInput("tags", "urn:li:tag:abc", null, true, FilterOperator.EQUAL), - mock(AspectRetriever.class)); + new FacetFilterInput("tags", "urn:li:tag:abc", null, true, FilterOperator.EQUAL)); assertEquals( valueCriterion, new Criterion() @@ -68,14 +65,12 @@ public void testCriterionFromFilter() throws Exception { .setValues(new StringArray(ImmutableList.of("urn:li:tag:abc"))) .setNegated(true) .setCondition(Condition.EQUAL) - .setField("tags.keyword")); + .setField("tags")); // check that both being null doesn't cause a NPE. this should never happen except via API // interaction Criterion doubleNullCriterion = - criterionFromFilter( - new FacetFilterInput("tags", null, null, true, FilterOperator.EQUAL), - mock(AspectRetriever.class)); + criterionFromFilter(new FacetFilterInput("tags", null, null, true, FilterOperator.EQUAL)); assertEquals( doubleNullCriterion, new Criterion() @@ -83,7 +78,7 @@ public void testCriterionFromFilter() throws Exception { .setValues(new StringArray(ImmutableList.of())) .setNegated(true) .setCondition(Condition.EQUAL) - .setField("tags.keyword")); + .setField("tags")); } @Test diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/auth/ListAccessTokensResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/auth/ListAccessTokensResolverTest.java index 020f74475ea607..30962aaef54125 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/auth/ListAccessTokensResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/auth/ListAccessTokensResolverTest.java @@ -46,7 +46,7 @@ public void testGetSuccess() throws Exception { any(), Mockito.eq(Constants.ACCESS_TOKEN_ENTITY_NAME), Mockito.eq(""), - Mockito.eq(buildFilter(filters, Collections.emptyList(), null)), + Mockito.eq(buildFilter(filters, Collections.emptyList())), Mockito.any(List.class), Mockito.eq(input.getStart()), Mockito.eq(input.getCount()))) diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/browse/BrowseV2ResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/browse/BrowseV2ResolverTest.java index 9cf7e62e65e253..4897d0819b59fb 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/browse/BrowseV2ResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/browse/BrowseV2ResolverTest.java @@ -2,7 +2,6 @@ import static com.linkedin.datahub.graphql.TestUtils.getMockAllowContext; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; import com.google.common.collect.ImmutableList; import com.linkedin.common.AuditStamp; @@ -18,7 +17,6 @@ import com.linkedin.datahub.graphql.resolvers.ResolverUtils; import com.linkedin.datahub.graphql.resolvers.chart.BrowseV2Resolver; import com.linkedin.entity.client.EntityClient; -import com.linkedin.metadata.aspect.AspectRetriever; import com.linkedin.metadata.browse.BrowseResultGroupV2; import com.linkedin.metadata.browse.BrowseResultGroupV2Array; import com.linkedin.metadata.browse.BrowseResultMetadata; @@ -102,7 +100,7 @@ public static void testBrowseV2SuccessWithQueryAndFilter() throws Exception { facetFilterInput.setValues(ImmutableList.of("urn:li:corpuser:test")); andFilterInput.setAnd(ImmutableList.of(facetFilterInput)); orFilters.add(andFilterInput); - Filter filter = ResolverUtils.buildFilter(null, orFilters, mock(AspectRetriever.class)); + Filter filter = ResolverUtils.buildFilter(null, orFilters); EntityClient mockClient = initMockEntityClient( diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/query/ListQueriesResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/query/ListQueriesResolverTest.java index ee728b17e8c621..414c62b693b698 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/query/ListQueriesResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/query/ListQueriesResolverTest.java @@ -170,6 +170,6 @@ private Filter buildFilter(@Nullable QuerySource source, @Nullable String entity FilterOperator.EQUAL)); } criteria.setAnd(andConditions); - return ResolverUtils.buildFilter(Collections.emptyList(), ImmutableList.of(criteria), null); + return ResolverUtils.buildFilter(Collections.emptyList(), ImmutableList.of(criteria)); } } diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/search/AggregateAcrossEntitiesResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/search/AggregateAcrossEntitiesResolverTest.java index d32eb9fcf120ca..129866bb0fa07a 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/search/AggregateAcrossEntitiesResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/search/AggregateAcrossEntitiesResolverTest.java @@ -107,7 +107,7 @@ public static void testApplyViewBaseFilter() throws Exception { FormService mockFormService = Mockito.mock(FormService.class); ViewService mockService = initMockViewService(TEST_VIEW_URN, info); - Filter baseFilter = createFilter("baseField.keyword", "baseTest"); + Filter baseFilter = createFilter("baseField", "baseTest"); EntityClient mockClient = initMockEntityClient( diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossEntitiesResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossEntitiesResolverTest.java index 30d6f2dc6f2836..86508f1fd2742b 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossEntitiesResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/search/SearchAcrossEntitiesResolverTest.java @@ -164,7 +164,7 @@ public static void testApplyViewBaseFilter() throws Exception { new CriterionArray( ImmutableList.of( new Criterion() - .setField("baseField.keyword") + .setField("baseField") .setValue("baseTest") .setCondition(Condition.EQUAL) .setNegated(false) diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/CreateViewResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/CreateViewResolverTest.java index 502188d4977a53..c009cf37c53971 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/CreateViewResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/CreateViewResolverTest.java @@ -110,7 +110,7 @@ public void testGetSuccess() throws Exception { ImmutableList.of( new Criterion() .setCondition(Condition.EQUAL) - .setField("test1.keyword") + .setField("test1") .setValue( "value1") // Unfortunate --- For // backwards compat. @@ -121,7 +121,7 @@ public void testGetSuccess() throws Exception { .setNegated(false), new Criterion() .setCondition(Condition.IN) - .setField("test2.keyword") + .setField("test2") .setValue( "value1") // Unfortunate --- For // backwards compat. diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ListGlobalViewsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ListGlobalViewsResolverTest.java index a3b9e25e992259..b5c0531db792ba 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ListGlobalViewsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ListGlobalViewsResolverTest.java @@ -56,7 +56,7 @@ public void testGetSuccessInput() throws Exception { new CriterionArray( ImmutableList.of( new Criterion() - .setField("type.keyword") + .setField("type") .setValue(DataHubViewType.GLOBAL.toString()) .setValues( new StringArray( diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ListMyViewsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ListMyViewsResolverTest.java index 99b0e76976748e..85d24f9251eaa3 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ListMyViewsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ListMyViewsResolverTest.java @@ -58,7 +58,7 @@ public void testGetSuccessInput1() throws Exception { new CriterionArray( ImmutableList.of( new Criterion() - .setField("createdBy.keyword") + .setField("createdBy") .setValue(TEST_USER.toString()) .setValues( new StringArray( @@ -67,7 +67,7 @@ public void testGetSuccessInput1() throws Exception { .setCondition(Condition.EQUAL) .setNegated(false), new Criterion() - .setField("type.keyword") + .setField("type") .setValue(DataHubViewType.GLOBAL.toString()) .setValues( new StringArray( @@ -124,7 +124,7 @@ public void testGetSuccessInput2() throws Exception { new CriterionArray( ImmutableList.of( new Criterion() - .setField("createdBy.keyword") + .setField("createdBy") .setValue(TEST_USER.toString()) .setValues( new StringArray( diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/UpdateViewResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/UpdateViewResolverTest.java index fe32bec01fd7ed..86a502b40b9364 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/UpdateViewResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/UpdateViewResolverTest.java @@ -111,7 +111,7 @@ public void testGetSuccessGlobalViewIsCreator() throws Exception { ImmutableList.of( new Criterion() .setCondition(Condition.EQUAL) - .setField("test1.keyword") + .setField("test1") .setValue( "value1") // Unfortunate --- For // backwards compat. @@ -122,7 +122,7 @@ public void testGetSuccessGlobalViewIsCreator() throws Exception { .setNegated(false), new Criterion() .setCondition(Condition.IN) - .setField("test2.keyword") + .setField("test2") .setValue( "value1") // Unfortunate --- For // backwards compat. @@ -175,7 +175,7 @@ public void testGetSuccessGlobalViewManageGlobalViews() throws Exception { ImmutableList.of( new Criterion() .setCondition(Condition.EQUAL) - .setField("test1.keyword") + .setField("test1") .setValue( "value1") // Unfortunate --- For // backwards compat. @@ -186,7 +186,7 @@ public void testGetSuccessGlobalViewManageGlobalViews() throws Exception { .setNegated(false), new Criterion() .setCondition(Condition.IN) - .setField("test2.keyword") + .setField("test2") .setValue( "value1") // Unfortunate --- For // backwards compat. diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ViewUtilsTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ViewUtilsTest.java index 701ddd84c173e7..d142be1321a5c3 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ViewUtilsTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/view/ViewUtilsTest.java @@ -154,8 +154,7 @@ public void testMapDefinition() throws Exception { new StringArray( ImmutableList.of("value1", "value2"))) .setValue("value1") // Disgraceful - .setField( - "test1.keyword") // Consider whether we + .setField("test1") // Consider whether we // should NOT go through // the keyword mapping. .setCondition(Condition.IN), @@ -165,8 +164,7 @@ public void testMapDefinition() throws Exception { new StringArray( ImmutableList.of("value3", "value4"))) .setValue("value3") // Disgraceful - .setField( - "test2.keyword") // Consider whether we + .setField("test2") // Consider whether we // should NOT go through // the keyword mapping. .setCondition(Condition.CONTAIN)))))))); diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/CreateAspectTableStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/CreateAspectTableStep.java index 4855cef95cb6e5..63b319d943a803 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/CreateAspectTableStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/CreateAspectTableStep.java @@ -77,7 +77,7 @@ public Function executable() { } try { - _server.execute(_server.createSqlUpdate(sqlUpdateStr)); + _server.execute(_server.sqlUpdate(sqlUpdateStr)); } catch (Exception e) { context.report().addLine("Failed to create table metadata_aspect_v2", e); return new DefaultUpgradeStepResult(id(), DataHubUpgradeState.FAILED); diff --git a/datahub-web-react/package.json b/datahub-web-react/package.json index f641706c7661e8..a1b3a94ace6406 100644 --- a/datahub-web-react/package.json +++ b/datahub-web-react/package.json @@ -132,7 +132,7 @@ "less": "^4.2.0", "prettier": "^2.8.8", "source-map-explorer": "^2.5.2", - "vite": "^4.5.3", + "vite": "^4.5.5", "vite-plugin-babel-macros": "^1.0.6", "vite-plugin-static-copy": "^0.17.0", "vite-plugin-svgr": "^4.1.0", diff --git a/datahub-web-react/src/app/entity/shared/tabs/Dataset/Schema/SchemaTab.tsx b/datahub-web-react/src/app/entity/shared/tabs/Dataset/Schema/SchemaTab.tsx index f9d7c8db025690..52c141282c3456 100644 --- a/datahub-web-react/src/app/entity/shared/tabs/Dataset/Schema/SchemaTab.tsx +++ b/datahub-web-react/src/app/entity/shared/tabs/Dataset/Schema/SchemaTab.tsx @@ -79,7 +79,10 @@ export const SchemaTab = ({ properties }: { properties?: any }) => { const hasProperties = useMemo( () => entityWithSchema?.schemaMetadata?.fields?.some( - (schemaField) => !!schemaField.schemaFieldEntity?.structuredProperties?.properties?.length, + (schemaField) => + !!schemaField.schemaFieldEntity?.structuredProperties?.properties?.filter( + (prop) => prop.structuredProperty.exists, + )?.length, ), [entityWithSchema], ); diff --git a/datahub-web-react/src/app/entity/shared/tabs/Dataset/Schema/components/SchemaFieldDrawer/FieldProperties.tsx b/datahub-web-react/src/app/entity/shared/tabs/Dataset/Schema/components/SchemaFieldDrawer/FieldProperties.tsx index 689a191f469f53..9a0da20f22dfde 100644 --- a/datahub-web-react/src/app/entity/shared/tabs/Dataset/Schema/components/SchemaFieldDrawer/FieldProperties.tsx +++ b/datahub-web-react/src/app/entity/shared/tabs/Dataset/Schema/components/SchemaFieldDrawer/FieldProperties.tsx @@ -34,14 +34,16 @@ interface Props { export default function FieldProperties({ expandedField }: Props) { const { schemaFieldEntity } = expandedField; const { refetch } = useGetEntityWithSchema(true); + const properties = + schemaFieldEntity?.structuredProperties?.properties?.filter((prop) => prop.structuredProperty.exists) || []; - if (!schemaFieldEntity?.structuredProperties?.properties?.length) return null; + if (!schemaFieldEntity || !properties.length) return null; return ( <> Properties - {schemaFieldEntity.structuredProperties.properties.map((structuredProp) => { + {properties.map((structuredProp) => { const isRichText = structuredProp.structuredProperty.definition.valueType?.info.type === StdDataType.RichText; const valuesData = mapStructuredPropertyValues(structuredProp); diff --git a/datahub-web-react/src/app/entity/shared/tabs/Properties/useStructuredProperties.tsx b/datahub-web-react/src/app/entity/shared/tabs/Properties/useStructuredProperties.tsx index 5600d7c3e8498e..86365b8232905c 100644 --- a/datahub-web-react/src/app/entity/shared/tabs/Properties/useStructuredProperties.tsx +++ b/datahub-web-react/src/app/entity/shared/tabs/Properties/useStructuredProperties.tsx @@ -27,23 +27,26 @@ export function mapStructuredPropertyValues(structuredPropertiesEntry: Structure function getStructuredPropertyRows(entityData?: GenericEntityProperties | null) { const structuredPropertyRows: PropertyRow[] = []; - entityData?.structuredProperties?.properties?.forEach((structuredPropertiesEntry) => { - const { displayName, qualifiedName } = structuredPropertiesEntry.structuredProperty.definition; - structuredPropertyRows.push({ - displayName: displayName || qualifiedName, - qualifiedName, - values: mapStructuredPropertyValues(structuredPropertiesEntry), - dataType: structuredPropertiesEntry.structuredProperty.definition.valueType, - structuredProperty: structuredPropertiesEntry.structuredProperty, - type: - structuredPropertiesEntry.values[0] && structuredPropertiesEntry.values[0].__typename - ? { - type: typeNameToType[structuredPropertiesEntry.values[0].__typename].type, - nativeDataType: typeNameToType[structuredPropertiesEntry.values[0].__typename].nativeDataType, - } - : undefined, + entityData?.structuredProperties?.properties + ?.filter((prop) => prop.structuredProperty.exists) + .forEach((structuredPropertiesEntry) => { + const { displayName, qualifiedName } = structuredPropertiesEntry.structuredProperty.definition; + structuredPropertyRows.push({ + displayName: displayName || qualifiedName, + qualifiedName, + values: mapStructuredPropertyValues(structuredPropertiesEntry), + dataType: structuredPropertiesEntry.structuredProperty.definition.valueType, + structuredProperty: structuredPropertiesEntry.structuredProperty, + type: + structuredPropertiesEntry.values[0] && structuredPropertiesEntry.values[0].__typename + ? { + type: typeNameToType[structuredPropertiesEntry.values[0].__typename].type, + nativeDataType: + typeNameToType[structuredPropertiesEntry.values[0].__typename].nativeDataType, + } + : undefined, + }); }); - }); return structuredPropertyRows; } diff --git a/datahub-web-react/src/graphql/fragments.graphql b/datahub-web-react/src/graphql/fragments.graphql index e5bbb5f0dc29d5..18742397517238 100644 --- a/datahub-web-react/src/graphql/fragments.graphql +++ b/datahub-web-react/src/graphql/fragments.graphql @@ -1314,6 +1314,7 @@ fragment structuredPropertyFields on StructuredPropertyEntity { fragment structuredPropertiesFields on StructuredPropertiesEntry { structuredProperty { + exists ...structuredPropertyFields } values { diff --git a/datahub-web-react/yarn.lock b/datahub-web-react/yarn.lock index db55cb4f095c08..558711251d490e 100644 --- a/datahub-web-react/yarn.lock +++ b/datahub-web-react/yarn.lock @@ -10610,10 +10610,10 @@ vite-plugin-svgr@^4.1.0: "@svgr/core" "^8.1.0" "@svgr/plugin-jsx" "^8.1.0" -"vite@^3.0.0 || ^4.0.0 || ^5.0.0-0", "vite@^3.1.0 || ^4.0.0 || ^5.0.0-0", vite@^4.5.3: - version "4.5.3" - resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.3.tgz#d88a4529ea58bae97294c7e2e6f0eab39a50fb1a" - integrity sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg== +"vite@^3.0.0 || ^4.0.0 || ^5.0.0-0", "vite@^3.1.0 || ^4.0.0 || ^5.0.0-0", vite@^4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.5.tgz#639b9feca5c0a3bfe3c60cb630ef28bf219d742e" + integrity sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ== dependencies: esbuild "^0.18.10" postcss "^8.4.27" diff --git a/docker/datahub-ingestion-base/Dockerfile b/docker/datahub-ingestion-base/Dockerfile index 92b17620998823..08cf2efdcb6a19 100644 --- a/docker/datahub-ingestion-base/Dockerfile +++ b/docker/datahub-ingestion-base/Dockerfile @@ -43,7 +43,9 @@ RUN apt-get update && apt-get upgrade -y \ krb5-user \ krb5-config \ libkrb5-dev \ + librdkafka-dev \ wget \ + curl \ zip \ unzip \ ldap-utils \ diff --git a/docker/kafka-setup/kafka-config.sh b/docker/kafka-setup/kafka-config.sh index 4d5698ccc3856f..cc714fa53b84df 100644 --- a/docker/kafka-setup/kafka-config.sh +++ b/docker/kafka-setup/kafka-config.sh @@ -8,7 +8,8 @@ : ${DATAHUB_ANALYTICS_ENABLED:=true} -export KAFKA_HEAP_OPTS="-Xmx64M" +: ${KAFKA_HEAP_OPTS:=-Xmx64M} +export KAFKA_HEAP_OPTS CONNECTION_PROPERTIES_PATH=/tmp/connection.properties diff --git a/docker/profiles/docker-compose.actions.yml b/docker/profiles/docker-compose.actions.yml index c0a0fd59328715..87385801ede6b5 100644 --- a/docker/profiles/docker-compose.actions.yml +++ b/docker/profiles/docker-compose.actions.yml @@ -1,7 +1,7 @@ x-datahub-actions-service: &datahub-actions-service hostname: actions - image: ${DATAHUB_ACTIONS_IMAGE:-${DATAHUB_ACTIONS_REPO:-acryldata}/datahub-actions}:${ACTIONS_VERSION:-v0.0.14} + image: ${DATAHUB_ACTIONS_IMAGE:-${DATAHUB_ACTIONS_REPO:-acryldata}/datahub-actions}:${ACTIONS_VERSION:-v0.1.1} env_file: - datahub-actions/env/docker.env - ${DATAHUB_LOCAL_COMMON_ENV:-empty.env} @@ -87,4 +87,4 @@ services: - debug-elasticsearch depends_on: datahub-gms-debug-elasticsearch: - condition: service_healthy \ No newline at end of file + condition: service_healthy diff --git a/docs-website/adoptionStoriesIndexes.json b/docs-website/adoptionStoriesIndexes.json index bb6e8d174e0ce8..1177d74dc6df95 100644 --- a/docs-website/adoptionStoriesIndexes.json +++ b/docs-website/adoptionStoriesIndexes.json @@ -37,7 +37,7 @@ { "name": "Optum", "slug": "optum", - "imageUrl": "/img/logos/companies/optum.jpg", + "imageUrl": "/img/logos/companies/optum.png", "imageSize": "medium", "link": "https://opensource.optum.com/blog/2022/03/23/data-mesh-via-datahub", "linkType": "blog", diff --git a/docs-website/docusaurus.config.js b/docs-website/docusaurus.config.js index 9b1b89afb329a5..88a2c79a450eee 100644 --- a/docs-website/docusaurus.config.js +++ b/docs-website/docusaurus.config.js @@ -3,7 +3,7 @@ const isSaas = process.env.DOCUSAURUS_IS_SAAS === "true"; module.exports = { title: process.env.DOCUSAURUS_CONFIG_TITLE || "DataHub", - tagline: "A Metadata Platform for the Modern Data Stack", + tagline: "The #1 Open Source Metadata Platform", url: process.env.DOCUSAURUS_CONFIG_URL || "https://datahubproject.io", baseUrl: process.env.DOCUSAURUS_CONFIG_BASE_URL || "/", onBrokenLinks: "throw", @@ -55,16 +55,16 @@ module.exports = { }, themeConfig: { - ...(!isSaas && { - announcementBar: { - id: "announcement", - content: - '

DataHub Cloud  Acryl Data delivers an easy to consume DataHub platform for the enterprise

Sign Up for DataHub Cloud →', - backgroundColor: "#070707", - textColor: "#ffffff", - isCloseable: false, - }, - }), + // ...(!isSaas && { + // announcementBar: { + // id: "announcement", + // content: + // '

DataHub Cloud  Acryl Data delivers an easy to consume DataHub platform for the enterprise

Sign Up for DataHub Cloud →', + // backgroundColor: "#070707", + // textColor: "#ffffff", + // isCloseable: false, + // }, + // }), navbar: { title: null, logo: { diff --git a/docs-website/package.json b/docs-website/package.json index 58820fbf42b21b..e1130148864e5e 100644 --- a/docs-website/package.json +++ b/docs-website/package.json @@ -42,6 +42,7 @@ "docusaurus-graphql-plugin": "0.5.0", "docusaurus-plugin-sass": "^0.2.1", "dotenv": "^16.0.1", + "framer-motion": "^11.5.4", "markdown-link-check": "^3.11.2", "markprompt": "^0.1.7", "react": "^18.2.0", diff --git a/docs-website/src/pages/_components/CaseStudy/case-study.module.scss b/docs-website/src/pages/_components/CaseStudy/case-study.module.scss new file mode 100644 index 00000000000000..e17f1f74656dc1 --- /dev/null +++ b/docs-website/src/pages/_components/CaseStudy/case-study.module.scss @@ -0,0 +1,209 @@ +.container { + display: flex; + flex-direction: column; + background: #F4F4F5; + font-family: "Manrope"; +} +.case_study { + display: flex; + flex-direction: column; + width: 100vw; + margin: 5rem auto; + + .case_study_heading { + text-align: center; + font-family: "Manrope"; + + div { + font-size: 2.5rem; + line-height: normal; + } + p { + font-size: 1.25rem; + margin-top: 10px; + } + } + + .card_row::-webkit-scrollbar { + display: none; + } + .card_row { + margin-top: 8px; + overflow-x: scroll; + width: 100vw; + scrollbar-width: none; + display: flex; + + .card_row_wrapper { + display: flex; + flex-direction: row; + align-items: center; + padding: 0 10vw; + flex: 1; + } + .cardLink { + color: #000; + + &:hover { + text-decoration: none; + } + } + + .card { + display: flex !important; + flex-shrink: 0; + justify-content: space-between; + flex-direction: column; + position: relative; + width: 340px !important; + height: 320px !important; + border-radius: 24px; + background: white; + padding: 8px; + margin-right: 20px; + transition: box-shadow .2s ease-in-out; + transition: opacity .2s ease-in-out; + + &:hover { + box-shadow: 0px 0px 4px 0px #0000001C; + opacity: .9; + } + + .card_image { + width: 100%; + height: 14rem; + + border-radius: 16px; + display: flex; + justify-content: center; + align-items: center; + position: relative; + overflow: hidden; + background-color: #25252e; + + img { + object-fit: center; + max-width: 40%; + max-height: 40%; + z-index: 10; + filter: brightness(2); + opacity: .9; + } + .cardImageBackground { + position: absolute; + height: 100%; + width: 100%; + z-index: 0; + background-size: cover; + opacity: .15; + } + } + + .card_tag { + position: absolute; + right: 1.2rem; + top: 1.2rem; + background-color: #edf2ff80; + color: #FFF; + font-size: 0.75rem; + font-family: 'Manrope'; + font-weight: 600; + padding: 0.1rem 0.5rem; + border-radius: 0.5rem; + z-index: 10; + } + .card_heading_div { + text-align: start; + padding: 12px; + + .card_heading { + font-family: "Manrope"; + font-size: 1.1rem; + font-weight: 600; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin-bottom: 2px; + } + .card_para { + font-size: .9rem; + line-height: normal; + display: -webkit-box; + line-clamp: 2; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + opacity: .75; + } + } + } + } + + .bottom_line { + cursor: pointer; + text-decoration: none; + display: flex; + align-items: center; + justify-content: center; + color: #12b0fb; + font-size: 1.1rem; + font-weight: 500; + margin-top: 50px; + margin-bottom: 10px; + + span { + line-height: 10px; + font-size: 1.5rem; + margin-left: 10px; + } + } +} + +@media (max-width: 800px) { + .case_study { + .case_study_heading { + text-align: center; + font-family: "Manrope"; + + div { + width: 80%; + margin: auto; + font-size: 2rem; + line-height: normal; + font-weight: 400; + } + p { + width: 80%; + margin: auto; + font-size: 1.1rem; + line-height: 1.5rem; + margin-top: 12px; + } + } + + .card_row { + margin-top: 24px; + + .card_row_wrapper { + padding: 0 5vw; + } + } + + .bottom_line { + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: #12b0fb; + font-size: 1.1rem; + font-weight: 500; + margin-top: 50px; + margin-bottom: 10px; + + span { + font-size: 1.5rem; + } + } + } +} diff --git a/docs-website/src/pages/_components/CaseStudy/caseStudyContent.js b/docs-website/src/pages/_components/CaseStudy/caseStudyContent.js new file mode 100644 index 00000000000000..524dbfd1b19d63 --- /dev/null +++ b/docs-website/src/pages/_components/CaseStudy/caseStudyContent.js @@ -0,0 +1,74 @@ +const caseStudyData = [ + { + title: "Enhancing Extensibility", + description: + "How Netflix is Collaborating with DataHub to Enhance its Extensibility.", + tag: "Technology", + backgroundImage: + "https://miro.medium.com/v2/resize:fit:1400/format:webp/1*iUnFujzVqMBpK41z32-Ctw.png", + image: "https://datahubproject.io/img/logos/companies/netflix.png", + link: "https://datahubproject.io/adoption-stories/#netflix", + }, + { + title: "Scaling Data Governance", + description: + "How VISA Uses DataHub to Scale Data Governance.", + tag: "Finance", + backgroundImage: + "https://miro.medium.com/v2/resize:fit:2000/format:webp/1*mtC4j8J-jumJKWg8RuR6xQ@2x.png", + image: "https://datahubproject.io/img/logos/companies/visa.png", + link: "https://datahubproject.io/adoption-stories/#visa", + }, + { + title: "Ensuring Data Reliability", + description: + "How Notion Uses DataHub Cloud to Ensure Data Reliability.", + tag: "Technology", + backgroundImage: + "https://www.notion.so/cdn-cgi/image/format=webp,width=1920/front-static/pages/product/super-duper/hero-illo.png", + image: "https://boost.space/wp-content/uploads/2023/08/notion.png", + link: "https://datahubproject.io/adoption-stories/#notion", + }, + { + title: "Working with Petabyte Scale Healthcare Data", + description: + "Enabling the Data Mesh via DataHub to do work on some of healthcare’s more impactful problems.", + tag: "Healthcare", + backgroundImage: + "https://opensource.optum.com/static/images/mesh-overview-e26ea2aaa8d3dbb1f1771b50f4e31449.png", + image: "/img/logos/companies/optum.png", + link: "https://datahubproject.io/adoption-stories/#optum", + }, + { + title: "Exploring Airtel's shift to a decentralized data architecture.", + description: + "Discover how DataHub has become integral to Airtel's datamesh architecture.", + tag: "Telecommunications", + backgroundImage: + "https://upload.wikimedia.org/wikipedia/commons/3/3a/Airtel_logo-01.png", + image: "/img/logos/companies/airtel.png", + link: "https://datahubproject.io/adoption-stories/#airtel", + }, + { + title: "Leveling Up Data Management.", + description: + "DataHub's role in improving data management, tracing data lineage, and ensuring quality.", + tag: "Gaming", + backgroundImage: + "https://upload.wikimedia.org/wikipedia/en/thumb/7/7b/Zynga.svg/1200px-Zynga.svg.png", + image: "/img/logos/companies/zynga.png", + link: "https://datahubproject.io/adoption-stories/#zynga", + }, + { + title: "And many more...", + description: + "See our adoption stories page for more.", + tag: "", + backgroundImage: + "", + image: "", + link: "https://datahubproject.io/adoption-stories/", + }, +]; + +export default caseStudyData; diff --git a/docs-website/src/pages/_components/CaseStudy/index.js b/docs-website/src/pages/_components/CaseStudy/index.js new file mode 100644 index 00000000000000..0362dec9a0d3ef --- /dev/null +++ b/docs-website/src/pages/_components/CaseStudy/index.js @@ -0,0 +1,54 @@ +import React from "react"; +import styles from "./case-study.module.scss"; +import Link from '@docusaurus/Link' +import { Carousel } from "antd"; +import caseStudyData from "./caseStudyContent"; + + +const CaseStudy = () => { + return ( +
+ {/* Section-1 */} +
+
+
See how industry leaders use Datahub
+

Across finance, healthcare, e-commerce, and countless more.

+
+ +
+
+ {caseStudyData.map((caseStudy) => ( + + + See all adoption stories → + +
+
+ ); +}; + +export default CaseStudy; diff --git a/docs-website/src/pages/_components/Community/community.module.scss b/docs-website/src/pages/_components/Community/community.module.scss new file mode 100644 index 00000000000000..37f1a00878f77a --- /dev/null +++ b/docs-website/src/pages/_components/Community/community.module.scss @@ -0,0 +1,280 @@ +.container { + display: flex; + flex-direction: column; + background: #fafafa; +} + +.community_section { + position: relative; + display: flex; + justify-content: space-between; + font-family: "Manrope"; + + .community_section_left { + padding: 60px 0; + width: 60%; + height: 100%; + background: #3e2644; + color: white; + display: flex; + align-items: center; + justify-content: center; + + .community_section_left_content { + margin: 2rem auto; + + .community_section_heading { + color: rgba($color: #fff, $alpha: 0.4); + font-size: 3.5rem; + line-height: normal; + font-weight: bold; + } + + p { + font-size: 1.2rem; + color: rgba($color: #fff, $alpha: 0.6); + font-weight: light; + margin-top: 10px; + } + + a { + cursor: pointer; + display: inline-block; + font-size: 1.2rem; + background-color: transparent; + padding: 5px 20px; + border-radius: 50px; + margin: 0 10px 0 0; + outline: none; + border: 1px solid white; + color: white; + text-decoration: none; + transition: background-color .2s ease-in-out; + &:hover { + background-color: #FFFFFF1A; + } + } + } + } + + .community_section_right { + width: 40%; + background: #000000; + flex: 1; + color: white; + display: flex; + justify-content: center; + flex-direction: column; + font-family: "Manrope"; + + .community_section_subText { + padding: 40px 60px 40px; + color: white; + + a { + text-decoration: none; + } + } + + .community_section_heading { + color: rgba($color: #fff, $alpha: 0.4); + font-size: 1.5rem; + line-height: normal; + font-weight: bold; + + a { + margin-top: 16px; + font-weight: 300; + cursor: pointer; + display: inline-flex; + font-size: 16px; + background-color: transparent; + padding: 8px 20px; + border-radius: 50px; + outline: none; + border: 0.89px solid #E9EAEE; + color: white; + align-items: center; + gap: 8px; + transition: background-color .2s ease-in-out; + &:hover { + background-color: #FFFFFF1A; + } + } + } + } +} + +.carouselContainer { + width: 100%; + background-color: #000; + min-height: 100px; + min-width: 400px; +} + +.slider { + background: #000; + height: 100px; + margin: auto; + overflow: hidden; + position: relative; + display: flex; + align-items: center; + width: 100%; + + &::before, + &::after { + position: absolute; + content: ''; + width: 90%; + height: 100%; + z-index: 9; + } + + &::before { + left: 0; + background: linear-gradient(90deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0) 70%); + } + + &::after { + right: 0; + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0.7) 100%); + } +} + +.carouselContainer { + overflow: hidden; +} + +.slider { + position: relative; +} + +.slide_track { + display: flex; + width: calc((72px + 24px) * 6 * 2); + /* Width of the track */ + animation: scroll 15s linear infinite; +} + +.slide { + width: 72px; + height: 72px; + margin-left: 24px; + display: flex; + justify-content: center; + overflow: hidden; + flex-direction: column; + align-items: center; + position: relative; + background-size: cover; + background-repeat: no-repeat; +} + +@keyframes scroll { + 0% { + transform: translateX(0); + } + + 100% { + transform: translateX(-50%); + } +} + +.slideCrown { + position: absolute; + right: 5px; + top: 6px; + width: 18px; + height: 18px; + background-image: url("/img/slack/Crown.png"); + background-repeat: no-repeat; + background-size: contain; +} + +.slide::before { + width: 25px; + height: 25px; + border-radius: 25px; + right: 2px; + top: 2px; + position: absolute; + content: ''; + background: white; + display: flex; + align-items: center; + justify-content: center; +} + + +@keyframes slideIn { + 0% { + opacity: 0; + transform: translateY(20px); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} + +.numberContainer { + display: inline-block; + width: 11rem; + text-align: right; +} + +.numberChange { + display: inline-block; + animation: slideIn 0.5s ease-in-out; + width: 11rem; +} + + +@media only screen and (max-width: 800px) { + .community_section { + flex-direction: column; + + .community_section_left { + width: 100%; + padding: 20px 24px; + + .community_section_left_content { + + .community_section_heading { + font-size: 2rem; + + img { + height: 24px; + width: 24px; + } + } + p { + font-size: 1rem; + line-height: 1.2rem; + margin-top: 8px; + margin-bottom: 12px; + } + a { + padding: 4px 8px; + font-size: 1rem; + } + .numberChange, .numberContainer { + width: 6.5rem; + } + } + } + + .community_section_right { + width: 100%; + overflow: hidden; + .community_section_subText { + padding: 32px 52px 16px; + } + .carouselContainer { + margin-bottom: 24px; + } + } + } +} \ No newline at end of file diff --git a/docs-website/src/pages/_components/Community/index.js b/docs-website/src/pages/_components/Community/index.js new file mode 100644 index 00000000000000..a4f2b2304e51e4 --- /dev/null +++ b/docs-website/src/pages/_components/Community/index.js @@ -0,0 +1,120 @@ +import React, { useState, useRef, useEffect } from "react"; +import styles from "./community.module.scss"; +import useBaseUrl from "@docusaurus/useBaseUrl"; + +const TARGET_COUNT = 11535; +const INCREMENT = 1; + +const Community = () => { + const currentCountRef = useRef(TARGET_COUNT - 50); + const [count, setCount] = useState(currentCountRef.current); + const hasAnimatedRef = useRef(false); + const counterRef = useRef(null); + + const animateNumber = () => { + const makeTimeout = () => { + const distance = TARGET_COUNT - currentCountRef.current; + const isSlowCount = distance < 10; + const isMediumCount = distance < 20; + setTimeout(() => { + if (currentCountRef.current < TARGET_COUNT) { + currentCountRef.current += INCREMENT; + setCount(currentCountRef.current); + makeTimeout(); + } + }, isSlowCount ? Math.random() * 6000 : (isMediumCount ? 150 : 50)); + } + makeTimeout(); + }; + const handleScroll = () => { + if (hasAnimatedRef.current) return; + if (!counterRef.current) return; + + const { top } = counterRef.current.getBoundingClientRect(); + const windowHeight = window.innerHeight; + + if (top <= windowHeight) { + hasAnimatedRef.current = true; + animateNumber(); + } + }; + + const formattedCount = count.toLocaleString(); + + useEffect(() => { + window.addEventListener('scroll', handleScroll); + return () => { + window.removeEventListener('scroll', handleScroll); + } + }, []) + + return ( +
+
+
+
+
+ A community that's +
+ Slack + + + {formattedCount} + + {" "} + strong. +
+
+

+ Q&A.  Office Hours.  Think Tanks.  Job Postings. +

+ Join Slack +
+
+
+
+
+
+ With{" "} + GitHub{" "} + 500+ contributors
world-wide. +
+ Open GitHub +
+
+
+
+ {/* Duplicate the slides */} + {[...Array(2)].map((_, i) => ( + + {[1, 2, 3, 4, 5, 6].map((item, index) => ( +
+
+
+ ))} + + ))} +
+
+
+
+
+
+
+ ); +}; + +export default Community; diff --git a/docs-website/src/pages/_components/Ecosystem/ecosystem.module.scss b/docs-website/src/pages/_components/Ecosystem/ecosystem.module.scss new file mode 100644 index 00000000000000..499fe4c89eaa58 --- /dev/null +++ b/docs-website/src/pages/_components/Ecosystem/ecosystem.module.scss @@ -0,0 +1,225 @@ +.container { + display: flex; + flex-direction: column; + background: #fafafa; +} +.ecosystem_section { + position: relative; + background: white; + padding: 4vh 0; + padding-bottom: 6vh; + max-height: 1100px; + display: flex; + justify-content: center; + align-items: center; + // padding: 2rem 0rem; + // margin: 4rem 0rem 0rem 0rem; + + .ecosystem_section_content { + width: 70%; + min-width: 800px; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 2rem 0rem; + + .ecosystem_section_upper_content { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding-top: 1rem; + + .ecosystem_section_heading { + font-size: 2.75rem; + line-height: 3.25rem; + font-weight: 500; + font-family: Manrope; + } + .ecosystem_section_subtitle { + font-size: 1.25rem; + margin-top: 2rem; + line-height: normal; + font-family: Manrope; + } + .bottom_line_cta { + color: #12b0fb; + font-size: 1rem; + font-weight: 500; + margin-top: 1.5rem; + margin-bottom: 1rem; + cursor: pointer; + } + } + .ecosystem_section_lower_content { + height: 380px; + margin-top: 48px; + display: flex; + flex-direction: row; + + .itemWrappers { + display: flex; + flex-direction: column; + margin-right: 8px; + } + .itemWrappersRow { + display: flex; + flex-direction: row; + height: 50%; + } + .itemWrappers>.itemWrappersRow:first-child { + padding-bottom: 4px; + } + .itemWrappers>.itemWrappersRow:last-child { + padding-top: 4px; + } + .itemWrappersRow>a:nth-child(2) { + margin-left: 8px; + } + + .diagramItem { + display: flex; + border-radius: 20px; + overflow: hidden; + aspect-ratio: 1; + height: 100%; + flex-basis: 45%; + background-color: #f6f8fb; + justify-content: center; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + } + + } + + .item1, + .item2, + .item3, + .item4 { + border-radius: 20px; + display: flex; + align-items: end; + justify-content: start; + position: relative; + padding: 36px 32px; + overflow: hidden; + white-space: normal; + cursor: pointer; + transition: box-shadow 0.3s ease-in-out; + text-decoration: none; + + &:hover { + box-shadow: 0px 2px 12px 0px #00000040; + .itemLinkOpenArrow { + opacity: 1; + } + } + } + .itemLinkOpenArrow { + position: absolute; + top: 12px; right: 12px; + height: 36px; + width: 36px; + opacity: 0.75; + transition: opacity 0.3s ease-in-out; + } + + .item1 { + flex-basis: 40%; + background-color: #77B750; + } + + .item2 { + flex-grow: 1; + background-color: #FC5263; + } + + .item3 { + flex-grow: 1; + background-color: #EFB300; + } + + .item4 { + flex-basis: 40%; + background-color: #1890FF; + } + + /* Additional: Control image size */ + .item_content img { + width: 20px; + height: 20px; + // make it all white + filter: brightness(0) invert(1); + } + + /* Additional: Limit text height with ellipsis */ + .item_content span { + display: -webkit-box; + -webkit-line-clamp: 3; /* Show only 2 lines */ + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + color: white; + font-size: 1.15rem; + line-height: 1.3rem; + } + } + + // Responsiveness + @media only screen and (max-width: 800px) { + .ecosystem_section_content { + width: 90%; + min-width: 0; + height: auto!important; + padding-bottom: 48px; + padding-top: 48px; + + .ecosystem_section_upper_content { + height: auto!important; + + .ecosystem_section_heading { + font-size: 1.75rem; + line-height: 2.25rem; + } + .ecosystem_section_subtitle { + font-size: 1rem; + line-height: 1.3rem; + margin-top: 1rem; + opacity: .75; + } + .bottom_line_cta { + margin-top: .5rem; + } + } + .ecosystem_section_lower_content { + height: auto; + margin-top: 8px; + flex-direction: column-reverse; + + .diagramItem { + margin-bottom: 12px; + } + + .item1, + .item2, + .item3, + .item4 { + padding: 24px 12px; + } + .item1, .item4 { + flex-basis: 45%; + } + .item_content span { + font-size: .8rem; + line-height: 1.1rem; + } + } + } + + } + +} diff --git a/docs-website/src/pages/_components/Ecosystem/index.js b/docs-website/src/pages/_components/Ecosystem/index.js new file mode 100644 index 00000000000000..4f33e01a7f4c73 --- /dev/null +++ b/docs-website/src/pages/_components/Ecosystem/index.js @@ -0,0 +1,95 @@ +import React from "react"; +import Link from "@docusaurus/Link"; +import styles from "./ecosystem.module.scss"; +import useBaseUrl from "@docusaurus/useBaseUrl"; + +const Ecosystem = () => { + return ( +
+
+
+
+
+ A single control plane for
your entire data ecosystem. +
+
+ DataHub is built on an extensible, scalable and secure foundation. +
It is hardened and ready for the toughest challenges large enterprises face. +
+ + See how Netflix uses DataHub at scale → + +
+
+
+
+ + +
+ right--v1 + + An architecture that's designed for true enterprise scale. + +
+ + + +
+ right--v1 + + 70+ native integrations,
growing every month. +
+
+ +
+
+ + +
+ right--v1 + + Execute ingestion in-VPC,
so your data never leaves +
the network. +
+
+ + + +
+ right--v1 + + Event-driven actions framework, rich APIs and SDKs. + +
+ +
+
+
+
+
+
+
+ ); +}; + +export default Ecosystem; diff --git a/docs-website/src/pages/_components/Hero/hero.module.scss b/docs-website/src/pages/_components/Hero/hero.module.scss index 97bdceaef69366..2484b259a32c28 100644 --- a/docs-website/src/pages/_components/Hero/hero.module.scss +++ b/docs-website/src/pages/_components/Hero/hero.module.scss @@ -1,44 +1,228 @@ .hero { + padding: 2vw 0; + :global { .button { margin-right: 1rem; } - .hero__alert { - margin-bottom: 2rem; - @media (min-width: 690px) { - display: flex; + + .container { + background-color: #1890FF; + border-radius: 50px; + max-width: 95vw !important; + background-image: url("data:image/svg+xml,%3Csvg width='1586' height='895' viewBox='0 0 1586 895' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg opacity='0.3'%3E%3Cmask id='mask0_312_2970' style='mask-type:alpha' maskUnits='userSpaceOnUse' x='4' y='0' width='1578' height='887'%3E%3Crect x='1582' y='887' width='1578' height='887' rx='49.66' transform='rotate(180 1582 887)' fill='%231890FF'/%3E%3C/mask%3E%3Cg mask='url(%23mask0_312_2970)'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M1258.06 -51.9644L1255.94 -49.8714L1287.88 -18.3583H1362.29C1362.88 -16.9122 1364.32 -15.8921 1366 -15.8921C1368.21 -15.8921 1370 -17.659 1370 -19.8387C1370 -22.0183 1368.21 -23.7853 1366 -23.7853C1364.32 -23.7853 1362.88 -22.7648 1362.29 -21.3183H1289.12L1258.06 -51.9644ZM1586.5 -50.9179H1583.5V51.3203L1625.38 92.64H1662V89.68H1626.62L1586.5 50.0943V-50.9179ZM905.709 -29.2115C905.116 -27.7653 903.679 -26.7452 902 -26.7452C899.791 -26.7452 898 -28.5122 898 -30.6918C898 -32.8715 899.791 -34.6384 902 -34.6384C903.679 -34.6384 905.116 -33.618 905.709 -32.1715H1240.12L1322.62 49.2273H1565.53C1566.23 48.0475 1567.52 47.2537 1569 47.2537C1571.21 47.2537 1573 49.0206 1573 51.2003C1573 53.3799 1571.21 55.1469 1569 55.1469C1567.14 55.1469 1565.57 53.8893 1565.13 52.1873H1321.38L1238.88 -29.2115H905.709ZM1401.46 -21.8116H1458.5V-24.7716H1401.87C1401.43 -26.474 1399.86 -27.7319 1398 -27.7319C1395.79 -27.7319 1394 -25.9649 1394 -23.7853C1394 -21.6056 1395.79 -19.8387 1398 -19.8387C1399.48 -19.8387 1400.77 -20.6322 1401.46 -21.8116ZM921.709 29.0009H1042.88L1092.38 77.8402H1227.54C1228.23 79.0197 1229.52 79.8132 1231 79.8132C1233.21 79.8132 1235 78.0462 1235 75.8666C1235 73.6869 1233.21 71.92 1231 71.92C1229.14 71.92 1227.57 73.1779 1227.13 74.8802H1093.62L1044.12 26.041H921.709C921.116 24.5945 919.679 23.574 918 23.574C915.791 23.574 914 25.341 914 27.5206C914 29.7003 915.791 31.4672 918 31.4672C919.679 31.4672 921.116 30.4471 921.709 29.0009ZM1305.56 60.514L1303.44 62.607L1359.88 118.293H1501.5V115.333H1361.12L1305.56 60.514ZM1580.97 107.933C1580.72 109.88 1579.04 111.386 1577 111.386C1574.79 111.386 1573 109.619 1573 107.439C1573 105.26 1574.79 103.493 1577 103.493C1578.26 103.493 1579.39 104.071 1580.12 104.973H1662V107.933H1580.97ZM938.465 130.133C937.773 131.312 936.48 132.106 935 132.106C932.791 132.106 931 130.339 931 128.159C931 125.979 932.791 124.213 935 124.213C936.864 124.213 938.43 125.47 938.874 127.173H1075.5V130.133H938.465ZM1372.5 164.378C1371.03 163.793 1370 162.375 1370 160.719C1370 158.539 1371.79 156.772 1374 156.772C1376.21 156.772 1378 158.539 1378 160.719C1378 162.375 1376.97 163.793 1375.5 164.378V233.611L1401.12 258.891H1564.88L1584.48 239.552C1584.17 238.994 1584 238.356 1584 237.677C1584 235.498 1585.79 233.731 1588 233.731C1590.21 233.731 1592 235.498 1592 237.677C1592 239.857 1590.21 241.624 1588 241.624C1587.58 241.624 1587.18 241.561 1586.8 241.445L1566.12 261.851H1399.88L1372.5 234.838V164.378ZM1283 178.479H1131.5V181.439H1283V178.479ZM1585 202.158H1490.38L1465.38 226.825H1415V229.785H1466.62L1491.62 205.118H1585V202.158ZM1337.13 232.745H1257V235.705H1337.54C1338.23 236.884 1339.52 237.677 1341 237.677C1343.21 237.677 1345 235.91 1345 233.731C1345 231.551 1343.21 229.784 1341 229.784C1339.14 229.784 1337.57 231.042 1337.13 232.745ZM1423.5 250.504H1517.5V247.544H1423.5V250.504ZM1587.87 317.597H1662V314.637H1587.47C1586.77 313.457 1585.48 312.663 1584 312.663C1581.79 312.663 1580 314.43 1580 316.61C1580 318.789 1581.79 320.556 1584 320.556C1585.86 320.556 1587.43 319.299 1587.87 317.597ZM1466 333.876H1541.38L1564.88 357.063H1639.5V354.103H1566.12L1542.62 330.916H1466V333.876ZM1640.5 522.327H1569.4L1539.4 550.446H1474.66C1474.1 549.279 1472.9 548.473 1471.5 548.473C1469.57 548.473 1468 550.019 1468 551.926C1468 553.833 1469.57 555.379 1471.5 555.379C1472.9 555.379 1474.1 554.573 1474.66 553.406H1540.6L1570.6 525.286H1640.5V522.327ZM1660 536.633H1590.88L1568.5 558.713V585.009C1566.53 585.252 1565 586.913 1565 588.925C1565 591.105 1566.79 592.872 1569 592.872C1571.21 592.872 1573 591.105 1573 588.925C1573 587.679 1572.41 586.568 1571.5 585.844V559.939L1592.12 539.593H1660V536.633ZM1481.66 567.219H1538.5V601.052C1537.03 601.638 1536 603.056 1536 604.712C1536 606.892 1537.79 608.659 1540 608.659C1542.21 608.659 1544 606.892 1544 604.712C1544 603.056 1542.97 601.638 1541.5 601.052V564.259H1481.66C1481.1 563.093 1479.9 562.286 1478.5 562.286C1476.57 562.286 1475 563.832 1475 565.739C1475 567.646 1476.57 569.193 1478.5 569.193C1479.9 569.193 1481.1 568.386 1481.66 567.219ZM1591.5 567.219H1660V564.259H1591.5V567.219ZM1609.5 588.432H1606.5V631.845H1660V628.885H1609.5V588.432ZM-70 622.472H99.7621L122.5 651.589V726.357C121.034 726.942 120 728.36 120 730.017C120 732.196 121.791 733.963 124 733.963C126.209 733.963 128 732.196 128 730.017C128 728.36 126.966 726.942 125.5 726.357V650.581L101.238 619.512H-70V622.472ZM1566.62 622.472H1398.88L1372.5 648.498V717.477C1371.03 718.063 1370 719.481 1370 721.137C1370 723.317 1371.79 725.083 1374 725.083C1376.21 725.083 1378 723.317 1378 721.137C1378 719.481 1376.97 718.063 1375.5 717.477V649.724L1400.12 625.432H1565.38L1588.18 647.931C1588.06 648.303 1588 648.7 1588 649.111C1588 651.291 1589.79 653.058 1592 653.058C1594.21 653.058 1596 651.291 1596 649.111C1596 646.932 1594.21 645.165 1592 645.165C1591.31 645.165 1590.67 645.336 1590.1 645.637L1566.62 622.472ZM1343 660.951C1341.14 660.951 1339.57 659.693 1339.13 657.991H1193.11L1145.61 703.87H958.5V700.911H1144.39L1191.89 655.031H1339.54C1340.23 653.852 1341.52 653.058 1343 653.058C1345.21 653.058 1347 654.825 1347 657.004C1347 659.184 1345.21 660.951 1343 660.951ZM1409 652.505C1410.7 652.505 1412.16 653.553 1412.73 655.031H1470.12L1495.62 680.191H1581.29C1581.88 678.745 1583.32 677.724 1585 677.724C1587.21 677.724 1589 679.491 1589 681.671C1589 683.85 1587.21 685.617 1585 685.617C1583.32 685.617 1581.88 684.597 1581.29 683.151H1494.38L1468.88 657.991H1412.68C1412.08 659.406 1410.66 660.398 1409 660.398C1406.79 660.398 1405 658.631 1405 656.451C1405 654.272 1406.79 652.505 1409 652.505ZM1619 653.058C1620.48 653.058 1621.77 653.852 1622.46 655.031H1660V657.991H1622.87C1622.43 659.693 1620.86 660.951 1619 660.951C1616.79 660.951 1615 659.184 1615 657.004C1615 654.825 1616.79 653.058 1619 653.058ZM382 753.696C383.679 753.696 385.116 754.717 385.709 756.163H573.5V759.123H385.709C385.116 760.569 383.679 761.59 382 761.59C379.791 761.59 378 759.823 378 757.643C378 755.463 379.791 753.696 382 753.696ZM1073 761.59C1071.32 761.59 1069.88 760.569 1069.29 759.123H943.621L890.621 811.416H835V808.456H889.379L942.379 756.163H1069.29C1069.88 754.717 1071.32 753.696 1073 753.696C1075.21 753.696 1077 755.463 1077 757.643C1077 759.823 1075.21 761.59 1073 761.59ZM1497.54 767.51H1353.88L1297.94 822.702L1300.06 824.795L1355.12 770.469H1497.13C1497.57 772.172 1499.14 773.429 1501 773.429C1503.21 773.429 1505 771.662 1505 769.483C1505 767.303 1503.21 765.536 1501 765.536C1499.52 765.536 1498.23 766.33 1497.54 767.51ZM1577 774.416C1578.68 774.416 1580.12 775.436 1580.71 776.883H1660V779.843H1580.71C1580.12 781.289 1578.68 782.309 1577 782.309C1574.79 782.309 1573 780.542 1573 778.363C1573 776.183 1574.79 774.416 1577 774.416ZM474.5 789.709H524.903L597.403 857.295H688V854.335H598.597L526.097 786.749H474.5V789.709ZM266.709 811.416H405.879L452.379 857.295H572.535C573.227 858.474 574.519 859.268 576 859.268C578.209 859.268 580 857.501 580 855.321C580 853.142 578.209 851.375 576 851.375C574.136 851.375 572.57 852.633 572.126 854.335H453.621L407.121 808.456H266.709C266.116 807.009 264.679 805.989 263 805.989C260.791 805.989 259 807.756 259 809.936C259 812.115 260.791 813.882 263 813.882C264.679 813.882 266.116 812.862 266.709 811.416ZM803.291 808.456C803.884 807.009 805.321 805.989 807 805.989C809.209 805.989 811 807.756 811 809.936C811 812.115 809.209 813.882 807 813.882C805.321 813.882 803.884 812.862 803.291 811.416H688V808.456H803.291ZM1232 813.882C1230.32 813.882 1228.88 812.862 1228.29 811.416H1094.62L1044.62 860.748H923.709C923.116 862.194 921.679 863.215 920 863.215C917.791 863.215 916 861.448 916 859.268C916 857.089 917.791 855.322 920 855.322C921.679 855.322 923.116 856.342 923.709 857.788H1043.38L1093.38 808.456H1228.29C1228.88 807.009 1230.32 805.989 1232 805.989C1234.21 805.989 1236 807.756 1236 809.936C1236 812.115 1234.21 813.882 1232 813.882ZM1577.5 829.175H1320.88L1233.88 915.014H906.123C905.39 914.112 904.263 913.534 903 913.534C900.791 913.534 899 915.301 899 917.481C899 919.66 900.791 921.427 903 921.427C905.04 921.427 906.723 919.921 906.969 917.974H1235.12L1322.12 832.135H1577.5V829.175ZM-66.5 833.122H169.879L254.016 916.136C254.005 916.254 254 916.373 254 916.494C254 918.674 255.791 920.44 258 920.44C260.209 920.44 262 918.674 262 916.494C262 914.314 260.209 912.547 258 912.547C257.054 912.547 256.184 912.872 255.499 913.414L171.121 830.162H-66.5V833.122ZM1366 904.161H1298.38L1265.94 936.167L1268.06 938.26L1299.62 907.121H1366V904.161ZM1396.5 907.121H1462.42L1496.99 938.306L1499.01 936.121L1463.58 904.161H1396.5V907.121ZM271 912.547C272.679 912.547 274.116 913.568 274.709 915.014H592.5V917.974H274.709C274.116 919.42 272.679 920.44 271 920.44C268.791 920.44 267 918.674 267 916.494C267 914.314 268.791 912.547 271 912.547ZM1660.5 792.669H1629.88L1583.5 838.429V934.254H1586.5V839.655L1631.12 795.629H1660.5V792.669ZM1515 639.245C1517.21 639.245 1519 637.478 1519 635.298C1519 633.119 1517.21 631.352 1515 631.352C1512.79 631.352 1511 633.119 1511 635.298C1511 637.478 1512.79 639.245 1515 639.245ZM1619 228.798C1621.21 228.798 1623 227.031 1623 224.851C1623 222.671 1621.21 220.904 1619 220.904C1616.79 220.904 1615 222.671 1615 224.851C1615 227.031 1616.79 228.798 1619 228.798ZM1606 308.716C1608.21 308.716 1610 306.949 1610 304.77C1610 302.59 1608.21 300.823 1606 300.823C1603.79 300.823 1602 302.59 1602 304.77C1602 306.949 1603.79 308.716 1606 308.716ZM1573 292.93C1573 295.11 1571.21 296.877 1569 296.877C1566.79 296.877 1565 295.11 1565 292.93C1565 290.75 1566.79 288.983 1569 288.983C1571.21 288.983 1573 290.75 1573 292.93ZM1545 284.05C1547.21 284.05 1549 282.283 1549 280.103C1549 277.924 1547.21 276.157 1545 276.157C1542.79 276.157 1541 277.924 1541 280.103C1541 282.283 1542.79 284.05 1545 284.05ZM1471 320.556C1471 322.736 1469.21 324.503 1467 324.503C1464.79 324.503 1463 322.736 1463 320.556C1463 318.377 1464.79 316.61 1467 316.61C1469.21 316.61 1471 318.377 1471 320.556ZM1112 826.709C1113.48 826.709 1114.77 825.915 1115.46 824.735H1137V821.775H1115.87C1115.43 820.073 1113.86 818.815 1112 818.815C1109.79 818.815 1108 820.582 1108 822.762C1108 824.942 1109.79 826.709 1112 826.709ZM916 809.936C916 812.115 914.209 813.882 912 813.882C909.791 813.882 908 812.115 908 809.936C908 807.756 909.791 805.989 912 805.989C914.209 805.989 916 807.756 916 809.936ZM1012 783.789H949V786.749H1012V783.789ZM1182 698.937H1221.5V701.897H1182V698.937ZM1112 723.604H1155V726.563H1112V723.604ZM1260.5 723.604H1346.5V726.563H1260.5V723.604Z' fill='white'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + height: 76vh; + min-height: 600px; + } + + // .hero__alert { + // margin-bottom: 2rem; + + // @media (min-width: 690px) { + // display: flex; + // align-items: center; + // justify-content: space-between; + // } + + // .button { + // text-decoration: none; + // margin: 0.5rem 0 0 0; + // display: block; + // white-space: nowrap; + + // @media (min-width: 690px) { + // margin: 0 0 0 0.5rem; + // } + // } + // } + + .hero__img, + .hero__text { + color: white; + } + .hero__img { + width: 45%; + } + + .hero__text { + width: 50%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + >* { + margin-left: 30%; + text-align: left; + width: 90%; + } + + .hero__title { + font-size: 3.5rem; + line-height: normal; + font-family: Manrope; + } + + .hero__subtitle { + font-size: 1.5rem; + line-height: 1.8rem; + font-family: Manrope; + margin-top: 2rem; + font-weight: 300; + display: inline-flex; align-items: center; - justify-content: space-between; + + span { + background: white; + display: inline-flex; + align-items: center; + border-radius: 4px; + margin-left: 4px; + height: 1.8rem; + padding-left: 2px; + padding-right: 6px; + font-family: 'Manrope'; + font-style: normal; + font-weight: 400; + font-size: 1.3rem; + + span { + padding: 0; + + + // background: linear-gradient(90deg, #3B20D9 0%, #C713C6 31%, #DD567D 64.5%, #D7AC27 100%); + background: linear-gradient(90deg, #3B20D9 0%, #533FD1 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-fill-color: transparent; + } + } } - .button { - text-decoration: none; - margin: 0.5rem 0 0 0; - display: block; - white-space: nowrap; - @media (min-width: 690px) { - margin: 0 0 0 0.5rem; + + .hero__cta { + margin-top: 2rem; + + a { + cursor: pointer; + display: inline-block; + font-size: 1rem; + background-color: white; + padding: 5px 20px; + border-radius: 50px; + margin: 0 10px 0 0; + font-weight: 600; + text-decoration: none; + transition: background-color .2s ease-in-out; + &:hover { + background-color: #FFFFFFEE; + } + } + + .cta__secondary { + background-color: rgba($color: #fff, $alpha: .2); + color: white; + border: 1px solid white; + transition: background-color .2s ease-in-out; + &:hover { + background-color: rgba($color: #fff, $alpha: .3); + } } } } - .hero__image { - margin: 2rem 0; + + .hero__footer_cta { + margin-top: 2rem; + font-weight: 500; + cursor: pointer; + text-decoration: none; + display: inline-block; + font-size: 1.2rem; + color: white; } - .hero__alert { - margin-bottom: 2rem; - @media (min-width: 690px) { - display: flex; + + + .hero__img { + display: flex; + align-items: center; + justify-content: center; + + img { + width: 80%; + } + } + + .hero__content { + padding: 2rem 0; + height: 100%; + display: flex; + } + + // .hero__alert { + // margin-bottom: 2rem; + + // @media (min-width: 690px) { + // display: flex; + // align-items: center; + // justify-content: space-between; + // } + + // .button { + // text-decoration: none; + // margin: 0.5rem 0 0 0; + // display: block; + // white-space: nowrap; + + // @media (min-width: 690px) { + // margin: 0 0 0 0.5rem; + // } + // } + // } + + + + + @media only screen and (max-width: 800px) { + .hero__content { + flex-direction: column; align-items: center; - justify-content: space-between; + justify-content: center; } - .button { - text-decoration: none; - margin: 0.5rem 0 0 0; - display: block; - white-space: nowrap; - @media (min-width: 690px) { - margin: 0 0 0 0.5rem; + .hero__img { + width: 100%; + margin-top: 12px; + } + .hero__text { + width: 100%; + padding-left: 24px; + align-items: start; + >* { + margin-left: 0; + width: auto; + } + .hero__title { + font-size: 2rem; + } + .hero__subtitle { + margin-top: .5rem; + font-size: 1rem; + span { + font-size: .8rem; + height: 1.2rem; + padding-left: 0px; + padding-right: 4px; + } + } + .hero__cta { + margin-top: 12px; + } + .hero__footer_cta { + margin-top: 12px; } } } } -} +} \ No newline at end of file diff --git a/docs-website/src/pages/_components/Hero/index.js b/docs-website/src/pages/_components/Hero/index.js index 12e41e2ecd1766..2369c4668bfcd9 100644 --- a/docs-website/src/pages/_components/Hero/index.js +++ b/docs-website/src/pages/_components/Hero/index.js @@ -1,53 +1,90 @@ -import React from "react"; +import React, { useEffect } from "react"; import clsx from "clsx"; import Link from "@docusaurus/Link"; import useBaseUrl from "@docusaurus/useBaseUrl"; -import Image from "@theme/IdealImage"; -import { useColorMode } from "@docusaurus/theme-common"; -import { QuestionCircleOutlined } from "@ant-design/icons"; +// import Image from "@theme/IdealImage"; +// import { useColorMode } from "@docusaurus/theme-common"; +// import { QuestionCircleOutlined } from "@ant-design/icons"; import styles from "./hero.module.scss"; -import CodeBlock from "@theme/CodeBlock"; -import TownhallButton from "../TownhallButton"; -import { Section } from "../Section"; +import { animate, motion, useMotionValue, useTransform } from "framer-motion"; +// import CodeBlock from "@theme/CodeBlock"; +// import TownhallButton from "../TownhallButton"; +// import { Section } from "../Section"; -const HeroAnnouncement = ({ message, linkUrl, linkText }) => ( -
- {message} - {linkUrl && ( - - {linkText} - - )} -
-); +// const HeroAnnouncement = ({ message, linkUrl, linkText }) => ( +//
+// {message} +// {linkUrl && ( +// +// {linkText} +// +// )} +//
+// ); -const Hero = ({}) => { - const { colorMode } = useColorMode(); +const SOLUTION_TEXTS = ["AI Governance", "Data Discovery", "AI Collaboration", "Data Governance", "Data Democratization", "Data Observability"]; + +const Hero = ({ onOpenTourModal }) => { + // const { colorMode } = useColorMode(); + const textIndex = useMotionValue(0); + const baseText = useTransform(textIndex, (latest) => SOLUTION_TEXTS[latest] || ""); + const count = useMotionValue(0); + const rounded = useTransform(count, (latest) => Math.round(latest)); + const displayText = useTransform(rounded, (latest) => + baseText.get().slice(0, latest) + ); + const updatedThisRound = useMotionValue(true); + + useEffect(() => { + animate(count, 60, { + type: "tween", + duration: 1.5, + ease: "easeIn", + repeat: Infinity, + repeatType: "reverse", + repeatDelay: 0.1, + onUpdate(latest) { + if (updatedThisRound.get() === true && latest > 0) { + updatedThisRound.set(false); + } else if (updatedThisRound.get() === false && latest === 0) { + textIndex.set((textIndex.get() + 1) % SOLUTION_TEXTS.length); + updatedThisRound.set(true); + } + }, + }); + }, []); return (
- {/* HeroAnnouncement goes here */}
-
-

The #1 Open Source Metadata Platform

-

- DataHub is an extensible data catalog that enables data discovery, data observability and federated governance to help tame the - complexity of your data ecosystem. -

-

- Built with ❤️ by {" "} - - Acryl Data - {" "} - and LinkedIn. -

- - Get Started → +
+
+ The #1 open source
metadata platform. +
+
+ A unified platform for + + {displayText} + +
+
+ + Book a Demo + + + Product Tour + +
+ + Get started with Core → - - Join our Slack - - +
+
+
@@ -55,4 +92,4 @@ const Hero = ({}) => { ); }; -export default Hero; +export default Hero; \ No newline at end of file diff --git a/docs-website/src/pages/_components/QuickstartContent/index.js b/docs-website/src/pages/_components/QuickstartContent/index.js index 8c942a6a2e440b..bb801e5a3c96d4 100644 --- a/docs-website/src/pages/_components/QuickstartContent/index.js +++ b/docs-website/src/pages/_components/QuickstartContent/index.js @@ -1,50 +1,103 @@ -import React from "react"; +import React, { useEffect, useRef, useState } from "react"; import clsx from "clsx"; -import Link from "@docusaurus/Link"; +// import Link from "@docusaurus/Link"; import useBaseUrl from "@docusaurus/useBaseUrl"; -import Image from "@theme/IdealImage"; -import { useColorMode } from "@docusaurus/theme-common"; -import { QuestionCircleOutlined } from "@ant-design/icons"; +// import Image from "@theme/IdealImage"; +// import { useColorMode } from "@docusaurus/theme-common"; +// import { QuestionCircleOutlined } from "@ant-design/icons"; import styles from "./quickstartcontent.module.scss"; -import CodeBlock from "@theme/CodeBlock"; -import TownhallButton from "../TownhallButton"; -import { Section } from "../Section"; - +// import CodeBlock from "@theme/CodeBlock"; +// import TownhallButton from "../TownhallButton"; +// import { Section } from "../Section"; +import quickstartContent from "./quickstartContent"; +import { motion, useScroll, useTransform} from 'framer-motion'; const QuickstartContent = ({}) => { - const { colorMode } = useColorMode(); + const scrollableElement = useRef(null) + const { scrollYProgress } = useScroll({ + target: scrollableElement, + offset: ["start end", "end end"] + }) + const scaleBar = useTransform(scrollYProgress, [0, 0.2, .9, 1], [0, 0, .8, 1]); + const opacityBar = useTransform(scrollYProgress, [0, 0.2, 0.4], [0, 0, 1]); + return ( -
-
-
-

Get Started Now

-

Run the following command to get started with DataHub.

-
- - python3 -m pip install --upgrade pip wheel setuptools
- python3 -m pip install --upgrade acryl-datahub
- datahub docker quickstart -
-
- - DataHub Quickstart Guide - - - Deploying With Kubernetes - -
-
-
- - Learn -
- What is DataHub? - How is DataHub architected? - See DataHub in action -
+
+ +
The only platform you need.
+
+ Unified Discovery, Observability, and Governance for Data and AI.
+
+
+ + {quickstartContent.map((data, idx) => ( + +
+
{data.heading}
+
{data.title}
+
+

+ {/* Learn More → */} +

+
+
+ +
+
+ ))}
+
); }; -export default QuickstartContent; +export default QuickstartContent; \ No newline at end of file diff --git a/docs-website/src/pages/_components/QuickstartContent/quickstartContent.js b/docs-website/src/pages/_components/QuickstartContent/quickstartContent.js new file mode 100644 index 00000000000000..f5afc09871977b --- /dev/null +++ b/docs-website/src/pages/_components/QuickstartContent/quickstartContent.js @@ -0,0 +1,25 @@ +const quickstartData = [ + { + heading: "Discovery", + title: "Make data democratization a reality", + description: + "Enable everyone in your organization to effortlessly discover trustworthy data, with experiences tailored for each persona.Eliminate breaking changes with detailed cross-platform and column-level lineage. Build confidence in your data with a comprehensive view of business, operational, and technical context, all in one place.", + image: "/img/quickstart_discovery.png", + }, + { + heading: "Observability", + title: "Build trust in your data", + description: + "Effortlessly detect data quality issues with automated checks and AI-driven anomaly detection. Notify your team where they work when issues arise and keep stakeholders in the loop with centralized incident tracking. Spend minutes, not days, resolving issues with detailed lineage, documentation, and ownership information all in one place.", + image: "/img/quickstart_observability.png", + }, + { + heading: "Governance", + title: "Minimize compliance risk, effortlessly", + description: + "Ensure every data asset is accounted for and responsibility governed by defining and enforcing documentation standards. Automate your governance program to automatically classify assets as they evolve over time. Minimize redundant, manual work with GenAI documentation, AI-driven classification, smart propagation, and more.", + image: "/img/quickstart_governance.png", + }, + ]; + + export default quickstartData; \ No newline at end of file diff --git a/docs-website/src/pages/_components/QuickstartContent/quickstartcontent.module.scss b/docs-website/src/pages/_components/QuickstartContent/quickstartcontent.module.scss index e1badca6d2e348..a5df90f89ddf3d 100644 --- a/docs-website/src/pages/_components/QuickstartContent/quickstartcontent.module.scss +++ b/docs-website/src/pages/_components/QuickstartContent/quickstartcontent.module.scss @@ -1,67 +1,261 @@ -.container { - margin-bottom: 2rem; +// .container { +// margin-bottom: 2rem; +// } + +// .button { +// text-decoration: none; +// margin: 0.5rem 0 0 0; +// white-space: nowrap; +// @media (min-width: 690px) { +// margin: 0 0 0 0.5rem; +// } +// } + +// .quickstartContent { +// text-align: center; +// padding: 2rem 0; +// height: 100%; +// margin: 2rem 0; +// background: #34394d; +// border-radius: var(--ifm-card-border-radius); +// } + +// .quickstartTitle { +// color: #fafafa; +// } + +// .quickstartSubtitle { +// font-size: 1.1rem; +// color: gray; +// } + +// .quickstartCodeblock { +// text-align: left; +// padding: 0 20vh; +// } + +// .quickLinks { +// display: flex; +// align-items: center; +// justify-content: space-between; +// padding: 1rem; +// font-weight: bold; +// margin-bottom: -2.5vh; +// @media (min-width: 768px) { +// flex-direction: row; +// } + +// > * { +// padding: 0.5rem 1rem; +// display: inline-block; + +// @media (min-width: 768px) { +// padding: 0 1rem; +// } +// } +// } + +// .quickLinksLabel { +// display: flex; +// align-items: center; +// svg { +// width: 24px; +// height: 24px; +// color: var(--ifm-text-color) !important; +// margin-right: 0.5rem; +// } +// } + + +@media only screen and (max-width: 800px) { + .quickstart { + margin: 6rem auto!important; + } } +.quickstart { + width: 80vw; + min-height: 100vh; + margin: 12rem auto; + display: flex; + flex-direction: column; + + :global { + .quickstart__header { + text-align: center; + margin-bottom: 100px; + + .quickstart__title, + .quickstart__subtitle { + line-height: normal; + font-family: Manrope; + } + .quickstart__title { + font-size: 3.5rem; + } -.button { - text-decoration: none; - margin: 0.5rem 0 0 0; - white-space: nowrap; - @media (min-width: 690px) { - margin: 0 0 0 0.5rem; + .quickstart__subtitle { + font-size: 1.8rem; + margin-top: 10px; + } } -} -.quickstartContent { - text-align: center; - padding: 2rem 0; - height: 100%; - margin: 2rem 0; - background: #34394d; - border-radius: var(--ifm-card-border-radius); -} + .quickstart__bar { + width: 10px; + height: 100%; + position: absolute; -.quickstartTitle { - color: #fafafa; -} + background: linear-gradient(180deg, #29B5E8 18.71%, #FFBF4C 143.37%); + border-radius: 10px; + transform-origin: top; + // transition: transform 0.3s; + // animation: progress 0.3s linear; -.quickstartSubtitle { - font-size: 1.1rem; - color: gray; -} + /* Inside auto layout */ + display: block; + } -.quickstartCodeblock { - text-align: left; - padding: 0 20vh; -} + // @keyframes progress { + // 0% { + // height: 0; + // } + // 100% { + // height: 100%; + // } + // } -.quickLinks { - display: flex; - align-items: center; - justify-content: space-between; - padding: 1rem; - font-weight: bold; - margin-bottom: -2.5vh; - @media (min-width: 768px) { - flex-direction: row; - } + .quickstart__container { + position: relative; + } + + .quickstart__content { + display: flex; + margin-bottom: 3rem; + width: 100%; + + .quickstart__text { + width: 60%; + min-width: 600px; + padding-right: 40px; + display: flex; + justify-content: center; + flex-direction: column; + + div { + padding-left: 10%; + } + + .quickstart__text__label { + + /* Label */ + font-family: 'Manrope'; + font-style: normal; + font-weight: 500; + font-size: 1rem; + line-height: 1.2rem; + letter-spacing: 0.4em; + text-transform: uppercase; + + color: #999EB3; + } + + .quickstart__text__head { + + /* H4 | Semibold */ + font-family: 'Manrope'; + font-style: normal; + font-weight: 600; + font-size: 2rem; + line-height: 2rem; + + color: #171B2B; + margin-top: 1rem; + } + + .quickstart__text__desc { + + margin-top: 1rem; + font-family: 'Manrope'; + font-style: normal; + font-weight: 400; + font-size: 1.1rem; + line-height: 1.75rem; + /* Text|Light */ + color: #838BA8; + + p { + margin-bottom: 1rem; + span { + margin-bottom: .75rem; + display: block; + } + } - > * { - padding: 0.5rem 1rem; - display: inline-block; + .learn_more { + color: #1890FF; + font-weight: 500; + } + } + } - @media (min-width: 768px) { - padding: 0 1rem; + .quickstart__img { + display: flex; + align-items: flex-start; + justify-content: center; + min-width: 400px; + width: 40%; + + img { + width: 100%; + } + } } - } -} -.quickLinksLabel { - display: flex; - align-items: center; - svg { - width: 24px; - height: 24px; - color: var(--ifm-text-color) !important; - margin-right: 0.5rem; + + @media only screen and (max-width: 800px) { + .quickstart__bar { + width: 4px; + left: -4px; + } + .quickstart__header { + width: 95%; + margin-bottom: 40px; + + .quickstart__title { + font-size: 2rem; + } + .quickstart__subtitle { + font-size: 1.25rem; + } + } + + .quickstart__content { + flex-direction: column; + + .quickstart__text { + min-width: 0; + width: 100%; + padding-left: 20px; + + div { + padding-left: 0; + } + + .quickstart__text__label { + font-size: .8rem; + } + .quickstart__text__head { + font-size: 1.4rem; + } + .quickstart__text__desc { + font-size: .9rem; + line-height: 1.3rem; + } + } + .quickstart__img { + min-width: 0; + width: 100%; + } + } + } } } diff --git a/docs-website/src/pages/_components/SocialMedia/index.js b/docs-website/src/pages/_components/SocialMedia/index.js new file mode 100644 index 00000000000000..9c5188bca06314 --- /dev/null +++ b/docs-website/src/pages/_components/SocialMedia/index.js @@ -0,0 +1,242 @@ +import React, { useEffect, useRef, useState } from "react"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import Link from "@docusaurus/Link"; +import styles from "./socialmedia.module.scss"; +import "swiper/css"; +import "swiper/css/pagination"; +import { + ArrowUpOutlined, + LinkedinOutlined, + ReadOutlined, + MediumWorkmarkOutlined, + YoutubeOutlined, +} from "@ant-design/icons"; +import { Carousel } from "antd"; + + +const VideoItem = ({ isActive, src }) => { + const ref = useRef(); + + useEffect(() => { + if (isActive) { + ref.current?.play(); + } else { + ref.current?.pause(); + } + }, [isActive]) + + return