improve frontend of emacs, ckeditor, tinymce, nicedit, meta and env functions

Improves in emacs:
- use htmx to send content to the controller
- show txt and formatted_txt content in the second panel
- show two tabs if "tabs" winix parameter is used
- add an option to show either one or two panels
- correctly resize the editor window (F11) when two panels are shown

Improves in ckeditor:
- use htmx to send content to the controller
- do not check automatically for ckeditor update

Improves in tinymce/nicedit/meta/env:
- use htmx to send content to the controller

while here:
- change PascalCase to snake_case in meta/env controllers
- update CodeMirror editor to 5.65.16
- udpate Showdown (markdown to html converter) to 2.1.0
This commit is contained in:
2024-07-20 15:13:27 +02:00
parent 89b37db48e
commit e63838faeb
27 changed files with 1075 additions and 496 deletions

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2014, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,14 +36,10 @@
#include "functions.h"
namespace Winix
namespace Winix::Fun
{
namespace Fun
{
Ckeditor::Ckeditor()
{
fun.url = L"ckeditor";
@@ -57,7 +53,16 @@ void Ckeditor::init()
bool Ckeditor::has_access()
{
return functions->fun_emacs.has_access();
FunctionBase * emacs = functions->Find(L"emacs");
if( emacs )
{
return emacs->has_access();
}
else
{
return false;
}
}
@@ -73,13 +78,20 @@ void Ckeditor::make_get()
void Ckeditor::make_post()
{
functions->fun_emacs.make_post();
}
FunctionBase * emacs = functions->Find(L"emacs");
if( emacs )
{
emacs->make_post();
}
else
{
log << log2 << "Ckeditor: I cannot save your content, there is no emacs function available" << logend;
}
}
} // namespace
} // namespace Winix

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2011-2014, Tomasz Sowa
* Copyright (c) 2011-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,11 +37,8 @@
#include "functionbase.h"
namespace Winix
{
namespace Fun
namespace Winix::Fun
{
@@ -50,16 +47,15 @@ class Ckeditor : public FunctionBase
public:
Ckeditor();
void init();
bool has_access();
void make_get();
void make_post();
void init() override;
bool has_access() override;
void make_get() override;
void make_post() override;
};
} // namespace
} // namespace Winix
#endif

View File

@@ -37,14 +37,10 @@
#include "functions.h"
namespace Winix
namespace Winix::Fun
{
namespace Fun
{
Emacs::Emacs()
{
fun.url = L"emacs";
@@ -128,13 +124,30 @@ return WINIX_NOTIFY_CODE_ADD;
}
// IMPROVEME
// make some kind of utils and put this method there
// because this method is used from ckeditor and other editors too
void Emacs::push_url_to_current_function(const wchar_t * local_url)
{
if( cur->request->is_htmx_request )
{
pt::WTextStream url;
if( cur->request->IsParam(L"tabs") )
prepare_current_function(L"/tabs", url);
else
prepare_current_function(nullptr, url);
cur->request->out_headers.add(Header::hx_push_url, url);
}
}
/*
* this make_post() is used from Ckeditor, Tinymce and Nicedit as well
*/
void Emacs::make_post()
{
bool status = false;
bool adding = !cur->request->is_item;
std::wstring old_url;
if( !adding )
old_url = cur->request->item.url;
@@ -163,38 +176,29 @@ void Emacs::make_post()
}
cur->request->status = status ? WINIX_ERR_OK : WINIX_ERR_PERMISSION_DENIED;
answer.add(L"status", status);
if( status )
{
if( adding )
{
system->RedirectToLastFunction(nullptr, false);
answer.add(L"redirect_to", cur->request->redirect_to);
if( cur->request->container_type != Request::ContainerType::container_raw )
{
cur->request->redirect_to.clear();
}
}
functions->CheckSpecialFile(cur->request->item);
bool was_url_changed = (adding || cur->request->item.url != old_url);
redirect_if_needed(was_url_changed);
}
cur->request->models.Add(L"answer", answer);
if( adding )
{
// App::AddDefaultModels() is called before make_post() and didn't see the item yet
cur->request->models.Add(L"item", cur->request->item);
}
}
void Emacs::clear()
{
answer.clear();
}
} // namespace
} // namespace Winix

View File

