import Component from '@ember/component'; import { task, TaskInstance } from 'ember-concurrency'; import { get, set, computed, setProperties, getProperties } from '@ember/object'; import ComputedProperty from '@ember/object/computed'; import { inject } from '@ember/service'; import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset'; import { assert } from '@ember/debug'; import { readUpstreamDatasetsByUrn } from 'wherehows-web/utils/api/datasets/lineage'; import { IUpstreamWithComplianceMetadata } from 'wherehows-web/typings/app/datasets/lineage'; import { datasetsWithComplianceMetadata } from 'wherehows-web/constants/datasets/lineage'; import { arraySome } from 'wherehows-web/utils/array'; import { IDatasetRetention, IGetDatasetRetentionResponse } from 'wherehows-web/typings/api/datasets/retention'; import { readDatasetRetentionByUrn, saveDatasetRetentionByUrn } from 'wherehows-web/utils/api/datasets/retention'; import { readPlatforms } from 'wherehows-web/utils/api/list/platforms'; import { getSupportedPurgePolicies, PurgePolicy } from 'wherehows-web/constants'; import { IDataPlatform } from 'wherehows-web/typings/api/list/platforms'; import { action } from '@ember-decorators/object'; import { retentionObjectFactory } from 'wherehows-web/constants/datasets/retention'; import Notifications, { NotificationEvent } from 'wherehows-web/services/notifications'; /** * Aliases the yieldable values for the container task * @alias {IterableIterator> | Promise> | TaskInstance> | TaskInstance>>} */ type ContainerYieldableResult = IterableIterator< | TaskInstance> | Promise> | TaskInstance> | TaskInstance> >; export default class UpstreamDatasetContainer extends Component { /** * References the application notifications service * @memberof UpstreamDatasetContainer * @type {ComputedProperty} */ notifications = >inject(); /** * urn for the child dataset * @type {string} * @memberof UpstreamDatasetContainer */ urn: string; /** * The plaform this dataset is stored on * @type {IDatasetView.platform} * @memberof UpstreamDatasetContainer */ platform: IDatasetView['platform']; /** * The list of supported purge policies for the related platform * @type {Array} * @memberof UpstreamDatasetContainer */ supportedPurgePolicies: Array = []; /** * The list of upstream datasets for the related urn * @type {Array} */ upstreamDatasets: Array = []; /** * List of metadata properties for upstream datasets * @type {Array} * @memberof UpstreamDatasetContainer */ upstreamsMetadata: Array = []; /** * Retention policy for the dataset with set urn * @type {IDatasetRetention} * @memberof UpstreamDatasetContainer */ retention: IDatasetRetention; constructor() { super(...arguments); assert(`A valid child urn must be provided on instantiation, got ${this.urn}`, !!this.urn); assert(`A valid dataset platform must be provided on instantiation, got ${this.platform}`, !!this.platform); this.retention = retentionObjectFactory(this.urn); } didUpdateAttrs() { this._super(...arguments); get(this, 'getContainerDataTask').perform(); } didInsertElement() { this._super(...arguments); get(this, 'getContainerDataTask').perform(); } /** * Flags if any of the upstream datasets has an incomplete compliance policy * @type ComputedProperty * @memberof UpstreamDatasetContainer */ hasIncompleteUpstream = computed('upstreamsMetadata.[]', function(this: UpstreamDatasetContainer): boolean { const upstreamsMetadata = get(this, 'upstreamsMetadata'); const upstreamIsIncomplete = ({ hasCompliance }: IUpstreamWithComplianceMetadata): boolean => !hasCompliance; return arraySome(upstreamIsIncomplete)(upstreamsMetadata); }); /** * Performs tasks related to container data instantiation * @type {Task} * @memberof UpstreamDatasetContainer */ getContainerDataTask = task(function*(this: UpstreamDatasetContainer): ContainerYieldableResult { yield get(this, 'getUpstreamMetadataTask').perform(); yield get(this, 'getPlatformPoliciesTask').perform(); yield get(this, 'getRetentionTask').perform(); }); /** * Task to get properties for the upstream dataset * @type {Task>>, (a?: {} | undefined) => TaskInstance>>>} * @memberof UpstreamDatasetContainer */ getUpstreamDatasetsTask = task(function*( this: UpstreamDatasetContainer ): IterableIterator>> { const upstreamDatasets: Array = yield readUpstreamDatasetsByUrn(get(this, 'urn')); return set(this, 'upstreamDatasets', upstreamDatasets); }); /** * Task to get and set upstream metadata for upstream datasets * @type {Task>> | Promise>>} * @memberof UpstreamDatasetContainer */ getUpstreamMetadataTask = task(function*( this: UpstreamDatasetContainer ): IterableIterator>> | Promise>> { const upstreamDatasets: Array = yield get(this, 'getUpstreamDatasetsTask').perform(); const upstreamMetadataPromises = datasetsWithComplianceMetadata(upstreamDatasets); const upstreamsMetadata: Array = yield Promise.all(upstreamMetadataPromises); set(this, 'upstreamsMetadata', upstreamsMetadata); }).restartable(); /** * Task to retrieve platform policies and set supported policies for the current platform * @type {Task>, () => TaskInstance>>>} * @memberof UpstreamDatasetContainer */ getPlatformPoliciesTask = task(function*( this: UpstreamDatasetContainer ): IterableIterator>> { const platform = get(this, 'platform'); if (platform) { set(this, 'supportedPurgePolicies', getSupportedPurgePolicies(platform, yield readPlatforms())); } }).restartable(); /** * Task to get the retention policy for the related child dataset * @type {Task, () => TaskInstance>>} * @memberof UpstreamDatasetContainer */ getRetentionTask = task(function*( this: UpstreamDatasetContainer ): IterableIterator> { const retentionResponse: IGetDatasetRetentionResponse | null = yield readDatasetRetentionByUrn(get(this, 'urn')); const retention = retentionResponse !== null ? retentionResponse.retentionPolicy : retentionObjectFactory(get(this, 'urn')); setProperties(get(this, 'retention'), retention); }).restartable(); /** * Task to update the dataset's retention policy with the user entered changes * @type {Task, () => TaskInstance>>} * @memberof UpstreamDatasetContainer */ saveRetentionTask = task(function*(this: UpstreamDatasetContainer): IterableIterator> { const { retention, notifications: { notify } } = getProperties(this, ['retention', 'notifications']); setProperties(retention, yield saveDatasetRetentionByUrn(get(this, 'urn'), retention)); notify(NotificationEvent.success, { content: 'Successfully updated retention policy for dataset' }); }).drop(); /** * Handles user action to change the dataset retention policy purgeType * @param {PurgePolicy} purgePolicy * @memberof UpstreamDatasetContainer */ @action onRetentionPolicyChange(purgePolicy: PurgePolicy) { set(get(this, 'retention'), 'purgeType', purgePolicy); } }