mirror of
https://github.com/openvk/openvk
synced 2025-04-23 16:43:02 +03:00
Wall: add early suggestions
This commit is contained in:
parent
a2384cc231
commit
10729d8294
19 changed files with 530 additions and 26 deletions
|
@ -2,6 +2,7 @@
|
|||
namespace openvk\ServiceAPI;
|
||||
use openvk\Web\Models\Entities\Post;
|
||||
use openvk\Web\Models\Entities\User;
|
||||
use openvk\Web\Models\Entities\Notifications\{PostAcceptedNotification};
|
||||
use openvk\Web\Models\Repositories\{Posts, Notes};
|
||||
|
||||
class Wall implements Handler
|
||||
|
@ -95,4 +96,60 @@ class Wall implements Handler
|
|||
|
||||
$resolve($arr);
|
||||
}
|
||||
|
||||
function declinePost(int $id, callable $resolve, callable $reject)
|
||||
{
|
||||
$post = $this->posts->get($id);
|
||||
if(!$post || $post->isDeleted())
|
||||
$reject(11, "No post with id=$id");
|
||||
|
||||
if($post->getSuggestionType() == 0)
|
||||
$reject(19, "Post is not suggested");
|
||||
|
||||
if($post->getSuggestionType() == 2)
|
||||
$reject(10, "Post is already declined");
|
||||
|
||||
if(!$post->canBePinnedBy($this->user))
|
||||
$reject(22, "Access to post denied :)");
|
||||
|
||||
$post->setSuggested(2);
|
||||
$post->save();
|
||||
|
||||
$resolve($this->posts->getSuggestedPostsCount($post->getWallOwner()->getId()));
|
||||
}
|
||||
|
||||
function acceptPost(int $id, bool $sign, string $content, callable $resolve, callable $reject)
|
||||
{
|
||||
$post = $this->posts->get($id);
|
||||
if(!$post || $post->isDeleted())
|
||||
$reject(11, "No post with id=$id");
|
||||
|
||||
if($post->getSuggestionType() == 0)
|
||||
$reject(19, "Post is not suggested");
|
||||
|
||||
if($post->getSuggestionType() == 2)
|
||||
$reject(10, "Post is declined");
|
||||
|
||||
if(!$post->canBePinnedBy($this->user))
|
||||
$reject(22, "Access to post denied :)");
|
||||
|
||||
$author = $post->getOwner();
|
||||
$flags = 0;
|
||||
$flags |= 0b10000000;
|
||||
|
||||
if($sign) {
|
||||
$flags |= 0b01000000;
|
||||
}
|
||||
|
||||
$post->setSuggested(0);
|
||||
$post->setCreated(time());
|
||||
$post->setFlags($flags);
|
||||
$post->setContent($content);
|
||||
|
||||
$post->save();
|
||||
|
||||
(new PostAcceptedNotification($author, $post, $post->getWallOwner()))->emit();
|
||||
|
||||
$resolve(["id" => $post->getPrettyId(), "new_count" => $this->posts->getSuggestedPostsCount($post->getWallOwner()->getId())]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ use openvk\Web\Models\Repositories\Notes as NotesRepo;
|
|||
|
||||
final class Wall extends VKAPIRequestHandler
|
||||
{
|
||||
function get(int $owner_id, string $domain = "", int $offset = 0, int $count = 30, int $extended = 0): object
|
||||
function get(int $owner_id, string $domain = "", int $offset = 0, int $count = 30, int $extended = 0, string $filter = "all"): object
|
||||
{
|
||||
$this->requireUser();
|
||||
|
||||
|
@ -27,7 +27,7 @@ final class Wall extends VKAPIRequestHandler
|
|||
$items = [];
|
||||
$profiles = [];
|
||||
$groups = [];
|
||||
$cnt = $posts->getPostCountOnUserWall($owner_id);
|
||||
$cnt = 0;
|
||||
|
||||
if ($owner_id > 0)
|
||||
$wallOnwer = (new UsersRepo)->get($owner_id);
|
||||
|
@ -41,7 +41,43 @@ final class Wall extends VKAPIRequestHandler
|
|||
if(!$wallOnwer)
|
||||
$this->fail(15, "Access denied: wall is disabled"); // Don't search for logic here pls
|
||||
|
||||
foreach($posts->getPostsFromUsersWall($owner_id, 1, $count, $offset) as $post) {
|
||||
$iteratorv;
|
||||
|
||||
switch($filter) {
|
||||
case "all":
|
||||
$iteratorv = $posts->getPostsFromUsersWall($owner_id, 1, $count, $offset);
|
||||
$cnt = $posts->getPostCountOnUserWall($owner_id);
|
||||
break;
|
||||
case "owner":
|
||||
$this->fail(66666, "Not implemented :(");
|
||||
break;
|
||||
case "others":
|
||||
$this->fail(66666, "Not implemented :(");
|
||||
break;
|
||||
case "postponed":
|
||||
$this->fail(66666, "Otlojka is not implemented :)");
|
||||
break;
|
||||
# В апи, походу, нету метода, который бы публиковал запись из предложки
|
||||
case "suggests":
|
||||
if($owner_id < 0) {
|
||||
if($wallOnwer->canBeModifiedBy($this->getUser())) {
|
||||
$iteratorv = $posts->getSuggestedPosts($owner_id * -1, 1, $count, $offset);
|
||||
$cnt = $posts->getSuggestedPostsCount($owner_id * -1);
|
||||
} else {
|
||||
$iteratorv = $posts->getSuggestedPosts($owner_id * -1, 1, $count, $offset);
|
||||
$cnt = $posts->getSuggestedPostsCount($owner_id * -1);
|
||||
}
|
||||
} else {
|
||||
$this->fail(528, "Suggested posts avaiable only at groups");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
$this->fail(254, "Invalid filter");
|
||||
break;
|
||||
}
|
||||
|
||||
foreach($iteratorv as $post) {
|
||||
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
|
||||
|
||||
$attachments = [];
|
||||
|
@ -428,6 +464,11 @@ final class Wall extends VKAPIRequestHandler
|
|||
$post->setContent($message);
|
||||
$post->setFlags($flags);
|
||||
$post->setApi_Source_Name($this->getPlatform());
|
||||
|
||||
if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2) {
|
||||
$post->setSuggested(1);
|
||||
}
|
||||
|
||||
$post->save();
|
||||
} catch(\LogicException $ex) {
|
||||
$this->fail(100, "One of the parameters specified was missing or invalid");
|
||||
|
@ -494,6 +535,10 @@ final class Wall extends VKAPIRequestHandler
|
|||
if($wall > 0 && $wall !== $this->user->identity->getId())
|
||||
(new WallPostNotification($wallOwner, $post, $this->user->identity))->emit();
|
||||
|
||||
if($owner_id < 0 && !$wallOwner->canBeModifiedBy($this->getUser()) && $wallOwner->getWallType() == 2) {
|
||||
return (object)["post_id" => "on_view"];
|
||||
}
|
||||
|
||||
return (object)["post_id" => $post->getVirtualId()];
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ class Club extends RowModel
|
|||
const NOT_RELATED = 0;
|
||||
const SUBSCRIBED = 1;
|
||||
const REQUEST_SENT = 2;
|
||||
|
||||
const WALL_CLOSED = 0;
|
||||
const WALL_OPEN = 1;
|
||||
const WALL_LIMITED = 2;
|
||||
|
||||
function getId(): int
|
||||
{
|
||||
|
@ -45,6 +49,11 @@ class Club extends RowModel
|
|||
|
||||
return is_null($avPhoto) ? "$serverUrl/assets/packages/static/openvk/img/camera_200.png" : $avPhoto->getURLBySizeId($size);
|
||||
}
|
||||
|
||||
function getWallType(): int
|
||||
{
|
||||
return $this->getRecord()->wall;
|
||||
}
|
||||
|
||||
function getAvatarLink(): string
|
||||
{
|
||||
|
@ -182,6 +191,14 @@ class Club extends RowModel
|
|||
$this->stateChanges("shortcode", $code);
|
||||
return true;
|
||||
}
|
||||
|
||||
function setWall(int $type)
|
||||
{
|
||||
if($type > 3 || $type < 0)
|
||||
throw new \LogicException("Invalid wall");
|
||||
|
||||
$this->stateChanges("wall", $type);
|
||||
}
|
||||
|
||||
function isSubscriptionAccepted(User $user): bool
|
||||
{
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Entities\Notifications;
|
||||
use openvk\Web\Models\Entities\{User, Club, Post};
|
||||
|
||||
final class PostAcceptedNotification extends Notification
|
||||
{
|
||||
protected $actionCode = 6;
|
||||
|
||||
function __construct(User $author, Post $post, Club $group)
|
||||
{
|
||||
parent::__construct($author, $post, $group, time(), "");
|
||||
}
|
||||
}
|
|
@ -245,6 +245,11 @@ class Post extends Postable
|
|||
$this->unwire();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
function getSuggestionType()
|
||||
{
|
||||
return $this->getRecord()->suggested;
|
||||
}
|
||||
|
||||
use Traits\TRichText;
|
||||
}
|
||||
|
|
|
@ -58,9 +58,10 @@ class Posts
|
|||
}
|
||||
|
||||
$sel = $this->posts->where([
|
||||
"wall" => $user,
|
||||
"pinned" => false,
|
||||
"deleted" => false,
|
||||
"wall" => $user,
|
||||
"pinned" => false,
|
||||
"deleted" => false,
|
||||
"suggested" => 0,
|
||||
])->order("created DESC")->limit($perPage, $offset);
|
||||
|
||||
foreach($sel as $post)
|
||||
|
@ -74,6 +75,7 @@ class Posts
|
|||
->where("MATCH (content) AGAINST (? IN BOOLEAN MODE)", "+$hashtag")
|
||||
->where("deleted", 0)
|
||||
->order("created DESC")
|
||||
->where("suggested", 0)
|
||||
->page($page, $perPage ?? OPENVK_DEFAULT_PER_PAGE);
|
||||
|
||||
foreach($sel as $post)
|
||||
|
@ -85,14 +87,22 @@ class Posts
|
|||
$hashtag = "#$hashtag";
|
||||
$sel = $this->posts
|
||||
->where("content LIKE ?", "%$hashtag%")
|
||||
->where("deleted", 0);
|
||||
->where("deleted", 0)
|
||||
->where("suggested", 0);
|
||||
|
||||
return sizeof($sel);
|
||||
}
|
||||
|
||||
function getPostById(int $wall, int $post): ?Post
|
||||
function getPostById(int $wall, int $post, bool $forceSuggestion = false): ?Post
|
||||
{
|
||||
$post = $this->posts->where(['wall' => $wall, 'virtual_id' => $post])->fetch();
|
||||
$post = $this->posts->where(['wall' => $wall, 'virtual_id' => $post]);
|
||||
|
||||
if(!$forceSuggestion) {
|
||||
$post->where("suggested", 0);
|
||||
}
|
||||
|
||||
$post = $post->fetch();
|
||||
|
||||
if(!is_null($post))
|
||||
return new Post($post);
|
||||
else
|
||||
|
@ -112,7 +122,7 @@ class Posts
|
|||
else
|
||||
$paramValue != NULL ? $notNullParams+=["$paramName" => "$paramValue"] : NULL;
|
||||
|
||||
$result = $this->posts->where("content LIKE ?", $query)->where("deleted", 0);
|
||||
$result = $this->posts->where("content LIKE ?", $query)->where("deleted", 0)->where("suggested", 0);
|
||||
$nnparamsCount = sizeof($notNullParams);
|
||||
|
||||
if($nnparamsCount > 0) {
|
||||
|
@ -134,7 +144,44 @@ class Posts
|
|||
|
||||
function getPostCountOnUserWall(int $user): int
|
||||
{
|
||||
return sizeof($this->posts->where(["wall" => $user, "deleted" => 0]));
|
||||
return sizeof($this->posts->where(["wall" => $user, "deleted" => 0, "suggested" => 0]));
|
||||
}
|
||||
|
||||
function getSuggestedPosts(int $club, int $page = 1, ?int $perPage = NULL, ?int $offset = NULL): \Traversable
|
||||
{
|
||||
$sel = $this->posts
|
||||
->where("deleted", 0)
|
||||
->where("wall", $club * -1)
|
||||
->order("created DESC")
|
||||
->where("suggested", 1)
|
||||
->page($page, $perPage ?? OPENVK_DEFAULT_PER_PAGE);
|
||||
|
||||
foreach($sel as $post)
|
||||
yield new Post($post);
|
||||
}
|
||||
|
||||
function getSuggestedPostsCount(int $club)
|
||||
{
|
||||
return sizeof($this->posts->where(["wall" => $club * -1, "deleted" => 0, "suggested" => 1]));
|
||||
}
|
||||
|
||||
function getSuggestedPostsByUser(int $club, int $user, int $page = 1, ?int $perPage = NULL): \Traversable
|
||||
{
|
||||
$sel = $this->posts
|
||||
->where("deleted", 0)
|
||||
->where("wall", $club * -1)
|
||||
->where("owner", $user)
|
||||
->order("created DESC")
|
||||
->where("suggested", 1)
|
||||
->page($page, $perPage ?? OPENVK_DEFAULT_PER_PAGE);
|
||||
|
||||
foreach($sel as $post)
|
||||
yield new Post($post);
|
||||
}
|
||||
|
||||
function getSuggestedPostsCountByUser(int $club, int $user): int
|
||||
{
|
||||
return sizeof($this->posts->where(["wall" => $club * -1, "deleted" => 0, "suggested" => 1, "owner" => $user]));
|
||||
}
|
||||
|
||||
function getCount(): int
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace openvk\Web\Presenters;
|
|||
use openvk\Web\Models\Entities\{Club, Photo, Post};
|
||||
use Nette\InvalidStateException;
|
||||
use openvk\Web\Models\Entities\Notifications\ClubModeratorNotification;
|
||||
use openvk\Web\Models\Repositories\{Clubs, Users, Albums, Managers, Topics};
|
||||
use openvk\Web\Models\Repositories\{Posts, Clubs, Users, Albums, Managers, Topics};
|
||||
use Chandler\Security\Authenticator;
|
||||
|
||||
final class GroupPresenter extends OpenVKPresenter
|
||||
|
@ -29,6 +29,14 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
$this->template->topics = (new Topics)->getLastTopics($club, 3);
|
||||
$this->template->topicsCount = (new Topics)->getClubTopicsCount($club);
|
||||
|
||||
if(!is_null($this->user->identity) && !$club->canBeModifiedBy($this->user->identity) && $club->getWallType() == 2) {
|
||||
$this->template->suggestedPostsCountByUser = (new Posts)->getSuggestedPostsCountByUser($club->getId(), $this->user->id);
|
||||
}
|
||||
|
||||
if(!is_null($this->user->identity) && $club->canBeModifiedBy($this->user->identity) && $club->getWallType() == 2) {
|
||||
$this->template->suggestedPostsCountByEveryone = (new Posts)->getSuggestedPostsCount($club->getId());
|
||||
}
|
||||
|
||||
$this->template->club = $club;
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +200,7 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
$this->willExecuteWriteAction();
|
||||
|
||||
$club = $this->clubs->get($id);
|
||||
if(!$club || !$club->canBeModifiedBy($this->user->identity))
|
||||
if(!$club || !$club->canBeModifiedBy($this->user->identity) || $club->isDeleted())
|
||||
$this->notFound();
|
||||
else
|
||||
$this->template->club = $club;
|
||||
|
@ -396,4 +404,68 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
|
||||
$this->flashFail("succ", tr("information_-1"), tr("group_owner_setted", $newOwner->getCanonicalName(), $club->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
function renderSuggestedThisUser(int $id)
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
|
||||
$club = $this->clubs->get($id);
|
||||
if(!$club || method_exists($club, "isDeleted") && $club->isDeleted())
|
||||
$this->notFound();
|
||||
else
|
||||
$this->template->club = $club;
|
||||
|
||||
if($club->getWallType() == 1) {
|
||||
$this->flash("err", tr("error_suggestions"), tr("error_suggestions_closed"));
|
||||
$this->redirect("/club".$club->getId());
|
||||
}
|
||||
|
||||
if($club->getWallType() == 0) {
|
||||
$this->flash("err", tr("error_suggestions"), tr("error_suggestions_open"));
|
||||
$this->redirect("/club".$club->getId());
|
||||
}
|
||||
|
||||
if($club->canBeModifiedBy($this->user->identity)) {
|
||||
$this->flash("err", tr("error_suggestions"), "No sense");
|
||||
$this->redirect("/club".$club->getId());
|
||||
}
|
||||
|
||||
$this->template->posts = (new Posts)->getSuggestedPostsByUser($club->getId(), $this->user->id, (int) ($this->queryParam("p") ?? 1));
|
||||
$this->template->count = (new Posts)->getSuggestedPostsCountByUser($club->getId(), $this->user->id);
|
||||
$this->template->type = "my";
|
||||
$this->template->page = (int) ($this->queryParam("p") ?? 1);
|
||||
$this->template->_template = "Group/Suggested.xml";
|
||||
}
|
||||
|
||||
function renderSuggestedAll(int $id)
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
|
||||
$club = $this->clubs->get($id);
|
||||
if(!$club || method_exists($club, "isDeleted") && $club->isDeleted())
|
||||
$this->notFound();
|
||||
else
|
||||
$this->template->club = $club;
|
||||
|
||||
if($club->getWallType() == 1) {
|
||||
$this->flash("err", tr("error_suggestions"), tr("error_suggestions_closed"));
|
||||
$this->redirect("/club".$club->getId());
|
||||
}
|
||||
|
||||
if($club->getWallType() == 0) {
|
||||
$this->flash("err", tr("error_suggestions"), tr("error_suggestions_open"));
|
||||
$this->redirect("/club".$club->getId());
|
||||
}
|
||||
|
||||
if(!$club->canBeModifiedBy($this->user->identity)) {
|
||||
$this->flash("err", tr("error_suggestions"), tr("error_suggestions_access"));
|
||||
$this->redirect("/club".$club->getId());
|
||||
}
|
||||
|
||||
$this->template->posts = (new Posts)->getSuggestedPosts($club->getId(), (int) ($this->queryParam("p") ?? 1));
|
||||
$this->template->count = (new Posts)->getSuggestedPostsCount($club->getId());
|
||||
$this->template->type = "everyone";
|
||||
$this->template->page = (int) ($this->queryParam("p") ?? 1);
|
||||
$this->template->_template = "Group/Suggested.xml";
|
||||
}
|
||||
}
|
|
@ -148,6 +148,7 @@ final class WallPresenter extends OpenVKPresenter
|
|||
->select("id")
|
||||
->where("wall IN (?)", $ids)
|
||||
->where("deleted", 0)
|
||||
->where("suggested", 0)
|
||||
->order("created DESC");
|
||||
$this->template->paginatorConf = (object) [
|
||||
"count" => sizeof($posts),
|
||||
|
@ -167,7 +168,7 @@ final class WallPresenter extends OpenVKPresenter
|
|||
$page = (int) ($_GET["p"] ?? 1);
|
||||
$pPage = min((int) ($_GET["posts"] ?? OPENVK_DEFAULT_PER_PAGE), 50);
|
||||
|
||||
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND `posts`.`deleted` = 0";
|
||||
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND `posts`.`deleted` = 0 AND `posts`.`suggested` = 0";
|
||||
|
||||
if($this->user->identity->getNsfwTolerance() === User::NSFW_INTOLERANT)
|
||||
$queryBase .= " AND `nsfw` = 0";
|
||||
|
@ -305,6 +306,11 @@ final class WallPresenter extends OpenVKPresenter
|
|||
$post->setAnonymous($anon);
|
||||
$post->setFlags($flags);
|
||||
$post->setNsfw($this->postParam("nsfw") === "on");
|
||||
|
||||
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) {
|
||||
$post->setSuggested(1);
|
||||
}
|
||||
|
||||
$post->save();
|
||||
} catch (\LengthException $ex) {
|
||||
$this->flashFail("err", tr("failed_to_publish_post"), tr("post_is_too_big"));
|
||||
|
@ -334,7 +340,11 @@ final class WallPresenter extends OpenVKPresenter
|
|||
if($mentionee instanceof User)
|
||||
(new MentionNotification($mentionee, $post, $post->getOwner(), strip_tags($post->getText())))->emit();
|
||||
|
||||
$this->redirect($wallOwner->getURL());
|
||||
if($wall < 0 && !$wallOwner->canBeModifiedBy($this->user->identity) && $wallOwner->getWallType() == 2) {
|
||||
$this->redirect("/club".$wallOwner->getId()."/suggested");
|
||||
} else {
|
||||
$this->redirect($wallOwner->getURL());
|
||||
}
|
||||
}
|
||||
|
||||
function renderPost(int $wall, int $post_id): void
|
||||
|
@ -436,7 +446,7 @@ final class WallPresenter extends OpenVKPresenter
|
|||
$this->assertUserLoggedIn();
|
||||
$this->willExecuteWriteAction();
|
||||
|
||||
$post = $this->posts->getPostById($wall, $post_id);
|
||||
$post = $this->posts->getPostById($wall, $post_id, true);
|
||||
if(!$post)
|
||||
$this->notFound();
|
||||
$user = $this->user->id;
|
||||
|
|
|
@ -77,7 +77,12 @@
|
|||
<span class="nobold">{_wall}: </span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" name="wall" value="1" n:attr="checked => $club->canPost()" /> {_group_allow_post_for_everyone}<br>
|
||||
<select name="wall">
|
||||
<option value="1" n:attr="selected => $club->getWallType() == 1" /> {_group_allow_post_for_everyone}</option>
|
||||
<option value="2" n:attr="selected => $club->getWallType() == 2" /> {_group_limited_post}</option>
|
||||
<option value="0" n:attr="selected => $club->getWallType() == 0" /> {_group_closed_post}</option>
|
||||
<select>
|
||||
|
||||
<input type="checkbox" name="hide_from_global_feed" value="1" n:attr="checked => $club->isHideFromGlobalFeedEnabled()" /> {_group_hide_from_global_feed}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
26
Web/Presenters/templates/Group/Suggested.xml
Normal file
26
Web/Presenters/templates/Group/Suggested.xml
Normal file
|
@ -0,0 +1,26 @@
|
|||
{extends "../@layout.xml"}
|
||||
|
||||
{block title}{_suggested} {$club->getCanonicalName()}{/block}
|
||||
|
||||
{block header}
|
||||
<a href="{$club->getURL()}">{$club->getName()}</a>
|
||||
» {if $type == "my"}{_suggested_posts_by_you}{else}{_suggested_posts_by_everyone}{/if}
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
{if $count < 1}
|
||||
{include "../components/error.xml", title => "", description => $type == "my" ? tr("no_suggested_posts_by_you") : tr("no_suggested_posts_by_people")}
|
||||
{else}
|
||||
<h4 id="cound">{if $type == "my"}{tr("x_suggested_posts_in_group_by_you", $count)}{else}{tr("x_suggested_posts_in_group", $count)}{/if}</h4>
|
||||
{foreach $posts as $post}
|
||||
{include "../components/post/microblogpost.xml", post => $post, commentSection => false, suggestion => true, forceNoCommentsLink => true, forceNoPinLink => true, forceNoLike => true, forceNoShareLink => true}
|
||||
{/foreach}
|
||||
{/if}
|
||||
{include "../components/paginator.xml", conf => (object) [
|
||||
"page" => $page,
|
||||
"count" => $count,
|
||||
"amount" => sizeof($posts),
|
||||
"perPage" => OPENVK_DEFAULT_PER_PAGE,
|
||||
"atBottom" => true,
|
||||
]}
|
||||
{/block}
|
|
@ -91,7 +91,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div n:if="!is_null($suggestedPostsCountByUser) && $suggestedPostsCountByUser > 0" class="sugglist">
|
||||
<a href="/club{$club->getId()}/suggested">{tr("show_suggested_posts", $suggestedPostsCountByUser)}</a>
|
||||
</div>
|
||||
|
||||
<div n:if="!is_null($suggestedPostsCountByEveryone) && $suggestedPostsCountByEveryone > 0" class="sugglist">
|
||||
<a href="/club{$club->getId()}/suggested/all">{tr("show_suggested_posts_everyone", $suggestedPostsCountByEveryone)}</a>
|
||||
</div>
|
||||
|
||||
{presenter "openvk!Wall->wallEmbedded", -$club->getId()}
|
||||
|
||||
<script n:if="isset($thisUser) && $club->getWallType() == 2 && !$club->canBeModifiedBy($thisUser)">
|
||||
document.querySelector("textarea").setAttribute("placeholder", tr("suggest_new"))
|
||||
</script>
|
||||
</div>
|
||||
<div class="right_small_block">
|
||||
{var $avatarPhoto = $club->getAvatarPhoto()}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{var $club = $notification->getModel(1)}
|
||||
{var $post = $notification->getModel(0)}
|
||||
|
||||
{_group}
|
||||
<a href="{$club->getURL()}"><b>{$club->getName()}</b></a>
|
||||
{_nt_accepted_your_post}
|
||||
<a href="/wall{$post->getPrettyId()}"><b>{_nt_post_small}</b></a>.
|
|
@ -65,7 +65,7 @@
|
|||
</div>
|
||||
<div class="post-content" id="{$post->getPrettyId()}">
|
||||
<div class="text" id="text{$post->getPrettyId()}">
|
||||
{$post->getText()|noescape}
|
||||
<span class="really_text">{$post->getText()|noescape}</span>
|
||||
|
||||
<div n:ifcontent class="attachments_b">
|
||||
<div class="attachment" n:foreach="$post->getChildren() as $attachment" data-localized-nsfw-text="{_nsfw_warning}">
|
||||
|
@ -88,7 +88,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="post-menu" n:if="$compact == false">
|
||||
<a href="/wall{$post->getPrettyId()}" class="date">{$post->getPublicationTime()}</a>
|
||||
<a href="{if !$suggestion}/wall{$post->getPrettyId()}{else}javascript:void(0){/if}" class="date">{$post->getPublicationTime()}</a>
|
||||
<a n:if="!empty($platform)" class="client_app" data-app-tag="{$platform}" data-app-name="{$platformDetails['name']}" data-app-url="{$platformDetails['url']}" data-app-img="{$platformDetails['img']}">
|
||||
<img src="/assets/packages/static/openvk/img/app_icons_mini/{$post->getPlatform(this)}.svg">
|
||||
</a>
|
||||
|
@ -124,6 +124,10 @@
|
|||
{include "../textArea.xml", route => $commentsURL, postOpts => false, graffiti => (bool) ovkGetQuirk("comments.allow-graffiti"), post => $post, club => $club}
|
||||
</div>
|
||||
</div>
|
||||
<div n:if="$suggestion && $post->canBePinnedBy($thisUser ?? NULL)" class="suggestionControls">
|
||||
<input type="button" class="button" id="publish_post" data-id="{$post->getId()}" value="{_publish_suggested}">
|
||||
<input type="button" class="button" id="decline_post" data-id="{$post->getId()}" value="{_decline_suggested}">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -201,6 +201,10 @@ routes:
|
|||
handler: "Group->admin"
|
||||
- url: "/club{num}/setAdmin"
|
||||
handler: "Group->modifyAdmin"
|
||||
- url: "/club{num}/suggested"
|
||||
handler: "Group->suggestedThisUser"
|
||||
- url: "/club{num}/suggested/all"
|
||||
handler: "Group->suggestedAll"
|
||||
- url: "/groups{num}"
|
||||
handler: "User->groups"
|
||||
- url: "/groups_pin"
|
||||
|
|
|
@ -2695,4 +2695,22 @@ body.article .floating_sidebar, body.article .page_content {
|
|||
position: absolute;
|
||||
right: 22px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.sugglist {
|
||||
padding-bottom: 5px;
|
||||
padding-top: 5px;
|
||||
margin-bottom: -5px;
|
||||
padding-left: 9px;
|
||||
border-top: 1px solid gray;
|
||||
background-color: #e6e6e6;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.sugglist a {
|
||||
color: #626262;
|
||||
}
|
||||
|
||||
.suggestionControls {
|
||||
text-align: center;
|
||||
}
|
|
@ -192,7 +192,7 @@ tippy(".client_app", {
|
|||
function addNote(textareaId, nid)
|
||||
{
|
||||
if(nid > 0) {
|
||||
note.value = nid
|
||||
document.getElementById("note").value = nid
|
||||
let noteObj = document.querySelector("#nd"+nid)
|
||||
|
||||
let nortd = document.querySelector("#post-buttons"+textareaId+" .post-has-note");
|
||||
|
@ -200,7 +200,7 @@ function addNote(textareaId, nid)
|
|||
|
||||
nortd.innerHTML = `${tr("note")} ${escapeHtml(noteObj.dataset.name)}`
|
||||
} else {
|
||||
note.value = "none"
|
||||
document.getElementById("note").value = "none"
|
||||
|
||||
let nortd = document.querySelector("#post-buttons"+textareaId+" .post-has-note");
|
||||
nortd.style.display = "none"
|
||||
|
@ -227,7 +227,7 @@ async function attachNote(id)
|
|||
${tr("select_or_create_new")}
|
||||
<div id="notesList">`
|
||||
|
||||
if(note.value != "none") {
|
||||
if(document.getElementById("note").value != "none") {
|
||||
body += `
|
||||
<div class="ntSelect" onclick="addNote(${id}, 0)">
|
||||
<span>${tr("do_not_attach_note")}</span>
|
||||
|
@ -262,4 +262,86 @@ async function showArticle(note_id) {
|
|||
u("#articleText").html(`<h1 class="articleView_nameHeading">${note.title}</h1>` + note.html);
|
||||
u("body").removeClass("dimmed");
|
||||
u("body").addClass("article");
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on("click", "#publish_post", async (e) => {
|
||||
let id = Number(e.currentTarget.dataset.id)
|
||||
let post;
|
||||
let body = `
|
||||
<textarea id="pooblish" style="max-height:500px;resize:vertical;min-height:54px;"></textarea>
|
||||
<label><input type="checkbox" id="signatr" checked>${tr("add_signature")}</label>
|
||||
`
|
||||
|
||||
MessageBox(tr("publishing_suggested_post"), body, [tr("publish"), tr("cancel")], [(async () => {
|
||||
let id = Number(e.currentTarget.dataset.id)
|
||||
let post;
|
||||
|
||||
try {
|
||||
post = await API.Wall.acceptPost(id, document.getElementById("signatr").checked, document.getElementById("pooblish").value)
|
||||
} catch(ex) {
|
||||
switch(ex.code) {
|
||||
case 11:
|
||||
MessageBox(tr("error"), tr("error_declining_invalid_post"), [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
case 19:
|
||||
MessageBox(tr("error"), tr("error_declining_not_suggested_post"), [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
case 10:
|
||||
MessageBox(tr("error"), tr("error_declining_declined_post"), [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
case 22:
|
||||
MessageBox(tr("error"), "Access denied", [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
default:
|
||||
MessageBox(tr("error"), "Unknown error "+ex.code+": "+ex.message, [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NewNotification(tr("suggestion_succefully_published"), tr("suggestion_press_to_go"), null, () => {window.location.assign("/wall" + post.id)});
|
||||
document.getElementById("cound").innerHTML = tr("x_suggested_posts_in_group", post.new_count)
|
||||
e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode.outerHTML = ""
|
||||
}), Function.noop]);
|
||||
|
||||
document.getElementById("pooblish").innerHTML = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode.querySelector(".really_text").innerHTML
|
||||
document.querySelector(".ovk-diag-body").style.padding = "9px";
|
||||
})
|
||||
|
||||
$(document).on("click", "#decline_post", async (e) => {
|
||||
let id = Number(e.currentTarget.dataset.id)
|
||||
let post;
|
||||
|
||||
try {
|
||||
e.currentTarget.parentNode.parentNode.insertAdjacentHTML("afterbegin", `<img id="deleteMe" src="/assets/packages/static/openvk/img/loading_mini.gif">`)
|
||||
post = await API.Wall.declinePost(id)
|
||||
} catch(ex) {
|
||||
switch(ex.code) {
|
||||
case 11:
|
||||
MessageBox(tr("error"), tr("error_declining_invalid_post"), [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
case 19:
|
||||
MessageBox(tr("error"), tr("error_declining_not_suggested_post"), [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
case 10:
|
||||
MessageBox(tr("error"), tr("error_declining_declined_post"), [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
case 22:
|
||||
MessageBox(tr("error"), "Access denied", [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
default:
|
||||
MessageBox(tr("error"), "Unknown error "+ex.code+": "+ex.message, [tr("ok")], [Function.noop]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} finally {
|
||||
u("#deleteMe").remove()
|
||||
}
|
||||
|
||||
// а хули
|
||||
NewNotification(tr("suggestion_succefully_declined"), "", null);
|
||||
e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode.outerHTML = ""
|
||||
document.getElementById("cound").innerHTML = tr("x_suggested_posts_in_group", post)
|
||||
})
|
1
install/sqls/00039-suggest-posts.sql
Normal file
1
install/sqls/00039-suggest-posts.sql
Normal file
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `posts` ADD `suggested` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER `deleted`;
|
|
@ -260,6 +260,7 @@
|
|||
|
||||
/* Group */
|
||||
|
||||
"group" = "Group";
|
||||
"name_group" = "Name";
|
||||
"subscribe" = "Subscribe";
|
||||
"unsubscribe" = "Unsubscribe";
|
||||
|
@ -297,8 +298,38 @@
|
|||
"set_comment" = "Set comment";
|
||||
"hidden_yes" = "Hidden: Yes";
|
||||
"hidden_no" = "Hidden: No";
|
||||
"group_allow_post_for_everyone" = "Allow posting for everyone";
|
||||
"group_allow_post_for_everyone" = "Open";
|
||||
"group_limited_post" = "Suggestions";
|
||||
"group_closed_post" = "Closed";
|
||||
"suggest_new" = "Suggest post";
|
||||
"show_suggested_posts" = "$1 suggested posts by you";
|
||||
"show_suggested_posts_everyone" = "$1 suggested posts";
|
||||
"group_hide_from_global_feed" = "Don't display posts in the global feed";
|
||||
"suggested_posts_by_you" = "Suggested posts by you";
|
||||
"suggested_posts_by_everyone" = "Suggested posts";
|
||||
"suggested" = "Suggested";
|
||||
"suggested_posts_everyone" = "Suggested by users posts";
|
||||
"no_suggested_posts_by_you" = "You haven't suggested posts to this group yet.";
|
||||
"no_suggested_posts_by_people" = "No posts have been suggested to this group yet.";
|
||||
|
||||
"publish_suggested" = "Accept";
|
||||
"decline_suggested" = "Decline";
|
||||
|
||||
"publishing_suggested_post" = "Publishing suggested post";
|
||||
"x_suggested_posts_in_group" = "This group has $1 suggested posts";
|
||||
"x_suggested_posts_in_group_by_you" = "You suggested $1 posts to this group";
|
||||
|
||||
"suggestion_succefully_published" = "Post successfully published";
|
||||
"suggestion_succefully_declined" = "Post successfully declined";
|
||||
"suggestion_press_to_go" = "Click to show him";
|
||||
|
||||
"error_declining_invalid_post" = "Error when declining post: post does not exists";
|
||||
"error_declining_not_suggested_post" = "Error when declining post: post is not suggested";
|
||||
"error_declining_declined_post" = "Error when declining post: post is already declined";
|
||||
|
||||
"error_accepting_invalid_post" = "Error when accepting post: post does not exists";
|
||||
"error_accepting_not_suggested_post" = "Error when accepting post: post is not suggested";
|
||||
"error_accepting_declined_post" = "Error when accepting post: cant accept declined post";
|
||||
"statistics" = "Statistics";
|
||||
"group_administrators_list" = "Admins list";
|
||||
"group_display_only_creator" = "Display only group creator";
|
||||
|
@ -331,6 +362,11 @@
|
|||
"search_by_groups" = "Search by groups";
|
||||
"search_group_desc" = "Here you can browse through the existing groups and choose a group to suit your needs...";
|
||||
|
||||
"error_suggestions" = "Error accessing to suggestions";
|
||||
"error_suggestions_closed" = "This group has closed wall.";
|
||||
"error_suggestions_open" = "This group has open wall.";
|
||||
"error_suggestions_access" = "Only group's administrators can view all suggested posts.";
|
||||
|
||||
/* Albums */
|
||||
|
||||
"create" = "Create";
|
||||
|
@ -675,6 +711,7 @@
|
|||
"nt_shared_yours" = "shared your";
|
||||
"nt_commented_yours" = "commented";
|
||||
"nt_written_on_your_wall" = "wrote on your wall";
|
||||
"nt_accepted_your_post" = "accepted your suggested";
|
||||
"nt_made_you_admin" = "appointed you in the community";
|
||||
|
||||
"nt_from" = "from";
|
||||
|
@ -694,6 +731,8 @@
|
|||
"nt_mention_in_note" = "in discussion of this note";
|
||||
"nt_mention_in_topic" = "in the discussion";
|
||||
|
||||
"nt_post_small" = "post";
|
||||
|
||||
/* Time */
|
||||
|
||||
"time_at_sp" = " at ";
|
||||
|
|
|
@ -245,6 +245,7 @@
|
|||
|
||||
/* Group */
|
||||
|
||||
"group" = "Сообщество";
|
||||
"name_group" = "Название";
|
||||
"subscribe" = "Подписаться";
|
||||
"unsubscribe" = "Отписаться";
|
||||
|
@ -281,8 +282,40 @@
|
|||
"set_comment" = "Изменить комментарий";
|
||||
"hidden_yes" = "Скрыт: Да";
|
||||
"hidden_no" = "Скрыт: Нет";
|
||||
"group_allow_post_for_everyone" = "Разрешить публиковать записи всем";
|
||||
|
||||
"group_allow_post_for_everyone" = "Открытая";
|
||||
"group_limited_post" = "Предложка";
|
||||
"group_closed_post" = "Закрытая";
|
||||
"suggest_new" = "Предложить новость";
|
||||
"show_suggested_posts" = "$1 предложенных вами записей";
|
||||
"show_suggested_posts_everyone" = "$1 предложенных записей";
|
||||
"group_hide_from_global_feed" = "Не отображать публикации в глобальной ленте";
|
||||
"suggested_posts_by_you" = "Предложенные вами записи";
|
||||
"suggested_posts_by_everyone" = "Предложенные записи";
|
||||
"suggested" = "Предложено";
|
||||
"suggested_posts_everyone" = "Предложенные пользователями записи";
|
||||
"no_suggested_posts_by_you" = "Вы ещё не предлагали записей в эту группу.";
|
||||
"no_suggested_posts_by_people" = "В эту группу ещё не предлагали записей.";
|
||||
|
||||
"publish_suggested" = "Опубликовать запись";
|
||||
"decline_suggested" = "Отклонить";
|
||||
|
||||
"publishing_suggested_post" = "Публикация предложенной записи";
|
||||
"x_suggested_posts_in_group" = "В эту группу предложили $1 записей";
|
||||
"x_suggested_posts_in_group_by_you" = "Вы предложили в эту группу $1 записей";
|
||||
|
||||
"suggestion_succefully_published" = "Запись успешно опубликована";
|
||||
"suggestion_succefully_declined" = "Запись успешно отклонена";
|
||||
"suggestion_press_to_go" = "Нажмите, чтобы перейти к ней";
|
||||
|
||||
"error_declining_invalid_post" = "Не удалость отклонить пост: поста не существует";
|
||||
"error_declining_not_suggested_post" = "Не удалость отклонить пост: пост не из предложки";
|
||||
"error_declining_declined_post" = "Не удалость отклонить пост: пост уже отклонён";
|
||||
|
||||
"error_accepting_invalid_post" = "Не удалость принять пост: поста не существует";
|
||||
"error_accepting_not_suggested_post" = "Не удалость принять пост: пост не из предложки";
|
||||
"error_accepting_declined_post" = "Не удалость принять пост: пост отклонён";
|
||||
|
||||
"statistics" = "Статистика";
|
||||
"group_administrators_list" = "Список админов";
|
||||
"group_display_only_creator" = "Отображать только создателя группы";
|
||||
|
@ -315,6 +348,11 @@
|
|||
"search_by_groups" = "Поиск по группам";
|
||||
"search_group_desc" = "Здесь Вы можете просмотреть существующие группы и выбрать группу себе по вкусу...";
|
||||
|
||||
"error_suggestions" = "Ошибка доступа к предложенным";
|
||||
"error_suggestions_closed" = "У этой группы закрытая стена.";
|
||||
"error_suggestions_open" = "У этой группы открытая стена.";
|
||||
"error_suggestions_access" = "Просматривать все предложенные записи могут только администраторы группы.";
|
||||
|
||||
/* Albums */
|
||||
|
||||
"create" = "Создать";
|
||||
|
@ -632,6 +670,7 @@
|
|||
"nt_shared_yours" = "поделился(-ась) вашим";
|
||||
"nt_commented_yours" = "оставил(а) комментарий под";
|
||||
"nt_written_on_your_wall" = "написал(а) на вашей стене";
|
||||
"nt_accepted_your_post" = "опубликовало вашу предложенную";
|
||||
"nt_made_you_admin" = "назначил(а) вас руководителем сообщества";
|
||||
"nt_from" = "от";
|
||||
"nt_yours_adjective" = "вашим";
|
||||
|
@ -649,6 +688,7 @@
|
|||
"nt_mention_in_video" = "в обсуждении видеозаписи";
|
||||
"nt_mention_in_note" = "в обсуждении заметки";
|
||||
"nt_mention_in_topic" = "в обсуждении";
|
||||
"nt_post_small" = "запись";
|
||||
|
||||
/* Time */
|
||||
|
||||
|
|
Loading…
Reference in a new issue