Merge pull request #714 from theseyi/compliance-dataset-field-split

updates notification confirm dialog. splits dataset field level quest…
This commit is contained in:
Seyi Adebajo 2017-08-30 10:23:42 -07:00 committed by GitHub
commit 364af9c4b9
8 changed files with 221 additions and 61 deletions

View File

@ -142,13 +142,63 @@ export default Component.extend({
* Flag indicating that the component is in edit mode * Flag indicating that the component is in edit mode
* @type {String} * @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 * Flag indicating that the component is currently saving / attempting to save the privacy policy
* @type {String} * @type {String}
*/ */
isSaving: false, 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 * Reference to the application notifications Service
* @type {Ember.Service} * @type {Ember.Service}
@ -156,9 +206,7 @@ export default Component.extend({
notifications: service(), notifications: service(),
didReceiveAttrs() { didReceiveAttrs() {
this._super(...arguments); this._super(...Array.from(arguments));
// If a compliance policy does not exist for this dataset, place it in edit mode by default
set(this, 'isEditing', get(this, 'isNewComplianceInfo'));
// Perform validation step on the received component attributes // Perform validation step on the received component attributes
this.validateAttrs(); this.validateAttrs();
}, },
@ -593,7 +641,7 @@ export default Component.extend({
{ formatted: [], unformatted: [] } { formatted: [], unformatted: [] }
); );
const actions = {}; const dialogActions = {};
let isConfirmed = true; let isConfirmed = true;
let unformattedComplianceEntities = []; let unformattedComplianceEntities = [];
@ -608,8 +656,8 @@ export default Component.extend({
const confirmHandler = (function() { const confirmHandler = (function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
actions['didConfirm'] = () => resolve(); dialogActions['didConfirm'] = () => resolve();
actions['didDismiss'] = () => reject(); dialogActions['didDismiss'] = () => reject();
}); });
})(); })();
@ -620,7 +668,7 @@ export default Component.extend({
`There are ${unformatted.length} non-ID fields that have no field format specified. ` + `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` + `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.`, `Name, Email, Phone, Address, Location, IP Address, Payment Info, Password, National ID, Device ID etc.`,
dialogActions: actions dialogActions: dialogActions
}); });
try { try {
@ -683,10 +731,24 @@ export default Component.extend({
/** /**
* Sets each datasetClassification value as false * Sets each datasetClassification value as false
*/ */
markDatasetAsNotContainingMemberData() { async markDatasetAsNotContainingMemberData() {
const willMarkAllAsNo = confirm( const dialogActions = {};
'Are you sure that any this dataset does not contain any of the listed types of member data' 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 ( return (
willMarkAllAsNo && 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() { onEditCompliancePolicy() {
set(this, 'isEditing', true); 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,13 +923,7 @@ export default Component.extend({
*/ */
async saveCompliance() { async saveCompliance() {
const setSaveFlag = (flag = false) => set(this, 'isSaving', flag); 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 { try {
const isSaving = true; const isSaving = true;
const onSave = get(this, 'onSave'); const onSave = get(this, 'onSave');
@ -870,7 +940,6 @@ export default Component.extend({
} finally { } finally {
setSaveFlag(); setSaveFlag();
} }
}
}, },
// Rolls back changes made to the compliance spec to current // Rolls back changes made to the compliance spec to current

View File

@ -2,3 +2,4 @@
@import "compliance-prompts"; @import "compliance-prompts";
@import "compliance-table"; @import "compliance-table";
@import "compliance-auto-suggester-action"; @import "compliance-auto-suggester-action";
@import "dataset-compliance-step";

View File

@ -8,4 +8,8 @@
&__notification-column { &__notification-column {
width: 5% width: 5%
} }
&__classification-column {
width: 17%;
}
} }

View File

@ -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;
}

View File

@ -15,7 +15,7 @@
&__header, &__header,
&__content, &__content,
&__footer { &__footer {
padding: item-spacing(2 4); padding: item-spacing(4 4);
} }
&__header { &__header {
@ -24,6 +24,9 @@
&__heading-text { &__heading-text {
margin-top: 0; margin-top: 0;
font-weight:fw(normal, 4);
font-size: 24px;
color: set-color(grey, dark);
} }
&__footer { &__footer {

View File

@ -14,7 +14,25 @@
{{else}} {{else}}
<section class="action-bar"> <section class="action-bar">
{{#if isEditing}} {{#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"> <div class="container action-bar__content">
{{#if isShowingComplianceEditMode}}
<button
class="nacho-button nacho-button--large-inverse action-bar__item"
title="Next"
{{action "onEditDatasetClassification"}}>
Next
</button>
{{/if}}
{{#if isShowingDatasetClassificationEditMode}}
<button <button
class="nacho-button nacho-button--large-inverse action-bar__item" class="nacho-button nacho-button--large-inverse action-bar__item"
title={{unless isDatasetFullyClassified title={{unless isDatasetFullyClassified
@ -25,19 +43,16 @@
Save Save
</button> </button>
<button class="nacho-button nacho-button--large action-bar__item" <button
{{action "resetCompliance"}}> class="nacho-button--large nacho-button--secondary action-bar__item"
<i class="fa fa-times" title="Cancel"> title="Back"
</i> {{action "onEditCompliancePolicy"}}>
Cancel Back
</button> </button>
{{#if _message}}
<div class="alert alert-{{_alertType}} post-action-notification action-footer-notification" role="alert">
{{_message}}
</div>
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}
</section> </section>
{{/if}} {{/if}}
@ -52,8 +67,9 @@
</div> </div>
{{#unless isEditing}} {{#unless isEditing}}
<button <button
{{action "onEdit"}} {{action "onEditCompliancePolicy"}}
class="nacho-button--large nacho-button--secondary secondary-actions__action"> class="nacho-button--large nacho-button--secondary secondary-actions__action">
Edit Edit
</button> </button>
@ -65,16 +81,27 @@
Download compliance metadata Download compliance metadata
</button> </button>
{{/unless}} {{/unless}}
{{/unless}} {{/unless}}
</div> </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"}} {{json-upload receiveJsonFile=(action "onComplianceJsonUpload") class="secondary-actions__action"}}
{{/if}} {{/if}}
{{#if (or isReadOnly isShowingDatasetClassificationEditMode)}}
{{partial "datasets/dataset-compliance/dataset-classification"}} {{partial "datasets/dataset-compliance/dataset-classification"}}
{{/if}}
{{#if (or isReadOnly isShowingComplianceEditMode)}}
{{partial "datasets/dataset-compliance/dataset-compliance-entities"}} {{partial "datasets/dataset-compliance/dataset-compliance-entities"}}
{{/if}}
</div> </div>
{{yield}} {{yield}}

View File

@ -39,7 +39,7 @@
value="{{table.searchTerm}}" value="{{table.searchTerm}}"
oninput={{action table.filterDidChange value="target.value"}}> oninput={{action table.filterDidChange value="target.value"}}>
{{#if hasRecentSuggestions}} {{#if (and hasRecentSuggestions (not isNewComplianceInfo))}}
<span class="dataset-compliance-fields__has-suggestions"> <span class="dataset-compliance-fields__has-suggestions">
{{complianceSuggestion.complianceSuggestions.length}} fields to be reviewed {{complianceSuggestion.complianceSuggestions.length}} fields to be reviewed
</span> </span>
@ -79,7 +79,7 @@
</sup> </sup>
</a> </a>
{{/head.column}} {{/head.column}}
{{#head.column class="nacho-table-cell-wrapped"}} {{#head.column class="nacho-table-cell-wrapped dataset-compliance-fields__classification-column"}}
Security Classification Security Classification
<sup> <sup>
<span <span

View File

@ -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}}