From c67c033aec8acc6d6c9508860b1b1b1e23ce6eaa Mon Sep 17 00:00:00 2001
From: Patrick Jentsch <pjentsch@sfb1288inf-Laptop.fritz.box>
Date: Mon, 27 Apr 2020 15:22:20 +0200
Subject: [PATCH] Rework notification system

---
 app/corpora/views.py                          | 21 ++++++++--------
 app/jobs/views.py                             |  2 +-
 app/services/views.py                         |  7 +++---
 app/static/js/nopaque.CorpusAnalysisClient.js |  2 +-
 app/static/js/nopaque.js                      | 24 ++++++++++++-------
 app/static/js/nopaque.lists.js                |  4 ++--
 6 files changed, 32 insertions(+), 28 deletions(-)

diff --git a/app/corpora/views.py b/app/corpora/views.py
index 07872c8f..6d78c8b4 100644
--- a/app/corpora/views.py
+++ b/app/corpora/views.py
@@ -26,13 +26,12 @@ def add_corpus():
         try:
             os.makedirs(dir)
         except OSError:
-            flash('[ERROR]: Could not add corpus!')
+            flash('[ERROR]: Could not add corpus!', 'corpus')
             corpus.delete()
         else:
-            corpus_url = url_for('corpora.corpus', corpus_id=corpus.id)
-            flash('<i class="left material-icons">book</i>'
-                  '[<a href="{}">{}</a>] added'.format(corpus_url,
-                                                       corpus.title))
+            url = url_for('corpora.corpus', corpus_id=corpus.id)
+            flash('[<a href="{}">{}</a>] added'.format(url, corpus.title),
+                  'corpus')
             return redirect(url_for('corpora.corpus', corpus_id=corpus.id))
     return render_template('corpora/add_corpus.html.j2',
                            add_corpus_form=add_corpus_form,
@@ -82,7 +81,7 @@ def delete_corpus(corpus_id):
     if not (corpus.creator == current_user or current_user.is_administrator()):
         abort(403)
     tasks.delete_corpus(corpus_id)
-    flash('Corpus deleted!')
+    flash('Corpus deleted!', 'corpus')
     return redirect(url_for('main.dashboard'))
 
 
@@ -121,7 +120,7 @@ def add_corpus_file(corpus_id):
         db.session.add(corpus_file)
         corpus.status = 'unprepared'
         db.session.commit()
-        flash('Corpus file added!')
+        flash('Corpus file added!', 'corpus')
         return make_response(
             {'redirect_url': url_for('corpora.corpus', corpus_id=corpus.id)},
             201)
@@ -141,7 +140,7 @@ def delete_corpus_file(corpus_id, corpus_file_id):
             or current_user.is_administrator()):
         abort(403)
     tasks.delete_corpus_file(corpus_file_id)
-    flash('Corpus file deleted!')
+    flash('Corpus file deleted!', 'corpus')
     return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
 
 
@@ -188,7 +187,7 @@ def edit_corpus_file(corpus_id, corpus_file_id):
         corpus_file.title = edit_corpus_file_form.title.data
         corpus.status = 'unprepared'
         db.session.commit()
-        flash('Corpus file edited!')
+        flash('Corpus file edited!', 'corpus')
         return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
     # If no form is submitted or valid, fill out fields with current values
     edit_corpus_file_form.address.data = corpus_file.address
@@ -217,7 +216,7 @@ def prepare_corpus(corpus_id):
         abort(403)
     if corpus.files.all():
         tasks.build_corpus(corpus_id)
-        flash('Corpus gets build now.')
+        flash('Corpus gets build now.', 'corpus')
     else:
-        flash('Can not build corpus, please add corpus file(s).')
+        flash('Can not build corpus, please add corpus file(s).', 'corpus')
     return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
diff --git a/app/jobs/views.py b/app/jobs/views.py
index fe5ac9b2..1708f1c7 100644
--- a/app/jobs/views.py
+++ b/app/jobs/views.py
@@ -23,7 +23,7 @@ def delete_job(job_id):
     if not (job.creator == current_user or current_user.is_administrator()):
         abort(403)
     tasks.delete_job(job_id)
-    flash('Job has been deleted!')
+    flash('Job has been deleted!', 'job')
     return redirect(url_for('main.dashboard'))
 
 
diff --git a/app/services/views.py b/app/services/views.py
index 688254d3..3c8d0b08 100644
--- a/app/services/views.py
+++ b/app/services/views.py
@@ -61,7 +61,7 @@ def service(service):
             os.makedirs(absolut_dir)
         except OSError:
             job.delete()
-            flash('Internal Server Error')
+            flash('Internal Server Error', 'job')
             return make_response({'redirect_url': url_for('services.service',
                                                           service=service)},
                                  500)
@@ -74,9 +74,8 @@ def service(service):
                 db.session.add(job_input)
             job.status = 'submitted'
             db.session.commit()
