mirror of
https://github.com/datahub-project/datahub.git
synced 2025-09-26 01:23:16 +00:00
implements feature to override the retention policy on a child dataset independent of the upstream policies
This commit is contained in:
parent
30926ecb48
commit
c726f136a1
@ -1,55 +1,205 @@
|
||||
import Component from '@ember/component';
|
||||
import { task } from 'ember-concurrency';
|
||||
import { get, setProperties } from '@ember/object';
|
||||
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 { readDatasetByUrn } from 'wherehows-web/utils/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<TaskInstance<TaskInstance<Promise<IDatasetView[]>> | Promise<IUpstreamWithComplianceMetadata[]>> | TaskInstance<Promise<IDataPlatform[]>> | TaskInstance<Promise<IGetDatasetRetentionResponse | null>>>}
|
||||
*/
|
||||
type ContainerYieldableResult = IterableIterator<
|
||||
| TaskInstance<TaskInstance<Promise<IDatasetView[]>> | Promise<IUpstreamWithComplianceMetadata[]>>
|
||||
| TaskInstance<Promise<IDataPlatform[]>>
|
||||
| TaskInstance<Promise<IGetDatasetRetentionResponse | null>>
|
||||
>;
|
||||
|
||||
export default class UpstreamDatasetContainer extends Component {
|
||||
/**
|
||||
* urn for the parent dataset
|
||||
* References the application notifications service
|
||||
* @memberof UpstreamDatasetContainer
|
||||
* @type {ComputedProperty<Notifications>}
|
||||
*/
|
||||
notifications = <ComputedProperty<Notifications>>inject();
|
||||
|
||||
/**
|
||||
* urn for the child dataset
|
||||
* @type {string}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
upstreamUrn: string;
|
||||
urn: string;
|
||||
|
||||
/**
|
||||
* The name of the upstream dataset
|
||||
* @type {IDatasetView.nativeName}
|
||||
* The plaform this dataset is stored on
|
||||
* @type {IDatasetView.platform}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
nativeName: IDatasetView['nativeName'];
|
||||
platform: IDatasetView['platform'];
|
||||
|
||||
/**
|
||||
* A description of the upstream dataset
|
||||
* @type {IDatasetView.description}
|
||||
* The list of supported purge policies for the related platform
|
||||
* @type {Array<PurgePolicy>}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
description: IDatasetView['description'];
|
||||
supportedPurgePolicies: Array<PurgePolicy> = [];
|
||||
|
||||
/**
|
||||
* The list of upstream datasets for the related urn
|
||||
* @type {Array<IDatasetView>}
|
||||
*/
|
||||
upstreamDatasets: Array<IDatasetView> = [];
|
||||
|
||||
/**
|
||||
* List of metadata properties for upstream datasets
|
||||
* @type {Array<IUpstreamWithComplianceMetadata>}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
upstreamsMetadata: Array<IUpstreamWithComplianceMetadata> = [];
|
||||
|
||||
/**
|
||||
* Retention policy for the dataset with set urn
|
||||
* @type {IDatasetRetention}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
retention: IDatasetRetention;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
assert('A valid upstreamUrn must be provided on instantiation', typeof this.upstreamUrn === 'string');
|
||||
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, 'getUpstreamPropertiesTask').perform();
|
||||
get(this, 'getContainerDataTask').perform();
|
||||
}
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
get(this, 'getUpstreamPropertiesTask').perform();
|
||||
get(this, 'getContainerDataTask').perform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Task to get properties for the upstream dataset
|
||||
* @type {Task<Promise<IDatasetView>>, (a?: {} | undefined) => TaskInstance<Promise<IDatasetView>>>}
|
||||
* Flags if any of the upstream datasets has an incomplete compliance policy
|
||||
* @type ComputedProperty<boolean>
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
getUpstreamPropertiesTask = task(function*(this: UpstreamDatasetContainer): IterableIterator<Promise<IDatasetView>> {
|
||||
const { nativeName, description }: IDatasetView = yield readDatasetByUrn(get(this, 'upstreamUrn'));
|
||||
setProperties(this, { nativeName, description });
|
||||
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<ContainerYieldableResult>}
|
||||
* @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<Promise<Array<IDatasetView>>>, (a?: {} | undefined) => TaskInstance<Promise<Array<IDatasetView>>>>}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
getUpstreamDatasetsTask = task(function*(
|
||||
this: UpstreamDatasetContainer
|
||||
): IterableIterator<Promise<Array<IDatasetView>>> {
|
||||
const upstreamDatasets: Array<IDatasetView> = yield readUpstreamDatasetsByUrn(get(this, 'urn'));
|
||||
return set(this, 'upstreamDatasets', upstreamDatasets);
|
||||
});
|
||||
|
||||
/**
|
||||
* Task to get and set upstream metadata for upstream datasets
|
||||
* @type {Task<TaskInstance<Promise<Array<IDatasetView>>> | Promise<Array<IUpstreamWithComplianceMetadata>>>}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
getUpstreamMetadataTask = task(function*(
|
||||
this: UpstreamDatasetContainer
|
||||
): IterableIterator<TaskInstance<Promise<Array<IDatasetView>>> | Promise<Array<IUpstreamWithComplianceMetadata>>> {
|
||||
const upstreamDatasets: Array<IDatasetView> = yield get(this, 'getUpstreamDatasetsTask').perform();
|
||||
const upstreamMetadataPromises = datasetsWithComplianceMetadata(upstreamDatasets);
|
||||
const upstreamsMetadata: Array<IUpstreamWithComplianceMetadata> = yield Promise.all(upstreamMetadataPromises);
|
||||
|
||||
set(this, 'upstreamsMetadata', upstreamsMetadata);
|
||||
}).restartable();
|
||||
|
||||
/**
|
||||
* Task to retrieve platform policies and set supported policies for the current platform
|
||||
* @type {Task<Promise<Array<IDataPlatform>>, () => TaskInstance<Promise<Array<IDataPlatform>>>>}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
getPlatformPoliciesTask = task(function*(
|
||||
this: UpstreamDatasetContainer
|
||||
): IterableIterator<Promise<Array<IDataPlatform>>> {
|
||||
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<Promise<IGetDatasetRetentionResponse | null>, () => TaskInstance<Promise<IGetDatasetRetentionResponse | null>>>}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
getRetentionTask = task(function*(
|
||||
this: UpstreamDatasetContainer
|
||||
): IterableIterator<Promise<IGetDatasetRetentionResponse | null>> {
|
||||
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<Promise<IDatasetRetention>, () => TaskInstance<Promise<IDatasetRetention>>>}
|
||||
* @memberof UpstreamDatasetContainer
|
||||
*/
|
||||
saveRetentionTask = task(function*(this: UpstreamDatasetContainer): IterableIterator<Promise<IDatasetRetention>> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,25 @@
|
||||
import Component from '@ember/component';
|
||||
import { set } from '@ember/object';
|
||||
import { action } from '@ember-decorators/object';
|
||||
|
||||
export default class UpstreamDataset extends Component {
|
||||
tagName = 'section';
|
||||
|
||||
classNames = ['upstream-dataset-banner'];
|
||||
|
||||
/**
|
||||
* Flag indicating the component is in view only mode and not editable
|
||||
* @type {boolean}
|
||||
* @memberof UpstreamDataset
|
||||
*/
|
||||
isReadOnly: boolean = true;
|
||||
|
||||
/**
|
||||
* Action handler to set component in edit mode
|
||||
* @memberof UpstreamDataset
|
||||
*/
|
||||
@action
|
||||
onEdit() {
|
||||
set(this, 'isReadOnly', false);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import {
|
||||
DatasetPlatform,
|
||||
exemptPolicy,
|
||||
isExempt,
|
||||
missingPolicyText,
|
||||
PurgePolicy,
|
||||
purgePolicyProps
|
||||
} from 'wherehows-web/constants';
|
||||
@ -24,7 +23,7 @@ export default class PurgePolicyComponent extends Component {
|
||||
* Reference to the informational text if the dataset does not have a saved purge policy
|
||||
* @type {string}
|
||||
*/
|
||||
missingPolicyText = missingPolicyText;
|
||||
missingPolicyText: string = '';
|
||||
|
||||
/**
|
||||
* Reference to client options for each purge policy
|
||||
|
@ -82,10 +82,4 @@ const exemptPolicy = PurgePolicy.PurgeExempt;
|
||||
*/
|
||||
const isExempt = (policy: PurgePolicy) => policy === PurgePolicy.PurgeExempt;
|
||||
|
||||
/**
|
||||
* User informational text for datasets without a purge policy
|
||||
* @type {string}
|
||||
*/
|
||||
const missingPolicyText = 'This dataset does not have a current compliance purge policy.';
|
||||
|
||||
export { PurgePolicy, purgePolicyProps, isExempt, exemptPolicy, missingPolicyText, getSupportedPurgePolicies };
|
||||
export { PurgePolicy, purgePolicyProps, isExempt, exemptPolicy, getSupportedPurgePolicies };
|
||||
|
32
wherehows-web/app/constants/datasets/lineage.ts
Normal file
32
wherehows-web/app/constants/datasets/lineage.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset';
|
||||
import { IReadComplianceResult, readDatasetComplianceByUrn } from 'wherehows-web/utils/api/datasets/compliance';
|
||||
import { IUpstreamWithComplianceMetadata } from 'wherehows-web/typings/app/datasets/lineage';
|
||||
import { arrayMap } from 'wherehows-web/utils/array';
|
||||
import { encodeUrn } from 'wherehows-web/utils/validators/urn';
|
||||
|
||||
/**
|
||||
* Maps a dataset urn/uri, other props with a property indicating if the dataset compliance policy exists
|
||||
* @param {(Pick<IDatasetView, 'uri' | 'nativeName'>)} {
|
||||
* uri,
|
||||
* nativeName
|
||||
* }
|
||||
* @returns {Promise<IUpstreamWithComplianceMetadata>}
|
||||
*/
|
||||
const datasetWithComplianceMetadata = async ({
|
||||
uri,
|
||||
nativeName
|
||||
}: Pick<IDatasetView, 'uri' | 'nativeName'>): Promise<IUpstreamWithComplianceMetadata> => {
|
||||
const { isNewComplianceInfo }: IReadComplianceResult = await readDatasetComplianceByUrn(encodeUrn(uri));
|
||||
return { urn: uri, hasCompliance: !isNewComplianceInfo, nativeName };
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a list of datasets and maps into a list of IUpstreamWithComplianceMetadata objects
|
||||
* @param {Array<IDatasetView>} datasets
|
||||
* @returns {Array<Promise<IUpstreamWithComplianceMetadata>>}
|
||||
*/
|
||||
const datasetsWithComplianceMetadata = (
|
||||
datasets: Array<IDatasetView>
|
||||
): Array<Promise<IUpstreamWithComplianceMetadata>> => arrayMap(datasetWithComplianceMetadata)(datasets);
|
||||
|
||||
export { datasetsWithComplianceMetadata };
|
14
wherehows-web/app/constants/datasets/retention.ts
Normal file
14
wherehows-web/app/constants/datasets/retention.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { IDatasetRetention } from 'wherehows-web/typings/api/datasets/retention';
|
||||
|
||||
/**
|
||||
* 'News' a IDatasetRetention instance with the provided dataset urn
|
||||
* @param {string} urn
|
||||
* @returns {IDatasetRetention}
|
||||
*/
|
||||
const retentionObjectFactory = (urn: string): IDatasetRetention => ({
|
||||
datasetUrn: urn,
|
||||
purgeNote: '',
|
||||
purgeType: ''
|
||||
});
|
||||
|
||||
export { retentionObjectFactory };
|
@ -32,3 +32,4 @@
|
||||
@import 'nacho/nacho-breadcrumbs';
|
||||
@import 'nacho/nacho-uploader';
|
||||
@import 'nacho/nacho-container';
|
||||
@import 'nacho/nacho-divider';
|
||||
|
@ -5,7 +5,6 @@
|
||||
&__item {
|
||||
@include nacho-container;
|
||||
list-style-type: none;
|
||||
margin-bottom: item-spacing(4);
|
||||
|
||||
&--disabled {
|
||||
color: set-color(grey, mid);
|
||||
|
@ -86,7 +86,8 @@
|
||||
padding: 9px $item-spacing-2 11px;
|
||||
margin-left: $item-spacing-5;
|
||||
&:first-child {
|
||||
margin-left: $item-spacing-4;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
// The underline will exist on all tabs, but be transparent
|
||||
|
@ -0,0 +1,5 @@
|
||||
.nacho-divider {
|
||||
margin: item-spacing(5 0);
|
||||
border: 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
|
||||
}
|
@ -1,9 +1,4 @@
|
||||
.upstream-dataset-banner {
|
||||
@include nacho-container;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
.upstream-dataset-banner__description {
|
||||
height: item-spacing(7);
|
||||
@ -28,3 +23,51 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upstream-dataset {
|
||||
@include nacho-container;
|
||||
padding: item-spacing(2 5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&__compliance-status {
|
||||
&__complete {
|
||||
color: get-color(green5);
|
||||
}
|
||||
|
||||
&__incomplete {
|
||||
color: get-color(orange5);
|
||||
}
|
||||
}
|
||||
|
||||
&__upstream-link {
|
||||
margin-left: item-spacing(3);
|
||||
}
|
||||
|
||||
&__upstream-link-chevron {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.downstream-purge-policy-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: item-spacing(6 0 5);
|
||||
}
|
||||
|
||||
.downstream-purge-policy {
|
||||
&__no-policy {
|
||||
@include nacho-container;
|
||||
}
|
||||
|
||||
&__edit {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&--label {
|
||||
margin-right: item-spacing(4);
|
||||
font-weight: fw(normal, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,10 +164,23 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if getPlatformPoliciesTask.last.isSuccessful}}
|
||||
<section class="metadata-prompt">
|
||||
<header class="metadata-prompt__header">
|
||||
<p>
|
||||
Compliance Purge Policy
|
||||
|
||||
{{more-info
|
||||
link="http://go/gdpr/deletions/purgePolicies"
|
||||
tooltip="Click for more information Purge Policies"
|
||||
}}
|
||||
</p>
|
||||
</header>
|
||||
</section>
|
||||
|
||||
{{purge-policy
|
||||
isEditable=(not isReadOnly)
|
||||
platform=platform
|
||||
missingPolicyText="This dataset does not have a current compliance purge policy."
|
||||
supportedPurgePolicies=supportedPurgePolicies
|
||||
purgeNote=complianceInfo.compliancePurgeNote
|
||||
purgePolicy=(readonly complianceInfo.complianceType)
|
||||
|
@ -12,7 +12,10 @@
|
||||
|
||||
{{#if complianceInfo.fromUpstream}}
|
||||
|
||||
{{datasets/containers/upstream-dataset upstreamUrn=complianceInfo.datasetUrn}}
|
||||
{{datasets/containers/upstream-dataset
|
||||
urn=urn
|
||||
platform=platform
|
||||
}}
|
||||
|
||||
{{else}}
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
{{#if getUpstreamPropertiesTask.isRunning}}
|
||||
{{#if getUpstreamMetadataTask.isRunning}}
|
||||
|
||||
{{pendulum-ellipsis-animation}}
|
||||
|
||||
{{else}}
|
||||
|
||||
{{datasets/upstream-dataset
|
||||
nativeName=nativeName
|
||||
description=description
|
||||
upstreamUrn=upstreamUrn
|
||||
upstreamsMetadata=upstreamsMetadata
|
||||
platform=platform
|
||||
retention=retention
|
||||
hasIncompleteUpstream=hasIncompleteUpstream
|
||||
supportedPurgePolicies=supportedPurgePolicies
|
||||
saveRetentionTask=saveRetentionTask
|
||||
onChange=(action "onRetentionPolicyChange")
|
||||
}}
|
||||
|
||||
{{/if}}
|
||||
|
@ -1,32 +1,101 @@
|
||||
<section class="upstream-dataset-banner__content">
|
||||
<div class="upstream-dataset-banner__informational">
|
||||
<i class="fa fa-info-circle fa-2x"></i>
|
||||
<h3>Compliance Info</h3>
|
||||
<p>
|
||||
Compliance Policy on this dataset is inherited from it's parent dataset(s). To make modifications on the purge
|
||||
<br>
|
||||
policy on this page, please complete the Compliance Metadata on all of the parent datasets.
|
||||
</p>
|
||||
|
||||
<p class="upstream-dataset-banner__informational__text">
|
||||
Compliance Policy on this dataset is inherited from a parent dataset.
|
||||
<br>
|
||||
To make modifications, please update the Compliance on the parent dataset.
|
||||
<br>
|
||||
</p>
|
||||
</div>
|
||||
<hr class="nacho-divider">
|
||||
|
||||
<h4>Parent Dataset</h4>
|
||||
|
||||
{{#each upstreamsMetadata as |parent|}}
|
||||
<div class="upstream-dataset">
|
||||
<span class="upstream-dataset__compliance-status">
|
||||
{{tooltip-on-element
|
||||
text=(if parent.hasCompliance "Compliance completed for parent dataset" "Please complete the Compliance on this parent dataset")
|
||||
}}
|
||||
|
||||
{{#if parent.hasCompliance}}
|
||||
{{fa-icon "check" class="upstream-dataset__compliance-status__complete"}}
|
||||
{{else}}
|
||||
{{fa-icon "exclamation" class="upstream-dataset__compliance-status__incomplete"}}
|
||||
{{/if}}
|
||||
</span>
|
||||
|
||||
{{#link-to
|
||||
"datasets.dataset"
|
||||
"urn"
|
||||
(query-params urn=parent.urn)
|
||||
class="upstream-dataset__upstream-link"
|
||||
}}
|
||||
<strong>{{parent.nativeName}}</strong>
|
||||
{{/link-to}}
|
||||
|
||||
{{#link-to
|
||||
"datasets.dataset"
|
||||
"urn"
|
||||
(query-params urn=parent.urn)
|
||||
class="upstream-dataset__upstream-link-chevron"
|
||||
}}
|
||||
<i class="glyphicon glyphicon-menu-right" aria-label="Navigate to upstream dataset"></i>
|
||||
{{/link-to}}
|
||||
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
<header class="downstream-purge-policy-header">
|
||||
<h4>Compliance Purge Policy</h4>
|
||||
<div class="downstream-purge-policy__edit">
|
||||
{{#unless hasIncompleteUpstream}}
|
||||
<label for="downstream-purge-edit" class="downstream-purge-policy__edit--label">
|
||||
Modifying this will not affect the purge policy on the parent dataset
|
||||
</label>
|
||||
|
||||
{{#if isReadOnly}}
|
||||
<button
|
||||
class="nacho-button nacho-button--large"
|
||||
id="downstream-purge-edit"
|
||||
onclick={{action "onEdit"}}>
|
||||
Edit
|
||||
</button>
|
||||
{{else}}
|
||||
<button
|
||||
class="nacho-button nacho-button--large"
|
||||
disabled={{not retention.purgeType}}
|
||||
onclick={{perform saveRetentionTask}}>
|
||||
|
||||
{{#if saveRetentionTask.isRunning}}
|
||||
{{pendulum-ellipsis-animation}}
|
||||
{{else}}
|
||||
Save
|
||||
{{/if}}
|
||||
|
||||
</button>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
||||
<header class="upstream-dataset-banner__title">
|
||||
Parent Dataset Name:
|
||||
{{#link-to
|
||||
"datasets.dataset"
|
||||
"urn"
|
||||
(query-params urn=upstreamUrn)
|
||||
}}
|
||||
<strong>{{nativeName}}</strong>
|
||||
{{/link-to}}
|
||||
</header>
|
||||
|
||||
{{#if description}}
|
||||
<div class="downstream-purge-policy">
|
||||
{{#if hasIncompleteUpstream}}
|
||||
<p class="downstream-purge-policy__no-policy">
|
||||
This dataset does not have a current compliance purge policy. To update, please complete the Compliance Metadata
|
||||
on the parent dataset(s).
|
||||
</p>
|
||||
{{else}}
|
||||
|
||||
<p class="upstream-dataset-banner__description">
|
||||
Parent Dataset Description:
|
||||
<strong>{{description}}</strong>
|
||||
</p>
|
||||
|
||||
{{/if}}
|
||||
{{purge-policy
|
||||
isEditable=(not isReadOnly)
|
||||
platform=platform
|
||||
supportedPurgePolicies=supportedPurgePolicies
|
||||
purgeNote=retention.purgeNote
|
||||
purgePolicy=(readonly retention.purgeType)
|
||||
missingPolicyText="This dataset does not have a current compliance purge policy"
|
||||
onPolicyChange=onChange
|
||||
}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</section>
|
||||
|
@ -1,16 +1,3 @@
|
||||
<section class="metadata-prompt">
|
||||
<header class="metadata-prompt__header">
|
||||
<p>
|
||||
Compliance Purge Policy
|
||||
|
||||
{{more-info
|
||||
link="http://go/gdpr/deletions/purgePolicies"
|
||||
tooltip="Click for more information Purge Policies"
|
||||
}}
|
||||
</p>
|
||||
</header>
|
||||
</section>
|
||||
|
||||
<ul class="purge-policy-list">
|
||||
{{#if isEditable}}
|
||||
|
||||
@ -51,17 +38,16 @@
|
||||
|
||||
{{else}}
|
||||
|
||||
{{#if purgePolicy}}
|
||||
<li class="purge-policy-list__item">
|
||||
<li class="purge-policy-list__item">
|
||||
{{#if purgePolicy}}
|
||||
<strong>
|
||||
{{get (get purgePolicyProps purgePolicy) "displayAs"}}
|
||||
</strong>
|
||||
</li>
|
||||
{{else}}
|
||||
{{else}}
|
||||
|
||||
<p>{{missingPolicyText}}</p>
|
||||
<sub>To update, click edit and follow the steps</sub>
|
||||
{{missingPolicyText}}
|
||||
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
31
wherehows-web/app/typings/api/datasets/retention.d.ts
vendored
Normal file
31
wherehows-web/app/typings/api/datasets/retention.d.ts
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
import { IComplianceInfo } from 'wherehows-web/typings/api/datasets/compliance';
|
||||
|
||||
/**
|
||||
* Describes the interface for a dataset retention policy
|
||||
*
|
||||
* @interface IDatasetRetention
|
||||
*/
|
||||
interface IDatasetRetention {
|
||||
// Unused attribute for the id of the dataset, use datasetUrn instead
|
||||
datasetId?: number | null;
|
||||
// Urn string identifying the dataset that owns this policy
|
||||
datasetUrn: string;
|
||||
// Purge Policy for the dataset
|
||||
purgeType: IComplianceInfo['complianceType'];
|
||||
// User entered purge notation for a dataset with a purge exempt policy
|
||||
purgeNote: IComplianceInfo['compliancePurgeNote'];
|
||||
// Who modified this retention policy
|
||||
modifiedBy?: string;
|
||||
// When this policy was last modified
|
||||
modifiedTime?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desribes the return type for requests to the endpoint returning the dataset retention policy
|
||||
* @interface IGetDatasetRetentionResponse
|
||||
*/
|
||||
interface IGetDatasetRetentionResponse {
|
||||
retentionPolicy: IDatasetRetention;
|
||||
}
|
||||
|
||||
export { IDatasetRetention, IGetDatasetRetentionResponse };
|
14
wherehows-web/app/typings/app/datasets/lineage.d.ts
vendored
Normal file
14
wherehows-web/app/typings/app/datasets/lineage.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset';
|
||||
|
||||
/**
|
||||
* Defines the interface for the attributes used by the app to render the upstream datasets for a child
|
||||
* dataset
|
||||
* @interface IUpstreamWithComplianceMetadata
|
||||
*/
|
||||
interface IUpstreamWithComplianceMetadata {
|
||||
urn: IDatasetView['uri'];
|
||||
nativeName: IDatasetView['nativeName'];
|
||||
hasCompliance: boolean;
|
||||
}
|
||||
|
||||
export { IUpstreamWithComplianceMetadata };
|
20
wherehows-web/app/utils/api/datasets/lineage.ts
Normal file
20
wherehows-web/app/utils/api/datasets/lineage.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { getJSON } from 'wherehows-web/utils/api/fetcher';
|
||||
import { datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
|
||||
import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset';
|
||||
|
||||
/**
|
||||
* Constructs the url for a datasets upstreams
|
||||
* @param {string} urn the urn for the child dataset
|
||||
* @return {string}
|
||||
*/
|
||||
const datasetUpstreamUrlByUrn = (urn: string): string => `${datasetUrlByUrn(urn)}/upstreams`;
|
||||
|
||||
/**
|
||||
* Fetches the list of upstream datasets for a dataset by urn
|
||||
* @param {string} urn urn for the child dataset
|
||||
* @return {Promise<Array<IDatasetView>>}
|
||||
*/
|
||||
const readUpstreamDatasetsByUrn = (urn: string): Promise<Array<IDatasetView>> =>
|
||||
getJSON<Array<IDatasetView>>({ url: datasetUpstreamUrlByUrn(urn) });
|
||||
|
||||
export { readUpstreamDatasetsByUrn };
|
39
wherehows-web/app/utils/api/datasets/retention.ts
Normal file
39
wherehows-web/app/utils/api/datasets/retention.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { getJSON, postJSON } from 'wherehows-web/utils/api/fetcher';
|
||||
import { datasetUrlByUrn } from 'wherehows-web/utils/api/datasets/shared';
|
||||
import { IDatasetRetention, IGetDatasetRetentionResponse } from 'wherehows-web/typings/api/datasets/retention';
|
||||
import { notFoundApiError } from 'wherehows-web/utils/api';
|
||||
|
||||
/**
|
||||
* Constructs the url for a datasets retention policy
|
||||
* @param {string} urn the urn for the dataset
|
||||
* @return {string}
|
||||
*/
|
||||
const datasetRetentionUrlByUrn = (urn: string): string => `${datasetUrlByUrn(urn)}/retention`;
|
||||
|
||||
/**
|
||||
* Fetches the list of retention policy for a dataset by urn
|
||||
* @param {string} urn urn for the dataset
|
||||
* @return {Promise<Array<IDatasetView>>}
|
||||
*/
|
||||
const readDatasetRetentionByUrn = async (urn: string): Promise<IGetDatasetRetentionResponse | null> => {
|
||||
try {
|
||||
return await getJSON<IGetDatasetRetentionResponse>({ url: datasetRetentionUrlByUrn(urn) });
|
||||
} catch (e) {
|
||||
if (notFoundApiError(e)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Persists the dataset retention policy remotely
|
||||
* @param {string} urn the urn of the dataset to save
|
||||
* @param {IDatasetRetention} retention the dataset retention policy to updae
|
||||
* @return {Promise<IDatasetRetention>}
|
||||
*/
|
||||
const saveDatasetRetentionByUrn = (urn: string, retention: IDatasetRetention): Promise<IDatasetRetention> =>
|
||||
postJSON<IDatasetRetention>({ url: datasetRetentionUrlByUrn(urn), data: retention });
|
||||
|
||||
export { readDatasetRetentionByUrn, saveDatasetRetentionByUrn };
|
Loading…
x
Reference in New Issue
Block a user