upmin-admin 0.0.35

Sign up to get free protection for your applications and to get access to all the features.
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