diff --git a/frontend/www/scripts/workout.js b/frontend/www/scripts/workout.js index 94eddb777de4dba4cc24b4ef447430a989b0c935..9cb67115417e25a1117118edab54121d86f7aed0 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 066705ce965bb162c61ebaf65ff77b9a0824eaf3..89160462b2a3b07889aa1818320aeda482d845d9 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 73747232adaea6ef4944cdd0fbec8693ca6b4a76..2e5d881a2103c5117d061618f44465d4486f7e7f 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>