mirror of
https://github.com/openvk/openvk
synced 2025-01-22 07:44:27 +03:00
better ui, search, uploading (icons by myslivets)
Co-Authored-By: Daniel <60743585+myslivets@users.noreply.github.com>
This commit is contained in:
parent
a91563fdf6
commit
36560555b6
18 changed files with 332 additions and 23 deletions
|
@ -36,6 +36,9 @@ final class Docs extends VKAPIRequestHandler
|
||||||
|
|
||||||
if(!$doc->canBeModifiedBy($this->getUser()))
|
if(!$doc->canBeModifiedBy($this->getUser()))
|
||||||
$this->fail(1153, "Access to document is denied");
|
$this->fail(1153, "Access to document is denied");
|
||||||
|
|
||||||
|
$doc->delete();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +164,7 @@ final class Docs extends VKAPIRequestHandler
|
||||||
$params["tags"] = $tags;
|
$params["tags"] = $tags;
|
||||||
|
|
||||||
if($search_own === 1)
|
if($search_own === 1)
|
||||||
$params["owner_id"] = $this->getUser()->getId();
|
$params["from_me"] = $this->getUser()->getId();
|
||||||
|
|
||||||
$documents = (new Documents)->find($q, $params, $o_order);
|
$documents = (new Documents)->find($q, $params, $o_order);
|
||||||
$res = (object)[
|
$res = (object)[
|
||||||
|
|
|
@ -433,6 +433,14 @@ class Club extends RowModel
|
||||||
return $this->isEveryoneCanUploadAudios() || $this->canBeModifiedBy($user);
|
return $this->isEveryoneCanUploadAudios() || $this->canBeModifiedBy($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function canUploadDocs(?User $user): bool
|
||||||
|
{
|
||||||
|
if(!$user)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return $this->canBeModifiedBy($user);
|
||||||
|
}
|
||||||
|
|
||||||
function getAudiosCollectionSize()
|
function getAudiosCollectionSize()
|
||||||
{
|
{
|
||||||
return (new \openvk\Web\Models\Repositories\Audios)->getClubCollectionSize($this);
|
return (new \openvk\Web\Models\Repositories\Audios)->getClubCollectionSize($this);
|
||||||
|
|
|
@ -151,6 +151,11 @@ class Document extends Media
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isAnonymous(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function isCopiedBy(User $user): bool
|
function isCopiedBy(User $user): bool
|
||||||
{
|
{
|
||||||
if($user->getId() === $this->getOwnerID())
|
if($user->getId() === $this->getOwnerID())
|
||||||
|
@ -159,11 +164,20 @@ class Document extends Media
|
||||||
return DatabaseConnection::i()->getContext()->table("documents")->where([
|
return DatabaseConnection::i()->getContext()->table("documents")->where([
|
||||||
"owner" => $user->getId(),
|
"owner" => $user->getId(),
|
||||||
"copy_of" => $this->getId(),
|
"copy_of" => $this->getId(),
|
||||||
|
"deleted" => 0,
|
||||||
])->count() > 0;
|
])->count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function copy(User $user): Document
|
function copy(User $user): Document
|
||||||
{
|
{
|
||||||
|
$item = DatabaseConnection::i()->getContext()->table("documents")->where([
|
||||||
|
"owner" => $user->getId(),
|
||||||
|
"copy_of" => $this->getId(),
|
||||||
|
]);
|
||||||
|
if($item->count() > 0) {
|
||||||
|
$older = new Document($item->fetch());
|
||||||
|
}
|
||||||
|
|
||||||
$this_document_array = $this->getRecord()->toArray();
|
$this_document_array = $this->getRecord()->toArray();
|
||||||
|
|
||||||
$new_document = new Document;
|
$new_document = new Document;
|
||||||
|
@ -186,6 +200,22 @@ class Document extends Media
|
||||||
return $new_document;
|
return $new_document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setTags(?string $tags): bool
|
||||||
|
{
|
||||||
|
if(!$tags) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed = explode(",", $tags);
|
||||||
|
$result = "";
|
||||||
|
foreach($parsed as $tag) {
|
||||||
|
$result .= mb_trim($tag) . ($tag != end($parsed) ? "," : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stateChanges("tags", $result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function getFileExtension(): string
|
function getFileExtension(): string
|
||||||
{
|
{
|
||||||
if($this->tmp_format) {
|
if($this->tmp_format) {
|
||||||
|
@ -200,6 +230,11 @@ class Document extends Media
|
||||||
return $this->getVirtualId() . "_" . $this->getId();
|
return $this->getVirtualId() . "_" . $this->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPrettiestId(): string
|
||||||
|
{
|
||||||
|
return $this->getVirtualId() . "_" . $this->getId() . "_" . $this->getAccessKey();
|
||||||
|
}
|
||||||
|
|
||||||
function getOriginal(): Document
|
function getOriginal(): Document
|
||||||
{
|
{
|
||||||
return $this->getRecord()->copy_of;
|
return $this->getRecord()->copy_of;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use Nette\Database\Table\ActiveRow;
|
||||||
use openvk\Web\Models\RowModel;
|
use openvk\Web\Models\RowModel;
|
||||||
use openvk\Web\Models\Entities\Club;
|
use openvk\Web\Models\Entities\Club;
|
||||||
use Chandler\Database\DatabaseConnection;
|
use Chandler\Database\DatabaseConnection;
|
||||||
use openvk\Web\Models\Repositories\{Applications, Comments, Notes, Reports, Audios, Users, Posts, Photos, Videos, Clubs};
|
use openvk\Web\Models\Repositories\{Applications, Comments, Notes, Reports, Audios, Documents, Users, Posts, Photos, Videos, Clubs};
|
||||||
use Chandler\Database\DatabaseConnection as DB;
|
use Chandler\Database\DatabaseConnection as DB;
|
||||||
use Nette\InvalidStateException as ISE;
|
use Nette\InvalidStateException as ISE;
|
||||||
use Nette\Database\Table\Selection;
|
use Nette\Database\Table\Selection;
|
||||||
|
@ -75,6 +75,7 @@ class Report extends RowModel
|
||||||
else if ($this->getContentType() == "app") return (new Applications)->get($this->getContentId());
|
else if ($this->getContentType() == "app") return (new Applications)->get($this->getContentId());
|
||||||
else if ($this->getContentType() == "user") return (new Users)->get($this->getContentId());
|
else if ($this->getContentType() == "user") return (new Users)->get($this->getContentId());
|
||||||
else if ($this->getContentType() == "audio") return (new Audios)->get($this->getContentId());
|
else if ($this->getContentType() == "audio") return (new Audios)->get($this->getContentId());
|
||||||
|
else if ($this->getContentType() == "doc") return (new Documents)->get($this->getContentId());
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class Documents
|
||||||
$result = DatabaseConnection::i()->getConnection()->query("SELECT `type`, COUNT(*) AS `count` FROM `documents` WHERE `owner` = $owner_id GROUP BY `type` ORDER BY `type`");
|
$result = DatabaseConnection::i()->getConnection()->query("SELECT `type`, COUNT(*) AS `count` FROM `documents` WHERE `owner` = $owner_id GROUP BY `type` ORDER BY `type`");
|
||||||
$response = [];
|
$response = [];
|
||||||
foreach($result as $res) {
|
foreach($result as $res) {
|
||||||
if($res->count < 1) continue;
|
if($res->count < 1 || $res->type == 0) continue;
|
||||||
|
|
||||||
$name = tr("document_type_".$res->type);
|
$name = tr("document_type_".$res->type);
|
||||||
$response[] = [
|
$response[] = [
|
||||||
|
@ -118,7 +118,7 @@ class Documents
|
||||||
case "tags":
|
case "tags":
|
||||||
$result->where("tags", $paramValue);
|
$result->where("tags", $paramValue);
|
||||||
break;
|
break;
|
||||||
case "owner_id":
|
case "from_me":
|
||||||
$result->where("owner", $paramValue);
|
$result->where("owner", $paramValue);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ final class DocumentsPresenter extends OpenVKPresenter
|
||||||
$docs = (new Documents)->getDocumentsByOwner($owner_id, (int)$order, (int)$tab);
|
$docs = (new Documents)->getDocumentsByOwner($owner_id, (int)$order, (int)$tab);
|
||||||
$this->template->tabs = (new Documents)->getTypes($owner_id);
|
$this->template->tabs = (new Documents)->getTypes($owner_id);
|
||||||
$this->template->current_tab = $tab;
|
$this->template->current_tab = $tab;
|
||||||
|
$this->template->order = $order;
|
||||||
$this->template->count = $docs->size();
|
$this->template->count = $docs->size();
|
||||||
$this->template->docs = iterator_to_array($docs->page($page, OPENVK_DEFAULT_PER_PAGE));
|
$this->template->docs = iterator_to_array($docs->page($page, OPENVK_DEFAULT_PER_PAGE));
|
||||||
$this->template->locale_string = "you_have_x_documents";
|
$this->template->locale_string = "you_have_x_documents";
|
||||||
|
@ -42,7 +43,8 @@ final class DocumentsPresenter extends OpenVKPresenter
|
||||||
} elseif($current_tab != 0) {
|
} elseif($current_tab != 0) {
|
||||||
$this->template->locale_string = "x_documents_in_tab";
|
$this->template->locale_string = "x_documents_in_tab";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->template->canUpload = $owner_id == $this->user->id || $this->template->group->canBeModifiedBy($this->user->identity);
|
||||||
$this->template->paginatorConf = (object) [
|
$this->template->paginatorConf = (object) [
|
||||||
"count" => $this->template->count,
|
"count" => $this->template->count,
|
||||||
"page" => $page,
|
"page" => $page,
|
||||||
|
@ -68,7 +70,7 @@ final class DocumentsPresenter extends OpenVKPresenter
|
||||||
if(!is_null($this->queryParam("gid"))) {
|
if(!is_null($this->queryParam("gid"))) {
|
||||||
$gid = (int) $this->queryParam("gid");
|
$gid = (int) $this->queryParam("gid");
|
||||||
$group = (new Clubs)->get($gid);
|
$group = (new Clubs)->get($gid);
|
||||||
if(!$group)
|
if(!$group || $group->isBanned())
|
||||||
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
$this->flashFail("err", tr("forbidden"), tr("not_enough_permissions_comment"), null, $isAjax);
|
||||||
|
|
||||||
if(!$group->canUploadDocs($this->user->identity))
|
if(!$group->canUploadDocs($this->user->identity))
|
||||||
|
@ -105,5 +107,14 @@ final class DocumentsPresenter extends OpenVKPresenter
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$document->save();
|
$document->save();
|
||||||
|
|
||||||
|
if(!$isAjax) {
|
||||||
|
$this->redirect("/docs" . (isset($group) ? $group->getRealId() : ""));
|
||||||
|
} else {
|
||||||
|
$this->returnJson([
|
||||||
|
"success" => true,
|
||||||
|
"redirect" => "/docs" . (isset($group) ? $group->getRealId() : ""),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ final class ReportPresenter extends OpenVKPresenter
|
||||||
if ($_SERVER["REQUEST_METHOD"] === "POST")
|
if ($_SERVER["REQUEST_METHOD"] === "POST")
|
||||||
$this->assertNoCSRF();
|
$this->assertNoCSRF();
|
||||||
|
|
||||||
$act = in_array($this->queryParam("act"), ["post", "photo", "video", "group", "comment", "note", "app", "user", "audio"]) ? $this->queryParam("act") : NULL;
|
$act = in_array($this->queryParam("act"), ["post", "photo", "video", "group", "comment", "note", "app", "user", "audio", "doc"]) ? $this->queryParam("act") : NULL;
|
||||||
|
|
||||||
if (!$this->queryParam("orig")) {
|
if (!$this->queryParam("orig")) {
|
||||||
$this->template->reports = $this->reports->getReports(0, (int)($this->queryParam("p") ?? 1), $act, $_SERVER["REQUEST_METHOD"] !== "POST");
|
$this->template->reports = $this->reports->getReports(0, (int)($this->queryParam("p") ?? 1), $act, $_SERVER["REQUEST_METHOD"] !== "POST");
|
||||||
|
@ -93,7 +93,7 @@ final class ReportPresenter extends OpenVKPresenter
|
||||||
if ($this->queryParam("type") === "user" && $id === $this->user->id)
|
if ($this->queryParam("type") === "user" && $id === $this->user->id)
|
||||||
exit(json_encode([ "error" => "You can't report yourself" ]));
|
exit(json_encode([ "error" => "You can't report yourself" ]));
|
||||||
|
|
||||||
if(in_array($this->queryParam("type"), ["post", "photo", "video", "group", "comment", "note", "app", "user", "audio"])) {
|
if(in_array($this->queryParam("type"), ["post", "photo", "video", "group", "comment", "note", "app", "user", "audio", "doc"])) {
|
||||||
if (count(iterator_to_array($this->reports->getDuplicates($this->queryParam("type"), $id, NULL, $this->user->id))) <= 0) {
|
if (count(iterator_to_array($this->reports->getDuplicates($this->queryParam("type"), $id, NULL, $this->user->id))) <= 0) {
|
||||||
$report = new Report;
|
$report = new Report;
|
||||||
$report->setUser_id($this->user->id);
|
$report->setUser_id($this->user->id);
|
||||||
|
|
|
@ -142,6 +142,7 @@
|
||||||
<option n:attr="selected => $_REQUEST['section'] == 'apps'" value="apps">{_s_by_apps}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'apps'" value="apps">{_s_by_apps}</option>
|
||||||
<option n:attr="selected => $_REQUEST['section'] == 'audios'" value="audios">{_s_by_audios}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'audios'" value="audios">{_s_by_audios}</option>
|
||||||
<option n:attr="selected => $_REQUEST['section'] == 'audios_playlists'" value="audios_playlists">{_s_by_audios_playlists}</option>
|
<option n:attr="selected => $_REQUEST['section'] == 'audios_playlists'" value="audios_playlists">{_s_by_audios_playlists}</option>
|
||||||
|
<option n:attr="selected => $_REQUEST['section'] == 'docs'" value="docs">{_s_by_documents}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button class="search_box_button">
|
<button class="search_box_button">
|
||||||
|
@ -195,12 +196,12 @@
|
||||||
(<b>{$thisUser->getNotificationsCount()}</b>)
|
(<b>{$thisUser->getNotificationsCount()}</b>)
|
||||||
</object>
|
</object>
|
||||||
</a>
|
</a>
|
||||||
<a n:if="$thisUser->getLeftMenuItemStatus('apps')" href="/apps?act=installed" class="link">{_my_apps}</a>
|
|
||||||
<a href="/settings" class="link">{_my_settings}</a>
|
<a href="/settings" class="link">{_my_settings}</a>
|
||||||
|
|
||||||
{if $thisUser->getLeftMenuItemStatus('docs')}
|
{if $thisUser->getLeftMenuItemStatus('docs') || $thisUser->getLeftMenuItemStatus('apps')}
|
||||||
<div class="menu_divider"></div>
|
<div class="menu_divider"></div>
|
||||||
<a href="/docs" class="link">{_my_documents}</a>
|
<a n:if="$thisUser->getLeftMenuItemStatus('apps')" href="/apps?act=installed" class="link">{_apps}</a>
|
||||||
|
<a n:if="$thisUser->getLeftMenuItemStatus('docs')" href="/docs" class="link">{_my_documents}</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{var $canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
|
{var $canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
|
||||||
|
@ -467,6 +468,8 @@
|
||||||
"current_id": {$thisUser ? $thisUser->getId() : 0},
|
"current_id": {$thisUser ? $thisUser->getId() : 0},
|
||||||
"disable_ajax": {$disable_ajax ? $disable_ajax : 0},
|
"disable_ajax": {$disable_ajax ? $disable_ajax : 0},
|
||||||
"max_add_fields": {ovkGetQuirk("users.max-fields")},
|
"max_add_fields": {ovkGetQuirk("users.max-fields")},
|
||||||
|
"docs_max": {\OPENVK_ROOT_CONF["openvk"]["preferences"]["docs"]["maxSize"]},
|
||||||
|
"docs_allowed": {\OPENVK_ROOT_CONF["openvk"]["preferences"]["docs"]["allowedFormats"]},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,27 @@
|
||||||
<input type="hidden" name="section" value="docs">
|
<input type="hidden" name="section" value="docs">
|
||||||
<input type="search" name="q" class="input_with_search_icon" placeholder="{_search_by_documents}">
|
<input type="search" name="q" class="input_with_search_icon" placeholder="{_search_by_documents}">
|
||||||
</form>
|
</form>
|
||||||
<input class="button" type="button" value="{_upload_button}">
|
<input n:if="$canUpload" id="upload_entry_point" class="button" type="button" value="{_upload_button}" {if isset($group)}data-gid="{$group->getId()}"{/if}>
|
||||||
</div>
|
</div>
|
||||||
<div class="docs_page_tabs">
|
<div class="docs_page_tabs">
|
||||||
<div class="mb_tabs">
|
<div class="mb_tabs">
|
||||||
|
<div class="mb_tab" n:attr="id => $current_tab == 0 ? active">
|
||||||
|
<a href="?tab=0">{_document_type_0}</a>
|
||||||
|
</div>
|
||||||
<div n:foreach="$tabs as $tab" class="mb_tab" n:attr="id => $tab['type'] == $current_tab ? active">
|
<div n:foreach="$tabs as $tab" class="mb_tab" n:attr="id => $tab['type'] == $current_tab ? active">
|
||||||
<a href="?tab={$tab['type']}">{$tab["name"]}</a>
|
<a href="?tab={$tab['type']}">{$tab["name"]}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="docs_page_content">
|
<div class="docs_page_content">
|
||||||
<div class="summaryBar">
|
<div class="summaryBar display_flex_row display_flex_space_between">
|
||||||
<div class="summary">{tr($locale_string, $count)}.</div>
|
<div class="summary">{tr($locale_string, $count)}.</div>
|
||||||
|
|
||||||
|
<select name="docs_sort">
|
||||||
|
<option n:attr="selected => $order == 0" value="0">{_documents_sort_add}</option>
|
||||||
|
<option n:attr="selected => $order == 1" value="1">{_documents_sort_alphabet}</option>
|
||||||
|
<option n:attr="selected => $order == 2" value="2">{_documents_sort_size}</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="container_white">
|
<div class="container_white">
|
||||||
{if $count > 0}
|
{if $count > 0}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
{var $copied = $doc->isCopiedBy($thisUser)}
|
{var $copied = $doc->isCopiedBy($thisUser)}
|
||||||
{var $modifiable = $doc->canBeModifiedBy($thisUser)}
|
{var $modifiable = $doc->canBeModifiedBy($thisUser)}
|
||||||
|
|
||||||
<div class="docListViewItem" data-id="{$doc->getId()}">
|
<div class="docListViewItem" data-id="{$doc->getPrettiestId()}">
|
||||||
<a>
|
<a>
|
||||||
{if $preview}
|
{if $preview}
|
||||||
<img class="doc_icon" alt="document_preview" src="{$preview->getURLBySizeId('tiny')}">
|
<img class="doc_icon" alt="document_preview" src="{$preview->getURLBySizeId('tiny')}">
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
<div class="doc_content_info">
|
<div class="doc_content_info">
|
||||||
<span>{$doc->getPublicationTime()}</span>,
|
<span>{$doc->getPublicationTime()}</span>,
|
||||||
<span>{readable_filesize($doc->getFilesize())}</span>{if sizeof($tags) > 0} -
|
<span>{readable_filesize($doc->getFilesize())}</span>{if sizeof($tags) > 0} -
|
||||||
<span>
|
<span style="text-wrap: wrap;">
|
||||||
{foreach $tags as $tag}
|
{foreach $tags as $tag}
|
||||||
<a href="/search?section=docs&tags={urlencode($tag)}">
|
<a href="/search?section=docs&tags={urlencode($tag)}">
|
||||||
{$tag}{if $tag != $tags[sizeof($tags) - 1]},{/if}
|
{$tag}{if $tag != $tags[sizeof($tags) - 1]},{/if}
|
||||||
|
@ -29,9 +29,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="doc_volume">
|
<div class="doc_volume">
|
||||||
<div n:if="!$$modifiable" id="report_icon"></div>
|
<div n:if="!$modifiable" id="report_icon"></div>
|
||||||
<div n:if="$modifiable" id="edit_icon"></div>
|
<div n:if="$modifiable" id="edit_icon"></div>
|
||||||
<div n:if="!$copied" id="add_icon"></div>
|
<div n:if="!$copied || $copied && $copyImportance" id="add_icon"></div>
|
||||||
<div n:if="$copied" id="remove_icon"></div>
|
<div n:if="$copied && !$copyImportance" id="remove_icon"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -49,6 +49,9 @@
|
||||||
<div n:attr="id => ($mode === 'audio' ? 'activetabs' : 'ki')" class="tab" mode="audio">
|
<div n:attr="id => ($mode === 'audio' ? 'activetabs' : 'ki')" class="tab" mode="audio">
|
||||||
<a n:attr="id => ($mode === 'audio' ? 'act_tab_a' : 'ki')">{_audios}</a>
|
<a n:attr="id => ($mode === 'audio' ? 'act_tab_a' : 'ki')">{_audios}</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div n:attr="id => ($mode === 'docs' ? 'activetabs' : 'ki')" class="tab" mode="doc">
|
||||||
|
<a n:attr="id => ($mode === 'docs' ? 'act_tab_a' : 'ki')">{_documents}</a>
|
||||||
|
</div>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
{/if}
|
{/if}
|
||||||
{elseif $type == "audio"}
|
{elseif $type == "audio"}
|
||||||
{include "../Audio/player.xml", audio => $object}
|
{include "../Audio/player.xml", audio => $object}
|
||||||
|
{elseif $type == "doc"}
|
||||||
|
{include "../Documents/components/doc.xml", doc => $object}
|
||||||
{else}
|
{else}
|
||||||
{include "../components/error.xml", description => tr("version_incompatibility")}
|
{include "../components/error.xml", description => tr("version_incompatibility")}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -284,6 +284,18 @@
|
||||||
highlightText({$query}, '.page_wrap_content_main', [".playlistName", ".playlistDesc"])
|
highlightText({$query}, '.page_wrap_content_main', [".playlistName", ".playlistDesc"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__scrollHook()
|
||||||
|
</script>
|
||||||
|
{elseif $section === 'docs'}
|
||||||
|
<div class='scroll_node search_content' n:foreach="$data as $dat">
|
||||||
|
{include "../Documents/components/doc.xml", doc => $dat, copyImportance => true}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script n:if="$count > 0 && !empty($query)">
|
||||||
|
function __scrollHook(page) {
|
||||||
|
highlightText({$query}, '.page_wrap_content_main', [".doc_content .noOverflow"])
|
||||||
|
}
|
||||||
|
|
||||||
__scrollHook()
|
__scrollHook()
|
||||||
</script>
|
</script>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -300,6 +312,7 @@
|
||||||
<a n:attr="id => $section === 'apps' ? 'used'" href="/search?section=apps&q={urlencode($query)}"> {_s_apps}</a>
|
<a n:attr="id => $section === 'apps' ? 'used'" href="/search?section=apps&q={urlencode($query)}"> {_s_apps}</a>
|
||||||
<a n:attr="id => $section === 'audios' ? 'used'" href="/search?section=audios&q={urlencode($query)}"> {_s_audios}</a>
|
<a n:attr="id => $section === 'audios' ? 'used'" href="/search?section=audios&q={urlencode($query)}"> {_s_audios}</a>
|
||||||
<a n:attr="id => $section === 'audios_playlists' ? 'used'" href="/search?section=audios_playlists&q={urlencode($query)}">{_s_audios_playlists}</a>
|
<a n:attr="id => $section === 'audios_playlists' ? 'used'" href="/search?section=audios_playlists&q={urlencode($query)}">{_s_audios_playlists}</a>
|
||||||
|
<a n:attr="id => $section === 'docs' ? 'used'" href="/search?section=docs&q={urlencode($query)}">{_s_documents}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='page_search_options'>
|
<div class='page_search_options'>
|
||||||
|
@ -415,6 +428,19 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div n:if="$section == 'docs'" class="search_option">
|
||||||
|
<div class="search_option_name">
|
||||||
|
<div class='search_option_name_ico'></div>
|
||||||
|
{_s_type}
|
||||||
|
</div>
|
||||||
|
<div class="search_option_content">
|
||||||
|
<select name="type" form="search_form" data-default='0'>
|
||||||
|
<option n:foreach="range(0, 8) as $i" value="{$i}" n:attr="selected => $_REQUEST['type'] == $i">
|
||||||
|
{tr("document_type_".$i)}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div n:if="$section == 'audios'" class="search_option">
|
<div n:if="$section == 'audios'" class="search_option">
|
||||||
<div class="search_option_name">
|
<div class="search_option_name">
|
||||||
<div class='search_option_name_ico'></div>
|
<div class='search_option_name_ico'></div>
|
||||||
|
|
|
@ -55,6 +55,10 @@ h1 {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.display_flex_space_between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
width: 791px;
|
width: 791px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
@ -4006,6 +4010,10 @@ hr {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#docs_page_wrapper select {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
.docListViewItem {
|
.docListViewItem {
|
||||||
max-height: 52px;
|
max-height: 52px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
|
@ -4068,17 +4076,39 @@ hr {
|
||||||
}
|
}
|
||||||
|
|
||||||
.docListViewItem .doc_volume {
|
.docListViewItem .doc_volume {
|
||||||
display: none;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.docListViewItem .doc_volume > div {
|
.docListViewItem .doc_volume > div {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
background-color: gray;
|
background: url('/assets/packages/static/openvk/img/docs_controls.png?v=3');
|
||||||
}
|
}
|
||||||
|
|
||||||
.docListViewItem:hover .doc_volume {
|
.docListViewItem:hover .doc_volume {
|
||||||
display: flex;
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docListViewItem .doc_volume > div:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-position-y: -21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docListViewItem .doc_volume #report_icon {
|
||||||
|
background-position-x: -40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docListViewItem .doc_volume #edit_icon {
|
||||||
|
background-position-x: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docListViewItem .doc_volume #add_icon {
|
||||||
|
background-position-x: -60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docListViewItem .doc_volume #mark_icon {
|
||||||
|
background-position-x: -80px;
|
||||||
}
|
}
|
||||||
|
|
BIN
Web/static/img/docs_controls.png
Normal file
BIN
Web/static/img/docs_controls.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
|
@ -1 +1,160 @@
|
||||||
u()
|
function showDocumentUploadDialog(target = null, append_to_url = null)
|
||||||
|
{
|
||||||
|
let file = null
|
||||||
|
const cmsg = new CMessageBox({
|
||||||
|
title: tr("document_uploading_in_general"),
|
||||||
|
body: `
|
||||||
|
<b>${tr("limits")}</b>
|
||||||
|
<ul style="margin: 5px 0px;padding-left: 20px;">
|
||||||
|
<li>${tr('limitations_file_limit_size', window.openvk.docs_max)}.</li>
|
||||||
|
<li>${tr('limitations_file_allowed_formats')}: ${window.openvk.docs_allowed.sort(() => Math.random() - 0.59).slice(0, 10).join(', ')}.</li>
|
||||||
|
<li>${tr("limitations_file_author_rights")}.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div style="text-align:center;margin: 10px 0px 2px 0px;">
|
||||||
|
<input onclick="upload_btn.click()" class="button" type="button" value="${tr("select_file_fp")}">
|
||||||
|
<input id="upload_btn" type="file" style="display:none;">
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
buttons: [tr('close')],
|
||||||
|
callbacks: [Function.noop],
|
||||||
|
})
|
||||||
|
|
||||||
|
cmsg.getNode().find('.ovk-diag-body').attr('style', "padding:15px;")
|
||||||
|
cmsg.getNode().attr('style', "width: 400px;")
|
||||||
|
cmsg.getNode().find('#upload_btn').on('change', (e) => {
|
||||||
|
file = e.target.files[0]
|
||||||
|
const name = file.name
|
||||||
|
const format = name.split(".")[1]
|
||||||
|
if(window.openvk.docs_allowed.indexOf(format) == -1) {
|
||||||
|
makeError(tr("error_file_invalid_format"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(file.size > window.openvk.docs_max * 1024 * 1024) {
|
||||||
|
makeError(tr("error_file_too_big"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmsg.close()
|
||||||
|
|
||||||
|
const cmsg_2 = new CMessageBox({
|
||||||
|
title: tr("document_uploading_in_general"),
|
||||||
|
body: `
|
||||||
|
<p><b>${tr("info_name")}</b></p>
|
||||||
|
<input type="text" name="doc_name" value="${name}" placeholder="...">
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input value="0" type="radio" name="doc_access" checked>
|
||||||
|
${tr("private_document")}
|
||||||
|
</label>
|
||||||
|
<br>
|
||||||
|
<label>
|
||||||
|
<input value="3" type="radio" name="doc_access">
|
||||||
|
${tr("public_document")}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<p><b>${tr("tags")}</b></p>
|
||||||
|
<input type="text" name="doc_tags" placeholder="...">
|
||||||
|
<br>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="doc_owner" checked>
|
||||||
|
${tr("owner_is_hidden")}
|
||||||
|
</label>
|
||||||
|
`,
|
||||||
|
buttons: [tr('upload_button'), tr('cancel')],
|
||||||
|
callbacks: [async () => {
|
||||||
|
const fd = new FormData
|
||||||
|
fd.append("name", u(`input[name="doc_name"]`).nodes[0].value)
|
||||||
|
fd.append("tags", u(`input[name="doc_tags"]`).nodes[0].value)
|
||||||
|
fd.append("folder", u(`input[name="doc_access"]:checked`).nodes[0].value)
|
||||||
|
fd.append("owner_hidden", u(`input[name="doc_owner"]`).nodes[0].checked ? "on" : "off")
|
||||||
|
fd.append("blob", file)
|
||||||
|
fd.append("ajax", 1)
|
||||||
|
fd.append("hash", window.router.csrf)
|
||||||
|
|
||||||
|
const endpoint_url = `/docs/upload` + (!isNaN(append_to_url) ? "?gid="+append_to_url : '')
|
||||||
|
const fetcher = await fetch(endpoint_url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: fd,
|
||||||
|
})
|
||||||
|
const json = await fetcher.json()
|
||||||
|
|
||||||
|
if(json.success) {
|
||||||
|
window.router.route(location.href)
|
||||||
|
}
|
||||||
|
}, Function.noop],
|
||||||
|
})
|
||||||
|
cmsg_2.getNode().find('.ovk-diag-body').attr('style', "padding:15px;")
|
||||||
|
cmsg_2.getNode().attr('style', "width: 400px;")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
u(document).on('click', '#upload_entry_point', (e) => {
|
||||||
|
showDocumentUploadDialog(null, Number(e.target.dataset.gid))
|
||||||
|
})
|
||||||
|
|
||||||
|
u(document).on('change', "#docs_page_wrapper select[name='docs_sort']", (e) => {
|
||||||
|
const new_url = new URL(location.href)
|
||||||
|
new_url.searchParams.set('order', e.target.value)
|
||||||
|
|
||||||
|
window.router.route(new_url.href)
|
||||||
|
})
|
||||||
|
|
||||||
|
u(document).on('click', '.docListViewItem #remove_icon', async (e) => {
|
||||||
|
const target = u(e.target).closest("#remove_icon")
|
||||||
|
const item = target.closest('.docListViewItem')
|
||||||
|
const id = item.nodes[0].dataset.id.split("_")
|
||||||
|
|
||||||
|
target.addClass('lagged')
|
||||||
|
const res = await window.OVKAPI.call('docs.delete', {owner_id: id[0], doc_id: id[1]})
|
||||||
|
target.removeClass('lagged')
|
||||||
|
|
||||||
|
if(res == 1) {
|
||||||
|
target.attr('id', 'add_icon')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
u(document).on('click', '.docListViewItem #add_icon', async (e) => {
|
||||||
|
const target = u(e.target).closest("#add_icon")
|
||||||
|
const item = target.closest('.docListViewItem')
|
||||||
|
const id = item.nodes[0].dataset.id.split("_")
|
||||||
|
|
||||||
|
target.addClass('lagged')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await window.OVKAPI.call('docs.add', {owner_id: id[0], doc_id: id[1], access_key: id[2]})
|
||||||
|
} catch(e) {
|
||||||
|
makeError(tr("error_file_adding_copied"))
|
||||||
|
target.removeClass('lagged')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
target.removeClass('lagged')
|
||||||
|
target.attr('id', 'mark_icon')
|
||||||
|
})
|
||||||
|
|
||||||
|
u(document).on('click', '.docListViewItem #report_icon', (e) => {
|
||||||
|
const target = u(e.target).closest("#report_icon")
|
||||||
|
const item = target.closest('.docListViewItem')
|
||||||
|
const id = item.nodes[0].dataset.id.split("_")
|
||||||
|
|
||||||
|
MessageBox(tr("report_question"), `
|
||||||
|
${tr("going_to_report_doc")}
|
||||||
|
<br/>${tr("report_question_text")}
|
||||||
|
<br/><br/><b> ${tr("report_reason")}</b>: <input type='text' id='uReportMsgInput' placeholder='${tr("reason")}' />`, [tr("confirm_m"), tr("cancel")], [(function() {
|
||||||
|
|
||||||
|
res = document.querySelector("#uReportMsgInput").value;
|
||||||
|
xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/report/" + id[1] + "?reason=" + res + "&type=doc", true);
|
||||||
|
xhr.onload = (function() {
|
||||||
|
if(xhr.responseText.indexOf("reason") === -1)
|
||||||
|
MessageBox(tr("error"), tr("error_sending_report"), ["OK"], [Function.noop]);
|
||||||
|
else
|
||||||
|
MessageBox(tr("action_successfully"), tr("will_be_watched"), ["OK"], [Function.noop]);
|
||||||
|
});
|
||||||
|
xhr.send(null)
|
||||||
|
}),
|
||||||
|
|
||||||
|
Function.noop])
|
||||||
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
CREATE TABLE `documents` (
|
CREATE TABLE `documents` (
|
||||||
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
`owner` BIGINT(20) UNSIGNED NOT NULL,
|
`owner` BIGINT(20) NOT NULL,
|
||||||
`virtual_id` BIGINT(20) UNSIGNED NOT NULL,
|
`virtual_id` BIGINT(20) UNSIGNED NOT NULL,
|
||||||
`hash` CHAR(128) NOT NULL,
|
`hash` CHAR(128) NOT NULL,
|
||||||
`owner_hidden` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1',
|
`owner_hidden` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1',
|
||||||
|
|
|
@ -682,6 +682,7 @@
|
||||||
"search_for_notes" = "Поиск записок";
|
"search_for_notes" = "Поиск записок";
|
||||||
"search_for_audios" = "Поиск музыки";
|
"search_for_audios" = "Поиск музыки";
|
||||||
"search_for_audios_playlists" = "Поиск плейлистов";
|
"search_for_audios_playlists" = "Поиск плейлистов";
|
||||||
|
"search_for_docs" = "Поиск документов";
|
||||||
"search_button" = "Найти";
|
"search_button" = "Найти";
|
||||||
"search_placeholder" = "Начните вводить любое имя, название или слово";
|
"search_placeholder" = "Начните вводить любое имя, название или слово";
|
||||||
"results_zero" = "Ни одного результата";
|
"results_zero" = "Ни одного результата";
|
||||||
|
@ -1239,6 +1240,7 @@
|
||||||
"going_to_report_user" = "Вы собираетесь пожаловаться на данного пользователя.";
|
"going_to_report_user" = "Вы собираетесь пожаловаться на данного пользователя.";
|
||||||
"going_to_report_video" = "Вы собираетесь пожаловаться на данную видеозапись.";
|
"going_to_report_video" = "Вы собираетесь пожаловаться на данную видеозапись.";
|
||||||
"going_to_report_audio" = "Вы собираетесь пожаловаться на данную аудиозапись.";
|
"going_to_report_audio" = "Вы собираетесь пожаловаться на данную аудиозапись.";
|
||||||
|
"going_to_report_doc" = "Вы собираетесь пожаловаться на этот документ.";
|
||||||
"going_to_report_post" = "Вы собираетесь пожаловаться на данную запись.";
|
"going_to_report_post" = "Вы собираетесь пожаловаться на данную запись.";
|
||||||
"going_to_report_comment" = "Вы собираетесь пожаловаться на данный комментарий.";
|
"going_to_report_comment" = "Вы собираетесь пожаловаться на данный комментарий.";
|
||||||
|
|
||||||
|
@ -2008,6 +2010,7 @@
|
||||||
"s_videos" = "Видео";
|
"s_videos" = "Видео";
|
||||||
"s_audios" = "Аудио";
|
"s_audios" = "Аудио";
|
||||||
"s_audios_playlists" = "Плейлисты";
|
"s_audios_playlists" = "Плейлисты";
|
||||||
|
"s_documents" = "Документы";
|
||||||
|
|
||||||
"s_by_people" = "по пользователям";
|
"s_by_people" = "по пользователям";
|
||||||
"s_by_groups" = "по группам";
|
"s_by_groups" = "по группам";
|
||||||
|
@ -2017,6 +2020,7 @@
|
||||||
"s_by_apps" = "по приложениям";
|
"s_by_apps" = "по приложениям";
|
||||||
"s_by_audios" = "по аудиозаписям";
|
"s_by_audios" = "по аудиозаписям";
|
||||||
"s_by_audios_playlists" = "по плейлистам";
|
"s_by_audios_playlists" = "по плейлистам";
|
||||||
|
"s_by_documents" = "по документам";
|
||||||
|
|
||||||
"s_order_by" = "Порядок";
|
"s_order_by" = "Порядок";
|
||||||
|
|
||||||
|
@ -2039,6 +2043,7 @@
|
||||||
"s_date_after" = "После";
|
"s_date_after" = "После";
|
||||||
|
|
||||||
"s_main" = "Основное";
|
"s_main" = "Основное";
|
||||||
|
"s_type" = "Тип";
|
||||||
|
|
||||||
"s_now_on_site" = "cейчас на сайте";
|
"s_now_on_site" = "cейчас на сайте";
|
||||||
"s_with_photo" = "с фото";
|
"s_with_photo" = "с фото";
|
||||||
|
@ -2214,6 +2219,7 @@
|
||||||
"document_uploading_in_general" = "Загрузка документа";
|
"document_uploading_in_general" = "Загрузка документа";
|
||||||
"file" = "Файл";
|
"file" = "Файл";
|
||||||
"tags" = "Теги";
|
"tags" = "Теги";
|
||||||
|
"owner_is_hidden" = "Автор скрыт";
|
||||||
"accessbility" = "Доступность";
|
"accessbility" = "Доступность";
|
||||||
|
|
||||||
"document_type_0" = "Все";
|
"document_type_0" = "Все";
|
||||||
|
@ -2245,3 +2251,16 @@
|
||||||
"x_documents_in_tab_zero" = "В этой вкладке $1 документов";
|
"x_documents_in_tab_zero" = "В этой вкладке $1 документов";
|
||||||
|
|
||||||
"there_is_no_documents_alright" = "Здесь нет документов.";
|
"there_is_no_documents_alright" = "Здесь нет документов.";
|
||||||
|
"limitations_file_limit_size" = "Файл не должен превышать $1 МБ";
|
||||||
|
"limitations_file_allowed_formats" = "Разрешены следующие типы файлов";
|
||||||
|
"limitations_file_author_rights" = "Файл не должен нарушать авторские права и правила сайта";
|
||||||
|
"select_file_fp" = "Выбрать файл";
|
||||||
|
"error_file_too_big" = "Файл слишком большой.";
|
||||||
|
"error_file_invalid_format" = "Формат файла не разрешён.";
|
||||||
|
"error_file_adding_copied" = "Не удалось добавить файл; он уже добавлен.";
|
||||||
|
|
||||||
|
"private_document" = "Приватный (по ссылке)";
|
||||||
|
"public_document" = "Публичный";
|
||||||
|
"documents_sort_add" = "По дате добавления";
|
||||||
|
"documents_sort_alphabet" = "A-Z/А-Я";
|
||||||
|
"documents_sort_size" = "По размеру";
|
||||||
|
|
Loading…
Reference in a new issue