mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-09 16:03:31 +00:00
feat(ui): Changes to allow editable dataset name (#10608)
Co-authored-by: Jay Kadambi <jayasimhan_venkatadri@optum.com>
This commit is contained in:
parent
aa07e2a937
commit
3a38415d6b
@ -21,5 +21,6 @@ public class FeatureFlags {
|
|||||||
private boolean schemaFieldEntityFetchEnabled = false;
|
private boolean schemaFieldEntityFetchEnabled = false;
|
||||||
private boolean businessAttributeEntityEnabled = false;
|
private boolean businessAttributeEntityEnabled = false;
|
||||||
private boolean dataContractsEnabled = false;
|
private boolean dataContractsEnabled = false;
|
||||||
|
private boolean editableDatasetNameEnabled = false;
|
||||||
private boolean showSeparateSiblings = false;
|
private boolean showSeparateSiblings = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -186,6 +186,7 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
|
|||||||
.setNestedDomainsEnabled(_featureFlags.isNestedDomainsEnabled())
|
.setNestedDomainsEnabled(_featureFlags.isNestedDomainsEnabled())
|
||||||
.setPlatformBrowseV2(_featureFlags.isPlatformBrowseV2())
|
.setPlatformBrowseV2(_featureFlags.isPlatformBrowseV2())
|
||||||
.setDataContractsEnabled(_featureFlags.isDataContractsEnabled())
|
.setDataContractsEnabled(_featureFlags.isDataContractsEnabled())
|
||||||
|
.setEditableDatasetNameEnabled(_featureFlags.isEditableDatasetNameEnabled())
|
||||||
.setShowSeparateSiblings(_featureFlags.isShowSeparateSiblings())
|
.setShowSeparateSiblings(_featureFlags.isShowSeparateSiblings())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@ -4,9 +4,11 @@ import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.bindArgument;
|
|||||||
import static com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils.persistAspect;
|
import static com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils.persistAspect;
|
||||||
|
|
||||||
import com.linkedin.businessattribute.BusinessAttributeInfo;
|
import com.linkedin.businessattribute.BusinessAttributeInfo;
|
||||||
|
import com.linkedin.common.AuditStamp;
|
||||||
import com.linkedin.common.urn.CorpuserUrn;
|
import com.linkedin.common.urn.CorpuserUrn;
|
||||||
import com.linkedin.common.urn.Urn;
|
import com.linkedin.common.urn.Urn;
|
||||||
import com.linkedin.common.urn.UrnUtils;
|
import com.linkedin.common.urn.UrnUtils;
|
||||||
|
import com.linkedin.data.template.SetMode;
|
||||||
import com.linkedin.datahub.graphql.QueryContext;
|
import com.linkedin.datahub.graphql.QueryContext;
|
||||||
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
|
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
|
||||||
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
|
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
|
||||||
@ -20,6 +22,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.util.BusinessAttributeUtils
|
|||||||
import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils;
|
import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils;
|
||||||
import com.linkedin.datahub.graphql.resolvers.mutate.util.GlossaryUtils;
|
import com.linkedin.datahub.graphql.resolvers.mutate.util.GlossaryUtils;
|
||||||
import com.linkedin.dataproduct.DataProductProperties;
|
import com.linkedin.dataproduct.DataProductProperties;
|
||||||
|
import com.linkedin.dataset.EditableDatasetProperties;
|
||||||
import com.linkedin.domain.DomainProperties;
|
import com.linkedin.domain.DomainProperties;
|
||||||
import com.linkedin.domain.Domains;
|
import com.linkedin.domain.Domains;
|
||||||
import com.linkedin.entity.client.EntityClient;
|
import com.linkedin.entity.client.EntityClient;
|
||||||
@ -70,6 +73,8 @@ public class UpdateNameResolver implements DataFetcher<CompletableFuture<Boolean
|
|||||||
return updateDataProductName(targetUrn, input, context);
|
return updateDataProductName(targetUrn, input, context);
|
||||||
case Constants.BUSINESS_ATTRIBUTE_ENTITY_NAME:
|
case Constants.BUSINESS_ATTRIBUTE_ENTITY_NAME:
|
||||||
return updateBusinessAttributeName(targetUrn, input, environment.getContext());
|
return updateBusinessAttributeName(targetUrn, input, environment.getContext());
|
||||||
|
case Constants.DATASET_ENTITY_NAME:
|
||||||
|
return updateDatasetName(targetUrn, input, environment.getContext());
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
String.format(
|
String.format(
|
||||||
@ -236,6 +241,37 @@ public class UpdateNameResolver implements DataFetcher<CompletableFuture<Boolean
|
|||||||
"Unauthorized to perform this action. Please contact your DataHub administrator.");
|
"Unauthorized to perform this action. Please contact your DataHub administrator.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// udpates editable dataset properties aspect's name field
|
||||||
|
private Boolean updateDatasetName(Urn targetUrn, UpdateNameInput input, QueryContext context) {
|
||||||
|
if (AuthorizationUtils.canEditProperties(targetUrn, context)) {
|
||||||
|
try {
|
||||||
|
if (input.getName() != null) {
|
||||||
|
final EditableDatasetProperties editableDatasetProperties =
|
||||||
|
new EditableDatasetProperties();
|
||||||
|
editableDatasetProperties.setName(input.getName());
|
||||||
|
final AuditStamp auditStamp = new AuditStamp();
|
||||||
|
Urn actor = UrnUtils.getUrn(context.getActorUrn());
|
||||||
|
auditStamp.setActor(actor, SetMode.IGNORE_NULL);
|
||||||
|
auditStamp.setTime(System.currentTimeMillis());
|
||||||
|
editableDatasetProperties.setLastModified(auditStamp);
|
||||||
|
persistAspect(
|
||||||
|
context.getOperationContext(),
|
||||||
|
targetUrn,
|
||||||
|
Constants.EDITABLE_DATASET_PROPERTIES_ASPECT_NAME,
|
||||||
|
editableDatasetProperties,
|
||||||
|
actor,
|
||||||
|
_entityService);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
String.format("Failed to perform update against input %s", input), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new AuthorizationException(
|
||||||
|
"Unauthorized to perform this action. Please contact your DataHub administrator.");
|
||||||
|
}
|
||||||
|
|
||||||
private Boolean updateDataProductName(
|
private Boolean updateDataProductName(
|
||||||
Urn targetUrn, UpdateNameInput input, QueryContext context) {
|
Urn targetUrn, UpdateNameInput input, QueryContext context) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -222,6 +222,7 @@ public class DatasetMapper implements ModelMapper<EntityResponse, Dataset> {
|
|||||||
properties.setQualifiedName(gmsProperties.getQualifiedName());
|
properties.setQualifiedName(gmsProperties.getQualifiedName());
|
||||||
dataset.setProperties(properties);
|
dataset.setProperties(properties);
|
||||||
dataset.setDescription(properties.getDescription());
|
dataset.setDescription(properties.getDescription());
|
||||||
|
dataset.setName(properties.getName());
|
||||||
if (gmsProperties.getUri() != null) {
|
if (gmsProperties.getUri() != null) {
|
||||||
dataset.setUri(gmsProperties.getUri().toString());
|
dataset.setUri(gmsProperties.getUri().toString());
|
||||||
}
|
}
|
||||||
@ -248,6 +249,9 @@ public class DatasetMapper implements ModelMapper<EntityResponse, Dataset> {
|
|||||||
new EditableDatasetProperties(dataMap);
|
new EditableDatasetProperties(dataMap);
|
||||||
final DatasetEditableProperties editableProperties = new DatasetEditableProperties();
|
final DatasetEditableProperties editableProperties = new DatasetEditableProperties();
|
||||||
editableProperties.setDescription(editableDatasetProperties.getDescription());
|
editableProperties.setDescription(editableDatasetProperties.getDescription());
|
||||||
|
if (editableDatasetProperties.getName() != null) {
|
||||||
|
editableProperties.setName(editableDatasetProperties.getName());
|
||||||
|
}
|
||||||
dataset.setEditableProperties(editableProperties);
|
dataset.setEditableProperties(editableProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -111,8 +111,13 @@ public class DatasetUpdateInputMapper
|
|||||||
|
|
||||||
if (datasetUpdateInput.getEditableProperties() != null) {
|
if (datasetUpdateInput.getEditableProperties() != null) {
|
||||||
final EditableDatasetProperties editableDatasetProperties = new EditableDatasetProperties();
|
final EditableDatasetProperties editableDatasetProperties = new EditableDatasetProperties();
|
||||||
editableDatasetProperties.setDescription(
|
if (datasetUpdateInput.getEditableProperties().getDescription() != null) {
|
||||||
datasetUpdateInput.getEditableProperties().getDescription());
|
editableDatasetProperties.setDescription(
|
||||||
|
datasetUpdateInput.getEditableProperties().getDescription());
|
||||||
|
}
|
||||||
|
if (datasetUpdateInput.getEditableProperties().getName() != null) {
|
||||||
|
editableDatasetProperties.setName(datasetUpdateInput.getEditableProperties().getName());
|
||||||
|
}
|
||||||
editableDatasetProperties.setLastModified(auditStamp);
|
editableDatasetProperties.setLastModified(auditStamp);
|
||||||
editableDatasetProperties.setCreated(auditStamp);
|
editableDatasetProperties.setCreated(auditStamp);
|
||||||
proposals.add(
|
proposals.add(
|
||||||
|
|||||||
@ -508,6 +508,11 @@ type FeatureFlagsConfig {
|
|||||||
"""
|
"""
|
||||||
dataContractsEnabled: Boolean!
|
dataContractsEnabled: Boolean!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Whether dataset names are editable
|
||||||
|
"""
|
||||||
|
editableDatasetNameEnabled: Boolean!
|
||||||
|
|
||||||
"""
|
"""
|
||||||
If turned on, all siblings will be separated with no way to get to a "combined" sibling view
|
If turned on, all siblings will be separated with no way to get to a "combined" sibling view
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -3482,6 +3482,11 @@ type DatasetEditableProperties {
|
|||||||
Description of the Dataset
|
Description of the Dataset
|
||||||
"""
|
"""
|
||||||
description: String
|
description: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Editable name of the Dataset
|
||||||
|
"""
|
||||||
|
name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -4850,6 +4855,10 @@ input DatasetEditablePropertiesUpdate {
|
|||||||
Writable description aka documentation for a Dataset
|
Writable description aka documentation for a Dataset
|
||||||
"""
|
"""
|
||||||
description: String!
|
description: String!
|
||||||
|
"""
|
||||||
|
Editable name of the Dataset
|
||||||
|
"""
|
||||||
|
name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -220,6 +220,7 @@ export class DatasetEntity implements Entity<Dataset> {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
sidebarSections={this.getSidebarSections()}
|
sidebarSections={this.getSidebarSections()}
|
||||||
|
isNameEditable
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -283,7 +284,7 @@ export class DatasetEntity implements Entity<Dataset> {
|
|||||||
return (
|
return (
|
||||||
<Preview
|
<Preview
|
||||||
urn={data.urn}
|
urn={data.urn}
|
||||||
name={data.properties?.name || data.name}
|
name={data.editableProperties?.name || data.properties?.name || data.name}
|
||||||
origin={data.origin}
|
origin={data.origin}
|
||||||
subtype={data.subTypes?.typeNames?.[0]}
|
subtype={data.subTypes?.typeNames?.[0]}
|
||||||
description={data.editableProperties?.description || data.properties?.description}
|
description={data.editableProperties?.description || data.properties?.description}
|
||||||
@ -311,7 +312,7 @@ export class DatasetEntity implements Entity<Dataset> {
|
|||||||
return (
|
return (
|
||||||
<Preview
|
<Preview
|
||||||
urn={data.urn}
|
urn={data.urn}
|
||||||
name={data.properties?.name || data.name}
|
name={data.editableProperties?.name || data.properties?.name || data.name}
|
||||||
origin={data.origin}
|
origin={data.origin}
|
||||||
description={data.editableProperties?.description || data.properties?.description}
|
description={data.editableProperties?.description || data.properties?.description}
|
||||||
platformName={
|
platformName={
|
||||||
@ -361,7 +362,7 @@ export class DatasetEntity implements Entity<Dataset> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
displayName = (data: Dataset) => {
|
displayName = (data: Dataset) => {
|
||||||
return data?.properties?.name || data.name || data.urn;
|
return data?.editableProperties?.name || data?.properties?.name || data.name || data.urn;
|
||||||
};
|
};
|
||||||
|
|
||||||
platformLogoUrl = (data: Dataset) => {
|
platformLogoUrl = (data: Dataset) => {
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import { capitalizeFirstLetterOnly } from '../../../../../shared/textUtil';
|
|||||||
import { useUserContext } from '../../../../../context/useUserContext';
|
import { useUserContext } from '../../../../../context/useUserContext';
|
||||||
import { useEntityRegistry } from '../../../../../useEntityRegistry';
|
import { useEntityRegistry } from '../../../../../useEntityRegistry';
|
||||||
import EntityHeaderLoadingSection from './EntityHeaderLoadingSection';
|
import EntityHeaderLoadingSection from './EntityHeaderLoadingSection';
|
||||||
|
import { useIsEditableDatasetNameEnabled } from '../../../../../useAppConfig';
|
||||||
|
|
||||||
const TitleWrapper = styled.div`
|
const TitleWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -71,6 +72,8 @@ export function getCanEditName(
|
|||||||
return true; // TODO: add permissions for data products
|
return true; // TODO: add permissions for data products
|
||||||
case EntityType.BusinessAttribute:
|
case EntityType.BusinessAttribute:
|
||||||
return privileges?.manageBusinessAttributes;
|
return privileges?.manageBusinessAttributes;
|
||||||
|
case EntityType.Dataset:
|
||||||
|
return entityData?.privileges?.canEditProperties;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -94,8 +97,11 @@ export const EntityHeader = ({ headerDropdownItems, headerActionItems, isNameEdi
|
|||||||
const entityName = entityData?.name;
|
const entityName = entityData?.name;
|
||||||
const subType = capitalizeFirstLetterOnly(entityData?.subTypes?.typeNames?.[0]) || undefined;
|
const subType = capitalizeFirstLetterOnly(entityData?.subTypes?.typeNames?.[0]) || undefined;
|
||||||
|
|
||||||
|
const isEditableDatasetNameEnabled = useIsEditableDatasetNameEnabled();
|
||||||
const canEditName =
|
const canEditName =
|
||||||
isNameEditable && getCanEditName(entityType, entityData, me?.platformPrivileges as PlatformPrivileges);
|
isEditableDatasetNameEnabled &&
|
||||||
|
isNameEditable &&
|
||||||
|
getCanEditName(entityType, entityData, me?.platformPrivileges as PlatformPrivileges);
|
||||||
const entityRegistry = useEntityRegistry();
|
const entityRegistry = useEntityRegistry();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -106,7 +112,7 @@ export const EntityHeader = ({ headerDropdownItems, headerActionItems, isNameEdi
|
|||||||
<>
|
<>
|
||||||
<PlatformContent />
|
<PlatformContent />
|
||||||
<TitleWrapper>
|
<TitleWrapper>
|
||||||
<EntityName isNameEditable={canEditName} />
|
<EntityName isNameEditable={canEditName || false} />
|
||||||
{entityData?.deprecation?.deprecated && (
|
{entityData?.deprecation?.deprecated && (
|
||||||
<DeprecationPill
|
<DeprecationPill
|
||||||
urn={urn}
|
urn={urn}
|
||||||
|
|||||||
@ -28,6 +28,11 @@ export function useIsAppConfigContextLoaded() {
|
|||||||
return appConfig.loaded;
|
return appConfig.loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useIsEditableDatasetNameEnabled() {
|
||||||
|
const appConfig = useAppConfig();
|
||||||
|
return appConfig.config.featureFlags.editableDatasetNameEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
export function useIsShowSeparateSiblingsEnabled() {
|
export function useIsShowSeparateSiblingsEnabled() {
|
||||||
const appConfig = useAppConfig();
|
const appConfig = useAppConfig();
|
||||||
return appConfig.config.featureFlags.showSeparateSiblings;
|
return appConfig.config.featureFlags.showSeparateSiblings;
|
||||||
|
|||||||
@ -54,6 +54,7 @@ export const DEFAULT_APP_CONFIG = {
|
|||||||
platformBrowseV2: false,
|
platformBrowseV2: false,
|
||||||
businessAttributeEntityEnabled: false,
|
businessAttributeEntityEnabled: false,
|
||||||
dataContractsEnabled: false,
|
dataContractsEnabled: false,
|
||||||
|
editableDatasetNameEnabled: false,
|
||||||
showSeparateSiblings: false,
|
showSeparateSiblings: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -69,6 +69,7 @@ query appConfig {
|
|||||||
platformBrowseV2
|
platformBrowseV2
|
||||||
businessAttributeEntityEnabled
|
businessAttributeEntityEnabled
|
||||||
dataContractsEnabled
|
dataContractsEnabled
|
||||||
|
editableDatasetNameEnabled
|
||||||
showSeparateSiblings
|
showSeparateSiblings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ query getBrowseResults($input: BrowseInput!) {
|
|||||||
description
|
description
|
||||||
}
|
}
|
||||||
editableProperties {
|
editableProperties {
|
||||||
|
name
|
||||||
description
|
description
|
||||||
}
|
}
|
||||||
platform {
|
platform {
|
||||||
|
|||||||
@ -251,6 +251,7 @@ fragment nonRecursiveDatasetFields on Dataset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
editableProperties {
|
editableProperties {
|
||||||
|
name
|
||||||
description
|
description
|
||||||
}
|
}
|
||||||
ownership {
|
ownership {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ fragment entityPreview on Entity {
|
|||||||
...platformFields
|
...platformFields
|
||||||
}
|
}
|
||||||
editableProperties {
|
editableProperties {
|
||||||
|
name
|
||||||
description
|
description
|
||||||
}
|
}
|
||||||
platformNativeType
|
platformNativeType
|
||||||
|
|||||||
@ -335,6 +335,7 @@ fragment nonSiblingsDatasetSearchFields on Dataset {
|
|||||||
...dataPlatformInstanceFields
|
...dataPlatformInstanceFields
|
||||||
}
|
}
|
||||||
editableProperties {
|
editableProperties {
|
||||||
|
name
|
||||||
description
|
description
|
||||||
}
|
}
|
||||||
access {
|
access {
|
||||||
|
|||||||
@ -19,4 +19,13 @@ record EditableDatasetProperties includes ChangeAuditStamps {
|
|||||||
"fieldName": "editedDescription",
|
"fieldName": "editedDescription",
|
||||||
}
|
}
|
||||||
description: optional string
|
description: optional string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editable display name of the Dataset
|
||||||
|
*/
|
||||||
|
@Searchable = {
|
||||||
|
"fieldType": "TEXT_PARTIAL",
|
||||||
|
"fieldName": "editedName",
|
||||||
|
}
|
||||||
|
name: optional string
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2328,6 +2328,15 @@
|
|||||||
"fieldName" : "editedDescription",
|
"fieldName" : "editedDescription",
|
||||||
"fieldType" : "TEXT"
|
"fieldType" : "TEXT"
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"type" : "string",
|
||||||
|
"doc" : "Editable display name of the Dataset",
|
||||||
|
"optional" : true,
|
||||||
|
"Searchable" : {
|
||||||
|
"fieldName" : "editedName",
|
||||||
|
"fieldType" : "TEXT_PARTIAL"
|
||||||
|
}
|
||||||
} ],
|
} ],
|
||||||
"Aspect" : {
|
"Aspect" : {
|
||||||
"name" : "editableDatasetProperties"
|
"name" : "editableDatasetProperties"
|
||||||
|
|||||||
@ -2328,6 +2328,15 @@
|
|||||||
"fieldName" : "editedDescription",
|
"fieldName" : "editedDescription",
|
||||||
"fieldType" : "TEXT"
|
"fieldType" : "TEXT"
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"type" : "string",
|
||||||
|
"doc" : "Editable display name of the Dataset",
|
||||||
|
"optional" : true,
|
||||||
|
"Searchable" : {
|
||||||
|
"fieldName" : "editedName",
|
||||||
|
"fieldType" : "TEXT_PARTIAL"
|
||||||
|
}
|
||||||
} ],
|
} ],
|
||||||
"Aspect" : {
|
"Aspect" : {
|
||||||
"name" : "editableDatasetProperties"
|
"name" : "editableDatasetProperties"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user