Extract event and race workspace markup into module
This commit is contained in:
144
src/app.js
144
src/app.js
@@ -12,6 +12,7 @@ import { renderDashboardView, renderClassesView, renderDriversView, renderCarsVi
|
||||
|
||||
import { renderGuideView, renderOverlayPageView } from "./misc_views.js";
|
||||
import { getSessionsForEventHelper, getModeLabelHelper, normalizeStartModeHelper, getStartModeLabelHelper, getClassNameHelper, getEventNameHelper, renderAssignmentListView, renderSessionsTableView } from "./event_common.js";
|
||||
import { renderEventWorkspaceMarkup } from "./event_views.js";
|
||||
import { createDefaultAmmcConfigHelper, getManagedWsUrlHelper, loadAmmcConfigFromBackendHelper, saveAmmcConfigToBackendHelper, refreshAmmcStatusHelper, startManagedAmmcHelper, stopManagedAmmcHelper, applyPersistedStateHelper, hydrateFromBackendHelper, scheduleBackendSyncHelper, syncStateToBackendHelper, pingBackendHelper, checkAppVersionHelper, startAppVersionPollingHelper, startOverlaySyncHelper, startOverlayRotationHelper, startOverlayLiveRefreshHelper, ensureAudioContextHelper, playPassingBeepHelper, playFinishSirenHelper, playLeaderCueHelper, playStartCueHelper, playBestLapCueHelper, pushOverlayEventHelper, speakTextHelper, announcePassingHelper, announceRaceFinishedHelper, handleSessionTimerTickHelper, tickClockHelper } from "./runtime_services.js";
|
||||
import { connectDecoderHelper, disconnectDecoderHelper, processDecoderMessageHelper } from "./decoder_runtime.js";
|
||||
|
||||
@@ -2815,135 +2816,24 @@ function renderEventWorkspace(mode) {
|
||||
ensureRaceWizardDraft();
|
||||
}
|
||||
const filteredEvents = state.events.filter((event) => event.mode === mode);
|
||||
const classOptions = state.classes
|
||||
.map((c) => `<option value="${c.id}">${escapeHtml(c.name)}</option>`)
|
||||
.join("");
|
||||
const wizardClassOptions = state.classes
|
||||
.map((c) => `<option value="${c.id}" ${c.id === raceWizardDraft?.classId ? "selected" : ""}>${escapeHtml(c.name)}</option>`)
|
||||
.join("");
|
||||
const editingEvent = filteredEvents.find((event) => event.id === selectedEventEditId) || null;
|
||||
|
||||
dom.view.innerHTML = `
|
||||
<section class="panel">
|
||||
<div class="panel-header"><h3>${t(isRaceMode ? "events.create_race" : "events.create")}</h3></div>
|
||||
<div class="panel-body">
|
||||
<p>${t(isRaceMode ? "events.race_only_intro" : "events.track_only_intro")}</p>
|
||||
${isRaceMode ? `<p class="hint">${t("events.wizard_hint")}</p>` : ""}
|
||||
</div>
|
||||
${
|
||||
isRaceMode
|
||||
? `
|
||||
<div class="panel-body race-wizard-steps">
|
||||
${renderRaceWizardStepsView()}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
${renderRaceWizardContentView(raceWizardDraft, wizardClassOptions, getDriversForClass(raceWizardDraft.classId), getRaceWizardPreset(raceWizardDraft.presetId))}
|
||||
</div>
|
||||
<div class="panel-body race-wizard-footer">
|
||||
<button id="raceWizardReset" class="btn" type="button">${t("common.reset")}</button>
|
||||
<div class="actions-inline">
|
||||
${raceWizardStep > 1 ? `<button id="raceWizardPrev" class="btn" type="button">${t("common.previous")}</button>` : ""}
|
||||
${raceWizardStep < 4 ? `<button id="raceWizardNext" class="btn btn-primary" type="button">${t("common.next")}</button>` : `<button id="raceWizardCreate" class="btn btn-primary" type="button">${t("events.wizard_create")}</button>`}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: `
|
||||
<form id="eventForm" class="panel-body form-grid cols-4">
|
||||
<label>
|
||||
${t("events.field_name")}
|
||||
<input required name="name" placeholder="${t("events.name_placeholder")}" />
|
||||
<small>${t("events.field_name_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
${t("events.field_date")}
|
||||
<input required type="date" name="date" />
|
||||
<small>${t("events.field_date_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
${t("events.field_class")}
|
||||
<select name="classId">${classOptions}</select>
|
||||
<small>${t("events.field_class_hint")}</small>
|
||||
</label>
|
||||
<div class="actions-inline align-end">
|
||||
<button class="btn btn-primary" type="submit">${t("events.add")}</button>
|
||||
</div>
|
||||
</form>
|
||||
`
|
||||
}
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-header"><h3>${t(isRaceMode ? "events.race_title" : "events.title")}</h3></div>
|
||||
<div class="panel-body">
|
||||
${renderTable(
|
||||
[t("table.name"), t("table.date"), t("table.class"), t("table.mode"), t("events.sessions"), t("events.actions")],
|
||||
filteredEvents.map((e) => {
|
||||
const sessions = getSessionsForEvent(e.id);
|
||||
return `
|
||||
<tr>
|
||||
<td>${escapeHtml(e.name)}</td>
|
||||
<td>${escapeHtml(e.date)}</td>
|
||||
<td>${escapeHtml(getClassName(e.classId))}</td>
|
||||
<td>${getModeLabel(e.mode)}</td>
|
||||
<td>${sessions.length}</td>
|
||||
<td class="actions-inline">
|
||||
<button id="event-edit-${e.id}" class="btn">${t("events.edit")}</button>
|
||||
<button id="event-manage-${e.id}" class="btn">${t("events.manage")}</button>
|
||||
<button id="event-delete-${e.id}" class="btn btn-danger">${t("common.delete")}</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="eventManageArea"></section>
|
||||
|
||||
${
|
||||
editingEvent
|
||||
? `
|
||||
<div class="modal-overlay" id="eventEditModalOverlay">
|
||||
<div class="modal-card">
|
||||
<div class="panel-header">
|
||||
<h3>${t("common.edit")}</h3>
|
||||
<button class="btn" id="eventEditCancel">${t("common.cancel")}</button>
|
||||
</div>
|
||||
<form id="eventEditForm" class="panel-body form-grid cols-3">
|
||||
<label>
|
||||
${t("events.field_name")}
|
||||
<input name="name" required value="${escapeHtml(editingEvent.name)}" placeholder="${t("events.name_placeholder")}" />
|
||||
<small>${t("events.field_name_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
${t("events.field_date")}
|
||||
<input name="date" required type="date" value="${escapeHtml(editingEvent.date || "")}" />
|
||||
<small>${t("events.field_date_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
${t("events.field_class")}
|
||||
<select name="classId">
|
||||
${state.classes
|
||||
.map(
|
||||
(item) =>
|
||||
`<option value="${item.id}" ${item.id === editingEvent.classId ? "selected" : ""}>${escapeHtml(item.name)}</option>`
|
||||
)
|
||||
.join("")}
|
||||
</select>
|
||||
<small>${t("events.field_class_hint")}</small>
|
||||
</label>
|
||||
<p class="form-error" id="eventEditError" hidden></p>
|
||||
<div class="actions-inline">
|
||||
<button class="btn btn-primary" type="submit">${t("common.save")}</button>
|
||||
<button class="btn" id="eventEditCancelFooter" type="button">${t("common.cancel")}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
`;
|
||||
dom.view.innerHTML = renderEventWorkspaceMarkup(mode, {
|
||||
state,
|
||||
t,
|
||||
escapeHtml,
|
||||
renderTable,
|
||||
renderRaceWizardStepsView,
|
||||
renderRaceWizardContentView,
|
||||
raceWizardDraft,
|
||||
raceWizardStep,
|
||||
getDriversForClass,
|
||||
getRaceWizardPreset,
|
||||
getSessionsForEvent,
|
||||
getClassName,
|
||||
getModeLabel,
|
||||
editingEvent,
|
||||
});
|
||||
|
||||
if (isRaceMode) {
|
||||
const persistWizardStepOne = () => {
|
||||
|
||||
143
src/event_views.js
Normal file
143
src/event_views.js
Normal file
@@ -0,0 +1,143 @@
|
||||
export function renderEventWorkspaceMarkup(mode, deps) {
|
||||
const {
|
||||
state,
|
||||
t,
|
||||
escapeHtml,
|
||||
renderTable,
|
||||
renderRaceWizardStepsView,
|
||||
renderRaceWizardContentView,
|
||||
raceWizardDraft,
|
||||
raceWizardStep,
|
||||
getDriversForClass,
|
||||
getRaceWizardPreset,
|
||||
getSessionsForEvent,
|
||||
getClassName,
|
||||
getModeLabel,
|
||||
editingEvent,
|
||||
} = deps;
|
||||
const isRaceMode = mode === "race";
|
||||
const filteredEvents = state.events.filter((event) => event.mode === mode);
|
||||
const classOptions = state.classes.map((c) => `<option value="${c.id}">${escapeHtml(c.name)}</option>`).join("");
|
||||
const wizardClassOptions = state.classes
|
||||
.map((c) => `<option value="${c.id}" ${c.id === raceWizardDraft?.classId ? "selected" : ""}>${escapeHtml(c.name)}</option>`)
|
||||
.join("");
|
||||
|
||||
return `
|
||||
<section class="panel">
|
||||
<div class="panel-header"><h3>${t(isRaceMode ? "events.create_race" : "events.create")}</h3></div>
|
||||
<div class="panel-body">
|
||||
<p>${t(isRaceMode ? "events.race_only_intro" : "events.track_only_intro")}</p>
|
||||
${isRaceMode ? `<p class="hint">${t("events.wizard_hint")}</p>` : ""}
|
||||
</div>
|
||||
${
|
||||
isRaceMode
|
||||
? `
|
||||
<div class="panel-body race-wizard-steps">
|
||||
${renderRaceWizardStepsView()}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
${renderRaceWizardContentView(raceWizardDraft, wizardClassOptions, getDriversForClass(raceWizardDraft.classId), getRaceWizardPreset(raceWizardDraft.presetId))}
|
||||
</div>
|
||||
<div class="panel-body race-wizard-footer">
|
||||
<button id="raceWizardReset" class="btn" type="button">${t("common.reset")}</button>
|
||||
<div class="actions-inline">
|
||||
${raceWizardStep > 1 ? `<button id="raceWizardPrev" class="btn" type="button">${t("common.previous")}</button>` : ""}
|
||||
${raceWizardStep < 4 ? `<button id="raceWizardNext" class="btn btn-primary" type="button">${t("common.next")}</button>` : `<button id="raceWizardCreate" class="btn btn-primary" type="button">${t("events.wizard_create")}</button>`}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: `
|
||||
<form id="eventForm" class="panel-body form-grid cols-4">
|
||||
<label>
|
||||
${t("events.field_name")}
|
||||
<input required name="name" placeholder="${t("events.name_placeholder")}" />
|
||||
<small>${t("events.field_name_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
${t("events.field_date")}
|
||||
<input required type="date" name="date" />
|
||||
<small>${t("events.field_date_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
${t("events.field_class")}
|
||||
<select name="classId">${classOptions}</select>
|
||||
<small>${t("events.field_class_hint")}</small>
|
||||
</label>
|
||||
<div class="actions-inline align-end">
|
||||
<button class="btn btn-primary" type="submit">${t("events.add")}</button>
|
||||
</div>
|
||||
</form>
|
||||
`
|
||||
}
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-header"><h3>${t(isRaceMode ? "events.race_title" : "events.title")}</h3></div>
|
||||
<div class="panel-body">
|
||||
${renderTable(
|
||||
[t("table.name"), t("table.date"), t("table.class"), t("table.mode"), t("events.sessions"), t("events.actions")],
|
||||
filteredEvents.map((e) => {
|
||||
const sessions = getSessionsForEvent(e.id);
|
||||
return `
|
||||
<tr>
|
||||
<td>${escapeHtml(e.name)}</td>
|
||||
<td>${escapeHtml(e.date)}</td>
|
||||
<td>${escapeHtml(getClassName(e.classId))}</td>
|
||||
<td>${getModeLabel(e.mode)}</td>
|
||||
<td>${sessions.length}</td>
|
||||
<td class="actions-inline">
|
||||
<button id="event-edit-${e.id}" class="btn">${t("events.edit")}</button>
|
||||
<button id="event-manage-${e.id}" class="btn">${t("events.manage")}</button>
|
||||
<button id="event-delete-${e.id}" class="btn btn-danger">${t("common.delete")}</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="eventManageArea"></section>
|
||||
|
||||
${
|
||||
editingEvent
|
||||
? `
|
||||
<div class="modal-overlay" id="eventEditModalOverlay">
|
||||
<div class="modal-card">
|
||||
<div class="panel-header">
|
||||
<h3>${t("common.edit")}</h3>
|
||||
<button class="btn" id="eventEditCancel">${t("common.cancel")}</button>
|
||||
</div>
|
||||
<form id="eventEditForm" class="panel-body form-grid cols-3">
|
||||
<label>
|
||||
${t("events.field_name")}
|
||||
<input name="name" required value="${escapeHtml(editingEvent.name)}" placeholder="${t("events.name_placeholder")}" />
|
||||
<small>${t("events.field_name_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
${t("events.field_date")}
|
||||
<input name="date" required type="date" value="${escapeHtml(editingEvent.date || "")}" />
|
||||
<small>${t("events.field_date_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
${t("events.field_class")}
|
||||
<select name="classId">
|
||||
${state.classes
|
||||
.map((item) => `<option value="${item.id}" ${item.id === editingEvent.classId ? "selected" : ""}>${escapeHtml(item.name)}</option>`)
|
||||
.join("")}
|
||||
</select>
|
||||
<small>${t("events.field_class_hint")}</small>
|
||||
</label>
|
||||
<p class="form-error" id="eventEditError" hidden></p>
|
||||
<div class="actions-inline">
|
||||
<button class="btn btn-primary" type="submit">${t("common.save")}</button>
|
||||
<button class="btn" id="eventEditCancelFooter" type="button">${t("common.cancel")}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user