-            job_url = url_for('jobs.job', job_id=job.id)
-            flash('<i class="left material-icons">work</i>'
-                  '[<a href="{}">{}</a>] added'.format(job_url, job.title))
+            url = url_for('jobs.job', job_id=job.id)
+            flash('[<a href="{}">{}</a>] added'.format(url, job.title), 'job')
             return make_response(
                 {'redirect_url': url_for('jobs.job', job_id=job.id)}, 201)
     return render_template('services/{}.html.j2'.format(service),
diff --git a/app/static/js/nopaque.CorpusAnalysisClient.js b/app/static/js/nopaque.CorpusAnalysisClient.js
index 268ba048..f5e701a7 100644
--- a/app/static/js/nopaque.CorpusAnalysisClient.js
+++ b/app/static/js/nopaque.CorpusAnalysisClient.js
@@ -44,7 +44,7 @@ class CorpusAnalysisClient {
         }
       } else {
         errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
-        nopaque.flash("error", errorText);
+        nopaque.flash(errorText, "error");
         if (this.displays.query.errorContainer != undefined)  {
           this.displays.query.errorContainer.innerHTML = `<p class="red-text">`+
                     `<i class="material-icons tiny">error</i> ${errorText}</p>`;
diff --git a/app/static/js/nopaque.js b/app/static/js/nopaque.js
index d2c6ddbf..2a689a75 100644
--- a/app/static/js/nopaque.js
+++ b/app/static/js/nopaque.js
@@ -58,7 +58,7 @@ nopaque.socket.init = function() {
         pathArray = operation.path.split("/").slice(1);
         if (operation.op === "replace" && pathArray[1] === "status") {
           if (nopaque.user.settings.jobStatusSiteNotifications === "end" && !["complete", "failed"].includes(operation.value)) {continue;}
-          nopaque.flash(`<i class="left material-icons">work</i>[<a href="/jobs/${pathArray[0]}">${nopaque.jobs[pathArray[0]].title}</a>] New status: ${operation.value}`);
+          nopaque.flash(`[<a href="/jobs/${pathArray[0]}">${nopaque.jobs[pathArray[0]].title}</a>] New status: ${operation.value}`, "job");
         }
       }
     }
@@ -184,23 +184,28 @@ nopaque.flash = function() {
       message = arguments[0];
       break;
     case 2:
-      category = arguments[0];
-      message = arguments[1];
+      message = arguments[0];
+      category = arguments[1];
       break;
     default:
-      console.error("Usage: nopaque.flash(message) or nopaque.flash(category, message)")
+      console.error("Usage: nopaque.flash(message) or nopaque.flash(message, category)")
   }
 
   switch (category) {
+    case "corpus":
+      message = `<i class="left material-icons">book</i>${message}`;
+      break;
     case "error":
-      classes = "red";
+      message = `<i class="left material-icons red-text">error</i>${message}`;
+      break;
+    case "job":
+      message = `<i class="left material-icons">work</i>${message}`;
       break;
     default:
-      classes = "";
+      message = `<i class="left material-icons">notifications</i>${message}`;
   }
 
-  toast = M.toast({classes: classes,
-                   html: `<span>${message}</span>
+  toast = M.toast({html: `<span>${message}</span>
                           <button data-action="close" class="btn-flat toast-action white-text">
                             <i class="material-icons">close</i>
                           </button>`});
@@ -225,7 +230,8 @@ document.addEventListener("DOMContentLoaded", function() {
   nopaque.Forms.init();
   nopaque.Navigation.init();
   while (nopaque.flashedMessages.length) {
-    nopaque.flash(...nopaque.flashedMessages.shift());
+    flashedMessage = nopaque.flashedMessages.shift();
+    nopaque.flash(flashedMessage[1], flashedMessage[0]);
   }
   if (nopaque.user.isAuthenticated) {
     if (nopaque.user.settings.darkMode) {
diff --git a/app/static/js/nopaque.lists.js b/app/static/js/nopaque.lists.js
index d62a11d3..c569c76d 100644
--- a/app/static/js/nopaque.lists.js
+++ b/app/static/js/nopaque.lists.js
@@ -378,7 +378,7 @@ class ResultsList extends List {
       if (expertModeSwitchElement.checked) {
         this.expertModeOn("query-display");  // page holds new result rows, so add new tooltips
       }
-      nopaque.flash("Updated matches per page.")
+      nopaque.flash("Updated matches per page.", "corpus")
     } catch (e) {
       // console.log(e);
       // console.log("resultsList has no results right now.");
@@ -394,7 +394,7 @@ class ResultsList extends List {
     let rc;
     try {
         if (event.type === "change") {
-            nopaque.flash("Updated context per match!");
+            nopaque.flash("Updated context per match!", "corpus");
         }
     } catch (e) {
     } finally {
-- 
GitLab