Loading src/blogi.cpp +53 −5 Original line number Diff line number Diff line Loading @@ -604,12 +604,11 @@ static void renderSettingsJson(json_object *jroot, libhtmlpp::HtmlString &out, c if(jenctype) out << " enctype=\"" << json_object_get_string(jenctype) << "\""; out << ">"; // Form fields json_object *jfields = nullptr; if(json_object_object_get_ex(jform, "fields", &jfields)){ int flen = json_object_array_length(jfields); // Field rendering helper (used by both flat fields and tabs) auto renderFieldArray = [&](json_object *jflds){ int flen = json_object_array_length(jflds); for(int f=0; f<flen; ++f){ json_object *jf = json_object_array_get_idx(jfields, f); json_object *jf = json_object_array_get_idx(jflds, f); json_object *jname=nullptr, *jtype=nullptr, *jlabel=nullptr, *jvalue=nullptr, *joptions=nullptr; json_object_object_get_ex(jf, "name", &jname); json_object_object_get_ex(jf, "type", &jtype); Loading Loading @@ -801,6 +800,55 @@ static void renderSettingsJson(json_object *jroot, libhtmlpp::HtmlString &out, c } out << "</div>"; } }; // Tabs support json_object *jtabs = nullptr; json_object_object_get_ex(jform, "tabs", &jtabs); if(jtabs){ int tlen = json_object_array_length(jtabs); out << "<style>" << ".set-tabs{display:flex;gap:0;border-bottom:2px solid var(--blogi-border,#3a3f44);margin-bottom:12px;}" << ".set-tab-btn{padding:8px 18px;border:none;background:none;color:var(--blogi-text-muted,#aaa);cursor:pointer;font-size:0.95em;border-bottom:2px solid transparent;margin-bottom:-2px;}" << ".set-tab-btn:hover{color:var(--blogi-text,#eee);}" << ".set-tab-btn.active{color:var(--blogi-accent,#3ad43a);border-bottom-color:var(--blogi-accent,#3ad43a);}" << ".set-tab-panel{display:none;}" << ".set-tab-panel.active{display:block;}" << "</style>"; out << "<div class=\"set-tabs\">"; for(int t=0; t<tlen; ++t){ json_object *jtab = json_object_array_get_idx(jtabs, t); json_object *jtlabel = nullptr; json_object_object_get_ex(jtab, "label", &jtlabel); out << "<button type=\"button\" class=\"set-tab-btn" << (t==0?" active":"") << "\" data-tab=\"" << t << "\">" << (jtlabel ? json_object_get_string(jtlabel) : "") << "</button>"; } out << "</div>"; for(int t=0; t<tlen; ++t){ json_object *jtab = json_object_array_get_idx(jtabs, t); json_object *jtfields = nullptr; json_object_object_get_ex(jtab, "fields", &jtfields); out << "<div class=\"set-tab-panel" << (t==0?" active":"") << "\" data-tab=\"" << t << "\">"; if(jtfields) renderFieldArray(jtfields); out << "</div>"; } out << "<script>" << "document.querySelectorAll('.set-tab-btn').forEach(function(btn){" << "btn.addEventListener('click',function(){" << "document.querySelectorAll('.set-tab-btn').forEach(function(b){b.classList.remove('active');});" << "document.querySelectorAll('.set-tab-panel').forEach(function(p){p.classList.remove('active');});" << "btn.classList.add('active');" << "document.querySelector('.set-tab-panel[data-tab=\"'+btn.dataset.tab+'\"]').classList.add('active');" << "});" << "});" << "</script>"; } // Form fields (flat, no tabs) json_object *jfields = nullptr; if(!jtabs && json_object_object_get_ex(jform, "fields", &jfields)){ renderFieldArray(jfields); } // Form-embedded table (e.g. navbar items inside a form) Loading src/theme.cpp +100 −87 Original line number Diff line number Diff line Loading @@ -693,9 +693,15 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_object_add(jform, "method", json_object_new_string("POST")); json_object_object_add(jform, "action", json_object_new_string(req.getRequestURL().c_str())); json_object *jtabs = json_object_new_array(); // --- Tab 1: Logo --- { json_object *jtab = json_object_new_object(); json_object_object_add(jtab, "label", json_object_new_string("Logo")); json_object *jfields = json_object_new_array(); // Section header: Logo // Logo heading with preview { std::string logoUrl = getLogoUrl(tid); std::string curUrl; Loading @@ -711,7 +717,7 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_object_add(jf, "label", json_object_new_string(logoLabel.c_str())); json_object_array_add(jfields, jf); } // Logo URL (from media plugin — upload via Media settings, paste URL here) // Logo URL { std::string curUrl; try { getConfig(*_Config.TDatabase[tid], "THEME_LOGO_URL", curUrl); } catch (...) {} Loading @@ -736,15 +742,17 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_object_add(jf, "value", json_object_new_string(curWidth.c_str())); json_object_array_add(jfields, jf); } // Section header: Dark { json_object *jf = json_object_new_object(); json_object_object_add(jf, "type", json_object_new_string("heading")); json_object_object_add(jf, "label", json_object_new_string("Dark Mode Colors")); json_object_array_add(jfields, jf); json_object_object_add(jtab, "fields", jfields); json_object_array_add(jtabs, jtab); } // Dark color fields // --- Tab 2: Dark Mode Colors --- { json_object *jtab = json_object_new_object(); json_object_object_add(jtab, "label", json_object_new_string("Dark Colors")); json_object *jfields = json_object_new_array(); for(auto &c : colors){ std::string val; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_DARK_") + c.suffix, val); } catch(...) {} Loading @@ -763,15 +771,16 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_array_add(jfields, jf); } // Section header: Light { json_object *jf = json_object_new_object(); json_object_object_add(jf, "type", json_object_new_string("heading")); json_object_object_add(jf, "label", json_object_new_string("Light Mode Colors")); json_object_array_add(jfields, jf); json_object_object_add(jtab, "fields", jfields); json_object_array_add(jtabs, jtab); } // Light color fields // --- Tab 3: Light Mode Colors --- { json_object *jtab = json_object_new_object(); json_object_object_add(jtab, "label", json_object_new_string("Light Colors")); json_object *jfields = json_object_new_array(); for(auto &c : colors){ std::string val; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_LIGHT_") + c.suffix, val); } catch(...) {} Loading @@ -790,7 +799,11 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_array_add(jfields, jf); } json_object_object_add(jform, "fields", jfields); json_object_object_add(jtab, "fields", jfields); json_object_array_add(jtabs, jtab); } json_object_object_add(jform, "tabs", jtabs); json_object_object_add(jform, "submit", json_object_new_string("save")); json_object_object_add(jform, "reset_name", json_object_new_string("theme_reset")); json_object_object_add(jform, "reset_label", json_object_new_string("Reset to Defaults")); Loading Loading
src/blogi.cpp +53 −5 Original line number Diff line number Diff line Loading @@ -604,12 +604,11 @@ static void renderSettingsJson(json_object *jroot, libhtmlpp::HtmlString &out, c if(jenctype) out << " enctype=\"" << json_object_get_string(jenctype) << "\""; out << ">"; // Form fields json_object *jfields = nullptr; if(json_object_object_get_ex(jform, "fields", &jfields)){ int flen = json_object_array_length(jfields); // Field rendering helper (used by both flat fields and tabs) auto renderFieldArray = [&](json_object *jflds){ int flen = json_object_array_length(jflds); for(int f=0; f<flen; ++f){ json_object *jf = json_object_array_get_idx(jfields, f); json_object *jf = json_object_array_get_idx(jflds, f); json_object *jname=nullptr, *jtype=nullptr, *jlabel=nullptr, *jvalue=nullptr, *joptions=nullptr; json_object_object_get_ex(jf, "name", &jname); json_object_object_get_ex(jf, "type", &jtype); Loading Loading @@ -801,6 +800,55 @@ static void renderSettingsJson(json_object *jroot, libhtmlpp::HtmlString &out, c } out << "</div>"; } }; // Tabs support json_object *jtabs = nullptr; json_object_object_get_ex(jform, "tabs", &jtabs); if(jtabs){ int tlen = json_object_array_length(jtabs); out << "<style>" << ".set-tabs{display:flex;gap:0;border-bottom:2px solid var(--blogi-border,#3a3f44);margin-bottom:12px;}" << ".set-tab-btn{padding:8px 18px;border:none;background:none;color:var(--blogi-text-muted,#aaa);cursor:pointer;font-size:0.95em;border-bottom:2px solid transparent;margin-bottom:-2px;}" << ".set-tab-btn:hover{color:var(--blogi-text,#eee);}" << ".set-tab-btn.active{color:var(--blogi-accent,#3ad43a);border-bottom-color:var(--blogi-accent,#3ad43a);}" << ".set-tab-panel{display:none;}" << ".set-tab-panel.active{display:block;}" << "</style>"; out << "<div class=\"set-tabs\">"; for(int t=0; t<tlen; ++t){ json_object *jtab = json_object_array_get_idx(jtabs, t); json_object *jtlabel = nullptr; json_object_object_get_ex(jtab, "label", &jtlabel); out << "<button type=\"button\" class=\"set-tab-btn" << (t==0?" active":"") << "\" data-tab=\"" << t << "\">" << (jtlabel ? json_object_get_string(jtlabel) : "") << "</button>"; } out << "</div>"; for(int t=0; t<tlen; ++t){ json_object *jtab = json_object_array_get_idx(jtabs, t); json_object *jtfields = nullptr; json_object_object_get_ex(jtab, "fields", &jtfields); out << "<div class=\"set-tab-panel" << (t==0?" active":"") << "\" data-tab=\"" << t << "\">"; if(jtfields) renderFieldArray(jtfields); out << "</div>"; } out << "<script>" << "document.querySelectorAll('.set-tab-btn').forEach(function(btn){" << "btn.addEventListener('click',function(){" << "document.querySelectorAll('.set-tab-btn').forEach(function(b){b.classList.remove('active');});" << "document.querySelectorAll('.set-tab-panel').forEach(function(p){p.classList.remove('active');});" << "btn.classList.add('active');" << "document.querySelector('.set-tab-panel[data-tab=\"'+btn.dataset.tab+'\"]').classList.add('active');" << "});" << "});" << "</script>"; } // Form fields (flat, no tabs) json_object *jfields = nullptr; if(!jtabs && json_object_object_get_ex(jform, "fields", &jfields)){ renderFieldArray(jfields); } // Form-embedded table (e.g. navbar items inside a form) Loading
src/theme.cpp +100 −87 Original line number Diff line number Diff line Loading @@ -693,9 +693,15 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_object_add(jform, "method", json_object_new_string("POST")); json_object_object_add(jform, "action", json_object_new_string(req.getRequestURL().c_str())); json_object *jtabs = json_object_new_array(); // --- Tab 1: Logo --- { json_object *jtab = json_object_new_object(); json_object_object_add(jtab, "label", json_object_new_string("Logo")); json_object *jfields = json_object_new_array(); // Section header: Logo // Logo heading with preview { std::string logoUrl = getLogoUrl(tid); std::string curUrl; Loading @@ -711,7 +717,7 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_object_add(jf, "label", json_object_new_string(logoLabel.c_str())); json_object_array_add(jfields, jf); } // Logo URL (from media plugin — upload via Media settings, paste URL here) // Logo URL { std::string curUrl; try { getConfig(*_Config.TDatabase[tid], "THEME_LOGO_URL", curUrl); } catch (...) {} Loading @@ -736,15 +742,17 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_object_add(jf, "value", json_object_new_string(curWidth.c_str())); json_object_array_add(jfields, jf); } // Section header: Dark { json_object *jf = json_object_new_object(); json_object_object_add(jf, "type", json_object_new_string("heading")); json_object_object_add(jf, "label", json_object_new_string("Dark Mode Colors")); json_object_array_add(jfields, jf); json_object_object_add(jtab, "fields", jfields); json_object_array_add(jtabs, jtab); } // Dark color fields // --- Tab 2: Dark Mode Colors --- { json_object *jtab = json_object_new_object(); json_object_object_add(jtab, "label", json_object_new_string("Dark Colors")); json_object *jfields = json_object_new_array(); for(auto &c : colors){ std::string val; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_DARK_") + c.suffix, val); } catch(...) {} Loading @@ -763,15 +771,16 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_array_add(jfields, jf); } // Section header: Light { json_object *jf = json_object_new_object(); json_object_object_add(jf, "type", json_object_new_string("heading")); json_object_object_add(jf, "label", json_object_new_string("Light Mode Colors")); json_object_array_add(jfields, jf); json_object_object_add(jtab, "fields", jfields); json_object_array_add(jtabs, jtab); } // Light color fields // --- Tab 3: Light Mode Colors --- { json_object *jtab = json_object_new_object(); json_object_object_add(jtab, "label", json_object_new_string("Light Colors")); json_object *jfields = json_object_new_array(); for(auto &c : colors){ std::string val; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_LIGHT_") + c.suffix, val); } catch(...) {} Loading @@ -790,7 +799,11 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & json_object_array_add(jfields, jf); } json_object_object_add(jform, "fields", jfields); json_object_object_add(jtab, "fields", jfields); json_object_array_add(jtabs, jtab); } json_object_object_add(jform, "tabs", jtabs); json_object_object_add(jform, "submit", json_object_new_string("save")); json_object_object_add(jform, "reset_name", json_object_new_string("theme_reset")); json_object_object_add(jform, "reset_label", json_object_new_string("Reset to Defaults")); Loading