From f3f2e44a7dafe9225886ef8ad4586aceb13929ff Mon Sep 17 00:00:00 2001 From: Lisann Engel Date: Wed, 5 Nov 2025 17:32:30 +0100 Subject: [PATCH 1/5] reuse getCookie method and renamed method --- .../editor/templates/editor/editor.html | 5 ++-- canvas_editor/jsconfig.json | 3 +- .../static/js/editor/jobInterface.mjs | 7 +++-- .../static/js/editor/previewHandler.mjs | 5 ++-- .../js/editor/projectOverviewManager.mjs | 27 ++---------------- .../static/js/editor/promptCommands.mjs | 7 +++-- .../static/js/editor/saveAndLoadHandler.mjs | 28 ++----------------- canvas_editor/static/js/utils/cookieUtils.js | 24 ++++++++++++++++ 8 files changed, 45 insertions(+), 61 deletions(-) create mode 100644 canvas_editor/static/js/utils/cookieUtils.js diff --git a/canvas_editor/editor/templates/editor/editor.html b/canvas_editor/editor/templates/editor/editor.html index 564ec033..4a9dad57 100644 --- a/canvas_editor/editor/templates/editor/editor.html +++ b/canvas_editor/editor/templates/editor/editor.html @@ -38,7 +38,7 @@ "inspectorClass": "{% static 'js/editor/inspector.mjs' %}", "previewHandler": "{% static 'js/editor/previewHandler.mjs' %}", "projectSettingsManager": "{% static 'js/projectSettingsManager.mjs' %}", - "projectOverviewHandler": "{% static 'js/editor/projectOverviewHandler.mjs' %}", + "projectOverviewManager": "{% static 'js/editor/projectOverviewManager.mjs' %}", "createCommands": "{% static 'js/commands/createCommands.mjs' %}", "navBar": "{% static 'js/editor/navbar.mjs' %}", "jobInterface": "{% static 'js/editor/jobInterface.mjs' %}", @@ -46,7 +46,8 @@ "promptCommands": "{% static 'js/editor/promptCommands.mjs' %}", "modeSelector": "{% static 'js/editor/modeSelector.mjs' %}", "message_dict": "{% static 'js/message_dict.js' %}", - "path_dict": "{% static 'js/path_dict.js' %}" + "path_dict": "{% static 'js/path_dict.js' %}", + "cookieUtils": "{% static 'js/utils/cookieUtils.js' %}" } } diff --git a/canvas_editor/jsconfig.json b/canvas_editor/jsconfig.json index 55be9334..3ebfa48e 100644 --- a/canvas_editor/jsconfig.json +++ b/canvas_editor/jsconfig.json @@ -38,7 +38,8 @@ "modeSelector": ["static/js/editor/modeSelector.mjs"], "projectOverviewHandler": ["static/js/editor/projectOverviewHandler.mjs"], "message_dict": ["static/js/message_dict.js"], - "path_dict": ["static/js/path_dict.js"] + "path_dict": ["static/js/path_dict.js"], + "cookieUtils": ["static/js/utils/cookieUtils.js"] } } } diff --git a/canvas_editor/static/js/editor/jobInterface.mjs b/canvas_editor/static/js/editor/jobInterface.mjs index 66c1cf5b..63503b21 100644 --- a/canvas_editor/static/js/editor/jobInterface.mjs +++ b/canvas_editor/static/js/editor/jobInterface.mjs @@ -1,4 +1,5 @@ -import { SaveAndLoadHandler } from "saveAndLoadHandler"; +import * as cookieUtils from "cookieUtils"; + let apiUrl = window.location.origin; @@ -60,7 +61,7 @@ export class JobInterface { method: "POST", headers: { "Content-Type": "application/json", - "X-CSRFToken": SaveAndLoadHandler.getCookie("csrftoken"), + "X-CSRFToken": cookieUtils.getCookie("csrftoken"), }, }) .then((res) => res.json()) @@ -96,7 +97,7 @@ export class JobInterface { method: "DELETE", headers: { "Content-Type": "application/json", - "X-CSRFToken": SaveAndLoadHandler.getCookie("csrftoken"), + "X-CSRFToken": cookieUtils.getCookie("csrftoken"), }, }).catch((error) => { console.error("Error deleting job:", error); diff --git a/canvas_editor/static/js/editor/previewHandler.mjs b/canvas_editor/static/js/editor/previewHandler.mjs index 7a5cd8fe..4d44de4f 100644 --- a/canvas_editor/static/js/editor/previewHandler.mjs +++ b/canvas_editor/static/js/editor/previewHandler.mjs @@ -1,6 +1,7 @@ import * as THREE from "three"; -import { SaveAndLoadHandler } from "saveAndLoadHandler"; import { errorUploadingFile } from "message_dict"; +import * as cookieUtils from "cookieUtils"; + /** * Handles the generation of project previews of the editor page @@ -65,7 +66,7 @@ export class PreviewHandler { method: "POST", body: formData, headers: { - "X-CSRFToken": SaveAndLoadHandler.getCookie("csrftoken"), + "X-CSRFToken": cookieUtils.getCookie("csrftoken"), }, }).catch((error) => { console.error(errorUploadingFile, error); diff --git a/canvas_editor/static/js/editor/projectOverviewManager.mjs b/canvas_editor/static/js/editor/projectOverviewManager.mjs index 2b9ebbdf..e21882e2 100644 --- a/canvas_editor/static/js/editor/projectOverviewManager.mjs +++ b/canvas_editor/static/js/editor/projectOverviewManager.mjs @@ -1,3 +1,4 @@ +import * as cookieUtils from "cookieUtils"; /** * Handles the project overview page */ @@ -46,7 +47,7 @@ export class ProjectOverviewManager { method: "POST", headers: { "Content-Type": "application/json", - "X-CSRFToken": this.#getCookie("csrftoken"), + "X-CSRFToken": cookieUtils.getCookie("csrftoken"), }, }); } @@ -100,28 +101,4 @@ export class ProjectOverviewManager { }); }); } - - /** - * Gets the cookie specified by the name - * @param {string} name The name of the cookie you want to get. - * @returns {string|null} the cookie or null if it couldn't be found. - */ - #getCookie(name) { - if (!document.cookie) { - return null; - } - - // document.cookie is a key=value list separated by ';' - const xsrfCookies = document.cookie - .split(";") - .map((c) => c.trim()) - //filter the right cookie name - .filter((c) => c.startsWith(name + "=")); - - if (xsrfCookies.length === 0) { - return null; - } - // return the decoded value of the first cookie found - return decodeURIComponent(xsrfCookies[0].split("=")[1]); - } } diff --git a/canvas_editor/static/js/editor/promptCommands.mjs b/canvas_editor/static/js/editor/promptCommands.mjs index 456e75dc..43b5b506 100644 --- a/canvas_editor/static/js/editor/promptCommands.mjs +++ b/canvas_editor/static/js/editor/promptCommands.mjs @@ -2,7 +2,8 @@ import { Modal } from "bootstrap"; import { CommandPrompt } from "commandPrompt"; import { abstractClassError, methodMustBeImplementedError } from "message_dict"; import { ObjectManager } from "objectManager"; -import { SaveAndLoadHandler } from "saveAndLoadHandler"; +import * as cookieUtils from "cookieUtils"; + /** * Parent class of all prompt commands @@ -402,7 +403,7 @@ export class ExportProjectPromptCommand extends PromptCommand { method: "GET", headers: { "Content-Type": "application/json", - "X-CSRFToken": SaveAndLoadHandler.getCookie("csrftoken"), + "X-CSRFToken": cookieUtils.getCookie("csrftoken"), }, }) .then((response) => { @@ -547,7 +548,7 @@ export class LogoutPromptCommand extends PromptCommand { method: "POST", headers: { "Content-Type": "application/json", - "X-CSRFToken": SaveAndLoadHandler.getCookie("csrftoken"), + "X-CSRFToken": cookieUtils.getCookie("csrftoken"), }, }).then(() => { window.location.href = window.location.origin; diff --git a/canvas_editor/static/js/editor/saveAndLoadHandler.mjs b/canvas_editor/static/js/editor/saveAndLoadHandler.mjs index f6872211..f4adf002 100644 --- a/canvas_editor/static/js/editor/saveAndLoadHandler.mjs +++ b/canvas_editor/static/js/editor/saveAndLoadHandler.mjs @@ -2,6 +2,8 @@ import { Heliostat } from "heliostat"; import { LightSource } from "lightSource"; import { projectIdRequiredError } from "message_dict"; import { Receiver } from "receiver"; +import * as cookieUtils from "cookieUtils"; + /** * Provides a wrapper for the API @@ -301,30 +303,6 @@ export class SaveAndLoadHandler { return this.#makeApiCall(url, "PUT", body); } - /** - * Utility function that gets the cookie specified by the name - * @param {string} name The name of the cookie you want to get. - * @returns {string|null} the cookie or null if it couldn't be found. - */ - static getCookie(name) { - if (!document.cookie) { - return null; - } - - // document.cookie is a key=value list separated by ';' - const xsrfCookies = document.cookie - .split(";") - .map((c) => c.trim()) - //filter the right cookie name - .filter((c) => c.startsWith(name + "=")); - - if (xsrfCookies.length === 0) { - return null; - } - // return the decoded value of the first cookie found - return decodeURIComponent(xsrfCookies[0].split("=")[1]); - } - /** * Wrapper function for an standard api call * @param {string} endpoint The endpoint to make the api call to @@ -337,7 +315,7 @@ export class SaveAndLoadHandler { method: method, headers: { "Content-Type": "application/json", - "X-CSRFToken": SaveAndLoadHandler.getCookie("csrftoken"), + "X-CSRFToken": cookieUtils.getCookie("csrftoken"), }, body: JSON.stringify(body), }) diff --git a/canvas_editor/static/js/utils/cookieUtils.js b/canvas_editor/static/js/utils/cookieUtils.js new file mode 100644 index 00000000..9ad07a88 --- /dev/null +++ b/canvas_editor/static/js/utils/cookieUtils.js @@ -0,0 +1,24 @@ +/** + * Utility function that gets the cookie specified by the name + * @param {string} name The name of the cookie you want to get. + * @returns {string|null} The cookie or null if it couldn't be found. + */ +export function getCookie(name) { + if (!document.cookie) { + return null; + } + + // document.cookie is a key=value list separated by ';' + const cookies = document.cookie + .split(";") + .map((c) => c.trim()) + //filter the right cookie name + .filter((c) => c.startsWith(name + "=")); + + if (cookies.length === 0) { + return null; + } + + // return the decoded value of the first cookie found + return decodeURIComponent(cookies[0].split("=")[1]); +} From b22b20a87366a4bd7f341c18982038c5c59428ac Mon Sep 17 00:00:00 2001 From: Lisann Engel Date: Sun, 23 Nov 2025 17:41:10 +0100 Subject: [PATCH 2/5] used relative import for cookieUtils --- canvas_editor/editor/templates/editor/editor.html | 3 +-- canvas_editor/jsconfig.json | 3 +-- canvas_editor/pyproject.toml | 1 - canvas_editor/static/js/editor/jobInterface.mjs | 7 +++---- canvas_editor/static/js/editor/previewHandler.mjs | 5 ++--- canvas_editor/static/js/editor/projectOverviewManager.mjs | 4 ++-- canvas_editor/static/js/editor/promptCommands.mjs | 7 +++---- canvas_editor/static/js/editor/saveAndLoadHandler.mjs | 5 ++--- .../static/js/utils/{cookieUtils.js => cookieUtils.mjs} | 0 9 files changed, 14 insertions(+), 21 deletions(-) rename canvas_editor/static/js/utils/{cookieUtils.js => cookieUtils.mjs} (100%) diff --git a/canvas_editor/editor/templates/editor/editor.html b/canvas_editor/editor/templates/editor/editor.html index 4a9dad57..77075136 100644 --- a/canvas_editor/editor/templates/editor/editor.html +++ b/canvas_editor/editor/templates/editor/editor.html @@ -46,8 +46,7 @@ "promptCommands": "{% static 'js/editor/promptCommands.mjs' %}", "modeSelector": "{% static 'js/editor/modeSelector.mjs' %}", "message_dict": "{% static 'js/message_dict.js' %}", - "path_dict": "{% static 'js/path_dict.js' %}", - "cookieUtils": "{% static 'js/utils/cookieUtils.js' %}" + "path_dict": "{% static 'js/path_dict.js' %}" } } diff --git a/canvas_editor/jsconfig.json b/canvas_editor/jsconfig.json index 3ebfa48e..55be9334 100644 --- a/canvas_editor/jsconfig.json +++ b/canvas_editor/jsconfig.json @@ -38,8 +38,7 @@ "modeSelector": ["static/js/editor/modeSelector.mjs"], "projectOverviewHandler": ["static/js/editor/projectOverviewHandler.mjs"], "message_dict": ["static/js/message_dict.js"], - "path_dict": ["static/js/path_dict.js"], - "cookieUtils": ["static/js/utils/cookieUtils.js"] + "path_dict": ["static/js/path_dict.js"] } } } diff --git a/canvas_editor/pyproject.toml b/canvas_editor/pyproject.toml index 0c791def..bc22d314 100644 --- a/canvas_editor/pyproject.toml +++ b/canvas_editor/pyproject.toml @@ -91,4 +91,3 @@ convention = "numpy" [tool.djlint] profile = "django" - diff --git a/canvas_editor/static/js/editor/jobInterface.mjs b/canvas_editor/static/js/editor/jobInterface.mjs index 63503b21..1fa70353 100644 --- a/canvas_editor/static/js/editor/jobInterface.mjs +++ b/canvas_editor/static/js/editor/jobInterface.mjs @@ -1,5 +1,4 @@ -import * as cookieUtils from "cookieUtils"; - +import { getCookie } from "../utils/cookieUtils.mjs"; let apiUrl = window.location.origin; @@ -61,7 +60,7 @@ export class JobInterface { method: "POST", headers: { "Content-Type": "application/json", - "X-CSRFToken": cookieUtils.getCookie("csrftoken"), + "X-CSRFToken": getCookie("csrftoken"), }, }) .then((res) => res.json()) @@ -97,7 +96,7 @@ export class JobInterface { method: "DELETE", headers: { "Content-Type": "application/json", - "X-CSRFToken": cookieUtils.getCookie("csrftoken"), + "X-CSRFToken": getCookie("csrftoken"), }, }).catch((error) => { console.error("Error deleting job:", error); diff --git a/canvas_editor/static/js/editor/previewHandler.mjs b/canvas_editor/static/js/editor/previewHandler.mjs index 4d44de4f..dbc089e5 100644 --- a/canvas_editor/static/js/editor/previewHandler.mjs +++ b/canvas_editor/static/js/editor/previewHandler.mjs @@ -1,7 +1,6 @@ import * as THREE from "three"; import { errorUploadingFile } from "message_dict"; -import * as cookieUtils from "cookieUtils"; - +import { getCookie } from "../utils/cookieUtils.mjs"; /** * Handles the generation of project previews of the editor page @@ -66,7 +65,7 @@ export class PreviewHandler { method: "POST", body: formData, headers: { - "X-CSRFToken": cookieUtils.getCookie("csrftoken"), + "X-CSRFToken": getCookie("csrftoken"), }, }).catch((error) => { console.error(errorUploadingFile, error); diff --git a/canvas_editor/static/js/editor/projectOverviewManager.mjs b/canvas_editor/static/js/editor/projectOverviewManager.mjs index e21882e2..91323cb8 100644 --- a/canvas_editor/static/js/editor/projectOverviewManager.mjs +++ b/canvas_editor/static/js/editor/projectOverviewManager.mjs @@ -1,4 +1,4 @@ -import * as cookieUtils from "cookieUtils"; +import { getCookie } from "../utils/cookieUtils.mjs"; /** * Handles the project overview page */ @@ -47,7 +47,7 @@ export class ProjectOverviewManager { method: "POST", headers: { "Content-Type": "application/json", - "X-CSRFToken": cookieUtils.getCookie("csrftoken"), + "X-CSRFToken": getCookie("csrftoken"), }, }); } diff --git a/canvas_editor/static/js/editor/promptCommands.mjs b/canvas_editor/static/js/editor/promptCommands.mjs index 43b5b506..e682ce3c 100644 --- a/canvas_editor/static/js/editor/promptCommands.mjs +++ b/canvas_editor/static/js/editor/promptCommands.mjs @@ -2,8 +2,7 @@ import { Modal } from "bootstrap"; import { CommandPrompt } from "commandPrompt"; import { abstractClassError, methodMustBeImplementedError } from "message_dict"; import { ObjectManager } from "objectManager"; -import * as cookieUtils from "cookieUtils"; - +import { getCookie } from "../utils/cookieUtils.mjs"; /** * Parent class of all prompt commands @@ -403,7 +402,7 @@ export class ExportProjectPromptCommand extends PromptCommand { method: "GET", headers: { "Content-Type": "application/json", - "X-CSRFToken": cookieUtils.getCookie("csrftoken"), + "X-CSRFToken": getCookie("csrftoken"), }, }) .then((response) => { @@ -548,7 +547,7 @@ export class LogoutPromptCommand extends PromptCommand { method: "POST", headers: { "Content-Type": "application/json", - "X-CSRFToken": cookieUtils.getCookie("csrftoken"), + "X-CSRFToken": getCookie("csrftoken"), }, }).then(() => { window.location.href = window.location.origin; diff --git a/canvas_editor/static/js/editor/saveAndLoadHandler.mjs b/canvas_editor/static/js/editor/saveAndLoadHandler.mjs index f4adf002..3d23d04b 100644 --- a/canvas_editor/static/js/editor/saveAndLoadHandler.mjs +++ b/canvas_editor/static/js/editor/saveAndLoadHandler.mjs @@ -2,8 +2,7 @@ import { Heliostat } from "heliostat"; import { LightSource } from "lightSource"; import { projectIdRequiredError } from "message_dict"; import { Receiver } from "receiver"; -import * as cookieUtils from "cookieUtils"; - +import { getCookie } from "../utils/cookieUtils.mjs"; /** * Provides a wrapper for the API @@ -315,7 +314,7 @@ export class SaveAndLoadHandler { method: method, headers: { "Content-Type": "application/json", - "X-CSRFToken": cookieUtils.getCookie("csrftoken"), + "X-CSRFToken": getCookie("csrftoken"), }, body: JSON.stringify(body), }) diff --git a/canvas_editor/static/js/utils/cookieUtils.js b/canvas_editor/static/js/utils/cookieUtils.mjs similarity index 100% rename from canvas_editor/static/js/utils/cookieUtils.js rename to canvas_editor/static/js/utils/cookieUtils.mjs From b0fa4f5936b1c6b7d7f1756bbac064d3d87f9606 Mon Sep 17 00:00:00 2001 From: Lisann Engel Date: Wed, 26 Nov 2025 15:40:40 +0100 Subject: [PATCH 3/5] Remove file deleted in main to prevent reintroducing it --- .../command_prompt/commands/promptCommand.mjs | 136 ------------------ 1 file changed, 136 deletions(-) delete mode 100644 canvas_editor/static/js/editor/command_prompt/commands/promptCommand.mjs diff --git a/canvas_editor/static/js/editor/command_prompt/commands/promptCommand.mjs b/canvas_editor/static/js/editor/command_prompt/commands/promptCommand.mjs deleted file mode 100644 index 5b279194..00000000 --- a/canvas_editor/static/js/editor/command_prompt/commands/promptCommand.mjs +++ /dev/null @@ -1,136 +0,0 @@ -import { methodMustBeImplementedError } from "message_dict"; -import { CommandPrompt } from "../commandPrompt.mjs"; - -/** - * Parent class of all prompt commands - */ -export class PromptCommand extends HTMLElement { - /** - * The score of how good the current input of the command prompt matches the command. - * Is used to filter and sort all of the currently available commands. - * @type {number} - */ - matchScore = 0; - - #commandName; - - /** - * An array containing all the indices of the chars that should be highlighted - * @type {number[] | null} - */ - #selectedCharsIndices = null; - #commandElem; - #commandPrompt; - - /** - * Creates a new prompt command - * @param {string} name the name of the command - * @param {CommandPrompt} commandPrompt the command prompt in use for this command - * @param {string} [keybind] the keybinding of the command - */ - constructor(name, commandPrompt, keybind = null) { - super(); - this.#commandName = name; - this.#commandPrompt = commandPrompt; - this.classList.add("rounded-2", "p-1", "px-2", "d-flex", "justify-content-between", "align-items-center"); - this.style.cursor = "pointer"; - - this.#commandElem = document.createElement("div"); - this.#commandElem.innerHTML = name; - this.appendChild(this.#commandElem); - - if (keybind) { - const keybindElem = document.createElement("div"); - keybindElem.innerHTML = keybind; - keybindElem.classList.add("rounded-2", "border", "p-0", "px-2"); - keybindElem.style.fontSize = "80%"; - this.appendChild(keybindElem); - } - - // execute on click - this.addEventListener("click", () => { - this.execute(); - this.#commandPrompt.hide(); - }); - - // select this element on hover - this.addEventListener("mousemove", () => { - this.#commandPrompt.selectCommand(this.#commandPrompt.currentlyAvailableCommands.indexOf(this)); - }); - } - - /** - * Returns the name of the command. - * @returns {string} the name of the command - */ - get commandName() { - return this.#commandName; - } - - /** - * Set the indices for the chars that should be highlighted for the search functionality - * @param {number[]} chars is an array of char indexes you want to be selected - */ - set selectedCharsIndices(chars) { - this.#selectedCharsIndices = chars; - } - - /** - * Calculates the new match score of this command. - * @param {number[] | null} indices an array containing all the indices of the selected chars - * by the searching algorithm. - */ - calculateMatchScore(indices) { - if (indices != null) { - if (indices.length == 0) { - this.matchScore = 0; - } else if (indices.length == 1) { - this.matchScore = 1; - } else { - this.matchScore = indices.at(-1) - indices[0]; - } - } - } - - /** - * Makes all the characters specified by 'selectedChars' bold. - */ - formatCommandName() { - if (this.#selectedCharsIndices) { - let formattedName = ""; - let lastIndex = 0; - for (const index of this.#selectedCharsIndices) { - formattedName += this.#commandName.slice(lastIndex, index); - formattedName += `${this.#commandName[index]}`; - lastIndex = index + 1; - } - formattedName += this.#commandName.slice(lastIndex); - this.#commandElem.innerHTML = formattedName; - } else { - this.#commandElem.innerHTML = this.#commandName; - } - } - - /** - * Selects this command (adds a background color). - */ - select() { - this.classList.add("bg-primary", "text-white"); - this.scrollIntoView({ block: "nearest" }); - } - - /** - * Unselects this command (removes the background color). - */ - unselect() { - this.classList.remove("bg-primary", "text-white"); - } - - /** - * Executes the prompt command. - */ - execute() { - throw new Error(methodMustBeImplementedError); - } -} -customElements.define("prompt-command", PromptCommand); From 35f578ed38cb90403ee6bf86ee951e12bfbb9d6f Mon Sep 17 00:00:00 2001 From: Lisann Engel Date: Sun, 30 Nov 2025 18:27:02 +0100 Subject: [PATCH 4/5] fix some imports --- .../editor/templates/editor/editor.html | 2 +- .../command_prompt/commands/promptCommand.mjs | 136 ++++++++++++++++++ .../static/js/projectOverviewManager.mjs | 2 +- 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 canvas_editor/static/js/editor/command_prompt/commands/promptCommand.mjs diff --git a/canvas_editor/editor/templates/editor/editor.html b/canvas_editor/editor/templates/editor/editor.html index 1d258b42..85aa4f09 100644 --- a/canvas_editor/editor/templates/editor/editor.html +++ b/canvas_editor/editor/templates/editor/editor.html @@ -37,7 +37,7 @@ "inspectorComponents": "{% static 'js/editor/inspectorComponents.mjs' %}", "inspectorClass": "{% static 'js/editor/inspector.mjs' %}", "previewHandler": "{% static 'js/editor/previewHandler.mjs' %}", - "projectSettingsManager": "{% static 'js/projectSettingsManager.mjs' %}", + "projectSettingsManager": "{% static 'js/editor/projectSettingsManager.mjs' %}", "projectOverviewManager": "{% static 'js/editor/projectOverviewManager.mjs' %}", "createCommands": "{% static 'js/commands/createCommands.mjs' %}", "navBar": "{% static 'js/editor/navbar.mjs' %}", diff --git a/canvas_editor/static/js/editor/command_prompt/commands/promptCommand.mjs b/canvas_editor/static/js/editor/command_prompt/commands/promptCommand.mjs new file mode 100644 index 00000000..5b279194 --- /dev/null +++ b/canvas_editor/static/js/editor/command_prompt/commands/promptCommand.mjs @@ -0,0 +1,136 @@ +import { methodMustBeImplementedError } from "message_dict"; +import { CommandPrompt } from "../commandPrompt.mjs"; + +/** + * Parent class of all prompt commands + */ +export class PromptCommand extends HTMLElement { + /** + * The score of how good the current input of the command prompt matches the command. + * Is used to filter and sort all of the currently available commands. + * @type {number} + */ + matchScore = 0; + + #commandName; + + /** + * An array containing all the indices of the chars that should be highlighted + * @type {number[] | null} + */ + #selectedCharsIndices = null; + #commandElem; + #commandPrompt; + + /** + * Creates a new prompt command + * @param {string} name the name of the command + * @param {CommandPrompt} commandPrompt the command prompt in use for this command + * @param {string} [keybind] the keybinding of the command + */ + constructor(name, commandPrompt, keybind = null) { + super(); + this.#commandName = name; + this.#commandPrompt = commandPrompt; + this.classList.add("rounded-2", "p-1", "px-2", "d-flex", "justify-content-between", "align-items-center"); + this.style.cursor = "pointer"; + + this.#commandElem = document.createElement("div"); + this.#commandElem.innerHTML = name; + this.appendChild(this.#commandElem); + + if (keybind) { + const keybindElem = document.createElement("div"); + keybindElem.innerHTML = keybind; + keybindElem.classList.add("rounded-2", "border", "p-0", "px-2"); + keybindElem.style.fontSize = "80%"; + this.appendChild(keybindElem); + } + + // execute on click + this.addEventListener("click", () => { + this.execute(); + this.#commandPrompt.hide(); + }); + + // select this element on hover + this.addEventListener("mousemove", () => { + this.#commandPrompt.selectCommand(this.#commandPrompt.currentlyAvailableCommands.indexOf(this)); + }); + } + + /** + * Returns the name of the command. + * @returns {string} the name of the command + */ + get commandName() { + return this.#commandName; + } + + /** + * Set the indices for the chars that should be highlighted for the search functionality + * @param {number[]} chars is an array of char indexes you want to be selected + */ + set selectedCharsIndices(chars) { + this.#selectedCharsIndices = chars; + } + + /** + * Calculates the new match score of this command. + * @param {number[] | null} indices an array containing all the indices of the selected chars + * by the searching algorithm. + */ + calculateMatchScore(indices) { + if (indices != null) { + if (indices.length == 0) { + this.matchScore = 0; + } else if (indices.length == 1) { + this.matchScore = 1; + } else { + this.matchScore = indices.at(-1) - indices[0]; + } + } + } + + /** + * Makes all the characters specified by 'selectedChars' bold. + */ + formatCommandName() { + if (this.#selectedCharsIndices) { + let formattedName = ""; + let lastIndex = 0; + for (const index of this.#selectedCharsIndices) { + formattedName += this.#commandName.slice(lastIndex, index); + formattedName += `${this.#commandName[index]}`; + lastIndex = index + 1; + } + formattedName += this.#commandName.slice(lastIndex); + this.#commandElem.innerHTML = formattedName; + } else { + this.#commandElem.innerHTML = this.#commandName; + } + } + + /** + * Selects this command (adds a background color). + */ + select() { + this.classList.add("bg-primary", "text-white"); + this.scrollIntoView({ block: "nearest" }); + } + + /** + * Unselects this command (removes the background color). + */ + unselect() { + this.classList.remove("bg-primary", "text-white"); + } + + /** + * Executes the prompt command. + */ + execute() { + throw new Error(methodMustBeImplementedError); + } +} +customElements.define("prompt-command", PromptCommand); diff --git a/canvas_editor/static/js/projectOverviewManager.mjs b/canvas_editor/static/js/projectOverviewManager.mjs index 16f7086c..ef937963 100644 --- a/canvas_editor/static/js/projectOverviewManager.mjs +++ b/canvas_editor/static/js/projectOverviewManager.mjs @@ -1,4 +1,4 @@ -import { getCookie } from "../utils/cookieUtils.mjs"; +import { getCookie } from "./utils/cookieUtils.mjs"; /** * Handles the project overview page */ From 32c4aee71e981b5cbc2ecb8c6df522a409b71f30 Mon Sep 17 00:00:00 2001 From: Lisann Engel Date: Sun, 30 Nov 2025 18:41:53 +0100 Subject: [PATCH 5/5] delete file that was deleted in main in the meantime --- .../static/js/editor/promptCommands.mjs | 598 ------------------ 1 file changed, 598 deletions(-) delete mode 100644 canvas_editor/static/js/editor/promptCommands.mjs diff --git a/canvas_editor/static/js/editor/promptCommands.mjs b/canvas_editor/static/js/editor/promptCommands.mjs deleted file mode 100644 index 467d1467..00000000 --- a/canvas_editor/static/js/editor/promptCommands.mjs +++ /dev/null @@ -1,598 +0,0 @@ -import { Modal } from "bootstrap"; -import { CommandPrompt } from "commandPrompt"; -import { abstractClassError, methodMustBeImplementedError } from "message_dict"; -import { ObjectManager } from "objectManager"; -import { getCookie } from "../utils/cookieUtils.mjs"; - -/** - * Parent class of all prompt commands - */ -export class PromptCommand extends HTMLElement { - #commandName; - #occurrenceLength = null; - /** - * @type {number[]} - */ - #selectedChars = null; - #commandElem; - #commandPrompt; - - /** - * Creates a new prompt command - * @param {string} name the name of the command - * @param {CommandPrompt} commandPrompt the command prompt in use for this command - * @param {string} [keybind] the keybinding of the command - */ - constructor(name, commandPrompt, keybind = null) { - super(); - this.#commandName = name; - this.#commandPrompt = commandPrompt; - this.classList.add("rounded-2", "p-1", "px-2", "d-flex", "justify-content-between", "align-items-center"); - this.style.cursor = "pointer"; - - this.#commandElem = document.createElement("div"); - this.#commandElem.innerHTML = name; - this.appendChild(this.#commandElem); - - if (keybind) { - const keybindElem = document.createElement("div"); - keybindElem.innerHTML = keybind; - keybindElem.classList.add("rounded-2", "border", "p-0", "px-2"); - keybindElem.style.fontSize = "80%"; - this.appendChild(keybindElem); - } - - // execute on click - this.addEventListener("click", () => { - this.execute(); - this.#commandPrompt.hide(); - }); - - // select this element on hover - this.addEventListener("mousemove", () => { - this.#commandPrompt.selectCommand(this.#commandPrompt.currentlyAvailableCommands.indexOf(this)); - }); - } - - /** - * Returns the name of the command. - * @returns {string} the name of the command - */ - get commandName() { - return this.#commandName; - } - - /** - * Returns the length of the occurrence that got selected by the searching algorithm. - * @returns {number|null} the length of the occurrence or null if no occurrence got selected - */ - get occurrenceLength() { - return this.#occurrenceLength; - } - - /** - * Sets the length of the occurrence that got selected by the searching algorithm. - * @param {number|null} length the length of the occurrence or null if no occurrence got selected - */ - set occurrenceLength(length) { - this.#occurrenceLength = length; - } - - /** - * Returns an array of all indexes of characters that got selected by the searching algorithm. - * Use for highlighting them. - * @param {number[]} chars is an array of char indexes you want to be selected - */ - set selectedChars(chars) { - this.#selectedChars = chars; - if (this.#selectedChars !== null) { - if (this.#selectedChars.length > 1) { - this.#occurrenceLength = this.#selectedChars[this.#selectedChars.length - 1] - this.#selectedChars[0]; - } else { - this.#occurrenceLength = 0; - } - } - } - - /** - * Makes all the characters specified by 'selectedChars' bold. - */ - formatCommandName() { - if (this.#selectedChars) { - let formattedName = ""; - let lastIndex = 0; - this.#selectedChars.forEach((index) => { - formattedName += this.#commandName.slice(lastIndex, index); - formattedName += `${this.#commandName[index]}`; - lastIndex = index + 1; - }); - formattedName += this.#commandName.slice(lastIndex); - this.#commandElem.innerHTML = formattedName; - } else { - this.#commandElem.innerHTML = this.#commandName; - } - } - - /** - * Selects this command (adds a background color). - */ - select() { - this.classList.add("bg-primary", "text-white"); - this.scrollIntoView({ block: "nearest" }); - } - - /** - * Unselects this command (removes the background color). - */ - unselect() { - this.classList.remove("bg-primary", "text-white"); - } - - /** - * Executes the prompt command. - */ - execute() { - throw new Error(methodMustBeImplementedError); - } -} - -/** - * Parent class for all theme related prompt commands - */ -export class ThemePromptCommand extends PromptCommand { - /** - * Create a new theme command - * @param {string} description the description of the command - * @param {CommandPrompt} commandPrompt the command prompt in use - */ - constructor(description, commandPrompt) { - if (new.target === ThemePromptCommand) { - throw new Error(abstractClassError(ThemePromptCommand)); - } - super(description, commandPrompt); - } - - /** - * Executes the theme command. - * @throws {Error} if the method is not implemented in a subclass - */ - execute() { - throw new Error(methodMustBeImplementedError); - } - - /** - * Sets the theme of the application - * @param {"light" | "dark" | "auto"} theme - The theme to set. Can be "light", "dark", or "auto". - */ - setTheme(theme) { - // store the theme - localStorage.setItem("theme", theme); - - // update the theme - if (theme === "auto") { - document.documentElement.setAttribute( - "data-bs-theme", - window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light", - ); - } else { - document.documentElement.setAttribute("data-bs-theme", theme); - } - - // update the settings - const themeSelect = document.getElementById("theme-select"); - - if (!themeSelect) { - return; - } - - switch (theme) { - case "light": - //@ts-ignore - themeSelect.value = "light"; - break; - case "dark": - //@ts-ignore - themeSelect.value = "dark"; - break; - default: - //@ts-ignore - themeSelect.value = "auto"; - break; - } - } -} - -/** - * Prompt command to enable light mode - */ -export class LightModePromptCommand extends ThemePromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Use light mode", commandPrompt); - } - - /** - * Executes the light mode command. - */ - execute() { - this.setTheme("light"); - } -} - -/** - * Prompt command to enable dark mode - */ -export class DarkModePromptCommand extends ThemePromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Use dark mode", commandPrompt); - } - - /** - * Executes the dark mode command. - */ - execute() { - this.setTheme("dark"); - } -} - -/** - * Prompt command to enable auto mode - */ -export class AutoModePromptCommand extends ThemePromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Use auto mode", commandPrompt); - } - - /** - * Executes the auto mode command. - */ - execute() { - this.setTheme("auto"); - } -} - -/** - * Prompt command to add a heliostat to the scene - */ -export class AddHeliostatPromptCommand extends PromptCommand { - #objectManager; - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - * @param {ObjectManager} objectManager - The ObjectManager instance to manage the creation of objects. - */ - constructor(commandPrompt, objectManager) { - super("Add heliostat", commandPrompt); - this.#objectManager = objectManager; - } - - /** - * Executes the add heliostat command. - */ - execute() { - this.#objectManager.createHeliostat(); - } -} - -/** - * Prompt command to add a receiver to the scene - */ -export class AddReceiverPromptCommand extends PromptCommand { - #objectManager; - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - * @param {ObjectManager} objectManager - The ObjectManager instance to manage the creation of objects. - */ - constructor(commandPrompt, objectManager) { - super("Add receiver", commandPrompt); - this.#objectManager = objectManager; - } - - /** - * Executes the add receiver command. - */ - execute() { - this.#objectManager.createReceiver(); - } -} - -/** - * Prompt command to add a light source to the scene - */ -export class AddLightSourcePromptCommand extends PromptCommand { - #objectManager; - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - * @param {ObjectManager} objectManager - The ObjectManager instance to manage the creation of objects. - */ - constructor(commandPrompt, objectManager) { - super("Add light source", commandPrompt); - this.#objectManager = objectManager; - } - - /** - * Executes the add light source command. - */ - execute() { - this.#objectManager.createLightSource(); - } -} - -/** - * Prompt command to toggle fullscreen - */ -export class ToggleFullscreenPromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Toggle fullscreen", commandPrompt, "F11"); - } - - /** - * Executes the toggle fullscreen command. - */ - execute() { - if (navigator.userAgent.indexOf("Safari") > -1) { - if (document.webkitFullscreenElement === null) { - document.documentElement.webkitRequestFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } - return; - } - - if (document.fullscreenElement === null) { - document.documentElement.requestFullscreen(); - } else if (document.exitFullscreen) { - document.exitFullscreen(); - } - } -} - -/** - * Prompt command to open the new job pane to the current project - */ -export class ExportProjectPromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Export project", commandPrompt); - } - - /** - * Executes the export project command. - */ - execute() { - let modal = new Modal(document.getElementById("loadingModal")); - modal.show(); - - const projectName = window.location.pathname.split("/")[2]; - - fetch(window.location + "/download", { - method: "GET", - headers: { - "Content-Type": "application/json", - "X-CSRFToken": getCookie("csrftoken"), - }, - }) - .then((response) => { - // Trigger file download after response - return response.blob(); - }) - .then((data) => { - let link = document.createElement("a"); - - link.href = URL.createObjectURL(data); - link.download = projectName + `.h5`; - link.click(); - - // After download, close modal and redirect - modal.hide(); - window.location.reload(); - }) - .catch((error) => { - console.error("Error:", error); - modal.hide(); - }); - } -} - -/** - * Prompt command to render the current project - */ -export class RenderProjectPromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Render project", commandPrompt); - } - - /** - * Executes the render project command. - */ - execute() { - const jobModal = new Modal(document.getElementById("startJobModal")); - jobModal.show(); - - document.getElementById("startJobModal").addEventListener("shown.bs.modal", () => { - document.getElementById("createNewJob").focus(); - }); - } -} - -/** - * Prompt command to open the settings pane - */ -export class OpenSettingsPromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Open settings", commandPrompt); - } - - /** - * Executes the open settings command. - */ - execute() { - const settingsModal = new Modal(document.getElementById("settings")); - settingsModal.show(); - } -} - -/** - * Prompt command to open the job interface pane - */ -export class OpenJobInterfacePromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Open job interface", commandPrompt); - } - - /** - * Executes the open job interface command. - */ - execute() { - const jobInterfaceModal = new Modal(document.getElementById("jobInterface")); - jobInterfaceModal.show(); - - document.getElementById("jobInterface").addEventListener("shown.bs.modal", () => { - document.getElementById("createNewJob").focus(); - }); - } -} - -/** - * Prompt command to open the keybindings help page - */ -export class OpenKeybindsPromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Open keybindings help page", commandPrompt); - } - - /** - * Executes the open keybindings command. - */ - execute() { - const keybindingsModal = new Modal(document.getElementById("keyboardModal")); - keybindingsModal.show(); - } -} - -/** - * Prompt command to logout the user - */ -export class LogoutPromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Logout", commandPrompt); - } - - /** - * Executes the logout command. - */ - execute() { - fetch(window.location.origin + "/logout/", { - method: "POST", - headers: { - "Content-Type": "application/json", - "X-CSRFToken": getCookie("csrftoken"), - }, - }).then(() => { - window.location.href = window.location.origin; - }); - } -} - -/** - * Prompt command to create a new project - */ -export class NewProjectPromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Create new project", commandPrompt); - } - - /** - * Executes the new project command. - */ - execute() { - const newProjectModal = new Modal(document.getElementById("createNewProject")); - newProjectModal.show(); - - document.getElementById("createNewProject").addEventListener("shown.bs.modal", () => { - document.getElementById("id_name").focus(); - }); - } -} - -/** - * Prompt command to open an existing project - */ -export class OpenProjectPromptCommand extends PromptCommand { - /** - * Create this prompt command - * @param {CommandPrompt} commandPrompt the command prompt that handles this command - */ - constructor(commandPrompt) { - super("Open exisiting project", commandPrompt); - } - - /** - * Executes the open project command. - */ - execute() { - const newProjectModal = new Modal(document.getElementById("openProject")); - newProjectModal.show(); - } -} - -// define the new HTML elements -customElements.define("light-mode-prompt-command", LightModePromptCommand); -customElements.define("dark-mode-prompt-command", DarkModePromptCommand); -customElements.define("auto-mode-prompt-command", AutoModePromptCommand); -customElements.define("add-heliostat-prompt-command", AddHeliostatPromptCommand); -customElements.define("add-receiver-prompt-command", AddReceiverPromptCommand); -customElements.define("add-light-source-prompt-command", AddLightSourcePromptCommand); -customElements.define("toggle-fullscreen-prompt-command", ToggleFullscreenPromptCommand); -customElements.define("export-project-prompt-command", ExportProjectPromptCommand); -customElements.define("render-project-prompt-command", RenderProjectPromptCommand); -customElements.define("open-settings-prompt-command", OpenSettingsPromptCommand); -customElements.define("open-job-interface-prompt-command", OpenJobInterfacePromptCommand); -customElements.define("open-keybings-prompt-command", OpenKeybindsPromptCommand); -customElements.define("logout-prompt-command", LogoutPromptCommand); -customElements.define("new-project-prompt-command", NewProjectPromptCommand); -customElements.define("open-project-prompt-command", OpenProjectPromptCommand);