trestle 0.8.5 → 0.8.6

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/trestle/admin.js +11 -10
  3. data/app/assets/javascripts/trestle/{_confirmation.js → components/_confirmation.js} +1 -1
  4. data/app/assets/javascripts/trestle/{_datepicker.js → components/_datepicker.js} +4 -4
  5. data/app/assets/javascripts/trestle/components/_dialog.js +107 -0
  6. data/app/assets/javascripts/trestle/{_errors.js → components/_errors.js} +2 -2
  7. data/app/assets/javascripts/trestle/components/_form.js +48 -0
  8. data/app/assets/javascripts/trestle/{_gallery.js → components/_gallery.js} +3 -3
  9. data/app/assets/javascripts/trestle/{_select.js → components/_select.js} +2 -2
  10. data/app/assets/javascripts/trestle/{_sidebar.js → components/_sidebar.js} +3 -1
  11. data/app/assets/javascripts/trestle/{_table.js → components/_table.js} +1 -1
  12. data/app/assets/javascripts/trestle/components/_tabs.js +24 -0
  13. data/app/assets/javascripts/trestle/components/_tooltips.js +3 -0
  14. data/app/assets/javascripts/trestle/core/_contexts.js +13 -0
  15. data/app/assets/javascripts/trestle/{_cookies.js → core/_cookies.js} +2 -1
  16. data/app/assets/javascripts/trestle/core/_events.js +39 -0
  17. data/app/assets/javascripts/trestle/core/_visit.js +10 -0
  18. data/app/assets/stylesheets/trestle/components/_buttons.scss +9 -0
  19. data/app/assets/stylesheets/trestle/components/_modal.scss +92 -0
  20. data/app/assets/stylesheets/trestle/components/_navigation.scss +47 -12
  21. data/app/assets/stylesheets/trestle/components/_sidebar.scss +1 -0
  22. data/app/assets/stylesheets/trestle/core/_defaults.scss +5 -1
  23. data/app/controllers/trestle/application_controller.rb +5 -1
  24. data/app/helpers/trestle/dialog_helper.rb +7 -0
  25. data/app/helpers/trestle/form_helper.rb +7 -0
  26. data/app/helpers/trestle/url_helper.rb +34 -6
  27. data/app/views/layouts/trestle/admin.html.erb +1 -1
  28. data/app/views/trestle/application/_dialog.html.erb +36 -0
  29. data/app/views/trestle/application/_tabs.html.erb +7 -1
  30. data/app/views/trestle/resource/edit.html.erb +5 -5
  31. data/app/views/trestle/resource/index.html.erb +2 -2
  32. data/app/views/trestle/resource/new.html.erb +2 -2
  33. data/app/views/trestle/resource/show.html.erb +5 -5
  34. data/bower.json +1 -1
  35. data/config/locales/en.yml +25 -21
  36. data/config/locales/fr.rb +18 -0
  37. data/config/locales/fr.yml +69 -0
  38. data/config/locales/nl.yml +14 -14
  39. data/config/locales/pl.rb +18 -0
  40. data/config/locales/pl.yml +70 -0
  41. data/config/locales/pt-BR.yml +22 -22
  42. data/lib/generators/trestle/resource/templates/admin.rb.erb +1 -1
  43. data/lib/trestle/admin.rb +14 -1
  44. data/lib/trestle/admin/builder.rb +10 -2
  45. data/lib/trestle/breadcrumb.rb +13 -0
  46. data/lib/trestle/configuration.rb +6 -1
  47. data/lib/trestle/form.rb +7 -3
  48. data/lib/trestle/form/automatic.rb +1 -1
  49. data/lib/trestle/reloader.rb +1 -1
  50. data/lib/trestle/resource.rb +20 -5
  51. data/lib/trestle/resource/builder.rb +15 -0
  52. data/lib/trestle/resource/controller.rb +19 -6
  53. data/lib/trestle/table.rb +4 -0
  54. data/lib/trestle/table/actions_column.rb +9 -7
  55. data/lib/trestle/table/column.rb +3 -2
  56. data/lib/trestle/table/row.rb +7 -1
  57. data/lib/trestle/version.rb +1 -1
  58. data/trestle.gemspec +3 -3
  59. data/vendor/assets/bower_components/trestle/select2/dist/js/select2.full.js +90 -69
  60. metadata +30 -19
  61. data/app/assets/javascripts/trestle/_form.js +0 -6
  62. data/app/assets/javascripts/trestle/_tabs.js +0 -13
  63. data/app/assets/javascripts/trestle/_tooltips.js +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f43ff0c051a7e29be0e0a815f1500753456f8aef
4
- data.tar.gz: 75bc749e3cd64de9c5339e98dda6c921985d5c61
3
+ metadata.gz: 1f07f2d3328a13c6ac319c7e04b8926a0dc09660
4
+ data.tar.gz: a8adb65b4c3bd295c5e80397fba9c8968d08febd
5
5
  SHA512:
