From e35d1a0e679bfc6d0b2212e84732956472cf9ff9 Mon Sep 17 00:00:00 2001 From: cptran777 Date: Mon, 1 Oct 2018 13:24:21 -0700 Subject: [PATCH 1/4] Refactor some compliance logic from dataset-compliance to compliance schema-entities --- .../app/components/dataset-compliance.ts | 93 ------------ .../datasets/compliance/schema-entities.ts | 132 +++++++++++++++++- .../components/dataset-compliance.hbs | 16 ++- .../datasets/compliance/schema-entities.hbs | 93 +++++++++++- .../dataset-compliance/-action-bar.hbs | 90 ++++++++++-- .../-dataset-compliance-entities.hbs | 89 ------------ 6 files changed, 310 insertions(+), 203 deletions(-) diff --git a/wherehows-web/app/components/dataset-compliance.ts b/wherehows-web/app/components/dataset-compliance.ts index 44240bc180..8a1295beed 100644 --- a/wherehows-web/app/components/dataset-compliance.ts +++ b/wherehows-web/app/components/dataset-compliance.ts @@ -300,12 +300,6 @@ export default class DatasetCompliance extends Component { * @memberof DatasetCompliance */ schemaless: boolean; - /** - * Tracks the current index of the compliance policy update wizard flow - * @type {number} - * @memberof DatasetCompliance - */ - editStepIndex: number; /** * List of complianceDataType values @@ -393,7 +387,6 @@ export default class DatasetCompliance extends Component { super(...arguments); //sets default values for class fields - this.editStepIndex = initialStepIndex; this.sortColumnWithName || set(this, 'sortColumnWithName', 'identifierField'); this.filterBy || set(this, 'filterBy', '0'); // first element in field type is identifierField this.sortDirection || set(this, 'sortDirection', 'asc'); @@ -404,20 +397,6 @@ export default class DatasetCompliance extends Component { set(this, 'suggestionConfidenceThreshold', lowQualitySuggestionConfidenceThreshold); } - /** - * Lists the compliance wizard edit steps based on the datasets schemaless property - * @memberof DatasetCompliance - */ - editSteps = computed('schemaless', function(this: DatasetCompliance): Array<{ name: string }> { - const hasSchema = !getWithDefault(this, 'schemaless', false); - const steps = getComplianceSteps(hasSchema); - - // Ensure correct step ordering - return Object.keys(steps) - .sort() - .map((key: string): { name: string } => steps[+key]); - }); - /** * Reads the complianceDataTypes property and transforms into a list of drop down options for the field * identifier type @@ -490,78 +469,6 @@ export default class DatasetCompliance extends Component { ]; }); - /** - * e-c Task to update the current edit step in the wizard flow. - * Handles the transitions between steps, including performing each step's - * post processing action once a user has completed a step, or reverting the step - * and stepping backward if the post process fails - * @type {Task TaskInstance>} - * @memberof DatasetCompliance - */ - updateEditStepTask = (function() { - // initialize the previous action with a no-op function - let previousAction = noop; - // initialize the last seen index to the same value as editStepIndex - let lastIndex = initialStepIndex; - - return task(function*(this: DatasetCompliance): IterableIterator { - const { editStepIndex: currentIndex, editSteps } = getProperties(this, ['editStepIndex', 'editSteps']); - // the current step in the edit sequence - const editStep = editSteps[currentIndex] || { name: '' }; - const { name } = editStep; - - if (name) { - // using the steps name, construct a reference to the step process handler - const nextAction = this.actions[`did${classify(name)}`]; - let previousActionResult: void; - - // if the transition is backward, then the previous action is ignored - currentIndex > lastIndex && (previousActionResult = previousAction.call(this)); - lastIndex = currentIndex; - - try { - yield previousActionResult; - // if the previous action is resolved successfully, then replace with the next processor - previousAction = typeof nextAction === 'function' ? nextAction : noop; - - set(this, 'editStep', editStep); - } catch { - // if the previous action settles in a rejected state, replace with no-op before - // invoking the previousStep action to go back in the sequence - // batch previousStep invocation in a afterRender queue due to editStepIndex update - previousAction = noop; - run( - (): void => { - if (this.isDestroyed || this.isDestroying) { - return; - } - schedule('afterRender', this, this.actions.previousStep); - } - ); - } - } - }).enqueue(); - })(); - - /** - * Holds a reference to the current step in the compliance edit wizard flow - * @type {{ name: string }} - */ - editStep: { name: string } = { name: '' }; - - /** - * A list of ui values and labels for review filter drop-down - * @type {Array<{value: TagFilter, label:string}>} - * @memberof DatasetCompliance - */ - fieldReviewOptions: Array<{ value: DatasetCompliance['fieldReviewOption']; label: string }> = [ - { value: TagFilter.showAll, label: ' Show all fields' }, - { value: TagFilter.showReview, label: '? Show fields missing a data type' }, - { value: TagFilter.showSuggested, label: '! Show fields that need review' }, - //@ts-ignore htmlSafe type definition is incorrect in @types/ember contains TODO: to return Handlebars.SafeStringStatic - { value: TagFilter.showCompleted, label: htmlSafe(`✓ Show completed fields`) } - ]; - didReceiveAttrs(): void { // Perform validation step on the received component attributes this.validateAttrs(); diff --git a/wherehows-web/app/components/datasets/compliance/schema-entities.ts b/wherehows-web/app/components/datasets/compliance/schema-entities.ts index 4d6713a921..6643856246 100644 --- a/wherehows-web/app/components/datasets/compliance/schema-entities.ts +++ b/wherehows-web/app/components/datasets/compliance/schema-entities.ts @@ -1,7 +1,131 @@ import Component from '@ember/component'; +import { action } from '@ember-decorators/object'; +import { set } from '@ember/object'; +import { noop } from 'wherehows-web/utils/helpers/functions'; +import { ComplianceEdit, TagFilter, ComplianceFieldIdValue } from 'wherehows-web/constants'; +import { htmlSafe } from '@ember/string'; +import { IComplianceChangeSet } from 'wherehows-web/typings/app/dataset-compliance'; +import { TrackableEventCategory, trackableEvent } from 'wherehows-web/constants/analytics/event-tracking'; -export default class DatasetsComplianceSchemaEntities extends Component.extend({ - // anything which *must* be merged to prototype here -}) { - // normal class body definition here +/** + * The ComplianceSchemaEntities component allows the user to individually tag fields to annotate the + * data contained in the dataset schema, found in the Compliance tab for datasets. + */ +export default class ComplianceSchemaEntities extends Component.extend({}) { + /** + * Passed in flag determining whether or not we are in an editing mode for the schema entities. + * @type {boolean} + */ + isEditing: boolean; + + /** + * Passed in computed prop, Lists the IComplianceChangeSet / tags without an identifierType value + * @type {Array} + */ + unspecifiedTags: Array; + + /** + * Passed in action/method from parent, updates the editing mode and corresponding target + */ + toggleEditing: (e: boolean, target?: ComplianceEdit) => void; + + /** + * Passed in action from parent, updates showGuidedEditMode state on parent + */ + // Note: [REFACTOR-COMPLIANCE] This passed in function is to maintain status quo while we migrate the + // refactor logic and should eventually no longer be required + showGuidedEditMode: (b: boolean) => void; + + /** + * Passed in action from parent, updates fieldReviewOption state on parent + */ + // Note: [REFACTOR-COMPLIANCE] Same as above showGuidedEditMode + fieldReviewChange: (o: { value: TagFilter }) => TagFilter; + + /** + * Specifies the filter to be applied on the list of fields shown in the compliance policy table + * @type {TagFilter} + * @memberof DatasetCompliance + */ + // Note: [REFACTOR-COMPLIANCE] This value will currently be passed in from the parent but should + // eventually live only on this component + fieldReviewOption!: TagFilter; + + /** + * Used in the template to help pass values for the edit target + * @type {ComplianceEdit} + */ + ComplianceEdit = ComplianceEdit; + + /** + * References the ComplianceFieldIdValue enum, which specifies hardcoded values for field + * identifiers + * @type {ComplianceFieldIdValue} + */ + ComplianceFieldIdValue = ComplianceFieldIdValue; + + /** + * Enum of categories that can be tracked for this component + * @type {TrackableEventCategory} + */ + trackableCategory = TrackableEventCategory; + + /** + * Map of events that can be tracked + * @type {ITrackableEventCategoryEvent} + */ + trackableEvent = trackableEvent; + + /** + * Flag indicating the current compliance policy edit-view mode. Guided edit mode allows users + * to go through a wizard to edit the schema entities while the other method is direct JSON editing + * @type {boolean} + * @memberof ComplianceSchemaEntities + */ + showGuidedComplianceEditMode = true; + + /** + * A list of ui values and labels for review filter drop-down + * @type {Array<{value: TagFilter, label:string}>} + * @memberof ComplianceSchemaEntities + */ + fieldReviewOptions: Array<{ value: ComplianceSchemaEntities['fieldReviewOption']; label: string }> = [ + { value: TagFilter.showAll, label: ' Show all fields' }, + { value: TagFilter.showReview, label: '? Show fields missing a data type' }, + { value: TagFilter.showSuggested, label: '! Show fields that need review' }, + //@ts-ignore htmlSafe type definition is incorrect in @types/ember contains TODO: to return Handlebars.SafeStringStatic + { value: TagFilter.showCompleted, label: htmlSafe(`✓ Show completed fields`) } + ]; + + constructor() { + super(...arguments); + + // Default values for undefined properties + this.unspecifiedTags || (this.unspecifiedTags = []); + this.toggleEditing || (this.toggleEditing = noop); + this.showGuidedEditMode || (this.showGuidedEditMode = noop); + this.fieldReviewChange || (this.fieldReviewChange = noop); + } + + /** + * Toggle the visibility of the guided compliance edit view vs the advanced (json) edit view modes + * @param {boolean} toggle flag ,if true, show guided edit mode, otherwise, advanced + */ + @action + onShowGuidedEditMode(this: ComplianceSchemaEntities, toggle: boolean): void { + const isShowingGuidedEditMode = set(this, 'showGuidedComplianceEditMode', toggle); + // Note: [REFACTOR-COMPLIANCE] Should be deleted once full functionality lives on this component + this.showGuidedEditMode(isShowingGuidedEditMode); + } + + /** + * Invokes the external action to update the tagFilter query + * @param {{value: TagFilter}} { value } + * @returns {TagFilter} + */ + @action + onFieldReviewChange(this: ComplianceSchemaEntities, option: { value: TagFilter }): TagFilter { + // Note: [REFACTOR-COMPLIANCE] The passed in effects should eventually live only on this component + return this.fieldReviewChange(option); + } } diff --git a/wherehows-web/app/templates/components/dataset-compliance.hbs b/wherehows-web/app/templates/components/dataset-compliance.hbs index 2dc3f8a14a..104a4f29d7 100644 --- a/wherehows-web/app/templates/components/dataset-compliance.hbs +++ b/wherehows-web/app/templates/components/dataset-compliance.hbs @@ -25,7 +25,7 @@ {{#if showAdvancedEditApplyStep}} {{#track-ui-event category=trackableCategory.Compliance action=trackableEvent.Compliance.ManualApply - name=editStep.name as |metrics|}} + name=editTarget as |metrics|}} + + + + +
+ {{#if showGuidedComplianceEditMode}} + {{ember-selector + values=fieldReviewOptions + selected=(readonly fieldReviewOption) + selectionDidChange=(action "onFieldReviewChange") + }} + + + {{pluralize foldedChangeSet.length "field"}} + + {{/if}} + + {{#if isEditing}} + +
+ {{#if (and unspecifiedTags showGuidedComplianceEditMode)}} +

Set all unspecified field types to {{ComplianceFieldIdValue.None}}

+ + {{#track-ui-event category=trackableCategory.Compliance + action=trackableEvent.Compliance.SetUnspecifiedAsNone as |metrics|}} + + {{/track-ui-event}} + {{/if}} +
+ + {{else}} + +
+ +
+ + {{/if}} +
+ +{{yield}} diff --git a/wherehows-web/app/templates/datasets/dataset-compliance/-action-bar.hbs b/wherehows-web/app/templates/datasets/dataset-compliance/-action-bar.hbs index 8698fd23d6..7b532b0449 100644 --- a/wherehows-web/app/templates/datasets/dataset-compliance/-action-bar.hbs +++ b/wherehows-web/app/templates/datasets/dataset-compliance/-action-bar.hbs @@ -2,21 +2,83 @@ {{#if isEditing}}
- + {{#if showApplyButton}} - + {{#if trackApplyEvent}} + {{#track-ui-event category=trackApplyEvent.category action=trackApplyEvent.action + name=trackApplyEvent.name as |metrics|}} + + {{/track-ui-event}} + {{else}} + + {{/if}} + + {{else}} + + {{#if trackSaveEvent}} + {{#track-ui-event category=trackSaveEvent.category action=trackSaveEvent.action + name=trackSaveEvent.name as |metrics|}} + + {{/track-ui-event}} + {{else}} + + {{/if}} + + {{/if}} + + {{#if trackCancelEvent}} + {{#track-ui-event category=trackCancelEvent.category action=trackCancelEvent.action + name=trackCancelEvent.name as |metrics|}} + + {{/track-ui-event}} + {{else}} + + {{/if}} + + {{#if (and manualParseError (not hideManualParseErrors))}} +
+ {{fa-icon "times-circle-o"}} + + + {{manualParseError}} + +
+ {{/if}}
{{/if}} - \ No newline at end of file + diff --git a/wherehows-web/app/templates/datasets/dataset-compliance/-dataset-compliance-entities.hbs b/wherehows-web/app/templates/datasets/dataset-compliance/-dataset-compliance-entities.hbs index 6eb734ec44..a16c44fb6b 100644 --- a/wherehows-web/app/templates/datasets/dataset-compliance/-dataset-compliance-entities.hbs +++ b/wherehows-web/app/templates/datasets/dataset-compliance/-dataset-compliance-entities.hbs @@ -1,92 +1,3 @@ - - -
- - - -
- -
- {{#if showGuidedComplianceEditMode}} - {{ember-selector - values=fieldReviewOptions - selected=(readonly fieldReviewOption) - selectionDidChange=(action "onFieldReviewChange") - }} - - - {{pluralize foldedChangeSet.length "field"}} - - {{/if}} - - {{#if isEditing}} - -
- {{#if (and unspecifiedTags showGuidedComplianceEditMode)}} -

Set all unspecified field types to {{ComplianceFieldIdValue.None}}

- - {{#track-ui-event category=trackableCategory.Compliance - action=trackableEvent.Compliance.SetUnspecifiedAsNone as |metrics|}} - - {{/track-ui-event}} - {{/if}} -
- {{/if}} - - {{#if isReadOnly}} -
- -
- {{/if}} -
-
{{fieldReviewHint}} From fdfa37695bc0ccf6506cfd43e4b199d046f06644 Mon Sep 17 00:00:00 2001 From: cptran777 Date: Mon, 1 Oct 2018 13:27:16 -0700 Subject: [PATCH 2/4] Removes unused logic from compliance wizard --- .../app/components/dataset-compliance.ts | 10 +--------- .../app/constants/dataset-compliance.ts | 17 ----------------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/wherehows-web/app/components/dataset-compliance.ts b/wherehows-web/app/components/dataset-compliance.ts index 8a1295beed..925ba1c711 100644 --- a/wherehows-web/app/components/dataset-compliance.ts +++ b/wherehows-web/app/components/dataset-compliance.ts @@ -1,8 +1,7 @@ import Component from '@ember/component'; import { computed, set, get, setProperties, getProperties, getWithDefault } from '@ember/object'; import ComputedProperty, { not, or, alias } from '@ember/object/computed'; -import { run, schedule, next } from '@ember/runloop'; -import { classify, htmlSafe } from '@ember/string'; +import { run, next } from '@ember/runloop'; import { assert } from '@ember/debug'; import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset'; import { IDataPlatform } from 'wherehows-web/typings/api/list/platforms'; @@ -14,7 +13,6 @@ import { getFieldIdentifierOptions, getDefaultSecurityClassification, compliancePolicyStrings, - getComplianceSteps, isExempt, ComplianceFieldIdValue, IDatasetClassificationOption, @@ -101,12 +99,6 @@ const datasetClassificationKey = 'complianceInfo.datasetClassification'; */ const datasetClassifiersKeys = >Object.keys(DatasetClassifiers); -/** - * The initial state of the compliance step for a zero based array - * @type {number} - */ -const initialStepIndex = -1; - export default class DatasetCompliance extends Component { isNewComplianceInfo: boolean; datasetName: string; diff --git a/wherehows-web/app/constants/dataset-compliance.ts b/wherehows-web/app/constants/dataset-compliance.ts index e23122eacd..11541288fe 100644 --- a/wherehows-web/app/constants/dataset-compliance.ts +++ b/wherehows-web/app/constants/dataset-compliance.ts @@ -118,22 +118,6 @@ enum ComplianceEdit { ExportPolicy = 'editExportPolicy' } -/** - * Takes a map of dataset options and constructs the relevant compliance edit wizard steps to build the wizard flow - * @param {boolean} [hasSchema=true] flag indicating if the dataset has a schema or otherwise - * @returns {({ [x: number]: { name: string } })} - */ -const getComplianceSteps = (hasSchema: boolean = true): { [x: number]: { name: string } } => { - // Step to tag dataset with PII data, this is at the dataset level for schema-less datasets - const piiTaggingStep = { 0: { name: 'editDatasetLevelCompliancePolicy' } }; - - if (!hasSchema) { - return { ...complianceSteps, ...piiTaggingStep }; - } - - return complianceSteps; -}; - /** * Returns true if argument of type IComplianceEntity has its readonly attribute not set to true * @param {IComplianceEntity} { readonly } @@ -705,7 +689,6 @@ export { getFieldIdentifierOption, getFieldIdentifierOptions, complianceSteps, - getComplianceSteps, editableTags, isTagFilter, isAutoGeneratedPolicy, From dc456343ca566c83e7c9e121d5f5ed09d79c0c85 Mon Sep 17 00:00:00 2001 From: cptran777 Date: Mon, 1 Oct 2018 13:35:20 -0700 Subject: [PATCH 3/4] Remove test related to edit steps for old compliance wizard --- .../unit/constants/dataset-compliance-test.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/wherehows-web/tests/unit/constants/dataset-compliance-test.js b/wherehows-web/tests/unit/constants/dataset-compliance-test.js index 1e6f6c9e9d..dc3e0fb384 100644 --- a/wherehows-web/tests/unit/constants/dataset-compliance-test.js +++ b/wherehows-web/tests/unit/constants/dataset-compliance-test.js @@ -62,24 +62,6 @@ module('Unit | Constants | dataset compliance', function() { ); }); - test('getComplianceSteps function should behave as expected', function(assert) { - assert.expect(3); - const piiTaggingStep = { 0: { name: 'editDatasetLevelCompliancePolicy' } }; - let result; - - assert.equal(typeof getComplianceSteps, 'function', 'getComplianceSteps is a function'); - result = getComplianceSteps(); - - assert.deepEqual(result, complianceSteps, 'getComplianceSteps result is expected shape when no args are passed'); - - result = getComplianceSteps(false); - assert.deepEqual( - result, - { ...complianceSteps, ...piiTaggingStep }, - 'getComplianceSteps result is expected shape when hasSchema attribute is false' - ); - }); - test('getFieldIdentifierOption function should behave as expected', function(assert) { const [complianceType] = complianceDataTypes; let result; From e1efafca52c62eff51e1b2bd51597fb15efa667f Mon Sep 17 00:00:00 2001 From: cptran777 Date: Mon, 1 Oct 2018 15:56:56 -0700 Subject: [PATCH 4/4] Code cleanup for refactoring dataset compliance entities --- .../datasets/compliance/schema-entities.ts | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/wherehows-web/app/components/datasets/compliance/schema-entities.ts b/wherehows-web/app/components/datasets/compliance/schema-entities.ts index 6643856246..742b5d5606 100644 --- a/wherehows-web/app/components/datasets/compliance/schema-entities.ts +++ b/wherehows-web/app/components/datasets/compliance/schema-entities.ts @@ -4,14 +4,14 @@ import { set } from '@ember/object'; import { noop } from 'wherehows-web/utils/helpers/functions'; import { ComplianceEdit, TagFilter, ComplianceFieldIdValue } from 'wherehows-web/constants'; import { htmlSafe } from '@ember/string'; -import { IComplianceChangeSet } from 'wherehows-web/typings/app/dataset-compliance'; +import { IComplianceChangeSet, IDropDownOption } from 'wherehows-web/typings/app/dataset-compliance'; import { TrackableEventCategory, trackableEvent } from 'wherehows-web/constants/analytics/event-tracking'; /** - * The ComplianceSchemaEntities component allows the user to individually tag fields to annotate the + * The DatasetComplianceEntities component allows the user to individually tag fields to annotate the * data contained in the dataset schema, found in the Compliance tab for datasets. */ -export default class ComplianceSchemaEntities extends Component.extend({}) { +export default class DatasetComplianceEntities extends Component.extend({}) { /** * Passed in flag determining whether or not we are in an editing mode for the schema entities. * @type {boolean} @@ -27,25 +27,24 @@ export default class ComplianceSchemaEntities extends Component.extend({}) { /** * Passed in action/method from parent, updates the editing mode and corresponding target */ - toggleEditing: (e: boolean, target?: ComplianceEdit) => void; + toggleEditing: (isEditing: boolean, target?: ComplianceEdit) => void; /** * Passed in action from parent, updates showGuidedEditMode state on parent */ // Note: [REFACTOR-COMPLIANCE] This passed in function is to maintain status quo while we migrate the // refactor logic and should eventually no longer be required - showGuidedEditMode: (b: boolean) => void; + showGuidedEditMode: (isShowingGuidedEditMode: boolean) => void; /** * Passed in action from parent, updates fieldReviewOption state on parent */ // Note: [REFACTOR-COMPLIANCE] Same as above showGuidedEditMode - fieldReviewChange: (o: { value: TagFilter }) => TagFilter; + fieldReviewChange: (o: { value: TagFilter }) => IDropDownOption; /** * Specifies the filter to be applied on the list of fields shown in the compliance policy table * @type {TagFilter} - * @memberof DatasetCompliance */ // Note: [REFACTOR-COMPLIANCE] This value will currently be passed in from the parent but should // eventually live only on this component @@ -80,16 +79,16 @@ export default class ComplianceSchemaEntities extends Component.extend({}) { * Flag indicating the current compliance policy edit-view mode. Guided edit mode allows users * to go through a wizard to edit the schema entities while the other method is direct JSON editing * @type {boolean} - * @memberof ComplianceSchemaEntities + * @memberof DatasetComplianceEntities */ showGuidedComplianceEditMode = true; /** * A list of ui values and labels for review filter drop-down * @type {Array<{value: TagFilter, label:string}>} - * @memberof ComplianceSchemaEntities + * @memberof DatasetComplianceEntities */ - fieldReviewOptions: Array<{ value: ComplianceSchemaEntities['fieldReviewOption']; label: string }> = [ + fieldReviewOptions: Array> = [ { value: TagFilter.showAll, label: ' Show all fields' }, { value: TagFilter.showReview, label: '? Show fields missing a data type' }, { value: TagFilter.showSuggested, label: '! Show fields that need review' }, @@ -112,7 +111,7 @@ export default class ComplianceSchemaEntities extends Component.extend({}) { * @param {boolean} toggle flag ,if true, show guided edit mode, otherwise, advanced */ @action - onShowGuidedEditMode(this: ComplianceSchemaEntities, toggle: boolean): void { + onShowGuidedEditMode(this: DatasetComplianceEntities, toggle: boolean): void { const isShowingGuidedEditMode = set(this, 'showGuidedComplianceEditMode', toggle); // Note: [REFACTOR-COMPLIANCE] Should be deleted once full functionality lives on this component this.showGuidedEditMode(isShowingGuidedEditMode); @@ -124,7 +123,7 @@ export default class ComplianceSchemaEntities extends Component.extend({}) { * @returns {TagFilter} */ @action - onFieldReviewChange(this: ComplianceSchemaEntities, option: { value: TagFilter }): TagFilter { + onFieldReviewChange(this: DatasetComplianceEntities, option: { value: TagFilter }): IDropDownOption { // Note: [REFACTOR-COMPLIANCE] The passed in effects should eventually live only on this component return this.fieldReviewChange(option); }