mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 17:52:32 +00:00
UI: Use HDS::Toast for flash messages (#25459)
* Move global-flash to HDS-specified area * Add flash-toast component * use flash toast for flash messages * Use spacing vars * Remove unnecessary key * Cleanup + tests * Remove nondeterministic build warning * add changelog * I wish this was automatic
This commit is contained in:
3
changelog/25459.txt
Normal file
3
changelog/25459.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
```release-note:change
|
||||
ui: flash messages render on right side of page
|
||||
```
|
||||
11
ui/app/components/flash-toast.hbs
Normal file
11
ui/app/components/flash-toast.hbs
Normal file
@@ -0,0 +1,11 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
<Hds::Toast @color={{this.color}} @onDismiss={{@close}} class="has-bottom-margin-m" data-test-flash-toast as |T|>
|
||||
<T.Title data-test-flash-toast-title>{{this.title}}</T.Title>
|
||||
<T.Description data-test-flash-message-body>
|
||||
<p class="is-word-break">{{@flash.message}}</p>
|
||||
</T.Description>
|
||||
</Hds::Toast>
|
||||
37
ui/app/components/flash-toast.js
Normal file
37
ui/app/components/flash-toast.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { capitalize } from '@ember/string';
|
||||
import Component from '@glimmer/component';
|
||||
|
||||
/**
|
||||
* FlashToast components are used to translate flash messages into toast notifications.
|
||||
* Flash object passed should have a `type` and `message` property at minimum.
|
||||
*/
|
||||
export default class FlashToastComponent extends Component {
|
||||
get color() {
|
||||
switch (this.args.flash.type) {
|
||||
case 'info':
|
||||
return 'highlight';
|
||||
case 'danger':
|
||||
return 'critical';
|
||||
case 'warning':
|
||||
case 'success':
|
||||
return this.args.flash.type;
|
||||
default:
|
||||
return 'neutral';
|
||||
}
|
||||
}
|
||||
|
||||
get title() {
|
||||
if (this.args.title) return this.args.title;
|
||||
switch (this.args.flash.type) {
|
||||
case 'danger':
|
||||
return 'Error';
|
||||
default:
|
||||
return capitalize(this.args.flash.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@
|
||||
*/
|
||||
|
||||
.global-flash {
|
||||
bottom: 0;
|
||||
left: $spacing-12;
|
||||
bottom: $spacing-32;
|
||||
right: $spacing-24;
|
||||
margin: 10px;
|
||||
max-width: $drawer-width;
|
||||
max-width: 360px;
|
||||
position: fixed;
|
||||
width: 95%;
|
||||
z-index: 300;
|
||||
|
||||
@@ -75,24 +75,7 @@
|
||||
<div class="global-flash">
|
||||
{{#each this.flashMessages.queue as |flash|}}
|
||||
<FlashMessage data-test-flash-message={{true}} @flash={{flash}} as |customComponent flash close|>
|
||||
{{#if flash.componentName}}
|
||||
{{component flash.componentName content=flash.content}}
|
||||
{{else}}
|
||||
{{#let (hash info="highlight" success="success" danger="critical" warning="warning") as |color|}}
|
||||
<Hds::Alert @type="inline" @color={{get color flash.type}} class="has-bottom-margin-s" @onDismiss={{close}} as |A|>
|
||||
{{#let (hash info="Info" success="Success" danger="Error" warning="Warning") as |title|}}
|
||||
<A.Title class="alert-title">{{get title flash.type}}</A.Title>
|
||||
{{/let}}
|
||||
<A.Description data-test-flash-message-body>
|
||||
{{#if flash.preformatted}}
|
||||
<p class="is-word-break">{{flash.message}}</p>
|
||||
{{else}}
|
||||
{{flash.message}}
|
||||
{{/if}}
|
||||
</A.Description>
|
||||
</Hds::Alert>
|
||||
{{/let}}
|
||||
{{/if}}
|
||||
<FlashToast @flash={{flash}} @close={{close}} />
|
||||
</FlashMessage>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,6 @@ IF YOUR TOKEN HAS THE PROPER CAPABILITIES, THIS WILL CREATE AND DELETE ITEMS ON
|
||||
Your token will also be shown on the screen in the example curl command output.`;
|
||||
this.flashMessages.warning(warning, {
|
||||
sticky: true,
|
||||
preformatted: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
58
ui/tests/integration/components/flash-toast-test.js
Normal file
58
ui/tests/integration/components/flash-toast-test.js
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'vault/tests/helpers';
|
||||
import { click, find, render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import sinon from 'sinon';
|
||||
|
||||
module('Integration | Component | flash-toast', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.flash = {
|
||||
type: 'info',
|
||||
message: 'The bare minimum flash message',
|
||||
};
|
||||
this.closeSpy = sinon.spy();
|
||||
});
|
||||
|
||||
test('it renders', async function (assert) {
|
||||
await render(hbs`<FlashToast @flash={{this.flash}} @close={{this.closeSpy}} />`);
|
||||
|
||||
assert.dom('[data-test-flash-message-body]').hasText('The bare minimum flash message');
|
||||
assert.dom('[data-test-flash-toast]').hasClass('hds-alert--color-highlight');
|
||||
await click('button');
|
||||
assert.ok(this.closeSpy.calledOnce, 'close action was called');
|
||||
});
|
||||
|
||||
[
|
||||
{ type: 'info', title: 'Info', color: 'hds-alert--color-highlight' },
|
||||
{ type: 'success', title: 'Success', color: 'hds-alert--color-success' },
|
||||
{ type: 'warning', title: 'Warning', color: 'hds-alert--color-warning' },
|
||||
{ type: 'danger', title: 'Error', color: 'hds-alert--color-critical' },
|
||||
{ type: 'foobar', title: 'Foobar', color: 'hds-alert--color-neutral' },
|
||||
].forEach(({ type, title, color }) => {
|
||||
test(`it has correct title and color for type: ${type}`, async function (assert) {
|
||||
this.flash.type = type;
|
||||
await render(hbs`<FlashToast @flash={{this.flash}} @close={{this.closeSpy}} />`);
|
||||
|
||||
assert.dom('[data-test-flash-toast-title]').hasText(title, 'title is correct');
|
||||
assert.dom('[data-test-flash-toast]').hasClass(color, 'color is correct');
|
||||
});
|
||||
});
|
||||
|
||||
test('it renders messages with whitespaces correctly', async function (assert) {
|
||||
this.flash.message = `multi-
|
||||
|
||||
line msg`;
|
||||
|
||||
await render(hbs`<FlashToast @flash={{this.flash}} @close={{this.closeSpy}} />`);
|
||||
const dom = find('[data-test-flash-message-body]');
|
||||
const lineHeight = 20;
|
||||
assert.true(dom.clientHeight > lineHeight, 'renders message on multiple lines');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user