kuppayam 0.1.5 → 0.1.6dev2

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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -0
  3. data/app/assets/images/{kuppayam/favicon.png → favicon.png} +0 -0
  4. data/app/assets/images/{kuppayam/logo.png → logo.png} +0 -0
  5. data/app/assets/javascripts/kuppayam.js +3 -0
  6. data/app/assets/javascripts/kuppayam/utilities.js +28 -0
  7. data/app/assets/stylesheets/kuppayam.css +1 -0
  8. data/app/assets/stylesheets/kuppayam/custom.css +4 -0
  9. data/app/controllers/kuppayam/base_controller.rb +14 -4
  10. data/app/controllers/kuppayam/documents_controller.rb +24 -0
  11. data/app/controllers/kuppayam/images_controller.rb +41 -1
  12. data/app/helpers/breadcrumbs_helper.rb +1 -1
  13. data/app/helpers/filter_helper.rb +9 -3
  14. data/app/helpers/image_helper.rb +11 -3
  15. data/app/helpers/kuppayam_helper.rb +2 -2
  16. data/app/helpers/meta_tags_helper.rb +0 -4
  17. data/app/helpers/notification_helper.rb +6 -6
  18. data/app/helpers/render_helper.rb +11 -2
  19. data/app/helpers/resource_helper.rb +23 -9
  20. data/app/models/document/base.rb +13 -15
  21. data/app/models/document/import_data_file.rb +14 -0
  22. data/app/models/document/import_report_file.rb +8 -0
  23. data/app/models/image/base.rb +12 -14
  24. data/app/models/import_data.rb +19 -2
  25. data/app/models/kuppayam/application_record.rb +3 -0
  26. data/app/uploaders/document_uploader.rb +4 -4
  27. data/app/uploaders/image_uploader.rb +1 -1
  28. data/app/uploaders/import_data_uploader.rb +15 -0
  29. data/app/views/kuppayam/documents/create.html.erb +1 -1
  30. data/app/views/kuppayam/documents/edit.js.erb +1 -1
  31. data/app/views/kuppayam/documents/new.js.erb +1 -1
  32. data/app/views/kuppayam/documents/update.html.erb +1 -1
  33. data/app/views/kuppayam/filters/_display_dropdown_filters.html.erb +11 -0
  34. data/app/views/kuppayam/filters/_display_filters.html.erb +29 -0
  35. data/app/views/kuppayam/http_status/404.html.erb +1 -0
  36. data/app/views/kuppayam/images/_form.html.erb +1 -1
  37. data/app/views/kuppayam/images/_index.html.erb +17 -20
  38. data/app/views/kuppayam/images/_show.html.erb +32 -0
  39. data/app/views/kuppayam/images/create.html.erb +4 -4
  40. data/app/views/kuppayam/images/crop.html.erb +1 -1
  41. data/app/views/kuppayam/images/destroy.js.erb +19 -0
  42. data/app/views/kuppayam/images/edit.js.erb +3 -3
  43. data/app/views/kuppayam/images/index.html.erb +8 -1
  44. data/app/views/kuppayam/images/new.js.erb +1 -1
  45. data/app/views/kuppayam/images/update.html.erb +5 -5
  46. data/app/views/kuppayam/import_data/new.js.erb +1 -1
  47. data/app/views/kuppayam/import_data/update.html.erb +1 -1
  48. data/app/views/kuppayam/workflows/parrot/create.js.erb +11 -6
  49. data/app/views/kuppayam/workflows/parrot/edit.js.erb +1 -1
  50. data/app/views/kuppayam/workflows/parrot/new.js.erb +2 -2
  51. data/app/views/kuppayam/workflows/parrot/row.js.erb +1 -1
  52. data/app/views/kuppayam/workflows/parrot/update.js.erb +10 -5
  53. data/app/views/kuppayam/workflows/peacock/create.js.erb +12 -7
  54. data/app/views/kuppayam/workflows/peacock/edit.js.erb +2 -2
  55. data/app/views/kuppayam/workflows/peacock/new.js.erb +2 -2
  56. data/app/views/kuppayam/workflows/peacock/row.js.erb +1 -1
  57. data/app/views/kuppayam/workflows/peacock/update.js.erb +11 -6
  58. data/app/views/layouts/kuppayam/_footer.html.erb +1 -0
  59. data/app/views/layouts/kuppayam/_head.html.erb +11 -2
  60. data/app/views/layouts/kuppayam/_heading.html.erb +11 -2
  61. data/app/views/layouts/kuppayam/_horizontal_menu.html.erb +932 -0
  62. data/app/views/layouts/kuppayam/_sidebar.html.erb +5 -2
  63. data/app/views/layouts/kuppayam/admin.html.erb +63 -6
  64. data/app/views/layouts/kuppayam/blank.html.erb +62 -5
  65. data/app/views/layouts/kuppayam/document_upload.html.erb +3 -2
  66. data/app/views/layouts/kuppayam/image_upload.html.erb +3 -2
  67. data/app/views/layouts/kuppayam/layout_horizontal_menu.html.erb +116 -0
  68. data/app/views/layouts/kuppayam/print_a4.html.erb +32 -0
  69. data/app/views/layouts/kuppayam/user.html.erb +120 -0
  70. data/config/initializers/importer.rb +303 -0
  71. data/config/initializers/validators.rb +78 -0
  72. data/config/locales/kuppayam/general.yml +1 -0
  73. data/config/routes.rb +1 -1
  74. data/db/migrate/20170000000000_create_images.rb +1 -0
  75. data/db/migrate/20170000000001_create_documents.rb +2 -1
  76. data/db/migrate/20170000000002_create_import_data.rb +2 -2
  77. data/lib/kuppayam/action_view/form_helper.rb +1 -1
  78. data/lib/kuppayam/action_view/theme_helper.rb +8 -2
  79. data/lib/kuppayam/engine.rb +2 -0
  80. data/lib/kuppayam/version.rb +1 -1
  81. data/lib/tasks/template.rake +72 -0
  82. data/lib/tasks/test_import.rake +40 -0
  83. data/vendor/assets/stylesheets/custom.css +0 -0
  84. metadata +76 -16
  85. data/app/views/kuppayam/images/_action_buttons.html.erb +0 -14
  86. data/app/views/layouts/kuppayam/_overlays.html.erb +0 -47
  87. data/config/initializers/kuppayam_validators.rb +0 -76
  88. data/lib/tasks/kuppayam_tasks.rake +0 -4
