mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-26 17:37:33 +00:00
bulk writes and sidebar hiding
This commit is contained in:
parent
1572dd7208
commit
a7c39761b1
@ -6,6 +6,7 @@ import com.linkedin.datahub.graphql.QueryContext;
|
||||
import com.linkedin.datahub.graphql.featureflags.FeatureFlags;
|
||||
import com.linkedin.datahub.graphql.generated.AnalyticsConfig;
|
||||
import com.linkedin.datahub.graphql.generated.AppConfig;
|
||||
import com.linkedin.datahub.graphql.generated.ApplicationConfig;
|
||||
import com.linkedin.datahub.graphql.generated.AuthConfig;
|
||||
import com.linkedin.datahub.graphql.generated.ChromeExtensionConfig;
|
||||
import com.linkedin.datahub.graphql.generated.EntityProfileConfig;
|
||||
@ -187,6 +188,12 @@ public class AppConfigResolver implements DataFetcher<CompletableFuture<AppConfi
|
||||
}
|
||||
visualConfig.setTheme(themeConfig);
|
||||
}
|
||||
if (_visualConfiguration != null && _visualConfiguration.getApplication() != null) {
|
||||
ApplicationConfig applicationConfig = new ApplicationConfig();
|
||||
applicationConfig.setShowSidebarSectionWhenEmpty(
|
||||
_visualConfiguration.getApplication().isShowSidebarSectionWhenEmpty());
|
||||
visualConfig.setApplication(applicationConfig);
|
||||
}
|
||||
appConfig.setVisualConfig(visualConfig);
|
||||
|
||||
final TelemetryConfig telemetryConfig = new TelemetryConfig();
|
||||
|
||||
@ -357,6 +357,21 @@ type VisualConfig {
|
||||
Configuration for custom theme-ing
|
||||
"""
|
||||
theme: ThemeConfig
|
||||
|
||||
"""
|
||||
Configuration for the application sidebar section
|
||||
"""
|
||||
application: ApplicationConfig
|
||||
}
|
||||
|
||||
"""
|
||||
Configuration for the application sidebar section
|
||||
"""
|
||||
type ApplicationConfig {
|
||||
"""
|
||||
Whether to show the application sidebar section even when empty
|
||||
"""
|
||||
showSidebarSectionWhenEmpty: Boolean
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
@ -24,6 +24,10 @@ export enum EntityActionItem {
|
||||
* Batch add a Data Product to a set of assets
|
||||
*/
|
||||
BATCH_ADD_DATA_PRODUCT,
|
||||
/**
|
||||
* Batch add an Application to a set of assets
|
||||
*/
|
||||
BATCH_ADD_APPLICATION,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
||||
@ -96,6 +96,10 @@ export enum EntityCapabilityType {
|
||||
* Lineage information of an entity
|
||||
*/
|
||||
LINEAGE,
|
||||
/**
|
||||
* Assigning the entity to an application
|
||||
*/
|
||||
APPLICATIONS,
|
||||
}
|
||||
|
||||
export interface EntityMenuActions {
|
||||
|
||||
@ -24,6 +24,7 @@ import { SidebarGlossaryTermsSection } from '@app/entityV2/shared/containers/pro
|
||||
import { SidebarTagsSection } from '@app/entityV2/shared/containers/profile/sidebar/SidebarTagsSection';
|
||||
import StatusSection from '@app/entityV2/shared/containers/profile/sidebar/shared/StatusSection';
|
||||
import { getDataForEntityType } from '@app/entityV2/shared/containers/profile/utils';
|
||||
import { EntityActionItem } from '@app/entityV2/shared/entity/EntityActions';
|
||||
import SidebarNotesSection from '@app/entityV2/shared/sidebarSection/SidebarNotesSection';
|
||||
import SidebarStructuredProperties from '@app/entityV2/shared/sidebarSection/SidebarStructuredProperties';
|
||||
import { DocumentationTab } from '@app/entityV2/shared/tabs/Documentation/DocumentationTab';
|
||||
@ -98,7 +99,7 @@ export class ApplicationEntity implements Entity<Application> {
|
||||
useEntityQuery={useGetApplicationQuery}
|
||||
useUpdateQuery={undefined}
|
||||
getOverrideProperties={this.getOverridePropertiesFromEntity}
|
||||
headerActionItems={new Set([])}
|
||||
headerActionItems={new Set([EntityActionItem.BATCH_ADD_APPLICATION])}
|
||||
headerDropdownItems={headerDropdownItems}
|
||||
isNameEditable
|
||||
tabs={[
|
||||
|
||||
@ -385,6 +385,7 @@ export class ChartEntity implements Entity<Chart> {
|
||||
EntityCapabilityType.TEST,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.HEALTH,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
@ -392,6 +392,7 @@ export class DashboardEntity implements Entity<Dashboard> {
|
||||
EntityCapabilityType.TEST,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.HEALTH,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
@ -257,6 +257,7 @@ export class DataFlowEntity implements Entity<DataFlow> {
|
||||
EntityCapabilityType.TEST,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.HEALTH,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
@ -322,6 +322,7 @@ export class DataJobEntity implements Entity<DataJob> {
|
||||
EntityCapabilityType.TEST,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.HEALTH,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
@ -262,6 +262,7 @@ export class DataProductEntity implements Entity<DataProduct> {
|
||||
EntityCapabilityType.GLOSSARY_TERMS,
|
||||
EntityCapabilityType.TAGS,
|
||||
EntityCapabilityType.DOMAINS,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
@ -515,6 +515,7 @@ export class DatasetEntity implements Entity<Dataset> {
|
||||
EntityCapabilityType.TEST,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.HEALTH,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
@ -197,6 +197,7 @@ class GlossaryNodeEntity implements Entity<GlossaryNode> {
|
||||
EntityCapabilityType.OWNERS,
|
||||
EntityCapabilityType.DEPRECATION,
|
||||
EntityCapabilityType.SOFT_DELETE,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
@ -239,6 +239,7 @@ export class GlossaryTermEntity implements Entity<GlossaryTerm> {
|
||||
EntityCapabilityType.OWNERS,
|
||||
EntityCapabilityType.DEPRECATION,
|
||||
EntityCapabilityType.SOFT_DELETE,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
@ -268,6 +268,7 @@ export class MLFeatureEntity implements Entity<MlFeature> {
|
||||
EntityCapabilityType.SOFT_DELETE,
|
||||
EntityCapabilityType.DATA_PRODUCTS,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
@ -235,6 +235,7 @@ export class MLFeatureTableEntity implements Entity<MlFeatureTable> {
|
||||
EntityCapabilityType.SOFT_DELETE,
|
||||
EntityCapabilityType.DATA_PRODUCTS,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
@ -247,6 +247,7 @@ export class MLModelEntity implements Entity<MlModel> {
|
||||
EntityCapabilityType.SOFT_DELETE,
|
||||
EntityCapabilityType.DATA_PRODUCTS,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
@ -221,6 +221,7 @@ export class MLModelGroupEntity implements Entity<MlModelGroup> {
|
||||
EntityCapabilityType.SOFT_DELETE,
|
||||
EntityCapabilityType.DATA_PRODUCTS,
|
||||
EntityCapabilityType.LINEAGE,
|
||||
EntityCapabilityType.APPLICATIONS,
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import EmptySectionText from '@app/entityV2/shared/containers/profile/sidebar/Em
|
||||
import SectionActionButton from '@app/entityV2/shared/containers/profile/sidebar/SectionActionButton';
|
||||
import { SidebarSection } from '@app/entityV2/shared/containers/profile/sidebar/SidebarSection';
|
||||
import { ApplicationLink } from '@app/shared/tags/ApplicationLink';
|
||||
import { useAppConfig } from '@app/useAppConfig';
|
||||
|
||||
import { useBatchSetApplicationMutation } from '@graphql/application.generated';
|
||||
|
||||
@ -38,6 +39,9 @@ interface Props {
|
||||
}
|
||||
|
||||
export const SidebarApplicationSection = ({ readOnly, properties }: Props) => {
|
||||
const {
|
||||
config: { visualConfig },
|
||||
} = useAppConfig();
|
||||
const updateOnly = properties?.updateOnly;
|
||||
const { entityData } = useEntityData();
|
||||
const refetch = useRefetch();
|
||||
@ -47,6 +51,10 @@ export const SidebarApplicationSection = ({ readOnly, properties }: Props) => {
|
||||
const application = entityData?.application?.application;
|
||||
const canEditApplication = !!entityData?.privileges?.canEditProperties;
|
||||
|
||||
if (!application && !visualConfig.application?.showSidebarSectionWhenEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const removeApplication = () => {
|
||||
batchSetApplicationMutation({
|
||||
variables: {
|
||||
|
||||
@ -11,6 +11,7 @@ import { SearchSelectModal } from '@app/entityV2/shared/components/styled/search
|
||||
import { handleBatchError } from '@app/entityV2/shared/utils';
|
||||
import { useEntityRegistry } from '@app/useEntityRegistry';
|
||||
|
||||
import { useBatchSetApplicationMutation } from '@graphql/application.generated';
|
||||
import { useBatchSetDataProductMutation } from '@graphql/dataProduct.generated';
|
||||
import { useBatchAddTermsMutation, useBatchSetDomainMutation } from '@graphql/mutations.generated';
|
||||
import { EntityType } from '@types';
|
||||
@ -36,6 +37,10 @@ export enum EntityActionItem {
|
||||
* Add a new Glossary Node as child
|
||||
*/
|
||||
ADD_CHILD_GLOSSARY_NODE,
|
||||
/**
|
||||
* Batch add an Application to a set of assets
|
||||
*/
|
||||
BATCH_ADD_APPLICATION,
|
||||
}
|
||||
|
||||
const ButtonWrapper = styled.div`
|
||||
@ -72,9 +77,11 @@ function EntityActions(props: Props) {
|
||||
const [isBatchSetDataProductModalVisible, setIsBatchSetDataProductModalVisible] = useState(false);
|
||||
const [isCreateTermModalVisible, setIsCreateTermModalVisible] = useState(false);
|
||||
const [isCreateNodeModalVisible, setIsCreateNodeModalVisible] = useState(false);
|
||||
const [isBatchSetApplicationModalVisible, setIsBatchSetApplicationModalVisible] = useState(false);
|
||||
const [batchAddTermsMutation] = useBatchAddTermsMutation();
|
||||
const [batchSetDomainMutation] = useBatchSetDomainMutation();
|
||||
const [batchSetDataProductMutation] = useBatchSetDataProductMutation();
|
||||
const [batchSetApplicationMutation] = useBatchSetApplicationMutation();
|
||||
|
||||
// eslint-disable-next-line
|
||||
const batchAddGlossaryTerms = (entityUrns: Array<string>) => {
|
||||
@ -186,6 +193,40 @@ function EntityActions(props: Props) {
|
||||
});
|
||||
};
|
||||
|
||||
const batchSetApplication = (entityUrns: Array<string>) => {
|
||||
batchSetApplicationMutation({
|
||||
variables: {
|
||||
input: {
|
||||
applicationUrn: urn,
|
||||
resourceUrns: entityUrns,
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(({ errors }) => {
|
||||
if (!errors) {
|
||||
setIsBatchSetApplicationModalVisible(false);
|
||||
message.loading({ content: 'Updating...', duration: 3 });
|
||||
setTimeout(() => {
|
||||
message.success({
|
||||
content: `Added assets to Application!`,
|
||||
duration: 3,
|
||||
});
|
||||
refetchForEntity?.();
|
||||
setShouldRefetchEmbeddedListSearch?.(true);
|
||||
}, 3000);
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
message.destroy();
|
||||
message.error(
|
||||
handleBatchError(entityUrns, e, {
|
||||
content: `Failed to add assets to Application. An unknown error occurred.`,
|
||||
duration: 3,
|
||||
}),
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const { entityData } = useEntityData();
|
||||
const canCreateGlossaryEntity = !!entityData?.privileges?.canManageChildren;
|
||||
|
||||
@ -245,6 +286,13 @@ function EntityActions(props: Props) {
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{actionItems.has(EntityActionItem.BATCH_ADD_APPLICATION) && (
|
||||
<Tooltip title="Add Assets to Application" showArrow={false} placement="bottom">
|
||||
<Button variant="outline" onClick={() => setIsBatchSetApplicationModalVisible(true)}>
|
||||
<LinkOutlined /> Add to Assets
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</ButtonWrapper>
|
||||
{isBatchAddGlossaryTermModalVisible && (
|
||||
<SearchSelectModal
|
||||
@ -268,6 +316,17 @@ function EntityActions(props: Props) {
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{isBatchSetApplicationModalVisible && (
|
||||
<SearchSelectModal
|
||||
titleText="Add assets to Application"
|
||||
continueText="Add"
|
||||
onContinue={batchSetApplication}
|
||||
onCancel={() => setIsBatchSetApplicationModalVisible(false)}
|
||||
fixedEntityTypes={Array.from(
|
||||
entityRegistry.getTypesWithSupportedCapabilities(EntityCapabilityType.APPLICATIONS),
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{isBatchSetDataProductModalVisible && (
|
||||
<SearchSelectModal
|
||||
titleText="Add assets to Data Product"
|
||||
|
||||
@ -52,6 +52,9 @@ query appConfig {
|
||||
theme {
|
||||
themeId
|
||||
}
|
||||
application {
|
||||
showSidebarSectionWhenEmpty
|
||||
}
|
||||
}
|
||||
telemetryConfig {
|
||||
enableThirdPartyLogging
|
||||
|
||||
@ -31,4 +31,6 @@ public class VisualConfiguration {
|
||||
|
||||
/** Boolean flag enabled shows the full title of an entity in lineage view by default */
|
||||
public boolean showFullTitleInLineage;
|
||||
|
||||
public ApplicationConfig application;
|
||||
}
|
||||
|
||||
@ -167,6 +167,8 @@ visualConfig:
|
||||
entityProfile:
|
||||
# we only support default tab for domains right now. In order to implement for other entities, update React code
|
||||
domainDefaultTab: ${DOMAIN_DEFAULT_TAB:} # set to DOCUMENTATION_TAB to show documentation tab first
|
||||
application:
|
||||
showSidebarSectionWhenEmpty: ${APPLICATION_SHOW_SIDEBAR_SECTION_WHEN_EMPTY:false}
|
||||
searchResult:
|
||||
enableNameHighlight: ${SEARCH_RESULT_NAME_HIGHLIGHT_ENABLED:true} # Enables visual highlighting on search result names/descriptions.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user