Release 0.249: banner edit fixes and thumbnail popup

This commit is contained in:
2026-02-08 17:29:52 +01:00
parent 0b80524d71
commit 926b6fcbca
24 changed files with 2273 additions and 47 deletions

View File

@@ -801,4 +801,4 @@ echo $grid -> draw();
});
}
</script>
<script>CKEDITOR.dtd.$removeEmpty['span'] = false;</script>
<script>CKEDITOR.dtd.$removeEmpty['span'] = false;</script>

View File

@@ -85,7 +85,7 @@ ob_start();
'id' => 'src_' . $lg['id'],
'value' => $this -> banner['languages'][ $lg['id'] ]['src'],
'icon_content' => 'przeglądaj',
'icon_js' => "window.open ( 'http://" . $_SERVER['SERVER_NAME'] . "/libraries/filemanager-9.14.2/dialog.php?type=1&popup=1&field_id=src_" . $lg['id'] . "&akey=" . $rfmAkeyJS . "', 'mywindow', 'location=1,status=1,scrollbars=1, width=1100,height=700');"
'icon_js' => "window.open ( '/libraries/filemanager-9.14.2/dialog.php?type=1&popup=1&field_id=src_" . $lg['id'] . "&akey=" . $rfmAkeyJS . "', 'mywindow', 'location=1,status=1,scrollbars=1, width=1100,height=700');"
)
);
?>
@@ -182,4 +182,4 @@ echo $grid -> draw();
});
</script>
<script>CKEDITOR.dtd.$removeEmpty['span'] = false;</script>
<script>CKEDITOR.dtd.$removeEmpty['span'] = false;</script>

View File

@@ -1,5 +1,105 @@
<?= \Tpl::view('components/table-list', ['list' => $this->viewModel]); ?>
<style type="text/css">
.banner-thumb-wrap {
display: inline-block;
}
.banner-thumb-image {
width: 72px;
height: 42px;
object-fit: cover;
border-radius: 4px;
cursor: zoom-in;
}
.banner-thumb-popup {
position: fixed;
top: 0;
left: 0;
width: min(70vw, 760px);
max-height: 80vh;
padding: 6px;
border-radius: 6px;
background: #fff;
box-shadow: 0 14px 30px rgba(0, 0, 0, .35);
z-index: 3000;
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: opacity .1s ease;
}
.banner-thumb-popup.is-visible {
opacity: 1;
visibility: visible;
}
.banner-thumb-popup img {
display: block;
width: 100%;
max-height: calc(80vh - 12px);
object-fit: contain;
border-radius: 4px;
}
</style>
<script type="text/javascript">
(function($) {
if (!$) {
return;
}
var $popup = $('<div class="banner-thumb-popup" aria-hidden="true"><img src="" alt=""></div>');
var $popupImage = $popup.find('img');
$('body').append($popup);
function positionPopup(event) {
var offset = 18;
var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
var popupWidth = $popup.outerWidth();
var popupHeight = $popup.outerHeight();
var left = (event.clientX || 0) + offset;
var top = (event.clientY || 0) + offset;
if (left + popupWidth + 12 > viewportWidth) {
left = Math.max(12, (event.clientX || 0) - popupWidth - offset);
}
if (top + popupHeight + 12 > viewportHeight) {
top = Math.max(12, viewportHeight - popupHeight - 12);
}
$popup.css({ left: left + 'px', top: top + 'px' });
}
$(document).off('.bannerThumbPopup');
$(document).on('mouseenter.bannerThumbPopup', '.js-banner-thumb-preview', function(event) {
var src = $(this).data('previewSrc');
if (!src) {
return;
}
$popupImage.attr('src', String(src));
$popup.addClass('is-visible');
positionPopup(event);
});
$(document).on('mousemove.bannerThumbPopup', '.js-banner-thumb-preview', function(event) {
if ($popup.hasClass('is-visible')) {
positionPopup(event);
}
});
$(document).on('mouseleave.bannerThumbPopup', '.js-banner-thumb-preview', function() {
$popup.removeClass('is-visible');
$popupImage.attr('src', '');
});
})(window.jQuery);
</script>
<?php if (!empty($this->viewModel->customScriptView)): ?>
<?= \Tpl::view($this->viewModel->customScriptView, ['list' => $this->viewModel]); ?>
<?php endif; ?>

