effective_style_guide 1.0.0
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/MIT-LICENSE +20 -0
- data/README.md +366 -0
- data/Rakefile +20 -0
- data/app/controllers/effective/style_guide_controller.rb +19 -0
- data/app/models/effective/access_denied.rb +17 -0
- data/app/models/effective/datatables/style_guide.rb +44 -0
- data/app/models/effective/style_guide.rb +28 -0
- data/app/views/effective/style_guide/_alerts.html.haml +14 -0
- data/app/views/effective/style_guide/_breadcrumbs.html.haml +12 -0
- data/app/views/effective/style_guide/_buttons.html.haml +52 -0
- data/app/views/effective/style_guide/_effective_datatable.html.haml +5 -0
- data/app/views/effective/style_guide/_form_horizontal.html.haml +38 -0
- data/app/views/effective/style_guide/_form_inline.html.haml +16 -0
- data/app/views/effective/style_guide/_form_vertical.html.haml +36 -0
- data/app/views/effective/style_guide/_jumbotron.html.haml +5 -0
- data/app/views/effective/style_guide/_labels.html.haml +37 -0
- data/app/views/effective/style_guide/_list_groups.html.haml +23 -0
- data/app/views/effective/style_guide/_modals.html.haml +69 -0
- data/app/views/effective/style_guide/_navs.html.haml +33 -0
- data/app/views/effective/style_guide/_pagination.html.haml +38 -0
- data/app/views/effective/style_guide/_panels.html.haml +36 -0
- data/app/views/effective/style_guide/_progress_bars.html.haml +30 -0
- data/app/views/effective/style_guide/_tables.html.haml +15 -0
- data/app/views/effective/style_guide/_thumbnails.html.haml +17 -0
- data/app/views/effective/style_guide/_typography.html.haml +20 -0
- data/app/views/effective/style_guide/_wells.html.haml +3 -0
- data/app/views/effective/style_guide/show.html.haml +88 -0
- data/config/routes.rb +11 -0
- data/lib/effective_style_guide/engine.rb +11 -0
- data/lib/effective_style_guide/version.rb +3 -0
- data/lib/effective_style_guide.rb +20 -0
- data/lib/generators/effective_style_guide/install_generator.rb +16 -0
- data/lib/generators/templates/README +1 -0
- data/lib/generators/templates/effective_style_guide.rb +26 -0
- metadata +136 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cc683801962056027264e975207cb98e85a9064b
|
4
|
+
data.tar.gz: da9b1084ddee2faf65a7f333f817118b3a227393
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7caed712627d44e591b6d58083231612f3a3f4732981a9f45f39ccd6f8f665050af71d93efa8d4b12307bf0bfb325e3f6c5c1821d1bacbe8e796d22d4c8dcd0a
|
7
|
+
data.tar.gz: 79a9cab7c6068d88c8f0ae52fdffdada6de4d2ddb353073df69063590fa38e5989824a5d3a1cc3ba9adb1b80de8403a4a561573aab333334f212d5e950e8e91c
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 Code and Effect Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,366 @@
|
|
1
|
+
# Effective Style Guide
|
2
|
+
|
3
|
+
Ensure that your custom CSS theme looks good with all Twitter Bootstrap3 html components.
|
4
|
+
|
5
|
+
Creates a /styleguide page that renders the correct HTML for all bootstrap3 (v3.2.0) components.
|
6
|
+
|
7
|
+
Use this page to ensure that your custom CSS theme looks good with the bootstrap3 components.
|
8
|
+
|
9
|
+
Create a _my_component.html.erb partial in the /effective/style_guide/ directory to add your own custom components.
|
10
|
+
|
11
|
+
Works with simple_form to ensure that the generated form HTML matches the bootstrap3 HTML.
|
12
|
+
|
13
|
+
|
14
|
+
## Getting Started
|
15
|
+
|
16
|
+
Add to your Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'effective_style_guide'
|
20
|
+
```
|
21
|
+
|
22
|
+
Run the bundle command to install it:
|
23
|
+
|
24
|
+
```console
|
25
|
+
bundle install
|
26
|
+
```
|
27
|
+
|
28
|
+
Then run the generator:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
rails generate effective_style_guide:install
|
32
|
+
```
|
33
|
+
|
34
|
+
The generator will install an initializer which describes all configuration options.
|
35
|
+
|
36
|
+
You must include the Twitter Bootstrap3 Javascript and CSS assets on your own. They are not included with this gem.
|
37
|
+
|
38
|
+
## Usage
|
39
|
+
|
40
|
+
Visit /styleguide to test how the bootstrap3 components look with your site's design (css theme).
|
41
|
+
|
42
|
+
|
43
|
+
### Add Custom Components
|
44
|
+
|
45
|
+
Create a _my_component.html.erb partial in the app/views/effective/style_guide/ directory.
|
46
|
+
|
47
|
+
This file will be automatically detected and included in the /styleguide page.
|
48
|
+
|
49
|
+
|
50
|
+
### simple_form
|
51
|
+
|
52
|
+
simple_form (https://github.com/plataformatec/simple_form) is a pretty good FormBuilder gem.
|
53
|
+
|
54
|
+
At this time of writing, the latest simple_form v3.1.0.rc2 includes a bootstrap3 config/initializer that gets very close to generating the correct bootstrap3 form HTML (as per bootstrap's example page).
|
55
|
+
|
56
|
+
Very close, but not quite perfect.
|
57
|
+
|
58
|
+
It is also somewhat cumbersome to work with vertical, horizontal and inline forms from within the same app.
|
59
|
+
|
60
|
+
Due to these limitations, we have created our own custom config/initializer that does generate the correct bootstrap3 form HTML.
|
61
|
+
|
62
|
+
Here is the initializer:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
SimpleForm.setup do |config|
|
66
|
+
config.error_notification_class = 'alert alert-danger'
|
67
|
+
config.button_class = 'btn btn-primary'
|
68
|
+
config.boolean_label_class = nil
|
69
|
+
|
70
|
+
config.boolean_style = :nested
|
71
|
+
config.browser_validations = true
|
72
|
+
|
73
|
+
config.form_class = ''
|
74
|
+
config.default_wrapper = :vertical_form
|
75
|
+
|
76
|
+
config.wrapper_mappings = {
|
77
|
+
:boolean => :vertical_boolean,
|
78
|
+
:check_boxes => :vertical_radio_and_checkboxes,
|
79
|
+
:radio_buttons => :vertical_radio_and_checkboxes,
|
80
|
+
|
81
|
+
:horizontal_form => {
|
82
|
+
:boolean => :horizontal_boolean,
|
83
|
+
:check_boxes => :horizontal_radio_and_checkboxes,
|
84
|
+
:radio_buttons => :horizontal_radio_and_checkboxes
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
89
|
+
b.use :html5
|
90
|
+
b.use :placeholder
|
91
|
+
b.optional :maxlength
|
92
|
+
b.optional :pattern
|
93
|
+
b.optional :min_max
|
94
|
+
b.optional :readonly
|
95
|
+
b.use :label, class: 'control-label'
|
96
|
+
|
97
|
+
b.use :input, class: 'form-control'
|
98
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
99
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
100
|
+
end
|
101
|
+
|
102
|
+
config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
103
|
+
b.use :html5
|
104
|
+
b.use :placeholder
|
105
|
+
b.optional :maxlength
|
106
|
+
b.optional :readonly
|
107
|
+
b.use :label, class: 'control-label'
|
108
|
+
|
109
|
+
b.use :input
|
110
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
111
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
112
|
+
end
|
113
|
+
|
114
|
+
config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
115
|
+
b.use :html5
|
116
|
+
b.optional :readonly
|
117
|
+
|
118
|
+
b.wrapper tag: 'div', class: 'checkbox' do |ba|
|
119
|
+
ba.use :label_input
|
120
|
+
end
|
121
|
+
|
122
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
123
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
124
|
+
end
|
125
|
+
|
126
|
+
config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
127
|
+
b.use :html5
|
128
|
+
b.optional :readonly
|
129
|
+
b.use :label_input, :class => 'control-label'
|
130
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
131
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
132
|
+
end
|
133
|
+
|
134
|
+
config.wrappers :vertical_inline_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
135
|
+
b.use :html5
|
136
|
+
b.optional :readonly
|
137
|
+
|
138
|
+
b.use :label, class: 'control-label'
|
139
|
+
|
140
|
+
b.wrapper tag: 'div', class: 'inline-radio-or-checkboxes' do |ba|
|
141
|
+
ba.use :input
|
142
|
+
end
|
143
|
+
|
144
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
145
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
146
|
+
end
|
147
|
+
|
148
|
+
config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
149
|
+
b.use :html5
|
150
|
+
b.use :placeholder
|
151
|
+
b.optional :maxlength
|
152
|
+
b.optional :pattern
|
153
|
+
b.optional :min_max
|
154
|
+
b.optional :readonly
|
155
|
+
b.use :label, class: 'col-sm-3 control-label'
|
156
|
+
|
157
|
+
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
158
|
+
ba.use :input, class: 'form-control'
|
159
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
160
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
165
|
+
b.use :html5
|
166
|
+
b.use :placeholder
|
167
|
+
b.optional :maxlength
|
168
|
+
b.optional :readonly
|
169
|
+
b.use :label, class: 'col-sm-3 control-label'
|
170
|
+
|
171
|
+
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
172
|
+
ba.use :input
|
173
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
174
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
179
|
+
b.use :html5
|
180
|
+
b.optional :readonly
|
181
|
+
|
182
|
+
b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
|
183
|
+
wr.wrapper tag: 'div', class: 'checkbox' do |ba|
|
184
|
+
ba.use :label_input, class: 'col-sm-9'
|
185
|
+
end
|
186
|
+
|
187
|
+
wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
188
|
+
wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
193
|
+
b.use :html5
|
194
|
+
b.optional :readonly
|
195
|
+
|
196
|
+
b.use :label, class: 'col-sm-3 control-label'
|
197
|
+
|
198
|
+
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
199
|
+
ba.use :input
|
200
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
201
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
config.wrappers :horizontal_inline_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
206
|
+
b.use :html5
|
207
|
+
b.optional :readonly
|
208
|
+
|
209
|
+
b.use :label, class: 'col-sm-3 control-label'
|
210
|
+
|
211
|
+
b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
|
212
|
+
ba.wrapper tag: 'div', :class => 'inline-radio-or-checkboxes' do |bb|
|
213
|
+
bb.use :input
|
214
|
+
end
|
215
|
+
|
216
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
217
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
222
|
+
b.use :html5
|
223
|
+
b.use :placeholder
|
224
|
+
b.optional :maxlength
|
225
|
+
b.optional :pattern
|
226
|
+
b.optional :min_max
|
227
|
+
b.optional :readonly
|
228
|
+
b.use :label, class: 'sr-only'
|
229
|
+
|
230
|
+
b.use :input, class: 'form-control'
|
231
|
+
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
232
|
+
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
```
|
237
|
+
|
238
|
+
To create a bootstrap3 vertical_form:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
= simple_form_for(@post) do |f|
|
242
|
+
# one or more inputs....
|
243
|
+
= f.buttom :submit
|
244
|
+
```
|
245
|
+
|
246
|
+
To create a bootstrap3 horizontal_form:
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
= simple_form_for(@post, :html => {:class => 'form-horizontal'}, :wrapper => :horizontal_form, :wrapper_mappings => SimpleForm.wrapper_mappings[:horizontal_form]) do |f|
|
250
|
+
# one or more inputs....
|
251
|
+
.form-group
|
252
|
+
.col-sm-offset-3.col-sm-9= f.button :submit
|
253
|
+
```
|
254
|
+
|
255
|
+
To create a bootstrap3 inline_form:
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
= simple_form_for(@post, :html => {:class => 'form-inline'}, :wrapper => :inline_form) do |f|
|
259
|
+
# one or more inputs....
|
260
|
+
= f.button :submit
|
261
|
+
```
|
262
|
+
|
263
|
+
In all 3 of the above examples, the proper wrappers will be used to generate the correct HTML for every type of form field.
|
264
|
+
|
265
|
+
This includes the frustrating booleans, radio and checkbox groups.
|
266
|
+
|
267
|
+
One gotcha, if you'd like to use the 'Inline checkboxes and radios' component, you will need to pass a wrapper to the f.input.
|
268
|
+
|
269
|
+
For a vertical_form or inline_form:
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
= f.input :favorite_drink, :as => :check_boxes, :wrapper => :vertical_inline_radio_and_checkboxes, :collection => ['Water', 'Tea', 'Coffee', 'Soda']
|
273
|
+
```
|
274
|
+
|
275
|
+
For a horizontal_form:
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
= f.input :favorite_drink, :as => :check_boxes, :wrapper => :horizontal_inline_radio_and_checkboxes, :collection => ['Water', 'Tea', 'Coffee', 'Soda']
|
279
|
+
```
|
280
|
+
|
281
|
+
And add the following CSS:
|
282
|
+
|
283
|
+
```css
|
284
|
+
form .inline-radio-or-checkboxes > span {
|
285
|
+
display: inline-block;
|
286
|
+
margin: 0px 10px 0px 0px;
|
287
|
+
}
|
288
|
+
```
|
289
|
+
|
290
|
+
|
291
|
+
## Authorization
|
292
|
+
|
293
|
+
All authorization checks are handled via the config.authorization_method found in the config/initializers/ file.
|
294
|
+
|
295
|
+
It is intended for flow through to CanCan or Pundit, but that is not required.
|
296
|
+
|
297
|
+
This method is called by all controller actions with the appropriate action and resource
|
298
|
+
|
299
|
+
Action will be `:show` and the resource `Effective::StyleGuide.new()`
|
300
|
+
|
301
|
+
The authorization method is defined in the initializer file:
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
# As a Proc (with CanCan)
|
305
|
+
config.authorization_method = Proc.new { |controller, action, resource| authorize!(action, resource) }
|
306
|
+
```
|
307
|
+
|
308
|
+
```ruby
|
309
|
+
# As a Custom Method
|
310
|
+
config.authorization_method = :my_authorization_method
|
311
|
+
```
|
312
|
+
|
313
|
+
and then in your application_controller.rb:
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
def my_authorization_method(action, resource)
|
317
|
+
current_user.is?(:admin) || EffectivePunditPolicy.new(current_user, resource).send('#{action}?')
|
318
|
+
end
|
319
|
+
```
|
320
|
+
|
321
|
+
or disabled entirely:
|
322
|
+
|
323
|
+
```ruby
|
324
|
+
config.authorization_method = false
|
325
|
+
```
|
326
|
+
|
327
|
+
If the method or proc returns false (user is not authorized) an Effective::AccessDenied exception will be raised
|
328
|
+
|
329
|
+
You can rescue from this exception by adding the following to your application_controller.rb:
|
330
|
+
|
331
|
+
```ruby
|
332
|
+
rescue_from Effective::AccessDenied do |exception|
|
333
|
+
respond_to do |format|
|
334
|
+
format.html { render 'static_pages/access_denied', :status => 403 }
|
335
|
+
format.any { render :text => 'Access Denied', :status => 403 }
|
336
|
+
end
|
337
|
+
end
|
338
|
+
```
|
339
|
+
|
340
|
+
## License
|
341
|
+
|
342
|
+
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
343
|
+
|
344
|
+
Code and Effect is the product arm of [AgileStyle](http://www.agilestyle.com/), an Edmonton-based shop that specializes in building custom web applications with Ruby on Rails.
|
345
|
+
|
346
|
+
|
347
|
+
## Testing
|
348
|
+
|
349
|
+
The test suite for this gem is unfortunately not yet complete.
|
350
|
+
|
351
|
+
Run tests by:
|
352
|
+
|
353
|
+
```ruby
|
354
|
+
rake spec
|
355
|
+
```
|
356
|
+
|
357
|
+
## Contributing
|
358
|
+
|
359
|
+
1. Fork it
|
360
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
361
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
362
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
363
|
+
5. Bonus points for test coverage
|
364
|
+
6. Create new Pull Request
|
365
|
+
|
366
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Testing tasks
|
9
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
10
|
+
load 'rails/tasks/engine.rake'
|
11
|
+
|
12
|
+
Bundler::GemHelper.install_tasks
|
13
|
+
|
14
|
+
require 'rspec/core'
|
15
|
+
require 'rspec/core/rake_task'
|
16
|
+
|
17
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
18
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
19
|
+
|
20
|
+
task :default => :spec
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Effective
|
2
|
+
class StyleGuideController < ApplicationController
|
3
|
+
layout EffectiveStyleGuide.layout || 'application'
|
4
|
+
|
5
|
+
def show
|
6
|
+
@partials = view_paths.map { |path| Dir["#{path}/effective/style_guide/_**"] }.flatten.map do |path|
|
7
|
+
name = File.basename(path)
|
8
|
+
name[1...name.index('.') || name.length] # remove the _ and .html.haml
|
9
|
+
end.uniq.sort
|
10
|
+
|
11
|
+
@partials.delete('effective_datatable') unless defined?(EffectiveDatatables)
|
12
|
+
|
13
|
+
@page_title ||= 'Style Guide'
|
14
|
+
|
15
|
+
EffectiveStyleGuide.authorized?(self, :show, Effective::StyleGuide.new())
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
unless defined?(Effective::AccessDenied)
|
2
|
+
module Effective
|
3
|
+
class AccessDenied < StandardError
|
4
|
+
attr_reader :action, :subject
|
5
|
+
|
6
|
+
def initialize(message = nil, action = nil, subject = nil)
|
7
|
+
@message = message
|
8
|
+
@action = action
|
9
|
+
@subject = subject
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
@message || I18n.t(:'unauthorized.default', :default => 'Access Denied')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
if defined?(EffectiveDatatables)
|
2
|
+
module Effective
|
3
|
+
module Datatables
|
4
|
+
class StyleGuide < Effective::Datatable
|
5
|
+
array_column :id, :width => '10%'
|
6
|
+
array_column :material, :filter => {:type => :select, :values => ['Stainless Steel', 'Copper', 'Cast Iron', 'Composite']}
|
7
|
+
array_column :bowl, :filter => {:type => :select, :values => ['Single Bowl', 'Double Bowl', 'Triple Bowl']}
|
8
|
+
array_column :name
|
9
|
+
array_column :actions, :filter => false, :sortable => false do
|
10
|
+
[link_to('View', '#'), link_to('Edit', '#')].join(' - ').html_safe
|
11
|
+
end
|
12
|
+
|
13
|
+
def collection
|
14
|
+
[
|
15
|
+
[1, 'Stainless Steel', 'Single Bowl', 'KOHLER Staccato'],
|
16
|
+
[2, 'Stainless Steel', 'Double Bowl', 'KOHLER Vault Undercounter'],
|
17
|
+
[3, 'Stainless Steel', 'Triple Bowl', 'KRAUS All-In-One'],
|
18
|
+
[4, 'Stainless Steel', 'Single Bowl', 'KOHLER Vault Dual Mount'],
|
19
|
+
[5, 'Stainless Steel', 'Single Bowl', 'KRAUS All-In-One Undermount'],
|
20
|
+
[6, 'Stainless Steel', 'Double Bowl', 'Glacier Bay All-in-One'],
|
21
|
+
[7, 'Stainless Steel', 'Single Bowl', 'Elkay Neptune'],
|
22
|
+
[8, 'Copper', 'Single Bowl', 'ECOSINKS Apron Front Dual Mount'],
|
23
|
+
[9, 'Copper', 'Double Bowl', 'ECOSINKS Dual Mount Front Hammered'],
|
24
|
+
[10, 'Copper', 'Triple Bowl', 'Glarier Bay Undermount'],
|
25
|
+
[11, 'Copper', 'Single Bowl', 'Whitehaus Undermount'],
|
26
|
+
[12, 'Copper', 'Double Bowl', 'Belle Foret Apron Front'],
|
27
|
+
[13, 'Copper', 'Double Bowl', 'Pegasus Dual Mount'],
|
28
|
+
[14, 'Cast Iron', 'Double Bowl', 'KOHLER Whitehaven'],
|
29
|
+
[15, 'Cast Iron', 'Triple Bowl', 'KOHLER Hartland'],
|
30
|
+
[16, 'Cast Iron', 'Single Bowl', 'KOHLER Cape Dory Undercounter'],
|
31
|
+
[17, 'Cast Iron', 'Double Bowl', 'KOLER Bakersfield'],
|
32
|
+
[18, 'Cast Iron', 'Double Bowl', 'American Standard Offset'],
|
33
|
+
[19, 'Cast Iron', 'Single Bowl', 'Brookfield Top'],
|
34
|
+
[20, 'Composite', 'Single Bowl', 'Blanco Diamond Undermount'],
|
35
|
+
[21, 'Composite', 'Double Bowl', 'Mont Blanc Waterbrook'],
|
36
|
+
[22, 'Composite', 'Triple Bowl', 'Pegasus Triple Mount'],
|
37
|
+
[23, 'Composite', 'Single Bowl', 'Swanstone Dual Mount']
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Effective
|
2
|
+
class StyleGuide < ActiveRecord::Base
|
3
|
+
def self.columns
|
4
|
+
@columns ||= [];
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.column(name, sql_type = nil, default = nil, null = true)
|
8
|
+
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
|
9
|
+
end
|
10
|
+
|
11
|
+
column :id, :integer
|
12
|
+
|
13
|
+
column :title, :string
|
14
|
+
column :email, :string
|
15
|
+
column :password, :string
|
16
|
+
column :number, :integer
|
17
|
+
column :range, :integer
|
18
|
+
column :category, :string
|
19
|
+
column :content, :text
|
20
|
+
column :archived, :boolean
|
21
|
+
column :drink, :string
|
22
|
+
column :food, :string
|
23
|
+
column :price, :integer
|
24
|
+
|
25
|
+
validates_presence_of :id, :title, :email, :password, :number, :range, :category, :content, :archived, :drink, :food, :price
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
- variations = ['Success', 'Info', 'Notice', 'Alert', 'Warning', 'Danger']
|
2
|
+
|
3
|
+
- variations.each do |variation|
|
4
|
+
.alert{:class => "alert-#{variation.downcase}"}
|
5
|
+
= "This is a #{variation.downcase} alert with a "
|
6
|
+
%a.alert-link{:href => '#'} link to somewhere
|
7
|
+
|
8
|
+
- variations.each do |variation|
|
9
|
+
.alert.alert-dismissable{:class => "alert-#{variation.downcase}"}
|
10
|
+
%button.close{:type => 'button', 'data-dismiss' => 'alert'}
|
11
|
+
%span ×
|
12
|
+
%span.sr-only Close
|
13
|
+
%strong= variation
|
14
|
+
= "This is a dismissable #{variation.downcase} alert"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
- variations = ['Default', 'Primary', 'Success', 'Info', 'Warning', 'Danger']
|
2
|
+
|
3
|
+
%p
|
4
|
+
- variations.each do |variation|
|
5
|
+
.btn{:class => "btn-#{variation.downcase}"}= variation
|
6
|
+
%a.glyphicon.glyphicon-remove{:href => '#'}
|
7
|
+
|
8
|
+
%p
|
9
|
+
.btn-group
|
10
|
+
%button.btn.btn-default{:type => 'button'} Left
|
11
|
+
%button.btn.btn-default{:type => 'button'} Middle
|
12
|
+
%button.btn.btn-default{:type => 'button'} Right
|
13
|
+
|
14
|
+
%p
|
15
|
+
- variations.each do |variation|
|
16
|
+
.btn-group
|
17
|
+
%button.btn.dropdown-toggle{'data-toggle' => 'dropdown', :class => "btn-#{variation.downcase}"}
|
18
|
+
= variation
|
19
|
+
%span.caret
|
20
|
+
%ul.dropdown-menu{:role => 'menu'}
|
21
|
+
%li= link_to 'First', '#'
|
22
|
+
%li= link_to 'Second', '#'
|
23
|
+
%li= link_to 'Third', '#'
|
24
|
+
%li.divider
|
25
|
+
%li= link_to 'Separated', '#'
|
26
|
+
|
27
|
+
%p
|
28
|
+
.btn-toolbar{:role => 'toolbar'}
|
29
|
+
.btn-group
|
30
|
+
%button.btn.btn-default{:type => 'button'} 1
|
31
|
+
%button.btn.btn-default{:type => 'button'} 2
|
32
|
+
%button.btn.btn-default{:type => 'button'} 3
|
33
|
+
.btn-group
|
34
|
+
%button.btn.btn-default{:type => 'button'} 4
|
35
|
+
%button.btn.btn-default{:type => 'button'} 5
|
36
|
+
%button.btn.btn-default{:type => 'button'} 6
|
37
|
+
.btn-group
|
38
|
+
%button.btn.btn-default{:type => 'button'} 7
|
39
|
+
|
40
|
+
%p
|
41
|
+
- variations.each do |variation|
|
42
|
+
.btn-group
|
43
|
+
%button.btn{:class => "btn-#{variation.downcase}"}=variation
|
44
|
+
%button.btn.dropdown-toggle{'data-toggle' => 'dropdown', :class => "btn-#{variation.downcase}"}
|
45
|
+
%span.caret
|
46
|
+
%span.sr-only Toggle Dropdown
|
47
|
+
%ul.dropdown-menu{:role => 'menu'}
|
48
|
+
%li= link_to 'First', '#'
|
49
|
+
%li= link_to 'Second', '#'
|
50
|
+
%li= link_to 'Third', '#'
|
51
|
+
%li.divider
|
52
|
+
%li= link_to 'Separated', '#'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
= simple_form_for Effective::StyleGuide.new(), :html => {:class => 'form-horizontal'}, :wrapper => :horizontal_form, :wrapper_mappings => SimpleForm.wrapper_mappings[:horizontal_form], :url => '/' do |f|
|
2
|
+
= f.input :title, :hint => 'please enter a title (this is a standard text field)'
|
3
|
+
= f.input :email, :hint => 'please enter an email address (this is an email field)'
|
4
|
+
= f.input :password, :hint => 'please enter a password (this is a password field)'
|
5
|
+
- if defined?(EffectiveOrders)
|
6
|
+
= f.input :price, :as => :price, :hint => 'please enter a price (this is a price field from EffectiveOrders)'
|
7
|
+
= f.input :number, :hint => 'please enter a number (this is a number field)'
|
8
|
+
= f.input :range, :as => :range, :hint => 'please enter a number range (this is a range field)'
|
9
|
+
= f.input :category, :as => :select, :collection => 10.times.map { |x| "Category #{x}"}, :hint => 'please select a category (this is a select field)'
|
10
|
+
= f.input :drink, :as => :check_boxes, :wrapper => :horizontal_inline_radio_and_checkboxes, :collection => ['Water', 'Tea', 'Coffee', 'Soda'], :hint => 'please select one or more drinks (this is a check_boxes :wrapper => :horizontal_inline_radio_and_checkboxes field)'
|
11
|
+
= f.input :food, :as => :radio_buttons, :wrapper => :horizontal_inline_radio_and_checkboxes, :collection => ['Pasta', 'Rice', 'Potato', 'Couscous'], :hint => 'please select one food (this is a radio_buttons :wrapper => :horizontal_inline_radio_and_checkboxes field)'
|
12
|
+
= f.input :content, :hint => 'please enter a whole bunch of content (this is a textarea)'
|
13
|
+
= f.input :archived, :hint => 'please select true or false (this is a boolean field)'
|
14
|
+
= f.input :drink, :as => :check_boxes, :collection => ['Water', 'Tea', 'Coffee', 'Soda'], :hint => 'please select one or more drinks (this is a check_boxes field)'
|
15
|
+
= f.input :food, :as => :radio_buttons, :collection => ['Pasta', 'Rice', 'Potato', 'Couscous'], :hint => 'please select one food (this is a radio_buttons field)'
|
16
|
+
.form-group
|
17
|
+
.col-sm-offset-3.col-sm-9= f.button :submit
|
18
|
+
|
19
|
+
%hr
|
20
|
+
.inline-example Form Horizontal Invalid State
|
21
|
+
|
22
|
+
= simple_form_for Effective::StyleGuide.new().tap { |s| s.valid? }, :html => {:class => 'form-horizontal'}, :wrapper => :horizontal_form, :wrapper_mappings => SimpleForm.wrapper_mappings[:horizontal_form], :url => '/' do |f|
|
23
|
+
= f.input :title, :hint => 'please enter a title (this is a standard text field)'
|
24
|
+
= f.input :email, :hint => 'please enter an email address (this is an email field)'
|
25
|
+
= f.input :password, :hint => 'please enter a password (this is a password field)'
|
26
|
+
- if defined?(EffectiveOrders)
|
27
|
+
= f.input :price, :as => :price, :hint => 'please enter a price (this is a price field from EffectiveOrders)'
|
28
|
+
= f.input :number, :hint => 'please enter a number (this is a number field)'
|
29
|
+
= f.input :range, :as => :range, :hint => 'please enter a number range (this is a range field)'
|
30
|
+
= f.input :category, :as => :select, :collection => 10.times.map { |x| "Category #{x}"}, :hint => 'please select a category (this is a select field)'
|
31
|
+
= f.input :drink, :as => :check_boxes, :wrapper => :horizontal_inline_radio_and_checkboxes, :collection => ['Water', 'Tea', 'Coffee', 'Soda'], :hint => 'please select one or more drinks (this is a check_boxes :wrapper => :horizontal_inline_radio_and_checkboxes field)'
|
32
|
+
= f.input :food, :as => :radio_buttons, :wrapper => :horizontal_inline_radio_and_checkboxes, :collection => ['Pasta', 'Rice', 'Potato', 'Couscous'], :hint => 'please select one food (this is a radio_buttons :wrapper => :horizontal_inline_radio_and_checkboxes field)'
|
33
|
+
= f.input :content, :hint => 'please enter a whole bunch of content (this is a textarea)'
|
34
|
+
= f.input :archived, :wrapper => :horizontal_boolean, :hint => 'please select true or false (this is a boolean field)'
|
35
|
+
= f.input :drink, :wrapper => :horizontal_radio_and_checkboxes, :as => :check_boxes, :collection => ['Water', 'Tea', 'Coffee', 'Soda'], :hint => 'please select one or more drinks (this is a check_boxes field)'
|
36
|
+
= f.input :food, :wrapper => :horizontal_radio_and_checkboxes, :as => :radio_buttons, :collection => ['Pasta', 'Rice', 'Potato', 'Couscous'], :hint => 'please select one food (this is a radio_buttons field)'
|
37
|
+
.form-group
|
38
|
+
.col-sm-offset-3.col-sm-9= f.button :submit
|
@@ -0,0 +1,16 @@
|
|
1
|
+
= simple_form_for Effective::StyleGuide.new(), :html => {:class => 'form-inline'}, :wrapper => :inline_form, :url => '/' do |f|
|
2
|
+
= f.input :title, :placeholder => 'Enter title'
|
3
|
+
= f.input :email, :placeholder => 'Enter email'
|
4
|
+
= f.input :category, :as => :select, :collection => 10.times.map { |x| "Category #{x}"}
|
5
|
+
= f.input :archived
|
6
|
+
= f.button :submit
|
7
|
+
|
8
|
+
%hr
|
9
|
+
.inline-example Inline Form Invalid State
|
10
|
+
|
11
|
+
= simple_form_for Effective::StyleGuide.new().tap { |s| s.valid? }, :html => {:class => 'form-inline'}, :wrapper => :inline_form, :url => '/' do |f|
|
12
|
+
= f.input :title, :placeholder => 'Enter title'
|
13
|
+
= f.input :email, :placeholder => 'Enter email'
|
14
|
+
= f.input :category, :as => :select, :collection => 10.times.map { |x| "Category #{x}"}
|
15
|
+
= f.input :archived
|
16
|
+
= f.button :submit
|