noventius 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +22 -0
  4. data/app/assets/javascripts/nuntius/application.js +39 -0
  5. data/app/assets/javascripts/nuntius/columns.js +57 -0
  6. data/app/assets/javascripts/nuntius/filters/select.js +88 -0
  7. data/app/assets/javascripts/nuntius/filters.js +44 -0
  8. data/app/assets/javascripts/nuntius/forms.js +38 -0
  9. data/app/assets/javascripts/nuntius/nested.js +25 -0
  10. data/app/assets/javascripts/nuntius/reports.js +7 -0
  11. data/app/assets/stylesheets/nuntius/application.css +36 -0
  12. data/app/assets/stylesheets/nuntius/nested.css +8 -0
  13. data/app/assets/stylesheets/nuntius/reports.css +17 -0
  14. data/app/controllers/concerns/nuntius/filter_params.rb +23 -0
  15. data/app/controllers/nuntius/application_controller.rb +17 -0
  16. data/app/controllers/nuntius/reports_controller.rb +45 -0
  17. data/app/helpers/concerns/nuntius/filter_wrappers.rb +86 -0
  18. data/app/helpers/nuntius/alerts_helper.rb +48 -0
  19. data/app/helpers/nuntius/application_helper.rb +19 -0
  20. data/app/helpers/nuntius/cells_helper.rb +24 -0
  21. data/app/helpers/nuntius/columns_helper.rb +47 -0
  22. data/app/helpers/nuntius/filters_helper.rb +147 -0
  23. data/app/helpers/nuntius/forms_helper.rb +18 -0
  24. data/app/helpers/nuntius/rows_helper.rb +21 -0
  25. data/app/views/layouts/nuntius/application.html.erb +21 -0
  26. data/app/views/nuntius/reports/_filter.erb +10 -0
  27. data/app/views/nuntius/reports/_form.erb +26 -0
  28. data/app/views/nuntius/reports/_table.erb +21 -0
  29. data/app/views/nuntius/reports/index.erb +0 -0
  30. data/app/views/nuntius/reports/nested.erb +1 -0
  31. data/app/views/nuntius/reports/show.erb +8 -0
  32. data/app/views/shared/nuntius/_header.erb +16 -0
  33. data/config/initializers/assets.rb +1 -0
  34. data/config/routes.rb +5 -0
  35. data/lib/nuntius/column.rb +64 -0
  36. data/lib/nuntius/columns_group.rb +38 -0
  37. data/lib/nuntius/engine.rb +15 -0
  38. data/lib/nuntius/extensions/date_query.rb +62 -0
  39. data/lib/nuntius/filter.rb +46 -0
  40. data/lib/nuntius/post_processors/date_ranges.rb +120 -0
  41. data/lib/nuntius/report/dsl/columns.rb +132 -0
  42. data/lib/nuntius/report/dsl/filters.rb +50 -0
  43. data/lib/nuntius/report/dsl/nested.rb +66 -0
  44. data/lib/nuntius/report/dsl/post_processors.rb +40 -0
  45. data/lib/nuntius/report/dsl/validations.rb +40 -0
  46. data/lib/nuntius/report/dsl.rb +42 -0
  47. data/lib/nuntius/report/interpolator.rb +75 -0
  48. data/lib/nuntius/report.rb +81 -0
  49. data/lib/nuntius/serializers/csv.rb +54 -0
  50. data/lib/nuntius/validation.rb +30 -0
  51. data/lib/nuntius/version.rb +5 -0
  52. data/lib/nuntius.rb +13 -0
  53. data/lib/tasks/nuntius_tasks.rake +4 -0
  54. metadata +251 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6cc617e8561a3d80508c66c26477028e6d8bf6fc
