fae-rails 2.1.0 → 3.0.0

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 (137) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -2
  3. data/app/assets/config/fae/manifest.js +2 -0
  4. data/app/assets/javascripts/fae/_contrast.js +50 -0
  5. data/app/assets/javascripts/fae/_deploy.js +198 -0
  6. data/app/assets/javascripts/fae/_modals.js +94 -0
  7. data/app/assets/javascripts/fae/application.js +7 -1
  8. data/app/assets/javascripts/fae/form/_ajax.js +17 -5
  9. data/app/assets/javascripts/fae/form/_filtering.js +34 -0
  10. data/app/assets/javascripts/fae/form/_form.js +5 -2
  11. data/app/assets/javascripts/fae/form/_form_manager.js +295 -0
  12. data/app/assets/javascripts/fae/form/_slugger.js.erb +2 -2
  13. data/app/assets/javascripts/fae/form/_validator.js +224 -55
  14. data/app/assets/javascripts/fae/form/drag_drop.js +109 -0
  15. data/app/assets/javascripts/fae/form/inputs/_select.js +10 -4
  16. data/app/assets/javascripts/fae/form/inputs/_text.js +23 -9
  17. data/app/assets/javascripts/fae/vendor/simplemde/codemirror-4.inline-attachment.js +95 -0
  18. data/app/assets/javascripts/fae/vendor/simplemde/inline-attachment.js +405 -0
  19. data/app/assets/stylesheets/fae/application.css +1 -0
  20. data/app/assets/stylesheets/fae/base.scss +7 -3
  21. data/app/assets/stylesheets/fae/globals/_tags.scss +1 -1
  22. data/app/assets/stylesheets/fae/globals/imports/_variables.scss +1 -0
  23. data/app/assets/stylesheets/fae/globals/layout/_base.scss +9 -4
  24. data/app/assets/stylesheets/fae/globals/layout/_content-header.scss +14 -4
  25. data/app/assets/stylesheets/fae/globals/legacy/_pre-1.3.scss +1 -1
  26. data/app/assets/stylesheets/fae/globals/navigation/_footer.scss +1 -1
  27. data/app/assets/stylesheets/fae/globals/navigation/_header.scss +3 -3
  28. data/app/assets/stylesheets/fae/globals/navigation/_multi-col-subnav.scss +50 -0
  29. data/app/assets/stylesheets/fae/globals/navigation/_sidenav.scss +2 -2
  30. data/app/assets/stylesheets/fae/globals/navigation/_utility.scss +1 -1
  31. data/app/assets/stylesheets/fae/modules/_buttons.scss +11 -0
  32. data/app/assets/stylesheets/fae/modules/_deploy.scss +25 -0
  33. data/app/assets/stylesheets/fae/modules/_errors-bar.scss +19 -0
  34. data/app/assets/stylesheets/fae/modules/_modal.scss +25 -0
  35. data/app/assets/stylesheets/fae/modules/_toggles.scss +39 -23
  36. data/app/assets/stylesheets/fae/modules/forms/_asset-actions.scss +1 -1
  37. data/app/assets/stylesheets/fae/modules/forms/_base.scss +14 -1
  38. data/app/assets/stylesheets/fae/modules/forms/_checkbox.scss +1 -1
  39. data/app/assets/stylesheets/fae/modules/forms/_date.scss +20 -4
  40. data/app/assets/stylesheets/fae/modules/forms/_form-manager.scss +82 -0
  41. data/app/assets/stylesheets/fae/modules/forms/_hints.scss +1 -1
  42. data/app/assets/stylesheets/fae/modules/forms/_label.scss +1 -1
  43. data/app/assets/stylesheets/fae/modules/forms/_radio.scss +1 -1
  44. data/app/assets/stylesheets/fae/modules/forms/_select.scss +9 -8
  45. data/app/assets/stylesheets/fae/modules/forms/_simple-mde.scss +72 -1
  46. data/app/assets/stylesheets/fae/modules/forms/_textarea.scss +1 -1
  47. data/app/assets/stylesheets/fae/modules/tables/_base.scss +1 -1
  48. data/app/assets/stylesheets/fae/modules/tables/_filters.scss +4 -0
  49. data/app/assets/stylesheets/fae/modules/tables/_pagination.scss +2 -2
  50. data/app/assets/stylesheets/fae/pages/_error.scss +1 -1
  51. data/app/assets/stylesheets/fae/pages/_login.scss +5 -1
  52. data/app/assets/stylesheets/fae/simplemde_override.scss +32 -0
  53. data/app/controllers/fae/application_controller.rb +9 -2
  54. data/app/controllers/fae/base_controller.rb +6 -2
  55. data/app/controllers/fae/deploy_controller.rb +24 -0
  56. data/app/controllers/fae/deploy_hooks_controller.rb +71 -0
  57. data/app/controllers/fae/form_managers_controller.rb +19 -0
  58. data/app/controllers/fae/options_controller.rb +1 -0
  59. data/app/controllers/fae/setup_controller.rb +2 -2
  60. data/app/controllers/fae/static_pages_controller.rb +6 -1
  61. data/app/controllers/fae/users_controller.rb +11 -1
  62. data/app/controllers/fae/utilities_controller.rb +18 -6
  63. data/app/helpers/fae/application_helper.rb +36 -2
  64. data/app/helpers/fae/form_helper.rb +26 -2
  65. data/app/helpers/fae/view_helper.rb +26 -9
  66. data/app/models/concerns/fae/base_model_concern.rb +17 -0
  67. data/app/models/concerns/fae/seo_set_concern.rb +1 -0
  68. data/app/models/fae/change.rb +20 -6
  69. data/app/models/fae/deploy_hook.rb +12 -0
  70. data/app/models/fae/form_manager.rb +24 -0
  71. data/app/models/fae/option.rb +1 -0
  72. data/app/models/fae/seo_set.rb +14 -0
  73. data/app/models/fae/user.rb +2 -2
  74. data/app/services/fae/netlify_api.rb +213 -0
  75. data/app/uploaders/fae/file_uploader.rb +1 -1
  76. data/app/uploaders/fae/image_uploader.rb +2 -2
  77. data/app/views/devise/unlocks/new.html.slim +5 -9
  78. data/app/views/fae/application/_content_form.html.slim +16 -11
  79. data/app/views/fae/application/_file_uploader.html.slim +7 -2
  80. data/app/views/fae/application/_global_search_results.html.slim +1 -1
  81. data/app/views/fae/application/_header.slim +4 -1
  82. data/app/views/fae/application/_mobilenav.slim +3 -0
  83. data/app/views/fae/application/_seo_set_form.html.slim +12 -0
  84. data/app/views/fae/deploy/index.html.slim +40 -0
  85. data/app/views/fae/deploy_hooks/_form.html.slim +18 -0
  86. data/app/views/fae/deploy_hooks/_table.html.slim +28 -0
  87. data/app/views/fae/deploy_hooks/edit.html.slim +3 -0
  88. data/app/views/fae/deploy_hooks/new.html.slim +3 -0
  89. data/app/views/fae/images/_image_uploader.html.slim +12 -3
  90. data/app/views/fae/options/_form.html.slim +6 -2
  91. data/app/views/fae/pages/activity_log.html.slim +7 -3
  92. data/app/views/fae/pages/home.html.slim +3 -4
  93. data/app/views/fae/shared/_errors.slim +0 -3
  94. data/app/views/fae/shared/_form_header.html.slim +20 -12
  95. data/app/views/fae/shared/_nested_table.html.slim +5 -2
  96. data/app/views/fae/shared/_recent_changes.html.slim +1 -1
  97. data/app/views/fae/shared/_shared_nested_table.html.slim +9 -3
  98. data/app/views/layouts/fae/application.html.slim +2 -1
  99. data/config/deploy.rb +3 -1
  100. data/config/initializers/carrierwave.rb +41 -2
  101. data/config/initializers/devise.rb +6 -6
  102. data/config/initializers/fae_judge.rb +4 -2
  103. data/config/locales/fae.en.yml +49 -4
  104. data/config/locales/fae.zh-CN.yml +2 -2
  105. data/config/puma.rb +82 -0
  106. data/config/routes.rb +9 -1
  107. data/db/migrate/20140809222030_add_user_table.rb +1 -1
  108. data/db/migrate/20190925153222_create_fae_form_managers.rb +11 -0
  109. data/db/migrate/20220118192729_create_fae_publish_hooks.rb +10 -0
  110. data/db/migrate/20220128133730_rename_publish_hooks.rb +5 -0
  111. data/db/migrate/20220202153607_add_position_to_deploy_hooks.rb +6 -0
  112. data/db/migrate/20221118161833_create_fae_seo_sets.rb +13 -0
  113. data/lib/fae/concerns/models/base.rb +2 -0
  114. data/lib/fae/engine.rb +3 -3
  115. data/lib/fae/options.rb +18 -18
  116. data/lib/fae/version.rb +1 -1
  117. data/lib/generators/fae/base_generator.rb +28 -5
  118. data/lib/generators/fae/controller_generator.rb +0 -1
  119. data/lib/generators/fae/install_generator.rb +1 -1
  120. data/lib/generators/fae/model_generator.rb +1 -2
  121. data/lib/generators/fae/nested_index_scaffold_generator.rb +1 -2
  122. data/lib/generators/fae/nested_scaffold_generator.rb +23 -2
  123. data/lib/generators/fae/page_generator.rb +1 -2
  124. data/lib/generators/fae/scaffold_generator.rb +1 -1
  125. data/lib/generators/fae/templates/assets/fae.js +1 -1
  126. data/lib/generators/fae/templates/controllers/nested_scaffold_controller.rb +13 -1
  127. data/lib/generators/fae/templates/controllers/scaffold_controller.rb +7 -0
  128. data/lib/generators/fae/templates/initializers/fae.rb +16 -1
  129. data/lib/generators/fae/templates/views/_form.html.slim +12 -1
  130. data/lib/generators/fae/templates/views/_form_index_nested.html.slim +15 -1
  131. data/lib/generators/fae/templates/views/_form_nested.html.slim +22 -2
  132. data/lib/generators/fae/templates/views/static_page_form.html.slim +13 -1
  133. metadata +53 -24
  134. data/config/deploy/dev.rb +0 -19
  135. data/config/deploy/prod.rb +0 -19
  136. data/config/deploy/stage.rb +0 -19
  137. /data/app/assets/javascripts/fae/vendor/{simplemde.min.js → simplemde/simplemde.min.js} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 64efa885d567372d041fc98081e6074e37adb03a
4
- data.tar.gz: 9945edf6077be0c1ef698a593da299c422baeb60
3
+ metadata.gz: '09c68df667f8b7ace15a19a487daa942920cbf0b'
4
+ data.tar.gz: dac2b54b4e27960568834510f11858e2173eddaa
5
5
  SHA512:
6
- metadata.gz: ab50aeecbc77980ccb20b73c742ef4043b74319b658a4e01f5a88432f538f95896e18bdf87cfdfee55331026d03283315e4b6ff1f1f8738274bc869a458f3bc9
7
- data.tar.gz: 48c3aae1f2cde1deb1405161f4942328c417733bf2832bac73fc4ca6967d96c30a0a8dfe994121c19e14631bdaabad28f721c9d4be82bdb099343bfff04f1947
6
+ metadata.gz: 99e3412b45fd0809a4af841af0c810971e0106dbe71f43104e9063abc691af0bf46d15b6d6b4890d68eca748ad8c633903c3446209675acb5f8c55dff9b9627e
7
+ data.tar.gz: aa26791d19a9c46c6cc9c4b8feb133832961d4035751bb2eeb534f402cc3eb9597d952dd517c62f1919bd4a3fcd53b0cbb4de82a14588ca2ba5995e6149cbca4
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  Like many Rails CMS engines, Fae delivers all the basics to get you up and running quickly: authentication, authorization, a sleek UI, form helpers, image processing and workflows. But unlike other engines, Fae's generated models, controllers, and views are built to customize and scale.
9
9
 
