diff --git a/platypush/backend/http/static/css/source/common/animations.scss b/platypush/backend/http/static/css/source/common/animations.scss
new file mode 100644
index 00000000..fc24399b
--- /dev/null
+++ b/platypush/backend/http/static/css/source/common/animations.scss
@@ -0,0 +1,37 @@
+.fade-in {
+ --duration: $fade-in-transition-duration;
+ opacity: 1;
+ animation-name: fadeInOpacity;
+ animation-iteration-count: 1;
+ animation-timing-function: ease-in;
+ animation-duration: var(--duration);
+}
+
+@keyframes fadeInOpacity {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+.fade-out {
+ --duration: $fade-out-transition-duration;
+ opacity: 1;
+ animation-name: fadeOutOpacity;
+ animation-iteration-count: 1;
+ animation-timing-function: ease-out;
+ animation-duration: var(--duration);
+}
+
+@keyframes fadeOutOpacity {
+ 0% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ display: none;
+ }
+}
+
diff --git a/platypush/backend/http/static/css/source/common/layout.scss b/platypush/backend/http/static/css/source/common/layout.scss
index f69d0e4c..2e6cc4ca 100644
--- a/platypush/backend/http/static/css/source/common/layout.scss
+++ b/platypush/backend/http/static/css/source/common/layout.scss
@@ -86,3 +86,10 @@ $widths: (
align-items: center;
}
+.horizontal-center {
+ display: flex;
+ justify-content: center;
+ margin-left: auto;
+ margin-right: auto;
+}
+
diff --git a/platypush/backend/http/static/css/source/common/notification.scss b/platypush/backend/http/static/css/source/common/notification.scss
deleted file mode 100644
index a0cc0bc8..00000000
--- a/platypush/backend/http/static/css/source/common/notification.scss
+++ /dev/null
@@ -1,65 +0,0 @@
-#notification-container {
- position: fixed;
- bottom: 0;
- right: 0;
- width: 25em;
-
- .notification {
- background: rgba(180,245,188,0.85);
- border: 1px solid #bbb;
- border-radius: 5px;
- margin-bottom: 1rem;
- margin-right: 1rem;
- cursor: pointer;
- display: none;
- }
-
- .notification:hover {
- background: rgba(160,235,168,0.9);
- }
-
- .notification-title {
- padding: 4px 10px;
- font-weight: bold;
- text-transform: capitalize;
- line-height: 30px;
- letter-spacing: .1rem;
- }
-
- .notification-body {
- height: 6em;
- overflow: hidden;
- padding-bottom: 1rem;
- letter-spacing: .05rem;
- }
-
- .notification-text {
- margin-left: 0 !important;
- }
-
- .notification-image {
- height: 100%;
- text-align: center;
- padding-top: .6em;
- padding-bottom: .6em;
-
- .notification-image-item {
- width: 100%;
- height: 100%;
- margin: auto;
- }
-
- .fa.notification-image-item {
- margin-top: .8em;
- margin-left: .2em;
- font-size: 25px;
- }
-
- img {
- width: 80%;
- height: 80%;
- }
- }
-}
-
-
diff --git a/platypush/backend/http/static/css/source/common/notifications.scss b/platypush/backend/http/static/css/source/common/notifications.scss
new file mode 100644
index 00000000..e568208c
--- /dev/null
+++ b/platypush/backend/http/static/css/source/common/notifications.scss
@@ -0,0 +1,73 @@
+#notifications {
+ position: fixed;
+ bottom: 0;
+ right: 0;
+ width: 25em;
+
+ .notification {
+ background: $notification-bg;
+ border: $notification-border;
+ border-radius: .5rem;
+ margin-bottom: 1rem;
+ margin-right: 1rem;
+ cursor: pointer;
+
+ &:hover {
+ background: $notification-hover-bg;
+ &.warning { background: $notification-warning-hover-bg; }
+ &.error { background: $notification-error-hover-bg; }
+ }
+
+ &.warning {
+ background: $notification-warning-bg;
+ border: $notification-warning-border;
+ .image { --color: $notification-warning-icon-color; }
+ }
+
+ &.error {
+ background: $notification-error-bg;
+ border: $notification-error-border;
+ .image { --color: $notification-error-icon-color; }
+ }
+
+ .title {
+ border-bottom: $notification-title-border;
+ padding: .4rem;
+ text-transform: uppercase;
+ line-height: 3rem;
+ letter-spacing: .1rem;
+ }
+
+ .body {
+ @extend .vertical-center;
+ height: 6em;
+ overflow: hidden;
+ padding-bottom: 1rem;
+ letter-spacing: .05rem;
+ }
+
+ .image {
+ height: 100%;
+ text-align: center;
+ --color: $notification-icon-color;
+
+ .row {
+ @extend .vertical-center;
+ @extend .horizontal-center;
+ width: 100%;
+ height: 100%;
+
+ .fa {
+ font-size: 2.5rem;
+ color: var(--color);
+ }
+
+ img {
+ width: 80%;
+ height: 80%;
+ }
+ }
+ }
+ }
+}
+
diff --git a/platypush/backend/http/static/css/source/common/vars.scss b/platypush/backend/http/static/css/source/common/vars.scss
index c87a4d2d..0ec0872a 100644
--- a/platypush/backend/http/static/css/source/common/vars.scss
+++ b/platypush/backend/http/static/css/source/common/vars.scss
@@ -19,6 +19,27 @@ $nav-date-time-shadow: 2px 2px 2px #ccc !default;
$modal-bg: #f0f0f0 !default;
+//// Animations defaults
+$transition-duration: .5s !default;
+$fade-transition-duration: .5s !default;
+$fade-in-transition-duration: $fade-transition-duration !default;
+$fade-out-transition-duration: $fade-transition-duration !default;
+
+//// Notifications
+$notification-bg: rgba(185, 255, 193, 0.85) !default;
+$notification-hover-bg: rgba(160,245,178,0.9) !default;
+$notification-warning-bg: rgba(228, 255, 78, 0.85) !default;
+$notification-warning-hover-bg: rgba(218, 245, 68, 0.9) !default;
+$notification-error-bg: rgba(255, 100, 100, 0.85) !default;
+$notification-error-hover-bg: rgba(245, 90, 90, 0.9) !default;
+$notification-border: 1px solid rgba(109, 205, 134, 0.62) !default;
+$notification-warning-border: 1px solid rgba(205, 205, 109, 0.62) !default;
+$notification-error-border: 1px solid rgba(205, 109, 109, 0.62) !default;
+$notification-title-border: 1px solid rgba(83, 158, 102, 0.43) !default;
+$notification-icon-color: black !default;
+$notification-warning-icon-color: #662 !default;
+$notification-error-icon-color: #8b0000 !default;
+
//// Switch element
$switch-bg-1: #f9f8f6 !default;
$switch-bg-2: #38ffa0 !default;
diff --git a/platypush/backend/http/static/css/source/webpanel/index.scss b/platypush/backend/http/static/css/source/webpanel/index.scss
index 1403b377..f9d3a09f 100644
--- a/platypush/backend/http/static/css/source/webpanel/index.scss
+++ b/platypush/backend/http/static/css/source/webpanel/index.scss
@@ -3,8 +3,9 @@
@import 'common/mixins';
@import 'common/layout';
@import 'common/elements';
+@import 'common/animations';
@import 'common/modal';
-@import 'common/notification';
+@import 'common/notifications';
@import 'header';
@import 'nav';
diff --git a/platypush/backend/http/static/js/api.js b/platypush/backend/http/static/js/api.js
index ea2c074f..b8e08c3f 100644
--- a/platypush/backend/http/static/js/api.js
+++ b/platypush/backend/http/static/js/api.js
@@ -22,12 +22,21 @@ function execute(request) {
if (!response.errors.length) {
resolve(response.output);
} else {
- // TODO Handle error
- reject(response.errors[0]);
+ const error = response.errors[0];
+ createNotification({
+ text: error,
+ error: true,
+ });
+
+ reject(error);
}
})
.catch((error) => {
- // TODO Handle error
+ createNotification({
+ text: error,
+ error: true,
+ });
+
reject(error);
});
});
diff --git a/platypush/backend/http/static/js/application.js b/platypush/backend/http/static/js/application.js
index 012da3d7..871ebd62 100644
--- a/platypush/backend/http/static/js/application.js
+++ b/platypush/backend/http/static/js/application.js
@@ -26,7 +26,7 @@ Vue.component('plugin', {
});
// Declaration of the main vue app
-var app = new Vue({
+window.vm = new Vue({
el: '#app',
// Override {{ }} delimiters to prevent clash with Flask templates
delimiters: ['[[',']]'],
diff --git a/platypush/backend/http/static/js/notifications.js b/platypush/backend/http/static/js/notifications.js
new file mode 100644
index 00000000..8b8b1767
--- /dev/null
+++ b/platypush/backend/http/static/js/notifications.js
@@ -0,0 +1,63 @@
+Vue.component('notifications', {
+ template: '#tmpl-notifications',
+ props: {
+ duration: {
+ // Default notification duration in milliseconds
+ type: Number,
+ default: 10000,
+ }
+ },
+
+ data: function() {
+ return {
+ index: 0,
+ notifications: {},
+ timeouts: {},
+ };
+ },
+
+ methods: {
+ create: function(args) {
+ var id = this.index++;
+ Vue.set(this.notifications, id, args);
+
+ if (args.duration == null) {
+ args.duration = this.duration;
+ }
+
+ if (args.duration != 0) {
+ this.timeouts[id] = setTimeout(this.destroy.bind(null, id), args.duration);
+ }
+ },
+
+ destroy: function(id) {
+ Vue.delete(this.notifications, id);
+ delete this.timeouts[id];
+ },
+ },
+});
+
+Vue.component('notification', {
+ template: '#tmpl-notification',
+ props: ['id','text','html','title','image','link','error','warning'],
+
+ methods: {
+ mousein: function(event) {
+ },
+
+ mouseout: function(event) {
+ },
+ clicked: function(event) {
+ if (this.link) {
+ window.open(this.link, '_blank');
+ }
+
+ this.$emit('clicked', this.id);
+ },
+ },
+});
+
+function createNotification(args) {
+ window.vm.$refs.notifications.create(args);
+}
+
diff --git a/platypush/backend/http/templates/index.html b/platypush/backend/http/templates/index.html
index acdd962d..0028a780 100644
--- a/platypush/backend/http/templates/index.html
+++ b/platypush/backend/http/templates/index.html
@@ -14,6 +14,7 @@
+
{% for style in styles.values() %}
@@ -60,6 +61,8 @@
{% endfor %}
+
+ {% include 'notifications.html' %}
{% include 'plugins/template.html' %}
diff --git a/platypush/backend/http/templates/notifications.html b/platypush/backend/http/templates/notifications.html
new file mode 100644
index 00000000..3eeb46c7
--- /dev/null
+++ b/platypush/backend/http/templates/notifications.html
@@ -0,0 +1,41 @@
+
+
+
+
+
+