digitalwand / digitalwand.admin_helper Goto Github PK
View Code? Open in Web Editor NEWAPI для сборки кастомных админок в Битриксе
License: MIT License
API для сборки кастомных админок в Битриксе
License: MIT License
В getCheckboxType() тип чекбокса определяется по типу поля в модели. Однако в битриксе часто существует следующая конструкция (пример из bitrix\modules\main\lib\user.php):
'ACTIVE' => array( 'data_type' => 'boolean', 'values' => array('N','Y') ),
тип чекбокса будет определен как TYPE_BOOLEAN, хотя на самом деле он TYPE_STRING
В AdminEditHelper используется getById при выборке элемента. Нужно заменить это на getList и выбирать только те поля которые используются при редактировании элемента, потому что не всегда нужны все поля из записи, например в случае с модификаторами значения которые тянут что-то из АПИ.
Если перейти на страницу списка записей с установленными в URL параметрами сортировки, то битрикс на бекенде генерирует корректный вариант списка. Однако после того, как загрузился js, битрикс пытается применить фильтр, и вот он уже выставляет дефолтную сортировку.
Для исправления этого поведения добавил ПР #63
Не хватает концептуального описания устройства АХ и принципов работы с ним. За неимением оного, новым разработчикам приходится объяснять, что такое хелперы, виджеты, Interface.php, как они взаимодействуют и т. д.
Это можно прописать для начала хотя бы в том же README.md.
Если к примеру HTTPS настроен не на 443-й порт, то при групповом удалении или удалении из контекстного меню строки (да и при любых действиях на странице списка) список не обновляется, т.к. браузер ругается на смешанное содержимое HTTPS.
Причина банальна: в классе AdminListHelper
после указанных выше операций прописан LocalRedirect($listHelperClass::getUrl($params))
с относительным URL.
Т.к. HTTPS работает не на стандартном порту, LocalRedirect()
криво определяет протокол и возвращает данные по HTTP, на что и ругается браузер.
Решение не менее банально: убираем эти LocalRedirect()
.
Понятно, что корень проблемы в настройках сервера, но по-моему эти LocalRedirect()
в любом случае лишние, т.к. js-метод битрикса, отвечающий за операции на странице списка, сам обновляет блок с таблицей с учетом всех изменений.
Речь идет про LocalRedirect()
в конструкторе и методе groupActions
класса DigitalWand\AdminHelper\Helper\AdminListHelper
.
При переходе в раздел сохраняется номер текущей страницы в постраничной навигации. При этом целевой раздел может содержать м̀еньшее количество страниц, и список окажется пустым.
Наблюдается как при переходе по ссылке на раздел в списке, так и по кнопке На раздел выше.
Можно воспроизвести на demo.adminhelper, набив текстовые данные с помощью этого скрипта.
Т.к. OrmElementWidget наследуется от NumberWidget, а в режиме режиме Multiple функция getValue() возвращает массив, а не число, то валидация не проходит.
public function processEditAction()
{
if (!$this->checkRequired()) {
$this->addError('DIGITALWAND_AH_REQUIRED_FIELD_ERROR');
} else if (!$this->isNumber($this->getValue())) {
$this->addError('VALUE_IS_NOT_NUMERIC');
}
}
С версии 17.0.11
главного модуля появился новый класс CAdminUiList на замену старому. Неплохо было бы научить admin_helper использовать его.
Доброго дня!
Есть ли в модуле возможность создавать взаимосвязанные поля? Например есть выпадашка ComboBoxWidget со списком инфоблоков и чтобы при выборе инфоблока в другом поле отображался список разделов выбранного инфоблока?
Если да, то подскажите, пожалуйста, как подобное реализовать)
в AdminEditHelper.php в
else {
unset($this->data);
$this->data = $_REQUEST['FIELDS']; //Заполняем, чтобы в случае ошибки сохранения поля не были пустыми
}
нало поправить т.к. например при сохранение с виджетом HL ИБ, веденные значения не хранятся в FIELDS. Или вообще убрать
Пытаюсь установить модуль программно примерно таким способом:
require_once( './bitrix/modules/digitalwand.admin_helper/install/index.php');
(new digitalwand_admin_helper())->DoInstall();
В конце метода DoInstall() подключается файл, который выводит форму с предложением вернуться назад в список модулей после установки. Файл с этой кнопкой подключается с помощью инструкции $APPLICATION->IncludeAdminFile(). Однако эта инструкция после выполнения подключения файла вызывает внутри себя die(), в связи с чем работа программы, выполняющей установку, становится невозможной.
Предлагаю 2 варианта решения проблемы:
Уидает исключение
Unknown primary 0
found when trying to query OrderStatus row.
$this->helper->getPk()
возвращает массив и в ключе 0 вмето ID
Не хватает конфигов, которые бы позволяли:
Думаю, большую часть из перечисленного лучше настраивать через Interface.php. Но после выполнения задачи #1.
Как я понял, чтобы ваше решение работало модуль должен быть вида aloha.adminhelper
Могу ли я это отключить?
доброго дня, собственно вопрос в топике
что с поддержкой? проект еще живой? будут ли какие то подвижки для поддержки php 8.1 ?
В теле функции getUrl при передаче параметра k=>'{{field_id}}' происходит экраниранирование значения, из-за чего шаблонизатор не делает замену и на выходе некорректная ссылка $popupUrl.
public function getMultipleEditHtml()
{
.....
$popupUrl = $linkedHelper::getUrl(array_merge(
array(
'popup' => 'Y',
'eltitle' => $this->getSettings('TITLE_FIELD_NAME'),
'n' => $name,
'k' => '{{field_id}}'
),
$this->getSettings('ADDITIONAL_URL_PARAMS')
));
Фиксится добавления if для проверки $this->getValue() в методы getEditHtml, generateRow и processEditAction
При удалении записи через контекстное меню не передаются в запрос $additionalUrlParams
Если у виджета нет настройки VARIANTS, строки из связанной таблицы не удалятся. Заметил при использовании FileWidget в режиме MULTIPLE.
В методе \DigitalWand\AdminHelper\EntityManager::processReferencesData:
$variantsField = $fieldWidget->getSettings('VARIANTS');
...
if($result->isSuccess()){ // Удаление записей, которые не были созданы или обновлены
foreach ($referenceStaleDataSet as $referenceData) {
if (
!in_array($referenceData[$fieldWidget->getMultipleField('ID')], $processedDataIds) &&
array_key_exists($referenceData[$fieldWidget->getMultipleField('VALUE')], $variantsField)
) {
$result = $this->deleteReferenceData($reference,
$referenceData[$fieldWidget->getMultipleField('ID')]);
if(!$result->isSuccess()) {
break; // ошибка, прерываем удаление данных
}
}
}
}
До конца не понимаю архитектуру, поэтому не знаю как лучше исправить, добавить проверку на тип виджета или реализовать настройку VARIANTS у FileWidget?
class CourseAdminInterface extends AdminInterface {
public function fields() {
return array(
'MAIN' => array(
'FIELDS' => array(
"UF_DATE_LESSON" => array(
'WIDGET' => new HLIBlockFieldWidget()
)
))
);
}
public function helpers() {
return array(
'\Pam\HLcourse\Course\AdminInterface\CourseListHelper',
'\Pam\HLcourse\Course\AdminInterface\CourseEditHelper'
);
}
}
UF_DATE_LESSON является типом Дата со временем в HighLoad ИБ, множественным и не объязательным. При сохранение нового элемента в сгнерированной админке появляется сообщение Значение поля «UF_DATE_LESSON» не является корректной датой/временем.
При этом само поле может быть пустым или заполеным датой из календаря. Я только смог понять что не србатывает CheckFields
Можно воспроизвести на demo.adminhelper:
При этом имя параметра с ID
текущего раздела в URL меняется с ID
на SECTION_ID
.
Добрый день.
Подскажите, пожалуйста, поддерживает ли данный модуль из коробки возможность редактирования связи многий ко многим для OrmElementWidget?
Есть ли возможность отображать только страницу списка элементов, без страницы редактирования?
Попробовал просто не создавать AdminEditHelper. Не получилось, ругается.
В модели создаю поле FILE_ID, свойство multiple =>true.
new Entity\IntegerField('FILE_ID',['multiple'=>true]),
создаю поле связку, указывающую на \Bitrix\Main\FileTable
new Entity\ReferenceField('FILES','\Bitrix\Main\FileTable',['=this.FILE_ID' => 'ref.ID'])
В классе админ интерфейса
'FILES'=>[
'WIDGET'=>new Widget\FileWidget(),
'IMAGE'=>true,
'MULTIPLE'=>true
]
После этого пытаюсь создать новую запись в админке, загружаю один/несколько файлов и получаю битриксовый Exception
[Bitrix\Main\NotImplementedException]
Use CFile class. (140)
/home/bitrix/www/bitrix/modules/main/lib/file.php:191
#0: Bitrix\Main\FileTable::add(array)
/home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/EntityManager.php:468
#1: DigitalWand\AdminHelper\EntityManager->createReferenceData(object, array)
/home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/EntityManager.php:379
#2: DigitalWand\AdminHelper\EntityManager->processReferencesData()
/home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/EntityManager.php:213
#3: DigitalWand\AdminHelper\EntityManager->save()
/home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/helper/AdminEditHelper.php:527
#4: DigitalWand\AdminHelper\Helper\AdminEditHelper->saveElement()
/home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/helper/AdminEditHelper.php:453
#5: DigitalWand\AdminHelper\Helper\AdminEditHelper->editAction()
/home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/helper/AdminEditHelper.php:126
#6: DigitalWand\AdminHelper\Helper\AdminEditHelper->__construct(array, array)
/home/bitrix/www/bitrix/modules/digitalwand.admin_helper/admin/route.php:101
#7: include_once(string)
/home/bitrix/www/bitrix/admin/admin_helper_route.php:2
Вопрос: есть ли пример использования CFile или надо сделать свою таблицу и туда сохранять данные файлов?
При создании нового элемента не бросает на листинг при нажатии "Сохранить"
Авторы! Отметьте в Packagist , что ваш пакет является заброшенным, если вы не реагируете и не исправляете его ошибки!!!
Разработчики-пользователи данного пакета: никогда его не используйте!
Причины:
1 Очень низкое качество кода: почти всё на статических методах :(
2 Для управления своей табличкой нужно делать свой модуль Битрикс. (это я попытался обойти, написав свой контроллер https://github.com/webarchitect609/bitrix-admin-helper-controller )
3 В модуле полным полно ошибок. Например, не работает массовое удаление записей.
4 Модуль по факту является брошенным: примерно с января 2017 года сообщения об ошибках (issue) плодятся, но никто их не исправляет.
Покажите пример как реализовать виджет многие к многим
Уже был Pull Request (#62).
Пример из жизни:
Надо, чтобы было LIMIT 0, 20 в конце такого запроса.
Можно воспроизвести на demo.adminhelper:
&popup=Y
Дальше два варианта ошибочного поведения:
В попапах для ссылок на подразделы используется url от AdminSectionListHelper, для чего — не очень понятно. @lithium-li, можешь пояснить, твой код вроде бы?
При загрузке элемента замена полей не происходит, при сохранении не вставляется ID элемента! Или это только у меня? При сохранении тоже значения пишутся в VALUE, а не в поле замены.
Можно воспроизвести на demo.adminhelper:
Если в сущности присутствует ReferenceField, то происходит ошибка в виджете CheckboxWidget.
В методе getCheckboxType виджета CheckboxWidget в цикле foreach для $field вызывается метод getColumnName(), который отсутствует у ReferenceField и у его родителя Field.
Call to undefined method Bitrix\Main\Entity\ReferenceField::getColumnName() in /home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/widget/CheckboxWidget.php on line 209
модуль main 16.5.7
digitalwand.admin_helper 2.0.0
Временное решение проблемы - перемещение описания поля reference на последнее по порядку место в методе getMap сущности. Тогда цикл просто до него не добирается (при условии что искомое поле будет найдено раньше). Ну а по хорошему надо перед вызовом getColumnName сделать проверку $field на тип и если это ReferenceField - пропускать его.
При попытке группового удаления возникает исключение вида:
[Bitrix\Main\ArgumentException]
Unknown primary `0` found when trying to query Poi row. (100)
/home/bitrix/www/bitrix/modules/main/lib/entity/datamanager.php:350
#0: Bitrix\Main\Entity\DataManager::validatePrimary(array)
/home/bitrix/www/bitrix/modules/highloadblock/lib/datamanager.php:297
#1: Bitrix\Highloadblock\DataManager::delete(array)
/home/bitrix/www/local/modules/digitalwand.admin_helper/lib/EntityManager.php:248
#2: DigitalWand\AdminHelper\EntityManager->delete()
/home/bitrix/www/local/modules/digitalwand.admin_helper/lib/helper/AdminListHelper.php:529
#3: DigitalWand\AdminHelper\Helper\AdminListHelper->groupActions(array, string)
/home/bitrix/www/local/modules/digitalwand.admin_helper/lib/helper/AdminListHelper.php:224
#4: DigitalWand\AdminHelper\Helper\AdminListHelper->__construct(array, boolean)
/home/bitrix/www/local/vendor/nav/adminhelper/AdminListHelper.php:11
#5: nav\AdminHelper\AdminListHelper->__construct(array, boolean)
/home/bitrix/www/local/vendor/nav/adminhelper/admin/admin_interface_route.php:117
#6: require(string)
/home/bitrix/www/bitrix/admin/nav_admin_helper_route.php:2
В \DigitalWand\AdminHelper\EntityManager::delete() идёт вызов:
$result = $model::delete($this->helper->getPk());
а в аргументах у него идёт не айди конкретной записи, а массив всех айдишников, которые надо удалить. Возможно, надо использовать $this->itemId. А может и где-то в другом месте исправить, чтобы не сломать логики.
CheckboxWidget::getCheckboxType()
имеет две проблемы:
Метод виджета changeGetListOptions должен влиять на аргументы, передаваемые в GetList()
.
Изменение $select
сейчас не влияет на выборку полей элементов (без разделов).
В changeGetListOptions передается переменная $visibleColumns, но её изменение не влияет на $listSelect
, которая используется при выборке.
Если имя поля задано в getMap() в классе модели, то при задании поля NAME в настройках виджета оно должно переопределяться. Но этого не происходит.
При удалении разделов удаление дочерних элементов остается на совести модели. Даже если это все таки реализовано в модели, то если этих элементов будет слишком много, то удаление может упасть по таймауту.
При любом изменении элемента, значения для множественного поля ComboBoxWidget создаются заново.
Т.к. данный виджет не передаёт id текущего значения в таблице, и мы всегда попадаем в блок создания связанных данных.
public function processEditAction()
{
if ($this->getSettings('MULTIPLE')) {
$sphere = $this->data[$this->getCode()];
unset($this->data[$this->getCode()]);
foreach ($sphere as $sphereKey) {
$this->data[$this->getCode()][] = array('VALUE' => $sphereKey);
}
}
parent::processEditAction();
}
Т.е. empty($referenceData['ID']) всегда true.
foreach ($referenceDataSet as $referenceData) {
if (empty($referenceData[$fieldWidget->getMultipleField('ID')])) {
// Создание связанных данных
if (!empty($referenceData[$fieldWidget->getMultipleField('VALUE')])) {
$result = $this->createReferenceData($reference, $referenceData);
if ($result->isSuccess()) {
$processedDataIds[] = $result->getId();
} else {
break; // ошибка, прерываем обработку данных
}
}
} else {
// Обновление связанных данных
$result = $this->updateReferenceData($reference, $referenceData, $referenceStaleDataSet);
if ($result->isSuccess()) {
$processedDataIds[] = $referenceData[$fieldWidget->getMultipleField('ID')];
} else {
break; // ошибка, прерываем обработку данных
}
}
}
При использовании множественного удаления на листинге получаем ошибку:
[Bitrix\Main\ArgumentException] Unknown primary
0 found when trying to query News row. (100) /home/bitrix/www/bitrix/modules/main/lib/entity/datamanager.php:373 #0: Bitrix\Main\Entity\DataManager::validatePrimary(array) /home/bitrix/www/bitrix/modules/main/lib/entity/datamanager.php:116 #1: Bitrix\Main\Entity\DataManager::getByPrimary(array) /home/bitrix/www/bitrix/modules/main/lib/entity/datamanager.php:145 #2: Bitrix\Main\Entity\DataManager::getById(array) /home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/helper/AdminListHelper.php:519 #3: DigitalWand\AdminHelper\Helper\AdminListHelper->groupActions(array, string) /home/bitrix/www/bitrix/modules/digitalwand.admin_helper/lib/helper/AdminListHelper.php:224 #4: DigitalWand\AdminHelper\Helper\AdminListHelper->__construct(array, boolean) /home/bitrix/www/bitrix/modules/digitalwand.admin_helper/admin/route.php:108 #5: include_once(string) /home/bitrix/www/bitrix/admin/admin_helper_route.php:2
Дабы не лишать разработчиков возможности применения ООП, нужно реализовать описание интерфейса админки на классах. Пример: https://gist.github.com/niksamokhvalov/315252f6b3ca22f77745
Нужно сделать так, что бы модуль автоматически загружался в админке, без необходимости вызова \Bitrix\Main\Loader. Таки образом, не будет необходимости прописывать в своих модулях подключение Админ-хелпера.
Если нет связанных данных, функция getOrmElementData
$rsMultEntity = $entityName::getList(array(
'select' => array('REFERENCE_' => $this->getCode() . '.*'),
'filter' => array('=ID' => $this->data['ID'])
));
выводит пустые поля ['REFERENCE_ID'=>NULL, 'REFERENCE_VALUE'=>NULL], которые затем записываются в список значений
while ($multEntity = $rsMultEntity->fetch()) {
$valueList[$multEntity['REFERENCE_VALUE']] = $multEntity['REFERENCE_VALUE'];
}
сформированный массив ["" => NULL] попадает в ОRM и возникает ошибка
$rsEntity = $linkedModel::getList(array(
'filter' => array('ID' => $valueList)
));
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.