trestle 0.8.4 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.travis.yml +10 -1
  4. data/Gemfile +4 -0
  5. data/README.md +1 -0
  6. data/app/assets/javascripts/trestle/_cookies.js +23 -0
  7. data/app/assets/javascripts/trestle/_sidebar.js +24 -3
  8. data/app/assets/stylesheets/trestle/components/_alerts.scss +28 -0
  9. data/app/assets/stylesheets/trestle/components/_navigation.scss +41 -6
  10. data/app/helpers/trestle/hook_helper.rb +8 -3
  11. data/app/views/trestle/application/_alert.html.erb +2 -0
  12. data/app/views/trestle/application/_flash.html.erb +18 -4
  13. data/app/views/trestle/resource/edit.html.erb +1 -1
  14. data/app/views/trestle/resource/index.html.erb +5 -2
  15. data/app/views/trestle/resource/new.html.erb +1 -1
  16. data/app/views/trestle/resource/show.html.erb +1 -1
  17. data/app/views/trestle/shared/_sidebar.html.erb +3 -2
  18. data/config/locales/en.yml +6 -4
  19. data/config/locales/nl.rb +18 -0
  20. data/config/locales/nl.yml +67 -0
  21. data/config/locales/pt-BR.rb +18 -0
  22. data/config/locales/pt-BR.yml +69 -0
  23. data/gemfiles/rails-4.2.gemfile +14 -0
  24. data/gemfiles/rails-5.0.gemfile +14 -0
  25. data/gemfiles/rails-5.1.gemfile +14 -0
  26. data/gemfiles/rails-edge.gemfile +15 -0
  27. data/lib/generators/trestle/install/templates/trestle.rb.erb +6 -0
  28. data/lib/trestle.rb +1 -0
  29. data/lib/trestle/configuration.rb +7 -1
  30. data/lib/trestle/display.rb +1 -1
  31. data/lib/trestle/model_name.rb +64 -0
  32. data/lib/trestle/navigation/group.rb +8 -0
  33. data/lib/trestle/navigation/item.rb +1 -1
  34. data/lib/trestle/options.rb +7 -5
  35. data/lib/trestle/resource.rb +2 -11
  36. data/lib/trestle/resource/controller.rb +12 -7
  37. data/lib/trestle/table.rb +3 -1
  38. data/lib/trestle/table/actions_column.rb +17 -14
  39. data/lib/trestle/table/automatic.rb +1 -2
  40. data/lib/trestle/table/builder.rb +2 -2
  41. data/lib/trestle/table/column.rb +3 -3
  42. data/lib/trestle/table/row.rb +2 -2
  43. data/lib/trestle/version.rb +1 -1
  44. data/trestle.gemspec +1 -0
  45. metadata +27 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f4f02402474a2f77fc6f4af6582e9b68f59274d0
4
- data.tar.gz: bb9815ae6b48b970443740c5b111aefef96dcea3
3
+ metadata.gz: f43ff0c051a7e29be0e0a815f1500753456f8aef
4
+ data.tar.gz: 75bc749e3cd64de9c5339e98dda6c921985d5c61
5
5
  SHA512:
6
- metadata.gz: c1593ee4dafcde35f20c312441df49e1b0861b82d87e387b4ed407e60a29758fb24e9efe4274339a1e04c78aac60cb0e85b9c76a425863fc3176d6a1f3afb70a
7
- data.tar.gz: 04e575f53c928a249a74aa4cc8ad3477c7cd16fad6ef26874e0d9adf9397bbfe070fd059f74b4c85c25cba599887d84dbf3f5da1fd0cd91d26704c85ef976a1b
6
+ metadata.gz: 86dbf71a36e6cfb0499e7ec5d6852103f9148acead9755775883fbb7011b019e435ccb7331866f19a6555c5d7fb9de049aed2139874a70bbe3417c88e79a806e
7
+ data.tar.gz: 10e8387dbb008465043180543be49f16a659372ce62f8d908b86595c91ebdb6b1b2950c7391c9ec7eb1041feb325f19c817e7c7f5c3e3fb5a078651d1518a0d2
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
3
  /Gemfile.lock
