the_notification 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5bc2d717d5e0cc126b7c8dc93351f47fec2f1272
4
+ data.tar.gz: 6eb52510b458ed2aed7d0370b55820b8bf62bec6
5
+ SHA512:
6
+ metadata.gz: 64b1389ee3867e58dfcb6403014c1a0b5e48b93fb35e4528ac55e40d5aa4d572800a75e4db8f054d45aec3a00b9e986d06225ce937a8b231009db86a140ee4e5
7
+ data.tar.gz: 37b5e61f3cbfa23aa3c365d9da9951dcad38cb4cde1ef51ed54e022ea17c71ca122c16f12723335076e63efeac726251a072e1f18fd3cd602e9cb704f482330c
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in the_notification.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ilya N. Zykin
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,125 @@
1
+ ## TheNotification
2
+
3
+ Just add JSON on HTML notifications in your APP
4
+
5
+ Designed for Bootstrap 3 style of for toastr notifications
6
+
7
+ ## How it works
8
+
9
+ Just remove
10
+
11
+ ```ruby
12
+ <%= form_for(@resource) do |f| %>
13
+ <% if @resource.errors.any? %>
14
+ <div id="error_explanation">
15
+ <h2><%= pluralize(@resource.errors.count, "error") %> prohibited this resource from being saved:</h2>
16
+
17
+ <ul>
18
+ <% @resource.errors.full_messages.each do |msg| %>
19
+ <li><%= msg %></li>
20
+ <% end %>
21
+ </ul>
22
+ </div>
23
+ <% end %>
24
+
25
+ # ....
26
+
27
+ <% end %>
28
+ ```
29
+
30
+ with
31
+
32
+ ```ruby
33
+ <%= form_for(@post) do |f| %>
34
+ <%= render partial: 'the_notification/form', locals: { object: @post } %>
35
+
36
+ # ....
37
+
38
+ <% end %>
39
+ ```
40
+
41
+ and add to Layout
42
+
43
+ ```ruby
44
+ <body>
45
+ <%= render partial: 'the_notification/flash' %>
46
+ <%= yield %>
47
+ ```
48
+
49
+ *application.js*
50
+ ```js
51
+ //= require the_notification/vendors/toastr
52
+ //= require the_notification
53
+ ```
54
+
55
+ *application.css*
56
+ ```js
57
+ *= require bootstrap
58
+ *= require the_notification/vendors/toastr
59
+ ```
60
+
61
+ ### HTML or JSON
62
+
63
+ ```erb
64
+ <%= render partial: 'the_notification/flash' locals: { format: :html } %>
65
+ <%= render partial: 'the_notification/form', locals: { object: @post, format: :html } %>
66
+ ```
67
+
68
+ or
69
+
70
+ ```erb
71
+ <%= render partial: 'the_notification/flash' locals: { format: :json } %>
72
+ <%= render partial: 'the_notification/form', locals: { object: @post, format: :json } %>
73
+ ```
74
+
75
+ *initializers/the_notification.rb*
76
+ ```ruby
77
+ TheNotification.configure do |config|
78
+ config.default_type = :json # :html
79
+ end
80
+ ```
81
+
82
+ ### Localized errors
83
+
84
+ *models/user.rb*
85
+ ```ruby
86
+ class Post < ActiveRecord::Base
87
+ include TheNotification::LocalizedErrors
88
+ end
89
+ ```
90
+
91
+ *config/locales/ru.yml*
92
+ ```
93
+ activerecord:
94
+ models:
95
+ post: Публикация
96
+ attributes:
97
+ post:
98
+ title: "Загловок"
99
+ ```
100
+
101
+ Now errors messages will looks like this:
102
+
103
+ ```
104
+ Загловок: не может быть пустым
105
+ ```
106
+
107
+ instead
108
+
109
+ ```
110
+ Title: не может быть пустым
111
+ ```
112
+
113
+ ### Installation
114
+
115
+ ```ruby
116
+ gem 'the_notification'
117
+ ```
118
+
119
+ ```sh
120
+ $ bundle
121
+ ```
122
+
123
+ ### Usage
124
+
125
+ TODO: Write usage instructions here
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,40 @@
1
+ @TheNotification = do ->
2
+ show_error: (error) ->
3
+ toastr.error(error) if error
4
+
5
+ show_errors: (errors) ->
6
+ for field, errs of errors
7
+ for err in errs
8
+ toastr.error "<b>#{ field }:</b> #{ err }"
9
+
10
+ show_flash: (flash) ->
11
+ fu =
12
+ notice: 'info'
13
+ errors: 'error'
14
+ error: 'error'
15
+ warning: 'warning'
16
+ alert: 'warning'
17
+
18
+ for level, msg of flash
19
+ method = fu[level] || 'info'
20
+
21
+ if msg instanceof Array
22
+ for _msg in msg
23
+ toastr[method] _msg
24
+ else
25
+ toastr[method] msg
26
+
27
+ show_notifications: ->
28
+ data = window.the_notifications
29
+ return false unless data
30
+
31
+ @show_errors errors if errors = data.errors
32
+ @show_flash flash if flash = data.flash
33
+
34
+ click_for_close_init: ->
35
+ $('.flash_msgs, .error_explanation').on 'click', ->
36
+ $(@).slideUp(500)
37
+
38
+ init: ->
39
+ do @click_for_close_init
40
+ do @show_notifications
@@ -0,0 +1,306 @@
1
+ /*
2
+ * Toastr
3
+ * Version 2.0.1
4
+ * Copyright 2012 John Papa and Hans Fjällemark.
5
+ * All Rights Reserved.
6
+ * Use, reproduction, distribution, and modification of this code is subject to the terms and
7
+ * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
8
+ *
9
+ * Author: John Papa and Hans Fjällemark
10
+ * Project: https://github.com/CodeSeven/toastr
11
+ */
12
+ ; (function (define) {
13
+ define(['jquery'], function ($) {
14
+ return (function () {
15
+ var version = '2.0.1';
16
+ var $container;
17
+ var listener;
18
+ var toastId = 0;
19
+ var toastType = {
20
+ error: 'error',
21
+ info: 'info',
22
+ success: 'success',
23
+ warning: 'warning'
24
+ };
25
+
26
+ var toastr = {
27
+ clear: clear,
28
+ error: error,
29
+ getContainer: getContainer,
30
+ info: info,
31
+ options: {},
32
+ subscribe: subscribe,
33
+ success: success,
34
+ version: version,
35
+ warning: warning
36
+ };
37
+
38
+ return toastr;
39
+
40
+ //#region Accessible Methods
41
+ function error(message, title, optionsOverride) {
42
+ return notify({
43
+ type: toastType.error,
44
+ iconClass: getOptions().iconClasses.error,
45
+ message: message,
46
+ optionsOverride: optionsOverride,
47
+ title: title
48
+ });
49
+ }
50
+
51
+ function info(message, title, optionsOverride) {
52
+ return notify({
53
+ type: toastType.info,
54
+ iconClass: getOptions().iconClasses.info,
55
+ message: message,
56
+ optionsOverride: optionsOverride,
57
+ title: title
58
+ });
59
+ }
60
+
61
+ function subscribe(callback) {
62
+ listener = callback;
63
+ }
64
+
65
+ function success(message, title, optionsOverride) {
66
+ return notify({
67
+ type: toastType.success,
68
+ iconClass: getOptions().iconClasses.success,
69
+ message: message,
70
+ optionsOverride: optionsOverride,
71
+ title: title
72
+ });
73
+ }
74
+
75
+ function warning(message, title, optionsOverride) {
76
+ return notify({
77
+ type: toastType.warning,
78
+ iconClass: getOptions().iconClasses.warning,
79
+ message: message,
80
+ optionsOverride: optionsOverride,
81
+ title: title
82
+ });
83
+ }
84
+
85
+ function clear($toastElement) {
86
+ var options = getOptions();
87
+ if (!$container) { getContainer(options); }
88
+ if ($toastElement && $(':focus', $toastElement).length === 0) {
89
+ $toastElement[options.hideMethod]({
90
+ duration: options.hideDuration,
91
+ easing: options.hideEasing,
92
+ complete: function () { removeToast($toastElement); }
93
+ });
94
+ return;
95
+ }
96
+ if ($container.children().length) {
97
+ $container[options.hideMethod]({
98
+ duration: options.hideDuration,
99
+ easing: options.hideEasing,
100
+ complete: function () { $container.remove(); }
101
+ });
102
+ }
103
+ }
104
+ //#endregion
105
+
106
+ //#region Internal Methods
107
+
108
+ function getDefaults() {
109
+ return {
110
+ tapToDismiss: true,
111
+ toastClass: 'toast',
112
+ containerId: 'toast-container',
113
+ debug: false,
114
+
115
+ showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
116
+ showDuration: 300,
117
+ showEasing: 'swing', //swing and linear are built into jQuery
118
+ onShown: undefined,
119
+ hideMethod: 'fadeOut',
120
+ hideDuration: 1000,
121
+ hideEasing: 'swing',
122
+ onHidden: undefined,
123
+
124
+ extendedTimeOut: 1000,
125
+ iconClasses: {
126
+ error: 'toast-error',
127
+ info: 'toast-info',
128
+ success: 'toast-success',
129
+ warning: 'toast-warning'
130
+ },
131
+ iconClass: 'toast-info',
132
+ positionClass: 'toast-top-right',
133
+ timeOut: 5000, // Set timeOut and extendedTimeout to 0 to make it sticky
134
+ titleClass: 'toast-title',
135
+ messageClass: 'toast-message',
136
+ target: 'body',
137
+ closeHtml: '<button>&times;</button>',
138
+ newestOnTop: true
139
+ };
140
+ }
141
+
142
+ function publish(args) {
143
+ if (!listener) {
144
+ return;
145
+ }
146
+ listener(args);
147
+ }
148
+
149
+ function notify(map) {
150
+ var
151
+ options = getOptions(),
152
+ iconClass = map.iconClass || options.iconClass;
153
+
154
+ if (typeof (map.optionsOverride) !== 'undefined') {
155
+ options = $.extend(options, map.optionsOverride);
156
+ iconClass = map.optionsOverride.iconClass || iconClass;
157
+ }
158
+
159
+ toastId++;
160
+
161
+ $container = getContainer(options);
162
+ var
163
+ intervalId = null,
164
+ $toastElement = $('<div/>'),
165
+ $titleElement = $('<div/>'),
166
+ $messageElement = $('<div/>'),
167
+ $closeElement = $(options.closeHtml),
168
+ response = {
169
+ toastId: toastId,
170
+ state: 'visible',
171
+ startTime: new Date(),
172
+ options: options,
173
+ map: map
174
+ };
175
+
176
+ if (map.iconClass) {
177
+ $toastElement.addClass(options.toastClass).addClass(iconClass);
178
+ }
179
+
180
+ if (map.title) {
181
+ $titleElement.append(map.title).addClass(options.titleClass);
182
+ $toastElement.append($titleElement);
183
+ }
184
+
185
+ if (map.message) {
186
+ $messageElement.append(map.message).addClass(options.messageClass);
187
+ $toastElement.append($messageElement);
188
+ }
189
+
190
+ if (options.closeButton) {
191
+ $closeElement.addClass('toast-close-button');
192
+ $toastElement.prepend($closeElement);
193
+ }
194
+
195
+ $toastElement.hide();
196
+ if (options.newestOnTop) {
197
+ $container.prepend($toastElement);
198
+ } else {
199
+ $container.append($toastElement);
200
+ }
201
+
202
+
203
+ $toastElement[options.showMethod](
204
+ { duration: options.showDuration, easing: options.showEasing, complete: options.onShown }
205
+ );
206
+ if (options.timeOut > 0) {
207
+ intervalId = setTimeout(hideToast, options.timeOut);
208
+ }
209
+
210
+ $toastElement.hover(stickAround, delayedhideToast);
211
+ if (!options.onclick && options.tapToDismiss) {
212
+ $toastElement.click(hideToast);
213
+ }
214
+ if (options.closeButton && $closeElement) {
215
+ $closeElement.click(function (event) {
216
+ event.stopPropagation();
217
+ hideToast(true);
218
+ });
219
+ }
220
+
221
+ if (options.onclick) {
222
+ $toastElement.click(function () {
223
+ options.onclick();
224
+ hideToast();
225
+ });
226
+ }
227
+
228
+ publish(response);
229
+
230
+ if (options.debug && console) {
231
+ console.log(response);
232
+ }
233
+
234
+ return $toastElement;
235
+
236
+ function hideToast(override) {
237
+ if ($(':focus', $toastElement).length && !override) {
238
+ return;
239
+ }
240
+ return $toastElement[options.hideMethod]({
241
+ duration: options.hideDuration,
242
+ easing: options.hideEasing,
243
+ complete: function () {
244
+ removeToast($toastElement);
245
+ if (options.onHidden) {
246
+ options.onHidden();
247
+ }
248
+ response.state = 'hidden';
249
+ response.endTime = new Date(),
250
+ publish(response);
251
+ }
252
+ });
253
+ }
254
+
255
+ function delayedhideToast() {
256
+ if (options.timeOut > 0 || options.extendedTimeOut > 0) {
257
+ intervalId = setTimeout(hideToast, options.extendedTimeOut);
258
+ }
259
+ }
260
+
261
+ function stickAround() {
262
+ clearTimeout(intervalId);
263
+ $toastElement.stop(true, true)[options.showMethod](
264
+ { duration: options.showDuration, easing: options.showEasing }
265
+ );
266
+ }
267
+ }
268
+ function getContainer(options) {
269
+ if (!options) { options = getOptions(); }
270
+ $container = $('#' + options.containerId);
271
+ if ($container.length) {
272
+ return $container;
273
+ }
274
+ $container = $('<div/>')
275
+ .attr('id', options.containerId)
276
+ .addClass(options.positionClass);
277
+ $container.appendTo($(options.target));
278
+ return $container;
279
+ }
280
+
281
+ function getOptions() {
282
+ return $.extend({}, getDefaults(), toastr.options);
283
+ }
284
+
285
+ function removeToast($toastElement) {
286
+ if (!$container) { $container = getContainer(); }
287
+ if ($toastElement.is(':visible')) {
288
+ return;
289
+ }
290
+ $toastElement.remove();
291
+ $toastElement = null;
292
+ if ($container.children().length === 0) {
293
+ $container.remove();
294
+ }
295
+ }
296
+ //#endregion
297
+
298
+ })();
299
+ });
300
+ }(typeof define === 'function' && define.amd ? define : function (deps, factory) {
301
+ if (typeof module !== 'undefined' && module.exports) { //Node
302
+ module.exports = factory(require(deps[0]));
303
+ } else {
304
+ window['toastr'] = factory(window['jQuery']);
305
+ }
306
+ }));
@@ -0,0 +1,37 @@
1
+ .flash_msgs{
2
+ padding: 10px 10px 0px 10px;
3
+ margin-bottom: 15px;
4
+ border-radius: 5px;
5
+ cursor: pointer;
6
+
7
+ &.alert-info{
8
+ border: 3px solid #3A87AD;
9
+ color: #3A87AD;
10
+
11
+ p{
12
+ font-size: 14px;
13
+ line-height: 130%;
14
+ }
15
+ }
16
+ }
17
+
18
+ .error_explanation.alert-danger{
19
+ border: 3px solid #B94A48;
20
+ color: #B94A48;
21
+
22
+ padding: 10px 10px 0px 10px;
23
+ margin-bottom: 15px;
24
+ border-radius: 5px;
25
+ cursor: pointer;
26
+
27
+ ul{
28
+ margin-left: 15px;
29
+ padding-bottom: 0.1px;
30
+ list-style: disc inside none;
31
+ }
32
+ li{
33
+ font-size: 14px;
34
+ line-height: 130%;
35
+ margin-bottom: 15px;
36
+ }
37
+ }
@@ -0,0 +1,183 @@
1
+ /*
2
+ * Toastr
3
+ * Version 2.0.1
4
+ * Copyright 2012 John Papa and Hans Fjällemark.
5
+ * All Rights Reserved.
6
+ * Use, reproduction, distribution, and modification of this code is subject to the terms and
7
+ * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
8
+ *
9
+ * Author: John Papa and Hans Fjällemark
10
+ * Project: https://github.com/CodeSeven/toastr
11
+ */
12
+ .toast-title {
13
+ font-weight: bold;
14
+ }
15
+ .toast-message {
16
+ -ms-word-wrap: break-word;
17
+ word-wrap: break-word;
18
+ }
19
+ .toast-message a,
20
+ .toast-message label {
21
+ color: #ffffff;
22
+ }
23
+ .toast-message a:hover {
24
+ color: #cccccc;
25
+ text-decoration: none;
26
+ }
27
+
28
+ .toast-close-button {
29
+ position: relative;
30
+ right: -0.3em;
31
+ top: -0.3em;
32
+ float: right;
33
+ font-size: 20px;
34
+ font-weight: bold;
35
+ color: #ffffff;
36
+ -webkit-text-shadow: 0 1px 0 #ffffff;
37
+ text-shadow: 0 1px 0 #ffffff;
38
+ opacity: 0.8;
39
+ -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
40
+ filter: alpha(opacity=80);
41
+ }
42
+ .toast-close-button:hover,
43
+ .toast-close-button:focus {
44
+ color: #000000;
45
+ text-decoration: none;
46
+ cursor: pointer;
47
+ opacity: 0.4;
48
+ -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
49
+ filter: alpha(opacity=40);
50
+ }
51
+
52
+ /*Additional properties for button version
53
+ iOS requires the button element instead of an anchor tag.
54
+ If you want the anchor version, it requires `href="#"`.*/
55
+ button.toast-close-button {
56
+ padding: 0;
57
+ cursor: pointer;
58
+ background: transparent;
59
+ border: 0;
60
+ -webkit-appearance: none;
61
+ }
62
+ .toast-top-full-width {
63
+ top: 0;
64
+ right: 0;
65
+ width: 100%;
66
+ }
67
+ .toast-bottom-full-width {
68
+ bottom: 0;
69
+ right: 0;
70
+ width: 100%;
71
+ }
72
+ .toast-top-left {
73
+ top: 12px;
74
+ left: 12px;
75
+ }
76
+ .toast-top-right {
77
+ top: 12px;
78
+ right: 12px;
79
+ }
80
+ .toast-bottom-right {
81
+ right: 12px;
82
+ bottom: 12px;
83
+ }
84
+ .toast-bottom-left {
85
+ bottom: 12px;
86
+ left: 12px;
87
+ }
88
+ #toast-container {
89
+ position: fixed;
90
+ z-index: 999999;
91
+ /*overrides*/
92
+
93
+ }
94
+ #toast-container * {
95
+ -moz-box-sizing: border-box;
96
+ -webkit-box-sizing: border-box;
97
+ box-sizing: border-box;
98
+ }
99
+ #toast-container > div {
100
+ margin: 0 0 6px;
101
+ padding: 15px 15px 15px 50px;
102
+ width: 300px;
103
+ -moz-border-radius: 3px 3px 3px 3px;
104
+ -webkit-border-radius: 3px 3px 3px 3px;
105
+ border-radius: 3px 3px 3px 3px;
106
+ background-position: 15px center;
107
+ background-repeat: no-repeat;
108
+ -moz-box-shadow: 0 0 12px #999999;
109
+ -webkit-box-shadow: 0 0 12px #999999;
110
+ box-shadow: 0 0 12px #999999;
111
+ color: #ffffff;
112
+ opacity: 0.8;
113
+ -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
114
+ filter: alpha(opacity=80);
115
+ }
116
+ #toast-container > :hover {
117
+ -moz-box-shadow: 0 0 12px #000000;
118
+ -webkit-box-shadow: 0 0 12px #000000;
119
+ box-shadow: 0 0 12px #000000;
120
+ opacity: 1;
121
+ -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
122
+ filter: alpha(opacity=100);
123
+ cursor: pointer;
124
+ }
125
+ #toast-container > .toast-info {
126
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important;
127
+ }
128
+ #toast-container > .toast-error {
129
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important;
130
+ }
131
+ #toast-container > .toast-success {
132
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important;
133
+ }
134
+ #toast-container > .toast-warning {
135
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important;
136
+ }
137
+ #toast-container.toast-top-full-width > div,
138
+ #toast-container.toast-bottom-full-width > div {
139
+ width: 96%;
140
+ margin: auto;
141
+ }
142
+ .toast {
143
+ background-color: #030303;
144
+ }
145
+ .toast-success {
146
+ background-color: #51a351;
147
+ }
148
+ .toast-error {
149
+ background-color: #bd362f;
150
+ }
151
+ .toast-info {
152
+ background-color: #2f96b4;
153
+ }
154
+ .toast-warning {
155
+ background-color: #f89406;
156
+ }
157
+ /*Responsive Design*/
158
+ @media all and (max-width: 240px) {
159
+ #toast-container > div {
160
+ padding: 8px 8px 8px 50px;
161
+ width: 11em;
162
+ }
163
+ #toast-container .toast-close-button {
164
+ right: -0.2em;
165
+ top: -0.2em;
166
+ }
167
+ }
168
+ @media all and (min-width: 241px) and (max-width: 480px) {
169
+ #toast-container > div {
170
+ padding: 8px 8px 8px 50px;
171
+ width: 18em;
172
+ }
173
+ #toast-container .toast-close-button {
174
+ right: -0.2em;
175
+ top: -0.2em;
176
+ }
177
+ }
178
+ @media all and (min-width: 481px) and (max-width: 768px) {
179
+ #toast-container > div {
180
+ padding: 15px 15px 15px 50px;
181
+ width: 25em;
182
+ }
183
+ }
@@ -0,0 +1,11 @@
1
+ module TheNotificationHelper
2
+ def flash_class(level)
3
+ case level.to_sym
4
+ when :notice then "alert-info"
5
+ when :errors then "alert-danger"
6
+ when :error then "alert-danger"
7
+ when :alert then "alert-warning"
8
+ else "alert-success"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module TheNotification
2
+ module LocalizedErrors
3
+ extend ActiveSupport::Concern
4
+
5
+ # include TheNotification::LocalizedErrors
6
+
7
+ # @post.localized_errors(except: [:'comment.title'])
8
+ def localized_errors opts = {}
9
+ opts.symbolize_keys!
10
+ excepts = opts.delete(:except) || []
11
+
12
+ errors.inject({}) do |hash, (k, v)|
13
+ unless excepts.include?(k.to_sym)
14
+ k = self.class.human_attribute_name k
15
+ hash[k].blank? ? hash[k] = [v] : hash[k].push(v)
16
+ end
17
+ hash
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ - format = (format || TheNotification.config.default_type).to_s
2
+ - flash_types = %w[ notice alert error errors ]
3
+
4
+ - if format == 'html'
5
+ - flash_types.each do |level|
6
+ - unless flash[level].blank?
7
+ .alert.flash_msgs class=flash_class(level)
8
+ = content_tag :p, flash[level]
9
+ - else
10
+ - unless flash.blank?
11
+ = javascript_tag defer: :defer, type: "text/javascript" do
12
+ | window.the_notifications = window.the_notifications || {};
13
+ | window.the_notifications['flash'] = window.the_notifications['flash'] || {};
14
+
15
+ - flash_types.each do |level|
16
+ - unless flash[level].blank?
17
+ = javascript_tag defer: :defer, type: "text/javascript" do
18
+ | window.the_notifications['flash']['#{ level }'] = JSON.parse('#{ raw j flash[level].to_json }');
@@ -0,0 +1,28 @@
1
+ -# Error mesages
2
+ -# Post.model_name.human => activerecord.models.post
3
+ -# Post.human_attribute_name('title') => activerecord.attributes.post.title
4
+ - format = (format || TheNotification.config.default_type).to_s
5
+
6
+ - if object.try(:errors).try(:any?)
7
+ - _errors = object.try(:localized_errors) || object.errors
8
+ - if format == 'html'
9
+ .error_explanation.alert.alert-danger
10
+ h4= t "the_notification.form_errors"
11
+ ul
12
+ - _errors.map do |name, msgs|
13
+ - if msgs.is_a? Array
14
+ - msgs.each do |msg|
15
+ li
16
+ strong= name
17
+ '
18
+ = msg
19
+ - else
20
+ li
21
+ strong= name
22
+ '
23
+ = msgs
24
+
25
+ - else
26
+ = javascript_tag defer: :defer, type: "text/javascript" do
27
+ | window.the_notifications = window.the_notifications || {};
28
+ | window.the_notifications['errors'] = JSON.parse('#{ raw j _errors.to_json }');
@@ -0,0 +1,3 @@
1
+ en:
2
+ the_notification:
3
+ form_errors: "Some errors here:"
@@ -0,0 +1,3 @@
1
+ ru:
2
+ the_notification:
3
+ form_errors: "При сохранении возникли ошибки:"
@@ -0,0 +1,3 @@
1
+ module TheNotification
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'slim'
2
+ require 'the_notification/version'
3
+ require 'the_notification/config'
4
+
5
+ module TheNotification
6
+ class Engine < Rails::Engine; end
7
+ end
8
+
9
+ _root_ = File.expand_path('../../', __FILE__)
10
+
11
+ %w[ localized_errors ].each do |concern|
12
+ require "#{ _root_ }/app/models/concerns/#{ concern }.rb"
13
+ end
@@ -0,0 +1,20 @@
1
+ module TheNotification
2
+ def self.configure(&block)
3
+ yield @config ||= TheNotification::Configuration.new
4
+ end
5
+
6
+ def self.config
7
+ @config
8
+ end
9
+
10
+ # Configuration class
11
+ class Configuration
12
+ include ActiveSupport::Configurable
13
+
14
+ config_accessor :default_type
15
+ end
16
+
17
+ configure do |config|
18
+ config.default_type = :html # :json
19
+ end
20
+ end
@@ -0,0 +1 @@
1
+ require_relative '../../gem_version'
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'the_notification/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "the_notification"
8
+ spec.version = TheNotification::VERSION
9
+ spec.authors = ["Ilya N. Zykin"]
10
+ spec.email = ["zykin-ilya@ya.ru"]
11
+ spec.description = %q{notifications and alerts}
12
+ spec.summary = %q{common code for notifications and alerts}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'slim'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: the_notification
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ilya N. Zykin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: slim
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: notifications and alerts
56
+ email:
57
+ - zykin-ilya@ya.ru
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - app/assets/javascripts/the_notification.js.coffee
68
+ - app/assets/javascripts/the_notification/vendors/toastr.js
69
+ - app/assets/stylesheets/the_notification.css.scss
70
+ - app/assets/stylesheets/the_notification/vendors/toastr.css
71
+ - app/helpers/the_notification_helper.rb
72
+ - app/models/concerns/localized_errors.rb
73
+ - app/views/the_notification/_flash.html.slim
74
+ - app/views/the_notification/_form.html.slim
75
+ - config/locales/en.yml
76
+ - config/locales/ru.yml
77
+ - gem_version.rb
78
+ - lib/the_notification.rb
79
+ - lib/the_notification/config.rb
80
+ - lib/the_notification/version.rb
81
+ - the_notification.gemspec
82
+ homepage: ''
83
+ licenses:
84
+ - MIT
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 2.2.2
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: common code for notifications and alerts
106
+ test_files: []