diff --git a/dashboard/app/Http/Controllers/Api/DashboardController.php b/dashboard/app/Http/Controllers/Api/DashboardController.php
index c963d4d..4f40631 100644
--- a/dashboard/app/Http/Controllers/Api/DashboardController.php
+++ b/dashboard/app/Http/Controllers/Api/DashboardController.php
@@ -184,7 +184,6 @@ class DashboardController extends Controller
public function covidLineageRelativeOverTime(Request $request)
{
$range = $this->getEpiRange($request);
-
if (!$range) {
return response()->json(['error' => 'Missing epiweek range'], 400);
}
@@ -202,7 +201,6 @@ class DashboardController extends Controller
public function influenzaRelativeOverTime(Request $request)
{
$range = $this->getEpiRange($request);
-
if (!$range) {
return response()->json(['error' => 'Missing epiweek range'], 400);
}
@@ -218,6 +216,24 @@ class DashboardController extends Controller
}
+ public function influenzaRelativeOverTimeSequencing(Request $request)
+ {
+ $range = $this->getEpiRange($request);
+ if (!$range) {
+ return response()->json(['error' => 'Missing epiweek range'], 400);
+ }
+
+ $data = $this->service->influenzaRelativeOverTimeSequencing(
+ $range['startYear'],
+ $range['startWeek'],
+ $range['endYear'],
+ $range['endWeek']
+ );
+
+ return response()->json($data);
+ }
+
+
diff --git a/dashboard/app/Services/DashboardService.php b/dashboard/app/Services/DashboardService.php
index 9e8c013..036e851 100644
--- a/dashboard/app/Services/DashboardService.php
+++ b/dashboard/app/Services/DashboardService.php
@@ -1020,7 +1020,7 @@ class DashboardService
})
->selectRaw("
- surveillance_cases.week_data as period,
+ concat(surveillance_cases.year_data,'-',surveillance_cases.week_data) as period,
subtype,
COUNT(DISTINCT surveillance_cases.lab_code) as total
")
@@ -1029,4 +1029,34 @@ class DashboardService
->orderBy('period')
->get();
}
+
+
+ public function influenzaRelativeOverTimeSequencing($startYear, $startWeek, $endYear, $endWeek)
+ {
+ return SurveillanceCase::join('case_lab_results', function ($join) {
+ $join->on('surveillance_cases.lab_code', '=', 'case_lab_results.lab_code')
+ ->on('surveillance_cases.surveillance_id', '=', 'case_lab_results.surveillance_id');
+ })
+ ->where(function ($q) use ($startYear, $startWeek, $endYear, $endWeek) {
+ $q->whereRaw(
+ "(surveillance_cases.year_data * 100 + surveillance_cases.week_data) BETWEEN ? AND ?",
+ [
+ $startYear * 100 + $startWeek,
+ $endYear * 100 + $endWeek
+ ]
+ );
+ })
+ ->whereRaw('case_lab_results.is_positive = 1 and surveillance_cases.surveillance_id in(6) and case_lab_results.indicator="Influenza"')
+ ->selectRaw("
+ case_lab_results.pathogen_name as lineage,
+ concat(surveillance_cases.year_data,'-',surveillance_cases.week_data) as week,
+ COUNT(DISTINCT surveillance_cases.lab_code) as total
+ ")
+ ->groupBy(
+ 'case_lab_results.pathogen_name',
+ 'week'
+ )
+ ->get();
+ }
+
}
diff --git a/dashboard/app/Services/DataRetrievalService.php b/dashboard/app/Services/DataRetrievalService.php
index b696d37..733c82f 100644
--- a/dashboard/app/Services/DataRetrievalService.php
+++ b/dashboard/app/Services/DataRetrievalService.php
@@ -2,27 +2,80 @@
namespace App\Services;
-use Carbon\Carbon;
-use App\Models\Surveillance;
-use App\Models\SurveillanceCase;
-use App\Models\CaseLabResult;
+use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class DataRetrievalService
{
+ protected $apiBaseUrl;
+ protected $apiUsername;
+ protected $apiPassword;
+
+ public function __construct()
+ {
+ $this->apiBaseUrl = config('services.nphl_api.url');
+ $this->apiUsername = config('services.nphl_api.username');
+ $this->apiPassword = config('services.nphl_api.password');
+ }
+
+ public function get($endpoint)
+ {
+ try {
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $this->apiBaseUrl . $endpoint);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_ENCODING, '');
+ curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 0);
+ curl_setopt($ch, CURL_HTTP_VERSION_1_1, 0);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
+ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
+ curl_setopt($ch, CURLOPT_USERPWD, $this->apiUsername . ":" . $this->apiPassword);
+ $resp = curl_exec($ch);
+ $b="";
+ if($e = curl_error($ch)){
+ $b= $e;
+ }else{
+ $b= $resp;
+ }
+ curl_close($ch);
+ return $b;
+
+ } catch (RequestException $e) {
+ return [
+ 'error' => true,
+ 'message' => $e->getMessage(),
+ 'status' => optional($e->response)->status()
+ ];
+ }
+ }
+
+
public function getSurveillanceData()
{
try{
- $toDate = now();
- $this->getSARICases(now()->subDays(config('app.lookback_days.SARI'))->toDateString(), $toDate); // done
- $this->getILICases(now()->subDays(config('app.lookback_days.ILI'))->toDateString(), $toDate); // done
- $this->getLBMCases(now()->subDays(config('app.lookback_days.LBM'))->toDateString(), $toDate); // done
- $this->getAFICases(now()->subDays(config('app.lookback_days.AFI'))->toDateString(), $toDate); // done
- $this->getNSDCases(now()->subDays(config('app.lookback_days.NDS'))->toDateString(), $toDate);
- $this->getSEQCases(now()->subDays(config('app.lookback_days.SEQ'))->toDateString(), $toDate); // done
- Log::channel('jobs')->info($toDate->toDateString(). ' Service Reload Data Successfully Ran');
+ $lookbackDays = config('app.lookback_days');
+ $surveillances = DB::connection('mysql')->select("select * from surveillances");
+ foreach ($surveillances as $surveillance){
+ $surveillance_data = $this->get('api/labsurveil.php?surveillance_id='.$surveillance->id.'&start_date='.now()->subDays($lookbackDays[$surveillance->code])->toDateString());
+ $data = json_decode(preg_replace('/^\xEF\xBB\xBF/', '', $surveillance_data));
+ @$this->insert_surveillance_cases((array)$data->laboratory_cases);
+ @$this->insert_surveillance_case_lab_results((array)$data->laboratory_results);
+
+ }
+
+ //$this->getSARICases(now()->subDays(config('app.lookback_days.SARI'))->toDateString(), $toDate); // done
+// $this->getILICases(now()->subDays(config('app.lookback_days.ILI'))->toDateString(), $toDate); // done
+// $this->getLBMCases(now()->subDays(config('app.lookback_days.LBM'))->toDateString(), $toDate); // done
+// $this->getAFICases(now()->subDays(config('app.lookback_days.AFI'))->toDateString(), $toDate); // done
+// $this->getNSDCases(now()->subDays(config('app.lookback_days.NDS'))->toDateString(), $toDate);
+// $this->getSEQCases(now()->subDays(config('app.lookback_days.SEQ'))->toDateString(), $toDate); // done
+ Log::channel('jobs')->info(now()->toDateString(). ' Service Reload Data Successfully Ran');
return true;
}
catch (\Exception $e){
@@ -35,6 +88,7 @@ class DataRetrievalService
public function getSARICases($dateFrom, $dateTo=NULL)
{
+
$cond = "";
$cond .= " and patient.patdate >= '".date('Y-m-d', strtotime($dateFrom))."' ";
$cond .= (!empty($dateTo)) ? " and patient.patdate <='".date('Y-m-d', strtotime($dateTo))."' ":"";
diff --git a/dashboard/config/services.php b/dashboard/config/services.php
index 6a90eb8..c093a4f 100644
--- a/dashboard/config/services.php
+++ b/dashboard/config/services.php
@@ -35,4 +35,10 @@ return [
],
],
+ 'nphl_api' => [
+ 'url' => env('NPHL_API_URL'),
+ 'username' => env('NPHL_API_USERNAME'),
+ 'password' => env('NPHL_API_PASSWORD'),
+ ],
+
];
diff --git a/dashboard/public/js/dashboard/charts.js b/dashboard/public/js/dashboard/charts.js
index bdda7d7..ed85032 100644
--- a/dashboard/public/js/dashboard/charts.js
+++ b/dashboard/public/js/dashboard/charts.js
@@ -8,7 +8,7 @@ Chart.register({
(ds.data || []).some(v => Number(v) > 0)
);
- chart.$noData = !hasData;
+ chart.$noData = !hasData;
if (hasData) return;
@@ -94,7 +94,7 @@ function buildStackedChart(canvasId, labels, datasets) {
bottom: 30
}
},
-
+
plugins: {
legend: {
@@ -159,9 +159,9 @@ function buildChart(id, type, labels, data) {
layout: {
padding: 30
},
-
- indexAxis: isHorizontal ? 'y' : 'x',
+
+ indexAxis: isHorizontal ? 'y' : 'x',
plugins: {
legend: {
@@ -189,7 +189,7 @@ function buildChart(id, type, labels, data) {
},
datalabels: {
color: "#282626",
- offset: 6,
+ offset: 6,
clip: false,
display: (ctx) => {
const chart = ctx.chart;
@@ -257,7 +257,7 @@ function buildChart(id, type, labels, data) {
arc: {
borderWidth: (ctx) => ctx.chart.$noData ? 0 : 1
}
-
+
};
}
@@ -306,7 +306,7 @@ function buildMixedTrendChart(canvasId, labels, samples, fluRate, covidRate) {
},
-
+
{
type: 'line',
label: 'COVID-19 %',
@@ -318,7 +318,7 @@ function buildMixedTrendChart(canvasId, labels, samples, fluRate, covidRate) {
pointStyle: 'line',
},
-
+
{
type: 'bar',
label: 'Total Cases',
@@ -327,7 +327,7 @@ function buildMixedTrendChart(canvasId, labels, samples, fluRate, covidRate) {
borderRadius: 2,
barPercentage: 0.8,
categoryPercentage: 0.7,
- yAxisID: 'y',
+ yAxisID: 'y',
}
]
@@ -338,7 +338,6 @@ function buildMixedTrendChart(canvasId, labels, samples, fluRate, covidRate) {
options: {
responsive: true,
maintainAspectRatio: false,
-
plugins: {
legend: {
position: 'bottom',
@@ -351,6 +350,7 @@ function buildMixedTrendChart(canvasId, labels, samples, fluRate, covidRate) {
align: "top",
anchor: "end",
color: "#555",
+ display: false,
font: {
size: 10
},
@@ -387,7 +387,7 @@ function buildMixedTrendChart(canvasId, labels, samples, fluRate, covidRate) {
display: true,
text: '% Positivity'
},
-
+
}
}
}
diff --git a/dashboard/public/js/dashboard/filter.js b/dashboard/public/js/dashboard/filter.js
index f6e9ddd..3e83bf2 100644
--- a/dashboard/public/js/dashboard/filter.js
+++ b/dashboard/public/js/dashboard/filter.js
@@ -75,8 +75,8 @@ class DashboardFilter {
const year = new Date().getFullYear();
- for (let y = year-20; y <= year; y++) {
+ for (let y = year; y >= year-20; y--) {
this.startYear.innerHTML += ``;
this.endYear.innerHTML += ``;
@@ -128,4 +128,4 @@ class DashboardFilter {
}
-}
\ No newline at end of file
+}
diff --git a/dashboard/public/js/overview.js b/dashboard/public/js/overview.js
index 88f88a7..88a7db1 100644
--- a/dashboard/public/js/overview.js
+++ b/dashboard/public/js/overview.js
@@ -931,13 +931,13 @@ function addPositivityLegend() {
Influenza Subtypes
-
A/H1N1pdm
+
A/H1N1pdm
A/H3N2
A/H9N2
A/H5N1
A/Unsubtypable
B/Yam
-
B/Vic
+
B/Vic
B/Unsubtypable
`;
@@ -1036,10 +1036,10 @@ function loadProvinceMap(startYear, startWeek, endYear, endWeek) {
function getColorByPathogen(name) {
const colors = {
- "A/H1N1pdm": "#2563eb",
+ "A/H1N1pdm": "#ff0200",
"A/H3N2": "#11de9d",
"B/Yam": "#9333ea",
- "B/Vic" : "#1021b9",
+ "B/Vic" : "#086037",
"A/H9N2": "#b91081",
"A/H5N1": "#ad850d",
"A/Unsubtypable": "#047393",
diff --git a/dashboard/public/js/sequencing.js b/dashboard/public/js/sequencing.js
index 6cfa5c8..daac952 100644
--- a/dashboard/public/js/sequencing.js
+++ b/dashboard/public/js/sequencing.js
@@ -1,20 +1,33 @@
let sequencingChart;
+let covidLineageFrequencyChart;
+let influenzaSubtypeFrequencyChart;
+
document.addEventListener("DOMContentLoaded", () => {
- const canvas = document.getElementById('sequencingChart');
- if (!canvas) return;
+ //const canvas = document.getElementById('sequencingChart');
+ //if (!canvas) return;
new DashboardFilter((startYear, startWeek, endYear, endWeek) => {
fetch(`/api/dashboard/sequencing?surveillance_id=${window.SURVEILLANCE_ID}&start_year=${startYear}&start_week=${startWeek}&end_year=${endYear}&end_week=${endWeek}`)
.then(res => res.json())
.then(data => {
- renderSequencingChart(data.trend || []);
+ //renderSequencingChart(data.trend || []);
renderSequencingCountChart(data.trend || []);
renderSequencingPieChart(data.distribution || []);
renderSequencingTotalChart(data.trend || []);
});
+ loadCovidLineageFrequency('week', startYear, startWeek, endYear, endWeek)
+ loadInfluenzaSubtypeFrequency('week', startYear, startWeek, endYear, endWeek)
+
+ const elements = document.querySelectorAll(".report-period");
+ elements.forEach(el => {
+ el.textContent = 'Week ' + startWeek + ' of '+startYear+' to ' + 'Week ' + endWeek + ' of ' + endYear
+ });
+
});
+
+
});
function renderSequencingCountChart(rows) {
@@ -39,7 +52,7 @@ function renderSequencingCountChart(rows) {
const found = rows.find(r => r.period === w && r.subtype === sub);
return found ? found.total : 0;
}),
- backgroundColor: colors[i % colors.length]
+ backgroundColor: hexToRGBA(colors[i % colors.length], 0.3)// colors[i % colors.length]
}));
new Chart(ctx, {
@@ -59,6 +72,9 @@ function renderSequencingCountChart(rows) {
display: true,
position: 'bottom',
align: 'center'
+ },
+ datalabels: {
+ display: true
}
}
@@ -123,9 +139,13 @@ function renderSequencingTotalChart(rows) {
options: {
maintainAspectRatio: false,
plugins: {
- legend: { display: false }
+ legend: { display: false },
+ datalabels: {
+ display: false
+ }
},
+
}
});
}
@@ -176,6 +196,8 @@ function renderSequencingChart(rows) {
}
});
+ console.log('aggregated', aggregated)
+
const cleanRows = Object.values(aggregated);
const weeks = [...new Set(cleanRows.map(r => r.period))];
@@ -235,4 +257,310 @@ function renderSequencingChart(rows) {
}
}
});
-}
\ No newline at end of file
+}
+
+
+
+function hexToRGBA(hex, alpha) {
+ const r = parseInt(hex.slice(1, 3), 16);
+ const g = parseInt(hex.slice(3, 5), 16);
+ const b = parseInt(hex.slice(5, 7), 16);
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
+}
+
+function loadCovidLineageFrequency(periodType, startYear, startWeek, endYear, endWeek) {
+
+ fetch(`/api/dashboard/covid-lineage-frequency?period_type=${periodType}&start_year=${startYear}&start_week=${startWeek}&end_year=${endYear}&end_week=${endWeek}`)
+ .then(res => res.json())
+ .then(data => {
+
+ // Extract unique weeks (X-axis)
+ const weeks = [...new Set(data.map(item => item.week))].sort();
+
+ // Extract unique lineages
+ const lineages = [...new Set(data.map(item => item.lineage))];
+
+ // Color palette
+ const colors = [
+ '#84cc16','#22c55e','#06b6d4','#3b82f6',
+ '#6366f1','#a855f7','#ec4899','#ef4444',
+ '#f97316','#eab308'
+ ];
+
+ // Build datasets
+ const datasets = lineages.map((lineage, index) => {
+ const lineageData = weeks.map(week => {
+ const found = data.find(
+ item => item.week === week && item.lineage === lineage
+ );
+ return found ? found.total : 0;
+ });
+
+ return {
+ label: lineage,
+ data: lineageData,
+ fill: true, // area fill
+ tension: 0.4, // smooth curve
+ borderColor: 'transparent', // hide the line
+ borderWidth: 0,
+ pointRadius: 0, // hide points
+ backgroundColor: hexToRGBA(colors[index % colors.length], 0.3),
+ stack: 'total'
+ };
+ });
+
+ // Destroy previous chart if exists
+ if (covidLineageFrequencyChart) covidLineageFrequencyChart.destroy();
+
+ const ctx = document.getElementById('covidLineageFrequency').getContext('2d');
+
+ covidLineageFrequencyChart = new Chart(ctx, {
+ type: 'line',
+ data: {
+ labels: weeks,
+ datasets: datasets
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ interaction: {
+ mode: 'index',
+ intersect: false
+ },
+ plugins: {
+ legend: {
+ display: false // hide default legend
+ },
+ tooltip: {
+ mode: 'index',
+ intersect: false
+ },
+ datalabels: {
+ display: false // hide labels
+ }
+ },
+ scales: {
+ x: {
+ stacked: true,
+ title: {
+ display: true,
+ text: 'Week'
+ },
+ grid:{
+ display: false
+ }
+ },
+ y: {
+ stacked: true,
+ beginAtZero: true,
+ title: {
+ display: true,
+ text: 'Relative Frequency'
+ },
+ }
+ }
+ }
+ });
+
+ // -------------------------
+ // Custom right-side scrollable legend
+ // -------------------------
+ const legendContainer = document.getElementById('legendContainer');
+ legendContainer.innerHTML = ''; // clear old legend
+
+ datasets.forEach((dataset, index) => {
+ const item = document.createElement('div');
+ item.style.display = 'flex';
+ item.style.alignItems = 'center';
+ item.style.marginBottom = '4px';
+ item.style.fontSize = '11px';
+ item.style.cursor = 'pointer';
+ item.innerHTML = `
+
+ ${dataset.label}
+ `;
+
+ item.addEventListener('click', () => {
+ const meta = covidLineageFrequencyChart.getDatasetMeta(index);
+
+ // If the clicked dataset is already the only visible one, show all
+ const allHidden = datasets.every((d, i) => covidLineageFrequencyChart.getDatasetMeta(i).hidden || i === index);
+ if (!allHidden) {
+ // Hide all datasets
+ datasets.forEach((d, i) => {
+ covidLineageFrequencyChart.getDatasetMeta(i).hidden = true;
+ });
+ // Show only clicked
+ meta.hidden = false;
+ } else {
+ // Show all datasets
+ datasets.forEach((d, i) => {
+ covidLineageFrequencyChart.getDatasetMeta(i).hidden = false;
+ });
+ }
+
+ covidLineageFrequencyChart.update();
+
+ // Update legend opacity
+ Array.from(legendContainer.children).forEach((child, i) => {
+ const metaItem = covidLineageFrequencyChart.getDatasetMeta(i);
+ child.style.opacity = metaItem.hidden ? 0.5 : 1;
+ });
+ });
+
+ legendContainer.appendChild(item);
+ });
+
+ // Scrollable CSS (in case legend is long)
+ legendContainer.style.maxHeight = '375px';
+ legendContainer.style.overflowY = 'auto';
+ legendContainer.style.padding = '8px';
+ legendContainer.style.borderRadius = '0px';
+ });
+}
+
+function loadInfluenzaSubtypeFrequency(periodType, startYear, startWeek, endYear, endWeek) {
+
+ fetch(`/api/dashboard/influenza-relative-frequency-sequencing?period_type=${periodType}&start_year=${startYear}&start_week=${startWeek}&end_year=${endYear}&end_week=${endWeek}`)
+ .then(res => res.json())
+ .then(data => {
+
+ // Extract unique weeks (X-axis)
+ const weeks = [...new Set(data.map(item => item.week))].sort();
+
+ const colors = [
+ '#84cc16','#22c55e','#06b6d4','#3b82f6',
+ '#6366f1','#a855f7','#ec4899','#ef4444',
+ '#f97316','#eab308'
+ ];
+
+ // Extract unique lineages
+ const lineages = [...new Set(data.map(item => item.lineage))];
+ // Build datasets
+ const datasets = lineages.map((lineage, index) => {
+ const lineageData = weeks.map(week => {
+ const found = data.find(
+ item => item.week === week && item.lineage === lineage
+ );
+ return found ? found.total : 0;
+ });
+
+ return {
+ label: lineage,
+ data: lineageData,
+ fill: true, // area fill
+ tension: 0.4, // smooth curve
+ borderColor: 'transparent', // hide the line
+ borderWidth: 0,
+ pointRadius: 0, // hide points
+ backgroundColor: hexToRGBA(colors[(index*2) % colors.length], 0.8),
+ stack: 'total'
+ };
+ });
+
+ // Destroy previous chart if exists
+ if (influenzaSubtypeFrequencyChart) influenzaSubtypeFrequencyChart.destroy();
+
+ const ctx = document.getElementById('influenzaSubtypeFrequency').getContext('2d');
+
+ influenzaSubtypeFrequencyChart = new Chart(ctx, {
+ type: 'line',
+ data: {
+ labels: weeks,
+ datasets: datasets
+ },
+ options: {
+ responsive: true,
+ maintainAspectRatio: false,
+ interaction: {
+ mode: 'index',
+ intersect: false
+ },
+ plugins: {
+ legend: {
+ display: false // hide default legend
+ },
+ tooltip: {
+ mode: 'index',
+ intersect: false
+ },
+ datalabels: {
+ display: false // hide labels
+ }
+ },
+ scales: {
+ x: {
+ stacked: true,
+ title: {
+ display: true,
+ text: 'Week'
+ },
+ grid:{
+ display: false
+ }
+ },
+ y: {
+ stacked: true,
+ beginAtZero: true,
+ title: {
+ display: true,
+ text: 'Relative Frequency'
+ },
+ }
+ }
+ }
+ });
+
+ const legendContainer = document.getElementById('legendContainerInfluenzaSubtypeFrequency');
+ legendContainer.innerHTML = ''; // clear old legend
+
+ datasets.forEach((dataset, index) => {
+ const item = document.createElement('div');
+ item.style.display = 'flex';
+ item.style.alignItems = 'center';
+ item.style.marginBottom = '4px';
+ item.style.fontSize = '11px';
+ item.style.cursor = 'pointer';
+ item.innerHTML = `
+
+ ${dataset.label}
+ `;
+
+ item.addEventListener('click', () => {
+ const meta = influenzaSubtypeFrequencyChart.getDatasetMeta(index);
+
+ // If the clicked dataset is already the only visible one, show all
+ const allHidden = datasets.every((d, i) => influenzaSubtypeFrequencyChart.getDatasetMeta(i).hidden || i === index);
+ if (!allHidden) {
+ // Hide all datasets
+ datasets.forEach((d, i) => {
+ influenzaSubtypeFrequencyChart.getDatasetMeta(i).hidden = true;
+ });
+ // Show only clicked
+ meta.hidden = false;
+ } else {
+ // Show all datasets
+ datasets.forEach((d, i) => {
+ influenzaSubtypeFrequencyChart.getDatasetMeta(i).hidden = false;
+ });
+ }
+
+ influenzaSubtypeFrequencyChart.update();
+
+ // Update legend opacity
+ Array.from(legendContainer.children).forEach((child, i) => {
+ const metaItem = influenzaSubtypeFrequencyChart.getDatasetMeta(i);
+ child.style.opacity = metaItem.hidden ? 0.5 : 1;
+ });
+ });
+
+ legendContainer.appendChild(item);
+ });
+
+ // Scrollable CSS (in case legend is long)
+ legendContainer.style.maxHeight = '375px';
+ legendContainer.style.overflowY = 'auto';
+ legendContainer.style.padding = '8px';
+ legendContainer.style.borderRadius = '0px';
+ });
+}
diff --git a/dashboard/resources/views/dashboard/overview.blade.php b/dashboard/resources/views/dashboard/overview.blade.php
index 92f6985..700b758 100644
--- a/dashboard/resources/views/dashboard/overview.blade.php
+++ b/dashboard/resources/views/dashboard/overview.blade.php
@@ -47,7 +47,6 @@
-
Epidemic Trend
(based on selected epiweek range)
@@ -108,11 +107,11 @@
(based on selected epiweek range)
-
+
(based on selected epiweek range)
-
+
-
-
+
+
+
+
+
+
Total Sequenced Samples Over Time
+
+ (based on selected epiweek range)
+
+
+
+
+
+
+
+
+
Influenza Subtypes Relative Frequencies Over Time
+
+ (based on selected epiweek range)
+
+
+
+
+
+
+
-
+
-
-
Lineage Counts Over Time
-
+
+
SARS-CoV-2 Lineage/Sublineage Relative Frequencies Over Time
+
+ (based on selected epiweek range)
+
+{{--
--}}
+
+
+{{--
--}}
+{{--
--}}
+{{--
--}}
+{{-- --}}
+{{-- --}}
+{{--
--}}
+{{--
--}}
+{{--
--}}
+
-
-
-
-
Total Sequenced Samples Over Time
-
-
-
-
+
@@ -62,8 +105,8 @@
@section('scripts')
-@endsection
\ No newline at end of file
+@endsection
diff --git a/dashboard/resources/views/layouts/app.blade.php b/dashboard/resources/views/layouts/app.blade.php
index 8e621e9..163044f 100644
--- a/dashboard/resources/views/layouts/app.blade.php
+++ b/dashboard/resources/views/layouts/app.blade.php
@@ -46,6 +46,9 @@
top: 0;
z-index: 1000;
}
+ .btn{
+ border-radius: 0 !important;
+ }
.btn-theme-outline {
background-color: #fff;
@@ -263,4 +266,4 @@