fixes #2486 add stdPgs config tab in admin

add skins and screenshots for skins
add admin tpl and css
update stdPgs tpl to have dynamic header section
This commit is contained in:
HWFord
2025-12-19 16:05:24 +01:00
parent 0c92a8ba33
commit 27caef885e
49 changed files with 4335 additions and 68 deletions

View File

@@ -162,6 +162,7 @@ function add_core_tabs($sheets, $tab_id)
$sheets['update'] = array('caption' => '<span class="icon-arrows-cw"></span>'.l10n('Check for updates'), 'url' => $my_base_url.'&amp;tab=update');
$sheets['new'] = array('caption' => '<span class="icon-plus-circled"></span>'.l10n('Add New Theme'), 'url' => $my_base_url.'&amp;tab=new');
}
$sheets['standard_pages'] = array('caption' => '<span class="icon-cog-alt"></span>'.l10n('Standard pages'), 'url' => $my_base_url.'&amp;tab=standard_pages');
break;
case 'updates':

View File

@@ -373,7 +373,6 @@ SELECT
'mobile' => false,
);
$theme_data = implode('', file($path.'/themeconf.inc.php'));
if (preg_match("|Theme Name:\\s*(.+)|", $theme_data, $val))
{
$theme['name'] = trim( $val[1] );
@@ -419,6 +418,10 @@ SELECT
{
$theme['mobile'] = get_boolean($val[1]);
}
if (preg_match('/["\']use_standard_pages["\'].*?(true|false)/i', $theme_data, $val))
{
$theme['use_standard_pages'] = get_boolean($val[1]);
}
// screenshot
$screenshot_path = $path.'/screenshot.png';

View File

@@ -252,18 +252,6 @@ jQuery("input[name='email_admin_on_new_user_filter']").change(function() {
<span class="icon-help-circled tiptip" title="{'During upload, if Piwigo detects the photo already exists, associate the existing photo to the destination album, without duplicating file'|translate}" style="cursor:help"></span>
</li>
<li>
<label class="font-checkbox">
<span class="icon-check"></span>
<input type="checkbox" name="use_standard_pages" {if ($main.use_standard_pages)}checked="checked"{/if}>
{'Use standard Piwigo template for common pages.'|translate}
</label>
<span class="icon-help-circled tiptip" title="{'When enabled, a common template is used for the login, registration and forgotten password pages, regardless of the theme. Some themes might use these templates even if you uncheck this option'|translate}" style="cursor:help"></span>
</li>
<li>
<label>{'Mail theme'|translate}</label>

View File

@@ -0,0 +1,195 @@
{combine_script id='common' load='footer' path='admin/themes/default/js/common.js'}
<section class="std_pgs">
<form method="post" action="{$F_ACTION}" class="properties" enctype="multipart/form-data">
<fieldset class="std_pgs_conf">
<legend><span class="icon-cog icon-purple"></span>{'Basic settings'|translate}</legend>
<ul>
<li>
<label class="font-checkbox">
<span class="icon-check"></span>
<input type="checkbox" name="use_standard_pages" {if $use_standard_pages }checked="checked"{/if}>
{'Use standard Piwigo template for common pages.'|translate}
</label>
<span class="icon-help-circled tiptip" title="{'When enabled, a common template is used for the login, registration and forgotten password pages, regardless of the theme. Some themes might use these templates even if you uncheck this option'|translate}" style="cursor:help"></span>
</li>
</ul>
</fieldset>
{if $is_standard_pages_used and !$use_standard_pages}
<div class="std_pgs_theme_info warnings">
<p class="">{'Standard pages aren\'t activated, however you have %d active themes that will still use them. These themes are:'|translate:count($standard_pages_used_by)} </p>
<ul>
{foreach $standard_pages_used_by as $theme_name}
<li>{$theme_name}</li>
{/foreach}
</ul>
</div>
{/if}
<fieldset class="std_pgs_personnalisation_settings">
<legend><span class="icon-dice-solid icon-green"></span>{'Personalization settings'|translate}</legend>
<ul>
<li>
<div class="std_pgs_header_options">
<strong>{'Standard pages header'|translate}</strong>
<br>
<label class="font-checkbox no-bold">
<span class="icon-dot-circled"></span>
<input type="radio" name="std_pgs_display_logo" value="piwigo_logo" {if "piwigo_logo" == $std_pgs_selected_logo}checked="checked"{/if}>
{'Use Piwigo logo'|translate}
</label>
<label class="font-checkbox no-bold" id="custom_logo_option">
<span class="icon-dot-circled"></span>
<input type="radio" name="std_pgs_display_logo" value="custom_logo" {if "custom_logo" == $std_pgs_selected_logo}checked="checked"{/if}>
{'Use custom logo (png, jpeg or svg)'|translate}
<div class="custom_logo_preview {if "custom_logo" == $std_pgs_selected_logo}show{else}hide{/if}">
{if isset($std_pgs_selected_logo_path)}
<div class="change_logo_container">
<img src="{$std_pgs_selected_logo_path}">
<a href="#" id="change_logo">{'Change logo'|translate}</a>
</div>
{/if}
<div class="use_existing_logo_container {if isset($std_pgs_selected_logo_path)}hide{/if}">
<input type="file" size="60" id="std_pgs_logo" name="std_pgs_logo" accept="image/*" />
<a href="#" id="use_existing_logo">{'Cancel'|translate}</a>
</div>
</div>
</label>
<label class="font-checkbox no-bold">
<span class="icon-dot-circled"></span>
<input type="radio" name="std_pgs_display_logo" value="gallery_title" {if "gallery_title" == $std_pgs_selected_logo}checked="checked"{/if}>
{'Display Gallery title'|translate}
</label>
<label class="font-checkbox no-bold">
<span class="icon-dot-circled"></span>
<input type="radio" name="std_pgs_display_logo" value="none" {if "none" == $std_pgs_selected_logo}checked="checked"{/if}>
{'None'|translate}
</label>
</div>
</li>
<li>
<div class="skin_choice">
<strong>{'Select a color theme for standard pages'|translate}</strong>
<div class="std_pgs_previews">
<input type="hidden" name="std_pgs_selected_skin" value="{$std_pgs_selected_skin}">
<div class="std_pgs_mini_previews">
{foreach $std_pgs_skin_options as $std_pgs_skin_option}
<img class="{if $std_pgs_selected_skin == $std_pgs_skin_option}selected{/if}" id="{$std_pgs_skin_option}" src="themes/standard_pages/skins/light-{$std_pgs_skin_option}.jpg">
{/foreach}
</div>
<div class="std_pgs_selected_preview">
<div class="std_pgs_selected_preview_container">
<h5>{'Light mode'|translate}</h5>
<img id="preview-light" src="themes/standard_pages/skins/light-{$std_pgs_selected_skin}.jpg">
</div>
<div class="std_pgs_selected_preview_container">
<h5>{'Dark mode'|translate}</h5>
<img id="preview-dark" src="themes/standard_pages/skins/dark-{$std_pgs_selected_skin}.jpg">
</div>
</div>
</div>
</div>
</li>
</ul>
</fieldset>
<div class="savebar-footer">
<div class="savebar-footer-start">
</div>
<div class="savebar-footer-end">
{if isset($save_success)}
<div class="savebar-footer-block">
<div class="badge info-message">
<i class="icon-ok"></i>{$save_success}
</div>
</div>
{/if}
{if isset($save_error)}
<div class="savebar-footer-block">
<div class="badge info-warning">
<i class="icon-attention"></i>{$save_error}
</div>
</div>
{/if}
<div class="savebar-footer-block">
<button class="buttonLike" type="submit" name="submit" {if $isWebmaster != 1}disabled{/if}><i class="icon-floppy"></i> {'Save Settings'|@translate}</button>
</div>
</div>
<input type="hidden" name="pwg_token" value="{$PWG_TOKEN}">
</div>
</form>
</section>
{footer_script}
// Update preview when user clicks on mini previews
jQuery(".std_pgs_mini_previews img").click(function () {
//Make selected skin outlined
jQuery(".std_pgs_mini_previews img").removeClass('selected');
jQuery(this).addClass('selected');
//Update preview when useer clicks on mini
jQuery('input[name=std_pgs_selected_skin]').val(jQuery(this).attr('id'));
let preview_light_path = "themes/standard_pages/skins/light-"+$(this).attr('id')+".jpg";
let preview_dark_path = "themes/standard_pages/skins/dark-"+$(this).attr('id')+".jpg";
jQuery('.std_pgs_selected_preview img#preview-light').attr("src", preview_light_path);
jQuery('.std_pgs_selected_preview img#preview-dark').attr("src", preview_dark_path);
});
jQuery("input[name=std_pgs_display_logo]").click(function () {
if('custom_logo' == jQuery(this).val())
{
// jQuery('#std_pgs_logo').addClass('show').removeClass('hide');
jQuery('.custom_logo_preview').addClass('show').removeClass('hide');
}
else
{
// jQuery('#std_pgs_logo').addClass('hide').removeClass('show');
jQuery('.custom_logo_preview').addClass('hide').removeClass('show');
}
});
// Scroll mini to show the selected one
jQuery(document).ready(function () {
const std_pgs_mini_previews = jQuery('.std_pgs_mini_previews');
const selected_mini = std_pgs_mini_previews.find('.selected');
if (selected_mini.length) {
std_pgs_mini_previews.scrollTop(
selected_mini.position().top + std_pgs_mini_previews.scrollTop()
);
}
});
//Switch between change logo and use existing logo
jQuery('#change_logo').click(function () {
jQuery('.use_existing_logo_container').show();
jQuery('.change_logo_container').hide();
});
jQuery('#use_existing_logo').click(function () {
jQuery('.change_logo_container').show();
jQuery('.use_existing_logo_container').hide();
jQuery('#std_pgs_logo').val('');
});
{/footer_script}

View File

@@ -8498,4 +8498,107 @@ color:#FF7B00;
.mcs-icon-options::before{
margin-right: 5px;
}
/* Standard pages configuration */
.std_pgs{
padding-bottom:60px;
}
.std_pgs_previews{
display:flex;
flex-direction:row;
margin-top:15px;
}
.std_pgs_mini_previews{
display:flex;
flex-direction: column;
overflow:auto;
width:15%;
max-height:500px;
}
.std_pgs_personnalisation_settings .std_pgs_mini_previews img{
max-height:100px;
object-fit:contain;
}
.std_pgs_selected_preview{
text-align:center;
display:flex;
width:85%;
margin-left:15px;
align-items:center;
}
.std_pgs_selected_preview img{
max-height: 500px;
width: 100%;
height: auto;
object-fit: contain;
}
.std_pgs_mini_previews img{
border:4px solid transparent;
cursor:pointer
}
.std_pgs_mini_previews img:hover,
.std_pgs_mini_previews img.selected{
border: 4px solid #FFA646;
}
.use_existing_logo_container.hide,
.custom_logo_preview.hide{
display:none;
}
#change_logo,
#use_existing_logo,
.use_existing_logo_container,
.change_logo_container{
margin-left:30px;
margin-bottom:5px;
}
.custom_logo_preview.show{
display:flex;
align-items:center;
}
.std_pgs_theme_info.warnings{
display:block;
}
.std_pgs_theme_info.warnings p{
text-align:left;
}
.std_pgs_theme_info.warnings li{
list-style:inside;
}
.custom_logo_preview{
display:flex;
align-items:center;
color:#777;
}
.custom_logo_preview img{
max-height:30px
}
.custom_logo_preview p{
margin:0;
}
.std_pgs_header_options{
display:flex;
flex-direction:column;
}
.skin_choice{
padding-top:30px;
}

View File

@@ -0,0 +1,177 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
global $template, $conf;
// +-----------------------------------------------------------------------+
// | Update standard pages configuration |
// +-----------------------------------------------------------------------+
$std_pgs_logo_options = array(
"piwigo_logo",
"custom_logo",
"gallery_title",
"none",
);
$std_pgs_skin_options = array(
"default",
"cadmium",
"cobalt",
"fuchsia",
"green",
"lime",
"purple",
"red",
"sienna",
"silver",
"teal",
);
if (isset($_POST['submit']) and !empty($_POST))
{
check_pwg_token();
//use_standard_pages or not
conf_update_param('use_standard_pages', !empty($_POST['use_standard_pages']), true);
//save selected logo
if(isset($_POST['std_pgs_display_logo']) and in_array($_POST['std_pgs_display_logo'], $std_pgs_logo_options))
{
conf_update_param('standard_pages_selected_logo', $_POST['std_pgs_display_logo'], true);
}
//save selected skin
if(isset($_POST['std_pgs_selected_skin']) and in_array($_POST['std_pgs_selected_skin'], $std_pgs_skin_options))
{
conf_update_param('standard_pages_selected_skin', $_POST['std_pgs_selected_skin'], true);
}
};
//Handle logo upload, allow png, jpg and svg
if (isset($_FILES['std_pgs_logo']) and !empty($_FILES['std_pgs_logo']['tmp_name']))
{
// if (function_exists('mime_content_type'))
// {
$mime_type = mime_content_type($_FILES['std_pgs_logo']['tmp_name']);
// Allowed MIME types
$allowed_mimes = array(
'image/png',
'image/jpeg',
'image/svg+xml',
'image/svg'
);
// Only get image size for raster images aka png and jpg,
// exclude svg because getimagesize dones't work on svg
if ($mime_type !== 'image/svg+xml' && $mime_type !== 'image/svg')
{
$image_info = getimagesize($_FILES['std_pgs_logo']['tmp_name']);
if ($image_info === false)
{
$template->assign(array(
'save_error' => l10n('Invalid image file.')
));
return;
}
list($width, $height, $type) = $image_info;
}
$upload_dir = PHPWG_ROOT_PATH . PWG_LOCAL_DIR . 'logo';
if (mkgetdir($upload_dir, MKGETDIR_DEFAULT & ~MKGETDIR_DIE_ON_ERROR))
{
$pathinfo = pathinfo($_FILES['std_pgs_logo']['name']);
$filename = str2url($pathinfo['filename']);
$extension = strtolower($pathinfo['extension']);
$new_name = $filename . '.' . $extension;
$file_path = $upload_dir . '/' . $new_name;
//Save logo path to conf
conf_update_param('standard_pages_selected_logo_path', $file_path, true);
if (move_uploaded_file($_FILES['std_pgs_logo']['tmp_name'], $file_path))
{
$logo['file'] = substr($file_path, strlen(PHPWG_ROOT_PATH));
}
else
{
$template->assign(array(
'save_error' => "$file_path " . l10n('no write access'),
));
}
// }
}
else
{
$template->assign(array(
'save_error' => sprintf(
l10n('Add write access to the "%s" directory'),
$upload_dir
),
));
}
}
//We want to now if any themes use standard pages and which ones
include_once(PHPWG_ROOT_PATH.'admin/include/themes.class.php');
$themes = new themes();
$themes->get_fs_themes();
$is_standard_pages_used = false;
$standard_pages_used_by = array();
foreach ($themes->fs_themes as $theme)
{
if (isset($theme['use_standard_pages']) and $theme['use_standard_pages'])
{
$is_standard_pages_used = true;
array_push($standard_pages_used_by, $theme['name']);
}
}
// +-----------------------------------------------------------------------+
// | template output |
// +-----------------------------------------------------------------------+
//Send all info to template
$template->assign(
array(
'use_standard_pages' => conf_get_param('use_standard_pages', true),
'std_pgs_selected_logo' => conf_get_param('standard_pages_selected_logo', 'piwigo_logo'),
'std_pgs_logo_options' => $std_pgs_logo_options,
'std_pgs_selected_skin' => conf_get_param('standard_pages_selected_skin', 'default'),
'std_pgs_skin_options' => $std_pgs_skin_options,
'is_standard_pages_used' => $is_standard_pages_used,
'standard_pages_used_by' => $standard_pages_used_by,
'std_pgs_selected_logo_path' => conf_get_param('standard_pages_selected_logo_path', null),
'PWG_TOKEN' => get_pwg_token(),
)
);
$template->assign('isWebmaster', (is_webmaster()) ? 1 : 0);
$template->set_filenames(array('themes' => 'themes_standard_pages.tpl'));
$template->assign('ADMIN_PAGE_TITLE', l10n('Themes'));
$template->assign_var_from_handle('ADMIN_CONTENT', 'themes');
?>