diff --git a/wherehows-web/app/components/dataset-compliance.ts b/wherehows-web/app/components/dataset-compliance.ts index baad40b214..66ad336f74 100644 --- a/wherehows-web/app/components/dataset-compliance.ts +++ b/wherehows-web/app/components/dataset-compliance.ts @@ -6,6 +6,9 @@ import { inject } from '@ember/service'; import { classify } from '@ember/string'; import { IFieldIdentifierOption } from 'wherehows-web/constants/dataset-compliance'; import { Classification } from 'wherehows-web/constants/datasets/compliance'; +import { IDatasetView } from 'wherehows-web/typings/api/datasets/dataset'; +import { IDataPlatform } from 'wherehows-web/typings/api/list/platforms'; +import { readPlatforms } from 'wherehows-web/utils/api/list/platforms'; import isTrackingHeaderField from 'wherehows-web/utils/validators/tracking-headers'; import { @@ -23,7 +26,8 @@ import { IComplianceField, DatasetClassification, SuggestionIntent, - PurgePolicy + PurgePolicy, + getSupportedPurgePolicies } from 'wherehows-web/constants'; import { isPolicyExpectedShape, @@ -44,7 +48,7 @@ import { IComplianceSuggestion } from 'wherehows-web/typings/api/datasets/compliance'; import { ApiStatus } from 'wherehows-web/utils/api'; -import { task } from 'ember-concurrency'; +import { task, TaskInstance } from 'ember-concurrency'; /** * Describes the DatasetCompliance actions index signature to allow @@ -140,11 +144,24 @@ const changeSetFieldsRequiringReview = arrayFilter(fieldCh const initialStepIndex = -1; /** - * Applies the observer to the editStepIndex to trigger the update edit step task + * Defines observers for the DatasetCompliance Component + * @type {Component} */ const ObservableDecorator = Component.extend({ + /** + * Observes changes editStepIndex to trigger the update edit step task + * @type {() => void} + */ editStepIndexChanged: observer('editStepIndex', function(this: DatasetCompliance) { get(this, 'updateEditStepTask').perform(); + }), + + /** + * Observes changes to the platform property and invokes the task to update the supportedPurgePolicies prop + * @type {() => void} + */ + platformChanged: observer('platform', function(this: DatasetCompliance) { + get(this, 'complianceAvailabilityTask').perform(); }) }); @@ -161,6 +178,8 @@ export default class DatasetCompliance extends ObservableDecorator { _hasBadData: boolean; _message: string; _alertType: string; + platform: IDatasetView['platform']; + isCompliancePolicyAvailable: boolean = false; showAllDatasetMemberData: boolean; complianceInfo: void | IComplianceInfo; complianceSuggestion: IComplianceSuggestion; @@ -234,6 +253,13 @@ export default class DatasetCompliance extends ObservableDecorator { */ isSaving = false; + /** + * The list of supported purge policies for the related platform + * @type {Array} + * @memberof DatasetCompliance + */ + supportedPurgePolicies: Array = []; + constructor() { super(...arguments); @@ -353,6 +379,10 @@ export default class DatasetCompliance extends ObservableDecorator { } } + didInsertElement() { + get(this, 'complianceAvailabilityTask').perform(); + } + /** * @override */ @@ -363,6 +393,33 @@ export default class DatasetCompliance extends ObservableDecorator { this.enableDomCloaking(); } + /** + * Parent task to determine if a compliance policy can be created or updated for the dataset + * @type {Task>>, () => TaskInstance>>>>} + * @memberof DatasetCompliance + */ + complianceAvailabilityTask = task(function*( + this: DatasetCompliance + ): IterableIterator>>> { + yield get(this, 'getPlatformPoliciesTask').perform(); + + const supportedPurgePolicies = get(this, 'supportedPurgePolicies'); + set(this, 'isCompliancePolicyAvailable', !!supportedPurgePolicies.length); + }).restartable(); + + /** + * Task to retrieve platform policies and set supported policies for the current platform + * @type {Task>, () => TaskInstance>>>} + * @memberof DatasetCompliance + */ + getPlatformPoliciesTask = task(function*(this: DatasetCompliance): IterableIterator>> { + const platform = get(this, 'platform'); + + if (platform) { + set(this, 'supportedPurgePolicies', getSupportedPurgePolicies(platform, yield readPlatforms())); + } + }).restartable(); + /** * A `lite` / intermediary step to occlusion culling, this helps to improve the rendering of * elements that are currently rendered in the viewport by hiding that aren't. @@ -372,13 +429,14 @@ export default class DatasetCompliance extends ObservableDecorator { */ enableDomCloaking() { const dom = this.element.querySelector('.dataset-compliance-fields'); - const triggerCount = 100; + const triggerThreshold = 100; + if (dom) { const rows = dom.querySelectorAll('tbody tr'); // if we already have watchers for elements, or if the elements previously cached are no longer valid, // e.g. those elements were destroyed when new data was received, pagination etc - if (rows.length > triggerCount && (!this.complianceWatchers || !this.complianceWatchers.has(rows[0]))) { + if (rows.length > triggerThreshold && (!this.complianceWatchers || !this.complianceWatchers.has(rows[0]))) { /** * If an item is not in the viewport add a class to occlude it */ @@ -1067,7 +1125,7 @@ export default class DatasetCompliance extends ObservableDecorator { }); // defaults the containing personal data flag to false if undefined - if (typeof containingPersonalData !== 'undefined') { + if (typeof containingPersonalData === 'undefined') { set(complianceInfo, 'containingPersonalData', false); } diff --git a/wherehows-web/app/components/purge-policy.ts b/wherehows-web/app/components/purge-policy.ts index 38d3ad1b50..2c6cb1fe6a 100644 --- a/wherehows-web/app/components/purge-policy.ts +++ b/wherehows-web/app/components/purge-policy.ts @@ -1,20 +1,17 @@ import Component from '@ember/component'; -import { get, set, observer } from '@ember/object'; +import { get, set } from '@ember/object'; import { run, next } from '@ember/runloop'; -import { task } from 'ember-concurrency'; +import DatasetCompliance from 'wherehows-web/components/dataset-compliance'; import { baseCommentEditorOptions, DatasetPlatform, exemptPolicy, - getSupportedPurgePolicies, isExempt, missingPolicyText, PurgePolicy, purgePolicyProps } from 'wherehows-web/constants'; import { IComplianceInfo } from 'wherehows-web/typings/api/datasets/compliance'; -import { IDataPlatform } from 'wherehows-web/typings/api/list/platforms'; -import { readPlatforms } from 'wherehows-web/utils/api/list/platforms'; export default class PurgePolicyComponent extends Component { /** @@ -40,7 +37,7 @@ export default class PurgePolicyComponent extends Component { * @type {Array} * @memberof PurgePolicyComponent */ - supportedPurgePolicies: Array = []; + supportedPurgePolicies: DatasetCompliance['supportedPurgePolicies']; /** * The dataset's platform @@ -87,31 +84,6 @@ export default class PurgePolicyComponent extends Component { this.checkExemption(get(this, 'purgePolicy')); } - didInsertElement() { - get(this, 'getPlatformPolicies').perform(); - } - - /** - * Observes changes to the platform property and invokes the task to update the supportedPurgePolicies prop - * @type {void} - * @memberof PurgePolicyComponent - */ - platformChanged = observer('platform', function(this: PurgePolicyComponent) { - get(this, 'getPlatformPolicies').perform(); - }); - - /** - * Task to retrieve platform policies for and set supported policies for the current platform - * @memberof PurgePolicyComponent - */ - getPlatformPolicies = task(function*(this: PurgePolicyComponent): IterableIterator>> { - const platform = get(this, 'platform'); - - if (platform) { - set(this, 'supportedPurgePolicies', getSupportedPurgePolicies(platform, yield readPlatforms())); - } - }).restartable(); - /** * Checks that the selected purge policy is exempt, if so, set the * flag to request the exemption to true diff --git a/wherehows-web/app/templates/components/dataset-compliance.hbs b/wherehows-web/app/templates/components/dataset-compliance.hbs index b003a9ba50..f90be12f97 100644 --- a/wherehows-web/app/templates/components/dataset-compliance.hbs +++ b/wherehows-web/app/templates/components/dataset-compliance.hbs @@ -1,134 +1,175 @@ -
- {{#if _hasBadData}} - - {{else}} -
- {{#if isEditing}} +{{#if complianceAvailabilityTask.isRunning}} + {{pendulum-ellipsis-animation}} +{{else}} + {{#if isCompliancePolicyAvailable}} - {{#if _message}} - - {{/if}} +
+ {{#if _hasBadData}} + + {{else}} +
+ {{#if isEditing}} -
- {{#if (has-next editStep editSteps)}} - - {{else}} - - {{/if}} + {{#if _message}} + + {{/if}} - {{#if (has-previous editStep editSteps)}} - +
+ {{#if (has-next editStep editSteps)}} + + {{else}} + + {{/if}} + + {{#if (has-previous editStep editSteps)}} + + + {{/if}} +
{{/if}} +
+ {{/if}} + +
+
+ Last saved: + + {{if isNewComplianceInfo 'Never' + (moment-from-now complianceInfo.modifiedTime)}} +
+ {{#unless isEditing}} + + + + {{#unless isNewComplianceInfo}} + + {{/unless}} + + {{/unless}} +
+ + {{#if isEditing}} +
+ {{partial "datasets/dataset-compliance/-dataset-compliance-step-indicator"}} +
{{/if}} -
- {{/if}} -
-
- Last saved: - - {{if isNewComplianceInfo 'Never' - (moment-from-now complianceInfo.modifiedTime)}} - -
- - {{#unless isEditing}} - - - - {{#unless isNewComplianceInfo}} - + {{#unless schemaless}} + {{#if (and (eq editStep.name editSteps.0.name) (not _hasBadData))}} + {{json-upload receiveJsonFile=(action "onComplianceJsonUpload") class="secondary-actions__action"}} + {{/if}} {{/unless}} - {{/unless}} -
+ {{#if (or isReadOnly (eq editStep.name editSteps.2.name))}} + {{partial "datasets/dataset-compliance/dataset-classification"}} + {{/if}} - {{#if isEditing}} -
- {{partial "datasets/dataset-compliance/-dataset-compliance-step-indicator"}} + {{#if (or isReadOnly (eq editStep.name editSteps.1.name))}} + {{#if getPlatformPoliciesTask.isRunning}} + {{pendulum-ellipsis-animation}} + {{/if}} + + {{#if getPlatformPoliciesTask.last.isError}} + {{!--todo: swap out with error-state component--}} + {{empty-state + heading="Purge Policies not available" + subHead="Could not find supported purge policies for this platform" + }} + +
+ +
+ + {{/if}} + + {{#if getPlatformPoliciesTask.last.isSuccessful}} + + {{purge-policy + isEditable=(not isReadOnly) + platform=platform + supportedPurgePolicies=supportedPurgePolicies + purgeNote=complianceInfo.compliancePurgeNote + purgePolicy=(readonly complianceInfo.complianceType) + onPolicyChange=(action "onDatasetPurgePolicyChange") + }} + + {{/if}} + {{/if}} + + {{#if schemaless}} + + {{#if (or isReadOnly (eq editStep.name editSteps.0.name))}} + {{datasets/schemaless-tagging + isEditable=(not isReadOnly) + classification=(readonly complianceInfo.confidentiality) + containsPersonalData=(readonly complianceInfo.containingPersonalData) + onClassificationChange=(action "onDatasetSecurityClassificationChange") + onPersonalDataChange=(action "onDatasetLevelPolicyChange") + }} + {{/if}} + + {{else}} + + {{#if (or isReadOnly (eq editStep.name editSteps.0.name))}} + {{partial "datasets/dataset-compliance/dataset-compliance-entities"}} + {{/if}} + + {{/if}}
- {{/if}} - - {{#unless schemaless}} - {{#if (and (eq editStep.name editSteps.0.name) (not _hasBadData))}} - {{json-upload receiveJsonFile=(action "onComplianceJsonUpload") class="secondary-actions__action"}} - {{/if}} - {{/unless}} - - {{#if (or isReadOnly (eq editStep.name editSteps.2.name))}} - {{partial "datasets/dataset-compliance/dataset-classification"}} - {{/if}} - - {{#if (or isReadOnly (eq editStep.name editSteps.1.name))}} - {{purge-policy - isEditable=(not isReadOnly) - platform=platform - purgeNote=complianceInfo.compliancePurgeNote - purgePolicy=(readonly complianceInfo.complianceType) - onPolicyChange=(action "onDatasetPurgePolicyChange") - }} - {{/if}} - - {{#if schemaless}} - - {{#if (or isReadOnly (eq editStep.name editSteps.0.name))}} - {{datasets/schemaless-tagging - isEditable=(not isReadOnly) - classification=(readonly complianceInfo.confidentiality) - containsPersonalData=(readonly complianceInfo.containingPersonalData) - onClassificationChange=(action "onDatasetSecurityClassificationChange") - onPersonalDataChange=(action "onDatasetLevelPolicyChange") - }} - {{/if}} {{else}} - {{#if (or isReadOnly (eq editStep.name editSteps.0.name))}} - {{partial "datasets/dataset-compliance/dataset-compliance-entities"}} - {{/if}} + {{empty-state + heading="Compliance Policy not available" + subHead="Compliance Policy is currently not available for this platform" + }} {{/if}} -
+{{/if}} {{yield}} diff --git a/wherehows-web/app/templates/components/purge-policy.hbs b/wherehows-web/app/templates/components/purge-policy.hbs index 1ec61d09ea..3d2238c102 100644 --- a/wherehows-web/app/templates/components/purge-policy.hbs +++ b/wherehows-web/app/templates/components/purge-policy.hbs @@ -9,65 +9,40 @@
    {{#if isEditable}} - {{#if getPlatformPolicies.isRunning}} - {{pendulum-ellipsis-animation}} - {{/if}} + {{#each-in purgePolicyProps as |purgeType prop|}} +
  • - {{#if getPlatformPolicies.last.isError}} - {{!--todo: swap out with error-state component--}} - {{empty-state - heading="Purge Policies not available" - subHead="Could not find supported purge policies for this platform" - }} + {{#radio-button-composer + name="dataset-purge-policy" + value=(if (contains purgeType supportedPurgePolicies) purgeType null) + disabled=(if (contains purgeType supportedPurgePolicies) false true) + groupValue=(readonly purgePolicy) + changed=(action "onChange") + }} + {{prop.displayAs}} + {{/radio-button-composer}} -
    - -
    + {{#unless (contains purgeType supportedPurgePolicies)}} +

    + Purge policy not available for + {{platform}} +

    + {{/unless}} - {{/if}} +

    {{prop.desc}}

    - {{#if getPlatformPolicies.last.isSuccessful}} + {{#if (and requestExemptionReason (eq purgeType exemptPolicy))}} - {{#each-in purgePolicyProps as |purgeType prop|}} -
  • + {{medium-content-editable + value=purgeNote + options=editorOptions + class="comment-new__content"}} - {{#radio-button-composer - name="dataset-purge-policy" - value=(if (contains purgeType supportedPurgePolicies) purgeType null) - disabled=(if (contains purgeType supportedPurgePolicies) false true) - groupValue=(readonly purgePolicy) - changed=(action "onChange") - }} - {{prop.displayAs}} - {{/radio-button-composer}} - - {{#unless (contains purgeType supportedPurgePolicies)}} -

    - Purge policy not available for - {{platform}} -

    - {{/unless}} - -

    {{prop.desc}}

    - - {{#if (and requestExemptionReason (eq purgeType exemptPolicy))}} - - {{medium-content-editable - value=purgeNote - options=editorOptions - class="comment-new__content"}} - - {{/if}} -
  • - {{/each-in}} - - {{/if}} + {{/if}} + + {{/each-in}} {{else}}