upmin-admin 0.0.35

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 (89) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +34 -0
  3. data/app/assets/images/upmin/logo_large.png +0 -0
  4. data/app/assets/images/upmin/logo_small.png +0 -0
  5. data/app/assets/javascripts/upmin/application.js +40 -0
  6. data/app/assets/javascripts/upmin/jquery-clockpicker.js +729 -0
  7. data/app/assets/javascripts/upmin/models.js +23 -0
  8. data/app/assets/javascripts/upmin/moment.js +2856 -0
  9. data/app/assets/javascripts/upmin/pikaday.js +997 -0
  10. data/app/assets/stylesheets/upmin/application.css +16 -0
  11. data/app/assets/stylesheets/upmin/attributes.css.scss +57 -0
  12. data/app/assets/stylesheets/upmin/base.css.scss +53 -0
  13. data/app/assets/stylesheets/upmin/button_mixins.scss +37 -0
  14. data/app/assets/stylesheets/upmin/colors.scss +20 -0
  15. data/app/assets/stylesheets/upmin/instances.css.scss +77 -0
  16. data/app/assets/stylesheets/upmin/jquery-clockpicker.css +370 -0
  17. data/app/assets/stylesheets/upmin/models.css.scss +207 -0
  18. data/app/assets/stylesheets/upmin/pikaday.css +196 -0
  19. data/app/controllers/upmin/application_controller.rb +4 -0
  20. data/app/controllers/upmin/models_controller.rb +90 -0
  21. data/app/helpers/upmin/application_helper.rb +28 -0
  22. data/app/helpers/upmin/instances_helper.rb +13 -0
  23. data/app/helpers/upmin/models_helper.rb +4 -0
  24. data/app/views/layouts/upmin/_navbar.html.haml +15 -0
  25. data/app/views/layouts/upmin/application.html.haml +27 -0
  26. data/app/views/upmin/models/dashboard.html.haml +9 -0
  27. data/app/views/upmin/models/search.html.haml +9 -0
  28. data/app/views/upmin/models/show.html.haml +21 -0
  29. data/app/views/upmin/partials/actions/_action.html.haml +13 -0
  30. data/app/views/upmin/partials/associations/_associations.html.haml +14 -0
  31. data/app/views/upmin/partials/attributes/_datetime.html.haml +95 -0
  32. data/app/views/upmin/partials/attributes/_integer.html.haml +7 -0
  33. data/app/views/upmin/partials/attributes/_progress_bar.html.haml +11 -0
  34. data/app/views/upmin/partials/attributes/_string.html.haml +7 -0
  35. data/app/views/upmin/partials/attributes/_unknown.html.haml +3 -0
  36. data/app/views/upmin/partials/models/_model.html.haml +67 -0
  37. data/app/views/upmin/partials/search_boxes/_ransack_search_box.html.haml +37 -0
  38. data/app/views/upmin/partials/search_results/_result.html.haml +8 -0
  39. data/app/views/upmin/partials/search_results/_results.html.haml +2 -0
  40. data/config/routes.rb +20 -0
  41. data/lib/tasks/accordive_rails_tasks.rake +4 -0
  42. data/lib/tasks/upmin_tasks.rake +4 -0
  43. data/lib/upmin.rb +18 -0
  44. data/lib/upmin/engine.rb +7 -0
  45. data/lib/upmin/klass.rb +165 -0
  46. data/lib/upmin/model.rb +133 -0
  47. data/lib/upmin/railtie.rb +19 -0
  48. data/lib/upmin/railties/active_record.rb +62 -0
  49. data/lib/upmin/railties/render.rb +120 -0
  50. data/lib/upmin/railties/render_helpers.rb +144 -0
  51. data/lib/upmin/version.rb +3 -0
  52. data/test/controllers/upmin/model_controller_test.rb +11 -0
  53. data/test/dummy/README.rdoc +28 -0
  54. data/test/dummy/Rakefile +6 -0
  55. data/test/dummy/app/assets/javascripts/application.js +13 -0
  56. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  57. data/test/dummy/app/controllers/application_controller.rb +5 -0
  58. data/test/dummy/app/helpers/application_helper.rb +2 -0
  59. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  60. data/test/dummy/bin/bundle +3 -0
  61. data/test/dummy/bin/rails +4 -0
  62. data/test/dummy/bin/rake +4 -0
  63. data/test/dummy/config.ru +4 -0
  64. data/test/dummy/config/application.rb +23 -0
  65. data/test/dummy/config/boot.rb +5 -0
  66. data/test/dummy/config/database.yml +25 -0
  67. data/test/dummy/config/environment.rb +5 -0
  68. data/test/dummy/config/environments/development.rb +37 -0
  69. data/test/dummy/config/environments/production.rb +83 -0
  70. data/test/dummy/config/environments/test.rb +39 -0
  71. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  72. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  73. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  74. data/test/dummy/config/initializers/inflections.rb +16 -0
  75. data/test/dummy/config/initializers/mime_types.rb +4 -0
  76. data/test/dummy/config/initializers/session_store.rb +3 -0
  77. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  78. data/test/dummy/config/locales/en.yml +23 -0
  79. data/test/dummy/config/routes.rb +4 -0
  80. data/test/dummy/config/secrets.yml +22 -0
  81. data/test/dummy/public/404.html +67 -0
  82. data/test/dummy/public/422.html +67 -0
  83. data/test/dummy/public/500.html +66 -0
  84. data/test/dummy/public/favicon.ico +0 -0
  85. data/test/helpers/upmin/model_helper_test.rb +6 -0
  86. data/test/integration/navigation_test.rb +10 -0
  87. data/test/test_helper.rb +15 -0
  88. data/test/upmin_test.rb +7 -0
  89. metadata +237 -0
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :accordive_rails do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :upmin do
3
+ # # Task goes here
4
+ # end
data/lib/upmin.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "upmin/engine"
2
+
3
+ require "upmin/klass"
4
+ require "upmin/model"
5
+
6
+ # Monkey patch code into rails
7
+ require "upmin/railties/active_record"
8
+ require "upmin/railties/render"
9
+ require "upmin/railties/render_helpers"
10
+ require "upmin/railtie"
11
+
12
+ # gems and stuff we use
13
+ require "ransack"
14
+ require "haml"
15
+ require "sass-rails"
16
+
17
+ module Upmin
18
+ end
@@ -0,0 +1,7 @@
1
+ # require 'haml-rails'
2
+
3
+ module Upmin
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace Upmin
6
+ end
7
+ end
@@ -0,0 +1,165 @@
1
+ module Upmin
2
+ class Klass
3
+
4
+ attr_accessor :model
5
+ attr_accessor :color
6
+
7
+ def initialize(model, options = {})
8
+ self.model = model
9
+
10
+ if options[:color]
11
+ self.color = options[:color]
12
+ end
13
+ end
14
+
15
+ # Exposing a model method, but wrapping the result in
16
+ # an Upmin::Model
17
+ def find(*args)
18
+ return Upmin::Model.new(model.find(*args))
19
+ end
20
+
21
+ def ransack(*args)
22
+ return model.ransack(*args)
23
+ end
24
+
25
+
26
+ # Returns all of the upmin attributes for the ActiveRecord model
27
+ # referenced by this Klass object.
28
+ def attributes
29
+ return model.upmin_attributes
30
+ end
31
+
32
+ # Returns the type for an attribute by checking the columns
33
+ # hash. If no match can be found, :unknown is returned.
34
+ # NOTE - the Upmin::Model version of this will look at the
35
+ # actual contents of the attr_name if :unknown is returned,
36
+ # so this version is more accurate if you can use it.
37
+ def attribute_type(attr_name)
38
+ if connection_adapter = model.columns_hash[attr_name.to_s]
39
+ return connection_adapter.type
40
+ else
41
+ return :unknown
42
+ end
43
+ end
44
+
45
+
46
+ # Returns all of the upmin actions for the ActiveRecord model
47
+ # referenced by this Klass object.
48
+ def actions
49
+ return model.upmin_actions
50
+ end
51
+
52
+ # Returns all associations that are not used in through associations
53
+ # eg - an Order's products, but not an order's product_orders that link the two.
54
+ def associations
55
+ return @associations if defined?(@associations)
56
+
57
+ all = []
58
+ ignored = []
59
+ model.reflect_on_all_associations.each do |reflection|
60
+ all << reflection.name.to_sym
61
+
62
+ # We need to remove the ignored later because we don't know the order they come in.
63
+ if reflection.is_a?(::ActiveRecord::Reflection::ThroughReflection)
64
+ ignored << reflection.options[:through]
65
+ end
66
+ end
67
+
68
+ return @associations = all - ignored
69
+ end
70
+
71
+ # Tries to find an association type based on the reflection
72
+ def association_type(assoc_name)
73
+ reflection = reflections.select { |r| r.name == assoc_name.to_sym }.first
74
+
75
+ if reflection
76
+ return reflection.foreign_type.to_s.gsub(/_type$/, "").pluralize.to_sym
77
+ else
78
+ return :unknown
79
+ end
80
+ end
81
+
82
+ def plural_associations
83
+ return model.reflect_on_all_associations
84
+ .select{ |r| r.collection? }
85
+ .map{ |r| r.name.to_sym }
86
+ end
87
+
88
+ def reflections
89
+ return model.reflect_on_all_associations
90
+ end
91
+
92
+
93
+
94
+ ## Methods for prettying up things to display them in views etc.
95
+
96
+ # Returns the class name, split at camelCase,
97
+ # with the last word pluralized if it is plural.
98
+ def humanized_name(type = :plural)
99
+ names = model.name.split(/(?=[A-Z])/)
100
+ if type == :plural
101
+ names[names.length-1] = names.last.pluralize
102
+ end
103
+ return names.join(" ")
104
+ end
105
+
106
+ # Returns the class name, capitalized as it would be with User.name or OrderShipment.name - "User", or "OrderShipment"
107
+ def name
108
+ return model.name
109
+ end
110
+
111
+ def path_hash
112
+ return {
113
+ klass: klass.name
114
+ }
115
+ end
116
+
117
+
118
+
119
+ ## Class Methods
120
+
121
+ # Takes a Rails ActiveRecord or the name of one and returns an
122
+ # Upmin::Klass instance of the model.
123
+ def Klass.find(model)
124
+ return all.select{|k| k.name == model.to_s}.first
125
+ end
126
+
127
+ # Returns an array of all Klass instances
128
+ def Klass.all
129
+ return @all if defined?(@all)
130
+ all = []
131
+
132
+ models.each_with_index do |model, i|
133
+ klass = Klass.new(model, color: colors[i % colors.length])
134
+ all << klass
135
+ end
136
+
137
+ return @all = all
138
+ end
139
+
140
+ def Klass.colors
141
+ return [
142
+ :light_blue,
143
+ :blue_green,
144
+ :red,
145
+ :yellow,
146
+ :orange,
147
+ :purple,
148
+ :dark_blue,
149
+ :dark_red,
150
+ :green
151
+ ]
152
+ end
153
+
154
+ def Klass.models
155
+ # If Rails
156
+ ::Rails.application.eager_load!
157
+ rails_models = ::ActiveRecord::Base.descendants.select do |m|
158
+ m.to_s != "ActiveRecord::SchemaMigration"
159
+ end
160
+
161
+ return rails_models
162
+ end
163
+
164
+ end
165
+ end
@@ -0,0 +1,133 @@
1
+ module Upmin
2
+ class Model
3
+
4
+ attr_accessor :instance
5
+ attr_accessor :klass
6
+
7
+ def initialize(instance, options = {})
8
+ self.instance = instance
9
+ self.klass = Upmin::Klass.find(instance.class.name)
10
+ end
11
+
12
+ ## Methods for rendering in views
13
+ def title
14
+ return "#{klass.humanized_name(:singular)} # #{instance.id}"
15
+ end
16
+
17
+ def color
18
+ return klass.color
19
+ end
20
+
21
+ def path_hash
22
+ return {
23
+ klass: klass.name,
24
+ id: instance.id
25
+ }
26
+ end
27
+
28
+ ## Methods for getting attributes, associations, etc and anything relevant to them.
29
+
30
+
31
+ # Returns the type of an attribute. If it is nil and we can't
32
+ # figure it out from the db columns we just fall back to
33
+ # :unknown
34
+ def attribute_type(attr_name)
35
+ type = klass.attribute_type(attr_name)
36
+
37
+ if type == :unknown
38
+ # See if we can deduce it by looking at the data
39
+ data = attribute(attr_name)
40
+ class_sym = data.class.to_s.underscore.to_sym
41
+ if class_sym == :false_class || class_sym == :true_class
42
+ type = :boolean
43
+ elsif class_sym == :nil_class
44
+ type = :unknown
45
+ elsif class_sym == :fixnum
46
+ type = :integer
47
+ elsif class_sym == :big_decimal
48
+ type = :decimal
49
+ elsif class_sym == :"active_support/time_with_zone"
50
+ type = :datetime
51
+ else
52
+ # This should prevent any classes from being skipped, but we may not have an exhaustive list yet.
53
+ type = class_sym
54
+ end
55
+ end
56
+
57
+ return type
58
+ end
59
+
60
+ # Returns whether or not the attr_name is an attribute that can be edited.
61
+ def attribute_editable?(attr_name)
62
+ attr_name = attr_name.to_sym
63
+ return false if attr_name == :id
64
+ return false if attr_name == :created_at
65
+ return false if attr_name == :updated_at
66
+ # TODO(jon): Add a way to declare which attributes are editable and which are not later.
67
+ return instance.respond_to?("#{attr_name}=")
68
+ end
69
+
70
+ # Returns the value of the attr_name method
71
+ def attribute(attr_name)
72
+ attr_name = attr_name.to_sym
73
+ # TODO(jon): Add some way to handle exceptions. Probably a custom error that we display.
74
+ return instance.send(attr_name)
75
+ end
76
+
77
+ def attribute_form_id(attr_name)
78
+ return "#{klass.name.underscore}_#{attr_name}"
79
+ end
80
+
81
+ def attribute_label_name(attr_name)
82
+ return attr_name.to_s.gsub(/_/, " ").capitalize
83
+ end
84
+
85
+
86
+ # Returns the type of an association. If we can't figure it
87
+ # out we fall back to :unknown
88
+ def association_type(assoc_name)
89
+ type = klass.association_type(assoc_name)
90
+ if type == :unknown && data = association(assoc_name).first
91
+ type = data.class.name.underscore
92
+ end
93
+ return type
94
+ end
95
+
96
+ def association(assoc_name, options = {})
97
+ association = instance.send(assoc_name)
98
+ if association.respond_to?(:each)
99
+ # We have a collection, at least we hope we do.
100
+ if options[:limit] && association.respond_to?(:limit)
101
+ association = association.limit(5)
102
+ end
103
+ end
104
+ return association
105
+ end
106
+
107
+ def action_parameters(action)
108
+ instance.method(action).parameters
109
+ end
110
+
111
+ def perform_action(action, arguments)
112
+ unless klass.actions.include?(action.to_sym)
113
+ raise "Invalid action: #{action}"
114
+ end
115
+
116
+ params = action_parameters(action)
117
+ params_array = []
118
+ params.each do |param_type, param_name|
119
+ if param_type == :req
120
+ raise "Missing argument: #{param_name}" unless arguments[param_name]
121
+ params_array << arguments[param_name]
122
+ elsif param_type == :opt
123
+ params_array << arguments[param_name] if arguments[param_name]
124
+ else # :block or ??
125
+ next
126
+ end
127
+ end
128
+ return instance.send(action, *params_array)
129
+ end
130
+
131
+
132
+ end
133
+ end
@@ -0,0 +1,19 @@
1
+ module Upmin
2
+ require 'rails'
3
+ class Railtie < Rails::Railtie
4
+ initializer('upmin.insert_into_active_record') do
5
+ ActiveSupport.on_load(:active_record) do
6
+ ::ActiveRecord::Base.send(:include, Upmin::Railties::ActiveRecord)
7
+ # ::ActiveRecord::Relation.send(:include, Upmin::ActiveRecordRelation)
8
+ end
9
+
10
+ ActiveSupport.on_load(:action_controller) do
11
+ ::ActionController::Base.send(:include, Upmin::Railties::Render)
12
+ end
13
+
14
+ ActiveSupport.on_load(:action_view) do
15
+ ::ActionView::Base.send(:include, Upmin::Railties::Render)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_support/concern'
2
+
3
+ module Upmin::Railties
4
+ module ActiveRecord
5
+ extend ::ActiveSupport::Concern
6
+
7
+ included do
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ # Add a single attribute to upmin attributes. If this is called
13
+ # before upmin_attributes the attributes will not include any defaults
14
+ # attributes.
15
+ def upmin_attribute(attribute)
16
+ upmin_attributes unless defined?(@upmin_attributes)
17
+
18
+ attribute = attribute.to_sym
19
+ @upmin_attributes << attribute unless @upmin_attributes.include?(attribute)
20
+ end
21
+
22
+ # Sets the upmin_attributes to the provided attributes if any are
23
+ # provided.
24
+ # If no attributes are provided, and upmin_attributes hasn't been defined,
25
+ # then the upmin_attributes are set to the default attributes.
26
+ # Returns the upmin_attributes
27
+ def upmin_attributes(*attributes)
28
+ if attributes.any?
29
+ @upmin_attributes = attributes.map{|a| a.to_sym}
30
+ end
31
+ @upmin_attributes ||= attribute_names.map{|a| a.to_sym}
32
+ return @upmin_attributes
33
+ end
34
+
35
+
36
+ # Add a single action to upmin actions. If this is called
37
+ # before upmin_actions the actions will not include any defaults
38
+ # actions.
39
+ def upmin_action(action)
40
+ @upmin_actions ||= []
41
+
42
+ action = action.to_sym
43
+ @upmin_actions << action unless @upmin_actions.include?(attribute)
44
+ end
45
+
46
+ # Sets the upmin_actions to the provided actions if any are
47
+ # provided.
48
+ # If no actions are provided, and upmin_actions hasn't been defined,
49
+ # then the upmin_actions are set to the default actions.
50
+ # Returns the upmin_actions
51
+ def upmin_actions(*actions)
52
+ if actions.any?
53
+ # set the actions
54
+ @upmin_actions = actions.map{|a| a.to_sym}
55
+ end
56
+ @upmin_actions ||= []
57
+ return @upmin_actions
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,120 @@
1
+
2
+ module Upmin::Railties
3
+ module Render
4
+
5
+ def up_model(model, options = {})
6
+ options[:locals] ||= {}
7
+
8
+ upmin_model = Upmin::Model.new(model)
9
+ options[:locals][:upmin_model] ||= upmin_model
10
+
11
+ partials = RenderHelpers.model_partials(upmin_model, options)
12
+ return up_render(model, partials, options, :up_model)
13
+ end
14
+
15
+ def up_attribute(model, attr_name, options = {})
16
+ options[:locals] ||= {}
17
+ options[:locals][:model] ||= model
18
+ options[:locals][:attr_name] = attr_name
19
+
20
+ upmin_model = Upmin::Model.new(model)
21
+ options[:locals][:upmin_model] ||= upmin_model
22
+
23
+ options[:locals][:form_id] ||= upmin_model.attribute_form_id(attr_name)
24
+ # Only fill this in if it was never set so the user can override this.
25
+ if options[:locals][:editable].nil?
26
+ options[:locals][:editable] = upmin_model.attribute_editable?(attr_name)
27
+ end
28
+
29
+
30
+ partials = RenderHelpers.attribute_partials(upmin_model, attr_name, options)
31
+
32
+ data = upmin_model.attribute(attr_name)
33
+ return up_render(data, partials, options, :up_attribute)
34
+ end
35
+
36
+ def up_association(model, assoc_name, options = {})
37
+ options[:locals] ||= {}
38
+ options[:locals][:model] ||= model
39
+ options[:locals][:assoc_name] = assoc_name
40
+
41
+ upmin_model = Upmin::Model.new(model)
42
+ options[:locals][:upmin_model] ||= upmin_model
43
+
44
+ partials = RenderHelpers.association_partials(upmin_model, assoc_name, options)
45
+
46
+ data = upmin_model.association(assoc_name, options)
47
+ return up_render([data].flatten, partials, options, :up_association)
48
+ end
49
+
50
+ def up_action(model, action_name, options = {})
51
+ options[:locals] ||= {}
52
+ options[:locals][:model] ||= model
53
+ options[:locals][:action_name] = action_name
54
+
55
+ upmin_model = Upmin::Model.new(model)
56
+ options[:locals][:upmin_model] ||= upmin_model
57
+
58
+ partials = RenderHelpers.action_partials(upmin_model, action_name, options)
59
+
60
+ data = upmin_model.action_parameters(action_name)
61
+ return up_render(data, partials, options, :up_action)
62
+ end
63
+
64
+ def up_search_results(ransack_search, ransack_results, options = {})
65
+ options[:locals] ||= {}
66
+ options[:locals][:klass] ||= Upmin::Klass.find(ransack_search.klass)
67
+ options[:locals][:ransack_search] ||= ransack_search
68
+ options[:locals][:ransack_results] ||= ransack_results
69
+
70
+ partials = RenderHelpers.search_results_partials(ransack_search, options)
71
+
72
+ return up_render(ransack_results, partials, options, :up_search_results)
73
+ end
74
+
75
+ def up_search_result(model, options = {})
76
+ options[:locals] ||= {}
77
+
78
+ upmin_model = Upmin::Model.new(model)
79
+ options[:locals][:upmin_model] ||= upmin_model
80
+
81
+ partials = RenderHelpers.search_result_partials(upmin_model, options)
82
+
83
+ return up_render(model, partials, options, :up_search_result)
84
+ end
85
+
86
+ def up_search_box(klass, options = {})
87
+ options[:locals] ||= {}
88
+
89
+ klass = Upmin::Klass.find(klass) unless klass.is_a?(Upmin::Klass)
90
+ if klass.nil?
91
+ raise "Invalid klass provided in `up_search_box`"
92
+ end
93
+
94
+ options[:locals][:klass] = klass
95
+
96
+ partials = RenderHelpers.search_box_partials(klass, options)
97
+
98
+ return up_render(klass, partials, options, :up_search_box)
99
+ end
100
+
101
+
102
+ # Generic render method that is used by all of the up_<something> methods. Tries to render the partials in order, passing data in as the :object, along with options.
103
+ def up_render(data, partials, options = {}, calling_method = nil)
104
+ # Use options as the render hash, and set :object as the data being used for rendering.
105
+ options[:object] = data
106
+
107
+ partials.each do |partial|
108
+ begin
109
+ options[:partial] = partial
110
+ return render(options)
111
+ rescue ActionView::MissingTemplate => e
112
+ end
113
+ end
114
+
115
+ # If we get here we tried all of the partials and nothing matched. This *shouldn't* be possible but might happen if partials are deleted.
116
+ raise "Failed to find a matching partial while trying to render `#{calling_method}` with the following data: #{data.inspect}"
117
+ end
118
+
119
+ end
120
+ end