comfortable_mexican_sofa 2.0.12 → 2.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +5 -2
  4. data/Gemfile +5 -0
  5. data/Rakefile +2 -0
  6. data/app/assets/javascripts/comfy/admin/cms/application.js +40 -0
  7. data/app/assets/javascripts/comfy/admin/cms/base.js +46 -0
  8. data/app/assets/javascripts/comfy/admin/cms/categories.js +17 -0
  9. data/app/assets/javascripts/comfy/admin/cms/codemirror.js +31 -0
  10. data/app/assets/javascripts/comfy/admin/cms/custom.js +1 -0
  11. data/app/assets/javascripts/comfy/admin/cms/diff.js +10 -0
  12. data/app/assets/javascripts/comfy/admin/cms/file_link.js +67 -0
  13. data/app/assets/javascripts/comfy/admin/cms/file_upload.js +194 -0
  14. data/app/assets/javascripts/comfy/admin/cms/files_modal.js +40 -0
  15. data/app/assets/javascripts/comfy/admin/cms/page_fragments.js +22 -0
  16. data/app/assets/javascripts/comfy/admin/cms/slugify.js +34 -0
  17. data/app/assets/javascripts/comfy/admin/cms/sortable_list.js +40 -0
  18. data/app/assets/javascripts/comfy/admin/cms/timepicker.js +30 -0
  19. data/app/assets/javascripts/comfy/admin/cms/wysiwyg.js +65 -0
  20. data/app/assets/javascripts/comfy/vendor/redactor.js +12 -6
  21. data/app/assets/stylesheets/comfy/admin/cms/base.sass +32 -35
  22. data/app/controllers/application_controller.rb +2 -0
  23. data/app/controllers/comfy/admin/base_controller.rb +3 -1
  24. data/app/controllers/comfy/admin/cms/base_controller.rb +9 -1
  25. data/app/controllers/comfy/admin/cms/categories_controller.rb +2 -0
  26. data/app/controllers/comfy/admin/cms/files_controller.rb +3 -1
  27. data/app/controllers/comfy/admin/cms/layouts_controller.rb +2 -0
  28. data/app/controllers/comfy/admin/cms/pages_controller.rb +4 -1
  29. data/app/controllers/comfy/admin/cms/revisions/base_controller.rb +2 -0
  30. data/app/controllers/comfy/admin/cms/revisions/layout_controller.rb +2 -0
  31. data/app/controllers/comfy/admin/cms/revisions/page_controller.rb +2 -0
  32. data/app/controllers/comfy/admin/cms/revisions/snippet_controller.rb +2 -0
  33. data/app/controllers/comfy/admin/cms/revisions/translation_controller.rb +2 -0
  34. data/app/controllers/comfy/admin/cms/sites_controller.rb +2 -0
  35. data/app/controllers/comfy/admin/cms/snippets_controller.rb +2 -0
  36. data/app/controllers/comfy/admin/cms/translations_controller.rb +8 -0
  37. data/app/controllers/comfy/cms/assets_controller.rb +2 -0
  38. data/app/controllers/comfy/cms/base_controller.rb +4 -2
  39. data/app/controllers/comfy/cms/content_controller.rb +3 -1
  40. data/app/controllers/concerns/comfy/paginate.rb +2 -0
  41. data/app/controllers/concerns/comfy/reorder_action.rb +2 -0
  42. data/app/helpers/comfy/admin/cms_helper.rb +19 -0
  43. data/app/helpers/comfy/cms_helper.rb +4 -2
  44. data/app/models/comfy/cms/categorization.rb +2 -0
  45. data/app/models/comfy/cms/category.rb +2 -0
  46. data/app/models/comfy/cms/file.rb +2 -0
  47. data/app/models/comfy/cms/fragment.rb +3 -1
  48. data/app/models/comfy/cms/layout.rb +3 -1
  49. data/app/models/comfy/cms/page.rb +3 -1
  50. data/app/models/comfy/cms/revision.rb +2 -0
  51. data/app/models/comfy/cms/site.rb +5 -1
  52. data/app/models/comfy/cms/snippet.rb +2 -0
  53. data/app/models/comfy/cms/translation.rb +2 -0
  54. data/app/models/concerns/comfy/cms/with_categories.rb +2 -0
  55. data/app/models/concerns/comfy/cms/with_fragments.rb +2 -0
  56. data/app/views/comfy/admin/cms/categories/_index.html.haml +3 -3
  57. data/app/views/comfy/admin/cms/categories/create.js.erb +1 -1
  58. data/app/views/comfy/admin/cms/categories/destroy.js.erb +8 -3
  59. data/app/views/comfy/admin/cms/files/_file.html.haml +9 -10
  60. data/app/views/comfy/admin/cms/files/_modal.html.haml +1 -2
  61. data/app/views/comfy/admin/cms/files/destroy.js.erb +4 -0
  62. data/app/views/comfy/admin/cms/files/index.html.haml +10 -10
  63. data/app/views/comfy/admin/cms/fragments/_form_fragment_attachments.html.haml +15 -6
  64. data/app/views/comfy/admin/cms/fragments/_form_fragments.html.haml +17 -21
  65. data/app/views/comfy/admin/cms/pages/_form.html.haml +3 -2
  66. data/app/views/comfy/admin/cms/pages/toggle_branch.js.erb +3 -1
  67. data/app/views/comfy/admin/cms/translations/_form.html.haml +3 -2
  68. data/app/views/layouts/comfy/admin/cms.html.haml +0 -1
  69. data/app/views/layouts/comfy/admin/cms/_body.html.haml +1 -0
  70. data/app/views/layouts/comfy/admin/cms/_left.html.haml +1 -1
  71. data/comfortable_mexican_sofa.gemspec +3 -2
  72. data/config.ru +2 -0
  73. data/config/application.rb +2 -0
  74. data/config/boot.rb +2 -0
  75. data/config/cms_routes.rb +2 -0
  76. data/config/environment.rb +2 -0
  77. data/config/environments/development.rb +2 -0
  78. data/config/environments/test.rb +2 -0
  79. data/config/initializers/comfortable_mexican_sofa.rb +2 -0
  80. data/lib/comfortable_mexican_sofa.rb +2 -0
  81. data/lib/comfortable_mexican_sofa/access_control/admin_authentication.rb +2 -0
  82. data/lib/comfortable_mexican_sofa/access_control/admin_authorization.rb +2 -0
  83. data/lib/comfortable_mexican_sofa/access_control/public_authentication.rb +2 -0
  84. data/lib/comfortable_mexican_sofa/access_control/public_authorization.rb +2 -0
  85. data/lib/comfortable_mexican_sofa/configuration.rb +3 -0
  86. data/lib/comfortable_mexican_sofa/content.rb +3 -0
  87. data/lib/comfortable_mexican_sofa/content/block.rb +2 -0
  88. data/lib/comfortable_mexican_sofa/content/params_parser.rb +59 -41
  89. data/lib/comfortable_mexican_sofa/content/renderer.rb +18 -4
  90. data/lib/comfortable_mexican_sofa/content/tag.rb +20 -5
  91. data/lib/comfortable_mexican_sofa/content/tags/asset.rb +2 -0
  92. data/lib/comfortable_mexican_sofa/content/tags/checkbox.rb +10 -3
  93. data/lib/comfortable_mexican_sofa/content/tags/date.rb +3 -1
  94. data/lib/comfortable_mexican_sofa/content/tags/datetime.rb +3 -1
  95. data/lib/comfortable_mexican_sofa/content/tags/file.rb +21 -27
  96. data/lib/comfortable_mexican_sofa/content/tags/file_link.rb +23 -24
  97. data/lib/comfortable_mexican_sofa/content/tags/files.rb +11 -9
  98. data/lib/comfortable_mexican_sofa/content/tags/fragment.rb +11 -1
  99. data/lib/comfortable_mexican_sofa/content/tags/helper.rb +3 -1
  100. data/lib/comfortable_mexican_sofa/content/tags/markdown.rb +3 -1
  101. data/lib/comfortable_mexican_sofa/content/tags/mixins/file_content.rb +38 -0
  102. data/lib/comfortable_mexican_sofa/content/tags/number.rb +3 -1
  103. data/lib/comfortable_mexican_sofa/content/tags/page_file_link.rb +82 -0
  104. data/lib/comfortable_mexican_sofa/content/tags/partial.rb +3 -1
  105. data/lib/comfortable_mexican_sofa/content/tags/snippet.rb +2 -0
  106. data/lib/comfortable_mexican_sofa/content/tags/template.rb +3 -1
  107. data/lib/comfortable_mexican_sofa/content/tags/text.rb +3 -1
  108. data/lib/comfortable_mexican_sofa/content/tags/textarea.rb +3 -1
  109. data/lib/comfortable_mexican_sofa/content/tags/wysiwyg.rb +3 -1
  110. data/lib/comfortable_mexican_sofa/engine.rb +2 -1
  111. data/lib/comfortable_mexican_sofa/error.rb +2 -0
  112. data/lib/comfortable_mexican_sofa/extensions/acts_as_tree.rb +2 -0
  113. data/lib/comfortable_mexican_sofa/extensions/has_revisions.rb +2 -0
  114. data/lib/comfortable_mexican_sofa/form_builder.rb +24 -17
  115. data/lib/comfortable_mexican_sofa/render_methods.rb +2 -0
  116. data/lib/comfortable_mexican_sofa/routes/cms.rb +2 -0
  117. data/lib/comfortable_mexican_sofa/routes/cms_admin.rb +2 -0
  118. data/lib/comfortable_mexican_sofa/routing.rb +2 -0
  119. data/lib/comfortable_mexican_sofa/seeds.rb +3 -1
  120. data/lib/comfortable_mexican_sofa/seeds/file/exporter.rb +2 -0
  121. data/lib/comfortable_mexican_sofa/seeds/file/importer.rb +2 -0
  122. data/lib/comfortable_mexican_sofa/seeds/layout/exporter.rb +2 -0
  123. data/lib/comfortable_mexican_sofa/seeds/layout/importer.rb +2 -0
  124. data/lib/comfortable_mexican_sofa/seeds/page/exporter.rb +2 -0
  125. data/lib/comfortable_mexican_sofa/seeds/page/importer.rb +2 -0
  126. data/lib/comfortable_mexican_sofa/seeds/snippet/exporter.rb +2 -0
  127. data/lib/comfortable_mexican_sofa/seeds/snippet/importer.rb +2 -0
  128. data/lib/comfortable_mexican_sofa/version.rb +3 -1
  129. data/lib/comfortable_mexican_sofa/view_hooks.rb +2 -0
  130. data/lib/generators/comfy/cms/assets_generator.rb +2 -0
  131. data/lib/generators/comfy/cms/cms_generator.rb +6 -4
  132. data/lib/generators/comfy/cms/controllers_generator.rb +2 -0
  133. data/lib/generators/comfy/cms/models_generator.rb +2 -0
  134. data/lib/generators/comfy/cms/views_generator.rb +2 -0
  135. data/lib/generators/comfy/scaffold/scaffold_generator.rb +6 -2
  136. data/lib/tasks/cms_seeds.rake +2 -0
  137. metadata +20 -26
  138. data/app/assets/javascripts/comfy/admin/cms/application.js.coffee +0 -30
  139. data/app/assets/javascripts/comfy/admin/cms/base.js.coffee +0 -224
  140. data/app/assets/javascripts/comfy/admin/cms/custom.js.coffee +0 -1
  141. data/app/assets/javascripts/comfy/admin/cms/files.js.coffee +0 -29
  142. data/app/assets/javascripts/comfy/admin/cms/uploader.js.coffee +0 -140
  143. data/app/views/comfy/admin/cms/files/create.js.erb +0 -1
  144. data/app/views/comfy/admin/cms/files/destroy.js.coffee +0 -2
  145. data/app/views/comfy/admin/cms/pages/form_fragments.js.erb +0 -1
  146. data/app/views/comfy/admin/cms/translations/form_fragments.js.erb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab2c176d43e3783a684bd7245eb28f889af9ad8d1bd38665e4847e0fdefdbf08
