mirror of
https://github.com/nextcloud/server.git
synced 2026-06-09 00:32:29 -04:00
Merge pull request #46589 from nextcloud/fix/files_sharing-file-request-followup
This commit is contained in:
commit
0bde47a392
71 changed files with 793 additions and 220 deletions
|
|
@ -87,6 +87,7 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct
|
|||
|
||||
$view = new \OC\Files\View($node->getPath());
|
||||
$filesDropPlugin->setView($view);
|
||||
$filesDropPlugin->setShare($share);
|
||||
|
||||
return $view;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct
|
|||
|
||||
$view = new View($node->getPath());
|
||||
$filesDropPlugin->setView($view);
|
||||
$filesDropPlugin->setShare($share);
|
||||
|
||||
return $view;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
namespace OCA\DAV\Files\Sharing;
|
||||
|
||||
use OC\Files\View;
|
||||
use OCP\Share\IShare;
|
||||
use Sabre\DAV\Exception\MethodNotAllowed;
|
||||
use Sabre\DAV\ServerPlugin;
|
||||
use Sabre\HTTP\RequestInterface;
|
||||
|
|
@ -16,20 +17,19 @@ use Sabre\HTTP\ResponseInterface;
|
|||
*/
|
||||
class FilesDropPlugin extends ServerPlugin {
|
||||
|
||||
/** @var View */
|
||||
private $view;
|
||||
private ?View $view = null;
|
||||
private ?IShare $share = null;
|
||||
private bool $enabled = false;
|
||||
|
||||
/** @var bool */
|
||||
private $enabled = false;
|
||||
|
||||
/**
|
||||
* @param View $view
|
||||
*/
|
||||
public function setView($view) {
|
||||
public function setView(View $view): void {
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
public function enable() {
|
||||
public function setShare(IShare $share): void {
|
||||
$this->share = $share;
|
||||
}
|
||||
|
||||
public function enable(): void {
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
|
|
@ -42,25 +42,51 @@ class FilesDropPlugin extends ServerPlugin {
|
|||
* @return void
|
||||
* @throws MethodNotAllowed
|
||||
*/
|
||||
public function initialize(\Sabre\DAV\Server $server) {
|
||||
public function initialize(\Sabre\DAV\Server $server): void {
|
||||
$server->on('beforeMethod:*', [$this, 'beforeMethod'], 999);
|
||||
$this->enabled = false;
|
||||
}
|
||||
|
||||
public function beforeMethod(RequestInterface $request, ResponseInterface $response) {
|
||||
if (!$this->enabled) {
|
||||
public function beforeMethod(RequestInterface $request, ResponseInterface $response): void {
|
||||
if (!$this->enabled || $this->share === null || $this->view === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only allow file drop
|
||||
if ($request->getMethod() !== 'PUT') {
|
||||
throw new MethodNotAllowed('Only PUT is allowed on files drop');
|
||||
}
|
||||
|
||||
// Always upload at the root level
|
||||
$path = explode('/', $request->getPath());
|
||||
$path = array_pop($path);
|
||||
|
||||
// Extract the attributes for the file request
|
||||
$isFileRequest = false;
|
||||
$attributes = $this->share->getAttributes();
|
||||
$nickName = $request->getHeader('X-NC-Nickname');
|
||||
if ($attributes !== null) {
|
||||
$isFileRequest = $attributes->getAttribute('fileRequest', 'enabled') === true;
|
||||
}
|
||||
|
||||
// We need a valid nickname for file requests
|
||||
if ($isFileRequest && ($nickName == null || trim($nickName) === '')) {
|
||||
throw new MethodNotAllowed('Nickname is required for file requests');
|
||||
}
|
||||
|
||||
// If this is a file request we need to create a folder for the user
|
||||
if ($isFileRequest) {
|
||||
// Check if the folder already exists
|
||||
if (!($this->view->file_exists($nickName) === true)) {
|
||||
$this->view->mkdir($nickName);
|
||||
}
|
||||
// Put all files in the subfolder
|
||||
$path = $nickName . '/' . $path;
|
||||
}
|
||||
|
||||
$newName = \OC_Helper::buildNotExistingFileNameForView('/', $path, $this->view);
|
||||
$url = $request->getBaseUrl() . $newName;
|
||||
$request->setUrl($url);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ namespace OCA\DAV\Tests\Files\Sharing;
|
|||
|
||||
use OC\Files\View;
|
||||
use OCA\DAV\Files\Sharing\FilesDropPlugin;
|
||||
use OCP\Share\IAttributes;
|
||||
use OCP\Share\IShare;
|
||||
use Sabre\DAV\Exception\MethodNotAllowed;
|
||||
use Sabre\DAV\Server;
|
||||
use Sabre\HTTP\RequestInterface;
|
||||
|
|
@ -18,6 +20,9 @@ class FilesDropPluginTest extends TestCase {
|
|||
/** @var View|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $view;
|
||||
|
||||
/** @var IShare|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $share;
|
||||
|
||||
/** @var Server|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $server;
|
||||
|
||||
|
|
@ -34,6 +39,7 @@ class FilesDropPluginTest extends TestCase {
|
|||
parent::setUp();
|
||||
|
||||
$this->view = $this->createMock(View::class);
|
||||
$this->share = $this->createMock(IShare::class);
|
||||
$this->server = $this->createMock(Server::class);
|
||||
$this->plugin = new FilesDropPlugin();
|
||||
|
||||
|
|
@ -42,6 +48,11 @@ class FilesDropPluginTest extends TestCase {
|
|||
|
||||
$this->response->expects($this->never())
|
||||
->method($this->anything());
|
||||
|
||||
$attributes = $this->createMock(IAttributes::class);
|
||||
$this->share->expects($this->any())
|
||||
->method('getAttributes')
|
||||
->willReturn($attributes);
|
||||
}
|
||||
|
||||
public function testInitialize(): void {
|
||||
|
|
@ -69,6 +80,7 @@ class FilesDropPluginTest extends TestCase {
|
|||
public function testValid(): void {
|
||||
$this->plugin->enable();
|
||||
$this->plugin->setView($this->view);
|
||||
$this->plugin->setShare($this->share);
|
||||
|
||||
$this->request->method('getMethod')
|
||||
->willReturn('PUT');
|
||||
|
|
@ -93,6 +105,7 @@ class FilesDropPluginTest extends TestCase {
|
|||
public function testFileAlreadyExistsValid(): void {
|
||||
$this->plugin->enable();
|
||||
$this->plugin->setView($this->view);
|
||||
$this->plugin->setShare($this->share);
|
||||
|
||||
$this->request->method('getMethod')
|
||||
->willReturn('PUT');
|
||||
|
|
@ -122,6 +135,7 @@ class FilesDropPluginTest extends TestCase {
|
|||
public function testNoMKCOL(): void {
|
||||
$this->plugin->enable();
|
||||
$this->plugin->setView($this->view);
|
||||
$this->plugin->setShare($this->share);
|
||||
|
||||
$this->request->method('getMethod')
|
||||
->willReturn('MKCOL');
|
||||
|
|
@ -134,6 +148,7 @@ class FilesDropPluginTest extends TestCase {
|
|||
public function testNoSubdirPut(): void {
|
||||
$this->plugin->enable();
|
||||
$this->plugin->setView($this->view);
|
||||
$this->plugin->setShare($this->share);
|
||||
|
||||
$this->request->method('getMethod')
|
||||
->willReturn('PUT');
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ return array(
|
|||
'OCA\\Files_Sharing\\Listener\\BeforeDirectFileDownloadListener' => $baseDir . '/../lib/Listener/BeforeDirectFileDownloadListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\BeforeZipCreatedListener' => $baseDir . '/../lib/Listener/BeforeZipCreatedListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\LoadPublicFileRequestAuthListener' => $baseDir . '/../lib/Listener/LoadPublicFileRequestAuthListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\ShareInteractionListener' => $baseDir . '/../lib/Listener/ShareInteractionListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\UserAddedToGroupListener' => $baseDir . '/../lib/Listener/UserAddedToGroupListener.php',
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ class ComposerStaticInitFiles_Sharing
|
|||
'OCA\\Files_Sharing\\Listener\\BeforeDirectFileDownloadListener' => __DIR__ . '/..' . '/../lib/Listener/BeforeDirectFileDownloadListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\BeforeZipCreatedListener' => __DIR__ . '/..' . '/../lib/Listener/BeforeZipCreatedListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\LoadPublicFileRequestAuthListener' => __DIR__ . '/..' . '/../lib/Listener/LoadPublicFileRequestAuthListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\ShareInteractionListener' => __DIR__ . '/..' . '/../lib/Listener/ShareInteractionListener.php',
|
||||
'OCA\\Files_Sharing\\Listener\\UserAddedToGroupListener' => __DIR__ . '/..' . '/../lib/Listener/UserAddedToGroupListener.php',
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
// note: password not be required, the endpoint
|
||||
// will recognize previous validation from the session
|
||||
root: OC.getRootPath() + '/public.php/dav/files/' + $('#sharingToken').val() + '/',
|
||||
useHTTPS: OC.getProtocol() === 'https'
|
||||
useHTTPS: OC.getProtocol() === 'https',
|
||||
});
|
||||
|
||||
// We only process one file at a time 🤷♀️
|
||||
|
|
@ -47,6 +47,10 @@
|
|||
data.headers = {};
|
||||
}
|
||||
|
||||
if (localStorage.getItem('nick') !== null) {
|
||||
data.headers['X-NC-Nickname'] = localStorage.getItem('nick')
|
||||
}
|
||||
|
||||
$('#drop-upload-done-indicator').addClass('hidden');
|
||||
$('#drop-upload-progress-indicator').removeClass('hidden');
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use OCA\Files_Sharing\Helper;
|
|||
use OCA\Files_Sharing\Listener\BeforeDirectFileDownloadListener;
|
||||
use OCA\Files_Sharing\Listener\BeforeZipCreatedListener;
|
||||
use OCA\Files_Sharing\Listener\LoadAdditionalListener;
|
||||
use OCA\Files_Sharing\Listener\LoadPublicFileRequestAuthListener;
|
||||
use OCA\Files_Sharing\Listener\LoadSidebarListener;
|
||||
use OCA\Files_Sharing\Listener\ShareInteractionListener;
|
||||
use OCA\Files_Sharing\Listener\UserAddedToGroupListener;
|
||||
|
|
@ -34,6 +35,7 @@ use OCP\AppFramework\App;
|
|||
use OCP\AppFramework\Bootstrap\IBootContext;
|
||||
use OCP\AppFramework\Bootstrap\IBootstrap;
|
||||
use OCP\AppFramework\Bootstrap\IRegistrationContext;
|
||||
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
|
||||
use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent as ResourcesLoadAdditionalScriptsEvent;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Federation\ICloudIdManager;
|
||||
|
|
@ -85,7 +87,7 @@ class Application extends App implements IBootstrap {
|
|||
$context->registerEventListener(GroupChangedEvent::class, GroupDisplayNameCache::class);
|
||||
$context->registerEventListener(GroupDeletedEvent::class, GroupDisplayNameCache::class);
|
||||
|
||||
// sidebar and files scripts
|
||||
// Sidebar and files scripts
|
||||
$context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
|
||||
$context->registerEventListener(LoadSidebar::class, LoadSidebarListener::class);
|
||||
$context->registerEventListener(ShareCreatedEvent::class, ShareInteractionListener::class);
|
||||
|
|
@ -95,6 +97,9 @@ class Application extends App implements IBootstrap {
|
|||
// Handle download events for view only checks
|
||||
$context->registerEventListener(BeforeZipCreatedEvent::class, BeforeZipCreatedListener::class);
|
||||
$context->registerEventListener(BeforeDirectFileDownloadEvent::class, BeforeDirectFileDownloadListener::class);
|
||||
|
||||
// File request auth
|
||||
$context->registerEventListener(BeforeTemplateRenderedEvent::class, LoadPublicFileRequestAuthListener::class);
|
||||
}
|
||||
|
||||
public function boot(IBootContext $context): void {
|
||||
|
|
|
|||
|
|
@ -596,8 +596,10 @@ class ShareAPIController extends OCSController {
|
|||
throw new OCSNotFoundException($this->l->t('Invalid permissions'));
|
||||
}
|
||||
|
||||
// Shares always require read permissions
|
||||
$permissions |= Constants::PERMISSION_READ;
|
||||
// Shares always require read permissions OR create permissions
|
||||
if (($permissions & Constants::PERMISSION_READ) === 0 && ($permissions & Constants::PERMISSION_CREATE) === 0) {
|
||||
$permissions |= Constants::PERMISSION_READ;
|
||||
}
|
||||
|
||||
if ($node instanceof \OCP\Files\File) {
|
||||
// Single file shares should never have delete or create permissions
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use OCP\AppFramework\Http\Template\LinkMenuAction;
|
|||
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
|
||||
use OCP\AppFramework\Http\Template\SimpleMenuAction;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\AppFramework\Services\IInitialState;
|
||||
use OCP\Constants;
|
||||
use OCP\Defaults;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
|
|
@ -37,39 +38,20 @@ use OCP\Template;
|
|||
use OCP\Util;
|
||||
|
||||
class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider {
|
||||
private IUserManager $userManager;
|
||||
private IAccountManager $accountManager;
|
||||
private IPreview $previewManager;
|
||||
protected FederatedShareProvider $federatedShareProvider;
|
||||
private IURLGenerator $urlGenerator;
|
||||
private IEventDispatcher $eventDispatcher;
|
||||
private IL10N $l10n;
|
||||
private Defaults $defaults;
|
||||
private IConfig $config;
|
||||
private IRequest $request;
|
||||
|
||||
public function __construct(
|
||||
IUserManager $userManager,
|
||||
IAccountManager $accountManager,
|
||||
IPreview $previewManager,
|
||||
FederatedShareProvider $federatedShareProvider,
|
||||
IUrlGenerator $urlGenerator,
|
||||
IEventDispatcher $eventDispatcher,
|
||||
IL10N $l10n,
|
||||
Defaults $defaults,
|
||||
IConfig $config,
|
||||
IRequest $request
|
||||
private IUserManager $userManager,
|
||||
private IAccountManager $accountManager,
|
||||
private IPreview $previewManager,
|
||||
protected FederatedShareProvider $federatedShareProvider,
|
||||
private IUrlGenerator $urlGenerator,
|
||||
private IEventDispatcher $eventDispatcher,
|
||||
private IL10N $l10n,
|
||||
private Defaults $defaults,
|
||||
private IConfig $config,
|
||||
private IRequest $request,
|
||||
private IInitialState $initialState,
|
||||
) {
|
||||
$this->userManager = $userManager;
|
||||
$this->accountManager = $accountManager;
|
||||
$this->previewManager = $previewManager;
|
||||
$this->federatedShareProvider = $federatedShareProvider;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->l10n = $l10n;
|
||||
$this->defaults = $defaults;
|
||||
$this->config = $config;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function shouldRespond(IShare $share): bool {
|
||||
|
|
@ -91,11 +73,19 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
|
|||
if ($ownerName->getScope() === IAccountManager::SCOPE_PUBLISHED) {
|
||||
$shareTmpl['owner'] = $owner->getUID();
|
||||
$shareTmpl['shareOwner'] = $owner->getDisplayName();
|
||||
$this->initialState->provideInitialState('owner', $shareTmpl['owner']);
|
||||
$this->initialState->provideInitialState('ownerDisplayName', $shareTmpl['shareOwner']);
|
||||
}
|
||||
}
|
||||
|
||||
// Provide initial state
|
||||
$this->initialState->provideInitialState('label', $share->getLabel());
|
||||
$this->initialState->provideInitialState('note', $share->getNote());
|
||||
$this->initialState->provideInitialState('filename', $shareNode->getName());
|
||||
|
||||
$shareTmpl['filename'] = $shareNode->getName();
|
||||
$shareTmpl['directory_path'] = $share->getTarget();
|
||||
$shareTmpl['label'] = $share->getLabel();
|
||||
$shareTmpl['note'] = $share->getNote();
|
||||
$shareTmpl['mimetype'] = $shareNode->getMimetype();
|
||||
$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
|
||||
|
|
@ -240,6 +230,11 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
|
|||
$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
|
||||
}
|
||||
|
||||
// If the share has a label, use it as the title
|
||||
if ($shareTmpl['label'] !== '') {
|
||||
$response->setHeaderTitle($shareTmpl['label']);
|
||||
}
|
||||
|
||||
$isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== Constants::PERMISSION_CREATE;
|
||||
|
||||
if ($isNoneFileDropFolder && !$share->getHideDownload()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\Files_Sharing\Listener;
|
||||
|
||||
use OCA\Files_Sharing\AppInfo\Application;
|
||||
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\Util;
|
||||
|
||||
/** @template-implements IEventListener<BeforeTemplateRenderedEvent> */
|
||||
class LoadPublicFileRequestAuthListener implements IEventListener {
|
||||
public function __construct(
|
||||
private IManager $shareManager,
|
||||
) {
|
||||
}
|
||||
|
||||
public function handle(Event $event): void {
|
||||
if (!$event instanceof BeforeTemplateRenderedEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we are on a public page rendering
|
||||
if ($event->getResponse()->getRenderAs() !== TemplateResponse::RENDER_AS_PUBLIC) {
|
||||
return;
|
||||
}
|
||||
|
||||
$token = $event->getResponse()->getParams()['sharingToken'] ?? null;
|
||||
if ($token === null || $token === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the share is a file request
|
||||
$isFileRequest = false;
|
||||
try {
|
||||
$share = $this->shareManager->getShareByToken($token);
|
||||
$attributes = $share->getAttributes();
|
||||
if ($attributes === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$isFileRequest = $attributes->getAttribute('fileRequest', 'enabled') === true;
|
||||
} catch (\Exception $e) {
|
||||
// Ignore, this is not a file request or the share does not exist
|
||||
}
|
||||
|
||||
if ($isFileRequest) {
|
||||
// Add the script to the public page
|
||||
Util::addScript(Application::APP_ID, 'public-file-request');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import { sharesViewId, sharedWithYouViewId, sharedWithOthersViewId, sharingByLin
|
|||
|
||||
export const action = new FileAction({
|
||||
id: 'open-in-files',
|
||||
displayName: () => t('files', 'Open in Files'),
|
||||
displayName: () => t('files_sharing', 'Open in Files'),
|
||||
iconSvgInline: () => '',
|
||||
|
||||
enabled: (nodes, view) => [
|
||||
|
|
|
|||
|
|
@ -50,19 +50,6 @@
|
|||
|
||||
<!-- Controls -->
|
||||
<template #actions>
|
||||
<!-- Cancel the creation -->
|
||||
<NcButton :aria-label="t('files_sharing', 'Cancel')"
|
||||
:disabled="loading"
|
||||
:title="t('files_sharing', 'Cancel the file request creation')"
|
||||
data-cy-file-request-dialog-controls="cancel"
|
||||
type="tertiary"
|
||||
@click="onCancel">
|
||||
{{ t('files_sharing', 'Cancel') }}
|
||||
</NcButton>
|
||||
|
||||
<!-- Align right -->
|
||||
<span class="dialog__actions-separator" />
|
||||
|
||||
<!-- Back -->
|
||||
<NcButton v-show="currentStep === STEP.SECOND"
|
||||
:aria-label="t('files_sharing', 'Previous step')"
|
||||
|
|
@ -73,6 +60,31 @@
|
|||
{{ t('files_sharing', 'Previous step') }}
|
||||
</NcButton>
|
||||
|
||||
<!-- Align right -->
|
||||
<span class="dialog__actions-separator" />
|
||||
|
||||
<!-- Cancel the creation -->
|
||||
<NcButton v-if="currentStep !== STEP.LAST"
|
||||
:aria-label="t('files_sharing', 'Cancel')"
|
||||
:disabled="loading"
|
||||
:title="t('files_sharing', 'Cancel the file request creation')"
|
||||
data-cy-file-request-dialog-controls="cancel"
|
||||
type="tertiary"
|
||||
@click="onCancel">
|
||||
{{ t('files_sharing', 'Cancel') }}
|
||||
</NcButton>
|
||||
|
||||
<!-- Cancel email and just close -->
|
||||
<NcButton v-else-if="emails.length !== 0"
|
||||
:aria-label="t('files_sharing', 'Close without sending emails')"
|
||||
:disabled="loading"
|
||||
:title="t('files_sharing', 'Close without sending emails')"
|
||||
data-cy-file-request-dialog-controls="cancel"
|
||||
type="tertiary"
|
||||
@click="onCancel">
|
||||
{{ t('files_sharing', 'Close') }}
|
||||
</NcButton>
|
||||
|
||||
<!-- Next -->
|
||||
<NcButton v-if="currentStep !== STEP.LAST"
|
||||
:aria-label="t('files_sharing', 'Continue')"
|
||||
|
|
@ -115,7 +127,7 @@ import { generateOcsUrl } from '@nextcloud/router'
|
|||
import { Permission } from '@nextcloud/files'
|
||||
import { ShareType } from '@nextcloud/sharing'
|
||||
import { showError, showSuccess } from '@nextcloud/dialogs'
|
||||
import { translate, translatePlural } from '@nextcloud/l10n'
|
||||
import { n, t } from '@nextcloud/l10n'
|
||||
import axios from '@nextcloud/axios'
|
||||
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
|
|
@ -170,9 +182,8 @@ export default defineComponent({
|
|||
setup() {
|
||||
return {
|
||||
STEP,
|
||||
|
||||
n: translatePlural,
|
||||
t: translate,
|
||||
n,
|
||||
t,
|
||||
|
||||
isShareByMailEnabled: sharingConfig.isMailShareAllowed,
|
||||
}
|
||||
|
|
@ -198,9 +209,9 @@ export default defineComponent({
|
|||
computed: {
|
||||
finishButtonLabel() {
|
||||
if (this.emails.length === 0) {
|
||||
return this.t('files_sharing', 'Close')
|
||||
return t('files_sharing', 'Close')
|
||||
}
|
||||
return this.n('files_sharing', 'Close and send email', 'Close and send {count} emails', this.emails.length, { count: this.emails.length })
|
||||
return n('files_sharing', 'Send email and close', 'Send {count} emails and close', this.emails.length, { count: this.emails.length })
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -209,13 +220,14 @@ export default defineComponent({
|
|||
const form = this.$refs.form as HTMLFormElement
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity()
|
||||
return
|
||||
}
|
||||
|
||||
// custom destination validation
|
||||
// cannot share root
|
||||
if (this.destination === '/' || this.destination === '') {
|
||||
const destinationInput = form.querySelector('input[name="destination"]') as HTMLInputElement
|
||||
destinationInput?.setCustomValidity(this.t('files_sharing', 'Please select a folder, you cannot share the root directory.'))
|
||||
destinationInput?.setCustomValidity(t('files_sharing', 'Please select a folder, you cannot share the root directory.'))
|
||||
form.reportValidity()
|
||||
return
|
||||
}
|
||||
|
|
@ -239,26 +251,44 @@ export default defineComponent({
|
|||
|
||||
async onFinish() {
|
||||
if (this.emails.length === 0 || this.isShareByMailEnabled === false) {
|
||||
showSuccess(this.t('files_sharing', 'File request created'))
|
||||
showSuccess(t('files_sharing', 'File request created'))
|
||||
this.$emit('close')
|
||||
return
|
||||
}
|
||||
|
||||
await this.setShareEmails()
|
||||
await this.sendEmails()
|
||||
showSuccess(this.t('files_sharing', 'File request created and emails sent'))
|
||||
if (sharingConfig.isMailShareAllowed && this.emails.length > 0) {
|
||||
await this.setShareEmails()
|
||||
await this.sendEmails()
|
||||
showSuccess(n('files_sharing', 'File request created and email sent', 'File request created and {count} emails sent', this.emails.length, { count: this.emails.length }))
|
||||
} else {
|
||||
showSuccess(t('files_sharing', 'File request created'))
|
||||
}
|
||||
|
||||
this.$emit('close')
|
||||
},
|
||||
|
||||
async createShare() {
|
||||
this.loading = true
|
||||
|
||||
// This should never happen™
|
||||
if (this.expirationDate == null) {
|
||||
throw new Error('Expiration date is missing')
|
||||
}
|
||||
|
||||
const year = this.expirationDate.getFullYear()
|
||||
const month = (this.expirationDate.getMonth() + 1).toString().padStart(2, '0')
|
||||
const day = this.expirationDate.getDate().toString().padStart(2, '0')
|
||||
|
||||
// Format must be YYYY-MM-DD
|
||||
const expireDate = this.expirationDate ? this.expirationDate.toISOString().split('T')[0] : undefined
|
||||
const expireDate = this.expirationDate
|
||||
? `${year}-${month}-${day}`
|
||||
: undefined
|
||||
const shareUrl = generateOcsUrl('apps/files_sharing/api/v1/shares')
|
||||
try {
|
||||
const request = await axios.post<OCSResponse>(shareUrl, {
|
||||
shareType: ShareType.Email,
|
||||
// Always create a file request, but without mail share
|
||||
// permissions, only a share link will be created.
|
||||
shareType: sharingConfig.isMailShareAllowed ? ShareType.Email : ShareType.Link,
|
||||
permissions: Permission.CREATE,
|
||||
|
||||
label: this.label,
|
||||
|
|
@ -294,8 +324,8 @@ export default defineComponent({
|
|||
const errorMessage = (error as AxiosError<OCSResponse>)?.response?.data?.ocs?.meta?.message
|
||||
showError(
|
||||
errorMessage
|
||||
? this.t('files_sharing', 'Error creating the share: {errorMessage}', { errorMessage })
|
||||
: this.t('files_sharing', 'Error creating the share'),
|
||||
? t('files_sharing', 'Error creating the share: {errorMessage}', { errorMessage })
|
||||
: t('files_sharing', 'Error creating the share'),
|
||||
)
|
||||
logger.error('Error while creating share', { error, errorMessage })
|
||||
throw error
|
||||
|
|
@ -320,6 +350,11 @@ export default defineComponent({
|
|||
value: this.emails,
|
||||
key: 'emails',
|
||||
scope: 'shareWith',
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
key: 'enabled',
|
||||
scope: 'fileRequest',
|
||||
}]),
|
||||
})
|
||||
|
||||
|
|
@ -366,8 +401,8 @@ export default defineComponent({
|
|||
const errorMessage = error.response?.data?.ocs?.meta?.message
|
||||
showError(
|
||||
errorMessage
|
||||
? this.t('files_sharing', 'Error sending emails: {errorMessage}', { errorMessage })
|
||||
: this.t('files_sharing', 'Error sending emails'),
|
||||
? t('files_sharing', 'Error sending emails: {errorMessage}', { errorMessage })
|
||||
: t('files_sharing', 'Error sending emails'),
|
||||
)
|
||||
logger.error('Error while sending emails', { error, errorMessage })
|
||||
},
|
||||
|
|
@ -375,10 +410,9 @@ export default defineComponent({
|
|||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
<style lang="scss">
|
||||
.file-request-dialog {
|
||||
--margin: 36px;
|
||||
--secondary-margin: 18px;
|
||||
--margin: 18px;
|
||||
|
||||
&__header {
|
||||
margin: 0 var(--margin);
|
||||
|
|
@ -387,35 +421,45 @@ export default defineComponent({
|
|||
&__form {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
padding: var(--secondary-margin) var(--margin);
|
||||
padding: var(--margin) var(--margin);
|
||||
// overlap header bottom padding
|
||||
margin-top: calc(-1 * var(--secondary-margin));
|
||||
margin-top: calc(-1 * var(--margin));
|
||||
}
|
||||
|
||||
:deep(fieldset) {
|
||||
fieldset {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
margin-top: var(--secondary-margin);
|
||||
margin-top: var(--margin);
|
||||
|
||||
:deep(legend) {
|
||||
legend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.dialog__actions) {
|
||||
// Using a NcNoteCard was a bit much sometimes.
|
||||
// Using a simple paragraph instead does it.
|
||||
&__info {
|
||||
color: var(--color-text-maxcontrast);
|
||||
padding-block: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.file-request-dialog__info-icon {
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog__actions {
|
||||
width: auto;
|
||||
margin-inline: 12px;
|
||||
// align left and remove margin
|
||||
margin-left: 0;
|
||||
span.dialog__actions-separator {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.input-field__helper-text-message) {
|
||||
.input-field__helper-text-message {
|
||||
// reduce helper text standing out
|
||||
color: var(--color-text-maxcontrast);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,17 +12,13 @@
|
|||
|
||||
<!-- Expiration date -->
|
||||
<fieldset class="file-request-dialog__expiration" data-cy-file-request-dialog-fieldset="expiration">
|
||||
<NcNoteCard v-if="defaultExpireDateEnforced" type="info">
|
||||
{{ t('files_sharing', 'Your administrator has enforced a default expiration date with a maximum {days} days.', { days: defaultExpireDate }) }}
|
||||
</NcNoteCard>
|
||||
|
||||
<!-- Enable expiration -->
|
||||
<legend>{{ t('files_sharing', 'When should the request expire?') }}</legend>
|
||||
<NcCheckboxRadioSwitch v-show="!defaultExpireDateEnforced"
|
||||
:checked="defaultExpireDateEnforced || expirationDate !== null"
|
||||
:disabled="disabled || defaultExpireDateEnforced"
|
||||
@update:checked="onToggleDeadline">
|
||||
{{ t('files_sharing', 'Set a submission expirationDate') }}
|
||||
{{ t('files_sharing', 'Set a submission expiration date') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
|
||||
<!-- Date picker -->
|
||||
|
|
@ -38,15 +34,16 @@
|
|||
:value="expirationDate"
|
||||
name="expirationDate"
|
||||
type="date"
|
||||
@update:value="$emit('update:expirationDate', $event)" />
|
||||
@input="$emit('update:expirationDate', $event)" />
|
||||
|
||||
<p v-if="defaultExpireDateEnforced" class="file-request-dialog__info">
|
||||
<IconInfo :size="18" class="file-request-dialog__info-icon" />
|
||||
{{ t('files_sharing', 'Your administrator has enforced a {count} days expiration policy.', { count: defaultExpireDate }) }}
|
||||
</p>
|
||||
</fieldset>
|
||||
|
||||
<!-- Password -->
|
||||
<fieldset class="file-request-dialog__password" data-cy-file-request-dialog-fieldset="password">
|
||||
<NcNoteCard v-if="enforcePasswordForPublicLink" type="info">
|
||||
{{ t('files_sharing', 'Your administrator has enforced a password protection.') }}
|
||||
</NcNoteCard>
|
||||
|
||||
<!-- Enable password -->
|
||||
<legend>{{ t('files_sharing', 'What password should be used for the request?') }}</legend>
|
||||
<NcCheckboxRadioSwitch v-show="!enforcePasswordForPublicLink"
|
||||
|
|
@ -75,13 +72,18 @@
|
|||
</template>
|
||||
</NcButton>
|
||||
</div>
|
||||
|
||||
<p v-if="enforcePasswordForPublicLink" class="file-request-dialog__info">
|
||||
<IconInfo :size="18" class="file-request-dialog__info-icon" />
|
||||
{{ t('files_sharing', 'Your administrator has enforced a password protection.') }}
|
||||
</p>
|
||||
</fieldset>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, type PropType } from 'vue'
|
||||
import { translate } from '@nextcloud/l10n'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
|
||||
|
|
@ -89,6 +91,7 @@ import NcDateTimePickerNative from '@nextcloud/vue/dist/Components/NcDateTimePic
|
|||
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
|
||||
import NcPasswordField from '@nextcloud/vue/dist/Components/NcPasswordField.js'
|
||||
|
||||
import IconInfo from 'vue-material-design-icons/Information.vue'
|
||||
import IconPasswordGen from 'vue-material-design-icons/AutoFix.vue'
|
||||
|
||||
import Config from '../../services/ConfigService'
|
||||
|
|
@ -100,6 +103,7 @@ export default defineComponent({
|
|||
name: 'NewFileRequestDialogDatePassword',
|
||||
|
||||
components: {
|
||||
IconInfo,
|
||||
IconPasswordGen,
|
||||
NcButton,
|
||||
NcCheckboxRadioSwitch,
|
||||
|
|
@ -133,7 +137,7 @@ export default defineComponent({
|
|||
|
||||
setup() {
|
||||
return {
|
||||
t: translate,
|
||||
t,
|
||||
|
||||
// Default expiration date if defaultExpireDateEnabled is true
|
||||
defaultExpireDate: sharingConfig.defaultExpireDate,
|
||||
|
|
@ -159,19 +163,19 @@ export default defineComponent({
|
|||
computed: {
|
||||
passwordAndExpirationSummary(): string {
|
||||
if (this.expirationDate && this.password) {
|
||||
return this.t('files_sharing', 'The request will expire on {date} at midnight and will be password protected.', {
|
||||
return t('files_sharing', 'The request will expire on {date} at midnight and will be password protected.', {
|
||||
date: this.expirationDate.toLocaleDateString(),
|
||||
})
|
||||
}
|
||||
|
||||
if (this.expirationDate) {
|
||||
return this.t('files_sharing', 'The request will expire on {date} at midnight.', {
|
||||
return t('files_sharing', 'The request will expire on {date} at midnight.', {
|
||||
date: this.expirationDate.toLocaleDateString(),
|
||||
})
|
||||
}
|
||||
|
||||
if (this.password) {
|
||||
return this.t('files_sharing', 'The request will be password protected.')
|
||||
return t('files_sharing', 'The request will be password protected.')
|
||||
}
|
||||
|
||||
return ''
|
||||
|
|
@ -232,5 +236,11 @@ export default defineComponent({
|
|||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
// Compensate label gab with legend
|
||||
margin-top: 12px;
|
||||
> div {
|
||||
// Force margin to 0 as we handle it above
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<div>
|
||||
<!-- Request note -->
|
||||
<NcNoteCard type="success">
|
||||
{{ t('files_sharing', 'Once created, you can share the link below to allow people to upload files to your directory.') }}
|
||||
{{ t('files_sharing', 'You can now share the link below to allow people to upload files to your directory.') }}
|
||||
</NcNoteCard>
|
||||
|
||||
<!-- Copy share link -->
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
:show-trailing-button="true"
|
||||
:trailing-button-label="t('files_sharing', 'Copy to clipboard')"
|
||||
@click="copyShareLink"
|
||||
@click-trailing-button="copyShareLink">
|
||||
@trailing-button-click="copyShareLink">
|
||||
<template #trailing-button-icon>
|
||||
<IconCheck v-if="isCopied" :size="20" />
|
||||
<IconClipboard v-else :size="20" />
|
||||
|
|
@ -32,7 +32,8 @@
|
|||
:placeholder="t('files_sharing', 'Enter an email address or paste a list')"
|
||||
type="email"
|
||||
@keypress.enter.stop="addNewEmail"
|
||||
@paste.stop.prevent="onPasteEmails" />
|
||||
@paste.stop.prevent="onPasteEmails"
|
||||
@focusout.native="addNewEmail" />
|
||||
|
||||
<!-- Email list -->
|
||||
<div v-if="emails.length > 0" class="file-request-dialog__emails">
|
||||
|
|
@ -44,9 +45,10 @@
|
|||
<template #icon>
|
||||
<NcAvatar :disable-menu="true"
|
||||
:disable-tooltip="true"
|
||||
:is-guest="true"
|
||||
:size="24"
|
||||
:user="mail" />
|
||||
:display-name="mail"
|
||||
:is-no-user="true"
|
||||
:show-user-status="false"
|
||||
:size="24" />
|
||||
</template>
|
||||
</NcChip>
|
||||
</div>
|
||||
|
|
@ -61,7 +63,7 @@ import Share from '../../models/Share'
|
|||
import { defineComponent } from 'vue'
|
||||
import { generateUrl, getBaseUrl } from '@nextcloud/router'
|
||||
import { showError, showSuccess } from '@nextcloud/dialogs'
|
||||
import { translate, translatePlural } from '@nextcloud/l10n'
|
||||
import { n, t } from '@nextcloud/l10n'
|
||||
|
||||
import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
|
||||
import NcInputField from '@nextcloud/vue/dist/Components/NcInputField.js'
|
||||
|
|
@ -70,7 +72,7 @@ import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
|
|||
import NcChip from '@nextcloud/vue/dist/Components/NcChip.js'
|
||||
|
||||
import IconCheck from 'vue-material-design-icons/Check.vue'
|
||||
import IconClipboard from 'vue-material-design-icons/Clipboard.vue'
|
||||
import IconClipboard from 'vue-material-design-icons/ClipboardText.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NewFileRequestDialogFinish',
|
||||
|
|
@ -104,8 +106,7 @@ export default defineComponent({
|
|||
|
||||
setup() {
|
||||
return {
|
||||
n: translatePlural,
|
||||
t: translate,
|
||||
n, t,
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -131,13 +132,13 @@ export default defineComponent({
|
|||
|
||||
if (!navigator.clipboard) {
|
||||
// Clipboard API not available
|
||||
window.prompt(this.t('files_sharing', 'Automatically copying failed, please copy the share link manually'), this.shareLink)
|
||||
window.prompt(t('files_sharing', 'Automatically copying failed, please copy the share link manually'), this.shareLink)
|
||||
return
|
||||
}
|
||||
|
||||
await navigator.clipboard.writeText(this.shareLink)
|
||||
|
||||
showSuccess(this.t('files_sharing', 'Link copied to clipboard'))
|
||||
showSuccess(t('files_sharing', 'Link copied to clipboard'))
|
||||
this.isCopied = true
|
||||
event.target?.select?.()
|
||||
|
||||
|
|
@ -147,7 +148,15 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
addNewEmail(e: KeyboardEvent) {
|
||||
if (this.email.trim() === '') {
|
||||
return
|
||||
}
|
||||
|
||||
if (e.target instanceof HTMLInputElement) {
|
||||
// Reset the custom validity
|
||||
e.target.setCustomValidity('')
|
||||
|
||||
// Check if the field is valid
|
||||
if (e.target.checkValidity() === false) {
|
||||
e.target.reportValidity()
|
||||
return
|
||||
|
|
@ -155,13 +164,14 @@ export default defineComponent({
|
|||
|
||||
// The email is already in the list
|
||||
if (this.emails.includes(this.email.trim())) {
|
||||
e.target.setCustomValidity(this.t('files_sharing', 'Email already added'))
|
||||
e.target.setCustomValidity(t('files_sharing', 'Email already added'))
|
||||
e.target.reportValidity()
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the email is valid
|
||||
if (!this.isValidEmail(this.email.trim())) {
|
||||
e.target.setCustomValidity(this.t('files_sharing', 'Invalid email address'))
|
||||
e.target.setCustomValidity(t('files_sharing', 'Invalid email address'))
|
||||
e.target.reportValidity()
|
||||
return
|
||||
}
|
||||
|
|
@ -188,24 +198,24 @@ export default defineComponent({
|
|||
|
||||
// Warn about invalid emails
|
||||
if (invalidEmails.length > 0) {
|
||||
showError(this.n('files_sharing', 'The following email address is not valid: {emails}', 'The following email addresses are not valid: {emails}', invalidEmails.length, { emails: invalidEmails.join(', ') }))
|
||||
showError(n('files_sharing', 'The following email address is not valid: {emails}', 'The following email addresses are not valid: {emails}', invalidEmails.length, { emails: invalidEmails.join(', ') }))
|
||||
}
|
||||
|
||||
// Warn about duplicate emails
|
||||
if (duplicateEmails.length > 0) {
|
||||
showError(this.n('files_sharing', '1 email address already added', '{count} email addresses already added', duplicateEmails.length, { count: duplicateEmails.length }))
|
||||
showError(n('files_sharing', '1 email address already added', '{count} email addresses already added', duplicateEmails.length, { count: duplicateEmails.length }))
|
||||
}
|
||||
|
||||
if (validEmails.length > 0) {
|
||||
showSuccess(this.n('files_sharing', '1 email address added', '{count} email addresses added', validEmails.length, { count: validEmails.length }))
|
||||
showSuccess(n('files_sharing', '1 email address added', '{count} email addresses added', validEmails.length, { count: validEmails.length }))
|
||||
}
|
||||
|
||||
this.email = ''
|
||||
},
|
||||
|
||||
isValidEmail(email) {
|
||||
const regExpEmail = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
return regExpEmail.test(email)
|
||||
// No need to have a fancy regex, just check for an @
|
||||
isValidEmail(email: string): boolean {
|
||||
return email.includes('@')
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
@ -213,7 +223,7 @@ export default defineComponent({
|
|||
<style scoped>
|
||||
.input-field,
|
||||
.file-request-dialog__emails {
|
||||
margin-top: var(--secondary-margin);
|
||||
margin-top: var(--margin);
|
||||
}
|
||||
|
||||
.file-request-dialog__emails {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
</legend>
|
||||
<NcTextField :value="destination"
|
||||
:disabled="disabled"
|
||||
:helper-text="t('files_sharing', 'The uploaded files are visible only to you unless you choose to share them.')"
|
||||
:label="t('files_sharing', 'Upload destination')"
|
||||
:minlength="2/* cannot share root */"
|
||||
:placeholder="t('files_sharing', 'Select a destination')"
|
||||
|
|
@ -42,6 +41,11 @@
|
|||
@trailing-button-click="$emit('update:destination', '')">
|
||||
<IconFolder :size="18" />
|
||||
</NcTextField>
|
||||
|
||||
<p class="file-request-dialog__info">
|
||||
<IconLock :size="18" class="file-request-dialog__info-icon" />
|
||||
{{ t('files_sharing', 'The uploaded files are visible only to you unless you choose to share them.') }}
|
||||
</p>
|
||||
</fieldset>
|
||||
|
||||
<!-- Request note -->
|
||||
|
|
@ -56,6 +60,11 @@
|
|||
:required="false"
|
||||
name="note"
|
||||
@update:value="$emit('update:note', $event)" />
|
||||
|
||||
<p class="file-request-dialog__info">
|
||||
<IconInfo :size="18" class="file-request-dialog__info-icon" />
|
||||
{{ t('files_sharing', 'You can add links, date or any other information that will help the recipient understand what you are requesting.') }}
|
||||
</p>
|
||||
</fieldset>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -66,9 +75,11 @@ import type { Folder, Node } from '@nextcloud/files'
|
|||
|
||||
import { defineComponent } from 'vue'
|
||||
import { getFilePickerBuilder } from '@nextcloud/dialogs'
|
||||
import { translate } from '@nextcloud/l10n'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
|
||||
import IconFolder from 'vue-material-design-icons/Folder.vue'
|
||||
import IconInfo from 'vue-material-design-icons/Information.vue'
|
||||
import IconLock from 'vue-material-design-icons/Lock.vue'
|
||||
import NcTextArea from '@nextcloud/vue/dist/Components/NcTextArea.js'
|
||||
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
|
||||
|
||||
|
|
@ -77,6 +88,8 @@ export default defineComponent({
|
|||
|
||||
components: {
|
||||
IconFolder,
|
||||
IconInfo,
|
||||
IconLock,
|
||||
NcTextArea,
|
||||
NcTextField,
|
||||
},
|
||||
|
|
@ -113,17 +126,17 @@ export default defineComponent({
|
|||
|
||||
setup() {
|
||||
return {
|
||||
t: translate,
|
||||
t,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onPickDestination() {
|
||||
const filepicker = getFilePickerBuilder(this.t('files_sharing', 'Select a destination'))
|
||||
const filepicker = getFilePickerBuilder(t('files_sharing', 'Select a destination'))
|
||||
.addMimeTypeFilter('httpd/unix-directory')
|
||||
.allowDirectories(true)
|
||||
.addButton({
|
||||
label: this.t('files_sharing', 'Select'),
|
||||
label: t('files_sharing', 'Select'),
|
||||
callback: this.onPickedDestination,
|
||||
})
|
||||
.setFilter(node => node.path !== '/')
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export default {
|
|||
async pickFolder() {
|
||||
|
||||
// Setup file picker
|
||||
const picker = getFilePickerBuilder(t('files', 'Choose a default folder for accepted shares'))
|
||||
const picker = getFilePickerBuilder(t('files_sharing', 'Choose a default folder for accepted shares'))
|
||||
.startAt(this.readableDirectory)
|
||||
.setMultiSelect(false)
|
||||
.setType(1)
|
||||
|
|
@ -69,7 +69,7 @@ export default {
|
|||
// Init user folder picking
|
||||
const dir = await picker.pick() || '/'
|
||||
if (!dir.startsWith('/')) {
|
||||
throw new Error(t('files', 'Invalid path selected'))
|
||||
throw new Error(t('files_sharing', 'Invalid path selected'))
|
||||
}
|
||||
|
||||
// Fix potential path issues and save results
|
||||
|
|
@ -78,7 +78,7 @@ export default {
|
|||
shareFolder: this.directory,
|
||||
})
|
||||
} catch (error) {
|
||||
showError(error.message || t('files', 'Unknown error'))
|
||||
showError(error.message || t('files_sharing', 'Unknown error'))
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
</div>
|
||||
|
||||
<!-- clipboard -->
|
||||
<NcActions v-if="share && !isEmailShareType && share.token" ref="copyButton" class="sharing-entry__copy">
|
||||
<NcActionButton :title="copyLinkTooltip"
|
||||
<NcActions v-if="share && (!isEmailShareType || isFileRequest) && share.token" ref="copyButton" class="sharing-entry__copy">
|
||||
<NcActionButton :title="copyLinkTooltip"
|
||||
:aria-label="copyLinkTooltip"
|
||||
@click.prevent="copyLink">
|
||||
<template #icon>
|
||||
|
|
|
|||
|
|
@ -4,22 +4,27 @@
|
|||
*/
|
||||
import type { Entry, Folder, Node } from '@nextcloud/files'
|
||||
|
||||
import { Permission } from '@nextcloud/files'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import Vue, { defineAsyncComponent } from 'vue'
|
||||
import FileUploadSvg from '@mdi/svg/svg/file-upload.svg?raw'
|
||||
import Vue, { defineAsyncComponent } from 'vue'
|
||||
import Config from '../services/ConfigService'
|
||||
|
||||
const NewFileRequestDialogVue = defineAsyncComponent(() => import('../components/NewFileRequestDialog.vue'))
|
||||
|
||||
const sharingConfig = new Config()
|
||||
|
||||
export const entry = {
|
||||
id: 'file-request',
|
||||
displayName: t('files', 'Create new file request'),
|
||||
displayName: t('files_sharing', 'Create file request'),
|
||||
iconSvgInline: FileUploadSvg,
|
||||
order: 30,
|
||||
enabled(): boolean {
|
||||
// TODO: determine requirements
|
||||
// 1. user can share the root folder
|
||||
// 2. OR user can create subfolders ?
|
||||
return true
|
||||
enabled(context: Folder): boolean {
|
||||
if ((context.permissions & Permission.SHARE) !== 0) {
|
||||
// We need to have either link shares creation permissions
|
||||
return sharingConfig.isPublicShareAllowed
|
||||
}
|
||||
return false
|
||||
},
|
||||
async handler(context: Folder, content: Node[]) {
|
||||
// Create document root
|
||||
|
|
|
|||
23
apps/files_sharing/src/public-file-request.ts
Normal file
23
apps/files_sharing/src/public-file-request.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { spawnDialog } from '@nextcloud/dialogs'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import logger from './services/logger'
|
||||
|
||||
const nick = localStorage.getItem('nick')
|
||||
const publicAuthPromptShown = localStorage.getItem('publicAuthPromptShown')
|
||||
|
||||
// If we don't have a nickname or the public auth prompt hasn't been shown yet, show it
|
||||
// We still show the prompt if the user has a nickname to double check
|
||||
if (!nick || !publicAuthPromptShown) {
|
||||
spawnDialog(
|
||||
defineAsyncComponent(() => import('./views/PublicAuthPrompt.vue')),
|
||||
{},
|
||||
() => localStorage.setItem('publicAuthPromptShown', 'true'),
|
||||
)
|
||||
} else {
|
||||
logger.debug(`Public auth prompt already shown. Current nickname is '${nick}'`)
|
||||
}
|
||||
|
|
@ -210,6 +210,13 @@ export default class Config {
|
|||
return window.OC.appConfig.core.remoteShareAllowed === true
|
||||
}
|
||||
|
||||
/**
|
||||
* Is public sharing enabled ?
|
||||
*/
|
||||
get isPublicShareAllowed(): boolean {
|
||||
return this._capabilities?.files_sharing?.public?.enabled === true
|
||||
}
|
||||
|
||||
/**
|
||||
* Is sharing my mail (link share) enabled ?
|
||||
*/
|
||||
|
|
@ -217,7 +224,7 @@ export default class Config {
|
|||
// eslint-disable-next-line camelcase
|
||||
return this._capabilities?.files_sharing?.sharebymail?.enabled === true
|
||||
// eslint-disable-next-line camelcase
|
||||
&& this._capabilities?.files_sharing?.public?.enabled === true
|
||||
&& this.isPublicShareAllowed === true
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
136
apps/files_sharing/src/views/PublicAuthPrompt.vue
Normal file
136
apps/files_sharing/src/views/PublicAuthPrompt.vue
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<template>
|
||||
<NcDialog class="public-auth-prompt"
|
||||
dialog-classes="public-auth-prompt__dialog"
|
||||
:can-close="false"
|
||||
:name="dialogName">
|
||||
<h3 v-if="owner" class="public-auth-prompt__subtitle">
|
||||
{{ t('files_sharing', '{ownerDisplayName} shared a folder with you.', { ownerDisplayName }) }}
|
||||
</h3>
|
||||
|
||||
<!-- Header -->
|
||||
<NcNoteCard type="info" class="public-auth-prompt__header">
|
||||
<p id="public-auth-prompt-dialog-description" class="public-auth-prompt__description">
|
||||
{{ t('files_sharing', 'To upload files, you need to provide your name first.') }}
|
||||
</p>
|
||||
</NcNoteCard>
|
||||
|
||||
<!-- Form -->
|
||||
<form ref="form"
|
||||
aria-describedby="public-auth-prompt-dialog-description"
|
||||
class="public-auth-prompt__form"
|
||||
@submit.prevent.stop="">
|
||||
<NcTextField ref="input"
|
||||
class="public-auth-prompt__input"
|
||||
:label="t('files_sharing', 'Enter your name')"
|
||||
name="name"
|
||||
:required="true"
|
||||
:minlength="2"
|
||||
:value.sync="name" />
|
||||
</form>
|
||||
|
||||
<!-- Submit -->
|
||||
<template #actions>
|
||||
<NcButton ref="submit"
|
||||
:disabled="name.trim() === ''"
|
||||
@click="onSubmit">
|
||||
{{ t('files_sharing', 'Submit name') }}
|
||||
</NcButton>
|
||||
</template>
|
||||
</NcDialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
|
||||
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
|
||||
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PublicAuthPrompt',
|
||||
|
||||
components: {
|
||||
NcButton,
|
||||
NcDialog,
|
||||
NcNoteCard,
|
||||
NcTextField,
|
||||
},
|
||||
|
||||
setup() {
|
||||
return {
|
||||
t,
|
||||
|
||||
owner: loadState('files_sharing', 'owner', ''),
|
||||
ownerDisplayName: loadState('files_sharing', 'ownerDisplayName', ''),
|
||||
label: loadState('files_sharing', 'label', ''),
|
||||
note: loadState('files_sharing', 'note', ''),
|
||||
filename: loadState('files_sharing', 'filename', ''),
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
name: '',
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
dialogName() {
|
||||
return this.t('files_sharing', 'Upload files to {folder}', { folder: this.label || this.filename })
|
||||
},
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
// Pre-load the name from local storage if already set by another app
|
||||
// like Talk, Colabora or Text...
|
||||
const talkNick = localStorage.getItem('nick')
|
||||
if (talkNick) {
|
||||
this.name = talkNick
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onSubmit() {
|
||||
const form = this.$refs.form as HTMLFormElement
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity()
|
||||
return
|
||||
}
|
||||
|
||||
if (this.name.trim() === '') {
|
||||
return
|
||||
}
|
||||
|
||||
localStorage.setItem('nick', this.name)
|
||||
this.$emit('close')
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.public-auth-prompt {
|
||||
&__subtitle {
|
||||
// Smaller than dialog title
|
||||
font-size: 16px;
|
||||
margin-block: 12px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
// Fix extra margin generating an unwanted gap
|
||||
margin-block: 12px;
|
||||
}
|
||||
|
||||
&__form {
|
||||
// Double the margin of the header
|
||||
margin-block: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -603,7 +603,10 @@ export default {
|
|||
return (this.fileInfo.canDownload() || this.canDownload)
|
||||
},
|
||||
canRemoveReadPermission() {
|
||||
return this.allowsFileDrop && this.share.type === this.SHARE_TYPES.SHARE_TYPE_LINK
|
||||
return this.allowsFileDrop && (
|
||||
this.share.type === this.SHARE_TYPES.SHARE_TYPE_LINK
|
||||
|| this.share.type === this.SHARE_TYPES.SHARE_TYPE_EMAIL
|
||||
)
|
||||
},
|
||||
// if newPassword exists, but is empty, it means
|
||||
// the user deleted the original password
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
<input type="hidden" name="mimetypeIcon" value="<?php p(\OC::$server->getMimeTypeDetector()->mimeTypeIcon($_['mimetype'])); ?>" id="mimetypeIcon">
|
||||
<input type="hidden" name="hideDownload" value="<?php p($_['hideDownload'] ? 'true' : 'false'); ?>" id="hideDownload">
|
||||
<input type="hidden" id="disclaimerText" value="<?php p($_['disclaimer']) ?>">
|
||||
|
||||
<?php
|
||||
$upload_max_filesize = OC::$server->get(\bantu\IniGetWrapper\IniGetWrapper::class)->getBytes('upload_max_filesize');
|
||||
$post_max_size = OC::$server->get(\bantu\IniGetWrapper\IniGetWrapper::class)->getBytes('post_max_size');
|
||||
|
|
@ -102,11 +103,11 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size);
|
|||
class="emptycontent <?php if (!empty($_['note'])) { ?>has-note<?php } ?>">
|
||||
<?php if ($_['shareOwner']) { ?>
|
||||
<div id="displayavatar"><div class="avatardiv"></div></div>
|
||||
<h2><?php p($l->t('Upload files to %s', [$_['shareOwner']])) ?></h2>
|
||||
<p><span class="icon-folder"></span> <?php p($_['filename']) ?></p>
|
||||
<h2><?php p($l->t('Upload files to %s', [$_['label'] ?: $_['filename']])) ?></h2>
|
||||
<p><?php p($l->t('%s shared a folder with you.', [$_['shareOwner']])) ?></p>
|
||||
<?php } else { ?>
|
||||
<div id="displayavatar"><span class="icon-folder"></span></div>
|
||||
<h2><?php p($l->t('Upload files to %s', [$_['filename']])) ?></h2>
|
||||
<h2><?php p($l->t('Upload files to %s', [$_['label'] ?: $_['filename']])) ?></h2>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (empty($_['note']) === false) { ?>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use OCP\AppFramework\Http\Template\ExternalShareMenuAction;
|
|||
use OCP\AppFramework\Http\Template\LinkMenuAction;
|
||||
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
|
||||
use OCP\AppFramework\Http\Template\SimpleMenuAction;
|
||||
use OCP\AppFramework\Services\IInitialState;
|
||||
use OCP\Constants;
|
||||
use OCP\Defaults;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
|
|
@ -121,6 +122,7 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
$this->defaults,
|
||||
$this->config,
|
||||
$this->createMock(IRequest::class),
|
||||
$this->createMock(IInitialState::class)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -350,7 +352,8 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
'previewURL' => 'downloadURL',
|
||||
'note' => $note,
|
||||
'hideDownload' => false,
|
||||
'showgridview' => false
|
||||
'showgridview' => false,
|
||||
'label' => ''
|
||||
];
|
||||
|
||||
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
|
||||
|
|
@ -511,7 +514,8 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
'previewURL' => 'downloadURL',
|
||||
'note' => $note,
|
||||
'hideDownload' => false,
|
||||
'showgridview' => false
|
||||
'showgridview' => false,
|
||||
'label' => ''
|
||||
];
|
||||
|
||||
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
|
||||
|
|
@ -672,7 +676,8 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
'previewURL' => 'downloadURL',
|
||||
'note' => $note,
|
||||
'hideDownload' => true,
|
||||
'showgridview' => false
|
||||
'showgridview' => false,
|
||||
'label' => ''
|
||||
];
|
||||
|
||||
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
|
||||
|
|
@ -798,7 +803,8 @@ class ShareControllerTest extends \Test\TestCase {
|
|||
'previewURL' => '',
|
||||
'note' => '',
|
||||
'hideDownload' => false,
|
||||
'showgridview' => false
|
||||
'showgridview' => false,
|
||||
'label' => ''
|
||||
];
|
||||
|
||||
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ REPODIR=`git rev-parse --show-toplevel`
|
|||
|
||||
cd $REPODIR
|
||||
|
||||
# Comments files plugin
|
||||
node node_modules/handlebars/bin/handlebars -n OCA.Comments.Templates apps/comments/src/templates -f apps/comments/src/templates.js
|
||||
|
||||
# Settings
|
||||
node node_modules/handlebars/bin/handlebars -n OC.Settings.Templates apps/settings/js/templates -f apps/settings/js/templates.js
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class FilesDropContext implements Context, SnippetAcceptingContext {
|
|||
/**
|
||||
* @When Dropping file :path with :content
|
||||
*/
|
||||
public function droppingFileWith($path, $content) {
|
||||
public function droppingFileWith($path, $content, $nickName = null) {
|
||||
$client = new Client();
|
||||
$options = [];
|
||||
if (count($this->lastShareData->data->element) > 0) {
|
||||
|
|
@ -25,11 +25,16 @@ class FilesDropContext implements Context, SnippetAcceptingContext {
|
|||
}
|
||||
|
||||
$base = substr($this->baseUrl, 0, -4);
|
||||
$fullUrl = $base . "/public.php/dav/files/$token/$path";
|
||||
$fullUrl = str_replace('//', '/', $base . "/public.php/dav/files/$token/$path");
|
||||
|
||||
$options['headers'] = [
|
||||
'X-REQUESTED-WITH' => 'XMLHttpRequest'
|
||||
];
|
||||
|
||||
if ($nickName) {
|
||||
$options['headers']['X-NC-NICKNAME'] = $nickName;
|
||||
}
|
||||
|
||||
$options['body'] = \GuzzleHttp\Psr7\Utils::streamFor($content);
|
||||
|
||||
try {
|
||||
|
|
@ -38,6 +43,15 @@ class FilesDropContext implements Context, SnippetAcceptingContext {
|
|||
$this->response = $e->getResponse();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @When Dropping file :path with :content as :nickName
|
||||
*/
|
||||
public function droppingFileWithAs($path, $content, $nickName) {
|
||||
$this->droppingFileWith($path, $content, $nickName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @When Creating folder :folder in drop
|
||||
|
|
@ -52,7 +66,7 @@ class FilesDropContext implements Context, SnippetAcceptingContext {
|
|||
}
|
||||
|
||||
$base = substr($this->baseUrl, 0, -4);
|
||||
$fullUrl = $base . "/public.php/dav/files/$token/$folder";
|
||||
$fullUrl = str_replace('//', '/', $base . "/public.php/dav/files/$token/$folder");
|
||||
|
||||
$options['headers'] = [
|
||||
'X-REQUESTED-WITH' => 'XMLHttpRequest'
|
||||
|
|
|
|||
|
|
@ -59,3 +59,34 @@ Feature: FilesDrop
|
|||
| permissions | 4 |
|
||||
When Creating folder "folder" in drop
|
||||
Then the HTTP status code should be "405"
|
||||
|
||||
Scenario: Files request drop
|
||||
Given user "user0" exists
|
||||
And As an "user0"
|
||||
And user "user0" created a folder "/drop"
|
||||
And as "user0" creating a share with
|
||||
| path | drop |
|
||||
| shareType | 4 |
|
||||
| permissions | 4 |
|
||||
| attributes | [{"scope":"fileRequest","key":"enabled","value":true}] |
|
||||
| shareWith | |
|
||||
When Dropping file "/folder/a.txt" with "abc" as "Alice"
|
||||
And Downloading file "/drop/Alice/a.txt"
|
||||
Then Downloaded content should be "abc"
|
||||
|
||||
Scenario: Put file same file multiple times via files drop
|
||||
Given user "user0" exists
|
||||
And As an "user0"
|
||||
And user "user0" created a folder "/drop"
|
||||
And as "user0" creating a share with
|
||||
| path | drop |
|
||||
| shareType | 4 |
|
||||
| permissions | 4 |
|
||||
| attributes | [{"scope":"fileRequest","key":"enabled","value":true}] |
|
||||
| shareWith | |
|
||||
When Dropping file "/folder/a.txt" with "abc" as "Mallory"
|
||||
And Dropping file "/folder/a.txt" with "def" as "Mallory"
|
||||
And Downloading file "/drop/Mallory/a.txt"
|
||||
Then Downloaded content should be "abc"
|
||||
And Downloading file "/drop/Mallory/a (2).txt"
|
||||
Then Downloaded content should be "def"
|
||||
|
|
|
|||
2
dist/128-128.js
vendored
2
dist/128-128.js
vendored
File diff suppressed because one or more lines are too long
1
dist/128-128.js.map
vendored
1
dist/128-128.js.map
vendored
File diff suppressed because one or more lines are too long
1
dist/128-128.js.map.license
vendored
1
dist/128-128.js.map.license
vendored
|
|
@ -1 +0,0 @@
|
|||
128-128.js.license
|
||||
2
dist/4589-4589.js
vendored
Normal file
2
dist/4589-4589.js
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
"use strict";(self.webpackChunknextcloud=self.webpackChunknextcloud||[]).push([[4589],{7869:(t,e,n)=>{n.d(e,{A:()=>l});var a=n(71354),i=n.n(a),s=n(76314),o=n.n(s)()(i());o.push([t.id,".public-auth-prompt__subtitle{font-size:16px;margin-block:12px}.public-auth-prompt__header{margin-block:12px}.public-auth-prompt__form{margin-block:24px}","",{version:3,sources:["webpack://./apps/files_sharing/src/views/PublicAuthPrompt.vue"],names:[],mappings:"AAEC,8BAEC,cAAA,CACA,iBAAA,CAGD,4BAEC,iBAAA,CAGD,0BAEC,iBAAA",sourcesContent:["\n.public-auth-prompt {\n\t&__subtitle {\n\t\t// Smaller than dialog title\n\t\tfont-size: 16px;\n\t\tmargin-block: 12px;\n\t}\n\n\t&__header {\n\t\t// Fix extra margin generating an unwanted gap\n\t\tmargin-block: 12px;\n\t}\n\n\t&__form {\n\t\t// Double the margin of the header\n\t\tmargin-block: 24px;\n\t}\n}\n"],sourceRoot:""}]);const l=o},4589:(t,e,n)=>{n.r(e),n.d(e,{default:()=>v});var a=n(85471),i=n(53334),s=n(54332),o=n(94219),l=n(52201),r=n(82182),p=n(32981);const u=(0,a.pM)({name:"PublicAuthPrompt",components:{NcButton:s.A,NcDialog:o.A,NcNoteCard:l.A,NcTextField:r.A},setup:()=>({t:i.t,owner:(0,p.C)("files_sharing","owner",""),ownerDisplayName:(0,p.C)("files_sharing","ownerDisplayName",""),label:(0,p.C)("files_sharing","label",""),note:(0,p.C)("files_sharing","note",""),filename:(0,p.C)("files_sharing","filename","")}),data:()=>({name:""}),computed:{dialogName(){return this.t("files_sharing","Upload files to {folder}",{folder:this.label||this.filename})}},beforeMount(){const t=localStorage.getItem("nick");t&&(this.name=t)},methods:{onSubmit(){const t=this.$refs.form;t.checkValidity()?""!==this.name.trim()&&(localStorage.setItem("nick",this.name),this.$emit("close")):t.reportValidity()}}});var c=n(85072),m=n.n(c),h=n(97825),d=n.n(h),_=n(77659),f=n.n(_),b=n(55056),g=n.n(b),A=n(10540),C=n.n(A),y=n(41113),x=n.n(y),N=n(7869),k={};k.styleTagTransform=x(),k.setAttributes=g(),k.insert=f().bind(null,"head"),k.domAPI=d(),k.insertStyleElement=C(),m()(N.A,k),N.A&&N.A.locals&&N.A.locals;const v=(0,n(14486).A)(u,(function(){var t=this,e=t._self._c;return t._self._setupProxy,e("NcDialog",{staticClass:"public-auth-prompt",attrs:{"dialog-classes":"public-auth-prompt__dialog","can-close":!1,name:t.dialogName},scopedSlots:t._u([{key:"actions",fn:function(){return[e("NcButton",{ref:"submit",attrs:{disabled:""===t.name.trim()},on:{click:t.onSubmit}},[t._v("\n\t\t\t"+t._s(t.t("files_sharing","Submit name"))+"\n\t\t")])]},proxy:!0}])},[t.owner?e("h3",{staticClass:"public-auth-prompt__subtitle"},[t._v("\n\t\t"+t._s(t.t("files_sharing","{ownerDisplayName} shared a folder with you.",{ownerDisplayName:t.ownerDisplayName}))+"\n\t")]):t._e(),t._v(" "),e("NcNoteCard",{staticClass:"public-auth-prompt__header",attrs:{type:"info"}},[e("p",{staticClass:"public-auth-prompt__description",attrs:{id:"public-auth-prompt-dialog-description"}},[t._v("\n\t\t\t"+t._s(t.t("files_sharing","To upload files, you need to provide your name first."))+"\n\t\t")])]),t._v(" "),e("form",{ref:"form",staticClass:"public-auth-prompt__form",attrs:{"aria-describedby":"public-auth-prompt-dialog-description"},on:{submit:function(t){t.preventDefault(),t.stopPropagation()}}},[e("NcTextField",{ref:"input",staticClass:"public-auth-prompt__input",attrs:{label:t.t("files_sharing","Enter your name"),name:"name",required:!0,minlength:2,value:t.name},on:{"update:value":function(e){t.name=e}}})],1)],1)}),[],!1,null,null,null).exports}}]);
|
||||
//# sourceMappingURL=4589-4589.js.map?v=f528d9600121156d9e2c
|
||||
174
dist/4589-4589.js.license
vendored
Normal file
174
dist/4589-4589.js.license
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
SPDX-License-Identifier: MIT
|
||||
SPDX-License-Identifier: ISC
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
|
||||
SPDX-FileCopyrightText: inherits developers
|
||||
SPDX-FileCopyrightText: escape-html developers
|
||||
SPDX-FileCopyrightText: assert developers
|
||||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Raynos <raynos2@gmail.com>
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Joyent
|
||||
SPDX-FileCopyrightText: Jordan Harband <ljharb@gmail.com>
|
||||
SPDX-FileCopyrightText: Jordan Harband
|
||||
SPDX-FileCopyrightText: John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)
|
||||
SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
|
||||
SPDX-FileCopyrightText: Guillaume Chau <guillaume.b.chau@gmail.com>
|
||||
SPDX-FileCopyrightText: Evan You
|
||||
SPDX-FileCopyrightText: Dr.-Ing. Mario Heiderich, Cure53 <mario@cure53.de> (https://cure53.de/)
|
||||
SPDX-FileCopyrightText: David Clark
|
||||
SPDX-FileCopyrightText: Christoph Wurst
|
||||
SPDX-FileCopyrightText: Anthony Fu <https://github.com/antfu>
|
||||
SPDX-FileCopyrightText: Andris Reinman
|
||||
|
||||
|
||||
This file is generated from multiple sources. Included packages:
|
||||
- @nextcloud/initial-state
|
||||
- version: 2.2.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/l10n
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/router
|
||||
- version: 3.0.1
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/vue
|
||||
- version: 8.14.0
|
||||
- license: AGPL-3.0-or-later
|
||||
- @vueuse/core
|
||||
- version: 10.11.0
|
||||
- license: MIT
|
||||
- @vueuse/shared
|
||||
- version: 10.11.0
|
||||
- license: MIT
|
||||
- assert
|
||||
- version: 2.1.0
|
||||
- license: MIT
|
||||
- available-typed-arrays
|
||||
- version: 1.0.7
|
||||
- license: MIT
|
||||
- call-bind
|
||||
- version: 1.0.7
|
||||
- license: MIT
|
||||
- console-browserify
|
||||
- version: 1.2.0
|
||||
- license: MIT
|
||||
- css-loader
|
||||
- version: 6.10.0
|
||||
- license: MIT
|
||||
- define-data-property
|
||||
- version: 1.1.4
|
||||
- license: MIT
|
||||
- define-properties
|
||||
- version: 1.2.1
|
||||
- license: MIT
|
||||
- dompurify
|
||||
- version: 3.1.4
|
||||
- license: (MPL-2.0 OR Apache-2.0)
|
||||
- es-define-property
|
||||
- version: 1.0.0
|
||||
- license: MIT
|
||||
- es-errors
|
||||
- version: 1.3.0
|
||||
- license: MIT
|
||||
- escape-html
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- floating-vue
|
||||
- version: 1.0.0-beta.19
|
||||
- license: MIT
|
||||
- focus-trap
|
||||
- version: 7.5.4
|
||||
- license: MIT
|
||||
- for-each
|
||||
- version: 0.3.3
|
||||
- license: MIT
|
||||
- function-bind
|
||||
- version: 1.1.2
|
||||
- license: MIT
|
||||
- get-intrinsic
|
||||
- version: 1.2.4
|
||||
- license: MIT
|
||||
- gopd
|
||||
- version: 1.0.1
|
||||
- license: MIT
|
||||
- has-property-descriptors
|
||||
- version: 1.0.2
|
||||
- license: MIT
|
||||
- has-proto
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- has-symbols
|
||||
- version: 1.0.3
|
||||
- license: MIT
|
||||
- has-tostringtag
|
||||
- version: 1.0.2
|
||||
- license: MIT
|
||||
- hasown
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
- inherits
|
||||
- version: 2.0.4
|
||||
- license: ISC
|
||||
- is-arguments
|
||||
- version: 1.1.1
|
||||
- license: MIT
|
||||
- is-callable
|
||||
- version: 1.2.7
|
||||
- license: MIT
|
||||
- is-generator-function
|
||||
- version: 1.0.10
|
||||
- license: MIT
|
||||
- is-nan
|
||||
- version: 1.3.2
|
||||
- license: MIT
|
||||
- is-typed-array
|
||||
- version: 1.1.13
|
||||
- license: MIT
|
||||
- lodash.get
|
||||
- version: 4.4.2
|
||||
- license: MIT
|
||||
- node-gettext
|
||||
- version: 3.0.0
|
||||
- license: MIT
|
||||
- object-is
|
||||
- version: 1.1.5
|
||||
- license: MIT
|
||||
- object-keys
|
||||
- version: 1.1.1
|
||||
- license: MIT
|
||||
- object.assign
|
||||
- version: 4.1.5
|
||||
- license: MIT
|
||||
- possible-typed-array-names
|
||||
- version: 1.0.0
|
||||
- license: MIT
|
||||
- process
|
||||
- version: 0.11.10
|
||||
- license: MIT
|
||||
- set-function-length
|
||||
- version: 1.2.1
|
||||
- license: MIT
|
||||
- style-loader
|
||||
- version: 3.3.4
|
||||
- license: MIT
|
||||
- tabbable
|
||||
- version: 6.2.0
|
||||
- license: MIT
|
||||
- util
|
||||
- version: 0.12.5
|
||||
- license: MIT
|
||||
- vue-loader
|
||||
- version: 15.11.1
|
||||
- license: MIT
|
||||
- vue
|
||||
- version: 2.7.16
|
||||
- license: MIT
|
||||
- which-typed-array
|
||||
- version: 1.1.15
|
||||
- license: MIT
|
||||
- nextcloud
|
||||
- version: 1.0.0
|
||||
- license: AGPL-3.0-or-later
|
||||
1
dist/4589-4589.js.map
vendored
Normal file
1
dist/4589-4589.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/4589-4589.js.map.license
vendored
Symbolic link
1
dist/4589-4589.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
4589-4589.js.license
|
||||
2
dist/4845-4845.js
vendored
2
dist/4845-4845.js
vendored
File diff suppressed because one or more lines are too long
1
dist/4845-4845.js.map
vendored
1
dist/4845-4845.js.map
vendored
File diff suppressed because one or more lines are too long
1
dist/4845-4845.js.map.license
vendored
1
dist/4845-4845.js.map.license
vendored
|
|
@ -1 +0,0 @@
|
|||
4845-4845.js.license
|
||||
2
dist/6968-6968.js
vendored
Normal file
2
dist/6968-6968.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/6968-6968.js.map
vendored
Normal file
1
dist/6968-6968.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/6968-6968.js.map.license
vendored
Symbolic link
1
dist/6968-6968.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
6968-6968.js.license
|
||||
2
dist/8755-8755.js
vendored
Normal file
2
dist/8755-8755.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/8755-8755.js.map
vendored
Normal file
1
dist/8755-8755.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/8755-8755.js.map.license
vendored
Symbolic link
1
dist/8755-8755.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
8755-8755.js.license
|
||||
2
dist/8971-8971.js
vendored
2
dist/8971-8971.js
vendored
File diff suppressed because one or more lines are too long
1
dist/8971-8971.js.map
vendored
1
dist/8971-8971.js.map
vendored
File diff suppressed because one or more lines are too long
1
dist/8971-8971.js.map.license
vendored
1
dist/8971-8971.js.map.license
vendored
|
|
@ -1 +0,0 @@
|
|||
8971-8971.js.license
|
||||
4
dist/comments-comments-tab.js
vendored
4
dist/comments-comments-tab.js
vendored
File diff suppressed because one or more lines are too long
2
dist/comments-comments-tab.js.map
vendored
2
dist/comments-comments-tab.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files-search.js
vendored
4
dist/files-search.js
vendored
|
|
@ -1,2 +1,2 @@
|
|||
(()=>{"use strict";var e,r,t,i={66747:(e,r,t)=>{var i=t(61338),o=t(85168),n=t(63814),a=t(53334);const l=(0,t(35947).YK)().setApp("files").detectUser().build();document.addEventListener("DOMContentLoaded",(function(){const e=window.OCA;e.UnifiedSearch&&(l.info("Initializing unified search plugin: folder search from files app"),e.UnifiedSearch.registerFilterAction({id:"files",appId:"files",label:(0,a.Tl)("files","In folder"),icon:(0,n.d0)("files","app.svg"),callback:()=>{(0,o.a1)("Pick plain text files").addMimeTypeFilter("httpd/unix-directory").allowDirectories(!0).addButton({label:"Pick",callback:e=>{l.info("Folder picked",{folder:e[0]});const r=e[0];(0,i.Ic)("nextcloud:unified-search:add-filter",{id:"files",payload:r,filterUpdateText:(0,a.Tl)("files","Search in folder: {folder}",{folder:r.basename}),filterParams:{path:r.path}})}}).build().pick()}}))}))}},o={};function n(e){var r=o[e];if(void 0!==r)return r.exports;var t=o[e]={id:e,loaded:!1,exports:{}};return i[e].call(t.exports,t,t.exports,n),t.loaded=!0,t.exports}n.m=i,e=[],n.O=(r,t,i,o)=>{if(!t){var a=1/0;for(s=0;s<e.length;s++){t=e[s][0],i=e[s][1],o=e[s][2];for(var l=!0,d=0;d<t.length;d++)(!1&o||a>=o)&&Object.keys(n.O).every((e=>n.O[e](t[d])))?t.splice(d--,1):(l=!1,o<a&&(a=o));if(l){e.splice(s--,1);var c=i();void 0!==c&&(r=c)}}return r}o=o||0;for(var s=e.length;s>0&&e[s-1][2]>o;s--)e[s]=e[s-1];e[s]=[t,i,o]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.f={},n.e=e=>Promise.all(Object.keys(n.f).reduce(((r,t)=>(n.f[t](e,r),r)),[])),n.u=e=>e+"-"+e+".js?v="+{4254:"5c2324570f66dff0c8a1",9480:"f3ebcf41e93bbd8cd678"}[e],n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="nextcloud:",n.l=(e,i,o,a)=>{if(r[e])r[e].push(i);else{var l,d;if(void 0!==o)for(var c=document.getElementsByTagName("script"),s=0;s<c.length;s++){var u=c[s];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==t+o){l=u;break}}l||(d=!0,(l=document.createElement("script")).charset="utf-8",l.timeout=120,n.nc&&l.setAttribute("nonce",n.nc),l.setAttribute("data-webpack",t+o),l.src=e),r[e]=[i];var f=(t,i)=>{l.onerror=l.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],l.parentNode&&l.parentNode.removeChild(l),o&&o.forEach((e=>e(i))),t)return t(i)},p=setTimeout(f.bind(null,void 0,{type:"timeout",target:l}),12e4);l.onerror=f.bind(null,l.onerror),l.onload=f.bind(null,l.onload),d&&document.head.appendChild(l)}},n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),n.j=2277,(()=>{var e;n.g.importScripts&&(e=n.g.location+"");var r=n.g.document;if(!e&&r&&(r.currentScript&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");if(t.length)for(var i=t.length-1;i>-1&&(!e||!/^http(s?):/.test(e));)e=t[i--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),n.p=e})(),(()=>{n.b=document.baseURI||self.location.href;var e={2277:0};n.f.j=(r,t)=>{var i=n.o(e,r)?e[r]:void 0;if(0!==i)if(i)t.push(i[2]);else{var o=new Promise(((t,o)=>i=e[r]=[t,o]));t.push(i[2]=o);var a=n.p+n.u(r),l=new Error;n.l(a,(t=>{if(n.o(e,r)&&(0!==(i=e[r])&&(e[r]=void 0),i)){var o=t&&("load"===t.type?"missing":t.type),a=t&&t.target&&t.target.src;l.message="Loading chunk "+r+" failed.\n("+o+": "+a+")",l.name="ChunkLoadError",l.type=o,l.request=a,i[1](l)}}),"chunk-"+r,r)}},n.O.j=r=>0===e[r];var r=(r,t)=>{var i,o,a=t[0],l=t[1],d=t[2],c=0;if(a.some((r=>0!==e[r]))){for(i in l)n.o(l,i)&&(n.m[i]=l[i]);if(d)var s=d(n)}for(r&&r(t);c<a.length;c++)o=a[c],n.o(e,o)&&e[o]&&e[o][0](),e[o]=0;return n.O(s)},t=self.webpackChunknextcloud=self.webpackChunknextcloud||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),n.nc=void 0;var a=n.O(void 0,[4208],(()=>n(66747)));a=n.O(a)})();
|
||||
//# sourceMappingURL=files-search.js.map?v=cfd84c76c0213e1c45a5
|
||||
(()=>{"use strict";var e,r,t,i={66747:(e,r,t)=>{var i=t(61338),o=t(85168),n=t(63814),a=t(53334);const l=(0,t(35947).YK)().setApp("files").detectUser().build();document.addEventListener("DOMContentLoaded",(function(){const e=window.OCA;e.UnifiedSearch&&(l.info("Initializing unified search plugin: folder search from files app"),e.UnifiedSearch.registerFilterAction({id:"files",appId:"files",label:(0,a.Tl)("files","In folder"),icon:(0,n.d0)("files","app.svg"),callback:()=>{(0,o.a1)("Pick plain text files").addMimeTypeFilter("httpd/unix-directory").allowDirectories(!0).addButton({label:"Pick",callback:e=>{l.info("Folder picked",{folder:e[0]});const r=e[0];(0,i.Ic)("nextcloud:unified-search:add-filter",{id:"files",payload:r,filterUpdateText:(0,a.Tl)("files","Search in folder: {folder}",{folder:r.basename}),filterParams:{path:r.path}})}}).build().pick()}}))}))}},o={};function n(e){var r=o[e];if(void 0!==r)return r.exports;var t=o[e]={id:e,loaded:!1,exports:{}};return i[e].call(t.exports,t,t.exports,n),t.loaded=!0,t.exports}n.m=i,e=[],n.O=(r,t,i,o)=>{if(!t){var a=1/0;for(s=0;s<e.length;s++){t=e[s][0],i=e[s][1],o=e[s][2];for(var l=!0,d=0;d<t.length;d++)(!1&o||a>=o)&&Object.keys(n.O).every((e=>n.O[e](t[d])))?t.splice(d--,1):(l=!1,o<a&&(a=o));if(l){e.splice(s--,1);var c=i();void 0!==c&&(r=c)}}return r}o=o||0;for(var s=e.length;s>0&&e[s-1][2]>o;s--)e[s]=e[s-1];e[s]=[t,i,o]},n.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return n.d(r,{a:r}),r},n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.f={},n.e=e=>Promise.all(Object.keys(n.f).reduce(((r,t)=>(n.f[t](e,r),r)),[])),n.u=e=>e+"-"+e+".js?v="+{4254:"5c2324570f66dff0c8a1",9480:"f3ebcf41e93bbd8cd678"}[e],n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="nextcloud:",n.l=(e,i,o,a)=>{if(r[e])r[e].push(i);else{var l,d;if(void 0!==o)for(var c=document.getElementsByTagName("script"),s=0;s<c.length;s++){var f=c[s];if(f.getAttribute("src")==e||f.getAttribute("data-webpack")==t+o){l=f;break}}l||(d=!0,(l=document.createElement("script")).charset="utf-8",l.timeout=120,n.nc&&l.setAttribute("nonce",n.nc),l.setAttribute("data-webpack",t+o),l.src=e),r[e]=[i];var u=(t,i)=>{l.onerror=l.onload=null,clearTimeout(p);var o=r[e];if(delete r[e],l.parentNode&&l.parentNode.removeChild(l),o&&o.forEach((e=>e(i))),t)return t(i)},p=setTimeout(u.bind(null,void 0,{type:"timeout",target:l}),12e4);l.onerror=u.bind(null,l.onerror),l.onload=u.bind(null,l.onload),d&&document.head.appendChild(l)}},n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),n.j=2277,(()=>{var e;n.g.importScripts&&(e=n.g.location+"");var r=n.g.document;if(!e&&r&&(r.currentScript&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");if(t.length)for(var i=t.length-1;i>-1&&(!e||!/^http(s?):/.test(e));)e=t[i--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),n.p=e})(),(()=>{n.b=document.baseURI||self.location.href;var e={2277:0};n.f.j=(r,t)=>{var i=n.o(e,r)?e[r]:void 0;if(0!==i)if(i)t.push(i[2]);else{var o=new Promise(((t,o)=>i=e[r]=[t,o]));t.push(i[2]=o);var a=n.p+n.u(r),l=new Error;n.l(a,(t=>{if(n.o(e,r)&&(0!==(i=e[r])&&(e[r]=void 0),i)){var o=t&&("load"===t.type?"missing":t.type),a=t&&t.target&&t.target.src;l.message="Loading chunk "+r+" failed.\n("+o+": "+a+")",l.name="ChunkLoadError",l.type=o,l.request=a,i[1](l)}}),"chunk-"+r,r)}},n.O.j=r=>0===e[r];var r=(r,t)=>{var i,o,a=t[0],l=t[1],d=t[2],c=0;if(a.some((r=>0!==e[r]))){for(i in l)n.o(l,i)&&(n.m[i]=l[i]);if(d)var s=d(n)}for(r&&r(t);c<a.length;c++)o=a[c],n.o(e,o)&&e[o]&&e[o][0](),e[o]=0;return n.O(s)},t=self.webpackChunknextcloud=self.webpackChunknextcloud||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),n.nc=void 0;var a=n.O(void 0,[4208],(()=>n(66747)));a=n.O(a)})();
|
||||
//# sourceMappingURL=files-search.js.map?v=5a3591bc322b26e3d654
|
||||
2
dist/files-search.js.map
vendored
2
dist/files-search.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files_external-init.js
vendored
4
dist/files_external-init.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_external-init.js.map
vendored
2
dist/files_external-init.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files_sharing-files_sharing_tab.js
vendored
4
dist/files_sharing-files_sharing_tab.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-files_sharing_tab.js.map
vendored
2
dist/files_sharing-files_sharing_tab.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files_sharing-init.js
vendored
4
dist/files_sharing-init.js
vendored
File diff suppressed because one or more lines are too long
4
dist/files_sharing-init.js.license
vendored
4
dist/files_sharing-init.js.license
vendored
|
|
@ -11,6 +11,7 @@ SPDX-FileCopyrightText: assert developers
|
|||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: T. Jameson Little <t.jameson.little@gmail.com>
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Roeland Jago Douma
|
||||
SPDX-FileCopyrightText: Raynos <raynos2@gmail.com>
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Matt Zabriskie
|
||||
|
|
@ -39,6 +40,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/axios
|
||||
- version: 2.5.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/capabilities
|
||||
- version: 1.2.0
|
||||
- license: GPL-3.0-or-later
|
||||
- semver
|
||||
- version: 7.6.2
|
||||
- license: ISC
|
||||
|
|
|
|||
2
dist/files_sharing-init.js.map
vendored
2
dist/files_sharing-init.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/files_sharing-personal-settings.js
vendored
4
dist/files_sharing-personal-settings.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-personal-settings.js.map
vendored
2
dist/files_sharing-personal-settings.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-public-file-request.js
vendored
Normal file
2
dist/files_sharing-public-file-request.js
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(()=>{"use strict";var e,t,r,o={38943:(e,t,r)=>{var o=r(85168),n=r(85471);const a=(0,r(35947).YK)().setApp("files_sharing").detectUser().build(),i=localStorage.getItem("nick"),l=localStorage.getItem("publicAuthPromptShown");i&&l?a.debug("Public auth prompt already shown. Current nickname is '".concat(i,"'")):(0,o.Ss)((0,n.$V)((()=>Promise.all([r.e(4208),r.e(4589)]).then(r.bind(r,4589)))),{},(()=>localStorage.setItem("publicAuthPromptShown","true")))}},n={};function a(e){var t=n[e];if(void 0!==t)return t.exports;var r=n[e]={id:e,loaded:!1,exports:{}};return o[e].call(r.exports,r,r.exports,a),r.loaded=!0,r.exports}a.m=o,e=[],a.O=(t,r,o,n)=>{if(!r){var i=1/0;for(s=0;s<e.length;s++){r=e[s][0],o=e[s][1],n=e[s][2];for(var l=!0,c=0;c<r.length;c++)(!1&n||i>=n)&&Object.keys(a.O).every((e=>a.O[e](r[c])))?r.splice(c--,1):(l=!1,n<i&&(i=n));if(l){e.splice(s--,1);var u=o();void 0!==u&&(t=u)}}return t}n=n||0;for(var s=e.length;s>0&&e[s-1][2]>n;s--)e[s]=e[s-1];e[s]=[r,o,n]},a.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var r in t)a.o(t,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},a.f={},a.e=e=>Promise.all(Object.keys(a.f).reduce(((t,r)=>(a.f[r](e,t),t)),[])),a.u=e=>e+"-"+e+".js?v="+{4254:"5c2324570f66dff0c8a1",4589:"f528d9600121156d9e2c",9480:"f3ebcf41e93bbd8cd678"}[e],a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),t={},r="nextcloud:",a.l=(e,o,n,i)=>{if(t[e])t[e].push(o);else{var l,c;if(void 0!==n)for(var u=document.getElementsByTagName("script"),s=0;s<u.length;s++){var d=u[s];if(d.getAttribute("src")==e||d.getAttribute("data-webpack")==r+n){l=d;break}}l||(c=!0,(l=document.createElement("script")).charset="utf-8",l.timeout=120,a.nc&&l.setAttribute("nonce",a.nc),l.setAttribute("data-webpack",r+n),l.src=e),t[e]=[o];var p=(r,o)=>{l.onerror=l.onload=null,clearTimeout(f);var n=t[e];if(delete t[e],l.parentNode&&l.parentNode.removeChild(l),n&&n.forEach((e=>e(o))),r)return r(o)},f=setTimeout(p.bind(null,void 0,{type:"timeout",target:l}),12e4);l.onerror=p.bind(null,l.onerror),l.onload=p.bind(null,l.onload),c&&document.head.appendChild(l)}},a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),a.j=9804,(()=>{var e;a.g.importScripts&&(e=a.g.location+"");var t=a.g.document;if(!e&&t&&(t.currentScript&&(e=t.currentScript.src),!e)){var r=t.getElementsByTagName("script");if(r.length)for(var o=r.length-1;o>-1&&(!e||!/^http(s?):/.test(e));)e=r[o--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),a.p=e})(),(()=>{a.b=document.baseURI||self.location.href;var e={9804:0};a.f.j=(t,r)=>{var o=a.o(e,t)?e[t]:void 0;if(0!==o)if(o)r.push(o[2]);else{var n=new Promise(((r,n)=>o=e[t]=[r,n]));r.push(o[2]=n);var i=a.p+a.u(t),l=new Error;a.l(i,(r=>{if(a.o(e,t)&&(0!==(o=e[t])&&(e[t]=void 0),o)){var n=r&&("load"===r.type?"missing":r.type),i=r&&r.target&&r.target.src;l.message="Loading chunk "+t+" failed.\n("+n+": "+i+")",l.name="ChunkLoadError",l.type=n,l.request=i,o[1](l)}}),"chunk-"+t,t)}},a.O.j=t=>0===e[t];var t=(t,r)=>{var o,n,i=r[0],l=r[1],c=r[2],u=0;if(i.some((t=>0!==e[t]))){for(o in l)a.o(l,o)&&(a.m[o]=l[o]);if(c)var s=c(a)}for(t&&t(r);u<i.length;u++)n=i[u],a.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return a.O(s)},r=self.webpackChunknextcloud=self.webpackChunknextcloud||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})(),a.nc=void 0;var i=a.O(void 0,[4208],(()=>a(38943)));i=a.O(i)})();
|
||||
//# sourceMappingURL=files_sharing-public-file-request.js.map?v=4ee42b64953b65a29438
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
SPDX-License-Identifier: MIT
|
||||
SPDX-License-Identifier: ISC
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
|
||||
SPDX-FileCopyrightText: inherits developers
|
||||
|
|
@ -9,12 +8,9 @@ SPDX-FileCopyrightText: escape-html developers
|
|||
SPDX-FileCopyrightText: assert developers
|
||||
SPDX-FileCopyrightText: Varun A P
|
||||
SPDX-FileCopyrightText: Tobias Koppers @sokra
|
||||
SPDX-FileCopyrightText: T. Jameson Little <t.jameson.little@gmail.com>
|
||||
SPDX-FileCopyrightText: Roman Shtylman <shtylman@gmail.com>
|
||||
SPDX-FileCopyrightText: Roeland Jago Douma
|
||||
SPDX-FileCopyrightText: Raynos <raynos2@gmail.com>
|
||||
SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
|
||||
SPDX-FileCopyrightText: Matt Zabriskie
|
||||
SPDX-FileCopyrightText: Joyent
|
||||
SPDX-FileCopyrightText: Jordan Harband <ljharb@gmail.com>
|
||||
SPDX-FileCopyrightText: Jordan Harband
|
||||
|
|
@ -22,7 +18,6 @@ SPDX-FileCopyrightText: John-David Dalton <john.david.dalton@gmail.com> (http://
|
|||
SPDX-FileCopyrightText: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
|
||||
SPDX-FileCopyrightText: Guillaume Chau <guillaume.b.chau@gmail.com>
|
||||
SPDX-FileCopyrightText: GitHub Inc.
|
||||
SPDX-FileCopyrightText: Feross Aboukhadijeh
|
||||
SPDX-FileCopyrightText: Evan You
|
||||
SPDX-FileCopyrightText: Dr.-Ing. Mario Heiderich, Cure53 <mario@cure53.de> (https://cure53.de/)
|
||||
SPDX-FileCopyrightText: David Clark
|
||||
|
|
@ -36,12 +31,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/auth
|
||||
- version: 2.3.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/axios
|
||||
- version: 2.5.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/capabilities
|
||||
- version: 1.2.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/dialogs
|
||||
- version: 5.3.5
|
||||
- license: AGPL-3.0-or-later
|
||||
|
|
@ -51,12 +40,12 @@ This file is generated from multiple sources. Included packages:
|
|||
- @nextcloud/event-bus
|
||||
- version: 3.3.1
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/initial-state
|
||||
- version: 2.2.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/l10n
|
||||
- version: 3.1.0
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/logger
|
||||
- version: 3.0.2
|
||||
- license: GPL-3.0-or-later
|
||||
- @nextcloud/router
|
||||
- version: 3.0.1
|
||||
- license: GPL-3.0-or-later
|
||||
|
|
@ -75,15 +64,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- available-typed-arrays
|
||||
- version: 1.0.7
|
||||
- license: MIT
|
||||
- axios
|
||||
- version: 1.7.2
|
||||
- license: MIT
|
||||
- base64-js
|
||||
- version: 1.5.1
|
||||
- license: MIT
|
||||
- buffer
|
||||
- version: 6.0.3
|
||||
- license: MIT
|
||||
- call-bind
|
||||
- version: 1.0.7
|
||||
- license: MIT
|
||||
|
|
@ -144,9 +124,6 @@ This file is generated from multiple sources. Included packages:
|
|||
- hasown
|
||||
- version: 2.0.2
|
||||
- license: MIT
|
||||
- ieee754
|
||||
- version: 1.2.1
|
||||
- license: BSD-3-Clause
|
||||
- inherits
|
||||
- version: 2.0.4
|
||||
- license: ISC
|
||||
|
|
@ -213,6 +190,9 @@ This file is generated from multiple sources. Included packages:
|
|||
- vue
|
||||
- version: 2.7.16
|
||||
- license: MIT
|
||||
- webpack
|
||||
- version: 5.93.0
|
||||
- license: MIT
|
||||
- which-typed-array
|
||||
- version: 1.1.15
|
||||
- license: MIT
|
||||
1
dist/files_sharing-public-file-request.js.map
vendored
Normal file
1
dist/files_sharing-public-file-request.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/files_sharing-public-file-request.js.map.license
vendored
Symbolic link
1
dist/files_sharing-public-file-request.js.map.license
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
files_sharing-public-file-request.js.license
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
dist/weather_status-weather-status.js
vendored
4
dist/weather_status-weather-status.js
vendored
File diff suppressed because one or more lines are too long
2
dist/weather_status-weather-status.js.map
vendored
2
dist/weather_status-weather-status.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -54,6 +54,7 @@ module.exports = {
|
|||
init: path.join(__dirname, 'apps/files_sharing/src', 'init.ts'),
|
||||
main: path.join(__dirname, 'apps/files_sharing/src', 'main.ts'),
|
||||
'personal-settings': path.join(__dirname, 'apps/files_sharing/src', 'personal-settings.js'),
|
||||
'public-file-request': path.join(__dirname, 'apps/files_sharing/src', 'public-file-request.ts'),
|
||||
},
|
||||
files_trashbin: {
|
||||
init: path.join(__dirname, 'apps/files_trashbin/src', 'files-init.ts'),
|
||||
|
|
|
|||
Loading…
Reference in a new issue