Merge pull request 'chore: Update branch' (#4) from 3002833/Backend:main into main
Reviewed-on: #4main
commit
fd5252bf0e
|
@ -77,16 +77,12 @@ function updateSecondarySkillsDropdown(secondarySkills, selectElement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
selectElement.appendChild(
|
selectElement.appendChild(
|
||||||
createOption("Select a secondary skill", true, true)
|
createOption("Bitte eine Fähigkeit auswählen", true, true)
|
||||||
);
|
);
|
||||||
|
|
||||||
secondarySkills.forEach((skill) => {
|
|
||||||
selectElement.appendChild(
|
|
||||||
createOption(skill.description, false, false, skill.ssid)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
selectElement.disabled = false;
|
selectElement.disabled = false;
|
||||||
|
|
||||||
|
initSkillSelector(secondarySkills);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,6 +103,15 @@ function initializeSkillsDropdowns() {
|
||||||
|
|
||||||
async function fetchSecondarySkills() {
|
async function fetchSecondarySkills() {
|
||||||
const primarySkillSelect = document.getElementById("primarySkill");
|
const primarySkillSelect = document.getElementById("primarySkill");
|
||||||
|
|
||||||
|
// If there is more than one selector delete all except the first one
|
||||||
|
const skillSelectors = document.querySelectorAll(".skill-selector");
|
||||||
|
if (skillSelectors.length > 1) {
|
||||||
|
for (let i = 1; i < skillSelectors.length; i++) {
|
||||||
|
skillSelectors[i].remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const secondarySkillSelect = document.getElementById("secondarySkill");
|
const secondarySkillSelect = document.getElementById("secondarySkill");
|
||||||
const selectedPrimarySkillId = primarySkillSelect.value;
|
const selectedPrimarySkillId = primarySkillSelect.value;
|
||||||
|
|
||||||
|
@ -122,64 +127,64 @@ async function fetchSecondarySkills() {
|
||||||
secondarySkillSelect.innerHTML = "";
|
secondarySkillSelect.innerHTML = "";
|
||||||
secondarySkillSelect.appendChild(createOption("Loading...", true, true));
|
secondarySkillSelect.appendChild(createOption("Loading...", true, true));
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/secondary-skill/from-primary-skill?psid=${selectedPrimarySkillId}`,
|
`/api/secondary-skill/from-primary-skill?psid=${selectedPrimarySkillId}`,
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
},
|
},
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const errorMessage = `Server returned ${response.status}: ${response.statusText}`;
|
|
||||||
throw new Error(errorMessage);
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const responseText = await response.text();
|
if (!response.ok) {
|
||||||
console.log("Response Text:", responseText);
|
const errorMessage = `Server returned ${response.status}: ${response.statusText}`;
|
||||||
|
throw new Error(errorMessage);
|
||||||
let secondarySkills;
|
|
||||||
try {
|
|
||||||
secondarySkills = JSON.parse(responseText);
|
|
||||||
} catch (jsonError) {
|
|
||||||
throw new Error(`Failed to parse JSON: ${jsonError.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSecondarySkillsDropdown(secondarySkills, secondarySkillSelect);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching secondary skills:", error);
|
|
||||||
secondarySkillSelect.innerHTML = "";
|
|
||||||
secondarySkillSelect.appendChild(
|
|
||||||
createOption("Error loading secondary skills", true, true)
|
|
||||||
);
|
|
||||||
secondarySkillSelect.disabled = true;
|
|
||||||
|
|
||||||
let userMessage = "";
|
|
||||||
if (error.name === "TypeError" && !window.navigator.onLine) {
|
|
||||||
userMessage =
|
|
||||||
"No internet connection. Please check your network and try again.";
|
|
||||||
} else if (error.message.includes("Server returned 404")) {
|
|
||||||
userMessage =
|
|
||||||
"The selected primary skill was not found. Please refresh and try again.";
|
|
||||||
} else if (error.message.includes("Server returned 500")) {
|
|
||||||
userMessage = "Server error occurred. Please try again in a few minutes.";
|
|
||||||
} else if (error.message.includes("Server returned 403")) {
|
|
||||||
userMessage =
|
|
||||||
"You don't have permission to access these skills. Please contact support.";
|
|
||||||
} else {
|
|
||||||
userMessage = `Failed to load secondary skills: ${error.message}`;
|
|
||||||
}
|
|
||||||
showTemporaryMessage(
|
|
||||||
userMessage,
|
|
||||||
"error",
|
|
||||||
5000,
|
|
||||||
secondarySkillSelect.parentNode
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const responseText = await response.text();
|
||||||
|
console.log("Response Text:", responseText);
|
||||||
|
|
||||||
|
let secondarySkills;
|
||||||
|
try {
|
||||||
|
secondarySkills = JSON.parse(responseText);
|
||||||
|
} catch (jsonError) {
|
||||||
|
throw new Error(`Failed to parse JSON: ${jsonError.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSecondarySkillsDropdown(secondarySkills, secondarySkillSelect);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Error fetching secondary skills:", error);
|
||||||
|
// secondarySkillSelect.innerHTML = "";
|
||||||
|
// secondarySkillSelect.appendChild(
|
||||||
|
// createOption("Error loading secondary skills", true, true)
|
||||||
|
// );
|
||||||
|
// secondarySkillSelect.disabled = true;
|
||||||
|
|
||||||
|
// let userMessage = "";
|
||||||
|
// if (error.name === "TypeError" && !window.navigator.onLine) {
|
||||||
|
// userMessage =
|
||||||
|
// "No internet connection. Please check your network and try again.";
|
||||||
|
// } else if (error.message.includes("Server returned 404")) {
|
||||||
|
// userMessage =
|
||||||
|
// "The selected primary skill was not found. Please refresh and try again.";
|
||||||
|
// } else if (error.message.includes("Server returned 500")) {
|
||||||
|
// userMessage = "Server error occurred. Please try again in a few minutes.";
|
||||||
|
// } else if (error.message.includes("Server returned 403")) {
|
||||||
|
// userMessage =
|
||||||
|
// "You don't have permission to access these skills. Please contact support.";
|
||||||
|
// } else {
|
||||||
|
// userMessage = `Failed to load secondary skills: ${error.message}`;
|
||||||
|
// }
|
||||||
|
// showTemporaryMessage(
|
||||||
|
// userMessage,
|
||||||
|
// "error",
|
||||||
|
// 5000,
|
||||||
|
// secondarySkillSelect.parentNode
|
||||||
|
// );
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", initializeSkillsDropdowns);
|
document.addEventListener("DOMContentLoaded", initializeSkillsDropdowns);
|
||||||
|
|
|
@ -1,31 +1,129 @@
|
||||||
function handleSecondarySkillSelection(selectElement) {
|
/**
|
||||||
const skillCreator = document.querySelector("#skillCreator");
|
* Creates an option element for a select dropdown
|
||||||
const newSkillSelector = selectElement.closest(".row").cloneNode(true);
|
*/
|
||||||
const selectedOptions = Array.from(
|
var secondarySkillsList = {};
|
||||||
document.querySelectorAll("#skillCreator select[name='ssid']")
|
|
||||||
).map((select) => select.value);
|
|
||||||
|
|
||||||
// Filter out already selected options
|
//====================================================================================
|
||||||
const secondarySkillSelect =
|
/**
|
||||||
newSkillSelector.querySelector("#secondarySkill");
|
* Initializes the skill selector with the available secondary skills
|
||||||
const options = Array.from(secondarySkillSelect.options);
|
* @param {SecondarySkill[]} secondarySkills - Array of secondary skills from the API
|
||||||
options.forEach((option) => {
|
*/
|
||||||
if (selectedOptions.includes(option.value)) {
|
function initSkillSelector(secondarySkills) {
|
||||||
option.remove();
|
secondarySkillsList = secondarySkills;
|
||||||
|
rebuildOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
//====================================================================================
|
||||||
|
/**
|
||||||
|
* Populates the secondary skills dropdowns with the available options
|
||||||
|
* and updates the options based on the selected values in the other dropdowns
|
||||||
|
*/
|
||||||
|
function rebuildOptions() {
|
||||||
|
// Get all secondary skill dropdowns
|
||||||
|
const secondarySkillSelects = document.querySelectorAll("#secondarySkill");
|
||||||
|
|
||||||
|
// Make a list with all options that are currently selected
|
||||||
|
const selectedOptions = [];
|
||||||
|
secondarySkillSelects.forEach((select) => {
|
||||||
|
selectedOptions.push(select.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make a list with all options that are not selected
|
||||||
|
const availableOptions = [];
|
||||||
|
secondarySkillsList.forEach((skill) => {
|
||||||
|
if (!selectedOptions.includes(skill.ssid.toString())) {
|
||||||
|
availableOptions.push(skill);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check if there are any options left to select
|
// Iterate over all secondary skill dropdowns
|
||||||
if (secondarySkillSelect.options.length <= 1) {
|
secondarySkillSelects.forEach((select) => {
|
||||||
return; // Exit if no options left
|
// Save the current selected value
|
||||||
|
const selectedValue = select.value;
|
||||||
|
const selectedElement = select.querySelector(
|
||||||
|
`option[value="${selectedValue}"]`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clear the dropdown
|
||||||
|
select.innerHTML = "";
|
||||||
|
|
||||||
|
// Add selectedElement back to the dropdown
|
||||||
|
select.appendChild(selectedElement);
|
||||||
|
|
||||||
|
// Add all other options
|
||||||
|
availableOptions.forEach((skill) => {
|
||||||
|
select.appendChild(
|
||||||
|
createOption(skill.description, false, false, skill.ssid)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//====================================================================================
|
||||||
|
/**
|
||||||
|
* Handles the selection of a secondary skill in a dropdown
|
||||||
|
* @param {HTMLSelectElement} selectElement - The secondary skill dropdown
|
||||||
|
*/
|
||||||
|
function handleSecondarySkillSelection(selectElement) {
|
||||||
|
const skillCreator = document.querySelector("#skillCreator");
|
||||||
|
const skillSelectors = document.querySelectorAll(".skill-selector");
|
||||||
|
|
||||||
|
// Check if all existing selectors have an option selected
|
||||||
|
const allSelected = Array.from(skillSelectors).every((selector) => {
|
||||||
|
const secondarySkillSelect = selector.querySelector("#secondarySkill");
|
||||||
|
return secondarySkillSelect.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test if we can have more selectors
|
||||||
|
if (!allSelected || skillSelectors.length >= secondarySkillsList.length) {
|
||||||
|
rebuildOptions();
|
||||||
|
updateRemoveButtonsVisibility();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
newSkillSelector.querySelector("#secondarySkill").value = "";
|
// Add a new skill selector
|
||||||
|
addSkillSelector(selectElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
//====================================================================================
|
||||||
|
/*
|
||||||
|
* Creates an option element for a select dropdown
|
||||||
|
*/
|
||||||
|
function addSkillSelector() {
|
||||||
|
// Clone the first skill selector
|
||||||
|
const newSkillSelector = document
|
||||||
|
.querySelector(".skill-selector")
|
||||||
|
.cloneNode(true);
|
||||||
|
|
||||||
|
// Clear the selected value and set the default level
|
||||||
newSkillSelector.querySelector("#level").value = "1";
|
newSkillSelector.querySelector("#level").value = "1";
|
||||||
newSkillSelector.querySelector(".btn-default").disabled = true;
|
newSkillSelector.querySelector(".btn-default").style.display = "none";
|
||||||
|
|
||||||
|
// Clear the secondary skill dropdown and set it to the default value
|
||||||
|
const secondarySkillSelect =
|
||||||
|
newSkillSelector.querySelector("#secondarySkill");
|
||||||
|
secondarySkillSelect.innerHTML = "";
|
||||||
|
secondarySkillSelect.appendChild(
|
||||||
|
createOption("Bitte eine Fähigkeit auswählen", true, true)
|
||||||
|
);
|
||||||
|
|
||||||
const skillSelectorList = document.querySelector("#skillSelectorList");
|
const skillSelectorList = document.querySelector("#skillSelectorList");
|
||||||
skillSelectorList.appendChild(newSkillSelector);
|
skillSelectorList.appendChild(newSkillSelector);
|
||||||
|
|
||||||
|
// Delete the existing options and set it to the default value
|
||||||
|
rebuildOptions();
|
||||||
|
|
||||||
|
// Add event listener to the new "Entfernen" button
|
||||||
|
newSkillSelector
|
||||||
|
.querySelector(".btn-default")
|
||||||
|
.addEventListener("click", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
handleRemoveSkillButtonClick(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Append the new skill selector to the container
|
||||||
|
skillSelectorList.appendChild(newSkillSelector);
|
||||||
|
|
||||||
// Initialize star rating components for the new skill selector
|
// Initialize star rating components for the new skill selector
|
||||||
initializeStarRatingComponents();
|
initializeStarRatingComponents();
|
||||||
|
|
||||||
|
@ -33,21 +131,21 @@ function handleSecondarySkillSelection(selectElement) {
|
||||||
updateRemoveButtonsVisibility();
|
updateRemoveButtonsVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================================
|
||||||
|
/**
|
||||||
|
* Updates the visibility of the "Entfernen" buttons based on the number of skill selectors
|
||||||
|
*/
|
||||||
function updateRemoveButtonsVisibility() {
|
function updateRemoveButtonsVisibility() {
|
||||||
const skillSelectors = document.querySelectorAll(".skill-selector");
|
const skillSelectors = document.querySelectorAll(".skill-selector");
|
||||||
const removeButtons = document.querySelectorAll(".btn-default");
|
const removeButtons = document.querySelectorAll(".btn-default");
|
||||||
|
|
||||||
// Show "Entfernen" buttons only if there are at least two skill selectors
|
|
||||||
if (skillSelectors.length > 1) {
|
if (skillSelectors.length > 1) {
|
||||||
removeButtons.forEach((button) => {
|
removeButtons.forEach((button) => {
|
||||||
const selectElement = button
|
const selectElement = button
|
||||||
.closest(".skill-selector")
|
.closest(".skill-selector")
|
||||||
.querySelector("#secondarySkill");
|
?.querySelector("#secondarySkill");
|
||||||
if (selectElement.value) {
|
button.style.display =
|
||||||
button.style.display = "inline-block";
|
selectElement && selectElement.value ? "inline-block" : "none";
|
||||||
} else {
|
|
||||||
button.style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
removeButtons.forEach((button) => {
|
removeButtons.forEach((button) => {
|
||||||
|
@ -56,12 +154,29 @@ function updateRemoveButtonsVisibility() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================================
|
||||||
|
/**
|
||||||
|
* Handles the removal of a skill selector
|
||||||
|
* @param {HTMLButtonElement} button - The "Entfernen" button that was clicked
|
||||||
|
*/
|
||||||
function handleRemoveSkillButtonClick(button) {
|
function handleRemoveSkillButtonClick(button) {
|
||||||
const skillSelector = button.closest(".skill-selector");
|
const skillSelector = button.closest(".skill-selector");
|
||||||
skillSelector.remove();
|
skillSelector.remove();
|
||||||
updateRemoveButtonsVisibility();
|
|
||||||
|
// If there is no slector with an empty value left we need to add one
|
||||||
|
if (
|
||||||
|
document.querySelectorAll("#secondarySkill option[value='']").length === 0
|
||||||
|
) {
|
||||||
|
addSkillSelector();
|
||||||
|
} else {
|
||||||
|
rebuildOptions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================================
|
||||||
|
/**
|
||||||
|
* Creates an option element for a select dropdown
|
||||||
|
*/
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
// Initialize star rating components on page load
|
// Initialize star rating components on page load
|
||||||
initializeStarRatingComponents();
|
initializeStarRatingComponents();
|
||||||
|
|
Loading…
Reference in New Issue