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.
- checksums.yaml +5 -5
- data/.gitignore +4 -0
- data/.travis.yml +14 -1
- data/Gemfile +6 -0
- data/README.md +15 -9
- data/app/assets/javascripts/trestle/admin.js +11 -10
- data/app/assets/javascripts/trestle/components/_confirmation.js +40 -0
- data/app/assets/javascripts/trestle/components/_datepicker.js +37 -0
- data/app/assets/javascripts/trestle/components/_dialog.js +136 -0
- data/app/assets/javascripts/trestle/{_errors.js → components/_errors.js} +2 -2
- data/app/assets/javascripts/trestle/components/_form.js +75 -0
- data/app/assets/javascripts/trestle/{_gallery.js → components/_gallery.js} +3 -3
- data/app/assets/javascripts/trestle/{_select.js → components/_select.js} +2 -2
- data/app/assets/javascripts/trestle/components/_sidebar.js +77 -0
- data/app/assets/javascripts/trestle/{_table.js → components/_table.js} +1 -1
- data/app/assets/javascripts/trestle/components/_tabs.js +25 -0
- data/app/assets/javascripts/trestle/components/_tooltips.js +19 -0
- data/app/assets/javascripts/trestle/core/_contexts.js +13 -0
- data/app/assets/javascripts/trestle/core/_cookies.js +24 -0
- data/app/assets/javascripts/trestle/core/_events.js +39 -0
- data/app/assets/javascripts/trestle/core/_l10n.js +23 -0
- data/app/assets/javascripts/trestle/core/_visit.js +10 -0
- data/app/assets/stylesheets/trestle/components/_alerts.scss +28 -0
- data/app/assets/stylesheets/trestle/components/_avatar.scss +23 -1
- data/app/assets/stylesheets/trestle/components/_breadcrumbs.scss +12 -0
- data/app/assets/stylesheets/trestle/components/_buttons.scss +111 -1
- data/app/assets/stylesheets/trestle/components/_content.scss +53 -21
- data/app/assets/stylesheets/trestle/components/_datepicker.scss +28 -0
- data/app/assets/stylesheets/trestle/components/_fields.scss +17 -0
- data/app/assets/stylesheets/trestle/components/_input-group.scss +26 -1
- data/app/assets/stylesheets/trestle/components/_modal.scss +108 -0
- data/app/assets/stylesheets/trestle/components/_navigation.scss +104 -14
- data/app/assets/stylesheets/trestle/components/_pagination.scss +3 -3
- data/app/assets/stylesheets/trestle/components/_scopes.scss +11 -2
- data/app/assets/stylesheets/trestle/components/_sidebar.scss +3 -2
- data/app/assets/stylesheets/trestle/components/_table.scss +34 -10
- data/app/assets/stylesheets/trestle/components/_tags.scss +9 -0
- data/app/assets/stylesheets/trestle/components/_timestamp.scss +4 -1
- data/app/assets/stylesheets/trestle/components/_toolbars.scss +55 -0
- data/app/assets/stylesheets/trestle/components/_wells.scss +9 -1
- data/app/assets/stylesheets/trestle/core/_defaults.scss +21 -6
- data/app/assets/stylesheets/trestle/core/_layout.scss +8 -0
- data/app/assets/stylesheets/trestle/core/_mixins.scss +11 -0
- data/app/assets/stylesheets/trestle/core/_typography.scss +39 -0
- data/app/controllers/concerns/trestle/controller/breadcrumbs.rb +21 -0
- data/app/controllers/concerns/trestle/controller/callbacks.rb +21 -0
- data/app/controllers/concerns/trestle/controller/dialog.rb +16 -0
- data/app/controllers/concerns/trestle/controller/helpers.rb +18 -0
- data/app/controllers/concerns/trestle/controller/layout.rb +16 -0
- data/app/controllers/concerns/trestle/controller/location.rb +15 -0
- data/app/controllers/trestle/application_controller.rb +6 -30
- data/app/helpers/trestle/avatar_helper.rb +9 -2
- data/app/helpers/trestle/flash_helper.rb +15 -0
- data/app/helpers/trestle/form_helper.rb +8 -5
- data/app/helpers/trestle/format_helper.rb +7 -3
- data/app/helpers/trestle/headings_helper.rb +27 -0
- data/app/helpers/trestle/hook_helper.rb +13 -4
- data/app/helpers/trestle/i18n_helper.rb +14 -0
- data/app/helpers/trestle/panel_helper.rb +24 -0
- data/app/helpers/trestle/tab_helper.rb +2 -2
- data/app/helpers/trestle/table_helper.rb +41 -2
- data/app/helpers/trestle/timestamp_helper.rb +49 -7
- data/app/helpers/trestle/toolbars_helper.rb +34 -0
- data/app/helpers/trestle/url_helper.rb +72 -8
- data/app/views/layouts/trestle/admin.html.erb +3 -5
- data/app/views/trestle/application/_dialog.html.erb +34 -0
- data/app/views/trestle/application/_header.html.erb +22 -20
- data/app/views/trestle/application/_layout.html.erb +1 -1
- data/app/views/trestle/application/_tabs.html.erb +8 -2
- data/app/views/trestle/{application → flash}/_alert.html.erb +7 -2
- data/app/views/trestle/flash/_debug.html.erb +8 -0
- data/app/views/trestle/flash/_flash.html.erb +7 -0
- data/app/views/trestle/resource/_scopes.html.erb +1 -1
- data/app/views/trestle/resource/edit.html.erb +8 -10
- data/app/views/trestle/resource/index.html.erb +16 -4
- data/app/views/trestle/resource/new.html.erb +6 -6
- data/app/views/trestle/resource/show.html.erb +8 -10
- data/app/views/trestle/shared/_sidebar.html.erb +10 -7
- data/app/views/trestle/shared/_title.html.erb +14 -0
- data/app/views/trestle/table/_table.html.erb +4 -6
- data/bower.json +1 -1
- data/config/locales/cs.rb +18 -0
- data/config/locales/cs.yml +95 -0
- data/config/locales/en.yml +65 -36
- data/config/locales/es-MX.yml +94 -0
- data/config/locales/es.yml +94 -0
- data/config/locales/fr.rb +18 -0
- data/config/locales/fr.yml +84 -0
- data/config/locales/lv.rb +18 -0
- data/config/locales/lv.yml +94 -0
- data/config/locales/nl.rb +18 -0
- data/config/locales/nl.yml +82 -0
- data/config/locales/pl.rb +18 -0
- data/config/locales/pl.yml +85 -0
- data/config/locales/pt-BR.rb +18 -0
- data/config/locales/pt-BR.yml +84 -0
- data/config/locales/zh-CN.rb +18 -0
- data/config/locales/zh-CN.yml +94 -0
- data/gemfiles/rails-4.2.gemfile +16 -0
- data/gemfiles/rails-5.0.gemfile +16 -0
- data/gemfiles/rails-5.1.gemfile +16 -0
- data/gemfiles/rails-5.2.gemfile +16 -0
- data/gemfiles/rails-edge.gemfile +17 -0
- data/lib/generators/trestle/install/templates/trestle.rb.erb +18 -2
- data/lib/generators/trestle/resource/templates/admin.rb.erb +2 -2
- data/lib/trestle/adapters/active_record_adapter.rb +2 -6
- data/lib/trestle/adapters/adapter.rb +40 -15
- data/lib/trestle/adapters/sequel_adapter.rb +2 -6
- data/lib/trestle/admin/builder.rb +42 -12
- data/lib/trestle/admin/controller.rb +3 -1
- data/lib/trestle/admin.rb +84 -3
- data/lib/trestle/breadcrumb.rb +16 -1
- data/lib/trestle/configurable.rb +6 -0
- data/lib/trestle/configuration.rb +28 -5
- data/lib/trestle/display.rb +1 -1
- data/lib/trestle/engine.rb +10 -4
- data/lib/trestle/form/automatic.rb +6 -3
- data/lib/trestle/form/builder.rb +5 -1
- data/lib/trestle/form/field.rb +1 -1
- data/lib/trestle/form/fields/date_picker.rb +2 -2
- data/lib/trestle/form/fields/form_control.rb +14 -4
- data/lib/trestle/form/fields/form_group.rb +14 -3
- data/lib/trestle/form/fields/select.rb +5 -1
- data/lib/trestle/form/fields/tag_select.rb +1 -1
- data/lib/trestle/form/renderer.rb +2 -2
- data/lib/trestle/form.rb +7 -3
- data/lib/trestle/hook.rb +27 -0
- data/lib/trestle/model_name.rb +64 -0
- data/lib/trestle/navigation/group.rb +16 -0
- data/lib/trestle/navigation/item.rb +11 -1
- data/lib/trestle/navigation.rb +24 -6
- data/lib/trestle/options.rb +7 -5
- data/lib/trestle/reloader.rb +1 -1
- data/lib/trestle/resource/adapter_methods.rb +62 -0
- data/lib/trestle/resource/builder.rb +43 -17
- data/lib/trestle/resource/collection.rb +68 -0
- data/lib/trestle/resource/controller.rb +70 -33
- data/lib/trestle/resource.rb +97 -105
- data/lib/trestle/scope.rb +13 -3
- data/lib/trestle/tab.rb +4 -0
- data/lib/trestle/table/actions_column.rb +41 -31
- data/lib/trestle/table/automatic.rb +1 -2
- data/lib/trestle/table/builder.rb +2 -2
- data/lib/trestle/table/column.rb +40 -9
- data/lib/trestle/table/row.rb +18 -2
- data/lib/trestle/table.rb +18 -2
- data/lib/trestle/toolbar/builder.rb +52 -0
- data/lib/trestle/toolbar/context.rb +39 -0
- data/lib/trestle/toolbar.rb +43 -0
- data/lib/trestle/version.rb +1 -1
- data/lib/trestle.rb +9 -4
- data/trestle.gemspec +5 -3
- data/vendor/assets/bower_components/trestle/select2/dist/js/select2.full.js +90 -69
- data/vendor/assets/javascripts/trestle/flatpickr.js.erb +2 -0
- data/vendor/assets/stylesheets/trestle/magnific-popup.scss +13 -1
- metadata +99 -22
- data/app/assets/javascripts/trestle/_confirmation.js +0 -23
- data/app/assets/javascripts/trestle/_datepicker.js +0 -22
- data/app/assets/javascripts/trestle/_form.js +0 -6
- data/app/assets/javascripts/trestle/_sidebar.js +0 -52
- data/app/assets/javascripts/trestle/_tabs.js +0 -13
- data/app/assets/javascripts/trestle/_tooltips.js +0 -3
- data/app/helpers/trestle/title_helper.rb +0 -26
- data/app/views/trestle/application/_flash.html.erb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c1640cda170a3f473968769e1c0380de2689ac11ecdd88c0b19bf93796701680
|
|
4
|
+
data.tar.gz: c3c78457d933155de6eba4bac6500a906e4fb78dce4232a68040ddeb2dfd919e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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
data/README.md
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
# Trestle
|
|
6
6
|
|
|
7
|
-
[](https://rubygems.org/gems/trestle)
|
|
8
|
+
[](https://travis-ci.org/TrestleAdmin/trestle)
|
|
9
|
+
[](https://coveralls.io/github/TrestleAdmin/trestle)
|
|
10
|
+
[](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
|
|
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 |
|
|
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 =
|
|
16
|
+
var Trestle = {
|
|
17
|
+
// Is Turbolinks enabled?
|
|
18
|
+
turbolinks: typeof(Turbolinks) !== 'undefined' && Turbolinks.supported,
|
|
14
19
|
|
|
15
|
-
|
|
20
|
+
// Store for i18n translations used within JS
|
|
21
|
+
i18n: {}
|
|
22
|
+
};
|
|
16
23
|
|
|
17
|
-
|
|
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">×</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
|
+
});
|
|
@@ -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.
|
|
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,
|
|
@@ -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
|
+
});
|
|
@@ -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
|
+
};
|