Доброго времени суток. Бывает, что задачи клиентов выходят за рамки функционала продукта, это касается и работы в административной части сайта. В связи с этим появляются задачи создания или изменения стандартных административных страниц.
Разберём реальный пример разработки страницы с нуля.[spoiler] Пойдём к результату, приведённому ниже:
Что мы должны уметь:
Создавать фильтр с произвольными полями.
Создавать контекстное меню в списке.
Задавать групповые операции над строками списка.
Реализовать сортировку в списке по произвольному полю.
Добавлять кнопки на панели инструментов (на скриншоте это кнопка "Добавить" ).
Сразу приложу готовый файл c исходным кодом страницы, чтобы были понятны детали, о который пойдёт речь ниже. (Скачать файл)
Создание объекта сортировки и инициализация административного списка:
$sTableID = "tbl_cons_user"; //задаём уникальный ID для своей таблицы
$oSort = new CAdminSorting($sTableID, "ID", "desc"); // указываем сортировку по умолчанию (ID=>desc)
$lAdmin = new CAdminList($sTableID, $oSort); //создаём объект списка
После этого начинаем описывать поля фильтра:
$arFilterRows = array(
GetMessage("CONS_G_L_FIL_NAME"), //Фильтруем по имени
GetMessage("CONS_G_L_FIL_DATE_CREATE"), //дате создания
GetMessage("CONS_G_L_FIL_LAST_ACTIVITY"), //дате последней активности
);
$filter = new CAdminFilter($sTableID."_filter_id", $arFilterRows); //Создаём объект фильтра
Задаём переменные, которые мы будем использовать в фильтре:
$lAdmin->AddHeaders(array(
array(
"id" =>"ID", //Идентификатор поля
"content" =>"ID", // Языковое сообщение - название поля
"sort" =>"id", //переменная, по которой будет идти сортировка
"align" =>"right", //выравнивание содержимого
"default" =>true, //по умолчанию поле отображается
),
array(
"id" =>"NAME",
"content" => GetMessage("CONS_G_L_COL_NAME"),
"sort" =>"name",
"default" =>true,
),
array(
"id" =>"ENTITY_ID",
"content" => GetMessage("CONS_G_L_COL_ENTITY_ID"),
"sort" =>"entity",
"default" =>true,
),
array(
"id" =>"DATE_CREATE",
"content" => GetMessage("CONS_G_L_COL_DATE_CREATE"),
"sort" =>"date_create",
"default" =>true,
),
array(
"id" =>"LAST_ACTIVITY",
"content" => GetMessage("CONS_G_L_COL_LAST_ACTIVITY"),
"sort" =>"last_activity",
"default" =>true,
),
));
Далее надо сделать выборку, чтобы получить список записей, которые будем выводить. Заметьте, что на данном этапе уже учитываются переменные фильтра, которые мы описывали выше:
$arFilter = Array(
"ID" => $find_id,
"%NAME" => $find_name,
">=DATE_CREATE" => $find_date_create_from,
"<=DATE_CREATE" => $find_date_create_to,
">=LAST_ACTIVITY" => $find_last_activity_from,
"<=LAST_ACTIVITY" => $find_last_activity_to,
);
//$by - по какому полю сортируем (задаётся в AddHeaders(), ключ ID)
//$order - передаётся asc или desc, значение определяется самим списком
$rsData = $cData->GetList(Array($by=>$order), $arFilter);
Задаём постраничную навигацию:
$rsData = new CAdminResult($rsData, $sTableID);
$rsData->NavStart();
//Текст в постраничной навигации
$lAdmin->NavText($rsData->GetNavPrint(GetMessage("CONS_NAV_USERS")));
while($arRes = $rsData->NavNext(true, "f_")):
Всё, теперь в блоке while формируем значения полей для конкретной записи в списке:
//Эта строка означает, что в список добавляем все выбранные поля
$row =& $lAdmin->AddRow($f_ID, $arRes);
if ($arRes["ENTITY_TYPE"] == "U")
$entity_str = '<a href="c_user_edit.php?ID='.$arRes["ENTITY_ID"].'">'.$arRes["ENTITY_ID"].'</a>';
else
$entity_str = $arRes["ENTITY_ID"];
//Добавляем инициализируем поле, которое не выбрано GetList'ом
$row->AddViewField("ENTITY_ID", $entity_str);
//Говорим, что значение поля "NAME" можно редактировать даже в списке
$row->AddInputField ("NAME", Array("size"=>"15"));
тут же в while добавляем контекстное меню:
$arActions = array();
if($CONS_RIGHT>="W")
{
$arActions[] = array(
"ICON"=>"delete",
"TEXT"=> "Delete",
//f_ID мы получили в GetList
"ACTION"=>"if(confirm('delete?')) ".$lAdmin->ActionDoGroup($f_ID, "delete"),
);
}
$row->AddActions($arActions);
Всё, while заканчивается, список построен. Добавляем подвал:
$lAdmin->AddFooter(
array(
//Языковое сообщение для количество выбранных элементов в GetList
array("title"=>GetMessage("MAIN_ADMIN_LIST_SELECTED"), "value"=>$rsData->SelectedRowsCount()),
//Языковое сообщение для количества отмеченных записей в списке
array("counter"=>true, "title"=> GetMessage("MAIN_ADMIN_LIST_CHECKED"), "value"=>"0"),
)
);
Групповые операции под подвалом:
$arB = Array(
"reset_activity"=>GetMessage("CONS_G_L_RESET_ACTIVITY")
);
if ($CONS_RIGHT=="W")
$arB["delete"]=GetMessage("MAIN_ADMIN_LIST_DELETE");
$lAdmin->AddGroupActionTable($arB);
Очень удачное решение в плане юзабилити. Как-то обычно не обращаешь на это внимания, а тут я удивился на сколько данный подход лучше решает мои задачи, нежели то что раньше я наверстал в админке сам.
Правда пришлось потратить пару часов на одну неприятную вещь - без предварительного вызова $lAdmin->EditAction() никак не хотел работать метод AddInputField. Грустно и смешно
Из пожеланий - хотелось бы иметь возможность убрать чекбокс "Для всех", т.к. в моём случае не предусмотрено групповых операций такого типа. И ещё я не понял как указать чтобы в фильтре были видны некоторые поля по умолчанию.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».