Skip to content

Commit

Permalink
add inline scalar editor
Browse files Browse the repository at this point in the history
  • Loading branch information
Yuzhakov committed Dec 11, 2024
1 parent ecf581d commit d201b97
Show file tree
Hide file tree
Showing 16 changed files with 481 additions and 19 deletions.
69 changes: 69 additions & 0 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class App {
this.#createModalWindowsForDeleteActions();
this.#createPopovers();
this.#createTooltips();
this.#inlineScalarEditor();

document.addEventListener('ea.collection.item-added', () => this.#createAutoCompleteFields());
}
Expand Down Expand Up @@ -449,4 +450,72 @@ class App {
});
});
}

#inlineScalarEditor() {
let selectedElement = null;
let currentData = null;
let newData = null;
let url = null;
document
.querySelectorAll('.field-number, .field-text')
.forEach(el => {
el.addEventListener('click', (event) => {
if (selectedElement !== null) {
return null;
}
selectedElement = event.target;
currentData = selectedElement.textContent.trim();
url = selectedElement.getAttribute('data-toggle-url');

const newInput = document.createElement('input');
this.#replace(newInput, selectedElement);

if (selectedElement.firstChild) {
selectedElement.replaceChild(newInput, selectedElement.firstChild);
} else {
selectedElement.appendChild(newInput);
}

newInput.value = currentData;
newInput.focus();
newInput.addEventListener('blur', (event) => {
newData = document.querySelector('#inlineInput').value;
let toggleUrl = url + "&newValue=" + newData;


fetch(toggleUrl, {
method: 'PATCH',
// the XMLHttpRequest header is needed to keep compatibility with the previous code, which didn't use the Fetch API
headers: { 'X-Requested-With': 'XMLHttpRequest' },
})
.then((response) => {
if (!response.ok) {
return;
}

document.querySelector('#inlineInput').remove()
selectedElement.textContent = newData

//reset data
selectedElement = null;
currentData = null;
newData = null;
url = null;
})
.then(() => { /* do nothing else when the toggle request is successful */ })
;
})
})
});
}

#replace(newInput, selectedElement) {
// add attribute
newInput.type = 'text';
newInput.id = 'inlineInput';
// add class Bootstrap
newInput.classList.add('form-control');

selectedElement.innerHTML = newInput.innerHTML
}
}
4 changes: 4 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@

->set(NumberConfigurator::class)
->arg(0, service(IntlFormatter::class))
->arg(1, service(AdminUrlGenerator::class))
->arg(2, new Reference('security.csrf.token_manager', ContainerInterface::NULL_ON_INVALID_REFERENCE))

->set(PercentConfigurator::class)
->arg(0, service(IntlFormatter::class))
Expand All @@ -388,6 +390,8 @@
->set(TelephoneConfigurator::class)

->set(TextConfigurator::class)
->arg(0, service(AdminUrlGenerator::class))
->arg(1, new Reference('security.csrf.token_manager', ContainerInterface::NULL_ON_INVALID_REFERENCE))

->set(TimezoneConfigurator::class)

Expand Down
2 changes: 0 additions & 2 deletions public/app.1ecd6d7a.js

This file was deleted.

5 changes: 0 additions & 5 deletions public/app.1ecd6d7a.js.LICENSE.txt

This file was deleted.

2 changes: 1 addition & 1 deletion public/entrypoints.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"/app.b1430af9.css"
],
"js": [
"/app.1ecd6d7a.js"
"/app.992caa58.js"
]
},
"form": {
Expand Down
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"app.css": "app.b1430af9.css",
"app.js": "app.1ecd6d7a.js",
"app.js": "app.992caa58.js",
"form.js": "form.bcec6c2a.js",
"page-layout.js": "page-layout.3347892e.js",
"page-color-scheme.js": "page-color-scheme.30cb23c2.js",
Expand Down
12 changes: 10 additions & 2 deletions src/Controller/AbstractCrudController.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,15 @@ public function edit(AdminContext $context)
}

$fieldName = $context->getRequest()->query->get('fieldName');
$newValue = 'true' === mb_strtolower($context->getRequest()->query->get('newValue'));

$valueData = $context->getRequest()->query->get('newValue');
if ('true' === mb_strtolower($valueData)) {
$newValue = true;
} elseif ('false' === mb_strtolower($valueData)) {
$newValue = false;
} else {
$newValue = $valueData;
}

try {
$event = $this->ajaxEdit($context->getEntity(), $fieldName, $newValue);
Expand Down Expand Up @@ -558,7 +566,7 @@ protected function getContext(): ?AdminContext
return $this->container->get(AdminContextProvider::class)->getContext();
}

