~aleteoryx/muditaos

50a73ca63888c09262176c1ec3f99ba0fbf610a4 — Piotr Tański 4 years ago ae0a970
[EGD-7051] Fixed saving multiple notes at once

When creating a new note, it was possible to save multiple notes
with 1 click.
M module-apps/application-notes/data/NoteSwitchData.cpp => module-apps/application-notes/data/NoteSwitchData.cpp +3 -3
@@ 1,15 1,15 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NoteSwitchData.hpp"

namespace app::notes
{
    NoteSwitchData::NoteSwitchData(NotesRecord record)
    NoteSwitchData::NoteSwitchData(std::shared_ptr<NotesRecord> record)
        : gui::SwitchData(std::string{"NotePreview"}), record{std::move(record)}
    {}

    const NotesRecord &NoteSwitchData::getRecord() const noexcept
    std::shared_ptr<NotesRecord> NoteSwitchData::getRecord() noexcept
    {
        return record;
    }

M module-apps/application-notes/data/NoteSwitchData.hpp => module-apps/application-notes/data/NoteSwitchData.hpp +4 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 12,11 12,11 @@ namespace app::notes
    class NoteSwitchData : public gui::SwitchData
    {
      public:
        explicit NoteSwitchData(NotesRecord record);
        explicit NoteSwitchData(std::shared_ptr<NotesRecord> record);

        const NotesRecord &getRecord() const noexcept;
        std::shared_ptr<NotesRecord> getRecord() noexcept;

      private:
        NotesRecord record;
        std::shared_ptr<NotesRecord> record = nullptr;
    };
} // namespace app::notes

M module-apps/application-notes/model/NotesListModel.cpp => module-apps/application-notes/model/NotesListModel.cpp +2 -2
@@ 46,8 46,8 @@ namespace app::notes
        }

        auto item               = new gui::NotesItem(note);
        item->activatedCallback = [this, note = note.get()](gui::Item &) {
            application->switchWindow(gui::name::window::note_preview, std::make_unique<NoteSwitchData>(*note));
        item->activatedCallback = [this, note](gui::Item &) {
            application->switchWindow(gui::name::window::note_preview, std::make_unique<NoteSwitchData>(note));
            return true;
        };
        item->inputCallback = [this, note = note.get()](gui::Item &, const gui::InputEvent &event) {

M module-apps/application-notes/model/NotesRepository.cpp => module-apps/application-notes/model/NotesRepository.cpp +3 -3
@@ 53,7 53,7 @@ namespace app::notes
        task->execute(application, this);
    }

    void NotesDBRepository::save(const NotesRecord &note, const OnResultCallback &callback)
    void NotesDBRepository::save(const NotesRecord &note, const OnSaveCallback &callback)
    {
        auto query = std::make_unique<db::query::QueryNoteStore>(note);
        auto task  = app::AsyncQuery::createFromQuery(std::move(query), db::Interface::Name::Notes);


@@ 63,14 63,14 @@ namespace app::notes
                return false;
            }
            if (callback) {
                callback(result->succeed());
                callback(result->succeed(), result->getNoteId());
            }
            return true;
        });
        task->execute(application, this);
    }

    void NotesDBRepository::remove(const NotesRecord &note, const OnResultCallback &callback)
    void NotesDBRepository::remove(const NotesRecord &note, const OnRemoveCallback &callback)
    {
        auto query = std::make_unique<db::query::QueryNoteRemove>(note.ID);
        auto task  = app::AsyncQuery::createFromQuery(std::move(query), db::Interface::Name::Notes);

M module-apps/application-notes/model/NotesRepository.hpp => module-apps/application-notes/model/NotesRepository.hpp +7 -6
@@ 14,8 14,9 @@ namespace app::notes
    class AbstractNotesRepository
    {
      public:
        using OnGetCallback      = std::function<bool(const std::vector<NotesRecord> &, unsigned int)>;
        using OnResultCallback   = std::function<void(bool)>;
        using OnGetCallback    = std::function<bool(const std::vector<NotesRecord> &, unsigned int)>;
        using OnSaveCallback   = std::function<void(bool, std::uint32_t)>;
        using OnRemoveCallback = std::function<void(bool)>;

        virtual ~AbstractNotesRepository() noexcept = default;



@@ 24,8 25,8 @@ namespace app::notes
                               std::uint32_t offset,
                               std::uint32_t limit,
                               const OnGetCallback &callback)                                      = 0;
        virtual void save(const NotesRecord &note, const OnResultCallback &callback)               = 0;
        virtual void remove(const NotesRecord &note, const OnResultCallback &callback)             = 0;
        virtual void save(const NotesRecord &note, const OnSaveCallback &callback)                 = 0;
        virtual void remove(const NotesRecord &note, const OnRemoveCallback &callback)             = 0;
    };

    class NotesDBRepository : public AbstractNotesRepository, public app::AsyncCallbackReceiver


