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 @@ + + + + + +