Add danger toast
This commit is contained in:
parent
d2b110ab84
commit
0a3fa41208
11 changed files with 170 additions and 33 deletions
1
app/components/icons/check.js
Normal file
1
app/components/icons/check.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { Check as default } from 'ember-mdi';
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{{#in-element this.toaster.destinationElement insertBefore=null}}
|
||||
<div
|
||||
class='absolute max-w-sm border rounded bg-base-7 shadow-sm'
|
||||
class='absolute border rounded shadow-sm'
|
||||
role='alert'
|
||||
style={{this.style}}
|
||||
{{did-insert this.didInsert}}
|
||||
|
|
|
|||
20
app/components/toast/danger.js
Normal file
20
app/components/toast/danger.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import ToastThemeComponent from './theme';
|
||||
import { ExclamationThick } from 'ember-mdi';
|
||||
|
||||
export default class ToastDangerComponent extends ToastThemeComponent {
|
||||
get bg() {
|
||||
return 'bg-danger-light';
|
||||
}
|
||||
|
||||
get color() {
|
||||
return null;
|
||||
}
|
||||
|
||||
get borderColor() {
|
||||
return 'border-danger';
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return ExclamationThick;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<Toast>
|
||||
<div class='inline-flex flex-shrink-0 justify-center items-center self-start'>
|
||||
<Icons::Loading @spin={{true}} class='mr-4' />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{@text}}
|
||||
</div>
|
||||
|
||||
<button
|
||||
type='button'
|
||||
class='ml-auto self-start'
|
||||
{{! data-dismiss-target='#toast-default' }}
|
||||
aria-label='Close'
|
||||
{{on 'click' @onClose}}
|
||||
>
|
||||
<Icons::Close />
|
||||
</button>
|
||||
</Toast>
|
||||
|
|
@ -1,3 +1,24 @@
|
|||
import Component from '@glimmer/component';
|
||||
import ToastThemeComponent from './theme';
|
||||
import { Check } from 'ember-mdi';
|
||||
|
||||
export default class ToastSuccessComponent extends Component {}
|
||||
export default class ToastSuccessComponent extends ToastThemeComponent {
|
||||
get bg() {
|
||||
return 'bg-success-light';
|
||||
}
|
||||
|
||||
get color() {
|
||||
return null;
|
||||
}
|
||||
|
||||
get borderColor() {
|
||||
return 'border-success';
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return Check;
|
||||
}
|
||||
|
||||
get autoClose() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
35
app/components/toast/theme.hbs
Normal file
35
app/components/toast/theme.hbs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<Toast
|
||||
@autoClose={{this.autoClose}}
|
||||
@onClose={{@onClose}}
|
||||
class='{{this.bg}} {{this.color}} {{this.borderColor}} {{this.width}}'
|
||||
as |toast|
|
||||
>
|
||||
<div class='flex items-center'>
|
||||
{{#if this.icon}}
|
||||
<div
|
||||
class='inline-flex flex-shrink-0 justify-center items-center self-start'
|
||||
>
|
||||
<this.icon class='mr-4 {{this.color}}' />
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class='mr-4'>
|
||||
{{#if @header}}
|
||||
<div class='font-semibold mb-2'>{{@header}}</div>
|
||||
{{/if}}
|
||||
{{#if @text}}
|
||||
{{@text}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<button
|
||||
type='button'
|
||||
class='ml-auto self-start'
|
||||
{{! data-dismiss-target='#toast-default' }}
|
||||
aria-label='Close'
|
||||
{{on 'click' toast.invokeOnClose}}
|
||||
>
|
||||
<Icons::Close />
|
||||
</button>
|
||||
</div>
|
||||
</Toast>
|
||||
19
app/components/toast/theme.js
Normal file
19
app/components/toast/theme.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import Component from '@glimmer/component';
|
||||
|
||||
export default class ToastThemeComponent extends Component {
|
||||
get bg() {
|
||||
return 'bg-base-7';
|
||||
}
|
||||
|
||||
get color() {
|
||||
return null;
|
||||
}
|
||||
|
||||
get borderColor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
get width() {
|
||||
return 'w-80';
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,11 @@ export default class AdminKeysKeyEditController extends Controller {
|
|||
try {
|
||||
const key = await this.model.save(value);
|
||||
|
||||
this.toaster.successToast({
|
||||
header: 'Success',
|
||||
text: 'The key has been successfuly updated',
|
||||
});
|
||||
|
||||
if (this.router.isActive('admin.keys.key')) {
|
||||
await this.router.refresh('admin.keys.key', key.uid);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { tracked } from '@glimmer/tracking';
|
|||
import { hbs } from 'ember-template-imports';
|
||||
import { action } from '@ember/object';
|
||||
import SuccessToast from '../components/toast/success';
|
||||
import DangerToast from '../components/toast/danger';
|
||||
import TaskToast from '../components/toast/task';
|
||||
|
||||
export default class ToasterService extends Service {
|
||||
|
|
@ -18,12 +19,23 @@ export default class ToasterService extends Service {
|
|||
}
|
||||
|
||||
@action
|
||||
successToast({ text }) {
|
||||
successToast({ text, header }) {
|
||||
const onClose = () => {
|
||||
this.container = this.container.filter((item) => item !== wrapper);
|
||||
};
|
||||
|
||||
const wrapper = hbs`<SuccessToast @text={{text}} @onClose={{onClose}} />`;
|
||||
const wrapper = hbs`<SuccessToast @header={{header}} @text={{text}} @onClose={{onClose}} />`;
|
||||
|
||||
this.container = this.container.concat([wrapper]);
|
||||
}
|
||||
|
||||
@action
|
||||
dangerToast({ text, header }) {
|
||||
const onClose = () => {
|
||||
this.container = this.container.filter((item) => item !== wrapper);
|
||||
};
|
||||
|
||||
const wrapper = hbs`<DangerToast @header={{header}} @text={{text}} @onClose={{onClose}} />`;
|
||||
|
||||
this.container = this.container.concat([wrapper]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { instance } from '../instance-initializers/application';
|
|||
|
||||
export default function query(path, options = {}) {
|
||||
const session = instance.lookup('service:session');
|
||||
const toaster = instance.lookup('service:toaster');
|
||||
const { url, key } = session.data.authenticated;
|
||||
const defaultHeaders = { 'Content-Type': 'application/json' };
|
||||
const headers = new Headers(Object.assign(defaultHeaders, options.headers));
|
||||
|
|
@ -15,13 +16,29 @@ export default function query(path, options = {}) {
|
|||
Object.assign(options, { headers })
|
||||
);
|
||||
|
||||
return fetch(req).then((response) => {
|
||||
if (response.status === 204) {
|
||||
return;
|
||||
} else if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
throw new Error('Network response was not OK');
|
||||
}
|
||||
});
|
||||
return fetch(req)
|
||||
.then((response) => {
|
||||
if (response.status === 204) {
|
||||
return;
|
||||
} else if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
response.json().then((reason) => {
|
||||
toaster.dangerToast({
|
||||
header: reason.type,
|
||||
text: reason.message,
|
||||
});
|
||||
|
||||
throw new Error('Network response was not OK');
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((response) => {
|
||||
response.json().then((reason) => {
|
||||
toaster.dangerToast({
|
||||
header: reason.type,
|
||||
text: reason.message,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
26
tests/integration/components/toast/theme-test.js
Normal file
26
tests/integration/components/toast/theme-test.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'meiliadmin/tests/helpers';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Component | toast/theme', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function (assert) {
|
||||
// Set any properties with this.set('myProperty', 'value');
|
||||
// Handle any actions with this.set('myAction', function(val) { ... });
|
||||
|
||||
await render(hbs`<Toast::Theme />`);
|
||||
|
||||
assert.dom(this.element).hasText('');
|
||||
|
||||
// Template block usage:
|
||||
await render(hbs`
|
||||
<Toast::Theme>
|
||||
template block text
|
||||
</Toast::Theme>
|
||||
`);
|
||||
|
||||
assert.dom(this.element).hasText('template block text');
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue