kuppayam 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +27 -4
  3. data/app/assets/javascripts/kuppayam/utilities.js +110 -5
  4. data/app/assets/javascripts/kuppayam.js +4 -0
  5. data/app/assets/stylesheets/kuppayam/custom.css +48 -1
  6. data/app/assets/stylesheets/kuppayam.css +1 -0
  7. data/app/assets/stylesheets/wysiwyg-color.css +15 -0
  8. data/app/controllers/kuppayam/base_controller.rb +24 -3
  9. data/app/controllers/kuppayam/documents_controller.rb +104 -0
  10. data/app/controllers/kuppayam/images_controller.rb +104 -0
  11. data/app/controllers/kuppayam/import_data_controller.rb +34 -0
  12. data/app/controllers/kuppayam/resource_controller.rb +9 -0
  13. data/app/helpers/breadcrumbs_helper.rb +32 -15
  14. data/app/helpers/document_helper.rb +40 -0
  15. data/app/helpers/flash_helper.rb +0 -8
  16. data/app/helpers/image_helper.rb +57 -88
  17. data/app/helpers/notification_helper.rb +41 -0
  18. data/app/helpers/render_helper.rb +44 -5
  19. data/app/helpers/resource_helper.rb +107 -52
  20. data/app/models/document/base.rb +43 -0
  21. data/app/models/image/base.rb +52 -0
  22. data/app/models/import_data.rb +20 -0
  23. data/app/models/kuppayam/application_record.rb +5 -0
  24. data/app/uploaders/document_uploader.rb +15 -0
  25. data/app/uploaders/image_uploader.rb +90 -0
  26. data/app/views/kuppayam/documents/_crop_form.html.erb +44 -0
  27. data/app/views/kuppayam/documents/_form.html.erb +47 -0
  28. data/app/views/kuppayam/documents/_new.html.erb +9 -0
  29. data/app/views/kuppayam/documents/_photos.html.erb +16 -0
  30. data/app/views/kuppayam/documents/create.html.erb +14 -0
  31. data/app/views/kuppayam/documents/crop.html.erb +9 -0
  32. data/app/views/kuppayam/documents/edit.js.erb +7 -0
  33. data/app/views/kuppayam/documents/new.js.erb +7 -0
  34. data/app/views/kuppayam/documents/update.html.erb +14 -0
  35. data/app/views/kuppayam/images/_action_buttons.html.erb +14 -0
  36. data/app/views/kuppayam/images/_crop_form.html.erb +44 -0
  37. data/app/views/kuppayam/images/_form.html.erb +56 -0
  38. data/app/views/kuppayam/images/_index.html.erb +49 -0
  39. data/app/views/kuppayam/images/_new.html.erb +9 -0
  40. data/app/views/kuppayam/images/_photos.html.erb +16 -0
  41. data/app/views/kuppayam/images/_row.html.erb +65 -0
  42. data/app/views/kuppayam/images/create.html.erb +38 -0
  43. data/app/views/kuppayam/images/crop.html.erb +9 -0
  44. data/app/views/kuppayam/images/edit.js.erb +8 -0
  45. data/app/views/kuppayam/images/index.html.erb +26 -0
  46. data/app/views/kuppayam/images/new.js.erb +8 -0
  47. data/app/views/kuppayam/images/update.html.erb +38 -0
  48. data/app/views/kuppayam/import_data/_form.html.erb +38 -0
  49. data/app/views/kuppayam/import_data/_new.html.erb +9 -0
  50. data/app/views/kuppayam/import_data/_photos.html.erb +16 -0
  51. data/app/views/kuppayam/import_data/create.html.erb +14 -0
  52. data/app/views/kuppayam/import_data/crop.html.erb +9 -0
  53. data/app/views/kuppayam/import_data/edit.js.erb +7 -0
  54. data/app/views/kuppayam/import_data/new.js.erb +11 -0
  55. data/app/views/kuppayam/import_data/update.html.erb +14 -0
  56. data/app/views/kuppayam/workflows/parrot/_info.html.erb +15 -0
  57. data/app/views/kuppayam/workflows/parrot/create.js.erb +36 -0
  58. data/app/views/kuppayam/workflows/parrot/destroy.js.erb +22 -0
  59. data/app/views/kuppayam/workflows/parrot/edit.js.erb +10 -0
  60. data/app/views/kuppayam/workflows/parrot/index.js.erb +14 -0
  61. data/app/views/kuppayam/workflows/parrot/new.js.erb +9 -0
  62. data/app/views/kuppayam/workflows/parrot/row.js.erb +24 -0
  63. data/app/views/kuppayam/workflows/parrot/show.js.erb +13 -0
  64. data/app/views/kuppayam/workflows/parrot/update.js.erb +34 -0
  65. data/app/views/kuppayam/workflows/peacock/_info.html.erb +15 -0
  66. data/app/views/kuppayam/workflows/peacock/create.js.erb +36 -0
  67. data/app/views/kuppayam/workflows/peacock/destroy.js.erb +22 -0
  68. data/app/views/kuppayam/workflows/peacock/edit.js.erb +10 -0
  69. data/app/views/kuppayam/workflows/peacock/index.js.erb +14 -0
  70. data/app/views/kuppayam/workflows/peacock/new.js.erb +9 -0
  71. data/app/views/kuppayam/workflows/peacock/row.js.erb +24 -0
  72. data/app/views/kuppayam/workflows/peacock/show.js.erb +13 -0
  73. data/app/views/kuppayam/workflows/peacock/update.js.erb +34 -0
  74. data/app/views/layouts/kuppayam/_heading.html.erb +4 -4
  75. data/app/views/layouts/kuppayam/_navbar.html.erb +1 -1
  76. data/app/views/layouts/kuppayam/_overlays.html.erb +7 -0
  77. data/app/views/layouts/kuppayam/_sidebar.html.erb +19 -1
  78. data/app/views/layouts/kuppayam/admin.html.erb +4 -0
  79. data/app/views/layouts/kuppayam/document_upload.html.erb +16 -0
  80. data/app/views/layouts/kuppayam/image_upload.html.erb +16 -0
  81. data/config/initializers/inflections.rb +3 -0
  82. data/config/locales/kuppayam/general.yml +29 -0
  83. data/config/routes.rb +15 -0
  84. data/db/migrate/20170000000000_create_images.rb +13 -0
  85. data/db/migrate/20170000000001_create_documents.rb +13 -0
  86. data/db/migrate/20170000000002_create_import_data.rb +14 -0
  87. data/lib/kuppayam/action_view/form_helper.rb +23 -4
  88. data/lib/kuppayam/action_view/theme_helper.rb +2 -2
  89. data/lib/kuppayam/engine.rb +11 -14
  90. data/lib/kuppayam/version.rb +1 -1
  91. metadata +75 -13
