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.
- checksums.yaml +7 -0
- data/Rakefile +34 -0
- data/app/assets/images/upmin/logo_large.png +0 -0
- data/app/assets/images/upmin/logo_small.png +0 -0
- data/app/assets/javascripts/upmin/application.js +40 -0
- data/app/assets/javascripts/upmin/jquery-clockpicker.js +729 -0
- data/app/assets/javascripts/upmin/models.js +23 -0
- data/app/assets/javascripts/upmin/moment.js +2856 -0
- data/app/assets/javascripts/upmin/pikaday.js +997 -0
- data/app/assets/stylesheets/upmin/application.css +16 -0
- data/app/assets/stylesheets/upmin/attributes.css.scss +57 -0
- data/app/assets/stylesheets/upmin/base.css.scss +53 -0
- data/app/assets/stylesheets/upmin/button_mixins.scss +37 -0
- data/app/assets/stylesheets/upmin/colors.scss +20 -0
- data/app/assets/stylesheets/upmin/instances.css.scss +77 -0
- data/app/assets/stylesheets/upmin/jquery-clockpicker.css +370 -0
- data/app/assets/stylesheets/upmin/models.css.scss +207 -0
- data/app/assets/stylesheets/upmin/pikaday.css +196 -0
- data/app/controllers/upmin/application_controller.rb +4 -0
- data/app/controllers/upmin/models_controller.rb +90 -0
- data/app/helpers/upmin/application_helper.rb +28 -0
- data/app/helpers/upmin/instances_helper.rb +13 -0
- data/app/helpers/upmin/models_helper.rb +4 -0
- data/app/views/layouts/upmin/_navbar.html.haml +15 -0
- data/app/views/layouts/upmin/application.html.haml +27 -0
- data/app/views/upmin/models/dashboard.html.haml +9 -0
- data/app/views/upmin/models/search.html.haml +9 -0
- data/app/views/upmin/models/show.html.haml +21 -0
- data/app/views/upmin/partials/actions/_action.html.haml +13 -0
- data/app/views/upmin/partials/associations/_associations.html.haml +14 -0
- data/app/views/upmin/partials/attributes/_datetime.html.haml +95 -0
- data/app/views/upmin/partials/attributes/_integer.html.haml +7 -0
- data/app/views/upmin/partials/attributes/_progress_bar.html.haml +11 -0
- data/app/views/upmin/partials/attributes/_string.html.haml +7 -0
- data/app/views/upmin/partials/attributes/_unknown.html.haml +3 -0
- data/app/views/upmin/partials/models/_model.html.haml +67 -0
- data/app/views/upmin/partials/search_boxes/_ransack_search_box.html.haml +37 -0
- data/app/views/upmin/partials/search_results/_result.html.haml +8 -0
- data/app/views/upmin/partials/search_results/_results.html.haml +2 -0
- data/config/routes.rb +20 -0
- data/lib/tasks/accordive_rails_tasks.rake +4 -0
- data/lib/tasks/upmin_tasks.rake +4 -0
- data/lib/upmin.rb +18 -0
- data/lib/upmin/engine.rb +7 -0
- data/lib/upmin/klass.rb +165 -0
- data/lib/upmin/model.rb +133 -0
- data/lib/upmin/railtie.rb +19 -0
- data/lib/upmin/railties/active_record.rb +62 -0
- data/lib/upmin/railties/render.rb +120 -0
- data/lib/upmin/railties/render_helpers.rb +144 -0
- data/lib/upmin/version.rb +3 -0
- data/test/controllers/upmin/model_controller_test.rb +11 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +83 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/helpers/upmin/model_helper_test.rb +6 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- data/test/upmin_test.rb +7 -0
- metadata +237 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module Upmin
|
2
|
+
module ApplicationHelper
|
3
|
+
def body_classes
|
4
|
+
ret = []
|
5
|
+
|
6
|
+
controller = "c-#{params[:controller].gsub(/_/, "-").gsub("upmin/", "")}"
|
7
|
+
ret << controller
|
8
|
+
|
9
|
+
action = "a-#{params[:action].gsub(/_/, "-")}"
|
10
|
+
ret << action
|
11
|
+
|
12
|
+
if params[:klass]
|
13
|
+
model = "m-#{params[:klass]}"
|
14
|
+
ret << model
|
15
|
+
end
|
16
|
+
|
17
|
+
return ret
|
18
|
+
end
|
19
|
+
|
20
|
+
def body_data
|
21
|
+
ret = {}
|
22
|
+
ret[:controller] = params[:controller].camelize.gsub("Upmin::", "")
|
23
|
+
ret[:action] = params[:action].camelize
|
24
|
+
return ret
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
.navbar.navbar-default.navbar-static-top
|
2
|
+
.container
|
3
|
+
.navbar-header
|
4
|
+
%a.navbar-brand{href: root_path}
|
5
|
+
Upmin
|
6
|
+
%button.navbar-toggle{"data-target" => "#navbar-main", "data-toggle" => "collapse", type: "button"}
|
7
|
+
%span.icon-bar
|
8
|
+
%span.icon-bar
|
9
|
+
%span.icon-bar
|
10
|
+
#navbar-main.navbar-collapse.collapse
|
11
|
+
%ul.nav.navbar-nav
|
12
|
+
- Upmin::Klass.all.each do |m|
|
13
|
+
%li
|
14
|
+
%a{href: upmin_search_path(klass: m.name)}
|
15
|
+
= m.name.pluralize
|
@@ -0,0 +1,27 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title
|
5
|
+
Upmin Dashboard
|
6
|
+
= stylesheet_link_tag("upmin/application", media: "all")
|
7
|
+
= javascript_include_tag("upmin/application")
|
8
|
+
= csrf_meta_tags
|
9
|
+
|
10
|
+
%link{href: "//cdn.jsdelivr.net/bootstrap/3.2.0/css/bootstrap.min.css", rel: "stylesheet", type: "text/css"}
|
11
|
+
%link{href: "//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css", rel: "stylesheet"}
|
12
|
+
%script{:src => "//cdn.jsdelivr.net/bootstrap/3.2.0/js/bootstrap.min.js"}
|
13
|
+
|
14
|
+
- if content_for?(:head)
|
15
|
+
= yield(:head)
|
16
|
+
|
17
|
+
|
18
|
+
%body{ class: body_classes, data: body_data.merge(root_path: root_path) }
|
19
|
+
.page-wrap
|
20
|
+
= render('layouts/upmin/navbar')
|
21
|
+
-# = render('layouts/flash')
|
22
|
+
= yield
|
23
|
+
|
24
|
+
-# = render('layouts/footer')
|
25
|
+
|
26
|
+
- if content_for?(:javascript)
|
27
|
+
= yield(:javascript)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
.container
|
2
|
+
- if notice
|
3
|
+
.alert.alert-dismissable.alert-info
|
4
|
+
%button.close{"data-dismiss" => "alert", type: "button"}
|
5
|
+
%span{"aria-hidden" => "true"} ×
|
6
|
+
= notice
|
7
|
+
- if alert
|
8
|
+
.alert.alert-dismissable.alert-danger
|
9
|
+
%button.close{"data-dismiss" => "alert", type: "button"}
|
10
|
+
%span{"aria-hidden" => "true"} ×
|
11
|
+
= alert
|
12
|
+
- if @instance.errors.any?
|
13
|
+
%ul
|
14
|
+
- @instance.errors.each do |field, error|
|
15
|
+
%li
|
16
|
+
%b
|
17
|
+
= field
|
18
|
+
= error
|
19
|
+
.row
|
20
|
+
.col-sm-12
|
21
|
+
= up_model(@model.instance)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
.well
|
2
|
+
= form_tag(upmin_action_path(upmin_model.path_hash.merge(method: action_name))) do
|
3
|
+
- upmin_model.action_parameters(action_name).each do |param_type, param_name|
|
4
|
+
|
5
|
+
- next if param_type == :block # Skip blocks
|
6
|
+
|
7
|
+
.form-group
|
8
|
+
= label(action_name, param_name, param_name.to_s.capitalize.gsub("_", " "))
|
9
|
+
= text_field(action_name, param_name, class: "form-control")
|
10
|
+
- if param_type == :opt
|
11
|
+
%small
|
12
|
+
* Optional
|
13
|
+
= submit_tag("Submit", class: "btn btn-primary")
|
@@ -0,0 +1,14 @@
|
|
1
|
+
- if associations.any?
|
2
|
+
%p
|
3
|
+
- associations.each do |u|
|
4
|
+
- nested_upmin_model = Upmin::Model.new(u)
|
5
|
+
%a.active-tag-link{href: upmin_model_path(nested_upmin_model.path_hash)}
|
6
|
+
%span.label{class: nested_upmin_model.color}
|
7
|
+
= nested_upmin_model.title
|
8
|
+
|
9
|
+
- else
|
10
|
+
%p.well
|
11
|
+
None
|
12
|
+
|
13
|
+
|
14
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
- datetime ||= nil
|
2
|
+
- if editable && f = form_builder
|
3
|
+
= f.hidden_field(attr_name, value: datetime)
|
4
|
+
- # TODO(jon): Figure out a better way to do transforms. This works for now though.
|
5
|
+
= f.hidden_field("transforms[#{attr_name}]", value: "DateTime#parse")
|
6
|
+
.row
|
7
|
+
.col-xs-12.col-md-4
|
8
|
+
.input-group.pikadate
|
9
|
+
%input.form-control{type: :text, value: datetime, id: "#{form_id}-date"}
|
10
|
+
%span.input-group-addon
|
11
|
+
%span.glyphicon.glyphicon-calendar
|
12
|
+
.col-xs-12.col-md-4
|
13
|
+
.input-group.clockpicker{"data-align" => "top", "data-autoclose" => "true", "data-placement" => "right"}
|
14
|
+
%input.form-control{:type => "text", :value => datetime, id: "#{form_id}-time"}
|
15
|
+
%span.input-group-addon
|
16
|
+
%span.glyphicon.glyphicon-time
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
- content_for(:javascript) do
|
21
|
+
:javascript
|
22
|
+
(function() {
|
23
|
+
var datePicker,
|
24
|
+
hiddenInput = $('##{form_id}'),
|
25
|
+
date = new Date(hiddenInput.val());
|
26
|
+
|
27
|
+
// Date Specific Code
|
28
|
+
var handleDateSelect = function() {
|
29
|
+
var pickerDate = datePicker.getDate();
|
30
|
+
console.log("Setting the date from " + date + " to " + pickerDate);
|
31
|
+
|
32
|
+
date.setUTCFullYear(pickerDate.getUTCFullYear());
|
33
|
+
date.setUTCMonth(pickerDate.getUTCMonth());
|
34
|
+
date.setUTCDate(pickerDate.getUTCDate());
|
35
|
+
|
36
|
+
hiddenInput.val(date.toUTCString());
|
37
|
+
}
|
38
|
+
|
39
|
+
datePicker = new Pikaday({ field: $('##{form_id}-date')[0], onSelect: handleDateSelect });
|
40
|
+
|
41
|
+
// Time Specific Code
|
42
|
+
var timeInput = $('##{form_id}-time');
|
43
|
+
|
44
|
+
var parseTime = function(timeString) {
|
45
|
+
var ret = new Date();
|
46
|
+
|
47
|
+
var time = timeString.match(/(\d+)(?::(\d\d))?\s*(p?)/i);
|
48
|
+
if (!time) {
|
49
|
+
return NaN;
|
50
|
+
}
|
51
|
+
var hours = parseInt(time[1], 10);
|
52
|
+
if (hours == 12 && !time[3]) {
|
53
|
+
hours = 0;
|
54
|
+
} else {
|
55
|
+
hours += (hours < 12 && time[3]) ? 12 : 0;
|
56
|
+
}
|
57
|
+
|
58
|
+
ret.setHours(hours);
|
59
|
+
ret.setMinutes(parseInt(time[2], 10) || 0);
|
60
|
+
ret.setSeconds(0, 0);
|
61
|
+
return ret;
|
62
|
+
}
|
63
|
+
|
64
|
+
var handleTimeSelect = function() {
|
65
|
+
var time = parseTime(timeInput.val());
|
66
|
+
|
67
|
+
date.setUTCHours(time.getUTCHours());
|
68
|
+
date.setUTCMinutes(time.getUTCMinutes());
|
69
|
+
|
70
|
+
hiddenInput.val(date.toUTCString());
|
71
|
+
}
|
72
|
+
|
73
|
+
timeInput.clockpicker({
|
74
|
+
autoclose: true,
|
75
|
+
donetext: "Done",
|
76
|
+
twelvehour: true,
|
77
|
+
afterDone: handleTimeSelect,
|
78
|
+
default: date.getHours() + ":" + date.getMinutes()
|
79
|
+
});
|
80
|
+
|
81
|
+
timeInput.val(date.getHours() + ":" + date.getMinutes());
|
82
|
+
|
83
|
+
|
84
|
+
// Make sure we set times when the form is input in case the user typed in values.
|
85
|
+
timeInput.closest("form").submit(function(event) {
|
86
|
+
// TODO(jon): Add code to handle typed in dates.
|
87
|
+
handleTimeSelect();
|
88
|
+
});
|
89
|
+
})();
|
90
|
+
|
91
|
+
|
92
|
+
- else
|
93
|
+
%p.well
|
94
|
+
-# TODO(jon): Make this show an uneditable date and time field.
|
95
|
+
= datetime
|
@@ -0,0 +1,11 @@
|
|
1
|
+
- state ||= nil
|
2
|
+
- states ||= []
|
3
|
+
%ol.progbar{data: { "progbar-steps" => states.length }}
|
4
|
+
- index = states.find_index(state) || -1
|
5
|
+
- states.each_with_index do |cur_state, cur_index|
|
6
|
+
- if index >= cur_index
|
7
|
+
%li.progbar-done
|
8
|
+
= cur_state.to_s.humanize
|
9
|
+
- else
|
10
|
+
%li.progbar-todo
|
11
|
+
= cur_state.to_s.humanize
|
@@ -0,0 +1,67 @@
|
|
1
|
+
-# The following are all available to you here:
|
2
|
+
-# unknown - This is the model passed into the up_model method.
|
3
|
+
-# This attribute is always present in any partial rendered
|
4
|
+
-# by Upmin, and will always match the name of the partial
|
5
|
+
-# *UNLESS* nil, true, or false are passed in.
|
6
|
+
-# upmin_model - This is an Upmin::Model instantiated with unknown
|
7
|
+
-# and is always present.
|
8
|
+
-#
|
9
|
+
-# In general, the upmin_model makes it significantly easier to
|
10
|
+
-# render a view, so I suggest using it. It is way simpler than
|
11
|
+
-# trying to find all associations for a model on your own.
|
12
|
+
-#
|
13
|
+
-# Just an FYI: upmin_model.instance == unknown
|
14
|
+
|
15
|
+
.upmin-model{class: upmin_model.color}
|
16
|
+
-# Display the model title as "Model # ID"
|
17
|
+
%h3
|
18
|
+
= upmin_model.title
|
19
|
+
|
20
|
+
%br
|
21
|
+
%br
|
22
|
+
%h3{style: "color: #333;"}
|
23
|
+
Attributes
|
24
|
+
%hr
|
25
|
+
-# Create a form to wrap the attributes in.
|
26
|
+
-# TODO(jon): Update the URL with a decent helper?
|
27
|
+
= form_for(upmin_model.instance, url: upmin_model_path(upmin_model.path_hash), html: { method: :put }) do |f|
|
28
|
+
|
29
|
+
-# Render each attribute
|
30
|
+
- upmin_model.klass.attributes.each do |attribute|
|
31
|
+
.form-group
|
32
|
+
-# = f.label(attribute.to_s) # Not using this because it drops _id and this isn't always desirable
|
33
|
+
|
34
|
+
%label{for: upmin_model.attribute_form_id(attribute)}
|
35
|
+
= upmin_model.attribute_label_name(attribute)
|
36
|
+
= up_attribute(upmin_model.instance, attribute, locals: { form_builder: f })
|
37
|
+
|
38
|
+
= f.submit("Save", class: "btn btn-primary")
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
- if upmin_model.klass.associations.any?
|
43
|
+
%br
|
44
|
+
%br
|
45
|
+
%br
|
46
|
+
%h3{style: "color: #333;"}
|
47
|
+
Associations
|
48
|
+
%hr
|
49
|
+
- upmin_model.klass.associations.each do |association|
|
50
|
+
%h5
|
51
|
+
= association.to_s.humanize
|
52
|
+
= up_association(upmin_model.instance, association, limit: 5)
|
53
|
+
|
54
|
+
- if upmin_model.klass.actions.any?
|
55
|
+
%br
|
56
|
+
%br
|
57
|
+
%br
|
58
|
+
%h3{style: "color: #333;"}
|
59
|
+
Actions
|
60
|
+
%hr
|
61
|
+
- upmin_model.klass.actions.each do |action|
|
62
|
+
%h4{style: "color: #333;"}
|
63
|
+
= action.to_s.capitalize.humanize
|
64
|
+
= up_action(upmin_model.instance, action)
|
65
|
+
|
66
|
+
|
67
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
%h4
|
2
|
+
Search
|
3
|
+
= klass.humanized_name
|
4
|
+
|
5
|
+
-# Upmin default search uses the ransack gem, see: https://github.com/activerecord-hackery/ransack
|
6
|
+
= form_tag(upmin_search_path(klass: klass.name), method: :get) do
|
7
|
+
- klass.attributes.each do |attr_name|
|
8
|
+
- type = klass.attribute_type(attr_name)
|
9
|
+
|
10
|
+
-# TODO(jon): Make sure these retain their data on a search
|
11
|
+
-# TODO(jon): Break these into partials possibly?
|
12
|
+
- if type == :string
|
13
|
+
.form-group
|
14
|
+
= label(:q, "#{attr_name}_cont", attr_name.to_s.capitalize.gsub("_", " "))
|
15
|
+
= text_field(:q, "#{attr_name}_cont", class: "form-control")
|
16
|
+
|
17
|
+
- if type == :integer
|
18
|
+
.form-group
|
19
|
+
= label(:q, "#{attr_name}_cont", attr_name.to_s.capitalize.gsub("_", " "))
|
20
|
+
.input-group
|
21
|
+
.input-group-addon From
|
22
|
+
= number_field(:q, "#{attr_name}_gteq", class: "form-control")
|
23
|
+
.input-group-addon to
|
24
|
+
= number_field(:q, "#{attr_name}_lteq", class: "form-control")
|
25
|
+
|
26
|
+
- if type == :datetime && Rails::VERSION::MAJOR == 4
|
27
|
+
-# TODO(jon): Add date fields to search boxes for Rails 3
|
28
|
+
.form-group
|
29
|
+
= label(:q, "#{attr_name}_cont", attr_name.to_s.capitalize.gsub("_", " "))
|
30
|
+
%br
|
31
|
+
From
|
32
|
+
= date_field(:q, "#{attr_name}_gteq", class: "form-control")
|
33
|
+
To
|
34
|
+
= date_field(:q, "#{attr_name}_lteq", class: "form-control")
|
35
|
+
|
36
|
+
= submit_tag("Search", class: "btn btn-primary btn-block")
|
37
|
+
= link_to("Clear All", upmin_search_path(klass: klass.name), class: "btn btn-default btn-block")
|
@@ -0,0 +1,8 @@
|
|
1
|
+
%a.search-result-link{href: upmin_model_path(upmin_model.path_hash)}
|
2
|
+
.upmin-model{class: upmin_model.color}
|
3
|
+
%dl.dl-horizontal
|
4
|
+
- @klass.attributes.each do |attribute|
|
5
|
+
%dt
|
6
|
+
= upmin_model.attribute_label_name(attribute)
|
7
|
+
%dd
|
8
|
+
= upmin_model.attribute(attribute)
|
data/config/routes.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Upmin::Engine.routes.draw do
|
2
|
+
root to: "models#dashboard"
|
3
|
+
|
4
|
+
# TODO(jon): Add support for dashboards (or some other main page).
|
5
|
+
# TODO(jon): Move dashboards to an appropriate controller
|
6
|
+
get "/", as: :upmin_dashboard, controller: :models, action: :dashboard
|
7
|
+
|
8
|
+
scope :m do
|
9
|
+
scope "/:klass" do
|
10
|
+
match "/", as: :upmin_search, controller: :models, action: :search, via: [:get, :post]
|
11
|
+
|
12
|
+
scope "/:id" do
|
13
|
+
get "/", as: :upmin_model, controller: :models, action: :show
|
14
|
+
put "/", controller: :models, action: :update
|
15
|
+
|
16
|
+
post "/:method", as: :upmin_action, controller: :models, action: :action
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|