From 61cca85b7f61c2c3f023ffb5d391107e85e88c25 Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Fri, 15 Jan 2021 10:45:21 -0600 Subject: [PATCH 01/11] Add button to fail running deployments As suggested in #9826. The placement is currently ridiculous. --- ui/app/adapters/deployment.js | 10 +++++++ ui/app/components/job-deployment.js | 24 +++++++++++++++++ ui/app/models/deployment.js | 5 ++++ .../templates/components/job-deployment.hbs | 8 ++++++ ui/mirage/config.js | 5 ++++ ui/tests/acceptance/job-deployments-test.js | 26 +++++++++++++++++++ ui/tests/pages/jobs/job/deployments.js | 4 +++ ui/tests/unit/adapters/deployment-test.js | 14 ++++++++++ 8 files changed, 96 insertions(+) diff --git a/ui/app/adapters/deployment.js b/ui/app/adapters/deployment.js index 5530166d6beb..d24628c369ae 100644 --- a/ui/app/adapters/deployment.js +++ b/ui/app/adapters/deployment.js @@ -1,6 +1,16 @@ import Watchable from './watchable'; export default class DeploymentAdapter extends Watchable { + fail(deployment) { + const id = deployment.get('id'); + const url = urlForAction(this.urlForFindRecord(id, 'deployment'), '/fail'); + return this.ajax(url, 'POST', { + data: { + DeploymentId: id, + }, + }); + } + promote(deployment) { const id = deployment.get('id'); const url = urlForAction(this.urlForFindRecord(id, 'deployment'), '/promote'); diff --git a/ui/app/components/job-deployment.js b/ui/app/components/job-deployment.js index f9b31ecf7361..813d00ced850 100644 --- a/ui/app/components/job-deployment.js +++ b/ui/app/components/job-deployment.js @@ -1,10 +1,34 @@ import Component from '@ember/component'; import { classNames } from '@ember-decorators/component'; import classic from 'ember-classic-decorator'; +import { task } from 'ember-concurrency'; +import { ForbiddenError } from '@ember-data/adapter/error'; +import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error'; @classic @classNames('job-deployment', 'boxed-section') export default class JobDeployment extends Component { deployment = null; isOpen = false; + + handleError() {} + + @task(function*() { + try { + yield this.deployment.fail(); + } catch (err) { + console.log('err?', err); + let message = messageFromAdapterError(err); + + if (err instanceof ForbiddenError) { + message = 'Your ACL token does not grant permission to fail deployments.'; + } + + this.handleError({ + title: 'Could Not Fail Deployment', + description: message, + }); + } + }) + fail; } diff --git a/ui/app/models/deployment.js b/ui/app/models/deployment.js index 66d6cb297e3f..5cbb7a0852c5 100644 --- a/ui/app/models/deployment.js +++ b/ui/app/models/deployment.js @@ -69,4 +69,9 @@ export default class Deployment extends Model { assert('A deployment needs to requirePromotion to be promoted', this.requiresPromotion); return this.store.adapterFor('deployment').promote(this); } + + fail() { + assert('A deployment must be running to be failed', this.isRunning); + return this.store.adapterFor('deployment').fail(this); + } } diff --git a/ui/app/templates/components/job-deployment.hbs b/ui/app/templates/components/job-deployment.hbs index 962549108223..2f01e2679ee6 100644 --- a/ui/app/templates/components/job-deployment.hbs +++ b/ui/app/templates/components/job-deployment.hbs @@ -4,6 +4,14 @@ {{#if this.deployment.requiresPromotion}} Requires Promotion {{/if}} + {{#if this.deployment.isRunning}} + + {{/if}} Version diff --git a/ui/mirage/config.js b/ui/mirage/config.js index eec2126b4a8d..4beabd56c00b 100644 --- a/ui/mirage/config.js +++ b/ui/mirage/config.js @@ -191,6 +191,11 @@ export default function() { }); this.get('/deployment/:id'); + + this.post('/deployment/fail/:id', function() { + return new Response(200, {}, ''); + }); + this.post('/deployment/promote/:id', function() { return new Response(204, {}, ''); }); diff --git a/ui/tests/acceptance/job-deployments-test.js b/ui/tests/acceptance/job-deployments-test.js index c4fb897ede92..000f64f9792e 100644 --- a/ui/tests/acceptance/job-deployments-test.js +++ b/ui/tests/acceptance/job-deployments-test.js @@ -71,6 +71,12 @@ module('Acceptance | job deployments', function(hooks) { deploymentRow.submitTime.includes(moment(version.submitTime / 1000000).fromNow()), 'Submit time ago' ); + + if (deployment.status === 'running') { + assert.ok(deploymentRow.failButton.isPresent, 'a runnning deployment can be failed'); + } else { + assert.ok(deploymentRow.failButton.isHidden, 'a deploymentn that is not running cannot be failed'); + } }); test('when the deployment is running and needs promotion, the deployment item says so', async function(assert) { @@ -97,6 +103,26 @@ module('Acceptance | job deployments', function(hooks) { assert.ok(deploymentRow.promotionIsRequired, 'Requires Promotion badge found'); }); + test('when the deployment is running, it can be caused to fail', async function(assert) { + // Ensure the deployment needs deployment + const deployment = sortedDeployments.models[0]; + + deployment.update('status', 'running'); + deployment.save(); + + await Deployments.visit({ id: job.id }); + + const deploymentRow = Deployments.deployments[0]; + + await deploymentRow.failButton.click(); + + assert.equal( + server.pretender.handledRequests.findBy('method', 'POST').url, + `/v1/deployment/fail/${deployment.id}`, + 'Stop request is made for the allocation' + ); + }); + test('each deployment item can be opened to show details', async function(assert) { await Deployments.visit({ id: job.id }); diff --git a/ui/tests/pages/jobs/job/deployments.js b/ui/tests/pages/jobs/job/deployments.js index 3a75faf320a1..086f4b2e0226 100644 --- a/ui/tests/pages/jobs/job/deployments.js +++ b/ui/tests/pages/jobs/job/deployments.js @@ -24,6 +24,10 @@ export default create({ toggle: clickable('[data-test-deployment-toggle-details]'), + failButton: { + scope: '[data-test-fail-deployment]', + }, + hasDetails: isPresent('[data-test-deployment-details]'), metrics: collection('[data-test-deployment-metric]', { diff --git a/ui/tests/unit/adapters/deployment-test.js b/ui/tests/unit/adapters/deployment-test.js index 70ecbe986fed..7a16751ba3c5 100644 --- a/ui/tests/unit/adapters/deployment-test.js +++ b/ui/tests/unit/adapters/deployment-test.js @@ -42,11 +42,13 @@ module('Unit | Adapter | Deployment', function(hooks) { { variation: '', region: null, + fail: id => `POST /v1/deployment/fail/${id}`, promote: id => `POST /v1/deployment/promote/${id}`, }, { variation: 'with non-default region', region: 'region-2', + fail: id => `POST /v1/deployment/fail/${id}?region=region-2`, promote: id => `POST /v1/deployment/promote/${id}?region=region-2`, }, ]; @@ -64,5 +66,17 @@ module('Unit | Adapter | Deployment', function(hooks) { All: true, }); }); + + test(`fail makes the correct API call ${testCase.variation}`, async function(assert) { + const deployment = await this.initialize({ region: testCase.region }); + await this.subject().fail(deployment); + + const request = this.server.pretender.handledRequests[0]; + + assert.equal(`${request.method} ${request.url}`, testCase.fail(deployment.id)); + assert.deepEqual(JSON.parse(request.requestBody), { + DeploymentId: deployment.id, + }); + }) }); }); From 58dc406270606fa99beca11c161e17097cfb1bc5 Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Fri, 15 Jan 2021 10:51:15 -0600 Subject: [PATCH 02/11] Replace logging statement with FIXME note --- ui/app/components/job-deployment.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/job-deployment.js b/ui/app/components/job-deployment.js index 813d00ced850..40a00d6480b2 100644 --- a/ui/app/components/job-deployment.js +++ b/ui/app/components/job-deployment.js @@ -17,7 +17,7 @@ export default class JobDeployment extends Component { try { yield this.deployment.fail(); } catch (err) { - console.log('err?', err); + // FIXME nothing actually handles errors at the moment let message = messageFromAdapterError(err); if (err instanceof ForbiddenError) { From 70cb7d3a2c25678f2f977c6db69f778075496cd2 Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Fri, 15 Jan 2021 10:51:35 -0600 Subject: [PATCH 03/11] Add missing semicolon --- ui/tests/unit/adapters/deployment-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/tests/unit/adapters/deployment-test.js b/ui/tests/unit/adapters/deployment-test.js index 7a16751ba3c5..a26a48f91dc8 100644 --- a/ui/tests/unit/adapters/deployment-test.js +++ b/ui/tests/unit/adapters/deployment-test.js @@ -77,6 +77,6 @@ module('Unit | Adapter | Deployment', function(hooks) { assert.deepEqual(JSON.parse(request.requestBody), { DeploymentId: deployment.id, }); - }) + }); }); }); From bc853a2721feacb23a1828270978d5a37c90ba05 Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Mon, 18 Jan 2021 10:29:37 -0600 Subject: [PATCH 04/11] Move fail button to latest deployment component @DingoEatingFuzz clarified to me that the deployments page is meant to be a historical overview vs a place to change things. --- ui/app/components/job-deployment.js | 24 -------- .../job-page/parts/latest-deployment.js | 18 ++++++ .../templates/components/job-deployment.hbs | 8 --- .../job-page/parts/latest-deployment.hbs | 8 +++ ui/tests/acceptance/job-deployments-test.js | 26 --------- .../components/job-page/service-test.js | 56 +++++++++++++++++++ ui/tests/pages/jobs/job/deployments.js | 4 -- 7 files changed, 82 insertions(+), 62 deletions(-) diff --git a/ui/app/components/job-deployment.js b/ui/app/components/job-deployment.js index 40a00d6480b2..f9b31ecf7361 100644 --- a/ui/app/components/job-deployment.js +++ b/ui/app/components/job-deployment.js @@ -1,34 +1,10 @@ import Component from '@ember/component'; import { classNames } from '@ember-decorators/component'; import classic from 'ember-classic-decorator'; -import { task } from 'ember-concurrency'; -import { ForbiddenError } from '@ember-data/adapter/error'; -import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error'; @classic @classNames('job-deployment', 'boxed-section') export default class JobDeployment extends Component { deployment = null; isOpen = false; - - handleError() {} - - @task(function*() { - try { - yield this.deployment.fail(); - } catch (err) { - // FIXME nothing actually handles errors at the moment - let message = messageFromAdapterError(err); - - if (err instanceof ForbiddenError) { - message = 'Your ACL token does not grant permission to fail deployments.'; - } - - this.handleError({ - title: 'Could Not Fail Deployment', - description: message, - }); - } - }) - fail; } diff --git a/ui/app/components/job-page/parts/latest-deployment.js b/ui/app/components/job-page/parts/latest-deployment.js index dc78a235ed9d..5fd64eea42fc 100644 --- a/ui/app/components/job-page/parts/latest-deployment.js +++ b/ui/app/components/job-page/parts/latest-deployment.js @@ -31,4 +31,22 @@ export default class LatestDeployment extends Component { } }) promote; + + @task(function*() { + try { + yield this.get('job.latestDeployment.content').fail(); + } catch (err) { + let message = messageFromAdapterError(err); + + if (err instanceof ForbiddenError) { + message = 'Your ACL token does not grant permission to fail deployments.'; + } + + this.handleError({ + title: 'Could Not Fail Deployment', + description: message, + }); + } + }) + fail; } diff --git a/ui/app/templates/components/job-deployment.hbs b/ui/app/templates/components/job-deployment.hbs index 2f01e2679ee6..962549108223 100644 --- a/ui/app/templates/components/job-deployment.hbs +++ b/ui/app/templates/components/job-deployment.hbs @@ -4,14 +4,6 @@ {{#if this.deployment.requiresPromotion}} Requires Promotion {{/if}} - {{#if this.deployment.isRunning}} - - {{/if}} Version diff --git a/ui/app/templates/components/job-page/parts/latest-deployment.hbs b/ui/app/templates/components/job-page/parts/latest-deployment.hbs index 78e4e0a8c1ce..ae17019b6df6 100644 --- a/ui/app/templates/components/job-page/parts/latest-deployment.hbs +++ b/ui/app/templates/components/job-page/parts/latest-deployment.hbs @@ -22,6 +22,14 @@ disabled={{this.promote.isRunning}} onclick={{perform this.promote}}>Promote Canary {{/if}} + {{#if this.job.latestDeployment.isRunning}} + + {{/if}}
diff --git a/ui/tests/acceptance/job-deployments-test.js b/ui/tests/acceptance/job-deployments-test.js index 000f64f9792e..c4fb897ede92 100644 --- a/ui/tests/acceptance/job-deployments-test.js +++ b/ui/tests/acceptance/job-deployments-test.js @@ -71,12 +71,6 @@ module('Acceptance | job deployments', function(hooks) { deploymentRow.submitTime.includes(moment(version.submitTime / 1000000).fromNow()), 'Submit time ago' ); - - if (deployment.status === 'running') { - assert.ok(deploymentRow.failButton.isPresent, 'a runnning deployment can be failed'); - } else { - assert.ok(deploymentRow.failButton.isHidden, 'a deploymentn that is not running cannot be failed'); - } }); test('when the deployment is running and needs promotion, the deployment item says so', async function(assert) { @@ -103,26 +97,6 @@ module('Acceptance | job deployments', function(hooks) { assert.ok(deploymentRow.promotionIsRequired, 'Requires Promotion badge found'); }); - test('when the deployment is running, it can be caused to fail', async function(assert) { - // Ensure the deployment needs deployment - const deployment = sortedDeployments.models[0]; - - deployment.update('status', 'running'); - deployment.save(); - - await Deployments.visit({ id: job.id }); - - const deploymentRow = Deployments.deployments[0]; - - await deploymentRow.failButton.click(); - - assert.equal( - server.pretender.handledRequests.findBy('method', 'POST').url, - `/v1/deployment/fail/${deployment.id}`, - 'Stop request is made for the allocation' - ); - }); - test('each deployment item can be opened to show details', async function(assert) { await Deployments.visit({ id: job.id }); diff --git a/ui/tests/integration/components/job-page/service-test.js b/ui/tests/integration/components/job-page/service-test.js index 6efd33e7910a..e4c3ac8be50b 100644 --- a/ui/tests/integration/components/job-page/service-test.js +++ b/ui/tests/integration/components/job-page/service-test.js @@ -226,4 +226,60 @@ module('Integration | Component | job-page/service', function(hooks) { assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable'); }); + + test('Active deployment can be failed', async function(assert) { + this.server.create('node'); + const mirageJob = makeMirageJob(this.server, { activeDeployment: true }); + + await this.store.findAll('job'); + + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const deployment = await job.get('latestDeployment'); + + this.setProperties(commonProperties(job)); + await render(commonTemplate); + + await click('[data-test-fail]'); + + const requests = this.server.pretender.handledRequests; + + assert.ok( + requests + .filterBy('method', 'POST') + .findBy('url', `/v1/deployment/fail/${deployment.get('id')}`), + 'A fail POST request was made' + ); + }); + + test('When failing the active deployment fails, an error is shown', async function(assert) { + this.server.pretender.post('/v1/deployment/fail/:id', () => [403, {}, '']); + + this.server.create('node'); + const mirageJob = makeMirageJob(this.server, { activeDeployment: true }); + + await this.store.findAll('job'); + + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + + this.setProperties(commonProperties(job)); + await render(commonTemplate); + + await click('[data-test-fail]'); + + assert.equal( + find('[data-test-job-error-title]').textContent, + 'Could Not Fail Deployment', + 'Appropriate error is shown' + ); + assert.ok( + find('[data-test-job-error-body]').textContent.includes('ACL'), + 'The error message mentions ACLs' + ); + + await componentA11yAudit(this.element, assert); + + await click('[data-test-job-error-close]'); + + assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable'); + }); }); diff --git a/ui/tests/pages/jobs/job/deployments.js b/ui/tests/pages/jobs/job/deployments.js index 086f4b2e0226..3a75faf320a1 100644 --- a/ui/tests/pages/jobs/job/deployments.js +++ b/ui/tests/pages/jobs/job/deployments.js @@ -24,10 +24,6 @@ export default create({ toggle: clickable('[data-test-deployment-toggle-details]'), - failButton: { - scope: '[data-test-fail-deployment]', - }, - hasDetails: isPresent('[data-test-deployment-details]'), metrics: collection('[data-test-deployment-metric]', { From 0ace71fe6ad088de3dac3bf68b9363e0ef5e43f0 Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Mon, 18 Jan 2021 10:44:09 -0600 Subject: [PATCH 05/11] Change failure to require confirmation As sensibly suggested by @picatz --- .../job-page/parts/latest-deployment.hbs | 14 +++++++++----- .../components/job-page/service-test.js | 6 ++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ui/app/templates/components/job-page/parts/latest-deployment.hbs b/ui/app/templates/components/job-page/parts/latest-deployment.hbs index ae17019b6df6..760e99730bf4 100644 --- a/ui/app/templates/components/job-page/parts/latest-deployment.hbs +++ b/ui/app/templates/components/job-page/parts/latest-deployment.hbs @@ -23,12 +23,16 @@ onclick={{perform this.promote}}>Promote Canary {{/if}} {{#if this.job.latestDeployment.isRunning}} - + @class="is-danger" + @idleText="Fail Deployment" + @cancelText="Cancel" + @confirmText="Yes, Fail" + @confirmationMessage="Are you sure?" + @awaitingConfirmation={{this.fail.isRunning}} + @disabled={{this.fail.isRunning}} + @onConfirm={{perform this.fail}} /> {{/if}}
diff --git a/ui/tests/integration/components/job-page/service-test.js b/ui/tests/integration/components/job-page/service-test.js index e4c3ac8be50b..075e001f1495 100644 --- a/ui/tests/integration/components/job-page/service-test.js +++ b/ui/tests/integration/components/job-page/service-test.js @@ -239,7 +239,8 @@ module('Integration | Component | job-page/service', function(hooks) { this.setProperties(commonProperties(job)); await render(commonTemplate); - await click('[data-test-fail]'); + await click('[data-test-active-deployment] [data-test-idle-button]'); + await click('[data-test-active-deployment] [data-test-confirm-button]'); const requests = this.server.pretender.handledRequests; @@ -264,7 +265,8 @@ module('Integration | Component | job-page/service', function(hooks) { this.setProperties(commonProperties(job)); await render(commonTemplate); - await click('[data-test-fail]'); + await click('[data-test-active-deployment] [data-test-idle-button]'); + await click('[data-test-active-deployment] [data-test-confirm-button]'); assert.equal( find('[data-test-job-error-title]').textContent, From d1d78b485d6b12fa2feb1cc2d95ce92045434920 Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Mon, 18 Jan 2021 11:00:52 -0600 Subject: [PATCH 06/11] Move possible buttons to right-aligned container --- .../job-page/parts/latest-deployment.hbs | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/ui/app/templates/components/job-page/parts/latest-deployment.hbs b/ui/app/templates/components/job-page/parts/latest-deployment.hbs index 760e99730bf4..4f664b38d6db 100644 --- a/ui/app/templates/components/job-page/parts/latest-deployment.hbs +++ b/ui/app/templates/components/job-page/parts/latest-deployment.hbs @@ -14,26 +14,28 @@ {{this.job.latestDeployment.status}} - {{#if this.job.latestDeployment.requiresPromotion}} - - {{/if}} - {{#if this.job.latestDeployment.isRunning}} - - {{/if}} +
+ {{#if this.job.latestDeployment.requiresPromotion}} + + {{/if}} + {{#if this.job.latestDeployment.isRunning}} + + {{/if}} +
From 2be2338fb6cd43ddb718692ef3a4f8311bde526a Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Mon, 18 Jan 2021 13:36:49 -0600 Subject: [PATCH 07/11] Add class overrides for two-step button Since isInfoAction was only being used in the one place and I needed a different set of overrides for this context, it seemed to me sensible to decompose the overrides so they can be individually set in the invocation vs being bundled together under a not-totally-clear name. --- ui/app/components/two-step-button.js | 1 - ui/app/templates/clients/client/index.hbs | 6 +++++- .../job-page/parts/latest-deployment.hbs | 5 ++++- .../templates/components/two-step-button.hbs | 8 +++---- .../components/two-step-button.stories.js | 21 +++++++++++++++++++ 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/ui/app/components/two-step-button.js b/ui/app/components/two-step-button.js index a3bb4f5f0673..dcbe2ccb5e42 100644 --- a/ui/app/components/two-step-button.js +++ b/ui/app/components/two-step-button.js @@ -17,7 +17,6 @@ export default class TwoStepButton extends Component { awaitingConfirmation = false; disabled = false; alignRight = false; - isInfoAction = false; onConfirm() {} onCancel() {} diff --git a/ui/app/templates/clients/client/index.hbs b/ui/app/templates/clients/client/index.hbs index c1b327656eff..7c5587403c5f 100644 --- a/ui/app/templates/clients/client/index.hbs +++ b/ui/app/templates/clients/client/index.hbs @@ -212,7 +212,11 @@ {{this.idleText}} @@ -10,13 +10,13 @@ {{else if this.isPendingConfirmation}} + class="confirmation-text {{this.classes.confirmationMessage}} {{if this.alignRight "is-right-aligned"}}"> {{this.confirmationMessage}} - {{/if}} {{#if this.job.latestDeployment.isRunning}} {{/if}} + {{#if this.job.latestDeployment.requiresPromotion}} + + {{/if}}
From 61597630b0d1c528962013a3151ca023f3033035 Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Mon, 18 Jan 2021 14:43:42 -0600 Subject: [PATCH 10/11] Change Mirage response to also 204 --- ui/mirage/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/mirage/config.js b/ui/mirage/config.js index 4beabd56c00b..da055dd79c29 100644 --- a/ui/mirage/config.js +++ b/ui/mirage/config.js @@ -193,7 +193,7 @@ export default function() { this.get('/deployment/:id'); this.post('/deployment/fail/:id', function() { - return new Response(200, {}, ''); + return new Response(204, {}, ''); }); this.post('/deployment/promote/:id', function() { From 13ab14204392d77c876d437ad5268241b4392627 Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Wed, 10 Feb 2021 07:47:04 -0600 Subject: [PATCH 11/11] Change CSS for two-step inline text This is a less magic number-y approach than before, but since the buttons were previously spaced with an actual space character rather than CSS, some margins are needed to replicate that in the flexbox layout. --- ui/app/components/two-step-button.js | 3 +- ui/app/styles/components/two-step-button.scss | 31 +++++++++---------- .../job-page/parts/latest-deployment.hbs | 1 - 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/ui/app/components/two-step-button.js b/ui/app/components/two-step-button.js index 3cb115d2cec1..4bf934eadb45 100644 --- a/ui/app/components/two-step-button.js +++ b/ui/app/components/two-step-button.js @@ -4,11 +4,12 @@ import { next } from '@ember/runloop'; import { equal } from '@ember/object/computed'; import { task, waitForEvent } from 'ember-concurrency'; import RSVP from 'rsvp'; -import { classNames } from '@ember-decorators/component'; +import { classNames, classNameBindings } from '@ember-decorators/component'; import classic from 'ember-classic-decorator'; @classic @classNames('two-step-button') +@classNameBindings('inlineText:has-inline-text') export default class TwoStepButton extends Component { idleText = ''; cancelText = ''; diff --git a/ui/app/styles/components/two-step-button.scss b/ui/app/styles/components/two-step-button.scss index 03ad779b99f6..c4dfcbb2665f 100644 --- a/ui/app/styles/components/two-step-button.scss +++ b/ui/app/styles/components/two-step-button.scss @@ -5,6 +5,20 @@ font-size: $body-size; line-height: 1; + &.has-inline-text { + display: inline-flex; + align-items: center; + + button { + margin-left: 0.5ch; + } + + .confirmation-text { + position: static; + margin-right: 0.5ch; + } + } + .confirmation-text { position: absolute; left: 0; @@ -20,23 +34,6 @@ right: 0; } - &.has-text-inline { - top: unset; - bottom: 0; - padding-bottom: 6.462px; - - left: 100%; - right: unset; - padding-left: 0.5rem; - - &.is-right-aligned { - padding-left: 0; - padding-right: 0.5rem; - left: unset; - right: 100%; - } - } - &.inherit-color { color: currentColor; } diff --git a/ui/app/templates/components/job-page/parts/latest-deployment.hbs b/ui/app/templates/components/job-page/parts/latest-deployment.hbs index 192646ecc383..f11111a34eeb 100644 --- a/ui/app/templates/components/job-page/parts/latest-deployment.hbs +++ b/ui/app/templates/components/job-page/parts/latest-deployment.hbs @@ -26,7 +26,6 @@ @cancelText="Cancel" @confirmText="Yes, Fail" @confirmationMessage="Are you sure?" - @alignRight={{true}} @inlineText={{true}} @awaitingConfirmation={{this.fail.isRunning}} @disabled={{this.fail.isRunning}}