From 715805f0de46c957c14c8cd18bf80da4b2e7ff13 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 30 Sep 2020 10:08:24 -0400 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20API=20suppor?= =?UTF-8?q?t=20for=20user=20accounts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/api/addon/models/user.js | 81 ++++++++++++- addons/api/addon/serializers/user.js | 33 ++++++ addons/api/app/serializers/user.js | 1 + addons/api/tests/unit/models/user-test.js | 111 +++++++++++++++++- .../unit/serializers/application-test.js | 6 +- .../api/tests/unit/serializers/user-test.js | 77 ++++++++++++ 6 files changed, 303 insertions(+), 6 deletions(-) create mode 100644 addons/api/addon/serializers/user.js create mode 100644 addons/api/app/serializers/user.js create mode 100644 addons/api/tests/unit/serializers/user-test.js diff --git a/addons/api/addon/models/user.js b/addons/api/addon/models/user.js index 51053788f..c2be5cfb0 100644 --- a/addons/api/addon/models/user.js +++ b/addons/api/addon/models/user.js @@ -1,3 +1,82 @@ import GeneratedUserModel from '../generated/models/user'; +import { attr } from '@ember-data/model'; +import { A } from '@ember/array'; -export default class UserModel extends GeneratedUserModel {} +export default class UserModel extends GeneratedUserModel { + + // =attributes + + /** + * Accounts is read-only under normal circumstances. But accounts can + * be persisted via calls to `addAccounts()` or `removeAccounts()`. + */ + @attr({ + readOnly: true, + defaultValue: () => A(), + emptyArrayIfMissing: true, + }) + account_ids; + + // =methods + + /** + * Adds accounts via the `add-accounts` method. + * See serializer and adapter for more information. + * @param {[string]} accountIDs + * @param {object} options + * @param {object} options.adapterOptions + * @return {Promise} + */ + addAccounts(accountIDs, options = { adapterOptions: {} }) { + const defaultAdapterOptions = { + method: 'add-accounts', + accountIDs, + }; + // There is no "deep merge" in ES. + // All of this nonsense is here to ensure we get + // a decent merge of `adapterOptions`. + return this.save({ + ...options, + adapterOptions: { + ...defaultAdapterOptions, + ...options.adapterOptions, + }, + }); + } + + /** + * Remove accounts via the `remove-accounts` method. + * See serializer and adapter for more information. + * @param {[string]} accountIDs + * @param {object} options + * @param {object} options.adapterOptions + * @return {Promise} + */ + removeAccounts(accountIDs, options = { adapterOptions: {} }) { + const defaultAdapterOptions = { + method: 'remove-accounts', + accountIDs, + }; + // There is no "deep merge" in ES. + // All of this nonsense is here to ensure we get + // a decent merge of `adapterOptions`. + return this.save({ + ...options, + adapterOptions: { + ...defaultAdapterOptions, + ...options.adapterOptions, + }, + }); + } + + /** + * Remove a single account via the `remove-accounts` method. + * @param {number} accountID + * @param {object} options + * @return {Promise} + */ + removeAccount(accountID, options) { + return this.removeAccounts([accountID], options); + } + +} diff --git a/addons/api/addon/serializers/user.js b/addons/api/addon/serializers/user.js new file mode 100644 index 000000000..9c4a47194 --- /dev/null +++ b/addons/api/addon/serializers/user.js @@ -0,0 +1,33 @@ +import ApplicationSerializer from './application'; + +export default class UserSerializer extends ApplicationSerializer { + // =methods + + /** + * If `adapterOptions.accountIDs` is set (to an array of user IDs), + * then the payload is serialized via `serializewithAccounts`. + * @override + * @param {Snapshot} snapshot + * @return {object} + */ + serialize(snapshot) { + let serialized = super.serialize(...arguments); + const accountIDs = snapshot?.adapterOptions?.accountIDs; + if (accountIDs) serialized = + this.serializewithAccounts(snapshot, accountIDs); + return serialized; + } + + /** + * Returns a payload containing only the `account_ids` array (and version). + * @param {Snapshot} snapshot + * @param {[string]} account_ids + * @return {object} + */ + serializewithAccounts(snapshot, account_ids) { + return { + version: snapshot.attr('version'), + account_ids, + }; + } +} diff --git a/addons/api/app/serializers/user.js b/addons/api/app/serializers/user.js new file mode 100644 index 000000000..5c5a92643 --- /dev/null +++ b/addons/api/app/serializers/user.js @@ -0,0 +1 @@ +export { default } from 'api/serializers/user'; diff --git a/addons/api/tests/unit/models/user-test.js b/addons/api/tests/unit/models/user-test.js index df69a6501..75a8f0916 100644 --- a/addons/api/tests/unit/models/user-test.js +++ b/addons/api/tests/unit/models/user-test.js @@ -1,12 +1,115 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; module('Unit | Model | user', function (hooks) { setupTest(hooks); + setupMirage(hooks); - test('it exists', function (assert) { - let store = this.owner.lookup('service:store'); - let model = store.createRecord('user', {}); - assert.ok(model); + test('it has an `addAccounts` method that users a specific POST API endpoint and serialization', async function (assert) { + assert.expect(1); + this.server.post('/v1/users/123abc:add-accounts', (schema, request) => { + const body = JSON.parse(request.requestBody); + assert.deepEqual(body, { + account_ids: ['123_abc', 'foobar'], + version: 1, + }); + }); + const store = this.owner.lookup('service:store'); + store.push({ + data: { + id: '123abc', + type: 'user', + attributes: { + name: 'User', + description: 'Description', + account_ids: ['1', '2'], + version: 1, + scope: { + scope_id: 'o_1', + type: 'scope', + }, + }, + }, + }); + const model = store.peekRecord('user', '123abc'); + await model.addAccounts(['123_abc', 'foobar']); + }); + + test('it has a `removeAccounts` method that users a specific POST API endpoint and serialization', async function (assert) { + assert.expect(1); + this.server.post('/v1/users/123abc:remove-accounts', (schema, request) => { + const body = JSON.parse(request.requestBody); + assert.deepEqual(body, { + account_ids: ['1', '3'], + version: 1, + }); + }); + const store = this.owner.lookup('service:store'); + store.push({ + data: { + id: '123abc', + type: 'user', + attributes: { + name: 'user', + description: 'Description', + account_ids: ['4', '5'], + version: 1, + scope: { + scope_id: 'o_1', + type: 'scope', + }, + }, + }, + }); + const model = store.peekRecord('user', '123abc'); + await model.removeAccounts(['1', '3']); + }); + + test('it has a `removeAccount` method that deletes a single account set using `removeAccounts` method', async function (assert) { + assert.expect(1); + this.server.post('/v1/users/123abc:remove-accounts', (schema, request) => { + const body = JSON.parse(request.requestBody); + assert.deepEqual(body, { + account_ids: ['3'], + version: 1, + }); + }); + const store = this.owner.lookup('service:store'); + store.push({ + data: { + id: '123abc', + type: 'user', + attributes: { + name: 'user', + description: 'Description', + account_ids: ['1', '3'], + version: 1, + scope: { + scope_id: 'o_1', + type: 'scope', + }, + }, + }, + }); + const model = store.peekRecord('user', '123abc'); + await model.removeAccount('3'); + }); + + test('it defaults `accounts_ids` to an empty array when model instance does not define it', function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + store.push({ + data: { + id: 'user_123', + type: 'user', + }, + }); + const user = store.peekRecord('user', 'user_123'); + assert.equal( + user.account_ids.length, + 0, + 'User has empty account_ids by default' + ); }); }); diff --git a/addons/api/tests/unit/serializers/application-test.js b/addons/api/tests/unit/serializers/application-test.js index 5c2c07a20..10de9d4fb 100644 --- a/addons/api/tests/unit/serializers/application-test.js +++ b/addons/api/tests/unit/serializers/application-test.js @@ -154,7 +154,11 @@ module('Unit | Serializer | application', function (hooks) { data: { id: '1', type: 'user', - attributes: { name: 'User 1', scope: { scope_id: 'o_123' } }, + attributes: { + name: 'User 1', + account_ids: [], + scope: { scope_id: 'o_123' } + }, relationships: {}, }, }); diff --git a/addons/api/tests/unit/serializers/user-test.js b/addons/api/tests/unit/serializers/user-test.js new file mode 100644 index 000000000..c0d2bd061 --- /dev/null +++ b/addons/api/tests/unit/serializers/user-test.js @@ -0,0 +1,77 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Serializer | user', function (hooks) { + setupTest(hooks); + + test('it serializes users normally, without accounts', function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + const serializer = store.serializerFor('user'); + const record = store.createRecord('user', { + name: 'user', + description: 'Description', + account_ids: ['1', '2'], + version: 1, + }); + const snapshot = record._createSnapshot(); + snapshot.adapterOptions = {}; + const serializedRecord = serializer.serialize(snapshot); + assert.deepEqual(serializedRecord, { + name: 'user', + description: 'Description', + version: 1, + }); + }); + + test('it serializes only host sets and version when an `adapterOptions.accountIDs` array is passed', function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + const serializer = store.serializerFor('user'); + const record = store.createRecord('user', { + name: 'user', + description: 'Description', + account_ids: ['1', '2'], + version: 1, + }); + const snapshot = record._createSnapshot(); + snapshot.adapterOptions = { + accountIDs: ['4', '5'], + }; + const serializedRecord = serializer.serialize(snapshot); + assert.deepEqual(serializedRecord, { + account_ids: ['4', '5'], + version: 1, + }); + }); + + test('it normalizes missing account_ids to empty array', function (assert) { + assert.expect(1); + const store = this.owner.lookup('service:store'); + const serializer = store.serializerFor('user'); + const user = store.createRecord('user').constructor; + const payload = { + id: '1', + name: 'user 1', + scope: { id: 'o_123' }, + }; + const normalized = serializer.normalizeSingleResponse( + store, + user, + payload + ); + assert.deepEqual(normalized, { + included: [], + data: { + id: '1', + type: 'user', + attributes: { + name: 'user 1', + scope: { scope_id: 'o_123' }, + account_ids: [], + }, + relationships: {}, + }, + }); + }); +}); From 956981b06e7ec41b3bc5179f78aa4979b4c15b63 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 30 Sep 2020 10:45:39 -0400 Subject: [PATCH 02/13] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20user=20accou?= =?UTF-8?q?nts=20listing=20and=20remove?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form/account/password/index.hbs | 2 - ui/core/app/router.js | 4 +- ui/core/app/routes/scopes/scope/users/user.js | 23 +++ .../scopes/scope/users/user/accounts.js | 51 +++++++ .../auth-method/accounts/index.hbs | 2 +- .../app/templates/scopes/scope/users/user.hbs | 24 ++- .../scopes/scope/users/user/-actions.hbs | 9 ++ .../scopes/scope/users/user/-header.hbs | 3 + .../scopes/scope/users/user/-navigation.hbs | 8 + .../scopes/scope/users/user/accounts.hbs | 53 +++++++ .../scopes/scope/users/user/index.hbs | 46 +----- ui/core/mirage/config.js | 25 +++ ui/core/mirage/factories/auth-method.js | 9 +- ui/core/mirage/models/user.js | 5 +- ui/core/mirage/scenarios/default.js | 2 +- ui/core/mirage/serializers/user.js | 15 +- .../tests/acceptance/users/accounts-test.js | 142 ++++++++++++++++++ .../scopes/scope/users/user/accounts-test.js | 11 ++ ui/core/translations/form/en-us.yaml | 6 +- ui/core/translations/resources/en-us.yaml | 10 +- 20 files changed, 393 insertions(+), 57 deletions(-) create mode 100644 ui/core/app/routes/scopes/scope/users/user/accounts.js create mode 100644 ui/core/app/templates/scopes/scope/users/user/-actions.hbs create mode 100644 ui/core/app/templates/scopes/scope/users/user/-header.hbs create mode 100644 ui/core/app/templates/scopes/scope/users/user/-navigation.hbs create mode 100644 ui/core/app/templates/scopes/scope/users/user/accounts.hbs create mode 100644 ui/core/tests/acceptance/users/accounts-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/users/user/accounts-test.js diff --git a/ui/core/app/components/form/account/password/index.hbs b/ui/core/app/components/form/account/password/index.hbs index e2890657e..34b7ed0e4 100644 --- a/ui/core/app/components/form/account/password/index.hbs +++ b/ui/core/app/components/form/account/password/index.hbs @@ -55,7 +55,6 @@ @value={{@model.attributes.login_name}} @label={{t "form.login_name.label"}} @error={{@model.errors.login_name}} - @helperText={{t "form.login_name.help"}} readonly={{false}} as |field|> {{#if @model.errors.login_name}} @@ -74,7 +73,6 @@ @value={{this.password}} @label={{t "form.password.label"}} @error={{@model.errors.password}} - @helperText={{t "form.password.help"}} readonly={{false}} autocomplete="new-password" as |field|> diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 0894289f9..8142aa85a 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -58,7 +58,9 @@ Router.map(function () { }); this.route('users', function () { - this.route('user', { path: ':user_id' }, function () {}); + this.route('user', { path: ':user_id' }, function () { + this.route('accounts'); + }); this.route('new'); }); diff --git a/ui/core/app/routes/scopes/scope/users/user.js b/ui/core/app/routes/scopes/scope/users/user.js index d26912707..2d7ed072e 100644 --- a/ui/core/app/routes/scopes/scope/users/user.js +++ b/ui/core/app/routes/scopes/scope/users/user.js @@ -12,4 +12,27 @@ export default class ScopesScopeUsersUserRoute extends Route { async model({ user_id }) { return this.store.findRecord('user', user_id); } + + /** + * Renders the route-set specific page sections + * @override + */ + renderTemplate() { + super.renderTemplate(...arguments); + + this.render('scopes/scope/users/user/-header', { + into: 'scopes/scope/users/user', + outlet: 'header', + }); + + this.render('scopes/scope/users/user/-actions', { + into: 'scopes/scope/users/user', + outlet: 'actions', + }); + + this.render('scopes/scope/users/user/-navigation', { + into: 'scopes/scope/users/user', + outlet: 'navigation', + }); + } } diff --git a/ui/core/app/routes/scopes/scope/users/user/accounts.js b/ui/core/app/routes/scopes/scope/users/user/accounts.js new file mode 100644 index 000000000..cb00ca24e --- /dev/null +++ b/ui/core/app/routes/scopes/scope/users/user/accounts.js @@ -0,0 +1,51 @@ +import Route from '@ember/routing/route'; +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; +import { hash, all } from 'rsvp'; +import loading from 'ember-loading/decorator'; + +export default class ScopesScopeUsersUserAccountsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Returns users associated with this user. + * @return {Promise{user: UserModel, accounts: Promise{[AccountModel]}}} + */ + model() { + const { id: scopeID } = this.modelFor('scopes.scope'); + const user = this.modelFor('scopes.scope.users.user'); + return hash({ + user, + accounts: all( + user.account_ids.map((id) => + this.store.findRecord('account', id, { adapterOptions: { scopeID } }) + ) + ), + }); + } + + // =actions + + /** + * Remove a account from the current role and redirect to accounts index. + * @param {UserModel} user + * @param {AccountModel} account + */ + @action + @loading + async removeAccount(user, account) { + try { + await user.removeAccount(account.id); + await this.refresh(); + this.notify.success(this.intl.t('notifications.remove-success')); + } catch (error) { + // TODO: replace with translated strings + this.notify.error(error.message, { closeAfter: null }); + } + } +} diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs index 81b93da9c..7df042046 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs @@ -4,7 +4,7 @@ {{t 'form.name.label'}} - {{t 'form.login_name.label'}} + {{t 'form.username.label'}} {{t 'form.id.label'}} diff --git a/ui/core/app/templates/scopes/scope/users/user.hbs b/ui/core/app/templates/scopes/scope/users/user.hbs index d66e83390..2a878ff51 100644 --- a/ui/core/app/templates/scopes/scope/users/user.hbs +++ b/ui/core/app/templates/scopes/scope/users/user.hbs @@ -1,3 +1,25 @@ {{title @model.displayName}} -{{outlet}} + + + + + + + + {{outlet "header"}} + + + + {{outlet "navigation"}} + + + + {{outlet "actions"}} + + + + {{outlet}} + + + diff --git a/ui/core/app/templates/scopes/scope/users/user/-actions.hbs b/ui/core/app/templates/scopes/scope/users/user/-actions.hbs new file mode 100644 index 000000000..b72d4c322 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/users/user/-actions.hbs @@ -0,0 +1,9 @@ + + + {{t 'actions.delete-user'}} + + diff --git a/ui/core/app/templates/scopes/scope/users/user/-header.hbs b/ui/core/app/templates/scopes/scope/users/user/-header.hbs new file mode 100644 index 000000000..2b107e842 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/users/user/-header.hbs @@ -0,0 +1,3 @@ +

{{t "resources.user.title"}}

+

{{t "resources.user.description"}}

+

{{@model.id}}

diff --git a/ui/core/app/templates/scopes/scope/users/user/-navigation.hbs b/ui/core/app/templates/scopes/scope/users/user/-navigation.hbs new file mode 100644 index 000000000..0228c92e8 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/users/user/-navigation.hbs @@ -0,0 +1,8 @@ + + + {{t 'titles.details'}} + + + {{t 'resources.user.messages.accounts.title'}} + + diff --git a/ui/core/app/templates/scopes/scope/users/user/accounts.hbs b/ui/core/app/templates/scopes/scope/users/user/accounts.hbs new file mode 100644 index 000000000..66c808da9 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/users/user/accounts.hbs @@ -0,0 +1,53 @@ +{{title (t 'resources.user.messages.accounts.title')}} + +{{#if @model.accounts}} + + + + + {{t 'form.username.label'}} + {{t 'form.id.label'}} + {{t "titles.actions"}} + + + + {{#each @model.accounts as |account|}} + + + {{account.username}} + + + {{account.id}} + + + + + {{t "actions.remove"}} + + + + + {{/each}} + + + +{{else}} + + + + + {{t "resources.user.messages.accounts.description"}} + + + + +{{/if}} diff --git a/ui/core/app/templates/scopes/scope/users/user/index.hbs b/ui/core/app/templates/scopes/scope/users/user/index.hbs index 35db006e9..67714eca0 100644 --- a/ui/core/app/templates/scopes/scope/users/user/index.hbs +++ b/ui/core/app/templates/scopes/scope/users/user/index.hbs @@ -1,41 +1,5 @@ - - - - - - - -

{{t "resources.user.title"}}

-

{{t "resources.user.description"}}

-

{{@model.id}}

-
- - - - - {{t 'actions.delete-user'}} - - - - - - - - {{t 'titles.details'}} - - - - - - - - -
+ diff --git a/ui/core/mirage/config.js b/ui/core/mirage/config.js index 3d332f121..678d5fafb 100644 --- a/ui/core/mirage/config.js +++ b/ui/core/mirage/config.js @@ -90,6 +90,31 @@ export default function() { this.get('/users/:id'); this.patch('/users/:id'); this.del('/users/:id'); + this.post('/users/:idMethod', function ({ users }, { params: { idMethod } }) { + const attrs = this.normalizedRequestAttrs(); + const id = idMethod.split(':')[0]; + const method = idMethod.split(':')[1]; + const user = users.find(id); + const updatedAttrs = { + version: attrs.version, + accountIds: user.accountIds + }; + // If adding accounts, push them into the array + if (method === 'add-accounts') { + attrs.accountIds.forEach(id => { + if (!updatedAttrs.accountIds.includes(id)) { + updatedAttrs.accountIds.push(id); + } + }); + } + // If deleting accounts, filter them out of the array + if (method === 'remove-accounts') { + updatedAttrs.accountIds = updatedAttrs.accountIds.filter(id => { + return !attrs.accountIds.includes(id); + }); + } + return user.update(updatedAttrs); + }); // IAM: Groups this.get('/groups', ({ groups }, { queryParams: { scope_id: scopeId } }) => { diff --git a/ui/core/mirage/factories/auth-method.js b/ui/core/mirage/factories/auth-method.js index 80254614a..61d29726b 100644 --- a/ui/core/mirage/factories/auth-method.js +++ b/ui/core/mirage/factories/auth-method.js @@ -5,12 +5,15 @@ export default factory.extend({ id: (i) => `auth-method-id-${i}`, /** - * Adds accounts to auth method. + * Adds accounts (with associated users) to auth method. */ - withAccounts: trait({ + withAccountsAndUsers: trait({ afterCreate(authMethod, server) { const { scope } = authMethod; - server.createList('account', 5, { scope, authMethod }); + server.createList('user', 5, { scope }).map(user => { + const { id } = server.create('account', { scope, authMethod }); + user.update({ accountIds: [id] }); + }); } }) diff --git a/ui/core/mirage/models/user.js b/ui/core/mirage/models/user.js index 08b1f5ad3..45cf14952 100644 --- a/ui/core/mirage/models/user.js +++ b/ui/core/mirage/models/user.js @@ -1,7 +1,8 @@ -import { Model, belongsTo } from 'ember-cli-mirage'; +import { Model, belongsTo, hasMany } from 'ember-cli-mirage'; export default Model.extend({ - scope: belongsTo() + scope: belongsTo(), + accounts: hasMany('account') }); diff --git a/ui/core/mirage/scenarios/default.js b/ui/core/mirage/scenarios/default.js index 5d1a85fe6..e4cd01854 100644 --- a/ui/core/mirage/scenarios/default.js +++ b/ui/core/mirage/scenarios/default.js @@ -15,7 +15,7 @@ export default function(server) { // Auth server.createList('auth-method', 3, { scope: globalScope }); - server.createList('auth-method', 3, { scope: orgScope }, 'withAccounts'); + server.createList('auth-method', 3, { scope: orgScope }, 'withAccountsAndUsers'); // Groups and Users server.createList('group', 5, { scope: orgScope }, 'withMembers'); diff --git a/ui/core/mirage/serializers/user.js b/ui/core/mirage/serializers/user.js index 142cbf508..0ef9298f5 100644 --- a/ui/core/mirage/serializers/user.js +++ b/ui/core/mirage/serializers/user.js @@ -1,5 +1,18 @@ import ApplicationSerializer from './application'; +import { underscore } from '@ember/string'; export default ApplicationSerializer.extend({ - modelName: 'user' + modelName: 'user', + + keyForRelationshipIds(relationshipName) { + return `${this._container.inflector.singularize( + underscore(relationshipName) + )}_ids`; + }, + + _hashForModel(model) { + const json = ApplicationSerializer.prototype._hashForModel.apply(this, arguments); + if (model.accountIds.length) json.account_ids = model.accountIds; + return json; + } }); diff --git a/ui/core/tests/acceptance/users/accounts-test.js b/ui/core/tests/acceptance/users/accounts-test.js new file mode 100644 index 000000000..0dead76e1 --- /dev/null +++ b/ui/core/tests/acceptance/users/accounts-test.js @@ -0,0 +1,142 @@ +import { module, test } from 'qunit'; +import { visit, currentURL, click, find, findAll } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { Response } from 'miragejs'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | users | accounts', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + }, + user: null, + }; + const urls = { + orgScope: null, + users: null, + user: null, + accounts: null, + addAccounts: null, + }; + let accountsCount; + + hooks.beforeEach(function () { + authenticateSession({}); + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + this.server.create('auth-method', { + scope: instances.scopes.org + }, 'withAccountsAndUsers'); + instances.user = this.server.db.users[0]; + accountsCount = instances.user.accountIds.length; + urls.users = `/scopes/${instances.scopes.org.id}/users`; + urls.user = `${urls.users}/${instances.user.id}`; + urls.accounts = `${urls.user}/accounts`; + urls.addAccounts = `${urls.user}/add-accounts`; + }); + + test('visiting user accounts', async function (assert) { + assert.expect(2); + await visit(urls.accounts); + await a11yAudit(); + assert.equal(currentURL(), urls.accounts); + assert.equal(findAll('tbody tr').length, accountsCount); + }); + + test('can remove a account', async function (assert) { + assert.expect(2); + await visit(urls.accounts); + assert.equal(findAll('tbody tr').length, accountsCount); + await click('tbody tr .rose-dropdown-button-danger'); + assert.equal(findAll('tbody tr').length, accountsCount - 1); + }); + + test('shows error message on account remove', async function (assert) { + assert.expect(2); + this.server.post('/users/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + await visit(urls.accounts); + assert.equal(findAll('tbody tr').length, accountsCount); + await click('tbody tr .rose-dropdown-button-danger'); + assert.ok(find('[role="alert"]')); + }); + + // test('visiting account add accounts', async function(assert) { + // assert.expect(1); + // await visit(urls.addAccounts); + // await a11yAudit(); + // assert.equal(currentURL(), urls.addAccounts); + // }); + // + // test('select and save accounts to add', async function (assert) { + // assert.expect(3); + // instances.user.update({ accountIds: [] }); + // await visit(urls.accounts); + // assert.equal(findAll('tbody tr').length, 0); + // await click('.rose-layout-page-actions a') + // assert.equal(currentURL(), urls.addAccounts); + // await click('tbody label'); + // await click('form [type="submit"]'); + // await visit(urls.accounts); + // assert.equal(findAll('tbody tr').length, 1); + // }); + // + // test('select and cancel accounts to add', async function (assert) { + // assert.expect(4); + // await visit(urls.accounts); + // assert.equal(findAll('tbody tr').length, accountsCount); + // await click('tbody tr .rose-dropdown-button-danger'); + // assert.equal(findAll('tbody tr').length, accountsCount - 1); + // await click('.rose-layout-page-actions a') + // assert.equal(currentURL(), urls.addAccounts); + // await click('tbody label'); + // await click('form [type="button"]'); + // await visit(urls.accounts); + // assert.equal(findAll('tbody tr').length, accountsCount - 1); + // }); + // + // test('shows error message on account add', async function (assert) { + // assert.expect(1); + // this.server.post('/users/:idMethod', () => { + // return new Response( + // 400, + // {}, + // { + // status: 400, + // code: 'invalid_argument', + // message: 'The request was invalid.', + // details: {}, + // } + // ); + // }); + // instances.user.update({ accountIds: [] }); + // await visit(urls.addAccounts); + // await click('tbody label'); + // await click('form [type="submit"]'); + // assert.ok(find('[role="alert"]')); + // }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/users/user/accounts-test.js b/ui/core/tests/unit/routes/scopes/scope/users/user/accounts-test.js new file mode 100644 index 000000000..a98f97d71 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/users/user/accounts-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/users/user/accounts', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/users/user/accounts'); + assert.ok(route); + }); +}); diff --git a/ui/core/translations/form/en-us.yaml b/ui/core/translations/form/en-us.yaml index ed2e1e160..7bbf5c7bc 100644 --- a/ui/core/translations/form/en-us.yaml +++ b/ui/core/translations/form/en-us.yaml @@ -10,14 +10,14 @@ type: label: Type help: The type of the resource, to help differentiate schemas login_name: + label: Login Name +username: label: Username - help: The username for the account set_password: label: Password - help: Create a new password for the account + help: Create a new password password: label: Password - help: The password for the account grant: label: Grant help: A permissions grant string for a role diff --git a/ui/core/translations/resources/en-us.yaml b/ui/core/translations/resources/en-us.yaml index fb595f18d..dd1b7848d 100644 --- a/ui/core/translations/resources/en-us.yaml +++ b/ui/core/translations/resources/en-us.yaml @@ -122,6 +122,14 @@ user: messages: welcome: title: Welcome to Users + accounts: + title: Accounts + description: Users may be associated with any number of accounts. + add-accounts: + title: Add Accounts + description: Select accounts to associate with this user. + actions: + add-accounts: Add Accounts role: title: Role title_plural: Roles @@ -180,4 +188,4 @@ target: description: No hosts sets available to add to target. add: title: Add Host Sets - description: Select host sets to assign to this target. \ No newline at end of file + description: Select host sets to assign to this target. From 77940968ac8b5703342dc73a359892c28dd12964 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 30 Sep 2020 11:32:25 -0400 Subject: [PATCH 03/13] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20user=20add-a?= =?UTF-8?q?ccounts=20flow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form/target/add-host-sets/index.hbs | 4 +- .../form/user/add-accounts/index.hbs | 56 +++++++++ .../form/user/add-accounts/index.js | 53 +++++++++ ui/core/app/router.js | 1 + .../scopes/scope/users/user/add-accounts.js | 90 ++++++++++++++ .../scopes/scope/users/user/-actions.hbs | 3 + .../scopes/scope/users/user/add-accounts.hbs | 25 ++++ .../scope/users/user/add-accounts/-header.hbs | 2 + .../tests/acceptance/users/accounts-test.js | 110 +++++++++--------- .../components/form/user/add-accounts-test.js | 12 ++ .../scope/users/user/add-accounts-test.js | 11 ++ ui/core/translations/resources/en-us.yaml | 3 + 12 files changed, 313 insertions(+), 57 deletions(-) create mode 100644 ui/core/app/components/form/user/add-accounts/index.hbs create mode 100644 ui/core/app/components/form/user/add-accounts/index.js create mode 100644 ui/core/app/routes/scopes/scope/users/user/add-accounts.js create mode 100644 ui/core/app/templates/scopes/scope/users/user/add-accounts.hbs create mode 100644 ui/core/app/templates/scopes/scope/users/user/add-accounts/-header.hbs create mode 100644 ui/core/tests/integration/components/form/user/add-accounts-test.js create mode 100644 ui/core/tests/unit/routes/scopes/scope/users/user/add-accounts-test.js diff --git a/ui/core/app/components/form/target/add-host-sets/index.hbs b/ui/core/app/components/form/target/add-host-sets/index.hbs index fa02412bb..545f45f91 100644 --- a/ui/core/app/components/form/target/add-host-sets/index.hbs +++ b/ui/core/app/components/form/target/add-host-sets/index.hbs @@ -18,7 +18,7 @@ {{t 'form.id.label'}} {{t 'form.name.label'}} {{t 'form.type.label'}} - {{t 'resources.host-catalog.title_plural'}} + {{t 'resources.host-catalog.title'}} @@ -57,4 +57,4 @@ -{{/unless}} \ No newline at end of file +{{/unless}} diff --git a/ui/core/app/components/form/user/add-accounts/index.hbs b/ui/core/app/components/form/user/add-accounts/index.hbs new file mode 100644 index 000000000..f3bfed288 --- /dev/null +++ b/ui/core/app/components/form/user/add-accounts/index.hbs @@ -0,0 +1,56 @@ +{{#if this.hasAvailableAccounts}} + + + + + + + + {{t 'form.id.label'}} + {{t 'form.username.label'}} + {{t 'resources.auth-method.title'}} + + + + {{#each this.filteredAccounts as |account|}} + + + + + {{account.username}} + + {{account.auth_method_id}} + + + {{/each}} + + + + +{{/if}} + +{{#unless this.hasAvailableAccounts}} + + + + {{t "resources.user.messages.no-accounts.description"}} + + + + {{t "actions.back"}} + + + +{{/unless}} diff --git a/ui/core/app/components/form/user/add-accounts/index.js b/ui/core/app/components/form/user/add-accounts/index.js new file mode 100644 index 000000000..b5f49e947 --- /dev/null +++ b/ui/core/app/components/form/user/add-accounts/index.js @@ -0,0 +1,53 @@ +import Component from '@glimmer/component'; +import { computed, action } from '@ember/object'; +import { A } from '@ember/array'; + +export default class FormUserAddAccountsComponent extends Component { + // =properties + + /** + * Array of selected account IDs. + * @type {EmberArray} + */ + selectedAccountIDs = A(); + + /** + * Checks for unassigned accounts. + * @param {[AccountModel]} filteredAccounts + * @type {boolean} + */ + @computed('filteredAccounts') + get hasAvailableAccounts() { + return this.filteredAccounts.length > 0; + } + + /** + * Accounts not already added to the user. + * @type {[AccountModel]} + */ + @computed('args.{accounts.[],model.account_ids.[]}') + get filteredAccounts() { + // Get IDs for accounts already added to the current user + const alreadyAddedAccountIDs = this.args.model.account_ids; + const notAddedAccounts = this.args.accounts.filter( + ({ id }) => !alreadyAddedAccountIDs.includes(id) + ); + return notAddedAccounts; + } + + // =actions + + @action + toggleAccount(account) { + if (!this.selectedAccountIDs.includes(account.id)) { + this.selectedAccountIDs.addObject(account.id); + } else { + this.selectedAccountIDs.removeObject(account.id); + } + } + + @action + submit(fn) { + fn(this.selectedAccountIDs); + } +} diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 8142aa85a..748ad73a6 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -60,6 +60,7 @@ Router.map(function () { this.route('users', function () { this.route('user', { path: ':user_id' }, function () { this.route('accounts'); + this.route('add-accounts'); }); this.route('new'); }); diff --git a/ui/core/app/routes/scopes/scope/users/user/add-accounts.js b/ui/core/app/routes/scopes/scope/users/user/add-accounts.js new file mode 100644 index 000000000..bdb7b0e9c --- /dev/null +++ b/ui/core/app/routes/scopes/scope/users/user/add-accounts.js @@ -0,0 +1,90 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; +import { all } from 'rsvp'; +import loading from 'ember-loading/decorator'; + +export default class ScopesScopeUsersUserAddAccountsRoute extends Route { + // =services + + @service intl; + @service notify; + + // =methods + + /** + * Emtpy out any previously loaded acconuts. + */ + beforeModel() { + this.store.unloadAll('account'); + } + + /** + * Returns the current target, all host catalogs, and all host sets. + * @return {{target: TargetModel, hostCatalogs: [HostCatalogModel], hostSets: [HostSetModel]}} + */ + async model() { + const user = this.modelFor('scopes.scope.users.user'); + const { id: scope_id } = this.modelFor('scopes.scope'); + const authMethods = await this.store.query('auth-method', { scope_id }); + await all( + authMethods.map(({ id: auth_method_id }) => + this.store.query('account', { auth_method_id }) + ) + ); + const accounts = this.store.peekAll('account'); + return { user, authMethods, accounts }; + } + + /** + * Renders the route-set specific page sections + * @override + */ + renderTemplate() { + super.renderTemplate(...arguments); + + this.render('scopes/scope/users/user/add-accounts/-header', { + into: 'scopes/scope/users/user', + outlet: 'header', + }); + + this.render('-empty', { + into: 'scopes/scope/users/user', + outlet: 'actions', + }); + + this.render('-empty', { + into: 'scopes/scope/users/user', + outlet: 'navigation', + }); + } + + // =actions + + /** + * Adds accounts to the user and saves, replaces with the accounts index + * route, and notifies the user of success or error. + * @param {UserModel} user + * @param {[string]} accountIDs + */ + @action + @loading + async addAccounts(user, accountIDs) { + try { + await user.addAccounts(accountIDs); + await this.replaceWith('scopes.scope.users.user.accounts'); + this.notify.success(this.intl.t('notifications.add-success')); + } catch (error) { + // TODO: replace with translated strings + this.notify.error(error.message, { closeAfter: null }); + } + } + + /** + * Redirect to user accounts as if nothing ever happened. + */ + @action + cancel() { + this.replaceWith('scopes.scope.users.user.accounts'); + } +} diff --git a/ui/core/app/templates/scopes/scope/users/user/-actions.hbs b/ui/core/app/templates/scopes/scope/users/user/-actions.hbs index b72d4c322..c5de304c1 100644 --- a/ui/core/app/templates/scopes/scope/users/user/-actions.hbs +++ b/ui/core/app/templates/scopes/scope/users/user/-actions.hbs @@ -1,4 +1,7 @@ + + {{t "resources.user.actions.add-accounts"}} + +{{/if}} + +{{#unless @model.accounts}} + + + + {{t "resources.user.messages.no-accounts.description"}} + + + + {{t "actions.back"}} + + + +{{/unless}} diff --git a/ui/core/app/templates/scopes/scope/users/user/add-accounts/-header.hbs b/ui/core/app/templates/scopes/scope/users/user/add-accounts/-header.hbs new file mode 100644 index 000000000..d9a819fe8 --- /dev/null +++ b/ui/core/app/templates/scopes/scope/users/user/add-accounts/-header.hbs @@ -0,0 +1,2 @@ +

{{t "resources.user.messages.add-accounts.title"}}

+

{{t "resources.user.messages.add-accounts.description"}}

diff --git a/ui/core/tests/acceptance/users/accounts-test.js b/ui/core/tests/acceptance/users/accounts-test.js index 0dead76e1..8bcaa951a 100644 --- a/ui/core/tests/acceptance/users/accounts-test.js +++ b/ui/core/tests/acceptance/users/accounts-test.js @@ -41,7 +41,7 @@ module('Acceptance | users | accounts', function (hooks) { this.server.create('auth-method', { scope: instances.scopes.org }, 'withAccountsAndUsers'); - instances.user = this.server.db.users[0]; + instances.user = this.server.schema.users.all().models[0]; accountsCount = instances.user.accountIds.length; urls.users = `/scopes/${instances.scopes.org.id}/users`; urls.user = `${urls.users}/${instances.user.id}`; @@ -85,58 +85,58 @@ module('Acceptance | users | accounts', function (hooks) { assert.ok(find('[role="alert"]')); }); - // test('visiting account add accounts', async function(assert) { - // assert.expect(1); - // await visit(urls.addAccounts); - // await a11yAudit(); - // assert.equal(currentURL(), urls.addAccounts); - // }); - // - // test('select and save accounts to add', async function (assert) { - // assert.expect(3); - // instances.user.update({ accountIds: [] }); - // await visit(urls.accounts); - // assert.equal(findAll('tbody tr').length, 0); - // await click('.rose-layout-page-actions a') - // assert.equal(currentURL(), urls.addAccounts); - // await click('tbody label'); - // await click('form [type="submit"]'); - // await visit(urls.accounts); - // assert.equal(findAll('tbody tr').length, 1); - // }); - // - // test('select and cancel accounts to add', async function (assert) { - // assert.expect(4); - // await visit(urls.accounts); - // assert.equal(findAll('tbody tr').length, accountsCount); - // await click('tbody tr .rose-dropdown-button-danger'); - // assert.equal(findAll('tbody tr').length, accountsCount - 1); - // await click('.rose-layout-page-actions a') - // assert.equal(currentURL(), urls.addAccounts); - // await click('tbody label'); - // await click('form [type="button"]'); - // await visit(urls.accounts); - // assert.equal(findAll('tbody tr').length, accountsCount - 1); - // }); - // - // test('shows error message on account add', async function (assert) { - // assert.expect(1); - // this.server.post('/users/:idMethod', () => { - // return new Response( - // 400, - // {}, - // { - // status: 400, - // code: 'invalid_argument', - // message: 'The request was invalid.', - // details: {}, - // } - // ); - // }); - // instances.user.update({ accountIds: [] }); - // await visit(urls.addAccounts); - // await click('tbody label'); - // await click('form [type="submit"]'); - // assert.ok(find('[role="alert"]')); - // }); + test('visiting account add accounts', async function(assert) { + assert.expect(1); + await visit(urls.addAccounts); + await a11yAudit(); + assert.equal(currentURL(), urls.addAccounts); + }); + + test('select and save accounts to add', async function (assert) { + assert.expect(3); + instances.user.update({ accountIds: [] }); + await visit(urls.accounts); + assert.equal(findAll('tbody tr').length, 0); + await click('.rose-layout-page-actions a') + assert.equal(currentURL(), urls.addAccounts); + await click('tbody label'); + await click('form [type="submit"]'); + await visit(urls.accounts); + assert.equal(findAll('tbody tr').length, 1); + }); + + test('select and cancel accounts to add', async function (assert) { + assert.expect(4); + await visit(urls.accounts); + assert.equal(findAll('tbody tr').length, accountsCount); + await click('tbody tr .rose-dropdown-button-danger'); + assert.equal(findAll('tbody tr').length, accountsCount - 1); + await click('.rose-layout-page-actions a') + assert.equal(currentURL(), urls.addAccounts); + await click('tbody label'); + await click('form [type="button"]'); + await visit(urls.accounts); + assert.equal(findAll('tbody tr').length, accountsCount - 1); + }); + + test('shows error message on account add', async function (assert) { + assert.expect(1); + this.server.post('/users/:idMethod', () => { + return new Response( + 400, + {}, + { + status: 400, + code: 'invalid_argument', + message: 'The request was invalid.', + details: {}, + } + ); + }); + instances.user.update({ accountIds: [] }); + await visit(urls.addAccounts); + await click('tbody label'); + await click('form [type="submit"]'); + assert.ok(find('[role="alert"]')); + }); }); diff --git a/ui/core/tests/integration/components/form/user/add-accounts-test.js b/ui/core/tests/integration/components/form/user/add-accounts-test.js new file mode 100644 index 000000000..ba96e4dba --- /dev/null +++ b/ui/core/tests/integration/components/form/user/add-accounts-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +// import { render } from '@ember/test-helpers'; +// import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | form/user/add-accounts', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function(assert) { + assert.expect(0); + }); +}); diff --git a/ui/core/tests/unit/routes/scopes/scope/users/user/add-accounts-test.js b/ui/core/tests/unit/routes/scopes/scope/users/user/add-accounts-test.js new file mode 100644 index 000000000..2aac18540 --- /dev/null +++ b/ui/core/tests/unit/routes/scopes/scope/users/user/add-accounts-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/users/user/add-accounts', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:scopes/scope/users/user/add-accounts'); + assert.ok(route); + }); +}); diff --git a/ui/core/translations/resources/en-us.yaml b/ui/core/translations/resources/en-us.yaml index dd1b7848d..81ade9e0f 100644 --- a/ui/core/translations/resources/en-us.yaml +++ b/ui/core/translations/resources/en-us.yaml @@ -128,6 +128,9 @@ user: add-accounts: title: Add Accounts description: Select accounts to associate with this user. + no-accounts: + title: No Accounts Available + description: There are no accounts available to add to this user. actions: add-accounts: Add Accounts role: From ce257be8a7c247a2e5055c0fd8a340904a0441e1 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 30 Sep 2020 11:35:49 -0400 Subject: [PATCH 04/13] chore: add breadcrumbs --- .../scopes/scope/users/user/add-accounts.js | 17 +++++++++++++++++ .../scope/users/user/add-accounts-test.js | 12 ++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 ui/core/app/controllers/scopes/scope/users/user/add-accounts.js create mode 100644 ui/core/tests/unit/controllers/scopes/scope/users/user/add-accounts-test.js diff --git a/ui/core/app/controllers/scopes/scope/users/user/add-accounts.js b/ui/core/app/controllers/scopes/scope/users/user/add-accounts.js new file mode 100644 index 000000000..de02366b1 --- /dev/null +++ b/ui/core/app/controllers/scopes/scope/users/user/add-accounts.js @@ -0,0 +1,17 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeUsersUserAddAccountsController extends Controller { + // =services + + @service intl; + + // =attributes + + /** + * @type {string} + */ + get breadCrumb() { + return this.intl.t('resources.user.messages.add-accounts.title'); + } +} diff --git a/ui/core/tests/unit/controllers/scopes/scope/users/user/add-accounts-test.js b/ui/core/tests/unit/controllers/scopes/scope/users/user/add-accounts-test.js new file mode 100644 index 000000000..a71b3d2e0 --- /dev/null +++ b/ui/core/tests/unit/controllers/scopes/scope/users/user/add-accounts-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/users/user/add-accounts', function(hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/users/user/add-accounts'); + assert.ok(controller); + }); +}); From da6192a3cd2704dc9f532ba80caa52820684f10d Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 30 Sep 2020 12:18:12 -0400 Subject: [PATCH 05/13] feat: Make all ids copyable --- ui/core/app/components/copyable/index.js | 1 - ui/core/app/styles/app.scss | 3 ++- .../scopes/scope/auth-methods/auth-method/-header.hbs | 4 +++- .../auth-methods/auth-method/accounts/account/-header.hbs | 4 +++- .../auth-method/accounts/account/set-password/-header.hbs | 4 +++- .../scopes/scope/auth-methods/auth-method/accounts/index.hbs | 4 +++- ui/core/app/templates/scopes/scope/auth-methods/index.hbs | 4 +++- ui/core/app/templates/scopes/scope/groups/group/-header.hbs | 4 +++- ui/core/app/templates/scopes/scope/groups/group/members.hbs | 4 +++- ui/core/app/templates/scopes/scope/groups/index.hbs | 4 +++- .../projects/project/host-catalogs/host-catalog/-header.hbs | 4 +++- .../project/host-catalogs/host-catalog/host-sets/-header.hbs | 4 +++- .../host-catalogs/host-catalog/host-sets/host-set/hosts.hbs | 4 +++- .../project/host-catalogs/host-catalog/host-sets/index.hbs | 4 +++- .../project/host-catalogs/host-catalog/hosts/-header.hbs | 4 +++- .../project/host-catalogs/host-catalog/hosts/index.hbs | 4 +++- .../scopes/scope/projects/project/host-catalogs/index.hbs | 4 +++- ui/core/app/templates/scopes/scope/projects/project/index.hbs | 4 +++- .../scopes/scope/projects/project/sessions/index.hbs | 4 +++- .../templates/scopes/scope/projects/project/targets/index.hbs | 4 +++- .../scopes/scope/projects/project/targets/target/-header.hbs | 4 +++- .../scope/projects/project/targets/target/host-sets.hbs | 4 +++- ui/core/app/templates/scopes/scope/roles/index.hbs | 4 +++- ui/core/app/templates/scopes/scope/roles/role/-header.hbs | 4 +++- .../app/templates/scopes/scope/roles/role/grants/-header.hbs | 4 +++- ui/core/app/templates/scopes/scope/roles/role/principals.hbs | 4 +++- .../templates/scopes/scope/roles/role/principals/-header.hbs | 4 +++- ui/core/app/templates/scopes/scope/users/index.hbs | 4 +++- ui/core/app/templates/scopes/scope/users/user/index.hbs | 4 +++- 29 files changed, 83 insertions(+), 29 deletions(-) diff --git a/ui/core/app/components/copyable/index.js b/ui/core/app/components/copyable/index.js index 01dcad838..cefc032fa 100644 --- a/ui/core/app/components/copyable/index.js +++ b/ui/core/app/components/copyable/index.js @@ -16,7 +16,6 @@ export default class CopyableComponent extends Component { icon = 'copy-action'; @tracked text; - @tracked clipboard; /** * A Ember Concurrency-based task that updates copy icon to a success state diff --git a/ui/core/app/styles/app.scss b/ui/core/app/styles/app.scss index 9e72b055f..dfe9fe1f9 100644 --- a/ui/core/app/styles/app.scss +++ b/ui/core/app/styles/app.scss @@ -82,5 +82,6 @@ } .copyable .copyable-button { - padding: 0rem; + padding: 0 sizing.rems(xxs); + margin: 0; } diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/-header.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/-header.hbs index ba94f66be..0748ed7b8 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/-header.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.auth-method.title"}}

{{t "resources.auth-method.description"}}

-

{{@model.id}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-header.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-header.hbs index 938c5fedb..c7a1ec474 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-header.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-header.hbs @@ -1,2 +1,4 @@

{{t "resources.account.title"}}

-

{{@model.id}}

\ No newline at end of file + + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/set-password/-header.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/set-password/-header.hbs index 5c5ee4dd4..1805683a2 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/set-password/-header.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/set-password/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.account.title"}}

{{t 'resources.account.messages.set-password.description'}}

-

{{@model.id}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs index 81b93da9c..d399eb1d8 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs @@ -24,7 +24,9 @@ {{account.username}} - {{account.id}} + + {{account.id}} + {{/each}} diff --git a/ui/core/app/templates/scopes/scope/auth-methods/index.hbs b/ui/core/app/templates/scopes/scope/auth-methods/index.hbs index e1c23f96f..26027d51b 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/index.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/index.hbs @@ -46,7 +46,9 @@ - {{authMethod.id}} + + {{authMethod.id}} + {{/each}} diff --git a/ui/core/app/templates/scopes/scope/groups/group/-header.hbs b/ui/core/app/templates/scopes/scope/groups/group/-header.hbs index ac1e772a0..a876cafac 100644 --- a/ui/core/app/templates/scopes/scope/groups/group/-header.hbs +++ b/ui/core/app/templates/scopes/scope/groups/group/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.group.title"}}

{{t "resources.group.description"}}

-

{{@model.id}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/groups/group/members.hbs b/ui/core/app/templates/scopes/scope/groups/group/members.hbs index 0b6dee825..ce5eee601 100644 --- a/ui/core/app/templates/scopes/scope/groups/group/members.hbs +++ b/ui/core/app/templates/scopes/scope/groups/group/members.hbs @@ -17,7 +17,9 @@ {{member.displayName}} - {{member.id}} + + {{member.id}} + {{group.description}}

- {{group.id}} + + {{group.id}} + {{/each}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs index 77e14a09b..8857383a2 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.host-catalog.title"}}

{{t "resources.host-catalog.description"}}

-

{{@model.id}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/-header.hbs index 752eae74c..26afcea96 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/-header.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.host-set.title"}}

{{t "resources.host-set.description"}}

-

{{@model.id}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs index abc6852da..7b65efa26 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs @@ -25,7 +25,9 @@ {{host.type}}
- {{host.id}} + + {{host.id}} + - {{hostSet.id}} + + {{hostSet.id}} + {{/each}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/-header.hbs index e8a7b9c8d..f0d679039 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/-header.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.host.title"}}

{{t "resources.host.description"}}

-

{{@model.id}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs index 3f1c23860..87ae8db1a 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs @@ -27,7 +27,9 @@ - {{host.id}} + + {{host.id}} + {{host.attributes.address}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs index 578a59c4a..2f758b992 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs @@ -47,7 +47,9 @@ - {{hostCatalog.id}} + + {{hostCatalog.id}} + {{/each}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/index.hbs index 79c5e6e41..58395a683 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/index.hbs @@ -7,7 +7,9 @@

{{t "resources.project.title"}}

{{t "resources.project.description"}}

-

{{@model.id}}

+ + {{@model.id}} +
diff --git a/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs index a34ceb077..b4e5d3e4f 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs @@ -28,7 +28,9 @@ {{#each @model as |sessionAggregate|}} - {{sessionAggregate.session.id}} + + {{sessionAggregate.session.id}} + {{sessionAggregate.user.displayName}} {{sessionAggregate.target.displayName}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs index d6e45da25..ff84ac48e 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs @@ -51,7 +51,9 @@ {{/if}} - {{target.id}} + + {{target.id}} + {{/each}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs index 280737623..b96093e47 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.target.title"}}

{{t "resources.target.description"}}

-

{{@model.id}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs index 827793ccd..e03aa2610 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs @@ -22,7 +22,9 @@ {{t (concat 'resources.host-set.types.' hostSet.model.type)}} - {{hostSet.model.id}} + + {{hostSet.model.id}} + {{role.description}}

- {{role.id}} + + {{role.id}} + {{/each}} diff --git a/ui/core/app/templates/scopes/scope/roles/role/-header.hbs b/ui/core/app/templates/scopes/scope/roles/role/-header.hbs index ccad156d5..926771735 100644 --- a/ui/core/app/templates/scopes/scope/roles/role/-header.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.role.title"}}

{{t "resources.role.description"}}

-

{{@model.id}}

+ + {{@model.id}} + diff --git a/ui/core/app/templates/scopes/scope/roles/role/grants/-header.hbs b/ui/core/app/templates/scopes/scope/roles/role/grants/-header.hbs index aa96ca797..ccea2b2d0 100644 --- a/ui/core/app/templates/scopes/scope/roles/role/grants/-header.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role/grants/-header.hbs @@ -1,3 +1,5 @@

{{t "resources.role.title"}}

{{t "resources.role.grant.description"}}

-

{{@model.id}}

+ + {{@model.id}} + \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/roles/role/principals.hbs b/ui/core/app/templates/scopes/scope/roles/role/principals.hbs index 73ac90715..58041d4a0 100644 --- a/ui/core/app/templates/scopes/scope/roles/role/principals.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role/principals.hbs @@ -21,7 +21,9 @@ {{t (concat 'resources.role.principal.types.' principal.type)}}
- {{principal.model.id}} + + {{principal.model.id}} + {{t "resources.role.title"}}

{{t "resources.role.principal.description"}}

-

{{@model.role.id}}

+ + {{@model.role.id}} + diff --git a/ui/core/app/templates/scopes/scope/users/index.hbs b/ui/core/app/templates/scopes/scope/users/index.hbs index 26458d273..50bcd7b74 100644 --- a/ui/core/app/templates/scopes/scope/users/index.hbs +++ b/ui/core/app/templates/scopes/scope/users/index.hbs @@ -41,7 +41,9 @@

{{user.description}}

- {{user.id}} + + {{user.id}} + {{/each}} diff --git a/ui/core/app/templates/scopes/scope/users/user/index.hbs b/ui/core/app/templates/scopes/scope/users/user/index.hbs index 35db006e9..7f9218f1b 100644 --- a/ui/core/app/templates/scopes/scope/users/user/index.hbs +++ b/ui/core/app/templates/scopes/scope/users/user/index.hbs @@ -7,7 +7,9 @@

{{t "resources.user.title"}}

{{t "resources.user.description"}}

-

{{@model.id}}

+ + {{@model.id}} +
From 2600411c700b29d0c88cf73a0cb4241aed0249b1 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 30 Sep 2020 12:57:30 -0400 Subject: [PATCH 06/13] refactor: Fix sass lint errors in ui/core --- ui/core/app/styles/_notify.scss | 8 ++++---- ui/core/app/styles/app.scss | 25 +++++++++++++------------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/ui/core/app/styles/_notify.scss b/ui/core/app/styles/_notify.scss index 438f0950c..784bc746f 100644 --- a/ui/core/app/styles/_notify.scss +++ b/ui/core/app/styles/_notify.scss @@ -61,19 +61,19 @@ .ember-notify-show { -webkit-animation-duration: 500ms; -webkit-animation-name: ember-notify-show; - -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1.275); animation-duration: 500ms; animation-name: ember-notify-show; - animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); + animation-timing-function: cubic-bezier(.175, .885, .32, 1.275); } .ember-notify-hide { -webkit-animation-duration: 250ms; -webkit-animation-name: ember-notify-hide; - -webkit-animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045); + -webkit-animation-timing-function: cubic-bezier(.6, -.28, .735, .045); animation-duration: 250ms; animation-name: ember-notify-hide; - animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045); + animation-timing-function: cubic-bezier(.6, -.28, .735, .045); &:hover { -moz-animation-play-state: paused; diff --git a/ui/core/app/styles/app.scss b/ui/core/app/styles/app.scss index 9e72b055f..8aad37e0b 100644 --- a/ui/core/app/styles/app.scss +++ b/ui/core/app/styles/app.scss @@ -61,17 +61,16 @@ &.loading { &::after { - content: " "; - position: absolute; - top: 100%; - left: 0; - right: 0; - height: 3px; - - background: repeating-linear-gradient(to right, #fff, #fff, var(--info), #fff, #fff); - background-size: 200% auto; - background-position: 0 100%; animation: gradient 1s linear infinite; + background: repeating-linear-gradient(to right, var(--white), var(--white), var(--info), var(--white), var(--white)); + background-position: 0 100%; + background-size: 200% auto; + content: ' '; + height: 3px; + left: 0; + position: absolute; + right: 0; + top: 100%; @keyframes gradient { 0% { background-position: 0 0; } @@ -81,6 +80,8 @@ } } -.copyable .copyable-button { - padding: 0rem; +.copyable { + .copyable-button { + padding: 0; + } } From 8bf3c295a6381aadd43afc3fe3e1ca0ca26ca114 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 30 Sep 2020 14:12:34 -0400 Subject: [PATCH 07/13] feat: Add footer section to global layout in addons/rose --- .../components/rose/layout/global/index.hbs | 1 + .../rose/layout/global/index.stories.mdx | 18 +++++++++--------- .../components/rose/layout/global-test.js | 7 +++++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/addons/rose/addon/components/rose/layout/global/index.hbs b/addons/rose/addon/components/rose/layout/global/index.hbs index bfa2c8e75..373f70531 100644 --- a/addons/rose/addon/components/rose/layout/global/index.hbs +++ b/addons/rose/addon/components/rose/layout/global/index.hbs @@ -2,5 +2,6 @@ {{yield (hash header=(component "rose/anonymous" tagName="header" class="rose-layout-global-header") body=(component "rose/anonymous" class="rose-layout-global-body") + footer=(component "rose/anonymous" class="rose-layout-global-footer") )}} diff --git a/addons/rose/addon/components/rose/layout/global/index.stories.mdx b/addons/rose/addon/components/rose/layout/global/index.stories.mdx index 9b8e34ea4..22cb6b8e6 100644 --- a/addons/rose/addon/components/rose/layout/global/index.stories.mdx +++ b/addons/rose/addon/components/rose/layout/global/index.stories.mdx @@ -1,29 +1,29 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { hbs } from 'ember-cli-htmlbars'; -import { action } from '@storybook/addon-actions'; -import { text, boolean, select } from '@storybook/addon-knobs'; # Layout|Global -A top-level layout/positioning component that allows two distinct sections to -be configured: header and body. +A top-level layout/positioning component that allows three distinct sections to +be configured: header, body, and footer. -```htmlbars +```html + ``` {{ template: hbs` - - Header - Body - + + Header + Body + Footer + `, }} diff --git a/addons/rose/tests/integration/components/rose/layout/global-test.js b/addons/rose/tests/integration/components/rose/layout/global-test.js index 2e6b91039..aa87f074b 100644 --- a/addons/rose/tests/integration/components/rose/layout/global-test.js +++ b/addons/rose/tests/integration/components/rose/layout/global-test.js @@ -30,4 +30,11 @@ module('Integration | Component | rose/layout/global', function (hooks) { `); assert.ok(find('.rose-layout-global-body')); }); + + test('it renders with footer', async function (assert) { + await render(hbs` + + `); + assert.ok(find('.rose-layout-global-footer')); + }); }); From 56b99a99a044dc5eb494f565740d0631070654e9 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 30 Sep 2020 14:15:32 -0400 Subject: [PATCH 08/13] chore: tweak button position, a11y, and add button text --- ui/core/app/components/copyable/index.hbs | 5 +++-- ui/core/app/styles/app.scss | 10 +++++++--- .../templates/scopes/scope/projects/project/index.hbs | 6 +++++- ui/core/translations/actions/en-us.yaml | 3 ++- ui/core/translations/states/en-us.yaml | 1 + 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ui/core/app/components/copyable/index.hbs b/ui/core/app/components/copyable/index.hbs index 8d0a3df75..fc47d613c 100644 --- a/ui/core/app/components/copyable/index.hbs +++ b/ui/core/app/components/copyable/index.hbs @@ -1,7 +1,6 @@ {{#if this.isClipboardLibrarySupported}} {{@text}} + title={{@buttonText}} + >{{@buttonText}} {{else}} {{yield}} diff --git a/ui/core/app/styles/app.scss b/ui/core/app/styles/app.scss index dfe9fe1f9..2cd923218 100644 --- a/ui/core/app/styles/app.scss +++ b/ui/core/app/styles/app.scss @@ -81,7 +81,11 @@ } } -.copyable .copyable-button { - padding: 0 sizing.rems(xxs); - margin: 0; +.copyable { + .copyable-button { + position: relative; + top: -2px; + padding: 0 sizing.rems(xxs); + margin: 0; + } } diff --git a/ui/core/app/templates/scopes/scope/projects/project/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/index.hbs index 58395a683..0de5bb65c 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/index.hbs @@ -7,7 +7,11 @@

{{t "resources.project.title"}}

{{t "resources.project.description"}}

- + {{@model.id}}
diff --git a/ui/core/translations/actions/en-us.yaml b/ui/core/translations/actions/en-us.yaml index 7e7a9002a..9b1fa9751 100644 --- a/ui/core/translations/actions/en-us.yaml +++ b/ui/core/translations/actions/en-us.yaml @@ -7,6 +7,7 @@ save: Save manage: Manage help: Need help? back: Back +copy-to-clipboard: Copy to Clipboard authenticate: Authenticate deauthenticate: Deauthenticate choose-org: Choose Scope @@ -27,4 +28,4 @@ add-members: Add Members add-hosts: Add Hosts set-password: Set Password change-password: Change Password -edit-form: Edit Form \ No newline at end of file +edit-form: Edit Form diff --git a/ui/core/translations/states/en-us.yaml b/ui/core/translations/states/en-us.yaml index 585ed6a26..96b1fd92c 100644 --- a/ui/core/translations/states/en-us.yaml +++ b/ui/core/translations/states/en-us.yaml @@ -2,3 +2,4 @@ info: Info success: Success warning: Warning error: Error +copied: Copied From af2710f6c47979832188ca8eac657446dc816600 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 30 Sep 2020 17:03:13 -0400 Subject: [PATCH 09/13] feat: Add global footer --- .../components/rose/footer/brand/index.hbs | 12 +++++ .../rose/footer/copyright/index.hbs | 11 ++++ .../components/rose/footer/copyright/index.js | 8 +++ .../addon/components/rose/footer/index.hbs | 11 ++++ .../components/rose/footer/index.stories.mdx | 42 +++++++++++++++ .../rose/footer/nav/external-link/index.hbs | 7 +++ .../components/rose/footer/nav/index.hbs | 5 ++ .../components/rose/footer/product/index.hbs | 11 ++++ .../addon/styles/rose/components/_index.scss | 1 + .../styles/rose/components/footer/_brand.scss | 14 +++++ .../rose/components/footer/_copyright.scss | 14 +++++ .../components/footer/_external-link.scss | 9 ++++ .../styles/rose/components/footer/_index.scss | 18 +++++++ .../styles/rose/components/footer/_nav.scss | 9 ++++ .../rose/components/footer/_product.scss | 11 ++++ addons/rose/app/components/rose/footer.js | 1 + .../rose/app/components/rose/footer/brand.js | 1 + .../app/components/rose/footer/copyright.js | 1 + addons/rose/app/components/rose/footer/nav.js | 1 + .../rose/footer/nav/external-link.js | 1 + .../app/components/rose/footer/product.js | 1 + .../components/rose/footer-test.js | 51 +++++++++++++++++++ .../components/rose/footer/brand-test.js | 15 ++++++ .../components/rose/footer/copyright-test.js | 20 ++++++++ .../components/rose/footer/nav-test.js | 24 +++++++++ .../rose/footer/nav/external-link-test.js | 15 ++++++ .../components/rose/footer/product-test.js | 22 ++++++++ ui/core/app/templates/application.hbs | 11 ++++ ui/core/translations/en-us.yaml | 9 +++- 29 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 addons/rose/addon/components/rose/footer/brand/index.hbs create mode 100644 addons/rose/addon/components/rose/footer/copyright/index.hbs create mode 100644 addons/rose/addon/components/rose/footer/copyright/index.js create mode 100644 addons/rose/addon/components/rose/footer/index.hbs create mode 100644 addons/rose/addon/components/rose/footer/index.stories.mdx create mode 100644 addons/rose/addon/components/rose/footer/nav/external-link/index.hbs create mode 100644 addons/rose/addon/components/rose/footer/nav/index.hbs create mode 100644 addons/rose/addon/components/rose/footer/product/index.hbs create mode 100644 addons/rose/addon/styles/rose/components/footer/_brand.scss create mode 100644 addons/rose/addon/styles/rose/components/footer/_copyright.scss create mode 100644 addons/rose/addon/styles/rose/components/footer/_external-link.scss create mode 100644 addons/rose/addon/styles/rose/components/footer/_index.scss create mode 100644 addons/rose/addon/styles/rose/components/footer/_nav.scss create mode 100644 addons/rose/addon/styles/rose/components/footer/_product.scss create mode 100644 addons/rose/app/components/rose/footer.js create mode 100644 addons/rose/app/components/rose/footer/brand.js create mode 100644 addons/rose/app/components/rose/footer/copyright.js create mode 100644 addons/rose/app/components/rose/footer/nav.js create mode 100644 addons/rose/app/components/rose/footer/nav/external-link.js create mode 100644 addons/rose/app/components/rose/footer/product.js create mode 100644 addons/rose/tests/integration/components/rose/footer-test.js create mode 100644 addons/rose/tests/integration/components/rose/footer/brand-test.js create mode 100644 addons/rose/tests/integration/components/rose/footer/copyright-test.js create mode 100644 addons/rose/tests/integration/components/rose/footer/nav-test.js create mode 100644 addons/rose/tests/integration/components/rose/footer/nav/external-link-test.js create mode 100644 addons/rose/tests/integration/components/rose/footer/product-test.js diff --git a/addons/rose/addon/components/rose/footer/brand/index.hbs b/addons/rose/addon/components/rose/footer/brand/index.hbs new file mode 100644 index 000000000..27b91417f --- /dev/null +++ b/addons/rose/addon/components/rose/footer/brand/index.hbs @@ -0,0 +1,12 @@ + + + {{#if @logo}} + {{inline-svg @logo}} + {{/if}} + + diff --git a/addons/rose/addon/components/rose/footer/copyright/index.hbs b/addons/rose/addon/components/rose/footer/copyright/index.hbs new file mode 100644 index 000000000..47e582dcb --- /dev/null +++ b/addons/rose/addon/components/rose/footer/copyright/index.hbs @@ -0,0 +1,11 @@ + + + © + + + {{this.currentYear}} + + + {{@text}} + + diff --git a/addons/rose/addon/components/rose/footer/copyright/index.js b/addons/rose/addon/components/rose/footer/copyright/index.js new file mode 100644 index 000000000..a9068f750 --- /dev/null +++ b/addons/rose/addon/components/rose/footer/copyright/index.js @@ -0,0 +1,8 @@ +import Component from '@glimmer/component'; + +export default class RoseFooterCopyrightComponent extends Component { + + // =attributes + currentYear = new Date().getFullYear(); + +} diff --git a/addons/rose/addon/components/rose/footer/index.hbs b/addons/rose/addon/components/rose/footer/index.hbs new file mode 100644 index 000000000..cafad5904 --- /dev/null +++ b/addons/rose/addon/components/rose/footer/index.hbs @@ -0,0 +1,11 @@ +
+ {{yield (hash + brand=(component 'rose/footer/brand') + copyright=(component 'rose/footer/copyright') + product=(component 'rose/footer/product') + nav=(component 'rose/footer/nav') + )}} +
diff --git a/addons/rose/addon/components/rose/footer/index.stories.mdx b/addons/rose/addon/components/rose/footer/index.stories.mdx new file mode 100644 index 000000000..779f1d2e6 --- /dev/null +++ b/addons/rose/addon/components/rose/footer/index.stories.mdx @@ -0,0 +1,42 @@ +import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; +import { hbs } from 'ember-cli-htmlbars'; +import { action } from '@storybook/addon-actions'; +import { text } from '@storybook/addon-knobs'; + + + +# Footer + +A footer component that allows four distinct sections to be configured: brand, nav, product, and copyright. + +```html + + + + + + Section + Section + + +``` + + + {{ + template: hbs` + + + + + + Section + Section + + + `, + context: { + brandName: text('brandName', 'Brand Name'), + copyright: text('copyright', 'Company Name'), + }, + }} + diff --git a/addons/rose/addon/components/rose/footer/nav/external-link/index.hbs b/addons/rose/addon/components/rose/footer/nav/external-link/index.hbs new file mode 100644 index 000000000..213ecce7a --- /dev/null +++ b/addons/rose/addon/components/rose/footer/nav/external-link/index.hbs @@ -0,0 +1,7 @@ + + {{yield}} + diff --git a/addons/rose/addon/components/rose/footer/nav/index.hbs b/addons/rose/addon/components/rose/footer/nav/index.hbs new file mode 100644 index 000000000..444202f6e --- /dev/null +++ b/addons/rose/addon/components/rose/footer/nav/index.hbs @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/addons/rose/addon/components/rose/footer/product/index.hbs b/addons/rose/addon/components/rose/footer/product/index.hbs new file mode 100644 index 000000000..6d3436db1 --- /dev/null +++ b/addons/rose/addon/components/rose/footer/product/index.hbs @@ -0,0 +1,11 @@ + + + {{@text}} + + + {{#if @version}} + + v{{@version}} + + {{/if}} + \ No newline at end of file diff --git a/addons/rose/addon/styles/rose/components/_index.scss b/addons/rose/addon/styles/rose/components/_index.scss index 19a9d3de6..6e6ef8490 100644 --- a/addons/rose/addon/styles/rose/components/_index.scss +++ b/addons/rose/addon/styles/rose/components/_index.scss @@ -2,6 +2,7 @@ @import 'dropdown'; @import 'form'; @import 'header'; +@import 'footer'; @import 'layout'; @import 'icon'; @import 'list'; diff --git a/addons/rose/addon/styles/rose/components/footer/_brand.scss b/addons/rose/addon/styles/rose/components/footer/_brand.scss new file mode 100644 index 000000000..26e5f2983 --- /dev/null +++ b/addons/rose/addon/styles/rose/components/footer/_brand.scss @@ -0,0 +1,14 @@ +@use '../../variables/sizing'; + +.rose-footer-brand { + display: flex; + align-items: center; + color: var(--ui-gray-starker-1); + margin: sizing.rems(xs); + + svg { + $logoSize: sizing.rems(m); + display: inline-block; + width: $logoSize; + } +} diff --git a/addons/rose/addon/styles/rose/components/footer/_copyright.scss b/addons/rose/addon/styles/rose/components/footer/_copyright.scss new file mode 100644 index 000000000..9db1a4fa1 --- /dev/null +++ b/addons/rose/addon/styles/rose/components/footer/_copyright.scss @@ -0,0 +1,14 @@ +@use '../../variables/sizing'; + +.rose-footer-copyright { + display: inline-flex; + align-items: center; + + .rose-footer-copyright-symbol { + margin-right: sizing.rems(xxxs); + } + + .rose-footer-copyright-year { + margin-right: sizing.rems(xxs); + } +} diff --git a/addons/rose/addon/styles/rose/components/footer/_external-link.scss b/addons/rose/addon/styles/rose/components/footer/_external-link.scss new file mode 100644 index 000000000..287db2b9b --- /dev/null +++ b/addons/rose/addon/styles/rose/components/footer/_external-link.scss @@ -0,0 +1,9 @@ +@use '../../variables/sizing'; + +.rose-footer-nav-external-link { + display: inline-flex; + align-items: center; + margin-right: sizing.rems(s); + text-decoration: underline; + color: var(--ui-gray-starker-1); +} diff --git a/addons/rose/addon/styles/rose/components/footer/_index.scss b/addons/rose/addon/styles/rose/components/footer/_index.scss new file mode 100644 index 000000000..93e03b5ec --- /dev/null +++ b/addons/rose/addon/styles/rose/components/footer/_index.scss @@ -0,0 +1,18 @@ +@use '../../variables/sizing'; +@use '../../variables/media'; +@use '../../utilities/type'; + +@import 'brand'; +@import 'nav'; +@import 'product'; +@import 'copyright'; +@import 'external-link'; + +.rose-footer { + @include type.type(xs); + + display: flex; + justify-content: center; + color: var(--ui-gray-starker-1); + height: sizing.rems(xxl) + sizing.rems(xxs); //65px +} diff --git a/addons/rose/addon/styles/rose/components/footer/_nav.scss b/addons/rose/addon/styles/rose/components/footer/_nav.scss new file mode 100644 index 000000000..bd23dde4a --- /dev/null +++ b/addons/rose/addon/styles/rose/components/footer/_nav.scss @@ -0,0 +1,9 @@ +@use '../../variables/sizing'; + +.rose-footer-nav { + grid-area: nav; + display: flex; + flex-wrap: wrap; + align-items: center; + margin-right: sizing.rems(s); +} diff --git a/addons/rose/addon/styles/rose/components/footer/_product.scss b/addons/rose/addon/styles/rose/components/footer/_product.scss new file mode 100644 index 000000000..510fc1670 --- /dev/null +++ b/addons/rose/addon/styles/rose/components/footer/_product.scss @@ -0,0 +1,11 @@ +@use '../../variables/sizing'; + +.rose-footer-product { + display: inline-flex; + align-items: center; + margin: 0 sizing.rems(l); + + .rose-footer-product-version { + margin-left: sizing.rems(xxxs); + } +} diff --git a/addons/rose/app/components/rose/footer.js b/addons/rose/app/components/rose/footer.js new file mode 100644 index 000000000..ccac33104 --- /dev/null +++ b/addons/rose/app/components/rose/footer.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/footer'; \ No newline at end of file diff --git a/addons/rose/app/components/rose/footer/brand.js b/addons/rose/app/components/rose/footer/brand.js new file mode 100644 index 000000000..995d715ba --- /dev/null +++ b/addons/rose/app/components/rose/footer/brand.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/footer/brand'; \ No newline at end of file diff --git a/addons/rose/app/components/rose/footer/copyright.js b/addons/rose/app/components/rose/footer/copyright.js new file mode 100644 index 000000000..d46304fc7 --- /dev/null +++ b/addons/rose/app/components/rose/footer/copyright.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/footer/copyright'; \ No newline at end of file diff --git a/addons/rose/app/components/rose/footer/nav.js b/addons/rose/app/components/rose/footer/nav.js new file mode 100644 index 000000000..3ca032af2 --- /dev/null +++ b/addons/rose/app/components/rose/footer/nav.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/footer/nav'; \ No newline at end of file diff --git a/addons/rose/app/components/rose/footer/nav/external-link.js b/addons/rose/app/components/rose/footer/nav/external-link.js new file mode 100644 index 000000000..40e8cd9f6 --- /dev/null +++ b/addons/rose/app/components/rose/footer/nav/external-link.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/footer/nav/external-link'; \ No newline at end of file diff --git a/addons/rose/app/components/rose/footer/product.js b/addons/rose/app/components/rose/footer/product.js new file mode 100644 index 000000000..7193b5690 --- /dev/null +++ b/addons/rose/app/components/rose/footer/product.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/footer/product'; \ No newline at end of file diff --git a/addons/rose/tests/integration/components/rose/footer-test.js b/addons/rose/tests/integration/components/rose/footer-test.js new file mode 100644 index 000000000..efb3147d7 --- /dev/null +++ b/addons/rose/tests/integration/components/rose/footer-test.js @@ -0,0 +1,51 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/footer', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + assert.expect(5); + await render(hbs``); + assert.ok(find('.rose-footer')); + assert.notOk(find('.rose-footer-nav')); + assert.notOk(find('.rose-footer-brand')); + assert.notOk(find('.rose-footer-product')); + assert.notOk(find('.rose-footer-copyright')); + }); + + test('it renders with brand', async function (assert) { + assert.expect(1); + await render(hbs` + + `); + assert.ok(find('.rose-footer-brand')); + }); + + test('it renders with nav', async function (assert) { + assert.expect(1); + await render(hbs` + + `); + assert.ok(find('.rose-footer-nav')); + }); + + test('it renders with product', async function (assert) { + assert.expect(1); + await render(hbs` + + `); + assert.ok(find('.rose-footer-product')); + }); + + test('it renders with copyright', async function (assert) { + assert.expect(1); + await render(hbs` + + `); + assert.ok(find('.rose-footer-copyright')); + }); + +}); diff --git a/addons/rose/tests/integration/components/rose/footer/brand-test.js b/addons/rose/tests/integration/components/rose/footer/brand-test.js new file mode 100644 index 000000000..2910d4a56 --- /dev/null +++ b/addons/rose/tests/integration/components/rose/footer/brand-test.js @@ -0,0 +1,15 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/footer/brand', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + assert.expect(2); + await render(hbs``); + assert.ok(find('.rose-footer-brand')); + assert.ok(find('.rose-footer-brand svg')); + }); +}); diff --git a/addons/rose/tests/integration/components/rose/footer/copyright-test.js b/addons/rose/tests/integration/components/rose/footer/copyright-test.js new file mode 100644 index 000000000..63d5feed0 --- /dev/null +++ b/addons/rose/tests/integration/components/rose/footer/copyright-test.js @@ -0,0 +1,20 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/footer/copyright', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + assert.expect(1); + await render(hbs``); + assert.equal(find('.rose-footer-copyright-text').textContent.trim(), 'copyright'); + }); + + test('it renders with current year', async function (assert) { + assert.expect(1); + await render(hbs``); + assert.equal(find('.rose-footer-copyright-year').textContent.trim(), new Date().getFullYear()); + }); +}); diff --git a/addons/rose/tests/integration/components/rose/footer/nav-test.js b/addons/rose/tests/integration/components/rose/footer/nav-test.js new file mode 100644 index 000000000..6ba5cdb19 --- /dev/null +++ b/addons/rose/tests/integration/components/rose/footer/nav-test.js @@ -0,0 +1,24 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find, findAll } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/footer/nav', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + assert.expect(1); + await render(hbs``); + assert.ok(find('.rose-footer-nav')); + }); + + test('it renders nav external link elements', async function (assert) { + assert.expect(1); + await render(hbs` + + + `); + assert.equal(findAll('a').length, 2); + }); + +}); diff --git a/addons/rose/tests/integration/components/rose/footer/nav/external-link-test.js b/addons/rose/tests/integration/components/rose/footer/nav/external-link-test.js new file mode 100644 index 000000000..58f389a2f --- /dev/null +++ b/addons/rose/tests/integration/components/rose/footer/nav/external-link-test.js @@ -0,0 +1,15 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/footer/nav/external-link', function(hooks) { + setupRenderingTest(hooks); + + test('it renders with link', async function (assert) { + assert.expect(2); + await render(hbs``); + assert.ok(find('a')); + assert.ok(find('.rose-footer-nav-external-link')); + }); +}); diff --git a/addons/rose/tests/integration/components/rose/footer/product-test.js b/addons/rose/tests/integration/components/rose/footer/product-test.js new file mode 100644 index 000000000..2cdd8927d --- /dev/null +++ b/addons/rose/tests/integration/components/rose/footer/product-test.js @@ -0,0 +1,22 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/footer/product', function(hooks) { + setupRenderingTest(hooks); + + test('it renders with product', async function (assert) { + assert.expect(3); + await render(hbs``); + assert.ok(find('.rose-footer-product')); + assert.equal(find('.rose-footer-product-text').textContent.trim(), 'boundary'); + assert.notOk(find('.rose-footer-product-version')); + }); + + test('it renders with product and version', async function (assert) { + assert.expect(1); + await render(hbs``); + assert.equal(find('.rose-footer-product-version').textContent.trim(), 'v1.0'); + }); +}); diff --git a/ui/core/app/templates/application.hbs b/ui/core/app/templates/application.hbs index b38e02f4d..d0728605a 100644 --- a/ui/core/app/templates/application.hbs +++ b/ui/core/app/templates/application.hbs @@ -37,6 +37,17 @@ {{outlet}} + + + + + + + {{t "hashicorp.documentation.title"}} + + + + diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml index a86a36263..cdb5cb5b7 100644 --- a/ui/core/translations/en-us.yaml +++ b/ui/core/translations/en-us.yaml @@ -17,4 +17,11 @@ titles: global: Global actions: Actions descriptions: - empty-set: There are no items to display yet. You may be able to add items or try back later. \ No newline at end of file + empty-set: There are no items to display yet. You may be able to add items or try back later. +hashicorp: + title: HashiCorp + documentation: + title: Documentation + link: https://boundaryproject.io +boundary: + version: '0.1' \ No newline at end of file From ce2fb39f596e8469047fde67dff3a9821c50add0 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 30 Sep 2020 22:15:30 -0400 Subject: [PATCH 10/13] refactor: Show acknowledgement text when copied using copyabl --- ui/core/app/components/copyable/index.hbs | 4 ++-- ui/core/app/components/copyable/index.js | 8 ++++---- .../scopes/scope/auth-methods/auth-method/-header.hbs | 6 +++++- .../auth-methods/auth-method/accounts/account/-header.hbs | 6 +++++- .../auth-method/accounts/account/set-password/-header.hbs | 6 +++++- .../scope/auth-methods/auth-method/accounts/index.hbs | 6 +++++- ui/core/app/templates/scopes/scope/auth-methods/index.hbs | 6 +++++- .../app/templates/scopes/scope/groups/group/-header.hbs | 6 +++++- .../app/templates/scopes/scope/groups/group/members.hbs | 6 +++++- ui/core/app/templates/scopes/scope/groups/index.hbs | 6 +++++- .../project/host-catalogs/host-catalog/-header.hbs | 6 +++++- .../host-catalogs/host-catalog/host-sets/-header.hbs | 6 +++++- .../host-catalog/host-sets/host-set/hosts.hbs | 6 +++++- .../host-catalogs/host-catalog/host-sets/index.hbs | 6 +++++- .../project/host-catalogs/host-catalog/hosts/-header.hbs | 6 +++++- .../project/host-catalogs/host-catalog/hosts/index.hbs | 6 +++++- .../scopes/scope/projects/project/host-catalogs/index.hbs | 6 +++++- .../scopes/scope/projects/project/sessions/index.hbs | 6 +++++- .../scopes/scope/projects/project/targets/index.hbs | 6 +++++- .../scope/projects/project/targets/target/-header.hbs | 6 +++++- .../scope/projects/project/targets/target/host-sets.hbs | 6 +++++- ui/core/app/templates/scopes/scope/roles/index.hbs | 6 +++++- ui/core/app/templates/scopes/scope/roles/role/-header.hbs | 6 +++++- .../templates/scopes/scope/roles/role/grants/-header.hbs | 6 +++++- .../app/templates/scopes/scope/roles/role/principals.hbs | 6 +++++- .../scopes/scope/roles/role/principals/-header.hbs | 8 ++++++-- ui/core/app/templates/scopes/scope/users/index.hbs | 6 +++++- ui/core/app/templates/scopes/scope/users/user/index.hbs | 6 +++++- ui/core/tests/integration/components/copyable-test.js | 2 +- 29 files changed, 138 insertions(+), 34 deletions(-) diff --git a/ui/core/app/components/copyable/index.hbs b/ui/core/app/components/copyable/index.hbs index fc47d613c..499c4fc43 100644 --- a/ui/core/app/components/copyable/index.hbs +++ b/ui/core/app/components/copyable/index.hbs @@ -15,8 +15,8 @@ class="copyable-button" @style="ghost" @iconOnly={{this.icon}} - title={{@buttonText}} - >{{@buttonText}} + title={{this.copyableButtonText}} + >{{this.copyableButtonText}} {{else}} {{yield}} diff --git a/ui/core/app/components/copyable/index.js b/ui/core/app/components/copyable/index.js index cefc032fa..010c12758 100644 --- a/ui/core/app/components/copyable/index.js +++ b/ui/core/app/components/copyable/index.js @@ -1,7 +1,6 @@ import Component from '@glimmer/component'; import ClipboardJS from 'clipboard'; import { action } from '@ember/object'; -import { tracked } from '@glimmer/tracking'; import { generateComponentID } from 'rose/utilities/component-auto-id'; import { task, timeout } from 'ember-concurrency'; import { set } from '@ember/object'; @@ -12,10 +11,9 @@ export default class CopyableComponent extends Component { // =attributes id = generateComponentID(); - copyableButtonId = `copyable-button-${this.id}`; icon = 'copy-action'; - - @tracked text; + copyableButtonId = `copyable-button-${this.id}`; + copyableButtonText = this.args.buttonText; /** * A Ember Concurrency-based task that updates copy icon to a success state @@ -29,8 +27,10 @@ export default class CopyableComponent extends Component { */ @task(function * () { set(this, 'icon', 'copy-success'); + set(this, 'copyableButtonText', this.args.acknowledgeText); yield timeout(1000); set(this, 'icon', 'copy-action'); + set(this, 'copyableButtonText', this.args.buttonText); }).drop() successIconTimer; // =methods diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/-header.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/-header.hbs index 0748ed7b8..bd1bc825e 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/-header.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.auth-method.title"}}

{{t "resources.auth-method.description"}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-header.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-header.hbs index c7a1ec474..d67dca8b1 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-header.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-header.hbs @@ -1,4 +1,8 @@

{{t "resources.account.title"}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/set-password/-header.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/set-password/-header.hbs index 1805683a2..c7d1d4670 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/set-password/-header.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/set-password/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.account.title"}}

{{t 'resources.account.messages.set-password.description'}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs index d399eb1d8..195e5a00b 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs @@ -24,7 +24,11 @@ {{account.username}}
- + {{account.id}} diff --git a/ui/core/app/templates/scopes/scope/auth-methods/index.hbs b/ui/core/app/templates/scopes/scope/auth-methods/index.hbs index 26027d51b..08b4606fe 100644 --- a/ui/core/app/templates/scopes/scope/auth-methods/index.hbs +++ b/ui/core/app/templates/scopes/scope/auth-methods/index.hbs @@ -46,7 +46,11 @@ - + {{authMethod.id}} diff --git a/ui/core/app/templates/scopes/scope/groups/group/-header.hbs b/ui/core/app/templates/scopes/scope/groups/group/-header.hbs index a876cafac..ae241529b 100644 --- a/ui/core/app/templates/scopes/scope/groups/group/-header.hbs +++ b/ui/core/app/templates/scopes/scope/groups/group/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.group.title"}}

{{t "resources.group.description"}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/groups/group/members.hbs b/ui/core/app/templates/scopes/scope/groups/group/members.hbs index ce5eee601..a478d6b83 100644 --- a/ui/core/app/templates/scopes/scope/groups/group/members.hbs +++ b/ui/core/app/templates/scopes/scope/groups/group/members.hbs @@ -17,7 +17,11 @@ {{member.displayName}} - + {{member.id}} diff --git a/ui/core/app/templates/scopes/scope/groups/index.hbs b/ui/core/app/templates/scopes/scope/groups/index.hbs index 9f9ad3fd2..559fb8314 100644 --- a/ui/core/app/templates/scopes/scope/groups/index.hbs +++ b/ui/core/app/templates/scopes/scope/groups/index.hbs @@ -39,7 +39,11 @@

{{group.description}}

- + {{group.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs index 8857383a2..647741ad9 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.host-catalog.title"}}

{{t "resources.host-catalog.description"}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/-header.hbs index 26afcea96..3c76eafd3 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/-header.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.host-set.title"}}

{{t "resources.host-set.description"}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs index 7b65efa26..74cbbe2bb 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs @@ -25,7 +25,11 @@ {{host.type}} - + {{host.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.hbs index f2dff570d..bb5f4c14c 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/host-sets/index.hbs @@ -26,7 +26,11 @@ - + {{hostSet.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/-header.hbs index f0d679039..d2628a102 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/-header.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.host.title"}}

{{t "resources.host.description"}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs index 87ae8db1a..e29e8dca1 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/host-catalog/hosts/index.hbs @@ -27,7 +27,11 @@ - + {{host.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs index 2f758b992..0a70b3ee4 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/host-catalogs/index.hbs @@ -47,7 +47,11 @@ - + {{hostCatalog.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs index b4e5d3e4f..16fc16a1c 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/sessions/index.hbs @@ -28,7 +28,11 @@ {{#each @model as |sessionAggregate|}} - + {{sessionAggregate.session.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs index ff84ac48e..2cb938f29 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/targets/index.hbs @@ -51,7 +51,11 @@ {{/if}} - + {{target.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs index b96093e47..b6f507ea4 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/targets/target/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.target.title"}}

{{t "resources.target.description"}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs b/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs index e03aa2610..f6e32b99a 100644 --- a/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs +++ b/ui/core/app/templates/scopes/scope/projects/project/targets/target/host-sets.hbs @@ -22,7 +22,11 @@ {{t (concat 'resources.host-set.types.' hostSet.model.type)}} - + {{hostSet.model.id}} diff --git a/ui/core/app/templates/scopes/scope/roles/index.hbs b/ui/core/app/templates/scopes/scope/roles/index.hbs index 417860216..77c5d7d6a 100644 --- a/ui/core/app/templates/scopes/scope/roles/index.hbs +++ b/ui/core/app/templates/scopes/scope/roles/index.hbs @@ -41,7 +41,11 @@

{{role.description}}

- + {{role.id}} diff --git a/ui/core/app/templates/scopes/scope/roles/role/-header.hbs b/ui/core/app/templates/scopes/scope/roles/role/-header.hbs index 926771735..03164c9b2 100644 --- a/ui/core/app/templates/scopes/scope/roles/role/-header.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.role.title"}}

{{t "resources.role.description"}}

- + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/roles/role/grants/-header.hbs b/ui/core/app/templates/scopes/scope/roles/role/grants/-header.hbs index ccea2b2d0..48e974188 100644 --- a/ui/core/app/templates/scopes/scope/roles/role/grants/-header.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role/grants/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.role.title"}}

{{t "resources.role.grant.description"}}

- + {{@model.id}} \ No newline at end of file diff --git a/ui/core/app/templates/scopes/scope/roles/role/principals.hbs b/ui/core/app/templates/scopes/scope/roles/role/principals.hbs index 58041d4a0..668b93e4f 100644 --- a/ui/core/app/templates/scopes/scope/roles/role/principals.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role/principals.hbs @@ -21,7 +21,11 @@ {{t (concat 'resources.role.principal.types.' principal.type)}} - + {{principal.model.id}} diff --git a/ui/core/app/templates/scopes/scope/roles/role/principals/-header.hbs b/ui/core/app/templates/scopes/scope/roles/role/principals/-header.hbs index 057a23f76..499d7ff96 100644 --- a/ui/core/app/templates/scopes/scope/roles/role/principals/-header.hbs +++ b/ui/core/app/templates/scopes/scope/roles/role/principals/-header.hbs @@ -1,5 +1,9 @@

{{t "resources.role.title"}}

{{t "resources.role.principal.description"}}

- - {{@model.role.id}} + + {{@model.id}} diff --git a/ui/core/app/templates/scopes/scope/users/index.hbs b/ui/core/app/templates/scopes/scope/users/index.hbs index 50bcd7b74..7f5154949 100644 --- a/ui/core/app/templates/scopes/scope/users/index.hbs +++ b/ui/core/app/templates/scopes/scope/users/index.hbs @@ -41,7 +41,11 @@

{{user.description}}

- + {{user.id}} diff --git a/ui/core/app/templates/scopes/scope/users/user/index.hbs b/ui/core/app/templates/scopes/scope/users/user/index.hbs index 7f9218f1b..e88672ab6 100644 --- a/ui/core/app/templates/scopes/scope/users/user/index.hbs +++ b/ui/core/app/templates/scopes/scope/users/user/index.hbs @@ -7,7 +7,11 @@

{{t "resources.user.title"}}

{{t "resources.user.description"}}

- + {{@model.id}}
diff --git a/ui/core/tests/integration/components/copyable-test.js b/ui/core/tests/integration/components/copyable-test.js index 07be2788f..8d6a29cf9 100644 --- a/ui/core/tests/integration/components/copyable-test.js +++ b/ui/core/tests/integration/components/copyable-test.js @@ -7,7 +7,7 @@ module('Integration | Component | copyable', function(hooks) { setupRenderingTest(hooks); test('it renders', async function(assert) { - await render(hbs`text`); + await render(hbs`text`); assert.ok(find('.copyable')); assert.equal(find('.copyable-content').textContent.trim(), 'text'); assert.equal(find('.copyable-button').textContent.trim(), 'Copy me'); From b19cbee609730ebdcf884c77c9675a75f6a6973a Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 30 Sep 2020 22:25:40 -0400 Subject: [PATCH 11/13] feat: Disable change password link in header --- ui/core/app/router.js | 3 ++- ui/core/app/templates/application.hbs | 4 ++-- ui/core/tests/acceptance/accounts/change-password-test.js | 5 +++++ ui/core/tests/unit/routes/account/change-password-test.js | 5 +++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ui/core/app/router.js b/ui/core/app/router.js index 0894289f9..bebf3f0a2 100644 --- a/ui/core/app/router.js +++ b/ui/core/app/router.js @@ -94,6 +94,7 @@ Router.map(function () { }); this.route('account', function() { - this.route('change-password'); + // Enable after full account feature implementation + // this.route('change-password'); }); }); diff --git a/ui/core/app/templates/application.hbs b/ui/core/app/templates/application.hbs index f8de5b3f9..d63eee931 100644 --- a/ui/core/app/templates/application.hbs +++ b/ui/core/app/templates/application.hbs @@ -19,9 +19,9 @@ @iconOnly={{true}} @icon="boundary-icons/user-profile" as |dropdown| > - + {{!-- {{t 'actions.change-password'}} - + --}} diff --git a/ui/core/tests/acceptance/accounts/change-password-test.js b/ui/core/tests/acceptance/accounts/change-password-test.js index 27a28ba3d..fee06b101 100644 --- a/ui/core/tests/acceptance/accounts/change-password-test.js +++ b/ui/core/tests/acceptance/accounts/change-password-test.js @@ -1,3 +1,5 @@ +// Enable after account workflow implementation +/* import { module, test } from 'qunit'; import { visit, currentURL, click, find, fillIn } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; @@ -15,6 +17,7 @@ module('Acceptance | accounts | change password', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); + const instances = { scopes: { global: null, @@ -114,4 +117,6 @@ module('Acceptance | accounts | change password', function (hooks) { await visit(urls.changePassword); assert.notEqual(currentURL(), urls.changePassword); }); + }); +*/ diff --git a/ui/core/tests/unit/routes/account/change-password-test.js b/ui/core/tests/unit/routes/account/change-password-test.js index ee6856d35..4481d783e 100644 --- a/ui/core/tests/unit/routes/account/change-password-test.js +++ b/ui/core/tests/unit/routes/account/change-password-test.js @@ -5,7 +5,8 @@ module('Unit | Route | account/change-password', function(hooks) { setupTest(hooks); test('it exists', function(assert) { - let route = this.owner.lookup('route:account/change-password'); - assert.ok(route); + // let route = this.owner.lookup('route:account/change-password'); + // assert.ok(route); + assert.expect(0); }); }); From d26f6896bcc55a29a16d20cbc11b700446162f88 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 30 Sep 2020 23:03:01 -0400 Subject: [PATCH 12/13] refactor: Simplify rose/footer component Reduce number of elements footer supports --- .../addon/components/rose/footer/index.hbs | 5 ++-- .../components/rose/footer/index.stories.mdx | 18 +++++++------- .../rose/footer/nav/external-link/index.hbs | 7 ------ .../components/rose/footer/nav/index.hbs | 2 +- .../components/rose/footer/nav/link/index.hbs | 20 ++++++++++++++++ .../rose/components/footer/_copyright.scss | 14 ----------- .../styles/rose/components/footer/_index.scss | 5 ++-- .../{_external-link.scss => _link.scss} | 4 ++-- .../rose/components/footer/_product.scss | 11 --------- .../styles/rose/components/footer/_text.scss | 7 ++++++ .../rose/footer/nav/external-link.js | 1 - .../app/components/rose/footer/nav/link.js | 1 + .../components/rose/footer-test.js | 19 ++++----------- .../components/rose/footer/brand-test.js | 15 ------------ .../components/rose/footer/copyright-test.js | 20 ---------------- .../components/rose/footer/nav-test.js | 4 ++-- .../rose/footer/nav/external-link-test.js | 15 ------------ .../components/rose/footer/nav/link-test.js | 22 +++++++++++++++++ .../components/rose/footer/product-test.js | 22 ----------------- .../components/rose/footer/text-test.js | 24 +++++++++++++++++++ ui/core/app/templates/application.hbs | 6 ++--- ui/core/translations/en-us.yaml | 4 ++-- 22 files changed, 101 insertions(+), 145 deletions(-) delete mode 100644 addons/rose/addon/components/rose/footer/nav/external-link/index.hbs create mode 100644 addons/rose/addon/components/rose/footer/nav/link/index.hbs delete mode 100644 addons/rose/addon/styles/rose/components/footer/_copyright.scss rename addons/rose/addon/styles/rose/components/footer/{_external-link.scss => _link.scss} (69%) delete mode 100644 addons/rose/addon/styles/rose/components/footer/_product.scss create mode 100644 addons/rose/addon/styles/rose/components/footer/_text.scss delete mode 100644 addons/rose/app/components/rose/footer/nav/external-link.js create mode 100644 addons/rose/app/components/rose/footer/nav/link.js delete mode 100644 addons/rose/tests/integration/components/rose/footer/brand-test.js delete mode 100644 addons/rose/tests/integration/components/rose/footer/copyright-test.js delete mode 100644 addons/rose/tests/integration/components/rose/footer/nav/external-link-test.js create mode 100644 addons/rose/tests/integration/components/rose/footer/nav/link-test.js delete mode 100644 addons/rose/tests/integration/components/rose/footer/product-test.js create mode 100644 addons/rose/tests/integration/components/rose/footer/text-test.js diff --git a/addons/rose/addon/components/rose/footer/index.hbs b/addons/rose/addon/components/rose/footer/index.hbs index cafad5904..bbe5ecc72 100644 --- a/addons/rose/addon/components/rose/footer/index.hbs +++ b/addons/rose/addon/components/rose/footer/index.hbs @@ -3,9 +3,8 @@ class="rose-footer" > {{yield (hash - brand=(component 'rose/footer/brand') - copyright=(component 'rose/footer/copyright') - product=(component 'rose/footer/product') nav=(component 'rose/footer/nav') + brand=(component 'rose/footer/brand') + text=(component "rose/anonymous" class="rose-footer-text") )}} diff --git a/addons/rose/addon/components/rose/footer/index.stories.mdx b/addons/rose/addon/components/rose/footer/index.stories.mdx index 779f1d2e6..608bc1068 100644 --- a/addons/rose/addon/components/rose/footer/index.stories.mdx +++ b/addons/rose/addon/components/rose/footer/index.stories.mdx @@ -7,16 +7,15 @@ import { text } from '@storybook/addon-knobs'; # Footer -A footer component that allows four distinct sections to be configured: brand, nav, product, and copyright. +A footer component that allows four distinct sections to be configured: brand, nav, and text. ```html - - + Text - Section - Section + Section + Section ``` @@ -26,17 +25,16 @@ A footer component that allows four distinct sections to be configured: brand, n template: hbs` - - + {{footerText}} - Section - Section + Section + Section `, context: { brandName: text('brandName', 'Brand Name'), - copyright: text('copyright', 'Company Name'), + footerText: text('footerText', 'Text'), }, }} diff --git a/addons/rose/addon/components/rose/footer/nav/external-link/index.hbs b/addons/rose/addon/components/rose/footer/nav/external-link/index.hbs deleted file mode 100644 index 213ecce7a..000000000 --- a/addons/rose/addon/components/rose/footer/nav/external-link/index.hbs +++ /dev/null @@ -1,7 +0,0 @@ - - {{yield}} - diff --git a/addons/rose/addon/components/rose/footer/nav/index.hbs b/addons/rose/addon/components/rose/footer/nav/index.hbs index 444202f6e..c03ac88c9 100644 --- a/addons/rose/addon/components/rose/footer/nav/index.hbs +++ b/addons/rose/addon/components/rose/footer/nav/index.hbs @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/addons/rose/addon/components/rose/footer/nav/link/index.hbs b/addons/rose/addon/components/rose/footer/nav/link/index.hbs new file mode 100644 index 000000000..bebaacc29 --- /dev/null +++ b/addons/rose/addon/components/rose/footer/nav/link/index.hbs @@ -0,0 +1,20 @@ +{{#if @href}} + + {{yield}} + +{{/if}} + +{{#if @route}} + + {{yield}} + +{{/if}} diff --git a/addons/rose/addon/styles/rose/components/footer/_copyright.scss b/addons/rose/addon/styles/rose/components/footer/_copyright.scss deleted file mode 100644 index 9db1a4fa1..000000000 --- a/addons/rose/addon/styles/rose/components/footer/_copyright.scss +++ /dev/null @@ -1,14 +0,0 @@ -@use '../../variables/sizing'; - -.rose-footer-copyright { - display: inline-flex; - align-items: center; - - .rose-footer-copyright-symbol { - margin-right: sizing.rems(xxxs); - } - - .rose-footer-copyright-year { - margin-right: sizing.rems(xxs); - } -} diff --git a/addons/rose/addon/styles/rose/components/footer/_index.scss b/addons/rose/addon/styles/rose/components/footer/_index.scss index 93e03b5ec..9de207b95 100644 --- a/addons/rose/addon/styles/rose/components/footer/_index.scss +++ b/addons/rose/addon/styles/rose/components/footer/_index.scss @@ -4,9 +4,8 @@ @import 'brand'; @import 'nav'; -@import 'product'; -@import 'copyright'; -@import 'external-link'; +@import 'text'; +@import 'link'; .rose-footer { @include type.type(xs); diff --git a/addons/rose/addon/styles/rose/components/footer/_external-link.scss b/addons/rose/addon/styles/rose/components/footer/_link.scss similarity index 69% rename from addons/rose/addon/styles/rose/components/footer/_external-link.scss rename to addons/rose/addon/styles/rose/components/footer/_link.scss index 287db2b9b..dc35db4c0 100644 --- a/addons/rose/addon/styles/rose/components/footer/_external-link.scss +++ b/addons/rose/addon/styles/rose/components/footer/_link.scss @@ -1,9 +1,9 @@ @use '../../variables/sizing'; -.rose-footer-nav-external-link { +.rose-footer-nav-link { display: inline-flex; align-items: center; - margin-right: sizing.rems(s); text-decoration: underline; color: var(--ui-gray-starker-1); + margin: 0 sizing.rems(xs); } diff --git a/addons/rose/addon/styles/rose/components/footer/_product.scss b/addons/rose/addon/styles/rose/components/footer/_product.scss deleted file mode 100644 index 510fc1670..000000000 --- a/addons/rose/addon/styles/rose/components/footer/_product.scss +++ /dev/null @@ -1,11 +0,0 @@ -@use '../../variables/sizing'; - -.rose-footer-product { - display: inline-flex; - align-items: center; - margin: 0 sizing.rems(l); - - .rose-footer-product-version { - margin-left: sizing.rems(xxxs); - } -} diff --git a/addons/rose/addon/styles/rose/components/footer/_text.scss b/addons/rose/addon/styles/rose/components/footer/_text.scss new file mode 100644 index 000000000..9e7b29b8b --- /dev/null +++ b/addons/rose/addon/styles/rose/components/footer/_text.scss @@ -0,0 +1,7 @@ +@use '../../variables/sizing'; + +.rose-footer-text { + display: inline-flex; + align-items: center; + margin: 0 sizing.rems(xs); +} diff --git a/addons/rose/app/components/rose/footer/nav/external-link.js b/addons/rose/app/components/rose/footer/nav/external-link.js deleted file mode 100644 index 40e8cd9f6..000000000 --- a/addons/rose/app/components/rose/footer/nav/external-link.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'rose/components/rose/footer/nav/external-link'; \ No newline at end of file diff --git a/addons/rose/app/components/rose/footer/nav/link.js b/addons/rose/app/components/rose/footer/nav/link.js new file mode 100644 index 000000000..e38b27530 --- /dev/null +++ b/addons/rose/app/components/rose/footer/nav/link.js @@ -0,0 +1 @@ +export { default } from 'rose/components/rose/footer/nav/link'; \ No newline at end of file diff --git a/addons/rose/tests/integration/components/rose/footer-test.js b/addons/rose/tests/integration/components/rose/footer-test.js index efb3147d7..4a43f0d4f 100644 --- a/addons/rose/tests/integration/components/rose/footer-test.js +++ b/addons/rose/tests/integration/components/rose/footer-test.js @@ -7,13 +7,12 @@ module('Integration | Component | rose/footer', function(hooks) { setupRenderingTest(hooks); test('it renders', async function (assert) { - assert.expect(5); + assert.expect(4); await render(hbs``); assert.ok(find('.rose-footer')); assert.notOk(find('.rose-footer-nav')); + assert.notOk(find('.rose-footer-text')); assert.notOk(find('.rose-footer-brand')); - assert.notOk(find('.rose-footer-product')); - assert.notOk(find('.rose-footer-copyright')); }); test('it renders with brand', async function (assert) { @@ -32,20 +31,12 @@ module('Integration | Component | rose/footer', function(hooks) { assert.ok(find('.rose-footer-nav')); }); - test('it renders with product', async function (assert) { + test('it renders with text', async function (assert) { assert.expect(1); await render(hbs` - + `); - assert.ok(find('.rose-footer-product')); - }); - - test('it renders with copyright', async function (assert) { - assert.expect(1); - await render(hbs` - - `); - assert.ok(find('.rose-footer-copyright')); + assert.ok(find('.rose-footer-text')); }); }); diff --git a/addons/rose/tests/integration/components/rose/footer/brand-test.js b/addons/rose/tests/integration/components/rose/footer/brand-test.js deleted file mode 100644 index 2910d4a56..000000000 --- a/addons/rose/tests/integration/components/rose/footer/brand-test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | rose/footer/brand', function(hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - assert.expect(2); - await render(hbs``); - assert.ok(find('.rose-footer-brand')); - assert.ok(find('.rose-footer-brand svg')); - }); -}); diff --git a/addons/rose/tests/integration/components/rose/footer/copyright-test.js b/addons/rose/tests/integration/components/rose/footer/copyright-test.js deleted file mode 100644 index 63d5feed0..000000000 --- a/addons/rose/tests/integration/components/rose/footer/copyright-test.js +++ /dev/null @@ -1,20 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | rose/footer/copyright', function(hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - assert.expect(1); - await render(hbs``); - assert.equal(find('.rose-footer-copyright-text').textContent.trim(), 'copyright'); - }); - - test('it renders with current year', async function (assert) { - assert.expect(1); - await render(hbs``); - assert.equal(find('.rose-footer-copyright-year').textContent.trim(), new Date().getFullYear()); - }); -}); diff --git a/addons/rose/tests/integration/components/rose/footer/nav-test.js b/addons/rose/tests/integration/components/rose/footer/nav-test.js index 6ba5cdb19..782602f44 100644 --- a/addons/rose/tests/integration/components/rose/footer/nav-test.js +++ b/addons/rose/tests/integration/components/rose/footer/nav-test.js @@ -15,8 +15,8 @@ module('Integration | Component | rose/footer/nav', function(hooks) { test('it renders nav external link elements', async function (assert) { assert.expect(1); await render(hbs` - - + + `); assert.equal(findAll('a').length, 2); }); diff --git a/addons/rose/tests/integration/components/rose/footer/nav/external-link-test.js b/addons/rose/tests/integration/components/rose/footer/nav/external-link-test.js deleted file mode 100644 index 58f389a2f..000000000 --- a/addons/rose/tests/integration/components/rose/footer/nav/external-link-test.js +++ /dev/null @@ -1,15 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | rose/footer/nav/external-link', function(hooks) { - setupRenderingTest(hooks); - - test('it renders with link', async function (assert) { - assert.expect(2); - await render(hbs``); - assert.ok(find('a')); - assert.ok(find('.rose-footer-nav-external-link')); - }); -}); diff --git a/addons/rose/tests/integration/components/rose/footer/nav/link-test.js b/addons/rose/tests/integration/components/rose/footer/nav/link-test.js new file mode 100644 index 000000000..d5405db01 --- /dev/null +++ b/addons/rose/tests/integration/components/rose/footer/nav/link-test.js @@ -0,0 +1,22 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/footer/nav/link', function(hooks) { + setupRenderingTest(hooks); + + test('it renders with @href', async function (assert) { + assert.expect(2); + await render(hbs``); + assert.ok(find('a')); + assert.ok(find('.rose-footer-nav-link')); + }); + + test('it renders with @route', async function (assert) { + assert.expect(2); + await render(hbs``); + assert.ok(find('a')); + assert.ok(find('.rose-footer-nav-link')); + }); +}); diff --git a/addons/rose/tests/integration/components/rose/footer/product-test.js b/addons/rose/tests/integration/components/rose/footer/product-test.js deleted file mode 100644 index 2cdd8927d..000000000 --- a/addons/rose/tests/integration/components/rose/footer/product-test.js +++ /dev/null @@ -1,22 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | rose/footer/product', function(hooks) { - setupRenderingTest(hooks); - - test('it renders with product', async function (assert) { - assert.expect(3); - await render(hbs``); - assert.ok(find('.rose-footer-product')); - assert.equal(find('.rose-footer-product-text').textContent.trim(), 'boundary'); - assert.notOk(find('.rose-footer-product-version')); - }); - - test('it renders with product and version', async function (assert) { - assert.expect(1); - await render(hbs``); - assert.equal(find('.rose-footer-product-version').textContent.trim(), 'v1.0'); - }); -}); diff --git a/addons/rose/tests/integration/components/rose/footer/text-test.js b/addons/rose/tests/integration/components/rose/footer/text-test.js new file mode 100644 index 000000000..d3cbfacff --- /dev/null +++ b/addons/rose/tests/integration/components/rose/footer/text-test.js @@ -0,0 +1,24 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render, find } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | rose/footer/text', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + assert.expect(1); + await render(hbs` + + `); + assert.ok(find('.rose-footer-text')); + }); + + test('it renders content', async function (assert) { + assert.expect(1); + await render(hbs` + content + `); + assert.equal(find('.rose-footer-text').textContent.trim(), 'content'); + }); +}); diff --git a/ui/core/app/templates/application.hbs b/ui/core/app/templates/application.hbs index 5a8003366..7d2f00db3 100644 --- a/ui/core/app/templates/application.hbs +++ b/ui/core/app/templates/application.hbs @@ -40,10 +40,10 @@ - - + {{t "hashicorp.copyright"}} + {{t "hashicorp.product"}} - {{t "hashicorp.documentation.title"}} + {{t "hashicorp.documentation.title"}} diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml index cdb5cb5b7..6755b8976 100644 --- a/ui/core/translations/en-us.yaml +++ b/ui/core/translations/en-us.yaml @@ -20,8 +20,8 @@ descriptions: empty-set: There are no items to display yet. You may be able to add items or try back later. hashicorp: title: HashiCorp + copyright: © 2020 HashiCorp + product: Boundary v0.1 documentation: title: Documentation link: https://boundaryproject.io -boundary: - version: '0.1' \ No newline at end of file From d76bc046a66d6d87ee5db8fa401bcd95484d226b Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 1 Oct 2020 11:19:41 -0400 Subject: [PATCH 13/13] chore: remove comment --- addons/rose/addon/styles/rose/components/footer/_index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/rose/addon/styles/rose/components/footer/_index.scss b/addons/rose/addon/styles/rose/components/footer/_index.scss index 9de207b95..9632c4e0c 100644 --- a/addons/rose/addon/styles/rose/components/footer/_index.scss +++ b/addons/rose/addon/styles/rose/components/footer/_index.scss @@ -13,5 +13,5 @@ display: flex; justify-content: center; color: var(--ui-gray-starker-1); - height: sizing.rems(xxl) + sizing.rems(xxs); //65px + height: sizing.rems(xxl) + sizing.rems(xxs); }