Skip to content

Commit

Permalink
Layout Editor: exchange tab should not be visible if the connector is…
Browse files Browse the repository at this point in the history
… disabled (#2734)

* Connector: add a template provider list route, event and handle in exchange connector.
* Editor: Add template connector dynamically

fixes xibosignage/xibo#3497

---------

Co-authored-by: maurofmferrao <maurofmferrao@gmail.com>
  • Loading branch information
dasgarner and maurofmferrao authored Sep 12, 2024
1 parent ce03c27 commit 622b199
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 37 deletions.
23 changes: 23 additions & 0 deletions lib/Connector/XiboExchangeConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use Xibo\Entity\SearchResult;
use Xibo\Event\TemplateProviderEvent;
use Xibo\Event\TemplateProviderImportEvent;
use Xibo\Event\TemplateProviderListEvent;
use Xibo\Support\Sanitizer\SanitizerInterface;

/**
Expand All @@ -50,6 +51,7 @@ public function registerWithDispatcher(EventDispatcherInterface $dispatcher): Co
{
$dispatcher->addListener('connector.provider.template', [$this, 'onTemplateProvider']);
$dispatcher->addListener('connector.provider.template.import', [$this, 'onTemplateProviderImport']);
$dispatcher->addListener('connector.provider.template.list', [$this, 'onTemplateList']);
return $this;
}

Expand Down Expand Up @@ -239,4 +241,25 @@ private function createSearchResult($template) : SearchResult
$searchResult->download = $template->downloadUrl;
return $searchResult;
}

/**
* Add this connector to the list of providers.
* @param \Xibo\Event\TemplateProviderListEvent $event
* @return void
*/
public function onTemplateList(TemplateProviderListEvent $event): void
{
$this->getLogger()->debug('onTemplateList:event');

$providerDetails = new ProviderDetails();
$providerDetails->id = $this->getSourceName();
$providerDetails->link = 'https://xibosignage.com';
$providerDetails->logoUrl = $this->getThumbnail();
$providerDetails->iconUrl = 'exchange-alt';
$providerDetails->message = $this->getTitle();
$providerDetails->backgroundColor = '';
$providerDetails->mediaTypes = ['xlf'];

$event->addProvider($providerDetails);
}
}
19 changes: 19 additions & 0 deletions lib/Controller/Template.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
namespace Xibo\Controller;

use Parsedown;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Response as Response;
use Slim\Http\ServerRequest as Request;
use Xibo\Entity\SearchResult;
use Xibo\Entity\SearchResults;
use Xibo\Event\TemplateProviderEvent;
use Xibo\Event\TemplateProviderListEvent;
use Xibo\Factory\LayoutFactory;
use Xibo\Factory\TagFactory;
use Xibo\Support\Exception\AccessDeniedException;
Expand Down Expand Up @@ -767,4 +769,21 @@ public function editForm(Request $request, Response $response, $id)

return $this->render($request, $response);
}

/**
* Get list of Template providers with their details.
*
* @param Request $request
* @param Response $response
* @return Response|ResponseInterface
*/
public function providersList(Request $request, Response $response): Response|\Psr\Http\Message\ResponseInterface
{
$event = new TemplateProviderListEvent();
$this->getDispatcher()->dispatch($event, $event->getName());

$providers = $event->getProviders();

return $response->withJson($providers);
}
}
60 changes: 60 additions & 0 deletions lib/Event/TemplateProviderListEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/*
* Copyright (C) 2024 Xibo Signage Ltd
*
* Xibo - Digital Signage - https://xibosignage.com
*
* This file is part of Xibo.
*
* Xibo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Xibo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Xibo. If not, see <http://www.gnu.org/licenses/>.
*/

namespace Xibo\Event;

use Xibo\Connector\ProviderDetails;