4
- data.tar.gz: d214102f49f6965873628fac4e9aec36a486c537d6548d6f0e76a5ffe027e208
3
+ metadata.gz: b4189f8584e5fbfcc3083d72b892dee0d17407e1893674eed30927e6e5c6d336
4
+ data.tar.gz: '02964679fbddf7a9f1c46dc35482d11a6a3736409a32daa4a137d0600a921d3d'
5
5
  SHA512:
6
- metadata.gz: 301bd06b86f9d7e6080edeed4aa0c39add0e83a8ffdebc799ef03507fedd09dbf2ac4d28adb46a45656991e68b361f5f300e54dba24d06a5996f6f63a6cbe4cb
7
- data.tar.gz: 6768a98127dfde9834afd18e5085644db61d76e4e6629ddef4a50a480d588ada9c79cb56bf9958dc11f2693289737d3f227eadf2a266ec3a3dcb727aadd1ce41
6
+ metadata.gz: 47387e45ccebcad1bc3429c6b64633dfd9cc8f0810f7c28745dc578f391404e57a16fb8bd1ecd221acdd6701710aded9ee318eb2b110f7d7374e63063fc472b0
7
+ data.tar.gz: d16d2d2aaeb92e761c6b3559816f33e1339dd239f8691d6b8194bc5cf60d67ec0dbe34aae18ee2cc2a4f1bf24b15edc4105812bcd4427d04b048a850bc339819
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.2
2
+ TargetRubyVersion: 2.3
3
3
  Exclude:
