added edit location
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good

This commit is contained in:
Scott E. Graves 2025-03-24 19:01:52 -05:00
parent 96827c007d
commit 1164b99e2b
5 changed files with 107 additions and 86 deletions

View File

@ -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;

View File

@ -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,
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<std::string_view, 26U> letters{
"A:", "B:", "C:", "D:", "E:", "F:", "G:", "H:", "I:",

View File

@ -329,3 +329,67 @@ Map<String, dynamic> getChanged(
return changed;
}
Future<String?> editMountLocation(
context,
List<String> 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<String>(
hint: const Text("Select drive"),
value: currentLocation,
onChanged:
(value) => setState(() => currentLocation = value),
items:
available.map<DropdownMenuItem<String>>((item) {
return DropdownMenuItem<String>(
value: item,
child: Text(item),
);
}).toList(),
),
title: const Text('Set Mount Location'),
);
},
);
},
);
}

View File

@ -101,15 +101,15 @@ class Mount with ChangeNotifier {
}
}
Future<void> clearMountLocation() async {
Future<void> 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',
),
),
);

View File

@ -17,6 +17,7 @@ class MountWidget extends StatefulWidget {
class _MountWidgetState extends State<MountWidget> {
bool _enabled = true;
bool _editEnabled = true;
Timer? _timer;
@override
@ -66,14 +67,26 @@ class _MountWidgetState extends State<MountWidget> {
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<MountWidget> {
? 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<MountWidget> {
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<String>(
hint: const Text("Select drive"),
value: currentLocation,
onChanged:
(value) => setState(() => currentLocation = value),
items:
available.map<DropdownMenuItem<String>>((item) {
return DropdownMenuItem<String>(
value: item,
child: Text(item),
);
}).toList(),
),
title: const Text('Set Mount Location'),
);
},
);
},
);
return editMountLocation(context, await mount.getAvailableLocations());
}
@override