diff --git a/.gitignore b/.gitignore index 210f39a..ca445a0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .phpunit.result.cache composer.lock docker-compose.override.yml +auth.json \ No newline at end of file diff --git a/README.md b/README.md index 3788c91..d6cab3c 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ elbformat_icon: - clock - house iconset2: - folder: "vendor/ezsystems/ezplatform-admin-ui/src/bundle/Resources/public/img/icons" + folder: "vendor/ibexa/admin-ui/src/bundle/Resources/public/img/icons" ``` See [configuration](doc/configuration.md) for more advanced examples diff --git a/Resources/encore/ez.config.manager.js b/Resources/encore/ez.config.manager.js deleted file mode 100644 index 26f1b62..0000000 --- a/Resources/encore/ez.config.manager.js +++ /dev/null @@ -1,29 +0,0 @@ -// See https://doc.ibexa.co/en/3.3/extending/import_assets_from_bundle/#configuration-from-main-project-files -const path = require('path'); - -module.exports = (eZConfig, eZConfigManager) => { - // Edit - eZConfigManager.add({ - eZConfig, - entryName: 'ezplatform-admin-ui-content-edit-parts-js', - newItems: [ - path.resolve(__dirname, '../public/js/elbformat-icon-edit.js') - ] - }); - eZConfigManager.add({ - eZConfig, - entryName: 'ezplatform-admin-ui-content-edit-parts-css', - newItems: [ - path.resolve(__dirname, '../public/css/elbformat-icon-edit.css') - ] - }); - // Preview - eZConfigManager.add({ - eZConfig, - entryName: 'ezplatform-admin-ui-layout-css', - newItems: [ - path.resolve(__dirname, '../public/css/elbformat-icon-preview.css') - ] - }); - -}; \ No newline at end of file diff --git a/Resources/encore/ibexa.config.manager.js b/Resources/encore/ibexa.config.manager.js new file mode 100644 index 0000000..9ab42db --- /dev/null +++ b/Resources/encore/ibexa.config.manager.js @@ -0,0 +1,22 @@ +// See https://doc.ibexa.co/en/3.3/extending/import_assets_from_bundle/#configuration-from-main-project-files +const path = require('path'); + +module.exports = (ibexaConfig, ibexaConfigManager) => { + // Edit + ibexaConfigManager.add({ + ibexaConfig, + entryName: 'ibexa-admin-ui-content-edit-parts-js', + newItems: [ + path.resolve(__dirname, '../public/js/elbformat-icon-edit.js') + ] + }); + // Preview + ibexaConfigManager.add({ + ibexaConfig, + entryName: 'ibexa-admin-ui-layout-css', + newItems: [ + path.resolve(__dirname, '../public/css/elbformat-icon-preview.css') + ] + }); + +}; \ No newline at end of file diff --git a/Resources/public/css/elbformat-icon-edit.css b/Resources/public/css/elbformat-icon-edit.css deleted file mode 100644 index f8fcb36..0000000 --- a/Resources/public/css/elbformat-icon-edit.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Inspired by https://codepen.io/giannisrig/pen/ywBWOV */ -.elbformat-icon-select { - display: none; -} -.icon-dropdown-wrapper { - width: 100%; - max-width: 34.375rem; - height: calc(1.5em + 0.75rem + 2px); - position: relative; - border:1px solid #878b90; -} - .icon-dropdown-wrapper .icon-dropdown-trigger { - width: 100%; - height: 100%; - background-color: #fff; - border: 0; - padding: 2px 10px; - transition: 0.2s ease-in; - cursor:pointer; - text-align: left; - } - .icon-dropdown-wrapper .icon-dropdown-trigger::before { - content: '˅'; - position: absolute; - top: 7px; - right: 10px; - } - .icon-dropdown-wrapper.open .icon-dropdown-trigger::before { - top: 5px; - right: 10px; - transform: rotate(180deg); - } - .icon-dropdown-wrapper .icon-dropdown-trigger .icon-container { - width: 50px; - height: 30px; - padding-right: 10px; - display: inline-block; - } - - .icon-dropdown-wrapper .icon-dropdown-list { - width: 100%; - display:none; - z-index: 1; - position: absolute; - background-color: #fff; - left: 0; - top: 37px; - box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.3); - max-height: 300px; - overflow: scroll; - } - .icon-dropdown-wrapper.open .icon-dropdown-list { - display:block; - } - - .icon-dropdown-wrapper .icon-dropdown-trigger button, - .icon-dropdown-wrapper .icon-dropdown-list button { - width: 100%; - height: 54px; - line-height: 54px; - border: 0; - padding: 2px 10px; - cursor: pointer; - transition:0.2s ease-in; - text-align: left; - overflow: hidden; - } - .icon-dropdown-wrapper .icon-dropdown-list button:hover { - background-color:#e5e5e5; - } - .icon-dropdown-wrapper .icon-dropdown-list button:not(:last-child){ - border-bottom: 1px solid #e5e5e5; - } - .icon-dropdown-wrapper .icon-dropdown-list .icon-container { - width: 50px; - height: 50px; - padding-right: 10px; - display: inline-block; - } - .icon-dropdown-wrapper .icon-dropdown-trigger .icon-container img, - .icon-dropdown-wrapper .icon-dropdown-list .icon-container img { - max-width: 90%; - max-height: 90%; - } diff --git a/Resources/public/css/elbformat-icon-preview.css b/Resources/public/css/elbformat-icon-preview.css index 4519005..130bdc5 100644 --- a/Resources/public/css/elbformat-icon-preview.css +++ b/Resources/public/css/elbformat-icon-preview.css @@ -1,12 +1,12 @@ -.ez-content-preview .elbformat-icon { +.ibexa-content-preview .elbformat-icon { text-align: left; } - .ez-content-preview .elbformat-icon .icon-container { + .ibexa-content-preview .elbformat-icon .icon-container { height: 18px; width: 30px; display: inline-block; } - .ez-content-preview .elbformat-icon .icon-container img { + .ibexa-content-preview .elbformat-icon .icon-container img { max-height: 90%; max-width: 90%; } diff --git a/Resources/public/js/elbformat-icon-edit.js b/Resources/public/js/elbformat-icon-edit.js index c4c0a37..5a6d9aa 100644 --- a/Resources/public/js/elbformat-icon-edit.js +++ b/Resources/public/js/elbformat-icon-edit.js @@ -1,60 +1,21 @@ -// Inspired by https://codepen.io/giannisrig/pen/ywBWOV window.addEventListener('load', function() { - document.querySelectorAll('.elbformat-icon-select').forEach((iconDropdown) => { - // Hidden field to carry the form data - let hiddenField = document.createElement('input'); - hiddenField.setAttribute('type','hidden'); - hiddenField.setAttribute('name', iconDropdown.getAttribute('name')); - let value = iconDropdown.value || ''; - hiddenField.setAttribute('value', value); - iconDropdown.after(hiddenField); + // Find list entries + document.querySelectorAll('.elbformat-icon-select').forEach((iconDropdownEntry) => { + let value = iconDropdownEntry.value || ''; + let iconMarkup = iconDropdownEntry.getAttribute('data-markup'); + let li = iconDropdownEntry.closest('.ibexa-dropdown').querySelector('.ibexa-dropdown__item[data-value="'+value+'"]'); - // Wrapper for new widget - let wrapper = document.createElement('div'); - wrapper.classList.add('icon-dropdown-wrapper'); - iconDropdown.after(wrapper); + // Create a span with icon + let wrapper = document.createElement('span'); + wrapper.classList.add('ibexa-icon'); + wrapper.classList.add('ibexa-icon--small'); + wrapper.innerHTML =iconMarkup; - let button = document.createElement('button'); - button.classList.add('icon-dropdown-trigger'); - wrapper.appendChild(button); - let iconList = document.createElement('div'); - iconList.classList.add('icon-dropdown-list'); - wrapper.appendChild(iconList); + // Insert before the label + let label = li.querySelector('.ibexa-dropdown__item-label'); + li.insertBefore(wrapper, label); - // Extract icons - let items = JSON.parse(iconDropdown.getAttribute('data-choices')); - for (const [key, tmpl] of Object.entries(items)) { - let container = document.createElement('button'); - container.setAttribute('value', key) - let iconContainer = document.createElement('div'); - iconContainer.classList.add('icon-container'); - iconContainer.innerHTML = tmpl; - container.appendChild(iconContainer); - container.innerHTML+=key - iconList.appendChild(container); - if (value===key) { - button.innerHTML = container.innerHTML; - } - // Click on entry - container.addEventListener('click',(e) => { - button.innerHTML = container.innerHTML; - hiddenField.value = key; - wrapper.classList.remove('open'); - e.preventDefault(); - return false; - }); - }; - - // Open/Close - button.addEventListener('click',(e) => { - if (wrapper.classList.contains('open')) { - wrapper.classList.remove('open'); - } else { - wrapper.classList.add('open'); - } - e.preventDefault(); - return false; - }); + // @todo also update the selected choice with an icon }); }); \ No newline at end of file diff --git a/composer.json b/composer.json index 27f4a70..7740d12 100644 --- a/composer.json +++ b/composer.json @@ -23,8 +23,8 @@ }, "require": { "php": "^8.1", - "ezsystems/ezplatform-core": "^2.3", - "ezsystems/ezplatform-admin-ui": "^2.3", + "ibexa/core": "^4.6", + "ibexa/admin-ui": "^4.6", "symfony/finder": "^5.4|^6.4" }, "require-dev": { diff --git a/config/ezplatform.yaml b/config/ibexa.yaml similarity index 95% rename from config/ezplatform.yaml rename to config/ibexa.yaml index c04684f..fa04a3e 100644 --- a/config/ezplatform.yaml +++ b/config/ibexa.yaml @@ -1,4 +1,4 @@ -ezplatform: +ibexa: system: default: field_templates: diff --git a/config/services.yaml b/config/services.yaml index b3c1c91..d5b356b 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -4,14 +4,14 @@ services: $serializer: '@eZ\Publish\SPI\FieldType\ValueSerializerInterface' $validator: '@Symfony\Component\Validator\Validator\ValidatorInterface' tags: - - { name: ezplatform.field_type, alias: icon } - - { name: ezplatform.field_type.form_mapper.value, fieldType: icon } - - { name: ezplatform.field_type.form_mapper.definition, fieldType: icon } + - { name: ibexa.field_type, alias: icon } + - { name: ibexa.admin_ui.field_type.form.mapper.value, fieldType: icon } + - { name: ibexa.admin_ui.field_type.form.mapper.definition, fieldType: icon } Elbformat\IconBundle\FieldType\Icon\SearchField: - class: '%ezpublish.fieldType.indexable.unindexed.class%' + class: 'Ibexa\Core\FieldType\Unindexed' tags: - - { name: ezplatform.field_type.indexable, alias: icon } + - { name: ibexa.field_type.indexable, alias: icon } Elbformat\IconBundle\Form\Type\IconType: arguments: diff --git a/doc/changelog.md b/doc/changelog.md new file mode 100644 index 0000000..b74f1cb --- /dev/null +++ b/doc/changelog.md @@ -0,0 +1,4 @@ +# Changelog + +## v2.0.0 +Ibexa 4.6 compatibility. Makes use of the dropdown already provided by ibexa. \ No newline at end of file diff --git a/doc/development.md b/doc/development.md index b14a5d6..4323f44 100644 --- a/doc/development.md +++ b/doc/development.md @@ -1,7 +1,7 @@ ## Local development For local development you can use docker-compose. ```bash -docker-compose run php sh +docker compose run php sh composer install ``` @@ -23,8 +23,8 @@ vendor/bin/phpstan Fix styles (from outside the container) ```bash -docker-compose run phpcsfixer fix src -docker-compose run phpcsfixer fix tests +docker compose run phpcsfixer fix src +docker compose run phpcsfixer fix tests ``` ## In-Place development diff --git a/docker-compose.yml b/docker-compose.yml index dd82453..285abc7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: '2.1' services: php: image: ghcr.io/elbformat/ibexa-icon-fieldtype/php diff --git a/src/DependencyInjection/ElbformatIconExtension.php b/src/DependencyInjection/ElbformatIconExtension.php index b65c3c7..92ece1d 100644 --- a/src/DependencyInjection/ElbformatIconExtension.php +++ b/src/DependencyInjection/ElbformatIconExtension.php @@ -6,6 +6,7 @@ use Elbformat\IconBundle\IconSet\IconSetManager; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; @@ -30,16 +31,17 @@ public function load(array $configs, ContainerBuilder $container): void public function prepend(ContainerBuilder $container): void { // Add template for rendering - $configFile = file_get_contents(__DIR__.'/../../config/ezplatform.yaml'); - if (false === $configFile) { - throw new \RuntimeException(sprintf('%s not found or not readable', __DIR__.'/../../config/ezplatform.yaml')); + $ibexaConfigFileName = __DIR__.'/../../config/ibexa.yaml'; + $ibexaConfigFile = file_get_contents($ibexaConfigFileName); + if (false === $ibexaConfigFile) { + throw new \RuntimeException(sprintf('%s not found or not readable', $ibexaConfigFileName)); } - /** @var array{'ezplatform':array} $config */ - $config = Yaml::parse($configFile); - $container->prependExtensionConfig('ezpublish', $config['ezplatform']); + /** @var array{'ibexa':array} $ibexaConfig */ + $ibexaConfig = Yaml::parse($ibexaConfigFile); + $container->prependExtensionConfig('ibexa', $ibexaConfig['ibexa']); + $container->addResource(new FileResource($ibexaConfigFileName)); // Register translations (as this is not done automatically. Maybe the missing "bundle" in path?) $container->prependExtensionConfig('framework', ['translator' => ['paths' => [__DIR__.'/../../translations']]]); - } } diff --git a/src/FieldType/Icon/Type.php b/src/FieldType/Icon/Type.php index 8998bf8..78744f6 100644 --- a/src/FieldType/Icon/Type.php +++ b/src/FieldType/Icon/Type.php @@ -6,11 +6,11 @@ use Elbformat\IconBundle\Form\Type\IconSettingsType; use Elbformat\IconBundle\Form\Type\IconType; -use eZ\Publish\SPI\FieldType\Generic\Type as GenericType; -use EzSystems\EzPlatformAdminUi\FieldType\FieldDefinitionFormMapperInterface; -use EzSystems\EzPlatformAdminUi\Form\Data\FieldDefinitionData; -use EzSystems\EzPlatformContentForms\Data\Content\FieldData; -use EzSystems\EzPlatformContentForms\FieldType\FieldValueFormMapperInterface; +use Ibexa\AdminUi\FieldType\FieldDefinitionFormMapperInterface; +use Ibexa\AdminUi\Form\Data\FieldDefinitionData; +use Ibexa\Contracts\ContentForms\Data\Content\FieldData; +use Ibexa\Contracts\ContentForms\FieldType\FieldValueFormMapperInterface; +use Ibexa\Contracts\Core\FieldType\Generic\Type as GenericType; use Symfony\Component\Form\FormInterface; final class Type extends GenericType implements FieldValueFormMapperInterface, FieldDefinitionFormMapperInterface diff --git a/src/FieldType/Icon/Value.php b/src/FieldType/Icon/Value.php index ee69763..97a51f0 100644 --- a/src/FieldType/Icon/Value.php +++ b/src/FieldType/Icon/Value.php @@ -4,7 +4,7 @@ namespace Elbformat\IconBundle\FieldType\Icon; -use eZ\Publish\SPI\FieldType\Value as ValueInterface; +use Ibexa\Contracts\Core\FieldType\Value as ValueInterface; final class Value implements ValueInterface { diff --git a/src/Form/Type/IconType.php b/src/Form/Type/IconType.php index 97936c3..242425c 100644 --- a/src/Form/Type/IconType.php +++ b/src/Form/Type/IconType.php @@ -26,17 +26,15 @@ public function buildForm(FormBuilderInterface $builder, array $options): void /** @var string $iconSet */ $iconSet = $options['icon_set']; $iconList = $this->iconSetManager->getSet($iconSet)->getList(); - $iconTemplates = []; + $attr = []; foreach($iconList as $icon) { - $iconTemplates[$icon] = $this->twig->render('@ElbformatIcon/icon.html.twig', ['icon' => $icon,'iconset' => $iconSet]); + $iconMarkup = $this->twig->render('@ElbformatIcon/icon.html.twig', ['icon' => $icon, 'iconset' => $iconSet]); + $attr[$icon] = ['class' => 'elbformat-icon-select', 'data-markup' => $iconMarkup]; } $builder->add('icon', ChoiceType::class, [ 'choices' => $iconList, + 'choice_attr' => $attr, 'label' => false, - 'attr' => [ - 'class' => 'elbformat-icon-select', - 'data-choices' => json_encode($iconTemplates) - ] ]); } diff --git a/templates/icon.html.twig b/templates/icon.html.twig index c48764c..33b20d6 100644 --- a/templates/icon.html.twig +++ b/templates/icon.html.twig @@ -6,7 +6,7 @@ #} {% if icon is not null %} {% if "set2" == iconset %} - + {% else %} {% endif %}