Skip to content

Commit

Permalink
Module icons (#1032)
Browse files Browse the repository at this point in the history
* feat: handle module icons

* fix: tests

* tests: more coverage

* doc: phpdoc for Modules configuration

* fix: box in sidebar view

* fix: testModuleLink

* fix: avoid multiple icons at the same time
  • Loading branch information
didoda authored Aug 24, 2023
1 parent 5ac6026 commit 7eb1dac
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 24 deletions.
6 changes: 3 additions & 3 deletions config/app_local.example.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@
* 'sort' - sort order to be used in index; use a field name prepending optionl `-` sign
* to indicate a descendant order, f.i. '-title' will sort by title in reverse alphabetical order
* (default is '-id'),
* 'icon' - icon code, f.i. `icon-article`, have a look in
* `webroot/css/be-icons-codes.css` for a complete list of codes
* 'icon' - icon, f.i. `carbon:document`, have a look at https://icon-sets.iconify.design/
* for a complete list of icons
* 'sidebar' - additional custom sidebar links added in modules index and single item view,
* defined as associative array with 'index' and 'view' keys
*/
Expand All @@ -119,7 +119,7 @@
// 'color' => '#230637',
// // 'secondaryColor' => '#d95700',
// 'sort' => '-modified',
// // 'icon' => 'icon-cube',
// // 'icon' => 'carbon:document',
// ],
// 'folders' => [
// 'color' => '#072440',
Expand Down
80 changes: 73 additions & 7 deletions src/View/Helper/LayoutHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace App\View\Helper;

use App\Utility\Translate;
use Cake\Core\Configure;
use Cake\Utility\Hash;
use Cake\View\Helper;

Expand All @@ -24,6 +25,7 @@
* @property \App\View\Helper\LinkHelper $Link
* @property \App\View\Helper\PermsHelper $Perms
* @property \App\View\Helper\SystemHelper $System
* @property \Cake\View\Helper\UrlHelper $Url
*/
class LayoutHelper extends Helper
{
Expand All @@ -32,7 +34,7 @@ class LayoutHelper extends Helper
*
* @var array
*/
public $helpers = ['Editors', 'Html', 'Link', 'Perms', 'System'];
public $helpers = ['Editors', 'Html', 'Link', 'Perms', 'System', 'Url'];

/**
* Is Dashboard
Expand Down Expand Up @@ -110,6 +112,71 @@ public function title(): string
return empty($title) ? $name : sprintf('%s | %s', $title, $name);
}

/**
* Return dashboard module link
*
* @param string $name The module name
* @param array $module The module data
* @return string
*/
public function dashboardModuleLink(string $name, array $module): string
{
if (in_array($name, ['trash', 'users'])) {
return '';
}
$label = $name === 'objects' ? __('All objects') : Hash::get($module, 'label', $name);
$route = (array)Hash::get($module, 'route');
$param = empty($route) ? ['_name' => 'modules:list', 'object_type' => $name, 'plugin' => null] : $route;

return sprintf(
'<a href="%s" class="%s"><span>%s</span>%s</a>',
$this->Url->build($param),
sprintf('dashboard-item has-background-module-%s %s', $name, Hash::get($module, 'class', '')),
$this->tr($label),
$this->moduleIcon($name, $module)
);
}

/**
* Return module icon.
*
* @param string $name The module name
* @param array $module The module data
* @return string
*/
public function moduleIcon(string $name, array $module): string
{
if (Hash::get($module, 'hints.multiple_types') && !Hash::get($module, 'class')) {
return '<Icon icon="carbon:grid"></Icon>';
}
$icon = (string)Configure::read(sprintf('Modules.%s.icon', $name));
if (!empty($icon)) {
return sprintf('<Icon icon="%s"></Icon>', $icon);
}
$map = [
'audio' => 'carbon:document-audio',
'categories' => 'carbon:collapse-categories',
'documents' => 'carbon:document',
'events' => 'carbon:event',
'files' => 'carbon:document-blank',
'folders' => 'carbon:tree-view',
'images' => 'carbon:image',
'links' => 'carbon:link',
'locations' => 'carbon:location',
'news' => 'carbon:calendar',
'profiles' => 'carbon:person',
'publications' => 'carbon:wikis',
'tags' => 'carbon:tag',
'users' => 'carbon:user',
'videos' => 'carbon:video',
];
if (!in_array($name, array_keys($map))) {
return '';
}

return sprintf('<Icon icon="%s"></Icon>', $map[$name]);
}

/**
* Return module css class(es).
* If object is locked by parents, return base class plus 'locked' class.
Expand Down Expand Up @@ -149,13 +216,12 @@ public function moduleLink(): string
$name = $currentModule['name'];
$label = Hash::get($currentModule, 'label', $name);

return $this->Html->link(
return sprintf(
'<a href="%s" class="%s"><span class="mr-05">%s</span>%s</a>',
$this->Url->build(['_name' => 'modules:list', 'object_type' => $name]),
sprintf('module-item has-background-module-%s', $name),
$this->tr($label),
['_name' => 'modules:list', 'object_type' => $name],
[
'id' => 'module-icon',
'class' => sprintf('has-background-module-%s', $name),
]
$this->moduleIcon($name, $currentModule)
);
}

Expand Down
30 changes: 30 additions & 0 deletions templates/Element/Menu/sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
}
}

.app-module-box-concurrent-editors a.module-item > svg {
display:none;
}

ul.concurrent-editors {
margin:0; padding:0;
li {
Expand Down Expand Up @@ -150,6 +154,32 @@ ul.concurrent-editors {
> *:not(:last-child) { margin-bottom: $gutter; }
}

.app-module-box > a.module-item {
justify-content: center;
}

.app-module-box > a.module-item > span {
flex: 1;
display: inline-block;
transform: translateY(0);
transition: transform 0.3s;
}

.app-module-box > a.module-item > svg {
position: absolute;
display: block;
top: 40%;
height: 24px;
width: 24px;
}

.app-module-box:is(.locked) > a.module-item > svg,
.app-module-box:is(.expired) > a.module-item > svg,
.app-module-box:is(.future) > a.module-item > svg,
.app-module-box:is(.draft) > a.module-item > svg {
display: none;
}

.listobjnav {
color:$gray-600;
font-size:4em;
Expand Down
12 changes: 1 addition & 11 deletions templates/Pages/Dashboard/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,7 @@
<section class="dashboard-section">
<div class="dashboard-items">
{% for name, module in modules %}
{% if not in_array(name, ['trash', 'users']) %}
{% set module = name == 'objects' ? {'label': __('All objects')}|merge(module) : module %}
{% set class = 'dashboard-item has-background-module-%s %s'|format(name, module.class|default('')) %}
{% set url = module.route ? Url.build(module.route) : Url.build({ '_name': 'modules:list', 'object_type': name, 'plugin': null }) %}
<a href="{{ url }}" class="{{ class }}">
<span>{{ Layout.tr(module.label|default(name)) }}</span>
{% if module.hints.multiple_types and not module.class %}<Icon icon="carbon:grid"></Icon>{% endif %}
{% if name == 'publications' %}<Icon icon="carbon:wikis"></Icon>{% endif %}
{% if name == 'folders' %}<Icon icon="carbon:tree-view"></Icon>{% endif %}
</a>
{% endif %}
{{ Layout.dashboardModuleLink(name, module)|raw }}
{% endfor %}
</div>
</section>
Expand Down
4 changes: 2 additions & 2 deletions tests/TestCase/View/Helper/ElementHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,15 @@ public function customProvider(): array
}

/**
* Test `element` method
* Test `custom` method
*
* @param string $expected The expected element
* @param string $item The item
* @param string $type The item type
* @param array $conf Configuration to use
* @return void
* @dataProvider customProvider()
* @covers ::element()
* @covers ::custom()
*/
public function testCustom(string $expected, string $item, string $type = 'relation', array $conf = []): void
{
Expand Down
113 changes: 112 additions & 1 deletion tests/TestCase/View/Helper/LayoutHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ public function moduleLinkProvider(): array
],
],
'objects' => [
'<a href="/objects" id="module-icon" class="has-background-module-objects">Objects</a>',
'<a href="/objects" class="module-item has-background-module-objects"><span class="mr-05">Objects</span></a>',
'Module',
[
'currentModule' => ['name' => 'objects'],
Expand Down Expand Up @@ -537,4 +537,115 @@ public function testTrashLink(): void
$actual = $layout->trashLink('dummies');
static::assertSame($expected, $actual);
}

/**
* Data provider for `testDashboardModuleLink` test case.
*
* @return array
*/
public function dashboardModuleLinkProvider(): array
{
return [
'trash' => [
'trash',
[],
'',
],
'users' => [
'users',
[],
'',
],
'documents' => [
'documents',
[],
'<a href="/documents" class="dashboard-item has-background-module-documents "><span>Documents</span><Icon icon="carbon:document"></Icon></a>',
],
];
}

/**
* Test `dashboardModuleLink`.
*
* @return void
* @dataProvider dashboardModuleLinkProvider()
* @covers ::dashboardModuleLink()
* @covers ::moduleIcon()
*/
public function testDashboardModuleLink(string $name, array $module, string $expected): void
{
$modules = (array)Configure::read('Modules', []);
$modules['test_items'] = ['icon' => 'test:items'];
Configure::write('Modules', $modules);
$viewVars = [];
$request = new ServerRequest();
$view = new View($request, null, null, compact('viewVars'));
$layout = new LayoutHelper($view);
$actual = $layout->dashboardModuleLink($name, $module);
static::assertEquals($expected, $actual);
}

/**
* Data provider for `testModuleIcon` test case.
*
* @return array
*/
public function moduleIconProvider(): array
{
return [
'hints multiple types' => [
'animals',
[
'hints' => [
'multiple_types' => true,
],
],
'<Icon icon="carbon:grid"></Icon>',

],
'documents' => [
'documents',
[],
'<Icon icon="carbon:document"></Icon>',
],
'from conf' => [
'test_items',
[],
'<Icon icon="test:items"></Icon>',
],
'from map (core modules)' => [
'locations',
[],
'<Icon icon="carbon:location"></Icon>',
],
'other module (non core, non conf)' => [
'cats',
[],
'',
],
];
}

/**
* Test `moduleIcon`.
*
* @param string $name The module name
* @param array $module The module configuration
* @param string $expected The expected result
* @return void
* @dataProvider moduleIconProvider()
* @covers ::moduleIcon()
*/
public function testModuleIcon(string $name, array $module, string $expected): void
{
$modules = (array)Configure::read('Modules', []);
$modules['test_items'] = ['icon' => 'test:items'];
Configure::write('Modules', $modules);
$viewVars = [];
$request = new ServerRequest();
$view = new View($request, null, null, compact('viewVars'));
$layout = new LayoutHelper($view);
$actual = $layout->moduleIcon($name, $module);
static::assertEquals($expected, $actual);
}
}

0 comments on commit 7eb1dac

Please sign in to comment.