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.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/app/assets/config/fae/manifest.js +2 -0
- data/app/assets/javascripts/fae/_contrast.js +50 -0
- data/app/assets/javascripts/fae/_deploy.js +198 -0
- data/app/assets/javascripts/fae/_modals.js +94 -0
- data/app/assets/javascripts/fae/application.js +7 -1
- data/app/assets/javascripts/fae/form/_ajax.js +17 -5
- data/app/assets/javascripts/fae/form/_filtering.js +34 -0
- data/app/assets/javascripts/fae/form/_form.js +5 -2
- data/app/assets/javascripts/fae/form/_form_manager.js +295 -0
- data/app/assets/javascripts/fae/form/_slugger.js.erb +2 -2
- data/app/assets/javascripts/fae/form/_validator.js +224 -55
- data/app/assets/javascripts/fae/form/drag_drop.js +109 -0
- data/app/assets/javascripts/fae/form/inputs/_select.js +10 -4
- data/app/assets/javascripts/fae/form/inputs/_text.js +23 -9
- data/app/assets/javascripts/fae/vendor/simplemde/codemirror-4.inline-attachment.js +95 -0
- data/app/assets/javascripts/fae/vendor/simplemde/inline-attachment.js +405 -0
- data/app/assets/stylesheets/fae/application.css +1 -0
- data/app/assets/stylesheets/fae/base.scss +7 -3
- data/app/assets/stylesheets/fae/globals/_tags.scss +1 -1
- data/app/assets/stylesheets/fae/globals/imports/_variables.scss +1 -0
- data/app/assets/stylesheets/fae/globals/layout/_base.scss +9 -4
- data/app/assets/stylesheets/fae/globals/layout/_content-header.scss +14 -4
- data/app/assets/stylesheets/fae/globals/legacy/_pre-1.3.scss +1 -1
- data/app/assets/stylesheets/fae/globals/navigation/_footer.scss +1 -1
- data/app/assets/stylesheets/fae/globals/navigation/_header.scss +3 -3
- data/app/assets/stylesheets/fae/globals/navigation/_multi-col-subnav.scss +50 -0
- data/app/assets/stylesheets/fae/globals/navigation/_sidenav.scss +2 -2
- data/app/assets/stylesheets/fae/globals/navigation/_utility.scss +1 -1
- data/app/assets/stylesheets/fae/modules/_buttons.scss +11 -0
- data/app/assets/stylesheets/fae/modules/_deploy.scss +25 -0
- data/app/assets/stylesheets/fae/modules/_errors-bar.scss +19 -0
- data/app/assets/stylesheets/fae/modules/_modal.scss +25 -0
- data/app/assets/stylesheets/fae/modules/_toggles.scss +39 -23
- data/app/assets/stylesheets/fae/modules/forms/_asset-actions.scss +1 -1
- data/app/assets/stylesheets/fae/modules/forms/_base.scss +14 -1
- data/app/assets/stylesheets/fae/modules/forms/_checkbox.scss +1 -1
- data/app/assets/stylesheets/fae/modules/forms/_date.scss +20 -4
- data/app/assets/stylesheets/fae/modules/forms/_form-manager.scss +82 -0
- data/app/assets/stylesheets/fae/modules/forms/_hints.scss +1 -1
- data/app/assets/stylesheets/fae/modules/forms/_label.scss +1 -1
- data/app/assets/stylesheets/fae/modules/forms/_radio.scss +1 -1
- data/app/assets/stylesheets/fae/modules/forms/_select.scss +9 -8
- data/app/assets/stylesheets/fae/modules/forms/_simple-mde.scss +72 -1
- data/app/assets/stylesheets/fae/modules/forms/_textarea.scss +1 -1
- data/app/assets/stylesheets/fae/modules/tables/_base.scss +1 -1
- data/app/assets/stylesheets/fae/modules/tables/_filters.scss +4 -0
- data/app/assets/stylesheets/fae/modules/tables/_pagination.scss +2 -2
- data/app/assets/stylesheets/fae/pages/_error.scss +1 -1
- data/app/assets/stylesheets/fae/pages/_login.scss +5 -1
- data/app/assets/stylesheets/fae/simplemde_override.scss +32 -0
- data/app/controllers/fae/application_controller.rb +9 -2
- data/app/controllers/fae/base_controller.rb +6 -2
- data/app/controllers/fae/deploy_controller.rb +24 -0
- data/app/controllers/fae/deploy_hooks_controller.rb +71 -0
- data/app/controllers/fae/form_managers_controller.rb +19 -0
- data/app/controllers/fae/options_controller.rb +1 -0
- data/app/controllers/fae/setup_controller.rb +2 -2
- data/app/controllers/fae/static_pages_controller.rb +6 -1
- data/app/controllers/fae/users_controller.rb +11 -1
- data/app/controllers/fae/utilities_controller.rb +18 -6
- data/app/helpers/fae/application_helper.rb +36 -2
- data/app/helpers/fae/form_helper.rb +26 -2
- data/app/helpers/fae/view_helper.rb +26 -9
- data/app/models/concerns/fae/base_model_concern.rb +17 -0
- data/app/models/concerns/fae/seo_set_concern.rb +1 -0
- data/app/models/fae/change.rb +20 -6
- data/app/models/fae/deploy_hook.rb +12 -0
- data/app/models/fae/form_manager.rb +24 -0
- data/app/models/fae/option.rb +1 -0
- data/app/models/fae/seo_set.rb +14 -0
- data/app/models/fae/user.rb +2 -2
- data/app/services/fae/netlify_api.rb +213 -0
- data/app/uploaders/fae/file_uploader.rb +1 -1
- data/app/uploaders/fae/image_uploader.rb +2 -2
- data/app/views/devise/unlocks/new.html.slim +5 -9
- data/app/views/fae/application/_content_form.html.slim +16 -11
- data/app/views/fae/application/_file_uploader.html.slim +7 -2
- data/app/views/fae/application/_global_search_results.html.slim +1 -1
- data/app/views/fae/application/_header.slim +4 -1
- data/app/views/fae/application/_mobilenav.slim +3 -0
- data/app/views/fae/application/_seo_set_form.html.slim +12 -0
- data/app/views/fae/deploy/index.html.slim +40 -0
- data/app/views/fae/deploy_hooks/_form.html.slim +18 -0
- data/app/views/fae/deploy_hooks/_table.html.slim +28 -0
- data/app/views/fae/deploy_hooks/edit.html.slim +3 -0
- data/app/views/fae/deploy_hooks/new.html.slim +3 -0
- data/app/views/fae/images/_image_uploader.html.slim +12 -3
- data/app/views/fae/options/_form.html.slim +6 -2
- data/app/views/fae/pages/activity_log.html.slim +7 -3
- data/app/views/fae/pages/home.html.slim +3 -4
- data/app/views/fae/shared/_errors.slim +0 -3
- data/app/views/fae/shared/_form_header.html.slim +20 -12
- data/app/views/fae/shared/_nested_table.html.slim +5 -2
- data/app/views/fae/shared/_recent_changes.html.slim +1 -1
- data/app/views/fae/shared/_shared_nested_table.html.slim +9 -3
- data/app/views/layouts/fae/application.html.slim +2 -1
- data/config/deploy.rb +3 -1
- data/config/initializers/carrierwave.rb +41 -2
- data/config/initializers/devise.rb +6 -6
- data/config/initializers/fae_judge.rb +4 -2
- data/config/locales/fae.en.yml +49 -4
- data/config/locales/fae.zh-CN.yml +2 -2
- data/config/puma.rb +82 -0
- data/config/routes.rb +9 -1
- data/db/migrate/20140809222030_add_user_table.rb +1 -1
- data/db/migrate/20190925153222_create_fae_form_managers.rb +11 -0
- data/db/migrate/20220118192729_create_fae_publish_hooks.rb +10 -0
- data/db/migrate/20220128133730_rename_publish_hooks.rb +5 -0
- data/db/migrate/20220202153607_add_position_to_deploy_hooks.rb +6 -0
- data/db/migrate/20221118161833_create_fae_seo_sets.rb +13 -0
- data/lib/fae/concerns/models/base.rb +2 -0
- data/lib/fae/engine.rb +3 -3
- data/lib/fae/options.rb +18 -18
- data/lib/fae/version.rb +1 -1
- data/lib/generators/fae/base_generator.rb +28 -5
- data/lib/generators/fae/controller_generator.rb +0 -1
- data/lib/generators/fae/install_generator.rb +1 -1
- data/lib/generators/fae/model_generator.rb +1 -2
- data/lib/generators/fae/nested_index_scaffold_generator.rb +1 -2
- data/lib/generators/fae/nested_scaffold_generator.rb +23 -2
- data/lib/generators/fae/page_generator.rb +1 -2
- data/lib/generators/fae/scaffold_generator.rb +1 -1
- data/lib/generators/fae/templates/assets/fae.js +1 -1
- data/lib/generators/fae/templates/controllers/nested_scaffold_controller.rb +13 -1
- data/lib/generators/fae/templates/controllers/scaffold_controller.rb +7 -0
- data/lib/generators/fae/templates/initializers/fae.rb +16 -1
- data/lib/generators/fae/templates/views/_form.html.slim +12 -1
- data/lib/generators/fae/templates/views/_form_index_nested.html.slim +15 -1
- data/lib/generators/fae/templates/views/_form_nested.html.slim +22 -2
- data/lib/generators/fae/templates/views/static_page_form.html.slim +13 -1
- metadata +53 -24
- data/config/deploy/dev.rb +0 -19
- data/config/deploy/prod.rb +0 -19
- data/config/deploy/stage.rb +0 -19
- /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
|
-
|
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'
|
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);
|
@@ -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
|
@@ -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:
|
31
|
-
background:
|
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
|
-
|
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
|
+
}
|