@@ -0,0 +1,40 @@
1
+ module DocumentHelper
2
+
3
+ # Returns new associated url or edit existing associated url based on object is associated with associated or not
4
+ # @example Basic Usage - User without Image
5
+ # >>> upload_document_link(@user, :profile_picture, :admin)
6
+ # "/admin/documents/new"
7
+ #
8
+ # @example Basic Usage - User with Iamge
9
+ #
10
+ # >>> upload_document_link(@user_with_document, :profile_picture, :admin)
11
+ # "/admin/documents/1/edit"
12
+ #
13
+ # @example Basic Usage - Custom Scope
14
+ #
15
+ # >>> upload_document_link(@project, :profile_picture, :customer)
16
+ # "/customer/documents/new"
17
+ # >>> upload_document_link(@project_with_document, :profile_picture, :customer)
18
+ # "/customer/documents/1/edit"
19
+ def upload_document_link(object, assoc_name=:associated, scope=:admin, **options)
20
+ associated_object = nil
21
+ associated_object = object.send(assoc_name) if object.respond_to?(assoc_name)
22
+ if associated_object.present? && associated_object.persisted?
23
+ main_app.url_for([:edit, scope, :document, id: associated_object.id, documentable_id: object.id, documentable_type: object.class.to_s, document_type: associated_object.class.name])
24
+ else
25
+ associated_object = object.send("build_#{assoc_name}")
26
+ main_app.url_for([:new, scope, :document, documentable_id: object.id, documentable_type: object.class.to_s, document_type: associated_object.class.name])
27
+ end
28
+ end
29
+
30
+ def import_data_link(object, class_name, assoc_name=:associated, scope=nil, **options)
31
+ if object.present?
32
+ #main_app.url_for([:edit, scope, :import_data, data_type: class_name])
33
+ edit_import_data_url(object, data_type: class_name)
34
+ else
35
+ #main_app.url_for([:new, scope, :import_data, data_type: class_name])
36
+ new_import_data_url(data_type: class_name)
37
+ end
38
+ end
39
+
40
+ end
@@ -43,12 +43,4 @@ module FlashHelper
43
43
  raw(link_to("×", "#", class: "close", "data-dismiss" => "alert") + content_tag(:p, message))
44
44
  end unless message.blank?