protected function ajaxEdit(EntityDto $entityDto, ?string $propertyName, bool $newValue): AfterCrudActionEvent
protected function ajaxEdit(EntityDto $entityDto, ?string $propertyName, $newValue): AfterCrudActionEvent
{
$field = $entityDto->getFields()->getByProperty($propertyName);
if (null === $field || true === $field->getFormTypeOption('disabled')) {
Expand Down
29 changes: 26 additions & 3 deletions src/Field/Configurator/NumberConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,34 @@

namespace EasyCorp\Bundle\EasyAdminBundle\Field\Configurator;

use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldConfiguratorInterface;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
use EasyCorp\Bundle\EasyAdminBundle\Intl\IntlFormatter;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGeneratorInterface;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;

/**
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
*/
final class NumberConfigurator implements FieldConfiguratorInterface
{
private IntlFormatter $intlFormatter;

public function __construct(IntlFormatter $intlFormatter)
{
private AdminUrlGeneratorInterface $adminUrlGenerator;
private ?CsrfTokenManagerInterface $csrfTokenManager;

public function __construct(
IntlFormatter $intlFormatter,
AdminUrlGeneratorInterface $adminUrlGenerator,
?CsrfTokenManagerInterface $csrfTokenManager = null
) {
$this->intlFormatter = $intlFormatter;
$this->adminUrlGenerator = $adminUrlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
}

public function supports(FieldDto $field, EntityDto $entityDto): bool
Expand Down Expand Up @@ -70,6 +81,18 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c
}

$field->setFormattedValue($this->intlFormatter->formatNumber($value, $formatterAttributes));

$crudDto = $context->getCrud();

if (null !== $crudDto && Action::NEW !== $crudDto->getCurrentAction()) {
$toggleUrl = $this->adminUrlGenerator
->setAction(Action::EDIT)
->setEntityId($entityDto->getPrimaryKeyValue())
->set('fieldName', $field->getProperty())
->set('csrfToken', $this->csrfTokenManager?->getToken(BooleanField::CSRF_TOKEN_NAME))
->generateUrl();
$field->setCustomOption(NumberField::OPTION_TOGGLE_URL, $toggleUrl);
}
}

private function getRoundingModeAsString(int $mode): string
Expand Down
27 changes: 27 additions & 0 deletions src/Field/Configurator/TextConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,30 @@
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldConfiguratorInterface;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGeneratorInterface;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use function Symfony\Component\String\u;

/**
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
*/
final class TextConfigurator implements FieldConfiguratorInterface
{
private AdminUrlGeneratorInterface $adminUrlGenerator;
private ?CsrfTokenManagerInterface $csrfTokenManager;

public function __construct(
AdminUrlGeneratorInterface $adminUrlGenerator,
?CsrfTokenManagerInterface $csrfTokenManager = null
) {
$this->adminUrlGenerator = $adminUrlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
}

public function supports(FieldDto $field, EntityDto $entityDto): bool
{
return \in_array($field->getFieldFqcn(), [TextField::class, TextareaField::class], true);
Expand Down Expand Up @@ -55,6 +70,18 @@ public function configure(FieldDto $field, EntityDto $entityDto, AdminContext $c
$formattedValue = u($formattedValue)->truncate($configuredMaxLength ?? $defaultMaxLength, '')->toString();
}

$crudDto = $context->getCrud();

if (null !== $crudDto && Action::NEW !== $crudDto->getCurrentAction()) {
$toggleUrl = $this->adminUrlGenerator
->setAction(Action::EDIT)
->setEntityId($entityDto->getPrimaryKeyValue())
->set('fieldName', $field->getProperty())
->set('csrfToken', $this->csrfTokenManager?->getToken(BooleanField::CSRF_TOKEN_NAME))
->generateUrl();
$field->setCustomOption(NumberField::OPTION_TOGGLE_URL, $toggleUrl);
}

$field->setFormattedValue($formattedValue);
}
}
4 changes: 3 additions & 1 deletion src/Field/NumberField.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ final class NumberField implements FieldInterface
public const OPTION_NUMBER_FORMAT = 'numberFormat';
public const OPTION_THOUSANDS_SEPARATOR = 'thousandsSeparator';
public const OPTION_DECIMAL_SEPARATOR = 'decimalSeparator';
public const OPTION_TOGGLE_URL = 'toggleUrl';

/**
* @param TranslatableInterface|string|false|null $label
Expand All @@ -37,7 +38,8 @@ public static function new(string $propertyName, $label = null): self
->setCustomOption(self::OPTION_STORED_AS_STRING, false)
->setCustomOption(self::OPTION_NUMBER_FORMAT, null)
->setCustomOption(self::OPTION_THOUSANDS_SEPARATOR, null)
->setCustomOption(self::OPTION_DECIMAL_SEPARATOR, null);
->setCustomOption(self::OPTION_DECIMAL_SEPARATOR, null)
->setCustomOption(self::OPTION_TOGGLE_URL, null);
}

public function setNumDecimals(int $num): self
Expand Down
6 changes: 5 additions & 1 deletion src/Field/TextField.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ final class TextField implements FieldInterface
public const OPTION_RENDER_AS_HTML = 'renderAsHtml';
public const OPTION_STRIP_TAGS = 'stripTags';

public const OPTION_TOGGLE_URL = 'toggleUrl';

/**
* @param TranslatableInterface|string|false|null $label
*/
Expand All @@ -31,7 +33,9 @@ public static function new(string $propertyName, $label = null): self
->setDefaultColumns('col-md-6 col-xxl-5')
->setCustomOption(self::OPTION_MAX_LENGTH, null)
->setCustomOption(self::OPTION_RENDER_AS_HTML, false)
->setCustomOption(self::OPTION_STRIP_TAGS, false);
->setCustomOption(self::OPTION_STRIP_TAGS, false)
->setCustomOption(self::OPTION_TOGGLE_URL, null)
;
}

/**
Expand Down
22 changes: 22 additions & 0 deletions src/Resources/public/app.19616e33.css

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions src/Resources/public/app.19616e33.rtl.css

Large diffs are not rendered by default.

Loading

0 comments on commit d201b97

Please sign in to comment.