diff --git a/apps/addons/models.py b/apps/addons/models.py
index 3bf9b27d9a..fedaabfbe1 100644
--- a/apps/addons/models.py
+++ b/apps/addons/models.py
@@ -8,7 +8,8 @@ from datetime import datetime, timedelta
from django.conf import settings
from django.db import models, transaction
-from django.db.models import Q, Max, signals as dbsignals
+from django.db.models import Q, Sum, Max, signals as dbsignals
+from django.dispatch import receiver
from django.utils.translation import trans_real as translation
import caching.base as caching
@@ -1123,6 +1124,13 @@ class Preview(amo.models.ModelBase):
return self._image_path(settings.PREVIEW_FULL_PATH)
+# Use pre_delete since we need to know what we want to delete in the fs.
+@receiver(dbsignals.pre_delete, sender=Preview)
+def delete_preview_handler(sender, instance, **kwargs):
+ from . import tasks
+ tasks.delete_preview_files.delay(instance.id)
+
+
class AppSupport(amo.models.ModelBase):
"""Cache to tell us if an add-on's current version supports an app."""
addon = models.ForeignKey(Addon)
diff --git a/apps/addons/tasks.py b/apps/addons/tasks.py
index 148cae1c21..9ce6437909 100644
--- a/apps/addons/tasks.py
+++ b/apps/addons/tasks.py
@@ -7,7 +7,7 @@ from celeryutils import task
import amo
from amo.decorators import write
from . import cron # Pull in tasks from cron.
-from .models import Addon
+from .models import Addon, Preview
log = logging.getLogger('z.task')
@@ -57,3 +57,15 @@ def update_appsupport(ids):
# All our updates were sql, so invalidate manually.
Addon.objects.invalidate(*addons)
+
+
+@task
+def delete_preview_files(id):
+ log.info('[1@None] Removing preview with id of %s.' % id)
+
+ p = Preview(id=id)
+ for f in (p.thumbnail_path, p.image_path):
+ try:
+ os.remove(f)
+ except Exception, e:
+ log.error('Error deleting preview file: %s' % f)
diff --git a/apps/devhub/forms.py b/apps/devhub/forms.py
index 42dcea2d96..f3430ffcd2 100644
--- a/apps/devhub/forms.py
+++ b/apps/devhub/forms.py
@@ -473,6 +473,13 @@ class PreviewForm(happyforms.ModelForm):
def save(self, addon, commit=True):
if self.cleaned_data:
self.instance.addon = addon
+ if self.cleaned_data.get('DELETE'):
+ # Existing preview.
+ if self.instance.id:
+ self.instance.delete()
+ # User has no desire to save this preview.
+ return
+
super(PreviewForm, self).save(commit=commit)
if self.cleaned_data['upload_hash']:
diff --git a/apps/devhub/templates/devhub/addons/submit/media.html b/apps/devhub/templates/devhub/addons/submit/media.html
index de85efb00c..0b8f6ea5e8 100644
--- a/apps/devhub/templates/devhub/addons/submit/media.html
+++ b/apps/devhub/templates/devhub/addons/submit/media.html
@@ -68,8 +68,14 @@
{% endif %}
{{ form.id|safe }}
+ {{ form.DELETE|safe }}{{ form.DELETE.label_tag()|safe }}
{{ form.caption|safe }}
+
+
+ {{ _('Delete this Screen Shot') }}
+
+
diff --git a/apps/devhub/templates/devhub/includes/addon_edit_media.html b/apps/devhub/templates/devhub/includes/addon_edit_media.html
index 9e7e6f2f29..92d8a9e3d6 100644
--- a/apps/devhub/templates/devhub/includes/addon_edit_media.html
+++ b/apps/devhub/templates/devhub/includes/addon_edit_media.html
@@ -88,10 +88,16 @@
{% endif %}
{{ form.id|safe }}
+ {{ form.DELETE|safe }}{{ form.DELETE.label_tag()|safe }}
{{ form.caption|safe }}
+
+
+ {{ _('Delete this Screen Shot') }}
+
+
diff --git a/apps/devhub/tests/test_views.py b/apps/devhub/tests/test_views.py
index f324d6113a..0035015776 100644
--- a/apps/devhub/tests/test_views.py
+++ b/apps/devhub/tests/test_views.py
@@ -1653,6 +1653,20 @@ class TestEdit(test_utils.TestCase):
eq_(str(self.get_addon().previews.all()[0].caption), 'bye')
eq_(len(self.get_addon().previews.all()), 1)
+ def test_edit_media_preview_delete(self):
+ self.preview_add()
+ preview = self.get_addon().previews.get()
+ edited = {'DELETE': 'checked',
+ 'upload_hash': '',
+ 'id': preview.id,
+ 'file_upload': None}
+
+ data_formset = self.formset_media(edited, initial_count=1)
+
+ self.client.post(self.get_url('media', True), data_formset)
+
+ eq_(len(self.get_addon().previews.all()), 0)
+
def test_edit_media_preview_add_another(self):
self.preview_add()
self.preview_add()
diff --git a/media/css/zamboni/developers.css b/media/css/zamboni/developers.css
index 0e2ed8e00c..3097145d41 100644
--- a/media/css/zamboni/developers.css
+++ b/media/css/zamboni/developers.css
@@ -304,6 +304,20 @@ form .char-count b {
display: none;
}
+#file-list .preview .preview-delete {
+ margin-right: 1.6em;
+ text-align: right;
+}
+
+#file-list .preview .preview-delete a {
+ color: red;
+ text-decoration: none;
+}
+
+.html-rtl #file-list .preview .preview-delete {
+ margin-right: 0;
+}
+
#file-list .preview .preview_extra {
display: none;
}
diff --git a/media/js/zamboni/devhub.js b/media/js/zamboni/devhub.js
index e61ae0878e..71d6a2662d 100644
--- a/media/js/zamboni/devhub.js
+++ b/media/js/zamboni/devhub.js
@@ -349,6 +349,12 @@ function initUploadPreview() {
});
+ $("#edit-addon-media, #submit-media").delegate(".preview-delete a", "click", function(e){
+ e.preventDefault();
+ var row = $(this).closest(".preview");
+ row.find(".delete input").attr("checked", "checked");
+ row.hide();
+ });
}
function initUploadIcon() {
diff --git a/media/js/zamboni/tests/devhub_tests.js b/media/js/zamboni/tests/devhub_tests.js
index d4823fded7..7871477d45 100644
--- a/media/js/zamboni/tests/devhub_tests.js
+++ b/media/js/zamboni/tests/devhub_tests.js
@@ -898,6 +898,22 @@ asyncTest('form errors are cleared', function() {
});
});
+module('preview_edit', {
+ setup: function() {
+ this.sandbox = tests.createSandbox('#preview-list');
+ initUploadPreview();
+ },
+ teardown: function() {
+ this.sandbox.remove();
+ }
+});
+
+test('Clicking delete screenshot marks checkbox.', function() {
+ $(".preview-delete a", this.sandbox).trigger('click');
+ equals($(".delete input", this.sandbox).attr("checked"), true);
+ equals($(".preview:visible", this.sandbox).length, 0);
+});
+
module('addon platform chooser', {
setup: function() {
diff --git a/templates/qunit.html b/templates/qunit.html
index 7295c1764f..22c8fc59a3 100644
--- a/templates/qunit.html
+++ b/templates/qunit.html
@@ -59,6 +59,21 @@
Bahasa Indonesia
+
+
+