mirror of
https://github.com/datahub-project/datahub.git
synced 2025-07-17 14:21:59 +00:00
267 lines
8.5 KiB
TypeScript
267 lines
8.5 KiB
TypeScript
import Component from '@ember/component';
|
|
import { get, set, setProperties, getProperties } from '@ember/object';
|
|
import ComputedProperty from '@ember/object/computed';
|
|
import { inject } from '@ember/service';
|
|
import { task, TaskInstance } from 'ember-concurrency';
|
|
import { action } from 'ember-decorators/object';
|
|
import Notifications, { NotificationEvent } from 'wherehows-web/services/notifications';
|
|
import { IDatasetColumn } from 'wherehows-web/typings/api/datasets/columns';
|
|
import { IComplianceInfo, IComplianceSuggestion } from 'wherehows-web/typings/api/datasets/compliance';
|
|
import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset';
|
|
import { IDatasetSchema } from 'wherehows-web/typings/api/datasets/schema';
|
|
import { IComplianceDataType } from 'wherehows-web/typings/api/list/compliance-datatypes';
|
|
import {
|
|
IReadComplianceResult,
|
|
notFoundApiError,
|
|
readDatasetComplianceByUrn,
|
|
readDatasetComplianceSuggestionByUrn,
|
|
saveDatasetComplianceByUrn
|
|
} from 'wherehows-web/utils/api';
|
|
import { columnDataTypesAndFieldNames } from 'wherehows-web/utils/api/datasets/columns';
|
|
import { readDatasetSchemaByUrn } from 'wherehows-web/utils/api/datasets/schema';
|
|
import { readComplianceDataTypes } from 'wherehows-web/utils/api/list/compliance-datatypes';
|
|
import { compliancePolicyStrings, removeReadonlyAttr, filterEditableEntities } from 'wherehows-web/constants';
|
|
|
|
const { successUpdating, failedUpdating } = compliancePolicyStrings;
|
|
|
|
export default class DatasetComplianceContainer extends Component {
|
|
/**
|
|
* External action on parent
|
|
*/
|
|
setOnChangeSetChange: (hasSuggestions: boolean) => void;
|
|
|
|
/**
|
|
* External action on parent
|
|
*/
|
|
setOnComplianceType: (isNewComplianceInfo: boolean) => void;
|
|
|
|
/**
|
|
* External action on parent
|
|
*/
|
|
setOnChangeSetDrift: (hasDrift: boolean) => void;
|
|
|
|
/**
|
|
* Mapping of field names on the dataset schema to the respective dataType
|
|
* @type {Array<Pick<IDatasetColumn, 'dataType' | 'fieldName'>>}
|
|
*/
|
|
schemaFieldNamesMappedToDataTypes: Array<Pick<IDatasetColumn, 'dataType' | 'fieldName'>> = [];
|
|
|
|
/**
|
|
* List of compliance data-type objects
|
|
* @type {Array<IComplianceDataType>}
|
|
*/
|
|
complianceDataTypes: Array<IComplianceDataType> = [];
|
|
|
|
/**
|
|
* Flag indicating that the compliance information for this dataset is new
|
|
* @type {boolean}
|
|
*/
|
|
isNewComplianceInfo: boolean = false;
|
|
|
|
/**
|
|
* Object containing the suggested values for the compliance form
|
|
* @type {IComplianceSuggestion | void}
|
|
*/
|
|
complianceSuggestion: IComplianceSuggestion | void;
|
|
|
|
/**
|
|
* Reference to the application notifications Service
|
|
* @type {ComputedProperty<Notifications>}
|
|
*/
|
|
notifications: ComputedProperty<Notifications> = inject();
|
|
|
|
/**
|
|
* Object containing the compliance information for the dataset
|
|
* @type {IComplianceInfo | void}
|
|
*/
|
|
complianceInfo: IComplianceInfo | void;
|
|
|
|
/**
|
|
* The platform / db that the dataset is persisted
|
|
* @type {IDatasetView.platform}
|
|
*/
|
|
platform: IDatasetView['platform'];
|
|
|
|
/**
|
|
* Flag indicating if the dataset has a schema representation
|
|
* @type {boolean}
|
|
*/
|
|
schemaless: boolean = false;
|
|
|
|
/**
|
|
* The nativeName of the dataset
|
|
* @type {string}
|
|
*/
|
|
datasetName: string = '';
|
|
|
|
/**
|
|
* The urn identifier for the dataset
|
|
* @type {string}
|
|
*/
|
|
urn: string;
|
|
|
|
didInsertElement() {
|
|
get(this, 'getContainerDataTask').perform();
|
|
}
|
|
|
|
didUpdateAttrs() {
|
|
get(this, 'getContainerDataTask').perform();
|
|
}
|
|
|
|
/**
|
|
* An async parent task to group all data tasks for this container component
|
|
* @type {Task<TaskInstance<Promise<any>>, (a?: any) => TaskInstance<TaskInstance<Promise<any>>>>}
|
|
*/
|
|
getContainerDataTask = task(function*(
|
|
this: DatasetComplianceContainer
|
|
): IterableIterator<TaskInstance<Promise<any>>> {
|
|
const { notify } = get(this, 'notifications');
|
|
|
|
const tasks = Object.values(
|
|
getProperties(this, [
|
|
'getComplianceTask',
|
|
'getComplianceDataTypesTask',
|
|
'getComplianceSuggestionsTask',
|
|
'getDatasetSchemaTask'
|
|
])
|
|
);
|
|
|
|
try {
|
|
yield* tasks.map(task => task.perform());
|
|
} catch (e) {
|
|
notify(NotificationEvent.info, { content: e });
|
|
}
|
|
}).drop();
|
|
|
|
/**
|
|
* Reads the compliance properties for the dataset
|
|
* @type {Task<Promise<IReadComplianceResult>, (a?: any) => TaskInstance<Promise<IReadComplianceResult>>>}
|
|
*/
|
|
getComplianceTask = task(function*(
|
|
this: DatasetComplianceContainer
|
|
): IterableIterator<Promise<IReadComplianceResult>> {
|
|
const { isNewComplianceInfo, complianceInfo } = yield readDatasetComplianceByUrn(get(this, 'urn'));
|
|
|
|
this.onCompliancePolicyStateChange(isNewComplianceInfo);
|
|
setProperties(this, { isNewComplianceInfo, complianceInfo });
|
|
});
|
|
|
|
/**
|
|
* Reads the compliance data types
|
|
* @type {Task<Promise<Array<IComplianceDataType>>, (a?: any) => TaskInstance<Promise<Array<IComplianceDataType>>>>}
|
|
*/
|
|
getComplianceDataTypesTask = task(function*(
|
|
this: DatasetComplianceContainer
|
|
): IterableIterator<Promise<Array<IComplianceDataType>>> {
|
|
const complianceDataTypes = yield readComplianceDataTypes();
|
|
|
|
set(this, 'complianceDataTypes', complianceDataTypes);
|
|
});
|
|
|
|
/**
|
|
* Reads the suggestions for the compliance properties on the dataset
|
|
* @type {Task<Promise<IComplianceSuggestion>, (a?: any) => TaskInstance<Promise<IComplianceSuggestion>>>}
|
|
*/
|
|
getComplianceSuggestionsTask = task(function*(
|
|
this: DatasetComplianceContainer
|
|
): IterableIterator<Promise<IComplianceSuggestion>> {
|
|
const complianceSuggestion = yield readDatasetComplianceSuggestionByUrn(get(this, 'urn'));
|
|
|
|
set(this, 'complianceSuggestion', complianceSuggestion);
|
|
});
|
|
|
|
/**
|
|
* Reads the schema properties for the dataset
|
|
* @type {Task<Promise<IDatasetSchema>, (a?: any) => TaskInstance<Promise<IDatasetSchema>>>}
|
|
*/
|
|
getDatasetSchemaTask = task(function*(this: DatasetComplianceContainer): IterableIterator<Promise<IDatasetSchema>> {
|
|
try {
|
|
const { columns, schemaless } = yield readDatasetSchemaByUrn(get(this, 'urn'));
|
|
const schemaFieldNamesMappedToDataTypes = columnDataTypesAndFieldNames(columns);
|
|
setProperties(this, { schemaFieldNamesMappedToDataTypes, schemaless });
|
|
} catch (e) {
|
|
// If this schema is missing, silence exception, otherwise propagate
|
|
if (!notFoundApiError(e)) {
|
|
throw e;
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Handles user notifications when save succeeds or fails
|
|
* @template T the return type for the save request
|
|
* @param {Promise<T>} request async policy save request
|
|
* @returns {Promise<T>}
|
|
* @memberof DatasetComplianceContainer
|
|
*/
|
|
async notifyOnSave<T>(this: DatasetComplianceContainer, request: Promise<T>): Promise<T> {
|
|
const { notify } = get(this, 'notifications');
|
|
|
|
try {
|
|
await request;
|
|
notify(NotificationEvent.success, { content: successUpdating });
|
|
} catch (e) {
|
|
notify(NotificationEvent.error, { content: failedUpdating });
|
|
}
|
|
|
|
return request;
|
|
}
|
|
|
|
/**
|
|
* Persists the updates to the compliance policy on the remote host
|
|
* @return {Promise<void>}
|
|
*/
|
|
@action
|
|
async savePrivacyCompliancePolicy(this: DatasetComplianceContainer): Promise<void> {
|
|
const complianceInfo = get(this, 'complianceInfo');
|
|
if (complianceInfo) {
|
|
const { complianceEntities } = complianceInfo;
|
|
|
|
await this.notifyOnSave<void>(
|
|
saveDatasetComplianceByUrn(get(this, 'urn'), {
|
|
...complianceInfo,
|
|
// filter out readonly entities, then fleece readonly attribute from remaining entities before save
|
|
complianceEntities: removeReadonlyAttr(filterEditableEntities(complianceEntities))
|
|
})
|
|
);
|
|
|
|
this.resetPrivacyCompliancePolicy.call(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets the compliance information for the dataset with the previously persisted properties
|
|
*/
|
|
@action
|
|
resetPrivacyCompliancePolicy() {
|
|
get(this, 'getComplianceTask').perform();
|
|
}
|
|
|
|
/**
|
|
* Invokes external action if field suggestions change
|
|
* @param {boolean} hasSuggestions
|
|
*/
|
|
@action
|
|
onSuggestionsChanged(hasSuggestions: boolean) {
|
|
this.setOnChangeSetChange(hasSuggestions);
|
|
}
|
|
|
|
/**
|
|
* Invokes external action if compliance info is new or otherwise
|
|
* @param {boolean} isNewComplianceInfo
|
|
*/
|
|
@action
|
|
onCompliancePolicyStateChange(isNewComplianceInfo: boolean) {
|
|
this.setOnComplianceType(isNewComplianceInfo);
|
|
}
|
|
|
|
/**
|
|
* Invokes external action on compliance policy fields drift
|
|
* @param {boolean} hasDrift
|
|
*/
|
|
@action
|
|
onCompliancePolicyChangeSetDrift(hasDrift: boolean) {
|
|
this.setOnChangeSetDrift(hasDrift);
|
|
}
|
|
}
|