Skip to content

Commit

Permalink
[Improvement]: Split and lazy load icon library (#567)
Browse files Browse the repository at this point in the history
* split in tabs,small tweaks and opmitizations
lazy loading 
avoid loading pimcore js files, copy the copytoClipboard function there

replace .click with on('click')

sort alphabetically by iso code, but should be by country name and translate in base of user language but not worth to change it

further refactor, reducing flags to 248 since we consider only the country code
* improve dataobject class icon selectors

---------

Co-authored-by: markus-moser <markus.moser@pimcore.com>
  • Loading branch information
kingjia90 and markus-moser authored Jun 17, 2024
1 parent 76eda40 commit 5d6b106
Show file tree
Hide file tree
Showing 12 changed files with 379 additions and 136 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
- [Composer] Added `phpoffice/phpspreadsheet` requirement (which got moved out from `pimcore/pimcore`) and extended support to `v2`.
- [Date & date/time fields] Date & date/time fields are now configured with `date` and `datetime` column type by default.
- [Date/time fields] Date/time fields now support the usage without timezone support.

- [Icons] Overhauled Icon library and icon dropdown selector in class definition editor.

#### v1.4.0
- [DataObject] Password data type algorithms other than `password_hash` are deprecated since `pimcore/pimcore:^11.2` and will be removed in `pimcore/pimcore:^12`.

Expand Down
87 changes: 87 additions & 0 deletions public/js/pimcore/iconlibrary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

pimcore.registerNS("pimcore.iconlibrary.panel");

/**
* @private
*/
pimcore.iconlibrary.panel = Class.create({

initialize: function () {
this.getTabPanel();
},

activate: function () {
const tabPanel = Ext.getCmp("pimcore_panel_tabs");
tabPanel.setActiveItem("pimcore_iconlibrary_panel");
},

getTabPanel: function () {
if (!this.panel) {
const iconLibraryTab = Ext.create('Ext.tab.Panel', {
region: 'center',
deferredRender: true,
id: "pimcore_icon_library_tabs",
hideMode: "display",
cls: "tab_panel",
height: "100%",
items: [
{
title: t('color_icons'),
html: '<iframe src="' + Routing.generate('pimcore_admin_misc_iconlist', {type: 'color'}) + '" frameborder="0" style="width:100%; height:100%" ></iframe>',
},
{
title: t('white_icons'),
html: '<iframe src="' + Routing.generate('pimcore_admin_misc_iconlist', {type: 'white'}) + '" frameborder="0" style="width:100%; height:100%" ></iframe>',
},
{
title: t('twemoji'),
html: '<iframe src="' + Routing.generate('pimcore_admin_misc_iconlist', {type: 'twemoji'}) + '" frameborder="0" style="width:100%; height:100%" ></iframe>',
},
{
title: t('flags'),
html: '<iframe src="' + Routing.generate('pimcore_admin_misc_iconlist', {type: 'flags'}) + '" frameborder="0" style="width:100%; height:100%" ></iframe>',
}
]
});

this.panel = new Ext.Panel({
id: "pimcore_iconlibrary_panel",
title: t("icon_library"),
iconCls: "pimcore_icon_icons",
border: false,
layout: 'border',
closable: true,
items: [
iconLibraryTab
],
});

const tabPanel = Ext.getCmp("pimcore_panel_tabs");
tabPanel.add(this.panel);


this.panel.on("destroy", function () {
pimcore.globalmanager.remove("iconlibrary");
});

pimcore.layout.refresh();
}

return this.panel;
},
});



16 changes: 12 additions & 4 deletions public/js/pimcore/layout/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -812,9 +812,7 @@ pimcore.layout.toolbar = Class.create({
iconCls: "pimcore_nav_icon_icons",
itemId: 'pimcore_menu_settings_icon_library',
text: t('icon_library'),
handler: function() {
pimcore.helpers.openGenericIframeWindow("icon-library", Routing.generate('pimcore_admin_misc_iconlist'), "pimcore_icon_icons", t("icon_library"));
}
handler: this.showIconLibrary.bind(this)
});
}

Expand Down Expand Up @@ -1366,6 +1364,16 @@ pimcore.layout.toolbar = Class.create({
}

pimcore.globalmanager.add("new_notifications", new pimcore.notification.modal());
}
},

