refactor(IMenuAction): Make public menu actions use the new Vue UI

This removes custom rendering code an replaces it with the declarative menu actions.
Also adjust the template to allow the Vue UI to mount.
Custom entries still are possible.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
pull/47568/head
Ferdinand Thiessen 2 years ago
parent 7b6c78c81d
commit 4d2556d4cf
No known key found for this signature in database
GPG Key ID: 45FAE7268762B400
  1. 8
      apps/files_sharing/lib/DefaultPublicShareTemplateProvider.php
  2. 6
      apps/files_sharing/tests/Controller/ShareControllerTest.php
  3. 42
      core/templates/layout.public.php
  4. 19
      lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php
  5. 7
      lib/public/AppFramework/Http/Template/IMenuAction.php
  6. 22
      lib/public/AppFramework/Http/Template/LinkMenuAction.php
  7. 47
      lib/public/AppFramework/Http/Template/PublicTemplateResponse.php
  8. 28
      lib/public/AppFramework/Http/Template/SimpleMenuAction.php
  9. 2
      tests/lib/AppFramework/Http/PublicTemplateResponseTest.php

@ -240,10 +240,8 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
if ($isNoneFileDropFolder && !$share->getHideDownload()) {
Util::addScript('files_sharing', 'public_note');
$downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
$downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 0, $shareTmpl['fileSize']);
$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 0, $shareTmpl['fileSize']);
$directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
// TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
$externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your %s', [$this->defaults->getProductName()]), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);
@ -251,10 +249,8 @@ class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider
$responseComposer = [];
if ($shareIsFolder) {
$responseComposer[] = $downloadAllWhite;
$responseComposer[] = $downloadAll;
} else {
$responseComposer[] = $downloadWhite;
$responseComposer[] = $download;
}
$responseComposer[] = $directLink;

@ -363,8 +363,7 @@ class ShareControllerTest extends \Test\TestCase {
$expectedResponse->setHeaderTitle($sharedTmplParams['filename']);
$expectedResponse->setHeaderDetails('shared by ' . $sharedTmplParams['shareOwner']);
$expectedResponse->setHeaderActions([
new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $sharedTmplParams['downloadURL'], 0),
new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $sharedTmplParams['downloadURL'], 10, $sharedTmplParams['fileSize']),
new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $sharedTmplParams['downloadURL'], 0, $sharedTmplParams['fileSize']),
new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $sharedTmplParams['previewURL']),
new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $sharedTmplParams['owner'], $sharedTmplParams['shareOwner'], $sharedTmplParams['filename']),
]);
@ -525,8 +524,7 @@ class ShareControllerTest extends \Test\TestCase {
$expectedResponse->setHeaderTitle($sharedTmplParams['filename']);
$expectedResponse->setHeaderDetails('');
$expectedResponse->setHeaderActions([
new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $sharedTmplParams['downloadURL'], 0),
new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $sharedTmplParams['downloadURL'], 10, $sharedTmplParams['fileSize']),
new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $sharedTmplParams['downloadURL'], 0, $sharedTmplParams['fileSize']),
new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $sharedTmplParams['previewURL']),
new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $sharedTmplParams['owner'], $sharedTmplParams['shareOwner'], $sharedTmplParams['filename']),
]);

