fullstack-admin 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/TODO.tasks +20 -14
- data/VERSION +1 -1
- data/app/assets/stylesheets/admin/base.css +312 -1
- data/app/assets/stylesheets/admin/login.css +54 -0
- data/app/assets/stylesheets/support/bootstrap-workarounds.css +1 -1
- data/app/controllers/admin/base_controller.rb +19 -14
- data/app/controllers/admin/sessions_controller.rb +18 -10
- data/app/controllers/admin/subject_model_adapter.rb +57 -0
- data/app/models/superuser.rb +4 -10
- data/app/views/admin/_nav.html.erb +39 -22
- data/app/views/admin/base/index.html.erb +47 -28
- data/app/views/admin/sessions/new.html.erb +34 -0
- data/app/views/layouts/admin.html.erb +6 -8
- data/app/views/layouts/login.html.erb +15 -0
- data/config/locales/it.yml +4 -0
- data/config/locales/labels.it.yml +2 -1
- data/config/routes.rb +4 -0
- data/fullstack-admin.gemspec +6 -2
- data/lib/fullstack/admin/resources.rb +22 -1
- data/lib/generators/fullstack/admin/install_generator.rb +3 -2
- data/lib/generators/fullstack/admin/templates/root/lib/support/user_subject.rb +1 -1
- metadata +7 -3
data/TODO.tasks
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
= Fullstack Admin Roadmap =
|
3
3
|
===========================
|
4
4
|
|
5
|
-
- Fix
|
5
|
+
- Fix assets compilation issues (and lock assets-related gems to working versions only)
|
6
|
+
✓ Fix positionable/_collection.html.erb not working
|
6
7
|
|
7
8
|
- Has many nested:
|
8
9
|
has_many_nested = has_many + accepts_nested_attributes_for + :allow_destroy => true [CORE]
|
@@ -33,17 +34,17 @@
|
|
33
34
|
|
34
35
|
✓ Ckeditor: upload assets to S3 according to app.config
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
✓ Localizable models
|
38
|
+
✓ Create Localized module: a model is localizable if has a :locale field (cms?)
|
39
|
+
✓ Add a scope to Localized to find models within the current locale (cms?)
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
✓ Create an option to specify the admin_locale
|
42
|
+
✓ add a before filter to Admin::BaseController that uses the default locale for the admin
|
43
|
+
✓ Split localized models index into tabs (either through ajax?)
|
44
|
+
✓ Let the programmer decide a default locale and a set of available locales
|
45
|
+
✓ Translations for locale codes
|
45
46
|
|
46
|
-
- Form for accepts_nested_attributes_for and has_one
|
47
|
+
- Form for accepts_nested_attributes_for and has_one (NOT TESTED?)
|
47
48
|
- Optional tracking of author/updaters for every model (CMS?)
|
48
49
|
|
49
50
|
==================
|
@@ -55,9 +56,9 @@
|
|
55
56
|
- find alternative to sortable
|
56
57
|
|
57
58
|
- Multiple scopes
|
58
|
-
- Tags input with
|
59
|
+
- Tags input with select2
|
59
60
|
|
60
|
-
-
|
61
|
+
- Conditional fields and Virtual Fields:
|
61
62
|
= Group of fields that can be setted exclusively
|
62
63
|
= eg
|
63
64
|
= field :age
|
@@ -65,5 +66,10 @@
|
|
65
66
|
|
66
67
|
= virtual_field :link_method, :in => %W(page external)
|
67
68
|
|
68
|
-
= belongs_to :related_page, :
|
69
|
-
= field :url, :
|
69
|
+
= belongs_to :related_page, :meaningful_when => :link_method.eq("page")
|
70
|
+
= field :url, :meaningful_when => :link_method.eq("external")
|
71
|
+
|
72
|
+
- Validation DSL
|
73
|
+
= field :name, :string, :required
|
74
|
+
= field :email, :required, :unique
|
75
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
@@ -1,4 +1,5 @@
|
|
1
1
|
/*
|
2
|
+
*= require admin/login
|
2
3
|
*= require support/base
|
3
4
|
*= require support/bootstrap
|
4
5
|
*= require support/forms
|
@@ -13,15 +14,113 @@
|
|
13
14
|
}
|
14
15
|
}
|
15
16
|
|
17
|
+
input {
|
18
|
+
-moz-box-sizing: border-box;
|
19
|
+
-webkit-box-sizing: border-box;
|
20
|
+
box-sizing: border-box;
|
21
|
+
width: 100%;
|
22
|
+
height: auto !important;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* ========= */
|
26
|
+
/* = Icons = */
|
27
|
+
/* ========= */
|
28
|
+
|
29
|
+
.icon-white, .nav-tabs > .active > a > [class^="icon-"], .nav-tabs > .active > a > [class*=" icon-"], .nav-pills > .active > a > [class^="icon-"], .nav-pills > .active > a > [class*=" icon-"], .nav-list > .active > a > [class^="icon-"], .nav-list > .active > a > [class*=" icon-"], .navbar-inverse .nav > .active > a > [class^="icon-"], .navbar-inverse .nav > .active > a > [class*=" icon-"], .dropdown-menu > li > a:hover > [class^="icon-"], .dropdown-menu > li > a:hover > [class*=" icon-"], .dropdown-menu > .active > a > [class^="icon-"], .dropdown-menu > .active > a > [class*=" icon-"] {
|
30
|
+
background-image: url("/img/glyphicons-halflings-white.png");
|
31
|
+
}
|
32
|
+
|
33
|
+
/* ========== */
|
34
|
+
/* = Navbar = */
|
35
|
+
/* ========== */
|
36
|
+
|
37
|
+
.navbar .nav li.dropdown > .dropdown-toggle .caret {
|
38
|
+
border-top-color: white;
|
39
|
+
border-bottom-color: white;
|
40
|
+
}
|
41
|
+
|
42
|
+
.navbar-inner {
|
43
|
+
background: #3993ba;
|
44
|
+
background: -moz-linear-gradient(top, #3993ba 0%, #067ead 100%);
|
45
|
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#3993ba), color-stop(100%,#067ead));
|
46
|
+
background: -webkit-linear-gradient(top, #3993ba 0%,#067ead 100%);
|
47
|
+
background: -o-linear-gradient(top, #3993ba 0%,#067ead 100%);
|
48
|
+
background: -ms-linear-gradient(top, #3993ba 0%,#067ead 100%);
|
49
|
+
background: linear-gradient(top, #3993ba 0%,#067ead 100%);
|
50
|
+
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3993ba', endColorstr='#067ead',GradientType=0 );
|
51
|
+
-webkit-box-shadow: none;
|
52
|
+
-moz-box-shadow: none;
|
53
|
+
box-shadow: none;
|
54
|
+
|
55
|
+
}
|
56
|
+
|
57
|
+
.navbar .nav > li > a {
|
58
|
+
color: #c1dce7;
|
59
|
+
}
|
60
|
+
|
61
|
+
.navbar .nav > li:hover > a {
|
62
|
+
color:#fff;
|
63
|
+
}
|
64
|
+
|
65
|
+
.navbar .nav .active > a, .navbar .nav .active > a:hover, .navbar .nav li.dropdown.open > .dropdown-toggle {
|
66
|
+
background: #206484;
|
67
|
+
color: #fff;
|
68
|
+
}
|
69
|
+
|
70
|
+
.navbar .divider-vertical {
|
71
|
+
background-color:#2078A1;
|
72
|
+
border-color:#3497C2;
|
73
|
+
}
|
74
|
+
|
75
|
+
.navbar .divider-vertical {
|
76
|
+
border-left-color: #2078A1;
|
77
|
+
border-right-color: #3497C2;
|
78
|
+
}
|
79
|
+
|
80
|
+
.dropdown-menu li > a:hover, .dropdown-menu .active > a,
|
81
|
+
.dropdown-menu .active > a:hover,
|
82
|
+
.nav-list > .active > a, .nav-list > .active > a:hover {
|
83
|
+
background: #48a6d2 !important;
|
84
|
+
}
|
85
|
+
|
86
|
+
.table thead th {background-color:#ebf2f6 !important}
|
87
|
+
.dataTables_wrapper th.sorting_asc,.dataTables_wrapper th.sorting_desc {background-color:#d4e3eb !important}
|
88
|
+
|
89
|
+
|
16
90
|
#left-aside .nav {
|
17
91
|
padding-bottom: 180px;
|
18
92
|
}
|
19
93
|
|
94
|
+
.navbar .nav > li > a {
|
95
|
+
padding-top: 10px;
|
96
|
+
}
|
97
|
+
.navbar .nav > li > a {
|
98
|
+
text-shadow: none;
|
99
|
+
padding: 9px 10px 11px;
|
100
|
+
}
|
101
|
+
.navbar .nav > li > a {
|
102
|
+
color: #C1DCE7;
|
103
|
+
}
|
104
|
+
|
105
|
+
.navbar .brand {
|
106
|
+
width: 200px;
|
107
|
+
font: 100 16px/16px 'PT Sans', sans-serif;
|
108
|
+
text-decoration: none;
|
109
|
+
color: #c1dce7;
|
110
|
+
text-shadow: none;
|
111
|
+
padding: 10px 20px 0;
|
112
|
+
}
|
113
|
+
|
114
|
+
.navbar .brand:hover {
|
115
|
+
color: #fff;
|
116
|
+
}
|
117
|
+
|
20
118
|
.sidenav > li:first-child {
|
21
119
|
-webkit-border-radius: 6px 6px 0 0;
|
22
120
|
-moz-border-radius: 6px 6px 0 0;
|
23
121
|
border-radius: 6px 6px 0 0;
|
24
122
|
}
|
123
|
+
|
25
124
|
.sidenav > li {
|
26
125
|
display: block;
|
27
126
|
margin: 0 0 -1px;
|
@@ -31,7 +130,6 @@ margin-left: -15px;
|
|
31
130
|
margin-right: -15px;
|
32
131
|
}
|
33
132
|
|
34
|
-
|
35
133
|
.thumbnails > li {
|
36
134
|
float: left;
|
37
135
|
margin-left: 0 !important;
|
@@ -58,4 +156,217 @@ margin-right: -15px;
|
|
58
156
|
background: url(/assets/iconic/gray/magnifying_glass_12x12.png) no-repeat left center;
|
59
157
|
margin-left: 7px !important;
|
60
158
|
padding-left: 12px !important;
|
159
|
+
}
|
160
|
+
|
161
|
+
/* ======= */
|
162
|
+
/* = Box = */
|
163
|
+
/* ======= */
|
164
|
+
|
165
|
+
.box {
|
166
|
+
-webkit-box-shadow: 0px 1px 2px 0px #EFEFEF;
|
167
|
+
-moz-box-shadow: 0px 1px 2px 0px #EFEFEF;
|
168
|
+
box-shadow: 0px 1px 2px 0px #EFEFEF;
|
169
|
+
margin-bottom: 20px;
|
170
|
+
}
|
171
|
+
|
172
|
+
.box-header, .box-content, .box-footer {
|
173
|
+
padding: 20px;
|
174
|
+
}
|
175
|
+
|
176
|
+
.box-header {
|
177
|
+
height: 32px;
|
178
|
+
line-height: 32px;
|
179
|
+
border: 1px solid #DDD;
|
180
|
+
padding: 0 10px;
|
181
|
+
background: #FBFBFB;
|
182
|
+
background: -moz-linear-gradient(top, #FBFBFB 0%, #F1F1F1 100%);
|
183
|
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FBFBFB), color-stop(100%,#F1F1F1));
|
184
|
+
background: -webkit-linear-gradient(top, #FBFBFB 0%,#F1F1F1 100%);
|
185
|
+
background: -o-linear-gradient(top, #FBFBFB 0%,#F1F1F1 100%);
|
186
|
+
background: -ms-linear-gradient(top, #FBFBFB 0%,#F1F1F1 100%);
|
187
|
+
background: linear-gradient(top, #FBFBFB 0%,#F1F1F1 100%);
|
188
|
+
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fbfbfb', endColorstr='#f1f1f1',GradientType=0 );
|
189
|
+
font-weight: 700;
|
190
|
+
color: #666;
|
191
|
+
font-size: 11px;
|
192
|
+
}
|
193
|
+
|
194
|
+
|
195
|
+
.box-content {
|
196
|
+
padding: 10px;
|
197
|
+
border: 1px solid #DDD;
|
198
|
+
border-top: none;
|
199
|
+
}
|
200
|
+
|
201
|
+
.box-content:last-child {
|
202
|
+
margin-bottom: 0;
|
203
|
+
padding-bottom: 0;
|
204
|
+
}
|
205
|
+
|
206
|
+
.box-footer {
|
207
|
+
border: 1px solid #DDD;
|
208
|
+
padding: 8px 10px;
|
209
|
+
background: #F1F1F1;
|
210
|
+
border-top: none;
|
211
|
+
}
|
212
|
+
|
213
|
+
.box-footer.align-right {
|
214
|
+
text-align: right;
|
215
|
+
}
|
216
|
+
|
217
|
+
fieldset.box-content {
|
218
|
+
padding-top: 20px;
|
219
|
+
}
|
220
|
+
|
221
|
+
/* ========== */
|
222
|
+
/* = Layout = */
|
223
|
+
/* ========== */
|
224
|
+
|
225
|
+
a, button, input {
|
226
|
+
outline: none !important;
|
227
|
+
}
|
228
|
+
|
229
|
+
a {
|
230
|
+
color: #08C;
|
231
|
+
text-decoration: none;
|
232
|
+
}
|
233
|
+
|
234
|
+
body {
|
235
|
+
padding-top: 60px;
|
236
|
+
}
|
237
|
+
|
238
|
+
.main {
|
239
|
+
background: white;
|
240
|
+
border-left: 1px solid transparent;
|
241
|
+
margin-left: 240px;
|
242
|
+
}
|
243
|
+
|
244
|
+
|
245
|
+
/* =============== */
|
246
|
+
/* = Page Header = */
|
247
|
+
/* =============== */
|
248
|
+
|
249
|
+
.resource_updated_at {
|
250
|
+
font: italic 12px/32px Arial, Helvetica, sans-serif;
|
251
|
+
color: #888;
|
252
|
+
}
|
253
|
+
|
254
|
+
.page-header h1, h1.page-header{
|
255
|
+
line-height: 34px;
|
256
|
+
font-size: 18px;
|
257
|
+
margin-top: 0;
|
258
|
+
}
|
259
|
+
.page-header h1 {
|
260
|
+
margin-bottom: 0;
|
261
|
+
}
|
262
|
+
|
263
|
+
#center > .page-header {
|
264
|
+
margin-top: 0;
|
265
|
+
margin-bottom: 20px;
|
266
|
+
padding: 0;
|
267
|
+
}
|
268
|
+
|
269
|
+
.index-actions {
|
270
|
+
float:right;
|
271
|
+
}
|
272
|
+
|
273
|
+
|
274
|
+
/* =========== */
|
275
|
+
/* = Sidebar = */
|
276
|
+
/* =========== */
|
277
|
+
|
278
|
+
.sidebar {
|
279
|
+
position: fixed;
|
280
|
+
top: 40px;
|
281
|
+
left: 0;
|
282
|
+
margin-left: 0;
|
283
|
+
padding-top: 20px;
|
284
|
+
width: 240px;
|
285
|
+
background: #f1f1f1;
|
286
|
+
border-right: 1px solid #ccc;
|
287
|
+
height: 100%;
|
288
|
+
font: 13px/18px "Helvetica Neue",Helvetica,Arial,sans-serif;
|
289
|
+
}
|
290
|
+
|
291
|
+
.sidebar .accordion {
|
292
|
+
border-top: 1px solid #CCC;
|
293
|
+
margin-bottom: 20px;
|
294
|
+
}
|
295
|
+
|
296
|
+
.sidebar .accordion-heading a:hover {
|
297
|
+
background-color: #CFCFCF;
|
298
|
+
}
|
299
|
+
|
300
|
+
.sidebar .accordion-heading {
|
301
|
+
text-shadow: 1px 1px 0 #EFEFEF;
|
302
|
+
background: #E0E0E0;
|
303
|
+
-webkit-box-shadow: inset 0px 1px 0px 0px #ECECEC;
|
304
|
+
box-shadow: inset 0px 1px 0px 0px #ECECEC;
|
305
|
+
}
|
306
|
+
|
307
|
+
.sidebar .accordion-inner {
|
308
|
+
border-top: 1px solid #CCC;
|
309
|
+
background: #FAFAFA;
|
310
|
+
}
|
311
|
+
|
312
|
+
.sidebar .accordion-group .accordion-heading a {
|
313
|
+
color: #222;
|
314
|
+
}
|
315
|
+
|
316
|
+
.sidebar .accordion-group .active a {
|
317
|
+
color: white;
|
318
|
+
}
|
319
|
+
|
320
|
+
.nav-list > li > a, .dropdown-menu li a {
|
321
|
+
-webkit-border-radius: 4px;
|
322
|
+
-moz-border-radius: 4px;
|
323
|
+
-ms-border-radius: 4px;
|
324
|
+
border-radius: 4px;
|
325
|
+
}
|
326
|
+
|
327
|
+
.dropdown-menu li > a:hover, .dropdown-menu .active > a, .dropdown-menu .active > a:hover, .nav-list > .active > a, .nav-list > .active > a:hover {
|
328
|
+
background: #48A6D2 !important;
|
329
|
+
}
|
330
|
+
|
331
|
+
.nav > li > a:hover {
|
332
|
+
text-decoration: none;
|
333
|
+
background-color: #EEE;
|
334
|
+
}
|
335
|
+
|
336
|
+
.sidebar .accordion-group a {
|
337
|
+
color: #222;
|
338
|
+
text-decoration: none!important;
|
339
|
+
}
|
340
|
+
|
341
|
+
.sidebar .accordion-group {
|
342
|
+
-webkit-border-radius: 0;
|
343
|
+
-moz-border-radius: 0;
|
344
|
+
border-radius: 0;
|
345
|
+
margin-bottom: 0;
|
346
|
+
border-color: #CCC;
|
347
|
+
border-style: solid;
|
348
|
+
border-width: 0 0 1px;
|
349
|
+
}
|
350
|
+
|
351
|
+
.accordion-heading .accordion-toggle {
|
352
|
+
display: block;
|
353
|
+
padding: 7px 15px;
|
354
|
+
}
|
355
|
+
|
356
|
+
.accordion-toggle {
|
357
|
+
-webkit-transition: background-color 0.2s ease-in-out;
|
358
|
+
-moz-transition: background-color 0.2s ease-in-out;
|
359
|
+
-o-transition: background-color 0.2s ease-in-out;
|
360
|
+
transition: background-color 0.2s ease-in-out;
|
361
|
+
}
|
362
|
+
.accordion-toggle {
|
363
|
+
cursor: pointer;
|
364
|
+
}
|
365
|
+
|
366
|
+
/* ================ */
|
367
|
+
/* = Filter Input = */
|
368
|
+
/* ================ */
|
369
|
+
|
370
|
+
.filter-inputs {
|
371
|
+
margin: 0;
|
61
372
|
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
.login-box {
|
2
|
+
width: 380px;
|
3
|
+
margin: auto;
|
4
|
+
padding: 0;
|
5
|
+
position: relative;
|
6
|
+
top: 50%;
|
7
|
+
background: white;
|
8
|
+
border: 1px solid #CCC;
|
9
|
+
-webkit-border-radius: 6px;
|
10
|
+
-moz-border-radius: 6px;
|
11
|
+
-ms-border-radius: 6px;
|
12
|
+
border-radius: 6px;
|
13
|
+
-webkit-box-shadow: 0 0 6px rgba(0, 0, 0, 0.2);
|
14
|
+
-moz-box-shadow: 0 0 6px rgba(0,0,0,0.2);
|
15
|
+
-ms-box-shadow: 0 0 6px rgba(0,0,0,0.2);
|
16
|
+
box-shadow: 0 0 6px rgba(0, 0, 0, 0.2);
|
17
|
+
}
|
18
|
+
|
19
|
+
.login-box-header, .login-box-content, .form-actions.login-box-footer {
|
20
|
+
padding: 20px;
|
21
|
+
margin: 0;
|
22
|
+
}
|
23
|
+
|
24
|
+
.login-box-header {
|
25
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
|
26
|
+
font: 100 18px/42px 'PT Sans', sans-serif;
|
27
|
+
height: 42px;
|
28
|
+
padding: 0 20px;
|
29
|
+
background: #E0E0E0;
|
30
|
+
border-bottom: 1px solid #CCC;
|
31
|
+
-moz-border-radius-topleft: 6px;
|
32
|
+
-moz-border-radius-topright: 6px;
|
33
|
+
-moz-border-radius-bottomright: 0px;
|
34
|
+
-moz-border-radius-bottomleft: 0px;
|
35
|
+
-webkit-border-radius: 6px 6px 0px 0px;
|
36
|
+
border-radius: 6px 6px 0px 0px;
|
37
|
+
font-size: 15px;
|
38
|
+
}
|
39
|
+
|
40
|
+
.login-box input[type="text"], .login-box input[type="password"] {
|
41
|
+
width: 298px;
|
42
|
+
}
|
43
|
+
|
44
|
+
.login-box-footer {
|
45
|
+
padding: 12px 20px;
|
46
|
+
border-top: 1px solid #E7E7E7;
|
47
|
+
background: #F7F7F7;
|
48
|
+
-moz-border-radius-topleft: 0px;
|
49
|
+
-moz-border-radius-topright: 0px;
|
50
|
+
-moz-border-radius-bottomright: 6px;
|
51
|
+
-moz-border-radius-bottomleft: 6px;
|
52
|
+
-webkit-border-radius: 0px 0px 6px 6px;
|
53
|
+
border-radius: 0px 0px 6px 6px;
|
54
|
+
}
|
@@ -1,17 +1,13 @@
|
|
1
1
|
class Admin::BaseController < ApplicationController
|
2
|
-
|
3
|
-
|
2
|
+
before_filter :require_login
|
3
|
+
before_filter :fetch_current_resource
|
4
|
+
|
4
5
|
layout 'admin'
|
5
|
-
authorize(:scope => :admin)
|
6
6
|
|
7
7
|
protected
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
redirect_to new_admin_session_path
|
12
|
-
else
|
13
|
-
render :text => "Not Authorized", :status => 403
|
14
|
-
end
|
9
|
+
def not_authenticated
|
10
|
+
redirect_to new_admin_session_url, :alert => "First login to access this page."
|
15
11
|
end
|
16
12
|
|
17
13
|
class << self
|
@@ -27,19 +23,24 @@ class Admin::BaseController < ApplicationController
|
|
27
23
|
:current_resource_class,
|
28
24
|
:current_resource,
|
29
25
|
:current_collection,
|
30
|
-
:title_column
|
26
|
+
:title_column,
|
27
|
+
:subject
|
31
28
|
|
32
29
|
|
30
|
+
def subject
|
31
|
+
@subject ||= ::Admin::SubjectModelAdapter.new(current_user)
|
32
|
+
end
|
33
|
+
|
33
34
|
def current_resource_class
|
34
|
-
@current_resource_class ||= controller_name.singularize.camelize.constantize
|
35
|
+
@current_resource_class ||= controller_name.singularize.camelize.constantize rescue nil
|
35
36
|
end
|
36
37
|
|
37
38
|
def resource_name
|
38
|
-
current_resource_class.name.demodulize.underscore
|
39
|
+
current_resource_class && current_resource_class.name.demodulize.underscore
|
39
40
|
end
|
40
41
|
|
41
42
|
def collection_name
|
42
|
-
resource_name.pluralize
|
43
|
+
resource_name.try(:pluralize)
|
43
44
|
end
|
44
45
|
|
45
46
|
alias :singular_name :resource_name
|
@@ -59,5 +60,9 @@ class Admin::BaseController < ApplicationController
|
|
59
60
|
@_title_columns[model] ||= ( model.column_names.map{ |c| c.to_s } & %W(title name label browser_title seo_title seo_name key claim email) ).first
|
60
61
|
end
|
61
62
|
|
63
|
+
def fetch_current_resource
|
64
|
+
return if !params[:id] || current_resource
|
65
|
+
instance_variable_set("@#{resource_name}", current_resource_class.find(params[:id]))
|
66
|
+
end
|
62
67
|
|
63
|
-
end
|
68
|
+
end
|
@@ -1,19 +1,27 @@
|
|
1
1
|
class Admin::SessionsController < ApplicationController
|
2
|
-
layout '
|
2
|
+
layout 'login'
|
3
|
+
|
4
|
+
def new
|
5
|
+
@user = Superuser.new
|
6
|
+
end
|
3
7
|
|
4
8
|
def create
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
respond_to do |format|
|
10
|
+
if @user = login(params[:username],params[:password])
|
11
|
+
format.html { redirect_back_or_to("/", :notice => I18n.t("signed_in", :scope => "fullstack.admin", :default => 'Signed in successfully.')) }
|
12
|
+
format.xml { render :xml => @user, :status => :created, :location => @user }
|
13
|
+
else
|
14
|
+
format.html { flash.now[:alert] = I18n.t("login_failed", :scope => "fullstack.admin", :default => 'Login failed.'); render :action => "new" }
|
15
|
+
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
|
16
|
+
end
|
11
17
|
end
|
12
18
|
end
|
13
|
-
|
19
|
+
|
14
20
|
def destroy
|
15
21
|
logout
|
16
|
-
redirect_to
|
22
|
+
redirect_to("/", :notice => I18n.t("signed_out", :scope => "fullstack.admin", :default => 'Signed out successfully.'))
|
17
23
|
end
|
18
24
|
|
19
|
-
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Admin::SubjectModelAdapter
|
2
|
+
attr_accessor :subject_model
|
3
|
+
|
4
|
+
def initialize(subject_model)
|
5
|
+
@subject_model = subject_model
|
6
|
+
end
|
7
|
+
|
8
|
+
def guest?
|
9
|
+
!subject_model
|
10
|
+
end
|
11
|
+
|
12
|
+
def logged_in?
|
13
|
+
!!subject_model
|
14
|
+
end
|
15
|
+
|
16
|
+
def owner?(object)
|
17
|
+
object && ( object.respond_to?(:author) && ( subject_model == object.author ) ) || ( object.respond_to?(:owner) && ( subject_model == object.owner ) )
|
18
|
+
end
|
19
|
+
alias :own? :owner?
|
20
|
+
|
21
|
+
def administrator?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def can?(*args)
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def can_edit?(*args)
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def can_create?(*args)
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def can_destroy?(*args)
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
def can_new?(*args)
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def can_update?(*args)
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def can_sort?(*args)
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def can_show?(*args)
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/app/models/superuser.rb
CHANGED
@@ -1,12 +1,6 @@
|
|
1
1
|
class Superuser < ActiveRecord::Base
|
2
2
|
authenticates_with_sorcery!
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
validates_presence_of :password, :on => :create
|
8
|
-
validates_presence_of :email
|
9
|
-
validates_uniqueness_of :email
|
10
|
-
field :email
|
11
|
-
field :password
|
12
|
-
end
|
3
|
+
def has_role?(r)
|
4
|
+
true
|
5
|
+
end
|
6
|
+
end
|
@@ -1,13 +1,15 @@
|
|
1
|
-
<% content_for :menu do -%>
|
1
|
+
<% content_for :menu do -%>
|
2
|
+
|
3
|
+
<%= nav(:class => 'float right') do %>
|
4
|
+
<li class="divider-vertical">
|
5
|
+
</li>
|
2
6
|
|
3
|
-
<%=
|
4
|
-
|
5
|
-
|
7
|
+
<%= nav_item t('fullstack.admin.homepage', :default => "Homepage"), "/", :icon => "globe", :"icon_color" => :white %>
|
8
|
+
<li class="divider-vertical">
|
9
|
+
</li>
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
<%= dropdown_nav_item t('fullstack.admin.account', :default => "Account"), :icon => "user" do %>
|
10
|
-
<%= nav_item t('fullstack.admin.logout', :default => "Logout"), destroy_user_session_path, :method => :delete %>
|
11
|
+
<%= dropdown_nav_item t('fullstack.admin.account', :default => "Account"), :icon => "user", :"icon_color" => :white do %>
|
12
|
+
<%= nav_item t('fullstack.admin.logout', :default => "Logout"), admin_sessions_path, :method => :delete %>
|
11
13
|
<% end %>
|
12
14
|
<% end %>
|
13
15
|
|
@@ -15,19 +17,34 @@
|
|
15
17
|
|
16
18
|
<% content_for :nav do -%>
|
17
19
|
|
18
|
-
<div class="tabbable tabs-left float right">
|
19
|
-
<%= nav_list :class => "nav-tabs" do %>
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
21
|
+
<div class="sidebar">
|
22
|
+
<div class="sidebar-inner">
|
23
|
+
<div class="accordion sidebar-accordion" id="sidebar-accordion">
|
24
|
+
<% i = 0 %>
|
25
|
+
<% Fullstack::Admin.grouped_resources.each do |group, resources| %>
|
26
|
+
<div class="accordion-group">
|
27
|
+
<div class="accordion-heading">
|
28
|
+
<a href="#sidebar_group_collapsable_<%= i+=1 %>" data-parent="#sidebar-accordion" data-toggle="collapse" class="accordion-toggle">
|
29
|
+
<i class="icon-<%= group.icon %>"></i> <%= t("fullstack.admin.groups.#{group.name}", :default => group.name.to_s.humanize) %>
|
30
|
+
<% if resources.map(&:name).include?(plural_name) %>
|
31
|
+
<i class="icon-chevron-left float right" style="opacity: 0.4;"></i>
|
32
|
+
<% end %>
|
33
|
+
</a>
|
34
|
+
</div>
|
35
|
+
<div class="accordion-body collapse <%= resources.map(&:name).include?(plural_name) ? 'in' : '' %>" id="sidebar_group_collapsable_<%= i %>">
|
36
|
+
<div class="accordion-inner">
|
37
|
+
<ul class="nav nav-list">
|
38
|
+
<% resources.each do |resource| %>
|
39
|
+
<%= nav_item t("fullstack.admin.resources.#{resource.name}", :default => resource.name.to_s.humanize), [:admin, resource.name] %>
|
40
|
+
<% end %>
|
41
|
+
</ul>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
<% end %>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
</div>
|
32
49
|
|
33
|
-
<% end
|
50
|
+
<% end %>
|
@@ -1,10 +1,43 @@
|
|
1
|
+
<div class="page-header">
|
2
|
+
<% unless partial?('collection')%>
|
3
|
+
<div class="mb1 index-actions">
|
4
|
+
<% if subject.can_create?(collection_name) && controller.action_methods.include?("new") %>
|
5
|
+
<%= button t('fullstack.admin.new', :default => "New"),
|
6
|
+
send("new_admin_#{resource_name}_path"),
|
7
|
+
:type => :primary, :icon => :plus, :icon_color => :white %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% if subject.can_sort?(collection_name) && positionable?(current_collection.klass) %>
|
11
|
+
<%= button t('fullstack.admin.sort', :default => "Sort"),
|
12
|
+
send("admin_positionables_path", :type => resource_name)
|
13
|
+
%>
|
14
|
+
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<%= button t('fullstack.admin.delete', :default => "Delete"),
|
18
|
+
'javascript:void(0)', :class => "toggle-delete",
|
19
|
+
:icon => :trash %>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<h1>
|
1
25
|
<% if content_for?(:title) %>
|
2
|
-
|
26
|
+
<%= yield(:title) %>
|
27
|
+
|
3
28
|
<% elsif @title %>
|
4
|
-
|
29
|
+
|
30
|
+
<%= @title %>
|
31
|
+
|
5
32
|
<% else -%>
|
6
|
-
|
33
|
+
|
34
|
+
<%= t(collection_name, :scope => "fullstack.admin.resources") %>
|
35
|
+
|
7
36
|
<% end -%>
|
37
|
+
</h1>
|
38
|
+
|
39
|
+
|
40
|
+
</div>
|
8
41
|
|
9
42
|
<% if partial?('collection') %>
|
10
43
|
<%= render :partial => "collection",
|
@@ -15,24 +48,7 @@
|
|
15
48
|
%>
|
16
49
|
<% else %>
|
17
50
|
|
18
|
-
|
19
|
-
<% if subject.can_create?(collection_name) && controller.action_methods.include?("new") %>
|
20
|
-
<%= button t('fullstack.admin.new', :default => "New"),
|
21
|
-
send("new_admin_#{resource_name}_path"),
|
22
|
-
:type => :primary, :icon => :plus, :icon_color => :white %>
|
23
|
-
<% end %>
|
24
|
-
|
25
|
-
<% if subject.can_sort?(collection_name) && positionable?(current_collection.klass) %>
|
26
|
-
<%= button t('fullstack.admin.sort', :default => "Sort"),
|
27
|
-
send("admin_positionables_path", :type => resource_name)
|
28
|
-
%>
|
29
|
-
|
30
|
-
<% end %>
|
31
|
-
|
32
|
-
<%= button t('fullstack.admin.delete', :default => "Delete"),
|
33
|
-
'javascript:void(0)', :class => "toggle-delete",
|
34
|
-
:icon => :trash %>
|
35
|
-
</div>
|
51
|
+
|
36
52
|
|
37
53
|
|
38
54
|
<table class="table table-bordered table-striped index-table">
|
@@ -56,16 +72,18 @@
|
|
56
72
|
<% content_for :aside do -%>
|
57
73
|
|
58
74
|
<% if (!@skip_filter) && (partial?('filter') || title_column(current_resource_class) || has_timestamps?(current_resource_class)) %>
|
59
|
-
<div class="
|
60
|
-
<div class="
|
61
|
-
|
75
|
+
<div class="box">
|
76
|
+
<div class="box-header">
|
77
|
+
<%= t('fullstack.admin.filter', :default => "Filter") %>
|
62
78
|
</div>
|
79
|
+
|
63
80
|
<%= admin_form_for @search, :url => self.send("admin_#{collection_name}_path") , :html => {:method => :get} do |f| %>
|
81
|
+
<div class="box-content">
|
64
82
|
|
65
83
|
<% if partial?('filter') %>
|
66
84
|
<%= render :partial => "filter", :locals => {:f => f} %>
|
67
85
|
<% else %>
|
68
|
-
<%= f.inputs do %>
|
86
|
+
<%= f.inputs :class => "filter-inputs" do %>
|
69
87
|
|
70
88
|
<% if tc = title_column(current_resource_class) %>
|
71
89
|
<%= f.input :"#{tc}_contains" %>
|
@@ -78,9 +96,10 @@
|
|
78
96
|
<% end %>
|
79
97
|
|
80
98
|
<% end %>
|
81
|
-
|
82
|
-
|
83
|
-
|
99
|
+
</div>
|
100
|
+
<div class="box-footer align-right">
|
101
|
+
<%= f.action t('fullstack.admin.filter', :default => "Filter"), :as => :button %>
|
102
|
+
</div>
|
84
103
|
<% end %>
|
85
104
|
</div>
|
86
105
|
<% end %>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<%= form_tag admin_sessions_path, :method => :post, :class => "login-box" do %>
|
2
|
+
<div class="login-box-header">
|
3
|
+
Login
|
4
|
+
</div>
|
5
|
+
<div class="login-box-content">
|
6
|
+
|
7
|
+
<% [:notice, :error, :alert].each do |sym| %>
|
8
|
+
|
9
|
+
<% if flash[sym].present? %>
|
10
|
+
<div class="alert alert-info alert-login ">
|
11
|
+
<%= flash[sym] %>
|
12
|
+
</div>
|
13
|
+
<% flash.discard(sym) %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
|
19
|
+
<div class="input-prepend">
|
20
|
+
<span class="add-on"><i class="icon-user"></i></span>
|
21
|
+
<%= text_field_tag :username, nil, :placeholder => I18n.t("username", :scope => "helpers.label", :default => "Username") %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="input-prepend">
|
25
|
+
<span class="add-on"><i class="icon-lock"></i></span>
|
26
|
+
<%= password_field_tag :password, nil, :placeholder => I18n.t("password", :scope => "helpers.label", :default => "Password") %>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class="actions form-actions login-box-footer">
|
31
|
+
<%= submit_tag "Login", :class => "btn btn-primary" %>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<% end %>
|
@@ -12,25 +12,23 @@
|
|
12
12
|
<%= render :partial => 'admin/nav' %>
|
13
13
|
|
14
14
|
<%= navbar :fluid => true, :fixed => :top do %>
|
15
|
-
|
15
|
+
<a class="brand" href="/admin">
|
16
|
+
<i class="icon-home icon-white"></i> <%= "#{app_name} Admin" %></a>
|
16
17
|
<%= yield :menu %>
|
17
18
|
<% end %>
|
18
19
|
|
19
20
|
<%= yield :crumbs %>
|
21
|
+
<%= yield :nav %>
|
20
22
|
|
21
23
|
<%= container :fluid => true, :class => "main" do %>
|
22
|
-
|
24
|
+
<%= row do %>
|
23
25
|
|
24
|
-
<%= span(
|
25
|
-
<%= yield :nav %>
|
26
|
-
<% end %>
|
27
|
-
|
28
|
-
<%= span(content_for?(:aside) ? 6 : 10, :id => "center") do %>
|
26
|
+
<%= span(content_for?(:aside) ? 9 : 12, :id => "center") do %>
|
29
27
|
<%= yield %>
|
30
28
|
<% end %>
|
31
29
|
|
32
30
|
<% if content_for?(:aside) %>
|
33
|
-
|
31
|
+
<%= span(3, :id => "right-aside") do %>
|
34
32
|
<%= yield :aside %>
|
35
33
|
<% end %>
|
36
34
|
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="it">
|
3
|
+
<head>
|
4
|
+
<%= csrf_meta_tags %>
|
5
|
+
<title><%= ( @title ? "#{@title} - " : "" ) + "#{app_name} Admin" %></title>
|
6
|
+
|
7
|
+
<%= stylesheet_link_tag 'admin/admin' %>
|
8
|
+
<%= yield :stylesheets %>
|
9
|
+
</head>
|
10
|
+
|
11
|
+
<body>
|
12
|
+
<%= yield %>
|
13
|
+
</body>
|
14
|
+
</html>
|
15
|
+
|
data/config/locales/it.yml
CHANGED
@@ -30,6 +30,10 @@ it:
|
|
30
30
|
choose_a_file: "Carica"
|
31
31
|
change: "Cambia"
|
32
32
|
preview: "Anteprima"
|
33
|
+
signed_in: 'Login effettuato con successo.'
|
34
|
+
signed_out: 'Logout effettuato con successo.'
|
35
|
+
login_failed: 'Nome utente o password non validi.'
|
36
|
+
|
33
37
|
|
34
38
|
form:
|
35
39
|
correct_these_errors_and_retry: "Correggi questi errori e riprova"
|
data/config/routes.rb
CHANGED
@@ -3,6 +3,10 @@ Rails.application.routes.draw do
|
|
3
3
|
mount Ckeditor::Engine => '/ckeditor'
|
4
4
|
|
5
5
|
namespace :admin do
|
6
|
+
resources :sessions, :only => [:new, :create] do
|
7
|
+
match :destroy, :via => :delete, :on => :collection
|
8
|
+
end
|
9
|
+
|
6
10
|
resources :positionables, :only => [:index] do
|
7
11
|
post :sort, :on => :collection
|
8
12
|
end
|
data/fullstack-admin.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "fullstack-admin"
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["mcasimir"]
|
12
|
-
s.date = "2012-11-
|
12
|
+
s.date = "2012-11-05"
|
13
13
|
s.description = "Administration interface framework for fullstack"
|
14
14
|
s.email = "maurizio.cas@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -939,6 +939,7 @@ Gem::Specification.new do |s|
|
|
939
939
|
"app/assets/javascripts/support/plupload.js.coffee",
|
940
940
|
"app/assets/javascripts/support/uploads.js.coffee",
|
941
941
|
"app/assets/stylesheets/admin/base.css",
|
942
|
+
"app/assets/stylesheets/admin/login.css",
|
942
943
|
"app/assets/stylesheets/support/ajax_loading.css",
|
943
944
|
"app/assets/stylesheets/support/base.css",
|
944
945
|
"app/assets/stylesheets/support/bootstrap-workarounds.css",
|
@@ -952,6 +953,7 @@ Gem::Specification.new do |s|
|
|
952
953
|
"app/controllers/admin/responder.rb",
|
953
954
|
"app/controllers/admin/scaffold_controller.rb",
|
954
955
|
"app/controllers/admin/sessions_controller.rb",
|
956
|
+
"app/controllers/admin/subject_model_adapter.rb",
|
955
957
|
"app/helpers/admin_form_helper.rb",
|
956
958
|
"app/helpers/scaffold_helper.rb",
|
957
959
|
"app/inputs/country_input.rb",
|
@@ -993,6 +995,7 @@ Gem::Specification.new do |s|
|
|
993
995
|
"app/views/admin/base/new.html.erb",
|
994
996
|
"app/views/admin/base/update.js.coffee",
|
995
997
|
"app/views/admin/positionables/_collection.html.erb",
|
998
|
+
"app/views/admin/sessions/new.html.erb",
|
996
999
|
"app/views/kaminari/_first_page.html.erb",
|
997
1000
|
"app/views/kaminari/_gap.html.erb",
|
998
1001
|
"app/views/kaminari/_last_page.html.erb",
|
@@ -1001,6 +1004,7 @@ Gem::Specification.new do |s|
|
|
1001
1004
|
"app/views/kaminari/_paginator.html.erb",
|
1002
1005
|
"app/views/kaminari/_prev_page.html.erb",
|
1003
1006
|
"app/views/layouts/admin.html.erb",
|
1007
|
+
"app/views/layouts/login.html.erb",
|
1004
1008
|
"config/initializers/formtastic_bootstrap_timeish_hack.rb",
|
1005
1009
|
"config/locales/devise.en.yml",
|
1006
1010
|
"config/locales/devise.views.en.yml",
|
@@ -61,7 +61,7 @@ module Fullstack
|
|
61
61
|
|
62
62
|
# Group
|
63
63
|
class Group < Entity
|
64
|
-
attr_accessor :children, :name
|
64
|
+
attr_accessor :children, :name, :icon
|
65
65
|
|
66
66
|
def initialize(name)
|
67
67
|
@name = "#{name}"
|
@@ -128,6 +128,27 @@ module Fullstack
|
|
128
128
|
end
|
129
129
|
|
130
130
|
module_function :resources
|
131
|
+
|
132
|
+
def grouped_resources
|
133
|
+
if !@resource_groups
|
134
|
+
@resource_groups = {}
|
135
|
+
current_group = nil
|
136
|
+
|
137
|
+
resources.each do |rog|
|
138
|
+
if rog.type == :group
|
139
|
+
@resource_groups[rog] = []
|
140
|
+
current_group = rog
|
141
|
+
elsif current_group
|
142
|
+
@resource_groups[current_group] << rog
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
@resource_groups
|
147
|
+
end
|
148
|
+
|
149
|
+
module_function :grouped_resources
|
150
|
+
|
151
|
+
|
131
152
|
end
|
132
153
|
end
|
133
154
|
|
@@ -33,12 +33,13 @@ eos
|
|
33
33
|
|
34
34
|
|
35
35
|
def users
|
36
|
+
generate "sorcery:install remember_me activity_logging brute_force_protection --model Superuser"
|
36
37
|
generate "migration:from user"
|
37
38
|
append_to_file "db/seeds.rb" do
|
38
39
|
<<-eos
|
39
40
|
|
40
41
|
if Rails.env.development?
|
41
|
-
user =
|
42
|
+
user = Superuser.new( :email => "admin@example.com",
|
42
43
|
:password => "password" )
|
43
44
|
|
44
45
|
user.skip_confirmation! if user.respond_to?(:skip_confirmation!)
|
@@ -64,7 +65,7 @@ eos
|
|
64
65
|
eos
|
65
66
|
route(src)
|
66
67
|
|
67
|
-
route("\n devise_for :users\n")
|
68
|
+
#route("\n devise_for :users\n")
|
68
69
|
end
|
69
70
|
|
70
71
|
protected
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fullstack-admin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -1149,6 +1149,7 @@ files:
|
|
1149
1149
|
- app/assets/javascripts/support/plupload.js.coffee
|
1150
1150
|
- app/assets/javascripts/support/uploads.js.coffee
|
1151
1151
|
- app/assets/stylesheets/admin/base.css
|
1152
|
+
- app/assets/stylesheets/admin/login.css
|
1152
1153
|
- app/assets/stylesheets/support/ajax_loading.css
|
1153
1154
|
- app/assets/stylesheets/support/base.css
|
1154
1155
|
- app/assets/stylesheets/support/bootstrap-workarounds.css
|
@@ -1162,6 +1163,7 @@ files:
|
|
1162
1163
|
- app/controllers/admin/responder.rb
|
1163
1164
|
- app/controllers/admin/scaffold_controller.rb
|
1164
1165
|
- app/controllers/admin/sessions_controller.rb
|
1166
|
+
- app/controllers/admin/subject_model_adapter.rb
|
1165
1167
|
- app/helpers/admin_form_helper.rb
|
1166
1168
|
- app/helpers/scaffold_helper.rb
|
1167
1169
|
- app/inputs/country_input.rb
|
@@ -1203,6 +1205,7 @@ files:
|
|
1203
1205
|
- app/views/admin/base/new.html.erb
|
1204
1206
|
- app/views/admin/base/update.js.coffee
|
1205
1207
|
- app/views/admin/positionables/_collection.html.erb
|
1208
|
+
- app/views/admin/sessions/new.html.erb
|
1206
1209
|
- app/views/kaminari/_first_page.html.erb
|
1207
1210
|
- app/views/kaminari/_gap.html.erb
|
1208
1211
|
- app/views/kaminari/_last_page.html.erb
|
@@ -1211,6 +1214,7 @@ files:
|
|
1211
1214
|
- app/views/kaminari/_paginator.html.erb
|
1212
1215
|
- app/views/kaminari/_prev_page.html.erb
|
1213
1216
|
- app/views/layouts/admin.html.erb
|
1217
|
+
- app/views/layouts/login.html.erb
|
1214
1218
|
- config/initializers/formtastic_bootstrap_timeish_hack.rb
|
1215
1219
|
- config/locales/devise.en.yml
|
1216
1220
|
- config/locales/devise.views.en.yml
|
@@ -1291,7 +1295,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
1291
1295
|
version: '0'
|
1292
1296
|
segments:
|
1293
1297
|
- 0
|
1294
|
-
hash:
|
1298
|
+
hash: 445393833660587370
|
1295
1299
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
1296
1300
|
none: false
|
1297
1301
|
requirements:
|