4
+ /gemfiles/*.lock
4
5
  /_yardoc/
5
6
  /coverage/
6
7
  /doc/
@@ -11,4 +12,7 @@
11
12
  /sandbox/*.sqlite3-journal
12
13
  /sandbox/log/*.log
13
14
  /sandbox/tmp/
15
+ /spec/dummy/db/*.sqlite3
16
+ /spec/dummy/*.sqlite3-journal
14
17
  /spec/dummy/log/*.log
18
+ /spec/dummy/tmp/*
@@ -1,4 +1,13 @@
1
1
  language: ruby
2
+
3
+ before_install:
4
+ - gem install bundler
5
+
2
6
  rvm:
3
7
  - 2.4.1
4
- before_install: gem install bundler
8
+
9
+ gemfile:
10
+ - gemfiles/rails-4.2.gemfile
11
+ - gemfiles/rails-5.0.gemfile
12
+ - gemfiles/rails-5.1.gemfile
13
+ - gemfiles/rails-edge.gemfile
data/Gemfile CHANGED
@@ -6,6 +6,10 @@ gemspec
6
6
  group :test do
7
7
  gem 'coveralls', require: false
8
8
  gem 'simplecov', require: false
9
+
10
+ gem 'capybara'
11
+ gem 'capybara-selenium'
12
+ gem 'selenium-webdriver'
9
13
  end
10
14
 
11
15
  gem 'haml'
data/README.md CHANGED
@@ -92,6 +92,7 @@ The following plugins are currently available:
92
92
  | *trestle-auth* | User authentication plugin | https://github.com/TrestleAdmin/trestle-auth |
93
93
  | *trestle-search* | Search plugin | https://github.com/TrestleAdmin/trestle-search |
94
94
  | *trestle-tinymce* | TinyMCE (WYSIWYG editor) integration | https://github.com/TrestleAdmin/trestle-tinymce |
95
+ | *trestle-simplemde* | SimpleMDE (Markdown editor) integration | https://github.com/TrestleAdmin/trestle-simplemde |
95
96
 
96
97
 
97
98
  ## License
@@ -0,0 +1,23 @@
1
+ Trestle.cookie = {
2
+ get: function(name) {
3
+ name += '=';
4
+
5
+ var cookies = document.cookie.split(/;\s*/)
6
+
7
+ for (i = cookies.length - 1; i >= 0; i--) {
8
+ if (!cookies[i].indexOf(name)) {
9
+ return cookies[i].replace(name, '');
10
+ }
11
+ }
12
+
13
+ return "";
14
+ },
15
+
16
+ set: function(name, value) {
17
+ document.cookie = name + "=" + encodeURIComponent(value) + "; path=/";
18
+ },
19
+
20
+ delete: function(name) {
21
+ document.cookie = name + "=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT";
22
+ }
23
+ };
@@ -40,13 +40,34 @@ Trestle.ready(function() {
40
40
 
41
41
  if (sidebar.hasClass('expanded') || sidebar.hasClass('collapsed')) {
42
42
  sidebar.removeClass('expanded').removeClass('collapsed');
43
- document.cookie = "trestle:sidebar=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT";
43
+ Trestle.cookie.delete("trestle:sidebar");
44
44
  } else if ($(document).width() >= 1200) {
45
45
  sidebar.addClass('collapsed');
46
- document.cookie = "trestle:sidebar=collapsed; path=/";
46
+ Trestle.cookie.set("trestle:sidebar", "collapsed");
47
47
  } else if ($(document).width() >= 768) {
48
48
  sidebar.addClass('expanded');
49
- document.cookie = "trestle:sidebar=expanded; path=/";
49
+ Trestle.cookie.set("trestle:sidebar", "expanded");
50
50
  }
51
51
  });
52
+
53
+
54
+ // Toggle navigation groups
55
+
56
+ sidebar.find('.nav-header a').on('click', function(e) {
57
+ e.preventDefault();
58
+
59
+ $(this).closest('ul').toggleClass('collapsed');
60
+
61
+ var collapsed = sidebar.find('.collapsed .nav-header a').map(function() {
62
+ return $(this).attr('href').replace(/^#/, '');
63
+ }).toArray();
64
+
65
+ Trestle.cookie.set("trestle:navigation:collapsed", collapsed.join(","))
66
+ });
67
+
68
+
69
+ // Scroll sidebar to active item
70
+
71
+ var active = sidebar.find('.active');
72
+ sidebar.find('.app-sidebar-inner').scrollTop(active.offset().top - 100);
52
73
  });
@@ -22,6 +22,10 @@
22
22
  margin-bottom: 0;
23
23
  }
24
24
 
25
+ a {
26
+ color: white;
27
+ }
28
+
25
29
  @include mobile {
26
30
  padding: 5px 10px;
27
31
 
@@ -57,3 +61,27 @@
57
61
  }
58
62
  }
59
63
  }
64
+
65
+ .toggle-debug-errors {
66
+ &:hover, &:focus {
67
+ text-decoration: none;
68
+ }
69
+
70
+ &:after {
71
+ @extend .ion;
72
+ content: $ionicon-var-chevron-down;
73
+ font-size: 10px;
74
+ margin-left: 5px;
75
+ }
76
+ }
77
+
78
+ .debug-errors {
79
+ overflow: hidden;
80
+
81
+ ul {
82
+ list-style: none;
83
+ margin: 5px 0 0 0;
84
+ padding: 0 0 0 5px;
85
+ border-left: 4px solid rgba(white, 0.25);
86
+ }
87
+ }
@@ -38,7 +38,8 @@
38
38
  vertical-align: 0;
39
39
  }
40
40
 
41
- .nav-header {
41
+ .nav-header a {
42
+ position: relative;
42
43
  color: rgba(white, 0.25);
43
44
 
44
45
  text-transform: uppercase;
@@ -46,6 +47,24 @@
46
47
  font-size: 11px;
47
48
 
48
49
  padding: 5px 20px;
50
+
51
+ &:after {
52
+ @extend .ion;
53
+ content: $ionicon-var-arrow-down-b;
54
+
55
+ float: right;
56
+ margin-top: 2px;
57
+
58
+ opacity: 0.75;
59
+ }
60
+
61
+ &:hover, &:focus {
62
+ background: none;
63
+
64
+ &:after {
65
+ opacity: 1.0;
66
+ }
67
+ }
49
68
  }
50
69
 
51
70
  .active a {
@@ -62,14 +81,30 @@
62
81
  position: relative;
63
82
  top: 1px;
64
83
  }
84
+
85
+ .collapsed {
86
+ li {
87
+ display: none;
88
+
89
+ &.nav-header {
90
+ display: block;
91
+ }
92
+ }
93
+ }
65
94
  }
66
95
 
