Project

General

Profile

RE: Multi Variables Mapping Path ยป routing.cpp

Example routing - Alex Tumovsky, 04/14/2025 09:24 AM

 
#include <Wt/WApplication.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WMenu.h>
#include <Wt/WStackedWidget.h>
#include <Wt/WText.h>
#include <Wt/WVBoxLayout.h>
#include <boost/algorithm/string.hpp>

class Menu : public Wt::WMenu {
protected:
void internalPathChanged(const std::string& path) override
{
// exp
Wt::WMenu::internalPathChanged(path);
};
};

class BaseWidget : public Wt::WContainerWidget {
public:
std::string s_;
const static inline std::string FORWARD_SLASH = "/";

std::map<std::string, std::string> urlParamByMask(const std::string& part, const std::string& mask)
{
std::map<std::string, std::string> result;

if (!part.empty() && !mask.empty()) {
typedef boost::split_iterator<std::string::const_iterator> spliterator;
spliterator it1 = spliterator(part.begin() + 1, part.end(),
boost::first_finder(FORWARD_SLASH, boost::is_equal()));
for (spliterator it2 = spliterator(mask.begin() + 1, mask.end(),
boost::first_finder(FORWARD_SLASH, boost::is_equal()));
it1 != spliterator() && it2 != spliterator(); ++it1, ++it2) {
// Check dynamic segment (e.g. "${var}")
if (boost::starts_with(*it2, "${") && boost::ends_with(*it2, "}")) {
auto range = boost::iterator_range<std::string::const_iterator>(it2->begin() + 2, it2->end() - 1);

// result[param] = val
result[boost::copy_range<std::string>(range)] = boost::copy_range<std::string>(*it1);
} else {
if (*it2 != *it1) {
return std::map<std::string, std::string>();
}
}
}
}

return result;
}
};

class OneParamWidget : public BaseWidget {
public:
OneParamWidget(const std::string& s, const std::string& basePath1)
: s_(s)
, basePath1_(basePath1)
{
Wt::log("log") << "Create OneParamWidget" << s;

vbox = this->setLayout(std::make_unique<Wt::WVBoxLayout>());
auto d = Wt::WCssDecorationStyle();
d.setBackgroundColor(Wt::WColor("#E2F3FF"));
this->setDecorationStyle(d);
handleInternalPath(Wt::WApplication::instance()->internalPath());
Wt::WApplication::instance()->internalPathChanged().connect(this, &OneParamWidget::handleInternalPath);
};

std::string s_, basePath1_;
Wt::WVBoxLayout* vbox = nullptr;
~OneParamWidget() {};
void handleInternalPath(const std::string& internalPath)
{

Wt::WApplication* app = Wt::WApplication::instance();
if (app->internalPathMatches(basePath1_)) {
vbox->addWidget(std::make_unique<Wt::WText>("__________BEGIN OneParamWidget__________"));

std::string s;

vbox->addWidget(std::make_unique<Wt::WText>("-> one " + basePath1_));

s = app->internalPathNextPart(basePath1_);
vbox->addWidget(std::make_unique<Wt::WText>("-> param {1} gallery > " + s));

auto partUrl = urlParamByMask(internalPath, "/gallery/${gal_id}");
for (const auto& [param, part] : partUrl) {
vbox->addWidget(std::make_unique<Wt::WText>("-> urlParamByMask (param: " + param + ", part: " + part + ")"));
}

vbox->addWidget(std::make_unique<Wt::WText>("__________END OneParamWidget__________"));
}
}
};

