feat(charts): Implement disk usage chart for server screen

This commit is contained in:
NaiJi 2024-08-05 12:43:52 +04:00 committed by Inex Code
parent 68f34dc7b7
commit bc121aa7ed
3 changed files with 155 additions and 180 deletions

View file

@ -136,6 +136,7 @@
"day": "Day", "day": "Day",
"hour": "Hour", "hour": "Hour",
"cpu_title": "CPU Usage", "cpu_title": "CPU Usage",
"disk_title": "Disk Usage",
"network_title": "Network Usage", "network_title": "Network Usage",
"in": "In", "in": "In",
"out": "Out", "out": "Out",

View file

@ -161,7 +161,7 @@ class _Chart extends StatelessWidget {
children: [ children: [
Flexible( Flexible(
child: Text( child: Text(
'resource_chart.network_title'.tr(), 'resource_chart.disk_title'.tr(),
style: style:
Theme.of(context).textTheme.titleMedium?.copyWith( Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context) color: Theme.of(context)
@ -177,16 +177,16 @@ class _Chart extends StatelessWidget {
runSpacing: 8.0, runSpacing: 8.0,
alignment: WrapAlignment.end, alignment: WrapAlignment.end,
runAlignment: WrapAlignment.end, runAlignment: WrapAlignment.end,
children: [ children: state.diskMetrics?.diskMetrics.keys
Legend( .map<Widget>(
color: Theme.of(context).colorScheme.primary, (final diskId) => Legend(
text: 'resource_chart.in'.tr(), color:
Theme.of(context).colorScheme.primary,
text: diskId,
), ),
Legend( )
color: Theme.of(context).colorScheme.tertiary, .toList() ??
text: 'resource_chart.out'.tr(), [],
),
],
), ),
), ),
], ],
@ -321,7 +321,7 @@ Widget getDiskChart(final MetricsLoaded state) {
return SizedBox( return SizedBox(
height: 200, height: 200,
child: DiskChart( child: DiskChart(
listData: data.diskMetrics.values.toList(), diskData: data.diskMetrics,
period: state.period, period: state.period,
start: state.metrics.start, start: state.metrics.start,
), ),

View file

@ -10,17 +10,17 @@ import 'package:selfprivacy/ui/pages/server_details/charts/bottom_title.dart';
class DiskChart extends StatelessWidget { class DiskChart extends StatelessWidget {
const DiskChart({ const DiskChart({
required this.listData, required this.diskData,
required this.period, required this.period,
required this.start, required this.start,
super.key, super.key,
}); });
final List<List<TimeSeriesData>> listData; final Map<String, List<TimeSeriesData>> diskData;
final Period period; final Period period;
final DateTime start; final DateTime start;
List<FlSpot> getSpots(final data) { List<FlSpot> getSpots(final List<TimeSeriesData> data) {
var i = 0; var i = 0;
final List<FlSpot> res = []; final List<FlSpot> res = [];
@ -33,7 +33,14 @@ class DiskChart extends StatelessWidget {
} }
@override @override
Widget build(final BuildContext context) => LineChart( Widget build(final BuildContext context) {
final anyDiskId = diskData.keys.toList()[0];
final diskDataMax = [
...diskData.values.map<List<double>>(
(final timeData) => timeData.map((final e) => e.value).toList(),
),
].expand((final x) => x).reduce(max);
return LineChart(
LineChartData( LineChartData(
lineTouchData: LineTouchData( lineTouchData: LineTouchData(
enabled: true, enabled: true,
@ -45,14 +52,13 @@ class DiskChart extends StatelessWidget {
final List<LineTooltipItem> res = []; final List<LineTooltipItem> res = [];
bool timeShown = false; bool timeShown = false;
for (final spot in touchedBarSpots) { for (final spot in touchedBarSpots) {
final value = spot.y; final value = spot.y;
final date = listData[0][spot.x.toInt()].time; final date = diskData[anyDiskId]![spot.x.toInt()].time;
res.add( res.add(
LineTooltipItem( LineTooltipItem(
'${timeShown ? '' : DateFormat('HH:mm dd.MM.yyyy').format(date)} ${spot.barIndex == 0 ? 'resource_chart.in'.tr() : 'resource_chart.out'.tr()} ${DiskSize(byte: value.toInt()).toString()}', '${timeShown ? '' : DateFormat('HH:mm dd.MM.yyyy').format(date)} ${diskData.keys.toList()[spot.barIndex]} ${value.toInt()}%',
TextStyle( TextStyle(
color: Theme.of(context).colorScheme.onSurface, color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -67,10 +73,11 @@ class DiskChart extends StatelessWidget {
}, },
), ),
), ),
lineBarsData: [ lineBarsData: diskData.values
// IN .toList()
LineChartBarData( .map<LineChartBarData>(
spots: getSpots(listData[0]), (final timeData) => LineChartBarData(
spots: getSpots(timeData),
isCurved: false, isCurved: false,
barWidth: 2, barWidth: 2,
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
@ -89,34 +96,10 @@ class DiskChart extends StatelessWidget {
), ),
), ),
), ),
// OUT )
LineChartBarData( .toList(),
spots: getSpots(listData[1]),
isCurved: false,
barWidth: 2,
color: Theme.of(context).colorScheme.tertiary,
dotData: const FlDotData(
show: false,
),
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: [
Theme.of(context).colorScheme.tertiary.withOpacity(0.5),
Theme.of(context).colorScheme.tertiary.withOpacity(0.0),
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
),
],
minY: 0, minY: 0,
maxY: [ maxY: 100,
...listData[0].map((final e) => e.value),
...listData[1].map((final e) => e.value),
].reduce(max) *
1.2,
minX: 0, minX: 0,
titlesData: FlTitlesData( titlesData: FlTitlesData(
topTitles: const AxisTitles( topTitles: const AxisTitles(
@ -131,7 +114,7 @@ class DiskChart extends StatelessWidget {
child: Text( child: Text(
bottomTitle( bottomTitle(
value.toInt(), value.toInt(),
listData[0], diskData[anyDiskId]!,
period, period,
), ),
style: Theme.of(context).textTheme.labelSmall?.copyWith( style: Theme.of(context).textTheme.labelSmall?.copyWith(
@ -151,18 +134,13 @@ class DiskChart extends StatelessWidget {
getTitlesWidget: (final value, final titleMeta) => Padding( getTitlesWidget: (final value, final titleMeta) => Padding(
padding: const EdgeInsets.only(left: 5), padding: const EdgeInsets.only(left: 5),
child: Text( child: Text(
DiskSize(byte: value.toInt()).toString(), '${value.toInt()}%',
style: Theme.of(context).textTheme.labelSmall?.copyWith( style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant, color: Theme.of(context).colorScheme.onSurfaceVariant,
), ),
), ),
), ),
interval: [ interval: diskDataMax * 2 / 6.5,
...listData[0].map((final e) => e.value),
...listData[1].map((final e) => e.value),
].reduce(max) *
2 /
6.5,
showTitles: true, showTitles: true,
), ),
), ),
@ -171,12 +149,7 @@ class DiskChart extends StatelessWidget {
show: true, show: true,
drawVerticalLine: true, drawVerticalLine: true,
verticalInterval: 40, verticalInterval: 40,
horizontalInterval: [ horizontalInterval: diskDataMax * 2 / 6.5,
...listData[0].map((final e) => e.value),
...listData[1].map((final e) => e.value),
].reduce(max) *
2 /
6.5,
getDrawingHorizontalLine: (final value) => FlLine( getDrawingHorizontalLine: (final value) => FlLine(
color: Theme.of(context).colorScheme.outline.withOpacity(0.3), color: Theme.of(context).colorScheme.outline.withOpacity(0.3),
strokeWidth: 1, strokeWidth: 1,
@ -209,6 +182,7 @@ class DiskChart extends StatelessWidget {
), ),
), ),
); );
}
bool checkToShowTitle( bool checkToShowTitle(
final double minValue, final double minValue,