robin_cms 0.1.2 → 0.1.4

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.
@@ -9,7 +9,7 @@
9
9
  <button type="submit">Close</button>
10
10
  </form>
11
11
  <form
12
- action='<%= url("/libraries/#{@library[:id]}/item/delete?id=#{@item.id}") %>'
12
+ action='<%= url("/libraries/#{@library.kind}/item/#{@item.id}/delete") %>'
13
13
  method="post"
14
14
  >
15
15
  <button type="submit" class="--danger">Delete</button>
@@ -11,7 +11,7 @@
11
11
  </option>
12
12
  <% end %>
13
13
  </select>
14
- <% if @config.drafts_enabled?(@library) %>
14
+ <% if @library.drafts_enabled? %>
15
15
  <select id="published" name="published">
16
16
  <% for option in PUBLISHED_OPTIONS%>
17
17
  <option
@@ -33,5 +33,5 @@
33
33
  placeholder="Search <%= @library[:label].downcase %>..."
34
34
  />
35
35
  <button type="submit">Apply</button>
36
- <a href="/admin/libraries/<%= @library[:id] %>">Clear filters</a>
36
+ <a href="/admin/libraries/<%= @library.kind %>">Clear filters</a>
37
37
  </form>
@@ -2,5 +2,5 @@
2
2
  id="<%= safe_id(field[:id], 'field') %>"
3
3
  type="hidden"
4
4
  name="<%= field[:id] %>"
5
- value="<%= @item.attributes[field[:id].to_sym] || field[:default] %>"
5
+ value="<%= @item.field_value_or_default(field) %>"
6
6
  />
@@ -3,7 +3,7 @@
3
3
  id="<%= safe_id(field[:id], 'field') %>"
4
4
  type="<%= field[:type] %>"
5
5
  name="<%= field[:id] %>"
6
- value="<%= @item.attributes[field[:id].to_sym] || field[:default] %>"
6
+ value="<%= @item.field_value_or_default(field) %>"
7
7
  <% if field[:required] %>required<% end %>
8
8
  <% if field[:readonly] %>readonly<% end %>
9
9
  />
@@ -3,8 +3,11 @@
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6
+ <meta name="robots" content="noindex,nofollow" />
6
7
  <title><%= @config[:title] %> | admin</title>
7
- <%= erb :style %>
8
+ <style>
9
+ <%= erb :"stylesheet.css" %>
10
+ </style>
8
11
  </head>
9
12
  <body <% if flash[:success_dialog] %>onload="successdialog.showModal()"<% end %>>
10
13
  <% if session[:auth_user] %>
@@ -14,7 +17,7 @@
14
17
  </span>
15
18
  <span class="controls --gap-md">
16
19
  <a href="<%= @config[:url] %>" target="_blank">
17
- <%= @config[:url] %><%= erb :new_tab %>
20
+ <%= @config[:url] %><%= erb :"new_tab.svg" %>
18
21
  </a>
19
22
  <% if @config[:build_command] %>
20
23
  <form id="publish-form" action="/admin/publish" method="post">
@@ -29,7 +32,7 @@
29
32
  <main id="site-content">
30
33
  <%= yield %>
31
34
  <footer id="site-footer" class="card --clear">
32
- <%= erb :logo %>
35
+ <%= erb :"logo.svg" %>
33
36
  <p>
34
37
  Made with 🧡
35
38
  <br />
@@ -6,7 +6,7 @@
6
6
  <p><%= @library[:description] %></p>
7
7
  <% end %>
8
8
  <% if @library[:can_create] %>
9
- <form action='<%= url("/libraries/#{@library[:id]}/item") %>'>
9
+ <form action='<%= url("/libraries/#{@library.kind}/item") %>'>
10
10
  <button type="submit">
11
11
  New <%= @library[:label_singular].downcase %>
12
12
  </button>
@@ -20,8 +20,8 @@
20
20
  <br />
21
21
  <br />
22
22
  <% if @library[:can_create] %>
