mirror of
https://github.com/openvk/openvk
synced 2024-12-22 16:42:32 +03:00
Group [Very WIP]: Add early implementation of group's contacts
This commit is contained in:
parent
cb8038590c
commit
594d025ab8
12 changed files with 313 additions and 6 deletions
|
@ -3,7 +3,7 @@ namespace openvk\Web\Models\Entities;
|
|||
use openvk\Web\Util\DateTime;
|
||||
use openvk\Web\Models\RowModel;
|
||||
use openvk\Web\Models\Entities\{User, Manager};
|
||||
use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Managers};
|
||||
use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Managers, Contacts};
|
||||
use Nette\Database\Table\{ActiveRow, GroupedSelection};
|
||||
use Chandler\Database\DatabaseConnection as DB;
|
||||
use Chandler\Security\User as ChandlerUser;
|
||||
|
@ -302,6 +302,11 @@ class Club extends RowModel
|
|||
]);
|
||||
}
|
||||
|
||||
function getContacts(): \Traversable
|
||||
{
|
||||
return (new Contacts)->getByClub($this->getId());
|
||||
}
|
||||
|
||||
function removeManager(User $user): void
|
||||
{
|
||||
DB::i()->getContext()->table("group_coadmins")->where([
|
||||
|
|
36
Web/Models/Entities/Contact.php
Normal file
36
Web/Models/Entities/Contact.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Entities;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
use openvk\Web\Models\RowModel;
|
||||
use openvk\Web\Models\Repositories\Contacts;
|
||||
use openvk\Web\Models\Repositories\{Users, Clubs};
|
||||
|
||||
class Contact extends RowModel
|
||||
{
|
||||
protected $tableName = "group_contacts";
|
||||
|
||||
function getId(): int
|
||||
{
|
||||
return $this->getRecord()->id;
|
||||
}
|
||||
|
||||
function getUser(): ?User
|
||||
{
|
||||
return (new Users)->get($this->getRecord()->user);
|
||||
}
|
||||
|
||||
function getGroup(): ?Club
|
||||
{
|
||||
return (new Clubs)->get($this->getId());
|
||||
}
|
||||
|
||||
function getDescription(): string
|
||||
{
|
||||
return ovk_proc_strtr($this->getRecord()->content, 32);
|
||||
}
|
||||
|
||||
function getEmail(): string
|
||||
{
|
||||
return $this->getRecord()->email;
|
||||
}
|
||||
}
|
35
Web/Models/Repositories/Contacts.php
Normal file
35
Web/Models/Repositories/Contacts.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Repositories;
|
||||
use openvk\Web\Models\Entities\Contact;
|
||||
use Nette\Database\Table\ActiveRow;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
|
||||
class Contacts
|
||||
{
|
||||
private $context;
|
||||
private $contacts;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->context = DatabaseConnection::i()->getContext();
|
||||
$this->contacts = $this->context->table("group_contacts");
|
||||
}
|
||||
|
||||
function get(int $id): ?Contact
|
||||
{
|
||||
$ar = $this->clubs->get($id);
|
||||
return is_null($ar) ? NULL : new Contact($ar);
|
||||
}
|
||||
|
||||
function getByClub(int $id): \Traversable
|
||||
{
|
||||
$contacts = $this->contacts->where("group", $id)->where("deleted", 0);
|
||||
return new Util\EntityStream("Contact", $contacts);
|
||||
}
|
||||
|
||||
function getByClubAndUser(int $club, int $user): ?Contact
|
||||
{
|
||||
$contact = $this->contacts->where("group", $club)->where("user", $user)->fetch();
|
||||
return $this->get($contact);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Presenters;
|
||||
use openvk\Web\Models\Entities\{Club, Photo};
|
||||
use openvk\Web\Models\Entities\{Club, Photo, Contact};
|
||||
use openvk\Web\Models\Entities\Notifications\ClubModeratorNotification;
|
||||
use openvk\Web\Models\Repositories\{Clubs, Users, Albums, Managers};
|
||||
use openvk\Web\Models\Repositories\{Clubs, Users, Albums, Managers, Contacts};
|
||||
|
||||
final class GroupPresenter extends OpenVKPresenter
|
||||
{
|
||||
|
@ -131,7 +131,6 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
$this->flashFail("succ", "Операция успешна", $user->getCanonicalName() . " назначен(а) администратором.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function renderEdit(int $id): void
|
||||
|
@ -197,6 +196,62 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
$this->template->views = $club->getPostViewStats(false);
|
||||
}
|
||||
|
||||
function renderContacts(int $id): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
|
||||
$club = $this->clubs->get($id);
|
||||
$this->template->club = $club;
|
||||
$this->template->contacts = $club->getContacts()->page($this->queryParam("p") ?? 1);
|
||||
$this->template->count = $club->getContacts()->size();
|
||||
$this->template->paginatorConf = (object) [
|
||||
"count" => $this->template->count,
|
||||
"page" => $this->queryParam("p") ?? 1,
|
||||
"amount" => NULL,
|
||||
"perPage" => OPENVK_DEFAULT_PER_PAGE,
|
||||
];
|
||||
}
|
||||
|
||||
function renderActionContact(): void
|
||||
{
|
||||
$contact;
|
||||
$id = $this->queryParam("id");
|
||||
|
||||
if($this->queryParam("type") == 'delete' || $this->queryParam("type") == 'edit') {
|
||||
if(!$id)
|
||||
exit(json_encode([ "error" => tr("error_segmentation") ]));
|
||||
|
||||
$contact = (new Contacts)->get($id);
|
||||
|
||||
if(!$contact)
|
||||
exit(json_encode([ "error" => "Contact does not exist" ]));
|
||||
|
||||
if(!$contact->getClub()->canBeModifiedBy($this->user->identity ?? NULL) && $contact->getClub()->getOwner()->getId() !== $user->getId())
|
||||
exit(json_encode([ "error" => "You have no permissions to modify this contact" ]));
|
||||
}
|
||||
|
||||
if($this->queryParam("type") == 'delete') {
|
||||
$contact->setDeleted(1);
|
||||
$contact->save();
|
||||
exit(json_encode([ "status" => 'ok' ]));
|
||||
} else if ($this->queryParam("type") == 'edit') {
|
||||
if(!empty($this->queryParam("desc"))) {
|
||||
$contact->setContent($this->queryParam("desc"));
|
||||
$contact->save();
|
||||
exit(json_encode([ "status" => 'ok' ]));
|
||||
} else
|
||||
exit(json_encode([ "error" => "Description cannot be empty" ]));
|
||||
|
||||
} else if ($this->queryParam("type") == 'create') {
|
||||
/* ну тут мне впринципе дальше лень делать
|
||||
|
||||
$contact = new Contact;
|
||||
$contact->setGroup();
|
||||
$contact->save(); */
|
||||
exit(json_encode([ "error" => "Not implemented yet" ]));
|
||||
}
|
||||
}
|
||||
|
||||
function renderAdmin(int $clb, int $id): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
|
|
89
Web/Presenters/templates/Group/Contacts.xml
Normal file
89
Web/Presenters/templates/Group/Contacts.xml
Normal file
|
@ -0,0 +1,89 @@
|
|||
{extends "../@listView.xml"}
|
||||
{var iterator = $contacts}
|
||||
{var count = $paginatorConf->count}
|
||||
{var page = $paginatorConf->page}
|
||||
{var perPage = 6}
|
||||
|
||||
{block title}{_contacts} {$club->getCanonicalName()}{/block}
|
||||
|
||||
{block header}
|
||||
<a href="{$club->getURL()}">{$club->getCanonicalName()}</a>
|
||||
» {_contacts}
|
||||
{/block}
|
||||
|
||||
{block actions}
|
||||
|
||||
{/block}
|
||||
|
||||
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||
|
||||
{block tabs}
|
||||
{if $club->canBeModifiedBy($thisUser)}
|
||||
<div class="tab">
|
||||
<a href="javascript:void(0)">
|
||||
{_main}
|
||||
</a>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<a href="/club{$club->getId()}/followers">
|
||||
{_followers}
|
||||
</a>
|
||||
</div>
|
||||
<div id="activetabs" class="tab">
|
||||
<a id="act_tab_a" href="/club{$club->getId()}/contacts">
|
||||
{_contacts}
|
||||
</a>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<a href="/club{$club->getId()}/stats">
|
||||
{_statistics}
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
{block link|strip|stripHtml}
|
||||
/id{$x->getId()}
|
||||
{/block}
|
||||
|
||||
{block preview}
|
||||
<img src="{$x->getUser()->getAvatarURL()}" alt="{$x->getUser()->getCanonicalName()}" width=75 />
|
||||
{/block}
|
||||
|
||||
{block name}
|
||||
{$x->getUser()->getCanonicalName()}
|
||||
{/block}
|
||||
|
||||
{block description}
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_"gender"}: </span></td>
|
||||
<td>{$x->getUser()->isFemale() ? "женский" : "мужской"}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_description}: </span></td>
|
||||
<td>
|
||||
{$x->getDescription()}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_role}: </span></td>
|
||||
<td>
|
||||
{$club->canBeModifiedBy($x->getUser()) ? tr("administrator") : tr("follower")}
|
||||
</td>
|
||||
</tr>
|
||||
<tr n:if="$club->canBeModifiedBy($thisUser ?? NULL) && $club->getOwner()->getId() !== $x->getUser()->getId()">
|
||||
<td width="120" valign="top"><span class="nobold">{_actions}: </span></td>
|
||||
<td>
|
||||
<a href="javascript:contactEdit({$x->getUser()->getId()}, {rawurlencode($csrfToken)})">
|
||||
{_edit}
|
||||
</a>,
|
||||
<a href="javascript:contactDelete({$x->getUser()->getId()}, {rawurlencode($csrfToken)})">
|
||||
{_delete}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{/block}
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
{block content}
|
||||
<div class="tabs">
|
||||
<div id="activetabs" class="tab">
|
||||
<div class="tab">
|
||||
<a id="act_tab_a" href="javascript:void(0)">
|
||||
{_main}
|
||||
</a>
|
||||
|
@ -17,6 +17,11 @@
|
|||
{_followers}
|
||||
</a>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<a href="/club{$club->getId()}/contacts">
|
||||
{_contacts}
|
||||
</a>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<a href="/club{$club->getId()}/stats">
|
||||
{_statistics}
|
||||
|
|
|
@ -17,6 +17,31 @@
|
|||
|
||||
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||
|
||||
{block tabs}
|
||||
{if $club->canBeModifiedBy($thisUser)}
|
||||
<div class="tab">
|
||||
<a href="javascript:void(0)">
|
||||
{_main}
|
||||
</a>
|
||||
</div>
|
||||
<div id="activetabs" class="tab">
|
||||
<a id="act_tab_a" href="/club{$club->getId()}/followers">
|
||||
{_followers}
|
||||
</a>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<a href="/club{$club->getId()}/contacts">
|
||||
{_contacts}
|
||||
</a>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<a href="/club{$club->getId()}/stats">
|
||||
{_statistics}
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
{block link|strip|stripHtml}
|
||||
/id{$x->getId()}
|
||||
{/block}
|
||||
|
|
|
@ -104,6 +104,29 @@
|
|||
<div style="padding:4px">
|
||||
{_"group_type_open"}
|
||||
</div>
|
||||
</div><div>
|
||||
<div class="content_title_expanded" onclick="hidePanel(this);">
|
||||
Контакты
|
||||
</div>
|
||||
<div>
|
||||
{var contacts = $club->getContacts()}
|
||||
<div class="content_subtitle">
|
||||
{$contacts->size()}
|
||||
<div style="float:right;">
|
||||
<a href="/club{$club->getId()}/contacts">{_"all_title"}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group_contact" n:foreach="$contacts->page(1, 5) as $contact">
|
||||
<avatar>
|
||||
<img src="{$contact->getUser()->getAvatarUrl()}" style="image-rendering: -webkit-optimize-contrast;" />
|
||||
</avatar>
|
||||
<description>
|
||||
<a href="{$contact->getUser()->getURL()}"><b>{$contact->getUser()->getFullName()}</b></a><br>
|
||||
{$contact->getDescription()}
|
||||
</description>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="content_title_expanded" onclick="hidePanel(this);">
|
||||
|
|
|
@ -37,3 +37,4 @@ services:
|
|||
- openvk\Web\Models\Repositories\Vouchers
|
||||
- openvk\Web\Models\Repositories\Gifts
|
||||
- openvk\Web\Models\Repositories\ContentSearchRepository
|
||||
- openvk\Web\Models\Repositories\Contacts
|
||||
|
|
|
@ -145,6 +145,10 @@ routes:
|
|||
handler: "Group->statistics"
|
||||
- url: "/club{num}/followers"
|
||||
handler: "Group->followers"
|
||||
- url: "/club{num}/contacts"
|
||||
handler: "Group->contacts"
|
||||
- url: "/club{num}/contacts/action"
|
||||
handler: "Group->actionContact"
|
||||
- url: "/club{num}/followers/{num}"
|
||||
handler: "Group->admin"
|
||||
- url: "/club{num}/setAdmin.jsp"
|
||||
|
|
|
@ -1425,3 +1425,18 @@ body.scrolled .toTop:hover {
|
|||
#ovkDraw .literally .lc-picker .toolbar-button:hover:not(.disabled), #ovkDraw .literally .horz-toolbar .square-toolbar-button:hover:not(.disabled) {
|
||||
border-color: #cdcdcd;
|
||||
}
|
||||
|
||||
.group_contact {
|
||||
font-size: 10px;
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.group_contact avatar {
|
||||
width: 30px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.group_contact avatar img {
|
||||
width: 30px;
|
||||
}
|
||||
|
|
14
install/sqls/00003-contact-groups.sql
Normal file
14
install/sqls/00003-contact-groups.sql
Normal file
|
@ -0,0 +1,14 @@
|
|||
DROP TABLE IF EXISTS `group_contacts`;
|
||||
CREATE TABLE `group_contacts` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`group` bigint(20) unsigned NOT NULL,
|
||||
`user` bigint(20) unsigned NOT NULL,
|
||||
`content` varchar(64) COLLATE utf8mb4_general_nopad_ci NOT NULL,
|
||||
`email` varchar(64) COLLATE utf8mb4_general_nopad_ci DEFAULT NULL,
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `group` (`group`),
|
||||
KEY `user` (`user`),
|
||||
CONSTRAINT `group_contacts_ibfk_1` FOREIGN KEY (`group`) REFERENCES `groups` (`id`),
|
||||
CONSTRAINT `group_contacts_ibfk_2` FOREIGN KEY (`user`) REFERENCES `profiles` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_nopad_ci;
|
Loading…
Reference in a new issue