4
+ data.tar.gz: 5dc709e45a22849681cc05e2d9ae4f632f39b7f6
5
+ SHA512:
6
+ metadata.gz: 349a9fd40d315d93b23ba0bac28d3ad7fb19c5bec4901868af0ec19eff7a7c6548c774bd7efaf22437ac1d67e7f2bf4a2fa31964d8d0317590a3eb9ddac16e7f
7
+ data.tar.gz: f4f3397862a83e647b06479beaee2b17dcd84e13cf8fb59be731931fb20b10687737c1a9d3206782375e89b3d41fe66c79f7e47d3b7d21d56cf26d8dbca5524c
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Andres Pache
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Nuntius'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,39 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require jquery/dist/jquery.min
14
+ //= require bootstrap/dist/js/bootstrap.min
15
+ //= require moment/min/moment-with-locales.min
16
+ //= require moment-timezone/builds/moment-timezone-with-data.min
17
+ //= require eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min
18
+ //= require jquery-validation/dist/jquery.validate.min
19
+ //= require jquery-validation/dist/additional-methods.min
20
+ //= require select2-dist/dist/js/select2.full
21
+ //= require jquery-tablesorter
22
+ //= require moment
23
+ //= require_self
24
+ //= require nuntius/reports
25
+
26
+ var DATE_FORMAT = 'DD/MM/YYYY';
27
+ var DATETIME_FORMAT = 'DD/MM/YYYY HH:mm';
28
+
29
+ (function() {
30
+
31
+ $.validator.addMethod('date', function(value, element) {
32
+ return this.optional( element ) || moment(value, DATE_FORMAT, true).isValid();
33
+ });
34
+
35
+ $.validator.addMethod('datetime', function(value, element) {
36
+ return this.optional( element ) || moment(value, DATETIME_FORMAT, true).isValid();
37
+ });
38
+
39
+ })();
@@ -0,0 +1,57 @@
1
+ function getSorterForType(type) {
2
+ switch(type) {
3
+ case 'datetime':
4
+ case 'date':
5
+ return 'date';
6
+ break;
7
+ case 'integer':
8
+ case 'float':
9
+ return 'digit';
10
+ break;
11
+ default:
12
+ return 'text';
13
+ }
14
+ }
15
+
16
+ function addColumnsSorting(table) {
17
+ var $this = $(table);
18
+
19
+ var headers = $this.find('th').map(function(index, element) {
20
+ var $element = $(element);
21
+ var sorter;
22
+
23
+ if ($element.hasClass('column-header')) {
24
+ var type = $element.data('type');
25
+ sorter = getSorterForType(type);
26
+ } else {
27
+ sorter = false;
28
+ }
29
+
30
+ return { sorter: sorter };
31
+ });
32
+
33
+ $this.tablesorter({
34
+ theme: 'bootstrap',
35
+ widthFixed: true,
36
+ headerTemplate: '{content} {icon}',
37
+ widgets: ['uitheme'],
38
+ headers: headers
39
+ });
40
+ }
41
+
42
+ $(function() {
43
+ $.tablesorter.addParser({
44
+ id: 'date',
45
+ is: function(s) {
46
+ return false;
47
+ },
48
+ format: function(datetime) {
49
+ return moment(datetime).utc().format('x');
50
+ },
51
+ type: 'numeric'
52
+ });
53
+
54
+ $('table').each(function() {
55
+ addColumnsSorting(this);
56
+ });
57
+ });
@@ -0,0 +1,88 @@
1
+ function depedencyValue(depedency) {
2
+ return $('select.nuntius-filter#q_' + depedency).val();
3
+ }
4
+
5
+ function handleSelectChange(filter, clear) {
6
+ var filterId = $(filter).attr('id').replace('q_', '');
7
+
8
+ $('select.nuntius-filter').each(function() {
9
+ var $this = $(this);
10
+ var dependentFilters = $this.data('dependent') || [];
11
+
12
+ if (!Array.isArray(dependentFilters)) {
13
+ dependentFilters = [dependentFilters];
14
+ }
15
+
16
+ if (dependentFilters.includes(filterId)) {
17
+ if (clear) {
18
+ clearDependentSelect($this);
19
+ } else {
20
+ updateDependentSelect($this, dependentFilters);
21
+ }
22
+ }
23
+ });
24
+ }
25
+
26
+ function clearDependentSelect($filter) {
27
+ $filter.html('').select2({data: null});
28
+ $filter.prop('disabled', true);
29
+ handleSelectChange($filter, true);
30
+ }
31
+
32
+ function updateDependentSelect($filter, dependencies) {
33
+ var values = dependencies.map(depedencyValue);
34
+ var options = $filter.data('options')[values.join('_!_')];
35
+ var currentValue = $filter.data('currentValue');
36
+
37
+ if (typeof options == 'undefined') {
38
+ $filter.html('').select2({data: null});
39
+ $filter.prop('disabled', true);
40
+ return;
41
+ }
42
+
43
+ $filter.prop('disabled', false);
44
+
45
+ options = options.map(function(option) {
46
+ if (typeof option == 'object' && option.length == 2 && typeof option[1] != 'undefined') {
47
+ return { id: option[1] || '', text: option[0] }
48
+ } else {
49
+ return { id: option, text: option }
50
+ }
51
+ });
52
+
53
+ var selectOptions = { data: options };
54
+ var includeBlank = $filter.data('includeBlank');
55
+
56
+ if (includeBlank != null && typeof includeBlank != 'undefined') {
57
+ options.unshift({ id: '', text: '' });
58
+
59
+ selectOptions.allowClear = true;
60
+ selectOptions.placeholder = $filter.data('includeBlank')
61
+ }
62
+
63
+ $filter.html('').select2(selectOptions);
64
+ handleSelectChange($filter, false);
65
+
66
+ if (currentValue != null && typeof currentValue != 'undefined') {
67
+ $filter.val(currentValue).trigger('change');
68
+ }
69
+ }
70
+
71
+ $(function() {
72
+ $('select.nuntius-filter').each(function() {
73
+ var $this = $(this);
74
+
75
+ var selectOptions = {};
76
+ var includeBlank = $this.data('includeBlank');
77
+ if (includeBlank != null && includeBlank != 'undefined') {
78
+ selectOptions.allowClear = true;
79
+ selectOptions.placeholder = $this.data('includeBlank')
80
+ }
81
+
82
+ $(this).select2(selectOptions)
83
+ .on('select2:select', function() { handleSelectChange(this, false) })
84
+ .on('select2:unselect', function() { handleSelectChange(this, true) });
85
+ handleSelectChange(this, false);
86
+ })
87
+
88
+ });
@@ -0,0 +1,44 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
3
+ (function(){
4
+
5
+ $(document).on('ready page:load', function(){
6
+
7
+ // Initialize all DatePickers
8
+ $("[type='date']").each(function (index, el) {
9
+ var $el = $(el);
10
+ var filterName = $el.attr('name');
11
+
12
+ if(FILTERS[filterName]['options']['icon']) {
13
+ $el = $el.parent();
14
+ }
15
+ $el.datetimepicker({ format: DATE_FORMAT });
16
+
17
+ setDateTimePickerDate($el, FILTER_PARAMS[filterName], DATE_FORMAT);
18
+ });
19
+
20
+ // Initialize all DateTimePickers
21
+ $("[type='datetime']").each(function (index, el) {
22
+ var $el = $(el);
23
+ var filterName = $el.attr('name');
24
+
25
+ if(FILTERS[filterName]['options']['icon']) {
26
+ $el = $el.parent();
27
+ }
28
+ $el.datetimepicker({ format: DATETIME_FORMAT, sideBySide: true });
29
+
30
+ setDateTimePickerDate($el, FILTER_PARAMS[filterName], DATETIME_FORMAT);
31
+ });
32
+
33
+ });
34
+
35
+ var setDateTimePickerDate = function(el, val, format) {
36
+ if(val) {
37
+ var $el = $(el);
38
+ var date = moment(val, format);
39
+
40
+ $el.data('DateTimePicker').defaultDate(date);
41
+ }
42
+ };
43
+
44
+ })();
@@ -0,0 +1,38 @@
1
+ (function(){
2
+
3
+ var FORM_SELECTOR = '#filter-form';
4
+
5
+ function submitWithFormat(form, event, format) {
6
+ event.preventDefault();
7
+ event.stopPropagation();
8
+
9
+ form.find('input[name=format]').val(format);
10
+ form.submit();
11
+ }
12
+
13
+ $(document).on('ready page:load', function(){
14
+ var $form = $(FORM_SELECTOR);
15
+ $form.validate({
16
+ errorClass: 'has-error has-feedback',
17
+ validClass: 'has-success has-feedback',
18
+ errorPlacement: function(error, element) {
19
+ $error = $(error);
20
+ $element = $(element);
21
+ $(error).addClass('control-label');
22
+ $element.closest('.form-group').append(error);
23
+ },
24
+ rules: VALIDATIONS['rules'],
25
+ messages: VALIDATIONS['messages']
26
+ });
27
+
28
+ $form.on('click', 'input[name=commit]', function(e) {
29
+ submitWithFormat($form, e, 'html');
30
+ });
31
+
32
+ $form.on('click', '.download', function(e) {
33
+ submitWithFormat($form, e, 'csv');
34
+ });
35
+
36
+ });
37
+
38
+ })();
@@ -0,0 +1,25 @@
1
+ $(function() {
2
+ $('table').on('click', 'tr[data-nested]', function() {
3
+ var $this = $(this);
4
+ var nested = $this.data('nested');
5
+
6
+ if ($this.next('tr.nested-container').length) {
7
+ $this.siblings('tr.nested-container').remove();
8
+ return;
9
+ }
10
+
11
+ var td = $('<td>').attr('colspan', $this.find('td').length);
12
+ var tr = $('<tr>').append(td).addClass('nested-container');
13
+
14
+ $this.siblings('tr.nested-container').remove();
15
+
16
+ $this.after(tr);
17
+
18
+ var data = nested.filters;
19
+ data.row = nested.row;
20
+ $.get(nested.url, data, function(table) {
21
+ td.append(table);
22
+ addColumnsSorting(td.find('table'));
23
+ });
24
+ });
25
+ });
@@ -0,0 +1,7 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
3
+ //= require nuntius/filters
4
+ //= require nuntius/forms
5
+ //= require nuntius/columns
6
+ //= require nuntius/nested
7
+ //= require_tree ./filters
@@ -0,0 +1,36 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require bootstrap/dist/css/bootstrap.min
14
+ *= require eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min
15
+ *= require select2-dist/dist/css/select2
16
+ *= require jquery-tablesorter/theme.bootstrap
17
+ *= require_self
18
+ *= require nuntius/reports
19
+ *= require nuntius/nested
20
+ */
21
+
22
+ .navbar {
23
+ border-bottom: none;
24
+ }
25
+
26
+ .has-error.form-control {
27
+ border-color: red;
28
+ }
29
+
30
+ .has-error.form-control:focus {
31
+ border-color: red;
32
+ }
33
+
34
+ .has-error.control-label {
35
+ color: red;
36
+ }
@@ -0,0 +1,8 @@
1
+ tr[data-nested] {
2
+ cursor: pointer
3
+ }
4
+
5
+ table.nested {
6
+ border: 3px solid red !important;
7
+ margin-bottom: 0;
8
+ }
@@ -0,0 +1,17 @@
1
+ .form-inline .form-group {
2
+ padding: 5px;
3
+ position: relative;
4
+ vertical-align: bottom;
5
+ }
6
+
7
+ .form-inline label {
8
+ display: block;
9
+ }
10
+
11
+ .select-filter-wrapper {
12
+ width: 14em;
13
+ }
14
+
15
+ select.nuntius-filter {
16
+ width: 100%;
17
+ }
@@ -0,0 +1,23 @@
1
+ module Nuntius
2
+
3
+ module FilterParams
4
+
5
+ SCOPE_KEY = :q
6
+
7
+ def self.included(base)
8
+ base.helper_method :filter_params
9
+ end
10
+
11
+ def filter_params
12
+ var_name = "@#{SCOPE_KEY}"
13
+
14
+ if instance_variable_defined?(var_name)
15
+ instance_variable_get(var_name)
16
+ else
17
+ instance_variable_set(var_name, params.fetch(SCOPE_KEY, {}))
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,17 @@
1
+ module Nuntius
2
+
3
+ class ApplicationController < ActionController::Base
4
+
5
+ include FilterParams
6
+
7
+ helper_method :reports
8
+
9
+ protect_from_forgery with: :exception
10
+
11
+ def reports
12
+ @reports ||= Report.all
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,45 @@
1
+ require_dependency 'nuntius/application_controller'
2
+
3
+ module Nuntius
4
+
5
+ class ReportsController < ApplicationController
6
+
7
+ before_action :set_report, only: [:show, :nested]
8
+ before_action :set_nested_report, only: [:nested]
9
+
10
+ def index
11
+ reports
12
+ end
13
+
14
+ def show
15
+ respond_to do |format|
16
+ format.html
17
+ format.csv { render text: @report.to(:csv) }
18
+ end
19
+ end
20
+
21
+ def nested
22
+ respond_to do |format|
23
+ format.html { render layout: false }
24
+ end
25
+ end
26
+
27
+ protected
28
+
29
+ def set_report
30
+ @report ||= report_class.new(filter_params)
31
+ rescue NameError
32
+ redirect_to reports_path, alert: 'Report not found'
33
+ end
34
+
35
+ def set_nested_report
36
+ @nested_report ||= @report.build_nested_report(params[:row])
37
+ end
38
+
39
+ def report_class
40
+ params.require(:name).constantize
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,86 @@
1
+ module Nuntius
2
+
3
+ module FilterWrappers
4
+
5
+ DEFAULT_CHECK_BOX_VALUE = '1'
6
+ DEFAULT_RADIO_BUTTON_VALUE = false
7
+
8
+ def self.included(base)
9
+ base.extend self
10
+ end
11
+
12
+ def check_box_filter_tag(name, value: DEFAULT_CHECK_BOX_VALUE, checked: false, options: {})
13
+ check_box_tag(name, value, checked, options)
14
+ end
15
+
16
+ def color_filter_tag(name, value: nil, options: {})
17
+ color_field_tag(name, value, options)
18
+ end
19
+
20
+ def date_filter_tag(name, value: nil, options: {})
21
+ date_field_tag(name, value, options)
22
+ end
23
+
24
+ def datetime_filter_tag(name, value: nil, options: {})
25
+ datetime_field_tag(name, value, options)
26
+ end
27
+
28
+ def email_filter_tag(name, value: nil, options: {})
29
+ datetime_field_tag(name, value, options)
30
+ end
31
+
32
+ def month_filter_tag(name, value: nil, options: {})
33
+ month_field_tag(name, value, options)
34
+ end
35
+
36
+ def number_filter_tag(name, value: nil, options: {})
37
+ number_field_tag(name, value, options)
38
+ end
39
+
40
+ def phone_filter_tag(name, value: nil, options: {})
41
+ phone_field_tag(name, value, options)
42
+ end
43
+
44
+ def radio_button_filter_tag(name, value: DEFAULT_RADIO_BUTTON_VALUE, checked: false, options: {})
45
+ radio_button_tag(name, value, checked, options)
46
+ end
47
+
48
+ def range_filter_tag(name, value: nil, options: {})
49
+ range_field_tag(name, value, options)
50
+ end
51
+
52
+ def search_filter_tag(name, value: nil, options: {})
53
+ search_field_tag(name, value, options)
54
+ end
55
+
56
+ def select_filter_tag(name, option_tags: nil, options: {})
57
+ select_tag(name, option_tags, options)
58
+ end
59
+
60
+ def telephone_filter_tag(name, value: nil, options: {})
61
+ text_field_tag(name, value, options)
62
+ end
63
+
64
+ def text_area_filter_tag(name, content: nil, options: {})
65
+ text_area_tag(name, content, options)
66
+ end
67
+
68
+ def text_filter_tag(name, value: nil, options: {})
69
+ text_field_tag(name, value, options)
70
+ end
71
+
72
+ def time_filter_tag(name, value: nil, options: {})
73
+ time_field_tag(name, value, options)
74
+ end
75
+
76
+ def url_filter_tag(name, value: nil, options: {})
77
+ url_field_tag(name, value, options)
78
+ end
79
+
80
+ def week_filter_tag(name, value: nil, options: {})
81
+ week_field_tag(name, value, options)
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,48 @@
1
+ module Nuntius
2
+
3
+ module AlertsHelper
4
+
5
+ ALERT_TYPES = [:success, :info, :warning, :danger] unless const_defined?(:ALERT_TYPES)
6
+
7
+ def flash_alert(options = {})
8
+ flash_messages = []
9
+ flash.each do |type, message|
10
+ # Skip empty messages, e.g. for devise messages set to nothing in a locale file.
11
+ next if message.blank?
12
+
13
+ type = transform_type(type)
14
+
15
+ next unless ALERT_TYPES.include?(type)
16
+
17
+ tag_options = options_for_type(options, type)
18
+
19
+ close_button = content_tag(:button, raw('&times;'),
20
+ type: 'button',
21
+ class: 'close',
22
+ 'data-dismiss' => 'alert')
23
+
24
+ Array(message).each do |msg|
25
+ text = content_tag(:div, close_button + msg, tag_options)
26
+ flash_messages << text if msg
27
+ end
28
+ end
29
+ flash_messages.join("\n").html_safe
30
+ end
31
+
32
+ def transform_type(type)
33
+ case type
34
+ when :notice then :success
35
+ when :alert, :error then :danger
36
+ else type
37
+ end
38
+ end
39
+
40
+ def options_for_type(options, type)
41
+ tag_class = options.extract!(:class)[:class]
42
+
43
+ { class: "alert fade in alert-#{type} #{tag_class}" }.merge(options)
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,19 @@
1
+ module Nuntius
2
+
3
+ module ApplicationHelper
4
+
5
+ SCOPE_KEY = Nuntius::FilterParams::SCOPE_KEY
6
+
7
+ def scope_name(name)
8
+ "#{SCOPE_KEY}[#{name}]"
9
+ end
10
+
11
+ def scope_keys(params)
12
+ Hash[*params.flat_map do |k, v|
13
+ [scope_name(k), v]
14
+ end]
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,24 @@
1
+ module Nuntius
2
+
3
+ module CellsHelper
4
+
5
+ def cell_tag(value)
6
+ content_tag(:td, format_value(value))
7
+ end
8
+
9
+ def format_value(value)
10
+ case value
11
+ when Date, DateTime, Time
12
+ l(value, format: :long)
13
+ else
14
+ value
15
+ end
16
+ end
17
+
18
+ def cell_for_row_column(report, row, column)
19
+ column.value(report, row)
20
+ end
21
+
22
+ end
23
+
24
+ end