mirror of
https://github.com/openvk/openvk
synced 2024-12-22 16:42:32 +03:00
[Wall] Список лайкнувших и поделившихся записью/комментарием
This commit is contained in:
parent
c2b6db1b8a
commit
4c9061827c
7 changed files with 132 additions and 7 deletions
|
@ -1,5 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
namespace openvk\Web\Models\Entities;
|
namespace openvk\Web\Models\Entities;
|
||||||
|
use openvk\Web\Models\Repositories\Posts;
|
||||||
use openvk\Web\Util\DateTime;
|
use openvk\Web\Util\DateTime;
|
||||||
use openvk\Web\Models\RowModel;
|
use openvk\Web\Models\RowModel;
|
||||||
use openvk\Web\Models\Entities\User;
|
use openvk\Web\Models\Entities\User;
|
||||||
|
@ -100,6 +101,24 @@ abstract class Postable extends Attachable
|
||||||
yield (new Users)->get($like->origin);
|
yield (new Users)->get($like->origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getReposters(): \Traversable
|
||||||
|
{
|
||||||
|
$sel = $this->getRecord()
|
||||||
|
->related("attachments.attachable_id")
|
||||||
|
->where([
|
||||||
|
"attachable_type" => get_class($this),
|
||||||
|
"attachable_id" => $this->getId(),
|
||||||
|
"target_type" => get_class(new Post),
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($sel as $repost) {
|
||||||
|
$post = (new Posts)->get($repost->target_id);
|
||||||
|
if ($post && !$post->isDeleted()) {
|
||||||
|
yield $post->getOwner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isAnonymous(): bool
|
function isAnonymous(): bool
|
||||||
{
|
{
|
||||||
return (bool) $this->getRecord()->anonymous;
|
return (bool) $this->getRecord()->anonymous;
|
||||||
|
|
|
@ -3,7 +3,7 @@ namespace openvk\Web\Presenters;
|
||||||
use openvk\Web\Models\Exceptions\TooMuchOptionsException;
|
use openvk\Web\Models\Exceptions\TooMuchOptionsException;
|
||||||
use openvk\Web\Models\Entities\{Poll, Post, Photo, Video, Club, User};
|
use openvk\Web\Models\Entities\{Poll, Post, Photo, Video, Club, User};
|
||||||
use openvk\Web\Models\Entities\Notifications\{MentionNotification, RepostNotification, WallPostNotification};
|
use openvk\Web\Models\Entities\Notifications\{MentionNotification, RepostNotification, WallPostNotification};
|
||||||
use openvk\Web\Models\Repositories\{Posts, Users, Clubs, Albums, Notes};
|
use openvk\Web\Models\Repositories\{Comments, Posts, Users, Clubs, Albums, Notes};
|
||||||
use Chandler\Database\DatabaseConnection;
|
use Chandler\Database\DatabaseConnection;
|
||||||
use Nette\InvalidStateException as ISE;
|
use Nette\InvalidStateException as ISE;
|
||||||
use Bhaktaraz\RSSGenerator\Item;
|
use Bhaktaraz\RSSGenerator\Item;
|
||||||
|
@ -498,4 +498,64 @@ final class WallPresenter extends OpenVKPresenter
|
||||||
# TODO localize message based on language and ?act=(un)pin
|
# TODO localize message based on language and ?act=(un)pin
|
||||||
$this->flashFail("succ", tr("information_-1"), tr("changes_saved_comment"));
|
$this->flashFail("succ", tr("information_-1"), tr("changes_saved_comment"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function fetchLikers($object): array
|
||||||
|
{
|
||||||
|
if (!$object || $object->isDeleted())
|
||||||
|
return ["success" => false, "error" => "Объект не найден"];
|
||||||
|
|
||||||
|
$response = [];
|
||||||
|
foreach ($object->getLikers() as $liker) {
|
||||||
|
$liker = [
|
||||||
|
"url" => $liker->getURL(),
|
||||||
|
"fname" => $liker->getFirstName(),
|
||||||
|
"lname" => $liker->getLastName(),
|
||||||
|
"avatar" => $liker->getAvatarURL()
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!in_array($liker, $response)) {
|
||||||
|
$response[] = $liker;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ["success" => true, "payload" => [count($response), $response]];
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderLikers(int $wall, int $post_id): void
|
||||||
|
{
|
||||||
|
$this->returnJson($this->fetchLikers($this->posts->getPostById($wall, $post_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderReposters(int $wall, int $post_id): void
|
||||||
|
{
|
||||||
|
$post = $this->posts->getPostById($wall, $post_id);
|
||||||
|
if (!$post || $post->isDeleted()) {
|
||||||
|
$this->returnJson(["success" => false, "error" => "Запись не найдена"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = [];
|
||||||
|
foreach ($post->getReposters() as $reposter) {
|
||||||
|
$_reposter = $reposter instanceof User ? [
|
||||||
|
"fname" => $reposter->getFirstName(),
|
||||||
|
"lname" => $reposter->getLastName()
|
||||||
|
] : [
|
||||||
|
"fname" => $reposter->getCanonicalName(),
|
||||||
|
"lname" => ""
|
||||||
|
];
|
||||||
|
|
||||||
|
$_reposter["url"] = $reposter->getURL();
|
||||||
|
$_reposter["avatar"] = $reposter->getAvatarURL();
|
||||||
|
|
||||||
|
if (!in_array($_reposter, $response)) {
|
||||||
|
$response[] = $_reposter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->returnJson(["success" => true, "payload" => [count($response), $response]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderCommentLikers(int $comment_id): void
|
||||||
|
{
|
||||||
|
$this->returnJson($this->fetchLikers((new Comments)->get($comment_id)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@
|
||||||
<a href="/photo{$photo->getPrettyId()}/edit" class="profile_link" style="display:block;width:96%;">{_edit}</a>
|
<a href="/photo{$photo->getPrettyId()}/edit" class="profile_link" style="display:block;width:96%;">{_edit}</a>
|
||||||
<a id="_photoDelete" href="/photo{$photo->getPrettyId()}/delete" class="profile_link" style="display:block;width:96%;">{_delete}</a>
|
<a id="_photoDelete" href="/photo{$photo->getPrettyId()}/delete" class="profile_link" style="display:block;width:96%;">{_delete}</a>
|
||||||
</div>
|
</div>
|
||||||
<a href="{$photo->getURL()}" class="profile_link" target="_blank" style="display:block;width:96%;">{_"open_original"}</a>
|
|
||||||
<a n:if="$canReport ?? false" class="profile_link" style="display:block;width:96%;" href="javascript:reportPhoto()">{_report}</a>
|
<a n:if="$canReport ?? false" class="profile_link" style="display:block;width:96%;" href="javascript:reportPhoto()">{_report}</a>
|
||||||
<script n:if="$canReport ?? false">
|
<script n:if="$canReport ?? false">
|
||||||
function reportPhoto() {
|
function reportPhoto() {
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
<div style="float: right; font-size: .7rem;">
|
<div style="float: right; font-size: .7rem;">
|
||||||
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
||||||
<div class="heart" style="{if $comment->hasLikeFrom($thisUser)}opacity: 1;{else}opacity: 0.4;{/if}"></div>
|
<div class="heart" style="{if $comment->hasLikeFrom($thisUser)}opacity: 1;{else}opacity: 0.4;{/if}"></div>
|
||||||
<span class="likeCnt">{if $comment->getLikesCount() > 0}{$comment->getLikesCount()}{/if}</span>
|
<span class="likeCnt" onClick="openCounter({$comment->getId()}, 'likers', true); event.preventDefault(); event.stopPropagation();">{if $comment->getLikesCount() > 0}{$comment->getLikesCount()}{/if}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -114,7 +114,7 @@
|
||||||
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"{/ifset}>
|
<a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"{/ifset}>
|
||||||
{_share}
|
{_share}
|
||||||
{if $post->getRepostCount() > 0}
|
{if $post->getRepostCount() > 0}
|
||||||
(<b id="repostsCount{$post->getPrettyId()}">{$post->getRepostCount()}</b>)
|
(<b id="repostsCount{$post->getPrettyId()}" onClick="openCounter({$post->getPrettyId()}, 'reposts'); event.preventDefault(); event.stopPropagation();">{$post->getRepostCount()}</b>)
|
||||||
{/if}
|
{/if}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -123,12 +123,12 @@
|
||||||
{var $liked = $post->hasLikeFrom($thisUser)}
|
{var $liked = $post->hasLikeFrom($thisUser)}
|
||||||
<a href="/wall{$post->getPrettyId()}/like?hash={rawurlencode($csrfToken)}" class="post-like-button" data-liked="{(int) $liked}" data-likes="{$post->getLikesCount()}">
|
<a href="/wall{$post->getPrettyId()}/like?hash={rawurlencode($csrfToken)}" class="post-like-button" data-liked="{(int) $liked}" data-likes="{$post->getLikesCount()}">
|
||||||
<div class="heart" id="{if $liked}liked{/if}"></div>
|
<div class="heart" id="{if $liked}liked{/if}"></div>
|
||||||
<span class="likeCnt">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
|
<span class="likeCnt" onClick="openCounter({$post->getPrettyId()}, 'likers'); event.preventDefault(); event.stopPropagation();">{if $post->getLikesCount() > 0}{$post->getLikesCount()}{/if}</span>
|
||||||
</a>
|
</a>
|
||||||
{else}
|
{else}
|
||||||
<a n:if="$post->getLikesCount() > 0" class="post-like-button">
|
<a n:if="$post->getLikesCount() > 0" class="post-like-button">
|
||||||
<div class="heart"></div>
|
<div class="heart"></div>
|
||||||
<span class="likeCnt">{$post->getLikesCount()}</span>
|
<span class="likeCnt" onClick="openCounter({$post->getPrettyId()}, 'likers'); event.preventDefault(); event.stopPropagation();">{$post->getLikesCount()}</span>
|
||||||
</a>
|
</a>
|
||||||
{/ifset}
|
{/ifset}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -139,6 +139,12 @@ routes:
|
||||||
handler: "Wall->delete"
|
handler: "Wall->delete"
|
||||||
- url: "/wall{num}_{num}/pin"
|
- url: "/wall{num}_{num}/pin"
|
||||||
handler: "Wall->pin"
|
handler: "Wall->pin"
|
||||||
|
- url: "/wall{num}_{num}/likers"
|
||||||
|
handler: "Wall->likers"
|
||||||
|
- url: "/wall{num}_{num}/reposts"
|
||||||
|
handler: "Wall->reposters"
|
||||||
|
- url: "/comment{num}/likers"
|
||||||
|
handler: "Wall->commentLikers"
|
||||||
- url: "/blob_{text}/{?path}.{text}"
|
- url: "/blob_{text}/{?path}.{text}"
|
||||||
handler: "Blob->file"
|
handler: "Blob->file"
|
||||||
placeholders:
|
placeholders:
|
||||||
|
|
|
@ -263,3 +263,44 @@ async function showArticle(note_id) {
|
||||||
u("body").removeClass("dimmed");
|
u("body").removeClass("dimmed");
|
||||||
u("body").addClass("article");
|
u("body").addClass("article");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getUserDiv(url, fname, lname, avatar) {
|
||||||
|
return `
|
||||||
|
<div class="cl_element" style="width: 20%">
|
||||||
|
<div class="cl_avatar">
|
||||||
|
<a href="${url}">
|
||||||
|
<img class="ava" src="${avatar}"/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<a href="${url}" class="cl_name">
|
||||||
|
<text class="cl_fname">${fname}</text>
|
||||||
|
<text class="cl_lname">${lname}</text>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openCounter(id, type, is_comment = false) {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: `/${is_comment ? "comment" : "wall"}${id}/${type}`,
|
||||||
|
success: (response) => {
|
||||||
|
if (response.success) {
|
||||||
|
let html = "";
|
||||||
|
response.payload[1].forEach((user) => {
|
||||||
|
html += getUserDiv(user.url, user.fname, user.lname, user.avatar);
|
||||||
|
});
|
||||||
|
|
||||||
|
MessageBox(
|
||||||
|
(type === "likers" ? "Оценили" : "Поделились") + " (" + response.payload[0] + ")",
|
||||||
|
"<div class='content_list' style='width: inherit;'>" + html + "</div>",
|
||||||
|
["ОК"],
|
||||||
|
[Function.noop]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
NewNotification(tr("error"), (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue