mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-05 19:24:39 +00:00
fix: ensure the ability to override weightings
This commit is contained in:
@@ -84,9 +84,111 @@ function parseGrade(text: string): number {
|
|||||||
return letterToNumber[str] ?? 0;
|
return letterToNumber[str] ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatWeightDisplay(weighting: string): string {
|
||||||
|
return `${Number(weighting) % 1 === 0 ? Number(weighting) : weighting}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveWeightingOverride(
|
||||||
|
api: any,
|
||||||
|
assessmentID: string,
|
||||||
|
raw: string,
|
||||||
|
): { ok: boolean; error?: string } {
|
||||||
|
const trimmed = raw.trim();
|
||||||
|
if (trimmed === "") {
|
||||||
|
const { [assessmentID]: _, ...rest } = api.storage.weightingOverrides;
|
||||||
|
api.storage.weightingOverrides = rest;
|
||||||
|
document.dispatchEvent(new CustomEvent("betterseqta:overrideChanged"));
|
||||||
|
return { ok: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
const val = parseFloat(trimmed);
|
||||||
|
if (isNaN(val) || val < 0) {
|
||||||
|
return { ok: false, error: "Invalid. Must be 0 or greater" };
|
||||||
|
}
|
||||||
|
|
||||||
|
api.storage.weightingOverrides = {
|
||||||
|
...api.storage.weightingOverrides,
|
||||||
|
[assessmentID]: String(val),
|
||||||
|
};
|
||||||
|
document.dispatchEvent(new CustomEvent("betterseqta:overrideChanged"));
|
||||||
|
return { ok: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachWeightInputListeners(
|
||||||
|
input: HTMLInputElement,
|
||||||
|
api: any,
|
||||||
|
assessmentID: string,
|
||||||
|
) {
|
||||||
|
const save = () => {
|
||||||
|
const result = saveWeightingOverride(api, assessmentID, input.value);
|
||||||
|
input.style.borderColor = result.ok
|
||||||
|
? "rgba(128,128,128,0.35)"
|
||||||
|
: "rgba(255,80,80,0.6)";
|
||||||
|
};
|
||||||
|
|
||||||
|
input.addEventListener("blur", save);
|
||||||
|
input.addEventListener("keydown", (e) => {
|
||||||
|
if (e.key === "Enter") input.blur();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateWeightLabelContent(
|
||||||
|
weightLabel: HTMLElement,
|
||||||
|
weighting: string | undefined,
|
||||||
|
assessmentID: string | undefined,
|
||||||
|
api: any,
|
||||||
|
) {
|
||||||
|
const existingInput = weightLabel.querySelector(
|
||||||
|
".betterseqta-weight-input",
|
||||||
|
) as HTMLInputElement | null;
|
||||||
|
if (existingInput && document.activeElement === existingInput) return;
|
||||||
|
|
||||||
|
weightLabel.querySelector(".betterseqta-weight-value")?.remove();
|
||||||
|
weightLabel.querySelector(".betterseqta-weight-input")?.remove();
|
||||||
|
Array.from(weightLabel.childNodes)
|
||||||
|
.filter((node) => node.nodeType === Node.TEXT_NODE && node.textContent?.trim())
|
||||||
|
.forEach((node) => node.remove());
|
||||||
|
|
||||||
|
weightLabel.title = "";
|
||||||
|
|
||||||
|
if (weighting === "processing") {
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.className = "betterseqta-weight-value";
|
||||||
|
span.textContent = "...";
|
||||||
|
span.style.opacity = "0.5";
|
||||||
|
weightLabel.appendChild(span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weighting === "N/A" && assessmentID) {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "number";
|
||||||
|
input.min = "0";
|
||||||
|
input.step = "5";
|
||||||
|
input.className = "betterseqta-weight-input";
|
||||||
|
input.placeholder = "Set %";
|
||||||
|
input.setAttribute("aria-label", "Assessment weighting percentage");
|
||||||
|
input.style.cssText =
|
||||||
|
"width:52px;padding:1px 4px;border-radius:4px;border:1px solid rgba(128,128,128,0.35);background:rgba(128,128,128,0.08);color:inherit;font-size:inherit;outline:none;";
|
||||||
|
attachWeightInputListeners(input, api, assessmentID);
|
||||||
|
weightLabel.appendChild(input);
|
||||||
|
weightLabel.title = "Enter assessment weighting %";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.className = "betterseqta-weight-value";
|
||||||
|
span.textContent =
|
||||||
|
weighting && weighting !== "N/A"
|
||||||
|
? formatWeightDisplay(weighting)
|
||||||
|
: "N/A";
|
||||||
|
weightLabel.appendChild(span);
|
||||||
|
}
|
||||||
|
|
||||||
function createWeightLabel(
|
function createWeightLabel(
|
||||||
assessmentItem: Element,
|
assessmentItem: Element,
|
||||||
weighting: string | undefined,
|
weighting: string | undefined,
|
||||||
|
api: any,
|
||||||
) {
|
) {
|
||||||
let statsContainer = assessmentItem.querySelector(
|
let statsContainer = assessmentItem.querySelector(
|
||||||
`[class*='AssessmentItem__stats___'], .betterseqta-stats-container`,
|
`[class*='AssessmentItem__stats___'], .betterseqta-stats-container`,
|
||||||
@@ -112,20 +214,17 @@ function createWeightLabel(
|
|||||||
? "space-between"
|
? "space-between"
|
||||||
: "flex-end";
|
: "flex-end";
|
||||||
|
|
||||||
const displayText =
|
const title = assessmentItem
|
||||||
weighting && weighting !== "processing" && weighting !== "N/A"
|
.querySelector(`[class*='AssessmentItem__title___']`)
|
||||||
? `${Number(weighting) % 1 === 0 ? Number(weighting) : weighting}%`
|
?.textContent?.trim();
|
||||||
: "N/A";
|
const assessmentID = title ? api.storage.assessments?.[title] : undefined;
|
||||||
|
|
||||||
const existingLabel = statsContainer.querySelector(
|
const existingLabel = statsContainer.querySelector(
|
||||||
".betterseqta-weight-label",
|
".betterseqta-weight-label",
|
||||||
) as HTMLElement | null;
|
) as HTMLElement | null;
|
||||||
|
|
||||||
if (existingLabel) {
|
if (existingLabel) {
|
||||||
const textNodes = Array.from(existingLabel.childNodes).filter(
|
updateWeightLabelContent(existingLabel, weighting, assessmentID, api);
|
||||||
(node) => node.nodeType === Node.TEXT_NODE,
|
|
||||||
);
|
|
||||||
if (textNodes.length) textNodes[0].textContent = displayText;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,15 +256,7 @@ function createWeightLabel(
|
|||||||
const innerTextDiv = weightLabel.querySelector(`[class*='Label__innerText___']`);
|
const innerTextDiv = weightLabel.querySelector(`[class*='Label__innerText___']`);
|
||||||
if (innerTextDiv) innerTextDiv.textContent = "Weight";
|
if (innerTextDiv) innerTextDiv.textContent = "Weight";
|
||||||
|
|
||||||
const textNodes = Array.from(weightLabel.childNodes).filter(
|
updateWeightLabelContent(weightLabel, weighting, assessmentID, api);
|
||||||
(node) => node.nodeType === Node.TEXT_NODE,
|
|
||||||
);
|
|
||||||
if (textNodes.length) {
|
|
||||||
textNodes[0].textContent = displayText;
|
|
||||||
} else {
|
|
||||||
weightLabel.appendChild(document.createTextNode(displayText));
|
|
||||||
}
|
|
||||||
|
|
||||||
statsContainer.appendChild(weightLabel);
|
statsContainer.appendChild(weightLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +704,7 @@ export async function processAssessments(api: any, assessmentItems: Element[]) {
|
|||||||
: undefined;
|
: undefined;
|
||||||
const weighting = override ?? autoWeighting;
|
const weighting = override ?? autoWeighting;
|
||||||
|
|
||||||
createWeightLabel(assessmentItem, weighting);
|
createWeightLabel(assessmentItem, weighting, api);
|
||||||
|
|
||||||
const gradeElement = assessmentItem.querySelector(
|
const gradeElement = assessmentItem.querySelector(
|
||||||
`[class*='Thermoscore__text___']`,
|
`[class*='Thermoscore__text___']`,
|
||||||
@@ -760,13 +851,13 @@ function buildWeightingsTabContent(api: any, sheet: HTMLElement) {
|
|||||||
<span style="font-size:13px;opacity:${autoWeight != null ? "1" : "0.4"}">${autoWeight != null ? `${autoWeight}%` : "none"}</span>
|
<span style="font-size:13px;opacity:${autoWeight != null ? "1" : "0.4"}">${autoWeight != null ? `${autoWeight}%` : "none"}</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:flex;align-items:center;gap:12px">
|
<div style="display:flex;align-items:center;gap:12px">
|
||||||
<label for="betterseqta-weight-override" style="font-size:13px;opacity:0.7;flex-shrink:0">Override %</label>
|
<label for="betterseqta-weight-override" style="font-size:13px;opacity:0.7;flex-shrink:0">${weightingUnavailable ? "Weight %" : "Override %"}</label>
|
||||||
<input
|
<input
|
||||||
id="betterseqta-weight-override"
|
id="betterseqta-weight-override"
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
step="5"
|
step="5"
|
||||||
placeholder="${autoWeight ?? ""}"
|
placeholder="${weightingUnavailable ? "Enter weight" : autoWeight ?? ""}"
|
||||||
value="${override ?? ""}"
|
value="${override ?? ""}"
|
||||||
${!assessmentID ? "disabled" : ""}
|
${!assessmentID ? "disabled" : ""}
|
||||||
style="
|
style="
|
||||||
@@ -800,26 +891,22 @@ function buildWeightingsTabContent(api: any, sheet: HTMLElement) {
|
|||||||
const save = () => {
|
const save = () => {
|
||||||
const raw = input.value.trim();
|
const raw = input.value.trim();
|
||||||
if (raw === "") {
|
if (raw === "") {
|
||||||
const { [assessmentID]: _, ...rest } = api.storage.weightingOverrides;
|
const result = saveWeightingOverride(api, assessmentID, "");
|
||||||
api.storage.weightingOverrides = rest;
|
if (!result.ok) return;
|
||||||
|
input.style.borderColor = "rgba(128,128,128,0.3)";
|
||||||
} else {
|
} else {
|
||||||
const val = parseFloat(raw);
|
const result = saveWeightingOverride(api, assessmentID, raw);
|
||||||
if (isNaN(val) || val < 0) {
|
if (!result.ok) {
|
||||||
input.style.borderColor = "rgba(255,80,80,0.6)";
|
input.style.borderColor = "rgba(255,80,80,0.6)";
|
||||||
statusEl.textContent = "Invalid. Must be 0 or greater";
|
statusEl.textContent = result.error ?? "Invalid. Must be 0 or greater";
|
||||||
statusEl.style.color = "rgba(255,80,80,0.8)";
|
statusEl.style.color = "rgba(255,80,80,0.8)";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
input.style.borderColor = "rgba(128,128,128,0.3)";
|
input.style.borderColor = "rgba(128,128,128,0.3)";
|
||||||
api.storage.weightingOverrides = {
|
|
||||||
...api.storage.weightingOverrides,
|
|
||||||
[assessmentID]: String(val),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
statusEl.textContent = "Saved";
|
statusEl.textContent = "Saved";
|
||||||
statusEl.style.color = "";
|
statusEl.style.color = "";
|
||||||
setTimeout(() => (statusEl.textContent = ""), 2000);
|
setTimeout(() => (statusEl.textContent = ""), 2000);
|
||||||
document.dispatchEvent(new CustomEvent("betterseqta:overrideChanged"));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
input.addEventListener("blur", save);
|
input.addEventListener("blur", save);
|
||||||
@@ -873,12 +960,8 @@ export function injectWeightingsTab(api: any) {
|
|||||||
].join(" ");
|
].join(" ");
|
||||||
container.appendChild(newSheet);
|
container.appendChild(newSheet);
|
||||||
|
|
||||||
let populated = false;
|
|
||||||
newTab.addEventListener("click", () => {
|
newTab.addEventListener("click", () => {
|
||||||
if (!populated) {
|
buildWeightingsTabContent(api, newSheet);
|
||||||
buildWeightingsTabContent(api, newSheet);
|
|
||||||
populated = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const allTabs = Array.from(tabList.querySelectorAll("li"));
|
const allTabs = Array.from(tabList.querySelectorAll("li"));
|
||||||
|
|||||||
Reference in New Issue
Block a user