23
- Create a <a href='<%= url("/libraries/#{@library[:id]}/item") %>'>new <%= @library[:label_singular].downcase %></a>
24
- or try <a href='<%= url("/libraries/#{@library[:id]}") %>'>clearing</a> your search filters.
23
+ Create a <a href='<%= url("/libraries/#{@library.kind}/item") %>'>new <%= @library[:label_singular].downcase %></a>
24
+ or try <a href='<%= url("/libraries/#{@library.kind}") %>'>clearing</a> your search filters.
25
25
  <% end %>
26
26
  </div>
27
27
  <% else %>
@@ -29,7 +29,7 @@
29
29
  <thead>
30
30
  <tr>
31
31
  <th class="grow-column">Name</th>
32
- <% if @config.drafts_enabled?(@library) %>
32
+ <% if @library.drafts_enabled? %>
33
33
  <th>Status</th>
34
34
  <% end %>
35
35
  <th>Created</th>
@@ -40,13 +40,13 @@
40
40
  <% for item in @items %>
41
41
  <tr>
42
42
  <td>
43
- <a href='<%= url("/libraries/#{@library[:id]}/item?id=#{item.id}") %>'>
43
+ <a href='<%= url("/libraries/#{@library.kind}/item/#{item.id}") %>'>
44
44
  <%= item.display_name %>
45
45
  </a>
46
46
  </td>
47
- <% if @config.drafts_enabled?(@library) %>
47
+ <% if @library.drafts_enabled? %>
48
48
  <td>
49
- <a href='<%= url("/libraries/#{@library[:id]}/item?id=#{item.id}") %>'>
49
+ <a href='<%= url("/libraries/#{@library.kind}/item/#{item.id}") %>'>
50
50
  <span class="badge --<%= item.published? ? 'published' : 'draft' %>">
51
51
  <%= item.published_label %>
52
52
  </span>
@@ -54,12 +54,12 @@
54
54
  </td>
55
55
  <% end %>
56
56
  <td>
57
- <a href='<%= url("/libraries/#{@library[:id]}/item?id=#{item.id}") %>'>
57
+ <a href='<%= url("/libraries/#{@library.kind}/item/#{item.id}") %>'>
58
58
  <%= item.created_at.strftime("%b %d, %Y") %>
59
59
  </a>
60
60
  </td>
61
61
  <td>
62
- <a href='<%= url("/libraries/#{@library[:id]}/item?id=#{item.id}") %>'>
62
+ <a href='<%= url("/libraries/#{@library.kind}/item/#{item.id}") %>'>
63
63
  <%= item.updated_at.strftime("%b %d, %Y") %>
64
64
  </a>
65
65
  </td>
@@ -1,4 +1,7 @@
1
1
  <span class="controls">
2
- <a href='<%= url("/libraries/#{@library[:id]}") %>'>Back</a>
2
+ <a href='<%= url("/libraries/#{@library.kind}") %>'>Back</a>
3
3
  <button type="submit">Save</button>
4
+ <% if has_delete %>
5
+ <%= erb :delete_dialog %>
6
+ <% end %>
4
7
  </span>
@@ -2,43 +2,38 @@
2
2
  <h2>
3
3
  <% if @item.id %>Edit<% else %>New<% end %> <%= @library[:label_singular].downcase %>
4
4
  </h2>
5
- <%= erb :library_actions %>
5
+ <%= erb :library_actions, locals: { has_delete: @library[:can_delete] && @item.id } %>
6
6
  </header>
7
7
  <form
8
8
  class="card"
9
9
  <% if @item.id %>
10
- action='<%= url("/libraries/#{@library[:id]}/item?id=#{@item.id}") %>'
10
+ action='<%= url("/libraries/#{@library.kind}/item/#{@item.id}") %>'
11
11
  <% else %>
12
- action='<%= url("/libraries/#{@library[:id]}/item") %>'
12
+ action='<%= url("/libraries/#{@library.kind}/item") %>'
13
13
  <% end %>
14
14
  method="post"
15
15
  enctype="multipart/form-data"
16
16
  >
17
- <% for field in @sorted_fields %>
17
+ <% @library.sorted_fields.each do |field| %>
18
18
  <div class="field">