/**
* Get a list of template providers
*/
class TemplateProviderListEvent extends Event
{
protected static $NAME = 'connector.provider.template.list';
/**
* @var array
*/
private mixed $providers;

public function __construct($providers = [])
{
$this->providers = $providers;
}

/**
* @param ProviderDetails $provider
* @return TemplateProviderListEvent
*/
public function addProvider(ProviderDetails $provider): TemplateProviderListEvent
{
$this->providers[] = $provider;
return $this;
}

/**
* @return ProviderDetails[]
*/
public function getProviders(): array
{
return $this->providers;
}
}
2 changes: 2 additions & 0 deletions lib/routes-web.php
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@
//
// template
//
$app->get('/template/connector/list', ['\Xibo\Controller\Template','providersList'])
->setName('template.search.providers');
$app->get('/template/search', ['\Xibo\Controller\Template', 'search'])->setName('template.search.all');
$app->get('/template/view', ['\Xibo\Controller\Template','displayPage'])
->addMiddleware(new FeatureAuth($app->getContainer(), ['template.view']))
Expand Down
106 changes: 74 additions & 32 deletions ui/src/editor-core/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -612,29 +612,6 @@ Toolbar.prototype.init = function({isPlaylist = false} = {}) {
state: '',
itemCount: 0,
},
{
name: 'layout_exchange',
disabled: isPlaylist,
itemName: toolbarTrans.menuItems.layoutExchangeName,
itemIcon: 'exchange-alt', // TODO: Change icon!
itemTitle: toolbarTrans.menuItems.layoutExchangeTitle,
contentType: 'layout_exchange',
filters: {
name: {
value: '',
key: 'template',
},
provider: {
value: 'remote',
locked: true,
},
orientation: {
value: '',
},
},
state: '',
itemCount: 0,
},
];