View File

@@ -0,0 +1,278 @@
<?php
/**
* Uniwersalny szablon formularza edycji
*
* @var FormEditViewModel $form
*/
use admin\Support\Forms\FormFieldRenderer;
use admin\ViewModels\Forms\FormFieldType;
$form = $this->form;
$renderer = new FormFieldRenderer($form);
// Przygotuj filemanager key
\S::set_session('admin', true);
if (
empty($_SESSION['rfm_akey']) ||
(($_SESSION['rfm_akey_expires'] ?? 0) < time())
) {
$_SESSION['rfm_akey'] = bin2hex(random_bytes(16));
}
$_SESSION['rfm_akey_expires'] = time() + 20 * 60;
$_SESSION['can_use_rfm'] = true;
?>
<script type="text/javascript" src="/libraries/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="/libraries/ckeditor/adapters/jquery.js"></script>
<!-- iCheck -->
<link rel="stylesheet" type="text/css" href="/libraries/grid/plugins/icheck/skins/minimal/minimal.css" />
<link rel="stylesheet" type="text/css" href="/libraries/grid/plugins/icheck/skins/minimal/blue.css" />
<script type="text/javascript" src="/libraries/grid/plugins/icheck/icheck.min.js"></script>
<style>
.icheckbox_minimal-blue { margin-top: 10px; }
</style>
<div class="row">
<div class="col col-xs-12">
<div class="g-container" data="table:<?= $form->formId ?>">
<div class="panel panel-info panel-border top">
<div class="panel-heading">
<span class="panel-title"><?= htmlspecialchars($form->title) ?></span>
</div>
<div class="panel-heading p10 pl15" id="g-menu" style="height: auto;">
<?php foreach ($form->actions as $action): ?>
<?php if ($action->name === 'save'): ?>
<?php if ($form->persist): ?>
<a href="#" id="g-edit-save-close" class="btn btn-system btn-sm"
persist_edit="0"
back_url="<?= htmlspecialchars($action->backUrl ?? '') ?>"
url="<?= htmlspecialchars($action->url) ?>">
<i class="fa fa-check-circle mr5"></i>Zatwierdź i zamknij
</a>
<?php endif; ?>
<a href="#" id="g-edit-save" class="btn btn-success btn-sm"
persist_edit="<?= $form->persist ? '1' : '0' ?>"
back_url="<?= htmlspecialchars($action->backUrl ?? '') ?>"
url="<?= htmlspecialchars($action->url) ?>">
<i class="fa fa-check-circle mr5"></i>Zatwierdź
</a>
<?php elseif ($action->name === 'cancel'): ?>
<a href="<?= htmlspecialchars($action->url) ?>" class="btn btn-dark btn-sm" id="g-edit-cancel">
<i class="fa fa-reply mr5"></i>Wstecz
</a>
<?php else: ?>
<a href="<?= htmlspecialchars($action->url) ?>" class="btn <?= htmlspecialchars($action->cssClass) ?> btn-sm">
<?= htmlspecialchars($action->label) ?>
</a>
<?php endif; ?>
<?php endforeach; ?>
</div>
<div class="panel-body">
<form method="<?= $form->method ?>" id="fg-<?= $form->formId ?>" class="g-form form-horizontal"
action="<?= htmlspecialchars($form->action) ?>" enctype="multipart/form-data">
<input type="hidden" name="_form_id" value="<?= htmlspecialchars($form->formId) ?>">
<?php foreach ($form->hiddenFields as $name => $value): ?>
<input type="hidden" name="<?= htmlspecialchars($name) ?>" value="<?= htmlspecialchars($value ?? '') ?>">
<?php endforeach; ?>
<?php if ($form->hasTabs()): ?>
<!-- Formularz z zakładkami -->
<div id="form-tabs-<?= $form->formId ?>">
<ul class="resp-tabs-list form-tabs">
<?php foreach ($form->tabs as $tab): ?>
<li><i class="fa <?= htmlspecialchars($tab->icon) ?>"></i><?= htmlspecialchars($tab->label) ?></li>
<?php endforeach; ?>
</ul>
<div class="resp-tabs-container form-tabs">
<?php foreach ($form->tabs as $tab): ?>
<div>
<?php
$tabFields = $form->getFieldsForTab($tab->id);
$langSections = $form->getLangSectionsForTab($tab->id);
?>
<?php foreach ($tabFields as $field): ?>
<?= $renderer->renderField($field) ?>
<?php endforeach; ?>
<?php foreach ($langSections as $section): ?>
<?= $renderer->renderLangSection($section) ?>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
</div>
</div>
<?php else: ?>
<!-- Formularz bez zakładek -->
<?php foreach ($form->fields as $field): ?>
<?php if ($field->type === FormFieldType::LANG_SECTION): ?>
<?= $renderer->renderLangSection($field) ?>
<?php else: ?>
<?= $renderer->renderField($field) ?>
<?php endif; ?>
<?php endforeach; ?>
<?php endif; ?>
</form>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(function() {
// Inicjalizacja datepickerów
$('input.date').datetimepicker({
format: "YYYY-MM-DD",
pickTime: false
});
$('input.datetime').datetimepicker({
format: "YYYY-MM-DD HH:mm"
});
// Inicjalizacja zakładek
<?php if ($form->hasTabs()): ?>
$('#form-tabs-<?= $form->formId ?>').easyResponsiveTabs({
width: 'auto',
fit: true,
tabidentify: 'form-tabs',
type: 'vertical'
});
<?php endif; ?>
// Inicjalizacja iCheck
$('.icheck').iCheck({
checkboxClass: 'icheckbox_minimal-blue',
radioClass: 'iradio_minimal-blue'
});
function showFormMessage(type, text) {
var safeText = $('<div/>').text(text || '').html();
var alertClass = type === 'error' ? 'alert-danger' : 'alert-primary';
var html = '' +
'<div class="row js-form-message">' +
'<div class="col col-xs-12">' +
'<div class="alert ' + alertClass + ' alert-dismissable">' +
'<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' +
'<i class="fa fa-info pr10"></i>' + safeText +
'</div>' +
'</div>' +
'</div>';
$('#content .js-form-message').remove();
$('#content').prepend(html);
}
// Obsługa przycisków zapisu
$('#g-edit-save, #g-edit-save-close').on('click', function(e) {
e.preventDefault();
var $btn = $(this);
var url = $btn.attr('url');
var backUrl = $btn.attr('back_url');
var persist = $btn.attr('persist_edit');
var formId = 'fg-<?= $form->formId ?>';
// Synchronizuj zawartosc CKEditor do textarea przed serializacja
if (typeof CKEDITOR !== 'undefined' && CKEDITOR.instances) {
for (var instanceName in CKEDITOR.instances) {
if (Object.prototype.hasOwnProperty.call(CKEDITOR.instances, instanceName)) {
CKEDITOR.instances[instanceName].updateElement();
}
}
}
// Zbierz dane formularza
var formData = $('#' + formId).serialize();
$.ajax({
url: url,
type: 'POST',
data: formData,
dataType: 'json',
success: function(response) {
if (response.success) {
var successMessage = response.message || 'Zmiany zostały zapisane.';
if (backUrl && persist === '0') {
window.location.href = backUrl;
} else {
showFormMessage('success', successMessage);
}
} else {
var errors = response.errors ? Object.values(response.errors).join(', ') : 'Błąd walidacji';
showFormMessage('error', 'Błąd: ' + errors);
}
},
error: function(xhr, status, error) {
// Fallback - tradycyjne submit formularza
$('#' + formId).attr('action', url).submit();
}
});
});
disable_menu();
});
</script>
<?php
// Renderowanie CKEditor dla pól edytora (zwykłych)
foreach ($form->fields as $field):
if ($field->type === FormFieldType::EDITOR):
?>
<script type="text/javascript">
$(function() {
$('#<?= $field->id ?>').ckeditor({
toolbar: '<?= $field->editorToolbar ?>',
height: '<?= $field->editorHeight ?>'
});
});
</script>
<?php
endif;
endforeach;
?>
<?php if ($form->hasLangSections()): ?>
<script type="text/javascript">
$(function() {
// Inicjalizacja zakładek językowych
$('[id^="languages-"].languages-tabs').each(function() {
$(this).easyResponsiveTabs({
width: 'auto',
fit: true,
tabidentify: 'languages-tabs',
type: 'horizontal'
});
});
// Inicjalizacja CKEditor dla pól w sekcjach językowych
<?php
foreach ($form->fields as $section):
if ($section->type === FormFieldType::LANG_SECTION && $section->langFields):
foreach ($section->langFields as $langField):
if ($langField->type === FormFieldType::EDITOR && $form->languages):
foreach ($form->languages as $lang):
if ($lang['status']):
?>
$('#<?= $langField->getLocalizedId($lang['id']) ?>').ckeditor({
toolbar: '<?= $langField->editorToolbar ?>',
height: '<?= $langField->editorHeight ?>'
});
<?php
endif;
endforeach;
endif;
endforeach;
endif;
endforeach;
?>
});
</script>
<?php endif; ?>
<script>CKEDITOR.dtd.$removeEmpty['span'] = false;</script>