19
19
  <% case field[:type]
20
20
  when "text", "date", "number", "color", "email", "url" %>
21
- <%= erb :input_field, locals: { :field => field } %>
21
+ <%= erb :input_field, locals: { field: field } %>
22
22
  <% when "hidden" %>
23
- <%= erb :hidden_field, locals: { :field => field } %>
23
+ <%= erb :hidden_field, locals: { field: field } %>
24
24
  <% when "select" %>
25
- <%= erb :select_field, locals: { :field => field } %>
25
+ <%= erb :select_field, locals: { field: field } %>
26
26
  <% when "image" %>
27
- <%= erb :image_field, locals: { :field => field } %>
27
+ <%= erb :image_field, locals: { field: field } %>
28
28
  <% when "richtext" %>
29
- <%= erb :richtext_field, locals: { :field => field } %>
29
+ <%= erb :richtext_field, locals: { field: field } %>
30
30
  <% else %>
31
31
  <div></div>
32
32
  <% end %>
33
33
  </div>
34
34
  <% end %>
35
35
  <%= erb :flash %>
36
- <footer class="controls --align-space">
37
- <% if @library[:can_delete] && @item.id %>
38
- <%= erb :delete_dialog %>
39
- <% else %>
40
- <span></span>
41
- <% end %>
42
- <%= erb :library_actions %>
36
+ <footer class="controls --align-right">
37
+ <%= erb :library_actions, locals: { has_delete: false } %>
43
38
  </footer>
44
39
  </form>
@@ -5,6 +5,6 @@
5
5
  id="richtext-content"
6
6
  type="hidden"
7
7
  name="<%= field[:id] %>"
8
- value="<%= @item.attributes[field[:id].to_sym] || field[:default] %>"
8
+ value="<%= @item.field_value_or_default(field) %>"
9
9
  >
10
10
  <trix-editor input="richtext-content"></trix-editor>
@@ -2,7 +2,7 @@
2
2
  <select
3
3
  id="<%= safe_id(field[:id], 'field') %>"
4
4
  name="<%= field[:id] %>"
5
- value="<%= @item.attributes[field[:id].to_sym] || field[:default] %>"
5
+ value="<%= @item.field_value_or_default(field) %>"
6
6
  >
7
7
  <% for option in field[:options] %>
8
8
  <option
@@ -12,7 +12,7 @@
12
12
  selected
13
13
  <% end %>
14
14
  <% else %>
15
- <% if option[:value].to_s == (@item.attributes[field[:id].to_sym] || field[:default]).to_s %>
15
+ <% if option[:value].to_s == @item.field_value_or_default(field) %>
16
16
  selected
17
17
  <% end %>
18
18
  <% end %>