@@ -37,11 +37,8 @@
#include "functionbase.h"
namespace Winix
{
namespace Fun
namespace Winix::Fun
{
@@ -50,25 +47,21 @@ class Emacs : public FunctionBase
public:
Emacs();
bool has_access();
void make_post();
bool has_access() override;
void make_post() override;
private:
bool has_emacs_access(const Item & item);
void clear();
void clear() override;
int notify_code_edit();
int notify_code_add();
std::wstring old_url;
pt::Space answer;
void push_url_to_current_function(const wchar_t * local_url = nullptr) override;
};
} // namespace
} // namespace Winix
#endif

View File

@@ -37,13 +37,10 @@
#include "core/misc.h"
namespace Winix
namespace Winix::Fun
{
namespace Fun
{
Env::Env()
{
fun.url = L"env";
@@ -68,15 +65,15 @@ return true;
bool Env::Parse(const std::wstring & env_str)
bool Env::parse(const std::wstring & env_str)
{
return (conf_parser.parse_space(env_str, space) == pt::SpaceParser::ok);
}
bool Env::EditAdminEnv(const std::wstring & env_str)
bool Env::edit_admin_env(const std::wstring & env_str)
{
if( Parse(env_str) )
if( parse(env_str) )
{
user_wrapper.user->admin_env = space;
@@ -102,9 +99,9 @@ return false;
}
bool Env::EditEnv(const std::wstring & env_str)
bool Env::edit_env(const std::wstring & env_str)
{
if( Parse(env_str) )
if( parse(env_str) )
{
user_wrapper.user->env = space;
@@ -131,7 +128,7 @@ return false;
void Env::SaveEnv()
void Env::save_env()
{
const std::wstring & env_str = cur->request->PostVar(L"envvar");
bool status = false;
@@ -140,27 +137,29 @@ void Env::SaveEnv()
{
if( cur->session->puser->is_super_user )
{
status = EditAdminEnv(env_str);
status = edit_admin_env(env_str);
if( status )
{
//slog << loginfo << T(L"env_admin_changed_successfully") << logend;
redirect_if_needed();
}
}
}
else
{
status = EditEnv(env_str);
status = edit_env(env_str);
if( status )
{
//slog << loginfo << T(L"env_changed_successfully") << logend;
redirect_if_needed();
}
}
}
void Env::RegisterModels()
void Env::register_models()
{
cur->request->models.Add(L"users", system->users);
cur->request->models.Add(L"env_user", user_wrapper);
@@ -192,7 +191,7 @@ void Env::make_post()
{
if( user_wrapper.user )
{
SaveEnv();
save_env();
}
else
{
@@ -201,7 +200,7 @@ void Env::make_post()
}
}
RegisterModels();
register_models();
}
@@ -210,7 +209,7 @@ void Env::make_get()
user_wrapper.user = cur->session->puser;
user_wrapper.set_connector(model_connector);
RegisterModels();
register_models();
}
@@ -223,6 +222,3 @@ void Env::clear()
} // namespace
} // namespace Winix

View File

@@ -40,11 +40,7 @@
#include "space/spaceparser.h"
namespace Winix
{
namespace Fun
namespace Winix::Fun
{
@@ -54,10 +50,10 @@ public:
Env();
bool has_access();
void make_post();
void make_get();
void clear();
bool has_access() override;
void make_post() override;
void make_get() override;
void clear() override;
private:
@@ -66,13 +62,13 @@ private:
pt::Space space;
UserWrapper user_wrapper;
bool EditAdminEnv(const std::wstring & env_str);
bool EditEnv(const std::wstring & env_str);
bool edit_admin_env(const std::wstring & env_str);
bool edit_env(const std::wstring & env_str);
bool Parse(const std::wstring & env_str);
void SaveEnv();
bool parse(const std::wstring & env_str);
void save_env();
void RegisterModels();
void register_models();
};
@@ -80,6 +76,4 @@ private:
} // namespace
} // namespace Winix
#endif

View File

@@ -659,6 +659,115 @@ std::wstring FunctionBase::prepare_doc_url(const std::wstring & local_url)
}
void FunctionBase::prepare_current_dir(const wchar_t * local_url, pt::WTextStream & url)
{
prepare_doc_url(nullptr, url);
for(Item * dir : cur->request->dir_tab)
{
if( !dir->url.empty() )
url << L"/" << dir->url;
}
if( local_url )
{
url << local_url;
}
}
void FunctionBase::prepare_current_dir(const wchar_t * local_url, std::wstring & url)
{
pt::WTextStream stream;
prepare_current_dir(local_url, stream);
stream.to_str(url);
}
std::wstring FunctionBase::prepare_current_dir(const wchar_t * local_url)
{
std::wstring url;
prepare_current_dir(local_url, url);
return url;
}
std::wstring FunctionBase::prepare_current_dir(const std::wstring & local_url)
{
return prepare_current_dir(local_url.c_str());
}
void FunctionBase::prepare_current_item(const wchar_t * local_url, pt::WTextStream & url)
{
prepare_current_dir(nullptr, url);
if( cur->request->is_item )
url << L"/" << cur->request->item.url;
if( local_url )
{
url << local_url;
}
}
void FunctionBase::prepare_current_item(const wchar_t * local_url, std::wstring & url)
{
pt::WTextStream stream;
prepare_current_item(local_url, stream);
stream.to_str(url);
}
std::wstring FunctionBase::prepare_current_item(const wchar_t * local_url)
{
std::wstring url;
prepare_current_item(local_url, url);
return url;
}
std::wstring FunctionBase::prepare_current_item(const std::wstring & local_url)
{
return prepare_current_item(local_url.c_str());
}
void FunctionBase::prepare_current_function(const wchar_t * local_url, pt::WTextStream & url)
{
prepare_current_item(nullptr, url);
url << L"/" << fun.url;
if( local_url )
{
url << local_url;
}
}
void FunctionBase::prepare_current_function(const wchar_t * local_url, std::wstring & url)
{
pt::WTextStream stream;
prepare_current_function(local_url, stream);
stream.to_str(url);
}
std::wstring FunctionBase::prepare_current_function(const wchar_t * local_url)
{
std::wstring url;
prepare_current_function(local_url, url);
return url;
}
std::wstring FunctionBase::prepare_current_function(const std::wstring & local_url)
{
return prepare_current_function(local_url.c_str());
}
void FunctionBase::redirect_to(const wchar_t * url, bool append_domain)
{
if( cur->request->is_htmx_request )
@@ -674,16 +783,19 @@ void FunctionBase::redirect_to(const wchar_t * url, bool append_domain)
}
else
{
if( append_domain )
if( cur->request->container_type == Request::ContainerType::container_raw )
{
prepare_doc_url(url, cur->request->redirect_to);
}
else
{
cur->request->redirect_to = url;
}
if( append_domain )
{
prepare_doc_url(url, cur->request->redirect_to);
}
else
{
cur->request->redirect_to = url;
}
cur->request->redirect_type = Header::status_303_see_other;
cur->request->redirect_type = Header::status_303_see_other;
}
}
}
@@ -899,8 +1011,93 @@ void FunctionBase::update_content(const wchar_t * frame, const wchar_t * dom_tar
void FunctionBase::close_modal_dialogs()
{
pt::Space & trigger = cur->request->out_headers.get_add_space(Header::hx_trigger);
trigger.add(L"winix:closedialogs", true);
if( cur->request->is_htmx_request )
{
pt::Space & trigger = cur->request->out_headers.get_add_space(Header::hx_trigger);
trigger.add(L"winix:closedialogs", true);
}
}
void FunctionBase::push_url_to_current_dir(const wchar_t * local_url)
{
if( cur->request->is_htmx_request )
{
pt::WTextStream url;
prepare_current_dir(local_url, url);
cur->request->out_headers.add(Header::hx_push_url, url);
}
}
void FunctionBase::push_url_to_current_item(const wchar_t * local_url)
{
if( cur->request->is_htmx_request )
{
pt::WTextStream url;
prepare_current_item(local_url, url);
cur->request->out_headers.add(Header::hx_push_url, url);
}
}
void FunctionBase::push_url_to_current_function(const wchar_t * local_url)
{
if( cur->request->is_htmx_request )
{
pt::WTextStream url;
prepare_current_function(local_url, url);
cur->request->out_headers.add(Header::hx_push_url, url);
}
}
void FunctionBase::redirect_to_current_dir()
{
pt::WTextStream url;
prepare_current_dir(nullptr, url);
redirect_to(url, false);
}
void FunctionBase::redirect_to_current_item()
{
pt::WTextStream url;
prepare_current_item(nullptr, url);
redirect_to(url, false);
}
void FunctionBase::redirect_to_current_function()
{
pt::WTextStream url;
prepare_current_function(nullptr, url);
redirect_to(url, false);
}
void FunctionBase::redirect_if_needed(bool was_url_changed)
{
if( cur->request->container_type == Request::ContainerType::container_raw )
{
/* save_and_close is not used at the moment anywhere in templates */
if( cur->request->post_in.has_key(L"save_and_close") )
{
redirect_to_current_item();
}
else
if( was_url_changed )
{
if( cur->request->is_htmx_request )
{
push_url_to_current_function();
}
else
{
system->RedirectToLastFunction(nullptr, false);
}
}
}
}

View File

@@ -185,6 +185,21 @@ public:
virtual std::wstring prepare_doc_url(const wchar_t * local_url = nullptr);
virtual std::wstring prepare_doc_url(const std::wstring & local_url);
virtual void prepare_current_dir(const wchar_t * local_url, pt::WTextStream & url);
virtual void prepare_current_dir(const wchar_t * local_url, std::wstring & url);
virtual std::wstring prepare_current_dir(const wchar_t * local_url = nullptr);
virtual std::wstring prepare_current_dir(const std::wstring & local_url);
virtual void prepare_current_item(const wchar_t * local_url, pt::WTextStream & url);
virtual void prepare_current_item(const wchar_t * local_url, std::wstring & url);
virtual std::wstring prepare_current_item(const wchar_t * local_url);
virtual std::wstring prepare_current_item(const std::wstring & local_url);
virtual void prepare_current_function(const wchar_t * local_url, pt::WTextStream & url);
virtual void prepare_current_function(const wchar_t * local_url, std::wstring & url);
virtual std::wstring prepare_current_function(const wchar_t * local_url);
virtual std::wstring prepare_current_function(const std::wstring & local_url);
virtual void redirect_to(const wchar_t * url, bool append_domain = true);
virtual void redirect_to(const std::wstring & url, bool append_domain = true);
virtual void redirect_to(const pt::WTextStream & url, bool append_domain = true);
@@ -211,6 +226,16 @@ public:
virtual void close_modal_dialogs();
virtual void push_url_to_current_dir(const wchar_t * local_url = nullptr);
virtual void push_url_to_current_item(const wchar_t * local_url = nullptr);
virtual void push_url_to_current_function(const wchar_t * local_url = nullptr);
virtual void redirect_to_current_dir();
virtual void redirect_to_current_item();
virtual void redirect_to_current_function();
virtual void redirect_if_needed(bool was_url_changed = false);
/*
* DEPRECATED

View File

@@ -36,13 +36,10 @@
#include "core/log.h"
namespace Winix
namespace Winix::Fun
{
namespace Fun
{
Meta::Meta()
{
fun.url = L"meta";
@@ -60,7 +57,7 @@ bool Meta::has_access()
bool Meta::Parse(const std::wstring & meta_str)
bool Meta::parse(const std::wstring & meta_str)
{
return (conf_parser.parse_space(meta_str, space) == pt::SpaceParser::ok);
}
@@ -68,9 +65,9 @@ bool Meta::Parse(const std::wstring & meta_str)
bool Meta::EditAdminMeta(Item & item, const std::wstring & meta_str)
bool Meta::edit_admin_meta(Item & item, const std::wstring & meta_str)
{
if( Parse(meta_str) )
if( parse(meta_str) )
{
item.propagate_connector();
item.item_content.admin_meta = space;
@@ -99,9 +96,9 @@ return false;
bool Meta::EditMeta(Item & item, const std::wstring & meta_str)
bool Meta::edit_meta(Item & item, const std::wstring & meta_str)
{
if( Parse(meta_str) )
if( parse(meta_str) )
{
item.propagate_connector();
item.item_content.meta = space;
@@ -130,7 +127,7 @@ return false;
void Meta::ChangeAdminMeta()
void Meta::change_admin_meta()
{
// IMPROVE ME we need to show an error msg if the user is not an admin
@@ -138,23 +135,23 @@ void Meta::ChangeAdminMeta()
{
const std::wstring & meta_str = cur->request->PostVar(L"itemmeta");
if( EditAdminMeta(*cur->request->last_item, meta_str) )
if( edit_admin_meta(*cur->request->last_item, meta_str) )
{
system->RedirectToLastItem();
redirect_if_needed();
}
}
}
void Meta::ChangeMeta()
void Meta::change_meta()
{
if( system->HasWriteAccess(*cur->request->last_item) )
{
const std::wstring & meta_str = cur->request->PostVar(L"itemmeta");
if( EditMeta(*cur->request->last_item, meta_str) )
if( edit_meta(*cur->request->last_item, meta_str) )
{
system->RedirectToLastItem();
redirect_if_needed();
}
}
}
@@ -164,9 +161,9 @@ void Meta::ChangeMeta()
void Meta::make_post()
{
if( cur->request->IsParam(L"a") )
ChangeAdminMeta();
change_admin_meta();
else
ChangeMeta();
change_meta();
}
@@ -174,5 +171,3 @@ void Meta::make_post()
} // namespace
} // namespace Winix

View File

@@ -38,11 +38,8 @@
#include "functionbase.h"
#include "space/spaceparser.h"
namespace Winix
{
namespace Fun
namespace Winix::Fun
{
@@ -52,26 +49,25 @@ public:
Meta();
bool has_access();
void make_post();
bool has_access() override;
void make_post() override;
bool EditAdminMeta(Item & item, const std::wstring & meta_str);
bool EditMeta(Item & item, const std::wstring & meta_str);
private:
pt::SpaceParser conf_parser;
pt::Space space;
bool Parse(const std::wstring & meta_str);
void ChangeAdminMeta();
void ChangeMeta();
bool edit_admin_meta(Item & item, const std::wstring & meta_str);
bool edit_meta(Item & item, const std::wstring & meta_str);
bool parse(const std::wstring & meta_str);
void change_admin_meta();
void change_meta();
};
} // namespace
} // namespace Winix
#endif

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2011-2014, Tomasz Sowa
* Copyright (c) 2011-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,14 +36,10 @@
#include "functions.h"
namespace Winix
namespace Winix::Fun
{
namespace Fun
{
Nicedit::Nicedit()
{
fun.url = L"nicedit";
@@ -52,19 +48,36 @@ Nicedit::Nicedit()
bool Nicedit::has_access()
{
return functions->fun_emacs.has_access();
FunctionBase * emacs = functions->Find(L"emacs");
if( emacs )
{
return emacs->has_access();
}
else
{
return false;
}
}
void Nicedit::make_post()
{
functions->fun_emacs.make_post();
}
FunctionBase * emacs = functions->Find(L"emacs");
if( emacs )
{
emacs->make_post();
}
else
{
log << log2 << "Nicedit: I cannot save your content, there is no emacs function available" << logend;
}
}
} // namespace
} // namespace Winix

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2011-2014, Tomasz Sowa
* Copyright (c) 2011-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,11 +37,8 @@
#include "functionbase.h"
namespace Winix
{
namespace Fun
namespace Winix::Fun
{
@@ -50,14 +47,13 @@ class Nicedit : public FunctionBase
public:
Nicedit();
bool has_access();
void make_post();
bool has_access() override;
void make_post() override;
};
} // namespace
} // namespace Winix
#endif

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2021, Tomasz Sowa
* Copyright (c) 2008-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,13 +36,10 @@
#include "functions.h"
namespace Winix
namespace Winix::Fun
{
namespace Fun
{
Tinymce::Tinymce()
{
fun.url = L"tinymce";
@@ -57,7 +54,16 @@ void Tinymce::init()
bool Tinymce::has_access()
{
return functions->fun_emacs.has_access();
FunctionBase * emacs = functions->Find(L"emacs");
if( emacs )
{
return emacs->has_access();
}
else
{
return false;
}
}
@@ -71,10 +77,18 @@ void Tinymce::make_get()
}
void Tinymce::make_post()
{
functions->fun_emacs.make_post();
FunctionBase * emacs = functions->Find(L"emacs");
if( emacs )
{
emacs->make_post();
}
else
{
log << log2 << "Tinymce: I cannot save your content, there is no emacs function available" << logend;
}
}
@@ -82,5 +96,3 @@ void Tinymce::make_post()
} // namespace
} // namespace Winix

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2010-2024, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,11 +37,8 @@
#include "functionbase.h"
namespace Winix
{
namespace Fun
namespace Winix::Fun
{
@@ -50,16 +47,14 @@ class Tinymce : public FunctionBase
public:
Tinymce();
void init();
bool has_access();
void make_get();
void make_post();
void init() override;
bool has_access() override;
void make_get() override;
void make_post() override;
};
} // namespace
} // namespace Winix
#endif