public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused`
@ 2025-06-02 13:37 Shan Shaji
  2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 1/2] refactor: move and split the `_MobileResourceFilterSheet` widget Shan Shaji
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Shan Shaji @ 2025-06-02 13:37 UTC (permalink / raw)
  To: pve-devel

This patch series includes the fix for guest missing when the status 
is `paused`. Additionaly the series also includes the changes from 
another patch which can be found here: 

https://lore.proxmox.com/pve-devel/20250522130825.79862-1-s.shaji@proxmox.com/

pve_flutter_frontend:

Shan Shaji (2):
  refactor: move and split the `_MobileResourceFilterSheet` widget
  fix: ui: guests missing in resources tab when status is `paused`

 lib/pages/main_layout_slim.dart               | 175 +--------------
 .../pve_mobile_resource_filter_sheet.dart     | 202 ++++++++++++++++++
 2 files changed, 204 insertions(+), 173 deletions(-)
 create mode 100644 lib/widgets/pve_mobile_resource_filter_sheet.dart


proxmox_dart_api_client:

Shan Shaji (1):
  fix: ui: add missing `paused` status check

 lib/src/models/pve_cluster_resources_model.dart | 2 ++
 1 file changed, 2 insertions(+)


Summary over all repositories:
  3 files changed, 206 insertions(+), 173 deletions(-)

-- 
Generated by git-murpp 0.8.1


_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] [PATCH pve_flutter_frontend v2 1/2] refactor: move and split the `_MobileResourceFilterSheet` widget
  2025-06-02 13:37 [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Shan Shaji
@ 2025-06-02 13:37 ` Shan Shaji
  2025-06-03  8:10   ` Michael Köppl
  2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 2/2] fix: ui: guests missing in resources tab when status is `paused` Shan Shaji
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Shan Shaji @ 2025-06-02 13:37 UTC (permalink / raw)
  To: pve-devel

This patch splits the `_MobileResourceFilterSheet` into multiple widgets
and since the `main_layout_slim.dart` file is large, the widget has been
moved to it's own file under the widgets folder.

Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
---
 
 changes since v1:
 * Removed all formatting changes.
 * Only includes the refactoring of `_MobileResourceFilterSheet` widget. 
 * Moved "paused guest not showing in resources tab" bug to another patch. 
 
 lib/pages/main_layout_slim.dart               | 175 +---------------
 .../pve_mobile_resource_filter_sheet.dart     | 188 ++++++++++++++++++
 2 files changed, 190 insertions(+), 173 deletions(-)
 create mode 100644 lib/widgets/pve_mobile_resource_filter_sheet.dart

diff --git a/lib/pages/main_layout_slim.dart b/lib/pages/main_layout_slim.dart
index 3bcd83b..8d6e5ed 100644
--- a/lib/pages/main_layout_slim.dart
+++ b/lib/pages/main_layout_slim.dart
@@ -11,6 +11,7 @@ import 'package:pve_flutter_frontend/bloc/pve_cluster_status_bloc.dart';
 import 'package:pve_flutter_frontend/bloc/pve_file_selector_bloc.dart';
 import 'package:pve_flutter_frontend/bloc/pve_resource_bloc.dart';
 import 'package:pve_flutter_frontend/bloc/pve_storage_selector_bloc.dart';
+import 'package:pve_flutter_frontend/widgets/pve_mobile_resource_filter_sheet.dart';
 import 'package:pve_flutter_frontend/states/pve_access_management_state.dart';
 import 'package:pve_flutter_frontend/states/pve_cluster_status_state.dart';
 import 'package:pve_flutter_frontend/states/pve_file_selector_state.dart';
@@ -606,7 +607,7 @@ class MobileResourceOverview extends StatelessWidget {
           },
           child: ColoredSafeArea(
               child: Scaffold(
-            endDrawer: _MobileResourceFilterSheet(),
+            endDrawer: PveMobileResourceFilterSheet(),
             appBar: AppBar(
               automaticallyImplyLeading: false,
               elevation: 0,
@@ -844,178 +845,6 @@ class _AppbarSearchTextFieldState extends State<AppbarSearchTextField> {
   }
 }
 
-class _MobileResourceFilterSheet extends StatelessWidget {
-  @override
-  Widget build(BuildContext context) {
-    final rBloc = Provider.of<PveResourceBloc>(context);
-
-    return ProxmoxStreamBuilder<PveResourceBloc, PveResourceState>(
-      bloc: rBloc,
-      builder: (context, state) => Drawer(
-        child: SingleChildScrollView(
-          child: Column(
-            crossAxisAlignment: CrossAxisAlignment.start,
-            children: <Widget>[
-              Padding(
-                padding: const EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 0),
-                child: ListTile(
-                  title: const Text(
-                    'Filter Results',
-                  ),
-                  trailing: rBloc.isFiltered
-                      ? TextButton(
-                          onPressed: () => rBloc.events.add(ResetFilter()),
-                          child: Text(
-                            'Reset',
-                            style: TextStyle(
-                              color: Theme.of(context).colorScheme.secondary,
-                            ),
-                          ),
-                        )
-                      : null,
-                ),
-              ),
-              const Divider(
-                indent: 0,
-                endIndent: 0,
-              ),
-              Padding(
-                padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0),
-                child: Column(
-                  children: [
-                    const ListTile(
-                      title: Text(
-                        'Type',
-                        style: TextStyle(fontWeight: FontWeight.bold),
-                      ),
-                    ),
-                    CheckboxListTile(
-                      dense: true,
-                      title: Text(
-                        'Nodes',
-                        style: TextStyle(
-                            color: Theme.of(context)
-                                .colorScheme
-                                .onSurface
-                                .withValues(alpha: 0.75)),
-                      ),
-                      value: state.typeFilter.contains('node'),
-                      onChanged: (v) => rBloc.events.add(FilterResources(
-                        typeFilter: addOrRemove(v!, 'node', state.typeFilter),
-                      )),
-                    ),
-                    CheckboxListTile(
-                      dense: true,
-                      title: Text(
-                        'Qemu',
-                        style: TextStyle(
-                            color: Theme.of(context)
-                                .colorScheme
-                                .onSurface
-                                .withValues(alpha: 0.75)),
-                      ),
-                      value: state.typeFilter.contains('qemu'),
-                      onChanged: (v) => rBloc.events.add(FilterResources(
-                        typeFilter: addOrRemove(v!, 'qemu', state.typeFilter),
-                      )),
-                    ),
-                    CheckboxListTile(
-                      dense: true,
-                      title: Text(
-                        'LXC',
-                        style: TextStyle(
-                            color: Theme.of(context)
-                                .colorScheme
-                                .onSurface
-                                .withValues(alpha: 0.75)),
-                      ),
-                      value: state.typeFilter.contains('lxc'),
-                      onChanged: (v) => rBloc.events.add(FilterResources(
-                        typeFilter: addOrRemove(v!, 'lxc', state.typeFilter),
-                      )),
-                    ),
-                    CheckboxListTile(
-                      dense: true,
-                      title: Text(
-                        'Storage',
-                        style: TextStyle(
-                            color: Theme.of(context)
-                                .colorScheme
-                                .onSurface
-                                .withValues(alpha: 0.75)),
-                      ),
-                      value: state.typeFilter.contains('storage'),
-                      onChanged: (v) => rBloc.events.add(FilterResources(
-                        typeFilter:
-                            addOrRemove(v!, 'storage', state.typeFilter),
-                      )),
-                    ),
-                  ],
-                ),
-              ),
-              Padding(
-                padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0),
-                child: Column(
-                  children: [
-                    const ListTile(
-                      title: Text(
-                        'Status',
-                        style: TextStyle(fontWeight: FontWeight.bold),
-                      ),
-                    ),
-                    CheckboxListTile(
-                      dense: true,
-                      title: Text(
-                        'Online',
-                        style: TextStyle(
-                            color: Theme.of(context)
-                                .colorScheme
-                                .onSurface
-                                .withValues(alpha: 0.75)),
-                      ),
-                      value: state.statusFilter
-                          .contains(PveResourceStatusType.running),
-                      onChanged: (v) => rBloc.events.add(FilterResources(
-                        statusFilter: addOrRemove(v!,
-                            PveResourceStatusType.running, state.statusFilter),
-                      )),
-                    ),
-                    CheckboxListTile(
-                      dense: true,
-                      title: Text(
-                        'Offline',
-                        style: TextStyle(
-                            color: Theme.of(context)
-                                .colorScheme
-                                .onSurface
-                                .withValues(alpha: 0.75)),
-                      ),
-                      value: state.statusFilter
-                          .contains(PveResourceStatusType.stopped),
-                      onChanged: (v) => rBloc.events.add(FilterResources(
-                        statusFilter: addOrRemove(v!,
-                            PveResourceStatusType.stopped, state.statusFilter),
-                      )),
-                    ),
-                  ],
-                ),
-              )
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-
-  BuiltSet<S> addOrRemove<S>(bool value, S element, BuiltSet<S> filter) {
-    if (value) {
-      return filter.rebuild((b) => b..add(element));
-    } else {
-      return filter.rebuild((b) => b..remove(element));
-    }
-  }
-}
-
 class AppBarFilterIconButton extends StatelessWidget {
   const AppBarFilterIconButton({super.key});
 
diff --git a/lib/widgets/pve_mobile_resource_filter_sheet.dart b/lib/widgets/pve_mobile_resource_filter_sheet.dart
new file mode 100644
index 0000000..cee3a49
--- /dev/null
+++ b/lib/widgets/pve_mobile_resource_filter_sheet.dart
@@ -0,0 +1,188 @@
+import 'package:built_collection/built_collection.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:proxmox_dart_api_client/proxmox_dart_api_client.dart';
+import 'package:pve_flutter_frontend/bloc/pve_resource_bloc.dart';
+import 'package:pve_flutter_frontend/states/pve_resource_state.dart';
+import 'package:pve_flutter_frontend/widgets/proxmox_stream_builder_widget.dart';
+
+class PveMobileResourceFilterSheet extends StatelessWidget {
+  const PveMobileResourceFilterSheet({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    final rBloc = Provider.of<PveResourceBloc>(context);
+    return ProxmoxStreamBuilder<PveResourceBloc, PveResourceState>(
+      bloc: rBloc,
+      builder: (context, state) => Drawer(
+        child: SingleChildScrollView(
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Padding(
+                padding: const EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 0),
+                child: ListTile(
+                  title: const Text(
+                    'Filter Results',
+                  ),
+                  trailing: rBloc.isFiltered
+                      ? TextButton(
+                          onPressed: () => rBloc.events.add(ResetFilter()),
+                          child: Text(
+                            'Reset',
+                            style: TextStyle(
+                              color: Theme.of(context).colorScheme.secondary,
+                            ),
+                          ),
+                        )
+                      : null,
+                ),
+              ),
+              const Divider(indent: 0, endIndent: 0),
+              _PveFilterSheetSection(
+                sectionTitle: 'Type',
+                items: [
+                  _ProxmoxResourceFilterListTile(
+                    title: 'Nodes',
+                    value: state.typeFilter.contains('node'),
+                    onChanged: (v) => rBloc.events.add(
+                      FilterResources(
+                        typeFilter: _addOrRemove(v!, 'node', state.typeFilter),
+                      ),
+                    ),
+                  ),
+                  _ProxmoxResourceFilterListTile(
+                    title: 'Qemu',
+                    value: state.typeFilter.contains('qemu'),
+                    onChanged: (v) => rBloc.events.add(
+                      FilterResources(
+                        typeFilter: _addOrRemove(v!, 'qemu', state.typeFilter),
+                      ),
+                    ),
+                  ),
+                  _ProxmoxResourceFilterListTile(
+                    title: 'LXC',
+                    value: state.typeFilter.contains('lxc'),
+                    onChanged: (v) => rBloc.events.add(
+                      FilterResources(
+                        typeFilter: _addOrRemove(v!, 'lxc', state.typeFilter),
+                      ),
+                    ),
+                  ),
+                  _ProxmoxResourceFilterListTile(
+                    title: 'Storage',
+                    value: state.typeFilter.contains('storage'),
+                    onChanged: (v) => rBloc.events.add(
+                      FilterResources(
+                        typeFilter:
+                            _addOrRemove(v!, 'storage', state.typeFilter),
+                      ),
+                    ),
+                  ),
+                ],
+              ),
+              _PveFilterSheetSection(
+                sectionTitle: 'Status',
+                items: [
+                  _ProxmoxResourceFilterListTile(
+                    title: 'Online',
+                    value: state.statusFilter
+                        .contains(PveResourceStatusType.running),
+                    onChanged: (v) => rBloc.events.add(
+                      FilterResources(
+                        statusFilter: _addOrRemove(
+                          v!,
+                          PveResourceStatusType.running,
+                          state.statusFilter,
+                        ),
+                      ),
+                    ),
+                  ),
+                  _ProxmoxResourceFilterListTile(
+                    title: 'Offline',
+                    value: state.statusFilter
+                        .contains(PveResourceStatusType.stopped),
+                    onChanged: (v) => rBloc.events.add(
+                      FilterResources(
+                        statusFilter: _addOrRemove(
+                          v!,
+                          PveResourceStatusType.stopped,
+                          state.statusFilter,
+                        ),
+                      ),
+                    ),
+                  ),
+                ],
+              )
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  BuiltSet<S> _addOrRemove<S>(bool value, S element, BuiltSet<S> filter) {
+    if (value) {
+      return filter.rebuild((b) => b..add(element));
+    } else {
+      return filter.rebuild((b) => b..remove(element));
+    }
+  }
+}
+
+class _PveFilterSheetSection extends StatelessWidget {
+  const _PveFilterSheetSection({
+    required this.items,
+    required this.sectionTitle,
+  });
+
+  final List<Widget> items;
+  final String sectionTitle;
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(horizontal: 8),
+      child: Column(
+        children: [
+          ListTile(
+            title: Text(
+              sectionTitle,
+              style: TextStyle(fontWeight: FontWeight.bold),
+            ),
+          ),
+          ...items,
+        ],
+      ),
+    );
+  }
+}
+
+class _ProxmoxResourceFilterListTile extends StatelessWidget {
+  const _ProxmoxResourceFilterListTile({
+    required this.title,
+    this.onChanged,
+    this.value,
+  });
+
+  final String title;
+  final ValueChanged<bool?>? onChanged;
+  final bool? value;
+
+  @override
+  Widget build(BuildContext context) {
+    return CheckboxListTile(
+      dense: true,
+      title: Text(
+        title,
+        style: TextStyle(
+          color: Theme.of(context).colorScheme.onSurface.withValues(
+                alpha: 0.75,
+              ),
+        ),
+      ),
+      value: value,
+      onChanged: onChanged,
+    );
+  }
+}
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] [PATCH pve_flutter_frontend v2 2/2] fix: ui: guests missing in resources tab when status is `paused`
  2025-06-02 13:37 [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Shan Shaji
  2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 1/2] refactor: move and split the `_MobileResourceFilterSheet` widget Shan Shaji
@ 2025-06-02 13:37 ` Shan Shaji
  2025-06-03  8:02   ` Michael Köppl
  2025-06-02 13:37 ` [pve-devel] [PATCH proxmox_dart_api_client v2 1/1] fix: ui: add missing `paused` status check Shan Shaji
  2025-06-03  8:15 ` [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Michael Köppl
  3 siblings, 1 reply; 8+ messages in thread
From: Shan Shaji @ 2025-06-02 13:37 UTC (permalink / raw)
  To: pve-devel

When the guest status is set to `paused` the guest was not showing in
the resources tab. Also there were no option in the resources
filter to select the `paused` status under the status section.

This commit fixes the issue by adding the `paused` status under the
status section in the resources filter sheet.

Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
---
 
 changes since v1:
 * Removed all formatting changes. 
 * New `paused` status option is added after refactoring the filter sheet. 
 
 lib/widgets/pve_mobile_resource_filter_sheet.dart | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/lib/widgets/pve_mobile_resource_filter_sheet.dart b/lib/widgets/pve_mobile_resource_filter_sheet.dart
index cee3a49..c09b2cf 100644
--- a/lib/widgets/pve_mobile_resource_filter_sheet.dart
+++ b/lib/widgets/pve_mobile_resource_filter_sheet.dart
@@ -112,6 +112,20 @@ class PveMobileResourceFilterSheet extends StatelessWidget {
                       ),
                     ),
                   ),
+                  _ProxmoxResourceFilterListTile(
+                    title: 'Paused',
+                    value: state.statusFilter
+                        .contains(PveResourceStatusType.paused),
+                    onChanged: (v) => rBloc.events.add(
+                      FilterResources(
+                        statusFilter: _addOrRemove(
+                          v!,
+                          PveResourceStatusType.paused,
+                          state.statusFilter,
+                        ),
+                      ),
+                    ),
+                  ),
                 ],
               )
             ],
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] [PATCH proxmox_dart_api_client v2 1/1] fix: ui: add missing `paused` status check
  2025-06-02 13:37 [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Shan Shaji
  2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 1/2] refactor: move and split the `_MobileResourceFilterSheet` widget Shan Shaji
  2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 2/2] fix: ui: guests missing in resources tab when status is `paused` Shan Shaji
@ 2025-06-02 13:37 ` Shan Shaji
  2025-06-03  8:15 ` [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Michael Köppl
  3 siblings, 0 replies; 8+ messages in thread
From: Shan Shaji @ 2025-06-02 13:37 UTC (permalink / raw)
  To: pve-devel

The `getStatus` function was not returning the corresponding
`PveResourceStatusType` when the status was `paused`. This commit adds
the missing status check.

Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
---
 
 changes since v1:
 * Removed all formatting changes

 lib/src/models/pve_cluster_resources_model.dart | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/src/models/pve_cluster_resources_model.dart b/lib/src/models/pve_cluster_resources_model.dart
index 16e18df..b92c1ef 100644
--- a/lib/src/models/pve_cluster_resources_model.dart
+++ b/lib/src/models/pve_cluster_resources_model.dart
@@ -69,6 +69,8 @@ abstract class PveClusterResourcesModel
       return PveResourceStatusType.stopped;
     }
 
+    if(status == 'paused') return PveResourceStatusType.paused;
+
     return PveResourceStatusType.unknown;
   }
 }
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [pve-devel] [PATCH pve_flutter_frontend v2 2/2] fix: ui: guests missing in resources tab when status is `paused`
  2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 2/2] fix: ui: guests missing in resources tab when status is `paused` Shan Shaji
@ 2025-06-03  8:02   ` Michael Köppl
  0 siblings, 0 replies; 8+ messages in thread