4
4
  - bin/*
5
5
  - db/schema.rb
@@ -1,9 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.9
4
3
  - 2.3.6
5
4
  - 2.4.3
6
5
  - 2.5.0
6
+ - ruby-head
7
7
  gemfile:
8
8
  - test/gemfiles/5.2.gemfile
9
9
  branches:
@@ -19,7 +19,7 @@ before_install:
19
19
  - gem update --system
20
20
  - gem update bundler
21
21
  before_script:
22
- - wget http://chromedriver.storage.googleapis.com/2.34/chromedriver_linux64.zip
22
+ - wget http://chromedriver.storage.googleapis.com/2.36/chromedriver_linux64.zip
23
23
  - unzip chromedriver_linux64.zip
24
24
  - sudo apt-get install libnss3
25
25
  - sudo apt-get --only-upgrade install google-chrome-stable
@@ -33,3 +33,6 @@ script:
33
33
  - bundle exec rake test
34
34
  - SKIP_COV=true bundle exec rake test:system
35
35
  - bundle exec rubocop
36
+ matrix:
37
+ allow_failures:
38
+ - rvm: ruby-head
data/Gemfile CHANGED
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "http://rubygems.org"
2
4
 
3
5
  gemspec
4
6
 
5
7
  group :development, :test do
8
+ gem "autoprefixer-rails", "~> 8.1.0"
6
9
  gem "byebug", "~> 10.0.0", platforms: %i[mri mingw x64_mingw]
7
10
  gem "capybara", "~> 2.17.0"
8
11
  gem "kaminari", "~> 1.1.1"
@@ -19,6 +22,8 @@ end
19
22
 
20
23
  group :test do
21
24
  gem "coveralls", "~> 0.8.21", require: false
25
+ gem "diffy", "~> 3.2.0"
26
+ gem "equivalent-xml", "~> 0.6.0"
22
27
  gem "mocha", "~> 1.3.0", require: false
23
28
  gem "rails-controller-testing", "~> 1.0.2"
24
29
  end
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "config/application"
2
4
 
3
5
  Rails.application.load_tasks
@@ -0,0 +1,40 @@
1
+ //= require rails-ujs
2
+ //= require jquery3
3
+
4
+ //= require comfy/vendor/codemirror
5
+ //= require comfy/vendor/codemirror/mode/css/css
6
+ //= require comfy/vendor/codemirror/mode/htmlmixed/htmlmixed
7
+ //= require comfy/vendor/codemirror/mode/javascript/javascript
8
+ //= require comfy/vendor/codemirror/mode/markdown/markdown
9
+ //= require comfy/vendor/codemirror/mode/xml/xml
10
+ //= require comfy/vendor/codemirror/addon/edit/closetag
11
+ //= require comfy/vendor/sortable.min
12
+ //= require comfy/vendor/popper.min
13
+ //= require comfy/vendor/bootstrap.min
14
+ //= require comfy/vendor/diff/diff_match_patch.min
15
+ //= require comfy/vendor/diff/pretty_text_diff
16
+ //= require comfy/vendor/fontawesome
17
+ //= require comfy/vendor/redactor
18
+ //= require comfy/vendor/redactor/filemanager
19
+ //= require comfy/vendor/redactor/imagemanager
20
+ //= require comfy/vendor/redactor/definedlinks
21
+ //= require comfy/vendor/redactor/table
22
+ //= require comfy/vendor/redactor/video
23
+ //= require_directory ../../vendor/redactor/i18n/
24
+ //= require comfy/vendor/flatpickr.min
25
+ //= require_directory ../../vendor/flatpickr/i18n/
26
+
27
+ //= require comfy/admin/cms/base
28
+ //= require comfy/admin/cms/categories
29
+ //= require comfy/admin/cms/codemirror
30
+ //= require comfy/admin/cms/diff
31
+ //= require comfy/admin/cms/file_link
32
+ //= require comfy/admin/cms/file_upload
33
+ //= require comfy/admin/cms/files_modal
34
+ //= require comfy/admin/cms/page_fragments
35
+ //= require comfy/admin/cms/sortable_list
36
+ //= require comfy/admin/cms/slugify
37
+ //= require comfy/admin/cms/timepicker
38
+ //= require comfy/admin/cms/wysiwyg
39
+
40
+ //= require comfy/admin/cms/custom
@@ -0,0 +1,46 @@
1
+ (() => {
2
+ if (!window.CMS) window.CMS = {};
3
+ const CMS = window.CMS;
4
+
5
+ // TODO(glebm): Use the battle-tested universal onPageLoad code and enable Turbolinks+async in the demo app.
6
+ // See: https://gist.github.com/glebm/2496daf445877055447a6fac46509d9a
7
+ const isTurbolinks = 'Turbolinks' in window && window.Turbolinks.supported;
8
+ if (isTurbolinks) {
9
+ document.addEventListener('turbolinks:load', () => {
10
+ window.CMS.init();
11
+ });
12
+ document.addEventListener('turbolinks:before-cache', () => {
13
+ window.CMS.dispose();
14
+ });
15
+ } else {
16
+ document.addEventListener('DOMContentLoaded', () => {
17
+ window.CMS.init();
18
+ });
19
+ }
20
+
21
+ CMS.init = () => {
22
+ CMS.current_path = window.location.pathname;
23
+ CMS.slugify();
24
+ CMS.codemirror.init();
25
+ CMS.wysiwyg.init();
26
+ CMS.sortableList.init();
27
+ CMS.timepicker.init();
28
+ CMS.pageFragments();
29
+ CMS.categories();
30
+ CMS.files.init();
31
+ CMS.fileLinks();
32
+ CMS.fileUpload.init();
33
+ CMS.diff();
34
+ };
35
+
36
+ CMS.dispose = () => {
37
+ CMS.codemirror.dispose();
38
+ CMS.wysiwyg.dispose();
39
+ CMS.files.dispose();
40
+ CMS.fileUpload.dispose();
41
+ CMS.sortableList.dispose();
42
+ CMS.timepicker.dispose();
43
+ };
44
+
45
+ CMS.getLocale = () => document.querySelector('meta[name="cms-locale"]').content;
46
+ })();
@@ -0,0 +1,17 @@
1
+ (() => {
2
+ window.CMS.categories = (root = document) => {
3
+ const widget = root.querySelector('.categories-widget');
4
+ if (widget === null) return;
5
+ const readSection = widget.querySelector('.read');
6
+ const editSection = widget.querySelector('.editable');
7
+ widget.querySelector('.read button.toggle-cat-edit').addEventListener('click', () => {
8
+ readSection.style.display = 'none';
9
+ editSection.style.display = 'block';
10
+ });
11
+ widget.querySelector('.editable button.toggle-cat-edit').addEventListener('click', () => {
12
+ editSection.style.display = 'none';
13
+ readSection.style.display = 'block';
14
+ });
15
+ };
16
+ })();
17
+
@@ -0,0 +1,31 @@
1
+ (() => {
2
+ const codeMirrorInstances = [];
3
+ window.CMS.codemirror = {
4
+ init(root = document) {
5
+ for (const textarea of root.querySelectorAll('textarea[data-cms-cm-mode]')) {
6
+ const codemirror = CodeMirror.fromTextArea(textarea, {
7
+ mode: textarea.dataset.cmsCmMode,
8
+ tabSize: 2,
9
+ lineWrapping: true,
10
+ autoCloseTags: true,
11
+ lineNumbers: true,
12
+ viewportMargin: Infinity
13
+ });
14
+ codeMirrorInstances.push(codemirror);
15
+ }
16
+
17
+ const tabsRoot = root.id === 'form-fragments' ? root : root.querySelector('#form-fragments');
18
+ jQuery(tabsRoot).find('a[data-toggle="tab"]').on('shown.bs.tab', () => {
19
+ for (const codemirror of codeMirrorInstances) {
20
+ codemirror.refresh();
21
+ }
22
+ });
23
+ },
24
+ dispose() {
25
+ for (const codemirror of codeMirrorInstances) {
26
+ codemirror.toTextArea();
27
+ }
28
+ codeMirrorInstances.length = 0;
29
+ }
30
+ }
31
+ })();
@@ -0,0 +1 @@
1
+ // Custom JS for the admin area
@@ -0,0 +1,10 @@
1
+ (() => {
2
+ window.CMS.diff = () => {
3
+ jQuery('.revision').prettyTextDiff({
4
+ cleanup: true,
5
+ originalContainer: '.original',
6
+ changedContainer: '.current',
7
+ diffContainer: '.diff .content',
8
+ });
9
+ }
10
+ })();
@@ -0,0 +1,67 @@
1
+ (() => {
2
+ const isFirefox = /\bFirefox\//.test(navigator.userAgent);
3
+
4
+ class FileLink {
5
+ constructor(link) {
6
+ this.link = link;
7
+ this.isImage = !!link.dataset.cmsFileThumbUrl;
8
+
9
+ link.addEventListener('dragstart', (evt) => {
10
+ evt.dataTransfer.setData('text/plain', this.link.dataset.cmsFileLinkTag);
11
+ });
12
+
13
+ if (this.isImage) {
14
+ new bootstrap.Popover(link, {
15
+ container: link.parentElement,
16
+ trigger: 'hover',
17
+ placement: 'top',
18
+ content: this.buildFileThumbnail(),
19
+ html: true
20
+ });
21
+
22
+ link.addEventListener('dragstart', (evt) => {
23
+ evt.dataTransfer.setDragImage(this.buildFileThumbnail(), 4, 2);
24
+ this.getPopover().hide();
25
+ });
26
+
27
+ this.workAroundFirefoxPopoverGlitch();
28
+ }
29
+ }
30
+
31
+ buildFileThumbnail() {
32
+ const img = new Image();
33
+ img.src = this.link.dataset.cmsFileThumbUrl;
34
+ return img;
35
+ }
36
+
37
+ // To work around a Firefox bug causing the popover to re-appear after the drop:
38
+ // https://github.com/comfy/comfortable-mexican-sofa/pull/799#issuecomment-369124161
39
+ //
40
+ // Possibly related to:
41
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=505521
42
+ workAroundFirefoxPopoverGlitch() {
43
+ if (!isFirefox) return;
44
+ this.link.addEventListener('dragstart', () => {
45
+ this.getPopover().disable();
46
+ });
47
+ this.link.addEventListener('dragend', () => {
48
+ setTimeout(() => {
49
+ const popover = this.getPopover();
50
+ popover.enable();
51
+ popover.hide();
52
+ }, 300);
53
+ });
54
+ }
55
+
56
+ // We can't keep a reference to the Popover object, because Bootstrap re-creates it internally.
57
+ getPopover() {
58
+ return jQuery(this.link).data(bootstrap.Popover.DATA_KEY);
59
+ }
60
+ }
61
+
62
+ window.CMS.fileLinks = (root = document) => {
63
+ for (const link of root.querySelectorAll('[data-cms-file-link-tag]')) {
64
+ new FileLink(link);
65
+ }
66
+ };
67
+ })();
@@ -0,0 +1,194 @@
1
+ //= require comfy/vendor/moxie.min
2
+ //= require comfy/vendor/plupload.dev
3
+
4
+ (() => {
5
+ const DROP_TARGET_ACTIVE_CLASS = 'cms-uploader-drag-drop-target-active';
6
+
7
+ class FileUpload {
8
+ constructor(container, settings) {
9
+ if (!container.id) container.id = plupload.guid();
10
+ settings = Object.assign(FileUpload.defaultUploaderSettings(container.id), settings);
11
+ this.ui = {
12
+ container,
13
+ list: container.querySelector('.cms-uploader-filelist'),
14
+ dropElement: container.querySelector(`#${settings.drop_element}`),
15
+ };
16
+ this.cleanupFns = [];
17
+ this.uploader = new plupload.Uploader(settings);
18
+ this.uploader.bind('PostInit', () => this.onUploaderPostInit());
19
+ this.uploader.bind('Error', (_uploader, error) => this.onUploaderError(error));
20
+ this.uploader.bind('FilesAdded', (_uploader, files) => this.onUploaderFilesAdded(files));
21
+ this.uploader.bind('UploadProgress', (_uploader, file) => this.onUploaderUploadProgress(file));
22
+ this.uploader.bind('FileUploaded', (_uploader, file, info) => this.onUploaderFileUploaded(file, info));
23
+ this.uploader.bind('FilesRemoved', (_uploader, files) => this.onUploaderFilesRemoved(files));
24
+ this.uploader.init();
25
+ if (settings.setup) {
26
+ settings.setup(this.uploader);
27
+ }
28
+ }
29
+
30
+ destroy() {
31
+ this.uploader.destroy();
32
+ for (const cleanupFn of this.cleanupFns) {
33
+ cleanupFn();
34
+ }
35
+ }
36
+
37
+ addCleanup(cleanupFn) {
38
+ this.cleanupFns.push(cleanupFn);
39
+ }
40
+
41
+ onUploaderPostInit() {
42
+ // Show drag and drop info and attach events only if drag and drop is enabled and supported.
43
+ if (!this.uploader.settings.dragdrop || !this.uploader.features.dragdrop) {
44
+ this.ui.container.querySelector('.cms-uploader-drag-drop-info').style.display = 'none';
45
+ return;
46
+ }
47
+ // When dragging over the document add a class to the drop target that puts it on top of every element and remove
48
+ // that class when dropping or leaving the drop target. Otherwise the dragleave event would fire whenever we drag
49
+ // over a child element inside the drop target such as text nodes.
50
+ const onDragEnter = (e) => {
51
+ // Only react to drag'n'drops that contain a file. See:
52
+ // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types
53
+ if (e.dataTransfer.types.includes('Files')) {
54
+ this.ui.dropElement.classList.add(DROP_TARGET_ACTIVE_CLASS);
55
+ }
56
+ };
57
+ document.addEventListener('dragenter', onDragEnter);
58
+ this.addCleanup(() => {
59
+ document.removeEventListener('dragenter', onDragEnter);
60
+ });
61
+ for (const eventName of ['drop', 'dragleave']) {
62
+ this.ui.dropElement.addEventListener(eventName, () => {
63
+ this.ui.dropElement.classList.remove(DROP_TARGET_ACTIVE_CLASS);
64
+ });
65
+ }
66
+ }
67
+
68
+ onUploaderError(error) {
69
+ if (error.code === plupload.INIT_ERROR) {
70
+ window.alert('Error: Initialisation error. Reload to try again.');
71
+ return;
72
+ }
73
+ const file = error.file;
74
+ if (!file) return;
75
+ // Get error message from the server response. Not all runtimes support this.
76
+ let message = error.response;
77
+ // If no error message is in the server response get standard plupload error messages.
78
+ // This will have descriptive error message for something like file size or file format errors but for
79
+ // server errors it will only display a general error message.
80
+ if (!message) {
81
+ message = error.message;
82
+ if (error.details) message += ` (${error.details})`;
83
+ }
84
+ file.status = plupload.FAILED;
85
+ file.error_message = message;
86
+ this.updateFileStatus(file);
87
+ }
88
+
89
+ onUploaderFilesAdded(files) {
90
+ for (const file of files) {
91
+ this.addFile(file);
92
+ }
93
+ // Auto start upload when files are added.
94
+ this.uploader.start();
95
+ }
96
+
97
+ onUploaderUploadProgress(file) {
98
+ this.updateFileStatus(file);
99
+ }
100
+
101
+ onUploaderFileUploaded(file, info) {
102
+ // Replace the dummy file entry in the file list with the the entry from the server response.
103
+ const template = document.createElement('template');
104
+ template.innerHTML = info.response;
105
+ const newListItem = template.content.firstElementChild;
106
+ this.ui.list.replaceChild(newListItem, this.fileListItem(file));
107
+ window.CMS.fileLinks(newListItem);
108
+ }
109
+
110
+ onUploaderFilesRemoved(files) {
111
+ for (const file of files) {
112
+ this.removeFile(file);
113
+ }
114
+ }
115
+
116
+ addFile(file) {
117
+ this.ui.list.insertAdjacentHTML('afterbegin', FileUpload.buildListItemHTML(file));
118
+ this.fileListItem(file).querySelector('.cms-uploader-file-delete').addEventListener('click', (evt) => {
119
+ evt.preventDefault();
120
+ this.uploader.removeFile(file);
121
+ });
122
+ this.updateFileStatus(file);
123
+ }
124
+
125
+ removeFile(file) {
126
+ this.fileListItem(file).remove();
127
+ }
128
+
129
+ updateFileStatus(file) {
130
+ const progressBar = this.fileListItem(file).querySelector('.progress-bar');
131
+ switch (file.status) {
132
+ case plupload.UPLOADING:
133
+ progressBar.style.width = `${file.percent}%`;
134
+ break;
135
+ case plupload.FAILED:
136
+ progressBar.style.width = '100%';
137
+ progressBar.classList.add('progress-bar-danger');
138
+ progressBar.querySelector('span').innerHTML = file.error_message;
139
+ break;
140
+ }
141
+ }
142
+
143
+ fileListItem({id}) {
144
+ return this.ui.container.querySelector(`#${id}`);
145
+ }
146
+
147
+ static buildListItemHTML({id, name}) {
148
+ return `<li id='${id}' class='row temp'>
149
+ <div class='col-md-9 d-flex align-items-center'>
150
+ <div class='progress'>
151
+ <div class='progress-bar progress-bar-striped progress-bar-animated'>
152
+ <span>${name}</span>
153
+ </div>
154
+ </div>
155
+ </div>
156
+ <div class='col-md-3 d-flex align-items-center justify-content-md-end'>
157
+ <a class='btn btn-sm btn-danger float-right cms-uploader-file-delete' href='#'>Delete</a>
158
+ </div>
159
+ </li>`;
160
+ }
161
+
162
+ static defaultUploaderSettings(id) {
163
+ return {
164
+ runtimes: 'html5,browserplus,silverlight,flash,gears',
165
+ dragdrop: true,
166
+ drop_element: `${id}-drag-drop-target`,
167
+ browse_button: `${id}-browse`,
168
+ container: id,
169
+ file_data_name: 'file[file]',
170
+ };
171
+ }
172
+ }
173
+
174
+ const uploaders = [];
175
+ window.CMS.fileUpload = {
176
+ init(root = document) {
177
+ const el = root.querySelector('#cms-uploader');
178
+ if (el === null) return;
179
+ uploaders.push(new FileUpload(el, {
180
+ url: el.dataset.cmsUploaderUrl,
181
+ multipart_params: {
182
+ [el.dataset.cmsUploaderTokenName]: el.dataset.cmsUploaderTokenValue,
183
+ [el.dataset.cmsUploaderSessionName]: el.dataset.cmsUploaderSessionValue
184
+ }
185
+ }));
186
+ },
187
+ dispose() {
188
+ for (const uploader of uploader) {
189
+ uploader.dispose();
190
+ }
191
+ uploaders.length = 0;
192
+ }
193
+ };
194
+ })();