@ -73,44 +73,18 @@ p($theme->getTitle());
</div>
<div class="header-end">
<?php
/** @var \OCP\AppFramework\Http\Template\PublicTemplateResponse $template */
if (isset($template) && $template->getActionCount() !== 0) {
$primary = $template->getPrimaryAction();
$others = $template->getOtherActions(); ?>
<span id="header-primary-action" class="<?php if ($template->getActionCount() === 1) {
p($primary->getIcon());
} ?>">
<a href="<?php p($primary->getLink()); ?>" class="primary button">
<span><?php p($primary->getLabel()) ?></span>
</a>
</span>
<?php if ($template->getActionCount() > 1) { ?>
<div id="header-secondary-action">
<button id="header-actions-toggle" class="menutoggle icon-more-white"></button>
<div id="header-actions-menu" class="popovermenu menu">
<ul>
<?php
/** @var \OCP\AppFramework\Http\Template\IMenuAction $action */
foreach ($others as $action) {
print_unescaped($action->render());
}
?>
</ul>
</div>
</div>
<?php } ?>
<?php
} ?>
<div id="public-page-menu"></div>
</div>
</header>
<main id="content" class="app-<?php p($_['appid']) ?>">
<h1 class="hidden-visually">
<?php if (isset($template) && $template->getHeaderTitle() !== '') { ?>
<?php p($template->getHeaderTitle()); ?>
<?php } else { ?>
<?php p($theme->getName()); ?>
<?php } ?>
<?php
if (isset($template) && $template->getHeaderTitle() !== '') {
p($template->getHeaderTitle());
} else {
p($theme->getName());
} ?>
</h1>
<?php print_unescaped($_['content']); ?>
</main>

@ -5,8 +5,6 @@
*/
namespace OCP\AppFramework\Http\Template;
use OCP\Util;
/**
* Class LinkMenuAction
*
@ -38,21 +36,4 @@ class ExternalShareMenuAction extends SimpleMenuAction {
$this->displayname = $displayname;
$this->shareName = $shareName;
}
/**
* @since 14.0.0
*/
public function render(): string {
return '<li>' .
' <button id="save-external-share" class="icon ' . Util::sanitizeHTML($this->getIcon()) . '" data-protected="false" data-owner-display-name="' . Util::sanitizeHTML($this->displayname) . '" data-owner="' . Util::sanitizeHTML($this->owner) . '" data-name="' . Util::sanitizeHTML($this->shareName) . '">' . Util::sanitizeHTML($this->getLabel()) . '</button>' .
'</li>' .
'<li id="external-share-menu-item" class="hidden">' .
' <span class="menuitem">' .
' <form class="save-form" action="#">' .
' <input type="text" id="remote_address" placeholder="user@yourNextcloud.org">' .
' <input type="submit" value=" " id="save-button-confirm" class="icon-confirm" disabled="disabled"></button>' .
' </form>' .
' </span>' .
'</li>';
}
}

