diff --git a/repertory/repertory/include/ui/handlers.hpp b/repertory/repertory/include/ui/handlers.hpp index e49bb0f8..ba1e2049 100644 --- a/repertory/repertory/include/ui/handlers.hpp +++ b/repertory/repertory/include/ui/handlers.hpp @@ -74,10 +74,7 @@ private: [[nodiscard]] auto data_directory_exists(provider_type prov, std::string_view name) const -> bool; - void handle_delete_mount_location(const httplib::Request &req, - httplib::Response &res) const; - - void handle_get_available_locations(httplib::Response &res) const; + static void handle_get_available_locations(httplib::Response &res); void handle_get_mount(const httplib::Request &req, httplib::Response &res) const; @@ -99,6 +96,9 @@ private: void handle_post_mount(const httplib::Request &req, httplib::Response &res); + void handle_put_mount_location(const httplib::Request &req, + httplib::Response &res) const; + void handle_put_set_value_by_name(const httplib::Request &req, httplib::Response &res) const; diff --git a/repertory/repertory/src/ui/handlers.cpp b/repertory/repertory/src/ui/handlers.cpp index 3fd2148a..4ae2cb45 100644 --- a/repertory/repertory/src/ui/handlers.cpp +++ b/repertory/repertory/src/ui/handlers.cpp @@ -168,10 +168,6 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) : http_error_codes::internal_error; }); - server->Delete("/api/v1/mount_location", [this](auto &&req, auto &&res) { - handle_delete_mount_location(req, res); - }); - server->Get("/api/v1/locations", [this](auto && /* req */, auto &&res) { handle_get_available_locations(res); }); @@ -205,6 +201,10 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) server->Post("/api/v1/mount", [this](auto &&req, auto &&res) { handle_post_mount(req, res); }); + server->Put("/api/v1/mount_location", [this](auto &&req, auto &&res) { + handle_put_mount_location(req, res); + }); + server->Put("/api/v1/set_value_by_name", [this](auto &&req, auto &&res) { handle_put_set_value_by_name(req, res); }); @@ -302,23 +302,24 @@ auto handlers::data_directory_exists(provider_type prov, return ret; } -void handlers::handle_delete_mount_location(const httplib::Request &req, - httplib::Response &res) const { +void handlers::handle_put_mount_location(const httplib::Request &req, + httplib::Response &res) const { REPERTORY_USES_FUNCTION_NAME(); auto prov = provider_type_from_string(req.get_param_value("type")); auto name = req.get_param_value("name"); + auto location = req.get_param_value("location"); if (not data_directory_exists(prov, name)) { res.status = http_error_codes::not_found; return; } - config_->set_mount_location(prov, name, ""); + config_->set_mount_location(prov, name, location); res.status = http_error_codes::ok; } -void handlers::handle_get_available_locations(httplib::Response &res) const { +void handlers::handle_get_available_locations(httplib::Response &res) { #if defined(_WIN32) constexpr const std::array letters{ "A:", "B:", "C:", "D:", "E:", "F:", "G:", "H:", "I:", diff --git a/web/repertory/lib/helpers.dart b/web/repertory/lib/helpers.dart index 06b64fd0..3082e114 100644 --- a/web/repertory/lib/helpers.dart +++ b/web/repertory/lib/helpers.dart @@ -329,3 +329,67 @@ Map getChanged( return changed; } + +Future editMountLocation( + context, + List available, { + bool allowEmpty = false, + String? location, +}) async { + String? currentLocation = location; + final controller = TextEditingController(text: currentLocation); + return await showDialog( + context: context, + builder: (context) { + return StatefulBuilder( + builder: (context, setState) { + return AlertDialog( + actions: [ + TextButton( + child: const Text('Cancel'), + onPressed: () => Navigator.of(context).pop(null), + ), + TextButton( + child: const Text('OK'), + onPressed: () { + final result = getSettingValidators('Path').firstWhereOrNull( + (validator) => !validator(currentLocation ?? ''), + ); + if (result != null) { + return displayErrorMessage( + context, + "Mount location is not valid", + ); + } + Navigator.of(context).pop(currentLocation); + }, + ), + ], + content: + available.isEmpty + ? TextField( + autofocus: true, + controller: controller, + onChanged: + (value) => setState(() => currentLocation = value), + ) + : DropdownButton( + hint: const Text("Select drive"), + value: currentLocation, + onChanged: + (value) => setState(() => currentLocation = value), + items: + available.map>((item) { + return DropdownMenuItem( + value: item, + child: Text(item), + ); + }).toList(), + ), + title: const Text('Set Mount Location'), + ); + }, + ); + }, + ); +} diff --git a/web/repertory/lib/models/mount.dart b/web/repertory/lib/models/mount.dart index 5abce292..f9fee15c 100644 --- a/web/repertory/lib/models/mount.dart +++ b/web/repertory/lib/models/mount.dart @@ -101,15 +101,15 @@ class Mount with ChangeNotifier { } } - Future clearMountLocation() async { + Future setMountLocation(String location) async { try { - mountConfig.path = ""; + mountConfig.path = location; final auth = await _auth.createAuth(); - final response = await http.delete( + final response = await http.put( Uri.parse( Uri.encodeFull( - '${getBaseUri()}/api/v1/mount_location?auth=$auth&name=$name&type=$type', + '${getBaseUri()}/api/v1/mount_location?auth=$auth&name=$name&type=$type&location=$location', ), ), ); diff --git a/web/repertory/lib/widgets/mount_widget.dart b/web/repertory/lib/widgets/mount_widget.dart index 13920c84..18a8718e 100644 --- a/web/repertory/lib/widgets/mount_widget.dart +++ b/web/repertory/lib/widgets/mount_widget.dart @@ -17,6 +17,7 @@ class MountWidget extends StatefulWidget { class _MountWidgetState extends State { bool _enabled = true; + bool _editEnabled = true; Timer? _timer; @override @@ -66,14 +67,26 @@ class _MountWidgetState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (mount.path.isNotEmpty && - mount.mounted != null && - !mount.mounted!) + if (mount.mounted != null && !mount.mounted!) IconButton( - icon: const Icon(Icons.remove), + icon: const Icon(Icons.edit), color: subTextColor, - onPressed: () => mount.clearMountLocation(), - tooltip: 'Clear Mount Location', + tooltip: 'Edit location', + onPressed: () async { + setState(() => _editEnabled = false); + final available = await mount.getAvailableLocations(); + if (context.mounted) { + final location = await editMountLocation( + context, + available, + location: mount.path, + ); + if (location != null) { + await mount.setMountLocation(location); + } + } + setState(() => _editEnabled = true); + }, ), IconButton( icon: Icon( @@ -87,6 +100,12 @@ class _MountWidgetState extends State { ? Color.fromARGB(255, 163, 96, 76) : subTextColor, ), + tooltip: + mount.mounted == null + ? '' + : mount.mounted! + ? 'Unmount' + : 'Mount', onPressed: _createMountHandler(context, mount), ), ], @@ -165,70 +184,7 @@ class _MountWidgetState extends State { return location; } - final available = await mount.getAvailableLocations(); - - String? currentLocation; - return await showDialog( - context: context, - builder: (context) { - return StatefulBuilder( - builder: (context, setState) { - return AlertDialog( - actions: [ - TextButton( - child: const Text('Cancel'), - onPressed: () => Navigator.of(context).pop(null), - ), - TextButton( - child: const Text('OK'), - onPressed: () { - final result = getSettingValidators( - 'Path', - ).firstWhereOrNull( - (validator) => !validator(currentLocation ?? ''), - ); - if (result != null) { - return displayErrorMessage( - context, - "Mount location is not valid", - ); - } - Navigator.of(context).pop(currentLocation); - }, - ), - ], - content: - available.isEmpty - ? TextField( - autofocus: true, - controller: TextEditingController( - text: currentLocation, - ), - inputFormatters: [ - FilteringTextInputFormatter.deny(RegExp(r'\s')), - ], - onChanged: - (value) => setState(() => currentLocation = value), - ) - : DropdownButton( - hint: const Text("Select drive"), - value: currentLocation, - onChanged: - (value) => setState(() => currentLocation = value), - items: - available.map>((item) { - return DropdownMenuItem( - value: item, - child: Text(item), - ); - }).toList(), - ), - title: const Text('Set Mount Location'), - ); - }, - ); - }, - ); + return editMountLocation(context, await mount.getAvailableLocations()); } @override