mirror of
https://github.com/datahub-project/datahub.git
synced 2025-07-29 04:20:00 +00:00
365 lines
11 KiB
TypeScript
365 lines
11 KiB
TypeScript
import Component from '@ember/component';
|
|
import { computed, action } from '@ember/object';
|
|
import { or } from '@ember/object/computed';
|
|
import { get } from '@ember/object';
|
|
import { set } from '@ember/object';
|
|
import { setProperties } from '@ember/object';
|
|
import { next } from '@ember/runloop';
|
|
import { getConfig } from 'wherehows-web/services/configurator';
|
|
import { IAppConfig } from '@datahub/shared/types/configurator/configurator';
|
|
import { inject as service } from '@ember/service';
|
|
import RouterService from '@ember/routing/router-service';
|
|
import { classNames } from '@ember-decorators/component';
|
|
import { Tab, TabProperties } from '@datahub/data-models/constants/entity/shared/tabs';
|
|
import { DatasetPlatform } from '@datahub/metadata-types/constants/entity/dataset/platform';
|
|
import { DatasetEntity, createDatasetEntity } from '@datahub/data-models/entity/dataset/dataset-entity';
|
|
import { ISearchEntityRenderProps } from '@datahub/data-models/types/entity/rendering/search-entity-render-prop';
|
|
import { encodeUrn } from '@datahub/utils/validators/urn';
|
|
import { containerDataSource } from '@datahub/utils/api/data-source';
|
|
import { task } from 'ember-concurrency';
|
|
import { ETaskPromise } from '@datahub/utils/types/concurrency';
|
|
import { IDatasetEntity } from '@datahub/metadata-types/types/entity/dataset/dataset-entity';
|
|
|
|
/**
|
|
* This file is a replacement of the DatasetController. Still there is too much
|
|
* going on here. It would be nice in the future to extract some parts out.
|
|
*/
|
|
@classNames('dataset-main')
|
|
@containerDataSource('containerDataTask', ['dataset'])
|
|
export default class DatasetMainContainer extends Component {
|
|
/**
|
|
* Inject the router as there are some transitions that we need to do
|
|
* @type {Route}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
@service
|
|
router: RouterService;
|
|
|
|
/**
|
|
* References the dataset
|
|
* @type {IDatasetView}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
dataset: IDatasetEntity;
|
|
|
|
/**
|
|
* Current metricUrn query parameter
|
|
* @type {string}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
metricUrn: string;
|
|
|
|
/**
|
|
* URN for the current dataset view
|
|
* @type {(string | void)}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
urn: string;
|
|
|
|
/**
|
|
* Enum of tab properties
|
|
* @type {Tab}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
tabIds = Tab;
|
|
|
|
/**
|
|
* Enum of tabs components to render each tab content
|
|
* @type {TabProperties}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
tabsComponent = TabProperties;
|
|
|
|
/**
|
|
* The currently selected tab in view
|
|
* @type {Tabs}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
tabSelected: Tab;
|
|
|
|
/**
|
|
* Flag indicating if the compliance info does not have user entered information
|
|
* @type {boolean}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
isNewComplianceInfo: boolean;
|
|
|
|
/**
|
|
* Flag indicating there are fields in the compliance policy that have not been updated by a user
|
|
* @type {boolean}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
compliancePolicyHasDrift: boolean;
|
|
|
|
/**
|
|
* References the collection of help links with references to external pages of help information
|
|
* @type {IAppConfig.wikiLinks}
|
|
*/
|
|
wikiLinks: IAppConfig['wikiLinks'] = getConfig('wikiLinks') || {};
|
|
|
|
/**
|
|
* References a collection of properties for avatar properties
|
|
* @type {IAppConfig.avatarEntityProps}
|
|
*/
|
|
avatarEntityProps: IAppConfig['userEntityProps'] = getConfig('userEntityProps');
|
|
|
|
/**
|
|
* Flag indicating the dataset policy is derived from an upstream source
|
|
* @type {boolean}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
isPolicyFromUpstream = false;
|
|
|
|
/**
|
|
* Flag indicating if the viewer is internal
|
|
* @type {boolean}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
isInternal: boolean = Boolean(getConfig('isInternal'));
|
|
|
|
/**
|
|
* Flag indicating whether or not we are in the staging environment, which is useful for determining whether
|
|
* or not to display some features in testing
|
|
* @type {boolean}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
isStaging: boolean = getConfig('isStagingBanner') || false;
|
|
|
|
/**
|
|
* Flags the lineage feature for datasets
|
|
* @type {boolean}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
shouldShowDatasetLineage: boolean = getConfig('shouldShowDatasetLineage');
|
|
|
|
/**
|
|
* Flags the institutional memory feature for entities, in this case datasets
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
shouldShowInstitutionalMemory: boolean = getConfig('showInstitutionalMemory');
|
|
|
|
/**
|
|
* Whether or not we have met the dataset ownership count requirements
|
|
* @type {boolean}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
datasetOwnersRequiredNotMet: boolean;
|
|
|
|
/**
|
|
* Flag indicating that the dataset ownership requires user attention
|
|
* @type {ComputedProperty<boolean>}
|
|
*/
|
|
@or('datasetOwnersRequiredNotMet')
|
|
ownershipRequiresUserAction: boolean;
|
|
|
|
/**
|
|
* Flag indicating that the compliance policy needs user attention
|
|
* @type {ComputedProperty<boolean>}
|
|
*/
|
|
|
|
@or('isNewComplianceInfo', 'compliancePolicyHasDrift')
|
|
requiresUserAction: boolean;
|
|
|
|
/**
|
|
* Flag to say if this dataset is a pinot dataset
|
|
* @type {boolean}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
isPinot: boolean;
|
|
|
|
/**
|
|
* Stores the entity definition for a dataset to be passed into the template
|
|
*/
|
|
fields: Array<ISearchEntityRenderProps> = DatasetEntity.renderProps.search.attributes;
|
|
|
|
/**
|
|
* This value will only be read by non-UMP dataset header, and powers whether
|
|
* the tag will show that we have PII in the dataset or not
|
|
*/
|
|
datasetContainsPersonalData: boolean;
|
|
|
|
/**
|
|
* Reference to the DatasetEntity
|
|
* @type {DatasetEntity}
|
|
*/
|
|
entity?: DatasetEntity;
|
|
|
|
/**
|
|
* List of tasks to perform on instantiation of this container
|
|
*/
|
|
@(task(function*(this: DatasetMainContainer): IterableIterator<Promise<DatasetEntity | boolean>> {
|
|
yield this.reifyEntityTask.perform();
|
|
}).restartable())
|
|
containerDataTask!: ETaskPromise<DatasetEntity | boolean>;
|
|
|
|
/**
|
|
* Materializes the DatasetEntity instance
|
|
*/
|
|
@(task(function*(this: DatasetMainContainer): IterableIterator<Promise<DatasetEntity>> {
|
|
// TODO should fetch the dataset itself, but right now dataset is fetched at route level
|
|
const { dataset } = this;
|
|
|
|
if (dataset) {
|
|
const entity: DatasetEntity = yield createDatasetEntity(this.dataset.uri, this.dataset);
|
|
|
|
set(this, 'entity', entity);
|
|
}
|
|
}).restartable())
|
|
reifyEntityTask!: ETaskPromise<DatasetEntity>;
|
|
|
|
/**
|
|
* This will return the paths for an entity. We should be able to consume entity.readPath
|
|
* direcly but since datasets are not migrated we need to flag guard it.
|
|
*
|
|
* TODO META-8863 Interim implementation to read categories for datasets
|
|
*/
|
|
@computed('entity')
|
|
get paths(): Promise<Array<string>> {
|
|
const { entity } = this;
|
|
if (!entity) {
|
|
return Promise.resolve([]);
|
|
}
|
|
|
|
return entity.readPath;
|
|
}
|
|
|
|
/**
|
|
* Converts the uri on a model to a usable URN format
|
|
* @type {ComputedProperty<string>}
|
|
*/
|
|
@computed('dataset.uri')
|
|
get encodedUrn(): string {
|
|
const { uri } = this.dataset || { uri: '' };
|
|
return encodeUrn(uri);
|
|
}
|
|
|
|
/**
|
|
* Array of tabs that are available for this entity
|
|
* @type {Array<Tab>}
|
|
*/
|
|
@computed('shouldShowDatasetLineage', 'isPinot', 'dataset.platform')
|
|
get datasetTabs(): Array<Tab> {
|
|
const { isPinot, shouldShowDatasetLineage, dataset } = this;
|
|
if (!dataset) {
|
|
return [];
|
|
}
|
|
const tabs: Array<Tab> = [];
|
|
|
|
tabs.push(Tab.Schema);
|
|
if (!isPinot) {
|
|
tabs.push(Tab.Properties);
|
|
}
|
|
tabs.push(Tab.Ownership);
|
|
|
|
if (shouldShowDatasetLineage) {
|
|
tabs.push(Tab.Relationships);
|
|
}
|
|
|
|
tabs.push(Tab.Wiki);
|
|
|
|
return tabs;
|
|
}
|
|
|
|
/**
|
|
* Map to say which tab we should highlight with a notification badge
|
|
* @type {{ [key in Tabs]?: boolean }}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
@computed('requiresUserAction', 'ownershipRequiresUserAction')
|
|
get notificationsMap(): { [key in Tab]?: boolean } {
|
|
// TODO: FIX this comment and remove
|
|
// somehow computed properties does not work well with this.XXX;
|
|
return {
|
|
[Tab.Ownership]: get(this, 'ownershipRequiresUserAction')
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Will return the current component for the header of the entity. Right now
|
|
* we have two headers: regular and ump.
|
|
* @type {string}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
@computed('dataset.platform')
|
|
get headerComponent(): string {
|
|
const { dataset } = this;
|
|
if (!dataset) {
|
|
return '';
|
|
}
|
|
const { platform } = dataset;
|
|
if (platform === DatasetPlatform.UMP) {
|
|
return 'datasets/dataset-ump-header';
|
|
}
|
|
return 'datasets/dataset-header';
|
|
}
|
|
|
|
/**
|
|
* Handles user generated tab selection action by transitioning to specified route
|
|
* @param {Tabs} tabSelected the currently selected tab
|
|
* @returns {void}
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
@action
|
|
tabSelectionChanged(tabSelected: Tab): void {
|
|
// if the tab selection is not same as current, transition
|
|
if (this.tabSelected !== tabSelected) {
|
|
const router = this.router;
|
|
router.transitionTo(router.currentRouteName, this.encodedUrn, tabSelected, {
|
|
queryParams: {
|
|
metric_urn: this.metricUrn // eslint-disable-line @typescript-eslint/camelcase
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the isNewComplianceInfo flag if the policy is not from an upstream dataset, otherwise set to false
|
|
* Also sets the isPolicyFromUpstream attribute
|
|
* @param {({
|
|
* isNewComplianceInfo: boolean;
|
|
* fromUpstream: boolean;
|
|
* })} {
|
|
* isNewComplianceInfo,
|
|
* fromUpstream
|
|
* }
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
@action
|
|
setOnComplianceTypeChange({
|
|
isNewComplianceInfo,
|
|
fromUpstream
|
|
}: {
|
|
isNewComplianceInfo: boolean;
|
|
fromUpstream: boolean;
|
|
}): void {
|
|
setProperties(this, {
|
|
isNewComplianceInfo: !fromUpstream && isNewComplianceInfo,
|
|
isPolicyFromUpstream: fromUpstream
|
|
});
|
|
|
|
if (fromUpstream) {
|
|
this.setOnChangeSetDrift(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Setter to update the drift flag
|
|
* @param {boolean} hasDrift
|
|
* @memberof DatasetMainContainer
|
|
*/
|
|
@action
|
|
setOnChangeSetDrift(hasDrift: boolean): void {
|
|
set(this, 'compliancePolicyHasDrift', !this.isPolicyFromUpstream && hasDrift);
|
|
}
|
|
|
|
/**
|
|
* Triggered when the ownership information changes, will alert the user on the tab with a red dot if
|
|
* the current state of the dataset doesn't match the rules set out for the dataset ownership
|
|
* @param ownersNotConfirmed - Whether or not the owners for the dataset meet the requirements
|
|
*/
|
|
@action
|
|
setOwnershipRuleChange(ownersNotConfirmed: boolean): void {
|
|
next(this, (): boolean => set(this, 'datasetOwnersRequiredNotMet', ownersNotConfirmed));
|
|
}
|
|
}
|