6
- metadata.gz: 86dbf71a36e6cfb0499e7ec5d6852103f9148acead9755775883fbb7011b019e435ccb7331866f19a6555c5d7fb9de049aed2139874a70bbe3417c88e79a806e
7
- data.tar.gz: 10e8387dbb008465043180543be49f16a659372ce62f8d908b86595c91ebdb6b1b2950c7391c9ec7eb1041feb325f19c817e7c7f5c3e3fb5a078651d1518a0d2
6
+ metadata.gz: 9d565ea8bd72cca11c5eb2de1ea72332e8980093e5f4147f598f64958ee82b3f1799de37dc7c2c99b68cbb773821454ee62c5230b4ba55bdc50828e516dc347e
7
+ data.tar.gz: da2e9069173f7fa34f0af87c392af4b00dc9ea5b9b42eb2e6cb3c2df536065bd9648b5482043260c748e919fa735127d3fafb32537e523fe356da52765d7221a
@@ -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;
@@ -11,7 +11,7 @@ Trestle.ready(function() {
11
11
  selector: '[data-toggle="confirm-delete"]',
12
12
  singleton: true,
13
13
  popout: true,
14
- title: Trestle.i18n['admin.confirmation.title'],
14
+ title: Trestle.i18n['admin.confirmation.title'] || 'Are you sure?',
15
15
  btnOkIcon: '',
16
16
  btnOkClass: 'btn-danger',
17
17
  btnOkLabel: Trestle.i18n['admin.confirmation.delete'] || 'Delete',
@@ -1,18 +1,18 @@
1
- Trestle.ready(function() {
2
- $('input[type="date"][data-picker="true"]').flatpickr({
1
+ Trestle.init(function(e, root) {
2
+ $(root).find('input[type="date"][data-picker="true"]').flatpickr({
3
3
  allowInput: true,
4
4
  altInput: true,
5
5
  altFormat: "m/d/Y",
6
6
  });
7
7
 
8
- $('input[type="datetime"][data-picker="true"], input[type="datetime-local"][data-picker="true"]').flatpickr({
8
+ $(root).find('input[type="datetime"][data-picker="true"], input[type="datetime-local"][data-picker="true"]').flatpickr({
9
9
  enableTime: true,
10
10
  allowInput: true,
11
11
  altInput: true,
12
12
  altFormat: "m/d/Y h:i K",
13
13
  });
14
14
 
15
- $('input[type="time"][data-picker="true"]').flatpickr({
15
+ $(root).find('input[type="time"][data-picker="true"]').flatpickr({
16
16
  enableTime: true,
17
17
  noCalendar: true,
18
18
  allowInput: true,
@@ -0,0 +1,107 @@
1
+ Trestle.Dialog = function() {
2
+ this.el = Trestle.Dialog.getElement();
3
+ };
4
+
5
+ Trestle.Dialog.TEMPLATE =
6
+ '<div id="dialog" class="modal fade" tabindex="-1">' +
7
+ '<div class="modal-dialog">' +
8
+ '<div class="modal-content" data-context></div>' +
9
+ '</div>' +
10
+ '</div>';
11
+
12
+ Trestle.Dialog.getElement = function() {
13
+ var el = $('#dialog');
14
+
15
+ if (el.length == 0) {
16
+ el = $(Trestle.Dialog.TEMPLATE).appendTo('body');
17
+
18
+ el.modal({ show: false });
19
+
20
+ // Remove dialog elements once hidden
21
+ el.on('hidden.bs.modal', function() {
22
+ el.remove();
23
+ });
24
+
25
+ // Set X-Trestle-Dialog header on AJAX requests initiated from the dialog
26
+ el.on('ajax:beforeSend', '[data-remote]', function(e, xhr, options) {
27
+ xhr.setRequestHeader("X-Trestle-Dialog", true);
28
+ });
29
+ }
30
+
31
+ return el;
32
+ };
33
+
34
+ Trestle.Dialog.prototype.load = function(url) {
35
+ var dialog = this;
36
+
37
+ dialog.show();
38
+ dialog.setLoading(true);
39
+
40
+ $.ajax({
41
+ url: url,
42
+ dataType: 'html',
43
+ headers: {
44
+ "X-Trestle-Dialog": true
45
+ },
46
+ complete: function() {
47
+ dialog.setLoading(false);
48
+ },
49
+ success: function(content) {
50
+ dialog.setContent(content);
51
+ },
52
+ error: function(xhr, status, error) {
53
+ dialog.showError(error);
54
+ }
55
+ });
56
+ };
57
+
58
+ Trestle.Dialog.prototype.setLoading = function(loading) {
59
+ if (loading) {
60
+ this.el.addClass('loading');
61
+ } else {
62
+ this.el.removeClass('loading');
63
+ }
64
+ }
65
+
66
+ Trestle.Dialog.prototype.setContent = function(content) {
67
+ this.el.find('.modal-content').html(content);
68
+ $(Trestle).trigger('init', this.el);
69
+ };
70
+
71
+ Trestle.Dialog.prototype.showError = function(error) {
72
+ this.el.addClass('error');
73
+
74
+ var container = this.el.find('.modal-content').empty();
75
+
76
+ var errorMessage = Trestle.i18n['trestle.dialog.error'] || 'The request could not be completed.';
77
+
78
+ $('<div class="modal-header">')
79
+ .append('<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>')
80
+ .append('<h4 class="modal-title"></h4>').find('h4').text(error || errorMessage).end()
81
+ .appendTo(container);
82
+
83
+ $('<div class="modal-body">')
84
+ .append('<p>').find('p').text(errorMessage).end()
85
+ .appendTo(container);
86
+
87
+ $('<div class="modal-footer">')
88
+ .append('<button type="button" class="btn btn-default" data-dismiss="modal" aria-label="OK">').find('button').text(Trestle.i18n['admin.buttons.ok'] || 'OK').end()
89
+ .appendTo(container);
90
+ };
91
+
92
+ Trestle.Dialog.prototype.show = function() {
93
+ this.el.modal('show');
94
+ };
95
+
96
+ Trestle.Dialog.prototype.hide = function() {
97
+ this.el.modal('hide');
98
+ };
99
+
100
+ $(document).on('click', '[data-behavior="dialog"]', function(e) {
101
+ e.preventDefault();
102
+
103
+ var url = $(this).data('url') || $(this).attr('href');
104
+
105
+ var dialog = new Trestle.Dialog();
106
+ dialog.load(url);
107
+ });
@@ -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,48 @@
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:complete', function(e, xhr, status) {
13
+ // Find the parent context and replace content
14
+ var context = $(this).closest('[data-context]');
15
+ context.html(xhr.responseText);
16
+
17
+ // Initialize replaced elements within the context
18
+ $(Trestle).trigger('init', context);
19
+
20
+ // Focus the correct tab
21
+ Trestle.focusActiveTab();
22
+ })
23
+ .on('ajax:success', function(e, data, status, xhr) {
24
+ var context = $(this).closest('[data-context]');
25
+ var location = xhr.getResponseHeader("X-Trestle-Location");
26
+
27
+ if (location) {
28
+ // Update the URL in the browser and context
29
+ history.replaceState({}, "", location);
30
+ context.data('context', location);
31
+ }
32
+
33
+ // Refresh the main context
34
+ if (!context.hasClass('app-main')) {
35
+ Trestle.refreshMainContext();
36
+ }
37
+ });
38
+
39
+ // Loading indicator
40
+ form.find(':submit').click(function() {
41
+ var button = $(this);
42
+
43
+ // Delay to ensure form is still submitted
44
+ setTimeout(function() {
45
+ button.prop('disabled', true).addClass('loading');
46
+ }, 1);
47
+ });
48
+ });
@@ -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:',
@@ -69,5 +69,7 @@ Trestle.ready(function() {
69
69
  // Scroll sidebar to active item
70
70
 
71
71
  var active = sidebar.find('.active');
72
- sidebar.find('.app-sidebar-inner').scrollTop(active.offset().top - 100);
72
+ if (active.length) {
73
+ sidebar.find('.app-sidebar-inner').scrollTop(active.offset().top - 100);
74
+ }
73
75
  });
@@ -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,24 @@
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
+
5
+ if (hash.substr(0, 1) == "#") {
6
+ history.replaceState({ turbolinks: {} }, "", "#!" + hash.substr(1));
7
+ }
8
+ });
9
+ });
10
+
11
+ Trestle.focusActiveTab = function() {
12
+ if (location.hash.substr(0, 2) == "#!") {
13
+ // Focus on active tab from URL
14
+ $("a[data-toggle='tab'][href='#" + location.hash.substr(2) + "']").tab("show");
15
+ } else if ($(".tab-pane:has(.has-error)").length) {
16
+ // Focus on first tab with errors
17
+ var pane = $(".tab-pane:has(.has-error)").first();
18
+ $("a[data-toggle='tab'][href='#" + pane.attr("id") + "']").tab("show");
19
+ }
20
+ };
21
+
22
+ Trestle.ready(function() {
23
+ Trestle.focusActiveTab();
24
+ });
@@ -0,0 +1,3 @@
1
+ Trestle.init(function(e, root) {
2
+ $(root).find('[data-toggle="tooltip"]').tooltip();
3
+ });
@@ -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
+ };
@@ -6,7 +6,8 @@ Trestle.cookie = {
6
6
 
7
7
  for (i = cookies.length - 1; i >= 0; i--) {
8
8
  if (!cookies[i].indexOf(name)) {
9
- return cookies[i].replace(name, '');
9
+ var value = cookies[i].replace(name, '');
10
+ return decodeURIComponent(value);
10
11
  }
11
12
  }
12
13
 
@@ -0,0 +1,39 @@
1
+ // The ready function sets up a callback to run on each page load.
2
+ //
3
+ // Trestle.ready(function() {
4
+ // ...
5
+ // });
6
+ //
7
+ Trestle.ready = function(callback) {
8
+ $(Trestle).on('load', callback);
9
+ };
10
+
11
+ // The init function sets up a callback to run on each page load, as well as when elements are added to the page
12
+ // dynamically (e.g. via a modal). It is used to initialize dynamic elements such as date pickers, although it is
13
+ // preferable if they can be set up using event delegation on the document element.
14
+ //
15
+ // The callback is triggered with the applicable root/container element as the second argument.
16
+ //
17
+ // Trestle.init(function(e, root) {
18
+ // $(root).find('...');
19
+ // });
20
+ //
21
+ Trestle.init = function(callback) {
22
+ $(Trestle).on('init', callback);
23
+ };
24
+
25
+ // Initialize all elements within the document on page load.
26
+ Trestle.ready(function() {
27
+ $(Trestle).trigger('init', document);
28
+ });
29
+
30
+ // Trigger the page load events.
31
+ if (Trestle.turbolinks) {
32
+ $(document).on('turbolinks:load', function() {
33
+ $(Trestle).trigger("load");
34
+ });
35
+ } else {
36
+ $(document).ready(function() {
37
+ $(Trestle).trigger("load");
38
+ });
39
+ }
@@ -0,0 +1,10 @@
1
+ // The visit function is used to direct the user to the given URL. It is provided as an abstraction as the redirection
2
+ // is handled differently depending on whether or not Turbolinks is enabled.
3
+ //
4
+ // Trestle.visit("/admin/pages");
5
+ //
6
+ if (Trestle.turbolinks) {
7
+ Trestle.visit = function(url) { Turbolinks.visit(url); };
8
+ } else {
9
+ Trestle.visit = function(url) { document.location = url; };
10
+ }
@@ -1,6 +1,15 @@
1
1
  .btn {
2
2
  border: none;
3
3
  box-shadow: none;
4
+
5
+ &.loading {
6
+ &::before {
7
+ @extend .fa;
8
+ @extend .fa-spin;
9
+ content: $fa-var-spinner;
10
+ margin-right: 10px;
11
+ }
12
+ }
4
13
  }
5
14
 
6
15
  .btn-delete {
@@ -0,0 +1,92 @@
1
+ .modal-content {
2
+ border: none;
3
+ border-radius: 0;
4
+
5
+ .modal.loading & {
6
+ min-height: 100px;
7
+
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+
12
+ &:after {
13
+ @extend .fa;
14
+ @extend .fa-spin;
15
+ content: $fa-var-spinner;
16
+
17
+ font-size: 32px;
18
+ opacity: 0.25;
19
+ }
20
+ }
21
+ }
22
+
23
+ .modal-header {
24
+ background: $theme-bg;
25
+ border-bottom: none;
26
+
27
+ .close {
28
+ opacity: 0.75;
29
+
30
+ &, &:hover, &:focus {
31
+ color: white;
32
+ }
33
+
34
+ &:hover, &:focus {
35
+ opacity: 1;
36
+ }
37
+ }
38
+
39
+ .modal.error & {
40
+ background: $error-bg;
41
+ }
42
+ }
43
+
44
+ .modal-title {
45
+ font-size: 18px;
46
+ font-weight: 500;
47
+ text-shadow: rgba(black, 0.5) 0 1px 1px;
48
+ color: white;
49
+ }
50
+
51
+ .modal-tabs .nav-tabs {
52
+ background: $body-bg;
53
+ padding: 10px 15px 0 15px;
54
+ }
55
+
56
+ .modal-flash {
57
+ .alert {
58
+ margin-bottom: 0;
59
+ border-radius: 0;
60
+ border-width: 0 0 1px 0;
61
+
62
+ padding-top: 10px;
63
+ padding-bottom: 10px;
64
+
65
+ .alert-icon {
66
+ font-size: 40px;
67
+ margin-right: 15px;
68
+ }
69
+
70
+ h3 {
71
+ font-size: 18px;
72
+ }
73
+
74
+ p {
75
+ font-size: 13px;
76
+ }
77
+ }
78
+ }
79
+
80
+ .modal-body {
81
+ @extend .tab-content;
82
+ }
83
+
84
+ .modal-footer {
85
+ .primary-toolbar {
86
+ float: right;
87
+ }
88
+
89
+ .secondary-toolbar {
90
+ float: left;
91
+ }
92
+ }