diff options
| -rw-r--r-- | app/views/assets/edit.html.erb | 7 | ||||
| -rw-r--r-- | app/views/assets/new.html.erb | 7 | ||||
| -rw-r--r-- | public/javascripts/admin_interface.js | 38 | ||||
| -rw-r--r-- | public/stylesheets/admin.css | 11 |
4 files changed, 61 insertions, 2 deletions
diff --git a/app/views/assets/edit.html.erb b/app/views/assets/edit.html.erb index 0c1dd8fe..d0a39aa3 100644 --- a/app/views/assets/edit.html.erb +++ b/app/views/assets/edit.html.erb | |||
| @@ -14,7 +14,12 @@ | |||
| 14 | <% end %> | 14 | <% end %> |
| 15 | 15 | ||
| 16 | <div class="node_description"><%= f.label :upload, "Replace file" %></div> | 16 | <div class="node_description"><%= f.label :upload, "Replace file" %></div> |
| 17 | <div class="node_content"><%= f.file_field :upload %></div> | 17 | <div class="node_content"> |
| 18 | <div id="asset_dropzone"> | ||
| 19 | <%= f.file_field :upload %> | ||
| 20 | <p class="field_hint">…or drop a file here.</p> | ||
| 21 | </div> | ||
| 22 | </div> | ||
| 18 | 23 | ||
| 19 | <div class="node_description"><%= f.label :creator %></div> | 24 | <div class="node_description"><%= f.label :creator %></div> |
| 20 | <div class="node_content"><%= f.text_field :creator %></div> | 25 | <div class="node_content"><%= f.text_field :creator %></div> |
diff --git a/app/views/assets/new.html.erb b/app/views/assets/new.html.erb index 7bded949..8a7a6094 100644 --- a/app/views/assets/new.html.erb +++ b/app/views/assets/new.html.erb | |||
| @@ -9,7 +9,12 @@ | |||
| 9 | <div class="node_content"><%= f.text_field :name %></div> | 9 | <div class="node_content"><%= f.text_field :name %></div> |
| 10 | 10 | ||
| 11 | <div class="node_description"><%= f.label :upload, "File" %></div> | 11 | <div class="node_description"><%= f.label :upload, "File" %></div> |
| 12 | <div class="node_content"><%= f.file_field :upload %></div> | 12 | <div class="node_content"> |
| 13 | <div id="asset_dropzone"> | ||
| 14 | <%= f.file_field :upload %> | ||
| 15 | <p class="field_hint">…or drop a file here.</p> | ||
| 16 | </div> | ||
| 17 | </div> | ||
| 13 | 18 | ||
| 14 | <div class="node_description"><%= f.label :creator %></div> | 19 | <div class="node_description"><%= f.label :creator %></div> |
| 15 | <div class="node_content"><%= f.text_field :creator %></div> | 20 | <div class="node_content"><%= f.text_field :creator %></div> |
diff --git a/public/javascripts/admin_interface.js b/public/javascripts/admin_interface.js index 5514f3b3..284d2b72 100644 --- a/public/javascripts/admin_interface.js +++ b/public/javascripts/admin_interface.js | |||
| @@ -85,6 +85,44 @@ $(document).ready(function () { | |||
| 85 | desktop_mq.addEventListener('change', sync_metadata); | 85 | desktop_mq.addEventListener('change', sync_metadata); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | var dropzone = document.getElementById('asset_dropzone'); | ||
| 89 | if (dropzone) { | ||
| 90 | var input = dropzone.querySelector('input[type=file]'); | ||
| 91 | |||
| 92 | // Without these, a drop that misses the zone navigates the browser | ||
| 93 | // to the file, losing the half-filled form. | ||
| 94 | ['dragover', 'drop'].forEach(function(ev) { | ||
| 95 | window.addEventListener(ev, function(e) { e.preventDefault(); }); | ||
| 96 | }); | ||
| 97 | |||
| 98 | ['dragenter', 'dragover'].forEach(function(ev) { | ||
| 99 | dropzone.addEventListener(ev, function(e) { | ||
| 100 | e.preventDefault(); dropzone.classList.add('dragging'); | ||
| 101 | }); | ||
| 102 | }); | ||
| 103 | ['dragleave', 'drop'].forEach(function(ev) { | ||
| 104 | dropzone.addEventListener(ev, function(e) { | ||
| 105 | e.preventDefault(); dropzone.classList.remove('dragging'); | ||
| 106 | }); | ||
| 107 | }); | ||
| 108 | |||
| 109 | dropzone.addEventListener('drop', function(e) { | ||
| 110 | if (!e.dataTransfer.files.length) return; | ||
| 111 | var dt = new DataTransfer(); | ||
| 112 | dt.items.add(e.dataTransfer.files[0]); | ||
| 113 | input.files = dt.files; | ||
| 114 | input.dispatchEvent(new Event('change', { bubbles: true })); | ||
| 115 | }); | ||
| 116 | |||
| 117 | input.addEventListener('change', function() { | ||
| 118 | var name_field = document.getElementById('asset_name'); | ||
| 119 | if (input.files.length && name_field && name_field.value === '') { | ||
| 120 | name_field.value = input.files[0].name.replace(/\.[^.]+$/, ''); | ||
| 121 | } | ||
| 122 | }); | ||
| 123 | } | ||
| 124 | |||
| 125 | |||
| 88 | jQuery.ajaxSetup({ | 126 | jQuery.ajaxSetup({ |
| 89 | 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript");} | 127 | 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript");} |
| 90 | }); | 128 | }); |
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 9f737752..69f0fcf2 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css | |||
| @@ -1386,6 +1386,17 @@ div#draft_list table td.actions a { | |||
| 1386 | background-color: #fffdf5; | 1386 | background-color: #fffdf5; |
| 1387 | } | 1387 | } |
| 1388 | 1388 | ||
| 1389 | #asset_dropzone { | ||
| 1390 | border: 2px dashed #ccc; | ||
| 1391 | border-radius: 6px; | ||
| 1392 | padding: 1.5rem; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | #asset_dropzone.dragging { | ||
| 1396 | border-color: #f96; | ||
| 1397 | background: #fff8f2; | ||
| 1398 | } | ||
| 1399 | |||
| 1389 | /* ============================================================ | 1400 | /* ============================================================ |
| 1390 | Live edit preview | 1401 | Live edit preview |
| 1391 | ============================================================ */ | 1402 | ============================================================ */ |