@@ -0,0 +1,443 @@
1
+ :root {
2
+ --border-color: #d2d5d8;
3
+ --border-radius: 8px;
4
+ --bg-color: rgb(246, 246, 247);
5
+ --font-color: #141414;
6
+ --link-color: rgb(71, 95, 145);
7
+ --accent-color: <%= @config[:accent_color] %>;
8
+ --accent-color-light: <%= @config[:accent_color] %>1e;
9
+ --danger-color: #f85149;
10
+ --danger-color-light: #f851491e;
11
+ --draft-color: #fd8a13;
12
+ --draft-color-light: #fd8a131e;
13
+ --action-color: #4493f8;
14
+ --action-color-light: #4493f81e;
15
+ --padding-xxs: 0.25rem;
16
+ --padding-xs: 0.5rem;
17
+ --padding-sm: 0.75rem;
18
+ --padding-md: 1rem;
19
+ --padding-lg: 1.5rem;
20
+ --padding: var(--padding-md);
21
+ --content-width: 60rem;
22
+ --content-left-margin: 16rem;
23
+ --box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 0px 0px;
24
+ --box-shadow-input: inset rgba(0, 0, 0, 0.1) 0px 1px 0px 0px;
25
+ }
26
+
27
+ test {
28
+ te
29
+ }
30
+
31
+ @media only screen and (max-width: 1250px) {
32
+ :root {
33
+ --content-left-margin: 3rem;
34
+ }
35
+ }
36
+
37
+ body {
38
+ margin: 0;
39
+ font-family: sans-serif;
40
+ color: var(--font-color);
41
+ background-color: var(--bg-color);
42
+ }
43
+
44
+ header {
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: space-between;
48
+ }
49
+
50
+ header h1,
51
+ header h2 {
52
+ margin: 0;
53
+ }
54
+
55
+ header h1 a {
56
+ text-decoration: none;
57
+ color: var(--font-color);
58
+ }
59
+
60
+ h1 {
61
+ font-size: 1.25rem;
62
+ }
63
+
64
+ h2 {
65
+ font-size: 1rem;
66
+ font-weight: 500;
67
+ color: var(--link-color);
68
+ }
69
+
70
+ a {
71
+ color: var(--link-color);
72
+ }
73
+
74
+ table {
75
+ width: 100%;
76
+ border-spacing: 0; /* border-collapse doesn't work with border radii */
77
+ }
78
+
79
+ th {
80
+ font-weight: 500;
81
+ }
82
+
83
+ th,
84
+ td {
85
+ white-space: nowrap;
86
+ overflow: hidden;
87
+ text-overflow: ellipsis;
88
+ }
89
+
90
+ td a {
91
+ display: block;
92
+ text-decoration: none;
93
+ color: initial;
94
+ }
95
+
96
+ th,
97
+ td > * {
98
+ padding: var(--padding-sm);
99
+ text-align: left;
100
+ }
101
+
102
+ th:first-child,
103
+ td:first-child > * {
104
+ padding-left: var(--padding);
105
+ }
106
+
107
+ th:last-child,
108
+ td:last-child > * {
109
+ padding-right: var(--padding);
110
+ }
111
+
112
+ tbody td {
113
+ background-color: white;
114
+ }
115
+
116
+ tbody tr:first-child td:first-child {
117
+ border-top-left-radius: var(--border-radius);
118
+ }
119
+
120
+ tbody tr:first-child td:last-child {
121
+ border-top-right-radius: var(--border-radius);
122
+ }
123
+
124
+ tbody tr:last-child td:first-child {
125
+ border-bottom-left-radius: var(--border-radius);
126
+ }
127
+
128
+ tbody tr:last-child td:last-child {
129
+ border-bottom-right-radius: var(--border-radius);
130
+ }
131
+
132
+ tbody tr td:first-child {
133
+ border-left: 1px solid var(--border-color);
134
+ }
135
+
136
+ tbody tr td:last-child {
137
+ border-right: 1px solid var(--border-color);
138
+ }
139
+
140
+ tbody tr td {
141
+ border-top: 1px solid var(--border-color);
142
+ }
143
+
144
+ tbody tr:last-child td {
145
+ border-bottom: 1px solid var(--border-color);
146
+ transform: scale(1); /* Weird hack to get box shadows to work on FF */
147
+ box-shadow: var(--box-shadow);
148
+ }
149
+
150
+ tbody tr:hover td {
151
+ background-color: var(--bg-color);
152
+ }
153
+
154
+ label {
155
+ display: block;
156
+ margin-bottom: var(--padding-xs);
157
+ }
158
+
159
+ input {
160
+ border: 1px solid var(--border-color);
161
+ border-radius: var(--border-radius);
162
+ width: 100%;
163
+ box-sizing: border-box;
164
+ padding: var(--padding-xs);
165
+ box-shadow: var(--box-shadow-input);
166
+ }
167
+
168
+ input[type="search"] {
169
+ width: initial;
170
+ }
171
+
172
+ input[type="file"] {
173
+ box-shadow: none;
174
+ }
175
+
176
+ input[name="image"] {
177
+ border: none;
178
+ }
179
+
180
+ input::placeholder {
181
+ color: var(--font-color);
182
+ }
183
+
184
+ select {
185
+ border: 1px solid var(--border-color);
186
+ border-radius: var(--border-radius);
187
+ box-sizing: border-box;
188
+ padding: var(--padding-xs);
189
+ background-color: white;
190
+ box-shadow: var(--box-shadow-input);
191
+ }
192
+
193
+ button {
194
+ padding: var(--padding-xxs) var(--padding-xs);
195
+ color: var(--accent-color);
196
+ border: 1px solid var(--accent-color);
197
+ border-radius: var(--border-radius);
198
+ background-color: var(--accent-color-light);
199
+ box-shadow: var(--box-shadow);
200
+ }
201
+
202
+ button.--danger {
203
+ color: var(--danger-color);
204
+ border: 1px solid var(--danger-color);
205
+ background-color: var(--danger-color-light);
206
+ }
207
+
208
+ button.--action {
209
+ color: var(--action-color);
210
+ border: 1px solid var(--action-color);
211
+ background-color: var(--action-color-light);
212
+ }
213
+
214
+ fieldset {
215
+ border: 0;
216
+ }
217
+
218
+ dialog {
219
+ border: 1px solid var(--border-color);
220
+ border-radius: var(--border-radius);
221
+ width: 20rem;
222
+ white-space: wrap;
223
+ }
224
+
225
+ dialog::backdrop {
226
+ background: rgba(0, 0, 0, .15);
227
+ backdrop-filter: blur(1px);
228
+ }
229
+
230
+ dialog .controls {
231
+ justify-content: flex-end;
232
+ background-color: var(--bg-color);
233
+ margin: 0 calc(-1 * var(--padding)) calc(-1 * var(--padding)) calc(-1 * var(--padding));
234
+ padding: var(--padding);
235
+ }
236
+
237
+ hr {
238
+ margin: var(--padding-xs) var(--padding);
239
+ border: 0;
240
+ height: 1px;
241
+ background-color: var(--border-color);
242
+ }
243
+
244
+ .flash {
245
+ display: block;
246
+ margin-bottom: var(--padding);
247
+ }
248
+
249
+ *.--danger {
250
+ color: var(--danger-color);
251
+ }
252
+
253
+ *.--success {
254
+ color: var(--action-color);
255
+ }
256
+
257
+ #robin-logo {
258
+ width: 80px;
259
+ margin-right: var(--padding-xs);
260
+ }
261
+
262
+ #site-header {
263
+ height: 3.5rem;
264
+ width: var(--content-width);
265
+ padding: 0 var(--padding);
266
+ margin-left: var(--content-left-margin);
267
+ margin-bottom: var(--padding);
268
+ box-sizing: border-box;
269
+ }
270
+
271
+ #site-nav ul {
272
+ list-style-type: none;
273
+ padding-left: 0;
274
+ margin: 0;
275
+ }
276
+
277
+ #site-nav a {
278
+ text-decoration: none;
279
+ font-weight: 500;
280
+ padding: var(--padding-xxs) 0;
281
+ }
282
+
283
+ #site-nav li.current a,
284
+ #site-nav li:hover a {
285
+ border-bottom: 3px solid var(--link-color);
286
+ }
287
+
288
+ #site-content {
289
+ max-width: var(--content-width);
290
+ margin-left: var(--content-left-margin);
291
+
292
+ <% unless session[:auth_user] %>
293
+ max-width: 30rem;
294
+ margin: 5.5rem auto 0 auto;
295
+ <% end %>
296
+ }
297
+
298
+ #site-content > * {
299
+ margin-bottom: var(--padding);
300
+ }
301
+
302
+ #site-footer {
303
+ display: flex;
304
+ justify-content: center;
305
+ align-items: center;
306
+ column-gap: var(--padding);
307
+ <% unless session[:auth_user] %>
308
+ text-align: center;
309
+ <% end %>
310
+ }
311
+
312
+ #filter-form {
313
+ margin-bottom: 0;
314
+ }
315
+
316
+ #filter-form select,
317
+ #filter-form input {
318
+ padding: 0.25rem;
319
+ border-radius: 12px;
320
+ }
321
+
322
+ #filter-form button {
323
+ height: 24px;
324
+ border-radius: 12px;
325
+ padding: 0 var(--padding-xs);
326
+ }
327
+
328
+ #login-form {
329
+ display: flex;
330
+ align-items: center;
331
+ justify-content: space-between;
332
+ }
333
+
334
+ #login-form fieldset {
335
+ margin-left: 2rem;
336
+ flex: 1 1 15rem;
337
+ }
338
+
339
+ .card {
340
+ background-color: white;
341
+ box-shadow: var(--box-shadow);
342
+ border-radius: var(--border-radius);
343
+ border: 1px solid var(--border-color);
344
+ padding: var(--padding);
345
+ }
346
+
347
+ .card.--no-padding {
348
+ padding: unset;
349
+ }
350
+
351
+ .card.--clear {
352
+ background-color: var(--bg-color);
353
+ box-shadow: none;
354
+ border: 0;
355
+ }
356
+
357
+ .card > p {
358
+ margin-top: 0;
359
+ }
360
+
361
+ .controls {
362
+ display: flex;
363
+ align-items: center;
364
+ column-gap: var(--padding);
365
+ }
366
+
367
+ .controls.--align-right {
368
+ justify-content: flex-end;
369
+ }
370
+
371
+ .controls.--align-space {
372
+ justify-content: space-between;
373
+ }
374
+
375
+ .controls.--gap-md {
376
+ column-gap: var(--padding-lg);
377
+ }
378
+
379
+ .badge {
380
+ font-size: 0.825rem;
381
+ border-radius: 0.625rem;
382
+ text-align: center;
383
+ padding: 0 0.5rem;
384
+ display: block;
385
+ height: 1.25rem;
386
+ line-height: 1.25rem;
387
+ }
388
+
389
+ .badge.--draft {
390
+ background-color: var(--draft-color-light);
391
+ color: var(--draft-color);
392
+ }
393
+
394
+ .badge.--published {
395
+ background-color: var(--action-color-light);
396
+ color: var(--action-color);
397
+ }
398
+
399
+ .field {
400
+ margin: var(--padding) 0;
401
+ }
402
+
403
+ .no-items {
404
+ text-align: center;
405
+ padding: 2rem;
406
+ }
407
+
408
+ .grow-column {
409
+ width: 100%;
410
+ }
411
+
412
+ .image-preview {
413
+ width: 8rem;
414
+ height: 8rem;
415
+ border: 1px solid var(--border-color);
416
+ object-fit: cover;
417
+ display: block;
418
+ }
419
+
420
+ /* trix editor overrides */
421
+
422
+ trix-editor {
423
+ height: 16rem;
424
+ border: 1px solid var(--border-color) !important;
425
+ border-radius: var(--border-radius) !important;
426
+ box-shadow: var(--box-shadow-input);
427
+ overflow: scroll;
428
+ }
429
+
430
+ .trix-button-group {
431
+ border: 1px solid var(--border-color) !important;
432
+ border-radius: var(--border-radius) !important;
433
+ box-shadow: var(--box-shadow-input);
434
+ }
435
+
436
+ .trix-button {
437
+ border-bottom: 0 !important;
438
+ box-shadow: none;
439
+ }
440
+
441
+ .trix-button.trix-active {
442
+ background: var(--accent-color-light) !important;
443
+ }
data/lib/robin_cms.rb CHANGED
@@ -27,12 +27,13 @@ end
27
27
 
28
28
  require_relative "robin_cms/version"
29
29
  require_relative "robin_cms/configuration"
30
- require_relative "robin_cms/itemable"
31
- require_relative "robin_cms/queryable"
30
+ require_relative "robin_cms/editable"
32
31
  require_relative "robin_cms/sluggable"
33
- require_relative "robin_cms/collection_item"
34
- require_relative "robin_cms/data_item"
35
- require_relative "robin_cms/static_item"
32
+ require_relative "robin_cms/queryable"
33
+ require_relative "robin_cms/item"
34
+ require_relative "robin_cms/library"
35
+ require_relative "robin_cms/collection_library"
36
+ require_relative "robin_cms/data_library"
36
37
  require_relative "robin_cms/item"
37
38
  require_relative "robin_cms/auth"
38
39
  require_relative "robin_cms/flash"