Skip to content
This repository has been archived by the owner on Aug 2, 2024. It is now read-only.

Commit

Permalink
fix alert dismissible class (#520)
Browse files Browse the repository at this point in the history
update alert component test snapshot

add notifications component and fdNotifications installation

update documentation

remove unnecessary checks

unsubscribe to events on beforeDestroy

updated documentation

fixed deleting by group

updated documentation and example

fix: group name with value '' was clearing all groups in hideAll

separated styles from sfc file

call onDismiss callback once notification is removed

update documentation: styles + onDismiss
  • Loading branch information
dandashino authored Aug 30, 2019
1 parent 14d0999 commit e73a4f4
Show file tree
Hide file tree
Showing 13 changed files with 813 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/components/Alert/Alert.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default {
computed: {
classes() {
const type = this.type === "default" ? [] : [`fd-alert--${this.type}`];
const dismissible = this.dismissible ? [] : ["fd-alert--dismissible"];
const dismissible = this.dismissible ? ["fd-alert--dismissible"] : [];
return ["fd-alert", ...type, ...dismissible];
}
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/Alert/__tests__/Alert.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("Alert", () => {
expect(warningAlert.element).toMatchSnapshot();
expect(errorAlert.element).toMatchSnapshot();
expect(warningAlert.classes("fd-alert--warning")).toBe(true);
expect(errorAlert.classes("fd-alert--dismissible")).toBe(true);
expect(errorAlert.classes("fd-alert--dismissible")).toBe(false);
});
it("renders default slot when passed", () => {
const dummySlot = "Slot text";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`Alert renders correctly 1`] = `
<div
class="fd-alert fd-alert--warning"
class="fd-alert fd-alert--warning fd-alert--dismissible"
id="warningAlert"
name="fade"
role="alert"
Expand All @@ -18,7 +18,7 @@ exports[`Alert renders correctly 1`] = `

exports[`Alert renders correctly 2`] = `
<div
class="fd-alert fd-alert--error fd-alert--dismissible"
class="fd-alert fd-alert--error"
id="errorAlert"
name="fade"
role="alert"
Expand Down
4 changes: 4 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ import TimePicker from "./TimePicker";
import Token from "./Token";
import Tree from "./tree";
import VirtualizedList from "./VirtualizedList";
import Notifications from "./notifications";
import { FdNotificationsManager } from "./notifications";

const plugin = {
install(vue, options) {
Expand Down Expand Up @@ -100,6 +102,7 @@ const plugin = {
MenuPopover,
Modal,
ModalOverlay,
Notifications,
ObjectTree,
Pagination,
Panel,
Expand All @@ -126,6 +129,7 @@ const plugin = {
VirtualizedList
];
plugins.forEach(plugin => vue.use(plugin, options));
vue.use(FdNotificationsManager);
}
};
export default plugin;
9 changes: 9 additions & 0 deletions src/components/notifications/EventsBus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Vue from "vue";

export const eventsBus = new Vue();

export const events = {
show: "show",
hide: "hide",
hideAll: "hideAll"
};
193 changes: 193 additions & 0 deletions src/components/notifications/Notifications.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
<template>
<div :class="computedContainerClasses" :style="computedContainerStyles">
<fd-alert
:key="item.id"
:type="item.type"
:dismissible="false"
:class="item.animation.class"
v-for="item in notifications"
@click.native="onManualDismiss(item)"
>
<slot>
<div v-if="item.title" class="fd-notification__title" v-html="item.title"></div>
<div class="fd-notification__content" v-html="item.content"></div>
</slot>
</fd-alert>
</div>
</template>

<script>
import FdAlert from "../Alert/Alert.vue";
import { eventsBus, events } from "./EventsBus";
/** @typedef { import('./notifications.types').NewNotificationOpts } NewNotificationOpts */
const config = {
defaultTimeout: 2000,
animationDuration: 400,
fadeInAnimationClass: "fadeIn",
fadeOutAnimationClass: "fadeOut"
};
export default {
name: "FdNotifications",
components: { FdAlert },
props: {
group: {
// the name of this notifications group, this will allow the
// user to have multiple notifications groups for easier control
type: String,
default: ""
},
position: {
// array of 2 elements to specify the position of this group
type: Array,
default: () => ["top", "right"],
validator: value => {
return (
value.length === 2 &&
["bottom", "top"].indexOf(value[0]) >= 0 &&
["left", "right", "center"].indexOf(value[1]) >= 0
);
}
},
customStyles: {
// custom styles that will be applied to the container
type: Object,
default: () => ({})
}
},
data() {
return {
notifications: [],
defaultStyles: {
maxWidth: "400px"
}
};
},
methods: {
/** Create the required notification object and adds it to the list
* @param {NewNotificationOpts} opts
*/
addNotification(opts) {
if (!this.isTargetGroup(opts)) {
return;
}
const notification = {
id: opts.id,
type: opts.type,
title: opts.title,
content: opts.content,
onDismiss: opts.onDismiss,
dismissible: opts.dismissible || true,
animation: {
class: config.fadeInAnimationClass
}
};
if (opts.timeout || !opts.permanent) {
notification.timeout = config.timeout || config.defaultTimeout;
notification.timer = setTimeout(() => {
this.destroyNotification(notification);
}, notification.timeout);
} else {
notification.permanent = true;
}
this.notifications.push(notification);
},
/**
* Destroy the notification on user click in cases it is dismissable
*/
onManualDismiss(notification) {
if (notification.dismissible) {
this.destroyNotification(notification);
}
},
/**
* Hide the notification and do the required cleanup
*/
destroyNotification(notification) {
notification.animation.class = config.fadeOutAnimationClass;
// hide notification timer if it's not permanent
if (!notification.permanent && notification.timer) {
clearTimeout(notification.timer);
}
// wait for animation to finish and remove the notification from the list
setTimeout(() => {
this.notifications = this.notifications.filter(n => n.id !== notification.id);
if (notification.onDismiss && typeof notification.onDismiss === "function") {
notification.onDismiss(notification);
}
}, config.animationDuration);
},
/**
* Remove all the notifications
*/
dismissAll() {
this.notifications.forEach(this.destroyNotification);
},
/**
* In case an existing id was passed, clear the notification that has it
*/
dismissById(id) {
const notification = this.notifications.find(n => n.id === id);
if (notification) {
this.destroyNotification(notification);
}
},
/**
* Check if this is the correct notifications group
*/
isTargetGroup(opts) {
opts.group = opts.group || "";
return opts.group === this.group;
},
/**
* Called when the bus emits the hideAll event
*/
onHideAll(group) {
if (group !== null && group !== undefined && !this.isTargetGroup({ group })) {
return;
}
this.dismissAll();
},
/**
* Called when the bus emits the hide event
*/
onHideSingle(opts) {
if (!this.isTargetGroup(opts)) {
return;
}
this.dismissById(opts.id);
}
},
computed: {
computedContainerClasses() {
return [
"fd-notifications__group",
`fd-notifications__group--${this.position[0]}`,
`fd-notifications__group--${this.position[1]}`
];
},
computedContainerStyles() {
return { ...this.defaultStyles, ...this.customStyles };
}
},
mounted() {
eventsBus.$on(events.hide, this.onHideSingle);
eventsBus.$on(events.hideAll, this.onHideAll);
eventsBus.$on(events.show, this.addNotification);
},
beforeDestroy() {
eventsBus.$off(events.hide, this.onHideSingle);
eventsBus.$off(events.hideAll, this.onHideAll);
eventsBus.$off(events.show, this.addNotification);
}
};
</script>

<style lang="scss">
@import "_notifications.styles";
@import "_notifications.animations";
</style>
Loading

0 comments on commit e73a4f4

Please sign in to comment.