greenmining 1.1.5__tar.gz → 1.1.7__tar.gz

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.
Files changed (52) hide show
  1. {greenmining-1.1.5 → greenmining-1.1.7}/CHANGELOG.md +31 -0
  2. {greenmining-1.1.5/greenmining.egg-info → greenmining-1.1.7}/PKG-INFO +1 -15
  3. {greenmining-1.1.5 → greenmining-1.1.7}/README.md +0 -12
  4. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/__init__.py +1 -1
  5. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/analyzers/statistical_analyzer.py +2 -1
  6. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/energy/base.py +8 -0
  7. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/services/local_repo_analyzer.py +12 -9
  8. {greenmining-1.1.5 → greenmining-1.1.7/greenmining.egg-info}/PKG-INFO +1 -15
  9. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining.egg-info/SOURCES.txt +0 -4
  10. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining.egg-info/requires.txt +0 -3
  11. {greenmining-1.1.5 → greenmining-1.1.7}/pyproject.toml +1 -4
  12. greenmining-1.1.5/greenmining/dashboard/__init__.py +0 -5
  13. greenmining-1.1.5/greenmining/dashboard/app.py +0 -200
  14. {greenmining-1.1.5 → greenmining-1.1.7}/LICENSE +0 -0
  15. {greenmining-1.1.5 → greenmining-1.1.7}/MANIFEST.in +0 -0
  16. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/__main__.py +0 -0
  17. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/__version__.py +0 -0
  18. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/analyzers/__init__.py +0 -0
  19. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/analyzers/code_diff_analyzer.py +0 -0
  20. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/analyzers/metrics_power_correlator.py +0 -0
  21. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/analyzers/power_regression.py +0 -0
  22. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/analyzers/qualitative_analyzer.py +0 -0
  23. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/analyzers/temporal_analyzer.py +0 -0
  24. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/analyzers/version_power_analyzer.py +0 -0
  25. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/config.py +0 -0
  26. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/controllers/__init__.py +0 -0
  27. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/controllers/repository_controller.py +0 -0
  28. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/energy/__init__.py +0 -0
  29. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/energy/carbon_reporter.py +0 -0
  30. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/energy/codecarbon_meter.py +0 -0
  31. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/energy/cpu_meter.py +0 -0
  32. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/energy/rapl.py +0 -0
  33. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/gsf_patterns.py +0 -0
  34. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/models/__init__.py +0 -0
  35. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/models/aggregated_stats.py +0 -0
  36. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/models/analysis_result.py +0 -0
  37. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/models/commit.py +0 -0
  38. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/models/repository.py +0 -0
  39. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/presenters/__init__.py +0 -0
  40. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/presenters/console_presenter.py +0 -0
  41. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/services/__init__.py +0 -0
  42. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/services/commit_extractor.py +0 -0
  43. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/services/data_aggregator.py +0 -0
  44. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/services/data_analyzer.py +0 -0
  45. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/services/github_fetcher.py +0 -0
  46. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/services/github_graphql_fetcher.py +0 -0
  47. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/services/reports.py +0 -0
  48. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining/utils.py +0 -0
  49. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining.egg-info/dependency_links.txt +0 -0
  50. {greenmining-1.1.5 → greenmining-1.1.7}/greenmining.egg-info/top_level.txt +0 -0
  51. {greenmining-1.1.5 → greenmining-1.1.7}/setup.cfg +0 -0
  52. {greenmining-1.1.5 → greenmining-1.1.7}/setup.py +0 -0
