{# Chart Module - Dynamic chart with Sample Data or HubDB integration #} {% set c = module.content %} {% set s = module.style %} {% set a = module.advanced %} {# Chart.js (201 KB) is NOT loaded eagerly. The inline script below lazy-loads it via IntersectionObserver only when a chart nears the viewport, and shares one load across all chart instances on the page. (chart-init.js also removed — it only initialised [data-chart-config] elements this module never emits.) #} {# Define color palette - used by both sample and HubDB data #} {# Each palette has: border (solid), bg (20% for line/area), bar_bg (80% for bars) #} {% if s.color_scheme == "theme" %} {% set color_palette = [ {"border": "rgba(59, 130, 246, 1)", "bg": "rgba(59, 130, 246, 0.2)", "bar_bg": "rgba(59, 130, 246, 0.8)"}, {"border": "rgba(255, 99, 132, 1)", "bg": "rgba(255, 99, 132, 0.2)", "bar_bg": "rgba(255, 99, 132, 0.8)"}, {"border": "rgba(16, 185, 129, 1)", "bg": "rgba(16, 185, 129, 0.2)", "bar_bg": "rgba(16, 185, 129, 0.8)"}, {"border": "rgba(245, 158, 11, 1)", "bg": "rgba(245, 158, 11, 0.2)", "bar_bg": "rgba(245, 158, 11, 0.8)"}, {"border": "rgba(139, 92, 246, 1)", "bg": "rgba(139, 92, 246, 0.2)", "bar_bg": "rgba(139, 92, 246, 0.8)"}, {"border": "rgba(236, 72, 153, 1)", "bg": "rgba(236, 72, 153, 0.2)", "bar_bg": "rgba(236, 72, 153, 0.8)"} ] %} {% elif s.color_scheme == "monochrome" %} {% set base_color = s.primary_color.color|default("#3b82f6") %} {% set color_palette = [ {"border": base_color, "bg": base_color ~ "33", "bar_bg": base_color ~ "cc"}, {"border": base_color, "bg": base_color ~ "26", "bar_bg": base_color ~ "b3"}, {"border": base_color, "bg": base_color ~ "1a", "bar_bg": base_color ~ "99"}, {"border": base_color, "bg": base_color ~ "0d", "bar_bg": base_color ~ "80"}, {"border": base_color ~ "cc", "bg": base_color ~ "1a", "bar_bg": base_color ~ "66"}, {"border": base_color ~ "99", "bg": base_color ~ "0d", "bar_bg": base_color ~ "4d"} ] %} {% elif s.color_scheme == "custom" and s.primary_color.color %} {% set base_color = s.primary_color.color %} {% set color_palette = [ {"border": base_color, "bg": base_color ~ "33", "bar_bg": base_color ~ "cc"}, {"border": "rgba(255, 99, 132, 1)", "bg": "rgba(255, 99, 132, 0.2)", "bar_bg": "rgba(255, 99, 132, 0.8)"}, {"border": "rgba(75, 192, 192, 1)", "bg": "rgba(75, 192, 192, 0.2)", "bar_bg": "rgba(75, 192, 192, 0.8)"}, {"border": "rgba(255, 206, 86, 1)", "bg": "rgba(255, 206, 86, 0.2)", "bar_bg": "rgba(255, 206, 86, 0.8)"}, {"border": "rgba(153, 102, 255, 1)", "bg": "rgba(153, 102, 255, 0.2)", "bar_bg": "rgba(153, 102, 255, 0.8)"}, {"border": "rgba(255, 159, 64, 1)", "bg": "rgba(255, 159, 64, 0.2)", "bar_bg": "rgba(255, 159, 64, 0.8)"} ] %} {% else %} {# Default color palette #} {% set color_palette = [ {"border": "rgba(54, 162, 235, 1)", "bg": "rgba(54, 162, 235, 0.2)", "bar_bg": "rgba(54, 162, 235, 0.8)"}, {"border": "rgba(255, 99, 132, 1)", "bg": "rgba(255, 99, 132, 0.2)", "bar_bg": "rgba(255, 99, 132, 0.8)"}, {"border": "rgba(75, 192, 192, 1)", "bg": "rgba(75, 192, 192, 0.2)", "bar_bg": "rgba(75, 192, 192, 0.8)"}, {"border": "rgba(255, 206, 86, 1)", "bg": "rgba(255, 206, 86, 0.2)", "bar_bg": "rgba(255, 206, 86, 0.8)"}, {"border": "rgba(153, 102, 255, 1)", "bg": "rgba(153, 102, 255, 0.2)", "bar_bg": "rgba(153, 102, 255, 0.8)"}, {"border": "rgba(255, 159, 64, 1)", "bg": "rgba(255, 159, 64, 0.2)", "bar_bg": "rgba(255, 159, 64, 0.8)"} ] %} {% endif %} {# Get style settings #} {% set line_tension = s.line_tension|default("0.4")|float %} {% set fill_area = s.fill_area|default(true) %} {% set bar_radius = s.border_radius|default("0")|int %} {# Determine data source and load appropriate data #} {% if c.data_source == "sample" %} {# Load sample dataset - inline data since HubL includes don't share scope #} {% if c.sample_dataset == "performance-metrics" %} {% set chart_labels = [ "Customer Satisfaction", "Website Performance", "Sales Conversion", "Brand Awareness", "Product Quality", "Customer Support", "Market Share", "Employee Satisfaction", "Innovation Index", "Social Engagement", "Mobile Experience", "Email Marketing", "Content Quality", "Lead Generation", "SEO Ranking", "User Retention", "Platform Stability", "Security Score", "API Response Time", "Data Accuracy", "Team Productivity", "Customer Loyalty", "Feature Adoption", "Revenue Growth" ] %} {% set sample_data = [ {"label": "Q1 2023", "data": [72, 68, 45, 58, 81, 76, 42, 69, 53, 61, 64, 57, 74, 51, 48, 79, 85, 88, 71, 82, 66, 73, 49, 56]}, {"label": "Q4 2024", "data": [94, 93, 75, 88, 96, 95, 66, 91, 83, 92, 94, 86, 96, 81, 81, 96, 98, 98, 94, 97, 91, 95, 81, 90]} ] %} {% set default_chart_type = "radar" %} {% set chart_title = "Performance Metrics: Q1 2023 vs Q4 2024" %} {% elif c.sample_dataset == "revenue-growth" %} {% set chart_labels = [ "Jan 2023", "Feb 2023", "Mar 2023", "Apr 2023", "May 2023", "Jun 2023", "Jul 2023", "Aug 2023", "Sep 2023", "Oct 2023", "Nov 2023", "Dec 2023", "Jan 2024", "Feb 2024", "Mar 2024", "Apr 2024", "May 2024", "Jun 2024", "Jul 2024", "Aug 2024", "Sep 2024", "Oct 2024", "Nov 2024", "Dec 2024" ] %} {% set sample_data = [ {"label": "SaaS Revenue", "data": [145000, 152000, 158000, 165000, 173000, 181000, 189000, 198000, 207000, 217000, 228000, 240000, 253000, 267000, 282000, 298000, 315000, 333000, 352000, 372000, 394000, 417000, 442000, 468000]}, {"label": "Consulting Revenue", "data": [82000, 88000, 91000, 95000, 99000, 104000, 108000, 113000, 118000, 124000, 130000, 136000, 143000, 150000, 158000, 166000, 174000, 183000, 192000, 202000, 212000, 223000, 235000, 247000]}, {"label": "Support Revenue", "data": [34000, 36000, 38000, 40000, 42000, 45000, 47000, 50000, 53000, 56000, 59000, 63000, 67000, 71000, 75000, 80000, 85000, 90000, 95000, 101000, 107000, 113000, 120000, 127000]} ] %} {% set default_chart_type = "line" %} {% set chart_title = "Revenue Growth (2023-2024)" %} {% endif %} {# Set chart type - user selection overrides default #} {% set chart_type = c.chart_type if c.chart_type else default_chart_type %} {# Override chart title if provided #} {% if c.chart_title %} {% set chart_title = c.chart_title %} {% endif %} {# Build datasets with proper colors based on chart type #} {% set chart_datasets = [] %} {% for item in sample_data %} {% set color = color_palette[loop.index0 % color_palette|length] %} {% if chart_type == "radar" %} {% set dataset = { "label": item.label, "data": item.data, "borderColor": color.border, "backgroundColor": color.bg, "pointBackgroundColor": color.border, "pointBorderColor": "#fff", "pointHoverBackgroundColor": "#fff", "pointHoverBorderColor": color.border } %} {% elif chart_type == "line" %} {% set dataset = { "label": item.label, "data": item.data, "borderColor": color.border, "backgroundColor": color.bg if fill_area else "transparent", "tension": line_tension, "fill": fill_area } %} {% elif chart_type == "bar" %} {% set dataset = { "label": item.label, "data": item.data, "borderColor": color.border, "backgroundColor": color.bar_bg, "borderRadius": bar_radius } %} {% else %} {% set dataset = { "label": item.label, "data": item.data, "borderColor": color.border, "backgroundColor": color.bar_bg } %} {% endif %} {% do chart_datasets.append(dataset) %} {% endfor %} {% elif c.data_source == "hubdb" and c.hubdb_table %} {# Load data from HubDB table #} {% set hubdb_rows = hubdb_table_rows(c.hubdb_table) %} {# Parse value column names #} {% set value_columns = c.hubdb_value_columns|split(',') %} {# Parse dataset labels if provided #} {% set dataset_label_list = [] %} {% if c.dataset_labels %} {% set dataset_label_list = c.dataset_labels|split(',') %} {% endif %} {# Build labels array from HubDB rows #} {% set chart_labels = [] %} {% for row in hubdb_rows %} {% do chart_labels.append(row[c.hubdb_label_column]) %} {% endfor %} {# Build datasets array from HubDB columns #} {% set chart_datasets = [] %} {% set chart_type = c.chart_type %} {% for col_name in value_columns %} {% set col_name_trimmed = col_name|trim %} {% set dataset_values = [] %} {# Extract values for this column #} {% for row in hubdb_rows %} {% do dataset_values.append(row[col_name_trimmed]) %} {% endfor %} {# Get color for this dataset #} {% set color_index = loop.index0 % color_palette|length %} {% set color = color_palette[color_index] %} {# Determine dataset label #} {% set dataset_label = col_name_trimmed %} {% if dataset_label_list and loop.index0 < dataset_label_list|length %} {% set dataset_label = dataset_label_list[loop.index0]|trim %} {% endif %} {# Build dataset object based on chart type #} {% set line_tension = s.line_tension|default("0.4")|float %} {% set fill_area = s.fill_area|default(true) %} {% if c.chart_type == "radar" %} {% set dataset = { "label": dataset_label, "data": dataset_values, "borderColor": color.border, "backgroundColor": color.bg, "pointBackgroundColor": color.border, "pointBorderColor": "#fff", "pointHoverBackgroundColor": "#fff", "pointHoverBorderColor": color.border } %} {% elif c.chart_type == "line" %} {% set dataset = { "label": dataset_label, "data": dataset_values, "borderColor": color.border, "backgroundColor": color.bg if fill_area else "transparent", "tension": line_tension, "fill": fill_area } %} {% elif c.chart_type == "bar" %} {% set dataset = { "label": dataset_label, "data": dataset_values, "borderColor": color.border, "backgroundColor": color.bar_bg, "borderRadius": s.border_radius|default("0")|int } %} {% else %} {# Pie, doughnut, polar area - use solid colors #} {% set dataset = { "label": dataset_label, "data": dataset_values, "borderColor": color.border, "backgroundColor": color.bar_bg } %} {% endif %} {% do chart_datasets.append(dataset) %} {% endfor %} {% set chart_title = c.chart_title if c.chart_title else "Chart" %} {% else %} {# No data source configured - show placeholder #} {% set show_placeholder = true %} {% endif %} {# Render chart or placeholder #} {% if show_placeholder %}

Configure the chart module to display data

{% else %} {# Chart container #}
{# Initialize chart #} {% endif %}