hyper_admin 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +157 -1
  3. data/app/assets/javascripts/hyper_admin/angularjs/controllers/form_ctrl.js.coffee +13 -3
  4. data/app/assets/javascripts/hyper_admin/angularjs/directives/form/resource_form.js.coffee +2 -2
  5. data/app/assets/javascripts/hyper_admin/angularjs/directives/table/resource_table.js.coffee +2 -2
  6. data/app/controllers/hyper_admin/resource_classes_controller.rb +8 -3
  7. data/app/views/admin/resources/show.html.erb +1 -1
  8. data/app/views/hyper_admin/resource_classes/index.json.jbuilder +6 -20
  9. data/app/views/hyper_admin/resource_classes/show.json.jbuilder +65 -15
  10. data/lib/hyper_admin.rb +0 -1
  11. data/lib/hyper_admin/application.rb +2 -2
  12. data/lib/hyper_admin/dsl.rb +9 -0
  13. data/lib/hyper_admin/dsl/form.rb +26 -0
  14. data/lib/hyper_admin/dsl/index.rb +26 -0
  15. data/lib/hyper_admin/dsl/parser.rb +42 -0
  16. data/lib/hyper_admin/dsl/show.rb +26 -0
  17. data/lib/hyper_admin/resource.rb +15 -2
  18. data/lib/hyper_admin/resource_collection.rb +14 -2
  19. data/lib/hyper_admin/version.rb +1 -1
  20. data/spec/dummy/app/admin/article.rb +13 -1
  21. data/spec/dummy/app/admin/person.rb +23 -1
  22. data/spec/dummy/db/development.sqlite3 +0 -0
  23. data/spec/dummy/db/test.sqlite3 +0 -0
  24. data/spec/dummy/log/development.log +14665 -0
  25. data/spec/dummy/tmp/cache/assets/development/sass/9e456cee4bd5ae2c5d0cc761be2251d8df6c08d6/navigation.css.sassc +0 -0
  26. data/spec/dummy/tmp/cache/assets/development/sprockets/06089f7f05a42c56b563eb17e0857e5b +0 -0
  27. data/spec/dummy/tmp/cache/assets/development/sprockets/06f8c2a573a416251bf5e507d716a2e1 +0 -0
  28. data/spec/dummy/tmp/cache/assets/development/sprockets/125ec787290ff1586c163c0ca12ba62f +0 -0
  29. data/spec/dummy/tmp/cache/assets/development/sprockets/2188d676be774bd7462bdf2f5f327cb7 +0 -0
  30. data/spec/dummy/tmp/cache/assets/development/sprockets/22b957ba8cbf7e66105a5a7a35a3c248 +0 -0
  31. data/spec/dummy/tmp/cache/assets/development/sprockets/2aa9269bc07919114bffba5e9c919561 +0 -0
  32. data/spec/dummy/tmp/cache/assets/development/sprockets/31e25d39e4c17797d201e2a4243efb4a +0 -0
  33. data/spec/dummy/tmp/cache/assets/development/sprockets/3dfce56bcf85a8a70d6306eace2b2e0e +0 -0
  34. data/spec/dummy/tmp/cache/assets/development/sprockets/4239e532e28c2248e7b8a03ed09fa372 +0 -0
  35. data/spec/dummy/tmp/cache/assets/development/sprockets/50e6229b9d02d1e82dfb4da27439fa19 +0 -0
  36. data/spec/dummy/tmp/cache/assets/development/sprockets/5342641d9e95b0085d3a8171b2a73834 +0 -0
  37. data/spec/dummy/tmp/cache/assets/development/sprockets/561c99db8a97f1f2c4b520c8d19fd98a +0 -0
  38. data/spec/dummy/tmp/cache/assets/development/sprockets/5817d714b843218e26feb1bbf2c64a4a +0 -0
  39. data/spec/dummy/tmp/cache/assets/development/sprockets/5e218fc126519008c7447c3d38048a95 +0 -0
  40. data/spec/dummy/tmp/cache/assets/development/sprockets/6aad5e692897ee309ec7fc1cf8b44cf9 +0 -0
  41. data/spec/dummy/tmp/cache/assets/development/sprockets/835213f339beaa129e265d17814d92a9 +0 -0
  42. data/spec/dummy/tmp/cache/assets/development/sprockets/944445ca0183d48b09ab52f3813a7a73 +0 -0
  43. data/spec/dummy/tmp/cache/assets/development/sprockets/97a00ae9511caadbf68d011ce54d94ca +0 -0
  44. data/spec/dummy/tmp/cache/assets/development/sprockets/99d492ff5654a4d4b238047d3ced9aa9 +0 -0
  45. data/spec/dummy/tmp/cache/assets/development/sprockets/a1f1fbb9115cf49e86ee8970633e5e7d +0 -0
  46. data/spec/dummy/tmp/cache/assets/development/sprockets/bd992c1bfaccb1e64386d36a8dd52993 +0 -0
  47. data/spec/dummy/tmp/cache/assets/development/sprockets/c068853fefe176a729dd75791d6d678c +0 -0
  48. data/spec/dummy/tmp/cache/assets/development/sprockets/c27cec6ddeaab0cafd2edbb61e975a95 +0 -0
  49. data/spec/dummy/tmp/cache/assets/development/sprockets/c397f6c9af946760da8841ad05bd4431 +0 -0
  50. data/spec/dummy/tmp/cache/assets/development/sprockets/c8730a8220ec89fcf6bb2da7a0f35093 +0 -0
  51. data/spec/dummy/tmp/cache/assets/development/sprockets/d11d25b13b947a0b29fdbde5bcff692a +0 -0
  52. data/spec/dummy/tmp/cache/assets/development/sprockets/d1be219698013b776618ed36876f13be +0 -0
  53. data/spec/dummy/tmp/cache/assets/development/sprockets/d8bd2a2fe67a4fcb7001f1fd53912993 +0 -0
  54. data/spec/dummy/tmp/cache/assets/development/sprockets/e012b1b8c25460d77492f11a972eb4af +0 -0
  55. data/spec/dummy/tmp/cache/assets/development/sprockets/e4939e2a59fcc9b3b062fb9c79386107 +0 -0
  56. data/spec/dummy/tmp/cache/assets/development/sprockets/e815f671a8bcf1e651eed8dee00eba51 +0 -0
  57. data/spec/dummy/tmp/cache/assets/development/sprockets/ee7aee67b689b4238ffc9b404b41dc38 +0 -0
  58. data/spec/dummy/tmp/cache/assets/development/sprockets/f0d2b5185b8f10dfc7e41f8c4f379fab +0 -0
  59. metadata +39 -5
  60. data/MIT-LICENSE +0 -20
  61. data/spec/dummy/tmp/pids/server.pid +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 892fb43df29ba674cc93e307fe0da6468f913183
