truthound-dashboard 1.3.1__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- truthound_dashboard/api/alerts.py +258 -0
- truthound_dashboard/api/anomaly.py +1302 -0
- truthound_dashboard/api/cross_alerts.py +352 -0
- truthound_dashboard/api/deps.py +143 -0
- truthound_dashboard/api/drift_monitor.py +540 -0
- truthound_dashboard/api/lineage.py +1151 -0
- truthound_dashboard/api/maintenance.py +363 -0
- truthound_dashboard/api/middleware.py +373 -1
- truthound_dashboard/api/model_monitoring.py +805 -0
- truthound_dashboard/api/notifications_advanced.py +2452 -0
- truthound_dashboard/api/plugins.py +2096 -0
- truthound_dashboard/api/profile.py +211 -14
- truthound_dashboard/api/reports.py +853 -0
- truthound_dashboard/api/router.py +147 -0
- truthound_dashboard/api/rule_suggestions.py +310 -0
- truthound_dashboard/api/schema_evolution.py +231 -0
- truthound_dashboard/api/sources.py +47 -3
- truthound_dashboard/api/triggers.py +190 -0
- truthound_dashboard/api/validations.py +13 -0
- truthound_dashboard/api/validators.py +333 -4
- truthound_dashboard/api/versioning.py +309 -0
- truthound_dashboard/api/websocket.py +301 -0
- truthound_dashboard/core/__init__.py +27 -0
- truthound_dashboard/core/anomaly.py +1395 -0
- truthound_dashboard/core/anomaly_explainer.py +633 -0
- truthound_dashboard/core/cache.py +206 -0
- truthound_dashboard/core/cached_services.py +422 -0
- truthound_dashboard/core/charts.py +352 -0
- truthound_dashboard/core/connections.py +1069 -42
- truthound_dashboard/core/cross_alerts.py +837 -0
- truthound_dashboard/core/drift_monitor.py +1477 -0
- truthound_dashboard/core/drift_sampling.py +669 -0
- truthound_dashboard/core/i18n/__init__.py +42 -0
- truthound_dashboard/core/i18n/detector.py +173 -0
- truthound_dashboard/core/i18n/messages.py +564 -0
- truthound_dashboard/core/lineage.py +971 -0
- truthound_dashboard/core/maintenance.py +443 -5
- truthound_dashboard/core/model_monitoring.py +1043 -0
- truthound_dashboard/core/notifications/channels.py +1020 -1
- truthound_dashboard/core/notifications/deduplication/__init__.py +143 -0
- truthound_dashboard/core/notifications/deduplication/policies.py +274 -0
- truthound_dashboard/core/notifications/deduplication/service.py +400 -0
- truthound_dashboard/core/notifications/deduplication/stores.py +2365 -0
- truthound_dashboard/core/notifications/deduplication/strategies.py +422 -0
- truthound_dashboard/core/notifications/dispatcher.py +43 -0
- truthound_dashboard/core/notifications/escalation/__init__.py +149 -0
- truthound_dashboard/core/notifications/escalation/backends.py +1384 -0
- truthound_dashboard/core/notifications/escalation/engine.py +429 -0
- truthound_dashboard/core/notifications/escalation/models.py +336 -0
- truthound_dashboard/core/notifications/escalation/scheduler.py +1187 -0
- truthound_dashboard/core/notifications/escalation/state_machine.py +330 -0
- truthound_dashboard/core/notifications/escalation/stores.py +2896 -0
- truthound_dashboard/core/notifications/events.py +49 -0
- truthound_dashboard/core/notifications/metrics/__init__.py +115 -0
- truthound_dashboard/core/notifications/metrics/base.py +528 -0
- truthound_dashboard/core/notifications/metrics/collectors.py +583 -0
- truthound_dashboard/core/notifications/routing/__init__.py +169 -0
- truthound_dashboard/core/notifications/routing/combinators.py +184 -0
- truthound_dashboard/core/notifications/routing/config.py +375 -0
- truthound_dashboard/core/notifications/routing/config_parser.py +867 -0
- truthound_dashboard/core/notifications/routing/engine.py +382 -0
- truthound_dashboard/core/notifications/routing/expression_engine.py +1269 -0
- truthound_dashboard/core/notifications/routing/jinja2_engine.py +774 -0
- truthound_dashboard/core/notifications/routing/rules.py +625 -0
- truthound_dashboard/core/notifications/routing/validator.py +678 -0
- truthound_dashboard/core/notifications/service.py +2 -0
- truthound_dashboard/core/notifications/stats_aggregator.py +850 -0
- truthound_dashboard/core/notifications/throttling/__init__.py +83 -0
- truthound_dashboard/core/notifications/throttling/builder.py +311 -0
- truthound_dashboard/core/notifications/throttling/stores.py +1859 -0
- truthound_dashboard/core/notifications/throttling/throttlers.py +633 -0
- truthound_dashboard/core/openlineage.py +1028 -0
- truthound_dashboard/core/plugins/__init__.py +39 -0
- truthound_dashboard/core/plugins/docs/__init__.py +39 -0
- truthound_dashboard/core/plugins/docs/extractor.py +703 -0
- truthound_dashboard/core/plugins/docs/renderers.py +804 -0
- truthound_dashboard/core/plugins/hooks/__init__.py +63 -0
- truthound_dashboard/core/plugins/hooks/decorators.py +367 -0
- truthound_dashboard/core/plugins/hooks/manager.py +403 -0
- truthound_dashboard/core/plugins/hooks/protocols.py +265 -0
- truthound_dashboard/core/plugins/lifecycle/__init__.py +41 -0
- truthound_dashboard/core/plugins/lifecycle/hot_reload.py +584 -0
- truthound_dashboard/core/plugins/lifecycle/machine.py +419 -0
- truthound_dashboard/core/plugins/lifecycle/states.py +266 -0
- truthound_dashboard/core/plugins/loader.py +504 -0
- truthound_dashboard/core/plugins/registry.py +810 -0
- truthound_dashboard/core/plugins/reporter_executor.py +588 -0
- truthound_dashboard/core/plugins/sandbox/__init__.py +59 -0
- truthound_dashboard/core/plugins/sandbox/code_validator.py +243 -0
- truthound_dashboard/core/plugins/sandbox/engines.py +770 -0
- truthound_dashboard/core/plugins/sandbox/protocols.py +194 -0
- truthound_dashboard/core/plugins/sandbox.py +617 -0
- truthound_dashboard/core/plugins/security/__init__.py +68 -0
- truthound_dashboard/core/plugins/security/analyzer.py +535 -0
- truthound_dashboard/core/plugins/security/policies.py +311 -0
- truthound_dashboard/core/plugins/security/protocols.py +296 -0
- truthound_dashboard/core/plugins/security/signing.py +842 -0
- truthound_dashboard/core/plugins/security.py +446 -0
- truthound_dashboard/core/plugins/validator_executor.py +401 -0
- truthound_dashboard/core/plugins/versioning/__init__.py +51 -0
- truthound_dashboard/core/plugins/versioning/constraints.py +377 -0
- truthound_dashboard/core/plugins/versioning/dependencies.py +541 -0
- truthound_dashboard/core/plugins/versioning/semver.py +266 -0
- truthound_dashboard/core/profile_comparison.py +601 -0
- truthound_dashboard/core/report_history.py +570 -0
- truthound_dashboard/core/reporters/__init__.py +57 -0
- truthound_dashboard/core/reporters/base.py +296 -0
- truthound_dashboard/core/reporters/csv_reporter.py +155 -0
- truthound_dashboard/core/reporters/html_reporter.py +598 -0
- truthound_dashboard/core/reporters/i18n/__init__.py +65 -0
- truthound_dashboard/core/reporters/i18n/base.py +494 -0
- truthound_dashboard/core/reporters/i18n/catalogs.py +930 -0
- truthound_dashboard/core/reporters/json_reporter.py +160 -0
- truthound_dashboard/core/reporters/junit_reporter.py +233 -0
- truthound_dashboard/core/reporters/markdown_reporter.py +207 -0
- truthound_dashboard/core/reporters/pdf_reporter.py +209 -0
- truthound_dashboard/core/reporters/registry.py +272 -0
- truthound_dashboard/core/rule_generator.py +2088 -0
- truthound_dashboard/core/scheduler.py +822 -12
- truthound_dashboard/core/schema_evolution.py +858 -0
- truthound_dashboard/core/services.py +152 -9
- truthound_dashboard/core/statistics.py +718 -0
- truthound_dashboard/core/streaming_anomaly.py +883 -0
- truthound_dashboard/core/triggers/__init__.py +45 -0
- truthound_dashboard/core/triggers/base.py +226 -0
- truthound_dashboard/core/triggers/evaluators.py +609 -0
- truthound_dashboard/core/triggers/factory.py +363 -0
- truthound_dashboard/core/unified_alerts.py +870 -0
- truthound_dashboard/core/validation_limits.py +509 -0
- truthound_dashboard/core/versioning.py +709 -0
- truthound_dashboard/core/websocket/__init__.py +59 -0
- truthound_dashboard/core/websocket/manager.py +512 -0
- truthound_dashboard/core/websocket/messages.py +130 -0
- truthound_dashboard/db/__init__.py +30 -0
- truthound_dashboard/db/models.py +3375 -3
- truthound_dashboard/main.py +22 -0
- truthound_dashboard/schemas/__init__.py +396 -1
- truthound_dashboard/schemas/anomaly.py +1258 -0
- truthound_dashboard/schemas/base.py +4 -0
- truthound_dashboard/schemas/cross_alerts.py +334 -0
- truthound_dashboard/schemas/drift_monitor.py +890 -0
- truthound_dashboard/schemas/lineage.py +428 -0
- truthound_dashboard/schemas/maintenance.py +154 -0
- truthound_dashboard/schemas/model_monitoring.py +374 -0
- truthound_dashboard/schemas/notifications_advanced.py +1363 -0
- truthound_dashboard/schemas/openlineage.py +704 -0
- truthound_dashboard/schemas/plugins.py +1293 -0
- truthound_dashboard/schemas/profile.py +420 -34
- truthound_dashboard/schemas/profile_comparison.py +242 -0
- truthound_dashboard/schemas/reports.py +285 -0
- truthound_dashboard/schemas/rule_suggestion.py +434 -0
- truthound_dashboard/schemas/schema_evolution.py +164 -0
- truthound_dashboard/schemas/source.py +117 -2
- truthound_dashboard/schemas/triggers.py +511 -0
- truthound_dashboard/schemas/unified_alerts.py +223 -0
- truthound_dashboard/schemas/validation.py +25 -1
- truthound_dashboard/schemas/validators/__init__.py +11 -0
- truthound_dashboard/schemas/validators/base.py +151 -0
- truthound_dashboard/schemas/versioning.py +152 -0
- truthound_dashboard/static/index.html +2 -2
- {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.0.dist-info}/METADATA +142 -22
- truthound_dashboard-1.4.0.dist-info/RECORD +239 -0
- truthound_dashboard/static/assets/index-BZG20KuF.js +0 -586
- truthound_dashboard/static/assets/index-D_HyZ3pb.css +0 -1
- truthound_dashboard/static/assets/unmerged_dictionaries-CtpqQBm0.js +0 -1
- truthound_dashboard-1.3.1.dist-info/RECORD +0 -110
- {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.0.dist-info}/WHEEL +0 -0
- {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.0.dist-info}/entry_points.txt +0 -0
- {truthound_dashboard-1.3.1.dist-info → truthound_dashboard-1.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"""Chart library configuration and selection system.
|
|
2
|
+
|
|
3
|
+
This module provides a pluggable chart library system supporting:
|
|
4
|
+
- Recharts (default, React-based)
|
|
5
|
+
- Chart.js (Canvas-based)
|
|
6
|
+
- ECharts (Apache ECharts)
|
|
7
|
+
- Plotly (Interactive scientific charts)
|
|
8
|
+
- SVG (Native SVG generation)
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
from truthound_dashboard.core.charts import (
|
|
12
|
+
ChartLibrary,
|
|
13
|
+
get_chart_config,
|
|
14
|
+
set_chart_library,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# Set preferred library
|
|
18
|
+
set_chart_library(ChartLibrary.CHARTJS)
|
|
19
|
+
|
|
20
|
+
# Get configuration for frontend
|
|
21
|
+
config = get_chart_config()
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import logging
|
|
27
|
+
from dataclasses import dataclass, field
|
|
28
|
+
from enum import Enum
|
|
29
|
+
from typing import Any
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ChartLibrary(str, Enum):
|
|
35
|
+
"""Supported chart libraries."""
|
|
36
|
+
|
|
37
|
+
RECHARTS = "recharts" # Default, React-based
|
|
38
|
+
CHARTJS = "chartjs" # Chart.js (canvas)
|
|
39
|
+
ECHARTS = "echarts" # Apache ECharts
|
|
40
|
+
PLOTLY = "plotly" # Plotly.js
|
|
41
|
+
SVG = "svg" # Native SVG rendering
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ChartType(str, Enum):
|
|
45
|
+
"""Available chart types."""
|
|
46
|
+
|
|
47
|
+
LINE = "line"
|
|
48
|
+
BAR = "bar"
|
|
49
|
+
AREA = "area"
|
|
50
|
+
PIE = "pie"
|
|
51
|
+
DONUT = "donut"
|
|
52
|
+
SCATTER = "scatter"
|
|
53
|
+
RADAR = "radar"
|
|
54
|
+
HEATMAP = "heatmap"
|
|
55
|
+
TREEMAP = "treemap"
|
|
56
|
+
GAUGE = "gauge"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class ChartLibraryConfig:
|
|
61
|
+
"""Configuration for a chart library.
|
|
62
|
+
|
|
63
|
+
Attributes:
|
|
64
|
+
library: The chart library to use.
|
|
65
|
+
npm_package: NPM package name for installation.
|
|
66
|
+
version: Recommended version.
|
|
67
|
+
supported_charts: List of supported chart types.
|
|
68
|
+
options: Library-specific default options.
|
|
69
|
+
cdn_url: CDN URL for script loading (if applicable).
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
library: ChartLibrary
|
|
73
|
+
npm_package: str
|
|
74
|
+
version: str
|
|
75
|
+
supported_charts: list[ChartType] = field(default_factory=list)
|
|
76
|
+
options: dict[str, Any] = field(default_factory=dict)
|
|
77
|
+
cdn_url: str | None = None
|
|
78
|
+
|
|
79
|
+
def to_dict(self) -> dict[str, Any]:
|
|
80
|
+
"""Convert to dictionary."""
|
|
81
|
+
return {
|
|
82
|
+
"library": self.library.value,
|
|
83
|
+
"npm_package": self.npm_package,
|
|
84
|
+
"version": self.version,
|
|
85
|
+
"supported_charts": [c.value for c in self.supported_charts],
|
|
86
|
+
"options": self.options,
|
|
87
|
+
"cdn_url": self.cdn_url,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Library configurations
|
|
92
|
+
CHART_LIBRARY_CONFIGS: dict[ChartLibrary, ChartLibraryConfig] = {
|
|
93
|
+
ChartLibrary.RECHARTS: ChartLibraryConfig(
|
|
94
|
+
library=ChartLibrary.RECHARTS,
|
|
95
|
+
npm_package="recharts",
|
|
96
|
+
version="^2.10.0",
|
|
97
|
+
supported_charts=[
|
|
98
|
+
ChartType.LINE,
|
|
99
|
+
ChartType.BAR,
|
|
100
|
+
ChartType.AREA,
|
|
101
|
+
ChartType.PIE,
|
|
102
|
+
ChartType.SCATTER,
|
|
103
|
+
ChartType.RADAR,
|
|
104
|
+
ChartType.TREEMAP,
|
|
105
|
+
],
|
|
106
|
+
options={
|
|
107
|
+
"responsive": True,
|
|
108
|
+
"animationDuration": 300,
|
|
109
|
+
"margin": {"top": 5, "right": 30, "left": 20, "bottom": 5},
|
|
110
|
+
},
|
|
111
|
+
),
|
|
112
|
+
ChartLibrary.CHARTJS: ChartLibraryConfig(
|
|
113
|
+
library=ChartLibrary.CHARTJS,
|
|
114
|
+
npm_package="chart.js",
|
|
115
|
+
version="^4.4.0",
|
|
116
|
+
supported_charts=[
|
|
117
|
+
ChartType.LINE,
|
|
118
|
+
ChartType.BAR,
|
|
119
|
+
ChartType.PIE,
|
|
120
|
+
ChartType.DONUT,
|
|
121
|
+
ChartType.SCATTER,
|
|
122
|
+
ChartType.RADAR,
|
|
123
|
+
],
|
|
124
|
+
options={
|
|
125
|
+
"responsive": True,
|
|
126
|
+
"maintainAspectRatio": False,
|
|
127
|
+
"animation": {"duration": 300},
|
|
128
|
+
"plugins": {"legend": {"display": True}},
|
|
129
|
+
},
|
|
130
|
+
cdn_url="https://cdn.jsdelivr.net/npm/chart.js",
|
|
131
|
+
),
|
|
132
|
+
ChartLibrary.ECHARTS: ChartLibraryConfig(
|
|
133
|
+
library=ChartLibrary.ECHARTS,
|
|
134
|
+
npm_package="echarts",
|
|
135
|
+
version="^5.4.0",
|
|
136
|
+
supported_charts=[
|
|
137
|
+
ChartType.LINE,
|
|
138
|
+
ChartType.BAR,
|
|
139
|
+
ChartType.AREA,
|
|
140
|
+
ChartType.PIE,
|
|
141
|
+
ChartType.SCATTER,
|
|
142
|
+
ChartType.RADAR,
|
|
143
|
+
ChartType.HEATMAP,
|
|
144
|
+
ChartType.TREEMAP,
|
|
145
|
+
ChartType.GAUGE,
|
|
146
|
+
],
|
|
147
|
+
options={
|
|
148
|
+
"animation": True,
|
|
149
|
+
"animationDuration": 300,
|
|
150
|
+
"tooltip": {"trigger": "axis"},
|
|
151
|
+
"grid": {"left": "3%", "right": "4%", "bottom": "3%", "containLabel": True},
|
|
152
|
+
},
|
|
153
|
+
cdn_url="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js",
|
|
154
|
+
),
|
|
155
|
+
ChartLibrary.PLOTLY: ChartLibraryConfig(
|
|
156
|
+
library=ChartLibrary.PLOTLY,
|
|
157
|
+
npm_package="plotly.js",
|
|
158
|
+
version="^2.27.0",
|
|
159
|
+
supported_charts=[
|
|
160
|
+
ChartType.LINE,
|
|
161
|
+
ChartType.BAR,
|
|
162
|
+
ChartType.AREA,
|
|
163
|
+
ChartType.PIE,
|
|
164
|
+
ChartType.SCATTER,
|
|
165
|
+
ChartType.HEATMAP,
|
|
166
|
+
],
|
|
167
|
+
options={
|
|
168
|
+
"responsive": True,
|
|
169
|
+
"displayModeBar": False,
|
|
170
|
+
"staticPlot": False,
|
|
171
|
+
},
|
|
172
|
+
cdn_url="https://cdn.plot.ly/plotly-2.27.0.min.js",
|
|
173
|
+
),
|
|
174
|
+
ChartLibrary.SVG: ChartLibraryConfig(
|
|
175
|
+
library=ChartLibrary.SVG,
|
|
176
|
+
npm_package="d3", # Uses D3 for SVG generation
|
|
177
|
+
version="^7.8.0",
|
|
178
|
+
supported_charts=[
|
|
179
|
+
ChartType.LINE,
|
|
180
|
+
ChartType.BAR,
|
|
181
|
+
ChartType.AREA,
|
|
182
|
+
ChartType.PIE,
|
|
183
|
+
],
|
|
184
|
+
options={
|
|
185
|
+
"viewBox": "0 0 400 300",
|
|
186
|
+
"preserveAspectRatio": "xMidYMid meet",
|
|
187
|
+
},
|
|
188
|
+
cdn_url="https://cdn.jsdelivr.net/npm/d3@7",
|
|
189
|
+
),
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@dataclass
|
|
194
|
+
class ChartSettings:
|
|
195
|
+
"""Global chart settings.
|
|
196
|
+
|
|
197
|
+
Attributes:
|
|
198
|
+
library: Active chart library.
|
|
199
|
+
theme: Chart color theme (light/dark/custom).
|
|
200
|
+
primary_color: Primary accent color.
|
|
201
|
+
animation_enabled: Whether animations are enabled.
|
|
202
|
+
default_height: Default chart height in pixels.
|
|
203
|
+
custom_options: Additional library-specific options.
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
library: ChartLibrary = ChartLibrary.RECHARTS
|
|
207
|
+
theme: str = "light"
|
|
208
|
+
primary_color: str = "#fd9e4b" # Truthound primary color
|
|
209
|
+
animation_enabled: bool = True
|
|
210
|
+
default_height: int = 300
|
|
211
|
+
custom_options: dict[str, Any] = field(default_factory=dict)
|
|
212
|
+
|
|
213
|
+
def get_library_config(self) -> ChartLibraryConfig:
|
|
214
|
+
"""Get configuration for the active library."""
|
|
215
|
+
return CHART_LIBRARY_CONFIGS[self.library]
|
|
216
|
+
|
|
217
|
+
def to_dict(self) -> dict[str, Any]:
|
|
218
|
+
"""Convert to dictionary for API response."""
|
|
219
|
+
library_config = self.get_library_config()
|
|
220
|
+
return {
|
|
221
|
+
"library": self.library.value,
|
|
222
|
+
"theme": self.theme,
|
|
223
|
+
"primary_color": self.primary_color,
|
|
224
|
+
"animation_enabled": self.animation_enabled,
|
|
225
|
+
"default_height": self.default_height,
|
|
226
|
+
"custom_options": self.custom_options,
|
|
227
|
+
"library_config": library_config.to_dict(),
|
|
228
|
+
"available_libraries": [
|
|
229
|
+
{
|
|
230
|
+
"library": lib.value,
|
|
231
|
+
"name": lib.value.title(),
|
|
232
|
+
"npm_package": cfg.npm_package,
|
|
233
|
+
"supported_charts": [c.value for c in cfg.supported_charts],
|
|
234
|
+
}
|
|
235
|
+
for lib, cfg in CHART_LIBRARY_CONFIGS.items()
|
|
236
|
+
],
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# Singleton settings instance
|
|
241
|
+
_chart_settings: ChartSettings | None = None
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def get_chart_settings() -> ChartSettings:
|
|
245
|
+
"""Get global chart settings singleton.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
ChartSettings instance.
|
|
249
|
+
"""
|
|
250
|
+
global _chart_settings
|
|
251
|
+
if _chart_settings is None:
|
|
252
|
+
_chart_settings = ChartSettings()
|
|
253
|
+
return _chart_settings
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def set_chart_library(library: ChartLibrary | str) -> None:
|
|
257
|
+
"""Set the active chart library.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
library: Chart library to use.
|
|
261
|
+
"""
|
|
262
|
+
if isinstance(library, str):
|
|
263
|
+
library = ChartLibrary(library.lower())
|
|
264
|
+
|
|
265
|
+
settings = get_chart_settings()
|
|
266
|
+
settings.library = library
|
|
267
|
+
logger.info(f"Chart library set to: {library.value}")
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def set_chart_theme(theme: str, primary_color: str | None = None) -> None:
|
|
271
|
+
"""Set chart theme settings.
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
theme: Theme name (light, dark, custom).
|
|
275
|
+
primary_color: Primary accent color (hex).
|
|
276
|
+
"""
|
|
277
|
+
settings = get_chart_settings()
|
|
278
|
+
settings.theme = theme
|
|
279
|
+
if primary_color:
|
|
280
|
+
settings.primary_color = primary_color
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def get_chart_config() -> dict[str, Any]:
|
|
284
|
+
"""Get current chart configuration for frontend.
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Dictionary with chart settings and library info.
|
|
288
|
+
"""
|
|
289
|
+
return get_chart_settings().to_dict()
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def update_chart_settings(
|
|
293
|
+
library: str | None = None,
|
|
294
|
+
theme: str | None = None,
|
|
295
|
+
primary_color: str | None = None,
|
|
296
|
+
animation_enabled: bool | None = None,
|
|
297
|
+
default_height: int | None = None,
|
|
298
|
+
custom_options: dict[str, Any] | None = None,
|
|
299
|
+
) -> ChartSettings:
|
|
300
|
+
"""Update chart settings.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
library: Chart library name.
|
|
304
|
+
theme: Color theme.
|
|
305
|
+
primary_color: Primary color hex.
|
|
306
|
+
animation_enabled: Enable animations.
|
|
307
|
+
default_height: Default chart height.
|
|
308
|
+
custom_options: Custom library options.
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
Updated ChartSettings.
|
|
312
|
+
"""
|
|
313
|
+
settings = get_chart_settings()
|
|
314
|
+
|
|
315
|
+
if library is not None:
|
|
316
|
+
settings.library = ChartLibrary(library.lower())
|
|
317
|
+
if theme is not None:
|
|
318
|
+
settings.theme = theme
|
|
319
|
+
if primary_color is not None:
|
|
320
|
+
settings.primary_color = primary_color
|
|
321
|
+
if animation_enabled is not None:
|
|
322
|
+
settings.animation_enabled = animation_enabled
|
|
323
|
+
if default_height is not None:
|
|
324
|
+
settings.default_height = default_height
|
|
325
|
+
if custom_options is not None:
|
|
326
|
+
settings.custom_options.update(custom_options)
|
|
327
|
+
|
|
328
|
+
return settings
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def get_supported_chart_types(library: ChartLibrary | str | None = None) -> list[str]:
|
|
332
|
+
"""Get chart types supported by a library.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
library: Library to check. Uses active library if None.
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
List of supported chart type names.
|
|
339
|
+
"""
|
|
340
|
+
if library is None:
|
|
341
|
+
library = get_chart_settings().library
|
|
342
|
+
elif isinstance(library, str):
|
|
343
|
+
library = ChartLibrary(library.lower())
|
|
344
|
+
|
|
345
|
+
config = CHART_LIBRARY_CONFIGS[library]
|
|
346
|
+
return [ct.value for ct in config.supported_charts]
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def reset_chart_settings() -> None:
|
|
350
|
+
"""Reset chart settings singleton (for testing)."""
|
|
351
|
+
global _chart_settings
|
|
352
|
+
_chart_settings = None
|