mirror of
https://github.com/datahub-project/datahub.git
synced 2025-08-31 12:52:13 +00:00
Merge pull request #714 from theseyi/compliance-dataset-field-split
updates notification confirm dialog. splits dataset field level quest…
This commit is contained in:
commit
364af9c4b9
@ -142,13 +142,63 @@ export default Component.extend({
|
||||
* Flag indicating that the component is in edit mode
|
||||
* @type {String}
|
||||
*/
|
||||
isEditing: false,
|
||||
isEditing: computed('isNewComplianceInfo', 'isEditingDatasetClassification', 'isEditingCompliancePolicy', function() {
|
||||
const { isNewComplianceInfo, isEditingDatasetClassification, isEditingCompliancePolicy } = getProperties(
|
||||
this,
|
||||
'isNewComplianceInfo',
|
||||
'isEditingDatasetClassification',
|
||||
'isEditingCompliancePolicy'
|
||||
);
|
||||
return isNewComplianceInfo || isEditingDatasetClassification || isEditingCompliancePolicy;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Convenience flag indicating the policy is not currently being edited
|
||||
* @type {Ember.computed}
|
||||
* @return {boolean}
|
||||
*/
|
||||
isReadOnly: computed.not('isEditing'),
|
||||
/**
|
||||
* Flag indicating that the component is currently saving / attempting to save the privacy policy
|
||||
* @type {String}
|
||||
*/
|
||||
isSaving: false,
|
||||
|
||||
/**
|
||||
* Determines if the the compliance policy update form should be shown
|
||||
* @type {Ember.computed}
|
||||
* @return {boolean}
|
||||
*/
|
||||
isShowingComplianceEditMode: computed('isNewComplianceInfo', 'isEditingCompliancePolicy', function() {
|
||||
const { isNewComplianceInfo, isEditingCompliancePolicy, isEditingDatasetClassification } = getProperties(
|
||||
this,
|
||||
'isNewComplianceInfo',
|
||||
'isEditingCompliancePolicy',
|
||||
'isEditingDatasetClassification'
|
||||
);
|
||||
|
||||
return (isNewComplianceInfo || isEditingCompliancePolicy) && !isEditingDatasetClassification;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Proxy to the check if the dataset classification form is being edited and should be shown
|
||||
* @type {Ember.computed}
|
||||
* @return {boolean}
|
||||
*/
|
||||
isShowingDatasetClassificationEditMode: computed.bool('isEditingDatasetClassification'),
|
||||
|
||||
datasetComplianceSteps: computed('isEditingCompliancePolicy', 'isEditingDatasetClassification', function() {
|
||||
const { isEditingCompliancePolicy, isEditingDatasetClassification } = getProperties(
|
||||
this,
|
||||
'isEditingCompliancePolicy',
|
||||
'isEditingDatasetClassification'
|
||||
);
|
||||
|
||||
return [isEditingCompliancePolicy, isEditingDatasetClassification].map((_step, index) => ({
|
||||
done: !index ? !!isEditingDatasetClassification : false
|
||||
}));
|
||||
}),
|
||||
|
||||
/**
|
||||
* Reference to the application notifications Service
|
||||
* @type {Ember.Service}
|
||||
@ -156,9 +206,7 @@ export default Component.extend({
|
||||
notifications: service(),
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
// If a compliance policy does not exist for this dataset, place it in edit mode by default
|
||||
set(this, 'isEditing', get(this, 'isNewComplianceInfo'));
|
||||
this._super(...Array.from(arguments));
|
||||
// Perform validation step on the received component attributes
|
||||
this.validateAttrs();
|
||||
},
|
||||
@ -593,7 +641,7 @@ export default Component.extend({
|
||||
{ formatted: [], unformatted: [] }
|
||||
);
|
||||
|
||||
const actions = {};
|
||||
const dialogActions = {};
|
||||
let isConfirmed = true;
|
||||
let unformattedComplianceEntities = [];
|
||||
|
||||
@ -608,8 +656,8 @@ export default Component.extend({
|
||||
|
||||
const confirmHandler = (function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
actions['didConfirm'] = () => resolve();
|
||||
actions['didDismiss'] = () => reject();
|
||||
dialogActions['didConfirm'] = () => resolve();
|
||||
dialogActions['didDismiss'] = () => reject();
|
||||
});
|
||||
})();
|
||||
|
||||
@ -620,7 +668,7 @@ export default Component.extend({
|
||||
`There are ${unformatted.length} non-ID fields that have no field format specified. ` +
|
||||
`Are you sure they don't contain any of the following PII?\n\n` +
|
||||
`Name, Email, Phone, Address, Location, IP Address, Payment Info, Password, National ID, Device ID etc.`,
|
||||
dialogActions: actions
|
||||
dialogActions: dialogActions
|
||||
});
|
||||
|
||||
try {
|
||||
@ -683,10 +731,24 @@ export default Component.extend({
|
||||
/**
|
||||
* Sets each datasetClassification value as false
|
||||
*/
|
||||
markDatasetAsNotContainingMemberData() {
|
||||
const willMarkAllAsNo = confirm(
|
||||
'Are you sure that any this dataset does not contain any of the listed types of member data'
|
||||
);
|
||||
async markDatasetAsNotContainingMemberData() {
|
||||
const dialogActions = {};
|
||||
const confirmMarkAllHandler = new Promise((resolve, reject) => {
|
||||
dialogActions.didDismiss = () => reject();
|
||||
dialogActions.didConfirm = () => resolve();
|
||||
});
|
||||
let willMarkAllAsNo = true;
|
||||
|
||||
get(this, 'notifications').notify('confirm', {
|
||||
content: 'Are you sure that any this dataset does not contain any of the listed types of member data',
|
||||
dialogActions
|
||||
});
|
||||
|
||||
try {
|
||||
await confirmMarkAllHandler;
|
||||
} catch (e) {
|
||||
willMarkAllAsNo = false;
|
||||
}
|
||||
|
||||
return (
|
||||
willMarkAllAsNo &&
|
||||
@ -708,10 +770,24 @@ export default Component.extend({
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle the user intent to place this compliance component in edit mode
|
||||
* Handler for setting the compliance policy into edit mode and rendering
|
||||
*/
|
||||
onEdit() {
|
||||
set(this, 'isEditing', true);
|
||||
onEditCompliancePolicy() {
|
||||
setProperties(this, { isEditingCompliancePolicy: true, isEditingDatasetClassification: false });
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for setting the dataset classification into edit mode and rendering into DOM
|
||||
*/
|
||||
async onEditDatasetClassification() {
|
||||
const isConfirmed = await this.confirmUnformattedFields();
|
||||
|
||||
// If user provides confirmation for unformatted fields or there are none,
|
||||
// then validate fields against expectations
|
||||
// otherwise inform user of validation exception
|
||||
if (isConfirmed) {
|
||||
setProperties(this, { isEditingCompliancePolicy: false, isEditingDatasetClassification: true });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -847,29 +923,22 @@ export default Component.extend({
|
||||
*/
|
||||
async saveCompliance() {
|
||||
const setSaveFlag = (flag = false) => set(this, 'isSaving', flag);
|
||||
// If fields are confirmed as unique we can proceed with saving compliance entities
|
||||
const saveConfirmed = await this.confirmUnformattedFields();
|
||||
|
||||
// If user provides confirmation for unformatted fields or there are none,
|
||||
// then validate fields against expectations
|
||||
// otherwise inform user of validation exception
|
||||
if (saveConfirmed) {
|
||||
try {
|
||||
const isSaving = true;
|
||||
const onSave = get(this, 'onSave');
|
||||
setSaveFlag(isSaving);
|
||||
await this.validateFields();
|
||||
try {
|
||||
const isSaving = true;
|
||||
const onSave = get(this, 'onSave');
|
||||
setSaveFlag(isSaving);
|
||||
await this.validateFields();
|
||||
|
||||
return await this.whenRequestCompletes(onSave(), { isSaving });
|
||||
} catch (e) {
|
||||
// Flag this dataset's data as problematic
|
||||
if (e instanceof Error && e.message === complianceDataException) {
|
||||
set(this, '_hasBadData', true);
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
} finally {
|
||||
setSaveFlag();
|
||||
return await this.whenRequestCompletes(onSave(), { isSaving });
|
||||
} catch (e) {
|
||||
// Flag this dataset's data as problematic
|
||||
if (e instanceof Error && e.message === complianceDataException) {
|
||||
set(this, '_hasBadData', true);
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
} finally {
|
||||
setSaveFlag();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2,3 +2,4 @@
|
||||
@import "compliance-prompts";
|
||||
@import "compliance-table";
|
||||
@import "compliance-auto-suggester-action";
|
||||
@import "dataset-compliance-step";
|
||||
|
@ -8,4 +8,8 @@
|
||||
&__notification-column {
|
||||
width: 5%
|
||||
}
|
||||
|
||||
&__classification-column {
|
||||
width: 17%;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
/// Specifies the width x height for the circle
|
||||
$dataset-compliance-step-circle-size: 30px;
|
||||
/// Specifies the base color for the step indicator
|
||||
$dataset-compliance-step-color-base: set-color(grey, mid);
|
||||
/// Specifies the completion color for the step indicator
|
||||
$dataset-compliance-step-color-complete: set-color(blue, blue5);
|
||||
|
||||
/// Defines rules for the dataset compliance step indicator
|
||||
/// A circle containing the step number, with a separating dash between successive steps
|
||||
.dataset-compliance-step {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: fw(normal, 4);
|
||||
height: $dataset-compliance-step-circle-size;
|
||||
width: $dataset-compliance-step-circle-size;
|
||||
color: $dataset-compliance-step-color-base;
|
||||
background-color: set-color(white, base);
|
||||
border: 2px solid $dataset-compliance-step-color-base;
|
||||
border-radius: 50%;
|
||||
|
||||
&--complete {
|
||||
color: transparent;
|
||||
border-color: $dataset-compliance-step-color-complete;
|
||||
|
||||
&::after {
|
||||
content: '\f00c';
|
||||
font-family: $font-awesome-stack;
|
||||
color: $dataset-compliance-step-color-complete;
|
||||
margin-left: -5px;
|
||||
}
|
||||
}
|
||||
|
||||
& + & {
|
||||
margin-left: item-spacing(5);
|
||||
overflow: visible;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
width: 16px;
|
||||
margin-left: -28px;
|
||||
border: 1px solid $dataset-compliance-step-color-base;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the styles for a wrapping container
|
||||
.dataset-compliance-step-container {
|
||||
margin: item-spacing(4) 0;
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
&__header,
|
||||
&__content,
|
||||
&__footer {
|
||||
padding: item-spacing(2 4);
|
||||
padding: item-spacing(4 4);
|
||||
}
|
||||
|
||||
&__header {
|
||||
@ -24,6 +24,9 @@
|
||||
|
||||
&__heading-text {
|
||||
margin-top: 0;
|
||||
font-weight:fw(normal, 4);
|
||||
font-size: 24px;
|
||||
color: set-color(grey, dark);
|
||||
}
|
||||
|
||||
&__footer {
|
||||
|
@ -14,30 +14,45 @@
|
||||
{{else}}
|
||||
<section class="action-bar">
|
||||
{{#if isEditing}}
|
||||
|
||||
{{#if _message}}
|
||||
<div class="alert alert-{{_alertType}} post-action-notification action-footer-notification" role="alert">
|
||||
{{_message}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="container action-bar__content">
|
||||
<button
|
||||
class="nacho-button nacho-button--large-inverse action-bar__item"
|
||||
title={{unless isDatasetFullyClassified
|
||||
"Ensure you have provided a yes/no value for all dataset tags"
|
||||
"Save"}}
|
||||
disabled={{isSavingDisabled}}
|
||||
{{action "saveCompliance"}}>
|
||||
Save
|
||||
</button>
|
||||
{{#if isShowingComplianceEditMode}}
|
||||
<button
|
||||
class="nacho-button nacho-button--large-inverse action-bar__item"
|
||||
title="Next"
|
||||
{{action "onEditDatasetClassification"}}>
|
||||
Next
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
<button class="nacho-button nacho-button--large action-bar__item"
|
||||
{{action "resetCompliance"}}>
|
||||
<i class="fa fa-times" title="Cancel">
|
||||
</i>
|
||||
Cancel
|
||||
</button>
|
||||
{{#if isShowingDatasetClassificationEditMode}}
|
||||
|
||||
<button
|
||||
class="nacho-button nacho-button--large-inverse action-bar__item"
|
||||
title={{unless isDatasetFullyClassified
|
||||
"Ensure you have provided a yes/no value for all dataset tags"
|
||||
"Save"}}
|
||||
disabled={{isSavingDisabled}}
|
||||
{{action "saveCompliance"}}>
|
||||
Save
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="nacho-button--large nacho-button--secondary action-bar__item"
|
||||
title="Back"
|
||||
{{action "onEditCompliancePolicy"}}>
|
||||
Back
|
||||
</button>
|
||||
|
||||
{{#if _message}}
|
||||
<div class="alert alert-{{_alertType}} post-action-notification action-footer-notification" role="alert">
|
||||
{{_message}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{/if}}
|
||||
</section>
|
||||
{{/if}}
|
||||
@ -52,8 +67,9 @@
|
||||
</div>
|
||||
|
||||
{{#unless isEditing}}
|
||||
|
||||
<button
|
||||
{{action "onEdit"}}
|
||||
{{action "onEditCompliancePolicy"}}
|
||||
class="nacho-button--large nacho-button--secondary secondary-actions__action">
|
||||
Edit
|
||||
</button>
|
||||
@ -65,16 +81,27 @@
|
||||
Download compliance metadata
|
||||
</button>
|
||||
{{/unless}}
|
||||
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
||||
{{#if (and isEditing (not _hasBadData))}}
|
||||
{{#if isEditing}}
|
||||
<div class="dataset-compliance-step-container">
|
||||
{{partial "datasets/dataset-compliance/-dataset-compliance-step-indicator"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if (and isShowingComplianceEditMode (not _hasBadData))}}
|
||||
{{json-upload receiveJsonFile=(action "onComplianceJsonUpload") class="secondary-actions__action"}}
|
||||
{{/if}}
|
||||
|
||||
{{partial "datasets/dataset-compliance/dataset-classification"}}
|
||||
{{#if (or isReadOnly isShowingDatasetClassificationEditMode)}}
|
||||
{{partial "datasets/dataset-compliance/dataset-classification"}}
|
||||
{{/if}}
|
||||
|
||||
{{partial "datasets/dataset-compliance/dataset-compliance-entities"}}
|
||||
{{#if (or isReadOnly isShowingComplianceEditMode)}}
|
||||
{{partial "datasets/dataset-compliance/dataset-compliance-entities"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{yield}}
|
||||
|
@ -39,7 +39,7 @@
|
||||
value="{{table.searchTerm}}"
|
||||
oninput={{action table.filterDidChange value="target.value"}}>
|
||||
|
||||
{{#if hasRecentSuggestions}}
|
||||
{{#if (and hasRecentSuggestions (not isNewComplianceInfo))}}
|
||||
<span class="dataset-compliance-fields__has-suggestions">
|
||||
{{complianceSuggestion.complianceSuggestions.length}} fields to be reviewed
|
||||
</span>
|
||||
@ -79,7 +79,7 @@
|
||||
</sup>
|
||||
</a>
|
||||
{{/head.column}}
|
||||
{{#head.column class="nacho-table-cell-wrapped"}}
|
||||
{{#head.column class="nacho-table-cell-wrapped dataset-compliance-fields__classification-column"}}
|
||||
Security Classification
|
||||
<sup>
|
||||
<span
|
||||
|
@ -0,0 +1,5 @@
|
||||
{{#each datasetComplianceSteps as |step index|}}
|
||||
<span class="dataset-compliance-step dataset-compliance-step--{{if step.done "complete" "incomplete"}}">
|
||||
{{inc index}}
|
||||
</span>
|
||||
{{/each}}
|
Loading…
x
Reference in New Issue
Block a user