Icu 13892 create tags tab route and view (#2362)
* 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
This commit is contained in:
1 parent
40ebbf8b09
commit
fd5143286f
18 files changed
+321
-42
No files matched your search
@@ -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:
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
<Hds::Dropdown data-test-manage-worker-dropdown as |dd|>
|
||||
<dd.ToggleButton @text={{t 'actions.manage'}} @color='secondary' />
|
||||
{{#if (can 'delete worker' @model)}}
|
||||
<dd.Interactive
|
||||
@icon='trash'
|
||||
@text={{t 'resources.worker.actions.delete'}}
|
||||
@color='critical'
|
||||
{{on 'click' (fn @delete @model)}}
|
||||
/>
|
||||
{{/if}}
|
||||
</Hds::Dropdown>
|
||||
@@ -0,0 +1,11 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
<h2>
|
||||
{{t 'resources.worker.title'}}
|
||||
<DocLink @doc='worker' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.worker.description'}}</p>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -0,0 +1,13 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
<Rose::Nav::Tabs as |nav|>
|
||||
<nav.link @route='scopes.scope.workers.worker.index'>
|
||||
{{t 'titles.details'}}
|
||||
</nav.link>
|
||||
<nav.link @route='scopes.scope.workers.worker.tags'>
|
||||
{{t 'resources.worker.tags.title_plural'}}
|
||||
</nav.link>
|
||||
</Rose::Nav::Tabs>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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 {}
|
||||
@@ -166,8 +166,8 @@
|
||||
<Hds::Table
|
||||
@model={{this.selectedWorkerTags}}
|
||||
@columns={{array
|
||||
(hash label=(t 'resources.worker.flyout.table.tag'))
|
||||
(hash label=(t 'resources.worker.flyout.table.type'))
|
||||
(hash label=(t 'resources.worker.table.tag'))
|
||||
(hash label=(t 'resources.worker.table.type'))
|
||||
}}
|
||||
@valign='middle'
|
||||
>
|
||||
@@ -186,12 +186,11 @@
|
||||
</Hds::Table>
|
||||
{{#if (gt this.selectedWorker.allTags.length 10)}}
|
||||
<div class='view-more-tags'>
|
||||
{{! TODO: Update route to worker.tags once route is added }}
|
||||
<Hds::Link::Standalone
|
||||
@icon='arrow-right'
|
||||
@iconPosition='trailing'
|
||||
@text={{t 'resources.worker.flyout.action.view_more'}}
|
||||
@route='scopes.scope.workers.worker'
|
||||
@route='scopes.scope.workers.worker.tags'
|
||||
@model={{this.selectedWorker}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -10,38 +10,18 @@
|
||||
</page.breadcrumbs>
|
||||
|
||||
<page.header>
|
||||
<h2>
|
||||
{{t 'resources.worker.title'}}
|
||||
<DocLink @doc='worker' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.worker.description'}}</p>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
<Workers::Worker::Header @model={{@model}} />
|
||||
</page.header>
|
||||
|
||||
<page.navigation>
|
||||
<Rose::Nav::Tabs as |nav|>
|
||||
<nav.link @route='scopes.scope.workers.worker.index'>
|
||||
{{t 'titles.details'}}
|
||||
</nav.link>
|
||||
</Rose::Nav::Tabs>
|
||||
<Workers::Worker::Nav />
|
||||
</page.navigation>
|
||||
|
||||
<page.actions>
|
||||
<Rose::Dropdown
|
||||
@text={{t 'actions.manage'}}
|
||||
@dropdownRight={{true}}
|
||||
as |dropdown|
|
||||
>
|
||||
{{#if (can 'delete worker' @model)}}
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
@disabled={{@model.canSave}}
|
||||
{{on 'click' (fn this.workers.delete @model)}}
|
||||
>
|
||||
{{t 'resources.worker.actions.delete'}}
|
||||
</dropdown.button>
|
||||
{{/if}}
|
||||
</Rose::Dropdown>
|
||||
<Workers::Worker::Actions
|
||||
@model={{@model}}
|
||||
@delete={{this.workers.delete}}
|
||||
/>
|
||||
</page.actions>
|
||||
|
||||
<page.body>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
}}
|
||||
|
||||
{{page-title (t 'resources.worker.tags.title_plural')}}
|
||||
<Breadcrumbs::Item
|
||||
@text={{t 'resources.worker.tags.title_plural'}}
|
||||
@route='scopes.scope.workers.worker.tags'
|
||||
/>
|
||||
|
||||
<Rose::Layout::Page as |page|>
|
||||
|
||||
<page.breadcrumbs>
|
||||
<Breadcrumbs::Container />
|
||||
</page.breadcrumbs>
|
||||
|
||||
<page.header>
|
||||
<Workers::Worker::Header @model={{@model}} />
|
||||
</page.header>
|
||||
|
||||
<page.navigation>
|
||||
<Workers::Worker::Nav />
|
||||
</page.navigation>
|
||||
|
||||
<page.actions>
|
||||
<Workers::Worker::Actions
|
||||
@model={{@model}}
|
||||
@delete={{this.workers.delete}}
|
||||
/>
|
||||
</page.actions>
|
||||
|
||||
<page.body>
|
||||
{{#if @model.allTags}}
|
||||
<Hds::Table
|
||||
@model={{@model.allTags}}
|
||||
@columns={{array
|
||||
(hash label=(t 'resources.worker.table.key'))
|
||||
(hash label=(t 'resources.worker.table.value'))
|
||||
(hash label=(t 'resources.worker.table.type'))
|
||||
}}
|
||||
@valign='middle'
|
||||
>
|
||||
<:body as |B|>
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
<Hds::Text::Code @tag='pre'>{{B.data.key}}</Hds::Text::Code>
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
<Hds::Text::Code @tag='pre'>{{B.data.value}}</Hds::Text::Code>
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
<Hds::Badge @text={{B.data.type}} />
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
</:body>
|
||||
</Hds::Table>
|
||||
{{/if}}
|
||||
|
||||
</page.body>
|
||||
|
||||
</Rose::Layout::Page>
|
||||
@@ -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.');
|
||||
});
|
||||
});
|
||||
@@ -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}"]`);
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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`<Workers::Worker::Actions @model={{this.model}} @delete={{this.delete}} />`,
|
||||
);
|
||||
await click('button');
|
||||
|
||||
assert.dom(this.element).includesText('Remove Worker');
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -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`
|
||||
<Workers::Worker::Header @model={{this.model}} />
|
||||
`);
|
||||
|
||||
assert.dom(this.element).includesText('w_123');
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -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`
|
||||
<Workers::Worker::Nav />
|
||||
`);
|
||||
|
||||
assert.dom(this.element).hasText('Details Tags');
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user