@@ -0,0 +1,303 @@
1
+ # require 'axlsx'
2
+ require 'colorized_string'
3
+ # require 'roo'
4
+ require 'benchmark'
5
+ require 'iconv'
6
+
7
+ module Kuppayam
8
+
9
+ module Importer
10
+
11
+ class ErrorHash
12
+
13
+ attr_accessor :warnings,
14
+ :errors
15
+
16
+ def initialize
17
+ @warnings = []
18
+ @errors = []
19
+ end
20
+
21
+ def warnings?
22
+ @warnings.any?
23
+ end
24
+
25
+ def errors?
26
+ @errors.any?
27
+ end
28
+
29
+ def print_dot
30
+ if self.warnings?
31
+ print ".".yellow
32
+ elsif self.errors?
33
+ print ".".red
34
+ else
35
+ print ".".green
36
+ end
37
+ end
38
+
39
+ def print_all
40
+ self.warnings.each do |item|
41
+ puts "Summary: #{item[:summary]}".yellow
42
+ puts "Details: #{item[:details]}".yellow if item[:details]
43
+ puts "Stack Trace: #{item[:stack_trace]}".yellow if item[:stack_trace]
44
+ puts ""
45
+ end
46
+ self.errors.each do |item|
47
+ puts "Summary: #{item[:summary]}".red
48
+ puts "Details: #{item[:details]}".red if item[:details]
49
+ puts "Stack Trace: #{item[:stack_trace]}".red if item[:stack_trace]
50
+ puts ""
51
+ end
52
+ end
53
+ end
54
+
55
+ class DataError
56
+ attr_accessor :errors, :columns
57
+
58
+ def initialize
59
+ @errors = {}
60
+ @columns = []
61
+ end
62
+
63
+ def add_column_error(name, value, errors, row_number)
64
+ if @errors[row_number].blank?
65
+ @errors[row_number] = {
66
+ name => { value: value, errors: errors }
67
+ }
68
+ else
69
+ @errors[row_number][name] = { value: value, errors: errors }
70
+ end
71
+ end
72
+
73
+ def generate_error_file
74
+
75
+ axlsx_package = Axlsx::Package.new
76
+ wb = axlsx_package.workbook
77
+
78
+ normal_cell = s.add_style :bg_color => "FFFFFF", :fg_color => "4B4B4B", :sz => 14, :alignment => { :horizontal=> :center }
79
+ error_cell = s.add_style :bg_color => "FFE2E2", :fg_color => "4B4B4B", :sz => 14, :alignment => { :horizontal=> :center }
80
+
81
+ wb.add_worksheet(:name => "Errors") do |sheet|
82
+
83
+ sheet.add_row self.columns
84
+
85
+ self.errors.each do |row_number, values|
86
+ row_data = self.columns.map{|col| values[col][:value] }
87
+ sheet.add_row row_data
88
+ end
89
+
90
+ end
91
+ axlsx_package.serialize("tmp/example.xlsx")
92
+ end
93
+ end
94
+
95
+ def clean_string(str, label=nil)
96
+ begin
97
+ cleaned_str = str.gsub(/\r/, "").gsub(/\n/, "").squeeze(" ")
98
+ cleaned_str = Iconv.conv('UTF-8', 'ISO-8859-1//TRANSLIT//IGNORE', cleaned_str)
99
+ rescue Exception => e
100
+ puts "Error while cleaning #{label ? label : 'string'} '#{str}' - #{e.message}".red
101
+ end
102
+ end
103
+
104
+ def check_file_type_and_import(path, single_transaction=true, verbose=true)
105
+ if File.exists?(path)
106
+ if File.extname(path) == ".csv"
107
+ puts "CSV file found at '#{path.to_s}'.".green if verbose
108
+ self.import_from_csv(path.to_s, single_transaction, verbose)
109
+ elsif File.extname(path) == ".xlsx"
110
+ puts "XSLX file found at '#{path.to_s}'.".green if verbose
111
+ self.import_from_xslx(path.to_s, single_transaction, verbose)
112
+ else
113
+ puts "Unsupported File encountered'#{path.to_s}'.".red if verbose
114
+ return
115
+ end
116
+ else
117
+ puts "Import File not found at '#{path.to_s}'.".red if verbose
118
+ end
119
+ end
120
+
121
+ def import_from_sql(sql_path, verbose=true)
122
+
123
+ errors = []
124
+
125
+ print_memory_usage do
126
+ print_time_spent do
127
+ sum = 0
128
+
129
+ CSV.foreach(csv_path, headers: true, header_converters: :symbol) do |row|
130
+ obj, error_object = save_row_data(row)
131
+ errors << error_object if error_object
132
+ error_object.print_dot if error_object && verbose
133
+ sum += 1
134
+ end
135
+
136
+ puts "Sum: #{sum}"
137
+ end
138
+ end
139
+
140
+ if verbose
141
+ puts ""
142
+ errors.each do |error_object|
143
+ error_object.print_all if error_object
144
+ end
145
+ end
146
+ end
147
+
148
+ def import_from_csv(csv_path, single_transaction=true, verbose=true)
149
+ errors = []
150
+ sum = 0
151
+
152
+ # , encoding: 'windows-1251:utf-8', :row_sep => :auto
153
+ if single_transaction
154
+ ActiveRecord::Base.transaction do
155
+ CSV.foreach(csv_path, headers: true, header_converters: :symbol, skip_blanks: true) do |row|
156
+ obj, error_object = save_row_data(row)
157
+ errors << error_object if error_object
158
+ error_object.print_dot if error_object && verbose
159
+ sum += 1
160
+ end
161
+ end
162
+ else
163
+ CSV.foreach(csv_path, headers: true, header_converters: :symbol, skip_blanks: true) do |row|
164
+ obj, error_object = save_row_data(row)
165
+ errors << error_object if error_object
166
+ error_object.print_dot if error_object && verbose
167
+ sum += 1
168
+ end
169
+ end
170
+ puts "\tScanned #{sum} rows".yellow
171
+
172
+ if verbose
173
+ puts ""
174
+ errors.each do |error_object|
175
+ error_object.print_all if error_object
176
+ end
177
+ end
178
+ end
179
+
180
+ def import_from_xslx(xlsx_path, single_transaction = true, verbose=true)
181
+ xlsx = Roo::Spreadsheet.open(xlsx_path, extension: :xlsx)
182
+ sheet = xlsx.sheet(0)
183
+ headers = sheet.row(1)
184
+
185
+ errors = []
186
+ if single_transaction
187
+ ActiveRecord::Base.transaction do
188
+ 2.upto(xlsx.last_row) do |line|
189
+ row_hash = ActiveSupport::HashWithIndifferentAccess[headers.zip(xlsx.row(line))]
190
+ obj, error_object = save_row_data(row_hash)
191
+ errors << error_object if error_object
192
+ error_object.print_dot if error_object && verbose
193
+ end
194
+ end
195
+ else
196
+ 2.upto(xlsx.last_row) do |line|
197
+ row_hash = ActiveSupport::HashWithIndifferentAccess[headers.zip(xlsx.row(line))]
198
+ obj, error_object = save_row_data(row_hash)
199
+ errors << error_object if error_object
200
+ error_object.print_dot if error_object && verbose
201
+ end
202
+ end
203
+
204
+ if verbose
205
+ puts ""
206
+ errors.each do |error_object|
207
+ error_object.print_all if error_object
208
+ end
209
+ end
210
+ end
211
+
212
+ def walk_and_import(start, single_transaction=true, verbose=true)
213
+ puts "Importing Files from the Folder '#{start.to_s}'".yellow if verbose
214
+ Dir.foreach(start) do |x|
215
+ next if x.starts_with?("master")
216
+ next unless x.ends_with?(".csv")
217
+ path = File.join(start, x)
218
+ if x == "." or x == ".."
219
+ next
220
+ elsif File.directory?(path)
221
+ self.walk_and_import(path, single_transaction, verbose)
222
+ else
223
+ self.check_file_type_and_import(path, single_transaction, verbose)
224
+ end
225
+ end
226
+ end
227
+
228
+ def import_data_recursively(path, single_transaction=true, verbose=true)
229
+ print_memory_usage do
230
+ print_time_spent do
231
+ if Dir.exists?(path)
232
+ self.walk_and_import(path, single_transaction, verbose)
233
+ else
234
+ puts "Import Folder not found: '#{path.to_s}'.".red if verbose
235
+ end
236
+ end
237
+ end
238
+ end
239
+
240
+ def import_data_file(path, single_transaction=true, verbose=true)
241
+ print_memory_usage do
242
+ print_time_spent do
243
+ check_file_type_and_import(path, single_transaction, verbose)
244
+ end
245
+ end
246
+ end
247
+
248
+ def print_memory_usage
249
+ memory_before = `ps -o rss= -p #{Process.pid}`.to_i
250
+ yield
251
+ memory_after = `ps -o rss= -p #{Process.pid}`.to_i
252
+
253
+ puts "Memory: #{((memory_after - memory_before) / 1024.0).round(2)} MB"
254
+ end
255
+
256
+ def print_time_spent
257
+ time = Benchmark.realtime do
258
+ yield
259
+ end
260
+
261
+ puts "Time: #{time.round(2)}"
262
+ end
263
+
264
+ def csv_foreach_backup_code
265
+ # batch_size = 1000
266
+
267
+ # File.open(csv_path) do |file|
268
+ # file.lazy.drop(header_lines).each_slice(batch_size) do |lines|
269
+ # puts lines
270
+ # end
271
+ # end
272
+
273
+ # File.open(csv_path) do |file|
274
+ # binding.pry
275
+ # headers = file.first
276
+ # file.lazy.each_slice(batch_size) do |lines|
277
+ # csv_rows = CSV.parse(lines.join, write_headers: true, headers: headers)
278
+ # csv_rows.each do |row|
279
+ # error_object = save_row_data(row)
280
+ # errors << error_object if error_object
281
+ # error_object.print_dot if error_object
282
+ # sum += 1
283
+ # end
284
+ # end
285
+ # end
286
+
287
+ # rows = CSV.new(File.open(csv_path,'r'), headers: true, header_converters: :symbol).lazy.select do |row|
288
+ # end
289
+
290
+ # binding.pry
291
+
292
+ # rows.each do |row|
293
+
294
+ # error_object = save_row_data(row)
295
+ # errors << error_object if error_object
296
+ # error_object.print_dot if error_object
297
+ # sum += 1
298
+ # end
299
+ end
300
+
301
+ end
302
+
303
+ end
@@ -0,0 +1,78 @@
1
+ module Kuppayam
2
+ module Validators
3
+
4
+ def generate_validation_options(attribute, options)
5
+ {a: 1}
6
+ reg_exp = /\A[a-zA-Z1-9\-\ \(\)\.+]*\z/i
7
+ options.reverse_merge!(
8
+ presence: true,
9
+ min_length: 3,
10
+ max_length: 256,
11
+ format: reg_exp,
12
+ uniqueness: false,
13
+ mandatory: false
14
+ )
15
+
16
+ if options.has_key?(:condition_method) && !options[:condition_method].blank?
17
+ condition_proc = proc {|obj| obj.send(options[:condition_method])}
18
+ elsif options.has_key?(:mandatory) && options[:mandatory] == false
19
+ condition_proc = proc {|obj| !obj.send(attribute).blank?}
20
+ else
21
+ condition_proc = nil
22
+ end
23
+
24
+ voptions = {
25
+ presence: options[:presence],
26
+ length: { minimum: options[:min_length], maximum: options[:max_length]},
27
+ format: {:with => options[:format]}
28
+ }
29
+ voptions.merge!(uniqueness: options[:uniqueness]) if options[:uniqueness]
30
+ voptions.merge!(if: condition_proc) if condition_proc
31
+
32
+ voptions
33
+ end
34
+
35
+ def validate_string(attribute, **options)
36
+ voptions = generate_validation_options(attribute, options)
37
+ validates attribute, **voptions
38
+ end
39
+
40
+ def validate_username(attribute, **options)
41
+ reg_exp = /\A[a-zA-Z0-9\_\.]*\z/
42
+ options.merge!(mandatory: true, min_length: 3, max_length: 128, format: reg_exp, :uniqueness => {:case_sensitive => false})
43
+ voptions = generate_validation_options(attribute, options)
44
+ validates attribute, **voptions
45
+ end
46
+
47
+ def validate_email(attribute, **options)
48
+ reg_exp = /\A(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6})\z/i
49
+ options.merge!(mandatory: true, format: reg_exp, :uniqueness => {:case_sensitive => false})
50
+ voptions = generate_validation_options(attribute, options)
51
+ validates attribute, **voptions
52
+ end
53
+
54
+ # format can be either :us or :indian
55
+ def validate_phone(attribute, **options)
56
+ options.reverse_merge!(phone_format: :india)
57
+ if options[:phone_format] == :us
58
+ reg_exp = /\A[0-9]{3}[-][0-9]{3}[-][0-9]{4}\z/
59
+ length = 12
60
+ else
61
+ reg_exp = /\A[0-9]{10}\z/
62
+ length = 10
63
+ end
64
+ options.merge!(format: reg_exp, min_length: length, max_length: length)
65
+ options.reverse_merge!(numericality: true, mandatory: true, uniqueness: true)
66
+ voptions = generate_validation_options(attribute, options)
67
+ validates attribute, **voptions
68
+ end
69
+
70
+ def validate_password(attribute, **options)
71
+ reg_exp = /\A(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9!@$#&*_\.,;:])/
72
+ options.merge!(mandatory: true, format: reg_exp, min_length: 7, max_length: 256)
73
+ voptions = generate_validation_options(attribute, options)
74
+ validates attribute, **voptions
75
+ end
76
+
77
+ end
78
+ end
@@ -23,6 +23,7 @@ en:
23
23
  updated: "%{item} has been updated successfully."
24
24
  deleted: "%{item} has been deleted successfully."
25
25
  removed: "%{item} has been removed successfully."
26
+ uploaded: "%{item} has been uploaded successfully."
26
27
  no_results_found: "No results found."
27
28
  state:
28
29
  changed: "%{item} has been %{new_state}."
@@ -1,6 +1,6 @@
1
1
  Rails.application.routes.draw do
2
2
 
3
- resources :images, controller: "kuppayam/images" do
3
+ resources :images, controller: "kuppayam/images" do
4
4
  member do
5
5
  put :crop
6
6
  end
@@ -8,6 +8,7 @@ class CreateImages < ActiveRecord::Migration[5.0]
8
8
  t.timestamps
9
9
  end
10
10
 
11
+ add_index(:images, :image_type)
11
12
  add_index(:images, [ :imageable_id, :imageable_type ])
12
13
  end
13
14
  end
@@ -1,4 +1,4 @@
1
- class CreateDocuments < ActiveRecord::Migration
1
+ class CreateDocuments < ActiveRecord::Migration[5.0]
2
2
  def change
3
3
  create_table :documents do |t|
4
4
  t.string :document
@@ -8,6 +8,7 @@ class CreateDocuments < ActiveRecord::Migration
8
8
  t.timestamps
9
9
  end
10
10
 
11
+ add_index(:documents, :document_type)
11
12
  add_index(:documents, [ :documentable_id, :documentable_type ])
12
13
  end
13
14
  end
@@ -1,9 +1,9 @@
1
- class CreateImportData < ActiveRecord::Migration
1
+ class CreateImportData < ActiveRecord::Migration[5.0]
2
2
  def change
3
3
  create_table :import_data do |t|
4
4
  t.integer :importable_id
5
5
  t.string :importable_type
6
- t.string :data_type
6
+ t.string :data_type # CSV, XLSX, XLS
7
7
  t.string :status, :null => false, :default=>"pending", :limit=>16
8
8
  t.timestamps
9
9
  end
@@ -145,7 +145,7 @@ module Kuppayam
145
145
  when :text, :email, :search, :password, :date, :time, :tel, :url, :month, :number
146
146
  text_field_tag(options[:param_name], object.send(field_name.to_s), **options[:html_options])
147
147
  when :textarea
148
- options[:html_options].merge!(style: "height: 140px;")
148
+ options[:html_options].reverse_merge!(style: "height: 140px;")
149
149
  text_area_tag(options[:param_name], object.send(field_name.to_s), **options[:html_options])
150
150
  when :file
151
151
  file_field_tag(options[:param_name], **options[:html_options])
@@ -6,6 +6,8 @@ module Kuppayam
6
6
  # <i class='fa fa-plus'></i>
7
7
  # theme_fa_icon('plus', 'lg')
8
8
  # <i class='fa fa-plus fa-lg'></i>
9
+
10
+ # TBR: To Be Removed
9
11
  def theme_fa_icon(icon_text, size="")
10
12
  size_class = %w{lg 2x 3x 4x 5x}.include?(size.strip) ? " fa-#{size.strip}" : ""
11
13
  "<i class='fa fa-#{icon_text}#{size_class}'></i>"
@@ -13,8 +15,10 @@ module Kuppayam
13
15
 
14
16
  # theme_button_text('New Project')
15
17
  # <span class='btn-text'> New Project</span>
18
+
19
+ # TBR: To Be Removed
16
20
  def theme_button_text(text)
17
- "<span class='btn-text'> #{text}</span>"
21
+ "<span class='btn-text hidden-sm hidden-xs'> #{text}</span>"
18
22
  end
19
23
 
20
24
  # theme_button is used to create buttons which has built in classes and icons
@@ -24,6 +28,8 @@ module Kuppayam
24
28
  # link_to raw("<i class='fa fa-plus mr-10'></i><span class='btn-text'> New Project</span>"), new_admin_project_path, :class=>"btn btn-primary pull-right ml-5", :remote=>true
25
29
  # And produces the following html
26
30
  # <a class="btn btn-primary pull-right ml-5" data-remote="true" href="/admin/projects/new"><i class="fa fa-plus mr-10"></i><span class="btn-text"> New Project</span></a>
31
+
32
+ # TBR: To Be Removed
27
33
  def theme_button(text, icon, url, options={})
28
34
  options.reverse_merge!(
29
35
  method: :get,
@@ -130,7 +136,7 @@ module Kuppayam
130
136
  # "No Results found"
131
137
  # </div>
132
138
  def theme_panel_message(message)
133
- content_tag(:div, class: "panel panel-default panel-message text-color-grey p-80 text-align-center", style: "height:200px;") do
139
+ content_tag(:div, class: "panel panel-default panel-message text-color-grey p-80 text-align-center", style: "height:200px;width:100%;") do
134
140
  raw(message)
135
141
  end
136
142
  end