[pve-devel] [PATCH pve_flutter_frontend] cleanup: run `dart format` command to fix formatting
Shan Shaji
s.shaji at proxmox.com
Tue Aug 12 12:15:52 CEST 2025
The following commit `f263217` [0] skipped running the `dart format`
command on changed files to avoid missing the changes. To fix the issue
ran the command again on master.
[0] - https://lore.proxmox.com/pve-devel/20250804110634.64816-1-s.shaji@proxmox.com/T/#t
Signed-off-by: Shan Shaji <s.shaji at proxmox.com>
---
lib/widgets/pve_lxc_options_widget.dart | 138 ++---
lib/widgets/pve_lxc_overview.dart | 325 +++++-----
lib/widgets/pve_node_overview.dart | 724 +++++++++++------------
lib/widgets/pve_qemu_options_widget.dart | 256 ++++----
lib/widgets/pve_qemu_overview.dart | 335 +++++------
lib/widgets/pve_task_log_widget.dart | 228 +++----
6 files changed, 997 insertions(+), 1009 deletions(-)
diff --git a/lib/widgets/pve_lxc_options_widget.dart b/lib/widgets/pve_lxc_options_widget.dart
index 7ad0224..5b6e009 100644
--- a/lib/widgets/pve_lxc_options_widget.dart
+++ b/lib/widgets/pve_lxc_options_widget.dart
@@ -16,76 +16,76 @@ class PveLxcOptions extends StatelessWidget {
final config = state.config;
if (config != null) {
return Scaffold(
- appBar: AppBar(),
- body: SingleChildScrollView(
- child: Column(
- children: <Widget>[
- ListTile(
- title: const Text("Name"),
- subtitle: Text(config.hostname ?? 'undefined'),
- ),
- PveConfigSwitchListTile(
- title: const Text("Start on boot"),
- value: config.onboot,
- defaultValue: false,
- pending: config.getPending('onboot'),
- onChanged: (v) => lxcBloc!.events
- .add(UpdateLxcConfigBool('onboot', v)),
- onDeleted: () => lxcBloc!.events
- .add(RevertPendingLxcConfig('onboot')),
- ),
- ListTile(
- title: const Text("Start/Shutdown order"),
- subtitle: Text(config.startup ?? "Default (any)"),
- ),
- ListTile(
- title: const Text("OS Type"),
- subtitle: Text("${config.ostype}"),
- ),
- ListTile(
- title: const Text("Architecture"),
- subtitle: Text("${config.arch}"),
- ),
- PveConfigSwitchListTile(
- title: const Text("/dev/console"),
- value: config.console,
- defaultValue: true,
- pending: config.getPending('console'),
- onChanged: (v) => lxcBloc!.events
- .add(UpdateLxcConfigBool('console', v)),
- onDeleted: () => lxcBloc!.events
- .add(RevertPendingLxcConfig('console')),
- ),
- ListTile(
- title: const Text("TTY Count"),
- subtitle: Text("${config.tty ?? 2}"),
- ),
- ListTile(
- title: const Text("Console Mode"),
- subtitle: Text(config.cmode?.name ?? 'tty'),
- ),
- PveConfigSwitchListTile(
- title: const Text("Protection"),
- value: config.protection,
- defaultValue: false,
- pending: config.getPending('protection'),
- onChanged: (v) => lxcBloc!.events
- .add(UpdateLxcConfigBool('protection', v)),
- onDeleted: () => lxcBloc!.events
- .add(RevertPendingLxcConfig('protection')),
- ),
- ListTile(
- title: const Text("Unprivileged"),
- subtitle:
- Text(config.unprivileged ?? false ? 'Yes' : 'No'),
- ),
- ListTile(
- title: const Text("Features"),
- subtitle: Text(config.features?.toString() ?? 'none'),
- ),
- ],
- ),
+ appBar: AppBar(),
+ body: SingleChildScrollView(
+ child: Column(
+ children: <Widget>[
+ ListTile(
+ title: const Text("Name"),
+ subtitle: Text(config.hostname ?? 'undefined'),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("Start on boot"),
+ value: config.onboot,
+ defaultValue: false,
+ pending: config.getPending('onboot'),
+ onChanged: (v) =>
+ lxcBloc!.events.add(UpdateLxcConfigBool('onboot', v)),
+ onDeleted: () =>
+ lxcBloc!.events.add(RevertPendingLxcConfig('onboot')),
+ ),
+ ListTile(
+ title: const Text("Start/Shutdown order"),
+ subtitle: Text(config.startup ?? "Default (any)"),
+ ),
+ ListTile(
+ title: const Text("OS Type"),
+ subtitle: Text("${config.ostype}"),
+ ),
+ ListTile(
+ title: const Text("Architecture"),
+ subtitle: Text("${config.arch}"),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("/dev/console"),
+ value: config.console,
+ defaultValue: true,
+ pending: config.getPending('console'),
+ onChanged: (v) => lxcBloc!.events
+ .add(UpdateLxcConfigBool('console', v)),
+ onDeleted: () => lxcBloc!.events
+ .add(RevertPendingLxcConfig('console')),
+ ),
+ ListTile(
+ title: const Text("TTY Count"),
+ subtitle: Text("${config.tty ?? 2}"),
+ ),
+ ListTile(
+ title: const Text("Console Mode"),
+ subtitle: Text(config.cmode?.name ?? 'tty'),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("Protection"),
+ value: config.protection,
+ defaultValue: false,
+ pending: config.getPending('protection'),
+ onChanged: (v) => lxcBloc!.events
+ .add(UpdateLxcConfigBool('protection', v)),
+ onDeleted: () => lxcBloc!.events
+ .add(RevertPendingLxcConfig('protection')),
+ ),
+ ListTile(
+ title: const Text("Unprivileged"),
+ subtitle:
+ Text(config.unprivileged ?? false ? 'Yes' : 'No'),
+ ),
+ ListTile(
+ title: const Text("Features"),
+ subtitle: Text(config.features?.toString() ?? 'none'),
+ ),
+ ],
),
+ ),
);
}
return const Center(
diff --git a/lib/widgets/pve_lxc_overview.dart b/lib/widgets/pve_lxc_overview.dart
index fe43a26..1148452 100644
--- a/lib/widgets/pve_lxc_overview.dart
+++ b/lib/widgets/pve_lxc_overview.dart
@@ -71,194 +71,193 @@ class PveLxcOverview extends StatelessWidget {
final status = state.currentStatus;
final config = state.config;
return Scaffold(
- appBar: PveAppBar(
- title: Text(config?.hostname ?? 'CT $guestID'),
- ),
- backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
- body: SingleChildScrollView(
- child: Column(
- children: <Widget>[
- PveGuestOverviewHeader(
- background: !(status?.template ?? false)
- ? PveGuestHeaderRRDPageView(
- rrdData: state.rrdData,
- )
- : Center(
- child: Text(
- "TEMPLATE",
- style: TextStyle(
- color: Theme.of(context)
- .colorScheme
- .onSurfaceVariant,
- ),
+ appBar: PveAppBar(
+ title: Text(config?.hostname ?? 'CT $guestID'),
+ ),
+ backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
+ body: SingleChildScrollView(
+ child: Column(
+ children: <Widget>[
+ PveGuestOverviewHeader(
+ background: !(status?.template ?? false)
+ ? PveGuestHeaderRRDPageView(
+ rrdData: state.rrdData,
+ )
+ : Center(
+ child: Text(
+ "TEMPLATE",
+ style: TextStyle(
+ color: Theme.of(context)
+ .colorScheme
+ .onSurfaceVariant,
),
),
- width: width,
- guestID: guestID,
- guestStatus: status?.getLxcStatus(),
- guestName: config?.hostname ?? 'CT $guestID',
- guestNodeID: state.nodeID,
- guestType: 'lxc',
- ha: status?.ha,
- template: status?.template ?? false,
- ),
- ProxmoxStreamBuilder<PveTaskLogBloc, PveTaskLogState>(
- bloc: taskBloc,
- builder: (context, taskState) {
- if (taskState.tasks.isNotEmpty) {
- return PveTaskExpansionTile(
- task: taskState.tasks.first,
- showMorePage: Provider<PveTaskLogBloc>(
- create: (context) => PveTaskLogBloc(
- apiClient: taskBloc.apiClient,
- init: PveTaskLogState.init(state.nodeID),
+ ),
+ width: width,
+ guestID: guestID,
+ guestStatus: status?.getLxcStatus(),
+ guestName: config?.hostname ?? 'CT $guestID',
+ guestNodeID: state.nodeID,
+ guestType: 'lxc',
+ ha: status?.ha,
+ template: status?.template ?? false,
+ ),
+ ProxmoxStreamBuilder<PveTaskLogBloc, PveTaskLogState>(
+ bloc: taskBloc,
+ builder: (context, taskState) {
+ if (taskState.tasks.isNotEmpty) {
+ return PveTaskExpansionTile(
+ task: taskState.tasks.first,
+ showMorePage: Provider<PveTaskLogBloc>(
+ create: (context) => PveTaskLogBloc(
+ apiClient: taskBloc.apiClient,
+ init: PveTaskLogState.init(state.nodeID),
+ )
+ ..events.add(
+ FilterTasksByGuestID(
+ guestID: guestID,
+ ),
)
- ..events.add(
- FilterTasksByGuestID(
- guestID: guestID,
- ),
- )
- ..events.add(LoadTasks()),
- dispose: (context, bloc) => bloc.dispose(),
- child: const PveTaskLog(),
- ),
- );
- }
- return Container();
- },
- ),
- SizedBox(
- height: 130,
- child: SingleChildScrollView(
- scrollDirection: Axis.horizontal,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: <Widget>[
- if (!(status?.template ?? false))
- createActionCard(
- 'Power Settings',
- Icons.power_settings_new,
- () => showPowerMenuBottomSheet(
- context, lxcBloc)),
- if (!(status?.template ?? false))
- createActionCard(
- 'Console',
- Icons.queue_play_next,
- () => showConsoleMenuBottomSheet(
- context,
- lxcBloc.apiClient,
- guestID,
- state.nodeID,
- 'lxc')),
+ ..events.add(LoadTasks()),
+ dispose: (context, bloc) => bloc.dispose(),
+ child: const PveTaskLog(),
+ ),
+ );
+ }
+ return Container();
+ },
+ ),
+ SizedBox(
+ height: 130,
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: <Widget>[
+ if (!(status?.template ?? false))
+ createActionCard(
+ 'Power Settings',
+ Icons.power_settings_new,
+ () => showPowerMenuBottomSheet(
+ context, lxcBloc)),
+ if (!(status?.template ?? false))
createActionCard(
- 'Options',
- Icons.settings,
- () => Navigator.of(context)
- .push(MaterialPageRoute(
- builder: (context) => PveLxcOptions(
- lxcBloc: lxcBloc,
- ),
- fullscreenDialog: true))),
- if (!resourceBloc.latestState.isStandalone)
- createActionCard(
- 'Migrate',
- FontAwesomeIcons.paperPlane,
- () => Navigator.of(context).push(
- _createMigrationRoute(
- guestID,
- state.nodeID,
- resourceBloc.apiClient!))),
+ 'Console',
+ Icons.queue_play_next,
+ () => showConsoleMenuBottomSheet(
+ context,
+ lxcBloc.apiClient,
+ guestID,
+ state.nodeID,
+ 'lxc')),
+ createActionCard(
+ 'Options',
+ Icons.settings,
+ () => Navigator.of(context)
+ .push(MaterialPageRoute(
+ builder: (context) => PveLxcOptions(
+ lxcBloc: lxcBloc,
+ ),
+ fullscreenDialog: true))),
+ if (!resourceBloc.latestState.isStandalone)
createActionCard(
- 'Backup',
- FontAwesomeIcons.floppyDisk,
+ 'Migrate',
+ FontAwesomeIcons.paperPlane,
() => Navigator.of(context).push(
- _createBackupRoute(guestID, state.nodeID,
+ _createMigrationRoute(
+ guestID,
+ state.nodeID,
resourceBloc.apiClient!))),
- ],
+ createActionCard(
+ 'Backup',
+ FontAwesomeIcons.floppyDisk,
+ () => Navigator.of(context).push(
+ _createBackupRoute(guestID, state.nodeID,
+ resourceBloc.apiClient!))),
+ ],
+ ),
+ ),
+ ),
+ if (config != null) ...[
+ PveResourceDataCardWidget(
+ title: const Text(
+ 'Resources',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 20,
),
),
+ children: <Widget>[
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.memory),
+ title: Text('${config.memory}'),
+ subtitle: const Text('Memory'),
+ dense: true,
+ ),
+ ListTile(
+ leading: const Icon(Icons.cached),
+ title: Text('${config.swap}'),
+ subtitle: const Text('Swap'),
+ dense: true,
+ ),
+ ListTile(
+ leading: const Icon(Icons.memory),
+ title: Text('${config.cores ?? 'unlimited'}'),
+ subtitle: const Text('Cores'),
+ dense: true,
+ ),
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.hardDrive),
+ dense: true,
+ title: Text('${config.rootfs}'),
+ ),
+ ],
),
- if (config != null) ...[
- PveResourceDataCardWidget(
+ PveResourceDataCardWidget(
title: const Text(
- 'Resources',
+ 'Network',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
children: <Widget>[
- ListTile(
- leading: const Icon(FontAwesomeIcons.memory),
- title: Text('${config.memory}'),
- subtitle: const Text('Memory'),
- dense: true,
- ),
- ListTile(
- leading: const Icon(Icons.cached),
- title: Text('${config.swap}'),
- subtitle: const Text('Swap'),
- dense: true,
+ for (var net in config.net!)
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.ethernet),
+ dense: true,
+ title: Text(net),
+ ),
+ ]),
+ PveResourceDataCardWidget(
+ title: const Text(
+ 'DNS',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 20,
),
+ ),
+ children: <Widget>[
ListTile(
- leading: const Icon(Icons.memory),
- title: Text('${config.cores ?? 'unlimited'}'),
- subtitle: const Text('Cores'),
+ leading: const Icon(FontAwesomeIcons.globe),
dense: true,
+ title: Text(
+ config.searchdomain ?? 'Use host settings'),
+ subtitle: const Text('DNS Domain'),
),
ListTile(
- leading: const Icon(FontAwesomeIcons.hardDrive),
+ leading:
+ const Icon(FontAwesomeIcons.magnifyingGlass),
dense: true,
- title: Text('${config.rootfs}'),
+ title: Text(
+ config.nameserver ?? 'Use host settings'),
+ subtitle: const Text('DNS Server'),
),
- ],
- ),
- PveResourceDataCardWidget(
- title: const Text(
- 'Network',
- style: TextStyle(
- fontWeight: FontWeight.bold,
- fontSize: 20,
- ),
- ),
- children: <Widget>[
- for (var net in config.net!)
- ListTile(
- leading:
- const Icon(FontAwesomeIcons.ethernet),
- dense: true,
- title: Text(net),
- ),
- ]),
- PveResourceDataCardWidget(
- title: const Text(
- 'DNS',
- style: TextStyle(
- fontWeight: FontWeight.bold,
- fontSize: 20,
- ),
- ),
- children: <Widget>[
- ListTile(
- leading: const Icon(FontAwesomeIcons.globe),
- dense: true,
- title: Text(
- config.searchdomain ?? 'Use host settings'),
- subtitle: const Text('DNS Domain'),
- ),
- ListTile(
- leading: const Icon(
- FontAwesomeIcons.magnifyingGlass),
- dense: true,
- title: Text(
- config.nameserver ?? 'Use host settings'),
- subtitle: const Text('DNS Server'),
- ),
- ]),
- ]
- ],
- ),
+ ]),
+ ]
+ ],
),
+ ),
);
}),
);
diff --git a/lib/widgets/pve_node_overview.dart b/lib/widgets/pve_node_overview.dart
index cc58df9..f99ca53 100644
--- a/lib/widgets/pve_node_overview.dart
+++ b/lib/widgets/pve_node_overview.dart
@@ -51,401 +51,397 @@ class PveNodeOverview extends StatelessWidget {
final fgColor =
Theme.of(context).colorScheme.onPrimary.withValues(alpha: 0.75);
return Scaffold(
- appBar: PveAppBar(
- title: Text(
- "Node $nodeID",
- style:
- const TextStyle(fontWeight: FontWeight.bold, fontSize: 25),
- maxLines: 2,
- overflow: TextOverflow.ellipsis,
- ),
+ appBar: PveAppBar(
+ title: Text(
+ "Node $nodeID",
+ style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 25),
+ maxLines: 2,
+ overflow: TextOverflow.ellipsis,
),
- backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
- body: SingleChildScrollView(
- child: Column(
- children: <Widget>[
- if (rrd.isNotEmpty)
- Container(
- height: 200,
- color: Theme.of(context).colorScheme.primary,
- child: ScrollConfiguration(
- behavior: PVEScrollBehavior(),
- child: PageView.builder(
- itemCount: 4,
- itemBuilder: (context, item) {
- final page = item + 1;
- final pageIndicator = Text(
- '$page of 4',
- style: const TextStyle(
- color: Colors.white54,
- fontWeight: FontWeight.w500,
- ),
- );
- double? lastCpu = rrd.last.cpu;
- String lastCpuText = lastCpu != null
- ? "${(lastCpu * 100.0).toStringAsFixed(2)} %"
- : "";
- return Column(
- children: [
- if (item == 0)
- Expanded(
- child: PveRRDChart(
- title:
- 'CPU (${state.status?.cpuinfo.cpus ?? '-'})',
- subtitle: lastCpuText,
- data: rrd.where((e) => e.cpu != null).map(
- (e) => Point(
- e.time!.millisecondsSinceEpoch,
- (e.cpu ?? 0) * 100.0)),
- icon: Icon(Icons.memory, color: fgColor),
- bottomRight: pageIndicator,
- dataRenderer: (data) =>
- '${data.toStringAsFixed(2)} %',
- ),
+ ),
+ backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
+ body: SingleChildScrollView(
+ child: Column(
+ children: <Widget>[
+ if (rrd.isNotEmpty)
+ Container(
+ height: 200,
+ color: Theme.of(context).colorScheme.primary,
+ child: ScrollConfiguration(
+ behavior: PVEScrollBehavior(),
+ child: PageView.builder(
+ itemCount: 4,
+ itemBuilder: (context, item) {
+ final page = item + 1;
+ final pageIndicator = Text(
+ '$page of 4',
+ style: const TextStyle(
+ color: Colors.white54,
+ fontWeight: FontWeight.w500,
+ ),
+ );
+ double? lastCpu = rrd.last.cpu;
+ String lastCpuText = lastCpu != null
+ ? "${(lastCpu * 100.0).toStringAsFixed(2)} %"
+ : "";
+ return Column(
+ children: [
+ if (item == 0)
+ Expanded(
+ child: PveRRDChart(
+ title:
+ 'CPU (${state.status?.cpuinfo.cpus ?? '-'})',
+ subtitle: lastCpuText,
+ data: rrd.where((e) => e.cpu != null).map(
+ (e) => Point(
+ e.time!.millisecondsSinceEpoch,
+ (e.cpu ?? 0) * 100.0)),
+ icon: Icon(Icons.memory, color: fgColor),
+ bottomRight: pageIndicator,
+ dataRenderer: (data) =>
+ '${data.toStringAsFixed(2)} %',
),
- if (item == 1)
- Expanded(
- child: PveRRDChart(
- title: 'Memory',
- subtitle: Renderers.formatSize(
- rrd.last.memused ?? 0),
- data: rrd.map((e) => Point(
- e.time!.millisecondsSinceEpoch,
- e.memused ?? 0)),
- icon: Icon(FontAwesomeIcons.memory,
- color: fgColor),
- bottomRight: pageIndicator,
- dataRenderer: (data) =>
- Renderers.formatSize(data),
- ),
+ ),
+ if (item == 1)
+ Expanded(
+ child: PveRRDChart(
+ title: 'Memory',
+ subtitle: Renderers.formatSize(
+ rrd.last.memused ?? 0),
+ data: rrd.map((e) => Point(
+ e.time!.millisecondsSinceEpoch,
+ e.memused ?? 0)),
+ icon: Icon(FontAwesomeIcons.memory,
+ color: fgColor),
+ bottomRight: pageIndicator,
+ dataRenderer: (data) =>
+ Renderers.formatSize(data),
),
- if (item == 2)
- Expanded(
- child: PveRRDChart(
- title: 'I/O wait',
- subtitle:
- rrd.last.iowait?.toStringAsFixed(2) ??
- '0',
- data: rrd.map((e) => Point(
- e.time!.millisecondsSinceEpoch,
- e.iowait ?? 0)),
- icon: Icon(Icons.timer, color: fgColor),
- bottomRight: pageIndicator,
- dataRenderer: (data) =>
- data.toStringAsFixed(3),
- ),
+ ),
+ if (item == 2)
+ Expanded(
+ child: PveRRDChart(
+ title: 'I/O wait',
+ subtitle:
+ rrd.last.iowait?.toStringAsFixed(2) ??
+ '0',
+ data: rrd.map((e) => Point(
+ e.time!.millisecondsSinceEpoch,
+ e.iowait ?? 0)),
+ icon: Icon(Icons.timer, color: fgColor),
+ bottomRight: pageIndicator,
+ dataRenderer: (data) =>
+ data.toStringAsFixed(3),
),
- if (item == 3)
- Expanded(
- child: PveRRDChart(
- title: 'Load',
- subtitle: rrd.last.loadavg
- ?.toStringAsFixed(2) ??
- '0',
- data: rrd.map((e) => Point(
- e.time!.millisecondsSinceEpoch,
- e.loadavg ?? 0)),
- icon: Icon(Icons.show_chart,
- color: fgColor),
- bottomRight: pageIndicator,
- dataRenderer: (data) =>
- data.toStringAsFixed(2),
- ),
+ ),
+ if (item == 3)
+ Expanded(
+ child: PveRRDChart(
+ title: 'Load',
+ subtitle:
+ rrd.last.loadavg?.toStringAsFixed(2) ??
+ '0',
+ data: rrd.map((e) => Point(
+ e.time!.millisecondsSinceEpoch,
+ e.loadavg ?? 0)),
+ icon:
+ Icon(Icons.show_chart, color: fgColor),
+ bottomRight: pageIndicator,
+ dataRenderer: (data) =>
+ data.toStringAsFixed(2),
),
- ],
- );
- },
- ),
+ ),
+ ],
+ );
+ },
),
),
- ProxmoxStreamBuilder<PveTaskLogBloc, PveTaskLogState>(
- bloc: tBloc,
- builder: (context, taskState) {
- if (taskState.tasks.isNotEmpty) {
- return Padding(
- padding: const EdgeInsets.all(4.0),
- child: PveTaskExpansionTile(
- task: taskState.tasks.first,
- showMorePage: Provider<PveTaskLogBloc>(
- create: (context) => PveTaskLogBloc(
- apiClient: tBloc.apiClient,
- init: PveTaskLogState.init(nodeID),
- )..events.add(LoadTasks()),
- dispose: (context, bloc) => bloc.dispose(),
- child: const PveTaskLog(),
- ),
- ),
- );
- }
- return Container();
- },
),
- SizedBox(
- height: 130,
- child: SingleChildScrollView(
- scrollDirection: Axis.horizontal,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: <Widget>[
- ActionCard(
- icon: const Icon(
- Icons.power_settings_new,
- size: 55,
- color: Colors.white24,
- ),
- title: 'Power Settings',
- onTap: () =>
- showPowerMenuBottomSheet(context, nBloc),
+ ProxmoxStreamBuilder<PveTaskLogBloc, PveTaskLogState>(
+ bloc: tBloc,
+ builder: (context, taskState) {
+ if (taskState.tasks.isNotEmpty) {
+ return Padding(
+ padding: const EdgeInsets.all(4.0),
+ child: PveTaskExpansionTile(
+ task: taskState.tasks.first,
+ showMorePage: Provider<PveTaskLogBloc>(
+ create: (context) => PveTaskLogBloc(
+ apiClient: tBloc.apiClient,
+ init: PveTaskLogState.init(nodeID),
+ )..events.add(LoadTasks()),
+ dispose: (context, bloc) => bloc.dispose(),
+ child: const PveTaskLog(),
),
- ActionCard(
- icon: const Icon(
- Icons.queue_play_next,
- size: 55,
- color: Colors.white24,
- ),
- title: 'Console',
- onTap: () => showConsoleMenuBottomSheet(
- context, nBloc.apiClient, null, nodeID, 'node'),
+ ),
+ );
+ }
+ return Container();
+ },
+ ),
+ SizedBox(
+ height: 130,
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: <Widget>[
+ ActionCard(
+ icon: const Icon(
+ Icons.power_settings_new,
+ size: 55,
+ color: Colors.white24,
),
- ],
- ),
+ title: 'Power Settings',
+ onTap: () => showPowerMenuBottomSheet(context, nBloc),
+ ),
+ ActionCard(
+ icon: const Icon(
+ Icons.queue_play_next,
+ size: 55,
+ color: Colors.white24,
+ ),
+ title: 'Console',
+ onTap: () => showConsoleMenuBottomSheet(
+ context, nBloc.apiClient, null, nodeID, 'node'),
+ ),
+ ],
),
),
- PveResourceDataCardWidget(
- expandable: false,
- showTitleTrailing: true,
- title: const Text(
- 'Summary',
- style: TextStyle(
- fontWeight: FontWeight.bold,
- fontSize: 20,
- ),
+ ),
+ PveResourceDataCardWidget(
+ expandable: false,
+ showTitleTrailing: true,
+ title: const Text(
+ 'Summary',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 20,
+ ),
+ ),
+ titleTrailing: Text(Renderers.renderDuration(
+ Duration(seconds: status?.uptime ?? 0))),
+ subtitle: Text(status?.pveversion ?? ''),
+ children: [
+ ListTile(
+ dense: true,
+ title: Text(status?.kversion ?? 'unknown'),
+ subtitle: const Text('Kernel'),
),
- titleTrailing: Text(Renderers.renderDuration(
- Duration(seconds: status?.uptime ?? 0))),
- subtitle: Text(status?.pveversion ?? ''),
- children: [
+ if (status?.cpuinfo != null)
ListTile(
dense: true,
- title: Text(status?.kversion ?? 'unknown'),
- subtitle: const Text('Kernel'),
+ title: Text(
+ '${status!.cpuinfo.cpus} x ${status.cpuinfo.model}'),
+ subtitle: Text(
+ 'CPU Information (Socket: ${status.cpuinfo.sockets})'),
),
- if (status?.cpuinfo != null)
- ListTile(
- dense: true,
- title: Text(
- '${status!.cpuinfo.cpus} x ${status.cpuinfo.model}'),
- subtitle: Text(
- 'CPU Information (Socket: ${status.cpuinfo.sockets})'),
- ),
- if (status?.ksm.shared ?? false)
- CheckboxListTile(
- dense: true,
- value: status?.ksm.shared ?? false,
- title: const Text('Kernel same-page merging (KSM)',
- style: TextStyle(color: Colors.black)),
- onChanged: null,
- ),
- if (status?.rootfs != null) ...[
- const Divider(
- indent: 10,
- endIndent: 10,
- ),
- Padding(
- padding: const EdgeInsets.symmetric(vertical: 8.0),
- child: ListTile(
- title: const Text('HD space (root)'),
- subtitle: ProxmoxCapacityIndicator(
- icon: Icon(
- FontAwesomeIcons.solidHardDrive,
- color: Colors.blueGrey[300],
- ),
- usedValue:
- Renderers.formatSize(status!.rootfs.used),
- totalValue:
- Renderers.formatSize(status.rootfs.total),
- usedPercent:
- (status.rootfs.used) / (status.rootfs.total),
+ if (status?.ksm.shared ?? false)
+ CheckboxListTile(
+ dense: true,
+ value: status?.ksm.shared ?? false,
+ title: const Text('Kernel same-page merging (KSM)',
+ style: TextStyle(color: Colors.black)),
+ onChanged: null,
+ ),
+ if (status?.rootfs != null) ...[
+ const Divider(
+ indent: 10,
+ endIndent: 10,
+ ),
+ Padding(
+ padding: const EdgeInsets.symmetric(vertical: 8.0),
+ child: ListTile(
+ title: const Text('HD space (root)'),
+ subtitle: ProxmoxCapacityIndicator(
+ icon: Icon(
+ FontAwesomeIcons.solidHardDrive,
+ color: Colors.blueGrey[300],
),
+ usedValue:
+ Renderers.formatSize(status!.rootfs.used),
+ totalValue:
+ Renderers.formatSize(status.rootfs.total),
+ usedPercent:
+ (status.rootfs.used) / (status.rootfs.total),
),
),
- ],
- ],
- ),
- PveResourceDataCardWidget(
- expandable: true,
- showTitleTrailing: !state.allServicesRunning,
- titleTrailing: const Icon(Icons.warning),
- title: const Text(
- 'Services',
- style: TextStyle(
- fontWeight: FontWeight.bold,
- fontSize: 20,
),
+ ],
+ ],
+ ),
+ PveResourceDataCardWidget(
+ expandable: true,
+ showTitleTrailing: !state.allServicesRunning,
+ titleTrailing: const Icon(Icons.warning),
+ title: const Text(
+ 'Services',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 20,
),
- subtitle: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- if (state.allServicesRunning) const Text('All running'),
- if (!state.allServicesRunning)
- const Text('One or more not running'),
- const Divider(),
- ],
- ),
- children: state.services
- .map(
- (s) => ListTile(
- dense: true,
- title: Text(s.name),
- subtitle: Text(s.desc),
- trailing: getServiceStateIcon(context, s),
- ),
- )
- .toList()
- ..sort((a, b) => (a.title as Text)
- .data!
- .compareTo((b.title as Text).data!)),
),
- PveResourceDataCardWidget(
- expandable: !state.updatesQueryPermissionFailure,
- showTitleTrailing: state.updates.isNotEmpty,
- titleTrailing: const Icon(Icons.info_outline),
- title: const Text(
- 'Updates',
- style: TextStyle(
- fontWeight: FontWeight.bold,
- fontSize: 20,
- ),
- ),
- subtitle: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- if (state.updatesQueryPermissionFailure)
- const Text('Lacking permission to query updates'),
- if (state.updates.isEmpty &&
- !state.updatesQueryPermissionFailure)
- const Text('No updates available'),
- if (state.updates.isNotEmpty)
- Text(
- '${state.updates.length} packages are ready to update'),
- if (!state.updatesQueryPermissionFailure)
- const Divider(),
- ],
+ subtitle: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: <Widget>[
+ if (state.allServicesRunning) const Text('All running'),
+ if (!state.allServicesRunning)
+ const Text('One or more not running'),
+ const Divider(),
+ ],
+ ),
+ children: state.services
+ .map(
+ (s) => ListTile(
+ dense: true,
+ title: Text(s.name),
+ subtitle: Text(s.desc),
+ trailing: getServiceStateIcon(context, s),
+ ),
+ )
+ .toList()
+ ..sort((a, b) => (a.title as Text)
+ .data!
+ .compareTo((b.title as Text).data!)),
+ ),
+ PveResourceDataCardWidget(
+ expandable: !state.updatesQueryPermissionFailure,
+ showTitleTrailing: state.updates.isNotEmpty,
+ titleTrailing: const Icon(Icons.info_outline),
+ title: const Text(
+ 'Updates',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 20,
),
- children: state.updates
- .map(
- (s) => ListTile(
- dense: true,
- title: Text(s.title),
- subtitle: Text(
- '${s.package}: ${s.oldVersion ?? ''} -> ${s.version}'),
- trailing: IconButton(
- icon: const Icon(
- Icons.info,
- ),
- onPressed: () => showDialog(
- context: context,
- builder: (context) => SimpleDialog(
- title: const Text('Description'),
- contentPadding: const EdgeInsets.all(24),
- children: <Widget>[
- Text(
- s.description ?? '',
- style: const TextStyle(fontSize: 12),
- )
- ],
- ),
+ ),
+ subtitle: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: <Widget>[
+ if (state.updatesQueryPermissionFailure)
+ const Text('Lacking permission to query updates'),
+ if (state.updates.isEmpty &&
+ !state.updatesQueryPermissionFailure)
+ const Text('No updates available'),
+ if (state.updates.isNotEmpty)
+ Text(
+ '${state.updates.length} packages are ready to update'),
+ if (!state.updatesQueryPermissionFailure) const Divider(),
+ ],
+ ),
+ children: state.updates
+ .map(
+ (s) => ListTile(
+ dense: true,
+ title: Text(s.title),
+ subtitle: Text(
+ '${s.package}: ${s.oldVersion ?? ''} -> ${s.version}'),
+ trailing: IconButton(
+ icon: const Icon(
+ Icons.info,
+ ),
+ onPressed: () => showDialog(
+ context: context,
+ builder: (context) => SimpleDialog(
+ title: const Text('Description'),
+ contentPadding: const EdgeInsets.all(24),
+ children: <Widget>[
+ Text(
+ s.description ?? '',
+ style: const TextStyle(fontSize: 12),
+ )
+ ],
),
),
),
- )
- .toList()
- ..sort((a, b) => (a.title as Text)
- .data!
- .compareTo((b.title as Text).data!)),
- ),
- PveResourceDataCardWidget(
- expandable: false,
- title: const Text(
- 'Disks',
- style: TextStyle(
- fontWeight: FontWeight.bold,
- fontSize: 20,
- ),
+ ),
+ )
+ .toList()
+ ..sort((a, b) => (a.title as Text)
+ .data!
+ .compareTo((b.title as Text).data!)),
+ ),
+ PveResourceDataCardWidget(
+ expandable: false,
+ title: const Text(
+ 'Disks',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 20,
),
- showTitleTrailing: !state.allDisksHealthy,
- titleTrailing: const Icon(Icons.warning),
- subtitle: state.allDisksHealthy
- ? const Text('No health issues')
- : const Text('Check disks, health error indicated!'),
- children: state.disks
- .map(
- (d) => ListTile(
- dense: true,
- leading: Icon(FontAwesomeIcons.solidHardDrive,
- color: state.isDiskHealthy(d)
- ? Colors.grey
- : Colors.red),
- title:
- Text('${d.type!.toUpperCase()}: ${d.devPath}'),
- subtitle: Text(
- 'Usage: ${d.used} ${Renderers.formatSize(d.size ?? 0)}'),
- trailing: IconButton(
- icon: const Icon(
- Icons.info,
- ),
- onPressed: () => showDialog(
- context: context,
- builder: (context) => SimpleDialog(
- title: const Text('Details'),
- contentPadding: const EdgeInsets.all(24),
- children: <Widget>[
- ListTile(
- title: const Text("Device"),
- subtitle: Text(d.devPath!),
- ),
- ListTile(
- title: const Text("Type"),
- subtitle: Text(d.type!),
- ),
- ListTile(
- title: const Text("Usage"),
- subtitle: Text(d.used!),
- ),
- ListTile(
- title: const Text("GPT"),
- subtitle: Text(d.gpt.toString()),
- ),
- ListTile(
- title: const Text("Model"),
- subtitle: Text(d.model!),
- ),
- ListTile(
- title: const Text("Serial"),
- subtitle: Text(d.serial!),
- ),
- ListTile(
- title: const Text("S.M.A.R.T"),
- subtitle: Text(d.health!),
- ),
- ListTile(
- title: const Text("Wearout"),
- subtitle: Text(d.wearoutPercentage),
- )
- ],
- ),
+ ),
+ showTitleTrailing: !state.allDisksHealthy,
+ titleTrailing: const Icon(Icons.warning),
+ subtitle: state.allDisksHealthy
+ ? const Text('No health issues')
+ : const Text('Check disks, health error indicated!'),
+ children: state.disks
+ .map(
+ (d) => ListTile(
+ dense: true,
+ leading: Icon(FontAwesomeIcons.solidHardDrive,
+ color: state.isDiskHealthy(d)
+ ? Colors.grey
+ : Colors.red),
+ title: Text('${d.type!.toUpperCase()}: ${d.devPath}'),
+ subtitle: Text(
+ 'Usage: ${d.used} ${Renderers.formatSize(d.size ?? 0)}'),
+ trailing: IconButton(
+ icon: const Icon(
+ Icons.info,
+ ),
+ onPressed: () => showDialog(
+ context: context,
+ builder: (context) => SimpleDialog(
+ title: const Text('Details'),
+ contentPadding: const EdgeInsets.all(24),
+ children: <Widget>[
+ ListTile(
+ title: const Text("Device"),
+ subtitle: Text(d.devPath!),
+ ),
+ ListTile(
+ title: const Text("Type"),
+ subtitle: Text(d.type!),
+ ),
+ ListTile(
+ title: const Text("Usage"),
+ subtitle: Text(d.used!),
+ ),
+ ListTile(
+ title: const Text("GPT"),
+ subtitle: Text(d.gpt.toString()),
+ ),
+ ListTile(
+ title: const Text("Model"),
+ subtitle: Text(d.model!),
+ ),
+ ListTile(
+ title: const Text("Serial"),
+ subtitle: Text(d.serial!),
+ ),
+ ListTile(
+ title: const Text("S.M.A.R.T"),
+ subtitle: Text(d.health!),
+ ),
+ ListTile(
+ title: const Text("Wearout"),
+ subtitle: Text(d.wearoutPercentage),
+ )
+ ],
),
),
),
- )
- .toList()
- ..sort((a, b) => (a.title as Text)
- .data!
- .compareTo((b.title as Text).data!)),
- ),
- ],
- ),
+ ),
+ )
+ .toList()
+ ..sort((a, b) => (a.title as Text)
+ .data!
+ .compareTo((b.title as Text).data!)),
+ ),
+ ],
),
+ ),
);
},
);
diff --git a/lib/widgets/pve_qemu_options_widget.dart b/lib/widgets/pve_qemu_options_widget.dart
index 7ed0a3e..992a382 100644
--- a/lib/widgets/pve_qemu_options_widget.dart
+++ b/lib/widgets/pve_qemu_options_widget.dart
@@ -19,137 +19,137 @@ class PveQemuOptions extends StatelessWidget {
if (state.config != null) {
final config = state.config!;
return Scaffold(
- appBar: AppBar(
- leading: IconButton(
- icon: const Icon(Icons.close),
- onPressed: () => Navigator.of(context).pop(),
- ),
+ appBar: AppBar(
+ leading: IconButton(
+ icon: const Icon(Icons.close),
+ onPressed: () => Navigator.of(context).pop(),
),
- body: SingleChildScrollView(
- child: Form(
- key: _formKey,
- onChanged: () {},
- child: Column(
- children: <Widget>[
- ListTile(
- title: const Text("Name"),
- subtitle: Text(config.name ?? 'VM$guestID'),
- ),
- PveConfigSwitchListTile(
- title: const Text("Start on boot"),
- value: config.onboot,
- defaultValue: false,
- pending: config.getPending('onboot'),
- onChanged: (v) => bloc.events
- .add(UpdateQemuConfigBool('onboot', v)),
- onDeleted: () => bloc.events
- .add(RevertPendingQemuConfig('onboot')),
- ),
- ListTile(
- title: const Text("Start/Shutdown order"),
- subtitle: Text(config.startup ?? "Default (any)"),
- ),
- ListTile(
- title: const Text("OS Type"),
- subtitle: Text(config.ostype != null
- ? "${config.ostype!.type} ${config.ostype!.description}"
- : "Other"),
- ),
- //TODO add better ui component e.g. collapseable
- ListTile(
- title: const Text("Boot Device"),
- subtitle: Text(config.boot ?? 'Disk, Network, USB'),
- ),
- PveConfigSwitchListTile(
- title: const Text("Use tablet for pointer"),
- value: config.tablet,
- defaultValue: true,
- pending: config.getPending('tablet'),
- onChanged: (v) => bloc.events
- .add(UpdateQemuConfigBool('tablet', v)),
- onDeleted: () => bloc.events
- .add(RevertPendingQemuConfig('tablet')),
- ),
- ListTile(
- title: const Text("Hotplug"),
- subtitle: Text(config.hotplug ?? 'disk,network,usb'),
- ),
- PveConfigSwitchListTile(
- title: const Text("ACPI support"),
- value: config.acpi,
- defaultValue: true,
- pending: config.getPending('acpi'),
- onChanged: (v) =>
- bloc.events.add(UpdateQemuConfigBool('acpi', v)),
- onDeleted: () =>
- bloc.events.add(RevertPendingQemuConfig('acpi')),
- ),
- PveConfigSwitchListTile(
- title: const Text("KVM hardware virtualization"),
- value: config.kvm,
- defaultValue: true,
- pending: config.getPending('kvm'),
- onChanged: (v) =>
- bloc.events.add(UpdateQemuConfigBool('kvm', v)),
- onDeleted: () =>
- bloc.events.add(RevertPendingQemuConfig('kvm')),
- ),
- PveConfigSwitchListTile(
- title: const Text("Freeze CPU on startup"),
- value: config.freeze,
- defaultValue: false,
- pending: config.getPending('freeze'),
- onChanged: (v) => bloc.events
- .add(UpdateQemuConfigBool('freeze', v)),
- onDeleted: () => bloc.events
- .add(RevertPendingQemuConfig('freeze')),
- ),
- PveConfigSwitchListTile(
- title: const Text("Use local time for RTC"),
- value: config.localtime,
- defaultValue: false,
- pending: config.getPending('localtime'),
- onChanged: (v) => bloc.events
- .add(UpdateQemuConfigBool('localtime', v)),
- onDeleted: () => bloc.events
- .add(RevertPendingQemuConfig('localtime')),
- ),
- ListTile(
- title: const Text("RTC start date"),
- subtitle: Text(config.startdate ?? 'now'),
- ),
- ListTile(
- title: const Text("SMBIOS settings (type1)"),
- subtitle: Text(config.smbios1 ?? ''),
- ),
- //Todo enhance UI
- ListTile(
- title: const Text("QEMU Guest Agent"),
- subtitle: Text(config.agent ?? 'Default (disabled)'),
- ),
- PveConfigSwitchListTile(
- title: const Text("Protection"),
- value: config.protection,
- defaultValue: false,
- pending: config.getPending('protection'),
- onChanged: (v) => bloc.events
- .add(UpdateQemuConfigBool('protection', v)),
- onDeleted: () => bloc.events
- .add(RevertPendingQemuConfig('protection')),
- ),
- ListTile(
- title: const Text("Spice Enhancements"),
- subtitle: Text(
- config.spiceEnhancements ?? 'No enhancements'),
- ),
- ListTile(
- title: const Text("VM State Storage"),
- subtitle: Text(config.vmstatestorage ?? 'Automatic'),
- ),
- ],
- ),
+ ),
+ body: SingleChildScrollView(
+ child: Form(
+ key: _formKey,
+ onChanged: () {},
+ child: Column(
+ children: <Widget>[
+ ListTile(
+ title: const Text("Name"),
+ subtitle: Text(config.name ?? 'VM$guestID'),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("Start on boot"),
+ value: config.onboot,
+ defaultValue: false,
+ pending: config.getPending('onboot'),
+ onChanged: (v) =>
+ bloc.events.add(UpdateQemuConfigBool('onboot', v)),
+ onDeleted: () =>
+ bloc.events.add(RevertPendingQemuConfig('onboot')),
+ ),
+ ListTile(
+ title: const Text("Start/Shutdown order"),
+ subtitle: Text(config.startup ?? "Default (any)"),
+ ),
+ ListTile(
+ title: const Text("OS Type"),
+ subtitle: Text(config.ostype != null
+ ? "${config.ostype!.type} ${config.ostype!.description}"
+ : "Other"),
+ ),
+ //TODO add better ui component e.g. collapseable
+ ListTile(
+ title: const Text("Boot Device"),
+ subtitle: Text(config.boot ?? 'Disk, Network, USB'),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("Use tablet for pointer"),
+ value: config.tablet,
+ defaultValue: true,
+ pending: config.getPending('tablet'),
+ onChanged: (v) =>
+ bloc.events.add(UpdateQemuConfigBool('tablet', v)),
+ onDeleted: () =>
+ bloc.events.add(RevertPendingQemuConfig('tablet')),
+ ),
+ ListTile(
+ title: const Text("Hotplug"),
+ subtitle: Text(config.hotplug ?? 'disk,network,usb'),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("ACPI support"),
+ value: config.acpi,
+ defaultValue: true,
+ pending: config.getPending('acpi'),
+ onChanged: (v) =>
+ bloc.events.add(UpdateQemuConfigBool('acpi', v)),
+ onDeleted: () =>
+ bloc.events.add(RevertPendingQemuConfig('acpi')),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("KVM hardware virtualization"),
+ value: config.kvm,
+ defaultValue: true,
+ pending: config.getPending('kvm'),
+ onChanged: (v) =>
+ bloc.events.add(UpdateQemuConfigBool('kvm', v)),
+ onDeleted: () =>
+ bloc.events.add(RevertPendingQemuConfig('kvm')),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("Freeze CPU on startup"),
+ value: config.freeze,
+ defaultValue: false,
+ pending: config.getPending('freeze'),
+ onChanged: (v) =>
+ bloc.events.add(UpdateQemuConfigBool('freeze', v)),
+ onDeleted: () =>
+ bloc.events.add(RevertPendingQemuConfig('freeze')),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("Use local time for RTC"),
+ value: config.localtime,
+ defaultValue: false,
+ pending: config.getPending('localtime'),
+ onChanged: (v) => bloc.events
+ .add(UpdateQemuConfigBool('localtime', v)),
+ onDeleted: () => bloc.events
+ .add(RevertPendingQemuConfig('localtime')),
+ ),
+ ListTile(
+ title: const Text("RTC start date"),
+ subtitle: Text(config.startdate ?? 'now'),
+ ),
+ ListTile(
+ title: const Text("SMBIOS settings (type1)"),
+ subtitle: Text(config.smbios1 ?? ''),
+ ),
+ //Todo enhance UI
+ ListTile(
+ title: const Text("QEMU Guest Agent"),
+ subtitle: Text(config.agent ?? 'Default (disabled)'),
+ ),
+ PveConfigSwitchListTile(
+ title: const Text("Protection"),
+ value: config.protection,
+ defaultValue: false,
+ pending: config.getPending('protection'),
+ onChanged: (v) => bloc.events
+ .add(UpdateQemuConfigBool('protection', v)),
+ onDeleted: () => bloc.events
+ .add(RevertPendingQemuConfig('protection')),
+ ),
+ ListTile(
+ title: const Text("Spice Enhancements"),
+ subtitle:
+ Text(config.spiceEnhancements ?? 'No enhancements'),
+ ),
+ ListTile(
+ title: const Text("VM State Storage"),
+ subtitle: Text(config.vmstatestorage ?? 'Automatic'),
+ ),
+ ],
),
),
+ ),
);
}
return const Center(
diff --git a/lib/widgets/pve_qemu_overview.dart b/lib/widgets/pve_qemu_overview.dart
index 50f7382..15ab409 100644
--- a/lib/widgets/pve_qemu_overview.dart
+++ b/lib/widgets/pve_qemu_overview.dart
@@ -72,183 +72,176 @@ class PveQemuOverview extends StatelessWidget {
final rrdData = state.rrdData;
return Scaffold(
- appBar: PveAppBar(
- title: Text(config?.name ?? 'VM $guestID'),
+ appBar: PveAppBar(
+ title: Text(config?.name ?? 'VM $guestID'),
+ ),
+ backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
+ body: SingleChildScrollView(
+ child: Column(
+ children: <Widget>[
+ PveGuestOverviewHeader(
+ background: !(status?.template ?? false)
+ ? PveGuestHeaderRRDPageView(
+ rrdData: rrdData,
+ )
+ : const Center(
+ child: Text(
+ "TEMPLATE",
+ style: TextStyle(
+ color: Colors.white,
+ ),
+ ),
+ ),
+ width: width,
+ guestID: guestID,
+ guestStatus: status?.getQemuStatus(),
+ guestName: config?.name ?? 'VM $guestID',
+ guestNodeID: state.nodeID,
+ guestType: 'qemu',
+ ha: status?.ha,
+ template: status?.template ?? false,
),
- backgroundColor:
- Theme.of(context).colorScheme.surfaceContainer,
- body: SingleChildScrollView(
- child: Column(
- children: <Widget>[
- PveGuestOverviewHeader(
- background: !(status?.template ?? false)
- ? PveGuestHeaderRRDPageView(
- rrdData: rrdData,
- )
- : const Center(
- child: Text(
- "TEMPLATE",
- style: TextStyle(
- color: Colors.white,
- ),
+ ProxmoxStreamBuilder<PveTaskLogBloc, PveTaskLogState>(
+ bloc: taskBloc,
+ builder: (context, taskState) {
+ if (taskState.tasks.isNotEmpty) {
+ return PveTaskExpansionTile(
+ headerColor:
+ Theme.of(context).colorScheme.onSurfaceVariant,
+ task: taskState.tasks.first,
+ showMorePage: Provider<PveTaskLogBloc>(
+ create: (context) => PveTaskLogBloc(
+ apiClient: taskBloc.apiClient,
+ init: PveTaskLogState.init(state.nodeID),
+ )
+ ..events.add(
+ FilterTasksByGuestID(
+ guestID: guestID,
),
- ),
- width: width,
- guestID: guestID,
- guestStatus: status?.getQemuStatus(),
- guestName: config?.name ?? 'VM $guestID',
- guestNodeID: state.nodeID,
- guestType: 'qemu',
- ha: status?.ha,
- template: status?.template ?? false,
- ),
- ProxmoxStreamBuilder<PveTaskLogBloc, PveTaskLogState>(
- bloc: taskBloc,
- builder: (context, taskState) {
- if (taskState.tasks.isNotEmpty) {
- return PveTaskExpansionTile(
- headerColor: Theme.of(context)
- .colorScheme
- .onSurfaceVariant,
- task: taskState.tasks.first,
- showMorePage: Provider<PveTaskLogBloc>(
- create: (context) => PveTaskLogBloc(
- apiClient: taskBloc.apiClient,
- init: PveTaskLogState.init(state.nodeID),
- )
- ..events.add(
- FilterTasksByGuestID(
- guestID: guestID,
- ),
- )
- ..events.add(LoadTasks()),
- dispose: (context, bloc) => bloc.dispose(),
- child: const PveTaskLog(),
- ),
- );
- }
- return Container();
- },
+ )
+ ..events.add(LoadTasks()),
+ dispose: (context, bloc) => bloc.dispose(),
+ child: const PveTaskLog(),
+ ),
+ );
+ }
+ return Container();
+ },
+ ),
+ SizedBox(
+ height: 130,
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: <Widget>[
+ if (!(status?.template ?? false))
+ createActionCard(
+ 'Power Settings',
+ Icons.power_settings_new,
+ () => showPowerMenuBottomSheet(context, bloc)),
+ if (!(status?.template ?? false))
+ createActionCard(
+ 'Console',
+ Icons.queue_play_next,
+ () => showConsoleMenuBottomSheet(
+ context,
+ bloc.apiClient,
+ guestID,
+ state.nodeID,
+ 'qemu',
+ allowSpice: status?.spice ?? false,
+ )),
+ createActionCard(
+ 'Options',
+ Icons.settings,
+ () => Navigator.of(context)
+ .push(_createOptionsRoute(bloc))),
+ if (!rBloc.latestState.isStandalone)
+ createActionCard(
+ 'Migrate',
+ FontAwesomeIcons.paperPlane,
+ () => Navigator.of(context).push(
+ _createMigrationRoute(guestID, state.nodeID,
+ bloc.apiClient))),
+ createActionCard(
+ 'Backup',
+ FontAwesomeIcons.floppyDisk,
+ () => Navigator.of(context).push(
+ _createBackupRoute(
+ guestID, state.nodeID, bloc.apiClient))),
+ ],
),
- SizedBox(
- height: 130,
- child: SingleChildScrollView(
- scrollDirection: Axis.horizontal,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: <Widget>[
- if (!(status?.template ?? false))
- createActionCard(
- 'Power Settings',
- Icons.power_settings_new,
- () => showPowerMenuBottomSheet(
- context, bloc)),
- if (!(status?.template ?? false))
- createActionCard(
- 'Console',
- Icons.queue_play_next,
- () => showConsoleMenuBottomSheet(
- context,
- bloc.apiClient,
- guestID,
- state.nodeID,
- 'qemu',
- allowSpice: status?.spice ?? false,
- )),
- createActionCard(
- 'Options',
- Icons.settings,
- () => Navigator.of(context)
- .push(_createOptionsRoute(bloc))),
- if (!rBloc.latestState.isStandalone)
- createActionCard(
- 'Migrate',
- FontAwesomeIcons.paperPlane,
- () => Navigator.of(context).push(
- _createMigrationRoute(guestID,
- state.nodeID, bloc.apiClient))),
- createActionCard(
- 'Backup',
- FontAwesomeIcons.floppyDisk,
- () => Navigator.of(context).push(
- _createBackupRoute(guestID, state.nodeID,
- bloc.apiClient))),
- ],
+ ),
+ ),
+ if (config != null)
+ PveResourceDataCardWidget(
+ expandable: false,
+ title: const Text(
+ 'Hardware',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 20,
),
),
- ),
- if (config != null)
- PveResourceDataCardWidget(
- expandable: false,
- title: const Text(
- 'Hardware',
- style: TextStyle(
- fontWeight: FontWeight.bold,
- fontSize: 20,
- ),
+ children: [
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.memory),
+ title: Text('${config.memory}'),
+ subtitle: const Text('Memory'),
+ dense: true,
+ ),
+ ListTile(
+ leading: const Icon(Icons.memory),
+ title: Text(
+ '${config.cores} Cores ${config.sockets} Socket'),
+ subtitle: const Text('Processor'),
+ dense: true,
+ ),
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.microchip),
+ title:
+ Text(config.bios?.name ?? 'Default (SeaBIOS)'),
+ subtitle: const Text('BIOS'),
+ dense: true,
+ ),
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.gears),
+ dense: true,
+ title: Text(config.machine ?? 'Default (i440fx)'),
+ subtitle: const Text('Machine Type'),
+ ),
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.database),
+ title:
+ Text(config.scsihw?.name ?? 'Default (i440fx)'),
+ subtitle: const Text('SCSI Controller'),
+ dense: true,
+ ),
+ for (var ide in config.ide!)
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.compactDisc),
+ title: Text(ide),
+ subtitle: const Text('CD/DVD Drive'),
+ dense: true,
),
- children: [
- ListTile(
- leading: const Icon(FontAwesomeIcons.memory),
- title: Text('${config.memory}'),
- subtitle: const Text('Memory'),
- dense: true,
- ),
- ListTile(
- leading: const Icon(Icons.memory),
- title: Text(
- '${config.cores} Cores ${config.sockets} Socket'),
- subtitle: const Text('Processor'),
- dense: true,
- ),
- ListTile(
- leading: const Icon(FontAwesomeIcons.microchip),
- title: Text(
- config.bios?.name ?? 'Default (SeaBIOS)'),
- subtitle: const Text('BIOS'),
- dense: true,
- ),
- ListTile(
- leading: const Icon(FontAwesomeIcons.gears),
- dense: true,
- title:
- Text(config.machine ?? 'Default (i440fx)'),
- subtitle: const Text('Machine Type'),
- ),
- ListTile(
- leading: const Icon(FontAwesomeIcons.database),
- title: Text(
- config.scsihw?.name ?? 'Default (i440fx)'),
- subtitle: const Text('SCSI Controller'),
- dense: true,
- ),
- for (var ide in config.ide!)
- ListTile(
- leading:
- const Icon(FontAwesomeIcons.compactDisc),
- title: Text(ide),
- subtitle: const Text('CD/DVD Drive'),
- dense: true,
- ),
- for (var scsi in config.scsi!)
- ListTile(
- leading:
- const Icon(FontAwesomeIcons.hardDrive),
- title: Text(scsi),
- subtitle: const Text('Hard Disk'),
- dense: true,
- ),
- for (var net in config.net!)
- ListTile(
- leading:
- const Icon(FontAwesomeIcons.ethernet),
- dense: true,
- subtitle: const Text('Network Device'),
- title: Text(net),
- )
- ]),
- ],
- )),
+ for (var scsi in config.scsi!)
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.hardDrive),
+ title: Text(scsi),
+ subtitle: const Text('Hard Disk'),
+ dense: true,
+ ),
+ for (var net in config.net!)
+ ListTile(
+ leading: const Icon(FontAwesomeIcons.ethernet),
+ dense: true,
+ subtitle: const Text('Network Device'),
+ title: Text(net),
+ )
+ ]),
+ ],
+ )),
);
}),
);
diff --git a/lib/widgets/pve_task_log_widget.dart b/lib/widgets/pve_task_log_widget.dart
index 7efb522..292e499 100644
--- a/lib/widgets/pve_task_log_widget.dart
+++ b/lib/widgets/pve_task_log_widget.dart
@@ -37,126 +37,126 @@ class _PveTaskLogState extends State<PveTaskLog> {
bloc: bloc,
builder: (context, state) {
return Scaffold(
- key: _scaffoldKey,
- appBar: AppBar(
- leading: IconButton(
- icon: const Icon(Icons.close),
- onPressed: () => Navigator.of(context).pop(),
- ),
- actions: <Widget>[
- IconButton(
- icon: const Icon(Icons.more_vert),
- onPressed: () => _scaffoldKey.currentState?.openEndDrawer(),
- )
- ],
+ key: _scaffoldKey,
+ appBar: AppBar(
+ leading: IconButton(
+ icon: const Icon(Icons.close),
+ onPressed: () => Navigator.of(context).pop(),
),
- endDrawer: Drawer(
+ actions: <Widget>[
+ IconButton(
+ icon: const Icon(Icons.more_vert),
+ onPressed: () => _scaffoldKey.currentState?.openEndDrawer(),
+ )
+ ],
+ ),
+ endDrawer: Drawer(
child: SafeArea(
- child: Padding(
- padding: const EdgeInsets.fromLTRB(16.0, 20.0, 16.0, 0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Text(
- 'Filters',
- style: Theme.of(context).textTheme.headlineSmall,
- ),
- const SizedBox(
- height: 20,
- ),
- TextFormField(
- decoration: const InputDecoration(
- labelText: 'by user',
- filled: true,
- prefixIcon: Icon(Icons.person)),
- onChanged: (newValue) {
- bloc.events.add(FilterTasksByUser(newValue));
- bloc.events.add(LoadTasks());
- },
- controller: _userFilterController,
- ),
- const SizedBox(
- height: 20,
- ),
- TextFormField(
- decoration: const InputDecoration(
- labelText: 'by type',
- filled: true,
- prefixIcon: Icon(Icons.description)),
- onChanged: (newValue) {
- bloc.events.add(FilterTasksByType(newValue));
- bloc.events.add(LoadTasks());
- },
- controller: _typeFilterController,
- ),
- const SizedBox(
- height: 20,
- ),
- DropdownButtonFormField<String>(
- decoration: const InputDecoration(labelText: 'Source'),
- value: state.source,
- icon: const Icon(Icons.arrow_downward),
- iconSize: 24,
- elevation: 16,
- onChanged: (String? newValue) {
- bloc.events.add(FilterTasksBySource(newValue));
- bloc.events.add(LoadTasks());
- },
- items: <String>[
- 'all',
- 'active',
- 'archive',
- ].map<DropdownMenuItem<String>>((String value) {
- return DropdownMenuItem<String>(
- value: value,
- child: Text(value),
- );
- }).toList(),
- ),
- const SizedBox(
- height: 20,
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(16.0, 20.0, 16.0, 0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: <Widget>[
+ Text(
+ 'Filters',
+ style: Theme.of(context).textTheme.headlineSmall,
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ TextFormField(
+ decoration: const InputDecoration(
+ labelText: 'by user',
+ filled: true,
+ prefixIcon: Icon(Icons.person)),
+ onChanged: (newValue) {
+ bloc.events.add(FilterTasksByUser(newValue));
+ bloc.events.add(LoadTasks());
+ },
+ controller: _userFilterController,
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ TextFormField(
+ decoration: const InputDecoration(
+ labelText: 'by type',
+ filled: true,
+ prefixIcon: Icon(Icons.description)),
+ onChanged: (newValue) {
+ bloc.events.add(FilterTasksByType(newValue));
+ bloc.events.add(LoadTasks());
+ },
+ controller: _typeFilterController,
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ DropdownButtonFormField<String>(
+ decoration: const InputDecoration(labelText: 'Source'),
+ value: state.source,
+ icon: const Icon(Icons.arrow_downward),
+ iconSize: 24,
+ elevation: 16,
+ onChanged: (String? newValue) {
+ bloc.events.add(FilterTasksBySource(newValue));
+ bloc.events.add(LoadTasks());
+ },
+ items: <String>[
+ 'all',
+ 'active',
+ 'archive',
+ ].map<DropdownMenuItem<String>>((String value) {
+ return DropdownMenuItem<String>(
+ value: value,
+ child: Text(value),
+ );
+ }).toList(),
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ FormField(
+ builder: (FormFieldState<bool> formFieldState) => Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: <Widget>[
+ const Text("Only errors"),
+ Checkbox(
+ value: state.onlyErrors,
+ onChanged: (value) {
+ formFieldState.didChange(value);
+ bloc.events.add(FilterTasksByError());
+ bloc.events.add(LoadTasks());
+ },
+ ),
+ ],
),
- FormField(
- builder: (FormFieldState<bool> formFieldState) => Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- const Text("Only errors"),
- Checkbox(
- value: state.onlyErrors,
- onChanged: (value) {
- formFieldState.didChange(value);
- bloc.events.add(FilterTasksByError());
- bloc.events.add(LoadTasks());
- },
- ),
- ],
- ),
- )
- ],
- ),
+ )
+ ],
),
- )),
- body: NotificationListener<ScrollNotification>(
- onNotification: (ScrollNotification scrollInfo) {
- if (scrollInfo.metrics.pixels >=
- (0.8 * scrollInfo.metrics.maxScrollExtent)) {
- if (!state.isLoading) {
- bloc.events.add(LoadMoreTasks());
- }
+ ),
+ )),
+ body: NotificationListener<ScrollNotification>(
+ onNotification: (ScrollNotification scrollInfo) {
+ if (scrollInfo.metrics.pixels >=
+ (0.8 * scrollInfo.metrics.maxScrollExtent)) {
+ if (!state.isLoading) {
+ bloc.events.add(LoadMoreTasks());
}
- return false;
- },
- child: state.tasks.isNotEmpty
- ? ListView.builder(
- itemCount: state.tasks.length,
- itemBuilder: (context, index) => PveTaskExpansionTile(
- task: state.tasks[index],
- ),
- )
- : const Center(
- child: Text("No tasks found"),
+ }
+ return false;
+ },
+ child: state.tasks.isNotEmpty
+ ? ListView.builder(
+ itemCount: state.tasks.length,
+ itemBuilder: (context, index) => PveTaskExpansionTile(
+ task: state.tasks[index],
),
- ),
+ )
+ : const Center(
+ child: Text("No tasks found"),
+ ),
+ ),
);
});
}
--
2.50.1
More information about the pve-devel
mailing list