10
- Fae 2.0 supports Rails 5.0 to 5.2, support for Rails 4.x is deprecated as of Fae 2.0.
10
+ Fae 3.x supports Rails 7. For legacy Rails support you can use Fae 2.x on Rails 5.0 to 5.2.
11
11
 
12
12
  ## Installation
13
13
 
@@ -27,7 +27,7 @@ $ rails g fae:install
27
27
 
28
28
  ## Documentation
29
29
 
30
- For full documentation visit:
30
+ For full documentation visit:
31
31
  https://www.faecms.com/documentation
32
32
 
33
33
  ### Topics
@@ -57,10 +57,13 @@ https://www.faecms.com/documentation
57
57
  * [Change Tracker](docs/features/change_tracker.md)
58
58
  * [Slugger](docs/features/slugger.md)
59
59
  * [Disabling Environments](docs/features/disable_envs.md)
60
+ * [Form Field Label & Helper Text Manager](docs/features/form_manager.md)
61
+ * [Netlify Deploy Monitor](docs/features/netlify.md)
60
62
 
61
63
 
62
64
  ### Tutorials
63
65
 
66
+ * [Setting Up SEO with Fae](docs/tutorials/seo.md)
64
67
  * [Setting Up GraphQL with Fae](docs/tutorials/graphql_support.md)
