Add brand fields for drivers and cars
This commit is contained in:
95
src/app.js
95
src/app.js
@@ -86,11 +86,13 @@ const TRANSLATIONS = {
|
|||||||
"classes.title": "Klasser",
|
"classes.title": "Klasser",
|
||||||
"drivers.create": "Skapa förare",
|
"drivers.create": "Skapa förare",
|
||||||
"drivers.name_placeholder": "Förarnamn",
|
"drivers.name_placeholder": "Förarnamn",
|
||||||
|
"drivers.brand_placeholder": "Team / märke (valfritt)",
|
||||||
"drivers.transponder_placeholder": "Personlig transponder (valfritt)",
|
"drivers.transponder_placeholder": "Personlig transponder (valfritt)",
|
||||||
"drivers.add": "Lägg till förare",
|
"drivers.add": "Lägg till förare",
|
||||||
"drivers.title": "Förare",
|
"drivers.title": "Förare",
|
||||||
"cars.create": "Skapa bil",
|
"cars.create": "Skapa bil",
|
||||||
"cars.name_placeholder": "Bilnamn eller nummer",
|
"cars.name_placeholder": "Bilnamn eller nummer",
|
||||||
|
"cars.brand_placeholder": "Märke / modell (valfritt)",
|
||||||
"cars.transponder_placeholder": "Bilens transponder",
|
"cars.transponder_placeholder": "Bilens transponder",
|
||||||
"cars.add": "Lägg till bil",
|
"cars.add": "Lägg till bil",
|
||||||
"cars.title": "Bilar",
|
"cars.title": "Bilar",
|
||||||
@@ -460,6 +462,7 @@ const TRANSLATIONS = {
|
|||||||
"settings.sync_now": "Synka nu",
|
"settings.sync_now": "Synka nu",
|
||||||
"settings.export_json": "Exportera JSON",
|
"settings.export_json": "Exportera JSON",
|
||||||
"table.name": "Namn",
|
"table.name": "Namn",
|
||||||
|
"table.brand": "Märke",
|
||||||
"table.class": "Klass",
|
"table.class": "Klass",
|
||||||
"table.transponder": "Transponder",
|
"table.transponder": "Transponder",
|
||||||
"table.delete": "Ta bort",
|
"table.delete": "Ta bort",
|
||||||
@@ -723,11 +726,13 @@ const TRANSLATIONS = {
|
|||||||
"classes.title": "Classes",
|
"classes.title": "Classes",
|
||||||
"drivers.create": "Create Driver",
|
"drivers.create": "Create Driver",
|
||||||
"drivers.name_placeholder": "Driver name",
|
"drivers.name_placeholder": "Driver name",
|
||||||
|
"drivers.brand_placeholder": "Team / brand (optional)",
|
||||||
"drivers.transponder_placeholder": "Personal transponder (optional)",
|
"drivers.transponder_placeholder": "Personal transponder (optional)",
|
||||||
"drivers.add": "Add Driver",
|
"drivers.add": "Add Driver",
|
||||||
"drivers.title": "Drivers",
|
"drivers.title": "Drivers",
|
||||||
"cars.create": "Create Track Car",
|
"cars.create": "Create Track Car",
|
||||||
"cars.name_placeholder": "Car name or number",
|
"cars.name_placeholder": "Car name or number",
|
||||||
|
"cars.brand_placeholder": "Brand / model (optional)",
|
||||||
"cars.transponder_placeholder": "Car transponder",
|
"cars.transponder_placeholder": "Car transponder",
|
||||||
"cars.add": "Add Car",
|
"cars.add": "Add Car",
|
||||||
"cars.title": "Cars",
|
"cars.title": "Cars",
|
||||||
@@ -1097,6 +1102,7 @@ const TRANSLATIONS = {
|
|||||||
"settings.sync_now": "Sync Now",
|
"settings.sync_now": "Sync Now",
|
||||||
"settings.export_json": "Export JSON",
|
"settings.export_json": "Export JSON",
|
||||||
"table.name": "Name",
|
"table.name": "Name",
|
||||||
|
"table.brand": "Brand",
|
||||||
"table.class": "Class",
|
"table.class": "Class",
|
||||||
"table.transponder": "Transponder",
|
"table.transponder": "Transponder",
|
||||||
"table.delete": "Delete",
|
"table.delete": "Delete",
|
||||||
@@ -1454,6 +1460,8 @@ function seedDefaultData() {
|
|||||||
state.settings.racePresets = [];
|
state.settings.racePresets = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.drivers = state.drivers.map((driver) => normalizeDriver(driver)).filter((driver) => driver.name);
|
||||||
|
state.cars = state.cars.map((car) => normalizeCar(car)).filter((car) => car.name);
|
||||||
state.events = state.events.map((event) => normalizeEvent(event));
|
state.events = state.events.map((event) => normalizeEvent(event));
|
||||||
state.sessions = state.sessions.map((session) => normalizeSession(session));
|
state.sessions = state.sessions.map((session) => normalizeSession(session));
|
||||||
|
|
||||||
@@ -1600,8 +1608,8 @@ function setupLanguageControl() {
|
|||||||
function buildPersistableState() {
|
function buildPersistableState() {
|
||||||
return {
|
return {
|
||||||
classes: state.classes,
|
classes: state.classes,
|
||||||
drivers: state.drivers,
|
drivers: state.drivers.map((driver) => normalizeDriver(driver)),
|
||||||
cars: state.cars,
|
cars: state.cars.map((car) => normalizeCar(car)),
|
||||||
events: state.events,
|
events: state.events,
|
||||||
sessions: state.sessions.map((session) => normalizeSession(session)),
|
sessions: state.sessions.map((session) => normalizeSession(session)),
|
||||||
resultsBySession: state.resultsBySession,
|
resultsBySession: state.resultsBySession,
|
||||||
@@ -1755,8 +1763,8 @@ async function hydrateFromBackend() {
|
|||||||
|
|
||||||
function applyPersistedState(persisted) {
|
function applyPersistedState(persisted) {
|
||||||
state.classes = persisted.classes || [];
|
state.classes = persisted.classes || [];
|
||||||
state.drivers = persisted.drivers || [];
|
state.drivers = (persisted.drivers || []).map((driver) => normalizeDriver(driver)).filter((driver) => driver.name);
|
||||||
state.cars = persisted.cars || [];
|
state.cars = (persisted.cars || []).map((car) => normalizeCar(car)).filter((car) => car.name);
|
||||||
state.events = (persisted.events || []).map((event) => normalizeEvent(event));
|
state.events = (persisted.events || []).map((event) => normalizeEvent(event));
|
||||||
state.sessions = (persisted.sessions || []).map((session) => normalizeSession(session));
|
state.sessions = (persisted.sessions || []).map((session) => normalizeSession(session));
|
||||||
state.resultsBySession = persisted.resultsBySession || {};
|
state.resultsBySession = persisted.resultsBySession || {};
|
||||||
@@ -1992,6 +2000,27 @@ function buildRaceFormatConfigFromForm(form, event) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeDriver(driver) {
|
||||||
|
const item = driver && typeof driver === "object" ? driver : {};
|
||||||
|
return {
|
||||||
|
id: item.id || uid("driver"),
|
||||||
|
name: String(item.name || "").trim(),
|
||||||
|
classId: String(item.classId || ""),
|
||||||
|
brand: String(item.brand || "").trim(),
|
||||||
|
transponder: String(item.transponder || "").trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeCar(car) {
|
||||||
|
const item = car && typeof car === "object" ? car : {};
|
||||||
|
return {
|
||||||
|
id: item.id || uid("car"),
|
||||||
|
name: String(item.name || "").trim(),
|
||||||
|
brand: String(item.brand || "").trim(),
|
||||||
|
transponder: String(item.transponder || "").trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeEvent(event) {
|
function normalizeEvent(event) {
|
||||||
return {
|
return {
|
||||||
...event,
|
...event,
|
||||||
@@ -2811,9 +2840,10 @@ function renderDrivers() {
|
|||||||
dom.view.innerHTML = `
|
dom.view.innerHTML = `
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<div class="panel-header"><h3>${t("drivers.create")}</h3></div>
|
<div class="panel-header"><h3>${t("drivers.create")}</h3></div>
|
||||||
<form id="driverForm" class="panel-body form-grid cols-4">
|
<form id="driverForm" class="panel-body form-grid cols-5">
|
||||||
<input required name="name" placeholder="${t("drivers.name_placeholder")}" />
|
<input required name="name" placeholder="${t("drivers.name_placeholder")}" />
|
||||||
<select name="classId">${classOptions}</select>
|
<select name="classId">${classOptions}</select>
|
||||||
|
<input name="brand" placeholder="${t("drivers.brand_placeholder")}" />
|
||||||
<input name="transponder" placeholder="${t("drivers.transponder_placeholder")}" />
|
<input name="transponder" placeholder="${t("drivers.transponder_placeholder")}" />
|
||||||
<button class="btn btn-primary" type="submit">${t("drivers.add")}</button>
|
<button class="btn btn-primary" type="submit">${t("drivers.add")}</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -2823,12 +2853,13 @@ function renderDrivers() {
|
|||||||
<div class="panel-header"><h3>${t("drivers.title")}</h3></div>
|
<div class="panel-header"><h3>${t("drivers.title")}</h3></div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
${renderTable(
|
${renderTable(
|
||||||
[t("table.name"), t("table.class"), t("table.transponder"), t("events.actions")],
|
[t("table.name"), t("table.class"), t("table.brand"), t("table.transponder"), t("events.actions")],
|
||||||
state.drivers.map(
|
state.drivers.map(
|
||||||
(d) => `
|
(d) => `
|
||||||
<tr>
|
<tr>
|
||||||
<td>${escapeHtml(d.name)}</td>
|
<td>${escapeHtml(d.name)}</td>
|
||||||
<td>${escapeHtml(getClassName(d.classId))}</td>
|
<td>${escapeHtml(getClassName(d.classId))}</td>
|
||||||
|
<td>${escapeHtml(d.brand || "-")}</td>
|
||||||
<td>${escapeHtml(d.transponder || "-")}</td>
|
<td>${escapeHtml(d.transponder || "-")}</td>
|
||||||
<td class="actions-inline">
|
<td class="actions-inline">
|
||||||
<button id="driver-edit-${d.id}" class="btn">${t("common.edit")}</button>
|
<button id="driver-edit-${d.id}" class="btn">${t("common.edit")}</button>
|
||||||
@@ -2850,7 +2881,7 @@ function renderDrivers() {
|
|||||||
<h3>${t("common.edit")}</h3>
|
<h3>${t("common.edit")}</h3>
|
||||||
<button class="btn" id="driverEditCancel">${t("common.cancel")}</button>
|
<button class="btn" id="driverEditCancel">${t("common.cancel")}</button>
|
||||||
</div>
|
</div>
|
||||||
<form id="driverEditForm" class="panel-body form-grid cols-3">
|
<form id="driverEditForm" class="panel-body form-grid cols-4">
|
||||||
<input name="name" required value="${escapeHtml(editingDriver.name)}" placeholder="${t("drivers.name_placeholder")}" />
|
<input name="name" required value="${escapeHtml(editingDriver.name)}" placeholder="${t("drivers.name_placeholder")}" />
|
||||||
<select name="classId">
|
<select name="classId">
|
||||||
${state.classes
|
${state.classes
|
||||||
@@ -2860,6 +2891,7 @@ function renderDrivers() {
|
|||||||
)
|
)
|
||||||
.join("")}
|
.join("")}
|
||||||
</select>
|
</select>
|
||||||
|
<input name="brand" value="${escapeHtml(editingDriver.brand || "")}" placeholder="${t("drivers.brand_placeholder")}" />
|
||||||
<input name="transponder" value="${escapeHtml(editingDriver.transponder || "")}" placeholder="${t("drivers.transponder_placeholder")}" />
|
<input name="transponder" value="${escapeHtml(editingDriver.transponder || "")}" placeholder="${t("drivers.transponder_placeholder")}" />
|
||||||
<p class="form-error" id="driverEditError" hidden></p>
|
<p class="form-error" id="driverEditError" hidden></p>
|
||||||
<div class="actions-inline">
|
<div class="actions-inline">
|
||||||
@@ -2877,12 +2909,15 @@ function renderDrivers() {
|
|||||||
document.getElementById("driverForm")?.addEventListener("submit", (e) => {
|
document.getElementById("driverForm")?.addEventListener("submit", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const form = new FormData(e.currentTarget);
|
const form = new FormData(e.currentTarget);
|
||||||
state.drivers.push({
|
state.drivers.push(
|
||||||
|
normalizeDriver({
|
||||||
id: uid("driver"),
|
id: uid("driver"),
|
||||||
name: String(form.get("name")).trim(),
|
name: String(form.get("name")).trim(),
|
||||||
classId: String(form.get("classId")),
|
classId: String(form.get("classId")),
|
||||||
|
brand: String(form.get("brand") || "").trim(),
|
||||||
transponder: String(form.get("transponder") || "").trim(),
|
transponder: String(form.get("transponder") || "").trim(),
|
||||||
});
|
})
|
||||||
|
);
|
||||||
saveState();
|
saveState();
|
||||||
renderView();
|
renderView();
|
||||||
});
|
});
|
||||||
@@ -2933,6 +2968,7 @@ function renderDrivers() {
|
|||||||
const form = new FormData(event.currentTarget);
|
const form = new FormData(event.currentTarget);
|
||||||
const cleanedName = String(form.get("name") || "").trim();
|
const cleanedName = String(form.get("name") || "").trim();
|
||||||
const cleanedClassId = String(form.get("classId") || "").trim();
|
const cleanedClassId = String(form.get("classId") || "").trim();
|
||||||
|
const cleanedBrand = String(form.get("brand") || "").trim();
|
||||||
const cleanedTp = String(form.get("transponder") || "").trim();
|
const cleanedTp = String(form.get("transponder") || "").trim();
|
||||||
if (!cleanedName) {
|
if (!cleanedName) {
|
||||||
setFormError("driverEditError", t("validation.required_name"));
|
setFormError("driverEditError", t("validation.required_name"));
|
||||||
@@ -2945,6 +2981,7 @@ function renderDrivers() {
|
|||||||
setFormError("driverEditError", "");
|
setFormError("driverEditError", "");
|
||||||
editingDriver.name = cleanedName;
|
editingDriver.name = cleanedName;
|
||||||
editingDriver.classId = cleanedClassId || editingDriver.classId;
|
editingDriver.classId = cleanedClassId || editingDriver.classId;
|
||||||
|
editingDriver.brand = cleanedBrand;
|
||||||
editingDriver.transponder = cleanedTp;
|
editingDriver.transponder = cleanedTp;
|
||||||
selectedDriverEditId = null;
|
selectedDriverEditId = null;
|
||||||
saveState();
|
saveState();
|
||||||
@@ -2957,8 +2994,9 @@ function renderCars() {
|
|||||||
dom.view.innerHTML = `
|
dom.view.innerHTML = `
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<div class="panel-header"><h3>${t("cars.create")}</h3></div>
|
<div class="panel-header"><h3>${t("cars.create")}</h3></div>
|
||||||
<form id="carForm" class="panel-body form-grid cols-3">
|
<form id="carForm" class="panel-body form-grid cols-4">
|
||||||
<input required name="name" placeholder="${t("cars.name_placeholder")}" />
|
<input required name="name" placeholder="${t("cars.name_placeholder")}" />
|
||||||
|
<input name="brand" placeholder="${t("cars.brand_placeholder")}" />
|
||||||
<input required name="transponder" placeholder="${t("cars.transponder_placeholder")}" />
|
<input required name="transponder" placeholder="${t("cars.transponder_placeholder")}" />
|
||||||
<button class="btn btn-primary" type="submit">${t("cars.add")}</button>
|
<button class="btn btn-primary" type="submit">${t("cars.add")}</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -2968,11 +3006,12 @@ function renderCars() {
|
|||||||
<div class="panel-header"><h3>${t("cars.title")}</h3></div>
|
<div class="panel-header"><h3>${t("cars.title")}</h3></div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
${renderTable(
|
${renderTable(
|
||||||
[t("table.car"), t("table.transponder"), t("events.actions")],
|
[t("table.car"), t("table.brand"), t("table.transponder"), t("events.actions")],
|
||||||
state.cars.map(
|
state.cars.map(
|
||||||
(c) => `
|
(c) => `
|
||||||
<tr>
|
<tr>
|
||||||
<td>${escapeHtml(c.name)}</td>
|
<td>${escapeHtml(c.name)}</td>
|
||||||
|
<td>${escapeHtml(c.brand || "-")}</td>
|
||||||
<td>${escapeHtml(c.transponder)}</td>
|
<td>${escapeHtml(c.transponder)}</td>
|
||||||
<td class="actions-inline">
|
<td class="actions-inline">
|
||||||
<button id="car-edit-${c.id}" class="btn">${t("common.edit")}</button>
|
<button id="car-edit-${c.id}" class="btn">${t("common.edit")}</button>
|
||||||
@@ -2994,8 +3033,9 @@ function renderCars() {
|
|||||||
<h3>${t("common.edit")}</h3>
|
<h3>${t("common.edit")}</h3>
|
||||||
<button class="btn" id="carEditCancel">${t("common.cancel")}</button>
|
<button class="btn" id="carEditCancel">${t("common.cancel")}</button>
|
||||||
</div>
|
</div>
|
||||||
<form id="carEditForm" class="panel-body form-grid cols-3">
|
<form id="carEditForm" class="panel-body form-grid cols-4">
|
||||||
<input name="name" required value="${escapeHtml(editingCar.name)}" placeholder="${t("cars.name_placeholder")}" />
|
<input name="name" required value="${escapeHtml(editingCar.name)}" placeholder="${t("cars.name_placeholder")}" />
|
||||||
|
<input name="brand" value="${escapeHtml(editingCar.brand || "")}" placeholder="${t("cars.brand_placeholder")}" />
|
||||||
<input
|
<input
|
||||||
name="transponder"
|
name="transponder"
|
||||||
required
|
required
|
||||||
@@ -3018,11 +3058,14 @@ function renderCars() {
|
|||||||
document.getElementById("carForm")?.addEventListener("submit", (e) => {
|
document.getElementById("carForm")?.addEventListener("submit", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const form = new FormData(e.currentTarget);
|
const form = new FormData(e.currentTarget);
|
||||||
state.cars.push({
|
state.cars.push(
|
||||||
|
normalizeCar({
|
||||||
id: uid("car"),
|
id: uid("car"),
|
||||||
name: String(form.get("name")).trim(),
|
name: String(form.get("name")).trim(),
|
||||||
|
brand: String(form.get("brand") || "").trim(),
|
||||||
transponder: String(form.get("transponder")).trim(),
|
transponder: String(form.get("transponder")).trim(),
|
||||||
});
|
})
|
||||||
|
);
|
||||||
saveState();
|
saveState();
|
||||||
renderView();
|
renderView();
|
||||||
});
|
});
|
||||||
@@ -3072,6 +3115,7 @@ function renderCars() {
|
|||||||
}
|
}
|
||||||
const form = new FormData(event.currentTarget);
|
const form = new FormData(event.currentTarget);
|
||||||
const cleanedName = String(form.get("name") || "").trim();
|
const cleanedName = String(form.get("name") || "").trim();
|
||||||
|
const cleanedBrand = String(form.get("brand") || "").trim();
|
||||||
const cleanedTp = String(form.get("transponder") || "").trim();
|
const cleanedTp = String(form.get("transponder") || "").trim();
|
||||||
if (!cleanedName) {
|
if (!cleanedName) {
|
||||||
setFormError("carEditError", t("validation.required_name"));
|
setFormError("carEditError", t("validation.required_name"));
|
||||||
@@ -3083,6 +3127,7 @@ function renderCars() {
|
|||||||
}
|
}
|
||||||
setFormError("carEditError", "");
|
setFormError("carEditError", "");
|
||||||
editingCar.name = cleanedName;
|
editingCar.name = cleanedName;
|
||||||
|
editingCar.brand = cleanedBrand;
|
||||||
editingCar.transponder = cleanedTp;
|
editingCar.transponder = cleanedTp;
|
||||||
selectedCarEditId = null;
|
selectedCarEditId = null;
|
||||||
saveState();
|
saveState();
|
||||||
@@ -4737,24 +4782,31 @@ function renderTiming() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const transponder = String(form.get("transponder") || "").trim();
|
const transponder = String(form.get("transponder") || "").trim();
|
||||||
|
const brand = String(form.get("brand") || "").trim();
|
||||||
if (!transponder) {
|
if (!transponder) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (quickAddDraft.type === "driver") {
|
if (quickAddDraft.type === "driver") {
|
||||||
if (!state.drivers.some((item) => String(item.transponder || "").trim() === transponder)) {
|
if (!state.drivers.some((item) => String(item.transponder || "").trim() === transponder)) {
|
||||||
state.drivers.push({
|
state.drivers.push(
|
||||||
|
normalizeDriver({
|
||||||
id: uid("driver"),
|
id: uid("driver"),
|
||||||
name,
|
name,
|
||||||
classId: String(form.get("classId") || getPreferredClassId(active)),
|
classId: String(form.get("classId") || getPreferredClassId(active)),
|
||||||
|
brand,
|
||||||
transponder,
|
transponder,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (!state.cars.some((item) => String(item.transponder || "").trim() === transponder)) {
|
} else if (!state.cars.some((item) => String(item.transponder || "").trim() === transponder)) {
|
||||||
state.cars.push({
|
state.cars.push(
|
||||||
|
normalizeCar({
|
||||||
id: uid("car"),
|
id: uid("car"),
|
||||||
name,
|
name,
|
||||||
|
brand,
|
||||||
transponder,
|
transponder,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
quickAddDraft = null;
|
quickAddDraft = null;
|
||||||
saveState();
|
saveState();
|
||||||
@@ -5148,7 +5200,7 @@ function renderQuickAddPanel(session) {
|
|||||||
return `
|
return `
|
||||||
<section class="panel mt-16">
|
<section class="panel mt-16">
|
||||||
<div class="panel-header"><h3>${t(isDriver ? "timing.quick_add_driver_title" : "timing.quick_add_car_title")}</h3></div>
|
<div class="panel-header"><h3>${t(isDriver ? "timing.quick_add_driver_title" : "timing.quick_add_car_title")}</h3></div>
|
||||||
<form id="quickAddForm" class="panel-body form-grid cols-4">
|
<form id="quickAddForm" class="panel-body form-grid cols-5">
|
||||||
<input name="transponder" value="${escapeHtml(quickAddDraft.transponder)}" readonly />
|
<input name="transponder" value="${escapeHtml(quickAddDraft.transponder)}" readonly />
|
||||||
<input
|
<input
|
||||||
name="name"
|
name="name"
|
||||||
@@ -5157,6 +5209,11 @@ function renderQuickAddPanel(session) {
|
|||||||
placeholder="${t(isDriver ? "drivers.name_placeholder" : "cars.name_placeholder")}"
|
placeholder="${t(isDriver ? "drivers.name_placeholder" : "cars.name_placeholder")}"
|
||||||
value="${escapeHtml(quickAddDraft.name || "")}"
|
value="${escapeHtml(quickAddDraft.name || "")}"
|
||||||
/>
|
/>
|
||||||
|
<input
|
||||||
|
name="brand"
|
||||||
|
placeholder="${t(isDriver ? "drivers.brand_placeholder" : "cars.brand_placeholder")}"
|
||||||
|
value="${escapeHtml(quickAddDraft.brand || "")}"
|
||||||
|
/>
|
||||||
${
|
${
|
||||||
isDriver
|
isDriver
|
||||||
? `<select name="classId">${classOptions}</select>`
|
? `<select name="classId">${classOptions}</select>`
|
||||||
|
|||||||
Reference in New Issue
Block a user