From 14d7dfc9571df2236e8562b15280ceb6e5f25e6f Mon Sep 17 00:00:00 2001
From: Patrick Jentsch <p.jentsch@uni-bielefeld.de>
Date: Mon, 19 Dec 2022 16:25:10 +0100
Subject: [PATCH] Update some logic for avatars

---
 app/profile/routes.py                      |  2 +-
 app/static/js/Utils.js                     | 48 ++++++++++++++
 app/templates/profile/edit_profile.html.j2 | 77 ++++++----------------
 3 files changed, 68 insertions(+), 59 deletions(-)

diff --git a/app/profile/routes.py b/app/profile/routes.py
index 85a68feb..60eef6ad 100644
--- a/app/profile/routes.py
+++ b/app/profile/routes.py
@@ -33,7 +33,7 @@ def profile(user_id):
         abort(403)
     return render_template(
         'profile/profile.html.j2', 
-        user=user.to_json_serializeable(),
+        user=user.to_json_serializeable()
     )
 
 
diff --git a/app/static/js/Utils.js b/app/static/js/Utils.js
index 899147b4..c38c5620 100644
--- a/app/static/js/Utils.js
+++ b/app/static/js/Utils.js
@@ -227,6 +227,54 @@ class Utils {
     });
   }
 
+  static deleteProfileAvatarRequest(userId) {
+    return new Promise((resolve, reject) => {
+      let modalElement = Utils.elementFromString(
+        `
+          <div class="modal">
+            <div class="modal-content">
+              <h4>Confirm Avatar deletion</h4>
+              <p>Do you really want to delete your Avatar?</p>
+            </div>
+            <div class="modal-footer">
+              <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
+              <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
+            </div>
+          </div>
+        `
+      );
+      document.querySelector('#modals').appendChild(modalElement);
+      let modal = M.Modal.init(
+        modalElement,
+        {
+          dismissible: false,
+          onCloseEnd: () => {
+            modal.destroy();
+            modalElement.remove();
+          }
+        }
+      );
+
+      let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
+      confirmElement.addEventListener('click', (event) => {
+        fetch(`/profile/${userId}/avatar`, {method: 'DELETE', headers: {Accept: 'application/json'}})
+          .then(
+            (response) => {
+              if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
+              if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
+              app.flash(`Avatar marked for deletion`);
+              resolve(response);
+            },
+            (response) => {
+              app.flash('Something went wrong', 'error');
+              reject(response);
+            }
+          );
+      });
+      modal.open();
+    });
+  }
+
   static deleteJobRequest(userId, jobId) {
     return new Promise((resolve, reject) => {
       let job = app.data.users[userId].jobs[jobId];
diff --git a/app/templates/profile/edit_profile.html.j2 b/app/templates/profile/edit_profile.html.j2
index b789e265..5e299262 100644
--- a/app/templates/profile/edit_profile.html.j2
+++ b/app/templates/profile/edit_profile.html.j2
@@ -71,7 +71,7 @@
                     {% if user.avatar %}
                     <img src="{{ url_for('.profile_avatar', user_id=user.id) }}" alt="user-image" class="circle responsive-img" id="avatar">
                     {% else %}
-                    <img src="{{ url_for('static', filename='images/user_avatar.png') }}" alt="user-image" class="circle responsive-img" id="placeholder-avatar">
+                    <img src="{{ url_for('static', filename='images/user_avatar.png') }}" alt="user-image" class="circle responsive-img" id="avatar">
                     {% endif %}
                   </div>
                   <div class="col s2"></div>
@@ -79,7 +79,7 @@
                 <div class="row">
                   <div class="col s2">
                     <div class="center-align">
-                      <a class="action-button btn-floating red waves-effect waves-light modal-trigger" href="#delete-request" style="margin-top:15px;"><i class="material-icons">delete</i></a>
+                      <a class="action-button btn-floating red waves-effect waves-light" style="margin-top:15px;" id="delete-avatar"><i class="material-icons">delete</i></a>
                     </div>
                   </div>
                   <div class="col s10">
@@ -111,83 +111,44 @@
 </div>
 {% endblock page_content %}
 
-{% block modals %}
-<div class="modal" id="delete-request">
-  <div class="modal-content">
-    <h4>Confirm Avatar deletion</h4>
-    <p>Do you really want to delete your Avatar?</p>
-  </div>
-  <div class="modal-footer">
-    <a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
-    <a class="action-button btn modal-close red waves-effect waves-light" data-action="delete">Delete</a>
-  </div>
-</div>
-{% endblock modals %}
-
 {% block scripts %}
 {{ super() }}
 <script>
 let publicProfile = document.querySelector('#public-profile');
 let disableButtons = document.querySelectorAll('[data-action="disable"]');
-let deleteButton = document.querySelector('[data-action="delete"]');
-let cancelButton = document.querySelector('[data-action="cancel"]');
-let deleteRequestModal = document.querySelector('#delete-request');
+let deleteButton = document.querySelector('#delete-avatar');
 let avatar = document.querySelector('#avatar');
-let placeholderAvatar = document.querySelector('#placeholder-avatar');
 let avatarUpload = document.querySelector('#avatar-upload');
 
-for (let i = 0; i < disableButtons.length; i++) {
-  disableButtons[i].disabled = !publicProfile.checked;
+for (let disableButton of disableButtons) {
+  disableButton.disabled = !publicProfile.checked;
 }
 
-publicProfile.addEventListener('change', function() {
+publicProfile.addEventListener('change', () => {
   if (publicProfile.checked) {
-    for (let i = 0; i < disableButtons.length; i++) {
-      disableButtons[i].disabled = false;
+    for (let disableButton of disableButtons) {
+      disableButton.disabled = false;
     }
-
   } else {
-    for (let i = 0; i < disableButtons.length; i++) {
-      disableButtons[i].checked = false;
-      disableButtons[i].disabled = true;
+    for (let disableButton of disableButtons) {
+      disableButton.checked = false;
+      disableButton.disabled = true;
     }
   }
 });
 
 avatarUpload.addEventListener('change', function() {
   let file = this.files[0];
-  if (avatar){
-    avatar.src = URL.createObjectURL(file);
-  } else {
-    placeholderAvatar.src = URL.createObjectURL(file);
-  }
+  avatar.src = URL.createObjectURL(file);
 });
 
-deleteButton.addEventListener('click', function() {
-  return new Promise((resolve, reject) => {
-    let user_id = {{ user.hashid }};
-
-    fetch(`/profile/${user_id}/avatar`, {method: 'DELETE', headers: {Accept: 'application/json'}})
-      .then(
-        (response) => {
-          if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
-          if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
-          app.flash('Avatar marked for deletion');
-          resolve(response);
-        },
-        (response) => {
-          app.flash('Something went wrong', 'error');
-          reject(response);
-        }
-      );
-    avatar.src = "{{ url_for('static', filename='images/user_avatar.png') }}";
-  });
+deleteButton.addEventListener('click', () => {
+  Utils.deleteProfileAvatarRequest({{ user.hashid|tojson }})
+    .then(
+      (response) => {
+        avatar.src = "{{ url_for('static', filename='images/user_avatar.png') }}";
+      }
+    );
 });
-
-cancelButton.addEventListener('click', function() {
-  let modal = M.Modal.getInstance(deleteRequestModal);
-  modal.close();
-});
-
 </script>
 {% endblock scripts %}
-- 
GitLab