mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-27 09:58:14 +00:00
Updates dataset compliance component to support tablular format for user updates to compliance data
This commit is contained in:
parent
06c8f44939
commit
bd8799b968
@ -1,163 +1,148 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
const {
|
||||
Component,
|
||||
computed,
|
||||
set,
|
||||
get,
|
||||
getWithDefault
|
||||
} = Ember;
|
||||
|
||||
const complianceListKey = 'privacyCompliancePolicy.compliancePurgeEntities';
|
||||
// List of field formats for security compliance
|
||||
const fieldFormats = [
|
||||
'MEMBER_ID', 'SUBJECT_MEMBER_ID', 'URN', 'SUBJECT_URN', 'COMPANY_ID', 'GROUP_ID', 'CUSTOMER_ID'
|
||||
];
|
||||
|
||||
/**
|
||||
* Computed macro tha checks if a dependentList has a specified privacy type
|
||||
* @param {String} dependentListKey
|
||||
* @param {String} type
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const datasetHasPrivacyIdentifierType = (dependentListKey, type) => {
|
||||
const prop = 'identifierType';
|
||||
|
||||
return computed(`${dependentListKey}.@each.${prop}`, {
|
||||
get() {
|
||||
const list = get(this, dependentListKey) || [];
|
||||
return list.filterBy(prop, type).length > 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default Component.extend({
|
||||
sortColumnWithName: 'name',
|
||||
filterBy: 'name',
|
||||
sortDirection: 'asc',
|
||||
searchTerm: '',
|
||||
complianceType: Ember.computed.alias('privacyCompliancePolicy.complianceType'),
|
||||
get complianceTypes() {
|
||||
return ['CUSTOM_PURGE', 'AUTO_PURGE', 'RETENTION_PURGE', 'NOT_APPLICABLE'].map(complianceType => ({
|
||||
value: complianceType,
|
||||
label: complianceType.replace('_', ' ').toLowerCase().capitalize()
|
||||
}))
|
||||
|
||||
radioSelection: {
|
||||
memberId: null,
|
||||
subjectMemberId: null,
|
||||
urnId: null,
|
||||
orgId: null
|
||||
},
|
||||
|
||||
// Cached list of dataset field names
|
||||
datasetSchemaFieldNames: Ember.computed('datasetSchemaFieldsAndTypes', function () {
|
||||
return this.get('datasetSchemaFieldsAndTypes').mapBy('name');
|
||||
hasMemberId: datasetHasPrivacyIdentifierType(complianceListKey, 'MEMBER_ID'),
|
||||
hasSubjectMemberId: datasetHasPrivacyIdentifierType(complianceListKey, 'SUBJECT_MEMBER_ID'),
|
||||
hasUrnId: datasetHasPrivacyIdentifierType(complianceListKey, 'URN'),
|
||||
hasOrgId: datasetHasPrivacyIdentifierType(complianceListKey, 'COMPANY_ID'),
|
||||
|
||||
isMemberIdSelected: computed.notEmpty('radioSelection.memberId'),
|
||||
isMemberIdSelectedTrue: computed.equal('radioSelection.memberId', true),
|
||||
isSubjectMemberIdSelected: computed.notEmpty('radioSelection.subjectMemberId'),
|
||||
isUrnIdSelected: computed.notEmpty('radioSelection.urnId'),
|
||||
|
||||
showSubjectMemberIdPrompt: computed.equal('radioSelection.memberId', false),
|
||||
showUrnIdPrompt: computed.or('isSubjectMemberIdSelected', 'isMemberIdSelectedTrue'),
|
||||
showOrgIdPrompt: computed.bool('isUrnIdSelected'),
|
||||
|
||||
identifierTypes: ['', ...fieldFormats].map(type => ({
|
||||
value: type,
|
||||
label: type ? type.replace(/_/g, ' ').toLowerCase().capitalize() : 'Please select'
|
||||
})),
|
||||
|
||||
complianceEntities: computed(`${complianceListKey}.[]`, function () {
|
||||
return getWithDefault(this, complianceListKey, []);
|
||||
}),
|
||||
|
||||
matchingFields: Ember.computed('searchTerm', 'datasetSchemaFieldsAndTypes', function () {
|
||||
if (this.get('datasetSchemaFieldsAndTypes')) {
|
||||
const searchTerm = this.get('searchTerm');
|
||||
const matches = $.ui.autocomplete.filter(this.get('datasetSchemaFieldNames'), searchTerm);
|
||||
return matches.map(value => {
|
||||
const {type} = this.get('datasetSchemaFieldsAndTypes').filterBy('name', value).get('firstObject');
|
||||
const dataType = Array.isArray(type) && type.toString().toUpperCase();
|
||||
ownerFieldIdType(field) {
|
||||
const ownerField = getWithDefault(this, complianceListKey, []).filterBy('identifierField', field).shift();
|
||||
return ownerField && ownerField.identifierType;
|
||||
},
|
||||
|
||||
return {
|
||||
value,
|
||||
dataType
|
||||
};
|
||||
});
|
||||
}
|
||||
complianceFields: computed('complianceEntities', 'datasetSchemaFieldsAndTypes', function () {
|
||||
const complianceFieldNames = get(this, 'complianceEntities').mapBy('identifierField');
|
||||
|
||||
return get(this, 'datasetSchemaFieldsAndTypes').map(({name, type}) => ({
|
||||
name,
|
||||
type,
|
||||
hasPrivacyData: complianceFieldNames.includes(name),
|
||||
format: get(this, 'ownerFieldIdType').call(this, name)
|
||||
}));
|
||||
}),
|
||||
|
||||
/**
|
||||
* Aliases compliancePurgeEntities on privacyCompliancePolicy, and transforms each nested comma-delimited identifierField string
|
||||
* into an array of fields that can easily be iterated over. Dependency on each identifierField will update
|
||||
* UI on updates
|
||||
*/
|
||||
purgeEntities: Ember.computed('privacyCompliancePolicy.compliancePurgeEntities.@each.identifierField', function () {
|
||||
const compliancePurgeEntities = this.get('privacyCompliancePolicy.compliancePurgeEntities');
|
||||
// Type ENUM is locally saved in the client.
|
||||
// The user is able to add a values to the identifier types that are not provided in the schema returned by the server.
|
||||
// Values are manually extracted from Nuage schema at develop time
|
||||
const purgeableEntityFieldIdentifierTypes = [
|
||||
'MEMBER_ID', 'SUBJECT_MEMBER_ID', 'URN', 'SUBJECT_URN', 'COMPANY_ID', 'GROUP_ID', 'CUSTOMER_ID'
|
||||
];
|
||||
changeFieldFormat(fieldName, format) {
|
||||
let field = get(this, 'complianceEntities').findBy('identifierField', fieldName);
|
||||
|
||||
// Create an object list for each purgeableEntityFieldIdentifier with a mapping to label and identifierField value
|
||||
return purgeableEntityFieldIdentifierTypes.map(identifierType => {
|
||||
// Find entity with matching identifierType that has been remotely persisted
|
||||
const savedPurgeEntity = compliancePurgeEntities.filterBy('identifierType', identifierType).shift();
|
||||
const label = identifierType.replace(/_/g, ' ').toLowerCase().capitalize();
|
||||
|
||||
return {
|
||||
identifierType,
|
||||
label,
|
||||
identifierField: savedPurgeEntity ? savedPurgeEntity.identifierField.split(',') : []
|
||||
};
|
||||
});
|
||||
}),
|
||||
|
||||
didRender() {
|
||||
const $typeahead = $('#compliance-typeahead') || [];
|
||||
if ($typeahead.length) {
|
||||
this.enableTypeaheadOn($typeahead);
|
||||
if (field && fieldFormats.includes(format)) {
|
||||
return set(field, 'identifierType', format);
|
||||
}
|
||||
},
|
||||
|
||||
enableTypeaheadOn(selector) {
|
||||
selector.autocomplete({
|
||||
minLength: 0,
|
||||
source: request => {
|
||||
const {term = ''} = request;
|
||||
this.set('searchTerm', term);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a compliancePurgeEntity matching the given Id.
|
||||
* @param {string} id value representing the identifierType
|
||||
* @returns {*}
|
||||
*/
|
||||
getPurgeEntity(id) {
|
||||
// There should be only one match in the resulting array
|
||||
return this.get('privacyCompliancePolicy.compliancePurgeEntities')
|
||||
.filterBy('identifierType', id)
|
||||
.get('firstObject');
|
||||
},
|
||||
|
||||
addPurgeEntityToComplianceEntities(identifierType) {
|
||||
this.get('privacyCompliancePolicy.compliancePurgeEntities').addObject({identifierType, identifierField: ''});
|
||||
return this.getPurgeEntity(identifierType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Internal abstraction for adding and removing an Id from an identifierField
|
||||
* @param {string} fieldValue name of identifier to add/remove from identifier type
|
||||
* @param {string} idType the identifierType for a compliancePurgeEntity
|
||||
* @param {string} toggleOperation string representing the operation to be performed
|
||||
* @returns {boolean|*} true on success
|
||||
* @private
|
||||
*/
|
||||
_togglePurgeIdOnIdentifierField(fieldValue, idType, toggleOperation) {
|
||||
function updateIdentifierFieldOn(entity, updatedValue) {
|
||||
return Ember.set(entity, 'identifierField', updatedValue);
|
||||
}
|
||||
|
||||
toggleFieldOnComplianceList(identifierField, toggle) {
|
||||
const complianceList = get(this, 'complianceEntities');
|
||||
const op = {
|
||||
/**
|
||||
* Adds the fieldValue to the specified idType if available, otherwise creates a new compliancePurgeEntity
|
||||
* @param purgeableEntityField
|
||||
* @returns {*|Object} the updated compliancePurgeEntity
|
||||
*/
|
||||
add: (purgeableEntityField = this.addPurgeEntityToComplianceEntities(idType)) => {
|
||||
const currentId = purgeableEntityField.identifierField;
|
||||
const updatedIds = currentId.length ? currentId.split(',').addObject(fieldValue).join(',') : fieldValue;
|
||||
|
||||
return updateIdentifierFieldOn(purgeableEntityField, updatedIds);
|
||||
},
|
||||
/**
|
||||
* Removes the fieldValue from the specified idType if available, otherwise function is no-op
|
||||
* @param purgeableEntityField
|
||||
* @returns {*|Object} the updated compliancePurgeEntity
|
||||
*/
|
||||
remove: (purgeableEntityField) => {
|
||||
if (purgeableEntityField) {
|
||||
const currentId = purgeableEntityField.identifierField;
|
||||
const updatedIds = currentId.length ? currentId.split(',').removeObject(fieldValue).join(',') : '';
|
||||
|
||||
return updateIdentifierFieldOn(purgeableEntityField, updatedIds);
|
||||
add() {
|
||||
if (!complianceList.findBy('identifierField', identifierField)) {
|
||||
return complianceList.setObjects([...complianceList, {identifierField}]);
|
||||
}
|
||||
}
|
||||
}[toggleOperation];
|
||||
},
|
||||
|
||||
return typeof op === 'function' && op(this.getPurgeEntity(idType));
|
||||
remove: () => complianceList.setObjects(complianceList.filter(item => item.identifierField !== identifierField)),
|
||||
}[toggle];
|
||||
|
||||
return typeof op === 'function' && op();
|
||||
},
|
||||
|
||||
ensureTypeContainsFormat: (updatedCompliance) =>
|
||||
updatedCompliance.every(entity => fieldFormats.includes(get(entity, 'identifierType'))),
|
||||
|
||||
actions: {
|
||||
addPurgeId(name, idType) {
|
||||
this._togglePurgeIdOnIdentifierField(name, idType, `add`);
|
||||
onFieldFormatChange({name: fieldName}, {value: format}) {
|
||||
return this.changeFieldFormat(fieldName, format);
|
||||
},
|
||||
|
||||
removePurgeId(name, idType) {
|
||||
this._togglePurgeIdOnIdentifierField(name, idType, `remove`);
|
||||
},
|
||||
onFieldPrivacyChange({name: fieldName, hasPrivacyData}) {
|
||||
const toggle = !hasPrivacyData ? 'add' : 'remove';
|
||||
|
||||
updateComplianceType ({value}) {
|
||||
this.set('privacyCompliancePolicy.complianceType', value);
|
||||
return this.toggleFieldOnComplianceList(fieldName, toggle);
|
||||
},
|
||||
|
||||
saveCompliance () {
|
||||
this.get('onSave')();
|
||||
return false;
|
||||
const allEntitiesHaveValidFormat = this.ensureTypeContainsFormat(get(this, 'complianceEntities'));
|
||||
|
||||
if (allEntitiesHaveValidFormat) {
|
||||
return this.get('onSave')();
|
||||
}
|
||||
},
|
||||
|
||||
// Rolls back changes made to the compliance spec to current
|
||||
// server state
|
||||
resetCompliance () {
|
||||
this.get('onReset')();
|
||||
},
|
||||
|
||||
didChangePrivacyIdentifiable (sectionName, isPrivacyIdentifiable) {
|
||||
const section = {
|
||||
'has-subject-member': 'subjectMemberId',
|
||||
'has-urn': 'urnId',
|
||||
'has-organization': 'orgId',
|
||||
'has-member': 'memberId'
|
||||
}[sectionName];
|
||||
|
||||
return set(this, `radioSelection.${section}`, isPrivacyIdentifiable);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user