diff --git a/wherehows-web/app/authenticators/custom-ldap.js b/wherehows-web/app/authenticators/custom-ldap.js index 1f44d22f49..023cf48f31 100644 --- a/wherehows-web/app/authenticators/custom-ldap.js +++ b/wherehows-web/app/authenticators/custom-ldap.js @@ -1,9 +1,7 @@ import Base from 'ember-simple-auth/authenticators/base'; import Ember from 'ember'; -const { - $: { post } -} = Ember; +const { $: { post } } = Ember; export default Base.extend({ /** @@ -11,7 +9,7 @@ export default Base.extend({ * Resolves with data object returned from successful request. * @param {String} username username to authenticate with * @param {String} password matching candidate password for username - * @return {Promise<{Object, String}>} + * @return {Promise} */ authenticate: (username, password) => Promise.resolve( diff --git a/wherehows-web/app/components/dataset-compliance.js b/wherehows-web/app/components/dataset-compliance.js index 221a9792a4..0238934a65 100644 --- a/wherehows-web/app/components/dataset-compliance.js +++ b/wherehows-web/app/components/dataset-compliance.js @@ -8,8 +8,19 @@ import { nonIdFieldLogicalTypes, defaultFieldDataTypeClassification } from 'wherehows-web/constants'; +import { isPolicyExpectedShape } from 'wherehows-web/utils/datasets/functions'; -const { Component, computed, set, get, setProperties, getWithDefault, isEmpty, String: { htmlSafe } } = Ember; +const { + Component, + computed, + set, + get, + setProperties, + getProperties, + getWithDefault, + isEmpty, + String: { htmlSafe } +} = Ember; // TODO: DSS-6671 Extract to constants module const missingTypes = 'Looks like some fields may contain privacy data but do not have a specified `Field Format`?'; @@ -153,6 +164,13 @@ export default Component.extend({ label: value ? formatAsCapitalizedStringWithSpaces(value) : '...' })), + /** + * Caches the policy's modification time in milliseconds + */ + policyModificationTimeInEpoch: computed('complianceInfo', function() { + return getWithDefault(this, 'complianceInfo.modifiedTime', 0) * 1000; + }), + /** * @type {Boolean} cached boolean flag indicating that fields do contain a `kafka type` * tracking header. @@ -405,6 +423,38 @@ export default Component.extend({ }, actions: { + /** + * Receives the json representation for compliance and applies each key to the policy + * @param {String} textString string representation for the JSON file + */ + onComplianceJsonUpload(textString) { + const policy = JSON.parse(textString); + if (isPolicyExpectedShape(policy)) { + const currentPolicy = get(this, 'complianceInfo'); + return set(this, 'complianceInfo', Object.assign({}, currentPolicy, policy)); + } + + alert('Received policy in an unexpected format! Please check the provided attributes and try again.'); + }, + + /** + * Handles the compliance policy download action + */ + onComplianceDownloadJson() { + const currentPolicy = get(this, 'complianceInfo'); + const policyProps = [ + datasetClassificationKey, + policyFieldClassificationKey, + policyComplianceEntitiesKey + ].map(name => name.split('.').pop()); + const policy = Object.assign({}, getProperties(currentPolicy, policyProps)); + const href = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(policy))}`; + const download = `${get(this, 'datasetName')}_policy.json`; + const anchor = document.createElement('a'); + Object.assign(anchor, { download, href }); + anchor.click(); + }, + /** * When a user updates the identifierFieldType in the DOM, update the backing store * @param {String} identifierField diff --git a/wherehows-web/app/components/json-upload.js b/wherehows-web/app/components/json-upload.js new file mode 100644 index 0000000000..46baa98aa3 --- /dev/null +++ b/wherehows-web/app/components/json-upload.js @@ -0,0 +1,51 @@ +import Ember from 'ember'; + +const { get, computed, Component } = Ember; + +export default Component.extend({ + classNames: ['nacho-uploader'], + + /** + * Handles the change event on the json-upload DOM element + * @param {FileList} files extracts a FileList object from the event object + * @return {void|null} + */ + change({ target: { files = [] } }) { + const hasFiles = !!files.length; + if (hasFiles) { + return this.sendFileAsText(Array.from(files).shift()); + } + + return null; + }, + + /** + * Caches a unique id for the HTML Element for file upload + */ + uploadInputId: computed(function() { + return `${get(this, 'elementId')}-uploader`; + }), + + /** + * Reads a file as a text string and passes the output to the closure action + * @param {Blob} fileBlob + */ + sendFileAsText(fileBlob) { + const closureAction = get(this, 'attrs.receiveJsonFile'); + const reader = new FileReader(); + if (typeof closureAction === 'function') { + reader.onload = ({ target: { result } }) => closureAction(result); + reader.readAsText(fileBlob); + } + }, + + actions: { + /** + * Proxies the user's click interaction on the styled upload button to the file input element + */ + didSelectUpload() { + const uploadInput = this.$(`#${get(this, 'uploadInputId')}`); + return uploadInput.click(); + } + } +}); diff --git a/wherehows-web/app/styles/abstracts/_variables.scss b/wherehows-web/app/styles/abstracts/_variables.scss index 0695b67346..90f2e82977 100644 --- a/wherehows-web/app/styles/abstracts/_variables.scss +++ b/wherehows-web/app/styles/abstracts/_variables.scss @@ -52,7 +52,8 @@ $color-scheme: ( ), blue: ( oxford: rgb(53, 75, 87), - curious: rgb(26, 161, 217) + curious: rgb(26, 161, 217), + eastern: rgb(26, 132, 188) ), grey: ( light: rgb(237, 237, 237), diff --git a/wherehows-web/app/styles/components/_all.scss b/wherehows-web/app/styles/components/_all.scss index 3520ec0543..a133309e3e 100644 --- a/wherehows-web/app/styles/components/_all.scss +++ b/wherehows-web/app/styles/components/_all.scss @@ -16,3 +16,4 @@ @import "nacho/nacho-select"; @import "nacho/nacho-pager"; @import "nacho/nacho-breadcrumbs"; +@import "nacho/nacho-uploader"; diff --git a/wherehows-web/app/styles/components/_navbar.scss b/wherehows-web/app/styles/components/_navbar.scss index b0762a24f2..b8155fb9d0 100644 --- a/wherehows-web/app/styles/components/_navbar.scss +++ b/wherehows-web/app/styles/components/_navbar.scss @@ -1,5 +1,8 @@ @import "../abstracts/functions"; @import "../abstracts/mixins"; + +$item-spacing: 10px; + /** * Override Bootstrap navigation class, .navbar, ruleset */ @@ -51,6 +54,19 @@ } } +/** + * Styles the non primary action bar for an entity + */ +.secondary-actions { + display: flex; + justify-content: flex-end; + align-items: center; + + &__action + &__action { + margin-left: $item-spacing; + } +} + /** * Styles the action bar on a tab component */ @@ -64,6 +80,15 @@ background-color: #f8f8f8; z-index: z(dropdown); max-height: 50px; + + &__content { + white-space: nowrap; + vertical-align: top; + } + + &__item + &__item { + margin-left: $item-spacing; + } } /** diff --git a/wherehows-web/app/styles/components/dataset-compliance/_compliance-prompts.scss b/wherehows-web/app/styles/components/dataset-compliance/_compliance-prompts.scss index 7c55c648e5..0f8a0899da 100644 --- a/wherehows-web/app/styles/components/dataset-compliance/_compliance-prompts.scss +++ b/wherehows-web/app/styles/components/dataset-compliance/_compliance-prompts.scss @@ -39,3 +39,11 @@ } } } + +.policy-last-saved { + margin-right: auto; + + &__saved { + font-weight: fw(normal, 6); + } +} diff --git a/wherehows-web/app/styles/components/nacho/_nacho-button.scss b/wherehows-web/app/styles/components/nacho/_nacho-button.scss index b52099d8f1..0504379e48 100644 --- a/wherehows-web/app/styles/components/nacho/_nacho-button.scss +++ b/wherehows-web/app/styles/components/nacho/_nacho-button.scss @@ -6,17 +6,20 @@ ); } +$main-button-color: set-color(blue, eastern); +$button-text-color: set-color(white, base); + @include restyle-define(button, ( // Button Component Variables restyle-var(height): 32px, restyle-var(horizontal-padding): 16px, - restyle-var(main-color): $secondary-color, - restyle-var(background-color): $secondary-color, + restyle-var(main-color): $main-button-color, + restyle-var(background-color): $main-button-color, restyle-var(font-size): 1.7rem, restyle-var(font-weight): 600, - restyle-var(text-color): $text-color, + restyle-var(text-color): $button-text-color, restyle-var(border-radius): 2px, - restyle-var(disabled-text): tint($text-color, 70%), + restyle-var(disabled-text): tint($button-text-color, 70%), background-color: restyle-var(background-color), border: 0, @@ -50,7 +53,7 @@ restyle-modifiers: ( 'with a border': ( - border: 1px solid restyle-var(text-color) + border: 1px solid restyle-var(main-color) ), small: ( restyle-var(font-size): 1.5rem, @@ -76,7 +79,7 @@ ), secondary: ( restyle-var(background-color): transparent, - restyle-var(text-color): $text-invert-color, + restyle-var(text-color): $main-button-color, restyle-var(box-shadow-size): inset 0 0 0 1px, restyle-var(box-shadow-size-hover): inset 0 0 0 2px, restyle-var(box-shadow-size-active): inset 0 0 0 3px, diff --git a/wherehows-web/app/styles/components/nacho/_nacho-global-search.scss b/wherehows-web/app/styles/components/nacho/_nacho-global-search.scss index f4fa025cef..d8aa5cb31b 100644 --- a/wherehows-web/app/styles/components/nacho/_nacho-global-search.scss +++ b/wherehows-web/app/styles/components/nacho/_nacho-global-search.scss @@ -18,4 +18,10 @@ $height: 40px; overflow: hidden; justify-content: flex-end; } + + .search-button { + border: 1px solid $secondary-color; + background-color: $secondary-color; + color: $text-color; + } } diff --git a/wherehows-web/app/styles/components/nacho/_nacho-uploader.scss b/wherehows-web/app/styles/components/nacho/_nacho-uploader.scss new file mode 100644 index 0000000000..7a6dd29c2b --- /dev/null +++ b/wherehows-web/app/styles/components/nacho/_nacho-uploader.scss @@ -0,0 +1,10 @@ +.nacho-uploader { + @include flex-center; + display: inline-flex; + + &__label { + width: 250px; + margin-bottom: 0; + padding-right: 5px; + } +} diff --git a/wherehows-web/app/styles/components/notifications/_action-notifications.scss b/wherehows-web/app/styles/components/notifications/_action-notifications.scss index 71a2decba7..8d7e99f768 100644 --- a/wherehows-web/app/styles/components/notifications/_action-notifications.scss +++ b/wherehows-web/app/styles/components/notifications/_action-notifications.scss @@ -3,4 +3,5 @@ display: inline-block; border-radius: 2px; padding: 5px; + vertical-align: top; } diff --git a/wherehows-web/app/templates/components/dataset-author.hbs b/wherehows-web/app/templates/components/dataset-author.hbs index 59ea76de0a..e8f14e81cd 100644 --- a/wherehows-web/app/templates/components/dataset-author.hbs +++ b/wherehows-web/app/templates/components/dataset-author.hbs @@ -1,7 +1,7 @@