From a04e286301acb5133abe3146b868920299831076 Mon Sep 17 00:00:00 2001 From: philippe lhardy Date: Wed, 30 Jul 2025 08:40:38 +0200 Subject: [PATCH] feat: add rank voting feature merge chosenrank with 8.1.4 refactorings reworked from git@github.com:vinimoz/polls.git rank-vote-feature-vue3 TRAPPE Vincent --- lib/Db/Poll.php | 18 +++ lib/Migration/TableSchema.php | 1 + lib/ResponseDefinitions.php | 1 + lib/Service/OptionService.php | 2 +- lib/Service/PollService.php | 4 +- .../Cards/modules/CardAddProposals.vue | 2 +- .../Configuration/ConfigRankOptions.vue | 114 ++++++++++++++++++ .../Navigation/PollNavigationItems.vue | 2 +- src/components/Options/OptionItem.vue | 2 +- src/components/PollList/PollItem.vue | 4 + .../SideBar/SideBarTabConfiguration.vue | 13 +- src/components/SideBar/SideBarTabOptions.vue | 2 +- src/components/User/UserMenu.vue | 4 + src/components/VoteTable/VoteIndicator.vue | 93 ++++++++++++-- src/components/VoteTable/VoteItem.vue | 23 +++- src/components/VoteTable/VoteTable.vue | 39 +++++- src/stores/poll.ts | 35 +++++- src/views/Dashboard.vue | 1 + src/views/Vote.vue | 1 + 19 files changed, 339 insertions(+), 22 deletions(-) create mode 100755 src/components/Configuration/ConfigRankOptions.vue diff --git a/lib/Db/Poll.php b/lib/Db/Poll.php index f5f8be30a1..51e8978747 100644 --- a/lib/Db/Poll.php +++ b/lib/Db/Poll.php @@ -41,6 +41,8 @@ * @method void setAllowComment(int $value) * @method int getAllowMaybe() * @method void setAllowMaybe(int $value) + * @method string getChosenRank() + * @method void setChosenRank(string $value) * @method string getAllowProposals() * @method void setAllowProposals(string $value) * @method int getProposalsExpire() @@ -79,6 +81,7 @@ class Poll extends EntityWithUser implements JsonSerializable { public const TABLE = 'polls_polls'; public const TYPE_DATE = 'datePoll'; + public const TYPE_GENERIC = 'genericPoll'; public const TYPE_TEXT = 'textPoll'; public const VARIANT_SIMPLE = 'simple'; public const ACCESS_HIDDEN = 'hidden'; @@ -146,6 +149,7 @@ class Poll extends EntityWithUser implements JsonSerializable { protected string $access = ''; protected int $anonymous = 0; protected int $allowMaybe = 0; + protected string $chosenRank = ''; protected string $allowProposals = ''; protected int $proposalsExpire = 0; protected int $voteLimit = 0; @@ -181,6 +185,7 @@ public function __construct() { $this->addType('anonymous', 'integer'); $this->addType('allowComment', 'integer'); $this->addType('allowMaybe', 'integer'); + $this->addType('chosenRank', 'string'); $this->addType('proposalsExpire', 'integer'); $this->addType('voteLimit', 'integer'); $this->addType('optionLimit', 'integer'); @@ -246,6 +251,7 @@ public function getConfigurationArray(): array { 'access' => $this->getAccess(), 'allowComment' => boolval($this->getAllowComment()), 'allowMaybe' => boolval($this->getAllowMaybe()), + 'chosenRank' => $this->getChosenRank(), 'allowProposals' => $this->getAllowProposals(), 'anonymous' => boolval($this->getAnonymous()), 'autoReminder' => $this->getAutoReminder(), @@ -315,6 +321,18 @@ public function deserializeArray(array $pollConfiguration): self { $this->setAccess($pollConfiguration['access'] ?? $this->getAccess()); $this->setAllowComment($pollConfiguration['allowComment'] ?? $this->getAllowComment()); $this->setAllowMaybe($pollConfiguration['allowMaybe'] ?? $this->getAllowMaybe()); + $chosenRank = $pollConfiguration['chosenRank'] ?? $this->getChosenRank(); + if (is_array($chosenRank)) { + $chosenRank = json_encode($chosenRank); // Sérialisation explicite + } elseif (is_string($chosenRank)) { + if (!json_decode($chosenRank)) { + $chosenRank = '[]'; // Fallback si JSON invalide + } + } else { + $chosenRank = '[]'; // Fallback + } + + $this->setChosenRank($chosenRank); $this->setAllowProposals($pollConfiguration['allowProposals'] ?? $this->getAllowProposals()); $this->setAnonymousSafe($pollConfiguration['anonymous'] ?? $this->getAnonymous()); $this->setAutoReminder($pollConfiguration['autoReminder'] ?? $this->getAutoReminder()); diff --git a/lib/Migration/TableSchema.php b/lib/Migration/TableSchema.php index 53954cd266..f0d79f6ebb 100644 --- a/lib/Migration/TableSchema.php +++ b/lib/Migration/TableSchema.php @@ -195,6 +195,7 @@ abstract class TableSchema { 'access' => ['type' => Types::STRING, 'options' => ['notnull' => true, 'default' => 'private', 'length' => 1024]], 'anonymous' => ['type' => Types::BIGINT, 'options' => ['notnull' => true, 'default' => 0, 'length' => 20]], 'allow_maybe' => ['type' => Types::BIGINT, 'options' => ['notnull' => true, 'default' => 1, 'length' => 20]], + 'chosen_rank' => ['type' => Types::TEXT, 'options' => ['notnull' => true, 'default' => 1, 'length' => 200]], 'allow_proposals' => ['type' => Types::STRING, 'options' => ['notnull' => true, 'default' => 'disallow', 'length' => 64]], 'proposals_expire' => ['type' => Types::BIGINT, 'options' => ['notnull' => true, 'default' => 0, 'length' => 20]], 'vote_limit' => ['type' => Types::BIGINT, 'options' => ['notnull' => true, 'default' => 0, 'length' => 20]], diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index c01231b8d6..9825e41e7b 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -79,6 +79,7 @@ * access: string, * allowComment: boolean, * allowMaybe: boolean, + * chosenRank: String, * allowProposals: string, * anonymous: boolean, * autoReminder: boolean, diff --git a/lib/Service/OptionService.php b/lib/Service/OptionService.php index 6fc12a7259..7b19990f20 100644 --- a/lib/Service/OptionService.php +++ b/lib/Service/OptionService.php @@ -108,7 +108,7 @@ public function addWithSequenceAndAutoVote( public function add(int $pollId, SimpleOption $simpleOption, bool $voteYes = false): Option { $this->getPoll($pollId, Poll::PERMISSION_OPTION_ADD); - if ($this->poll->getType() === Poll::TYPE_TEXT) { + if ($this->poll->getType() === Poll::TYPE_TEXT or $this->poll->getType() === Poll::TYPE_GENERIC) { $simpleOption->setOrder($this->getHighestOrder($pollId) + 1); } diff --git a/lib/Service/PollService.php b/lib/Service/PollService.php index 84a1566740..022d0abb78 100644 --- a/lib/Service/PollService.php +++ b/lib/Service/PollService.php @@ -226,6 +226,7 @@ public function add(string $type, string $title, string $votingVariant = Poll::V $this->poll->setExpire(0); $this->poll->setAnonymousSafe(0); $this->poll->setAllowMaybe(0); + $this->poll->setChosenRank(''); $this->poll->setVoteLimit(0); $this->poll->setShowResults(Poll::SHOW_RESULTS_ALWAYS); $this->poll->setDeleted(0); @@ -418,6 +419,7 @@ public function clone(int $pollId): Poll { // deanonymize cloned polls by default, to avoid locked anonymous polls $this->poll->setAnonymous(0); $this->poll->setAllowMaybe($origin->getAllowMaybe()); + $this->poll->setChosenRank($origin->getChosenRank()); $this->poll->setVoteLimit($origin->getVoteLimit()); $this->poll->setShowResults($origin->getShowResults()); $this->poll->setAdminAccess($origin->getAdminAccess()); @@ -471,7 +473,7 @@ public function getValidEnum(): array { * @psalm-return array{0: string, 1: string} */ private function getValidPollType(): array { - return [Poll::TYPE_DATE, Poll::TYPE_TEXT]; + return [Poll::TYPE_DATE, Poll::TYPE_TEXT, poll::TYPE_GENERIC]; } /** diff --git a/src/components/Cards/modules/CardAddProposals.vue b/src/components/Cards/modules/CardAddProposals.vue index b49cd271c5..3d301b53f1 100644 --- a/src/components/Cards/modules/CardAddProposals.vue +++ b/src/components/Cards/modules/CardAddProposals.vue @@ -32,7 +32,7 @@ const optionAddDatesModalProps = {