diff --git a/Server/Database/Database.cpp b/Server/Database/Database.cpp index 0c915cc..492fa25 100644 --- a/Server/Database/Database.cpp +++ b/Server/Database/Database.cpp @@ -29,6 +29,8 @@ static int selectTaskCallback(void *data, int argc, char **argv, char **columnNa task.comment = argv[i]; } else if (strcmp(columnName[i], "finished") == 0) { task.finished = std::atol(argv[i]); + } else if (strcmp(columnName[i], "parent_id") == 0) { + task.parentId = std::atol(argv[i]); } } tasks->push_back(task); @@ -42,14 +44,27 @@ Tasks Database::tasks() { LOG(error) << "sqlite3_exec() failed: " << error << std::endl; sqlite3_free(error); } + std::unordered_map tasks; + for (auto iterator = ret.begin(); iterator != ret.end();) { + if (iterator->parentId >= 0) { + auto parentTask = tasks.at(iterator->parentId); + parentTask->children.push_back(*iterator); + tasks.insert({iterator->id, &parentTask->children.back()}); + iterator = ret.erase(iterator); + } else { + tasks.insert({iterator->id, &(*iterator)}); + ++iterator; + } + } return ret; } -bool Database::addTask(uint64_t createTime, const std::string &content, const std::string &comment, bool finished) { +bool Database::addTask(uint64_t createTime, const std::string &content, const std::string &comment, int parentId, + bool finished) { bool ret = true; std::ostringstream oss; - oss << "INSERT INTO tasks (create_time,content,comment,finished) VALUES (" << createTime << ",\"" << content - << "\",\"" << comment << "\"," << finished << ");"; + oss << "INSERT INTO tasks (create_time,content,comment,parent_id,finished) VALUES (" << createTime << ",\"" + << content << "\",\"" << comment << "\"," << parentId << "," << finished << ");"; auto sql = oss.str(); char *error = nullptr; int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error); diff --git a/Server/Database/Database.h b/Server/Database/Database.h index 3de8a64..9906f81 100644 --- a/Server/Database/Database.h +++ b/Server/Database/Database.h @@ -14,7 +14,7 @@ public: ~Database(); bool open(const std::string &path); Tasks tasks(); - bool addTask(uint64_t createTime, const std::string &content, const std::string &comment = "", + bool addTask(uint64_t createTime, const std::string &content, const std::string &comment = "", int parentId = -1, bool finished = false); bool removeTask(int id); void setTaskFinished(int id, bool finished, uint64_t finishedTime); diff --git a/Server/Database/Task.cpp b/Server/Database/Task.cpp index 32223b0..3798c70 100644 --- a/Server/Database/Task.cpp +++ b/Server/Database/Task.cpp @@ -5,16 +5,28 @@ namespace boost { namespace json { + +static boost::json::object serialize(const Task &task) { + boost::json::object ret; + ret["id"] = task.id; + ret["parentId"] = task.parentId; + ret["finished"] = task.finished; + ret["createTime"] = task.createTime; + ret["content"] = task.content; + ret["comment"] = task.comment; + + boost::json::array children; + for (auto &child : task.children) { + children.push_back(serialize(child)); + } + ret["children"] = std::move(children); + return ret; +} + std::string serialize(const Tasks &tasks) { boost::json::array ret; for (auto &task : tasks) { - boost::json::object t; - t["id"] = task.id; - t["finished"] = task.finished; - t["createTime"] = task.createTime; - t["content"] = task.content; - t["comment"] = task.comment; - ret.push_back(std::move(t)); + ret.push_back(serialize(task)); } return boost::json::serialize(ret); } diff --git a/Server/Database/Task.h b/Server/Database/Task.h index 5f21182..445173a 100644 --- a/Server/Database/Task.h +++ b/Server/Database/Task.h @@ -4,15 +4,19 @@ #include #include +class Task; +using Tasks = std::list; + class Task { public: int id = -1; + int parentId = -1; bool finished = false; int32_t createTime = 0; std::string content; std::string comment; + Tasks children; }; -using Tasks = std::list; namespace boost { namespace json { diff --git a/Server/SharedState.cpp b/Server/SharedState.cpp index 6757614..037ee40 100644 --- a/Server/SharedState.cpp +++ b/Server/SharedState.cpp @@ -70,7 +70,7 @@ SharedState::SharedState(boost::asio::io_context &ioContext, std::string doc_roo auto database = Amass::Singleton::instance(); auto root = boost::json::parse(request.body()); bool ret = database->addTask(root.at("createTime").as_int64(), std::string(root.at("content").as_string()), - std::string(root.at("comment").as_string())); + std::string(root.at("comment").as_string()), root.at("parentId").as_int64()); boost::json::object reply; reply["status"] = ret ? 0 : -1; http::response s{boost::beast::http::status::ok, request.version()};