45
45
  end
46
-
47
- def set_notification_messages(id, alert_type, now_type=false)
48
- @heading = I18n.t("#{id}.heading")
49
- @message = I18n.t("#{id}.message")
50
- @alert ||= "#{@heading}: #{@message}"
51
- @alert_type = alert_type
52
- set_flash_message(@alert, alert_type, now_type) if defined?(flash) && flash
53
- end
54
46
  end
@@ -29,10 +29,10 @@ module ImageHelper
29
29
  # image_url is a helper method which can be used along with carrier_wave gem
30
30
  # Suppose, you have an object 'user' which has a profile_picture
31
31
  # image_url will return you the system default image url if profile_picture is not set else it will return you the carrier wave url
32
- # the convention is that the there is a folder named defaults in /assets which has user-medium.png file
33
- # user-medium => user is the class name and medium is the size name
32
+ # the convention is that the there is a folder named defaults in /assets which has user-small.png file
33
+ # user-small => user is the class name and small is the size name
34
34
  # for e.g: if the class name is JackFruit, then:
35
- # the filename which it expect would be /assets/defaults/jackfruit-medium.png
35
+ # the filename which it expect would be /assets/defaults/jackfruit-small.png
36
36
  #
37
37
  # @example Basic Usage without Image
38
38
  #
@@ -77,106 +77,66 @@ module ImageHelper
77
77
  # >>> display_image(user_with_image, 'profile_picture.image.large.url', width: "30px", height: "50px", size: "small")
78
78
  # "<img class=\"\" width=\"30px\" height=\"50px\" src=\"/spec/dummy/uploads/image/profile_picture/1/large_test.jpg\" alt=\"Large test\" />"
79
79
  def display_image(object, method_name, **options)
80
- options.reverse_merge!(size: "small")
80
+ options.reverse_merge!(size: "large")
81
81
  options.reverse_merge!(
82
82
  width: "100%",
83
83
  height: "auto",
84
84
  place_holder: {},
85
- class: object.persisted? ? "#{object.id}-#{options[:size]}-image" : ""
85
+ class: ""
86
86
  )
87
87
 
88
+ options[:class] = options[:class] + (object.persisted? ? " #{object.id}-#{options[:size]}-image" : "")
89
+
88
90
  img_url = image_url(object, method_name, **options)
89
91
  return image_tag(img_url, class: options[:class], width: options[:width], height: options[:height])
90
92
  end
91
93
 
92
- # @example Basic Usage
93
- #
94
- # >>> display_user_image(@user, 'profile_picture.image.thumb.url')
95
- # "<div><div class="rounded" style="width:60px;height:60px;"><img alt="Thumb krishnan" class="" src="/uploads/image/profile_picture/39/thumb_krishnan.jpg" style="width:100%;height:auto;cursor:default;"></div></div>"
96
- #
97
- # @example Advanced Usage with
98
- #
99
- # >>> display_user_image(@user, 'profile_picture.image.thumb.url', width: 100px, height: 100px)
100
- # "<div><div class="rounded" style="width:100px;height:60px;"><img alt="Thumb krishnan" class="" src="/uploads/image/profile_picture/39/thumb_krishnan.jpg" style="width:100%;height:auto;cursor:default;"></div></div>"
101
- def display_user_image(user, method_name, **options)
102
-
103
- url_domain = defined?(QAuthRubyCustomer) ? QAuthRubyCustomer.configuration.q_auth_url : ""
104
-
105
- options.reverse_merge!(
106
- width: "60px",
107
- height: "auto",
108
- size: "medium",
109
- url_domain: url_domain,
110
- place_holder: {},
111
- html_options: {}
112
- )
113
-
114
- options[:html_options].reverse_merge!(
115
- style: "width:100%;height:auto;cursor:#{options.has_key?(:popover) ? "pointer" : "default"};",
116
- class: user.persisted? ? "#{user.id}-#{options[:size]}-image" : ""
117
- )
118
-
119
- if user.respond_to?(:name)
120
- options[:place_holder].reverse_merge!(text: namify(user.name))
121
- end
122
-
123
- options[:html_options].reverse_merge!(
124
- "data-toggle" => "popover",
125
- "data-placement" => "bottom",
126
- "title" => user.name,
127
- "data-content" => options[:popover] === true ? "" : options[:popover].to_s
128
- ) if options[:popover]
129
-
130
- begin
131
- image_path = user.send(:eval, method_name)
132
- if image_path.starts_with?(:http)
133
- url = image_path
134
- else
135
- url = options[:url_domain] + image_path
136
- end
137
- rescue
138
- url = image_url(user, method_name, **options)
139
- end
140
-
141
- content_tag(:div) do
142
- content_tag(:div, class: "rounded", style: "width:#{options[:width]};height:#{options[:height]}") do
143
- image_tag(url, options[:html_options])
144
- end
145
- end
146
- end
147
-
148
94
  # Displays the image with a edit button below it