@ -18,12 +18,16 @@ interface IMenuAction {
public function getId(): string;
/**
* The translated label of the menu item.
*
* @since 14.0.0
* @return string
*/
public function getLabel(): string;
/**
* The link this menu item points to.
*
* @since 14.0.0
* @return string
*/
@ -36,6 +40,9 @@ interface IMenuAction {
public function getPriority(): int;
/**
* Custom render function.
* The returned HTML will be wrapped within a listitem element (`<li>...</li>`).
*
* @since 14.0.0
* @return string
*/

@ -5,8 +5,6 @@
*/
namespace OCP\AppFramework\Http\Template;
use OCP\Util;
/**
* Class LinkMenuAction
*
@ -22,24 +20,6 @@ class LinkMenuAction extends SimpleMenuAction {
* @since 14.0.0
*/
public function __construct(string $label, string $icon, string $link) {
parent::__construct('directLink-container', $label, $icon, $link);
}
/**
* @return string
* @since 14.0.0
*/
public function render(): string {
return '<li>' .
'<a id="directLink-container">' .
'<span class="icon ' . Util::sanitizeHTML($this->getIcon()) . '"></span>' .
'<label for="directLink">' . Util::sanitizeHTML($this->getLabel()) . '</label>' .
'</a>' .
'</li>' .
'<li>' .
'<span class="menuitem">' .
'<input id="directLink" type="text" readonly="" value="' . Util::sanitizeHTML($this->getLink()) . '">' .
'</span>' .
'</li>';
parent::__construct('directLink', $label, $icon, $link);
}
}

@ -8,6 +8,7 @@ namespace OCP\AppFramework\Http\Template;
use InvalidArgumentException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IInitialStateService;
/**
* Class PublicTemplateResponse
@ -20,6 +21,7 @@ use OCP\AppFramework\Http\TemplateResponse;
class PublicTemplateResponse extends TemplateResponse {
private $headerTitle = '';
private $headerDetails = '';
/** @var IMenuAction[] */
private $headerActions = [];
private $footerVisible = true;
@ -33,9 +35,38 @@ class PublicTemplateResponse extends TemplateResponse {
* @param H $headers
* @since 14.0.0
*/
public function __construct(string $appName, string $templateName, array $params = [], $status = Http::STATUS_OK, array $headers = []) {
public function __construct(
string $appName,
string $templateName,
array $params = [],
$status = Http::STATUS_OK,
array $headers = [],
) {
parent::__construct($appName, $templateName, $params, 'public', $status, $headers);
\OC_Util::addScript('core', 'public/publicpage');
\OCP\Util::addScript('core', 'public-page-menu');
$state = \OCP\Server::get(IInitialStateService::class);
$state->provideLazyInitialState('core', 'public-page-menu', function () {
$response = [];
foreach ($this->headerActions as $action) {
// First try in it is a custom action that provides rendered HTML
$rendered = $action->render();
if ($rendered === '') {
// If simple action, add the response data
if ($action instanceof SimpleMenuAction) {
$response[] = $action->getData();
}
} else {
// custom action so add the rendered output
$response[] = [
'id' => $action->getId(),
'label' => $action->getLabel(),
'html' => $rendered,
];
}
}
return $response;
});
}
/**
@ -128,16 +159,4 @@ class PublicTemplateResponse extends TemplateResponse {
public function getFooterVisible(): bool {
return $this->footerVisible;
}
/**
* @return string
* @since 14.0.0
*/
public function render(): string {
$params = array_merge($this->getParams(), [
'template' => $this,
]);
$this->setParams($params);
return parent::render();
}
}

@ -5,8 +5,6 @@
*/
namespace OCP\AppFramework\Http\Template;
use OCP\Util;
/**
* Class SimpleMenuAction
*
@ -68,6 +66,8 @@ class SimpleMenuAction implements IMenuAction {
}
/**
* The icon CSS class to use.
*
* @return string
* @since 14.0.0
*/
@ -92,14 +92,28 @@ class SimpleMenuAction implements IMenuAction {
}
/**
* Custom render function.
* The returned HTML must be wrapped within a listitem (`<li>...</li>`).
* * If an empty string is returned, the default design is used (based on the label and link specified).
* @return string
* @since 14.0.0
*/
public function render(): string {
$detailContent = ($this->detail !== '') ? '&nbsp;<span class="download-size">(' . Util::sanitizeHTML($this->detail) . ')</span>' : '';
return sprintf(
'<li id="%s"><a href="%s"><span class="icon %s"></span>%s %s</a></li>',
Util::sanitizeHTML($this->id), Util::sanitizeHTML($this->link), Util::sanitizeHTML($this->icon), Util::sanitizeHTML($this->label), $detailContent
);
return '';
}
/**
* Return JSON data to let the frontend render the menu entry.
* @return array{id: string, label: string, href: string, icon: string, details: string|null}
* @since 31.0.0
*/
public function getData(): array {
return [
'id' => $this->id,
'label' => $this->label,
'href' => $this->link,
'icon' => $this->icon,
'details' => $this->detail,
];
}
}

@ -14,7 +14,6 @@ use Test\TestCase;
class PublicTemplateResponseTest extends TestCase {
public function testSetParamsConstructor() {
$template = new PublicTemplateResponse('app', 'home', ['key' => 'value']);
$this->assertContains('core/js/public/publicpage', \OC_Util::$scripts);
$this->assertEquals(['key' => 'value'], $template->getParams());
}
@ -57,7 +56,6 @@ class PublicTemplateResponseTest extends TestCase {
public function testGetRenderAs() {
$template = new PublicTemplateResponse('app', 'home', ['key' => 'value']);
$this->assertContains('core/js/public/publicpage', \OC_Util::$scripts);
$this->assertEquals(['key' => 'value'], $template->getParams());
$this->assertEquals('public', $template->getRenderAs());
}

Loading…
Cancel
Save