From 160231316018c59e42c0f98c34ae23f0c4943a24 Mon Sep 17 00:00:00 2001 From: mrilyew <99399973+mrilyew@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:16:21 +0300 Subject: [PATCH] preparations for picker --- Web/Models/Entities/Document.php | 18 ++++++++++-- Web/Models/Repositories/Documents.php | 24 ++++++---------- Web/Presenters/GroupPresenter.php | 5 +++- Web/Presenters/templates/Documents/List.xml | 6 ++-- .../templates/Documents/components/doc.xml | 6 ++-- .../templates/Documents/components/image.xml | 10 +++---- Web/Presenters/templates/Group/View.xml | 18 ++++++++++++ .../templates/components/attachment.xml | 4 +++ Web/static/css/main.css | 26 ++++++++++++++++-- Web/static/img/docs_controls.png | Bin 5482 -> 6094 bytes Web/static/js/al_docs.js | 10 ++++++- bootstrap.php | 9 ++++++ locales/ru.strings | 6 ++++ 13 files changed, 107 insertions(+), 35 deletions(-) diff --git a/Web/Models/Entities/Document.php b/Web/Models/Entities/Document.php index 7093e1ed..15b558b1 100644 --- a/Web/Models/Entities/Document.php +++ b/Web/Models/Entities/Document.php @@ -161,13 +161,16 @@ class Document extends Media return in_array($this->getVKAPIType(), [3, 4]); } - function isCopiedBy(User $user): bool + function isCopiedBy($user = NULL): bool { - if($user->getId() === $this->getOwnerID()) + if(!$user) + return false; + + if($user->getRealId() === $this->getOwnerID()) return true; return DatabaseConnection::i()->getContext()->table("documents")->where([ - "owner" => $user->getId(), + "owner" => $user->getRealId(), "copy_of" => $this->getId(), "deleted" => 0, ])->count() > 0; @@ -221,6 +224,15 @@ class Document extends Media return true; } + function getOwner(bool $real = false): RowModel + { + $oid = (int) $this->getRecord()->owner; + if($oid > 0) + return (new Users)->get($oid); + else + return (new Clubs)->get($oid * -1); + } + function getFileExtension(): string { if($this->tmp_format) { diff --git a/Web/Models/Repositories/Documents.php b/Web/Models/Repositories/Documents.php index 1e4fba6c..b102c30f 100644 --- a/Web/Models/Repositories/Documents.php +++ b/Web/Models/Repositories/Documents.php @@ -30,17 +30,19 @@ class Documents function getDocumentById(int $virtual_id, int $real_id, ?string $access_key = NULL): ?Document { $doc = $this->documents->where(['virtual_id' => $virtual_id, 'id' => $real_id]); - - if($access_key) { + /*if($access_key) { $doc->where("access_key", $access_key); - } + }*/ $doc = $doc->fetch(); - if(!is_null($doc)) - return new Document($doc); - else + if(is_null($doc)) return NULL; - + + $n_doc = new Document($doc); + if(!$n_doc->checkAccessKey($access_key)) + return NULL; + + return $n_doc; } function getDocumentsByOwner(int $owner, int $order = 0, int $type = -1): EntityStream @@ -85,14 +87,6 @@ class Documents ]; } - if(sizeof($response) < 1) { - return [[ - "count" => 0, - "type" => 0, - "name" => tr("document_type_0"), - ]]; - } - return $response; } diff --git a/Web/Presenters/GroupPresenter.php b/Web/Presenters/GroupPresenter.php index fd0e9a3d..cde025b5 100644 --- a/Web/Presenters/GroupPresenter.php +++ b/Web/Presenters/GroupPresenter.php @@ -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, Audios, Posts}; +use openvk\Web\Models\Repositories\{Clubs, Users, Albums, Managers, Topics, Audios, Posts, Documents}; use Chandler\Security\Authenticator; final class GroupPresenter extends OpenVKPresenter @@ -27,12 +27,15 @@ final class GroupPresenter extends OpenVKPresenter if ($club->isBanned()) { $this->template->_template = "Group/Banned.xml"; } else { + $docs = (new Documents)->getDocumentsByOwner($club->getRealId()); $this->template->albums = (new Albums)->getClubAlbums($club, 1, 3); $this->template->albumsCount = (new Albums)->getClubAlbumsCount($club); $this->template->topics = (new Topics)->getLastTopics($club, 3); $this->template->topicsCount = (new Topics)->getClubTopicsCount($club); $this->template->audios = (new Audios)->getRandomThreeAudiosByEntityId($club->getRealId()); $this->template->audiosCount = (new Audios)->getClubCollectionSize($club); + $this->template->docsCount = $docs->size(); + $this->template->docs = $docs->offsetLimit(0, 2); } if(!is_null($this->user->identity) && $club->getWallType() == 2) { diff --git a/Web/Presenters/templates/Documents/List.xml b/Web/Presenters/templates/Documents/List.xml index cd662aff..61613c50 100644 --- a/Web/Presenters/templates/Documents/List.xml +++ b/Web/Presenters/templates/Documents/List.xml @@ -51,18 +51,16 @@ {if $count > 0} {foreach $docs as $doc} {if $is_gallery} - {include "components/image.xml", doc => $doc, scroll_context => true} + {include "components/image.xml", doc => $doc, scroll_context => true, club => isset($group) ? $group : NULL} {else} - {include "components/doc.xml", doc => $doc, scroll_context => true} + {include "components/doc.xml", doc => $doc, scroll_context => true, club => isset($group) ? $group : NULL} {/if} {/foreach} {else} {include "../components/error.xml", description => tr("there_is_no_documents_alright")} {/if} - {include "../components/paginator.xml", conf => $paginatorConf} - {/block} diff --git a/Web/Presenters/templates/Documents/components/doc.xml b/Web/Presenters/templates/Documents/components/doc.xml index 4b81b5a3..c805661f 100644 --- a/Web/Presenters/templates/Documents/components/doc.xml +++ b/Web/Presenters/templates/Documents/components/doc.xml @@ -1,6 +1,6 @@ {var $preview = $doc->hasPreview() ? $doc->getPreview() : NULL} {var $tags = $doc->getTags()} -{var $copied = $doc->isCopiedBy($thisUser)} +{var $copied = !isset($club) ? $doc->isCopiedBy($thisUser) : $doc->isCopiedBy($club)} {var $modifiable = $doc->canBeModifiedBy($thisUser)}
@@ -19,7 +19,7 @@
{$doc->getPublicationTime()}, {readable_filesize($doc->getFilesize())}{if sizeof($tags) > 0} - - + {foreach $tags as $tag} {$tag}{if $tag != $tags[sizeof($tags) - 1]},{/if} @@ -28,7 +28,7 @@ {/if}
-
+
diff --git a/Web/Presenters/templates/Documents/components/image.xml b/Web/Presenters/templates/Documents/components/image.xml index d29458e9..e10dad17 100644 --- a/Web/Presenters/templates/Documents/components/image.xml +++ b/Web/Presenters/templates/Documents/components/image.xml @@ -1,15 +1,15 @@ {var $preview = $doc->hasPreview() ? $doc->getPreview() : NULL} -{var $copied = $doc->isCopiedBy($thisUser)} +{var $copied = !isset($club) ? $doc->isCopiedBy($thisUser) : $doc->isCopiedBy($club)} {var $modifiable = $doc->canBeModifiedBy($thisUser)}
gallery photo
-
-
-
-
+
+
+
+
diff --git a/Web/Presenters/templates/Group/View.xml b/Web/Presenters/templates/Group/View.xml index 915f96b3..a4f44c9a 100644 --- a/Web/Presenters/templates/Group/View.xml +++ b/Web/Presenters/templates/Group/View.xml @@ -291,6 +291,24 @@
+
+
+ {_documents} +
+
+ +
+ {foreach $docs as $doc} + {include "../Documents/components/doc.xml", doc => $doc, hideButtons => true, noTags => true} + {/foreach} +
+
+
{/block} diff --git a/Web/Presenters/templates/components/attachment.xml b/Web/Presenters/templates/components/attachment.xml index 59925f27..b60fbc1d 100644 --- a/Web/Presenters/templates/components/attachment.xml +++ b/Web/Presenters/templates/components/attachment.xml @@ -65,6 +65,10 @@
{include "../Audio/player.xml", audio => $attachment}
+{elseif $attachment instanceof \openvk\Web\Models\Entities\Document} +
+ {include "../Documents/components/doc.xml", doc => $attachment, copyImportance => true, noTags => true} +
{else} {_version_incompatibility} {/if} diff --git a/Web/static/css/main.css b/Web/static/css/main.css index 492b7ae8..0c6d6af4 100644 --- a/Web/static/css/main.css +++ b/Web/static/css/main.css @@ -4074,7 +4074,10 @@ hr { .docGalleryItem .doc_top_panel > div { width: 10px; height: 10px; - background-color: white; + background: url('/assets/packages/static/openvk/img/docs_controls.png?v=8'); + background-size: 57px; + background-position-y: -24px; + background-repeat: no-repeat; } #docs_page_wrapper select { @@ -4151,7 +4154,7 @@ hr { .docListViewItem .doc_volume > div { width: 20px; height: 20px; - background: url('/assets/packages/static/openvk/img/docs_controls.png?v=3'); + background: url('/assets/packages/static/openvk/img/docs_controls.png?v=8'); } .docListViewItem:hover .doc_volume { @@ -4163,7 +4166,7 @@ hr { background-position-y: -21px; } -.docListViewItem .doc_volume #report_icon { +.docListViewItem .doc_volume #report_icon, .docGalleryItem .doc_top_panel #report_icon { background-position-x: -40px; } @@ -4175,10 +4178,27 @@ hr { background-position-x: -60px; } +.docGalleryItem .doc_top_panel #add_icon { + background-position-x: -35px; +} + +.docGalleryItem .doc_top_panel #edit_icon { + background-position-x: -12px; +} + .docListViewItem .doc_volume #mark_icon { background-position-x: -80px; } +.docGalleryItem .doc_top_panel #mark_icon { + background-position-x: -46px; +} + .doc_viewer_wrapper { overflow: hidden; } + +.attachments .docListViewItem { + min-height: 30px; + border-bottom: unset; +} diff --git a/Web/static/img/docs_controls.png b/Web/static/img/docs_controls.png index f56b3c85ef752c86e4da9802cb094c242d7ec8c3..22f9d03d42ca0d2f56c775055aaf56c99d819335 100644 GIT binary patch delta 3193 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 { const docs = await window.OVKAPI.call('docs.getById', {docs: id, return_tags: 1}) const doc = docs[0] + if(!doc) { + fastError("(") + CMessageBox.toggleLoader() + return + } const cmsg_2 = new CMessageBox({ title: tr("document_editing_in_general"), @@ -248,6 +253,9 @@ u(document).on('click', '.docMainItem #report_icon', (e) => { u(document).on("click", ".docListViewItem a.viewerOpener, a.docGalleryItem", async (e) => { e.preventDefault() + if(e.target.closest('.doc_volume_action')) { + return + } const target = u(e.target) const link = target.closest('a') @@ -262,7 +270,7 @@ u(document).on("click", ".docListViewItem a.viewerOpener, a.docGalleryItem", asy const preview = body.querySelector('.photo-page-wrapper-photo') const details = body.querySelector('.ovk-photo-details') - preview.querySelector('img').setAttribute('id', 'ovk-photo-img') + u(preview.querySelector('img')).attr('id', 'ovk-photo-img') const photo_viewer = new CMessageBox({ title: '', diff --git a/bootstrap.php b/bootstrap.php index 8a5061d3..75b3140e 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -264,6 +264,7 @@ function parseAttachments($attachments, array $allow_types = ['photo', 'video', 'doc' => [ 'repo' => 'openvk\Web\Models\Repositories\Documents', 'method' => 'getDocumentById', + 'withKey' => true, ] ]; @@ -281,6 +282,14 @@ function parseAttachments($attachments, array $allow_types = ['photo', 'video', $repository_class = $repositories[$attachment_type]['repo']; if(!$repository_class) continue; $attachment_model = (new $repository_class)->{$repositories[$attachment_type]['method']}($attachment_id); + $output_attachments[] = $attachment_model; + } elseif($repositories[$attachment_type]['withKey']) { + [$attachment_owner, $attachment_id, $access_key] = explode('_', $attachment_ids); + + $repository_class = $repositories[$attachment_type]['repo']; + if(!$repository_class) continue; + $attachment_model = (new $repository_class)->{$repositories[$attachment_type]['method']}((int)$attachment_owner, (int)$attachment_id, $access_key); + $output_attachments[] = $attachment_model; } else { [$attachment_owner, $attachment_id] = array_map('intval', explode('_', $attachment_ids)); diff --git a/locales/ru.strings b/locales/ru.strings index 36bf91fc..dd27c424 100644 --- a/locales/ru.strings +++ b/locales/ru.strings @@ -2236,6 +2236,12 @@ "document_type_7" = "Книги"; "document_type_8" = "Остальные"; +"documents_one" = "$1 документ"; +"documents_few" = "$1 документа"; +"documents_many" = "$1 документов"; +"documents_other" = "$1 документов"; +"documents_zero" = "$1 документов"; + "you_have_x_documents_one" = "У Вас $1 документ"; "you_have_x_documents_few" = "У Вас $1 документа"; "you_have_x_documents_many" = "У Вас $1 документов";