67
96
  @mixin collapsed-nav-header {
68
- border-bottom: 1px solid rgba(white, 0.1);
69
97
  height: 0;
70
- margin: 0 15px 14px;
71
- padding: 5px 0;
98
+ padding: 10px 15px 15px;
72
99
  text-indent: -99999px;
100
+
101
+ &:after {
102
+ display: block;
103
+ float: none;
104
+ margin-top: -12px;
105
+ content: '';
106
+ border-bottom: 1px solid rgba(white, 0.1);
107
+ }
73
108
  }
74
109
 
75
110
  @include tablet {
@@ -78,7 +113,7 @@
78
113
  display: none;
79
114
  }
80
115
 
81
- .nav-header {
116
+ .nav-header a {
82
117
  @include collapsed-nav-header;
83
118
  }
84
119
 
@@ -104,7 +139,7 @@
104
139
  display: none;
105
140
  }
106
141
 
107
- .nav-header {
142
+ .nav-header a {
108
143
  @include collapsed-nav-header;
109
144
  }
110
145
  }
@@ -1,13 +1,18 @@
1
1
  module Trestle
2
2
  module HookHelper
3
3
  def hook(name)
4
- safe_join(Trestle.config.hooks[name.to_s].map { |hook|
4
+ safe_join(hooks[name.to_s].map { |hook|
5
5
  instance_exec(&hook)
6
- }, "\n")
6
+ }, "\n") if hook?(name)
7
7
  end
8
8
 
9
9
  def hook?(name)
10
- Trestle.config.hooks[name.to_s].any?
10
+ hooks.key?(name.to_s) && hooks[name.to_s].any?
11
+ end
12
+
13
+ protected
14
+ def hooks
15
+ Trestle.config.hooks
11
16
  end
12
17
  end
13
18
  end
@@ -6,5 +6,7 @@
6
6
  <div class="alert-content">
7
7
  <h3><%= title %></h3>
8
8
  <p><%= message %></p>
9
+
10
+ <%= yield if block_given? %>
9
11
  </div>
10
12
  </div>
@@ -4,8 +4,22 @@
4
4
  title: t("trestle.flash.success.title", default: "Success!"),
5
5
  message: flash[:message] %>
6
6
  <% elsif flash[:error] -%>
7
- <%= render "alert", html_class: "alert-danger",
8
- icon: icon("alert-icon ion-ios-close-outline"),
9
- title: t("trestle.flash.failure.title", default: "Warning!"),
10
- message: flash[:error] %>
7
+ <%= render layout: "alert",
8
+ locals: {
9
+ html_class: "alert-danger",
10
+ icon: icon("alert-icon ion-ios-close-outline"),
11
+ title: t("trestle.flash.failure.title", default: "Warning!"),
12
+ message: flash[:error]
13
+ } do %>
14
+ <%- if Trestle.config.debug_form_errors && instance && instance.errors.any? -%>
15
+ <%= link_to "Debug errors", "#debug-errors", class: "toggle-debug-errors small", data: { toggle: "collapse" } %>
16
+ <div id="debug-errors" class="debug-errors collapse">
17
+ <ul>
18
+ <% instance.errors.each do |key, message| %>
19
+ <li class="small"><tt><%= key %>:</tt> <%= message %></li>
20
+ <% end %>
21
+ </ul>
22
+ </div>
23
+ <%- end -%>
24
+ <% end %>
11
25
  <% end -%>
@@ -1,4 +1,4 @@
1
- <% title = t("admin.titles.edit", default: "Editing %{model_name}", model_name: admin.model_name, pluralized_model_name: admin.model_name.pluralize) %>
1
+ <% title = t("admin.titles.edit", default: "Editing %{model_name}", model_name: admin.model_name.titleize, pluralized_model_name: admin.model_name.plural.titleize) %>
2
2
 
3
3
  <% content_for(:title, title) %>
4
4
  <% breadcrumb title %>
@@ -1,7 +1,10 @@
1
- <% content_for(:title, t("admin.titles.index", default: "Listing %{pluralized_model_name}", model_name: admin.model_name, pluralized_model_name: admin.model_name.pluralize)) %>
1
+ <% content_for(:title, t("admin.titles.index", default: "Listing %{pluralized_model_name}", model_name: admin.model_name.titleize, pluralized_model_name: admin.model_name.plural.titleize)) %>
2
2
 
3
3
  <% content_for(:primary_toolbar) do %>
4
- <%= link_to icon("fa fa-plus"), admin.path(:new), class: "btn btn-default btn-lg" unless admin.readonly? %>
4
+ <%= link_to admin.path(:new), class: "btn btn-default btn-lg" do %>
5
+ <%= icon("fa fa-plus") %>
6
+ <span class="sr-only"><%= t("admin.buttons.new", default: "New %{model_name}", model_name: admin.model_name) %></span>
7
+ <% end unless admin.readonly? %>
5
8
  <% end %>
6
9
 
7
10
  <% content_for(:utilities) do %>
@@ -1,4 +1,4 @@
1
- <% title = t("admin.titles.new", default: "New %{model_name}", model_name: admin.model_name, pluralized_model_name: admin.model_name.pluralize) %>
1
+ <% title = t("admin.titles.new", default: "New %{model_name}", model_name: admin.model_name.titleize, pluralized_model_name: admin.model_name.plural.titleize) %>
2
2
 
3
3
  <% content_for(:title, title) %>
4
4
  <% breadcrumb title %>
@@ -1,4 +1,4 @@
1
- <% title = t("admin.titles.edit", default: "Editing %{model_name}", model_name: admin.model_name, pluralized_model_name: admin.model_name.pluralize) %>
1
+ <% title = t("admin.titles.edit", default: "Editing %{model_name}", model_name: admin.model_name.titleize, pluralized_model_name: admin.model_name.plural.titleize) %>
2
2
 
