Confirm leaving when changes are made or confirmation needs to take place

pull/334/head
ElementalAlchemist 2 years ago committed by Mike Lang
parent dd747416e0
commit 766b4d111d

@ -1,16 +1,25 @@
var googleUser = null; var googleUser = null;
var videoInfo; var videoInfo;
var currentRange = 1; var currentRange = 1;
let globalPageState = 0;
const CHAPTER_MARKER_DELIMITER = "\n==========\n"; const CHAPTER_MARKER_DELIMITER = "\n==========\n";
const CHAPTER_MARKER_DELIMITER_PARTIAL = "=========="; const CHAPTER_MARKER_DELIMITER_PARTIAL = "==========";
const PAGE_STATE = {
CLEAN: 0,
DIRTY: 1,
SUBMITTING: 2,
CONFIRMING: 3,
};
window.addEventListener("DOMContentLoaded", async (event) => { window.addEventListener("DOMContentLoaded", async (event) => {
commonPageSetup(); commonPageSetup();
globalLoadChatWorker.onmessage = (event) => { globalLoadChatWorker.onmessage = (event) => {
updateChatDataFromWorkerResponse(event.data); updateChatDataFromWorkerResponse(event.data);
renderChatLog(); renderChatLog();
}; };
window.addEventListener("beforeunload", handleLeavePage);
const timeUpdateForm = document.getElementById("stream-time-settings"); const timeUpdateForm = document.getElementById("stream-time-settings");
timeUpdateForm.addEventListener("submit", async (event) => { timeUpdateForm.addEventListener("submit", async (event) => {
@ -51,7 +60,8 @@ window.addEventListener("DOMContentLoaded", async (event) => {
newDuration += segmentList[segmentList.length - 1].duration; newDuration += segmentList[segmentList.length - 1].duration;
// Abort for ranges that exceed new times // Abort for ranges that exceed new times
for (const rangeContainer of document.getElementById("range-definitions").children) { const rangeDefinitionsElements = document.getElementById("range-definitions").children;
for (const rangeContainer of rangeDefinitionsElements) {
const rangeStartField = rangeContainer.getElementsByClassName("range-definition-start")[0]; const rangeStartField = rangeContainer.getElementsByClassName("range-definition-start")[0];
const rangeEndField = rangeContainer.getElementsByClassName("range-definition-end")[0]; const rangeEndField = rangeContainer.getElementsByClassName("range-definition-end")[0];
const rangeStart = videoPlayerTimeFromVideoHumanTime(rangeStartField.value); const rangeStart = videoPlayerTimeFromVideoHumanTime(rangeStartField.value);
@ -68,7 +78,6 @@ window.addEventListener("DOMContentLoaded", async (event) => {
} }
const rangesData = []; const rangesData = [];
const rangeDefinitionsElements = document.getElementById("range-definitions").children;
for (const rangeContainer of rangeDefinitionsElements) { for (const rangeContainer of rangeDefinitionsElements) {
const rangeStartField = rangeContainer.getElementsByClassName("range-definition-start")[0]; const rangeStartField = rangeContainer.getElementsByClassName("range-definition-start")[0];
const rangeEndField = rangeContainer.getElementsByClassName("range-definition-end")[0]; const rangeEndField = rangeContainer.getElementsByClassName("range-definition-end")[0];
@ -152,19 +161,22 @@ window.addEventListener("DOMContentLoaded", async (event) => {
const addRangeIcon = document.getElementById("add-range-definition"); const addRangeIcon = document.getElementById("add-range-definition");
if (videoInfo.state !== "DONE") { if (videoInfo.state !== "DONE") {
addRangeIcon.addEventListener("click", (_event) => { addRangeIcon.addEventListener("click", (event) => {
addRangeDefinition(); addRangeDefinition();
handleFieldChange(event);
}); });
addRangeIcon.addEventListener("keypress", (event) => { addRangeIcon.addEventListener("keypress", (event) => {
if (event.key === "Enter") { if (event.key === "Enter") {
addRangeDefinition(); addRangeDefinition();
handleFieldChange(event);
} }
}); });
} }
const enableChaptersElem = document.getElementById("enable-chapter-markers"); const enableChaptersElem = document.getElementById("enable-chapter-markers");
enableChaptersElem.addEventListener("change", (_event) => { enableChaptersElem.addEventListener("change", (event) => {
changeEnableChaptersHandler(); changeEnableChaptersHandler();
handleFieldChange(event);
}); });
for (const rangeStartSet of document.getElementsByClassName("range-definition-set-start")) { for (const rangeStartSet of document.getElementsByClassName("range-definition-set-start")) {
@ -180,13 +192,15 @@ window.addEventListener("DOMContentLoaded", async (event) => {
rangeEndPlay.addEventListener("click", rangePlayFromEndHandler); rangeEndPlay.addEventListener("click", rangePlayFromEndHandler);
} }
for (const rangeStart of document.getElementsByClassName("range-definition-start")) { for (const rangeStart of document.getElementsByClassName("range-definition-start")) {
rangeStart.addEventListener("change", (_event) => { rangeStart.addEventListener("change", (event) => {
rangeDataUpdated(); rangeDataUpdated();
handleFieldChange(event);
}); });
} }
for (const rangeEnd of document.getElementsByClassName("range-definition-end")) { for (const rangeEnd of document.getElementsByClassName("range-definition-end")) {
rangeEnd.addEventListener("change", (_event) => { rangeEnd.addEventListener("change", (event) => {
rangeDataUpdated(); rangeDataUpdated();
handleFieldChange(event);
}); });
} }
for (const addChapterMarker of document.getElementsByClassName( for (const addChapterMarker of document.getElementsByClassName(
@ -195,17 +209,22 @@ window.addEventListener("DOMContentLoaded", async (event) => {
addChapterMarker.addEventListener("click", addChapterMarkerHandler); addChapterMarker.addEventListener("click", addChapterMarkerHandler);
} }
document.getElementById("video-info-title").addEventListener("input", (_event) => { document.getElementById("video-info-title").addEventListener("input", (event) => {
validateVideoTitle(); validateVideoTitle();
document.getElementById("video-info-title-abbreviated").innerText = document.getElementById("video-info-title-abbreviated").innerText =
videoInfo.title_prefix + document.getElementById("video-info-title").value; videoInfo.title_prefix + document.getElementById("video-info-title").value;
handleFieldChange(event);
}); });
document.getElementById("video-info-description").addEventListener("input", (_event) => { document.getElementById("video-info-description").addEventListener("input", (event) => {
validateVideoDescription(); validateVideoDescription();
handleFieldChange(event);
}); });
document document
.getElementById("video-info-thumbnail-mode") .getElementById("video-info-thumbnail-mode")
.addEventListener("change", updateThumbnailInputState); .addEventListener("change", updateThumbnailInputState);
document
.getElementById("video-info-thumbnail-time")
.addEventListener("change", handleFieldChange);
document.getElementById("video-info-thumbnail-time-set").addEventListener("click", (_event) => { document.getElementById("video-info-thumbnail-time-set").addEventListener("click", (_event) => {
const field = document.getElementById("video-info-thumbnail-time"); const field = document.getElementById("video-info-thumbnail-time");
const videoPlayer = document.getElementById("video"); const videoPlayer = document.getElementById("video");
@ -264,6 +283,8 @@ window.addEventListener("DOMContentLoaded", async (event) => {
); );
}); });
} }
// Ensure that changing values on load doesn't set keep the page dirty.
globalPageState = PAGE_STATE.CLEAN;
document.getElementById("submit-button").addEventListener("click", (_event) => { document.getElementById("submit-button").addEventListener("click", (_event) => {
submitVideo(); submitVideo();
@ -619,6 +640,9 @@ async function initializeVideoInfo() {
const timePercent = (videoElement.currentTime / videoElement.duration) * 100; const timePercent = (videoElement.currentTime / videoElement.duration) * 100;
document.getElementById("waveform-marker").style.left = `${timePercent}%`; document.getElementById("waveform-marker").style.left = `${timePercent}%`;
}); });
// Ensure that changes made to fields during initial load don't affect the state
globalPageState = PAGE_STATE.CLEAN;
} }
function updateWaveform() { function updateWaveform() {
@ -651,7 +675,9 @@ async function googleSignOut() {
} }
} }
function updateThumbnailInputState() { function updateThumbnailInputState(event) {
handleFieldChange(event);
const newValue = document.getElementById("video-info-thumbnail-mode").value; const newValue = document.getElementById("video-info-thumbnail-mode").value;
const unhideIDs = []; const unhideIDs = [];
@ -723,21 +749,6 @@ function validateVideoDescription() {
} }
async function submitVideo() { async function submitVideo() {
const enableChaptersElem = document.getElementById("enable-chapter-markers");
const chapterStartFieldList = document.getElementsByClassName("range-definition-chapter-time");
if (enableChaptersElem.checked && chapterStartFieldList.length > 0) {
const firstRangeStartElem = document.getElementsByClassName("range-definition-start")[0];
const firstRangeStart = videoPlayerTimeFromMVideoHumanTime(firstRangeStartElem.value);
const firstChapterStartField = chapterStartFieldList[0];
const firstChapterStart = videoPlayerTimeFromVideoHumanTime(firstChapterStartField.value);
if (firstRangeStart !== firstChapterStart) {
addError("The first chapter marker must be at the beginning of the video");
return;
}
}
return sendVideoData("EDITED", false); return sendVideoData("EDITED", false);
} }
@ -763,7 +774,6 @@ async function sendVideoData(newState, overrideChanges) {
const submissionResponseElem = document.getElementById("submission-response"); const submissionResponseElem = document.getElementById("submission-response");
submissionResponseElem.classList.value = ["submission-response-pending"]; submissionResponseElem.classList.value = ["submission-response-pending"];
submissionResponseElem.innerText = "Submitting video..."; submissionResponseElem.innerText = "Submitting video...";
window.addEventListener("beforeunload", handleLeavePageWhilePending);
const rangesData = []; const rangesData = [];
let chaptersData = []; let chaptersData = [];
@ -994,6 +1004,8 @@ async function sendVideoData(newState, overrideChanges) {
editData.override_changes = true; editData.override_changes = true;
} }
globalPageState = PAGE_STATE.SUBMITTING;
const submitResponse = await fetch(`/thrimshim/${videoInfo.id}`, { const submitResponse = await fetch(`/thrimshim/${videoInfo.id}`, {
method: "POST", method: "POST",
headers: { headers: {
@ -1003,9 +1015,8 @@ async function sendVideoData(newState, overrideChanges) {
body: JSON.stringify(editData), body: JSON.stringify(editData),
}); });
window.removeEventListener("beforeunload", handleLeavePageWhilePending);
if (submitResponse.ok) { if (submitResponse.ok) {
globalPageState = PAGE_STATE.CLEAN;
submissionResponseElem.classList.value = ["submission-response-success"]; submissionResponseElem.classList.value = ["submission-response-success"];
if (newState === "EDITED") { if (newState === "EDITED") {
submissionResponseElem.innerText = "Submitted edit"; submissionResponseElem.innerText = "Submitted edit";
@ -1029,8 +1040,10 @@ async function sendVideoData(newState, overrideChanges) {
submissionResponseElem.innerText = `Submitted state ${newState}`; submissionResponseElem.innerText = `Submitted state ${newState}`;
} }
} else { } else {
globalPageState = PAGE_STATE.DIRTY;
submissionResponseElem.classList.value = ["submission-response-error"]; submissionResponseElem.classList.value = ["submission-response-error"];
if (submitResponse.status === 409) { if (submitResponse.status === 409) {
globalPageState = PAGE_STATE.CONFIRMING;
const serverErrorNode = document.createTextNode(await submitResponse.text()); const serverErrorNode = document.createTextNode(await submitResponse.text());
const submitButton = document.createElement("button"); const submitButton = document.createElement("button");
submitButton.innerText = "Submit Anyway"; submitButton.innerText = "Submit Anyway";
@ -1080,10 +1093,29 @@ function unformatChapterTime(chapterTime) {
return hours * 3600 + minutes * 60 + seconds; return hours * 3600 + minutes * 60 + seconds;
} }
function handleLeavePageWhilePending(event) { function handleFieldChange(_event) {
globalPageState = PAGE_STATE.DIRTY;
}
function handleLeavePage(event) {
if (globalPageState === PAGE_STATE.CLEAN) {
return;
}
event.preventDefault(); event.preventDefault();
switch (globalPageState) {
case PAGE_STATE.DIRTY:
event.returnValue = event.returnValue =
"The video submission is still pending. Are you sure you want to exit? You may lose your edits."; "There are unsaved edits. Are you sure you want to exit? You will lose your edits.";
break;
case PAGE_STATE.SUBMITTING:
event.returnValue =
"The video is stsill being submitted. Are you sure you want to exit? You may lose your edits.";
break;
case PAGE_STATE.CONFIRMING:
event.returnValue =
"There's a confirmation for video submission. Are you sure you want to exit? You will lose your edits.";
break;
}
return event.returnValue; return event.returnValue;
} }
@ -1288,6 +1320,8 @@ function rangeDefinitionDOM() {
rangeEndPlay.addEventListener("click", rangePlayFromEndHandler); rangeEndPlay.addEventListener("click", rangePlayFromEndHandler);
removeRange.addEventListener("click", (event) => { removeRange.addEventListener("click", (event) => {
handleFieldChange(event);
let rangeContainer = event.currentTarget; let rangeContainer = event.currentTarget;
while (rangeContainer && !rangeContainer.classList.contains("range-definition-removable")) { while (rangeContainer && !rangeContainer.classList.contains("range-definition-removable")) {
rangeContainer = rangeContainer.parentElement; rangeContainer = rangeContainer.parentElement;
@ -1495,6 +1529,7 @@ function chapterMarkerDefinitionDOM() {
function addChapterMarkerHandler(event) { function addChapterMarkerHandler(event) {
const newChapterMarker = chapterMarkerDefinitionDOM(); const newChapterMarker = chapterMarkerDefinitionDOM();
event.currentTarget.previousElementSibling.appendChild(newChapterMarker); event.currentTarget.previousElementSibling.appendChild(newChapterMarker);
handleFieldChange(event);
} }
async function rangeDataUpdated() { async function rangeDataUpdated() {

Loading…
Cancel
Save