showIconLibrary: function () {
try {
pimcore.globalmanager.get("iconlibrary").activate();
}
catch (e) {
pimcore.globalmanager.add("iconlibrary", new pimcore.iconlibrary.panel());
pimcore.globalmanager.get("iconlibrary").activate();
}
}
});

67 changes: 55 additions & 12 deletions public/js/pimcore/object/classes/class.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pimcore.object.classes.klass = Class.create({
context: "class",
uploadRoute: 'pimcore_admin_dataobject_class_importclass',
exportRoute: 'pimcore_admin_dataobject_class_exportclass',

iconCss: ' left center no-repeat; text-indent: 20px',
initialize: function (data, parentPanel, reopen, editorPrefix) {
this.parentPanel = parentPanel;
this.data = data;
Expand Down Expand Up @@ -701,7 +701,38 @@ pimcore.object.classes.klass = Class.create({
return "Pimcore\\Model\\DataObject\\" + ucfirst(name);
};

var iconStore = new Ext.data.ArrayStore({
const iconTypes = Ext.create('Ext.data.Store', {
fields: ['text', 'value'],
data: [
{ "text": t('color_icons'), "value": 'color' },
{ "text": t('white_icons'), "value": 'white' },
{ "text": t('twemoji') + ' (1/3)', "value": 'twemoji-1' },
{ "text": t('twemoji') + ' (2/3)', "value": 'twemoji-2' },
{ "text": t('twemoji') + ' (3/3)', "value": 'twemoji-3' },
{ "text": t('twemoji_variants') + ' (1/3)', "value": 'twemoji_variants-1' },
{ "text": t('twemoji_variants') + ' (2/3)', "value": 'twemoji_variants-2' },
{ "text": t('twemoji_variants') + ' (3/3)', "value": 'twemoji_variants-3' },
]
});

const iconTypeBox = Ext.create('Ext.form.ComboBox', {
store: iconTypes,
width: 180,
displayField: 'text',
valueField: 'value',
emptyText: t('type'),
listeners: {
select: function (elem) {
iconStore.proxy.extraParams = {
'type' : elem.value,
classId: this.getId(),
};
iconStore.load();
}.bind(this)
}
});

const iconStore = new Ext.data.ArrayStore({
proxy: {
url: Routing.generate('pimcore_admin_dataobject_class_geticons'),
type: 'ajax',
Expand All @@ -723,8 +754,8 @@ pimcore.object.classes.klass = Class.create({
value: this.data.icon,
listeners: {
"afterrender": function (el) {
el.inputEl.applyStyles("background:url(" + el.getValue() + ") right center no-repeat;");
}
el.inputEl.applyStyles("background:url(" + el.getValue() + ")" + this.iconCss);
}.bind(this)
}
});

Expand Down Expand Up @@ -872,19 +903,31 @@ pimcore.object.classes.klass = Class.create({
labelWidth: 200
},
items: [
iconField,
iconField
]
},
{
xtype: "fieldcontainer",
layout: "hbox",
fieldLabel: t("icon_tools"),
defaults: {
labelWidth: 200
},
items: [
iconTypeBox,
{
xtype: "combobox",
store: iconStore,
width: 50,
width: 75,
valueField: 'value',
displayField: 'text',
emptyText: t('select_type_first'),
listeners: {
select: function (ele, rec, idx) {
var icon = ele.container.down("#iconfield-" + this.getId());
var newValue = rec.data.value;
icon.component.setValue(newValue);
icon.component.inputEl.applyStyles("background:url(" + newValue + ") right center no-repeat;");
const icon = Ext.getCmp("iconfield-" + this.getId());
const newValue = rec.data.value;
icon.setValue(newValue);
icon.inputEl.applyStyles("background:url(" + newValue + ")" + this.iconCss);
return newValue;
}.bind(this)
}
Expand All @@ -894,15 +937,15 @@ pimcore.object.classes.klass = Class.create({
xtype: "button",
tooltip: t("refresh"),
handler: function(iconField) {
iconField.inputEl.applyStyles("background:url(" + iconField.getValue() + ") right center no-repeat;");
iconField.inputEl.applyStyles("background:url(" + iconField.getValue() + ")" + this.iconCss);
}.bind(this, iconField)
},
{
xtype: "button",
iconCls: "pimcore_icon_icons",
text: t('icon_library'),
handler: function () {
pimcore.helpers.openGenericIframeWindow("icon-library", Routing.generate('pimcore_admin_misc_iconlist'), "pimcore_icon_icons", t("icon_library"));
pimcore.globalmanager.get("layout_toolbar").showIconLibrary();
}
}
]
Expand Down
2 changes: 1 addition & 1 deletion public/js/pimcore/object/classes/layout/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ pimcore.object.classes.layout.layout = Class.create({
iconCls: "pimcore_icon_icons",
text: t('icon_library'),
handler: function () {
pimcore.helpers.openGenericIframeWindow("icon-library", Routing.generate('pimcore_admin_misc_iconlist'), "pimcore_icon_icons", t("icon_library"));
pimcore.globalmanager.get("layout_toolbar").showIconLibrary();
}
}
]
Expand Down
65 changes: 59 additions & 6 deletions src/Controller/Admin/DataObject/ClassController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1810,14 +1810,27 @@ public function getSelectOptionsUsagesAction(Request $request): Response
public function getIconsAction(Request $request, EventDispatcherInterface $eventDispatcher): Response
{
$classId = $request->get('classId');
$type = $request->get('type');

if (!$type) {
return $this->adminJson([]);
}

$iconDir = PIMCORE_WEB_ROOT . '/bundles/pimcoreadmin/img';
$classIcons = rscandir($iconDir . '/object-icons/');
$colorIcons = rscandir($iconDir . '/flat-color-icons/');
$twemoji = rscandir($iconDir . '/twemoji/');

$icons = array_merge($classIcons, $colorIcons, $twemoji);
$icons = match($type) {
'color' => rscandir($iconDir . '/flat-color-icons/'),
'white' => rscandir($iconDir . '/flat-white-icons/'),
'twemoji-1', 'twemoji-2', 'twemoji-3',
'twemoji_variants-1', 'twemoji_variants-2', 'twemoji_variants-3'
=> rscandir($iconDir . '/twemoji/'),
default => []
};

$style = '';
if ($type === 'white') {
$style = 'background-color:#000';
}
foreach ($icons as &$icon) {
$icon = str_replace(PIMCORE_WEB_ROOT, '', $icon);
}
Expand All @@ -1829,11 +1842,51 @@ public function getIconsAction(Request $request, EventDispatcherInterface $event
$eventDispatcher->dispatch($event, AdminEvents::CLASS_OBJECT_ICONS_PRE_SEND_DATA);
$icons = $event->getArgument('icons');

$startIndex = 0;
$result = [];
foreach ($icons as $icon) {

if (str_starts_with($type, 'twemoji')) {
foreach ($icons as $index => $twemojiIcon) {
$iconBase = basename($twemojiIcon);

// All the variants (like skin color) have a hyphen in their base name
// Here we remove/unset wheter if the selected icon type is the variant list
$explodeByHyphen = explode('-', $iconBase);
if (
(!str_starts_with($type, 'twemoji_variants') && isset($explodeByHyphen[1])) ||
(str_starts_with($type, 'twemoji_variants') && !isset($explodeByHyphen[1]))
) {
unset($icons[$index]);
}
}

$icons = array_values($icons);
$limit = count($icons);

if (str_ends_with($type, '-1')) {
$limit = floor($limit / 3);
}
if (str_ends_with($type, '-2')) {
$startIndex = floor($limit / 3);
$limit = floor($limit / 3 * 2);
}
if (str_ends_with($type, '-3')) {
$startIndex = floor($limit / 3 * 2);
}
} else {
$limit = count($icons);
}

for ($i = $startIndex; $i < $limit; $i++) {
$icon = $icons[$i];
$content = file_get_contents(PIMCORE_WEB_ROOT . $icon);
$result[] = [
'text' => sprintf('<img src="data:%s;base64,%s"/>', mime_content_type(PIMCORE_WEB_ROOT . $icon), base64_encode($content)),
'text' => sprintf(
'<img style="%s" src="data:%s;base64,%s"/>',
$style,
mime_content_type(PIMCORE_WEB_ROOT . $icon),
base64_encode($content)
),
'value' => $icon,
];
}
Expand Down
Loading

0 comments on commit 5d6b106

Please sign in to comment.