View File

@@ -1 +1 @@
<iframe src="/libraries/filemanager-9.14.2/dialog.php?akey=c3cb2537d25c0efc9e573d059d79c3b8" style="border: 0px; width: 100%; height: 800px; background: #FFF; padding: 5px;"></iframe>
<iframe src="/libraries/filemanager-9.14.2/dialog.php?akey=c3cb2537d25c0efc9e573d059d79c3b8" style="border: 0px; width: 100%; height: 800px; background: #FFF; padding: 5px;"></iframe>

View File

@@ -15,7 +15,7 @@
$out .= 'id="' . $this -> params['id'] . '" ';
else
$out .= 'id="' . $this -> params['name'] . '" ';
$out .= 'name="' . $this -> params['name'] . '" type="checkbox"';
$out .= 'name="' . $this -> params['name'] . '" type="checkbox" value="1"';
if ( $this -> params['checked'] )
$out .= 'checked="checked" ';

View File

@@ -36,7 +36,7 @@ ob_start();
'id' => 'img',
'value' => $this -> producer['img'],
'icon_content' => 'przeglądaj',
'icon_js' => "window.open ( 'http://" . $_SERVER['SERVER_NAME'] . "/libraries/filemanager-9.14.2/dialog.php?type=1&popup=1&field_id=img&akey=" . $rfmAkeyJS . "', 'mywindow', 'location=1,status=1,scrollbars=1, width=1100,height=700');"
'icon_js' => "window.open ( '/libraries/filemanager-9.14.2/dialog.php?type=1&popup=1&field_id=img&akey=" . $rfmAkeyJS . "', 'mywindow', 'location=1,status=1,scrollbars=1, width=1100,height=700');"
] );
?>
</div>
@@ -177,4 +177,4 @@ echo $grid -> draw();
tabidentify: 'languages-main'
});
});
</script>
</script>

View File

@@ -1343,4 +1343,4 @@ echo $grid->draw();
</script>
<script>
CKEDITOR.dtd.$removeEmpty['span'] = false;
</script>
</script>