From cc301e207ca164aa4e7654765ef3902bd0f2a630 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Mon, 3 Mar 2025 10:42:11 -0600 Subject: [PATCH] portal configuration --- repertory/repertory/include/ui/handlers.hpp | 14 ++--- .../repertory/include/ui/mgmt_app_config.hpp | 54 +++++++++++++++++++ repertory/repertory/src/ui/handlers.cpp | 30 ++++++++++- .../repertory/src/ui/mgmt_app_config.cpp | 43 +++++++++++++++ web/repertory/lib/widgets/mount_widget.dart | 27 +++++----- 5 files changed, 140 insertions(+), 28 deletions(-) create mode 100644 repertory/repertory/include/ui/mgmt_app_config.hpp create mode 100644 repertory/repertory/src/ui/mgmt_app_config.cpp diff --git a/repertory/repertory/include/ui/handlers.hpp b/repertory/repertory/include/ui/handlers.hpp index b8cb1935..7ef260f0 100644 --- a/repertory/repertory/include/ui/handlers.hpp +++ b/repertory/repertory/include/ui/handlers.hpp @@ -25,17 +25,7 @@ #include "events/consumers/console_consumer.hpp" namespace repertory::ui { -struct mgmt_app_config final { - std::string api_auth_{"test"}; - std::uint16_t api_port_{default_ui_mgmt_port}; - std::string api_user_{"test"}; - - [[nodiscard]] auto get_api_auth() const -> std::string { return api_auth_; } - - [[nodiscard]] auto get_api_port() const -> std::uint16_t { return api_port_; } - - [[nodiscard]] auto get_api_user() const -> std::string { return api_user_; } -}; +class mgmt_app_config; class handlers final { public: @@ -62,6 +52,8 @@ private: void handle_get_mount_list(auto &&res) const; + void handle_get_mount_location(auto &&req, auto &&res) const; + void handle_get_mount_status(auto &&req, auto &&res) const; void handle_post_mount(auto &&req, auto &&res) const; diff --git a/repertory/repertory/include/ui/mgmt_app_config.hpp b/repertory/repertory/include/ui/mgmt_app_config.hpp new file mode 100644 index 00000000..5bf2df86 --- /dev/null +++ b/repertory/repertory/include/ui/mgmt_app_config.hpp @@ -0,0 +1,54 @@ +/* + Copyright <2018-2025> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef REPERTORY_INCLUDE_UI_MGMT_APP_CONFIG_HPP_ +#define REPERTORY_INCLUDE_UI_MGMT_APP_CONFIG_HPP_ + +#include "types/repertory.hpp" + +namespace repertory::ui { +class mgmt_app_config final { +private: + std::string api_auth_{"test"}; + std::uint16_t api_port_{default_ui_mgmt_port}; + std::string api_user_{"test"}; + std::unordered_map> + locations_; + mutable std::recursive_mutex mtx_; + +public: + [[nodiscard]] auto get_api_auth() const -> std::string { return api_auth_; } + + [[nodiscard]] auto get_api_port() const -> std::uint16_t { return api_port_; } + + [[nodiscard]] auto get_api_user() const -> std::string { return api_user_; } + + [[nodiscard]] auto get_mount_location(provider_type prov, + std::string_view name) const + -> std::string; + + void set_mount_location(provider_type prov, std::string_view name, + std::string_view location); +}; +} // namespace repertory::ui + +#endif // REPERTORY_INCLUDE_UI_MGMT_APP_CONFIG_HPP_ diff --git a/repertory/repertory/src/ui/handlers.cpp b/repertory/repertory/src/ui/handlers.cpp index 8c7c7308..0e391e78 100644 --- a/repertory/repertory/src/ui/handlers.cpp +++ b/repertory/repertory/src/ui/handlers.cpp @@ -25,6 +25,7 @@ #include "events/event_system.hpp" #include "rpc/common.hpp" #include "types/repertory.hpp" +#include "ui/mgmt_app_config.hpp" #include "utils/error_utils.hpp" #include "utils/file.hpp" #include "utils/path.hpp" @@ -74,6 +75,10 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) server->Get("/api/v1/mount", [this](auto &&req, auto &&res) { handle_get_mount(req, res); }); + server->Get("/api/v1/mount_location", [this](auto &&req, auto &&res) { + handle_get_mount_location(req, res); + }); + server->Get("/api/v1/mount_list", [this](auto && /* req */, auto &&res) { handle_get_mount_list(res); }); @@ -183,6 +188,19 @@ void handlers::handle_get_mount_list(auto &&res) const { res.status = http_error_codes::ok; } +void handlers::handle_get_mount_location(auto &&req, auto &&res) const { + auto type = req.get_param_value("type"); + auto prov = provider_type_from_string(type); + auto name = req.get_param_value("name"); + res.set_content( + nlohmann::json({ + {"Location", config_->get_mount_location(prov, name)}, + }) + .dump(), + "application/json"); + res.status = http_error_codes::ok; +} + void handlers::handle_get_mount_status(auto &&req, auto &&res) const { REPERTORY_USES_FUNCTION_NAME(); @@ -214,8 +232,16 @@ void handlers::handle_get_mount_status(auto &&req, auto &&res) const { auto lines = handlers::read_process(prov, name, "-status"); - auto result = - nlohmann::json::parse(utils::string::join(lines, '\n')).at(status_name); + nlohmann::json result{ + nlohmann::json::parse(utils::string::join(lines, '\n')).at(status_name), + }; + if (result["Location"].empty()) { + result["Location"] = config_->get_mount_location(prov, name); + } else { + config_->set_mount_location(prov, name, + result["Location"].get()); + } + res.set_content(result.dump(), "application/json"); res.status = http_error_codes::ok; } diff --git a/repertory/repertory/src/ui/mgmt_app_config.cpp b/repertory/repertory/src/ui/mgmt_app_config.cpp new file mode 100644 index 00000000..668cf688 --- /dev/null +++ b/repertory/repertory/src/ui/mgmt_app_config.cpp @@ -0,0 +1,43 @@ +/* + Copyright <2018-2025> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#include "ui/mgmt_app_config.hpp" + +namespace repertory::ui { +auto mgmt_app_config::get_mount_location(provider_type prov, + std::string_view name) const + -> std::string { + recur_mutex_lock lock(mtx_); + if (locations_.contains(prov) && + locations_.at(prov).contains(std::string{name})) { + return locations_.at(prov).at(std::string{name}); + } + + return ""; +} + +void mgmt_app_config::set_mount_location(provider_type prov, + std::string_view name, + std::string_view location) { + recur_mutex_lock lock(mtx_); + locations_[prov][std::string{name}] = std::string{location}; +} +} // namespace repertory::ui diff --git a/web/repertory/lib/widgets/mount_widget.dart b/web/repertory/lib/widgets/mount_widget.dart index e449c873..688674d1 100644 --- a/web/repertory/lib/widgets/mount_widget.dart +++ b/web/repertory/lib/widgets/mount_widget.dart @@ -34,26 +34,23 @@ class _MountWidgetState extends State { ); return ListTile( - isThreeLine: isActive, + isThreeLine: true, leading: IconButton( icon: Icon(Icons.settings, color: textColor), onPressed: () { Navigator.pushNamed(context, '/settings', arguments: mount); }, ), - subtitle: - isActive - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - nameText, - SelectableText( - mount.path, - style: TextStyle(color: subTextColor), - ), - ], - ) - : nameText, + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + nameText, + SelectableText( + mount.path, + style: TextStyle(color: subTextColor), + ), + ], + ), title: SelectableText( initialCaps(mount.type), style: TextStyle(color: textColor, fontWeight: FontWeight.bold), @@ -72,7 +69,7 @@ class _MountWidgetState extends State { }); String? location; - if (!isActive) { + if (!isActive && mount.path.isEmpty) { location = await mount.getMountLocation(); if (location == null) {} }