updates the edit view. adds hasRecentSuggestions flag for compliance metadata. refactors suggestions getter to include lastModified date.

This commit is contained in:
Seyi Adebajo 2017-08-20 20:05:18 -07:00
parent 9bbf77fe99
commit 79854ab9ae
8 changed files with 63 additions and 22 deletions

View File

@ -196,14 +196,14 @@ export default DatasetTableRow.extend({
* Extracts the field suggestions into a cached computed property, if a suggestion exists
* @type {Ember.computed}
*/
prediction: computed('field.suggestion', 'field.suggestionAuthority', function() {
const field = get(this, 'field') || {};
prediction: computed('field.suggestion', 'field.suggestionAuthority', 'hasRecentSuggestions', function() {
const { field = {}, hasRecentSuggestions } = getProperties(this, 'field', 'hasRecentSuggestions');
// If a suggestionAuthority property exists on the field, then the user has already either accepted or ignored
// the suggestion for this field. It's value should not be take into account on re-renders
// this line takes that into account and substitutes an empty suggestion
const { suggestion } = field.hasOwnProperty('suggestionAuthority') ? {} : field;
if (suggestion) {
if (suggestion && hasRecentSuggestions) {
const { identifierTypePrediction, logicalTypePrediction } = suggestion;
// The order of the array supplied to getFieldSuggestions is importance to it's order of operations
// the last element in the array takes highest precedence: think Object.assign

View File

@ -260,6 +260,26 @@ export default Component.extend({
return getWithDefault(this, 'complianceInfo.modifiedTime', 0) * 1000;
}),
/**
* Checks that suggested values postdate the last save date or that suggestions exist
* @type {boolean}
*/
hasRecentSuggestions: computed('policyModificationTimeInEpoch', 'complianceSuggestion', function() {
const { policyModificationTimeInEpoch, complianceSuggestion = {} } = getProperties(this, [
'policyModificationTimeInEpoch',
'complianceSuggestion'
]);
const { lastModified: suggestionsLastModified, complianceSuggestions = [] } = complianceSuggestion;
// If modification dates exist, check that the suggestions are newer than the last time the policy was saved
// and we have at least 1 suggestion, otherwise check that the count of suggestions is at least 1
if (policyModificationTimeInEpoch && suggestionsLastModified) {
return complianceSuggestions.length && suggestionsLastModified > policyModificationTimeInEpoch;
}
return !!complianceSuggestions.length;
}),
/**
* @type {Boolean} cached boolean flag indicating that fields do contain a `kafka type`
* tracking header.
@ -438,9 +458,9 @@ export default Component.extend({
* happens only once and is cached
* @type {Ember.computed}
*/
identifierFieldToSuggestion: computed('complianceSuggestions', function() {
identifierFieldToSuggestion: computed('complianceSuggestion', function() {
const identifierFieldToSuggestion = {};
const complianceSuggestions = getWithDefault(this, 'complianceSuggestions', []);
const complianceSuggestions = getWithDefault(this, 'complianceSuggestion.complianceSuggestions', []);
// If the compliance suggestions array contains suggestions the create reduced map,
// otherwise, ignore
if (complianceSuggestions.length) {

View File

@ -170,7 +170,7 @@ export default Route.extend({
* @return {Promise.<void>}
*/
(async id => {
const [columns, compliance, complianceSuggestions] = await Promise.all([
const [columns, compliance, complianceSuggestion] = await Promise.all([
getDatasetColumn(id),
datasetComplianceFor(id),
datasetComplianceSuggestionsFor(id)
@ -179,7 +179,7 @@ export default Route.extend({
setProperties(controller, {
complianceInfo,
isNewComplianceInfo,
complianceSuggestions,
complianceSuggestion,
schemaFieldNamesMappedToDataTypes: columns
});
})(id);

View File

@ -50,6 +50,9 @@ $color-scheme: (
green: (
green5: rgb(70, 154, 31)
),
orange: (
orange5: rgb(229, 88, 0)
),
blue: (
oxford: rgb(53, 75, 87),
curious: rgb(26, 161, 217),

View File

@ -1,4 +1,4 @@
/// Contains variables applicable to application components
/// Stores the color for the compliance suggestions indicator.
$compliance-suggestion-hint: set-color(green, green5);
$compliance-suggestion-hint: set-color(orange, orange5);

View File

@ -62,7 +62,7 @@
<button
{{action "onComplianceDownloadJson"}}
class="nacho-button nacho-button--large-inverse secondary-actions__action">
Download as a JSON file
Download compliance metadata
</button>
{{/unless}}
{{/unless}}
@ -75,7 +75,9 @@
<section class="metadata-prompt">
<header class="metadata-prompt__header">
<p>
Does this dataset contain the following types of Member data?
{{if isEditing
"Does this dataset contain the following types of Member data?"
"Types of member data contained in this dataset"}}
<!--TODO: DSS-6716-->
<!-- DRY out with wrapper component that takes the link as an attribute-->
@ -186,8 +188,8 @@
<section class="metadata-prompt">
<header class="metadata-prompt__header">
<p>
Do fields in the schema contain the ID of a member (e.g. id, urn,
etcetera) and what are the formats of the fields in the schema?
{{if isEditing "Do fields in the schema contain the ID of a member (e.g. id, urn,
etcetera) and what are the formats of the fields in the schema?" "Field formats in the schema"}}
<a
target="_blank"
href="http://go/gdpr-taxonomy#MetadataTaxonomyforDataSets-Field-levelDataTypelists">
@ -214,8 +216,8 @@
filterBy=filterBy
sortDirection=sortDirection
tableRowComponent='dataset-compliance-row'
searchTerm=searchTerm as |table|
}}
searchTerm=searchTerm as |table|}}
<caption>
<input
type="text"
@ -223,7 +225,14 @@
placeholder="Search fields"
value="{{table.searchTerm}}"
oninput={{action table.filterDidChange value="target.value"}}>
{{#if hasRecentSuggestions}}
<span class="dataset-compliance-fields__has-suggestions">
{{complianceSuggestion.complianceSuggestions.length}} fields to be reviewed
</span>
{{/if}}
</caption>
{{#table.head as |head|}}
{{#head.column class="dataset-compliance-fields__notification-column"}}{{/head.column}}
{{#head.column columnName="identifierField"}}Field{{/head.column}}
@ -272,11 +281,13 @@
</sup>
{{/head.column}}
{{/table.head}}
{{#table.body as |body|}}
{{#each (sort-by table.sortBy table.data) as |field|}}
{{#body.row
field=field
class=(if field.suggestion "dataset-compliance-fields__has-suggestions")
class=(if (and hasRecentSuggestions field.suggestion) "dataset-compliance-fields__has-suggestions")
hasRecentSuggestions=hasRecentSuggestions
onFieldLogicalTypeChange=(action 'onFieldLogicalTypeChange')
onFieldClassificationChange=(action 'onFieldClassificationChange')
onSuggestionIntent=(action 'onFieldSuggestionIntentChange')
@ -305,8 +316,10 @@
{{#row.cell}}
{{#if row.suggestion}}
{{row.suggestion.confidence}}%
{{auto-suggest-action type="accept" action=(action row.onSuggestionAction)}}
{{auto-suggest-action action=(action row.onSuggestionAction)}}
{{#if isEditing}}
{{auto-suggest-action type="accept" action=(action row.onSuggestionAction)}}
{{auto-suggest-action action=(action row.onSuggestionAction)}}
{{/if}}
{{else}}
{{#if row.suggestionAuthority}}
{{capitalize row.suggestionResolution}}
@ -351,6 +364,7 @@
{{/body.row}}
{{/each}}
{{/table.body}}
{{/dataset-table}}
{{/if}}
</div>

View File

@ -222,7 +222,7 @@
{{dataset-compliance
datasetName=model.name
complianceInfo=complianceInfo
complianceSuggestions=complianceSuggestions
complianceSuggestion=complianceSuggestion
isNewComplianceInfo=isNewComplianceInfo
schemaFieldNamesMappedToDataTypes=schemaFieldNamesMappedToDataTypes
onSave=(action "savePrivacyCompliancePolicy")

View File

@ -65,24 +65,28 @@ const datasetComplianceFor = async (id: number): Promise<{ isNewComplianceInfo:
* @param {number} id the id of the dataset
* @return {Promise<Array<IComplianceSuggestion>>}
*/
const datasetComplianceSuggestionsFor = async (id: number): Promise<Array<IComplianceSuggestion>> => {
const datasetComplianceSuggestionsFor = async (
id: number
): Promise<{ complianceSuggestions: Array<IComplianceSuggestion>; lastModified: number | void }> => {
const response: IComplianceSuggestionResponse = await Promise.resolve(
getJSON(datasetComplianceSuggestionsUrlById(id))
);
const { status, autoClassification = { classificationResult: '[]' } } = response;
const { status, autoClassification = { classificationResult: '[]', lastModified: 0 } } = response;
let complianceSuggestions: Array<IComplianceSuggestion> = [];
let lastModifiedDate;
if (status === ApiStatus.OK) {
const { classificationResult } = autoClassification;
const { classificationResult, lastModified } = autoClassification;
try {
complianceSuggestions = [...JSON.parse(classificationResult)];
lastModifiedDate = lastModified;
} catch (e) {
throw e;
}
}
return complianceSuggestions;
return { complianceSuggestions, lastModified: lastModifiedDate };
};
export { datasetsUrlRoot, datasetComplianceFor, datasetComplianceSuggestionsFor, datasetComplianceUrlById };