better ui, search, uploading (icons by myslivets)

Co-Authored-By: Daniel <60743585+myslivets@users.noreply.github.com>
This commit is contained in:
mrilyew 2024-12-28 22:54:32 +03:00
parent a91563fdf6
commit 36560555b6
18 changed files with 332 additions and 23 deletions

View file

@ -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)[

View file

@ -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);

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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";
@ -43,6 +44,7 @@ final class DocumentsPresenter extends OpenVKPresenter
$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() : ""),
]);
}
} }
} }

View file

@ -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);

View file

@ -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>

View file

@ -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}

View file

@ -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>

View file

@ -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>

View file

@ -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}

View file

@ -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>

View file

@ -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;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View file

@ -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])
})

View file

@ -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',

View file

@ -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" = "По размеру";