#pragma once #include "TaskBoard.hpp" #include "TaskStore.hpp" #include "picojson.h" #include #include #include #include #include namespace tp::taskboard { enum class LinkKind { Parent, Dependency }; struct TaskLink { LinkKind kind = LinkKind::Parent; ui::NodeId from = 0; ui::NodeId to = 0; auto operator<=>(const TaskLink&) const = default; }; struct NodeLayout { Vec2F position; halnf width = 0; halnf bodyHeight = 0; bool collapsed = false; bool operator==(const NodeLayout&) const = default; }; struct TaskRecord { std::map fields; NodeLayout layout; }; // A complete description of the board's persistent content. The server's last known board and the // board the user is editing are both snapshots; what is unsaved is exactly their difference. struct BoardSnapshot { std::map tasks; std::set links; std::vector palette; [[nodiscard]] static BoardSnapshot capture(const TaskBoard& board); }; struct FieldEdit { ui::NodeId task = 0; TaskField field = TaskField::Title; picojson::value value; picojson::value expected; }; struct BoardChanges { std::vector created; std::vector deleted; std::vector edits; std::vector layouts; std::vector linksAdded; std::vector linksRemoved; std::optional> palette; [[nodiscard]] bool empty() const; [[nodiscard]] size_t count() const; [[nodiscard]] static BoardChanges between(const BoardSnapshot& saved, const BoardSnapshot& current); }; [[nodiscard]] LinkKind linkKind(const ui::Link& link); [[nodiscard]] const std::vector& persistentFields(); }