branding och namechange
This commit is contained in:
90
src/app.js
90
src/app.js
@@ -30,6 +30,8 @@ import { renderTeamStintLog as renderTeamStintLogHelper, renderSessionChannelAna
|
||||
|
||||
import { getManualCorrectionSummary as getManualCorrectionSummaryLogic, applyCompetitorCorrection as applyCompetitorCorrectionLogic, recalculateCompetitorFromPassings as recalculateCompetitorFromPassingsLogic, invalidateCompetitorLastLap as invalidateCompetitorLastLapLogic, restoreCompetitorLastInvalidLap as restoreCompetitorLastInvalidLapLogic, findPassingByUndoMarker as findPassingByUndoMarkerLogic, undoJudgingAdjustment as undoJudgingAdjustmentLogic, getJudgeFilteredRows as getJudgeFilteredRowsLogic, getJudgeFilteredLog as getJudgeFilteredLogLogic } from "./judging_logic.js";
|
||||
|
||||
const PRODUCT_NAME = "RC RaceCore";
|
||||
|
||||
const renderRaceFormatFieldView = (labelKey, hintKey, controlHtml, options = {}) => renderRaceFormatField(labelKey, hintKey, controlHtml, options, { t });
|
||||
const renderRaceFormatContextCardView = (titleKey, hintKey) => renderRaceFormatContextCard(titleKey, hintKey, { t });
|
||||
const renderManageStatusBadgeView = (status) => renderManageStatusBadge(status, { t });
|
||||
@@ -327,8 +329,8 @@ const TRANSLATIONS = {
|
||||
"ui.theme_dark": "Mörk",
|
||||
"ui.theme_nord": "Nord",
|
||||
"ui.theme_light": "Ljus",
|
||||
"brand.title": "JMK RB RaceController",
|
||||
"brand.subtitle": "RC Timing System",
|
||||
"brand.title": "RC RaceCore",
|
||||
"brand.subtitle": "Live Timing & Race Control",
|
||||
"ui.no_active_session": "Ingen aktiv session",
|
||||
"ui.event": "Event",
|
||||
"ui.decoder_online": "Decoder online",
|
||||
@@ -1074,7 +1076,9 @@ const TRANSLATIONS = {
|
||||
"settings.test_audio": "Testa ljud",
|
||||
"settings.audio_note": "Browsern kräver oftast ett klick först innan ljud/tal tillåts.",
|
||||
"settings.voice_note": "Rösterna kommer från operativsystemet. På Windows ger Microsofts svenska röst oftast bäst uttal. Ange vid behov ett särskilt uttalsnamn under Förare.",
|
||||
"settings.branding": "Klubbinfo / PDF",
|
||||
"settings.branding": "Klubbbranding / UI / PDF",
|
||||
"settings.branding_note": "Klubbnamn, klubbtext och logotyp används i huvudmenyn, overlay, publik träningsprofil och PDF-export.",
|
||||
"settings.save_branding": "Spara branding",
|
||||
"settings.club_name": "Klubbnamn",
|
||||
"settings.club_tagline": "Klubbtext",
|
||||
"settings.pdf_footer": "PDF-footer",
|
||||
@@ -1082,10 +1086,10 @@ const TRANSLATIONS = {
|
||||
"settings.pdf_theme_classic": "Classic",
|
||||
"settings.pdf_theme_minimal": "Minimal",
|
||||
"settings.pdf_theme_motorsport": "Motorsport",
|
||||
"settings.logo": "Logo / overlay",
|
||||
"settings.logo": "Klubblogotyp",
|
||||
"settings.logo_upload": "Ladda logo",
|
||||
"settings.logo_clear": "Rensa logo",
|
||||
"settings.logo_note": "Logon visas i overlay. PDF-export försöker bädda in loggan automatiskt via backend.",
|
||||
"settings.logo_note": "Logotypen visas i huvudmenyn, overlay och publik träningsprofil. PDF-export försöker bädda in den via backend.",
|
||||
"settings.storage": "Lagring",
|
||||
"settings.race_presets": "Klubb-presetar",
|
||||
"settings.race_presets_note": "Exportera eller importera lokala klubb-presetar mellan installationer.",
|
||||
@@ -1320,7 +1324,7 @@ const TRANSLATIONS = {
|
||||
"overlay.subtitle": "Extern leaderboard-skärm",
|
||||
"overlay.no_active": "Ingen aktiv session vald.",
|
||||
"overlay.last_passings": "Senaste passeringar",
|
||||
"overlay.window_title": "JMK RB RaceController Overlay",
|
||||
"overlay.window_title": "RC RaceCore Overlay",
|
||||
"overlay.mode_leaderboard": "Leaderboard",
|
||||
"overlay.mode_speaker": "Speaker",
|
||||
"overlay.mode_results": "Resultat",
|
||||
@@ -1447,8 +1451,8 @@ const TRANSLATIONS = {
|
||||
"ui.theme_dark": "Dark",
|
||||
"ui.theme_nord": "Nord",
|
||||
"ui.theme_light": "Light",
|
||||
"brand.title": "JMK RB RaceController",
|
||||
"brand.subtitle": "RC Timing System",
|
||||
"brand.title": "RC RaceCore",
|
||||
"brand.subtitle": "Live Timing & Race Control",
|
||||
"ui.no_active_session": "No Active Session",
|
||||
"ui.event": "Event",
|
||||
"ui.decoder_online": "Decoder Online",
|
||||
@@ -2194,7 +2198,9 @@ const TRANSLATIONS = {
|
||||
"settings.test_audio": "Test audio",
|
||||
"settings.audio_note": "Browsers usually require a click first before sound/speech is allowed.",
|
||||
"settings.voice_note": "Voices are provided by the operating system. Select a matching local voice and set a separate spoken name under Drivers when pronunciation needs help.",
|
||||
"settings.branding": "Club Info / PDF",
|
||||
"settings.branding": "Club branding / UI / PDF",
|
||||
"settings.branding_note": "Club name, tagline, and logo are used in the main menu, overlays, public training profiles, and PDF exports.",
|
||||
"settings.save_branding": "Save branding",
|
||||
"settings.club_name": "Club name",
|
||||
"settings.club_tagline": "Club tagline",
|
||||
"settings.pdf_footer": "PDF footer",
|
||||
@@ -2202,10 +2208,10 @@ const TRANSLATIONS = {
|
||||
"settings.pdf_theme_classic": "Classic",
|
||||
"settings.pdf_theme_minimal": "Minimal",
|
||||
"settings.pdf_theme_motorsport": "Motorsport",
|
||||
"settings.logo": "Logo / overlay",
|
||||
"settings.logo": "Club logo",
|
||||
"settings.logo_upload": "Upload logo",
|
||||
"settings.logo_clear": "Clear logo",
|
||||
"settings.logo_note": "The logo is shown in overlay. PDF export attempts to embed the logo automatically via the backend.",
|
||||
"settings.logo_note": "The logo is shown in the main menu, overlays, and public training profiles. PDF export attempts to embed it via the backend.",
|
||||
"settings.storage": "Storage",
|
||||
"settings.race_presets": "Club presets",
|
||||
"settings.race_presets_note": "Export or import local club presets between installations.",
|
||||
@@ -2440,7 +2446,7 @@ const TRANSLATIONS = {
|
||||
"overlay.subtitle": "External leaderboard screen",
|
||||
"overlay.no_active": "No active session selected.",
|
||||
"overlay.last_passings": "Recent passings",
|
||||
"overlay.window_title": "JMK RB RaceController Overlay",
|
||||
"overlay.window_title": "RC RaceCore Overlay",
|
||||
"overlay.mode_leaderboard": "Leaderboard",
|
||||
"overlay.mode_speaker": "Speaker",
|
||||
"overlay.mode_results": "Results",
|
||||
@@ -2909,16 +2915,19 @@ function seedDefaultData() {
|
||||
state.settings.speakerFinishCueEnabled = true;
|
||||
}
|
||||
|
||||
if (!state.settings.clubName) {
|
||||
state.settings.clubName = "JMK RB RaceController";
|
||||
const storedClubName = String(state.settings.clubName || "").trim();
|
||||
if (!storedClubName || ["JMK RB RaceController", "RC RaceCore"].includes(storedClubName)) {
|
||||
state.settings.clubName = "JMK RB";
|
||||
}
|
||||
|
||||
if (!state.settings.clubTagline) {
|
||||
state.settings.clubTagline = "RC Timing System";
|
||||
const storedClubTagline = String(state.settings.clubTagline || "").trim();
|
||||
if (!storedClubTagline || storedClubTagline === "RC Timing System") {
|
||||
state.settings.clubTagline = "Live Timing & Race Control";
|
||||
}
|
||||
|
||||
if (!state.settings.pdfFooter) {
|
||||
state.settings.pdfFooter = "Generated by JMK RB RaceController";
|
||||
const storedPdfFooter = String(state.settings.pdfFooter || "").trim();
|
||||
if (!storedPdfFooter || storedPdfFooter === "Generated by JMK RB RaceController") {
|
||||
state.settings.pdfFooter = "Generated by RC RaceCore";
|
||||
}
|
||||
|
||||
if (!state.settings.pdfTheme) {
|
||||
@@ -2996,9 +3005,9 @@ function loadState() {
|
||||
speakerBestLapCueEnabled: parsed.settings?.speakerBestLapCueEnabled !== false,
|
||||
speakerTop3CueEnabled: parsed.settings?.speakerTop3CueEnabled === true,
|
||||
speakerSessionStartCueEnabled: parsed.settings?.speakerSessionStartCueEnabled !== false,
|
||||
clubName: parsed.settings?.clubName || "JMK RB RaceController",
|
||||
clubTagline: parsed.settings?.clubTagline || "RC Timing System",
|
||||
pdfFooter: parsed.settings?.pdfFooter || "Generated by JMK RB RaceController",
|
||||
clubName: parsed.settings?.clubName || "JMK RB",
|
||||
clubTagline: parsed.settings?.clubTagline || "Live Timing & Race Control",
|
||||
pdfFooter: parsed.settings?.pdfFooter || "Generated by RC RaceCore",
|
||||
pdfTheme: parsed.settings?.pdfTheme || "classic",
|
||||
logoDataUrl: parsed.settings?.logoDataUrl || "",
|
||||
racePresets: Array.isArray(parsed.settings?.racePresets)
|
||||
@@ -3062,9 +3071,9 @@ function loadState() {
|
||||
speakerBestLapCueEnabled: true,
|
||||
speakerTop3CueEnabled: false,
|
||||
speakerSessionStartCueEnabled: true,
|
||||
clubName: "JMK RB RaceController",
|
||||
clubTagline: "RC Timing System",
|
||||
pdfFooter: "Generated by JMK RB RaceController",
|
||||
clubName: "JMK RB",
|
||||
clubTagline: "Live Timing & Race Control",
|
||||
pdfFooter: "Generated by RC RaceCore",
|
||||
pdfTheme: "classic",
|
||||
logoDataUrl: "",
|
||||
racePresets: [],
|
||||
@@ -3143,14 +3152,7 @@ function setupLanguageControl() {
|
||||
if (label) {
|
||||
label.textContent = t("ui.language");
|
||||
}
|
||||
const brandTitle = document.getElementById("brandTitle");
|
||||
if (brandTitle) {
|
||||
brandTitle.textContent = t("brand.title");
|
||||
}
|
||||
const brandSubtitle = document.getElementById("brandSubtitle");
|
||||
if (brandSubtitle) {
|
||||
brandSubtitle.textContent = t("brand.subtitle");
|
||||
}
|
||||
updateAppBranding();
|
||||
|
||||
const select = document.getElementById("languageSelect");
|
||||
if (!(select instanceof HTMLSelectElement)) {
|
||||
@@ -3168,6 +3170,27 @@ function setupLanguageControl() {
|
||||
};
|
||||
}
|
||||
|
||||
function updateAppBranding() {
|
||||
const clubName = String(state.settings?.clubName || "").trim() || PRODUCT_NAME;
|
||||
const clubTagline = String(state.settings?.clubTagline || "").trim() || t("brand.subtitle");
|
||||
const logoDataUrl = String(state.settings?.logoDataUrl || "").trim();
|
||||
const hasLogo = /^data:image\/(?:png|jpeg|webp);base64,/i.test(logoDataUrl);
|
||||
const brandTitle = document.getElementById("brandTitle");
|
||||
const brandSubtitle = document.getElementById("brandSubtitle");
|
||||
const brandMark = document.getElementById("brandMark");
|
||||
const brandLogo = document.getElementById("brandLogo");
|
||||
|
||||
if (brandTitle) brandTitle.textContent = clubName;
|
||||
if (brandSubtitle) brandSubtitle.textContent = clubTagline;
|
||||
if (brandMark) brandMark.classList.toggle("has-logo", hasLogo);
|
||||
if (brandLogo instanceof HTMLImageElement) {
|
||||
brandLogo.hidden = !hasLogo;
|
||||
if (hasLogo) brandLogo.src = logoDataUrl;
|
||||
else brandLogo.removeAttribute("src");
|
||||
}
|
||||
document.title = clubName === PRODUCT_NAME ? PRODUCT_NAME : `${clubName} | ${PRODUCT_NAME}`;
|
||||
}
|
||||
|
||||
function buildPersistableState() {
|
||||
syncTrainingLedger();
|
||||
return {
|
||||
@@ -3193,7 +3216,7 @@ function normalizeImportedClass(classItem) {
|
||||
|
||||
function buildExportMeta(exportType) {
|
||||
return {
|
||||
app: "JMK RB RaceController",
|
||||
app: "RC RaceCore",
|
||||
schemaVersion: EXPORT_SCHEMA_VERSION,
|
||||
exportType,
|
||||
exportedAt: new Date().toISOString(),
|
||||
@@ -3571,6 +3594,7 @@ function updateViewUrl(view, driverId = "", classId = "") {
|
||||
}
|
||||
|
||||
function renderView() {
|
||||
updateAppBranding();
|
||||
if (currentView === "settings") settingsDraftActive = false;
|
||||
clearModalEscapeHandler();
|
||||
const navMeta = NAV_ITEMS.find((x) => x.id === currentView);
|
||||
|
||||
Reference in New Issue
Block a user