3
3
  <% content_for(:title, title) %>
4
4
  <% breadcrumb title %>
@@ -12,10 +12,11 @@
12
12
 
13
13
  <div class="app-sidebar-inner">
14
14
  <nav class="app-nav">
15
+ <% collapsed = cookies["trestle:navigation:collapsed"].try(:split, ",") || [] %>
15
16
  <% Trestle.navigation.each do |group, items| %>
16
- <ul>
17
+ <ul<% if group.present? && collapsed.include?(group.id) %> class="collapsed"<% end %>>
17
18
  <% if group.present? %>
18
- <li class="nav-header"><%= group.label %></li>
19
+ <li class="nav-header"><%= link_to group.label, "##{group.id}" %></li>
19
20
  <% end %>
20
21
 
21
22
  <% items.each do |item| %>
@@ -7,15 +7,15 @@ en:
7
7
  flash:
8
8
  success:
9
9
  title: "Success!"
10
- create: "The %{model_name} was successfully created."
11
- update: "The %{model_name} was successfully updated."
12
- destroy: "The %{model_name} was successfully deleted."
10
+ create: "The %{lowercase_model_name} was successfully created."
11
+ update: "The %{lowercase_model_name} was successfully updated."
12
+ destroy: "The %{lowercase_model_name} was successfully deleted."
13
13
 
14
14
  failure:
15
15
  title: "Warning!"
16
16
  create: "Please correct the errors below."
17
17
  update: "Please correct the errors below."
18
- destroy: "Could not delete %{model_name}."
18
+ destroy: "Could not delete %{lowercase_model_name}."
19
19
 
20
20
  helpers:
21
21
  page_entries_info:
@@ -37,9 +37,11 @@ en:
37
37
  admin:
38
38
  titles:
39
39
  index: Listing %{pluralized_model_name}
40
+ new: New %{model_name}
40
41
  edit: Editing %{model_name}
41
42
 
42
43
  buttons:
44
+ new: New %{model_name}
43
45
  save: Save %{model_name}
44
46
  delete: Delete %{model_name}
45
47
 
