trestle 0.8.4 → 0.8.11

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.
Files changed (164) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -0
  3. data/.travis.yml +14 -1
  4. data/Gemfile +6 -0
  5. data/README.md +15 -9
  6. data/app/assets/javascripts/trestle/admin.js +11 -10
  7. data/app/assets/javascripts/trestle/components/_confirmation.js +40 -0
  8. data/app/assets/javascripts/trestle/components/_datepicker.js +37 -0
  9. data/app/assets/javascripts/trestle/components/_dialog.js +136 -0
  10. data/app/assets/javascripts/trestle/{_errors.js → components/_errors.js} +2 -2
  11. data/app/assets/javascripts/trestle/components/_form.js +75 -0
  12. data/app/assets/javascripts/trestle/{_gallery.js → components/_gallery.js} +3 -3
  13. data/app/assets/javascripts/trestle/{_select.js → components/_select.js} +2 -2
  14. data/app/assets/javascripts/trestle/components/_sidebar.js +77 -0
  15. data/app/assets/javascripts/trestle/{_table.js → components/_table.js} +1 -1
  16. data/app/assets/javascripts/trestle/components/_tabs.js +25 -0
  17. data/app/assets/javascripts/trestle/components/_tooltips.js +19 -0
  18. data/app/assets/javascripts/trestle/core/_contexts.js +13 -0
  19. data/app/assets/javascripts/trestle/core/_cookies.js +24 -0
  20. data/app/assets/javascripts/trestle/core/_events.js +39 -0
  21. data/app/assets/javascripts/trestle/core/_l10n.js +23 -0
  22. data/app/assets/javascripts/trestle/core/_visit.js +10 -0
  23. data/app/assets/stylesheets/trestle/components/_alerts.scss +28 -0
  24. data/app/assets/stylesheets/trestle/components/_avatar.scss +23 -1
  25. data/app/assets/stylesheets/trestle/components/_breadcrumbs.scss +12 -0
  26. data/app/assets/stylesheets/trestle/components/_buttons.scss +111 -1
  27. data/app/assets/stylesheets/trestle/components/_content.scss +53 -21
  28. data/app/assets/stylesheets/trestle/components/_datepicker.scss +28 -0
  29. data/app/assets/stylesheets/trestle/components/_fields.scss +17 -0
  30. data/app/assets/stylesheets/trestle/components/_input-group.scss +26 -1
  31. data/app/assets/stylesheets/trestle/components/_modal.scss +108 -0
  32. data/app/assets/stylesheets/trestle/components/_navigation.scss +104 -14
  33. data/app/assets/stylesheets/trestle/components/_pagination.scss +3 -3
  34. data/app/assets/stylesheets/trestle/components/_scopes.scss +11 -2
  35. data/app/assets/stylesheets/trestle/components/_sidebar.scss +3 -2
  36. data/app/assets/stylesheets/trestle/components/_table.scss +34 -10
  37. data/app/assets/stylesheets/trestle/components/_tags.scss +9 -0
  38. data/app/assets/stylesheets/trestle/components/_timestamp.scss +4 -1
  39. data/app/assets/stylesheets/trestle/components/_toolbars.scss +55 -0
  40. data/app/assets/stylesheets/trestle/components/_wells.scss +9 -1
  41. data/app/assets/stylesheets/trestle/core/_defaults.scss +21 -6
  42. data/app/assets/stylesheets/trestle/core/_layout.scss +8 -0
  43. data/app/assets/stylesheets/trestle/core/_mixins.scss +11 -0
  44. data/app/assets/stylesheets/trestle/core/_typography.scss +39 -0
  45. data/app/controllers/concerns/trestle/controller/breadcrumbs.rb +21 -0
  46. data/app/controllers/concerns/trestle/controller/callbacks.rb +21 -0
  47. data/app/controllers/concerns/trestle/controller/dialog.rb +16 -0
  48. data/app/controllers/concerns/trestle/controller/helpers.rb +18 -0
  49. data/app/controllers/concerns/trestle/controller/layout.rb +16 -0
  50. data/app/controllers/concerns/trestle/controller/location.rb +15 -0
  51. data/app/controllers/trestle/application_controller.rb +6 -30
  52. data/app/helpers/trestle/avatar_helper.rb +9 -2
  53. data/app/helpers/trestle/flash_helper.rb +15 -0
  54. data/app/helpers/trestle/form_helper.rb +8 -5
  55. data/app/helpers/trestle/format_helper.rb +7 -3
  56. data/app/helpers/trestle/headings_helper.rb +27 -0
  57. data/app/helpers/trestle/hook_helper.rb +13 -4
  58. data/app/helpers/trestle/i18n_helper.rb +14 -0
  59. data/app/helpers/trestle/panel_helper.rb +24 -0
  60. data/app/helpers/trestle/tab_helper.rb +2 -2
  61. data/app/helpers/trestle/table_helper.rb +41 -2
  62. data/app/helpers/trestle/timestamp_helper.rb +49 -7
  63. data/app/helpers/trestle/toolbars_helper.rb +34 -0
  64. data/app/helpers/trestle/url_helper.rb +72 -8
  65. data/app/views/layouts/trestle/admin.html.erb +3 -5
  66. data/app/views/trestle/application/_dialog.html.erb +34 -0
  67. data/app/views/trestle/application/_header.html.erb +22 -20
  68. data/app/views/trestle/application/_layout.html.erb +1 -1
  69. data/app/views/trestle/application/_tabs.html.erb +8 -2
  70. data/app/views/trestle/{application → flash}/_alert.html.erb +7 -2
  71. data/app/views/trestle/flash/_debug.html.erb +8 -0
  72. data/app/views/trestle/flash/_flash.html.erb +7 -0
  73. data/app/views/trestle/resource/_scopes.html.erb +1 -1
  74. data/app/views/trestle/resource/edit.html.erb +8 -10
  75. data/app/views/trestle/resource/index.html.erb +16 -4
  76. data/app/views/trestle/resource/new.html.erb +6 -6
  77. data/app/views/trestle/resource/show.html.erb +8 -10
  78. data/app/views/trestle/shared/_sidebar.html.erb +10 -7
  79. data/app/views/trestle/shared/_title.html.erb +14 -0
  80. data/app/views/trestle/table/_table.html.erb +4 -6
  81. data/bower.json +1 -1
  82. data/config/locales/cs.rb +18 -0
  83. data/config/locales/cs.yml +95 -0
  84. data/config/locales/en.yml +65 -36
  85. data/config/locales/es-MX.yml +94 -0
  86. data/config/locales/es.yml +94 -0
  87. data/config/locales/fr.rb +18 -0
  88. data/config/locales/fr.yml +84 -0
  89. data/config/locales/lv.rb +18 -0
  90. data/config/locales/lv.yml +94 -0
  91. data/config/locales/nl.rb +18 -0
  92. data/config/locales/nl.yml +82 -0
  93. data/config/locales/pl.rb +18 -0
  94. data/config/locales/pl.yml +85 -0
  95. data/config/locales/pt-BR.rb +18 -0
  96. data/config/locales/pt-BR.yml +84 -0
  97. data/config/locales/zh-CN.rb +18 -0
  98. data/config/locales/zh-CN.yml +94 -0
  99. data/gemfiles/rails-4.2.gemfile +16 -0
  100. data/gemfiles/rails-5.0.gemfile +16 -0
  101. data/gemfiles/rails-5.1.gemfile +16 -0
  102. data/gemfiles/rails-5.2.gemfile +16 -0
  103. data/gemfiles/rails-edge.gemfile +17 -0
  104. data/lib/generators/trestle/install/templates/trestle.rb.erb +18 -2
  105. data/lib/generators/trestle/resource/templates/admin.rb.erb +2 -2
  106. data/lib/trestle/adapters/active_record_adapter.rb +2 -6
  107. data/lib/trestle/adapters/adapter.rb +40 -15
  108. data/lib/trestle/adapters/sequel_adapter.rb +2 -6
  109. data/lib/trestle/admin/builder.rb +42 -12
  110. data/lib/trestle/admin/controller.rb +3 -1
  111. data/lib/trestle/admin.rb +84 -3
  112. data/lib/trestle/breadcrumb.rb +16 -1
  113. data/lib/trestle/configurable.rb +6 -0
  114. data/lib/trestle/configuration.rb +28 -5
  115. data/lib/trestle/display.rb +1 -1
  116. data/lib/trestle/engine.rb +10 -4
  117. data/lib/trestle/form/automatic.rb +6 -3
  118. data/lib/trestle/form/builder.rb +5 -1
  119. data/lib/trestle/form/field.rb +1 -1
  120. data/lib/trestle/form/fields/date_picker.rb +2 -2
  121. data/lib/trestle/form/fields/form_control.rb +14 -4
  122. data/lib/trestle/form/fields/form_group.rb +14 -3
  123. data/lib/trestle/form/fields/select.rb +5 -1
  124. data/lib/trestle/form/fields/tag_select.rb +1 -1
  125. data/lib/trestle/form/renderer.rb +2 -2
  126. data/lib/trestle/form.rb +7 -3
  127. data/lib/trestle/hook.rb +27 -0
  128. data/lib/trestle/model_name.rb +64 -0
  129. data/lib/trestle/navigation/group.rb +16 -0
  130. data/lib/trestle/navigation/item.rb +11 -1
  131. data/lib/trestle/navigation.rb +24 -6
  132. data/lib/trestle/options.rb +7 -5
  133. data/lib/trestle/reloader.rb +1 -1
  134. data/lib/trestle/resource/adapter_methods.rb +62 -0
  135. data/lib/trestle/resource/builder.rb +43 -17
  136. data/lib/trestle/resource/collection.rb +68 -0
  137. data/lib/trestle/resource/controller.rb +70 -33
  138. data/lib/trestle/resource.rb +97 -105
  139. data/lib/trestle/scope.rb +13 -3
  140. data/lib/trestle/tab.rb +4 -0
  141. data/lib/trestle/table/actions_column.rb +41 -31
  142. data/lib/trestle/table/automatic.rb +1 -2
  143. data/lib/trestle/table/builder.rb +2 -2
  144. data/lib/trestle/table/column.rb +40 -9
  145. data/lib/trestle/table/row.rb +18 -2
  146. data/lib/trestle/table.rb +18 -2
  147. data/lib/trestle/toolbar/builder.rb +52 -0
  148. data/lib/trestle/toolbar/context.rb +39 -0
  149. data/lib/trestle/toolbar.rb +43 -0
  150. data/lib/trestle/version.rb +1 -1
  151. data/lib/trestle.rb +9 -4
  152. data/trestle.gemspec +5 -3
  153. data/vendor/assets/bower_components/trestle/select2/dist/js/select2.full.js +90 -69
  154. data/vendor/assets/javascripts/trestle/flatpickr.js.erb +2 -0
  155. data/vendor/assets/stylesheets/trestle/magnific-popup.scss +13 -1
  156. metadata +99 -22
  157. data/app/assets/javascripts/trestle/_confirmation.js +0 -23
  158. data/app/assets/javascripts/trestle/_datepicker.js +0 -22
  159. data/app/assets/javascripts/trestle/_form.js +0 -6
  160. data/app/assets/javascripts/trestle/_sidebar.js +0 -52
  161. data/app/assets/javascripts/trestle/_tabs.js +0 -13
  162. data/app/assets/javascripts/trestle/_tooltips.js +0 -3
  163. data/app/helpers/trestle/title_helper.rb +0 -26
  164. data/app/views/trestle/application/_flash.html.erb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f4f02402474a2f77fc6f4af6582e9b68f59274d0
