From badd098fe0c483193e6e2ce6458311c0f8aa4906 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Tue, 4 Mar 2025 13:32:15 -0600 Subject: [PATCH] Create management portal in Flutter #39 --- .../lib/errors/duplicate_mount_exception.dart | 6 -- web/repertory/lib/main.dart | 102 ++++++++++++------ web/repertory/lib/models/mount_list.dart | 17 ++- .../lib/widgets/add_mount_widget.dart | 31 ++++-- 4 files changed, 97 insertions(+), 59 deletions(-) delete mode 100644 web/repertory/lib/errors/duplicate_mount_exception.dart diff --git a/web/repertory/lib/errors/duplicate_mount_exception.dart b/web/repertory/lib/errors/duplicate_mount_exception.dart deleted file mode 100644 index 0f2c0182..00000000 --- a/web/repertory/lib/errors/duplicate_mount_exception.dart +++ /dev/null @@ -1,6 +0,0 @@ -class DuplicateMountException implements Exception { - final String _name; - const DuplicateMountException({required name}) : _name = name, super(); - - String get name => _name; -} diff --git a/web/repertory/lib/main.dart b/web/repertory/lib/main.dart index 839d333b..7d719071 100644 --- a/web/repertory/lib/main.dart +++ b/web/repertory/lib/main.dart @@ -73,6 +73,10 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { + bool _allowAdd = true; + String _mountType = "S3"; + String _mountName = ""; + @override Widget build(BuildContext context) { return Scaffold( @@ -86,40 +90,74 @@ class _MyHomePageState extends State { child: MountListWidget(), ), floatingActionButton: FloatingActionButton( - onPressed: () { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('Add Mount'), - content: Consumer( - builder: (_, mountList, __) { - return AddMountWidget( - allowEncrypt: - !mountList.items.contains( - (item) => item.type == "encrypt", + onPressed: + _allowAdd + ? () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Add Mount'), + content: Consumer( + builder: (_, mountList, __) { + return AddMountWidget( + allowEncrypt: + !mountList.items.contains( + (item) => item.type == "encrypt", + ), + mountName: _mountName, + mountType: _mountType, + onNameChanged: + (mountName) => setState( + () => _mountName = mountName ?? "", + ), + onTypeChanged: + (mountType) => setState( + () => _mountType = mountType ?? "S3", + ), + ); + }, + ), + actions: [ + TextButton( + child: const Text('Cancel'), + onPressed: () { + setState(() { + _mountType = "S3"; + _mountName = ""; + }); + Navigator.of(context).pop(); + }, ), - ); - }, - ), - actions: [ - TextButton( - child: const Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); + TextButton( + child: const Text('OK'), + onPressed: () { + setState(() => _allowAdd = false); + + Provider.of(context, listen: false) + .add(_mountType, _mountName) + .then((_) { + setState(() { + _allowAdd = true; + _mountType = "S3"; + _mountName = ""; + }); + }) + .catchError((_) { + setState(() { + _allowAdd = true; + }); + }); + + Navigator.of(context).pop(); + }, + ), + ], + ); }, - ), - TextButton( - child: const Text('Add'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], - ); - }, - ); - }, + ); + } + : null, tooltip: 'Add Mount', child: const Icon(Icons.add), ), diff --git a/web/repertory/lib/models/mount_list.dart b/web/repertory/lib/models/mount_list.dart index 83eb7ade..67607a9d 100644 --- a/web/repertory/lib/models/mount_list.dart +++ b/web/repertory/lib/models/mount_list.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; -import 'package:repertory/errors/duplicate_mount_exception.dart'; import 'package:repertory/types/mount_config.dart'; class MountList with ChangeNotifier { @@ -47,16 +46,14 @@ class MountList with ChangeNotifier { }); } - void add(MountConfig config) { - var item = _mountList.firstWhereOrNull((cfg) => cfg.name == config.name); - if (item != null) { - throw DuplicateMountException(name: config.name); - } + Future add(String type, String name) async { + await http.post( + Uri.parse( + Uri.encodeFull('${Uri.base.origin}/api/v1/mount?name=$name&type=$type'), + ), + ); - _mountList.add(config); - _sort(_mountList); - - notifyListeners(); + return _fetch(); } void remove(String name) { diff --git a/web/repertory/lib/widgets/add_mount_widget.dart b/web/repertory/lib/widgets/add_mount_widget.dart index a02111eb..98944ffb 100644 --- a/web/repertory/lib/widgets/add_mount_widget.dart +++ b/web/repertory/lib/widgets/add_mount_widget.dart @@ -1,18 +1,24 @@ import 'package:flutter/material.dart'; -class AddMountWidget extends StatefulWidget { +class AddMountWidget extends StatelessWidget { final bool allowEncrypt; - const AddMountWidget({super.key, required this.allowEncrypt}); + final String mountName; + final String mountType; + final void Function(String? newName) onNameChanged; + final void Function(String? newType) onTypeChanged; + const AddMountWidget({ + super.key, + required this.allowEncrypt, + required this.mountName, + required this.mountType, + required this.onNameChanged, + required this.onTypeChanged, + }); - @override - State createState() => _AddMountWidgetState(); -} - -class _AddMountWidgetState extends State { @override Widget build(BuildContext context) { var items = ["S3", "Sia"]; - if (widget.allowEncrypt) { + if (allowEncrypt) { items.insert(0, "Encrypt"); } @@ -20,14 +26,17 @@ class _AddMountWidgetState extends State { mainAxisSize: MainAxisSize.min, children: [ DropdownButton( - value: "S3", - onChanged: (newValue) {}, + value: mountType, + onChanged: onTypeChanged, items: items.map>((item) { return DropdownMenuItem(value: item, child: Text(item)); }).toList(), ), - TextField(decoration: InputDecoration(labelText: 'Name')), + TextField( + decoration: InputDecoration(labelText: 'Name'), + onChanged: onNameChanged, + ), ], ); }