diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2018-09-08 17:46:57 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2018-09-08 21:00:05 +0300 |
commit | d63e34a7e8612dc69ae25f3d3903ba04cc808bf7 (patch) | |
tree | a70540d6d7ec2b9ce72eae52d83ff35bcf150c1c | |
parent | 70c1cdfd8f34472761fe5ec97f0713990c1b4f5b (diff) |
Add support for root global and tenant views
-rw-r--r-- | mod/mod-package-details.cxx | 2 | ||||
-rw-r--r-- | mod/mod-packages.cxx (renamed from mod/mod-package-search.cxx) | 44 | ||||
-rw-r--r-- | mod/mod-packages.hxx (renamed from mod/mod-package-search.hxx) | 18 | ||||
-rw-r--r-- | mod/mod-repository-root.cxx | 112 | ||||
-rw-r--r-- | mod/mod-repository-root.hxx | 4 | ||||
-rw-r--r-- | mod/options.cli | 25 | ||||
-rw-r--r-- | mod/page.cxx | 25 | ||||
-rw-r--r-- | mod/page.hxx | 13 |
8 files changed, 157 insertions, 86 deletions
diff --git a/mod/mod-package-details.cxx b/mod/mod-package-details.cxx index 6ec0b0f..a36d4c0 100644 --- a/mod/mod-package-details.cxx +++ b/mod/mod-package-details.cxx @@ -215,7 +215,7 @@ handle (request& rq, response& rs) package_db_->query_value<package_count> ( search_params<package_count> (squery, tenant, name))); - s << FORM_SEARCH (squery) + s << FORM_SEARCH (squery, "q") << DIV_COUNTER (pkg_count, "Version", "Versions"); // Enclose the subsequent tables to be able to use nth-child CSS selector. diff --git a/mod/mod-package-search.cxx b/mod/mod-packages.cxx index 347abf1..1157378 100644 --- a/mod/mod-package-search.cxx +++ b/mod/mod-packages.cxx @@ -1,8 +1,8 @@ -// file : mod/mod-package-search.cxx -*- C++ -*- +// file : mod/mod-packages.cxx -*- C++ -*- // copyright : Copyright (c) 2014-2018 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#include <mod/mod-package-search.hxx> +#include <mod/mod-packages.hxx> #include <libstudxml/serializer.hxx> @@ -28,19 +28,19 @@ using namespace brep::cli; // need to deep copy nullptr's), it is a good idea to keep the placeholder // ready for less trivial cases. // -brep::package_search:: -package_search (const package_search& r) +brep::packages:: +packages (const packages& r) : database_module (r), options_ (r.initialized_ ? r.options_ : nullptr) { } -void brep::package_search:: +void brep::packages:: init (scanner& s) { HANDLER_DIAG; - options_ = make_shared<options::package_search> ( + options_ = make_shared<options::packages> ( s, unknown_mode::fail, unknown_mode::fail); database_module::init (*options_, options_->package_db_retry ()); @@ -79,7 +79,7 @@ search_param (const brep::string& q, const brep::string& t) ")"; } -bool brep::package_search:: +bool brep::packages:: handle (request& rq, response& rs) { using namespace web::xhtml; @@ -90,13 +90,12 @@ handle (request& rq, response& rs) const dir_path& root (options_->root ()); const string& title (options_->search_title ()); - params::package_search params; + params::packages params; try { name_value_scanner s (rq.parameters (8 * 1024)); - params = params::package_search ( - s, unknown_mode::fail, unknown_mode::fail); + params = params::packages (s, unknown_mode::fail, unknown_mode::fail); } catch (const cli::exception& e) { @@ -104,10 +103,8 @@ handle (request& rq, response& rs) } size_t page (params.page ()); - const string& squery (params.query ()); - string squery_param (squery.empty () - ? "" - : "?q=" + web::mime_url_encode (squery)); + const string& squery (params.q ()); + string equery (web::mime_url_encode (squery)); xml::serializer s (rs.content (), title); @@ -145,7 +142,7 @@ handle (request& rq, response& rs) package_db_->query_value<latest_package_count> ( search_param<latest_package_count> (squery, tenant))); - s << FORM_SEARCH (squery) + s << FORM_SEARCH (squery, "packages") << DIV_COUNTER (pkg_count, "Package", "Packages"); // Enclose the subsequent tables to be able to use nth-child CSS selector. @@ -164,7 +161,7 @@ handle (request& rq, response& rs) s << TABLE(CLASS="proplist package") << TBODY - << TR_NAME (p->name, squery_param, root, tenant) + << TR_NAME (p->name, equery, root, tenant) << TR_SUMMARY (p->summary) << TR_LICENSE (p->license_alternatives) << TR_TAGS (p->project, p->tags, root, tenant) @@ -177,8 +174,19 @@ handle (request& rq, response& rs) t.commit (); - s << DIV_PAGER (page, pkg_count, res_page, options_->search_pages (), - tenant_dir (root, tenant).string () + squery_param) + string url (tenant_dir (root, tenant).string () + "?packages"); + + if (!equery.empty ()) + { + url += '='; + url += equery; + } + + s << DIV_PAGER (page, + pkg_count, + res_page, + options_->search_pages (), + url) << ~DIV << ~BODY << ~HTML; diff --git a/mod/mod-package-search.hxx b/mod/mod-packages.hxx index 406476e..dd11136 100644 --- a/mod/mod-package-search.hxx +++ b/mod/mod-packages.hxx @@ -1,9 +1,9 @@ -// file : mod/mod-package-search.hxx -*- C++ -*- +// file : mod/mod-packages.hxx -*- C++ -*- // copyright : Copyright (c) 2014-2018 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file -#ifndef MOD_MOD_PACKAGE_SEARCH_HXX -#define MOD_MOD_PACKAGE_SEARCH_HXX +#ifndef MOD_MOD_PACKAGES_HXX +#define MOD_MOD_PACKAGES_HXX #include <libbrep/types.hxx> #include <libbrep/utility.hxx> @@ -13,30 +13,30 @@ namespace brep { - class package_search: public database_module + class packages: public database_module { public: - package_search () = default; + packages () = default; // Create a shallow copy (handling instance) if initialized and a deep // copy (context exemplar) otherwise. // explicit - package_search (const package_search&); + packages (const packages&); virtual bool handle (request&, response&); virtual const cli::options& - cli_options () const {return options::package_search::description ();} + cli_options () const {return options::packages::description ();} private: virtual void init (cli::scanner&); private: - shared_ptr<options::package_search> options_; + shared_ptr<options::packages> options_; }; } -#endif // MOD_MOD_PACKAGE_SEARCH_HXX +#endif // MOD_MOD_PACKAGES_HXX diff --git a/mod/mod-repository-root.cxx b/mod/mod-repository-root.cxx index b8777fd..b825ea1 100644 --- a/mod/mod-repository-root.cxx +++ b/mod/mod-repository-root.cxx @@ -7,6 +7,7 @@ #include <time.h> // tzset() #include <sstream> +#include <algorithm> // find() #include <web/module.hxx> @@ -16,11 +17,11 @@ #include <mod/mod-ci.hxx> #include <mod/mod-submit.hxx> #include <mod/mod-builds.hxx> +#include <mod/mod-packages.hxx> #include <mod/mod-build-log.hxx> #include <mod/mod-build-task.hxx> #include <mod/mod-build-force.hxx> #include <mod/mod-build-result.hxx> -#include <mod/mod-package-search.hxx> #include <mod/mod-package-details.hxx> #include <mod/mod-repository-details.hxx> #include <mod/mod-package-version-details.hxx> @@ -105,7 +106,7 @@ namespace brep // repository_root:: repository_root () - : package_search_ (make_shared<package_search> ()), + : packages_ (make_shared<packages> ()), package_details_ (make_shared<package_details> ()), package_version_details_ (make_shared<package_version_details> ()), repository_details_ (make_shared<repository_details> ()), @@ -126,10 +127,10 @@ namespace brep // Deep/shallow-copy sub-handlers depending on whether this is an // exemplar/handler. // - package_search_ ( + packages_ ( r.initialized_ - ? r.package_search_ - : make_shared<package_search> (*r.package_search_)), + ? r.packages_ + : make_shared<packages> (*r.packages_)), package_details_ ( r.initialized_ ? r.package_details_ @@ -185,7 +186,7 @@ namespace brep options () { option_descriptions r (handler::options ()); - append (r, package_search_->options ()); + append (r, packages_->options ()); append (r, package_details_->options ()); append (r, package_version_details_->options ()); append (r, repository_details_->options ()); @@ -229,7 +230,7 @@ namespace brep // Initialize sub-handlers. // - sub_init (*package_search_, "package_search"); + sub_init (*packages_, "packages"); sub_init (*package_details_, "package_details"); sub_init (*package_version_details_, "package_version_details"); sub_init (*repository_details_, "repository_details"); @@ -255,6 +256,19 @@ namespace brep options_ = make_shared<options::repository_root> ( s, unknown_mode::fail, unknown_mode::fail); + // Verify that the root default views are properly configured. + // + auto verify = [&fail] (const string& v, const char* what) + { + cstrings vs ({"packages", "builds", "about", "submit", "ci"}); + + if (find (vs.begin (), vs.end (), v) == vs.end ()) + fail << what << " value '" << v << "' is invalid"; + }; + + verify (options_->root_global_view (), "root-global-view"); + verify (options_->root_tenant_view (), "root-tenant-view"); + if (options_->root ().empty ()) options_->root (dir_path ("/")); @@ -340,73 +354,97 @@ namespace brep // if (lpath.empty ()) { - // Dispatch request handling to the repository_details or the one of - // build_* handlers depending on the function name passed as a first HTTP - // request parameter (example: cppget.org/?about). Dispatch to the - // package_search handler if the function name is unavailable (no - // parameters) or is not recognized. + // Dispatch request handling to one of the sub-handlers depending on the + // function name passed as a first HTTP request parameter (example: + // cppget.org/?about). If it doesn't denote a handler or there are no + // parameters, then dispatch to the default handler. // const name_values& params (rq.parameters (0 /* limit */, true /* url_only */)); - if (!params.empty ()) + + auto dispatch = [&handle, this] (const string& func, + bool param) -> optional<bool> { - const string& fn (params.front ().name); + // When adding a new handler don't forget to check if need to add it + // to the default view list in the init() function. + // + if (func == "build-task") + { + if (handler_ == nullptr) + handler_.reset (new build_task (*build_task_)); - if (fn == "about") + return handle ("build_task", param); + } + else if (func == "build-result") { if (handler_ == nullptr) - handler_.reset (new repository_details (*repository_details_)); + handler_.reset (new build_result (*build_result_)); - return handle ("repository_details", true); + return handle ("build_result", param); } - else if (fn == "build-task") + else if (func == "build-force") { if (handler_ == nullptr) - handler_.reset (new build_task (*build_task_)); + handler_.reset (new build_force (*build_force_)); - return handle ("build_task", true); + return handle ("build_force", param); } - else if (fn == "build-result") + else if (func == "builds") { if (handler_ == nullptr) - handler_.reset (new build_result (*build_result_)); + handler_.reset (new builds (*builds_)); - return handle ("build_result", true); + return handle ("builds", param); } - else if (fn == "build-force") + else if (func == "packages") { if (handler_ == nullptr) - handler_.reset (new build_force (*build_force_)); + handler_.reset (new packages (*packages_)); - return handle ("build_force", true); + return handle ("packages", param); } - else if (fn == "builds") + else if (func == "about") { if (handler_ == nullptr) - handler_.reset (new builds (*builds_)); + handler_.reset (new repository_details (*repository_details_)); - return handle ("builds", true); + return handle ("repository_details", param); } - else if (fn == "submit") + else if (func == "submit") { if (handler_ == nullptr) handler_.reset (new submit (*submit_)); - return handle ("submit", true); + return handle ("submit", param); } - else if (fn == "ci") + else if (func == "ci") { if (handler_ == nullptr) handler_.reset (new ci (*ci_)); - return handle ("ci", true); + return handle ("ci", param); } - } + else + return nullopt; + }; + + optional<bool> r; + + if (!params.empty () && + (r = dispatch (params.front ().name, true /* param */))) + return *r; - if (handler_ == nullptr) - handler_.reset (new package_search (*package_search_)); + const string& view (!tenant.empty () + ? options_->root_tenant_view () + : options_->root_global_view ()); + + r = dispatch (view, false /* param */); + + // The default views are verified in the init() function. + // + assert (r); - return handle ("package_search"); + return *r; } else { diff --git a/mod/mod-repository-root.hxx b/mod/mod-repository-root.hxx index 9a71849..a46f43f 100644 --- a/mod/mod-repository-root.hxx +++ b/mod/mod-repository-root.hxx @@ -13,7 +13,7 @@ namespace brep { - class package_search; + class packages; class package_details; class package_version_details; class repository_details; @@ -58,7 +58,7 @@ namespace brep version (); private: - shared_ptr<package_search> package_search_; + shared_ptr<packages> packages_; shared_ptr<package_details> package_details_; shared_ptr<package_version_details> package_version_details_; shared_ptr<repository_details> repository_details_; diff --git a/mod/options.cli b/mod/options.cli index 619df66..12f577c 100644 --- a/mod/options.cli +++ b/mod/options.cli @@ -311,7 +311,8 @@ namespace brep // Handler options. // - class package_search: search, package_db, page, handler + + class packages: search, package_db, page, handler { string search-title = "Packages" { @@ -532,6 +533,21 @@ namespace brep class repository_root: handler { + string root-global-view = "packages" + { + "<service>", + "The default view to display for the global repository root. The + <service> argument is one of the supported services (\c{packages}, + \c{builds}, \c{submit}, \c{ci}, etc)." + } + + string root-tenant-view = "packages" + { + "<service>" + "The default view to display for the tenant repository root. The + <service> argument is one of the supported services (\c{packages}, + \c{builds}, \c{submit}, \c{ci}, etc)." + } }; } @@ -542,7 +558,7 @@ namespace brep // Use parameters long names in the C++ code, short aliases (if present) // in HTTP URL. // - class package_search + class packages { // Display package search result list starting from this page. // @@ -550,7 +566,10 @@ namespace brep // Package search criteria. // - string query | q; + // Note that the packages parameter is renamed to '_' by the root + // handler (see the request_proxy class for details). + // + string q | _; }; class package_details diff --git a/mod/page.cxx b/mod/page.cxx index 46f4879..ce12da6 100644 --- a/mod/page.cxx +++ b/mod/page.cxx @@ -98,7 +98,8 @@ namespace brep << TBODY << TR << TD(ID="search-txt") - << *INPUT(TYPE="search", NAME="q", VALUE=query_, AUTOFOCUS="") + << *INPUT(TYPE="search", NAME=name_, VALUE=query_, + AUTOFOCUS="") << ~TD << TD(ID="search-btn") << *INPUT(TYPE="submit", VALUE="Search") @@ -192,14 +193,15 @@ namespace brep << SPAN(CLASS="value") << A << HREF - - // Propagate search criteria to the package details page. - // << tenant_dir (root_, tenant_) / - path (mime_url_encode (name_.string (), false)) - << query_param_ + path (mime_url_encode (name_.string (), false)); - << ~HREF + // Propagate search criteria to the package details page. + // + if (!query_.empty ()) + s << "?q=" << query_; + + s << ~HREF << name_ << ~A << ~SPAN @@ -255,7 +257,7 @@ namespace brep << SPAN(CLASS="value") << A << HREF - << tenant_dir (root_, tenant_) << "?q=" + << tenant_dir (root_, tenant_) << "?packages=" << mime_url_encode (project_.string ()) << ~HREF << project_ @@ -356,7 +358,8 @@ namespace brep { s << A << HREF - << tenant_dir (root_, tenant_) << "?q=" << mime_url_encode (t) + << tenant_dir (root_, tenant_) << "?packages=" + << mime_url_encode (t) << ~HREF << t << ~A; @@ -500,8 +503,8 @@ namespace brep if (r.empty ()) { - // If there is no requirement alternatives specified, then - // print the comment first word. + // If there is no requirement alternatives specified, then print the + // comment first word. // const auto& c (r.comment); if (!c.empty ()) diff --git a/mod/page.hxx b/mod/page.hxx index d3e10db..d9f4249 100644 --- a/mod/page.hxx +++ b/mod/page.hxx @@ -60,18 +60,20 @@ namespace brep const string& tenant_; }; - // Generates package search form element. + // Generates package search form element with the specified query input + // element name. // class FORM_SEARCH { public: - FORM_SEARCH (const string& q): query_ (q) {} + FORM_SEARCH (const string& q, const string& n): query_ (q), name_ (n) {} void operator() (xml::serializer&) const; private: const string& query_; + const string& name_; }; // Generates counter element. @@ -160,7 +162,8 @@ namespace brep const vector<pair<string, string>>& options_; }; - // Generates package name element. + // Generates package name element with an optional search criteria. The + // search string should be url-encoded, if specified. // class TR_NAME { @@ -169,14 +172,14 @@ namespace brep const string& q, const dir_path& r, const string& t) - : name_ (n), query_param_ (q), root_ (r), tenant_ (t) {} + : name_ (n), query_ (q), root_ (r), tenant_ (t) {} void operator() (xml::serializer&) const; private: const package_name& name_; - const string& query_param_; + const string& query_; const dir_path& root_; const string& tenant_; }; |