// Menu items
Expand Down Expand Up @@ -666,7 +643,71 @@ Toolbar.prototype.init = function({isPlaylist = false} = {}) {
this.moduleListOtherTypes = moduleListOtherTypes;
this.moduleGroups = moduleGroups;

// Get providers
// Get template providers
$.ajax(urlsForApi.template.getProviders).done(function(res) {
// Stop if not available
if (Object.keys(self).length === 0) {
return;
}

if (
Array.isArray(res)
) {
res.forEach((provider) => {
// Add provider to menu items
self.menuItems.push(
{
name: provider.id,
disabled: isPlaylist,
itemName: provider.message,
// link: provider.link,
itemTitle: toolbarTrans.menuItems
.layoutExchangeTitle.replace('%obj%', provider.message),
itemIcon: provider.iconUrl,
contentType: 'template_exchange',
filters: {
name: {
value: '',
key: 'template',
},
provider: {
value: 'remote',
locked: true,
},
orientation: {
value: '',
},
},
state: '',
itemCount: 0,
});
});
} else {
// Login Form needed?
if (res.login) {
window.location.href = window.location.href;
location.reload();
} else {
// Just an error we dont know about
if (res.message == undefined) {
console.error(res);
} else {
console.error(res.message);
}
}
}

// Render
self.render();
}).catch(function(jqXHR, textStatus, errorThrown) {
console.error(jqXHR, textStatus, errorThrown);
console.error(errorMessagesTrans.getProvidersFailed);

// Render
self.render();
});

// Get media providers
$.ajax(urlsForApi.media.getProviders).done(function(res) {
// Stop if not available
if (Object.keys(self).length === 0) {
Expand Down Expand Up @@ -1326,7 +1367,7 @@ Toolbar.prototype.createContent = function(
this.elementsContentCreateWindow(menu, savePrefs);
} else if (
content.contentType === 'layout_templates' ||
content.contentType === 'layout_exchange'
content.contentType === 'template_exchange'
) {
this.layoutTemplatesContentCreateWindow(menu);
} else if (content.contentType === 'playlists') {
Expand Down Expand Up @@ -2413,7 +2454,7 @@ Toolbar.prototype.elementsContentCreateWindow = function(
Toolbar.prototype.layoutTemplatesContentCreateWindow = function(menu) {
const self = this;
const app = this.parent;
const tabContentName = this.menuItems[menu].name;
const tabContentType = this.menuItems[menu].contentType;

// Deselect previous selections
self.deselectCardsAndDropZones();
Expand All @@ -2424,18 +2465,19 @@ Toolbar.prototype.layoutTemplatesContentCreateWindow = function(menu) {
filters: this.menuItems[menu].filters,
trans: toolbarTrans,
formClass: 'layout_tempates-search-form',
headerMessage: (tabContentName == 'layout_exchange') ?
toolbarTrans.layoutExchangeTemplatesMessage :
headerMessage: (tabContentType == 'template_exchange') ?
toolbarTrans.layoutExchangeTemplatesMessage
.replace('%obj%', this.menuItems[menu].itemName) :
toolbarTrans.layoutTemplatesMessage,
});

// Clear temp data
app.common.clearContainer(
self.DOMObject.find('#' + tabContentName + '-container-' + menu),
self.DOMObject.find('#' + tabContentType + '-container-' + menu),
);

// Append template to the search main div
self.DOMObject.find('#' + tabContentName + '-container-' + menu).html(html);
self.DOMObject.find('#' + tabContentType + '-container-' + menu).html(html);

// Load content
this.layoutTemplatesContentPopulate(menu);
Expand Down Expand Up @@ -2473,9 +2515,9 @@ Toolbar.prototype.playlistsContentCreateWindow = function(menu) {
Toolbar.prototype.layoutTemplatesContentPopulate = function(menu) {
const app = this.parent;
const self = this;
const tabContentName = this.menuItems[menu].name;
const tabContentType = this.menuItems[menu].contentType;
const $container = self.DOMObject.find(
'#' + tabContentName + '-container-' + menu,
'#' + tabContentType + '-container-' + menu,
);
const $content = self.DOMObject.find('#media-content-' + menu);
const $searchForm = $container.parent().find('.toolbar-search-form');
Expand Down
2 changes: 1 addition & 1 deletion ui/src/style/toolbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@
}
}

&.toolbar-layout_templates-pane, &.toolbar-layout_exchange-pane {
&.toolbar-layout_templates-pane, &.toolbar-template_exchange-pane {
.toolbar-card:not(.has-thumb):hover .media-title {
overflow: visible;
white-space: normal;
Expand Down
2 changes: 1 addition & 1 deletion ui/src/templates/toolbar-content.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div id="content-{{menuIndex}}"
class="toolbar-pane toolbar-{{name}}-pane {{state}} {{#eq contentType 'media'}}toolbar-library-pane{{/eq}} {{#eq contentType 'layout_templates'}}toolbar-library-pane{{/eq}} {{#eq contentType 'layout_exchange'}}toolbar-library-pane{{/eq}} {{#eq contentType 'playlists'}}toolbar-library-pane{{/eq}}"
class="toolbar-pane toolbar-{{name}}-pane {{state}} {{#eq contentType 'media'}}toolbar-library-pane{{/eq}} {{#eq contentType 'layout_templates'}}toolbar-library-pane{{/eq}} {{#eq contentType 'template_exchange'}}toolbar-library-pane toolbar-template_exchange-pane{{/eq}} {{#eq contentType 'playlists'}}toolbar-library-pane{{/eq}}"
data-menu-index="{{menuIndex}}"
>

Expand Down
9 changes: 6 additions & 3 deletions views/common.twig
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@
list: {
url: "{{ url_for("template.view") }}"
},
getProviders: {
url: "{{ url_for("template.search.providers") }}",
type: 'GET'
},
},
region: {
transform: {
Expand Down Expand Up @@ -765,8 +769,7 @@
actionsTitle: "{{ "Interactive actions"|trans }}",
layoutTemplateName: "{{ "Layout Templates" |trans }}",
layoutTemplateTitle: "{{ "Search for Layout Templates"|trans }}",
layoutExchangeName: "{{ "Xibo Layout Exchange" |trans }}",
layoutExchangeTitle: "{{ "Search for templates available from the Xibo Exchange."|trans }}",
layoutExchangeTitle: "{{ "Search for templates available from the %obj%."|trans }}",
playlistsName: "{{ "Playlists" |trans }}",
playlistsTitle: "{{ "Add Playlists"|trans }}",
providerTitle: "{{ "Provider: %obj%"|trans }}",
Expand Down Expand Up @@ -816,7 +819,7 @@
layout: "{{ "Layout"|trans }}",
region: "{{ "Zone"|trans }}",
layoutTemplatesMessage: "{{ "Replace your Layout with a template?"|trans }}",
layoutExchangeTemplatesMessage: "{{ "Replace your Layout with a Xibo Exchange template?"|trans }}",
layoutExchangeTemplatesMessage: "{{ "Replace your Layout with a %obj% template?"|trans }}",
isRequired: "{{ "Required"|trans }}",
libraryTypes: {
image: "{{ "Image" |trans }}",
Expand Down

0 comments on commit 622b199

Please sign in to comment.