From 13b614c3774c335487158c37b726efd6e43c083a Mon Sep 17 00:00:00 2001 From: Maxim Leshchenko Date: Mon, 7 Feb 2022 23:20:55 +0200 Subject: [PATCH] Users: Add the ability to convert votes into a rating for yourself or other users Closes #345 --- .../CoinsTransferNotification.php | 2 +- .../Notifications/RatingUpNotification.php | 13 ++++ Web/Presenters/UserPresenter.php | 42 ++++++++++- Web/Presenters/templates/User/View.xml | 3 + .../components/notifications/9603/_18_18_.xml | 8 ++ Web/routes.yml | 2 + Web/static/js/openvk.cls.js | 75 +++++++++++++++++++ locales/en.strings | 15 ++++ locales/ru.strings | 15 ++++ 9 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 Web/Models/Entities/Notifications/RatingUpNotification.php create mode 100644 Web/Presenters/templates/components/notifications/9603/_18_18_.xml diff --git a/Web/Models/Entities/Notifications/CoinsTransferNotification.php b/Web/Models/Entities/Notifications/CoinsTransferNotification.php index d515631a..2cfc5230 100644 --- a/Web/Models/Entities/Notifications/CoinsTransferNotification.php +++ b/Web/Models/Entities/Notifications/CoinsTransferNotification.php @@ -1,6 +1,6 @@ flashFail("succ", tr("information_-1"), tr("points_transfer_successful", tr("points_amount", $value), $receiver->getURL(), htmlentities($receiver->getCanonicalName()))); } + + function renderIncreaseRating(): void + { + $this->assertUserLoggedIn(); + $this->willExecuteWriteAction(); + + if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"]) + $this->flashFail("err", tr("error"), tr("feature_disabled")); + + $receiverAddress = $this->postParam("receiver"); + $value = (int) $this->postParam("value"); + $message = $this->postParam("message"); + + if(!$receiverAddress || !$value) + $this->flashFail("err", tr("failed_to_increase_rating"), tr("not_all_information_has_been_entered")); + + if($value < 0) + $this->flashFail("err", tr("failed_to_increase_rating"), tr("negative_rating_value")); + + if(iconv_strlen($message) > 255) + $this->flashFail("err", tr("failed_to_increase_rating"), tr("message_is_too_long")); + + $receiver = $this->users->getByAddress($receiverAddress); + if(!$receiver) + $this->flashFail("err", tr("failed_to_increase_rating"), tr("receiver_not_found")); + + if($this->user->identity->getCoins() < $value) + $this->flashFail("err", tr("failed_to_increase_rating"), tr("you_dont_have_enough_points")); + + $this->user->identity->setCoins($this->user->identity->getCoins() - $value); + $this->user->identity->save(); + + $receiver->setRating($receiver->getRating() + $value); + $receiver->save(); + + if($this->user->id !== $receiver->getId()) + (new RatingUpNotification($receiver, $this->user->identity, $value, $message))->emit(); + + $this->flashFail("succ", tr("information_-1"), tr("rating_increase_successful", $receiver->getURL(), htmlentities($receiver->getCanonicalName()), $value)); + } } diff --git a/Web/Presenters/templates/User/View.xml b/Web/Presenters/templates/User/View.xml index 6a7dfb9e..f421925c 100644 --- a/Web/Presenters/templates/User/View.xml +++ b/Web/Presenters/templates/User/View.xml @@ -72,6 +72,9 @@ + {else} {if $thisUser->getChandlerUser()->can("substitute")->model('openvk\Web\Models\Entities\User')->whichBelongsTo(0)} diff --git a/Web/Presenters/templates/components/notifications/9603/_18_18_.xml b/Web/Presenters/templates/components/notifications/9603/_18_18_.xml new file mode 100644 index 00000000..a139ccb7 --- /dev/null +++ b/Web/Presenters/templates/components/notifications/9603/_18_18_.xml @@ -0,0 +1,8 @@ +{var sender = $notification->getModel(1)} +{var value = (int) explode(" ", $notification->getData(), 2)[0]} +{var message = explode(" ", $notification->getData(), 2)[1]} + +{$sender->getCanonicalName()} {_increased_your_rating_by} {$value}%. +{if !empty($message)} + {_message}: "{$message}". +{/if} diff --git a/Web/routes.yml b/Web/routes.yml index 65d1df1f..bd682782 100644 --- a/Web/routes.yml +++ b/Web/routes.yml @@ -73,6 +73,8 @@ routes: handler: "User->disableTwoFactorAuth" - url: "/coins_transfer" handler: "User->coinsTransfer" + - url: "/increase_social_credits" + handler: "User->increaseRating" - url: "/id{num}" handler: "User->view" - url: "/friends{num}" diff --git a/Web/static/js/openvk.cls.js b/Web/static/js/openvk.cls.js index 8d600715..77677191 100644 --- a/Web/static/js/openvk.cls.js +++ b/Web/static/js/openvk.cls.js @@ -289,3 +289,78 @@ function supportFastAnswerDialogOnClick(answer) { answerInput.value = answer; answerInput.focus(); } + +function ovk_proc_strtr(string, length = 0) { + const newString = string.substring(0, length); + return newString + (string !== newString ? "…" : ""); +} + +function showIncreaseRatingDialog(coinsCount, userUrl, hash) { + MessageBox(tr("increase_rating"), ` +
+ ${tr("you_have_unused_votes", coinsCount)}
+ ${tr("apply_voucher")} » +
+
+ + + + + + + + + + + + + + + + + + + + + + +
+ ${tr("to_whom")}: + + +
+ ${tr("increase_by")}: + + +
+ ${tr("message")}: + + +
+ +
+ ${tr("price")}: + + ${tr("points_amount", 0)} (1% = ${tr("points_amount_one", 1)}) +
+ +
+ `, [tr("increase_rating_button"), tr("cancel")], [ + () => { + document.querySelector("#increase_rating_form").submit(); + }, + Function.noop + ]); + + document.querySelector("#value_input").oninput = function () { + let value = Number(this.value); + value = isNaN(value) ? "?" : ovk_proc_strtr(String(value), 7); + if(!value.endsWith("…") && value != "?") + value = Number(value); + + if(typeof value === "number") + document.querySelector("#rating_price").innerHTML = tr("points_amount", value); + else + document.querySelector("#rating_price").innerHTML = value + " " + tr("points_amount_other").replace("$1 ", ""); + }; +} diff --git a/locales/en.strings b/locales/en.strings index 53d1428e..c649d40b 100644 --- a/locales/en.strings +++ b/locales/en.strings @@ -583,6 +583,21 @@ "receiver_not_found" = "The receiver was not found."; "you_dont_have_enough_points" = "You don't have enough votes."; +"increase_rating" = "Increase rating"; +"increase_rating_button" = "Increase"; +"to_whom" = "To whom"; +"increase_by" = "Increase by"; +"price" = "Price"; + +"you_have_unused_votes" = "You have $1 unused votes on your balance."; +"apply_voucher" = "Apply voucher"; + +"failed_to_increase_rating" = "Failed to increase rating"; +"rating_increase_successful" = "You have successfully increased rating of $2 by $3%."; +"negative_rating_value" = "We cannot steal rating from another person, sorry."; + +"increased_your_rating_by" = "increased your rating by"; + /* Gifts */ "gift" = "Gift"; diff --git a/locales/ru.strings b/locales/ru.strings index ce456b6c..ae9a2098 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -609,6 +609,21 @@ "receiver_not_found" = "Получатель не найден."; "you_dont_have_enough_points" = "У вас недостаточно голосов."; +"increase_rating" = "Повысить рейтинг"; +"increase_rating_button" = "Повысить"; +"to_whom" = "Кому"; +"increase_by" = "Повысить на"; +"price" = "Стоимость"; + +"you_have_unused_votes" = "У Вас $1 неиспользованных голоса на балансе."; +"apply_voucher" = "Применить ваучер"; + +"failed_to_increase_rating" = "Не удалось повысить рейтинг"; +"rating_increase_successful" = "Вы успешно повысыли рейтинг $2 на $3%."; +"negative_rating_value" = "Мы не можем украсть рейтинг у другого человека, извините."; + +"increased_your_rating_by" = "повысил ваш рейтинг на"; + /* Gifts */ "gift" = "Подарок";