mirror of
https://github.com/kjanat/livegraphs-django.git
synced 2026-01-16 12:52:10 +01:00
Implement data integration tasks with Celery, including periodic fetching and manual refresh of chat data; add utility functions for data processing and transcript handling; create views and URLs for manual data refresh; establish Redis and Celery configuration; enhance error handling and logging; introduce scripts for data cleanup and fixing dashboard data; update documentation for Redis and Celery setup and troubleshooting.
This commit is contained in:
@ -7,6 +7,122 @@
|
||||
*/
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Set up Plotly default config based on theme
|
||||
function updatePlotlyTheme() {
|
||||
// Force a fresh check of the current theme
|
||||
const isDarkMode = document.documentElement.getAttribute("data-bs-theme") === "dark";
|
||||
console.log(
|
||||
"updatePlotlyTheme called - Current theme mode:",
|
||||
isDarkMode ? "dark" : "light",
|
||||
);
|
||||
|
||||
window.plotlyDefaultLayout = {
|
||||
font: {
|
||||
color: isDarkMode ? "#f8f9fa" : "#212529",
|
||||
family: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
||||
},
|
||||
paper_bgcolor: isDarkMode ? "#343a40" : "#ffffff",
|
||||
plot_bgcolor: isDarkMode ? "#343a40" : "#ffffff",
|
||||
colorway: [
|
||||
"#4285F4",
|
||||
"#EA4335",
|
||||
"#FBBC05",
|
||||
"#34A853",
|
||||
"#FF6D00",
|
||||
"#46BDC6",
|
||||
"#DB4437",
|
||||
"#0F9D58",
|
||||
"#AB47BC",
|
||||
"#00ACC1",
|
||||
],
|
||||
margin: {
|
||||
l: 50,
|
||||
r: 30,
|
||||
t: 30,
|
||||
b: 50,
|
||||
pad: 10,
|
||||
},
|
||||
hovermode: "closest",
|
||||
xaxis: {
|
||||
automargin: true,
|
||||
gridcolor: isDarkMode ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.1)",
|
||||
zerolinecolor: isDarkMode ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)",
|
||||
title: {
|
||||
font: {
|
||||
color: isDarkMode ? "#f8f9fa" : "#212529",
|
||||
},
|
||||
},
|
||||
tickfont: {
|
||||
color: isDarkMode ? "#f8f9fa" : "#212529",
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
automargin: true,
|
||||
gridcolor: isDarkMode ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.1)",
|
||||
zerolinecolor: isDarkMode ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)",
|
||||
title: {
|
||||
font: {
|
||||
color: isDarkMode ? "#f8f9fa" : "#212529",
|
||||
},
|
||||
},
|
||||
tickfont: {
|
||||
color: isDarkMode ? "#f8f9fa" : "#212529",
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
font: {
|
||||
color: isDarkMode ? "#f8f9fa" : "#212529",
|
||||
},
|
||||
bgcolor: isDarkMode ? "rgba(52, 58, 64, 0.8)" : "rgba(255, 255, 255, 0.8)",
|
||||
},
|
||||
modebar: {
|
||||
bgcolor: isDarkMode ? "rgba(52, 58, 64, 0.8)" : "rgba(255, 255, 255, 0.8)",
|
||||
color: isDarkMode ? "#f8f9fa" : "#212529",
|
||||
activecolor: isDarkMode ? "#6ea8fe" : "#007bff",
|
||||
},
|
||||
};
|
||||
|
||||
// Config for specific chart types
|
||||
window.plotlyBarConfig = {
|
||||
...window.plotlyDefaultLayout,
|
||||
bargap: 0.1,
|
||||
bargroupgap: 0.2,
|
||||
};
|
||||
|
||||
window.plotlyPieConfig = {
|
||||
...window.plotlyDefaultLayout,
|
||||
showlegend: true,
|
||||
legend: {
|
||||
...window.plotlyDefaultLayout.legend,
|
||||
xanchor: "center",
|
||||
yanchor: "top",
|
||||
y: -0.2,
|
||||
x: 0.5,
|
||||
orientation: "h",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Initialize theme setting
|
||||
updatePlotlyTheme();
|
||||
|
||||
// Listen for theme changes
|
||||
const observer = new MutationObserver(function (mutations) {
|
||||
mutations.forEach(function (mutation) {
|
||||
if (mutation.attributeName === "data-bs-theme") {
|
||||
console.log(
|
||||
"Theme changed detected by observer:",
|
||||
document.documentElement.getAttribute("data-bs-theme"),
|
||||
);
|
||||
updatePlotlyTheme();
|
||||
// Use a small delay to ensure styles have been applied
|
||||
setTimeout(refreshAllCharts, 100);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(document.documentElement, { attributes: true });
|
||||
|
||||
// Chart responsiveness
|
||||
function resizeCharts() {
|
||||
const charts = document.querySelectorAll(".chart-container");
|
||||
@ -20,6 +136,66 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
});
|
||||
}
|
||||
|
||||
// Refresh all charts with current theme
|
||||
function refreshAllCharts() {
|
||||
if (!window.Plotly) return;
|
||||
|
||||
const currentTheme = document.documentElement.getAttribute("data-bs-theme");
|
||||
console.log("Refreshing charts with theme:", currentTheme);
|
||||
|
||||
// Update the theme settings
|
||||
updatePlotlyTheme();
|
||||
|
||||
const charts = document.querySelectorAll(".chart-container");
|
||||
charts.forEach(function (chart) {
|
||||
if (chart.id) {
|
||||
try {
|
||||
// Safe way to check if element has a plot
|
||||
const plotElement = document.getElementById(chart.id);
|
||||
if (plotElement && plotElement._fullLayout) {
|
||||
console.log("Updating chart theme for:", chart.id);
|
||||
|
||||
// Determine chart type to apply appropriate settings
|
||||
let layoutUpdate = { ...window.plotlyDefaultLayout };
|
||||
|
||||
// Check if it's a bar chart
|
||||
if (
|
||||
plotElement.data &&
|
||||
plotElement.data.some((trace) => trace.type === "bar")
|
||||
) {
|
||||
layoutUpdate = { ...window.plotlyBarConfig };
|
||||
}
|
||||
|
||||
// Check if it's a pie chart
|
||||
if (
|
||||
plotElement.data &&
|
||||
plotElement.data.some((trace) => trace.type === "pie")
|
||||
) {
|
||||
layoutUpdate = { ...window.plotlyPieConfig };
|
||||
}
|
||||
|
||||
// Force paper and plot background colors based on current theme
|
||||
// This ensures the chart background always matches the current theme
|
||||
layoutUpdate.paper_bgcolor =
|
||||
currentTheme === "dark" ? "#343a40" : "#ffffff";
|
||||
layoutUpdate.plot_bgcolor = currentTheme === "dark" ? "#343a40" : "#ffffff";
|
||||
|
||||
// Update font colors too
|
||||
layoutUpdate.font.color = currentTheme === "dark" ? "#f8f9fa" : "#212529";
|
||||
|
||||
// Apply layout updates
|
||||
Plotly.relayout(chart.id, layoutUpdate);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error updating chart theme:", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Make refreshAllCharts available globally
|
||||
window.refreshAllCharts = refreshAllCharts;
|
||||
|
||||
// Handle window resize
|
||||
window.addEventListener("resize", function () {
|
||||
if (window.Plotly) {
|
||||
@ -27,6 +203,29 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}
|
||||
});
|
||||
|
||||
// Call resizeCharts on initial load
|
||||
if (window.Plotly) {
|
||||
// Use a longer delay to ensure charts are fully loaded
|
||||
setTimeout(function () {
|
||||
updatePlotlyTheme();
|
||||
refreshAllCharts();
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Apply theme to newly created charts
|
||||
const originalPlotlyNewPlot = Plotly.newPlot;
|
||||
Plotly.newPlot = function () {
|
||||
const args = Array.from(arguments);
|
||||
// Get the layout argument (3rd argument)
|
||||
if (args.length >= 3 && typeof args[2] === "object") {
|
||||
// Ensure plotlyDefaultLayout is up to date
|
||||
updatePlotlyTheme();
|
||||
// Apply current theme to new plot
|
||||
args[2] = { ...window.plotlyDefaultLayout, ...args[2] };
|
||||
}
|
||||
return originalPlotlyNewPlot.apply(this, args);
|
||||
};
|
||||
|
||||
// Time range filtering
|
||||
const timeRangeDropdown = document.getElementById("timeRangeDropdown");
|
||||
if (timeRangeDropdown) {
|
||||
@ -157,11 +356,14 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
},
|
||||
],
|
||||
{
|
||||
...window.plotlyDefaultLayout,
|
||||
margin: { t: 10, r: 10, b: 40, l: 40 },
|
||||
xaxis: {
|
||||
...window.plotlyDefaultLayout.xaxis,
|
||||
title: "Date",
|
||||
},
|
||||
yaxis: {
|
||||
...window.plotlyDefaultLayout.yaxis,
|
||||
title: "Number of Sessions",
|
||||
},
|
||||
},
|
||||
@ -204,6 +406,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
},
|
||||
],
|
||||
{
|
||||
...window.plotlyDefaultLayout,
|
||||
margin: { t: 10, r: 10, b: 10, l: 10 },
|
||||
},
|
||||
);
|
||||
@ -229,8 +432,10 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
},
|
||||
],
|
||||
{
|
||||
...window.plotlyDefaultLayout,
|
||||
margin: { t: 10, r: 10, b: 40, l: 100 },
|
||||
xaxis: {
|
||||
...window.plotlyDefaultLayout.xaxis,
|
||||
title: "Number of Sessions",
|
||||
},
|
||||
},
|
||||
@ -255,6 +460,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
},
|
||||
],
|
||||
{
|
||||
...window.plotlyDefaultLayout,
|
||||
margin: { t: 10, r: 10, b: 10, l: 10 },
|
||||
},
|
||||
);
|
||||
|
||||
@ -148,5 +148,99 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("resize", handleSidebarOnResize);
|
||||
window.addEventListener("resize", handleSidebarOnResize); // Theme toggling functionality
|
||||
function setTheme(theme, isUserPreference = false) {
|
||||
console.log("Setting theme to:", theme, "User preference:", isUserPreference);
|
||||
|
||||
// Update the HTML attribute that controls theme
|
||||
document.documentElement.setAttribute("data-bs-theme", theme);
|
||||
|
||||
// Save the theme preference to localStorage
|
||||
localStorage.setItem("theme", theme);
|
||||
|
||||
// If this was a user choice (from the toggle button), record that fact
|
||||
if (isUserPreference) {
|
||||
localStorage.setItem("userPreferredTheme", "true");
|
||||
}
|
||||
|
||||
// Update toggle button icon
|
||||
const themeToggle = document.getElementById("theme-toggle");
|
||||
if (themeToggle) {
|
||||
const icon = themeToggle.querySelector("i");
|
||||
if (theme === "dark") {
|
||||
icon.classList.remove("fa-moon");
|
||||
icon.classList.add("fa-sun");
|
||||
themeToggle.setAttribute("title", "Switch to light mode");
|
||||
themeToggle.setAttribute("aria-label", "Switch to light mode");
|
||||
} else {
|
||||
icon.classList.remove("fa-sun");
|
||||
icon.classList.add("fa-moon");
|
||||
themeToggle.setAttribute("title", "Switch to dark mode");
|
||||
themeToggle.setAttribute("aria-label", "Switch to dark mode");
|
||||
}
|
||||
}
|
||||
|
||||
// If we're on a page with charts, refresh them to match the theme
|
||||
if (typeof window.refreshAllCharts === "function") {
|
||||
console.log("Calling refresh charts from theme toggle");
|
||||
// Add a small delay to ensure DOM updates have completed
|
||||
setTimeout(window.refreshAllCharts, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the user has a system preference for dark mode
|
||||
function getSystemPreference() {
|
||||
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
}
|
||||
|
||||
// Initialize theme based on saved preference or system setting
|
||||
function initializeTheme() {
|
||||
// Check if the user has explicitly set a preference
|
||||
const hasUserPreference = localStorage.getItem("userPreferredTheme") === "true";
|
||||
const savedTheme = localStorage.getItem("theme");
|
||||
const systemTheme = getSystemPreference();
|
||||
|
||||
console.log("Theme initialization:", {
|
||||
hasUserPreference,
|
||||
savedTheme,
|
||||
systemTheme,
|
||||
});
|
||||
|
||||
// Use saved theme if it exists and was set by user
|
||||
// Otherwise, use system preference
|
||||
if (hasUserPreference && savedTheme) {
|
||||
setTheme(savedTheme);
|
||||
} else {
|
||||
// No user preference, use system preference
|
||||
setTheme(systemTheme);
|
||||
// Clear any saved theme to ensure it uses system preference
|
||||
localStorage.removeItem("userPreferredTheme");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize theme on page load
|
||||
initializeTheme();
|
||||
|
||||
// Listen for system preference changes
|
||||
const colorSchemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
colorSchemeMediaQuery.addEventListener("change", (e) => {
|
||||
// Only update theme based on system if user hasn't set a preference
|
||||
const hasUserPreference = localStorage.getItem("userPreferredTheme") === "true";
|
||||
console.log("System preference changed. Following system?", !hasUserPreference);
|
||||
|
||||
if (!hasUserPreference) {
|
||||
setTheme(e.matches ? "dark" : "light");
|
||||
}
|
||||
});
|
||||
|
||||
// Theme toggle button functionality
|
||||
const themeToggle = document.getElementById("theme-toggle");
|
||||
if (themeToggle) {
|
||||
themeToggle.addEventListener("click", function () {
|
||||
const currentTheme = document.documentElement.getAttribute("data-bs-theme") || "light";
|
||||
const newTheme = currentTheme === "dark" ? "light" : "dark";
|
||||
console.log("Manual theme toggle from", currentTheme, "to", newTheme);
|
||||
setTheme(newTheme, true); // true indicates this is a user preference
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user