149
95
  # @example Basic Usage
150
96
  # >>> edit_image(@project, "logo.image.url", edit_url, width: "100px", height: "auto")
151
97
  # ""
152
- def edit_image(object, method_name, edit_url, **options)
98
+ def edit_image(object, method_name, edit_url, delete_url, **options)
153
99
  options.reverse_merge!(
100
+ image_options: {},
101
+ edit_options: {},
102
+ delete_options: {}
103
+ )
104
+
105
+ # options[:image_options].reverse_merge!()
106
+ options[:edit_options].reverse_merge!(
154
107
  remote: true,
155
108
  text: "Change Image",
156
109
  icon: "photo",
157
- classes: "btn btn-white btn-block btn-xs mt-10"
110
+ class: "btn btn-primary btn-block btn-only-hover btn-xs",
158
111
  )
159
- img_tag = display_image(object, method_name, **options)
160
- btn_display = raw(theme_fa_icon(options[:icon]) + theme_button_text(options[:text]))
161
- link_to(img_tag, edit_url, :remote => options[:remote]) +
162
- link_to(btn_display, edit_url, :class=>options[:classes], :remote=>options[:remote])
163
- end
164
112
 
165
- # Displays the user image in a rounded frame with a edit button below it
166
- # @example Basic Usage
167
- # >>> edit_user_image(@project, "logo.image.url", edit_url, width: "100px", height: "auto")
168
- # ""
169
- def edit_user_image(object, method_name, edit_url, **options)
170
- options.reverse_merge!(
113
+ options[:delete_options].reverse_merge!(
171
114
  remote: true,
172
- text: "Change Image",
173
- icon: "photo",
174
- classes: "btn btn-default btn-xs mt-10"
115
+ text: "Remove Image",
116
+ icon: "trash",
117
+ class: "btn btn-danger btn-block btn-only-hover btn-xs"
175
118
  )
176
- img_tag = display_user_image(object, method_name, **options)
177
- btn_display = raw(theme_fa_icon(options[:icon]) + theme_button_text(options[:text]))
178
- link_to(img_tag, edit_url, :remote => options[:remote]) +
179
- link_to(btn_display, edit_url, :class=>options[:classes], :remote=>options[:remote])
119
+
120
+ # Image HTML
121
+ image_tag = display_image(object, method_name, **options[:image_options])
122
+
123
+ # Edit Button
124
+ edit_btn_display = raw(theme_fa_icon(options[:edit_options][:icon]) + theme_button_text(options[:edit_options][:text]))
125
+ edit_btn = link_to(edit_btn_display, edit_url, :class=>options[:edit_options][:class], :remote=>options[:edit_options][:remote])
126
+
127
+ # Remove Button (only if the object is persisted)
128
+ assoc_name = options[:image_options][:assoc_name]
129
+ image_object = nil
130
+ image_object = object.send(assoc_name) if object.respond_to?(assoc_name)
131
+ if image_object && image_object.persisted?
132
+ remove_btn_display = raw(theme_fa_icon(options[:delete_options][:icon]) + theme_button_text(options[:delete_options][:text]))
133
+ remove_btn = link_to(remove_btn_display, delete_url, :class=>options[:delete_options][:class], :remote=>options[:delete_options][:remote])
134
+ end
135
+
136
+ link_to(image_tag, edit_url, :remote => options[:remote]) +
137
+ content_tag(:div, class: "btn-group btn-group-justified mt-30") do
138
+ edit_btn + (object.persisted? ? remove_btn : "")
139
+ end
180
140
  end
181
141
 
182
142
  # Returns new photo url or edit existing photo url based on object is associated with photo or not
@@ -196,14 +156,23 @@ module ImageHelper
196
156
  # >>> upload_image_link(@project_with_image, :profile_picture, :customer)
197
157
  # "/customer/images/1/edit"
198
158
  def upload_image_link(object, assoc_name=:photo, scope=:admin, **options)
199
- photo_object = nil
200
- photo_object = object.send(assoc_name) if object.respond_to?(assoc_name)
201
- #binding.pry
202
- if photo_object.present? && photo_object.persisted?
203
- url_for([:edit, scope, :image, id: photo_object.id, imageable_id: object.id, imageable_type: object.class.to_s, image_type: photo_object.class.name, account_id: options[:account_id]])
159
+ image_object = nil
160
+ image_object = object.send(assoc_name) if object.respond_to?(assoc_name)
161
+ if image_object.present? && image_object.persisted?
162
+ main_app.url_for([:edit, scope, :image, id: image_object.id, imageable_id: object.id, imageable_type: object.class.to_s, image_type: image_object.class.name])
163
+ else
164
+ image_object = object.send("build_#{assoc_name}")
165
+ main_app.url_for([:new, scope, :image, imageable_id: object.id, imageable_type: object.class.to_s, image_type: image_object.class.name])
166
+ end
167
+ end
168
+
169
+ def remove_image_link(object, assoc_name=:photo, scope=:admin, **options)
170
+ image_object = nil
171
+ image_object = object.send(assoc_name) if object.respond_to?(assoc_name)
172
+ if image_object.persisted?
173
+ main_app.url_for([scope, :image, id: image_object.id, imageable_id: object.id, imageable_type: object.class.to_s, image_type: image_object.class.name])
204
174
  else
205
- photo_object = object.send("build_#{assoc_name}")
206
- url_for([:new, scope, :image, imageable_id: object.id, imageable_type: object.class.to_s, image_type: photo_object.class.name, account_id: options[:account_id]])
175
+ "#"
207
176
  end
208
177
  end
209
178
  end
@@ -0,0 +1,41 @@
1
+ module NotificationHelper
2
+ # This function will set a notification message depending up on the request type (ajax - xml http or direct http)
3
+ # Example
4
+ # set_notification("Success", "The message has been sent successfully")
5
+ # set_notification("Success", "Permission denied")
6
+
7
+ def default_notification_configuration
8
+ {
9
+ success: false,
10
+ title: "<NOT SET>",
11
+ message: "<NO MESSAGE SET>"
12
+ }
13
+ end
14
+
15
+ def configure_notification
16
+ if defined?(@notification)
17
+ @notification.reverse_merge!(default_notification_configuration)
18
+ else
19
+ @notification = default_notification_configuration
20
+ end
21
+ end
22
+
23
+ def set_notification(success, title, message)
24
+ @notification[:success] = success
25
+ @notification[:title] = title
26
+ @notification[:message] = message
27
+ end
28
+
29
+ def set_resource_notification(obj)
30
+ if obj.errors.any?
31
+ @notification[:success] = false
32
+ @notification[:title] = I18n.translate("status.error")
33
+ @notification[:message] = obj.errors.full_messages.join("<br>")
34
+ else
35
+ @notification[:success] = true
36
+ @notification[:title] = I18n.translate("status.success")
37
+ @notification[:message] = I18n.translate("success.saved", item: default_item_name.titleize)
38
+ end
39
+ end
40
+
41
+ end
@@ -1,5 +1,25 @@
1
1
  module RenderHelper
2
2
 
3
+ def render_404
4
+ respond_to do |format|
5
+ format.html { render :file => "#{Rails.root}/public/404", :layout => true, :status => :not_found }
6
+ format.any { head :not_found }
7
+ end
8
+ end
9
+
10
+ def handle_invalid_authenticity_token
11
+ heading = I18n.t("status.invalid_token.heading")
12
+ message = I18n.t("status.invalid_token.message")
13
+ js_message = <<-eos
14
+ showMessageModal('#{heading}','#{message}');
15
+ notifyError('#{heading}','#{message}');
16
+ eos
17
+ respond_to do |format|
18
+ format.html { render :status => 404 }
19
+ format.js { render text: js_message }
20
+ end
21
+ end
22
+
3
23
  def render_or_redirect(error, redirect_url, action, notice=nil)
4
24
  respond_to do |format|
5
25
  format.html {
@@ -9,20 +29,39 @@ module RenderHelper
9
29
  redirect_to redirect_url, notice: notice
10
30
  end
11
31
  }
12
- format.js {}
32
+ format.js {
33
+ view_path = @resource_options && @resource_options[:view_path] ? "#{@resource_options[:js_view_path]}/#{params[:action]}" : params[:action].to_s
34
+ render view_path
35
+ }
13
36
  end
14
37
  end
15
38
 
16
- def render_list
39
+ def render_accordingly
17
40
  respond_to do |format|
18
- format.html { get_collections and render :index }
19
- format.js {}
41
+ format.html { get_collections and render params[:action].to_sym }
42
+ format.js {
43
+ view_path = @resource_options && @resource_options[:view_path] ? "#{@resource_options[:js_view_path]}/#{params[:action]}" : params[:action].to_sym
44
+ render view_path
45
+ }
20
46
  end
21
47
  end
22
48
 
23
49
  def render_show
24
50
  respond_to do |format|
25
- format.js { render action: :show }
51
+ format.js {
52
+ js_view_path = @resource_options && @resource_options[:view_path] ? "#{@resource_options[:js_view_path]}/show" : :show
53
+ render js_view_path
54
+ }
55
+ end
56
+ end
57
+
58
+ def render_row
59
+ respond_to do |format|
60
+ format.html {}
61
+ format.js {
62
+ js_view_path = @resource_options && @resource_options[:js_view_path] ? "#{@resource_options[:js_view_path]}/row" : :row
63
+ render js_view_path
64
+ }
26
65
  end
27
66
  end
28
67
  end
@@ -2,52 +2,105 @@ module ResourceHelper
2
2
 
3
3
  def index
4
4
  get_collections
5
+ respond_to do |format|
6
+ format.html {}
7
+ format.js {
8
+ js_view_path = @resource_options && @resource_options[:js_view_path] ? "#{@resource_options[:js_view_path]}/index" : :index
9
+ render js_view_path
10
+ }
11
+ end
5
12
  end
6
13
 
7
14
  def show
8
- obj = @options[:class].find(params[:id])
9
- instance_variable_set("@#{@options[:item_name]}", obj)
10
- render_list
15
+ @r_object = @resource_options[:class].find_by_id(params[:id])
16
+ if @r_object
17
+ instance_variable_set("@#{@resource_options[:item_name]}", @r_object)
18
+ else
19
+ set_notification(false, I18n.t('status.error'), I18n.t('status.not_found', item: default_item_name.titleize))
20
+ end
21
+ render_accordingly
11
22
  end
12
23
 
13
24
  def new
14
- obj = @options[:class].new
15
- instance_variable_set("@#{@options[:item_name]}", obj)
16
- render_list
25
+ @r_object = @resource_options[:class].new
26
+ instance_variable_set("@#{@resource_options[:item_name]}", @r_object)
27
+ render_accordingly
17
28
  end
18
29
 
19
30
  def edit
20
- obj = @options[:class].find(params[:id])
21
- instance_variable_set("@#{@options[:item_name]}", obj)
22
- render_list
31
+ @r_object = @resource_options[:class].find_by_id(params[:id])
32
+ if @r_object
33
+ instance_variable_set("@#{@resource_options[:item_name]}", @r_object)
34
+ else
35
+ set_notification(false, I18n.t('status.error'), I18n.t('status.not_found', item: default_item_name.titleize))
36
+ end
37
+ render_accordingly
23
38
  end
24
39
 
25
40
  def create
26
- obj = @options[:class].new
27
- obj.assign_attributes(permitted_params)
28
- instance_variable_set("@#{@options[:item_name]}", obj)
29
- save_resource(obj)
41
+ @r_object = @resource_options[:class].new
42
+ @r_object.assign_attributes(permitted_params)
43
+ instance_variable_set("@#{@resource_options[:item_name]}", @r_object)
44
+ save_resource
30
45
  end
31
46
 
32
47
  def update
33
- obj = @options[:class].find(params[:id])
34
- obj.assign_attributes(permitted_params)
35
- instance_variable_set("@#{@options[:item_name]}", obj)
36
- save_resource(obj)
48
+ @r_object = @resource_options[:class].find_by_id(params[:id])
49
+ if @r_object
50
+ @r_object.assign_attributes(permitted_params)
51
+ instance_variable_set("@#{@resource_options[:item_name]}", @r_object)
52
+ save_resource
53
+ else
54
+ set_notification(false, I18n.t('status.error'), I18n.t('status.not_found', item: default_item_name.titleize))
55
+ end
37
56
  end
38
57
 
39
58
  def destroy
40
- obj = @options[:class].find(params[:id])
41
- instance_variable_set("@#{@options[:item_name]}", obj)
42
- if obj.can_be_destroyed?
43
- obj.destroy
44
- get_collections
45
- set_flash_message(@options[:messages][:delete], :success)
46
- @destroyed = true
59
+ @r_object = @resource_options[:class].find_by_id(params[:id])
60
+
61
+ if @r_object
62
+ instance_variable_set("@#{@resource_options[:item_name]}", @r_object)
63
+ if @r_object.can_be_deleted?
64
+ @r_object.destroy
65
+ get_collections
66
+ set_flash_message(I18n.t('success.deleted'), :success)
67
+ set_notification(false, I18n.t('status.success'), I18n.t('success.deleted', item: default_item_name.titleize))
68
+ @destroyed = true
69
+ else
70
+ message = I18n.t('errors.failed_to_delete', item: default_item_name.titleize)
71
+ set_flash_message(message, :failure)
72
+ set_notification(false, I18n.t('status.error'), message)
73
+ @destroyed = false
74
+ end
47
75
  else
48
- set_flash_message("Cannot remove! Remove the dependant data first", :failure)
49
- @destroyed = false
76
+ set_notification(false, I18n.t('status.error'), I18n.t('status.not_found', item: default_item_name.titleize))
50
77
  end
78
+
79
+ respond_to do |format|
80
+ format.html {}
81
+ format.js {
82
+ js_view_path = @resource_options && @resource_options[:js_view_path] ? "#{@resource_options[:js_view_path]}/destroy" : :destroy
83
+ render js_view_path
84
+ }
85
+ end
86
+
87
+ end
88
+
89
+ def update_status
90
+ @r_object = @resource_options[:class].find_by_id(params[:id])
91
+ if @r_object
92
+ instance_variable_set("@#{@resource_options[:item_name]}", @r_object)
93
+ @r_object.status = params[:status]
94
+ if @r_object.valid?
95
+ @r_object.save
96
+ set_notification(true, I18n.t('status.success'), I18n.t('state.changed', item: default_item_name.titleize, new_state: @r_object.status))
97
+ else
98
+ set_notification(false, I18n.t('status.error'), I18n.translate("error"), @r_object.errors.full_messages.join("<br>"))
99
+ end
100
+ else
101
+ set_notification(false, I18n.t('status.not_found'), I18n.t('status.not_found', item: default_item_name.titleize))
102
+ end
103
+ render_row
51
104
  end
52
105
 
53
106
  private
@@ -72,33 +125,34 @@ module ResourceHelper
72
125
  default_collection_name.singularize.camelize.constantize
73
126
  end
74
127
 
128
+ def resource_controller_configuration
129
+ {}
130
+ end
131
+
75
132
  def default_resource_controller_configuration
76
133
  {
134
+ page_title: "Page Title | Kuppayam",
135
+ current_nav: "kuppayam/current_page",
77
136
  collection_name: default_collection_name,
78
137
  item_name: default_item_name,
79
138
  class: default_class,
80
139
  layout: :table,
81
- messages: {
82
- add: I18n.translate("forms.add", item: default_item_name.titleize),
83
- create: I18n.translate("forms.create", item: default_item_name.titleize),
84
- update: I18n.translate("forms.update", item: default_item_name.titleize),
85
- save: I18n.translate("forms.save", item: default_item_name.titleize),
86
- remove: I18n.translate("forms.remove", item: default_item_name.titleize),
87
- delete: I18n.translate("forms.delete",item: default_item_name.titleize)
88
- }
140
+ view_path: "/kuppayam/workflows/peacock",
141
+ js_view_path: "/kuppayam/workflows/peacock"
89
142
  }
90
143
  end
91
144
 
92
145
  def configure_resource_controller
93
- if defined?(@options)
94
- @options.reverse_merge!(default_resource_controller_configuration)
95
- else
96
- @options = default_resource_controller_configuration
97
- end
146
+ @resource_options = resource_controller_configuration
147
+ @resource_options.reverse_merge!(default_resource_controller_configuration)
148
+
149
+ # Set Default Title
150
+ set_title(@resource_options[:page_title])
151
+ set_nav(@resource_options[:current_nav])
98
152
  end
99
153
 
100
154
  def prepare_query
101
- @relation = @options[:class].where("")
155
+ @relation = @resource_options[:class].where("")
102
156
  if params[:query]
103
157
  @query = params[:query].strip
104
158
  @relation = @relation.search(@query) if !@query.blank?
@@ -107,27 +161,28 @@ module ResourceHelper
107
161
 
108
162
  def get_collections
109
163
  prepare_query
110
- objects = @relation.order("created_at desc").page(@current_page).per(@per_page)
111
- instance_variable_set("@#{@options[:collection_name]}", objects)
112
- unless instance_variable_get("@#{@options[:item_name]}")
113
- instance_variable_set("@#{@options[:item_name]}", objects.first)
164
+ @r_objects = @relation.order("created_at desc").page(@current_page).per(@per_page)
165
+ instance_variable_set("@#{@resource_options[:collection_name]}", @r_objects)
166
+ unless instance_variable_get("@#{@resource_options[:item_name]}")
167
+ instance_variable_set("@#{@resource_options[:item_name]}", @r_objects.first)
114
168
  end
115
169
  return true
116
170
  end
117
171
 
118
172
  def resource_url(obj)
119
- url_for([:admin, obj])
173
+ url_for(obj)
120
174
  end
121
175
 
122
- def save_resource(obj)
123
- obj.save
124
- if obj.errors.blank?
125
- get_collections if @options[:layout] = :table
126
- set_flash_message(@options[:messages][:save], :success)
176
+ def save_resource
177
+ if @r_object.valid?
178
+ @r_object.save
179
+ get_collections if @resource_options[:layout] = :table
180
+ set_flash_message(I18n.translate("forms.save", item: default_item_name.titleize), :success)
127
181
  end
182
+ set_resource_notification(@r_object)
128
183
  action_name = params[:action].to_s == "create" ? "new" : "edit"
129
- url = obj.persisted? ? resource_url(obj) : nil
130
- render_or_redirect(obj.errors.any?, url, action_name)
184
+ url = @r_object.persisted? ? resource_url(@r_object) : nil
185
+ render_or_redirect(@r_object.errors.any?, url, action_name)
131
186
  end
132
187
 
133
188
  end
@@ -0,0 +1,43 @@
1
+ class Document::Base < Kuppayam::ApplicationRecord
2
+
3
+ # Constants
4
+ UPLOAD_LIMIT = 10
5
+
6
+ self.table_name = "documents"
7
+ self.inheritance_column = :image_type
8
+
9
+ # Validations
10
+ validates :document, :presence => true
11
+ validate :file_size
12
+
13
+ # Associations
14
+ belongs_to :documentable, :polymorphic => true, optional: true
15
+
16
+ # ------------------
17
+ # Class Methods
18
+ # ------------------
19
+
20
+ # return an published record relation object with the search query in its where clause
21
+ # Return the ActiveRecord::Relation object
22
+ # == Examples
23
+ # >>> document.search(query)
24
+ # => ActiveRecord::Relation object
25
+ scope :search, lambda { |query| where("LOWER(imageable_type) LIKE LOWER('%#{query}%') OR\
26
+ LOWER(imageable_id) LIKE LOWER('%#{query}%')")
27
+ }
28
+
29
+ # ------------------
30
+ # Instance Methods
31
+ # ------------------
32
+
33
+ def file_size
34
+ if document && document.file && document.file.size.to_f > UPLOAD_LIMIT.megabytes.to_f
35
+ errors.add(:document, "You cannot upload a document greater than #{UPLOAD_LIMIT.to_f} MB")
36
+ end
37
+ end
38
+
39
+ def display_name
40
+ "#{id} - #{self.class.name.split('::').last.titleize}"
41
+ end
42
+
43
+ end
@@ -0,0 +1,52 @@
1
+ class Image::Base < Kuppayam::ApplicationRecord
2
+
3
+ # Constants
4
+ UPLOAD_LIMIT = 1
5
+
6
+ self.table_name = "images"
7
+ self.inheritance_column = :image_type
8
+
9
+ attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
10
+
11
+ # Validations
12
+ validates :image, :presence => true
13
+ validate :file_size
14
+
15
+ # Associations
16
+ belongs_to :imageable, :polymorphic => true #, optional: false
17
+
18
+ # Callbacks
19
+ after_save :crop_image
20
+
21
+ # ------------------
22
+ # Class Methods
23
+ # ------------------
24
+
25
+ # return an published record relation object with the search query in its where clause
26
+ # Return the ActiveRecord::Relation object
27
+ # == Examples
28
+ # >>> image.search(query)
29
+ # => ActiveRecord::Relation object
30
+ scope :search, lambda { |query| where("LOWER(imageable_type) LIKE LOWER('%#{query}%') OR\
31
+ LOWER(imageable_id) LIKE LOWER('%#{query}%')")
32
+ }
33
+
34
+ # ------------------
35
+ # Instance Methods
36
+ # ------------------
37
+
38
+ def crop_image
39
+ image.recreate_versions! if crop_x.present?
40
+ end
41
+
42
+ def file_size
43
+ if image && image.file && image.file.size.to_f > UPLOAD_LIMIT.megabytes.to_f
44
+ errors.add(:image, "You cannot upload an image greater than #{UPLOAD_LIMIT.to_f} MB")
45
+ end
46
+ end
47
+
48
+ def display_name
49
+ "#{id} - #{self.class.name.split('::').last.titleize}"
50
+ end
51
+
52
+ end