@@ 38,8 39,8 @@ namespace app::notes
                       std::uint32_t offset,
                       std::uint32_t limit,
                       const OnGetCallback &callback) override;
        void save(const NotesRecord &note, const OnResultCallback &callback) override;
        void remove(const NotesRecord &note, const OnResultCallback &callback) override;
        void save(const NotesRecord &note, const OnSaveCallback &callback) override;
        void remove(const NotesRecord &note, const OnRemoveCallback &callback) override;

      private:
        Application *application;

M module-apps/application-notes/presenter/NoteEditWindowPresenter.cpp => module-apps/application-notes/presenter/NoteEditWindowPresenter.cpp +7 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NoteEditWindowPresenter.hpp"


@@ 9,8 9,12 @@ namespace app::notes
        : notesRepository{std::move(notesRepository)}
    {}

    void NoteEditWindowPresenter::save(const NotesRecord &note)
    void NoteEditWindowPresenter::save(std::shared_ptr<NotesRecord> &note)
    {
        notesRepository->save(note, nullptr);
        notesRepository->save(*note, [this, note](bool succeed, std::uint32_t noteId) {
            if (succeed) {
                note->ID = noteId;
            }
        });
    }
} // namespace app::notes

M module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp => module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp +2 -2
@@ 22,7 22,7 @@ namespace app::notes
          public:
            virtual ~Presenter() noexcept = default;

            virtual void save(const NotesRecord &note) = 0;
            virtual void save(std::shared_ptr<NotesRecord> &note) = 0;
        };
    };



@@ 31,7 31,7 @@ namespace app::notes
      public:
        explicit NoteEditWindowPresenter(std::unique_ptr<AbstractNotesRepository> &&notesRepository);

        void save(const NotesRecord &note) override;
        void save(std::shared_ptr<NotesRecord> &note) override;

      private:
        std::unique_ptr<AbstractNotesRepository> notesRepository;

M module-apps/application-notes/windows/NoteEditWindow.cpp => module-apps/application-notes/windows/NoteEditWindow.cpp +3 -3
@@ 107,7 107,7 @@ namespace app::notes
            return;
        }

        notesRecord = std::make_unique<NotesRecord>(editData->getRecord());
        notesRecord = editData->getRecord();
        setNoteText(notesRecord->snippet);
    }



@@ 121,7 121,7 @@ namespace app::notes
        if (inputEvent.isShortRelease()) {
            if (inputEvent.is(gui::KeyCode::KEY_ENTER)) {
                saveNote();
                auto switchData                        = std::make_unique<NoteSwitchData>(*notesRecord);
                auto switchData                        = std::make_unique<NoteSwitchData>(notesRecord);
                switchData->ignoreCurrentWindowOnStack = true;
                application->switchWindow(gui::name::window::note_preview, std::move(switchData));
            }


@@ 138,6 138,6 @@ namespace app::notes
    {
        notesRecord->date    = std::time(nullptr);
        notesRecord->snippet = edit->getText();
        presenter->save(*notesRecord);
        presenter->save(notesRecord);
    }
} // namespace app::notes

M module-apps/application-notes/windows/NoteEditWindow.hpp => module-apps/application-notes/windows/NoteEditWindow.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 36,7 36,7 @@ namespace app::notes
        void saveNote();

        std::unique_ptr<NoteEditWindowContract::Presenter> presenter;
        std::unique_ptr<NotesRecord> notesRecord;
        std::shared_ptr<NotesRecord> notesRecord;
        gui::Label *charactersCounter;
        gui::Text *edit;
    };

M module-apps/application-notes/windows/NoteMainWindow.cpp => module-apps/application-notes/windows/NoteMainWindow.cpp +1 -1
@@ 119,7 119,7 @@ namespace app::notes
        if (inputEvent.isShortRelease()) {
            if (inputEvent.is(gui::KeyCode::KEY_LEFT)) {
                application->switchWindow(gui::name::window::note_edit,
                                          std::make_unique<NoteSwitchData>(NotesRecord{}));
                                          std::make_unique<NoteSwitchData>(std::make_shared<NotesRecord>()));
            }
            else if (inputEvent.is(gui::KeyCode::KEY_RIGHT)) {
                application->switchWindow(gui::name::window::notes_search);

M module-apps/application-notes/windows/NotePreviewWindow.cpp => module-apps/application-notes/windows/NotePreviewWindow.cpp +2 -2
@@ 86,7 86,7 @@ namespace app::notes
            return;
        }

        notesRecord = std::make_unique<NotesRecord>(previewData->getRecord());
        notesRecord = previewData->getRecord();
        setEditDateText(notesRecord->date);
        note->setText(notesRecord->snippet);
    }


@@ 115,7 115,7 @@ namespace app::notes
    {
        if (inputEvent.isShortRelease()) {
            if (inputEvent.is(gui::KeyCode::KEY_ENTER)) {
                application->switchWindow(gui::name::window::note_edit, std::make_unique<NoteSwitchData>(*notesRecord));
                application->switchWindow(gui::name::window::note_edit, std::make_unique<NoteSwitchData>(notesRecord));
            }
            else if (inputEvent.is(gui::KeyCode::KEY_LF)) {
                application->switchWindow(utils::translate("app_phonebook_options_title"),

M module-apps/application-notes/windows/NotePreviewWindow.hpp => module-apps/application-notes/windows/NotePreviewWindow.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 32,7 32,7 @@ namespace app::notes
        void setEditDateText(std::uint32_t editTimestamp);

        std::unique_ptr<NotePreviewWindowContract::Presenter> presenter;
        std::unique_ptr<NotesRecord> notesRecord;
        std::shared_ptr<NotesRecord> notesRecord;
        gui::Text *note  = nullptr;
        gui::Label *date = nullptr;
    };

M module-db/Interface/NotesRecord.cpp => module-db/Interface/NotesRecord.cpp +12 -5
@@ 155,17 155,24 @@ std::unique_ptr<db::QueryResult> NotesRecordInterface::getByTextQuery(const std:

std::unique_ptr<db::QueryResult> NotesRecordInterface::storeQuery(const std::shared_ptr<db::Query> &query)
{
    const auto localQuery = static_cast<db::query::QueryNoteStore *>(query.get());
    const auto &record    = localQuery->getRecord();
    bool isSuccess        = false;
    if (const auto exists = notesDB->notes.getById(record.ID).ID != DB_ID_NONE; exists) {
    const auto localQuery  = static_cast<db::query::QueryNoteStore *>(query.get());
    const auto &record     = localQuery->getRecord();
    bool isSuccess         = false;
    std::uint32_t resultId = DB_ID_NONE;

    if (const auto id = notesDB->notes.getById(record.ID).ID; id != DB_ID_NONE) {
        // Already exists in the DB.
        isSuccess = Update(record);
        resultId  = id;
    }
    else {
        isSuccess = Add(record);
        if (isSuccess) {
            resultId = notesDB->getLastInsertRowId();
        }
    }

    auto response = std::make_unique<db::query::NoteStoreResult>(isSuccess);
    auto response = std::make_unique<db::query::NoteStoreResult>(isSuccess, resultId);
    response->setRequestQuery(query);
    return response;
}

M module-db/queries/notes/QueryNoteStore.cpp => module-db/queries/notes/QueryNoteStore.cpp +7 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryNoteStore.hpp"


@@ 18,7 18,7 @@ namespace db::query
        return {"QueryNoteStore"};
    }

    NoteStoreResult::NoteStoreResult(bool isSuccess) : isSuccess{isSuccess}
    NoteStoreResult::NoteStoreResult(bool isSuccess, std::uint32_t noteId) : isSuccess{isSuccess}, noteId{noteId}
    {}

    bool NoteStoreResult::succeed() const noexcept


@@ 26,6 26,11 @@ namespace db::query
        return isSuccess;
    }

    std::uint32_t NoteStoreResult::getNoteId() const noexcept
    {
        return noteId;
    }

    auto NoteStoreResult::debugInfo() const -> std::string
    {
        return {"NoteStoreResult"};

M module-db/queries/notes/QueryNoteStore.hpp => module-db/queries/notes/QueryNoteStore.hpp +4 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 25,12 25,14 @@ namespace db::query
    class NoteStoreResult : public QueryResult
    {
      public:
        explicit NoteStoreResult(bool isSuccess);
        NoteStoreResult(bool isSuccess, std::uint32_t noteId);

        [[nodiscard]] bool succeed() const noexcept;
        [[nodiscard]] std::uint32_t getNoteId() const noexcept;
        [[nodiscard]] std::string debugInfo() const override;

      private:
        bool isSuccess;
        std::uint32_t noteId;
    };
} // namespace db::query

M module-db/tests/NotesRecord_tests.cpp => module-db/tests/NotesRecord_tests.cpp +18 -0
@@ 64,9 64,27 @@ TEST_CASE("Notes Record tests")
        auto addResult = static_cast<db::query::NoteStoreResult *>(response.get());

        REQUIRE(addResult->succeed());
        REQUIRE(addResult->getNoteId() == 2);
        REQUIRE(notesRecordInterface.GetCount() == 2);
    }

    SECTION("Update a note")
    {
        constexpr auto testId = 1;

        NotesRecord record;
        record.ID      = testId;
        record.snippet = testSnippet;

        auto query        = std::make_unique<db::query::QueryNoteStore>(record);
        auto response     = notesRecordInterface.runQuery(std::move(query));
        auto updateResult = static_cast<db::query::NoteStoreResult *>(response.get());

        REQUIRE(updateResult->succeed());
        REQUIRE(updateResult->getNoteId() == testId);
        REQUIRE(notesRecordInterface.GetCount() == 1);
    }

    SECTION("Remove a note")
    {
        auto query        = std::make_unique<db::query::QueryNoteRemove>(1);