@@ -1,5 +1,36 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.7] - 2026-01-31
4
+
5
+ ### Removed
6
+ - Web dashboard module (`greenmining/dashboard/`) and Flask dependency
7
+ - Dashboard documentation page and all dashboard references
8
+
9
+ ### Fixed
10
+ - ReadTheDocs experiment page not rendering (trailing whitespace in mkdocs nav)
11
+ - Plotly rendering in notebook (nbformat dependency)
12
+
13
+ ## [1.1.6] - 2026-01-31
14
+
15
+ ### Fixed
16
+ - EnergyMetrics property aliases (`energy_joules`, `average_power_watts`)
17
+ - Parallel energy measurement conflict with shared meter instance
18
+ - StatisticalAnalyzer timezone-aware date handling
19
+ - DataFrame column collision in pattern correlation analysis
20
+
21
+ ### Added
22
+ - `since_date` / `to_date` parameters for date-bounded commit analysis
23
+ - `created_before` / `pushed_after` search filters
24
+ - GraphQL API and experiment documentation pages
25
+ - Full process metrics and method-level metrics documentation
26
+
27
+ ### Changed
28
+ - Energy measurement demonstrates all 4 backends: RAPL, CPU Meter, CodeCarbon, tracemalloc
29
+ - Removed all PyDriller references (replaced with gitpython + lizard)
30
+
31
+ ### Removed
32
+ - Qualitative Validation and Carbon Footprint Reporting steps from experiment
33
+
3
34
  ## [0.1.12] - 2025-12-03
4
35
 
5
36
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: greenmining
3
- Version: 1.1.5
3
+ Version: 1.1.7
4
4
  Summary: An empirical Python library for Mining Software Repositories (MSR) in Green IT research
5
5
  Author-email: Adam Bouafia <a.bouafia@student.vu.nl>
6
6
  License: MIT
@@ -49,8 +49,6 @@ Requires-Dist: twine; extra == "dev"
49
49
  Provides-Extra: energy
50
50
  Requires-Dist: psutil; extra == "energy"
51
51
  Requires-Dist: codecarbon; extra == "energy"
52
- Provides-Extra: dashboard
53
- Requires-Dist: flask; extra == "dashboard"
54
52
  Provides-Extra: docs
55
53
  Requires-Dist: sphinx; extra == "docs"
56
54
  Requires-Dist: sphinx-rtd-theme; extra == "docs"
@@ -80,7 +78,6 @@ An empirical Python library for Mining Software Repositories (MSR) in Green IT r
80
78
  - **Method-level analysis** - Per-method complexity and metrics via Lizard integration
81
79
  - **Version power comparison** - Compare power consumption across software versions
82
80
  - **Generate research datasets** - Statistical analysis, temporal trends, and publication-ready reports
83
- - **Web dashboard** - Flask-based interactive visualization of analysis results
84
81
 
85
82
  Whether you're conducting MSR research, analyzing green software adoption, or measuring the energy footprint of codebases, GreenMining provides the empirical toolkit you need.
86
83
 
@@ -452,15 +449,6 @@ print(f"Spearman: {correlator.spearman}")
452
449
  print(f"Feature importance: {correlator.feature_importance}")
453
450
  ```
454
451
 
455
- #### Web Dashboard
456
-
457
- ```python
458
- from greenmining.dashboard import run_dashboard
459
-
460
- # Launch interactive dashboard (requires pip install greenmining[dashboard])
461
- run_dashboard(data_dir="./data", host="127.0.0.1", port=5000)
462
- ```
463
-
464
452
  #### Pipeline Batch Analysis
465
453
 
466
454
  ```python