From: Michael Köppl @ 2025-06-03  8:02 UTC (permalink / raw)
  To: Proxmox VE development discussion, Shan Shaji

On 6/2/25 15:37, Shan Shaji wrote:
> When the guest status is set to `paused` the guest was not showing in
> the resources tab. Also there were no option in the resources
> filter to select the `paused` status under the status section.

The first sentence confused me a bit. The resource tab seems to show the
guest for me, but displays its status as "Unknown". That is fixed by the
following patch. This patch "only" adds the filter. I think a commit
message like "resources: add filter option for paused guest status"
would be more appropriate.

> 
> This commit fixes the issue by adding the `paused` status under the
> status section in the resources filter sheet.

nit: the commit message should not contain "This commit...".


> 
> Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
> ---
>  
>  changes since v1:
>  * Removed all formatting changes. 
>  * New `paused` status option is added after refactoring the filter sheet. 
>  
>  lib/widgets/pve_mobile_resource_filter_sheet.dart | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/lib/widgets/pve_mobile_resource_filter_sheet.dart b/lib/widgets/pve_mobile_resource_filter_sheet.dart
> index cee3a49..c09b2cf 100644
> --- a/lib/widgets/pve_mobile_resource_filter_sheet.dart
> +++ b/lib/widgets/pve_mobile_resource_filter_sheet.dart
> @@ -112,6 +112,20 @@ class PveMobileResourceFilterSheet extends StatelessWidget {
>                        ),
>                      ),
>                    ),
> +                  _ProxmoxResourceFilterListTile(
> +                    title: 'Paused',
> +                    value: state.statusFilter
> +                        .contains(PveResourceStatusType.paused),
> +                    onChanged: (v) => rBloc.events.add(
> +                      FilterResources(
> +                        statusFilter: _addOrRemove(
> +                          v!,
> +                          PveResourceStatusType.paused,
> +                          state.statusFilter,
> +                        ),
> +                      ),
> +                    ),
> +                  ),

