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