fae-rails 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -6,7 +6,7 @@
6
6
  * @memberof form
7
7
  */
8
8
  Fae.form.text = {
9
- init: function() {
9
+ init: function () {
10
10
  this.overrideMarkdownDefaults();
11
11
  this.initMarkdown();
12
12
  this.initHTML();
@@ -16,7 +16,7 @@ Fae.form.text = {
16
16
  * Override SimpleMDE's preference for font-awesome icons and use a modal for the guide
17
17
  * @see {@link modals.markdownModal}
18
18
  */
19
- overrideMarkdownDefaults: function() {
19
+ overrideMarkdownDefaults: function () {
20
20
  toolbarBuiltInButtons['bold'].className = 'icon-bold';
21
21
  toolbarBuiltInButtons['italic'].className = 'icon-italic';
22
22
  toolbarBuiltInButtons['heading'].className = 'icon-font';
@@ -40,8 +40,20 @@ Fae.form.text = {
40
40
  * Find all markdown fields and initialize them with a markdown GUI
41
41
  * @has_test {features/form_helpers/fae_input_spec.rb}
42
42
  */
43
- initMarkdown: function() {
44
- $('.js-markdown-editor:not(.mde-enabled)').each(function() {
43
+ initMarkdown: function () {
44
+ var inlineAttachmentConfig = {
45
+ uploadUrl: '/admin/html_embedded_image',
46
+ uploadFieldName: 'image',
47
+ jsonFieldName: 'file',
48
+ progressText: '![Uploading file...]()',
49
+ urlText: '![file]({filename})',
50
+ errorText: 'Error uploading file, file may be too large',
51
+ extraHeaders: {
52
+ 'X-CSRF-Token': $.rails.csrfToken()
53
+ }
54
+ }
55
+
56
+ $('.js-markdown-editor:not(.mde-enabled)').each(function () {
45
57
  var $this = $(this);
46
58
 
47
59
  var editor = new SimpleMDE({
@@ -49,9 +61,11 @@ Fae.form.text = {
49
61
  autoDownloadFontAwesome: false,
50
62
  status: false,
51
63
  spellChecker: false,
52
- hideIcons: ['image', 'side-by-side', 'fullscreen', 'preview']
64
+ hideIcons: ['image', 'side-by-side', 'fullscreen']
53
65
  });
54
66
 
67
+ inlineAttachment.editors.codemirror4.attach(editor.codemirror, inlineAttachmentConfig);
68
+
55
69
  // Disable tabbing within editor
56
70
  editor.codemirror.options.extraKeys['Tab'] = false;
57
71
  editor.codemirror.options.extraKeys['Shift-Tab'] = false;
@@ -59,16 +73,16 @@ Fae.form.text = {
59
73
  $this.addClass('mde-enabled');
60
74
 
61
75
  // code mirror events to hook into current form element functions
62
- editor.codemirror.on('change', function(){
76
+ editor.codemirror.on('change', function (){
63
77
  // updates the original textarea's value for JS validations
64
78
  $this.val(editor.value());
65
79
  // update length counter
66
80
  Fae.form.validator.length_counter.updateCounter($this);
67
81
  });
68
- editor.codemirror.on('focus', function(){
82
+ editor.codemirror.on('focus', function (){
69
83
  $this.parent().addClass('mde-focus');
70
84
  });
71
- editor.codemirror.on('blur', function(){
85
+ editor.codemirror.on('blur', function (){
72
86
  // trigger blur on the original textarea to trigger JS validations
73
87
  $this.blur();
74
88
  $this.parent().removeClass('mde-focus');
@@ -80,7 +94,7 @@ Fae.form.text = {
80
94
  * Find all HTML fields and initialize them with a wysiwyg GUI
81
95
  * @has_test {features/form_helpers/fae_input_spec.rb}
82
96
  */
83
- initHTML: function() {
97
+ initHTML: function () {
84
98
  var $html_editors = $('.js-html-editor');
85
99
  if(!$html_editors.length) {
86
100
  return;
@@ -0,0 +1,95 @@
1
+ // https://github.com/Rovak/InlineAttachment/blob/master/src/codemirror-4.inline-attachment.js
2
+
3
+ /*jslint newcap: true */
4
+ /*global inlineAttachment: false */
5
+ /**
6
+ * CodeMirror version for inlineAttachment
7
+ *
8
+ * Call inlineAttachment.attach(editor) to attach to a codemirror instance
9
+ */
10
+ (function () {
11
+ 'use strict';
12
+
13
+ var codeMirrorEditor = function (instance) {
14
+ if (!instance.getWrapperElement) {
15
+ throw 'Invalid CodeMirror object given';
16
+ }
17
+
18
+ this.codeMirror = instance;
19
+ };
20
+
21
+ codeMirrorEditor.prototype.getValue = function () {
22
+ return this.codeMirror.getValue();
23
+ };
24
+
25
+ codeMirrorEditor.prototype.insertValue = function (val) {
26
+ this.codeMirror.replaceSelection(val);
27
+ };
28
+
29
+ codeMirrorEditor.prototype.setValue = function (val) {
30
+ var cursor = this.codeMirror.getCursor();
31
+ this.codeMirror.setValue(val);
32
+ this.codeMirror.setCursor(cursor);
33
+ };
34
+
35
+ /**
36
+ * Attach InlineAttachment to CodeMirror
37
+ *
38
+ * @param {CodeMirror} codeMirror
39
+ */
40
+ codeMirrorEditor.attach = function (codeMirror, options) {
41
+ options = options || {};
42
+
43
+ var editor = new codeMirrorEditor(codeMirror),
44
+ inlineattach = new inlineAttachment(options, editor),
45
+ el = codeMirror.getWrapperElement();
46
+
47
+ el.addEventListener(
48
+ 'paste',
49
+ function (e) {
50
+ inlineattach.onPaste(e);
51
+ },
52
+ false
53
+ );
54
+
55
+ codeMirror.setOption('onDragEvent', function (data, e) {
56
+ if (e.type === 'drop') {
57
+ e.stopPropagation();
58
+ e.preventDefault();
59
+ return inlineattach.onDrop(e);
60
+ }
61
+ });
62
+ };
63
+
64
+ var codeMirrorEditor4 = function (instance) {
65
+ codeMirrorEditor.call(this, instance);
66
+ };
67
+
68
+ codeMirrorEditor4.attach = function (codeMirror, options) {
69
+ options = options || {};
70
+
71
+ var editor = new codeMirrorEditor(codeMirror),
72
+ inlineattach = new inlineAttachment(options, editor),
73
+ el = codeMirror.getWrapperElement();
74
+
75
+ el.addEventListener(
76
+ 'paste',
77
+ function (e) {
78
+ inlineattach.onPaste(e);
79
+ },
80
+ false
81
+ );
82
+
83
+ codeMirror.on('drop', function (data, e) {
84
+ if (inlineattach.onDrop(e)) {
85
+ e.stopPropagation();
86
+ e.preventDefault();
87
+ return true;
88
+ } else {
89
+ return false;
90
+ }
91
+ });
92
+ };
93
+
94
+ inlineAttachment.editors.codemirror4 = codeMirrorEditor4;
95
+ })();
@@ -0,0 +1,405 @@
1
+ /*jslint newcap: true */
2
+ /*global XMLHttpRequest: false, FormData: false */
3
+ /*
4
+ * https://raw.githubusercontent.com/Rovak/InlineAttachment/master/src/inline-attachment.js
5
+ * Inline Text Attachment
6
+ *
7
+ * Author: Roy van Kaathoven
8
+ * Contact: ik@royvankaathoven.nl
9
+ */
10
+ (function (document, window) {
11
+ 'use strict';
12
+
13
+ var inlineAttachment = function (options, instance) {
14
+ this.settings = inlineAttachment.util.merge(
15
+ options,
16
+ inlineAttachment.defaults
17
+ );
18
+ this.editor = instance;
19
+ this.filenameTag = '{filename}';
20
+ this.lastValue = null;
21
+ };
22
+
23
+ /**
24
+ * Will holds the available editors
25
+ *
26
+ * @type {Object}
27
+ */
28
+ inlineAttachment.editors = {};
29
+
30
+ /**
31
+ * Utility functions
32
+ */
33
+ inlineAttachment.util = {
34
+ /**
35
+ * Simple function to merge the given objects
36
+ *
37
+ * @param {Object[]} object Multiple object parameters
38
+ * @returns {Object}
39
+ */
40
+ merge: function () {
41
+ var result = {};
42
+ for (var i = arguments.length - 1; i >= 0; i--) {
43
+ var obj = arguments[i];
44
+ for (var k in obj) {
45
+ if (obj.hasOwnProperty(k)) {
46
+ result[k] = obj[k];
47
+ }
48
+ }
49
+ }
50
+ return result;
51
+ },
52
+
53
+ /**
54
+ * Append a line of text at the bottom, ensuring there aren't unnecessary newlines
55
+ *
56
+ * @param {String} appended Current content
57
+ * @param {String} previous Value which should be appended after the current content
58
+ */
59
+ appendInItsOwnLine: function (previous, appended) {
60
+ return (previous + "\n\n[[D]]" + appended)
61
+ .replace(/(\n{2,})\[\[D\]\]/, "\n\n")
62
+ .replace(/^(\n*)/, "");
63
+ },
64
+
65
+ /**
66
+ * Inserts the given value at the current cursor position of the textarea element
67
+ *
68
+ * @param {HtmlElement} el
69
+ * @param {String} value Text which will be inserted at the cursor position
70
+ */
71
+ insertTextAtCursor: function (el, text) {
72
+ var scrollPos = el.scrollTop,
73
+ strPos = 0,
74
+ browser = false,
75
+ range;
76
+
77
+ if (el.selectionStart || el.selectionStart === '0') {
78
+ browser = 'ff';
79
+ } else if (document.selection) {
80
+ browser = 'ie';
81
+ }
82
+
83
+ if (browser === 'ie') {
84
+ el.focus();
85
+ range = document.selection.createRange();
86
+ range.moveStart('character', -el.value.length);
87
+ strPos = range.text.length;
88
+ } else if (browser === 'ff') {
89
+ strPos = el.selectionStart;
90
+ }
91
+
92
+ var front = el.value.substring(0, strPos);
93
+ var back = el.value.substring(strPos, el.value.length);
94
+ el.value = front + text + back;
95
+ strPos = strPos + text.length;
96
+ if (browser === 'ie') {
97
+ el.focus();
98
+ range = document.selection.createRange();
99
+ range.moveStart('character', -el.value.length);
100
+ range.moveStart('character', strPos);
101
+ range.moveEnd('character', 0);
102
+ range.select();
103
+ } else if (browser === 'ff') {
104
+ el.selectionStart = strPos;
105
+ el.selectionEnd = strPos;
106
+ el.focus();
107
+ }
108
+ el.scrollTop = scrollPos;
109
+ }
110
+ };
111
+
112
+ /**
113
+ * Default configuration options
114
+ *
115
+ * @type {Object}
116
+ */
117
+ inlineAttachment.defaults = {
118
+ /**
119
+ * URL where the file will be send
120
+ */
121
+ uploadUrl: 'upload_attachment.php',
122
+
123
+ /**
124
+ * Which method will be used to send the file to the upload URL
125
+ */
126
+ uploadMethod: 'POST',
127
+
128
+ /**
129
+ * Name in which the file will be placed
130
+ */
131
+ uploadFieldName: 'image',
132
+
133
+ /**
134
+ * Extension which will be used when a file extension could not
135
+ * be detected
136
+ */
137
+ defaultExtension: 'png',
138
+
139
+ /**
140
+ * JSON field which refers to the uploaded file URL
141
+ */
142
+ jsonFieldName: 'filename',
143
+
144
+ /**
145
+ * Allowed MIME types
146
+ */
147
+ allowedTypes: [
148
+ 'image/jpeg',
149
+ 'image/png',
150
+ 'image/jpg',
151
+ 'image/gif'
152
+ ],
153
+
154
+ /**
155
+ * Text which will be inserted when dropping or pasting a file.
156
+ * Acts as a placeholder which will be replaced when the file is done with uploading
157
+ */
158
+ progressText: '![Uploading file...]()',
159
+
160
+ /**
161
+ * When a file has successfully been uploaded the progressText
162
+ * will be replaced by the urlText, the {filename} tag will be replaced
163
+ * by the filename that has been returned by the server
164
+ */
165
+ urlText: '![file]({filename})',
166
+
167
+ /**
168
+ * Text which will be used when uploading has failed
169
+ */
170
+ errorText: 'Error uploading file',
171
+
172
+ /**
173
+ * Extra parameters which will be send when uploading a file
174
+ */
175
+ extraParams: {},
176
+
177
+ /**
178
+ * Extra headers which will be send when uploading a file
179
+ */
180
+ extraHeaders: {},
181
+
182
+ /**
183
+ * Before the file is send
184
+ */
185
+ beforeFileUpload: function () {
186
+ return true;
187
+ },
188
+
189
+ /**
190
+ * Triggers when a file is dropped or pasted
191
+ */
192
+ onFileReceived: function () {},
193
+
194
+ /**
195
+ * Custom upload handler
196
+ *
197
+ * @return {Boolean} when false is returned it will prevent default upload behavior
198
+ */
199
+ onFileUploadResponse: function () {
200
+ return true;
201
+ },
202
+
203
+ /**
204
+ * Custom error handler. Runs after removing the placeholder text and before the alert().
205
+ * Return false from this function to prevent the alert dialog.
206
+ *
207
+ * @return {Boolean} when false is returned it will prevent default error behavior
208
+ */
209
+ onFileUploadError: function () {
210
+ return true;
211
+ },
212
+
213
+ /**
214
+ * When a file has succesfully been uploaded
215
+ */
216
+ onFileUploaded: function () {}
217
+ };
218
+
219
+ /**
220
+ * Uploads the blob
221
+ *
222
+ * @param {Blob} file blob data received from event.dataTransfer object
223
+ * @return {XMLHttpRequest} request object which sends the file
224
+ */
225
+ inlineAttachment.prototype.uploadFile = function (file) {
226
+ var me = this,
227
+ formData = new FormData(),
228
+ xhr = new XMLHttpRequest(),
229
+ settings = this.settings,
230
+ extension = settings.defaultExtension || settings.defualtExtension;
231
+
232
+ if (typeof settings.setupFormData === 'function') {
233
+ settings.setupFormData(formData, file);
234
+ }
235
+
236
+ // Attach the file. If coming from clipboard, add a default filename (only works in Chrome for now)
237
+ // http://stackoverflow.com/questions/6664967/how-to-give-a-blob-uploaded-as-formdata-a-file-name
238
+ if (file.name) {
239
+ var fileNameMatches = file.name.match(/\.(.+)$/);
240
+ if (fileNameMatches) {
241
+ extension = fileNameMatches[1];
242
+ }
243
+ }
244
+
245
+ var remoteFilename = 'image-' + Date.now() + '.' + extension;
246
+ if (typeof settings.remoteFilename === 'function') {
247
+ remoteFilename = settings.remoteFilename(file);
248
+ }
249
+
250
+ formData.append(settings.uploadFieldName, file, remoteFilename);
251
+
252
+ // Append the extra parameters to the formdata
253
+ if (typeof settings.extraParams === 'object') {
254
+ for (var key in settings.extraParams) {
255
+ if (settings.extraParams.hasOwnProperty(key)) {
256
+ formData.append(key, settings.extraParams[key]);
257
+ }
258
+ }
259
+ }
260
+
261
+ xhr.open('POST', settings.uploadUrl);
262
+
263
+ // Add any available extra headers
264
+ if (typeof settings.extraHeaders === 'object') {
265
+ for (var header in settings.extraHeaders) {
266
+ if (settings.extraHeaders.hasOwnProperty(header)) {
267
+ xhr.setRequestHeader(header, settings.extraHeaders[header]);
268
+ }
269
+ }
270
+ }
271
+
272
+ xhr.onload = function () {
273
+ // If HTTP status is OK or Created
274
+ if (xhr.status === 200 || xhr.status === 201) {
275
+ me.onFileUploadResponse(xhr);
276
+ } else {
277
+ me.onFileUploadError(xhr);
278
+ }
279
+ };
280
+ if (settings.beforeFileUpload(xhr) !== false) {
281
+ xhr.send(formData);
282
+ }
283
+ return xhr;
284
+ };
285
+
286
+ /**
287
+ * Returns if the given file is allowed to handle
288
+ *
289
+ * @param {File} clipboard data file
290
+ */
291
+ inlineAttachment.prototype.isFileAllowed = function (file) {
292
+ if (file.kind === 'string') {
293
+ return false;
294
+ }
295
+ if (this.settings.allowedTypes.indexOf('*') === 0) {
296
+ return true;
297
+ } else {
298
+ return this.settings.allowedTypes.indexOf(file.type) >= 0;
299
+ }
300
+ };
301
+
302
+ /**
303
+ * Handles upload response
304
+ *
305
+ * @param {XMLHttpRequest} xhr
306
+ * @return {Void}
307
+ */
308
+ inlineAttachment.prototype.onFileUploadResponse = function (xhr) {
309
+ if (this.settings.onFileUploadResponse.call(this, xhr) !== false) {
310
+ var result = JSON.parse(xhr.responseText),
311
+ filename = result[this.settings.jsonFieldName];
312
+
313
+ if (result && filename) {
314
+ var newValue;
315
+ if (typeof this.settings.urlText === 'function') {
316
+ newValue = this.settings.urlText.call(this, filename, result);
317
+ } else {
318
+ newValue = this.settings.urlText.replace(this.filenameTag, filename);
319
+ }
320
+ var text = this.editor.getValue().replace(this.lastValue, newValue);
321
+ this.editor.setValue(text);
322
+ this.settings.onFileUploaded.call(this, filename);
323
+ }
324
+ }
325
+ };
326
+
327
+ /**
328
+ * Called when a file has failed to upload
329
+ *
330
+ * @param {XMLHttpRequest} xhr
331
+ * @return {Void}
332
+ */
333
+ inlineAttachment.prototype.onFileUploadError = function (xhr) {
334
+ if (this.settings.onFileUploadError.call(this, xhr) !== false) {
335
+ var text = this.editor
336
+ .getValue()
337
+ .replace(this.lastValue, this.settings.errorText);
338
+ this.editor.setValue(text);
339
+ }
340
+ };
341
+
342
+ /**
343
+ * Called when a file has been inserted, either by drop or paste
344
+ *
345
+ * @param {File} file
346
+ * @return {Void}
347
+ */
348
+ inlineAttachment.prototype.onFileInserted = function (file) {
349
+ if (this.settings.onFileReceived.call(this, file) !== false) {
350
+ this.lastValue = this.settings.progressText;
351
+ this.editor.insertValue(this.lastValue);
352
+ }
353
+ };
354
+
355
+ /**
356
+ * Called when a paste event occured
357
+ * @param {Event} e
358
+ * @return {Boolean} if the event was handled
359
+ */
360
+ inlineAttachment.prototype.onPaste = function (e) {
361
+ var result = false,
362
+ clipboardData = e.clipboardData,
363
+ items;
364
+
365
+ if (typeof clipboardData === 'object') {
366
+ items = clipboardData.items || clipboardData.files || [];
367
+
368
+ for (var i = 0; i < items.length; i++) {
369
+ var item = items[i];
370
+ if (this.isFileAllowed(item)) {
371
+ result = true;
372
+ this.onFileInserted(item.getAsFile());
373
+ this.uploadFile(item.getAsFile());
374
+ }
375
+ }
376
+ }
377
+
378
+ if (result) {
379
+ e.preventDefault();
380
+ }
381
+
382
+ return result;
383
+ };
384
+
385
+ /**
386
+ * Called when a drop event occures
387
+ * @param {Event} e
388
+ * @return {Boolean} if the event was handled
389
+ */
390
+ inlineAttachment.prototype.onDrop = function (e) {
391
+ var result = false;
392
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
393
+ var file = e.dataTransfer.files[i];
394
+ if (this.isFileAllowed(file)) {
395
+ result = true;
396
+ this.onFileInserted(file);
397
+ this.uploadFile(file);
398
+ }
399
+ }
400
+
401
+ return result;
402
+ };
403
+
404
+ window.inlineAttachment = inlineAttachment;
405
+ })(document, window);
@@ -5,4 +5,5 @@
5
5
  *= require fae/vendor/simplemde.min
6
6
  *= require fae/vendor/trumbowyg
7
7
  *= require fae/base
8
+ *= require fae/simplemde_override
8
9
  */
@@ -32,7 +32,8 @@
32
32
  'globals/navigation/sidenav',
33
33
  'globals/navigation/mobilenav',
34
34
  'globals/navigation/utility',
35
- 'globals/navigation/search'
35
+ 'globals/navigation/search',
36
+ 'globals/navigation/multi-col-subnav'
36
37
  ;
37
38
 
38
39
  // Tables
@@ -52,8 +53,10 @@
52
53
  @import
53
54
  'modules/buttons',
54
55
  'modules/modal',
56
+ 'modules/deploy',
55
57
  'modules/toggles',
56
- 'modules/alerts'
58
+ 'modules/alerts',
59
+ 'modules/errors-bar'
57
60
  ;
58
61
 
59
62
  // Forms
@@ -70,7 +73,8 @@
70
73
  'modules/forms/colorpicker',
71
74
  'modules/forms/hints',
72
75
  'modules/forms/validation',
73
- 'modules/forms/simple-mde'
76
+ 'modules/forms/simple-mde',
77
+ 'modules/forms/form-manager'
74
78
  ;
75
79
 
76
80
  // Pages
@@ -33,7 +33,7 @@ body {
33
33
 
34
34
  a {
35
35
  @include transition(color .2s);
36
- color: $c-custom-highlight;
36
+ color: var(--highlight-color);
37
37
  text-decoration: none;
38
38
 
39
39
  &:hover {
@@ -89,6 +89,7 @@ $c-chosen-gradient-end: $c-light-grey !default;
89
89
  $c-chosen-multi-bg: $c-lightest-grey !default;
90
90
  $c-chosen-multi-text: $c-dark-grey !default;
91
91
  $c-chosen-multi-delete: $c-darker-grey !default;
92
+ $c-focus-border: $c-mid-dark-grey !default;
92
93
 
93
94
  // Yes / No Sliders
94
95
  $c-slider-no-color: $c-light-grey !default;
@@ -27,14 +27,13 @@
27
27
 
28
28
  h2 {
29
29
  padding: 17px $content-buffer;
30
- color: pickForegroundColor($c-custom-highlight, $c-white, $c-black);
31
- background: $c-custom-highlight;
30
+ color: var(--foreground-color);
31
+ background: var(--highlight-color);
32
32
  border-top: 1px solid $c-border;
33
33
  text-transform: uppercase;
34
34
  font-size: 14px;
35
35
  letter-spacing: .2em;
36
- // counters the padding from .content
37
- margin: 0 negate($content-buffer) 30px;
36
+ margin: 0 0 30px;
38
37
  }
39
38
 
40
39
  h3 {
@@ -46,3 +45,9 @@
46
45
  margin-bottom: 20px;
47
46
  }
48
47
  }
48
+
49
+ p {
50
+ margin-bottom: 1.3em;
51
+ max-width: 80%;
52
+ line-height: 1.2em;
53
+ }