mirror of
https://github.com/datahub-project/datahub.git
synced 2025-10-19 12:53:28 +00:00
implements purge policy feature. constants for platforms and purge types. adds styles for feature. implements ui logic for selecting purge based on platform availability.
This commit is contained in:
parent
1f3fb8b30f
commit
64c442b938
@ -1,5 +1,6 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import isTrackingHeaderField from 'wherehows-web/utils/validators/tracking-headers';
|
import isTrackingHeaderField from 'wherehows-web/utils/validators/tracking-headers';
|
||||||
|
import { getPlatformFromUrn } from 'wherehows-web/utils/validators/urn';
|
||||||
import {
|
import {
|
||||||
classifiers,
|
classifiers,
|
||||||
datasetClassifiers,
|
datasetClassifiers,
|
||||||
@ -189,6 +190,15 @@ export default Component.extend({
|
|||||||
return get(this, 'isNewComplianceInfo') ? 'showAll' : 'showReview';
|
return get(this, 'isNewComplianceInfo') ? 'showAll' : 'showReview';
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the dataset platform from the dataset urn
|
||||||
|
* @type {Ember.ComputedProperty}
|
||||||
|
* @return {string | void}
|
||||||
|
*/
|
||||||
|
datasetPlatform: computed('complianceInfo.datasetUrn', function() {
|
||||||
|
return getPlatformFromUrn(get(this, 'complianceInfo.datasetUrn'));
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the application notifications Service
|
* Reference to the application notifications Service
|
||||||
* @type {Ember.Service}
|
* @type {Ember.Service}
|
||||||
@ -723,6 +733,26 @@ export default Component.extend({
|
|||||||
return sourceDatasetClassification;
|
return sourceDatasetClassification;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a modal dialog requesting that the user check affirm that the purge type is exempt
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
showPurgeExemptionWarning() {
|
||||||
|
const dialogActions = {};
|
||||||
|
|
||||||
|
get(this, 'notifications').notify('confirm', {
|
||||||
|
header: 'Confirm purge exemption',
|
||||||
|
content:
|
||||||
|
'By choosing this option you understand that either Legal or HSEC may contact you to verify the purge exemption',
|
||||||
|
dialogActions
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
dialogActions['didConfirm'] = () => resolve();
|
||||||
|
dialogActions['didDismiss'] = () => reject();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
/**
|
/**
|
||||||
* Sets each datasetClassification value as false
|
* Sets each datasetClassification value as false
|
||||||
@ -957,6 +987,15 @@ export default Component.extend({
|
|||||||
return set(this.getDatasetClassificationRef(), classifier, value);
|
return set(this.getDatasetClassificationRef(), classifier, value);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the complianceType on the compliance policy
|
||||||
|
* @param {PurgePolicy} purgePolicy
|
||||||
|
*/
|
||||||
|
onDatasetPurgePolicyChange(purgePolicy) {
|
||||||
|
// directly set the complianceType to the updated value
|
||||||
|
return set(this, 'complianceInfo.complianceType', purgePolicy);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If all validity checks are passed, invoke onSave action on controller
|
* If all validity checks are passed, invoke onSave action on controller
|
||||||
*/
|
*/
|
||||||
|
80
wherehows-web/app/components/purge-policy.ts
Normal file
80
wherehows-web/app/components/purge-policy.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import Ember from 'ember';
|
||||||
|
import { baseCommentEditorOptions, PurgePolicy, purgePolicyProps } from 'wherehows-web/constants';
|
||||||
|
import noop from 'wherehows-web/utils/noop';
|
||||||
|
|
||||||
|
const { Component, get, set } = Ember;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cache for the exempt policy
|
||||||
|
* @type {PurgePolicy}
|
||||||
|
*/
|
||||||
|
const exemptPolicy = PurgePolicy.PurgeExempt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that a purge policy is exempt
|
||||||
|
* @param {PurgePolicy} policy the policy to check
|
||||||
|
*/
|
||||||
|
const isExempt = (policy: PurgePolicy) => policy === exemptPolicy;
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
tagName: 'ul',
|
||||||
|
|
||||||
|
classNames: ['purge-policy-list'],
|
||||||
|
|
||||||
|
exemptPolicy,
|
||||||
|
|
||||||
|
purgePolicyProps,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dataset's platform
|
||||||
|
*/
|
||||||
|
platform: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently save policy for the dataset purge
|
||||||
|
*/
|
||||||
|
purgePolicy: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An options hash for the purge exempt reason text editor
|
||||||
|
* @type {}
|
||||||
|
*/
|
||||||
|
editorOptions: {
|
||||||
|
...baseCommentEditorOptions,
|
||||||
|
placeholder: {
|
||||||
|
text: 'Please provide an explanation for why this dataset is marked "Purge Exempt" status'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action to handle policy change, by default a no-op function
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
|
onPolicyChange: noop,
|
||||||
|
|
||||||
|
didReceiveAttrs() {
|
||||||
|
this._super(...arguments);
|
||||||
|
this.checkExemption(get(this, 'purgePolicy'));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the selected purge policy is exempt, if so, set the
|
||||||
|
* flag to request the exemption to true
|
||||||
|
* @param {PurgePolicy} purgePolicy
|
||||||
|
*/
|
||||||
|
checkExemption(purgePolicy: PurgePolicy) {
|
||||||
|
const exemptionReasonRequested = isExempt(purgePolicy);
|
||||||
|
set(this, 'requestExemptionReason', exemptionReasonRequested);
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
/**
|
||||||
|
* Handles the change to the currently selected purge policy
|
||||||
|
* @param {string} _name unused name for the radio group
|
||||||
|
* @param {PurgePolicy} purgePolicy the selected purge policy
|
||||||
|
*/
|
||||||
|
onChange(_name: string, purgePolicy: PurgePolicy) {
|
||||||
|
return get(this, 'onPolicyChange')(purgePolicy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
14
wherehows-web/app/constants/dataset-platforms.ts
Normal file
14
wherehows-web/app/constants/dataset-platforms.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* The known/supported list of dataset platforms
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
enum DatasetPlatform {
|
||||||
|
Kafka = 'KAFKA',
|
||||||
|
Espresso = 'ESPRESSO',
|
||||||
|
Oracle = 'ORACLE',
|
||||||
|
MySql = 'MYSQL',
|
||||||
|
Teradata = 'TERADATA',
|
||||||
|
HDFS = 'HDFS'
|
||||||
|
}
|
||||||
|
|
||||||
|
export { DatasetPlatform };
|
62
wherehows-web/app/constants/dataset-purge-policy.ts
Normal file
62
wherehows-web/app/constants/dataset-purge-policy.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { DatasetPlatform } from 'wherehows-web/constants/dataset-platforms';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available values for the purge policy
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
enum PurgePolicy {
|
||||||
|
AutoPurge = 'AUTO_PURGE',
|
||||||
|
ManualPurge = 'MANUAL_PURGE',
|
||||||
|
AutoLimitedRetention = 'AUTO_LIMITED_RETENTION',
|
||||||
|
ManualLimitedRetention = 'MANUAL_LIMITED_RETENTION',
|
||||||
|
PurgeExempt = 'PURGE_EXEMPT'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index signature for purge policy properties
|
||||||
|
*/
|
||||||
|
type PurgePolicyProperties = {
|
||||||
|
[K in PurgePolicy]: {
|
||||||
|
platforms: Array<DatasetPlatform>;
|
||||||
|
desc: string;
|
||||||
|
displayAs: string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client options for each purge policy
|
||||||
|
* Lists, the available platforms, a descriptions field and a user friendly name for the purge key
|
||||||
|
*/
|
||||||
|
const purgePolicyProps: PurgePolicyProperties = {
|
||||||
|
AUTO_PURGE: {
|
||||||
|
platforms: [DatasetPlatform.Teradata, DatasetPlatform.Espresso, DatasetPlatform.HDFS],
|
||||||
|
desc: 'A centralized system will automatically purge this dataset based on the provided metadata.',
|
||||||
|
displayAs: 'Auto Purge'
|
||||||
|
},
|
||||||
|
MANUAL_PURGE: {
|
||||||
|
platforms: [DatasetPlatform.MySql, DatasetPlatform.Espresso, DatasetPlatform.Teradata, DatasetPlatform.HDFS],
|
||||||
|
desc: '',
|
||||||
|
displayAs: 'Manual Purge'
|
||||||
|
},
|
||||||
|
AUTO_LIMITED_RETENTION: {
|
||||||
|
platforms: [DatasetPlatform.Kafka, DatasetPlatform.Teradata, DatasetPlatform.HDFS],
|
||||||
|
desc:
|
||||||
|
'The data platform enforces limited retention. Only choose this option if your dataset ' +
|
||||||
|
"complies with the platform's limited retention policy.",
|
||||||
|
displayAs: 'Auto Limited Retention'
|
||||||
|
},
|
||||||
|
MANUAL_LIMITED_RETENTION: {
|
||||||
|
platforms: [DatasetPlatform.Espresso, DatasetPlatform.Oracle, DatasetPlatform.MySql],
|
||||||
|
desc: '',
|
||||||
|
displayAs: 'Manual Limited Retention'
|
||||||
|
},
|
||||||
|
PURGE_EXEMPT: {
|
||||||
|
platforms: Object.keys(DatasetPlatform).map((k: keyof typeof DatasetPlatform) => DatasetPlatform[k]),
|
||||||
|
desc:
|
||||||
|
'The dataset is exempted from purging due to legal or financial requirements.' +
|
||||||
|
" Only choose this option if you've received an explicit exemption from legal.",
|
||||||
|
displayAs: 'Purge Exempt'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { PurgePolicy, purgePolicyProps };
|
@ -3,3 +3,5 @@ export * from 'wherehows-web/constants/dataset-classification';
|
|||||||
export * from 'wherehows-web/constants/dataset-compliance';
|
export * from 'wherehows-web/constants/dataset-compliance';
|
||||||
export * from 'wherehows-web/constants/application';
|
export * from 'wherehows-web/constants/application';
|
||||||
export * from 'wherehows-web/constants/dataset-comments';
|
export * from 'wherehows-web/constants/dataset-comments';
|
||||||
|
export * from 'wherehows-web/constants/dataset-purge-policy';
|
||||||
|
export * from 'wherehows-web/constants/dataset-platforms';
|
||||||
|
@ -44,11 +44,7 @@
|
|||||||
$breakpoint-query: map-get($breakpoints, $breakpoint);
|
$breakpoint-query: map-get($breakpoints, $breakpoint);
|
||||||
|
|
||||||
@if $breakpoint-query {
|
@if $breakpoint-query {
|
||||||
$query: if(
|
$query: if(type-of($breakpoint-query) == 'string', unquote($breakpoint-query), inspect($breakpoint-query));
|
||||||
type-of($breakpoint-query) == 'string',
|
|
||||||
unquote($breakpoint-query),
|
|
||||||
inspect($breakpoint-query)
|
|
||||||
);
|
|
||||||
|
|
||||||
@media #{$query} {
|
@media #{$query} {
|
||||||
@content;
|
@content;
|
||||||
@ -84,6 +80,34 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Proxy for AD container styles
|
||||||
|
@mixin nacho-container {
|
||||||
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
|
||||||
|
background-color: set-color(white, base);
|
||||||
|
background-clip: padding-box;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: item-spacing(4);
|
||||||
|
transition: box-shadow 83ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies rules to render an element with a pill shape
|
||||||
|
/// @param {Color} $bg-color the background color for the pill
|
||||||
|
/// @param {Color} $color font/text color
|
||||||
|
/// @param {Color} $border-color=$bg-color the color to apply to the pill border
|
||||||
|
///@example - Usage
|
||||||
|
/// .foo {
|
||||||
|
/// @include pill(get-color(gray1), get-color(gray6));
|
||||||
|
/// }
|
||||||
|
@mixin pill($bg-color, $color, $border-color: $bg-color) {
|
||||||
|
border-radius: 32px;
|
||||||
|
background-color: $bg-color;
|
||||||
|
border: 1px solid $border-color;
|
||||||
|
color: $color;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: item-spacing(3);
|
||||||
|
padding: 1px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/// Temp implementation before Auto Prefixer is installed
|
/// Temp implementation before Auto Prefixer is installed
|
||||||
/// @link https://github.com/postcss/autoprefixer
|
/// @link https://github.com/postcss/autoprefixer
|
||||||
|
|
||||||
@ -99,7 +123,6 @@
|
|||||||
#{$property}: $value;
|
#{$property}: $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Maintains the aspect ratio for a wrapped element
|
/// Maintains the aspect ratio for a wrapped element
|
||||||
/// @param {Number} $width number value for the container's width ratio
|
/// @param {Number} $width number value for the container's width ratio
|
||||||
/// @param {Number} $height number value for the container's with ratio
|
/// @param {Number} $height number value for the container's with ratio
|
||||||
@ -107,7 +130,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: "";
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-top: ($height / $width) * 100%;
|
padding-top: ($height / $width) * 100%;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
@import 'dataset-comments/all';
|
@import 'dataset-comments/all';
|
||||||
@import 'comments/all';
|
@import 'comments/all';
|
||||||
@import 'empty-state/all';
|
@import 'empty-state/all';
|
||||||
|
@import 'dataset-purge-policy/all';
|
||||||
|
|
||||||
@import 'nacho/nacho-button';
|
@import 'nacho/nacho-button';
|
||||||
@import 'nacho/nacho-global-search';
|
@import 'nacho/nacho-global-search';
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
@import 'purge-policy-list';
|
@ -0,0 +1,21 @@
|
|||||||
|
.purge-policy-list {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
@include nacho-container;
|
||||||
|
list-style-type: none;
|
||||||
|
margin-bottom: item-spacing(4);
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
color: set-color(grey, mid);
|
||||||
|
background-color: set-color(grey, light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__platform {
|
||||||
|
&--unavailable {
|
||||||
|
@include pill(set-color(red, maroonflush), set-color(white, base));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -102,6 +102,15 @@
|
|||||||
{{#if (or isReadOnly isShowingComplianceEditMode)}}
|
{{#if (or isReadOnly isShowingComplianceEditMode)}}
|
||||||
{{partial "datasets/dataset-compliance/dataset-compliance-entities"}}
|
{{partial "datasets/dataset-compliance/dataset-compliance-entities"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isShowingCompliancePurgePolicy}}
|
||||||
|
{{purge-policy
|
||||||
|
platform=datasetPlatform
|
||||||
|
purgeNote=complianceInfo.compliancePurgeNote
|
||||||
|
purgePolicy=(readonly complianceInfo.complianceType)
|
||||||
|
onPolicyChange=(action "onDatasetPurgePolicyChange")
|
||||||
|
}}
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{yield}}
|
{{yield}}
|
||||||
|
@ -13,12 +13,9 @@ const createInitialComplianceInfo = datasetId => ({
|
|||||||
datasetId,
|
datasetId,
|
||||||
// default to first item in compliance types list
|
// default to first item in compliance types list
|
||||||
complianceType: 'AUTO_PURGE',
|
complianceType: 'AUTO_PURGE',
|
||||||
|
compliancePurgeNote: '',
|
||||||
complianceEntities: [],
|
complianceEntities: [],
|
||||||
fieldClassification: {},
|
datasetClassification: {}
|
||||||
datasetClassification: {},
|
|
||||||
geographicAffinity: { affinity: '' },
|
|
||||||
recordOwnerType: '',
|
|
||||||
retentionPolicy: { retentionType: '' }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
4
wherehows-web/app/utils/noop.ts
Normal file
4
wherehows-web/app/utils/noop.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* exports a noop that can be used in place of Ember.K which is currently deprecated.
|
||||||
|
*/
|
||||||
|
export default () => {};
|
@ -14,8 +14,23 @@ const specialFlowUrnRegex = /(?:\?urn=)([a-z0-9_\-/{}\s]+)/i;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that a provided string matches the urn pattern above
|
* Asserts that a provided string matches the urn pattern above
|
||||||
* @param {String} candidateUrn the string to test on
|
* @param {string} candidateUrn the string to test on
|
||||||
*/
|
*/
|
||||||
export default (candidateUrn: string) => urnRegex.test(String(candidateUrn));
|
const isUrn = (candidateUrn: string) => urnRegex.test(String(candidateUrn));
|
||||||
|
|
||||||
export { urnRegex, specialFlowUrnRegex };
|
/**
|
||||||
|
* Extracts the platform string from the candidate urn string
|
||||||
|
* @param {string} candidateUrn the urn string with leading platform identifier
|
||||||
|
* @returns {string | void}
|
||||||
|
*/
|
||||||
|
const getPlatformFromUrn = (candidateUrn: string) => {
|
||||||
|
const matches = urnRegex.exec(candidateUrn);
|
||||||
|
if (matches) {
|
||||||
|
const [, platform] = matches;
|
||||||
|
return platform.toUpperCase();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isUrn;
|
||||||
|
|
||||||
|
export { urnRegex, specialFlowUrnRegex, getPlatformFromUrn };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user