New York Transit Line is finally usable at least a little. Integrated it with frontend
This commit is contained in:
parent
393703b0b2
commit
dd806a5633
@ -1,31 +1,32 @@
|
||||
{% ELDEF main JSON pres %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Список Чат-Комнат</title>
|
||||
<title>{% WRITE pres.phr.decl.list-of-chat-rooms %}</title>
|
||||
<link rel="stylesheet" href="/assets/css/list-rooms.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 style="color: white;">Выберите Чат-Комнату</h1>
|
||||
<h1 style="color: white;">{% WRITE pres.phr.decl.select-chat-room %}</h1>
|
||||
<ul class="room-list">
|
||||
<!-- Здесь будет список комнат -->
|
||||
</ul>
|
||||
<button class="create-room-button" onclick="openCreateRoomModal()">Создать Комнату</button>
|
||||
<button class="create-room-button" onclick="openCreateRoomModal()">{% WRITE pres.phr.act.create-room %}</button>
|
||||
</div>
|
||||
|
||||
<div id="passwordModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<span class="close" onclick="closeModal()">×</span>
|
||||
<h2>Введите Пароль</h2>
|
||||
<h2>VVedite parol</h2> <!-- Nam ne nuzhen parol ot komnat -->
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="password" id="roomPassword" placeholder="Пароль">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="join-button" onclick="validatePassword()">Подтвердить</button>
|
||||
<button class="join-button" onclick="validatePassword()">{% WRITE pres.phr.act.confirm %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -35,14 +36,14 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<span class="close" onclick="closeCreateRoomModal()">×</span>
|
||||
<h2>Создать Комнату</h2>
|
||||
<h2>{% WRITE pres.phr.decl.create-room %}</h2>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="text" id="newRoomName" placeholder="Название комнаты">
|
||||
<input type="password" id="newRoomPassword" placeholder="Пароль">
|
||||
<input type="text" id="newRoomName" placeholder="{% WRITE pres.phr.decl.name-of-room %}">
|
||||
<input type="password" id="newRoomPassword" placeholder="Пароль"> <!-- Fedya, nam ne nuzhen parol -->
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="join-button" onclick="createRoom()">Создать</button>
|
||||
<button class="join-button" onclick="createRoom()">{% WRITE pres.phr.act.create %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -50,3 +51,4 @@
|
||||
<script src="/assets/js/list-rooms.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{% ENDELDEF %}
|
@ -1,3 +1,32 @@
|
||||
{
|
||||
"name": "Web chat"
|
||||
"presentation": {
|
||||
"instance-identity": {
|
||||
"top-title": "Вэб чат ИУ9"
|
||||
},
|
||||
"phr": {
|
||||
"decl": {
|
||||
"list-of-chat-rooms": "Список Чат-Комнат",
|
||||
"select-chat-room": "Выберете чат комнату",
|
||||
"name-of-room": "Название комнаты",
|
||||
"create-room": "Создать комнату"
|
||||
},
|
||||
"act": {
|
||||
"create-room": "Создать комнату",
|
||||
"confirm": "Подтвердить",
|
||||
"create": "Создать"
|
||||
}
|
||||
}
|
||||
},
|
||||
"assets": "./assets",
|
||||
"limits": {
|
||||
"max-users": 100000,
|
||||
"max-rooms": 100000,
|
||||
"max-messages": 10000000000000,
|
||||
"storage-size-limit": 100000000000
|
||||
},
|
||||
"server": {
|
||||
"workers": 8,
|
||||
"http-listen": ["127.0.0.1:1025"],
|
||||
"command-listen": []
|
||||
}
|
||||
}
|
@ -82,10 +82,10 @@ namespace een9 {
|
||||
|
||||
struct WorkersEnv {
|
||||
WorkersEnvCommon& wtec;
|
||||
int id;
|
||||
worker_id_t id;
|
||||
ClientRequestParser_WorkerBuffers personal_parser_buffer;
|
||||
|
||||
explicit WorkersEnv(WorkersEnvCommon& wtec, int id): wtec(wtec), id(id), personal_parser_buffer(wtec.parser_programs){}
|
||||
explicit WorkersEnv(WorkersEnvCommon& wtec, worker_id_t id): wtec(wtec), id(id), personal_parser_buffer(wtec.parser_programs){}
|
||||
};
|
||||
|
||||
// todo: add timeout for multiple bytes, add more settings
|
||||
@ -125,7 +125,7 @@ namespace een9 {
|
||||
|
||||
void process_connection(const SlaveTask& task, WorkersEnv& wte) {
|
||||
ClientRequest client_request = process_connection_input(task.fd(), task.s_tips, wte);
|
||||
std::string server_response = wte.wtec.guest_core(task, client_request);
|
||||
std::string server_response = wte.wtec.guest_core(task, client_request, wte.id);
|
||||
process_connection_output(task.fd(), server_response);
|
||||
}
|
||||
|
||||
@ -149,6 +149,7 @@ namespace een9 {
|
||||
} catch (const std::exception& e) {
|
||||
printf("Client request procession failure in worker\n");
|
||||
printf("%s\n", e.what());
|
||||
/* Under mysterious some circumstances, in this place destructor of string in SystemError causes segfault. I can't fix that */
|
||||
}
|
||||
}
|
||||
printf("Worker finished\n");
|
||||
@ -166,7 +167,7 @@ namespace een9 {
|
||||
std::vector<pthread_t> workers(params.slave_number);
|
||||
std::vector<uptr<WorkersEnv>> wtes(params.slave_number);
|
||||
for (size_t i = 0; i < params.slave_number; i++) {
|
||||
wtes[i] = std::make_unique<WorkersEnv>(wtec, i);
|
||||
wtes[i] = std::make_unique<WorkersEnv>(wtec, (worker_id_t)i);
|
||||
}
|
||||
for (size_t i = 0; i < params.slave_number; i++) {
|
||||
pthread_create(&workers[i], NULL, worker_func, wtes[i].get());
|
||||
|
@ -29,8 +29,10 @@ namespace een9 {
|
||||
EEN9_ServerTips s_tips;
|
||||
};
|
||||
|
||||
typedef int worker_id_t;
|
||||
|
||||
/* guest_core function must not throw anything that is not derived from std::exception */
|
||||
typedef std::function<std::string(const SlaveTask&, const ClientRequest&)> guest_core_t;
|
||||
typedef std::function<std::string(const SlaveTask&, const ClientRequest&, worker_id_t worker_id)> guest_core_t;
|
||||
|
||||
struct ServersConfiguration {
|
||||
size_t critical_load_1 = 90;
|
||||
|
@ -447,10 +447,8 @@ namespace nytl {
|
||||
mediocre_operator("str2code");
|
||||
goto ya_e_ya_h_i_ya_g_d_o;;
|
||||
}
|
||||
if (op == "ENDELDEF") {
|
||||
ASSERT(myself == gone_for_nothing, "Unexpected end of element");
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
if (!result.parts.empty()) {
|
||||
auto prepare_to_depart_parts = [&]() {
|
||||
assert(!result.parts.empty());
|
||||
if (result.parts[0].type == ElementPart::p_code)
|
||||
result.parts[0].when_code.lines = clement_lstrip(result.parts[0].when_code.lines);
|
||||
if (result.parts.back().type == ElementPart::p_code)
|
||||
@ -467,7 +465,11 @@ namespace nytl {
|
||||
result.parts[i].when_code.lines = one_part_cut_excess_tab(result.parts[i].when_code.lines, i, N, cut);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (op == "ENDELDEF") {
|
||||
ASSERT(myself == gone_for_nothing, "Unexpected end of element");
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
prepare_to_depart_parts();
|
||||
return NULL;
|
||||
}
|
||||
if (op == "ENDFOR") {
|
||||
@ -485,10 +487,13 @@ namespace nytl {
|
||||
THROW("Expected LF, NOLF or end of magic block");
|
||||
}
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
prepare_to_depart_parts();
|
||||
return NULL;
|
||||
}
|
||||
if (op == "ENDREF") {
|
||||
assert(myself == gone_for_ref);
|
||||
skip_magic_block_end(ctx, syntax);
|
||||
prepare_to_depart_parts();
|
||||
return NULL;
|
||||
}
|
||||
THROW("Unknown operator. Expected FOR, REF, PUT, WRITE, ROUGHINSERT, ENDELDEF, ENDFOR, ENDREF");
|
||||
|
@ -9,22 +9,25 @@ namespace nytl {
|
||||
std::string result;
|
||||
size_t cur_line_width = 0;
|
||||
|
||||
/* Fix idea: get rid of newlined_somewhere */
|
||||
void append(const std::string& text, size_t wsp_before_newlines, bool& newlined_somewhere) {
|
||||
size_t n = result.size();
|
||||
size_t m = text.size();
|
||||
result.reserve(n + m);
|
||||
for (size_t i = 0; i < m; i++) {
|
||||
result += text[i];
|
||||
if (text[i] == '\n') {
|
||||
newlined_somewhere = true;
|
||||
cur_line_width = 0;
|
||||
} else {
|
||||
if (cur_line_width == 0 && newlined_somewhere) {
|
||||
// newlined_somewhere = true;
|
||||
|
||||
result.resize(result.size() + wsp_before_newlines, ' ');
|
||||
cur_line_width = wsp_before_newlines;
|
||||
}
|
||||
} else {
|
||||
// if (cur_line_width == 0 && newlined_somewhere) {
|
||||
// result.resize(result.size() + wsp_before_newlines, ' ');
|
||||
// cur_line_width = wsp_before_newlines;
|
||||
// }
|
||||
cur_line_width++;
|
||||
}
|
||||
result += text[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -88,7 +91,7 @@ namespace nytl {
|
||||
RFrame_OverArray(const ElementPart::when_for_put_S& part, size_t multiline_put_start, const std::vector<LocalVarValue> &saved_args,
|
||||
const std::vector<json::JSON> &arr): RFrame_OverJSON(part, multiline_put_start, saved_args),
|
||||
arr(arr) {
|
||||
if (part.where_key_var < 0)
|
||||
if (part.where_key_var >= 0)
|
||||
additional_json_wrapper = json::JSON(json::Integer(0l));
|
||||
}
|
||||
|
||||
@ -106,7 +109,7 @@ namespace nytl {
|
||||
const std::map<std::string, json::JSON> &dict): RFrame_OverJSON(part, multiline_put_start, saved_args_plus_iter),
|
||||
dict(dict) {
|
||||
it = dict.begin();
|
||||
if (part.where_key_var < 0)
|
||||
if (part.where_key_var >= 0)
|
||||
addition_json_wrapper = json::JSON("");
|
||||
}
|
||||
|
||||
@ -151,6 +154,8 @@ namespace nytl {
|
||||
std::string escaped_json = escape(json::generate_str(*X, json::print_pretty));
|
||||
rstrip(escaped_json);
|
||||
append(escaped_json, result);
|
||||
} else if (name == "jesccomp") {
|
||||
append(escape(json::generate_str(*X, json::print_compact)), result);
|
||||
} else if (name == "str2text") {
|
||||
ASSERT(X->isString(), "str2text takes json string");
|
||||
append(escape(X->asString()), result);
|
||||
@ -215,10 +220,10 @@ namespace nytl {
|
||||
}
|
||||
|
||||
uptr<RFrame> RFrame_OverDictionary::toMe(bool returned, RFrame_passed) {
|
||||
if (returned && part.line_feed)
|
||||
append("\n", result);
|
||||
if (it == dict.end())
|
||||
return NULL;
|
||||
if (returned && part.line_feed)
|
||||
append("\n", result);
|
||||
if (part.where_key_var > -1) {
|
||||
addition_json_wrapper.asString() = it->first;
|
||||
saved_args_plus_iter[part.where_key_var] = {true, "", &addition_json_wrapper};
|
||||
|
@ -112,7 +112,10 @@ namespace nytl {
|
||||
void Templater::update() {
|
||||
elements = {
|
||||
{"jesc", Element{{json::JSON(true)}, true}},
|
||||
{"jesccomp", Element{{json::JSON(true)}, true}},
|
||||
/* str2text base element has a dedicated operator - WRITE */
|
||||
{"str2text", Element{{json::JSON(true)}, true}},
|
||||
/* str2code base element has a dedicated operator - ROUGHINSERT */
|
||||
{"str2code", Element{{json::JSON(true)}, true}},
|
||||
};
|
||||
std::vector<InterestingFile> intersting_files = indexing_detour(settings.det);
|
||||
|
@ -0,0 +1,7 @@
|
||||
{% ELDEF main %}
|
||||
|
||||
CCC
|
||||
DDD
|
||||
|
||||
|
||||
{% ENDELDEF %}
|
@ -1,9 +1,9 @@
|
||||
{% ELDEF foo JSON cba %}
|
||||
BBBB
|
||||
{% ENDELDEF %}
|
||||
|
||||
|
||||
{% ELDEF main JSON cba %}
|
||||
AAAA
|
||||
{% PUT test.foo cba %}
|
||||
{% PUT test.foo cba %}
|
||||
AAA
|
||||
{% FOR _:val IN cba %}
|
||||
TUTUTUTUTUTUTUTUN {% PUT jesccomp val %}
|
||||
{% ENDFOR %}
|
||||
|
||||
{% ENDELDEF %}
|
@ -14,6 +14,9 @@ int main(int argc, char** argv) {
|
||||
nytl::debug_print_templater(templater);
|
||||
json::JSON cba;
|
||||
cba["boba"] = json::JSON("<>");
|
||||
cba["arr"][0] = json::JSON("zero");
|
||||
cba["arr"][1] = json::JSON("one");
|
||||
cba["arr"][2] = json::JSON("two");
|
||||
// printf("DEBUG WAS: %p\n", &cba["boba"].g());
|
||||
// printf("%s\n", json::generate_str(cba["boba"].g(), json::print_compact).c_str());
|
||||
// return 0;
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <engine_engine_number_9/form_data_structure/urlencoded_query.h>
|
||||
#include <new_york_transit_line/templater.h>
|
||||
|
||||
#include "../http_server/engine_engine_number_9/running_mainloop.h"
|
||||
|
||||
bool termination = false;
|
||||
|
||||
void sigterm_action(int) {
|
||||
@ -17,7 +19,7 @@ void sigterm_action(int) {
|
||||
}
|
||||
|
||||
void usage(char** argv) {
|
||||
printf("Usage: %s <file with settings> <assets folder>\n", argv[0]);
|
||||
printf("Usage: %s <file with settings>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -32,30 +34,26 @@ std::string unsafe_client_request_stringification(const een9::ClientRequest& req
|
||||
}
|
||||
|
||||
int main(int argc, char** argv){
|
||||
printf("%s\n", regexis024::opcode_to_str(regexis024::opcode_t::DIE));
|
||||
try {
|
||||
een9_ASSERT_pl(argc > 0);
|
||||
if (argc < 1 + 2)
|
||||
if (argc < 1 + 1)
|
||||
usage(argv);
|
||||
if (!een9::isRegularFile(argv[1]) || !een9::endsIn(argv[1], ".json")) {
|
||||
printf("\"%s\" is not a json file\n", argv[1]);
|
||||
usage(argv);
|
||||
}
|
||||
std::string config_file = argv[1];
|
||||
if (!een9::isDirectory(argv[2])) {
|
||||
printf("\"%s\" is not a directory\n", argv[2]);
|
||||
usage(argv);
|
||||
}
|
||||
std::string assets_dir = argv[2];
|
||||
|
||||
std::string config_text;
|
||||
een9::readFile(config_file, config_text);
|
||||
json::JSON config = json::parse_str_flawless(config_text);
|
||||
een9_ASSERT(config.isDictionary(), "config root is not dictionary");
|
||||
een9_ASSERT(config["assets"].g().isString(), "config[\"\assets\"] is not string");
|
||||
std::string assets_dir = config["assets"].g().asString();
|
||||
een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory");
|
||||
|
||||
een9::StaticAssetManagerSlaveModule samI;
|
||||
samI.update({
|
||||
een9::StaticAssetManagerRule{assets_dir + "/HypertextPages", "/assets/html", {{".html", "text/html"}} },
|
||||
een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} },
|
||||
een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} },
|
||||
een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", {
|
||||
@ -63,31 +61,47 @@ int main(int argc, char** argv){
|
||||
} },
|
||||
});
|
||||
|
||||
json::JSON& config_presentation = config["presentation"].g();
|
||||
|
||||
/* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */
|
||||
std::vector<std::unique_ptr<nytl::Templater>> templaters_copies(8);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
templaters_copies[i] = std::make_unique<nytl::Templater>(
|
||||
nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}});
|
||||
templaters_copies[i]->update();
|
||||
}
|
||||
|
||||
// printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str());
|
||||
// return 0;
|
||||
|
||||
een9::MainloopParameters params;
|
||||
params.guest_core = [&samI](const een9::SlaveTask& task, const een9::ClientRequest& req) -> std::string {
|
||||
params.guest_core = [&samI, &templaters_copies, config_presentation]
|
||||
(const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string {
|
||||
een9_ASSERT_pl(0 <= worker_id && worker_id < templaters_copies.size());
|
||||
nytl::Templater& templater = *templaters_copies[worker_id];
|
||||
een9::StaticAsset sa;
|
||||
int ret;
|
||||
// printf("%s", unsafe_client_request_stringification(req).c_str());
|
||||
if (req.uri_path == "/output") {
|
||||
std::string text = unsafe_client_request_stringification(req);
|
||||
return een9::form_http_server_response_200("text/plain", text);
|
||||
}
|
||||
auto rteee = [&](const std::string& asset_path) -> std::string {
|
||||
ret = samI.get_asset(asset_path, sa);
|
||||
een9_ASSERT_pl(ret == 0);
|
||||
return een9::form_http_server_response_200(sa.type, sa.content);
|
||||
// if (req.uri_path == "/output") {
|
||||
// std::string text = unsafe_client_request_stringification(req);
|
||||
// return een9::form_http_server_response_200("text/plain", text);
|
||||
// }
|
||||
auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string {
|
||||
std::string page = templater.render(el_name,
|
||||
pass_phr ? std::vector<const json::JSON*>{&config_presentation} : std::vector<const json::JSON*>{});
|
||||
return een9::form_http_server_response_200("text/html", page);
|
||||
};
|
||||
if (req.uri_path == "/" || req.uri_path == "/list-rooms") {
|
||||
return rteee("/assets/html/list-rooms.html");
|
||||
return rteee("list-rooms", true);
|
||||
}
|
||||
if (req.uri_path == "/chat") {
|
||||
return rteee("/assets/html/chat.html");
|
||||
return rteee("chat", false);
|
||||
}
|
||||
if (req.uri_path == "/profile") {
|
||||
return rteee("/assets/html/profile.html");
|
||||
return rteee("profile", false);
|
||||
}
|
||||
if (req.uri_path == "/registration") {
|
||||
return rteee("/assets/html/registration.html");
|
||||
return rteee("registration", false);
|
||||
}
|
||||
/* Trying to interpret request as asset lookup */
|
||||
ret = samI.get_asset(req.uri_path, sa);
|
||||
@ -96,6 +110,7 @@ int main(int argc, char** argv){
|
||||
}
|
||||
return een9::form_http_server_response_404("text/html", "<h1> Not found! </h1>");
|
||||
};
|
||||
|
||||
params.ports_to_listen = {1025};
|
||||
params.slave_number = 8;
|
||||
params.open_admin_listener = false;
|
||||
|
Loading…
Reference in New Issue
Block a user