From fd5143286f8792576c9a297a754f1ae7c52d0840 Mon Sep 17 00:00:00 2001 From: Cameron Perera Date: Tue, 25 Jun 2024 22:29:43 -0500 Subject: [PATCH] Icu 13892 create tags tab route and view (#2362) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 add workers/worker/tags route ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * feat: 🎸 create workers/worker/header component ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * feat: 🎸 create workers/worker/nav component ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * feat: 🎸 create workers/worker/actions component ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * feat: 🎸 add breadcrumbs, header, nav, and actions for tags ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * feat: 🎸 create table to display worker tags ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * chore: 🤖 add license headers ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * refactor: 💡 small changes after flyout changes added ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * refactor: 💡 update manage dropdown to use hds::dropdown ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 * test: 💍 fix failing test after HDS refactor ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-13892 --- addons/core/translations/resources/en-us.yaml | 10 ++- .../workers/worker/actions/index.hbs | 16 +++++ .../workers/worker/header/index.hbs | 11 ++++ .../components/workers/worker/nav/index.hbs | 13 ++++ .../scopes/scope/workers/worker/tags.js | 10 +++ ui/admin/app/router.js | 4 +- .../scopes/scope/workers/worker/tags.js | 8 +++ .../templates/scopes/scope/workers/index.hbs | 7 +-- .../scopes/scope/workers/worker/index.hbs | 32 ++-------- .../scopes/scope/workers/worker/tags.hbs | 62 +++++++++++++++++++ .../tests/acceptance/workers/delete-test.js | 21 ++++--- .../tests/acceptance/workers/list-test.js | 4 +- .../tests/acceptance/workers/tags-test.js | 47 ++++++++++++++ .../workers/worker/actions/index-test.js | 30 +++++++++ .../workers/worker/header/index-test.js | 28 +++++++++ .../workers/worker/nav/index-test.js | 23 +++++++ .../scopes/scope/workers/worker/tags-test.js | 21 +++++++ .../scopes/scope/workers/worker/tags-test.js | 16 +++++ 18 files changed, 321 insertions(+), 42 deletions(-) create mode 100644 ui/admin/app/components/workers/worker/actions/index.hbs create mode 100644 ui/admin/app/components/workers/worker/header/index.hbs create mode 100644 ui/admin/app/components/workers/worker/nav/index.hbs create mode 100644 ui/admin/app/controllers/scopes/scope/workers/worker/tags.js create mode 100644 ui/admin/app/routes/scopes/scope/workers/worker/tags.js create mode 100644 ui/admin/app/templates/scopes/scope/workers/worker/tags.hbs create mode 100644 ui/admin/tests/acceptance/workers/tags-test.js create mode 100644 ui/admin/tests/integration/components/workers/worker/actions/index-test.js create mode 100644 ui/admin/tests/integration/components/workers/worker/header/index-test.js create mode 100644 ui/admin/tests/integration/components/workers/worker/nav/index-test.js create mode 100644 ui/admin/tests/unit/controllers/scopes/scope/workers/worker/tags-test.js create mode 100644 ui/admin/tests/unit/routes/scopes/scope/workers/worker/tags-test.js diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml index f972197c0..57d379ac9 100644 --- a/addons/core/translations/resources/en-us.yaml +++ b/addons/core/translations/resources/en-us.yaml @@ -983,11 +983,15 @@ worker: ip_address: IP Address release_version: Release Version tag_count: '{tagCount, plural, =1 {# tag} other {# tags}}' + tag: Tag + key: Key + value: Value + type: Type + tags: + title_plural: Tags + description: Tags are used to define the type of worker and to make it distinguishable amongst other workers. flyout: title: Tags in {workerName} - table: - tag: Tag - type: Type action: view_more: View more tags form: diff --git a/ui/admin/app/components/workers/worker/actions/index.hbs b/ui/admin/app/components/workers/worker/actions/index.hbs new file mode 100644 index 000000000..e6882134e --- /dev/null +++ b/ui/admin/app/components/workers/worker/actions/index.hbs @@ -0,0 +1,16 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + + + {{#if (can 'delete worker' @model)}} + + {{/if}} + \ No newline at end of file diff --git a/ui/admin/app/components/workers/worker/header/index.hbs b/ui/admin/app/components/workers/worker/header/index.hbs new file mode 100644 index 000000000..cd932eb18 --- /dev/null +++ b/ui/admin/app/components/workers/worker/header/index.hbs @@ -0,0 +1,11 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + +

+ {{t 'resources.worker.title'}} + +

+

{{t 'resources.worker.description'}}

+ \ No newline at end of file diff --git a/ui/admin/app/components/workers/worker/nav/index.hbs b/ui/admin/app/components/workers/worker/nav/index.hbs new file mode 100644 index 000000000..db8eaed35 --- /dev/null +++ b/ui/admin/app/components/workers/worker/nav/index.hbs @@ -0,0 +1,13 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + + + + {{t 'titles.details'}} + + + {{t 'resources.worker.tags.title_plural'}} + + \ No newline at end of file diff --git a/ui/admin/app/controllers/scopes/scope/workers/worker/tags.js b/ui/admin/app/controllers/scopes/scope/workers/worker/tags.js new file mode 100644 index 000000000..95fd1a3ef --- /dev/null +++ b/ui/admin/app/controllers/scopes/scope/workers/worker/tags.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Controller, { inject as controller } from '@ember/controller'; + +export default class ScopesScopeWorkersWorkerTagsController extends Controller { + @controller('scopes/scope/workers/index') workers; +} diff --git a/ui/admin/app/router.js b/ui/admin/app/router.js index ecac55a4e..8e7970414 100644 --- a/ui/admin/app/router.js +++ b/ui/admin/app/router.js @@ -153,7 +153,9 @@ Router.map(function () { }); this.route('workers', function () { this.route('new'); - this.route('worker', { path: ':worker_id' }, function () {}); + this.route('worker', { path: ':worker_id' }, function () { + this.route('tags'); + }); }); this.route('session-recordings', function () { this.route( diff --git a/ui/admin/app/routes/scopes/scope/workers/worker/tags.js b/ui/admin/app/routes/scopes/scope/workers/worker/tags.js new file mode 100644 index 000000000..a472aac49 --- /dev/null +++ b/ui/admin/app/routes/scopes/scope/workers/worker/tags.js @@ -0,0 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Route from '@ember/routing/route'; + +export default class ScopesScopeWorkersWorkerTagsRoute extends Route {} diff --git a/ui/admin/app/templates/scopes/scope/workers/index.hbs b/ui/admin/app/templates/scopes/scope/workers/index.hbs index c33f3ec3c..054eb45ff 100644 --- a/ui/admin/app/templates/scopes/scope/workers/index.hbs +++ b/ui/admin/app/templates/scopes/scope/workers/index.hbs @@ -166,8 +166,8 @@ @@ -186,12 +186,11 @@ {{#if (gt this.selectedWorker.allTags.length 10)}}
- {{! TODO: Update route to worker.tags once route is added }}
diff --git a/ui/admin/app/templates/scopes/scope/workers/worker/index.hbs b/ui/admin/app/templates/scopes/scope/workers/worker/index.hbs index b3bb0260c..34679a7c9 100644 --- a/ui/admin/app/templates/scopes/scope/workers/worker/index.hbs +++ b/ui/admin/app/templates/scopes/scope/workers/worker/index.hbs @@ -10,38 +10,18 @@ -

- {{t 'resources.worker.title'}} - -

-

{{t 'resources.worker.description'}}

- +
- - - {{t 'titles.details'}} - - + - - {{#if (can 'delete worker' @model)}} - - {{t 'resources.worker.actions.delete'}} - - {{/if}} - + diff --git a/ui/admin/app/templates/scopes/scope/workers/worker/tags.hbs b/ui/admin/app/templates/scopes/scope/workers/worker/tags.hbs new file mode 100644 index 000000000..18bb2ea59 --- /dev/null +++ b/ui/admin/app/templates/scopes/scope/workers/worker/tags.hbs @@ -0,0 +1,62 @@ +{{! + Copyright (c) HashiCorp, Inc. + SPDX-License-Identifier: BUSL-1.1 +}} + +{{page-title (t 'resources.worker.tags.title_plural')}} + + + + + + + + + + + + + + + + + + + + + + {{#if @model.allTags}} + + <:body as |B|> + + + {{B.data.key}} + + + {{B.data.value}} + + + + + + + + {{/if}} + + + + \ No newline at end of file diff --git a/ui/admin/tests/acceptance/workers/delete-test.js b/ui/admin/tests/acceptance/workers/delete-test.js index 4ddb06992..9350c1e79 100644 --- a/ui/admin/tests/acceptance/workers/delete-test.js +++ b/ui/admin/tests/acceptance/workers/delete-test.js @@ -21,6 +21,10 @@ module('Acceptance | workers | delete', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); + const MANAGE_DROPDOWN_TOGGLE = + '[data-test-manage-worker-dropdown] div button'; + const REMOVE_WORKER_BUTTON = + '[data-test-manage-worker-dropdown] div:nth-child(2) button'; let getWorkerCount; const instances = { @@ -54,7 +58,8 @@ module('Acceptance | workers | delete', function (hooks) { test('can delete a worker', async function (assert) { const count = getWorkerCount(); await visit(urls.worker); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + await click(MANAGE_DROPDOWN_TOGGLE); + await click(REMOVE_WORKER_BUTTON); assert.strictEqual(getWorkerCount(), count - 1); }); @@ -64,7 +69,8 @@ module('Acceptance | workers | delete', function (hooks) { confirmService.confirm = sinon.fake.returns(resolve()); const count = getWorkerCount(); await visit(urls.worker); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + await click(MANAGE_DROPDOWN_TOGGLE); + await click(REMOVE_WORKER_BUTTON); assert.strictEqual(getWorkerCount(), count - 1); assert.ok(confirmService.confirm.calledOnce); }); @@ -75,7 +81,8 @@ module('Acceptance | workers | delete', function (hooks) { confirmService.confirm = sinon.fake.returns(reject()); const count = getWorkerCount(); await visit(urls.worker); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + await click(MANAGE_DROPDOWN_TOGGLE); + await click(REMOVE_WORKER_BUTTON); assert.strictEqual(getWorkerCount(), count); assert.ok(confirmService.confirm.calledOnce); }); @@ -84,9 +91,8 @@ module('Acceptance | workers | delete', function (hooks) { instances.worker.authorized_actions = instances.worker.authorized_actions.filter((item) => item !== 'delete'); await visit(urls.worker); - assert - .dom('.rose-layout-page-actions .rose-dropdown-button-danger') - .isNotVisible(); + await click(MANAGE_DROPDOWN_TOGGLE); + assert.dom(REMOVE_WORKER_BUTTON).isNotVisible(); }); test('deleting a worker which errors displays error messages', async function (assert) { @@ -102,7 +108,8 @@ module('Acceptance | workers | delete', function (hooks) { ); }); await visit(urls.worker); - await click('.rose-layout-page-actions .rose-dropdown-button-danger'); + await click(MANAGE_DROPDOWN_TOGGLE); + await click(REMOVE_WORKER_BUTTON); assert.ok(find('[role="alert"]').textContent.trim(), 'Oops.'); }); }); diff --git a/ui/admin/tests/acceptance/workers/list-test.js b/ui/admin/tests/acceptance/workers/list-test.js index f9275b506..2e73cb327 100644 --- a/ui/admin/tests/acceptance/workers/list-test.js +++ b/ui/admin/tests/acceptance/workers/list-test.js @@ -42,6 +42,7 @@ module('Acceptance | workers | list', function (hooks) { globalScope: null, workers: null, worker: null, + workerTags: null, }; hooks.beforeEach(function () { @@ -51,6 +52,7 @@ module('Acceptance | workers | list', function (hooks) { urls.globalScope = `/scopes/global/scopes`; urls.workers = `/scopes/global/workers`; urls.worker = `${urls.workers}/${instances.worker.id}`; + urls.workerTags = `${urls.worker}/tags`; authenticateSession({}); featuresService = this.owner.lookup('service:features'); }); @@ -189,7 +191,7 @@ module('Acceptance | workers | list', function (hooks) { await click(WORKERS_FLYOUT_VIEW_MORE_TAGS); - assert.strictEqual(currentURL(), urls.worker); + assert.strictEqual(currentURL(), urls.workerTags); await click(`[href="${urls.workers}"]`); diff --git a/ui/admin/tests/acceptance/workers/tags-test.js b/ui/admin/tests/acceptance/workers/tags-test.js new file mode 100644 index 000000000..fe1390aca --- /dev/null +++ b/ui/admin/tests/acceptance/workers/tags-test.js @@ -0,0 +1,47 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { visit, currentURL, click, 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 { authenticateSession } from 'ember-simple-auth/test-support'; + +module('Acceptance | workers | tags', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + }, + }; + + const urls = { + workers: null, + worker: null, + tags: null, + }; + + hooks.beforeEach(function () { + instances.scopes.global = this.server.create('scope', { id: 'global' }); + const scope = instances.scopes.global; + instances.worker = this.server.create('worker', { scopeId: scope.id }); + urls.workers = `/scopes/global/workers`; + urls.worker = `${urls.workers}/${instances.worker.id}`; + urls.tags = `${urls.worker}/tags`; + authenticateSession({}); + }); + + test('visiting worker tags', async function (assert) { + await visit(urls.worker); + await click(`[href="${urls.tags}"]`); + await a11yAudit(); + + assert.strictEqual(currentURL(), urls.tags); + assert.strictEqual(findAll('tbody tr').length, 11); + }); +}); diff --git a/ui/admin/tests/integration/components/workers/worker/actions/index-test.js b/ui/admin/tests/integration/components/workers/worker/actions/index-test.js new file mode 100644 index 000000000..cc4d07343 --- /dev/null +++ b/ui/admin/tests/integration/components/workers/worker/actions/index-test.js @@ -0,0 +1,30 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'admin/tests/helpers'; +import { setupIntl } from 'ember-intl/test-support'; +import { click, render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module( + 'Integration | Component | workers/worker/actions/index', + function (hooks) { + setupRenderingTest(hooks); + setupIntl(hooks); + + test('it renders', async function (assert) { + this.set('model', { id: 'w_123', authorized_actions: ['delete'] }); + this.set('delete', () => {}); + + await render( + hbs``, + ); + await click('button'); + + assert.dom(this.element).includesText('Remove Worker'); + }); + }, +); diff --git a/ui/admin/tests/integration/components/workers/worker/header/index-test.js b/ui/admin/tests/integration/components/workers/worker/header/index-test.js new file mode 100644 index 000000000..48bd3cda8 --- /dev/null +++ b/ui/admin/tests/integration/components/workers/worker/header/index-test.js @@ -0,0 +1,28 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'admin/tests/helpers'; +import { setupIntl } from 'ember-intl/test-support'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module( + 'Integration | Component | workers/worker/header/index', + function (hooks) { + setupRenderingTest(hooks); + setupIntl(hooks); + + test('it renders with the id of the model passed in', async function (assert) { + this.set('model', { id: 'w_123' }); + + await render(hbs` + + `); + + assert.dom(this.element).includesText('w_123'); + }); + }, +); diff --git a/ui/admin/tests/integration/components/workers/worker/nav/index-test.js b/ui/admin/tests/integration/components/workers/worker/nav/index-test.js new file mode 100644 index 000000000..5027a8df2 --- /dev/null +++ b/ui/admin/tests/integration/components/workers/worker/nav/index-test.js @@ -0,0 +1,23 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'admin/tests/helpers'; +import { setupIntl } from 'ember-intl/test-support'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | workers/worker/nav/index', function (hooks) { + setupRenderingTest(hooks); + setupIntl(hooks); + + test('it renders', async function (assert) { + await render(hbs` + + `); + + assert.dom(this.element).hasText('Details Tags'); + }); +}); diff --git a/ui/admin/tests/unit/controllers/scopes/scope/workers/worker/tags-test.js b/ui/admin/tests/unit/controllers/scopes/scope/workers/worker/tags-test.js new file mode 100644 index 000000000..16d60750d --- /dev/null +++ b/ui/admin/tests/unit/controllers/scopes/scope/workers/worker/tags-test.js @@ -0,0 +1,21 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupTest } from 'admin/tests/helpers'; + +module( + 'Unit | Controller | scopes/scope/workers/worker/tags', + function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let controller = this.owner.lookup( + 'controller:scopes/scope/workers/worker/tags', + ); + assert.ok(controller); + }); + }, +); diff --git a/ui/admin/tests/unit/routes/scopes/scope/workers/worker/tags-test.js b/ui/admin/tests/unit/routes/scopes/scope/workers/worker/tags-test.js new file mode 100644 index 000000000..cb8cdec88 --- /dev/null +++ b/ui/admin/tests/unit/routes/scopes/scope/workers/worker/tags-test.js @@ -0,0 +1,16 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupTest } from 'admin/tests/helpers'; + +module('Unit | Route | scopes/scope/workers/worker/tags', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/workers/worker/tags'); + assert.ok(route); + }); +});