class TwoParamWidget : public BaseWidget {
public:
TwoParamWidget(const std::string& s, const std::string& basePath1, const std::string& basePath2)
: s_(s)
, basePath1_(basePath1)
, basePath2_(basePath2)
{
Wt::log("log") << "Create TwoParamWidget" << s;

vbox = this->setLayout(std::make_unique<Wt::WVBoxLayout>());
auto d = Wt::WCssDecorationStyle();
d.setBackgroundColor(Wt::WColor("#FDFFE2"));
this->setDecorationStyle(d);
handleInternalPath(Wt::WApplication::instance()->internalPath());
Wt::WApplication::instance()->internalPathChanged().connect(this, &TwoParamWidget::handleInternalPath);
};
std::string s_, basePath1_, basePath2_;
Wt::WVBoxLayout* vbox = nullptr;
~TwoParamWidget() {};
void handleInternalPath(const std::string& internalPath)
{
Wt::WApplication* app = Wt::WApplication::instance();
if (app->internalPathMatches(basePath2_)) {
vbox->addWidget(std::make_unique<Wt::WText>("__________BEGIN TwoParamWidget__________"));

std::string s;
vbox->addWidget(std::make_unique<Wt::WText>(" -> two " + basePath1_ + "photo/" + app->internalPathNextPart(basePath2_)));

vbox->addWidget(std::make_unique<Wt::WText>(basePath1_));

vbox->addWidget(std::make_unique<Wt::WText>(basePath2_));

s = app->internalPathNextPart(basePath1_);
vbox->addWidget(std::make_unique<Wt::WText>(" -> param {1} gallery > " + s));

if (app->internalPathMatches(basePath2_)) {
s = app->internalPathNextPart(basePath2_);
vbox->addWidget(std::make_unique<Wt::WText>(" -> param {2} photo > " + s));
}

auto partUrl = urlParamByMask(internalPath, "/gallery/${gal_id}/photo/${pho_id}");
for (const auto& [param, part] : partUrl) {
vbox->addWidget(std::make_unique<Wt::WText>("-> urlParamByMask (param: " + param + ", part: " + part + ")"));
}

vbox->addWidget(std::make_unique<Wt::WText>("__________END TwoParamWidget__________"));
}
}
};

class HelloApplication : public Wt::WApplication {
public:
HelloApplication(const Wt::WEnvironment& env);

private:
Wt::WLineEdit* nameEdit_;
Wt::WContainerWidget* text_;
Wt::WMenu *menu, *menuGal, *menuGalPhoto;
std::unique_ptr<Wt::WStackedWidget> contentWidget;
};

HelloApplication::HelloApplication(const Wt::WEnvironment& env)
: WApplication(env)
{
text_ = root()->addWidget(std::make_unique<Wt::WContainerWidget>());
text_->setMargin(12);

contentWidget = std::make_unique<Wt::WStackedWidget>();
contentWidget->setMargin(12);

auto menu = root()->addWidget(std::make_unique<Wt::WMenu>(contentWidget.get()));
menu->setInternalBasePath("/");
menu->setInternalPathEnabled("/");

// ...
{ // Add item Home on menu
auto item = menu->addItem("Home", std::make_unique<OneParamWidget>("Home page", menu->internalBasePath()), Wt::ContentLoading::Lazy);
item->setPathComponent("");
}
{ // Add item all Galleries on menu
auto item = menu->addItem("Galleries", std::make_unique<OneParamWidget>("Galleries page", menu->internalBasePath()), Wt::ContentLoading::Lazy);
item->setPathComponent("gallery");
}
// ...
{
menuGal = root()->addWidget(std::make_unique<Wt::WMenu>(contentWidget.get()));
menuGal->setInternalPathEnabled("gallery");
{
for (int i = 1; i <= 3; ++i) { // Add gallery in menu
auto item = menuGal->addItem(Wt::WString("Gallery {1}")
.arg(i),
std::make_unique<OneParamWidget>(Wt::WString("Gallegy {1}")
.arg(i)
.toUTF8(),
menuGal->internalBasePath()),
Wt::ContentLoading::Lazy);
item->setPathComponent(Wt::WString("g{1}")
.arg(i)
.toUTF8());

{
menuGalPhoto = root()->addWidget(std::make_unique<Wt::WMenu>(contentWidget.get()));
menuGalPhoto->setInternalPathEnabled(menuGal->internalBasePath() + item->pathComponent() + "/photo");
{
for (int j = 1; j <= 3; ++j) { // Add photos in gallery
auto item1 = menuGalPhoto->addItem(Wt::WString("Photo {1} from Galley {2}")
.arg(j)
.arg(i),
std::make_unique<TwoParamWidget>(Wt::WString("Photo {1} from Galley {2}")
.arg(j)
.arg(i)
.toUTF8(),
menuGal->internalBasePath(), menuGalPhoto->internalBasePath()),
Wt::ContentLoading::Lazy);
item1->setPathComponent(Wt::WString("p{1}")
.arg(j)
.toUTF8());
}
}
}
}
}
}

root()->addWidget(std::move(contentWidget));
}

int main(int argc, char** argv)
{
return Wt::WRun(argc, argv, [](const Wt::WEnvironment& env) {
return std::make_unique<HelloApplication>(env);
});
}
    (1-1/1)