mirror of
https://github.com/datahub-project/datahub.git
synced 2025-09-25 09:00:50 +00:00
5408 Prevents adding a new field if the field identifier type is already None, adds an error indicator if the field identifier type has a None type added when it already has another that is not None
This commit is contained in:
parent
d4e2aeb9c0
commit
895a252006
@ -1,7 +1,7 @@
|
||||
import Component from '@ember/component';
|
||||
import ComputedProperty from '@ember/object/computed';
|
||||
import { get, getProperties, computed } from '@ember/object';
|
||||
import { ComplianceFieldIdValue, idTypeFieldHasLogicalType, isFieldIdType } from 'wherehows-web/constants';
|
||||
import { ComplianceFieldIdValue, idTypeFieldHasLogicalType, isTagIdType } from 'wherehows-web/constants';
|
||||
import {
|
||||
IComplianceChangeSet,
|
||||
IComplianceFieldFormatOption,
|
||||
@ -61,7 +61,7 @@ export default class DatasetComplianceFieldTag extends Component {
|
||||
this: DatasetComplianceFieldTag
|
||||
): boolean {
|
||||
const { tag, complianceDataTypes } = getProperties(this, ['tag', 'complianceDataTypes']);
|
||||
return isFieldIdType(complianceDataTypes)(tag);
|
||||
return isTagIdType(complianceDataTypes)(tag);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -69,27 +69,25 @@ export default class DatasetComplianceFieldTag extends Component {
|
||||
* @type ComputedProperty<Array<IComplianceFieldFormatOption>>
|
||||
* @memberof DatasetComplianceFieldTag
|
||||
*/
|
||||
fieldFormats: ComputedProperty<Array<IComplianceFieldFormatOption>> = computed(
|
||||
'isIdType',
|
||||
'complianceDataTypes',
|
||||
function(this: DatasetComplianceFieldTag): Array<IComplianceFieldFormatOption> {
|
||||
const identifierType = get(this, 'tag')['identifierType'] || '';
|
||||
const { isIdType, complianceDataTypes } = getProperties(this, ['isIdType', 'complianceDataTypes']);
|
||||
const complianceDataType = complianceDataTypes.findBy('id', identifierType);
|
||||
let fieldFormatOptions: Array<IComplianceFieldFormatOption> = [];
|
||||
fieldFormats: ComputedProperty<Array<IComplianceFieldFormatOption>> = computed('isIdType', function(
|
||||
this: DatasetComplianceFieldTag
|
||||
): Array<IComplianceFieldFormatOption> {
|
||||
const identifierType = get(this, 'tag')['identifierType'] || '';
|
||||
const { isIdType, complianceDataTypes } = getProperties(this, ['isIdType', 'complianceDataTypes']);
|
||||
const complianceDataType = complianceDataTypes.findBy('id', identifierType);
|
||||
let fieldFormatOptions: Array<IComplianceFieldFormatOption> = [];
|
||||
|
||||
if (complianceDataType && isIdType) {
|
||||
const supportedFieldFormats = complianceDataType.supportedFieldFormats || [];
|
||||
const supportedFormatOptions = supportedFieldFormats.map(format => ({ value: format, label: format }));
|
||||
if (complianceDataType && isIdType) {
|
||||
const supportedFieldFormats = complianceDataType.supportedFieldFormats || [];
|
||||
const supportedFormatOptions = supportedFieldFormats.map(format => ({ value: format, label: format }));
|
||||
|
||||
return supportedFormatOptions.length
|
||||
? [unSelectedFieldFormatValue, ...supportedFormatOptions]
|
||||
: supportedFormatOptions;
|
||||
}
|
||||
|
||||
return fieldFormatOptions;
|
||||
return supportedFormatOptions.length
|
||||
? [unSelectedFieldFormatValue, ...supportedFormatOptions]
|
||||
: supportedFormatOptions;
|
||||
}
|
||||
);
|
||||
|
||||
return fieldFormatOptions;
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks if the field format / logical type for this tag is missing, if the field is of ID type
|
||||
|
@ -8,15 +8,17 @@ import {
|
||||
ISuggestedFieldTypeValues
|
||||
} from 'wherehows-web/typings/app/dataset-compliance';
|
||||
import {
|
||||
changeSetFieldsRequiringReview,
|
||||
changeSetReviewableAttributeTriggers,
|
||||
ComplianceFieldIdValue,
|
||||
complianceFieldChangeSetItemFactory,
|
||||
SuggestionIntent
|
||||
SuggestionIntent,
|
||||
fieldTagsRequiringReview,
|
||||
tagsHaveNoneAndNotNoneType,
|
||||
tagsHaveNoneType
|
||||
} from 'wherehows-web/constants';
|
||||
import { getTagSuggestions } from 'wherehows-web/utils/datasets/compliance-suggestions';
|
||||
import { IColumnFieldProps } from 'wherehows-web/typings/app/dataset-columns';
|
||||
import { isFieldTagged } from 'wherehows-web/constants/dataset-compliance';
|
||||
import { fieldTagsHaveIdentifierType } from 'wherehows-web/constants/dataset-compliance';
|
||||
import { IComplianceDataType } from 'wherehows-web/typings/api/list/compliance-datatypes';
|
||||
|
||||
export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
@ -75,7 +77,10 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
`fieldChangeSet.@each.{${changeSetReviewableAttributeTriggers}}`,
|
||||
'complianceDataTypes',
|
||||
function(this: DatasetComplianceRollupRow): boolean {
|
||||
return !!changeSetFieldsRequiringReview(get(this, 'complianceDataTypes'))(get(this, 'fieldChangeSet')).length;
|
||||
const tags = get(this, 'fieldChangeSet');
|
||||
const { length } = fieldTagsRequiringReview(get(this, 'complianceDataTypes'))(get(this, 'identifierField'))(tags);
|
||||
|
||||
return !!length || tagsHaveNoneAndNotNoneType(tags);
|
||||
}
|
||||
);
|
||||
|
||||
@ -133,6 +138,16 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
*/
|
||||
hasSingleTag: ComputedProperty<boolean> = equal('fieldChangeSet.length', 1);
|
||||
|
||||
/**
|
||||
* Checks if any of the tags on this field have a ComplianceFieldIdValue.None identifierType
|
||||
* @type {ComputedProperty<boolean>}
|
||||
*/
|
||||
hasNoneTag: ComputedProperty<boolean> = computed('fieldChangeSet', function(
|
||||
this: DatasetComplianceRollupRow
|
||||
): boolean {
|
||||
return tagsHaveNoneType(get(this, 'fieldChangeSet'));
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks if any of the field tags for this row are dirty
|
||||
* @type {ComputedProperty<boolean>}
|
||||
@ -244,7 +259,7 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
'fieldProps'
|
||||
]);
|
||||
|
||||
if (isFieldTagged(fieldChangeSet)) {
|
||||
if (fieldTagsHaveIdentifierType(fieldChangeSet)) {
|
||||
onFieldTagAdded(
|
||||
complianceFieldChangeSetItemFactory({
|
||||
identifierField,
|
||||
@ -293,7 +308,7 @@ export default class DatasetComplianceRollupRow extends Component.extend({
|
||||
// Accept the suggestion for either identifierType and/or logicalType
|
||||
if (suggestion && intent === SuggestionIntent.accept) {
|
||||
const { identifierType, logicalType } = suggestion;
|
||||
const updateDefault = hasSingleTag && !isFieldTagged(get(this, 'fieldChangeSet'));
|
||||
const updateDefault = hasSingleTag && !fieldTagsHaveIdentifierType(get(this, 'fieldChangeSet'));
|
||||
|
||||
if (identifierType && !suggestedValuesInChangeSet.includes(identifierType)) {
|
||||
if (updateDefault) {
|
||||
|
@ -8,8 +8,8 @@ import {
|
||||
ComplianceFieldIdValue,
|
||||
SuggestionIntent,
|
||||
getDefaultSecurityClassification,
|
||||
fieldChangeSetRequiresReview,
|
||||
isFieldIdType,
|
||||
tagNeedsReview,
|
||||
isTagIdType,
|
||||
changeSetReviewableAttributeTriggers,
|
||||
idTypeFieldHasLogicalType
|
||||
} from 'wherehows-web/constants';
|
||||
@ -151,7 +151,7 @@ export default class DatasetComplianceRow extends DatasetTableRow {
|
||||
isReviewRequested = computed(`field.{${changeSetReviewableAttributeTriggers}}`, 'complianceDataTypes', function(
|
||||
this: DatasetComplianceRow
|
||||
): boolean {
|
||||
return fieldChangeSetRequiresReview(get(this, 'complianceDataTypes'))(get(this, 'field'));
|
||||
return tagNeedsReview(get(this, 'complianceDataTypes'))(get(this, 'field'));
|
||||
});
|
||||
|
||||
/**
|
||||
@ -292,7 +292,7 @@ export default class DatasetComplianceRow extends DatasetTableRow {
|
||||
this: DatasetComplianceRow
|
||||
): boolean {
|
||||
const { field, complianceDataTypes } = getProperties(this, ['field', 'complianceDataTypes']);
|
||||
return isFieldIdType(complianceDataTypes)(field);
|
||||
return isTagIdType(complianceDataTypes)(field);
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -24,10 +24,9 @@ import {
|
||||
PurgePolicy,
|
||||
getSupportedPurgePolicies,
|
||||
mergeComplianceEntitiesWithSuggestions,
|
||||
getFieldsRequiringReview,
|
||||
isFieldIdType,
|
||||
tagsRequiringReview,
|
||||
isTagIdType,
|
||||
idTypeFieldsHaveLogicalType,
|
||||
changeSetFieldsRequiringReview,
|
||||
changeSetReviewableAttributeTriggers,
|
||||
mapSchemaColumnPropsToCurrentPrivacyPolicy,
|
||||
foldComplianceChangeSets,
|
||||
@ -110,6 +109,12 @@ export default class DatasetCompliance extends Component {
|
||||
showAllDatasetMemberData: boolean;
|
||||
complianceInfo: void | IComplianceInfo;
|
||||
|
||||
/**
|
||||
* References the ComplianceFieldIdValue enum
|
||||
* @type {ComplianceFieldIdValue}
|
||||
*/
|
||||
ComplianceFieldIdValue = ComplianceFieldIdValue;
|
||||
|
||||
/**
|
||||
* Suggested values for compliance types e.g. identifier type and/or logical type
|
||||
* @type {IComplianceSuggestion | void}
|
||||
@ -691,7 +696,7 @@ export default class DatasetCompliance extends Component {
|
||||
]);
|
||||
|
||||
return get(this, 'fieldReviewOption') === 'showReview'
|
||||
? changeSetFieldsRequiringReview(complianceDataTypes)(changeSet)
|
||||
? tagsRequiringReview(complianceDataTypes)(changeSet)
|
||||
: changeSet;
|
||||
}
|
||||
);
|
||||
@ -718,21 +723,20 @@ export default class DatasetCompliance extends Component {
|
||||
};
|
||||
|
||||
/**
|
||||
* Invokes external action with flag indicating that a field in the changeSet requires user review
|
||||
* Invokes external action with flag indicating that a field in the tags requires user review
|
||||
* @param {Array<IComplianceDataType>} complianceDataTypes
|
||||
* @param {Array<IComplianceChangeSet>} changeSet
|
||||
* @param {Array<IComplianceChangeSet>} tags
|
||||
*/
|
||||
notifyHandlerOfFieldsRequiringReview = (
|
||||
complianceDataTypes: Array<IComplianceDataType>,
|
||||
changeSet: Array<IComplianceChangeSet>
|
||||
tags: Array<IComplianceChangeSet>
|
||||
) => {
|
||||
// adding assertions for run-loop callback invocation, because static type checks are bypassed
|
||||
assert('expected complianceDataTypes to be of type `array`', Array.isArray(complianceDataTypes));
|
||||
assert('expected changeSet to be of type `array`', Array.isArray(changeSet));
|
||||
assert('expected tags to be of type `array`', Array.isArray(tags));
|
||||
|
||||
const hasChangeSetDrift = !!tagsRequiringReview(complianceDataTypes)(tags).length;
|
||||
|
||||
const hasChangeSetDrift = getFieldsRequiringReview(complianceDataTypes)(changeSet).some(
|
||||
(isReviewRequired: boolean) => isReviewRequired
|
||||
);
|
||||
this.notifyOnChangeSetRequiresReview(hasChangeSetDrift);
|
||||
};
|
||||
|
||||
@ -745,8 +749,7 @@ export default class DatasetCompliance extends Component {
|
||||
`compliancePolicyChangeSet.@each.{${changeSetReviewableAttributeTriggers}}`,
|
||||
'complianceDataTypes',
|
||||
function(this: DatasetCompliance): number {
|
||||
return changeSetFieldsRequiringReview(get(this, 'complianceDataTypes'))(get(this, 'compliancePolicyChangeSet'))
|
||||
.length;
|
||||
return tagsRequiringReview(get(this, 'complianceDataTypes'))(get(this, 'compliancePolicyChangeSet')).length;
|
||||
}
|
||||
);
|
||||
|
||||
@ -857,7 +860,7 @@ export default class DatasetCompliance extends Component {
|
||||
validateFields(this: DatasetCompliance) {
|
||||
const { notify } = get(this, 'notifications');
|
||||
const { complianceEntities = [] } = get(this, 'complianceInfo') || {};
|
||||
const idTypeComplianceEntities = complianceEntities.filter(isFieldIdType(get(this, 'complianceDataTypes')));
|
||||
const idTypeComplianceEntities = complianceEntities.filter(isTagIdType(get(this, 'complianceDataTypes')));
|
||||
|
||||
// Validation operations
|
||||
const idFieldsHaveValidLogicalType: boolean = idTypeFieldsHaveLogicalType(idTypeComplianceEntities);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { PurgePolicy } from 'wherehows-web/constants/index';
|
||||
import { IComplianceEntity, IComplianceInfo } from 'wherehows-web/typings/api/datasets/compliance';
|
||||
import { IComplianceDataType } from 'wherehows-web/typings/api/list/compliance-datatypes';
|
||||
import { arrayEvery, arrayFilter, arrayMap, arrayReduce } from 'wherehows-web/utils/array';
|
||||
import { arrayEvery, arrayFilter, arrayMap, arrayReduce, arraySome } from 'wherehows-web/utils/array';
|
||||
import { fleece, hasEnumerableKeys } from 'wherehows-web/utils/object';
|
||||
import { lastSeenSuggestionInterval } from 'wherehows-web/constants/metadata-acquisition';
|
||||
import { decodeUrn } from 'wherehows-web/utils/validators/urn';
|
||||
@ -20,6 +20,7 @@ import {
|
||||
ISchemaWithPolicyTagsReducingFn
|
||||
} from 'wherehows-web/typings/app/dataset-columns';
|
||||
import { IDatasetColumn } from 'wherehows-web/typings/api/datasets/columns';
|
||||
import { ComplianceFieldIdValue } from 'wherehows-web/constants/datasets/compliance';
|
||||
|
||||
/**
|
||||
* Defines a map of values for the compliance policy on a dataset
|
||||
@ -165,22 +166,17 @@ const isRecentSuggestion = (
|
||||
* Checks if a compliance policy changeSet field requires user attention: if a suggestion
|
||||
* is available but the user has not indicated intent or a policy for the field does not currently exist remotely
|
||||
* and the related field changeSet has not been modified on the client and isn't readonly
|
||||
* @param {boolean} isDirty
|
||||
* @return {boolean}
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @param {Array<IComplianceDataType>} complianceDataTypes
|
||||
* @return {(changeSet: IComplianceChangeSet) => boolean}
|
||||
* @return {(tag: IComplianceChangeSet) => boolean}
|
||||
*/
|
||||
const fieldChangeSetRequiresReview = (complianceDataTypes: Array<IComplianceDataType>) =>
|
||||
const tagNeedsReview = (complianceDataTypes: Array<IComplianceDataType>) =>
|
||||
/**
|
||||
*
|
||||
* @param {IComplianceChangeSet} changeSet
|
||||
* @param {IComplianceChangeSet} tag
|
||||
* @return {boolean}
|
||||
*/
|
||||
(changeSet: IComplianceChangeSet): boolean => {
|
||||
const { isDirty, suggestion, privacyPolicyExists, suggestionAuthority, readonly, identifierType } = changeSet;
|
||||
(tag: IComplianceChangeSet): boolean => {
|
||||
const { isDirty, suggestion, privacyPolicyExists, suggestionAuthority, readonly, identifierType } = tag;
|
||||
let isReviewRequired = false;
|
||||
|
||||
if (readonly) {
|
||||
@ -192,33 +188,69 @@ const fieldChangeSetRequiresReview = (complianceDataTypes: Array<IComplianceData
|
||||
isReviewRequired = isReviewRequired || !suggestionAuthority;
|
||||
}
|
||||
|
||||
if (isFieldIdType(complianceDataTypes)(changeSet)) {
|
||||
isReviewRequired = isReviewRequired || !idTypeFieldHasLogicalType(changeSet);
|
||||
if (isTagIdType(complianceDataTypes)(tag)) {
|
||||
isReviewRequired = isReviewRequired || !idTypeFieldHasLogicalType(tag);
|
||||
}
|
||||
// If either the privacy policy doesn't exists, or user hasn't made changes, then review is required
|
||||
return isReviewRequired || !(privacyPolicyExists || isDirty);
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that a compliance field tag has an identifierType of ComplianceFieldIdValue.None
|
||||
* @param {ComplianceFieldIdValue | NonIdLogicalType | null} identifierType
|
||||
* @return {boolean}
|
||||
*/
|
||||
const isTagNoneType = ({ identifierType }: IComplianceChangeSet): boolean =>
|
||||
identifierType === ComplianceFieldIdValue.None;
|
||||
|
||||
/**
|
||||
* Asserts the inverse of isTagNoneType
|
||||
* @param {IComplianceChangeSet} tag
|
||||
* @return {boolean}
|
||||
*/
|
||||
const isTagNotNoneType = (tag: IComplianceChangeSet): boolean => !isTagNoneType(tag);
|
||||
|
||||
/**
|
||||
* Asserts that a list of tags have at least 1 type of ComplianceFieldIdValue.None
|
||||
* @type {(array: Array<IComplianceChangeSet>) => boolean}
|
||||
*/
|
||||
const tagsHaveNoneType = arraySome(isTagNoneType);
|
||||
|
||||
/**
|
||||
* Asserts that a list of tags have at least 1 type that is not of ComplianceFieldIdValue.None
|
||||
* @type {(array: Array<IComplianceChangeSet>) => boolean}
|
||||
*/
|
||||
const tagsHaveNotNoneType = arraySome(isTagNotNoneType);
|
||||
|
||||
/**
|
||||
* Asserts that a list of tags have a type of ComplianceFieldIdValue.None and not ComplianceFieldIdValue.None
|
||||
* @param {Array<IComplianceChangeSet>} tags
|
||||
* @return {boolean}
|
||||
*/
|
||||
const tagsHaveNoneAndNotNoneType = (tags: Array<IComplianceChangeSet>) =>
|
||||
tagsHaveNoneType(tags) && tagsHaveNotNoneType(tags);
|
||||
|
||||
/**
|
||||
* Asserts that a tag / change set item has an identifier type that is in the list of compliance data types
|
||||
* @param {Array<IComplianceDataType>} [complianceDataTypes=[]]
|
||||
*/
|
||||
const isFieldIdType = (complianceDataTypes: Array<IComplianceDataType> = []) => ({
|
||||
const isTagIdType = (complianceDataTypes: Array<IComplianceDataType> = []) => ({
|
||||
identifierType
|
||||
}: IComplianceChangeSet): boolean => getIdTypeDataTypes(complianceDataTypes).includes(<string>identifierType);
|
||||
|
||||
/**
|
||||
* Asserts that a tag has a value for it's identifierType property
|
||||
* Asserts that a tag has a value for it's identifierType property and the identifierType is not ComplianceFieldIdValue.None
|
||||
* @param {IComplianceChangeSet} {identifierType}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const tagHasIdentifierType = ({ identifierType }: IComplianceChangeSet): boolean => !!identifierType;
|
||||
const tagHasIdentifierType = ({ identifierType }: IComplianceChangeSet): boolean =>
|
||||
!!identifierType && identifierType !== ComplianceFieldIdValue.None;
|
||||
|
||||
/**
|
||||
* Takes an array of compliance change sets and checks that each item has an identifierType
|
||||
* @type {(array: IComplianceChangeSet[]) => boolean}
|
||||
*/
|
||||
const isFieldTagged = arrayEvery(tagHasIdentifierType);
|
||||
const fieldTagsHaveIdentifierType = arrayEvery(tagHasIdentifierType);
|
||||
|
||||
/**
|
||||
* Asserts that a compliance entity has a logical type
|
||||
@ -232,19 +264,31 @@ const idTypeFieldHasLogicalType = ({ logicalType }: IComplianceEntity): boolean
|
||||
* @type {(array: IComplianceEntity[]) => boolean}
|
||||
*/
|
||||
const idTypeFieldsHaveLogicalType = arrayEvery(idTypeFieldHasLogicalType);
|
||||
/**
|
||||
* Gets the fields requiring review
|
||||
* @type {(array: Array<IComplianceChangeSet>) => Array<boolean>}
|
||||
*/
|
||||
const getFieldsRequiringReview = (complianceDataTypes: Array<IComplianceDataType>) =>
|
||||
arrayMap(fieldChangeSetRequiresReview(complianceDataTypes));
|
||||
|
||||
/**
|
||||
* Returns a list of changeSet fields that requires user attention
|
||||
* @type {function({}): Array<{ isDirty, suggestion, privacyPolicyExists, suggestionAuthority, identifierType }>}
|
||||
* Gets the tags for a specific identifier field
|
||||
* @param {string} identifierField
|
||||
* @return {(array: Array<IComplianceChangeSet>) => Array<IComplianceChangeSet>}
|
||||
*/
|
||||
const changeSetFieldsRequiringReview = (complianceDataTypes: Array<IComplianceDataType>) =>
|
||||
arrayFilter<IComplianceChangeSet>(fieldChangeSetRequiresReview(complianceDataTypes));
|
||||
const tagsForIdentifierField = (identifierField: string) =>
|
||||
arrayFilter(isSchemaFieldTag<IComplianceChangeSet>(identifierField));
|
||||
|
||||
/**
|
||||
* Returns a list of changeSet tags that requires user attention
|
||||
* @param {Array<IComplianceDataType>} complianceDataTypes
|
||||
* @return {(array: Array<IComplianceChangeSet>) => Array<IComplianceChangeSet>}
|
||||
*/
|
||||
const tagsRequiringReview = (complianceDataTypes: Array<IComplianceDataType>) =>
|
||||
arrayFilter<IComplianceChangeSet>(tagNeedsReview(complianceDataTypes));
|
||||
|
||||
/**
|
||||
* Lists the tags for a specific identifier field that need to be reviewed
|
||||
* @param {Array<IComplianceDataType>} complianceDataTypes
|
||||
* @return {(identifierField: string) => (tags: Array<IComplianceChangeSet>) => Array<IComplianceChangeSet>}
|
||||
*/
|
||||
const fieldTagsRequiringReview = (complianceDataTypes: Array<IComplianceDataType>) => (identifierField: string) => (
|
||||
tags: Array<IComplianceChangeSet>
|
||||
) => tagsRequiringReview(complianceDataTypes)(tagsForIdentifierField(identifierField)(tags));
|
||||
|
||||
/**
|
||||
* Extracts a suggestion for a field from a suggestion map and merges a compliance entity with the suggestion
|
||||
@ -371,8 +415,9 @@ const complianceFieldChangeSetItemFactory = ({
|
||||
* @param {string} identifierFieldMatch the field name to match to the IComplianceEntity
|
||||
* @return {({ identifierField }: IComplianceEntity) => boolean}
|
||||
*/
|
||||
const isSchemaFieldTag = (identifierFieldMatch: string) => ({ identifierField }: IComplianceEntity): boolean =>
|
||||
identifierFieldMatch === identifierField;
|
||||
const isSchemaFieldTag = <T extends { identifierField: string }>(identifierFieldMatch: string) => ({
|
||||
identifierField
|
||||
}: T): boolean => identifierFieldMatch === identifierField;
|
||||
|
||||
/**
|
||||
* Creates an instance of a compliance entity with client side metadata about the entity
|
||||
@ -408,7 +453,7 @@ const schemaFieldsWithPolicyTagsReducingFn: ISchemaWithPolicyTagsReducingFn = (
|
||||
{ identifierField, dataType }: IColumnFieldProps
|
||||
): ISchemaFieldsToPolicy => {
|
||||
let complianceEntitiesWithMetadata: Array<IComplianceEntityWithMetadata>;
|
||||
let schemaFieldTags = arrayFilter(isSchemaFieldTag(identifierField))(currentEntities);
|
||||
let schemaFieldTags = arrayFilter(isSchemaFieldTag<IComplianceEntity>(identifierField))(currentEntities);
|
||||
|
||||
schemaFieldTags = schemaFieldTags.length ? schemaFieldTags : [complianceFieldTagFactory(identifierField)];
|
||||
complianceEntitiesWithMetadata = arrayMap(complianceEntityWithMetadata(policyModificationTime, dataType))(
|
||||
@ -457,17 +502,19 @@ export {
|
||||
filterEditableEntities,
|
||||
isAutoGeneratedPolicy,
|
||||
removeReadonlyAttr,
|
||||
fieldChangeSetRequiresReview,
|
||||
isFieldIdType,
|
||||
tagNeedsReview,
|
||||
isTagIdType,
|
||||
mergeComplianceEntitiesWithSuggestions,
|
||||
isRecentSuggestion,
|
||||
getFieldsRequiringReview,
|
||||
tagsRequiringReview,
|
||||
tagsHaveNoneType,
|
||||
fieldTagsRequiringReview,
|
||||
tagsHaveNoneAndNotNoneType,
|
||||
createInitialComplianceInfo,
|
||||
getIdTypeDataTypes,
|
||||
isFieldTagged,
|
||||
fieldTagsHaveIdentifierType,
|
||||
idTypeFieldHasLogicalType,
|
||||
idTypeFieldsHaveLogicalType,
|
||||
changeSetFieldsRequiringReview,
|
||||
changeSetReviewableAttributeTriggers,
|
||||
mapSchemaColumnPropsToCurrentPrivacyPolicy,
|
||||
foldComplianceChangeSets,
|
||||
|
@ -5,6 +5,7 @@
|
||||
identifierField=identifierField
|
||||
dataType=dataType
|
||||
isIdType=isIdType
|
||||
hasNoneTag=hasNoneTag
|
||||
fieldFormats=fieldFormats
|
||||
fieldProps=fieldProps
|
||||
suggestion=suggestion
|
||||
|
@ -154,7 +154,6 @@
|
||||
{{row.suggestion.confidence}}%
|
||||
|
||||
{{#if isEditing}}
|
||||
|
||||
{{#if row.suggestionResolution}}
|
||||
<div class="dataset-compliance-fields__resolution {{if (eq row.suggestionResolution 'Accepted')
|
||||
'dataset-compliance-fields__resolution--ok'}}">
|
||||
@ -184,7 +183,7 @@
|
||||
{{/row.cell}}
|
||||
|
||||
{{#row.cell}}
|
||||
{{#if (and isEditing (not row.isReadonly))}}
|
||||
{{#if (and isEditing (and (not row.isReadonly) (not row.hasNoneTag)))}}
|
||||
<button
|
||||
class="nacho-button nacho-button--tertiary dataset-compliance-fields__add-field"
|
||||
onclick={{action row.onAddFieldTag}}>
|
||||
@ -236,6 +235,7 @@
|
||||
values=complianceFieldIdDropdownOptions
|
||||
selected=(readonly tag.identifierType)
|
||||
selectionDidChange=(action tagRowComponent.tagIdentifierTypeDidChange)
|
||||
class=(if (and row.hasNoneTag (not-eq tag.identifierType ComplianceFieldIdValue.None)) "dataset-compliance-fields--missing-selection")
|
||||
}}
|
||||
</div>
|
||||
{{/row.cell}}
|
||||
|
@ -23,6 +23,15 @@ const arrayFilter = <T>(filtrationFunction: (param: T) => boolean): ((array: Arr
|
||||
const arrayEvery = <T>(filter: (param: T) => boolean): ((array: Array<T>) => boolean) => (array = []) =>
|
||||
array.every(filter);
|
||||
|
||||
/**
|
||||
* Type safe utility `iterate-first data-last` function for array some
|
||||
* @template T
|
||||
* @param {(param: T) => boolean} filter
|
||||
* @return {(array: Array<T>) => boolean}
|
||||
*/
|
||||
const arraySome = <T>(filter: (param: T) => boolean): ((array: Array<T>) => boolean) => (array = []) =>
|
||||
array.some(filter);
|
||||
|
||||
/**
|
||||
* Composable reducer abstraction, curries a reducing iteratee and returns a reducing function that takes a list
|
||||
* @template U
|
||||
@ -51,4 +60,4 @@ const isListUnique = <T>(list: Array<T> = []): boolean => new Set(list).size ===
|
||||
*/
|
||||
const compact = <T>(list: Array<T> = []): Array<T> => list.filter(item => item);
|
||||
|
||||
export { arrayMap, arrayFilter, arrayReduce, isListUnique, compact, arrayEvery };
|
||||
export { arrayMap, arrayFilter, arrayReduce, isListUnique, compact, arrayEvery, arraySome };
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
PurgePolicy,
|
||||
createInitialComplianceInfo,
|
||||
isRecentSuggestion,
|
||||
fieldChangeSetRequiresReview
|
||||
tagNeedsReview
|
||||
} from 'wherehows-web/constants';
|
||||
import complianceDataTypes from 'wherehows-web/mirage/fixtures/compliance-data-types';
|
||||
import { mockTimeStamps } from 'wherehows-web/tests/helpers/datasets/compliance-policy/recent-suggestions-constants';
|
||||
@ -46,23 +46,17 @@ test('isRecentSuggestion correctly determines if a suggestion is recent or not',
|
||||
});
|
||||
});
|
||||
|
||||
test('fieldChangeSetRequiresReview exists', function(assert) {
|
||||
assert.ok(typeof fieldChangeSetRequiresReview === 'function', 'fieldChangeSetRequiresReview is a function');
|
||||
test('tagNeedsReview exists', function(assert) {
|
||||
assert.ok(typeof tagNeedsReview === 'function', 'tagNeedsReview is a function');
|
||||
|
||||
assert.ok(
|
||||
typeof fieldChangeSetRequiresReview([])({}) === 'boolean',
|
||||
'fieldChangeSetRequiresReview returns a boolean'
|
||||
);
|
||||
assert.ok(typeof tagNeedsReview([])({}) === 'boolean', 'tagNeedsReview returns a boolean');
|
||||
});
|
||||
|
||||
test('fieldChangeSetRequiresReview correctly determines if a fieldChangeSet requires review', function(assert) {
|
||||
test('tagNeedsReview correctly determines if a fieldChangeSet requires review', function(assert) {
|
||||
assert.expect(mockFieldChangeSets.length);
|
||||
|
||||
mockFieldChangeSets.forEach(changeSet =>
|
||||
assert.ok(
|
||||
fieldChangeSetRequiresReview(complianceDataTypes)(changeSet) === changeSet.__requiresReview__,
|
||||
changeSet.__msg__
|
||||
)
|
||||
assert.ok(tagNeedsReview(complianceDataTypes)(changeSet) === changeSet.__requiresReview__, changeSet.__msg__)
|
||||
);
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user