Could make sense to do something like this:
_PveFilterSheetSection(
  sectionTitle: 'Status',
  items: [
    for (var statusFilterItem in [
      ('Online', PveResourceStatusType.running),
      ('Offline', PveResourceStatusType.stopped),
      ('Paused', PveResourceStatusType.paused),
    ]) _ProxmoxResourceFilterListTile(
      title: statusFilterItem.$1,
      value: state.statusFilter
          .contains(statusFilterItem.$2),
      onChanged: (v) => rBloc.events.add(
        FilterResources(
          statusFilter: _addOrRemove(
            v!,
            statusFilterItem.$2,
            state.statusFilter,
          ),
        ),
      ),
    ),
  ],
)

instead of copying the entire _ProxmoxResourceFilterListTile every time
we want to add another status as a filter. Not directly related to this
patch, just a suggestion. If you do send a v3 including this, it should
probably be a separate patch.

>                  ],
>                )
>              ],




_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [pve-devel] [PATCH pve_flutter_frontend v2 1/2] refactor: move and split the `_MobileResourceFilterSheet` widget
  2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 1/2] refactor: move and split the `_MobileResourceFilterSheet` widget Shan Shaji
@ 2025-06-03  8:10   ` Michael Köppl
  0 siblings, 0 replies; 8+ messages in thread
From: Michael Köppl @ 2025-06-03  8:10 UTC (permalink / raw)
  To: Proxmox VE development discussion, Shan Shaji

I think it's a good change. The MainLayoutSlim class is already more
than big enough.

On 6/2/25 15:37, Shan Shaji wrote:
> This patch splits the `_MobileResourceFilterSheet` into multiple widgets
> and since the `main_layout_slim.dart` file is large, the widget has been
> moved to it's own file under the widgets folder.

nit: commit message should not contain "This patch..."
also: s/it's/its

> 
> Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
> ---
>  
>  changes since v1:
>  * Removed all formatting changes.
>  * Only includes the refactoring of `_MobileResourceFilterSheet` widget. 
>  * Moved "paused guest not showing in resources tab" bug to another patch. 
>  
>  lib/pages/main_layout_slim.dart               | 175 +---------------
>  .../pve_mobile_resource_filter_sheet.dart     | 188 ++++++++++++++++++
>  2 files changed, 190 insertions(+), 173 deletions(-)
>  create mode 100644 lib/widgets/pve_mobile_resource_filter_sheet.dart
> 
> diff --git a/lib/pages/main_layout_slim.dart b/lib/pages/main_layout_slim.dart
> index 3bcd83b..8d6e5ed 100644
> --- a/lib/pages/main_layout_slim.dart
> +++ b/lib/pages/main_layout_slim.dart
> @@ -11,6 +11,7 @@ import 'package:pve_flutter_frontend/bloc/pve_cluster_status_bloc.dart';
>  import 'package:pve_flutter_frontend/bloc/pve_file_selector_bloc.dart';
>  import 'package:pve_flutter_frontend/bloc/pve_resource_bloc.dart';
>  import 'package:pve_flutter_frontend/bloc/pve_storage_selector_bloc.dart';
> +import 'package:pve_flutter_frontend/widgets/pve_mobile_resource_filter_sheet.dart';
>  import 'package:pve_flutter_frontend/states/pve_access_management_state.dart';
>  import 'package:pve_flutter_frontend/states/pve_cluster_status_state.dart';
>  import 'package:pve_flutter_frontend/states/pve_file_selector_state.dart';
> @@ -606,7 +607,7 @@ class MobileResourceOverview extends StatelessWidget {
>            },
>            child: ColoredSafeArea(
>                child: Scaffold(
> -            endDrawer: _MobileResourceFilterSheet(),
> +            endDrawer: PveMobileResourceFilterSheet(),
>              appBar: AppBar(
>                automaticallyImplyLeading: false,
>                elevation: 0,
> @@ -844,178 +845,6 @@ class _AppbarSearchTextFieldState extends State<AppbarSearchTextField> {
>    }
>  }
>  
> -class _MobileResourceFilterSheet extends StatelessWidget {
> -  @override
> -  Widget build(BuildContext context) {
> -    final rBloc = Provider.of<PveResourceBloc>(context);
> -
> -    return ProxmoxStreamBuilder<PveResourceBloc, PveResourceState>(
> -      bloc: rBloc,
> -      builder: (context, state) => Drawer(
> -        child: SingleChildScrollView(
> -          child: Column(
> -            crossAxisAlignment: CrossAxisAlignment.start,
> -            children: <Widget>[
> -              Padding(
> -                padding: const EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 0),
> -                child: ListTile(
> -                  title: const Text(
> -                    'Filter Results',
> -                  ),
> -                  trailing: rBloc.isFiltered
> -                      ? TextButton(
> -                          onPressed: () => rBloc.events.add(ResetFilter()),
> -                          child: Text(
> -                            'Reset',
> -                            style: TextStyle(
> -                              color: Theme.of(context).colorScheme.secondary,
> -                            ),
> -                          ),
> -                        )
> -                      : null,
> -                ),
> -              ),
> -              const Divider(
> -                indent: 0,
> -                endIndent: 0,
> -              ),
> -              Padding(
> -                padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0),
> -                child: Column(
> -                  children: [
> -                    const ListTile(
> -                      title: Text(
> -                        'Type',
> -                        style: TextStyle(fontWeight: FontWeight.bold),
> -                      ),
> -                    ),
> -                    CheckboxListTile(
> -                      dense: true,
> -                      title: Text(
> -                        'Nodes',
> -                        style: TextStyle(
> -                            color: Theme.of(context)
> -                                .colorScheme
> -                                .onSurface
> -                                .withValues(alpha: 0.75)),
> -                      ),
> -                      value: state.typeFilter.contains('node'),
> -                      onChanged: (v) => rBloc.events.add(FilterResources(
> -                        typeFilter: addOrRemove(v!, 'node', state.typeFilter),
> -                      )),
> -                    ),
> -                    CheckboxListTile(
> -                      dense: true,
> -                      title: Text(
> -                        'Qemu',
> -                        style: TextStyle(
> -                            color: Theme.of(context)
> -                                .colorScheme
> -                                .onSurface
> -                                .withValues(alpha: 0.75)),
> -                      ),
> -                      value: state.typeFilter.contains('qemu'),
> -                      onChanged: (v) => rBloc.events.add(FilterResources(
> -                        typeFilter: addOrRemove(v!, 'qemu', state.typeFilter),
> -                      )),
> -                    ),
> -                    CheckboxListTile(
> -                      dense: true,
> -                      title: Text(
> -                        'LXC',
> -                        style: TextStyle(
> -                            color: Theme.of(context)
> -                                .colorScheme
> -                                .onSurface
> -                                .withValues(alpha: 0.75)),
> -                      ),
> -                      value: state.typeFilter.contains('lxc'),
> -                      onChanged: (v) => rBloc.events.add(FilterResources(
> -                        typeFilter: addOrRemove(v!, 'lxc', state.typeFilter),
> -                      )),
> -                    ),
> -                    CheckboxListTile(
> -                      dense: true,
> -                      title: Text(
> -                        'Storage',
> -                        style: TextStyle(
> -                            color: Theme.of(context)
> -                                .colorScheme
> -                                .onSurface
> -                                .withValues(alpha: 0.75)),
> -                      ),
> -                      value: state.typeFilter.contains('storage'),
> -                      onChanged: (v) => rBloc.events.add(FilterResources(
> -                        typeFilter:
> -                            addOrRemove(v!, 'storage', state.typeFilter),
> -                      )),
> -                    ),
> -                  ],
> -                ),
> -              ),
> -              Padding(
> -                padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0),
> -                child: Column(
> -                  children: [
> -                    const ListTile(
> -                      title: Text(
> -                        'Status',
> -                        style: TextStyle(fontWeight: FontWeight.bold),
> -                      ),
> -                    ),
> -                    CheckboxListTile(
> -                      dense: true,
> -                      title: Text(
> -                        'Online',
> -                        style: TextStyle(
> -                            color: Theme.of(context)
> -                                .colorScheme
> -                                .onSurface
> -                                .withValues(alpha: 0.75)),
> -                      ),
> -                      value: state.statusFilter
> -                          .contains(PveResourceStatusType.running),
> -                      onChanged: (v) => rBloc.events.add(FilterResources(
> -                        statusFilter: addOrRemove(v!,
> -                            PveResourceStatusType.running, state.statusFilter),
> -                      )),
> -                    ),
> -                    CheckboxListTile(
> -                      dense: true,
> -                      title: Text(
> -                        'Offline',
> -                        style: TextStyle(
> -                            color: Theme.of(context)
> -                                .colorScheme
> -                                .onSurface
> -                                .withValues(alpha: 0.75)),
> -                      ),
> -                      value: state.statusFilter
> -                          .contains(PveResourceStatusType.stopped),
> -                      onChanged: (v) => rBloc.events.add(FilterResources(
> -                        statusFilter: addOrRemove(v!,
> -                            PveResourceStatusType.stopped, state.statusFilter),
> -                      )),
> -                    ),
> -                  ],
> -                ),
> -              )
> -            ],
> -          ),
> -        ),
> -      ),
> -    );
> -  }
> -
> -  BuiltSet<S> addOrRemove<S>(bool value, S element, BuiltSet<S> filter) {
> -    if (value) {
> -      return filter.rebuild((b) => b..add(element));
> -    } else {
> -      return filter.rebuild((b) => b..remove(element));
> -    }
> -  }
> -}
> -
>  class AppBarFilterIconButton extends StatelessWidget {
>    const AppBarFilterIconButton({super.key});
>  
> diff --git a/lib/widgets/pve_mobile_resource_filter_sheet.dart b/lib/widgets/pve_mobile_resource_filter_sheet.dart
> new file mode 100644
> index 0000000..cee3a49
> --- /dev/null
> +++ b/lib/widgets/pve_mobile_resource_filter_sheet.dart
> @@ -0,0 +1,188 @@
> +import 'package:built_collection/built_collection.dart';
> +import 'package:flutter/material.dart';
> +import 'package:provider/provider.dart';
> +import 'package:proxmox_dart_api_client/proxmox_dart_api_client.dart';
> +import 'package:pve_flutter_frontend/bloc/pve_resource_bloc.dart';
> +import 'package:pve_flutter_frontend/states/pve_resource_state.dart';
> +import 'package:pve_flutter_frontend/widgets/proxmox_stream_builder_widget.dart';
> +
> +class PveMobileResourceFilterSheet extends StatelessWidget {
> +  const PveMobileResourceFilterSheet({super.key});
> +
> +  @override
> +  Widget build(BuildContext context) {
> +    final rBloc = Provider.of<PveResourceBloc>(context);
> +    return ProxmoxStreamBuilder<PveResourceBloc, PveResourceState>(
> +      bloc: rBloc,
> +      builder: (context, state) => Drawer(
> +        child: SingleChildScrollView(
> +          child: Column(
> +            crossAxisAlignment: CrossAxisAlignment.start,
> +            children: [
> +              Padding(
> +                padding: const EdgeInsets.fromLTRB(8.0, 20.0, 8.0, 0),
> +                child: ListTile(
> +                  title: const Text(
> +                    'Filter Results',
> +                  ),
> +                  trailing: rBloc.isFiltered
> +                      ? TextButton(
> +                          onPressed: () => rBloc.events.add(ResetFilter()),
> +                          child: Text(
> +                            'Reset',
> +                            style: TextStyle(
> +                              color: Theme.of(context).colorScheme.secondary,
> +                            ),
> +                          ),
> +                        )
> +                      : null,
> +                ),
> +              ),
> +              const Divider(indent: 0, endIndent: 0),
> +              _PveFilterSheetSection(
> +                sectionTitle: 'Type',
> +                items: [
> +                  _ProxmoxResourceFilterListTile(
> +                    title: 'Nodes',
> +                    value: state.typeFilter.contains('node'),
> +                    onChanged: (v) => rBloc.events.add(
> +                      FilterResources(
> +                        typeFilter: _addOrRemove(v!, 'node', state.typeFilter),
> +                      ),
> +                    ),
> +                  ),
> +                  _ProxmoxResourceFilterListTile(
> +                    title: 'Qemu',
> +                    value: state.typeFilter.contains('qemu'),
> +                    onChanged: (v) => rBloc.events.add(
> +                      FilterResources(
> +                        typeFilter: _addOrRemove(v!, 'qemu', state.typeFilter),
> +                      ),
> +                    ),
> +                  ),
> +                  _ProxmoxResourceFilterListTile(
> +                    title: 'LXC',
> +                    value: state.typeFilter.contains('lxc'),
> +                    onChanged: (v) => rBloc.events.add(
> +                      FilterResources(
> +                        typeFilter: _addOrRemove(v!, 'lxc', state.typeFilter),
> +                      ),
> +                    ),
> +                  ),
> +                  _ProxmoxResourceFilterListTile(
> +                    title: 'Storage',
> +                    value: state.typeFilter.contains('storage'),
> +                    onChanged: (v) => rBloc.events.add(
> +                      FilterResources(
> +                        typeFilter:
> +                            _addOrRemove(v!, 'storage', state.typeFilter),
> +                      ),
> +                    ),
> +                  ),
> +                ],
> +              ),
> +              _PveFilterSheetSection(
> +                sectionTitle: 'Status',
> +                items: [
> +                  _ProxmoxResourceFilterListTile(
> +                    title: 'Online',
> +                    value: state.statusFilter
> +                        .contains(PveResourceStatusType.running),
> +                    onChanged: (v) => rBloc.events.add(
> +                      FilterResources(
> +                        statusFilter: _addOrRemove(
> +                          v!,
> +                          PveResourceStatusType.running,
> +                          state.statusFilter,
> +                        ),
> +                      ),
> +                    ),
> +                  ),
> +                  _ProxmoxResourceFilterListTile(
> +                    title: 'Offline',
> +                    value: state.statusFilter
> +                        .contains(PveResourceStatusType.stopped),
> +                    onChanged: (v) => rBloc.events.add(
> +                      FilterResources(
> +                        statusFilter: _addOrRemove(
> +                          v!,
> +                          PveResourceStatusType.stopped,
> +                          state.statusFilter,
> +                        ),
> +                      ),
> +                    ),
> +                  ),
> +                ],
> +              )
> +            ],
> +          ),
> +        ),
> +      ),
> +    );
> +  }
> +
> +  BuiltSet<S> _addOrRemove<S>(bool value, S element, BuiltSet<S> filter) {
> +    if (value) {
> +      return filter.rebuild((b) => b..add(element));
> +    } else {
> +      return filter.rebuild((b) => b..remove(element));
> +    }
> +  }
> +}
> +
> +class _PveFilterSheetSection extends StatelessWidget {
> +  const _PveFilterSheetSection({
> +    required this.items,
> +    required this.sectionTitle,
> +  });
> +
> +  final List<Widget> items;
> +  final String sectionTitle;
> +
> +  @override
> +  Widget build(BuildContext context) {
> +    return Padding(
> +      padding: const EdgeInsets.symmetric(horizontal: 8),
> +      child: Column(
> +        children: [
> +          ListTile(
> +            title: Text(
> +              sectionTitle,
> +              style: TextStyle(fontWeight: FontWeight.bold),
> +            ),
> +          ),
> +          ...items,
> +        ],
> +      ),
> +    );
> +  }
> +}
> +
> +class _ProxmoxResourceFilterListTile extends StatelessWidget {
> +  const _ProxmoxResourceFilterListTile({
> +    required this.title,
> +    this.onChanged,
> +    this.value,
> +  });
> +
> +  final String title;
> +  final ValueChanged<bool?>? onChanged;
> +  final bool? value;
> +
> +  @override
> +  Widget build(BuildContext context) {
> +    return CheckboxListTile(
> +      dense: true,
> +      title: Text(
> +        title,
> +        style: TextStyle(
> +          color: Theme.of(context).colorScheme.onSurface.withValues(
> +                alpha: 0.75,
> +              ),
> +        ),
> +      ),
> +      value: value,
> +      onChanged: onChanged,
> +    );
> +  }
> +}



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused`
  2025-06-02 13:37 [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Shan Shaji
                   ` (2 preceding siblings ...)
  2025-06-02 13:37 ` [pve-devel] [PATCH proxmox_dart_api_client v2 1/1] fix: ui: add missing `paused` status check Shan Shaji
@ 2025-06-03  8:15 ` Michael Köppl
  2025-06-05  9:46   ` Shan Shaji
  3 siblings, 1 reply; 8+ messages in thread
From: Michael Köppl @ 2025-06-03  8:15 UTC (permalink / raw)
  To: Proxmox VE development discussion, Shan Shaji

Thanks for tackling this! Definitely improves the UX. I tested this in
my Android emulator. Paused guests were displayed with the correct
status instead of "Unknown" and I was able to filter for the "Paused"
status. Did not notice anything off. Well done!

I left some minor comments on the individual patches. With those
addressed, consider this:

Reviewed-by: Michael Köppl <m.koeppl@proxmox.com>
Tested-by: Michael Köppl <m.koeppl@proxmox.com>

On 6/2/25 15:37, Shan Shaji wrote:
> This patch series includes the fix for guest missing when the status 
> is `paused`. Additionaly the series also includes the changes from 
> another patch which can be found here: 
> 
> https://lore.proxmox.com/pve-devel/20250522130825.79862-1-s.shaji@proxmox.com/
> 
> pve_flutter_frontend:
> 
> Shan Shaji (2):
>   refactor: move and split the `_MobileResourceFilterSheet` widget
>   fix: ui: guests missing in resources tab when status is `paused`
> 
>  lib/pages/main_layout_slim.dart               | 175 +--------------
>  .../pve_mobile_resource_filter_sheet.dart     | 202 ++++++++++++++++++
>  2 files changed, 204 insertions(+), 173 deletions(-)
>  create mode 100644 lib/widgets/pve_mobile_resource_filter_sheet.dart
> 
> 
> proxmox_dart_api_client:
> 
> Shan Shaji (1):
>   fix: ui: add missing `paused` status check
> 
>  lib/src/models/pve_cluster_resources_model.dart | 2 ++
>  1 file changed, 2 insertions(+)
> 
> 
> Summary over all repositories:
>   3 files changed, 206 insertions(+), 173 deletions(-)
> 



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused`
  2025-06-03  8:15 ` [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Michael Köppl
@ 2025-06-05  9:46   ` Shan Shaji
  0 siblings, 0 replies; 8+ messages in thread
From: Shan Shaji @ 2025-06-05  9:46 UTC (permalink / raw)
  To: Michael Köppl, Proxmox VE development discussion

On Tue Jun 3, 2025 at 10:15 AM CEST, Michael Köppl wrote:
> Thanks for tackling this! Definitely improves the UX. I tested this in
> my Android emulator. Paused guests were displayed with the correct
> status instead of "Unknown" and I was able to filter for the "Paused"
> status. Did not notice anything off. Well done!
>
> I left some minor comments on the individual patches. With those
> addressed, consider this:

Superseeded by v3: https://lore.proxmox.com/pve-devel/20250605094118.93815-2-s.shaji@proxmox.com/T/#u




_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2025-06-05  9:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-02 13:37 [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Shan Shaji
2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 1/2] refactor: move and split the `_MobileResourceFilterSheet` widget Shan Shaji
2025-06-03  8:10   ` Michael Köppl
2025-06-02 13:37 ` [pve-devel] [PATCH pve_flutter_frontend v2 2/2] fix: ui: guests missing in resources tab when status is `paused` Shan Shaji
2025-06-03  8:02   ` Michael Köppl
2025-06-02 13:37 ` [pve-devel] [PATCH proxmox_dart_api_client v2 1/1] fix: ui: add missing `paused` status check Shan Shaji
2025-06-03  8:15 ` [pve-devel] [PATCH proxmox_dart_api_client/pve_flutter_frontend v2 0/3] fix: ui: guest missing in resources tab when status is `paused` Michael Köppl
2025-06-05  9:46   ` Shan Shaji

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal