первая часть редактирование в админке

This commit is contained in:
2026-01-22 12:44:59 +05:00
parent 65bb464b9f
commit 01ed61e02d
4 changed files with 387 additions and 188 deletions

View File

@@ -108,6 +108,10 @@ class Comment
public $conf_cookie_life;
private $_anon_cookie_name = 'ave_anon_comment_key';
/**
* Редактирование Авторской оценки (1-разрешено, 0-запрещено)
*/
private $_edit_avtor_rating = 1;
/**
* Конструктор класса
@@ -1751,85 +1755,165 @@ $AVE_Template->assign([
/**
* Метод, предназначенный для редактирования комментариев в Административной части.
*
* @param string $tpl_dir - путь к шаблонам модуля
*/
function commentAdminPostEdit($tpl_dir)
function commentAdminPostEdit($tpl_dir)
{
global $AVE_DB, $AVE_Template;
$post_sub = $_POST['sub'] ?? '';
$request_id = (int)($_REQUEST['Id'] ?? 0);
$is_ajax = isset($_REQUEST['ajax']);
// 1. Получаем данные и настройки одним запросом
$row = $AVE_DB->Query("
SELECT
msg.*,
cmnt.comment_allowed_extensions,
cmnt.comment_max_file_size,
cmnt.comment_max_files,
cmnt.comment_allow_files,
cmnt.comment_show_f1,
cmnt.comment_show_f2,
cmnt.comment_show_user_rating
FROM " . PREFIX . "_module_comment_info AS msg
JOIN " . PREFIX . "_module_comments AS cmnt ON cmnt.Id = 1
WHERE msg.Id = '" . (int)$request_id . "'
LIMIT 1
")->FetchAssocArray();
if ($post_sub == 'send' && $row)
{
global $AVE_DB, $AVE_Template;
$upload_dir = BASE_DIR . '/uploads/comments/';
// Получаем массив текущих файлов (разбиваем по запятой)
$current_files = !empty($row['comment_file']) ? explode(',', $row['comment_file']) : [];
// Используем оператор объединения с null для PHP 8.4
$post_sub = $_POST['sub'] ?? '';
$request_id = (int)($_REQUEST['Id'] ?? 0);
$request_docid = (int)($_REQUEST['docid'] ?? 0);
$is_ajax = isset($_REQUEST['ajax']);
// --- А. Удаление файлов ---
if (!empty($_POST['delete_files'])) {
$files_to_remove = (array)$_POST['delete_files'];
foreach ($files_to_remove as $rem_file) {
$rem_file = basename(trim($rem_file)); // Очистка имени для безопасности
if (empty($rem_file)) continue;
// Выполняем запрос к БД на получение информации о редактируемом комментарии
$row = $AVE_DB->Query("
SELECT *
FROM " . PREFIX . "_module_comment_info
WHERE Id = '" . $request_id . "'
LIMIT 1
")->FetchAssocArray();
if (file_exists($upload_dir . $rem_file)) {
@unlink($upload_dir . $rem_file);
}
// Используем стрелочную функцию (PHP 7.4+)
$current_files = array_filter($current_files, fn($v) => trim($v) !== $rem_file);
}
}
// Если в запросе содержится подзапрос на сохранение данных
if ($post_sub == 'send' && false != $row)
{
// Экранирование данных перед сохранением
$AVE_DB->Query("
UPDATE " . PREFIX . "_module_comment_info
SET
comment_author_name = '" . addslashes(htmlspecialchars($_POST['comment_author_name'] ?? '')) . "',
comment_author_email = '" . addslashes(htmlspecialchars($_POST['comment_author_email'] ?? '')) . "',
comment_author_city = '" . addslashes(htmlspecialchars($_POST['comment_author_city'] ?? '')) . "',
comment_author_website = '" . addslashes(htmlspecialchars($_POST['comment_author_website'] ?? '')) . "',
comment_text = '" . addslashes(htmlspecialchars($_POST['comment_text'] ?? '')) . "',
comment_changed = '" . time() . "'
WHERE
Id = '" . (int)($_POST['Id'] ?? 0) . "'
");
// Если это AJAX-запрос (наша новая модалка), отдаем JSON
if ($is_ajax) {
header('Content-Type: application/json');
echo json_encode([
'status' => 'success',
'theme' => 'success',
'header' => 'Обновлено', // Можно заменить на переменную из языкового файла
'message' => 'Изменения успешно сохранены'
]);
exit;
// --- Б. Загрузка новых файлов ---
if ($row['comment_allow_files'] == 1 && isset($_FILES['comment_image']) && is_array($_FILES['comment_image']['name'])) {
if (!is_dir($upload_dir)) {
@mkdir($upload_dir, 0775, true);
@file_put_contents($upload_dir . 'index.php', "<?php\nheader('Location:/');\nexit;");
}
// Если вдруг зашли без AJAX (старым способом), просто выходим
$max_limit = (int)($row['comment_max_files'] ?? 5);
$allowed_ext_str = $row['comment_allowed_extensions'] ?? 'jpg,jpeg,png,gif,webp';
$allowed_extensions = array_map(fn($e) => trim(strtolower($e)), explode(',', $allowed_ext_str));
$max_file_size_bytes = (int)($row['comment_max_file_size'] ?? 2048) * 1024;
$processed_hashes = [];
foreach ($_FILES['comment_image']['name'] as $k => $fname) {
if ($_FILES['comment_image']['error'][$k] == UPLOAD_ERR_OK) {
// Важно: проверяем лимит на каждой итерации
if (count($current_files) >= $max_limit) break;
$tmp_name = $_FILES['comment_image']['tmp_name'][$k];
$file_size = $_FILES['comment_image']['size'][$k];
$file_hash = md5_file($tmp_name);
if (in_array($file_hash, $processed_hashes)) continue;
$ext = strtolower(pathinfo($fname, PATHINFO_EXTENSION));
$is_allowed_ext = in_array($ext, $allowed_extensions);
$is_dangerous = in_array($ext, ['php', 'php3', 'php4', 'php5', 'phtml', 'exe', 'pl', 'cgi', 'html', 'js']);
if ($is_allowed_ext && !$is_dangerous && $file_size > 0 && $file_size <= $max_file_size_bytes) {
$clean_name = function_exists('prepare_fname') ? prepare_fname(pathinfo($fname, PATHINFO_FILENAME)) : 'file';
if (empty($clean_name)) $clean_name = 'file';
$new_name = $clean_name . '_' . time() . '_' . rand(100,999) . '.' . $ext;
if (move_uploaded_file($tmp_name, $upload_dir . $new_name)) {
$current_files[] = $new_name;
$processed_hashes[] = $file_hash;
}
}
}
}
}
// Финальная строка файлов для базы
$final_files_str = implode(',', array_unique(array_filter($current_files)));
// --- В. Рейтинг ---
$new_rating = ($this->_edit_avtor_rating == 1 && isset($_POST['user_rating']))
? (int)$_POST['user_rating']
: (int)($row['user_rating'] ?? 0);
if ($new_rating < 0) $new_rating = 0;
if ($new_rating > 5) $new_rating = 5;
// Обновление БД
$AVE_DB->Query("
UPDATE " . PREFIX . "_module_comment_info
SET
comment_author_name = '" . addslashes(htmlspecialchars($_POST['comment_author_name'] ?? '')) . "',
comment_author_email = '" . addslashes(htmlspecialchars($_POST['comment_author_email'] ?? '')) . "',
comment_author_city = '" . addslashes(htmlspecialchars($_POST['comment_author_city'] ?? '')) . "',
comment_author_website = '" . addslashes(htmlspecialchars($_POST['comment_author_website'] ?? '')) . "',
comment_text = '" . addslashes(htmlspecialchars($_POST['comment_text'] ?? '')) . "',
user_rating = '" . $new_rating . "',
comment_file = '" . addslashes($final_files_str) . "',
comment_changed = '" . time() . "'
WHERE Id = '" . (int)$request_id . "'
");
if ($is_ajax) {
header('Content-Type: application/json');
echo json_encode([
'status' => 'success',
'theme' => 'success',
'header' => 'Обновлено',
'message' => 'Данные успешно сохранены'
]);
exit;
}
// Если в первой выборке из БД получили нулевой результат
if ($row == false)
{
$AVE_Template->assign('editfalse', 1);
}
else
{
$closed = $AVE_DB->Query("
SELECT comments_close
FROM " . PREFIX . "_module_comment_info
WHERE document_id = '" . $request_docid . "'
LIMIT 1
")->GetCell();
$AVE_Template->assign('closed', $closed);
$AVE_Template->assign('row', $row);
$AVE_Template->assign('comment_max_chars', $this->_commentSettingsGet('comment_max_chars'));
}
// Отображаем шаблон
$AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . $this->_admin_edit_link_tpl));
exit;
}
if (!$row) {
$AVE_Template->assign('editfalse', 1);
} else {
$row['file_list'] = !empty($row['comment_file']) ? explode(',', $row['comment_file']) : [];
$AVE_Template->assign('row', $row);
$AVE_Template->assign('edit_rating_enabled', $this->_edit_avtor_rating);
$AVE_Template->assign('comment_max_chars', (int)$this->_commentSettingsGet('comment_max_chars'));
}
$AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . $this->_admin_edit_link_tpl));
}
/**
* Метод, предназначенный для управления настройками модуля
*

View File

@@ -230,7 +230,7 @@ COMMENT_ICON_EDIT_ADM = "Редактировать"
COMMENT_ICON_DEL_SOFT = "Мягкое удаление/заменяет текст (сохраняет ветку)"
COMMENT_ICON_DEL_HARD = "Удалить навсегда (вместе с веткой)"
COMMENT_NOT_COOMENTS_MES = "Сообщение:"
COMMENT_NOT_COOMENTS_MES_A = "Нет комментариев."
COMMENT_NOT_COOMENTS_MES_A = "Комментарии не найдены..."
COMMENT_ACTION_SELECT = "Выберите действие..."
COMMENT_ACTION_SELECT_PUB = "Опубликовать"
COMMENT_ACTION_HIDE = "Скрыть"

View File

@@ -521,7 +521,7 @@
{* ИЗМЕНЕНО: Добавлены параметры в href *}
<a data-dialog="edit-comment-{$row.CId}"
href="index.php?do=modules&action=modedit&mod=comment&moduleaction=admin_edit&Id={$row.CId}&cp={$sess}&pop=1&onlycontent=1&sort_order={$smarty.get.sort_order|default:'new'}&view_mode={$smarty.get.view_mode|default:'flat'}&filter_type={$smarty.get.filter_type|default:''}&per_page={$smarty.get.per_page|default:'15'}"
data-width="1180" data-height="700" data-modal="true" data-title="{#COMMENT_ICON_EDIT_ADM#}"
data-width="" data-height="700" data-modal="true" data-title="{#COMMENT_ICON_EDIT_ADM#}"
class="openDialog icon_sprite ico_edit" title="{#COMMENT_ICON_EDIT_ADM#}"></a>
{if $row.has_children}

View File

@@ -1,164 +1,279 @@
<script type="text/javascript" language="JavaScript">
{literal}
$(document).ready(function(){
// 1. Инициализация параметров из Smarty
var maxFiles = {/literal}{$row.comment_max_files|default:5}{literal};
var maxFileSize = {/literal}{$row.comment_max_file_size|default:2048}{literal} * 1024;
var allowedExts = {/literal}'{$row.comment_allowed_extensions|default:"jpg,jpeg,png,gif,webp,zip,txt"}'{literal}.split(',');
var existingFilesCount = {/literal}{$row.file_list|@count|default:0}{literal};
// Логика счетчика символов
var left = {/literal}{$comment_max_chars}{literal};
var left = {/literal}{$comment_max_chars|default:1000}{literal};
$('#text_counter').text(left);
$('#in_message').keyup(function () {
left = {/literal}{$comment_max_chars}{literal} - $(this).val().length;
if(left < 0){
$('#text_counter').addClass("overlimit");
}
if(left >= 0){
$('#text_counter').removeClass("overlimit");
}
$('#text_counter').text(left);
// 2. Счетчик символов в текстовом поле
$('#in_message').on('keyup change', function () {
left = {/literal}{$comment_max_chars|default:1000}{literal} - $(this).val().length;
$('#text_counter').toggleClass("overlimit", left < 0).text(left);
});
// --- ЛОГИКА ДЛЯ МОДАЛЬНОГО ОКНА (AJAX) ---
// Формируем ID диалога точно так же, как его создает система AVE.cms
var dialogId = '#ajax-dialog-edit-comment-{/literal}{$smarty.request.Id|escape}{literal}';
// 3. Проверки файлов "на лету" при выборе
$('input[name="comment_image[]"]').on('change', function() {
var files = this.files;
var deletedCount = $('input[name="delete_files[]"]:checked').length;
var currentTotal = existingFilesCount - deletedCount;
// Кнопка сохранения
$(".SaveCommentAjax").on('click', function(event){
event.preventDefault();
if ((currentTotal + files.length) > maxFiles) {
alert("Лимит: " + maxFiles + " шт.");
$(this).val('');
return false;
}
for (var i = 0; i < files.length; i++) {
var file = files[i];
var ext = file.name.split('.').pop().toLowerCase();
if ($.inArray(ext, allowedExts) == -1) {
alert("Запрещенный формат: " + ext);
$(this).val('');
return false;
}
if (file.size > maxFileSize) {
alert("Файл слишком велик: " + (maxFileSize/1024) + " KB");
$(this).val('');
return false;
}
}
});
// 4. Логика Авторского рейтинга (звезды)
$('.rating-star').click(function() {
var val = $(this).data('value');
$('#user_rating_input').val(val);
$('.rating-star').each(function() {
$(this).toggleClass('active', $(this).data('value') <= val);
});
});
$('.reset-rating').click(function() {
$('#user_rating_input').val(0);
$('.rating-star').removeClass('active');
});
// 5. Удаление существующих файлов (клик по крестику)
$('.del-file-btn').on('click', function(e) {
e.preventDefault(); // Предотвращаем стандартное поведение
var $checkbox = $(this).find('input[type="checkbox"]');
var isChecked = !$checkbox.prop('checked');
$checkbox.prop('checked', isChecked);
var $item = $(this).closest('.file-preview-item');
if (isChecked) {
$item.find('.file-thumb, .ext-placeholder').css({'opacity': '0.3', 'filter': 'grayscale(1)'});
$(this).css('background', '#000');
} else {
$item.find('.file-thumb, .ext-placeholder').css({'opacity': '1', 'filter': 'none'});
$(this).css('background', '#dc3545');
}
});
// 6. Отправка формы через AJAX с прогресс-баром
$(".SaveCommentAjax").on('click', function(e){
e.preventDefault();
var $btn = $(this);
$("#comment_edit_form").ajaxSubmit({
// Добавляем флаг ajax=1, чтобы PHP понял, что нужно вернуть JSON
url: 'index.php?ajax=1&onlycontent=1&cp={/literal}{$sess}{literal}',
type: 'POST',
dataType: 'json',
beforeSubmit: function(){
$.alerts._overlay('show');
beforeSubmit: function(){
$btn.attr('disabled', true);
$('#comment-upload-progress').show();
},
uploadProgress: function(event, position, total, percentComplete) {
$('#upload-bar-fill').css('width', percentComplete + '%').text(percentComplete + '%');
},
success: function(data){
$.alerts._overlay('hide');
// Показываем уведомление (jGrowl)
$.jGrowl(data['message'], {
header: data['header'],
theme: data['theme']
});
// Если сохранение прошло без ошибок
$.jGrowl(data['message'], { header: data['header'], theme: data['theme'] });
if (data['theme'] !== 'error') {
// Уничтожаем модальное окно
$(dialogId).dialog('destroy').remove();
// Перезагружаем родительское окно, чтобы увидеть изменения в списке
if (window.parent) {
window.parent.location.reload();
}
// Короткая задержка перед релоадом, чтобы юзер увидел 100% и jGrowl
setTimeout(function() {
if (window.parent) window.parent.location.reload();
}, 600);
} else {
$btn.attr('disabled', false);
$('#comment-upload-progress').hide();
}
},
error: function(xhr, textStatus, errorThrown) {
$.alerts._overlay('hide');
$.jGrowl('Ошибка системы при сохранении', { theme: 'error' });
console.log(xhr.responseText);
error: function() {
alert("Ошибка при сохранении данных.");
$btn.attr('disabled', false);
$('#comment-upload-progress').hide();
}
});
return false;
});
// Кнопка отмены/закрытия
$(".CloseCommentDialog").on('click', function(event){
event.preventDefault();
$(dialogId).dialog('destroy').remove();
return false;
// 7. Закрытие диалогового окна
var dialogId = '#ajax-dialog-edit-comment-{/literal}{$smarty.request.Id|escape}{literal}';
$(".CloseCommentDialog").on('click', function(e){
e.preventDefault();
$(dialogId).dialog('destroy').remove();
});
});
{/literal}
</script>
<div class="widget first"></div>
<style>
{literal}
/* Возврат системных шрифтов и размеров */
.widget.first, .widget.first table { font-size: 12px !important; font-family: Tahoma, Arial, sans-serif !important; color: #333; }
.tableStatic td { padding: 8px 10px !important; vertical-align: middle; }
/* ИНПУТЫ: Высота и Шрифт */
.tableStatic input[type="text"] {
height: 30px !important;
line-height: 30px !important;
font-size: 13px !important;
padding: 0 8px !important;
border: 1px solid #ccc;
box-sizing: border-box;
}
/* ТЕКСТОВОЕ ПОЛЕ */
.tableStatic textarea {
height: 140px !important;
font-size: 13px !important;
padding: 8px !important;
border: 1px solid #ccc;
box-sizing: border-box;
line-height: 1.5;
}
<div class="title"><h5>{#COMMENT_MODULE_NAME#}</h5></div>
<div class="widget" style="margin-top: 0px;">
<div class="body">
{#COMMENT_EDIT_TITLE#}
</div>
</div>
<div class="breadCrumbHolder module">
<div class="breadCrumb module">
<ul>
<li class="firstB"><a href="index.php" title="{#MAIN_PAGE#}">{#MAIN_PAGE#}</a></li>
<li>{#COMMENT_MODULE_NAME#}</li>
<li>{#COMMENT_EDIT_TITLE#}</li>
</ul>
</div>
</div>
/* Рейтинг */
.rating-area { display: flex; align-items: center; gap: 5px; height: 30px; }
.rating-star { color: #ccc; cursor: pointer; font-size: 26px; line-height: 1; }
.rating-star.active { color: #ffc107; }
.reset-rating { cursor: pointer; color: #dc3545; margin-left: 10px; font-weight: bold; font-size: 16px; }
/* Файлы */
.file-preview-item { position: relative; display: inline-block; margin: 0 10px 10px 0; width: 60px; text-align: center; }
.file-thumb { width: 60px; height: 60px; object-fit: cover; border-radius: 4px; border: 1px solid #ccc; }
.ext-placeholder { width: 60px; height: 60px; background: #0d6efd; color: #fff; display: flex; align-items: center; justify-content: center; font-weight: bold; border-radius: 4px; text-transform: uppercase; font-size: 11px; }
.del-file-btn { position: absolute; top: -5px; right: -5px; background: #dc3545; color: #fff; border-radius: 50%; width: 18px; height: 18px; cursor: pointer; line-height: 17px; text-align: center; font-size: 12px; border: 1px solid #fff; z-index: 10; }
.del-file-btn input { display: none; }
.file-name-label { display: block; font-size: 10px; color: #666; margin-top: 3px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
/* Прогресс-бар */
#comment-upload-progress { display: none; width: 100%; background: #eee; height: 16px; border-radius: 3px; margin: 10px 0; border: 1px solid #ccc; }
#upload-bar-fill { height: 100%; background: #28a745; color: #fff; font-size: 10px; text-align: center; line-height: 16px; width: 0; }
.upload-info-box { margin-top:10px; padding: 10px; border: 1px dashed #ccc; background: #fcfcfc; }
.overlimit { color: #dc3545; font-weight: bold; }
{/literal}
</style>
<div class="widget first">
{if $closed == 1 && $smarty.const.UGROUP != 1}
<div class="body">
{#COMMENT_IS_CLOSED#}
<p style="margin-top:10px;">
<a href="javascript:void(0);" class="button redBtn CloseCommentDialog">{#COMMENT_CLOSE_BUTTON#}</a>
</p>
</div>
{if $editfalse == 1}
<div class="body">{#COMMENT_EDIT_FALSE#}</div>
{else}
{if $editfalse == 1}
<div class="body">{#COMMENT_EDIT_FALSE#}</div>
{else}
<form method="post" action="index.php" class="mainForm" id="comment_edit_form">
<table cellpadding="0" cellspacing="0" width="100%" class="tableStatic">
<col width="150">
{if $smarty.const.UGROUP == 1}
<tr>
<td>{#COMMENT_YOUR_NAME#}</td>
<td><input name="comment_author_name" type="text" id="in_author_name" style="width:250px" value="{$row.comment_author_name|stripslashes|escape}" /></td>
</tr>
<tr>
<td>{#COMMENT_YOUR_EMAIL#}</td>
<td><input name="comment_author_email" type="text" id="in_author_email" style="width:250px" value="{$row.comment_author_email|stripslashes|escape}" /></td>
</tr>
{else}
<input type="hidden" name="comment_author_name" value="{$row.comment_author_name|stripslashes|escape}" />
<input type="hidden" name="comment_author_email" value="{$row.comment_author_email|stripslashes|escape}" />
{/if}
<form method="post" id="comment_edit_form" enctype="multipart/form-data">
<table cellpadding="0" cellspacing="0" width="100%" class="tableStatic">
<col width="150">
<tr>
<td>{#COMMENT_YOUR_NAME#}*</td>
<td><input name="comment_author_name" type="text" style="width:300px" value="{$row.comment_author_name|stripslashes|escape}" /></td>
</tr>
<tr>
<td>{#COMMENT_YOUR_EMAIL#}*</td>
<td><input name="comment_author_email" type="text" style="width:300px" value="{$row.comment_author_email|stripslashes|escape}" /></td>
</tr>
<tr>
<td>{#COMMENT_YOUR_SITE#}</td>
<td><input name="comment_author_website" type="text" id="in_author_website" style="width:250px" value="{$row.comment_author_website|stripslashes|escape}" /></td>
</tr>
{if $row.comment_show_f2 == 1}
<tr>
<td>{#COMMENT_YOUR_SITE#}</td>
<td><input name="comment_author_website" type="text" style="width:300px" value="{$row.comment_author_website|stripslashes|escape}" /></td>
</tr>
{/if}
<tr>
<td>{#COMMENT_YOUR_FROM#}</td>
<td><input name="comment_author_city" type="text" id="in_author_city" style="width:250px" value="{$row.comment_author_city|stripslashes|escape}" /></td>
</tr>
{if $row.comment_show_f1 == 1}
<tr>
<td>{#COMMENT_YOUR_FROM#}</td>
<td><input name="comment_author_city" type="text" style="width:300px" value="{$row.comment_author_city|stripslashes|escape}" /></td>
</tr>
{/if}
<tr>
<td>{#COMMENT_YOUR_TEXT#}</td>
<td>
<div class="pr12">
<textarea style="width:100%; height:170px" name="comment_text" id="in_message">{$row.comment_text}</textarea>
{if $row.comment_show_user_rating == 1}
<tr>
<td>{#COMMENT_RATING_TITEL#}</td>
<td>
<div class="rating-area">
<input type="hidden" name="user_rating" id="user_rating_input" value="{$row.user_rating|default:0}">
{section name=r start=1 loop=6}
<span class="rating-star {if $row.user_rating >= $smarty.section.r.index}active{/if}" data-value="{$smarty.section.r.index}">★</span>
{/section}
<span class="reset-rating" title="{#COMMENT_RATING_RESET#}">×</span>
</div>
</td>
</tr>
{/if}
<tr>
<td>{#COMMENT_FILES#}</td>
<td>
<div id="image_preview_wrapper">
{foreach from=$row.file_list item=file}
{assign var="fileExt" value=$file|substr:-3|lower}
<div class="file-preview-item">
<label class="del-file-btn" title="Удалить">×<input type="checkbox" name="delete_files[]" value="{$file}"></label>
{if $fileExt == 'jpg' || $fileExt == 'png' || $fileExt == 'gif' || $fileExt == 'ebp' || $fileExt == 'peg'}
<img src="{$ABS_PATH}uploads/comments/{$file}" class="file-thumb">
{else}
<div class="ext-placeholder">{$fileExt}</div>
{/if}
<span class="file-name-label">{$file|regex_replace:"/^[0-9]+_/":""}</span>
</div>
{/foreach}
</div>
{if $row.comment_allow_files == 1}
<div class="upload-info-box">
<input type="file" name="comment_image[]" multiple />
<div style="font-size:10px; color:#888; margin-top:5px;">
{#COMMENT_ADD_FILES_ALLOW#}: {$row.comment_allowed_extensions} (max: {$row.comment_max_files})
</div>
<span id="text_counter"></span>&nbsp;{#COMMENT_CHARS_LEFT#}
</td>
</tr>
</div>
{/if}
</td>
</tr>
<input type="hidden" name="do" value="modules" />
<input type="hidden" name="action" value="modedit" />
<input type="hidden" name="mod" value="comment" />
<input type="hidden" name="moduleaction" value="admin_edit" />
<input type="hidden" name="sub" value="send" />
<input type="hidden" name="Id" value="{$smarty.request.Id|escape}" />
<tr>
<td>{#COMMENT_YOUR_TEXT#}*</td>
<td>
<textarea style="width:100%" name="comment_text" id="in_message">{$row.comment_text|stripslashes}</textarea>
<div style="text-align:right; font-size:11px; color:#999; margin-top:5px;">
{#COMMENT_CHARS_LEFT#} <span id="text_counter"></span>
</div>
</td>
</tr>
<tr>
<td colspan="2">
<input type="hidden" name="do" value="modules" />
<input type="hidden" name="action" value="modedit" />
<input type="hidden" name="mod" value="comment" />
<input type="hidden" name="moduleaction" value="admin_edit" />
<input type="hidden" name="sub" value="send" />
<input type="hidden" name="Id" value="{$smarty.request.Id|escape}" />
<tr>
<td colspan="2">
<div id="comment-upload-progress"><div id="upload-bar-fill"></div></div>
<div style="padding:15px 0;">
<input type="submit" class="basicBtn SaveCommentAjax" value="{#COMMENT_BUTTON_EDIT#}" />&nbsp;
<a href="javascript:void(0);" class="button redBtn CloseCommentDialog">{#COMMENT_BUTTON_CANCEL#}</a>
</td>
</tr>
</table>
</form>
{/if}
</div>
</td>
</tr>
</table>
</form>
{/if}
</div>