From 4fa04f9ded66fc5140b001617105d22abffe2e17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pernille=20N=C3=B8dtvedt=20Welle-Watne?=
 <1417-pernilnw@users.noreply.gitlab.stud.idi.ntnu.no>
Date: Mon, 1 Mar 2021 13:01:51 +0100
Subject: [PATCH] Google calendar

---
 frontend/www/scripts/workout.js | 110 +++++++++++++++++++++++++++++---
 frontend/www/styles/style.css   |   5 ++
 frontend/www/workout.html       |   1 +
 3 files changed, 106 insertions(+), 10 deletions(-)

diff --git a/frontend/www/scripts/workout.js b/frontend/www/scripts/workout.js
index 94eddb7..9cb6711 100644
--- a/frontend/www/scripts/workout.js
+++ b/frontend/www/scripts/workout.js
@@ -2,9 +2,10 @@ let cancelWorkoutButton;
 let okWorkoutButton;
 let deleteWorkoutButton;
 let editWorkoutButton;
+let exportWorkoutButton;
 let postCommentButton;
 
-async function retrieveWorkout(id) {  
+async function retrieveWorkout(id) {
     let workoutData = null;
     let response = await sendRequest("GET", `${HOST}/api/workouts/${id}/`);
     if (!response.ok) {
@@ -57,11 +58,11 @@ async function retrieveWorkout(id) {
 
             let exerciseTypeLabel = divExerciseContainer.querySelector('.exercise-type');
             exerciseTypeLabel.for = `inputExerciseType${i}`;
-    
-            let exerciseTypeSelect = divExerciseContainer.querySelector("select");            
+
+            let exerciseTypeSelect = divExerciseContainer.querySelector("select");
             exerciseTypeSelect.id = `inputExerciseType${i}`;
             exerciseTypeSelect.disabled = true;
-            
+
             let splitUrl = workoutData.exercise_instances[i].exercise.split("/");
             let currentExerciseTypeId = splitUrl[splitUrl.length - 2];
             let currentExerciseType = "";
@@ -75,7 +76,7 @@ async function retrieveWorkout(id) {
                 option.innerText = exerciseTypes.results[j].name;
                 exerciseTypeSelect.append(option);
             }
-            
+
             exerciseTypeSelect.value = currentExerciseType.id;
 
             let exerciseSetLabel = divExerciseContainer.querySelector('.exercise-sets');
@@ -99,7 +100,7 @@ async function retrieveWorkout(id) {
             exercisesDiv.appendChild(divExerciseContainer);
         }
     }
-    return workoutData;     
+    return workoutData;
 }
 
 function handleCancelDuringWorkoutEdit() {
@@ -109,11 +110,12 @@ function handleCancelDuringWorkoutEdit() {
 function handleEditWorkoutButtonClick() {
     let addExerciseButton = document.querySelector("#btn-add-exercise");
     let removeExerciseButton = document.querySelector("#btn-remove-exercise");
-    
+
     setReadOnly(false, "#form-workout");
     document.querySelector("#inputOwner").readOnly = true;  // owner field should still be readonly 
 
     editWorkoutButton.className += " hide";
+    exportWorkoutButton.className += " hide";
     okWorkoutButton.className = okWorkoutButton.className.replace(" hide", "");
     cancelWorkoutButton.className = cancelWorkoutButton.className.replace(" hide", "");
     deleteWorkoutButton.className = deleteWorkoutButton.className.replace(" hide", "");
@@ -124,6 +126,91 @@ function handleEditWorkoutButtonClick() {
 
 }
 
+//Taken from github: https://gist.github.com/dannypule/48418b4cd8223104c6c92e3016fc0f61
+function handleExportToCalendarClick(workoutData) {
+
+    const headers = {
+        subject: "Subject",
+        startDate: "Start date",
+        startTime: "Start time",
+        description: "Description"
+    }
+
+    const dataFormatted = []
+
+    const startTime = new Date(workoutData.date).toLocaleTimeString("en-us")
+    const startDate = new Date(workoutData.date).toLocaleString('en-us', {
+        year: 'numeric',
+        month: '2-digit',
+        day: '2-digit'
+    }).replace(/(\d+)\/(\d+)\/(\d+)/, '$1/$2/$3')
+
+
+    dataFormatted.push({
+        subject: workoutData.name,
+        startDate: startDate,
+        startTime: startTime,
+        description: workoutData.notes
+    })
+
+
+    console.log(dataFormatted)
+
+    exportCSVFile(headers, dataFormatted, "event")
+}
+
+//Taken from github: https://gist.github.com/dannypule/48418b4cd8223104c6c92e3016fc0f61
+function convertToCSV(objArray) {
+    var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
+    var str = '';
+
+    for (var i = 0; i < array.length; i++) {
+        var line = '';
+        for (var index in array[i]) {
+            if (line != '') line += ','
+
+            line += array[i][index];
+        }
+
+        str += line + '\r\n';
+    }
+
+    return str;
+}
+
+//Taken from github: https://gist.github.com/dannypule/48418b4cd8223104c6c92e3016fc0f61
+function exportCSVFile(headers, items, fileTitle) {
+
+    console.log(items, headers)
+    if (headers) {
+        items.unshift(headers);
+    }
+
+    // Convert Object to JSON
+    var jsonObject = JSON.stringify(items);
+
+    var csv = this.convertToCSV(jsonObject);
+
+    var exportedFilenmae = fileTitle + '.csv' || 'export.csv';
+
+    var blob = new Blob([csv], {type: 'text/csv;charset=utf-8;'});
+    if (navigator.msSaveBlob) { // IE 10+
+        navigator.msSaveBlob(blob, exportedFilenmae);
+    } else {
+        var link = document.createElement("a");
+        if (link.download !== undefined) { // feature detection
+            // Browsers that support HTML5 download attribute
+            var url = URL.createObjectURL(blob);
+            link.setAttribute("href", url);
+            link.setAttribute("download", exportedFilenmae);
+            link.style.visibility = 'hidden';
+            document.body.appendChild(link);
+            link.click();
+            document.body.removeChild(link);
+        }
+    }
+}
+
 async function deleteWorkout(id) {
     let response = await sendRequest("DELETE", `${HOST}/api/workouts/${id}/`);
     if (!response.ok) {
@@ -208,7 +295,7 @@ async function createBlankExercise() {
     let exerciseTemplate = document.querySelector("#template-exercise");
     let divExerciseContainer = exerciseTemplate.content.firstElementChild.cloneNode(true);
     let exerciseTypeSelect = divExerciseContainer.querySelector("select");
-    
+
     for (let i = 0; i < exerciseTypes.count; i++) {
         let option = document.createElement("option");
         option.value = exerciseTypes.results[i].id;
@@ -218,7 +305,7 @@ async function createBlankExercise() {
 
     let currentExerciseType = exerciseTypes.results[0];
     exerciseTypeSelect.value = currentExerciseType.name;
-    
+
     let divExercises = document.querySelector("#div-exercises");
     divExercises.appendChild(divExerciseContainer);
 }
@@ -251,7 +338,7 @@ function addComment(author, text, date, append) {
 
     dateSpan.appendChild(smallText);
     commentBody.appendChild(dateSpan);
-    
+
     let strong = document.createElement("strong");
     strong.className = "text-success";
     strong.innerText = author;
@@ -309,6 +396,7 @@ window.addEventListener("DOMContentLoaded", async () => {
     okWorkoutButton = document.querySelector("#btn-ok-workout");
     deleteWorkoutButton = document.querySelector("#btn-delete-workout");
     editWorkoutButton = document.querySelector("#btn-edit-workout");
+    exportWorkoutButton = document.querySelector("#btn-export-workout");
     let postCommentButton = document.querySelector("#post-comment");
     let divCommentRow = document.querySelector("#div-comment-row");
     let buttonAddExercise = document.querySelector("#btn-add-exercise");
@@ -327,7 +415,9 @@ window.addEventListener("DOMContentLoaded", async () => {
 
         if (workoutData["owner"] == currentUser.url) {
             editWorkoutButton.classList.remove("hide");
+            exportWorkoutButton.classList.remove("hide");
             editWorkoutButton.addEventListener("click", handleEditWorkoutButtonClick);
+            exportWorkoutButton.addEventListener("click", ((workoutData) => handleExportToCalendarClick(workoutData)).bind(undefined, workoutData));
             deleteWorkoutButton.addEventListener("click", (async (id) => await deleteWorkout(id)).bind(undefined, id));
             okWorkoutButton.addEventListener("click", (async (id) => await updateWorkout(id)).bind(undefined, id));
             postCommentButton.addEventListener("click", (async (id) => await createComment(id)).bind(undefined, id));
diff --git a/frontend/www/styles/style.css b/frontend/www/styles/style.css
index 066705c..8916046 100644
--- a/frontend/www/styles/style.css
+++ b/frontend/www/styles/style.css
@@ -62,3 +62,8 @@
 .link-block {
   display: block;
 }
+
+.btn-green {
+  background-color: #256d27;
+  color: #fff;
+}
diff --git a/frontend/www/workout.html b/frontend/www/workout.html
index 7374723..2e5d881 100644
--- a/frontend/www/workout.html
+++ b/frontend/www/workout.html
@@ -60,6 +60,7 @@
         <div class="col-lg-6">
           <input type="button" class="btn btn-primary hide" id="btn-ok-workout" value="  OK  ">
           <input type="button" class="btn btn-primary hide" id="btn-edit-workout" value=" Edit ">
+           <input type="button" class="btn btn-green hide" id="btn-export-workout" value=" Export to calendar">
           <input type="button" class="btn btn-secondary hide" id="btn-cancel-workout" value="Cancel">
           <input type="button" class="btn btn-danger float-end hide" id="btn-delete-workout" value="Delete">
         </div>
-- 
GitLab