65
68
  * [Setting Up Images and Files](docs/tutorials/image_and_files.md)
66
69
  * [Adding Dynamic Relationships to Pages](docs/tutorials/dynamic_relationships_to_pages.md)
@@ -0,0 +1,2 @@
1
+ //= link fae/application.css
2
+ //= link fae/application.js
@@ -0,0 +1,50 @@
1
+ /* global Fae, modal, FCH */
2
+
3
+ /**
4
+ * Fae contrast
5
+ * @namespace
6
+ */
7
+
8
+ Fae.contrast = {
9
+ ready: function () {
10
+ this.highlightHex = getComputedStyle(document.body).getPropertyValue('--highlight-color');
11
+
12
+ // exit if highlight color css var not found
13
+ if (!this.highlightHex) {
14
+ return;
15
+ }
16
+
17
+ this.$body = $('body');
18
+ this.whiteHex = '#fff';
19
+ this.blackHex = '#000';
20
+ this.hexRegex = /(^#[0-9a-fA-F]{6}$)/;
21
+
22
+ // exit if highlight color is not a valid hex color
23
+ if (!this.hexRegex.test(this.highlightHex)) {
24
+ return;
25
+ }
26
+
27
+ this.setForegroundColor();
28
+ },
29
+
30
+
31
+ // dynamically set foreground color based on contrast with user set highlight color
32
+ setForegroundColor() {
33
+ const yiq = this.getContrastYIQ();
34
+ if (yiq >= 170) {
35
+ this.$body[0].style.setProperty('--foreground-color', this.blackHex);
36
+ } else {
37
+ this.$body[0].style.setProperty('--foreground-color', this.whiteHex);
38
+ }
39
+ },
40
+
41
+ getContrastYIQ() {
42
+ const hex = this.highlightHex.replace('#', '');
43
+ const r = parseInt(hex.substr(0, 2), 16);
44
+ const g = parseInt(hex.substr(2, 2), 16);
45
+ const b = parseInt(hex.substr(4, 2), 16);
46
+ return ((r * 299) + (g * 587) + (b * 114)) / 1000;
47
+ }
48
+
49
+
50
+ };
@@ -0,0 +1,198 @@
1
+
2
+ /* global Fae, modal, FCH */
3
+
4
+ /**
5
+ * Fae deploy
6
+ * @namespace
7
+ */
8
+
9
+ Fae.deploy = {
10
+
11
+ ready: function() {
12
+ if (!$('body').hasClass('deploy')) return false;
13
+ this.$deployButtons = $('.js-run-deploy');
14
+ this.deployFinished = true;
15
+ this.buttonsEnabled = true;
16
+ this.pollTimeout = null;
17
+ this.pollInterval = 5000;
18
+ this.idleStates = ['ready', 'error', 'rejected']
19
+
20
+ this.pollDeployStatus();
21
+ this.deployButtonListener();
22
+ this.documentFocusListener();
23
+ this.notifyIdle();
24
+ this.refreshDeploysListAndStatuses();
25
+ },
26
+
27
+ deployButtonListener: function() {
28
+ var _this = this;
29
+ _this.$deployButtons.click(function(e) {
30
+ e.preventDefault();
31
+ _this.disableButtons();
32
+ var deploy_hook_type = $(this).data('build-hook-type');
33
+ $.post( '/admin/deploy/deploy_site', { deploy_hook_type: deploy_hook_type }, function(data) {
34
+ // Netlify returns nothing for deploy hook posts
35
+ });
36
+ });
37
+ },
38
+
39
+ documentFocusListener: function() {
40
+ var _this = this;
41
+ document.addEventListener('visibilitychange', function(ev) {
42
+ if (document.visibilityState === 'visible') {
43
+ _this.pollDeployStatus();
44
+ } else if (document.visibilityState === 'hidden') {
45
+ _this.destroyPoll();
46
+ }
47
+ });
48
+ },
49
+
50
+ refreshDeploysListAndStatuses: function() {
51
+ var _this = this;
52
+ $.get('/admin/deploy/deploys_list', function (data) {
53
+ if (data) {
54
+ _this.drawTables(data);
55
+ _this.stateChecks(data);
56
+ }
57
+ });
58
+ },
59
+
60
+ pollDeployStatus: function() {
61
+ var _this = this;
62
+ function poll() {
63
+ _this.refreshDeploysListAndStatuses();
64
+ _this.pollTimeout = setTimeout(poll, _this.pollInterval);
65
+ }
66
+ poll();
67
+ },
68
+
69
+ destroyPoll: function() {
70
+ clearTimeout(this.pollTimeout);
71
+ },
72
+
73
+ notifyRunning: function() {
74
+ $('.deploying-heading').addClass('running');
75
+ $('#js-deploying-section').removeClass('hidden');
76
+ },
77
+
78
+ notifyIdle: function() {
79
+ $('.deploying-heading').removeClass('running');
80
+ $('#js-deploying-section').addClass('hidden');
81
+ },
82
+
83
+ enableButtons: function() {
84
+ var _this = this;
85
+ if (!_this.buttonsEnabled) {
86
+ _this.buttonsEnabled = true;
87
+ _this.$deployButtons.prop('disabled', false);
88
+ }
89
+ },
90
+
91
+ disableButtons: function() {
92
+ var _this = this;
93
+ if (_this.buttonsEnabled) {
94
+ _this.buttonsEnabled = false;
95
+ _this.$deployButtons.prop('disabled', true);
96
+ }
97
+ },
98
+
99
+ afterDeploy: function() {
100
+ var _this = this;
101
+ if (!_this.deployFinished) {
102
+ _this.notifyIdle();
103
+ _this.enableButtons();
104
+ _this.deployFinished = true;
105
+ }
106
+ },
107
+
108
+ drawTables: function(data) {
109
+ var _this = this;
110
+ var runningDeploys = _this.getRunningDeploys(data);
111
+ var pastDeploys = _this.getPastDeploys(data);
112
+ $('.js-deploys-list').find('tbody').find('tr').remove();
113
+ _this.injectTableDeployData(runningDeploys, $('.js-deploys-list.running').find('tbody'));
114
+ _this.injectTableDeployData(pastDeploys, $('.js-deploys-list.past').find('tbody'));
115
+ Fae.navigation.lockFooter();
116
+ },
117
+
118
+ getRunningDeploys: function(data) {
119
+ var _this = this;
120
+ return data.filter(function(deploy) {
121
+ return $.inArray(deploy.state, _this.idleStates) === -1;
122
+ });
123
+ },
124
+
125
+ getPastDeploys: function(data) {
126
+ var _this = this;
127
+ return data.filter(function(deploy) {
128
+ return $.inArray(deploy.state, _this.idleStates) !== -1;
129
+ });
130
+ },
131
+
132
+ injectTableDeployData: function(deploys, $tbody) {
133
+ var _this = this;
134
+ $.each(deploys, function(i, deploy) {
135
+ $tbody.append(
136
+ $('<tr>').append([
137
+ $('<td>').text(deploy.commit_ref !== null ? 'FINE dev update' : deploy.title),
138
+ $('<td>').text(moment(deploy.updated_at).format('MM/DD/YYYY h:mm a')),
139
+ $('<td>').text(_this.deployDuration(deploy)),
140
+ $('<td>').text(_this.deployEnvironment(deploy)),
141
+ $('<td>').html(_this.errorMsg(deploy)),
142
+ ])
143
+ );
144
+ });
145
+ },
146
+
147
+ stateChecks: function(data) {
148
+ var _this = this;
149
+ if (_this.deployIsRunning(data)) {
150
+ _this.notifyRunning();
151
+ _this.disableButtons();
152
+ _this.deployFinished = false;
153
+ } else {
154
+ _this.afterDeploy();
155
+ }
156
+ },
157
+
158
+ valCheck: function(val) {
159
+ if (val !== null) return val;
160
+ },
161
+
162
+ deployIsRunning: function(data) {
163
+ var _this = this;
164
+ var running = false;
165
+ $.each(data, function(i, deploy) {
166
+ if(_this.idleStates.indexOf(deploy.state) === -1) {
167
+ running = true;
168
+ return false;
169
+ }
170
+ });
171
+ return running;
172
+ },
173
+
174
+ deployDuration: function(deploy) {
175
+ if (deploy.deploy_time === null) {
176
+ return '–';
177
+ } else {
178
+ return moment.utc(parseInt(deploy.deploy_time)*1000).format('HH:mm:ss');
179
+ }
180
+ },
181
+
182
+ deployEnvironment: function(deploy) {
183
+ if (deploy.branch === 'master' || deploy.branch === 'main') {
184
+ return 'Production';
185
+ }
186
+ return deploy.branch.charAt(0).toUpperCase() + deploy.branch.slice(1);
187
+ },
188
+
189
+ errorMsg: function(deploy) {
190
+ if (deploy.error_message) {
191
+ var out = 'An error occurred. Please contact your ';
192
+ out += '<a href="/admin/help">FINE team</a>.'
193
+ return out;
194
+ }
195
+ }
196
+
197
+ };
198
+
@@ -6,8 +6,19 @@
6
6
  */
7
7
  Fae.modals = {
8
8
  ready: function() {
9
+ this.$body = $('body');
10
+ this.openClass = 'modal-open';
11
+ this.modalClass = 'MODAL_ID-modal-open';
12
+ this.showEvent = 'modal:show';
13
+ this.shownEvent = 'modal:shown';
14
+ this.closeEvent = 'modal:close';
15
+ this.closedEvent = 'modal:closed';
16
+ this.modalOpen = false;
17
+
9
18
  this.imageModals();
10
19
  this.markdownModalListener();
20
+
21
+ this.ajaxModalListener();
11
22
  },
12
23
 
13
24
  /**
@@ -56,5 +67,88 @@ Fae.modals = {
56
67
  */
57
68
  markdownModalListener: function() {
58
69
  FCH.$document.on('click', '.markdown-support', this.markdownModal);
70
+ },
71
+
72
+ /**
73
+ * load remote data, open modal view
74
+ * @see {@link modals.formModalListener}
75
+ * @has_test {features/form_helpers/fae_input_spec.rb}
76
+ */
77
+ openAjaxModal: function (remoteUrl, relatedTarget) {
78
+ var _this = this;
79
+
80
+ $.get(remoteUrl, function (data) {
81
+ //Open remote url content in modal window
82
+ $(data).modal({
83
+ minHeight: "75%",
84
+ minWidth: "75%",
85
+ overlayClose: true,
86
+ zIndex: 1100,
87
+ containerId: "fae-modal",
88
+ persist: true,
89
+ opacity: 70,
90
+ overlayCss: { backgroundColor: "#000" },
91
+ onOpen: function (dialog) {
92
+ // Fade in modal + show data
93
+ dialog.overlay.fadeIn();
94
+ dialog.container.fadeIn(function() {
95
+ var shownEvent = $.Event(_this.shownEvent, { dialog: dialog, relatedTarget: relatedTarget });
96
+ _this.$body.trigger(shownEvent);
97
+ });
98
+ dialog.data.show();
99
+
100
+ var modalClasses = [_this.createClassFromModalId(relatedTarget.attr('id')), _this.openClass].join(' ');
101
+
102
+ _this.modalOpen = true;
103
+ _this.$body.addClass(modalClasses);
104
+ },
105
+ onShow: function (dialog) {
106
+ var showEvent = $.Event(_this.showEvent, { dialog: dialog, relatedTarget: relatedTarget });
107
+ _this.$body.trigger(showEvent);
108
+
109
+ $(dialog.container).css('height', 'auto')
110
+ },
111
+ onClose: function (dialog) {
112
+ var closeEvent = $.Event(_this.closeEvent, { dialog: dialog, relatedTarget: relatedTarget });
113
+ _this.$body.trigger(closeEvent);
114
+
115
+ // Fade out modal and close
116
+ dialog.container.fadeOut();
117
+ dialog.overlay.fadeOut(function () {
118
+ $.modal.close(); // must call this!
119
+
120
+ var closedEvent = $.Event(_this.closedEvent, { dialog: dialog, relatedTarget: relatedTarget });
121
+ var modalClasses = [_this.createClassFromModalId(relatedTarget.attr('id')), _this.openClass].join(' ');
122
+
123
+ _this.modalOpen = false;
124
+ _this.$body.removeClass(modalClasses);
125
+ _this.$body.trigger(closedEvent);
126
+ });
127
+ }
128
+ });
129
+
130
+ });
131
+ },
132
+
133
+ /**
134
+ * Click event listener for ajax modal links triggering specific view within modal popup
135
+ * @fires {@link modals.ajaxModal}
136
+ * @has_test {features/form_helpers/fae_input_spec.rb}
137
+ */
138
+ ajaxModalListener: function () {
139
+ var _this = this;
140
+
141
+ FCH.$document.on('click', '.js-fae-modal', function (e) {
142
+ e.preventDefault();
143
+ var $this = $(this);
144
+ var url = $this.attr('href');
145
+ var id = $this.attr('id');
146
+
147
+ _this.openAjaxModal(url, $this)
148
+ });
149
+ },
150
+
151
+ createClassFromModalId: function(modalId) {
152
+ return this.modalClass.replace('MODAL_ID', modalId);
59
153
  }
60
154
  };
@@ -30,7 +30,9 @@
30
30
  //= require fae/vendor/jquery.tablesorter
31
31
  //= require fae/vendor/js.cookie
32
32
  //= require fae/vendor/touch_punch
33
- //= require fae/vendor/simplemde.min
33
+ //= require fae/vendor/simplemde/simplemde.min
34
+ //= require fae/vendor/simplemde/inline-attachment
35
+ //= require fae/vendor/simplemde/codemirror-4.inline-attachment
34
36
 
35
37
  //= require fae/admin
36
38
 
@@ -46,8 +48,10 @@
46
48
  //= require fae/form/_cancel
47
49
  //= require fae/form/_ajax
48
50
  //= require fae/form/_filtering
51
+ //= require fae/form/_form_manager
49
52
  //= require fae/form/fae_chosen
50
53
  //= require fae/form/fileinputer
54
+ //= require fae/form/drag_drop
51
55
 
52
56
  //= require fae/navigation/sticky
53
57
  //= require fae/navigation/_navigation
@@ -57,6 +61,8 @@
57
61
 
58
62
  //= require fae/_modals
59
63
  //= require fae/_tables
64
+ //= require fae/_deploy
65
+ //= require fae/_contrast
60
66
 
61
67
  //= require fae
62
68
 
@@ -67,6 +67,8 @@ Fae.form.ajax = {
67
67
  $wrapper.find('.input.file').fileinputer();
68
68
  }
69
69
 
70
+ this.$nested_form = $('.nested-form');
71
+
70
72
  // Bind validation to nested form fields added by AJAX
71
73
  Fae.form.validator.bindValidationEvents(this.$nested_form);
72
74
 
@@ -80,6 +82,9 @@ Fae.form.ajax = {
80
82
  Fae.form.text.initHTML();
81
83
  Fae.form.checkbox.setCheckboxAsActive();
82
84
  Fae.form.select.init();
85
+ Fae.form.formManager.setupAllFields($wrapper.find('form'));
86
+ Fae.form.dragDrop.init();
87
+ Fae.tables.rowSorting();
83
88
 
84
89
  // validate nested form fields on submit
85
90
  Fae.form.validator.formValidate(this.$nested_form);
@@ -116,6 +121,11 @@ Fae.form.ajax = {
116
121
 
117
122
  var $target = $(evt.target);
118
123
 
124
+ // We need to target the form wrapper containing the target form to enable nesting
125
+ // multiple forms.
126
+ // Relying on $this will end up redrawing the top-most parent form with the returned table
127
+ var $theFormWrapper = $target.closest('.js-addedit-form');
128
+
119
129
  // ignore calls not returning html
120
130
  if (data !== ' ' && $(data)[0]) {
121
131
  var $this = $(this);
@@ -131,13 +141,13 @@ Fae.form.ajax = {
131
141
  if ($html) {
132
142
  if($html.hasClass('js-addedit-form') || $html.hasClass( 'js-index-addedit-form' )) {
133
143
  // we're returning the table, replace everything
134
- _this._addEditReplaceAndReinit($this, $html.html(), $target);
144
+ _this._addEditReplaceAndReinit($theFormWrapper, $html.html(), $target);
135
145
  } else if ($html.hasClass('nested-form')) {
136
146
 
137
147
  // we're returning the form due to an error, just replace the form
138
- $this.find('.nested-form' ).replaceWith($html);
139
- $this.find('.select select').fae_chosen();
140
- $this.find('.input.file').fileinputer();
148
+ $theFormWrapper.find('.nested-form' ).replaceWith($html);
149
+ $theFormWrapper.find('.select select').fae_chosen();
150
+ $theFormWrapper.find('.input.file').fileinputer();
141
151
 
142
152
  Fae.form.dates.initDatepicker();
143
153
  Fae.form.dates.initDateRangePicker();
@@ -163,6 +173,7 @@ Fae.form.ajax = {
163
173
 
164
174
  $parent.fadeOut(function(){
165
175
  $parent.next('.asset-inputs').fadeIn();
176
+ $parent.remove();
166
177
  });
167
178
  }
168
179
 
@@ -271,6 +282,7 @@ Fae.form.ajax = {
271
282
 
272
283
  $parent.fadeOut(function(){
273
284
  $parent.next('.asset-inputs').fadeIn();
285
+ $parent.remove();
274
286
  });
275
287
  }
276
288
  });
@@ -297,7 +309,7 @@ Fae.form.ajax = {
297
309
  * @todo Clean this up, moving listeners into their respective component classes (select, checkbox, etc.)
298
310
  */
299
311
  htmlListeners: function() {
300
- $('#js-main-content, .login-form > form')
312
+ $('#js-main-content, .login-form > form, #simplemodal-data')
301
313
 
302
314
  /**
303
315
  * For the delete button on file input
@@ -25,6 +25,7 @@ Fae.form.filtering = {
25
25
  }
26
26
 
27
27
  this.setFilterDropDowns();
28
+ this.setTextInputs();
28
29
  this.filterFormListeners();
29
30
  this.paginationListeners();
30
31
  this.sortingSetup();
@@ -87,6 +88,7 @@ Fae.form.filtering = {
87
88
  // update search param when form submits
88
89
  .on('submit', function(ev) {
89
90
  $('.js-reset-btn').show();
91
+ $('.js-reset-btn').removeClass('hidden');
90
92
  _this.updateFryrAndResetPaging('search', $('#filter_search').val());
91
93
  return false;
92
94
  })
@@ -117,6 +119,17 @@ Fae.form.filtering = {
117
119
  _this.updateFryrAndResetPaging(key, value);
118
120
 
119
121
  $('.js-reset-btn').show();
122
+ $('.js-reset-btn').removeClass('hidden');
123
+ })
124
+
125
+ // update hash when date inputs changed
126
+ .on('change', '.datepicker input', function() {
127
+ var key = $(this).attr('id').split('filter_')[1];
128
+ var value = $(this).val();
129
+ timer = setTimeout(function() {
130
+ _this.updateFryrAndResetPaging(key, value);
131
+ $('.js-reset-btn').show();
132
+ }, 500);
120
133
  });
121
134
  },
122
135
 
@@ -147,6 +160,27 @@ Fae.form.filtering = {
147
160
  $('.js-reset-btn').show();
148
161
  },
149
162
 
163
+ /**
164
+ * Sets filter dropdowns on page load based on Fryr params
165
+ */
166
+ setTextInputs: function() {
167
+ // Exit early if this.fry.params is blank
168
+ if ($.isEmptyObject(this.fry.params)) {
169
+ return;
170
+ }
171
+
172
+ // Loop through all available this.fry.params to find the select menu and the proper option
173
+ $.each(this.fry.params, function(key, value) {
174
+ var $input = $('.js-filter-form .table-filter-group.text-input #filter_' + key);
175
+
176
+ if($input.length) {
177
+ $input.val(decodeURIComponent(value));
178
+ }
179
+ });
180
+
181
+ $('.js-reset-btn').show();
182
+ },
183
+
150
184
  /**
151
185
  * Updates a Fryr param while reseting paging
152
186
  * Use for most cases of pushing a single params to Fryr, as paging will always reset in those cases
@@ -20,15 +20,18 @@ Fae.form = {
20
20
  this.ajax.init();
21
21
  this.filtering.init();
22
22
  this.slugger.init();
23
-
23
+ this.formManager.init();
24
+
24
25
  // input type=file customization
25
26
  // This doesn't work in IE. It's not worth figuring out why by this point. IE9 gets plain file uploader.
26
27
  if (!FCH.IE9) {
27
28
  $('.input.file').fileinputer();
28
29
  }
29
-
30
+
30
31
  // make all the hint areas
31
32
  $('.hint').hinter();
33
+
34
+ this.dragDrop.init();
32
35
  },
33
36
 
34
37
  makeTwoColumnLabels: function() {