M module-db/Interface/SMSTemplateRecord.cpp => module-db/Interface/SMSTemplateRecord.cpp +7 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "SMSTemplateRecord.hpp"
@@ 19,6 19,7 @@ SMSTemplateRecord::SMSTemplateRecord(const SMSTemplateTableRow &w)
ID = w.ID;
text = w.text;
lastUsageTimestamp = w.lastUsageTimestamp;
+ order = w.order;
}
SMSTemplateRecordInterface::SMSTemplateRecordInterface(SmsDB *smsDb) : smsDB(smsDb)
@@ 51,13 52,15 @@ std::unique_ptr<std::vector<SMSTemplateRecord>> SMSTemplateRecordInterface::GetL
bool SMSTemplateRecordInterface::Update(const SMSTemplateRecord &rec)
{
- auto templ = smsDB->templates.getById(rec.ID);
+ const auto templ = smsDB->templates.getById(rec.ID);
if (templ.ID == DB_ID_NONE) {
return false;
}
+ const auto templateText = rec.text.empty() ? templ.text : rec.text;
+ const auto templateOrder = rec.order == 0 ? templ.order : rec.order;
- return smsDB->templates.update(
- SMSTemplateTableRow{Record(rec.ID), .text = rec.text, .lastUsageTimestamp = rec.lastUsageTimestamp});
+ return smsDB->templates.update(SMSTemplateTableRow{
+ Record(rec.ID), .text = templateText, .lastUsageTimestamp = rec.lastUsageTimestamp, .order = templateOrder});
}
bool SMSTemplateRecordInterface::RemoveByID(uint32_t id)
M module-db/Interface/SMSTemplateRecord.hpp => module-db/Interface/SMSTemplateRecord.hpp +2 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 14,6 14,7 @@ struct SMSTemplateRecord : public Record
{
UTF8 text;
time_t lastUsageTimestamp = 0;
+ std::uint32_t order = 0;
SMSTemplateRecord() = default;
SMSTemplateRecord(const SMSTemplateTableRow &);
M module-db/Tables/SMSTemplateTable.cpp => module-db/Tables/SMSTemplateTable.cpp +18 -9
@@ 1,7 1,8 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "SMSTemplateTable.hpp"
+#include "Common/Types.hpp"
#include <Utils.hpp>
#include <log/log.hpp>
@@ 21,10 22,16 @@ bool SMSTemplateTable::create()
bool SMSTemplateTable::add(SMSTemplateTableRow entry)
{
- return db->execute("INSERT or ignore INTO templates (text, lastUsageTimestamp) VALUES ('%q', '%q');",
-
+ auto retQuery = db->query("SELECT MAX(rowOrder) FROM templates;");
+ if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
+ return false;
+ }
+ auto lastOrderValue = (*retQuery)[0].getUInt32() + 1;
+ return db->execute("INSERT or ignore INTO templates (text, lastUsageTimestamp, rowOrder) VALUES (" str_c str_c u32_
+ ");",
entry.text.c_str(),
- utils::to_string(entry.lastUsageTimestamp).c_str());
+ utils::to_string(entry.lastUsageTimestamp).c_str(),
+ lastOrderValue);
}
bool SMSTemplateTable::removeById(uint32_t id)
@@ 40,9 47,11 @@ bool SMSTemplateTable::removeByField(SMSTemplateTableFields field, const char *s
bool SMSTemplateTable::update(SMSTemplateTableRow entry)
{
- return db->execute("UPDATE templates SET text = '%q', lastUsageTimestamp = %q WHERE _id=%" PRIu32 ";",
+ return db->execute("UPDATE templates SET text = '%q', lastUsageTimestamp = %q, rowOrder = %" PRIu32
+ " WHERE _id=%" PRIu32 ";",
entry.text.c_str(),
utils::to_string(entry.lastUsageTimestamp).c_str(),
+ entry.order,
entry.ID);
}
@@ 58,15 67,14 @@ SMSTemplateTableRow SMSTemplateTable::getById(uint32_t id)
(*retQuery)[0].getUInt32(), // ID
(*retQuery)[1].getString(), // text
static_cast<time_t>((*retQuery)[2].getUInt64()), // lastUsageTimestamp
+ (*retQuery)[3].getUInt32(), // order
};
}
std::vector<SMSTemplateTableRow> SMSTemplateTable::getLimitOffset(uint32_t offset, uint32_t limit)
{
- auto retQuery =
- db->query("SELECT * from templates ORDER BY lastUsageTimestamp DESC LIMIT %" PRIu32 " OFFSET %" PRIu32 ";",
- limit,
- offset);
+ auto retQuery = db->query(
+ "SELECT * from templates ORDER BY rowOrder DESC LIMIT %" PRIu32 " OFFSET %" PRIu32 ";", limit, offset);
if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
return std::vector<SMSTemplateTableRow>();
@@ 79,6 87,7 @@ std::vector<SMSTemplateTableRow> SMSTemplateTable::getLimitOffset(uint32_t offse
(*retQuery)[0].getUInt32(), // ID
(*retQuery)[1].getString(), // text
static_cast<time_t>((*retQuery)[2].getUInt64()), // lastUsageTimestamp
+ (*retQuery)[3].getUInt32(), // order
});
} while (retQuery->nextRow());
M module-db/Tables/SMSTemplateTable.hpp => module-db/Tables/SMSTemplateTable.hpp +3 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 14,6 14,7 @@ struct SMSTemplateTableRow : public Record
{
UTF8 text;
time_t lastUsageTimestamp = 0;
+ std::uint32_t order = 0;
};
enum class SMSTemplateTableFields
@@ 23,7 24,7 @@ enum class SMSTemplateTableFields
class SMSTemplateTable : public Table<SMSTemplateTableRow, SMSTemplateTableFields>
{
public:
- SMSTemplateTable(Database *db);
+ explicit SMSTemplateTable(Database *db);
virtual ~SMSTemplateTable();
bool create() override final;
M module-db/tests/Helpers.cpp => module-db/tests/Helpers.cpp +27 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Helpers.hpp"
@@ 76,6 76,23 @@ namespace
return versions;
}
+ std::vector<std::filesystem::path> searchForScripts(const std::filesystem::path &pathToVersion,
+ const std::string &scriptName)
+ {
+ std::vector<std::filesystem::path> scripts{};
+ if (std::filesystem::exists(pathToVersion / scriptName)) {
+ scripts.push_back(pathToVersion / scriptName);
+ }
+ else {
+ for (const auto &subVersion : std::filesystem::directory_iterator(pathToVersion)) {
+ if (std::filesystem::exists(subVersion.path() / scriptName)) {
+ scripts.push_back(subVersion.path() / scriptName);
+ }
+ }
+ }
+ return scripts;
+ }
+
std::vector<std::filesystem::path> listFiles(const std::filesystem::path &path,
const std::string &prefix,
const bool withDevelopment)
@@ 84,9 101,15 @@ namespace
constexpr auto devel_sql = "devel.sql";
std::vector<std::filesystem::path> files;
for (const auto &version : listVersionDirectories(path, prefix)) {
- files.push_back(version / up_sql);
- if (withDevelopment and std::filesystem::exists(version / devel_sql)) {
- files.push_back(version / devel_sql);
+ auto scriptsPath = searchForScripts(version, up_sql);
+ if (not scriptsPath.empty()) {
+ files.insert(files.end(), scriptsPath.begin(), scriptsPath.end());
+ }
+ if (withDevelopment) {
+ scriptsPath = searchForScripts(version, devel_sql);
+ if (not scriptsPath.empty()) {
+ files.insert(files.end(), scriptsPath.begin(), scriptsPath.end());
+ }
}
}
return files;
M module-db/tests/SMSTemplateRecord_tests.cpp => module-db/tests/SMSTemplateRecord_tests.cpp +12 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <catch2/catch.hpp>
@@ 39,15 39,26 @@ TEST_CASE("SMS templates Record tests")
REQUIRE(templ.lastUsageTimestamp == testRec.lastUsageTimestamp);
}
+ SECTION("Check entry order")
+ {
+ for (std::uint32_t templateNumber = 1; templateNumber <= 4; templateNumber++) {
+ auto messageTemplate = SMSTemplateRecordInterface.GetByID(templateNumber);
+ REQUIRE(messageTemplate.ID == templateNumber);
+ REQUIRE(messageTemplate.order == templateNumber);
+ }
+ }
+
SECTION("Entry update")
{
testRec.ID = 4;
testRec.text = "New text";
+ testRec.order = 9;
testRec.lastUsageTimestamp = 200;
REQUIRE(SMSTemplateRecordInterface.Update(testRec));
auto templ = SMSTemplateRecordInterface.GetByID(4);
REQUIRE(templ.ID == 4);
REQUIRE(templ.text == testRec.text);
+ REQUIRE(templ.order == testRec.order);
REQUIRE(templ.lastUsageTimestamp == testRec.lastUsageTimestamp);
}
M module-db/tests/SMSTemplateTable_tests.cpp => module-db/tests/SMSTemplateTable_tests.cpp +3 -0
@@ 42,6 42,7 @@ TEST_CASE("SMS Templates Table tests")
auto templ = templatesTbl.getById(4);
REQUIRE(templ.ID == 4);
REQUIRE(templ.text == testRow.text);
+ REQUIRE(templ.order == 4);
REQUIRE(templ.lastUsageTimestamp == testRow.lastUsageTimestamp);
}
@@ 49,11 50,13 @@ TEST_CASE("SMS Templates Table tests")
{
testRow.ID = 4;
testRow.text = "New text";
+ testRow.order = 5;
testRow.lastUsageTimestamp = 200;
REQUIRE(templatesTbl.update(testRow));
auto templ = templatesTbl.getById(4);
REQUIRE(templ.ID == 4);
REQUIRE(templ.text == testRow.text);
+ REQUIRE(templ.order == testRow.order);
REQUIRE(templ.lastUsageTimestamp == testRow.lastUsageTimestamp);
}
M module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp => module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp +1 -0
@@ 80,6 80,7 @@ namespace sdesktop::endpoints::json
inline constexpr auto limit = "limit";
inline constexpr auto offset = "offset";
+ inline constexpr auto order = "order";
inline constexpr auto totalCount = "totalCount";
inline constexpr auto nextPage = "nextPage";
inline constexpr auto entries = "entries";
M products/PurePhone/services/db/databases/migration/sms/0/devel.sql => products/PurePhone/services/db/databases/migration/sms/0/devel.sql +1 -1
@@ 1,4 1,4 @@
--- Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+-- Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
BEGIN TRANSACTION;
INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","error_code","body","type") VALUES (1,2,2,1547492320,0,'Thank you for today!' || CHAR(10) || 'You chose a fantastic place :)',8);
M products/PurePhone/services/db/databases/migration/sms/0/up.sql => products/PurePhone/services/db/databases/migration/sms/0/up.sql +1 -1
@@ 1,4 1,4 @@
--- Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+-- Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
CREATE TABLE IF NOT EXISTS sms
A products/PurePhone/services/db/databases/migration/sms/current/111a2d1b_Adding_new_column_to_templates_table_to_manage_templates_order/.meta => products/PurePhone/services/db/databases/migration/sms/current/111a2d1b_Adding_new_column_to_templates_table_to_manage_templates_order/.meta +6 -0
@@ 0,0 1,6 @@
+{
+ "id": "111a2d1b-dc32-40a3-9a2a-02a9e186bcac",
+ "date": "2023-03-23 10:11:44",
+ "message": "Adding new column to templates table to manage templates order",
+ "parent": 0
+}
A products/PurePhone/services/db/databases/migration/sms/current/111a2d1b_Adding_new_column_to_templates_table_to_manage_templates_order/down.sql => products/PurePhone/services/db/databases/migration/sms/current/111a2d1b_Adding_new_column_to_templates_table_to_manage_templates_order/down.sql +9 -0
@@ 0,0 1,9 @@
+-- Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+-- Message: Adding new column to templates table to manage templates order
+-- Revision: 111a2d1b-dc32-40a3-9a2a-02a9e186bcac
+-- Create Date: 2023-03-23 10:11:44
+
+ALTER TABLE templates
+DROP COLUMN rowOrder;
A products/PurePhone/services/db/databases/migration/sms/current/111a2d1b_Adding_new_column_to_templates_table_to_manage_templates_order/up.sql => products/PurePhone/services/db/databases/migration/sms/current/111a2d1b_Adding_new_column_to_templates_table_to_manage_templates_order/up.sql +10 -0
@@ 0,0 1,10 @@
+-- Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+-- Message: Adding new column to templates table to manage templates order
+-- Revision: 111a2d1b-dc32-40a3-9a2a-02a9e186bcac
+-- Create Date: 2023-03-23 10:11:44
+
+ALTER TABLE templates ADD rowOrder INTEGER;
+
+UPDATE OR IGNORE templates SET rowOrder = _id;
M products/PurePhone/services/desktop/endpoints/messages/MessageHelper.cpp => products/PurePhone/services/desktop/endpoints/messages/MessageHelper.cpp +13 -5
@@ 55,7 55,8 @@ namespace sdesktop::endpoints
auto recordEntry =
json11::Json::object{{json::messages::templateID, static_cast<int>(record.ID)},
{json::messages::templateBody, record.text.c_str()},
- {json::messages::lastUsedAt, static_cast<int>(record.lastUsageTimestamp)}};
+ {json::messages::lastUsedAt, static_cast<int>(record.lastUsageTimestamp)},
+ {json::messages::order, static_cast<int>(record.order)}};
return recordEntry;
}
@@ 314,16 315,23 @@ namespace sdesktop::endpoints
return sys::ReturnCodes::Unresolved;
}
- if (!context.getBody()[json::messages::templateBody].is_string()) {
- LOG_ERROR("Bad request! templateBody is incorrect or missing!");
+ auto updateTemplateBody = context.getBody()[json::messages::templateBody].is_string();
+ auto updateTemplateOrder = context.getBody()[json::messages::order].is_number();
+ if (!updateTemplateBody && !updateTemplateOrder) {
+ LOG_ERROR("Bad request! templateBody/order is incorrect or missing!");
context.setResponseStatus(http::Code::BadRequest);
putToSendQueue(context.createSimpleResponse());
return sys::ReturnCodes::Unresolved;
}
SMSTemplateRecord record;
- record.ID = context.getBody()[json::messages::templateID].int_value();
- record.text = context.getBody()[json::messages::templateBody].string_value();
+ record.ID = context.getBody()[json::messages::templateID].int_value();
+ if (updateTemplateBody) {
+ record.text = context.getBody()[json::messages::templateBody].string_value();
+ }
+ if (updateTemplateOrder) {
+ record.order = context.getBody()[json::messages::order].int_value();
+ }
auto query = std::make_unique<db::query::SMSTemplateUpdate>(record);
auto listener = std::make_unique<db::EndpointListener>(
M test/pytest/service-desktop/test_templates.py => test/pytest/service-desktop/test_templates.py +42 -2
@@ 100,7 100,6 @@ class TemplatesTester:
for template in templates:
if template["templateBody"] == self.template_body:
-
# Change template
new_template_body = "NEW TEMPLATE BODY TEST"
body = {"category": "template", "templateID": template["templateID"], "templateBody": new_template_body}
@@ 117,6 116,37 @@ class TemplatesTester:
assert total_count == initial_count
assert test_passed == True
+ def test_changing_template_order(self):
+ template_id = 1
+ initial_order = 1
+ new_order = 9
+ body = {"category": "template", "templateID": template_id}
+ ret = self.harness.endpoint_request("messages", "get", body)
+
+ assert ret["status"] == status["OK"]
+ assert ret["body"]["templateID"] == template_id
+ assert ret["body"]["order"] == initial_order
+
+ body = {"category": "template", "templateID": template_id, "order": new_order}
+ ret = self.harness.endpoint_request("messages", "put", body)
+ assert ret["status"] == status["NoContent"]
+
+ body = {"category": "template", "templateID": template_id}
+ ret = self.harness.endpoint_request("messages", "get", body)
+ assert ret["status"] == status["OK"]
+ assert ret["body"]["templateID"] == template_id
+ assert ret["body"]["order"] == new_order
+
+ body = {"category": "template", "templateID": template_id, "order": initial_order}
+ ret = self.harness.endpoint_request("messages", "put", body)
+ assert ret["status"] == status["NoContent"]
+
+ body = {"category": "template", "templateID": template_id}
+ ret = self.harness.endpoint_request("messages", "get", body)
+ assert ret["status"] == status["OK"]
+ assert ret["body"]["templateID"] == template_id
+ assert ret["body"]["order"] == initial_order
+
def test_getting_templates_with_pagination(self):
initial_count = self.__get_count()
@@ 158,13 188,23 @@ def test_get_templates_without_pagination(harness):
templates_tester = TemplatesTester(harness)
templates_tester.test_getting_templates_without_pagination()
+
@pytest.mark.rt1051
@pytest.mark.service_desktop_test
@pytest.mark.usefixtures("phone_unlocked")
-def test_change_template(harness):
+def test_change_template_text(harness):
templates_tester = TemplatesTester(harness)
templates_tester.test_changing_template_body()
+
+@pytest.mark.rt1051
+@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("phone_unlocked")
+def test_change_template_order(harness):
+ templates_tester = TemplatesTester(harness)
+ templates_tester.test_changing_template_order()
+
+
@pytest.mark.rt1051
@pytest.mark.service_desktop_test
@pytest.mark.usefixtures("phone_unlocked")