Repository: freedomofpress/securedrop

Issue:
Admin interface: Improve UX on successful logo upload
## Description

As pointed out in #2844, the error message and success messages should ideally be consistent in terms of where they show up on the page. We have error messages on many of our forms displayed below the form (intended to be as close as possible to http://uipatterns.io/input-validation/form-validation):

![screen shot 2018-01-12 at 12 32 48 pm](https://user-images.githubusercontent.com/7832803/34894160-15a6eae2-f795-11e7-9f0b-cb70da9e63af.png)

but the successful logo upload user feedback occurs in a flashed message at the top of the screen. It would be more intuitive for the user to get user feedback next to the "UPDATE LOGO" button itself, e.g. a green checkmark with "Logo updated" or similar. 

## User Stories

As a SecureDrop administrator, I want a successful action to produce user feedback near the area of the webpage I am on. 


Discussion:

Resolving patch:
diff --git a/securedrop/journalist_app/admin.py b/securedrop/journalist_app/admin.py
--- a/securedrop/journalist_app/admin.py
+++ b/securedrop/journalist_app/admin.py
@@ -34,9 +34,12 @@ def manage_config():
             static_filepath = os.path.join(config.SECUREDROP_ROOT,
                                            "static/i/logo.png")
             f.save(static_filepath)
-            flash(gettext("Image updated."), "notification")
+            flash(gettext("Image updated."), "logo-success")
             return redirect(url_for("admin.manage_config"))
         else:
+            for field, errors in form.errors.items():
+                for error in errors:
+                    flash(error, "logo-error")
             return render_template("config.html", form=form)
 
     @view.route('/add', methods=('GET', 'POST'))


Test patch:
diff --git a/securedrop/tests/test_journalist.py b/securedrop/tests/test_journalist.py
--- a/securedrop/tests/test_journalist.py
+++ b/securedrop/tests/test_journalist.py
@@ -746,7 +746,7 @@ def test_logo_upload_with_valid_image_succeeds(self):
                              data=form.data,
                              follow_redirects=True)
 
-            self.assertMessageFlashed("Image updated.", "notification")
+            self.assertMessageFlashed("Image updated.", "logo-success")
         finally:
             # Restore original image to logo location for subsequent tests
             with open(logo_image_location, 'w') as logo_file:
@@ -761,7 +761,7 @@ def test_logo_upload_with_invalid_filetype_fails(self):
         resp = self.client.post(url_for('admin.manage_config'),
                                 data=form.data,
                                 follow_redirects=True)
-
+        self.assertMessageFlashed("Upload images only.", "logo-error")
         self.assertIn('Upload images only.', resp.data)
 
     def test_logo_upload_with_empty_input_field_fails(self):
@@ -774,6 +774,7 @@ def test_logo_upload_with_empty_input_field_fails(self):
                                 data=form.data,
                                 follow_redirects=True)
 
+        self.assertMessageFlashed("File required.", "logo-error")
         self.assertIn('File required.', resp.data)
 
     @patch('journalist.app.logger.error')