Chart library not available. Please refresh the page.
';
+ });
+ return;
+ }
+
+ // Update sessions over time chart
+ const timeSeriesData = data.time_series_data;
+ if (timeSeriesData && timeSeriesData.length > 0) {
+ try {
+ const timeSeriesX = timeSeriesData.map((item) => item.date);
+ const timeSeriesY = timeSeriesData.map((item) => item.count);
+
+ Plotly.react(
+ "sessions-time-chart",
+ [
+ {
+ x: timeSeriesX,
+ y: timeSeriesY,
+ type: "scatter",
+ mode: "lines+markers",
+ line: {
+ color: "rgb(75, 192, 192)",
+ width: 2,
+ },
+ marker: {
+ color: "rgb(75, 192, 192)",
+ size: 6,
+ },
+ },
+ ],
+ {
+ ...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",
+ },
+ },
+ );
+ } catch (error) {
+ console.error("Error rendering time series chart:", error);
+ document.getElementById("sessions-time-chart").innerHTML =
+ 'No time series data available
';
+ }
+
+ // Update sentiment chart
+ const sentimentData = data.sentiment_data;
+ if (sentimentData && sentimentData.length > 0 && window.Plotly) {
+ const sentimentLabels = sentimentData.map((item) => item.sentiment);
+ const sentimentValues = sentimentData.map((item) => item.count);
+ const sentimentColors = sentimentLabels.map((sentiment) => {
+ if (sentiment.toLowerCase().includes("positive")) return "rgb(75, 192, 92)";
+ if (sentiment.toLowerCase().includes("negative")) return "rgb(255, 99, 132)";
+ if (sentiment.toLowerCase().includes("neutral")) return "rgb(255, 205, 86)";
+ return "rgb(201, 203, 207)";
+ });
+
+ Plotly.react(
+ "sentiment-chart",
+ [
+ {
+ values: sentimentValues,
+ labels: sentimentLabels,
+ type: "pie",
+ marker: {
+ colors: sentimentColors,
+ },
+ hole: 0.4,
+ textinfo: "label+percent",
+ insidetextorientation: "radial",
+ },
+ ],
+ {
+ ...window.plotlyDefaultLayout,
+ margin: { t: 10, r: 10, b: 10, l: 10 },
+ },
+ );
+ }
+
+ // Update country chart
+ const countryData = data.country_data;
+ if (countryData && countryData.length > 0 && window.Plotly) {
+ const countryLabels = countryData.map((item) => item.country);
+ const countryValues = countryData.map((item) => item.count);
+
+ Plotly.react(
+ "country-chart",
+ [
+ {
+ x: countryValues,
+ y: countryLabels,
+ type: "bar",
+ orientation: "h",
+ marker: {
+ color: "rgb(54, 162, 235)",
+ },
+ },
+ ],
+ {
+ ...window.plotlyDefaultLayout,
+ margin: { t: 10, r: 10, b: 40, l: 100 },
+ xaxis: {
+ ...window.plotlyDefaultLayout.xaxis,
+ title: "Number of Sessions",
+ },
+ },
+ );
+ }
+
+ // Update category chart
+ const categoryData = data.category_data;
+ if (categoryData && categoryData.length > 0 && window.Plotly) {
+ const categoryLabels = categoryData.map((item) => item.category);
+ const categoryValues = categoryData.map((item) => item.count);
+
+ Plotly.react(
+ "category-chart",
+ [
+ {
+ labels: categoryLabels,
+ values: categoryValues,
+ type: "pie",
+ textinfo: "label+percent",
+ insidetextorientation: "radial",
+ },
+ ],
+ {
+ ...window.plotlyDefaultLayout,
+ margin: { t: 10, r: 10, b: 10, l: 10 },
+ },
+ );
+ }
+}
+
+document.addEventListener("DOMContentLoaded", function () {
// Initialize theme setting
updatePlotlyTheme();
@@ -122,19 +311,6 @@ document.addEventListener("DOMContentLoaded", function () {
observer.observe(document.documentElement, { attributes: true });
- // Chart responsiveness
- function resizeCharts() {
- const charts = document.querySelectorAll(".chart-container");
- charts.forEach((chart) => {
- if (chart.id && window.Plotly) {
- Plotly.relayout(chart.id, {
- "xaxis.automargin": true,
- "yaxis.automargin": true,
- });
- }
- });
- }
-
// Refresh all charts with current theme
function refreshAllCharts() {
if (!window.Plotly) return;
@@ -283,182 +459,6 @@ document.addEventListener("DOMContentLoaded", function () {
});
}
- // Function to update dashboard statistics
- function updateDashboardStats(data) {
- // Update total sessions
- const totalSessionsElement = document.querySelector(".stats-card:nth-child(1) h3");
- if (totalSessionsElement) {
- totalSessionsElement.textContent = data.total_sessions;
- }
-
- // Update average response time
- const avgResponseTimeElement = document.querySelector(".stats-card:nth-child(2) h3");
- if (avgResponseTimeElement) {
- avgResponseTimeElement.textContent = data.avg_response_time + "s";
- }
-
- // Update total tokens
- const totalTokensElement = document.querySelector(".stats-card:nth-child(3) h3");
- if (totalTokensElement) {
- totalTokensElement.textContent = data.total_tokens;
- }
-
- // Update total cost
- const totalCostElement = document.querySelector(".stats-card:nth-child(4) h3");
- if (totalCostElement) {
- totalCostElement.textContent = "€" + data.total_cost;
- }
- }
-
- // Function to update dashboard charts
- function updateDashboardCharts(data) {
- // Check if Plotly is available
- if (!window.Plotly) {
- console.error("Plotly library not loaded!");
- document.querySelectorAll(".chart-container").forEach((container) => {
- container.innerHTML =
- 'Chart library not available. Please refresh the page.
';
- });
- return;
- }
-
- // Update sessions over time chart
- const timeSeriesData = data.time_series_data;
- if (timeSeriesData && timeSeriesData.length > 0) {
- try {
- const timeSeriesX = timeSeriesData.map((item) => item.date);
- const timeSeriesY = timeSeriesData.map((item) => item.count);
-
- Plotly.react(
- "sessions-time-chart",
- [
- {
- x: timeSeriesX,
- y: timeSeriesY,
- type: "scatter",
- mode: "lines+markers",
- line: {
- color: "rgb(75, 192, 192)",
- width: 2,
- },
- marker: {
- color: "rgb(75, 192, 192)",
- size: 6,
- },
- },
- ],
- {
- ...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",
- },
- },
- );
- } catch (error) {
- console.error("Error rendering time series chart:", error);
- document.getElementById("sessions-time-chart").innerHTML =
- 'No time series data available
';
- }
-
- // Update sentiment chart
- const sentimentData = data.sentiment_data;
- if (sentimentData && sentimentData.length > 0 && window.Plotly) {
- const sentimentLabels = sentimentData.map((item) => item.sentiment);
- const sentimentValues = sentimentData.map((item) => item.count);
- const sentimentColors = sentimentLabels.map((sentiment) => {
- if (sentiment.toLowerCase().includes("positive")) return "rgb(75, 192, 92)";
- if (sentiment.toLowerCase().includes("negative")) return "rgb(255, 99, 132)";
- if (sentiment.toLowerCase().includes("neutral")) return "rgb(255, 205, 86)";
- return "rgb(201, 203, 207)";
- });
-
- Plotly.react(
- "sentiment-chart",
- [
- {
- values: sentimentValues,
- labels: sentimentLabels,
- type: "pie",
- marker: {
- colors: sentimentColors,
- },
- hole: 0.4,
- textinfo: "label+percent",
- insidetextorientation: "radial",
- },
- ],
- {
- ...window.plotlyDefaultLayout,
- margin: { t: 10, r: 10, b: 10, l: 10 },
- },
- );
- }
-
- // Update country chart
- const countryData = data.country_data;
- if (countryData && countryData.length > 0 && window.Plotly) {
- const countryLabels = countryData.map((item) => item.country);
- const countryValues = countryData.map((item) => item.count);
-
- Plotly.react(
- "country-chart",
- [
- {
- x: countryValues,
- y: countryLabels,
- type: "bar",
- orientation: "h",
- marker: {
- color: "rgb(54, 162, 235)",
- },
- },
- ],
- {
- ...window.plotlyDefaultLayout,
- margin: { t: 10, r: 10, b: 40, l: 100 },
- xaxis: {
- ...window.plotlyDefaultLayout.xaxis,
- title: "Number of Sessions",
- },
- },
- );
- }
-
- // Update category chart
- const categoryData = data.category_data;
- if (categoryData && categoryData.length > 0 && window.Plotly) {
- const categoryLabels = categoryData.map((item) => item.category);
- const categoryValues = categoryData.map((item) => item.count);
-
- Plotly.react(
- "category-chart",
- [
- {
- labels: categoryLabels,
- values: categoryValues,
- type: "pie",
- textinfo: "label+percent",
- insidetextorientation: "radial",
- },
- ],
- {
- ...window.plotlyDefaultLayout,
- margin: { t: 10, r: 10, b: 10, l: 10 },
- },
- );
- }
- }
-
// Dashboard selector
const dashboardSelector = document.querySelectorAll('a[href^="?dashboard_id="]');
dashboardSelector.forEach((link) => {
diff --git a/dashboard_project/static/js/main.js b/dashboard_project/static/js/main.js
index 4884e82..4b358a4 100644
--- a/dashboard_project/static/js/main.js
+++ b/dashboard_project/static/js/main.js
@@ -6,6 +6,58 @@
* the entire application, including navigation, forms, and UI interactions.
*/
+// Handle sidebar collapse on small screens
+function handleSidebarOnResize() {
+ if (window.innerWidth < 768) {
+ document.querySelector(".sidebar")?.classList.remove("show");
+ }
+}
+
+// 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";
+}
+
document.addEventListener("DOMContentLoaded", function () {
// Initialize tooltips
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
@@ -142,57 +194,7 @@ document.addEventListener("DOMContentLoaded", function () {
});
});
- // Handle sidebar collapse on small screens
- function handleSidebarOnResize() {
- if (window.innerWidth < 768) {
- document.querySelector(".sidebar")?.classList.remove("show");
- }
- }
-
- 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";
- }
+ window.addEventListener("resize", handleSidebarOnResize);
// Initialize theme based on saved preference or system setting
function initializeTheme() {