@@ -698,7 +686,6 @@ config = Config(
698
686
  - **Full Process Metrics**: All 8 process metrics (ChangeSet, CodeChurn, CommitsCount, ContributorsCount, ContributorsExperience, HistoryComplexity, HunksCount, LinesCount)
699
687
  - **Statistical Analysis**: Correlations, effect sizes, and temporal trends
700
688
  - **Multi-format Output**: Markdown reports, CSV exports, JSON data
701
- - **Web Dashboard**: Flask-based interactive visualization (`pip install greenmining[dashboard]`)
702
689
  - **Docker Support**: Pre-built images for containerized analysis
703
690
 
704
691
  ### Energy Measurement
@@ -857,7 +844,6 @@ ruff check greenmining/ tests/
857
844
 
858
845
  ```bash
859
846
  pip install greenmining[energy] # psutil, codecarbon (energy measurement)
860
- pip install greenmining[dashboard] # flask (web dashboard)
861
847
  pip install greenmining[dev] # pytest, black, ruff, mypy (development)
862
848
  ```
863
849
 
@@ -21,7 +21,6 @@ An empirical Python library for Mining Software Repositories (MSR) in Green IT r
21
21
  - **Method-level analysis** - Per-method complexity and metrics via Lizard integration
22
22
  - **Version power comparison** - Compare power consumption across software versions
23
23
  - **Generate research datasets** - Statistical analysis, temporal trends, and publication-ready reports
24
- - **Web dashboard** - Flask-based interactive visualization of analysis results
25
24
 
26
25
  Whether you're conducting MSR research, analyzing green software adoption, or measuring the energy footprint of codebases, GreenMining provides the empirical toolkit you need.
27
26
 
@@ -393,15 +392,6 @@ print(f"Spearman: {correlator.spearman}")
393
392
  print(f"Feature importance: {correlator.feature_importance}")
394
393
  ```
395
394
 
396
- #### Web Dashboard
397
-
398
- ```python
399
- from greenmining.dashboard import run_dashboard
400
-
401
- # Launch interactive dashboard (requires pip install greenmining[dashboard])
402
- run_dashboard(data_dir="./data", host="127.0.0.1", port=5000)
403
- ```
404
-
405
395
  #### Pipeline Batch Analysis
406
396
 
407
397
  ```python
@@ -639,7 +629,6 @@ config = Config(
639
629
  - **Full Process Metrics**: All 8 process metrics (ChangeSet, CodeChurn, CommitsCount, ContributorsCount, ContributorsExperience, HistoryComplexity, HunksCount, LinesCount)
640
630
  - **Statistical Analysis**: Correlations, effect sizes, and temporal trends
641
631
  - **Multi-format Output**: Markdown reports, CSV exports, JSON data
642
- - **Web Dashboard**: Flask-based interactive visualization (`pip install greenmining[dashboard]`)
643
632
  - **Docker Support**: Pre-built images for containerized analysis
644
633
 
645
634
  ### Energy Measurement
@@ -798,7 +787,6 @@ ruff check greenmining/ tests/
798
787
 
799
788
  ```bash
800
789
  pip install greenmining[energy] # psutil, codecarbon (energy measurement)
801
- pip install greenmining[dashboard] # flask (web dashboard)
802
790
  pip install greenmining[dev] # pytest, black, ruff, mypy (development)
803
791
  ```
804
792
 
@@ -9,7 +9,7 @@ from greenmining.gsf_patterns import (
9
9
  is_green_aware,
10
10
  )
11
11
 
12
- __version__ = "1.1.5"
12
+ __version__ = "1.1.7"
13
13
 
14
14
 
15
15
  def fetch_repositories(
@@ -50,7 +50,8 @@ class StatisticalAnalyzer:
50
50
  def temporal_trend_analysis(self, commits_df: pd.DataFrame) -> Dict[str, Any]:
51
51
  # Analyze temporal trends in green awareness.
52
52
  # Prepare time series data
53
- commits_df["date"] = pd.to_datetime(commits_df["date"])
53
+ commits_df["date"] = pd.to_datetime(commits_df["date"], utc=True, errors="coerce")
54
+ commits_df["date"] = commits_df["date"].dt.tz_localize(None)
54
55
  commits_df = commits_df.sort_values("date")
55
56
 
56
57
  # Monthly aggregation
@@ -42,6 +42,14 @@ class EnergyMetrics:
42
42
  start_time: Optional[datetime] = None
43
43
  end_time: Optional[datetime] = None
44
44
 
45
+ @property
46
+ def energy_joules(self) -> float:
47
+ return self.joules
48
+
49
+ @property
50
+ def average_power_watts(self) -> float:
51
+ return self.watts_avg
52
+
45
53
  def to_dict(self) -> Dict[str, Any]:
46
54
  # Convert to dictionary.
47
55
  return {
@@ -470,13 +470,16 @@ class LocalRepoAnalyzer:
470
470
 
471
471
  colored_print(f" Cloning to: {local_path}", "cyan")
472
472
 
473
- # Phase 2.2: Start energy measurement if enabled
473
+ # Phase 2.2: Start energy measurement if enabled (fresh meter per repo)
474
474
  energy_result = None
475
- if self.energy_tracking and self._energy_meter:
475
+ energy_meter = None
476
+ if self.energy_tracking:
476
477
  try:
477
- self._energy_meter.start()
478
- except Exception as e:
479
- colored_print(f" Warning: Energy measurement start failed: {e}", "yellow")
478
+ from greenmining.energy.base import get_energy_meter
479
+ energy_meter = get_energy_meter(self.energy_backend)
480
+ energy_meter.start()
481
+ except Exception:
482
+ energy_meter = None
480
483
 
481
484
  commits_analyzed = []
482
485
  commit_count = 0
@@ -503,11 +506,11 @@ class LocalRepoAnalyzer:
503
506
  colored_print(f" Analyzed {len(commits_analyzed)} commits", "green")
504
507
 
505
508
  # Phase 2.2: Stop energy measurement
506
- if self.energy_tracking and self._energy_meter:
509
+ if energy_meter:
507
510
  try:
508
- energy_result = self._energy_meter.stop()
509
- except Exception as e:
510
- colored_print(f" Warning: Energy measurement stop failed: {e}", "yellow")
511
+ energy_result = energy_meter.stop()
512
+ except Exception:
513
+ pass
511
514
 
512
515
  # Compute process metrics if enabled
513
516
  process_metrics = {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: greenmining
3
- Version: 1.1.5
3
+ Version: 1.1.7
4
4
  Summary: An empirical Python library for Mining Software Repositories (MSR) in Green IT research
5
5
  Author-email: Adam Bouafia <a.bouafia@student.vu.nl>
6
6
  License: MIT
@@ -49,8 +49,6 @@ Requires-Dist: twine; extra == "dev"
49
49
  Provides-Extra: energy
50
50
  Requires-Dist: psutil; extra == "energy"
51
51
  Requires-Dist: codecarbon; extra == "energy"
52
- Provides-Extra: dashboard
53
- Requires-Dist: flask; extra == "dashboard"
54
52
  Provides-Extra: docs
55
53
  Requires-Dist: sphinx; extra == "docs"
56
54
  Requires-Dist: sphinx-rtd-theme; extra == "docs"
@@ -80,7 +78,6 @@ An empirical Python library for Mining Software Repositories (MSR) in Green IT r
80
78
  - **Method-level analysis** - Per-method complexity and metrics via Lizard integration
81
79
  - **Version power comparison** - Compare power consumption across software versions
82
80
  - **Generate research datasets** - Statistical analysis, temporal trends, and publication-ready reports
83
- - **Web dashboard** - Flask-based interactive visualization of analysis results
84
81
 
85
82
  Whether you're conducting MSR research, analyzing green software adoption, or measuring the energy footprint of codebases, GreenMining provides the empirical toolkit you need.
86
83
 
@@ -452,15 +449,6 @@ print(f"Spearman: {correlator.spearman}")
452
449
  print(f"Feature importance: {correlator.feature_importance}")
453
450
  ```
454
451
 
455
- #### Web Dashboard
456
-
457
- ```python
458
- from greenmining.dashboard import run_dashboard
459
-
460
- # Launch interactive dashboard (requires pip install greenmining[dashboard])
461
- run_dashboard(data_dir="./data", host="127.0.0.1", port=5000)
462
- ```
463
-
464
452
  #### Pipeline Batch Analysis
465
453
 
466
454
  ```python
@@ -698,7 +686,6 @@ config = Config(
698
686
  - **Full Process Metrics**: All 8 process metrics (ChangeSet, CodeChurn, CommitsCount, ContributorsCount, ContributorsExperience, HistoryComplexity, HunksCount, LinesCount)
699
687
  - **Statistical Analysis**: Correlations, effect sizes, and temporal trends
700
688
  - **Multi-format Output**: Markdown reports, CSV exports, JSON data
701
- - **Web Dashboard**: Flask-based interactive visualization (`pip install greenmining[dashboard]`)
702
689
  - **Docker Support**: Pre-built images for containerized analysis
703
690
 
704
691
  ### Energy Measurement
@@ -857,7 +844,6 @@ ruff check greenmining/ tests/
857
844
 
858
845
  ```bash
859
846
  pip install greenmining[energy] # psutil, codecarbon (energy measurement)
860
- pip install greenmining[dashboard] # flask (web dashboard)
861
847
  pip install greenmining[dev] # pytest, black, ruff, mypy (development)
862
848
  ```
863
849
 
@@ -20,8 +20,6 @@ setup.py
20
20
  ./greenmining/analyzers/version_power_analyzer.py
21
21
  ./greenmining/controllers/__init__.py
22
22
  ./greenmining/controllers/repository_controller.py
23
- ./greenmining/dashboard/__init__.py
24
- ./greenmining/dashboard/app.py
25
23
  ./greenmining/energy/__init__.py
26
24
  ./greenmining/energy/base.py
27
25
  ./greenmining/energy/carbon_reporter.py
@@ -64,8 +62,6 @@ greenmining/analyzers/temporal_analyzer.py
64
62
  greenmining/analyzers/version_power_analyzer.py
65
63
  greenmining/controllers/__init__.py
66
64
  greenmining/controllers/repository_controller.py
67
- greenmining/dashboard/__init__.py
68
- greenmining/dashboard/app.py
69
65
  greenmining/energy/__init__.py
70
66
  greenmining/energy/base.py
71
67
  greenmining/energy/carbon_reporter.py
@@ -9,9 +9,6 @@ plotly
9
9
  python-dotenv
10
10
  requests
11
11
 
12
- [dashboard]
13
- flask
14
-
15
12
  [dev]
16
13
  pytest
17
14
  pytest-cov
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "greenmining"
7
- version = "1.1.5"
7
+ version = "1.1.7"
8
8
  description = "An empirical Python library for Mining Software Repositories (MSR) in Green IT research"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -72,9 +72,6 @@ energy = [
72
72
  "codecarbon"
73
73
  ]
74
74
 
75
- dashboard = [
76
- "flask"
77
- ]
78
75
 
79
76
  docs = [
80
77
  "sphinx",
@@ -1,5 +0,0 @@
1
- # Web dashboard module for GreenMining visualization.
2
-
3
- from .app import create_app, run_dashboard
4
-
5
- __all__ = ["create_app", "run_dashboard"]
@@ -1,200 +0,0 @@
1
- # Flask-based web dashboard for GreenMining analysis visualization.
2
- # Provides interactive charts for repository analysis, pattern distribution,
3
- # temporal trends, and energy consumption.
4
-
5
- from __future__ import annotations
6
-
7
- import json
8
- from pathlib import Path
9
- from typing import Any, Dict, List, Optional
10
-
11
-
12
- def create_app(data_dir: str = "./data"):
13
- # Create Flask application for the dashboard.
14
- # Args:
15
- # data_dir: Path to directory containing analysis JSON files
16
- # Returns:
17
- # Flask application instance
18
- try:
19
- from flask import Flask, render_template_string, jsonify, request
20
- except ImportError:
21
- raise ImportError("Flask is required for the dashboard. Install it with: pip install flask")
22
-
23
- app = Flask(__name__)
24
- data_path = Path(data_dir)
25
-
26
- def _load_data(filename: str) -> Dict[str, Any]:
27
- filepath = data_path / filename
28
- if filepath.exists():
29
- with open(filepath, encoding="utf-8") as f:
30
- return json.load(f)
31
- return {}
32
-
33
- @app.route("/")
34
- def index():
35
- return render_template_string(DASHBOARD_HTML)
36
-
37
- @app.route("/api/repositories")
38
- def api_repositories():
39
- data = _load_data("repositories.json")
40
- return jsonify(data)
41
-
42
- @app.route("/api/analysis")
43
- def api_analysis():
44
- data = _load_data("analysis_results.json")
45
- return jsonify(data)
46
-
47
- @app.route("/api/statistics")
48
- def api_statistics():
49
- data = _load_data("aggregated_statistics.json")
50
- return jsonify(data)
51
-
52
- @app.route("/api/energy")
53
- def api_energy():
54
- data = _load_data("energy_report.json")
55
- return jsonify(data)
56
-
57
- @app.route("/api/summary")
58
- def api_summary():
59
- # Build summary from available data
60
- repos = _load_data("repositories.json")
61
- analysis = _load_data("analysis_results.json")
62
-
63
- repo_count = 0
64
- if isinstance(repos, list):
65
- repo_count = len(repos)
66
- elif isinstance(repos, dict):
67
- repo_count = repos.get("total_repositories", len(repos.get("repositories", [])))
68
-
69
- commit_count = 0
70
- green_count = 0
71
- if isinstance(analysis, list):
72
- commit_count = len(analysis)
73
- green_count = sum(1 for a in analysis if a.get("green_aware"))
74
- elif isinstance(analysis, dict):
75
- results = analysis.get("results", [])
76
- for r in results:
77
- commits = r.get("commits", [])
78
- commit_count += len(commits)
79
- green_count += sum(1 for c in commits if c.get("green_aware"))
80
-
81
- green_rate = (green_count / commit_count * 100) if commit_count > 0 else 0
82
-
83
- return jsonify(
84
- {
85
- "repositories": repo_count,
86
- "commits_analyzed": commit_count,
87
- "green_commits": green_count,
88
- "green_rate": round(green_rate, 1),
89
- }
90
- )
91
-
92
- return app
93
-
94
-
95
- def run_dashboard(data_dir: str = "./data", host: str = "127.0.0.1", port: int = 5000):
96
- # Run the dashboard server.
97
- # Args:
98
- # data_dir: Path to analysis data directory
99
- # host: Host to bind to
100
- # port: Port to bind to
101
- app = create_app(data_dir)
102
- print(f"GreenMining Dashboard running at http://{host}:{port}")
103
- print(f"Data directory: {data_dir}")
104
- app.run(host=host, port=port, debug=False)
105
-
106
-
107
- # Dashboard HTML template with embedded JS (no external dependencies)
108
- DASHBOARD_HTML = """
109
- <!DOCTYPE html>
110
- <html lang="en">
111
- <head>
112
- <meta charset="UTF-8">
113
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
114
- <title>GreenMining Dashboard</title>
115
- <style>
116
- * { margin: 0; padding: 0; box-sizing: border-box; }
117
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
118
- background: #f5f7fa; color: #333; }
119
- .header { background: #1a472a; color: white; padding: 20px 40px; }
120
- .header h1 { font-size: 24px; font-weight: 600; }
121
- .header p { font-size: 14px; opacity: 0.8; margin-top: 4px; }
122
- .container { max-width: 1200px; margin: 0 auto; padding: 20px; }
123
- .grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }
124
- .card { background: white; border-radius: 8px; padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
125
- .card h3 { font-size: 13px; color: #666; text-transform: uppercase; letter-spacing: 0.5px; }
126
- .card .value { font-size: 32px; font-weight: 700; color: #1a472a; margin-top: 8px; }
127
- .card .subtitle { font-size: 12px; color: #999; margin-top: 4px; }
128
- .section { margin-bottom: 24px; }
129
- .section h2 { font-size: 18px; margin-bottom: 12px; color: #1a472a; }
130
- table { width: 100%; border-collapse: collapse; background: white; border-radius: 8px;
131
- overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
132
- th, td { padding: 12px 16px; text-align: left; border-bottom: 1px solid #eee; }
133
- th { background: #f8f9fa; font-size: 12px; text-transform: uppercase; color: #666; }
134
- td { font-size: 14px; }
135
- .badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 11px; }
136
- .badge-green { background: #d4edda; color: #155724; }
137
- .badge-gray { background: #e9ecef; color: #495057; }
138
- .bar { height: 8px; background: #e9ecef; border-radius: 4px; overflow: hidden; }
139
- .bar-fill { height: 100%; background: #1a472a; border-radius: 4px;
140
- transition: width 0.5s ease; }
141
- .loading { text-align: center; padding: 40px; color: #999; }
142
- </style>
143
- </head>
144
- <body>
145
- <div class="header">
146
- <h1>GreenMining Dashboard</h1>
147
- <p>Mining Software Repositories for Green IT Research</p>
148
- </div>
149
- <div class="container">
150
- <div class="grid" id="summary-cards">
151
- <div class="card"><h3>Repositories</h3><div class="value" id="repo-count">-</div></div>
152
- <div class="card"><h3>Commits Analyzed</h3><div class="value" id="commit-count">-</div></div>
153
- <div class="card"><h3>Green Commits</h3><div class="value" id="green-count">-</div></div>
154
- <div class="card"><h3>Green Rate</h3><div class="value" id="green-rate">-</div></div>
155
- </div>
156
- <div class="section">
157
- <h2>Repositories</h2>
158
- <div id="repo-table"><div class="loading">Loading data...</div></div>
159
- </div>
160
- </div>
161
- <script>
162
- async function loadDashboard() {
163
- try {
164
- const summary = await fetch('/api/summary').then(r => r.json());
165
- document.getElementById('repo-count').textContent = summary.repositories;
166
- document.getElementById('commit-count').textContent = summary.commits_analyzed.toLocaleString();
167
- document.getElementById('green-count').textContent = summary.green_commits.toLocaleString();
168
- document.getElementById('green-rate').textContent = summary.green_rate + '%';
169
- } catch(e) {
170
- console.log('Summary not available:', e);
171
- }
172
-
173
- try {
174
- const repos = await fetch('/api/repositories').then(r => r.json());
175
- const list = repos.repositories || (Array.isArray(repos) ? repos : []);
176
- if (list.length > 0) {
177
- let html = '<table><thead><tr><th>Repository</th><th>Language</th>' +
178
- '<th>Stars</th><th>Description</th></tr></thead><tbody>';
179
- list.slice(0, 50).forEach(r => {
180
- html += '<tr><td><strong>' + (r.full_name || r.name) + '</strong></td>' +
181
- '<td><span class="badge badge-green">' + (r.language || '-') + '</span></td>' +
182
- '<td>' + (r.stars || 0).toLocaleString() + '</td>' +
183
- '<td>' + (r.description || '-').substring(0, 80) + '</td></tr>';
184
- });
185
- html += '</tbody></table>';
186
- document.getElementById('repo-table').innerHTML = html;
187
- } else {
188
- document.getElementById('repo-table').innerHTML =
189
- '<div class="card">No repository data found. Run an analysis first.</div>';
190
- }
191
- } catch(e) {
192
- document.getElementById('repo-table').innerHTML =
193
- '<div class="card">Run an analysis to populate the dashboard.</div>';
194
- }
195
- }
196
- loadDashboard();
197
- </script>
198
- </body>
199
- </html>
200
- """
File without changes
File without changes
File without changes
File without changes