4
- data.tar.gz: bb9815ae6b48b970443740c5b111aefef96dcea3
2
+ SHA256:
3
+ metadata.gz: c1640cda170a3f473968769e1c0380de2689ac11ecdd88c0b19bf93796701680
4
+ data.tar.gz: c3c78457d933155de6eba4bac6500a906e4fb78dce4232a68040ddeb2dfd919e
5
5
  SHA512:
6
- metadata.gz: c1593ee4dafcde35f20c312441df49e1b0861b82d87e387b4ed407e60a29758fb24e9efe4274339a1e04c78aac60cb0e85b9c76a425863fc3176d6a1f3afb70a
7
- data.tar.gz: 04e575f53c928a249a74aa4cc8ad3477c7cd16fad6ef26874e0d9adf9397bbfe070fd059f74b4c85c25cba599887d84dbf3f5da1fd0cd91d26704c85ef976a1b
6
+ metadata.gz: d597693a4f29721adb0a3b8e0b6d15679bef552b6d050b390940fcf53a28922f99cca9c993d1f9458d284786f5f4e29fbce2bef6bcc7891be639b53e7502ea83
7
+ data.tar.gz: ba5bd00f7a509ea1a349e57d52dd46e15f86c78d95fd0cabc755a82c5079155fcc9db8b405523378977119f274d171ff9e3ca0d5c128631a39f6a2fb72577afa
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/*
data/.travis.yml CHANGED
@@ -1,4 +1,17 @@
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-5.2.gemfile
14
+ - gemfiles/rails-edge.gemfile
15
+
16
+ addons:
17
+ chrome: stable
data/Gemfile CHANGED
@@ -6,6 +6,12 @@ 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'
13
+ gem 'chromedriver-helper'
14
+ gem 'puma'
9
15
  end
10
16
 
11
17
  gem 'haml'
data/README.md CHANGED
@@ -4,10 +4,10 @@
4
4
 
5
5
  # Trestle
6
6
 
7
- [![RubyGem](https://img.shields.io/gem/v/trestle.svg?style=flat-square&colorB=4065a9)](https://rubygems.org/gems/trestle)
8
- [![Travis](https://img.shields.io/travis/TrestleAdmin/trestle.svg?style=flat-square)](https://travis-ci.org/TrestleAdmin/trestle)
9
- [![Code Climate](https://img.shields.io/codeclimate/github/TrestleAdmin/trestle.svg?style=flat-square)](https://codeclimate.com/github/TrestleAdmin/trestle)
10
- [![Coveralls](https://img.shields.io/coveralls/TrestleAdmin/trestle.svg?style=flat-square)](https://coveralls.io/github/TrestleAdmin/trestle)
7
+ [![RubyGem](https://img.shields.io/gem/v/trestle.svg?style=flat&colorB=4065a9)](https://rubygems.org/gems/trestle)
8
+ [![Travis](https://img.shields.io/travis/TrestleAdmin/trestle.svg?style=flat)](https://travis-ci.org/TrestleAdmin/trestle)
9
+ [![Coveralls](https://img.shields.io/coveralls/TrestleAdmin/trestle.svg?style=flat)](https://coveralls.io/github/TrestleAdmin/trestle)
10
+ [![Code Climate](https://api.codeclimate.com/v1/badges/c529a7a9c500ed81baed/maintainability)](https://codeclimate.com/github/TrestleAdmin/trestle)
11
11
 
12
12
  > A modern, responsive admin framework for Ruby on Rails
13
13
 
@@ -38,7 +38,11 @@ After restarting your Rails server, visit http://localhost:3000/admin to view yo
38
38
  ```ruby
39
39
  Trestle.resource(:posts) do
40
40
  # Add a link to this admin in the main navigation
41
- menu :posts, icon: "fa fa-file-text-o", group: :blog_management
41
+ menu do
42
+ group :blog_management, priority: :first do
43
+ item :posts, icon: "fa fa-file-text-o"
44
+ end
45
+ end
42
46
 
43
47
  # Define custom scopes for the index view
44
48
  scope :all, default: true
@@ -87,11 +91,13 @@ end
87
91
 
88
92
  The following plugins are currently available:
89
93
 
90
- | Name | Description | GitHub |
94
+ | Name | Description | Links |
91
95
  | --- | --- | --- |
92
- | *trestle-auth* | User authentication plugin | https://github.com/TrestleAdmin/trestle-auth |
93
- | *trestle-search* | Search plugin | https://github.com/TrestleAdmin/trestle-search |
94
- | *trestle-tinymce* | TinyMCE (WYSIWYG editor) integration | https://github.com/TrestleAdmin/trestle-tinymce |
96
+ | *trestle-auth* | User authentication plugin | [GitHub](https://github.com/TrestleAdmin/trestle-auth) \| [RubyGems](https://rubygems.org/gems/trestle-auth) |
97
+ | *trestle-search* | Search plugin | [GitHub](https://github.com/TrestleAdmin/trestle-search) \| [RubyGems](https://rubygems.org/gems/trestle-search) |
98
+ | *trestle-tinymce* | [TinyMCE](https://www.tinymce.com/) (WYSIWYG editor) integration | [GitHub](https://github.com/TrestleAdmin/trestle-tinymce) \| [RubyGems](https://rubygems.org/gems/trestle-tinymce) |
99
+ | *trestle-simplemde* | [SimpleMDE](https://simplemde.com/) (Markdown editor) integration | [GitHub](https://github.com/TrestleAdmin/trestle-simplemde) \| [RubyGems](https://rubygems.org/gems/trestle-simplemde) |
100
+ | *trestle-sidekiq* | [Sidekiq](http://sidekiq.org/) integration | [GitHub](https://github.com/TrestleAdmin/trestle-sidekiq) \| [RubyGems](https://rubygems.org/gems/trestle-sidekiq) |
95
101
 
96
102
 
97
103
  ## License
@@ -7,17 +7,18 @@
7
7
  //= require trestle/select2
8
8
  //
9
9
  //= require_self
10
+ //
11
+ //= require_tree ./core
12
+ //= require_tree ./components
13
+ //
10
14
  //= require trestle/custom
11
- //= require_tree .
12
15
 
13
- var Trestle = window.Trestle = {};
16
+ var Trestle = {
17
+ // Is Turbolinks enabled?
18
+ turbolinks: typeof(Turbolinks) !== 'undefined' && Turbolinks.supported,
14
19
 
15
- Trestle.i18n = {};
20
+ // Store for i18n translations used within JS
21
+ i18n: {}
22
+ };
16
23
 
17
- if (typeof(Turbolinks) !== 'undefined' && Turbolinks.supported) {
18
- Trestle.ready = function(callback) { $(document).on('turbolinks:load', callback); };
19
- Trestle.visit = function(url) { Turbolinks.visit(url); };
20
- } else {
21
- Trestle.ready = function(callback) { $(callback); };
22
- Trestle.visit = function(url) { document.location = url; };
23
- }
24
+ window.Trestle = Trestle;
@@ -0,0 +1,40 @@
1
+ Trestle.confirmation = {};
2
+
3
+ Trestle.confirmation.DEFAULTS = {
4
+ rootSelector: 'body',
5
+ singleton: true,
6
+ popout: true,
7
+ title: Trestle.i18n['admin.confirmation.title'] || 'Are you sure?',
8
+ btnOkIcon: '',
9
+ btnOkClass: 'btn-primary',
10
+ btnOkLabel: Trestle.i18n['admin.confirmation.ok'] || 'OK',
11
+ btnCancelIcon: '',
12
+ btnCancelClass: 'btn-default',
13
+ btnCancelLabel: Trestle.i18n['admin.confirmation.cancel'] || 'Cancel',
14
+ copyAttributes: ''
15
+ };
16
+
17
+ Trestle.confirmation.CONFIRM = $.extend({}, Trestle.confirmation.DEFAULTS, {
18
+ selector: '[data-toggle="confirm"]'
19
+ });
20
+
21
+ Trestle.confirmation.DELETE = $.extend({}, Trestle.confirmation.DEFAULTS, {
22
+ selector: '[data-toggle="confirm-delete"]',
23
+ btnOkClass: 'btn-danger',
24
+ btnOkLabel: Trestle.i18n['admin.confirmation.delete'] || 'Delete'
25
+ });
26
+
27
+ Trestle.ready(function() {
28
+ // This must be bound to an element beneath document so
29
+ // that it is fired before any jquery_ujs events.
30
+ var root = $('body');
31
+
32
+ // Ensure it is only initialized once
33
+ if (root.data('bs.confirmation')) return;
34
+
35
+ // Delete confirmation
36
+ new $.fn.confirmation.Constructor(root, Trestle.confirmation.DELETE);
37
+
38
+ // General confirmation
39
+ new $.fn.confirmation.Constructor(root, Trestle.confirmation.CONFIRM);
40
+ });
@@ -0,0 +1,37 @@
1
+ Trestle.setupDatePicker = function(selectedDates, dateStr, instance) {
2
+ if ($(instance.input).data('allow-clear')) {
3
+ $('<a href="#">')
4
+ .on('click', function(e) {
5
+ e.preventDefault();
6
+ instance.clear();
7
+ })
8
+ .addClass('clear-datepicker')
9
+ .insertBefore(instance.altInput);
10
+ }
11
+ };
12
+
13
+ Trestle.init(function(e, root) {
14
+ $(root).find('input[type="date"][data-picker="true"]').flatpickr({
15
+ allowInput: true,
16
+ altInput: true,
17
+ altFormat: Trestle.i18n["admin.datepicker.formats.date"] || "m/d/Y",
18
+ onReady: Trestle.setupDatePicker
19
+ });
20
+
21
+ $(root).find('input[type="datetime"][data-picker="true"], input[type="datetime-local"][data-picker="true"]').flatpickr({
22
+ enableTime: true,
23
+ allowInput: true,
24
+ altInput: true,
25
+ altFormat: Trestle.i18n["admin.datepicker.formats.datetime"] || "m/d/Y h:i K",
26
+ onReady: Trestle.setupDatePicker
27
+ });
28
+
29
+ $(root).find('input[type="time"][data-picker="true"]').flatpickr({
30
+ enableTime: true,
31
+ noCalendar: true,
32
+ allowInput: true,
33
+ altInput: true,
34
+ altFormat: Trestle.i18n["admin.datepicker.formats.time"] || "h:i K",
35
+ onReady: Trestle.setupDatePicker
36
+ });
37
+ });
@@ -0,0 +1,136 @@
1
+ Trestle.Dialog = function(options) {
2
+ options = options || {};
3
+
4
+ this.el = Trestle.Dialog.createElement();
5
+
6
+ if (options.modalClass) {
7
+ this.el.find('.modal-dialog').addClass(options.modalClass);
8
+ }
9
+ };
10
+
11
+ Trestle.Dialog.TEMPLATE =
12
+ '<div class="modal fade" tabindex="-1">' +
13
+ '<div class="modal-dialog">' +
14
+ '<div class="modal-content" data-context></div>' +
15
+ '</div>' +
16
+ '</div>';
17
+
18
+ Trestle.Dialog.createElement = function() {
19
+ var el = $(Trestle.Dialog.TEMPLATE).appendTo('body');
20
+
21
+ el.modal({ show: false });
22
+
23
+ // Remove dialog elements once hidden
24
+ el.on('hidden.bs.modal', function() {
25
+ el.remove();
26
+ });
27
+
28
+ // Restore the next visible modal to the foreground
29
+ el.on('hide.bs.modal', function() {
30
+ el.prevAll('.modal.in').last().removeClass('background');
31
+ });
32
+
33
+ // Set X-Trestle-Dialog header on AJAX requests initiated from the dialog
34
+ el.on('ajax:beforeSend', '[data-remote]', function(e, xhr, options) {
35
+ xhr.setRequestHeader("X-Trestle-Dialog", true);
36
+ });
37
+
38
+ return el;
39
+ };
40
+
41
+ Trestle.Dialog.showError = function(title, errorText) {
42
+ var dialog = new Trestle.Dialog({ modalClass: 'modal-lg' });
43
+
44
+ dialog.showError(title, $('<pre>').addClass('exception').text(errorText));
45
+ dialog.show();
46
+
47
+ return dialog;
48
+ };
49
+
50
+ Trestle.Dialog.prototype.load = function(url, callback) {
51
+ var dialog = this;
52
+
53
+ dialog.show();
54
+ dialog.setLoading(true);
55
+
56
+ $.ajax({
57
+ url: url,
58
+ dataType: 'html',
59
+ headers: {
60
+ "X-Trestle-Dialog": true
61
+ },
62
+ complete: function() {
63
+ dialog.setLoading(false);
64
+ },
65
+ success: function(content) {
66
+ dialog.setContent(content);
67
+
68
+ if (callback) {
69
+ callback.apply(dialog);
70
+ }
71
+ },
72
+ error: function(xhr, status, error) {
73
+ var errorMessage = Trestle.i18n['trestle.dialog.error'] || 'The request could not be completed.';
74
+
75
+ var title = error || errorMessage;
76
+ var content = $('<p>').text(errorMessage);
77
+
78
+ dialog.showError(title, content);
79
+ }
80
+ });
81
+ };
82
+
83
+ Trestle.Dialog.prototype.setLoading = function(loading) {
84
+ if (loading) {
85
+ this.el.addClass('loading');
86
+ } else {
87
+ this.el.removeClass('loading');
88
+ }
89
+ }
90
+
91
+ Trestle.Dialog.prototype.setContent = function(content) {
92
+ this.el.find('.modal-content').html(content);
93
+ $(Trestle).trigger('init', this.el);
94
+ };
95
+
96
+ Trestle.Dialog.prototype.showError = function(title, content) {
97
+ this.el.addClass('error');
98
+
99
+ var container = this.el.find('.modal-content').empty();
100
+
101
+ $('<div class="modal-header">')
102
+ .append('<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>')
103
+ .append('<h4 class="modal-title"></h4>').find('h4').text(title).end()
104
+ .appendTo(container);
105
+
106
+ $('<div class="modal-body">')
107
+ .append(content)
108
+ .appendTo(container);
109
+
110
+ $('<div class="modal-footer">')
111
+ .append('<button type="button" class="btn btn-default" data-dismiss="modal" aria-label="OK">').find('button').text(Trestle.i18n['admin.buttons.ok'] || 'OK').end()
112
+ .appendTo(container);
113
+ };
114
+
115
+ Trestle.Dialog.prototype.show = function() {
116
+ this.el.modal('show');
117
+
118
+ // Background any existing visible modals
119
+ this.el.prevAll('.modal.in').addClass('background');
120
+ };
121
+
122
+ Trestle.Dialog.prototype.hide = function() {
123
+ this.el.modal('hide');
124
+ };
125
+
126
+ $(document).on('click', '[data-behavior="dialog"]', function(e) {
127
+ e.preventDefault();
128
+
129
+ var url = $(this).data('url') || $(this).attr('href');
130
+
131
+ var dialog = new Trestle.Dialog({
132
+ modalClass: $(this).data('dialog-class')
133
+ });
134
+
135
+ dialog.load(url);
136
+ });
@@ -1,6 +1,6 @@
1
1
  // Add error indicators to tabs
2
- Trestle.ready(function() {
3
- $('.tab-pane').each(function() {
2
+ Trestle.init(function(e, root) {
3
+ $(root).find('.tab-pane').each(function() {
4
4
  var errorCount = $(this).find('.has-error').length;
5
5
 
6
6
  if (errorCount > 0) {
@@ -0,0 +1,75 @@
1
+ // Prevent enter key from submitting the form
2
+ $(document).on('keypress', 'form[data-behavior="trestle-form"] :input:not(textarea):not([type=submit])', function(e) {
3
+ if (e.keyCode == 13) {
4
+ e.preventDefault();
5
+ }
6
+ });
7
+
8
+ Trestle.init(function(e, root) {
9
+ var form = $(root).find('form[data-behavior="trestle-form"]');
10
+
11
+ form
12
+ .on('ajax:send', function(e, xhr) {
13
+ // Disable submit buttons
14
+ $(this).find(':submit').prop('disabled', true);
15
+
16
+ // Set loading status on button that triggered submission
17
+ var button = $(this).data('trestle:submitButton');
18
+ if (button) { $(button).addClass('loading'); }
19
+ })
20
+ .on('ajax:complete', function(e, xhr, status) {
21
+ // Reset submit buttons
22
+ $(this).find(':submit').prop('disabled', false).removeClass('loading');
23
+ $(this).removeData('trestle:submitButton');
24
+
25
+ var contentType = xhr.getResponseHeader("Content-Type");
26
+
27
+ if (contentType && contentType.split(";")[0] == "text/html") {
28
+ if (/<html/i.test(xhr.responseText)) {
29
+ // Response is a full HTML page, likely an error page. Render within an iframe.
30
+ var context = $(this).closest('[data-context]');
31
+ var iframe = $("<iframe>").addClass('error-iframe').get(0);
32
+ context.html(iframe);
33
+
34
+ iframe.contentWindow.document.documentElement.innerHTML = xhr.responseText;
35
+ } else {
36
+ // Find the parent context and replace content
37
+ var context = $(this).closest('[data-context]');
38
+ context.html(xhr.responseText);
39
+
40
+ // Initialize replaced elements within the context
41
+ $(Trestle).trigger('init', context);
42
+
43
+ // Focus the correct tab
44
+ Trestle.focusActiveTab();
45
+ }
46
+ } else {
47
+ // Assume an error response
48
+ var title = xhr.status + " (" + xhr.statusText + ")";
49
+ Trestle.Dialog.showError(title, xhr.responseText);
50
+ }
51
+ })
52
+ .on('ajax:success', function(e, data, status, xhr) {
53
+ var context = $(this).closest('[data-context]');
54
+ var location = xhr.getResponseHeader("X-Trestle-Location");
55
+
56
+ if (location) {
57
+ // Retain current active tab
58
+ location = location + document.location.hash;
59
+
60
+ // Update the URL in the browser and context
61
+ history.replaceState({}, "", location);
62
+ context.data('context', location);
63
+ }
64
+
65
+ // Refresh the main context
66
+ if (!context.hasClass('app-main')) {
67
+ Trestle.refreshMainContext();
68
+ }
69
+ });
70
+
71
+ form.find(':submit').click(function() {
72
+ // Save this as the button that triggered the form
73
+ $(this).closest('form').data('trestle:submitButton', this);
74
+ });
75
+ });
@@ -1,5 +1,5 @@
1
- Trestle.ready(function() {
2
- $('[data-behavior~="zoom"]').magnificPopup({
1
+ Trestle.init(function(e, root) {
2
+ $(root).find('[data-behavior~="zoom"]').magnificPopup({
3
3
  type: 'image',
4
4
  closeOnContentClick: false,
5
5
  closeBtnInside: false,
@@ -10,7 +10,7 @@ Trestle.ready(function() {
10
10
  }
11
11
  });
12
12
 
13
- $('[data-behavior~="gallery"]').magnificPopup({
13
+ $(root).find('[data-behavior~="gallery"]').magnificPopup({
14
14
  delegate: 'a',
15
15
  type: 'image',
16
16
  closeOnContentClick: false,
@@ -1,5 +1,5 @@
1
- Trestle.ready(function() {
2
- $('select[data-enable-select2]').each(function() {
1
+ Trestle.init(function(e, root) {
2
+ $(root).find('select[data-enable-select2]').each(function() {
3
3
  $(this).select2({
4
4
  theme: 'bootstrap',
5
5
  containerCssClass: ':all:',
@@ -0,0 +1,77 @@
1
+ Trestle.ready(function() {
2
+ var body = $('body');
3
+ var wrapper = $('.app-wrapper');
4
+ var sidebar = $('.app-sidebar');
5
+
6
+ // Toggle mobile navigation using menu button
7
+
8
+ sidebar.find('.navbar-toggle').on('click', function(e) {
9
+ e.preventDefault();
10
+
11
+ wrapper.addClass('animate');
12
+ body.toggleClass('mobile-nav-expanded');
13
+ });
14
+
15
+ wrapper.on('transitionend webkitTransitionEnd', function() {
16
+ $(this).removeClass('animate');
17
+ });
18
+
19
+
20
+ // Interacting outside of the sidebar closes the navigation
21
+
22
+ wrapper.on('click touchstart', function(e) {
23
+ var navExpanded = $('body').hasClass('mobile-nav-expanded');
24
+
25
+ var clickInHeader = $(e.target).closest('.app-header').length;
26
+ var clickInSidebar = $(e.target).closest('.app-sidebar').length;
27
+
28
+ if (navExpanded && !clickInHeader && !clickInSidebar) {
29
+ e.stopPropagation();
30
+ e.preventDefault();
31
+
32
+ $('.app-wrapper').addClass('animate');
33
+ $('body').removeClass('mobile-nav-expanded');
34
+ }
35
+ });
36
+
37
+
38
+ // Toggle sidebar expand/collapse
39
+
40
+ sidebar.find('.toggle-sidebar').on('click', function(e) {
41
+ e.preventDefault();
42
+
43
+ if (body.hasClass('sidebar-expanded') || body.hasClass('sidebar-collapsed')) {
44
+ body.removeClass('sidebar-expanded').removeClass('sidebar-collapsed');
45
+ Trestle.cookie.delete("trestle:sidebar");
46
+ } else if ($(document).width() >= 1200) {
47
+ body.addClass('sidebar-collapsed');
48
+ Trestle.cookie.set("trestle:sidebar", "collapsed");
49
+ } else if ($(document).width() >= 768) {
50
+ body.addClass('sidebar-expanded');
51
+ Trestle.cookie.set("trestle:sidebar", "expanded");
52
+ }
53
+ });
54
+
55
+
56
+ // Toggle navigation groups
57
+
58
+ sidebar.find('.nav-header a').on('click', function(e) {
59
+ e.preventDefault();
60
+
61
+ $(this).closest('ul').toggleClass('collapsed');
62
+
63
+ var collapsed = sidebar.find('.collapsed .nav-header a').map(function() {
64
+ return $(this).attr('href').replace(/^#/, '');
65
+ }).toArray();
66
+
67
+ Trestle.cookie.set("trestle:navigation:collapsed", collapsed.join(","))
68
+ });
69
+
70
+
71
+ // Scroll sidebar to active item
72
+
73
+ var active = sidebar.find('.active');
74
+ if (active.length) {
75
+ sidebar.find('.app-sidebar-inner').scrollTop(active.offset().top - 100);
76
+ }
77
+ });
@@ -1,4 +1,4 @@
1
- $(document).on('click', 'tr[data-url]', function(e) {
1
+ $(document).on('click', 'tr[data-url]:not([data-behavior="dialog"])', function(e) {
2
2
  var row = $(e.currentTarget);
3
3
 
4
4
  if (row.data('url') == 'auto') {
@@ -0,0 +1,25 @@
1
+ Trestle.init(function(e, root) {
2
+ $(root).find("a[data-toggle='tab']").on('shown.bs.tab', function(e) {
3
+ var hash = $(this).attr("href");
4
+ var withinModal = $(this).closest('.modal').length > 0;
5
+
6
+ if (hash.substr(0, 1) == "#" && !withinModal) {
7
+ history.replaceState({ turbolinks: {} }, "", "#!" + hash.substr(1));
8
+ }
9
+ });
10
+ });
11
+
12
+ Trestle.focusActiveTab = function() {
13
+ if (location.hash.substr(0, 2) == "#!") {
14
+ // Focus on active tab from URL
15
+ $("a[data-toggle='tab'][href='#" + location.hash.substr(2) + "']").tab("show");
16
+ } else if ($(".tab-pane:has(.has-error)").length) {
17
+ // Focus on first tab with errors
18
+ var pane = $(".tab-pane:has(.has-error)").first();
19
+ $("a[data-toggle='tab'][href='#" + pane.attr("id") + "']").tab("show");
20
+ }
21
+ };
22
+
23
+ Trestle.init(function() {
24
+ Trestle.focusActiveTab();
25
+ });
@@ -0,0 +1,19 @@
1
+ Trestle.init(function(e, root) {
2
+ $(root).find('[data-toggle="tooltip"]').tooltip();
3
+ $(root).find('[data-toggle="popover"]').popover();
4
+ });
5
+
6
+ if (!('ontouchstart' in window)) {
7
+ Trestle.ready(function() {
8
+ $(document).tooltip({
9
+ selector: '.app-nav a',
10
+ trigger: 'hover',
11
+ placement: 'right',
12
+ container: 'body',
13
+ template: '<div class="tooltip nav-tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
14
+ title: function() {
15
+ return $(this).find('.nav-label').text();
16
+ }
17
+ });
18
+ });
19
+ };
@@ -0,0 +1,13 @@
1
+ Trestle.refreshContext = function(context) {
2
+ var url = context.data('context');
3
+
4
+ $.get(url, function(data) {
5
+ context.html(data);
6
+ $(Trestle).trigger('init', context);
7
+ });
8
+ };
9
+
10
+ Trestle.refreshMainContext = function() {
11
+ var context = $('.app-main[data-context]');
12
+ Trestle.refreshContext(context);
13
+ };
@@ -0,0 +1,24 @@
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
+ var value = cookies[i].replace(name, '');
10
+ return decodeURIComponent(value);
11
+ }
12
+ }
13
+
14
+ return "";
15
+ },
16
+
17
+ set: function(name, value) {
18
+ document.cookie = name + "=" + encodeURIComponent(value) + "; path=/";
19
+ },
20
+
21
+ delete: function(name) {
22
+ document.cookie = name + "=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT";
23
+ }
24
+ };