4
- data.tar.gz: 85c2871d89a0bf17ae5a66e209f4d1b86fbf5b40
3
+ metadata.gz: e9caafcf2dc9aa7815c539b2ff800a272bd93c25
4
+ data.tar.gz: fee5bc8be042bcdd4fc478f88c73de2503b346af
5
5
  SHA512:
6
- metadata.gz: 33baa5048c224fc55d765c94e9c3aed2bebbaa83b0a7905fc0236ba6287276c362322d1147d1ed20d29695555f767aba0216593c489a11fea3da18a47a836410
7
- data.tar.gz: a3db6f9479aa407f55115b2a86177c7676591fb95639b1dfe4ac440d2cbf798581062ab44d7bc245c2878b979ed12947686beb52779bbaa4ecf73783233088f4
6
+ metadata.gz: 1fdba92fa922efa18cd304f21c2335c02d32861532778892f6d8006c4b10d7ea64f42fd8031d9ef776e77266136ce7f47caac2947fef8a3e62f4abcf822357ea
7
+ data.tar.gz: c03f7a813cf6774a8d3efb65af36923d04105d0ca3685cd85bf1a3e4491f4542c7e8d67547d7d94e4904611a01bf4f25ea52b30c94cc04b07c24d3fc3cd02295
data/README.md CHANGED
@@ -1,3 +1,159 @@
1
1
  # HyperAdmin
