##// END OF EJS Templates
rhodecode-toasts: allow removing single elements from toast queue.
marcink -
r1513:940ac693 default
parent child Browse files
Show More
@@ -1,25 +1,24 b''
1 1 <link rel="import" href="../../../../../../bower_components/paper-button/paper-button.html">
2 2 <link rel="import" href="../../../../../../bower_components/paper-toast/paper-toast.html">
3 3 <link rel="import" href="../../../../../../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
4 4 <link rel="import" href="../rhodecode-unsafe-html/rhodecode-unsafe-html.html">
5 5 <dom-module id="rhodecode-toast">
6 6 <template>
7 7 <style include="shared-styles"></style>
8 8 <link rel="stylesheet" href="rhodecode-toast.css">
9 9 <template is="dom-if" if="[[hasToasts]]">
10 10 <div class$="container toast-message-holder [[conditionalClass(isFixed)]]">
11 11 <template is="dom-repeat" items="[[toasts]]">
12 12 <div class$="alert alert-[[item.level]]">
13 <div on-tap="dismissNotification" class="toast-close" index-pos="[[index]]">
14 <span>[[_gettext('Close')]]</span>
15 </div>
13 16 <rhodecode-unsafe-html text="[[item.message]]"></rhodecode-unsafe-html>
14 17 </div>
15 18 </template>
16
17 <div class="toast-close">
18 <button on-tap="dismissNotifications" class="btn btn-default">[[_gettext('Close')]]</button>
19 </div>
20 19 </div>
21 20 </template>
22 21 </template>
23 22
24 23 <script src="rhodecode-toast.js"></script>
25 24 </dom-module>
@@ -1,92 +1,98 b''
1 1 Polymer({
2 2 is: 'rhodecode-toast',
3 3 properties: {
4 4 toasts: {
5 5 type: Array,
6 6 value: function(){
7 7 return []
8 8 }
9 9 },
10 10 isFixed: {
11 11 type: Boolean,
12 12 value: false
13 13 },
14 14 hasToasts: {
15 15 type: Boolean,
16 16 computed: '_computeHasToasts(toasts.*)'
17 17 },
18 18 keyEventTarget: {
19 19 type: Object,
20 20 value: function() {
21 21 return document.body;
22 22 }
23 23 }
24 24 },
25 25 behaviors: [
26 26 Polymer.IronA11yKeysBehavior
27 27 ],
28 28 observers: [
29 29 '_changedToasts(toasts.splices)'
30 30 ],
31 31
32 32 keyBindings: {
33 33 'esc:keyup': '_hideOnEsc'
34 34 },
35 35
36 36 _hideOnEsc: function (event) {
37 37 return this.dismissNotifications();
38 38 },
39 39
40 40 _computeHasToasts: function(){
41 41 return this.toasts.length > 0;
42 42 },
43 43
44 44 _debouncedCalc: function(){
45 45 // calculate once in a while
46 46 this.debounce('debouncedCalc', this.toastInWindow, 25);
47 47 },
48 48
49 49 conditionalClass: function(){
50 50 return this.isFixed ? 'fixed': '';
51 51 },
52 52
53 53 toastInWindow: function() {
54 54 if (!this._headerNode){
55 55 return true
56 56 }
57 57 var headerHeight = this._headerNode.offsetHeight;
58 58 var scrollPosition = window.scrollY;
59 59
60 60 if (this.isFixed){
61 61 this.isFixed = 1 <= scrollPosition;
62 62 }
63 63 else{
64 64 this.isFixed = headerHeight <= scrollPosition;
65 65 }
66 66 },
67 67
68 68 attached: function(){
69 69 this._headerNode = document.querySelector('.header', document);
70 70 this.listen(window,'scroll', '_debouncedCalc');
71 71 this.listen(window,'resize', '_debouncedCalc');
72 72 this._debouncedCalc();
73 73 },
74 74 _changedToasts: function(newValue, oldValue){
75 75 $.Topic('/favicon/update').publish({count: this.toasts.length});
76 76 },
77 dismissNotification: function(e) {
78 $.Topic('/favicon/update').publish({count: this.toasts.length-1});
79 var idx = e.target.parentNode.indexPos
80 this.splice('toasts', idx, 1);
81
82 },
77 83 dismissNotifications: function(){
78 84 $.Topic('/favicon/update').publish({count: 0});
79 85 this.splice('toasts', 0);
80 86 },
81 87 handleNotification: function(data){
82 88 if (!templateContext.rhodecode_user.notification_status && !data.message.force) {
83 89 // do not act if notifications are disabled
84 90 return
85 91 }
86 92 this.push('toasts',{
87 93 level: data.message.level,
88 94 message: data.message.message
89 95 });
90 96 },
91 97 _gettext: _gettext
92 98 });
@@ -1,28 +1,27 b''
1 1 @import '../../../../css/variables';
2 2 @import '../../../../css/mixins';
3 3
4 4 .alert{
5 5 margin: 10px 0;
6 6 }
7 7
8 .toast-close{
9 text-align: right;
10 .btn {
11 margin: 0;
12 }
8 .toast-close {
9 margin: 0;
10 float: right;
11 cursor: pointer;
13 12 }
14 13
15 14 .toast-message-holder{
16 15 background: fade(#fff, 25%);
17 16
18 17 &.fixed{
19 18 position: fixed;
20 19 padding: 10px 0;
21 20 margin-left: 10px;
22 21 margin-right: 10px;
23 22 top: 0;
24 23 left: 0;
25 24 right:0;
26 25 z-index: 100;
27 26 }
28 27 }
@@ -1,106 +1,130 b''
1 1 <template is="dom-bind" id="notificationsPage">
2 2 <iron-ajax id="toggleNotifications"
3 3 method="post"
4 4 url="${url('my_account_notifications_toggle_visibility')}"
5 5 content-type="application/json"
6 6 loading="{{changeNotificationsLoading}}"
7 7 on-response="handleNotifications"
8 8 handle-as="json">
9 9 </iron-ajax>
10 10
11 11 <iron-ajax id="sendTestNotification"
12 12 method="post"
13 13 url="${url('my_account_notifications_test_channelstream')}"
14 14 content-type="application/json"
15 15 on-response="handleTestNotification"
16 16 handle-as="json">
17 17 </iron-ajax>
18 18
19 19 <div class="panel panel-default">
20 20 <div class="panel-heading">
21 21 <h3 class="panel-title">${_('Your Live Notification Settings')}</h3>
22 22 </div>
23 23 <div class="panel-body">
24 24
25 25 <p><strong>IMPORTANT:</strong> This feature requires enabled channelstream websocket server to function correctly.</p>
26 26
27 27 <p class="hidden">Status of browser notifications permission: <strong id="browser-notification-status"></strong></p>
28 28
29 29 <div class="form">
30 30 <div class="fields">
31 31 <div class="field">
32 32 <div class="label">
33 33 <label for="new_email">${_('Notifications Status')}:</label>
34 34 </div>
35 35 <div class="checkboxes">
36 36 <rhodecode-toggle id="live-notifications" active="[[changeNotificationsLoading]]" on-change="toggleNotifications" ${'checked' if c.rhodecode_user.get_instance().user_data.get('notification_status') else ''}></rhodecode-toggle>
37 37 </div>
38 38 </div>
39 39 </div>
40 40 </div>
41 41 </div>
42 42 </div>
43 43
44 44 <div class="panel panel-default">
45 45 <div class="panel-heading">
46 46 <h3 class="panel-title">${_('Test Notifications')}</h3>
47 47 </div>
48 48 <div class="panel-body">
49 49
50 50
51 51 <div style="padding: 0px 0px 20px 0px">
52 52 <button class="btn" id="test-notification" on-tap="testNotifications">Test flash message</button>
53 53 <button class="btn" id="test-notification-live" on-tap="testNotificationsLive">Test live notification</button>
54 54 </div>
55 55 <h4 id="test-response"></h4>
56 56
57 57 </div>
58 58
59 59
60 60
61 61 </div>
62 62
63 63 <script type="text/javascript">
64 64 /** because im not creating a custom element for this page
65 65 * we need to push the function onto the dom-template
66 66 * ideally we turn this into notification-settings elements
67 67 * then it will be cleaner
68 68 */
69 69 var ctrlr = $('#notificationsPage')[0];
70 70 ctrlr.toggleNotifications = function(event){
71 71 var ajax = $('#toggleNotifications')[0];
72 72 ajax.headers = {"X-CSRF-Token": CSRF_TOKEN};
73 73 ajax.body = {notification_status:event.target.active};
74 74 ajax.generateRequest();
75 75 };
76 76 ctrlr.handleNotifications = function(event){
77 77 $('#live-notifications')[0].checked = event.detail.response;
78 78 };
79 79
80 80 ctrlr.testNotifications = function(event){
81 81 var levels = ['info', 'error', 'warning', 'success'];
82 82 var level = levels[Math.floor(Math.random()*levels.length)];
83 function getRandomArbitrary(min, max) {
84 return parseInt(Math.random() * (max - min) + min);
85 }
86 function shuffle(a) {
87 var j, x, i;
88 for (i = a.length; i; i--) {
89 j = Math.floor(Math.random() * i);
90 x = a[i - 1];
91 a[i - 1] = a[j];
92 a[j] = x;
93 }
94 }
95 var wordDb = [
96 "Leela,", "Bender,", "we are", "going", "grave", "robbing.",
97 "Oh,", "I", "think", "we", "should", "just", "stay", "friends.",
98 "got", "to", "find", "a", "way", "to", "escape", "the", "horrible",
99 "ravages", "of", "youth.", "Suddenly,", "going", "to",
100 "the", "bathroom", "like", "clockwork,", "every", "three",
101 "hours.", "And", "those", "jerks", "at", "Social", "Security",
102 "stopped", "sending", "me", "checks.", "Now", "have", "to", "pay"
103 ];
104 shuffle(wordDb);
105 wordDb = wordDb.slice(0, getRandomArbitrary(3, wordDb.length));
106 var randomMessage = wordDb.join(" ");
83 107 var payload = {
84 108 message: {
85 message: 'This is a test notification. ' + new Date(),
109 message: randomMessage + " " + new Date(),
86 110 level: level,
87 111 force: true
88 112 }
89 113 };
90 114 $.Topic('/notifications').publish(payload);
91 115 };
92 116 ctrlr.testNotificationsLive = function(event){
93 117 var ajax = $('#sendTestNotification')[0];
94 118 ajax.headers = {"X-CSRF-Token": CSRF_TOKEN};
95 119 ajax.body = {test_msg: 'Hello !'};
96 120 ajax.generateRequest();
97 121 };
98 122 ctrlr.handleTestNotification = function(event){
99 123 var reply = event.detail.response.response;
100 124 reply = reply || 'no reply form server';
101 125 $('#test-response').html(reply);
102 126 };
103 127
104 128 </script>
105 129
106 130 </template>
General Comments 0
You need to be logged in to leave comments. Login now