Merge pull request #29 from HB9HIL/themes_menu

Themes menu
This commit is contained in:
HB9HIL
2024-01-26 11:03:44 +01:00
committed by GitHub
8 changed files with 418 additions and 180 deletions

View File

@@ -36,9 +36,11 @@ class Themes extends CI_Controller {
$this->load->model('Themes_model');
$this->load->library('form_validation');
$this->form_validation->set_rules('name', 'Theme Name', 'required');
$this->form_validation->set_rules('foldername', 'Folder Name', 'required');
$this->form_validation->set_rules('theme_mode', 'Theme Mode', 'required');
$this->form_validation->set_rules('name', 'Theme Name', 'required|callback_character_check');
$this->form_validation->set_rules('foldername', 'Folder Name', 'required|callback_character_check');
$this->form_validation->set_rules('theme_mode', 'Theme Mode', 'required|callback_character_check');
$this->form_validation->set_rules('header_logo', 'Header Logo', 'required|callback_character_check');
$this->form_validation->set_rules('main_logo', 'Main Logo', 'required|callback_character_check');
if ($this->form_validation->run() == FALSE)
{
@@ -63,21 +65,21 @@ class Themes extends CI_Controller {
$data['page_title'] = "Edit Theme";
$this->form_validation->set_rules('name', 'Theme Name', 'required');
$this->form_validation->set_rules('foldername', 'Folder Name', 'required');
$this->form_validation->set_rules('theme_mode', 'Theme Mode', 'required');
$this->form_validation->set_rules('name', 'Theme Name', 'required|callback_character_check');
$this->form_validation->set_rules('foldername', 'Folder Name', 'required|callback_character_check');
$this->form_validation->set_rules('theme_mode', 'Theme Mode', 'required|callback_character_check');
$this->form_validation->set_rules('header_logo', 'Header Logo', 'required|callback_character_check');
$this->form_validation->set_rules('main_logo', 'Main Logo', 'required|callback_character_check');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('interface_assets/header', $data);
$this->load->view('themes/edit');
$this->load->view('interface_assets/footer');
$this->load->view('themes/edit', $data);
}
else
{
$this->Themes_model->edit($item_id_clean);
$this->session->set_flashdata("success", "Theme '".$this->security->xss_clean($this->input->post('name', true))."' updated");
$this->session->set_flashdata("success", "Theme updated");
redirect('themes');
}
@@ -88,4 +90,48 @@ class Themes extends CI_Controller {
$this->load->model('Themes_model');
$this->Themes_model->delete($id);
}
function character_check() {
$input_name = $this->input->post('name');
$input_foldername = $this->input->post('foldername');
$input_theme_mode = $this->input->post('theme_mode');
$input_header_logo = $this->input->post('header_logo');
$input_main_logo = $this->input->post('main_logo');
if ($input_name !== null && preg_match('/^[^\/:\*\?"<>\|@.]*$/', $input_name)) {
return true;
} else {
$this->session->set_flashdata('danger', 'Invalid value for ' . $input_name . '.');
return false;
}
if ($input_foldername !== null && preg_match('/^[^\/:\*\?"<>\|@.]*$/', $input_foldername)) {
return true;
} else {
$this->session->set_flashdata('danger', 'Invalid value for ' . $input_foldername . '.');
return false;
}
if ($input_theme_mode !== null && preg_match('/^[^\/:\*\?"<>\|@.]*$/', $input_theme_mode)) {
return true;
} else {
$this->session->set_flashdata('danger', 'Invalid value for ' . $input_theme_mode . '.');
return false;
}
if ($input_header_logo !== null && preg_match('/^[^\/:\*\?"<>\|@.]*$/', $input_header_logo)) {
return true;
} else {
$this->session->set_flashdata('danger', 'Invalid value for ' . $input_header_logo . '.');
return false;
}
if ($input_main_logo !== null && preg_match('/^[^\/:\*\?"<>\|@.]*$/', $input_main_logo)) {
return true;
} else {
$this->session->set_flashdata('danger', 'Invalid value for ' . $input_main_logo . '.');
return false;
}
}
}

View File

@@ -22,6 +22,8 @@ class Themes_model extends CI_Model {
'name' => xss_clean($this->input->post('name', true)),
'foldername' => xss_clean($this->input->post('foldername', true)),
'theme_mode' => xss_clean($this->input->post('theme_mode', true)),
'header_logo' => xss_clean($this->input->post('header_logo', true)),
'main_logo' => xss_clean($this->input->post('main_logo', true)),
);
$this->db->insert('themes', $data);
@@ -44,6 +46,8 @@ class Themes_model extends CI_Model {
'name' => xss_clean($this->input->post('name', true)),
'foldername' => xss_clean($this->input->post('foldername', true)),
'theme_mode' => xss_clean($this->input->post('theme_mode', true)),
'header_logo' => xss_clean($this->input->post('header_logo', true)),
'main_logo' => xss_clean($this->input->post('main_logo', true)),
);
$this->db->where('id', $id);

View File

@@ -2927,70 +2927,7 @@ function viewEqsl(picture, callsign) {
<?php } ?>
<?php if ($this->uri->segment(1) == "themes") { ?>
<script>
function deleteTheme(id, name) {
BootstrapDialog.confirm({
title: 'DANGER',
message: 'Warning! Are you sure you want to delete the following theme: ' + name + '?' ,
type: BootstrapDialog.TYPE_DANGER,
closable: true,
draggable: true,
btnOKClass: 'btn-danger',
callback: function(result) {
if(result) {
$.ajax({
url: base_url + 'index.php/themes/delete',
type: 'post',
data: {'id': id
},
success: function(data) {
$(".theme_" + id).parent("tr:first").remove(); // removes mode from table
}
});
}
}
});
}
function addThemeDialog() {
$.ajax({
url: base_url + 'index.php/themes/add',
type: 'post',
success: function(html) {
BootstrapDialog.show({
title: 'Create Theme',
size: BootstrapDialog.SIZE_WIDE,
cssClass: 'create-theme-dialog',
nl2br: false,
message: html,
buttons: [{
label: lang_admin_close,
action: function (dialogItself) {
dialogItself.close();
}
}]
});
}
});
}
function addTheme(form) {
if (form.name.value != '') {
$.ajax({
url: base_url + 'index.php/themes/add',
type: 'post',
data: {
'name': form.name.value,
'foldername': form.foldername.value,
'theme_mode': form.theme_mode.value,
},
success: function(html) {
location.reload();
}
});
}
}
</script>
<script src="<?php echo base_url() ;?>assets/js/sections/themes.js"></script>
<?php } ?>

View File

@@ -1,25 +1,5 @@
<div class="container" id="create_mode">
<br>
<?php if($this->session->flashdata('message')) { ?>
<!-- Display Message -->
<div class="alert-message error">
<p><?php echo $this->session->flashdata('message'); ?></p>
</div>
<?php } ?>
<?php if($this->session->flashdata('notice')) { ?>
<div id="message" >
<?php echo $this->session->flashdata('notice'); ?>
</div>
<?php } ?>
<?php $this->load->helper('form'); ?>
<?php echo validation_errors(); ?>
<form>
<div class="container">
<form id="ThemeForm">
<div class="mb-3">
<label for="nameInput">Theme Name</label>
<input type="text" class="form-control" name="name" id="nameInput" aria-describedby="nameInputHelp" required>
@@ -38,9 +18,21 @@
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
<small id="themeModeInputHelp" class="form-text text-muted">This defines wherever the theme is a light or a dark one. On this basis the Logo is chosen.</small>
<small id="themeModeInputHelp" class="form-text text-muted">This defines wherever the theme is a light or a dark one.</small>
</div>
<button type="button" onclick="addTheme(this.form);" class="btn btn-primary"><i class="fas fa-plus-square"></i> Add theme</button>
<div class="mb-3">
<label for="headerLogoInput">Header Logo</label>
<input type="text" class="form-control" name="header_logo" id="headerLogoInput" aria-describedby="headerLogoInputHelp">
<small id="headerLogoInputHelp" class="form-text text-muted">This is the name of the file which is used as <u>small</u> Logo in the header placed in assets/logo.<br>Only PNG files with a size ratio of 1:1 are allowed.</small>
</div>
<div class="mb-3">
<label for="mainLogoInput">Main Logo</label>
<input type="text" class="form-control" name="main_logo" id="mainLogoInput" aria-describedby="mainLogoInputHelp">
<small id="mainLogoInputHelp" class="form-text text-muted">This is the name of the file which is used as <u>big</u> Logo in the login screen placed in assets/logo.<br>Only PNG files with a size ratio of 1:1 are allowed.</small>
</div>
<div class="alert alert-warning" role="alert" id="warningMessageTheme" style="display: none"> </div>
<button id="submitButton" type="button" onclick="addTheme(this.form);" class="btn btn-primary"><i class="fas fa-plus-square"></i> Add theme</button>
</form>
</div>
</div>

View File

@@ -1,59 +1,38 @@
<div class="container">
<br>
<?php if($this->session->flashdata('message')) { ?>
<!-- Display Message -->
<div class="alert-message error">
<p><?php echo $this->session->flashdata('message'); ?></p>
<form id="ThemeForm">
<div class="mb-3">
<label for="themenameInput">Theme Name</label>
<input type="text" class="form-control" name="name" id="nameInput" aria-describedby="themenameInputHelp" value="<?php if(set_value('name') != "") { echo set_value('name'); } else { echo $theme->name; } ?>">
<small id="themenameInputHelp" class="form-text text-muted">This is the name that is used to display the theme in the theme list.</small>
</div>
<?php } ?>
<div class="card">
<div class="card-header">
<?php echo $page_title; ?>
<div class="mb-3">
<label for="foldernameInput">Folder Name</label>
<input type="text" class="form-control" name="foldername" id="foldernameInput" aria-describedby="foldernameInputHelp" value="<?php if(set_value('foldername') != "") { echo set_value('foldername'); } else { echo $theme->foldername; } ?>">
<small id="foldernameInputHelp" class="form-text text-muted">This is the name of the folder where your CSS-files are placed under assets/css.</small>
</div>
<div class="card-body">
<h5 class="card-title"></h5>
<p class="card-text"></p>
<?php if($this->session->flashdata('notice')) { ?>
<div id="message" >
<?php echo $this->session->flashdata('notice'); ?>
</div>
<?php } ?>
<?php $this->load->helper('form'); ?>
<?php echo validation_errors(); ?>
<form method="post" action="<?php echo site_url('themes/edit/'); ?><?php echo $theme->id; ?>" name="edit_theme">
<div class="mb-3">
<label for="themenameInput">Theme Name</label>
<input type="text" class="form-control" name="name" id="nameInput" aria-describedby="themenameInputHelp" value="<?php if(set_value('name') != "") { echo set_value('name'); } else { echo $theme->name; } ?>" required>
<small id="themenameInputHelp" class="form-text text-muted">This is the name that is used to display the theme in the theme list.</small>
</div>
<div class="mb-3">
<label for="foldernameInput">Folder Name</label>
<input type="text" class="form-control" name="foldername" id="foldernameInput" aria-describedby="foldernameInputHelp" value="<?php if(set_value('foldername') != "") { echo set_value('foldername'); } else { echo $theme->foldername; } ?>">
<small id="foldernameInputHelp" class="form-text text-muted">This is the name of the folder where your CSS-files are placed under assets/css.</small>
</div>
<div class="mb-3">
<label for="themeModeInput">Theme Mode</label>
<select class="form-select" id="themeModeInput" name="theme_mode">
<option value="light" <?php if ($theme->theme_mode == 'light') { echo " selected =\"selected\""; } ?>>Light</option>
<option value="dark" <?php if ($theme->theme_mode == 'dark') { echo " selected =\"selected\""; } ?>>Dark</option>
</select>
<small id="themeModeInputHelp" class="form-text text-muted">This defines wherever the theme is a light or a dark one. On this basis the Logo is chosen.</small>
</div>
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-plus-square"></i> Update Theme</button>
</form>
<div class="mb-3">
<label for="themeModeInput">Theme Mode</label>
<select class="form-select" id="themeModeInput" name="theme_mode">
<option value="light" <?php if ($theme->theme_mode == 'light') { echo " selected =\"selected\""; } ?>>Light</option>
<option value="dark" <?php if ($theme->theme_mode == 'dark') { echo " selected =\"selected\""; } ?>>Dark</option>
</select>
<small id="themeModeInputHelp" class="form-text text-muted">This defines wherever the theme is a light or a dark one. On this basis the Logo is chosen.</small>
</div>
</div>
<br>
<div class="mb-3">
<label for="headerLogoInput">Header Logo</label>
<input type="text" class="form-control" name="header_logo" id="headerLogoInput" aria-describedby="headerLogoInputHelp" value="<?php if(set_value('header_logo') != "") { echo set_value('header_logo'); } else { echo $theme->header_logo; } ?>">
<small id="headerLogoInputHelp" class="form-text text-muted">This is the name of the file which is used as <u>small</u> Logo in the header placed in assets/logo.<br>Only PNG files with a size ratio of 1:1 are allowed.</small>
</div>
<div class="mb-3">
<label for="mainLogoInput">Main Logo</label>
<input type="text" class="form-control" name="main_logo" id="mainLogoInput" aria-describedby="mainLogoInputHelp" value="<?php if(set_value('main_logo') != "") { echo set_value('main_logo'); } else { echo $theme->main_logo; } ?>">
<small id="mainLogoInputHelp" class="form-text text-muted">This is the name of the file which is used as <u>big</u> Logo in the login screen placed in assets/logo.<br>Only PNG files with a size ratio of 1:1 are allowed.</small>
</div>
<div class="alert alert-warning" role="alert" id="warningMessageTheme" style="display: none"> </div>
<button id="submitButton" type="button" onclick="editTheme(this.form, '<?php echo $theme->id; ?>');" class="btn btn-primary"><i class="fas fa-plus-square"></i> Update theme</button>
</form>
</div>

View File

@@ -1,14 +1,14 @@
<div class="container">
<br>
<?php if($this->session->flashdata('danger')) { ?>
<?php if ($this->session->flashdata('danger')) { ?>
<!-- Display Message -->
<div class="alert alert-danger">
<p><?php echo $this->session->flashdata('danger'); ?></p>
</div>
<?php } ?>
<?php if($this->session->flashdata('success')) { ?>
<?php if ($this->session->flashdata('success')) { ?>
<!-- Display Message -->
<div class="alert alert-success">
<p><?php echo $this->session->flashdata('success'); ?></p>
@@ -22,43 +22,97 @@
Themes list
</div>
<div class="card-body">
<p class="card-text">
Using the theme list, you can control which Themes are shown in the account settings. Deleting a theme here, does not delete the css theme folder.
</p>
<div class="card-text border-bottom mb-2 mt-2">
<div class="row">
<div class="col">
<p>In this menu you can add and edit themes to Wavelog. The process of adding a theme is not really straightforward and should only be done by an admin who is aware of their actions.<br>
Also, it has to be said that this feature is still under development.<br></p>
</div>
</div>
<div class="row">
<div class="col">
<h5>Process of adding a new theme</h5>
</div>
</div>
<div class="row">
<div class="col-md-2">
<h6>1. Step</h6>
</div>
<div class="col-md-10">
<p>Create a new folder in 'assets/css/' and upload a 'bootstrap.min.css' file which contains basic styling rules. We use the themes from <a href="https://bootswatch.com/" target="_blank">https://bootswatch.com/</a></p>
</div>
</div>
<div class="row">
<div class="col-md-2">
<h6>2. Step</h6>
</div>
<div class="col-md-10">
<p>Create a file in this folder called 'overrides.css'. Place your custom CSS code in there.</p>
</div>
</div>
<div class="row">
<div class="col-md-2">
<h6>3. Step</h6>
</div>
<div class="col-md-10">
<p>For each new theme, you need two logo files. One for the login screen and one for the header.<br>
Only PNG files are allowed, and they should have a pixel ratio of 1:1 (e.g., 1000px height and 1000px width).<br>
Place the two logo files in the folder 'assets/logo/'</p>
</div>
</div>
<div class="row">
<div class="col-md-2">
<h6>4. Step</h6>
</div>
<div class="col-md-10">
<p>Click here on 'Add a Theme' and type in the necessary data. Type in the filenames for the logos <b>without</b> the file extension '.png'</p>
</div>
</div>
</div>
<div class="table-responsive">
<table style="width:100%" class="contesttable table table-sm table-striped">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Foldername</th>
<th scope="col">Theme Mode</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
<tr>
<th scope="col">Name</th>
<th scope="col">Foldername</th>
<th scope="col">Theme Mode</th>
<th scope="col">Header Logo</th>
<th scope="col">Main Logo</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<?php foreach ($themes as $theme) { ?>
<tr>
<td><?php echo $theme->name;?></td>
<td><?php echo $theme->foldername;?></td>
<td><?php if($theme->theme_mode != "") {
echo $theme->theme_mode;
} else {
echo "<span class=\"text-danger\">Theme-Mode undefined! Please edit</span>";
} ?></td>
<td>
<a href="<?php echo site_url('themes/edit')."/".$theme->id; ?>" class="btn btn-outline-primary btn-sm"><i class="fas fa-edit"></i> Edit</a>
</td>
<td class='theme_<?php echo $theme->id ?>'>
<a href="javascript:deleteTheme('<?php echo $theme->id; ?>', '<?php echo $theme->name; ?>');" class="btn btn-danger btn-sm" ><i class="fas fa-trash-alt"></i> Delete</a>
</td>
</tr>
<?php foreach ($themes as $theme) { ?>
<tr>
<td><?php echo $theme->name; ?></td>
<td><?php echo $theme->foldername; ?></td>
<td><?php if ($theme->theme_mode != "") {
echo $theme->theme_mode;
} else {
echo "<span class=\"text-danger\">Theme-Mode undefined! Please edit</span>";
} ?></td>
<td><?php echo $theme->header_logo; ?></td>
<td><?php echo $theme->main_logo; ?></td>
<td>
<a onclick="editThemeDialog('<?php echo $theme->id; ?>')" class="btn btn-outline-primary btn-sm"><i class="fas fa-edit"></i> Edit</a>
</td>
<td class='theme_<?php echo $theme->id ?>'>
<a href="javascript:deleteTheme('<?php echo $theme->id; ?>', '<?php echo $theme->name; ?>');" class="btn btn-danger btn-sm"><i class="fas fa-trash-alt"></i> Delete</a>
</td>
</tr>
<?php } ?>
<?php } ?>
</tbody>
<table>
</div>
<br/>
<br />
<p><button onclick="addThemeDialog();" class="btn btn-primary btn-sm"><i class="fas fa-plus"></i> Add a Theme</button></p>
</div>
</div>
</div>

View File

@@ -0,0 +1,226 @@
function deleteTheme(id, name) {
BootstrapDialog.confirm({
title: "DANGER",
message:
"Warning! Are you sure you want to delete the following theme: " + name + "?",
type: BootstrapDialog.TYPE_DANGER,
closable: true,
draggable: true,
btnOKClass: "btn-danger",
callback: function (result) {
if (result) {
$.ajax({
url: base_url + "index.php/themes/delete",
type: "post",
data: { id: id },
success: function (data) {
$(".theme_" + id)
.parent("tr:first")
.remove(); // removes mode from table
},
});
}
},
});
}
function addThemeDialog() {
$.ajax({
url: base_url + "index.php/themes/add",
type: "post",
success: function (html) {
BootstrapDialog.show({
title: "Create Theme",
size: BootstrapDialog.SIZE_NORMAL,
cssClass: "create-theme-dialog",
nl2br: false,
message: html,
buttons: [
{
label: lang_admin_close,
action: function (dialogItself) {
dialogItself.close();
},
},
],
});
},
});
}
function addTheme(form) {
if (formValidation()) {
if (form.name.value != "") {
$.ajax({
url: base_url + "index.php/themes/add",
type: "post",
data: {
name: form.name.value,
foldername: form.foldername.value,
theme_mode: form.theme_mode.value,
header_logo: form.header_logo.value,
main_logo: form.main_logo.value,
},
success: function (html) {
location.reload();
},
});
}
}
}
function editThemeDialog(theme_id) {
$.ajax({
url: base_url + "index.php/themes/edit/" + theme_id,
type: "post",
success: function (html) {
BootstrapDialog.show({
title: "Edit Theme",
size: BootstrapDialog.SIZE_NORMAL,
cssClass: "edit-theme-dialog",
nl2br: false,
message: html,
buttons: [
{
label: lang_admin_close,
action: function (dialogItself) {
dialogItself.close();
},
},
],
});
},
});
}
function editTheme(form, theme_id) {
if (formValidation()) {
if (form.name.value != "") {
$.ajax({
url: base_url + "index.php/themes/edit/" + theme_id,
type: "post",
data: {
name: form.name.value,
foldername: form.foldername.value,
theme_mode: form.theme_mode.value,
header_logo: form.header_logo.value,
main_logo: form.main_logo.value,
},
success: function (html) {
location.reload();
},
});
}
}
}
function printWarning(input, warning) {
$('#warningMessageTheme').show();
$(input).css('border', '2px solid rgb(217, 83, 79)');
$('#warningMessageTheme').text(warning);
}
function removeWarning(input) {
$(input).css('border', '');
$('#warningMessageTheme').hide();
}
function formValidation() {
let name = $("#nameInput");
let foldername = $("#foldernameInput");
let theme_mode = $("#themeModeInput");
let header_logo = $("#headerLogoInput");
let main_logo = $("#mainLogoInput");
var unwantedCharacters = ['@', '.', '/', '\\', '$'];
// name
if (name.val() == "") {
printWarning(name, "Please enter a name for the theme.");
name.focus();
$(name).css('border-color', 'red');
return false;
}
removeWarning(name);
if (unwantedCharacters.some(char => name.val().includes(char))) {
printWarning(name, "The name contains unwanted characters. Only '()_-' are allowed.");
name.focus();
$(name).css('border-color', 'red');
return false;
}
removeWarning(name);
// foldername
if (foldername.val() == "") {
printWarning(foldername, "Please enter the name of the folder for that theme placed under assets/css.");
foldername.focus();
$(foldername).css('border-color', 'red');
return false;
}
removeWarning(foldername);
if (unwantedCharacters.some(char => foldername.val().includes(char))) {
printWarning(foldername, "The foldername contains unwanted characters. Only '_' and '-' are allowed.");
foldername.focus();
$(foldername).css('border-color', 'red');
return false;
}
removeWarning(foldername);
// theme_mode
if (theme_mode.val() == "") {
printWarning(theme_mode, "Please select the theme_mode.");
theme_mode.focus();
$(theme_mode).css('border-color', 'red');
return false;
}
removeWarning(theme_mode);
// header_logo
if (header_logo.val() == "") {
printWarning(header_logo, "Please enter the filename of the header_logo for that theme placed under assets/logo without the file extension '.png'");
header_logo.focus();
$(header_logo).css('border-color', 'red');
return false;
}
removeWarning(header_logo);
if (unwantedCharacters.some(char => header_logo.val().includes(char))) {
printWarning(header_logo, "The header_logo contains unwanted characters. Only '_' and '-' are allowed. Only PNG files are allowed. Remove the file extension '.png'");
header_logo.focus();
$(header_logo).css('border-color', 'red');
return false;
}
removeWarning(header_logo);
// main_logo
if (main_logo.val() == "") {
printWarning(main_logo, "Please enter the filename of the main_logo for that theme placed under assets/logo without the file extension '.png'");
main_logo.focus();
$(main_logo).css('border-color', 'red');
return false;
} else {
removeWarning(main_logo);
}
if (unwantedCharacters.some(char => main_logo.val().includes(char))) {
printWarning(main_logo, "The main_logo contains unwanted characters. Only '_' and '-' are allowed. Only PNG files are allowed. Remove the file extension '.png'");
main_logo.focus();
$(main_logo).css('border-color', 'red');
return false;
} else {
removeWarning(main_logo);
}
return true;
}
$(document).ready(function() {
$("#submitButton").click(function() { // Validate the form when the submit button is clicked
formValidation();
});
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 30 KiB