2
2
 
3
- This project rocks and uses MIT-LICENSE.
3
+ HyperAdmin is an admin interface solution for Ruby on Rails. It works pretty
4
+ much as a mountable engine, except it always mounts under _/admin_. This is
5
+ currently not configurable.
6
+
7
+ ## Installation
8
+
9
+ Simply put the gem in your Rails application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'hyper_admin'
13
+ ```
14
+
15
+ Then, install the bundle as usual:
16
+
17
+ ```
18
+ $ bundle install
19
+ ```
20
+
21
+ Finally, mount HyperAdmin into your application. Put this in your
22
+ _config/routes.rb_ file:
23
+
24
+ ```ruby
25
+ HyperAdmin.routes self
26
+ mount HyperAdmin::Engine, at: '/admin'
27
+ ```
28
+
29
+ As mentioned above, you must mount it under _/admin_ for the time being. In a
30
+ later version, this will be configurable.
31
+
32
+ ## Usage
33
+
34
+ To register models that should be accessible through the admin, all you need to
35
+ do is register them with a single line of code. Do this in any Ruby file(s) you
36
+ want under _app/admin/_, such as _app/admin/article.rb_ or
37
+ _app/admin/person.rb_. When the application boots, HyperAdmin will check each
38
+ file under the _app/admin/_. To register a resource:
39
+
40
+ ```ruby
41
+ HyperAdmin.register NameOfYourResource
42
+ ```
43
+
44
+ For instance:
45
+
46
+ ```ruby
47
+ HyperAdmin.register Article
48
+ ```
49
+
50
+ With this in place, you can now visit _/admin/articles_ in your application and
51
+ start managing your articles.
52
+
53
+ ### Configuring views
54
+
55
+ When registering resources, it is also possible to customize what fields should
56
+ show up where and (to some degree) how they should be displayed. For instance,
57
+ we might want to only show the ID, title and publication date of an article in
58
+ the index view. For that, we would pass in a block to `register` and specify
59
+ which columns to display on the index view, like this:
60
+
61
+ ```ruby
62
+ HyperAdmin.register Article do
63
+ index do
64
+ column :id
65
+ column :title
66
+ column :published_at
67
+ end
68
+ end
69
+ ```
70
+
71
+ Note that the order matters here, so this could also be used to force an order
72
+ of attributes to be displayed. In the example above, HyperAdmin would know the
73
+ types of the attributes because of how it is registered in the database.
74
+ However, some types cannot be determined from the database alone. URL fields and
75
+ e-mail fields, for instance, are stored as text, so they will be treated as text
76
+ by default. It is possible to tell HyperAdmin what type of field you're
77
+ specifying by using the `type` keyword:
78
+
79
+ ```ruby
80
+ HyperAdmin.register Article do
81
+ index do
82
+ column :id
83
+ column :title
84
+ column :published_at
85
+ column :author_email, type: :email
86
+ end
87
+ end
88
+ ```
89
+
90
+ The **email** type will create a “mailto”-style link in the index and show
91
+ views, and an `<input type="email">` in the form. Likewise, the “url” type will
92
+ create a regular link in index/show and an `<input type="url">` in forms.
93
+
94
+ Lastly, it is also possible to customize the labeling of the attributes in each
95
+ view using the `human` keyword:
96
+
97
+ ```ruby
98
+ HyperAdmin.register Article do
99
+ index do
100
+ column :id
101
+ column :title
102
+ column :published_at, human: "Publication date"
103
+ column :author_email, type: :email
104
+ end
105
+ end
106
+ ```
107
+
108
+ Note that if `human` is not specified, HyperAdmin will fetch the attribute name
109
+ from the currently active locale, which is recommended most of the time. `human`
110
+ is available for special cases where you want a label other than the localized
111
+ name of the attribute.
112
+
113
+ Customizing the show and form pages work the same way as the index pages, but
114
+ using the `row` and `field` methods instead, respectively. A fully customized
115
+ resource registration might look something like this:
116
+
117
+ ```ruby
118
+ HyperAdmin.register Article do
119
+ index do
120
+ column :id
121
+ column :title
122
+ column :published_at, human: "Publication date"
123
+ end
124
+
125
+ show do
126
+ row :id, human: "Article ID"
127
+ row :title
128
+ row :body
129
+ row :published_at, human: "Publication date"
130
+
131
+ column :author_email, type: :email
132
+ end
133
+
134
+ form do
135
+ field :title
136
+ field :body
137
+ field :published_at
138
+ field :author_email, type: :email
139
+ end
140
+ end
141
+ ```
142
+
143
+ ## Contributing
144
+
145
+ 1. Fork it
146
+ 2. Check out the develop branch (`git checkout develop`)
147
+ 3. Create your feature branch (`git checkout -b feature/my-new-feature`)
148
+ 4. Commit your changes (`git commit -am 'Add my new feature'`)
149
+ 5. Push to the branch (`git push origin my-new-feature`)
150
+ 6. Create a new Pull Request
151
+
152
+ ## Credits
153
+
154
+ Hyper made this. We're a digital communications agency with a passion for good
155
+ code, and if you're using HyperAdmin we probably want to hire you.
156
+
157
+ ## License
158
+
159
+ HyperAdmin is available under the MIT license. See LICENSE.md for more details.
@@ -15,18 +15,28 @@ angular.module("hyperadmin")
15
15
  Restangular.one(target).get().then (resource) =>
16
16
  @resource = resource
17
17
 
18
- $scope.resourceClass.attributes.forEach (attr) =>
18
+ $scope.resourceClass.form_attributes.forEach (attr) =>
19
19
  if attr.type == "date" or attr.type == "datetime"
20
20
  if @resource[attr.key]
21
21
  @resource[attr.key] = new Date @resource[attr.key]
22
22
 
23
23
  [ "id", "created_at", "updated_at" ].forEach (key) ->
24
- _.remove $scope.resourceClass.attributes, (attr) ->
24
+ _.remove $scope.resourceClass.form_attributes, (attr) ->
25
25
  attr.key == key
26
26
 
27
+ prettifyErrors = (errors) ->
28
+ result = { }
29
+ for own attr of errors
30
+ attrSchema = _.find $scope.resourceClass.form_attributes, (attribute) =>
31
+ attribute.key == attr
32
+
33
+ result[attrSchema.human] = errors[attr]
34
+
35
+ result
36
+
27
37
  @submit = =>
28
38
  onError = (response) =>
29
- @errors = response.data
39
+ @errors = prettifyErrors response.data
30
40
 
31
41
  onSuccess = (resource) =>
32
42
  $state.go "^.show", id: resource.id
@@ -6,7 +6,7 @@ angular.module("hyperadmin")
6
6
  <form-errors errors="formCtrl.errors"></form-errors>
7
7
 
8
8
  <form class="form-horizontal" name="form" ng-submit="formCtrl.submit()" novalidate>
9
- <form-input-group ng-repeat="attribute in resourceClass.attributes"
9
+ <form-input-group ng-repeat="attribute in resourceClass.form_attributes"
10
10
  resource="formCtrl.resource"
11
11
  attr="attribute.key"
12
12
  errors="formCtrl.errors[attribute.key]"
@@ -24,4 +24,4 @@ angular.module("hyperadmin")
24
24
  resourceClass: "=resourceClass"
25
25
  controller: ($scope) ->
26
26
  [ "id", "created_at", "updated_at" ].forEach (attr) ->
27
- delete $scope.resourceClass.attributes[attr]
27
+ delete $scope.resourceClass.form_attributes[attr]
@@ -4,14 +4,14 @@ angular.module("hyperadmin")
4
4
  <table class="table table-striped">
5
5
  <thead>
6
6
  <tr>
7
- <th ng-repeat="attribute in resourceClass.attributes">
7
+ <th ng-repeat="attribute in resourceClass.index_attributes">
8
8
  {{ attribute.human }}
9
9
  </th>
10
10
  <th>Actions</th>
11
11
  </tr>
12
12
  </thead>
13
13
  <tbody>
14
- <tr table-row attributes="resourceClass.attributes"
14
+ <tr table-row attributes="resourceClass.index_attributes"
15
15
  ng-repeat="resource in resources" resource="resource">
16
16
  </tr>
17
17
  </tbody>
@@ -4,15 +4,20 @@ module HyperAdmin
4
4
 
5
5
  def index
6
6
  collection = ::HyperAdmin.application.resources
7
- @resource_classes = collection.resources.values.map(&:resource_class)
7
+ @resource_classes = collection.resources.values
8
8
 
9
9
  respond_with @resource_classes
10
10
  end
11
11
 
12
12
  def show
13
13
  collection = ::HyperAdmin.application.resources
14
- resource_classes = collection.resources.values.map(&:resource_class)
15
- @resource_class = resource_classes.find { |c| c.model_name.route_key == params[:id] }
14
+ resource_classes = collection.resources.values
15
+
16
+ @resource_class = resource_classes.find do |c|
17
+ c.resource_class.model_name.route_key == params[:id]
18
+ end
19
+
20
+ fail ActiveRecord::RecordNotFound unless @resource_class
16
21
 
17
22
  respond_with @resource_class
18
23
  end
@@ -15,7 +15,7 @@
15
15
  <div class="col-xs-12">
16
16
  <div class="well">
17
17
  <dl class="dl-horizontal">
18
- <dt ng-repeat-start="attribute in showCtrl.resource_class.attributes">
18
+ <dt ng-repeat-start="attribute in showCtrl.resource_class.show_attributes">
19
19
  {{ attribute.human }}
20
20
  </dt>
21
21
  <dd ng-repeat-end>
@@ -1,23 +1,9 @@
1
- def infer_type_from_attribute(resource_class, attribute)
2
- return :email if attribute == "email"
3
- return :url if attribute == "url"
4
-
5
- resource_class.columns_hash[attribute].type
6
- end
7
-
8
1
  json.array! @resource_classes do |resource_class|
9
- json.menu_label resource_class.model_name.human(count: 2)
10
- json.singular resource_class.model_name.singular
11
- json.singular_human resource_class.model_name.human(count: 1)
12
- json.plural resource_class.model_name.plural
13
- json.plural_human resource_class.model_name.human(count: 2)
2
+ real_resource = resource_class.resource_class
14
3
 
15
- attributes = resource_class.attribute_names.map do |attr|
16
- {
17
- key: attr,
18
- human: resource_class.human_attribute_name(attr),
19
- type: infer_type_from_attribute(resource_class, attr)
20
- }
21
- end
22
- json.attributes attributes
4
+ json.menu_label real_resource.model_name.human(count: 2)
5
+ json.singular real_resource.model_name.singular
6
+ json.singular_human real_resource.model_name.human(count: 1)
7
+ json.plural real_resource.model_name.plural
8
+ json.plural_human real_resource.model_name.human(count: 2)
23
9
  end
@@ -1,21 +1,71 @@
1
1
  def infer_type_from_attribute(resource_class, attribute)
2
- return :email if attribute == "email"
3
- return :url if attribute == "url"
2
+ attribute = attribute.to_s
4
3
 
5
4
  resource_class.columns_hash[attribute].type
6
5
  end
7
6
 
8
- json.menu_label @resource_class.model_name.human(count: 2)
9
- json.singular @resource_class.model_name.singular
10
- json.singular_human @resource_class.model_name.human(count: 1)
11
- json.plural @resource_class.model_name.plural
12
- json.plural_human @resource_class.model_name.human(count: 2)
7
+ real_resource = @resource_class.resource_class
13
8
 
14
- attributes = @resource_class.attribute_names.map do |attr|
15
- {
16
- key: attr,
17
- human: @resource_class.human_attribute_name(attr),
18
- type: infer_type_from_attribute(@resource_class, attr)
19
- }
20
- end
21
- json.attributes attributes
9
+ json.menu_label real_resource.model_name.human(count: 2)
10
+ json.singular real_resource.model_name.singular
11
+ json.singular_human real_resource.model_name.human(count: 1)
12
+ json.plural real_resource.model_name.plural
13
+ json.plural_human real_resource.model_name.human(count: 2)
14
+
15
+ show_attributes = if @resource_class.show_config
16
+ @resource_class.show_config.each.map do |config|
17
+ {
18
+ key: config[:attribute],
19
+ human: config[:human],
20
+ type: config[:type]
21
+ }
22
+ end
23
+ else
24
+ real_resource.attribute_names.map do |attr|
25
+ {
26
+ key: attr,
27
+ human: real_resource.human_attribute_name(attr),
28
+ type: infer_type_from_attribute(real_resource, attr)
29
+ }
30
+ end
31
+ end
32
+
33
+ index_attributes = if @resource_class.index_config
34
+ @resource_class.index_config.each.map do |config|
35
+ {
36
+ key: config[:attribute],
37
+ human: config[:human],
38
+ type: config[:type]
39
+ }
40
+ end
41
+ else
42
+ real_resource.attribute_names.map do |attr|
43
+ {
44
+ key: attr,
45
+ human: real_resource.human_attribute_name(attr),
46
+ type: infer_type_from_attribute(real_resource, attr)
47
+ }
48
+ end
49
+ end
50
+
51
+ form_attributes = if @resource_class.form_config
52
+ @resource_class.form_config.each.map do |config|
53
+ {
54
+ key: config[:attribute],
55
+ human: config[:human],
56
+ type: config[:type]
57
+ }
58
+ end
59
+ else
60
+ real_resource.attribute_names.map do |attr|
61
+ {
62
+ key: attr,
63
+ human: real_resource.human_attribute_name(attr),
64
+ type: infer_type_from_attribute(real_resource, attr)
65
+ }
66
+ end
67
+ end
68
+
69
+ json.show_attributes show_attributes
70
+ json.index_attributes index_attributes
71
+ json.form_attributes form_attributes
@@ -10,7 +10,6 @@ module HyperAdmin
10
10
 
11
11
  delegate :register, to: :application
12
12
  delegate :routes, to: :application
13
- delegate :setup, to: :application
14
13
 
15
14
  def application
16
15
  @application ||= HyperAdmin::Application.new
@@ -13,8 +13,8 @@ module HyperAdmin
13
13
  prevent_rails_autoloading_load_paths
14
14
  end
15
15
 
16
- def register(resource_class)
17
- resource = @resources.add resource_class
16
+ def register(resource_class, &block)
17
+ resource = @resources.add resource_class, &block
18
18
  create_resource_controller resource
19
19
  end
20
20
 
@@ -0,0 +1,9 @@
1
+ require 'hyper_admin/dsl/parser'
2
+ require 'hyper_admin/dsl/show'
3
+ require 'hyper_admin/dsl/index'
4
+ require 'hyper_admin/dsl/form'
5
+
6
+ module HyperAdmin
7
+ module DSL
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ module HyperAdmin
2
+ module DSL
3
+ class Form
4
+
5
+ def initialize(resource_class)
6
+ @resource_class = resource_class
7
+ @fields = []
8
+ end
9
+
10
+ def field(attribute, type: infer_type(attribute), human: human_name(attribute))
11
+ @fields << { attribute: attribute, type: type, human: human }
12
+ end
13
+
14
+ private
15
+
16
+ def infer_type(attribute)
17
+ @resource_class.columns_hash[attribute.to_s].type
18
+ end
19
+
20
+ def human_name(attribute)
21
+ @resource_class.human_attribute_name attribute
22
+ end
23
+
24
+ end
25
+ end
26
+ end