@@ -0,0 +1,18 @@
1
+ {
2
+ nl: {
3
+ date: {
4
+ formats: {
5
+ trestle_date: proc { |date| "#{date.day} %b %Y" },
6
+ trestle_calendar: "%-d-%-m-%Y"
7
+ }
8
+ },
9
+
10
+ time: {
11
+ formats: {
12
+ trestle_date: proc { |time| "#{time.day} %b %Y" },
13
+ trestle_time: "%R %p",
14
+ trestle_time_with_seconds: "%T %p"
15
+ }
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,67 @@
1
+ nl:
2
+ trestle:
3
+ title: Trestle Admin
4
+ footer: Powered by Trestle
5
+ version: Versie
6
+
7
+ flash:
8
+ success:
9
+ title: "Gelukt!"
10
+ create: "De %{model_name} succesvol toegevoegd."
11
+ update: "De %{model_name} is succesvol gewijzigd."
12
+ destroy: "De %{model_name} is succesvol verwijderd."
13
+
14
+ failure:
15
+ title: "Waarschuwing!"
16
+ create: "Kon niet toevoegen om de volgende redenen."
17
+ update: "Kon niet aanpassen om de volgende redenen."
18
+ destroy: "Kon %{model_name} niet verwijderen."
19
+
20
+ helpers:
21
+ page_entries_info:
22
+ one_page:
23
+ display_entries:
24
+ zero: "Geen %{entry_name} gevonden"
25
+ one: "<strong>1</strong> %{entry_name} wordt weergeven"
26
+ other: "<strong>Alle %{count}</strong> %{entry_name} worden weergeven"
27
+
28
+ more_pages:
29
+ display_entries: "%{entry_name} <strong>%{first}&nbsp;-&nbsp;%{last}</strong> van de <b>%{total}</b> worden weergeven"
30
+
31
+ onboarding:
32
+ welcome: Welkom bij Trestle
33
+ no_admins: Voeg een admin toe in <code>app/admin</code> om te beginnen.
34
+ no_template: Maak <code>%{path}</code> aan om dit template aan te passen.
35
+ no_form: Definieer een form block of maak een <code>_form.html</code> partial.
36
+
37
+ admin:
38
+ titles:
39
+ index: Lijst van %{pluralized_model_name}
40
+ edit: "%{model_name} aanpassen"
41
+
42
+ buttons:
43
+ save: "%{model_name} opslaan"
44
+ delete: "%{model_name} verwijderen"
45
+
46
+ breadcrumbs:
47
+ home: Home
48
+
49
+ table:
50
+ headers:
51
+ id: ID
52
+
53
+ form:
54
+ select:
55
+ prompt: "- Selecteer %{attribute_name} -"
56
+
57
+ confirmation:
58
+ title: Weer je het zeker?
59
+ delete: Verwijderen
60
+ cancel: Annuleren
61
+
62
+ ui:
63
+ toggle_navigation: "Navigation tonen/verbergen"
64
+ toggle_sidebar: "Sidebar tonen/verbergen"
65
+
66
+ format:
67
+ blank: Geen
@@ -0,0 +1,18 @@
1
+ {
2
+ 'pt-BR': {
3
+ date: {
4
+ formats: {
5
+ trestle_date: proc { |date| "#{date.day}º %b %Y" },
6
+ trestle_calendar: "%-m/%-d/%Y"
7
+ }
8
+ },
9
+
10
+ time: {
11
+ formats: {
12
+ trestle_date: proc { |time| "#{time.day}º %b %Y" },
13
+ trestle_time: "%-l:%M %p",
14
+ trestle_time_with_seconds: "%l:%M:%S %p"
15
+ }
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,69 @@
1
+ pt-BR:
2
+ trestle:
3
+ title: Trestle Admin
4
+ footer: Powered by Trestle
5
+ version: Versão
6
+
7
+ flash:
8
+ success:
9
+ title: "Sucesso!"
10
+ create: "O %{model_name} foi criado com sucesso."
11
+ update: "O %{model_name} foi atualizado com sucesso."
12
+ destroy: "O %{model_name} foi deletado com sucesso."
13
+
14
+ failure:
15
+ title: "Atenção!"
16
+ create: "Por favor corrija os erros abaixo."
17
+ update: "Por favor corrija os erros abaixo."
18
+ destroy: "Falha ao excluir %{model_name}."
19
+
20
+ helpers:
21
+ page_entries_info:
22
+ one_page:
23
+ display_entries:
24
+ zero: "Nenhum %{entry_name} encontrado"
25
+ one: "Mostrando <strong>1</strong> %{entry_name}"
26
+ other: "Mostrando <strong>all %{count}</strong> %{entry_name}"
27
+
28
+ more_pages:
29
+ display_entries: "Mostrando %{entry_name} <strong>%{first}&nbsp;-&nbsp;%{last}</strong> de <b>%{total}</b>"
30
+
31
+ onboarding:
32
+ welcome: Bem-vindo ao Trestle
33
+ no_admins: Para começar, crie um admin dentro de <code>app/admin</code>.
34
+ no_template: Para personalizar este template, crie <code>%{path}</code>.
35
+ no_form: Defina um bloco de formulário ou crie um <code>_form.html</code> parcial.
36
+
37
+ admin:
38
+ titles:
39
+ index: Listando %{pluralized_model_name}
40
+ new: Novo %{model_name}
41
+ edit: Editando %{model_name}
42
+
43
+ buttons:
44
+ new: Novo %{model_name}
45
+ save: Salvar %{model_name}
46
+ delete: Excluir %{model_name}
47
+
48
+ breadcrumbs:
49
+ home: Home
50
+
51
+ table:
52
+ headers:
53
+ id: ID
54
+
55
+ form:
56
+ select:
57
+ prompt: "- Selecione %{attribute_name} -"
58
+
59
+ confirmation:
60
+ title: Você tem certeza?
61
+ delete: Excluir
62
+ cancel: Cancelar
63
+
64
+ ui:
65
+ toggle_navigation: Alternar naveção
66
+ toggle_sidebar: Alternar barra lateral
67
+
68
+ format:
69
+ blank: Nenhum
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'coveralls', require: false
5
+ gem 'simplecov', require: false
6
+
7
+ gem 'capybara'
8
+ gem 'capybara-selenium'
9
+ gem 'selenium-webdriver'
10
+ end
11
+
12
+ gem 'rails', '~> 4.2.0'
13
+
14
+ gemspec :path => "../"
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'coveralls', require: false
5
+ gem 'simplecov', require: false
6
+
7
+ gem 'capybara'
8
+ gem 'capybara-selenium'
9
+ gem 'selenium-webdriver'
10
+ end
11
+
12
+ gem 'rails', '~> 5.0.0'
13
+
14
+ gemspec :path => "../"
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'coveralls', require: false
5
+ gem 'simplecov', require: false
6
+
7
+ gem 'capybara'
8
+ gem 'capybara-selenium'
9
+ gem 'selenium-webdriver'
10
+ end
11
+
12
+ gem 'rails', '~> 5.1.0'
13
+
14
+ gemspec :path => "../"
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'coveralls', require: false
5
+ gem 'simplecov', require: false
6
+
7
+ gem 'capybara'
8
+ gem 'capybara-selenium'
9
+ gem 'selenium-webdriver'
10
+ end
11
+
12
+ gem 'rails', github: 'rails/rails'
13
+ gem 'arel', github: 'rails/arel'
14
+
15
+ gemspec :path => "../"
@@ -105,4 +105,10 @@ Trestle.configure do |config|
105
105
  # end
106
106
  #
107
107
  # config.form_field :custom, CustomFormField
108
+
109
+ # == Debugging Options
110
+ #
111
+ # Enable debugging of form errors. Defaults to true in development mode.
112
+ #
113
+ # config.debug_form_errors = true
108
114
  end
@@ -18,6 +18,7 @@ module Trestle
18
18
  autoload :Configuration
19
19
  autoload :Display
20
20
  autoload :Form
21
+ autoload :ModelName
21
22
  autoload :Navigation
22
23
  autoload :Options
23
24
  autoload :Reloader
@@ -64,7 +64,7 @@ module Trestle
64
64
  option :persistent_params, [:sort, :order, :scope]
65
65
 
66
66
  # List of methods to try calling on an instance when displayed by the `display` helper
67
- option :display_methods, [:display_name, :full_name, :name, :title, :username, :login, :email, :to_s]
67
+ option :display_methods, [:display_name, :full_name, :name, :title, :username, :login, :email]
68
68
 
69
69
  # Default adapter class used by all admin resources
70
70
  option :default_adapter, Adapters.compose(Adapters::ActiveRecordAdapter, Adapters::DraperAdapter)
@@ -86,6 +86,12 @@ module Trestle
86
86
  option :javascript_i18n_keys, ["admin.confirmation.title", "admin.confirmation.delete", "admin.confirmation.cancel"]
87
87
 
88
88
 
89
+ ## Debugging
90
+
91
+ # Enable debugging of form errors
92
+ option :debug_form_errors, Rails.env.development?
93
+
94
+
89
95
  ## Callbacks
90
96
 
91
97
  Action = Struct.new(:options, :block)
@@ -14,7 +14,7 @@ module Trestle
14
14
 
15
15
  private
16
16
  def display_method
17
- @display_method ||= Trestle.config.display_methods.find { |m| @instance.respond_to?(m) }
17
+ @display_method ||= Trestle.config.display_methods.find { |m| @instance.respond_to?(m) } || :to_s
18
18
  end
19
19
  end
20
20
  end
@@ -0,0 +1,64 @@
1
+ require "active_model/naming"
2
+
3
+ module Trestle
4
+ class ModelName
5
+ attr_reader :klass
6
+
7
+ delegate :downcase, :upcase, :titleize, :titlecase, to: :to_s
8
+
9
+ def initialize(klass)
10
+ @klass = klass
11
+ @name = klass.respond_to?(:model_name) ? klass.model_name : ActiveModel::Name.new(klass)
12
+ end
13
+
14
+ def ==(other)
15
+ other.is_a?(self.class) && klass == other.klass
16
+ end
17
+
18
+ def to_s
19
+ singular
20
+ end
21
+
22
+ def singular(options={})
23
+ human(default_singular, options)
24
+ end
25
+ alias_method :singularize, :singular
26
+
27
+ def plural(options={})
28
+ if i18n_supported? && i18n_pluralizations_available?
29
+ human(default_plural, { count: :many }.merge(options))
30
+ else
31
+ default_plural
32
+ end
33
+ end
34
+ alias_method :pluralize, :plural
35
+
36
+ protected
37
+ # Default singular version if it cannot be determined from i18n
38
+ def default_singular
39
+ @name.name.demodulize.titleize
40
+ end
41
+
42
+ # Default plural version if it cannot be determined from i18n
43
+ def default_plural
44
+ singular.pluralize(I18n.locale)
45
+ end
46
+
47
+ # Safely delegates to ActiveModel::Name#human, catching exceptions caused by missing pluralizations
48
+ def human(default, options={})
49
+ @name.human(options.merge(default: default))
50
+ rescue I18n::InvalidPluralizationData
51
+ default
52
+ end
53
+
54
+ # Checks if the model can be translated by ActiveModel
55
+ def i18n_supported?
56
+ klass.respond_to?(:lookup_ancestors) && klass.respond_to?(:i18n_scope)
57
+ end
58
+
59
+ # Checks if multiple pluralization forms (e.g. zero/one/few/many/other) are available from i18n
60
+ def i18n_pluralizations_available?
61
+ @name.human(count: nil).is_a?(Hash)
62
+ end
63
+ end
64
+ end
@@ -40,6 +40,10 @@ module Trestle
40
40
  def label
41
41
  I18n.t("admin.navigation.groups.#{name}", default: name.to_s.titlecase)
42
42
  end
43
+
44
+ def id
45
+ name.to_s.parameterize
46
+ end
43
47
  end
44
48
 
45
49
  class NullGroup
@@ -59,6 +63,10 @@ module Trestle
59
63
  NullGroup.hash
60
64
  end
61
65
 
66
+ def id
67
+ nil
68
+ end
69
+
62
70
  def <=>(other)
63
71
  -1
64
72
  end
@@ -40,7 +40,7 @@ module Trestle
40
40
  end
41
41
 
42
42
  def label
43
- I18n.t("admin.navigation.items.#{name}", default: name.to_s.titlecase)
43
+ options[:label] || I18n.t("admin.navigation.items.#{name}", default: name.to_s.titlecase)
44
44
  end
45
45
 
46
46
  def icon
@@ -4,13 +4,15 @@ module Trestle
4
4
  self[hash]
5
5
  end
6
6
 
7
- def merge(other)
8
- dup.merge!(other)
7
+ def merge(other, &block)
8
+ dup.merge!(other, &block)
9
9
  end
10
10
 
11
- def merge!(other)
12
- deep_merge!(other || {}) do |key, v1, v2|
13
- if v1.is_a?(Array)
11
+ def merge!(other, &block)
12
+ super(other || {}) do |key, v1, v2|
13
+ if v1.is_a?(Hash) && v2.is_a?(Hash)
14
+ v1.merge(v2, &block)
15
+ elsif v1.is_a?(Array)
14
16
  v1 + Array(v2)
15
17
  else
16
18
  v2
@@ -119,7 +119,7 @@ module Trestle
119
119
  end
120
120
 
121
121
  def model_name
122
- options[:as] || default_model_name
122
+ @model_name ||= Trestle::ModelName.new(model)
123
123
  end
124
124
 
125
125
  def readonly?
@@ -127,7 +127,7 @@ module Trestle
127
127
  end
128
128
 
129
129
  def breadcrumb
130
- Breadcrumb.new(model_name.pluralize, path)
130
+ Breadcrumb.new(model_name.plural.titleize, path)
131
131
  end
132
132
 
133
133
  def routes
@@ -150,15 +150,6 @@ module Trestle
150
150
  rescue NameError
151
151
  raise NameError, "Unable to find model #{admin_name.classify}. Specify a different model using Trestle.resource(:#{admin_name}, model: MyModel)"
152
152
  end
153
-
154
- def default_model_name
155
- if model.respond_to?(:model_name)
156
- model_name = model.model_name
157
- model_name.respond_to?(:human) ? model_name.human : model_name.to_s.titleize
158
- else
159
- model.name.titleize
160
- end
161
- end
162
153
  end
163
154
  end
164
155
  end
@@ -25,7 +25,7 @@ module Trestle
25
25
  if admin.save_instance(instance)
26
26
  respond_to do |format|
27
27
  format.html do
28
- flash[:message] = flash_message("success.create", default: "The %{model_name} was successfully created.")
28
+ flash[:message] = flash_message("success.create", default: "The %{lowercase_model_name} was successfully created.")
29
29
  redirect_to action: :show, id: admin.to_param(instance)
30
30
  end
31
31
  format.json { render json: instance, status: :created, location: { action: :show, id: admin.to_param(instance) } }
@@ -62,7 +62,7 @@ module Trestle
62
62
  if admin.save_instance(instance)
63
63
  respond_to do |format|
64
64
  format.html do
65
- flash[:message] = flash_message("success.update", default: "The %{model_name} was successfully updated.")
65
+ flash[:message] = flash_message("success.update", default: "The %{lowercase_model_name} was successfully updated.")
66
66
  redirect_to action: :show, id: admin.to_param(instance)
67
67
  end
68
68
  format.json { render json: instance, status: :ok }
@@ -86,12 +86,17 @@ module Trestle
86
86
  respond_to do |format|
87
87
  format.html do
88
88
  if success
89
- flash[:message] = flash_message("success.destroy", default: "The %{model_name} was successfully deleted.")
89
+ flash[:message] = flash_message("success.destroy", default: "The %{lowercase_model_name} was successfully deleted.")
90
+ redirect_to action: :index
90
91
  else
91
- flash[:message] = flash_message("failure.destroy", default: "Could not delete %{model_name}.")
92
- end
92
+ flash[:error] = flash_message("failure.destroy", default: "Could not delete %{lowercase_model_name}.")
93
93
 
94
- redirect_to action: :index
94
+ if self.instance = admin.find_instance(params)
95
+ redirect_to action: :show, id: admin.to_param(instance)
96
+ else
97
+ redirect_to action: :index
98
+ end
99
+ end
95
100
  end
96
101
  format.json { head :no_content }
97
102
  format.js
@@ -106,7 +111,7 @@ module Trestle
106
111
  helper_method :instance
107
112
 
108
113
  def flash_message(type, options={})
109
- t("trestle.flash.#{type}", options.merge(model_name: admin.model_name.underscore.humanize(capitalize: false)))
114
+ t("trestle.flash.#{type}", options.merge(model_name: admin.model_name, lowercase_model_name: admin.model_name.downcase))
110
115
  end
111
116
  end
112
117
  end
@@ -9,11 +9,13 @@ module Trestle
9
9
  autoload :SelectColumn
10
10
  autoload :Row
11
11
 
12
- attr_reader :columns, :options
12
+ attr_reader :columns, :options, :admin
13
13
  attr_writer :row
14
14
 
15
15
  def initialize(options={})
16
16
  @options = options
17
+ @admin = Trestle.lookup(options[:admin]) if options.key?(:admin)
18
+
17
19
  @columns = []
18
20
  end
19
21
 
@@ -1,10 +1,10 @@
1
1
  module Trestle
2
2
  class Table
3
3
  class ActionsColumn
4
- attr_reader :table, :block
4
+ attr_reader :table, :options, :block
5
5
 
6
- def initialize(table, &block)
7
- @table = table
6
+ def initialize(table, options={}, &block)
7
+ @table, @options = table, options
8
8
  @block = block_given? ? block : default_actions
9
9
  end
10
10
 
@@ -23,37 +23,40 @@ module Trestle
23
23
 
24
24
  delegate :table, to: :@column
25
25
 
26
+ delegate :icon, :admin_url_for, :concat, :link_to, to: :@template
27
+
26
28
  def initialize(column, template, instance)
27
29
  @column, @template, @instance = column, template, instance
28
30
  end
29
31
 
32
+ def show
33
+ button(icon("fa fa-info"), admin_url_for(instance, admin: table.admin, action: :show), class: "btn-info")
34
+ end
35
+
36
+ def edit
37
+ button(icon("fa fa-pencil"), admin_url_for(instance, admin: table.admin, action: :edit), class: "btn-warning")
38
+ end
39
+
30
40
  def delete
31
- button(@template.icon("fa fa-trash"), @template.admin_url_for(instance, admin: table.options[:admin], action: :destroy), method: :delete, class: "btn-danger", data: { toggle: "confirm-delete", placement: "left" })
41
+ button(icon("fa fa-trash"), admin_url_for(instance, admin: table.admin, action: :destroy), method: :delete, class: "btn-danger", data: { toggle: "confirm-delete", placement: "left" })
32
42
  end
33
43
 
34
44
  def button(content, url, options={})
35
45
  options[:class] = Array(options[:class])
36
46
  options[:class] << "btn" unless options[:class].include?("btn")
37
47
 
38
- @template.concat @template.link_to(content, url, options)
48
+ concat link_to(content, url, options)
39
49
  end
40
50
  alias_method :link, :button
41
51
  end
42
52
 
43
53
  class Renderer < Column::Renderer
44
54
  def header
55
+ options[:header]
45
56
  end
46
57
 
47
58
  def classes
48
- "actions"
49
- end
50
-
51
- def options
52
- {}
53
- end
54
-
55
- def data
56
- {}
59
+ super + ["actions"]
57
60
  end
58
61
 
59
62
  def content(instance)
@@ -3,7 +3,6 @@ module Trestle
3
3
  class Automatic < Table
4
4
  def initialize(admin)
5
5
  super(sortable: true, admin: admin)
6
- @admin = admin
7
6
  end
8
7
 
9
8
  def columns
@@ -11,7 +10,7 @@ module Trestle
11
10
  end
12
11
 
13
12
  def content_columns
14
- @admin.default_table_attributes.map.with_index do |attribute, index|
13
+ admin.default_table_attributes.map.with_index do |attribute, index|
15
14
  case attribute.type
16
15
  when :association
17
16
  Column.new(self, attribute.association_name, sort: false)
@@ -25,8 +25,8 @@ module Trestle
25
25
  table.columns << Column.new(table, field, options, &(proc || block))
26
26
  end
27
27
 
28
- def actions(&block)
29
- table.columns << ActionsColumn.new(table, &block)
28
+ def actions(options={}, &block)
29
+ table.columns << ActionsColumn.new(table, options, &block)
30
30
  end
31
31
  end
32
32
  end
@@ -31,8 +31,8 @@ module Trestle
31
31
  def header
32
32
  if options[:header]
33
33
  options[:header]
34
- elsif admin = table.options[:admin]
35
- admin.human_attribute_name(field)
34
+ elsif table.admin
35
+ table.admin.human_attribute_name(field)
36
36
  else
37
37
  field.to_s.humanize.titleize
38
38
  end
@@ -62,7 +62,7 @@ module Trestle
62
62
  content = @template.admin_link_to(content, value)
63
63
  elsif options[:link]
64
64
  # Explicitly link to the specified admin, or the table's admin
65
- content = @template.admin_link_to(content, instance, admin: options[:admin] || @column.table.options[:admin])
65
+ content = @template.admin_link_to(content, instance, admin: options[:admin] || @column.table.admin)
66
66
  end
67
67
 
68
68
  content
@@ -21,7 +21,7 @@ module Trestle
21
21
 
22
22
  def options(instance)
23
23
  options = Trestle::Options.new
24
- options.merge!(data: { url: admin_url_for(instance) }) if table.options[:admin]
24
+ options.merge!(data: { url: admin_url_for(instance) }) if table.admin
25
25
  options.merge!(@row.options)
26
26
  options.merge!(@template.instance_exec(instance, &@row.block)) if @row.block
27
27
  options
@@ -29,7 +29,7 @@ module Trestle
29
29
 
30
30
  protected
31
31
  def admin_url_for(instance)
32
- @template.admin_url_for(instance, admin: table.options[:admin])
32
+ @template.admin_url_for(instance, admin: table.admin)
33
33
  end
34
34
  end
35
35
  end
@@ -1,3 +1,3 @@
1
1
  module Trestle
2
- VERSION = "0.8.4"
2
+ VERSION = "0.8.5"
3
3
  end
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.required_ruby_version = ">= 2.2.2"
35
35
 
36
36
  spec.add_dependency "railties", ">= 4.2.0"
37
+ spec.add_dependency "activemodel", ">= 4.2.0"
37
38
  spec.add_dependency "sass-rails", "~> 5.0.6"
38
39
  spec.add_dependency "autoprefixer-rails", "~> 7.1.2"
39
40
  spec.add_dependency "kaminari", "~> 1.0.1"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trestle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.4
4
+ version: 0.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Pohlenz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-24 00:00:00.000000000 Z
11
+ date: 2017-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 4.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activemodel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 4.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 4.2.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: sass-rails
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -168,6 +182,7 @@ files:
168
182
  - app/assets/images/trestle/textures/billie-holiday.png
169
183
  - app/assets/images/trestle/textures/bright-squares.png
170
184
  - app/assets/javascripts/trestle/_confirmation.js
185
+ - app/assets/javascripts/trestle/_cookies.js
171
186
  - app/assets/javascripts/trestle/_datepicker.js
172
187
  - app/assets/javascripts/trestle/_errors.js
173
188
  - app/assets/javascripts/trestle/_form.js
@@ -264,7 +279,15 @@ files:
264
279
  - bower.json
265
280
  - config/locales/en.rb
266
281
  - config/locales/en.yml
282
+ - config/locales/nl.rb
283
+ - config/locales/nl.yml
284
+ - config/locales/pt-BR.rb
285
+ - config/locales/pt-BR.yml
267
286
  - config/routes.rb
287
+ - gemfiles/rails-4.2.gemfile
288
+ - gemfiles/rails-5.0.gemfile
289
+ - gemfiles/rails-5.1.gemfile
290
+ - gemfiles/rails-edge.gemfile
268
291
  - lib/generators/trestle/admin/admin_generator.rb
269
292
  - lib/generators/trestle/admin/templates/admin.rb.erb
270
293
  - lib/generators/trestle/admin/templates/index.html.erb
@@ -329,6 +352,7 @@ files:
329
352
  - lib/trestle/form/fields/url_field.rb
330
353
  - lib/trestle/form/fields/week_field.rb
331
354
  - lib/trestle/form/renderer.rb
355
+ - lib/trestle/model_name.rb
332
356
  - lib/trestle/navigation.rb
333
357
  - lib/trestle/navigation/block.rb
334
358
  - lib/trestle/navigation/group.rb
@@ -560,7 +584,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
560
584
  version: '0'
561
585
  requirements: []
562
586
  rubyforge_project:
563
- rubygems_version: 2.6.12
587
+ rubygems_version: 2.6.13
564
588
  signing_key:
565
589
  specification_version: 4
566
590
  summary: A modern, responsive admin framework for Ruby on Rails