Merge branch '395-custom-blocks-to-database' into '3-1-0'
Move Custom Blocks/Nav Elements to Database See merge request !60
This commit is contained in:
commit
09c650d487
275
admin/manage_custom_nav_elements.php
Normal file
275
admin/manage_custom_nav_elements.php
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
define('IN_SCRIPT', 1);
|
||||||
|
define('HESK_PATH', '../');
|
||||||
|
define('PAGE_TITLE', 'ADMIN_CUSTOM_NAV_ELEMENTS');
|
||||||
|
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
|
||||||
|
define('EXTRA_JS', '<script src="'.HESK_PATH.'internal-api/js/manage-custom-nav-elements.js"></script>');
|
||||||
|
|
||||||
|
/* Get all the required files and functions */
|
||||||
|
require(HESK_PATH . 'hesk_settings.inc.php');
|
||||||
|
require(HESK_PATH . 'inc/common.inc.php');
|
||||||
|
require(HESK_PATH . 'inc/admin_functions.inc.php');
|
||||||
|
require(HESK_PATH . 'inc/mail_functions.inc.php');
|
||||||
|
hesk_load_database_functions();
|
||||||
|
|
||||||
|
hesk_session_start();
|
||||||
|
hesk_dbConnect();
|
||||||
|
hesk_isLoggedIn();
|
||||||
|
|
||||||
|
//hesk_checkPermission('can_man_custom_nav');
|
||||||
|
|
||||||
|
/* Print header */
|
||||||
|
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
|
||||||
|
|
||||||
|
/* Print main manage users page */
|
||||||
|
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
|
||||||
|
?>
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<section class="content">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h1 class="box-title">
|
||||||
|
<?php echo $hesklang['custom_nav_menu_elements']; ?>
|
||||||
|
</h1>
|
||||||
|
<div class="box-tools pull-right">
|
||||||
|
<button type="button" class="btn btn-box-tool" data-widget="collapse">
|
||||||
|
<i class="fa fa-minus"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12 text-right">
|
||||||
|
<button id="create-button" class="btn btn-success">
|
||||||
|
<i class="fa fa-plus-circle"></i>
|
||||||
|
<?php echo $hesklang['create_new']; ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><?php echo $hesklang['id']; ?></th>
|
||||||
|
<th><?php echo $hesklang['custom_nav_text']; ?></th>
|
||||||
|
<th><?php echo $hesklang['custom_nav_subtext']; ?></th>
|
||||||
|
<th><?php echo $hesklang['image_url_slash_font_icon']; ?></th>
|
||||||
|
<th><?php echo $hesklang['url']; ?></th>
|
||||||
|
<th><?php echo $hesklang['actions']; ?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="table-body">
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="overlay" id="overlay">
|
||||||
|
<i class="fa fa-spinner fa-spin"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="modal fade" id="nav-element-modal" tabindex="-1" role="dialog" style="overflow: hidden">
|
||||||
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header" style="cursor: move">
|
||||||
|
<button type="button" class="close cancel-callback" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<h4 class="modal-title" id="edit-label">
|
||||||
|
<?php echo $hesklang['edit_custom_nav_element_title_case']; ?>
|
||||||
|
</h4>
|
||||||
|
<h4 class="modal-title" id="create-label">
|
||||||
|
<?php echo $hesklang['create_custom_nav_element_title_case']; ?>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<form id="manage-nav-element" class="form-horizontal" data-toggle="validator">
|
||||||
|
<input type="hidden" name="id">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="place" class="col-md-4 col-sm-12 control-label">
|
||||||
|
<?php echo $hesklang['place']; ?>
|
||||||
|
<i class="fa fa-question-circle settingsquestionmark" data-toggle="htmlpopover"
|
||||||
|
title="<?php echo $hesklang['place']; ?>"
|
||||||
|
data-content="<?php echo $hesklang['place_help']; ?>"></i>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-8 col-sm-12">
|
||||||
|
<select name="place" id="place" class="form-control"
|
||||||
|
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
|
||||||
|
required>
|
||||||
|
<option value="1"><?php echo $hesklang['homepage_block']; ?></option>
|
||||||
|
<option value="2"><?php echo $hesklang['customer_navigation']; ?></option>
|
||||||
|
<option value="3"><?php echo $hesklang['staff_navigation']; ?></option>
|
||||||
|
</select>
|
||||||
|
<div class="help-block with-errors"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 col-sm-12">
|
||||||
|
<h4><?php echo $hesklang['custom_nav_text']; ?></h4>
|
||||||
|
<?php foreach ($hesk_settings['languages'] as $language => $value): ?>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="text[<?php echo $language; ?>]" class="col-md-4 col-sm-12 control-label">
|
||||||
|
<?php echo $language; ?>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-8 col-sm-12">
|
||||||
|
<input type="text" name="text" class="form-control"
|
||||||
|
data-text-language="<?php echo $language; ?>"
|
||||||
|
id="text[<?php echo $language; ?>" placeholder="<?php echo $hesklang['custom_nav_text']; ?>"
|
||||||
|
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
|
||||||
|
required>
|
||||||
|
<div class="help-block with-errors"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<div id="subtext">
|
||||||
|
<h4><?php echo $hesklang['custom_nav_subtext']; ?></h4>
|
||||||
|
<?php foreach ($hesk_settings['languages'] as $language => $value): ?>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="subtext[<?php echo $language; ?>]" class="col-md-4 col-sm-12 control-label">
|
||||||
|
<?php echo $language; ?>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-8 col-sm-12">
|
||||||
|
<input type="text" name="subtext" class="form-control"
|
||||||
|
data-subtext-language="<?php echo $language; ?>"
|
||||||
|
id="subtext[<?php echo $language; ?>" placeholder="<?php echo $hesklang['custom_nav_subtext']; ?>"
|
||||||
|
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
|
||||||
|
required>
|
||||||
|
<div class="help-block with-errors"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-sm-12">
|
||||||
|
<h4><?php echo $hesklang['url']; ?></h4>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="image-type" class="col-md-4 col-sm-12 control-label">
|
||||||
|
<?php echo $hesklang['url']; ?>
|
||||||
|
<i class="fa fa-question-circle settingsquestionmark" data-toggle="htmlpopover"
|
||||||
|
title="<?php echo $hesklang['url']; ?>"
|
||||||
|
data-content="<?php echo $hesklang['url_help']; ?>"></i>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-8 col-sm-12">
|
||||||
|
<input type="text" name="url" class="form-control"
|
||||||
|
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
|
||||||
|
placeholder="<?php echo $hesklang['url']; ?>" required>
|
||||||
|
<div class="help-block with-errors"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4><?php echo $hesklang['image']; ?></h4>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="image-type" class="col-md-4 col-sm-12 control-label"><?php echo $hesklang['image_type']; ?></label>
|
||||||
|
<div class="col-md-8 col-sm-12">
|
||||||
|
<select name="image-type" id="image-type" class="form-control"
|
||||||
|
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
|
||||||
|
required>
|
||||||
|
<option value="image-url"><?php echo $hesklang['image_url']; ?></option>
|
||||||
|
<option value="font-icon"><?php echo $hesklang['font_icon']; ?></option>
|
||||||
|
</select>
|
||||||
|
<div class="help-block with-errors"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" id="image-url-group">
|
||||||
|
<label for="image-url" class="col-md-4 col-sm-12 control-label">
|
||||||
|
<?php echo $hesklang['image_url']; ?>
|
||||||
|
<i class="fa fa-question-circle settingsquestionmark" data-toggle="htmlpopover"
|
||||||
|
title="<?php echo $hesklang['image_url']; ?>"
|
||||||
|
data-content="<?php echo $hesklang['image_url_help']; ?>"></i>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-8 col-sm-12">
|
||||||
|
<input type="text" name="image-url" class="form-control"
|
||||||
|
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
|
||||||
|
placeholder="<?php echo $hesklang['image_url']; ?>" required>
|
||||||
|
<div class="help-block with-errors"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" id="font-icon-group">
|
||||||
|
<p style="display:none" id="no-icon"><?php echo $hesklang['sm_no_icon']; ?></p>
|
||||||
|
|
||||||
|
<p style="display:none" id="search-icon"><?php echo $hesklang['sm_search_icon']; ?></p>
|
||||||
|
|
||||||
|
<p style="display:none"
|
||||||
|
id="footer-icon"><?php echo $hesklang['sm_iconpicker_footer_label']; ?></p>
|
||||||
|
<label for="font-icon" class="col-md-4 col-sm-12 control-label"><?php echo $hesklang['font_icon']; ?></label>
|
||||||
|
<div class="col-md-8 col-sm-12">
|
||||||
|
<div class="btn btn-default iconpicker-container" data-toggle="nav-iconpicker">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="btn-group" id="action-buttons">
|
||||||
|
<button type="button" class="btn btn-default cancel-button" data-dismiss="modal">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
<span><?php echo $hesklang['cancel']; ?></span>
|
||||||
|
</button>
|
||||||
|
<button type="submit" class="btn btn-success save-button">
|
||||||
|
<i class="fa fa-check-circle"></i>
|
||||||
|
<span><?php echo $hesklang['save']; ?></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
echo mfh_get_hidden_fields_for_language(
|
||||||
|
array(
|
||||||
|
'edit',
|
||||||
|
'delete',
|
||||||
|
'no_custom_nav_elements_found',
|
||||||
|
'failed_to_load_custom_nav_elements',
|
||||||
|
'custom_nav_element_deleted',
|
||||||
|
'error_deleting_custom_nav_element',
|
||||||
|
'error_sorting_custom_nav_elements',
|
||||||
|
'custom_nav_element_created',
|
||||||
|
'custom_nav_element_saved',
|
||||||
|
'homepage_block',
|
||||||
|
'customer_navigation',
|
||||||
|
'staff_navigation',
|
||||||
|
'error_saving_custom_nav_element',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<script type="text/html" id="nav-element-template">
|
||||||
|
<tr>
|
||||||
|
<td><span data-property="id" data-value="x"></span></td>
|
||||||
|
<td><span>
|
||||||
|
<ul data-property="text" class="list-unstyled"></ul>
|
||||||
|
</span></td>
|
||||||
|
<td><span>
|
||||||
|
<ul data-property="subtext" class="list-unstyled"></ul>
|
||||||
|
</span></td>
|
||||||
|
<td><span data-property="image-or-font"></span></td>
|
||||||
|
<td><span data-property="url"></span></td>
|
||||||
|
<td>
|
||||||
|
<a href="#" data-action="sort"
|
||||||
|
data-direction="up">
|
||||||
|
<i class="fa fa-fw fa-arrow-up icon-link green"
|
||||||
|
data-toggle="tooltip" title="<?php echo $hesklang['move_up']; ?>"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" data-action="sort"
|
||||||
|
data-direction="down">
|
||||||
|
<i class="fa fa-fw fa-arrow-down icon-link green"
|
||||||
|
data-toggle="tooltip" title="<?php echo $hesklang['move_dn'] ?>"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" data-action="edit">
|
||||||
|
<i class="fa fa-fw fa-pencil icon-link orange"
|
||||||
|
data-toggle="tooltip" title="<?php echo $hesklang['edit']; ?>"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" data-action="delete">
|
||||||
|
<i class="fa fa-fw fa-times icon-link red"
|
||||||
|
data-toggle="tooltip" title="<?php echo $hesklang['delete']; ?>"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
require_once(HESK_PATH . 'inc/footer.inc.php');
|
@ -9,6 +9,7 @@ use BusinessLogic\Emails\EmailSenderHelper;
|
|||||||
use BusinessLogic\Emails\EmailTemplateParser;
|
use BusinessLogic\Emails\EmailTemplateParser;
|
||||||
use BusinessLogic\Emails\EmailTemplateRetriever;
|
use BusinessLogic\Emails\EmailTemplateRetriever;
|
||||||
use BusinessLogic\Emails\MailgunEmailSender;
|
use BusinessLogic\Emails\MailgunEmailSender;
|
||||||
|
use BusinessLogic\Navigation\CustomNavElementHandler;
|
||||||
use BusinessLogic\Security\BanRetriever;
|
use BusinessLogic\Security\BanRetriever;
|
||||||
use BusinessLogic\Security\UserContextBuilder;
|
use BusinessLogic\Security\UserContextBuilder;
|
||||||
use BusinessLogic\Security\UserToTicketChecker;
|
use BusinessLogic\Security\UserToTicketChecker;
|
||||||
@ -30,6 +31,7 @@ use DataAccess\Files\FileDeleter;
|
|||||||
use DataAccess\Files\FileReader;
|
use DataAccess\Files\FileReader;
|
||||||
use DataAccess\Files\FileWriter;
|
use DataAccess\Files\FileWriter;
|
||||||
use DataAccess\Logging\LoggingGateway;
|
use DataAccess\Logging\LoggingGateway;
|
||||||
|
use DataAccess\Navigation\CustomNavElementGateway;
|
||||||
use DataAccess\Security\BanGateway;
|
use DataAccess\Security\BanGateway;
|
||||||
use DataAccess\Security\UserGateway;
|
use DataAccess\Security\UserGateway;
|
||||||
use DataAccess\Settings\ModsForHeskSettingsGateway;
|
use DataAccess\Settings\ModsForHeskSettingsGateway;
|
||||||
@ -41,6 +43,9 @@ use DataAccess\Tickets\VerifiedEmailGateway;
|
|||||||
class ApplicationContext {
|
class ApplicationContext {
|
||||||
public $get;
|
public $get;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApplicationContext constructor.
|
||||||
|
*/
|
||||||
function __construct() {
|
function __construct() {
|
||||||
$this->get = array();
|
$this->get = array();
|
||||||
|
|
||||||
@ -50,6 +55,10 @@ class ApplicationContext {
|
|||||||
// API Checker
|
// API Checker
|
||||||
$this->get[ApiChecker::class] = new ApiChecker($this->get[ModsForHeskSettingsGateway::class]);
|
$this->get[ApiChecker::class] = new ApiChecker($this->get[ModsForHeskSettingsGateway::class]);
|
||||||
|
|
||||||
|
// Custom Navigation
|
||||||
|
$this->get[CustomNavElementGateway::class] = new CustomNavElementGateway();
|
||||||
|
$this->get[CustomNavElementHandler::class] = new CustomNavElementHandler($this->get[CustomNavElementGateway::class]);
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
$this->get[LoggingGateway::class] = new LoggingGateway();
|
$this->get[LoggingGateway::class] = new LoggingGateway();
|
||||||
|
|
||||||
|
30
api/BusinessLogic/Navigation/CustomNavElement.php
Normal file
30
api/BusinessLogic/Navigation/CustomNavElement.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BusinessLogic\Navigation;
|
||||||
|
|
||||||
|
|
||||||
|
class CustomNavElement {
|
||||||
|
/* @var $id int*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/* @var $text string[] */
|
||||||
|
public $text;
|
||||||
|
|
||||||
|
/* @var $subtext string[]|null */
|
||||||
|
public $subtext;
|
||||||
|
|
||||||
|
/* @var $imageUrl string|null */
|
||||||
|
public $imageUrl;
|
||||||
|
|
||||||
|
/* @var $fontIcon string|null */
|
||||||
|
public $fontIcon;
|
||||||
|
|
||||||
|
/* @var $place int */
|
||||||
|
public $place;
|
||||||
|
|
||||||
|
/* @var $url string */
|
||||||
|
public $url;
|
||||||
|
|
||||||
|
/* @var $sort int */
|
||||||
|
public $sort;
|
||||||
|
}
|
70
api/BusinessLogic/Navigation/CustomNavElementHandler.php
Normal file
70
api/BusinessLogic/Navigation/CustomNavElementHandler.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BusinessLogic\Navigation;
|
||||||
|
|
||||||
|
// TODO Test!
|
||||||
|
use BusinessLogic\Exceptions\ApiFriendlyException;
|
||||||
|
use DataAccess\Navigation\CustomNavElementGateway;
|
||||||
|
|
||||||
|
class CustomNavElementHandler {
|
||||||
|
/* @var $customNavElementGateway CustomNavElementGateway */
|
||||||
|
private $customNavElementGateway;
|
||||||
|
|
||||||
|
function __construct($customNavElementGateway) {
|
||||||
|
$this->customNavElementGateway = $customNavElementGateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getAllCustomNavElements($heskSettings) {
|
||||||
|
return $this->customNavElementGateway->getAllCustomNavElements($heskSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCustomNavElement($id, $heskSettings) {
|
||||||
|
$elements = $this->getAllCustomNavElements($heskSettings);
|
||||||
|
|
||||||
|
foreach ($elements as $element) {
|
||||||
|
if ($element->id === intval($id)) {
|
||||||
|
return output($element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ApiFriendlyException("Custom nav element {$id} not found!", "Element Not Found", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteCustomNavElement($id, $heskSettings) {
|
||||||
|
$this->customNavElementGateway->deleteCustomNavElement($id, $heskSettings);
|
||||||
|
$this->customNavElementGateway->resortAllElements($heskSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveCustomNavElement($element, $heskSettings) {
|
||||||
|
$this->customNavElementGateway->saveCustomNavElement($element, $heskSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCustomNavElement($element, $heskSettings) {
|
||||||
|
$element = $this->customNavElementGateway->createCustomNavElement($element, $heskSettings);
|
||||||
|
$this->customNavElementGateway->resortAllElements($heskSettings);
|
||||||
|
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortCustomNavElement($elementId, $direction, $heskSettings) {
|
||||||
|
/* @var $element CustomNavElement */
|
||||||
|
$elements = $this->customNavElementGateway->getAllCustomNavElements($heskSettings);
|
||||||
|
$elementToChange = null;
|
||||||
|
foreach ($elements as $element) {
|
||||||
|
if ($element->id === intval($elementId)) {
|
||||||
|
$elementToChange = $element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($direction === Direction::UP) {
|
||||||
|
$elementToChange->sort -= 15;
|
||||||
|
} else {
|
||||||
|
$elementToChange->sort += 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->customNavElementGateway->saveCustomNavElement($elementToChange, $heskSettings);
|
||||||
|
$this->customNavElementGateway->resortAllElements($heskSettings);
|
||||||
|
}
|
||||||
|
}
|
10
api/BusinessLogic/Navigation/CustomNavElementPlace.php
Normal file
10
api/BusinessLogic/Navigation/CustomNavElementPlace.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BusinessLogic\Navigation;
|
||||||
|
|
||||||
|
|
||||||
|
class CustomNavElementPlace {
|
||||||
|
const HOMEPAGE_BLOCK = 1;
|
||||||
|
const CUSTOMER_NAVIGATION = 2;
|
||||||
|
const ADMIN_NAVIGATION = 3;
|
||||||
|
}
|
9
api/BusinessLogic/Navigation/Direction.php
Normal file
9
api/BusinessLogic/Navigation/Direction.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BusinessLogic\Navigation;
|
||||||
|
|
||||||
|
|
||||||
|
class Direction {
|
||||||
|
const UP = 'up';
|
||||||
|
const DOWN = 'down';
|
||||||
|
}
|
@ -61,7 +61,6 @@ class UserContext {
|
|||||||
* @return UserContext the built user context
|
* @return UserContext the built user context
|
||||||
*/
|
*/
|
||||||
static function fromDataRow($dataRow) {
|
static function fromDataRow($dataRow) {
|
||||||
var_dump($dataRow);
|
|
||||||
$userContext = new UserContext();
|
$userContext = new UserContext();
|
||||||
$userContext->id = intval($dataRow['id']);
|
$userContext->id = intval($dataRow['id']);
|
||||||
$userContext->username = $dataRow['user'];
|
$userContext->username = $dataRow['user'];
|
||||||
|
@ -7,6 +7,13 @@ use BusinessLogic\Exceptions\InternalUseOnlyException;
|
|||||||
use BusinessLogic\Helpers;
|
use BusinessLogic\Helpers;
|
||||||
|
|
||||||
abstract class InternalApiController {
|
abstract class InternalApiController {
|
||||||
|
static function staticCheckForInternalUseOnly() {
|
||||||
|
$tokenHeader = Helpers::getHeader('X-AUTH-TOKEN');
|
||||||
|
if ($tokenHeader !== null && trim($tokenHeader) !== '') {
|
||||||
|
throw new InternalUseOnlyException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function checkForInternalUseOnly() {
|
function checkForInternalUseOnly() {
|
||||||
$tokenHeader = Helpers::getHeader('X-AUTH-TOKEN');
|
$tokenHeader = Helpers::getHeader('X-AUTH-TOKEN');
|
||||||
if ($tokenHeader !== null && trim($tokenHeader) !== '') {
|
if ($tokenHeader !== null && trim($tokenHeader) !== '') {
|
||||||
|
101
api/Controllers/Navigation/CustomNavElementController.php
Normal file
101
api/Controllers/Navigation/CustomNavElementController.php
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controllers\Navigation;
|
||||||
|
|
||||||
|
|
||||||
|
use BusinessLogic\Exceptions\ApiFriendlyException;
|
||||||
|
use BusinessLogic\Helpers;
|
||||||
|
use BusinessLogic\Navigation\CustomNavElement;
|
||||||
|
use BusinessLogic\Navigation\CustomNavElementHandler;
|
||||||
|
use Controllers\InternalApiController;
|
||||||
|
use Controllers\JsonRetriever;
|
||||||
|
|
||||||
|
class CustomNavElementController extends InternalApiController {
|
||||||
|
static function getAll() {
|
||||||
|
global $applicationContext, $hesk_settings;
|
||||||
|
|
||||||
|
self::staticCheckForInternalUseOnly();
|
||||||
|
|
||||||
|
/* @var $handler CustomNavElementHandler */
|
||||||
|
$handler = $applicationContext->get[CustomNavElementHandler::class];
|
||||||
|
|
||||||
|
output($handler->getAllCustomNavElements($hesk_settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
static function sort($id, $direction) {
|
||||||
|
global $applicationContext, $hesk_settings;
|
||||||
|
|
||||||
|
self::staticCheckForInternalUseOnly();
|
||||||
|
|
||||||
|
/* @var $handler CustomNavElementHandler */
|
||||||
|
$handler = $applicationContext->get[CustomNavElementHandler::class];
|
||||||
|
|
||||||
|
$handler->sortCustomNavElement(intval($id), $direction, $hesk_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($id) {
|
||||||
|
global $applicationContext, $hesk_settings;
|
||||||
|
|
||||||
|
$this->checkForInternalUseOnly();
|
||||||
|
|
||||||
|
/* @var $handler CustomNavElementHandler */
|
||||||
|
$handler = $applicationContext->get[CustomNavElementHandler::class];
|
||||||
|
|
||||||
|
output($handler->getCustomNavElement($id, $hesk_settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
function post() {
|
||||||
|
global $applicationContext, $hesk_settings;
|
||||||
|
|
||||||
|
$this->checkForInternalUseOnly();
|
||||||
|
|
||||||
|
/* @var $handler CustomNavElementHandler */
|
||||||
|
$handler = $applicationContext->get[CustomNavElementHandler::class];
|
||||||
|
|
||||||
|
$data = JsonRetriever::getJsonData();
|
||||||
|
$element = $handler->createCustomNavElement($this->buildElementModel($data), $hesk_settings);
|
||||||
|
|
||||||
|
return output($element, 201);
|
||||||
|
}
|
||||||
|
|
||||||
|
function put($id) {
|
||||||
|
global $applicationContext, $hesk_settings;
|
||||||
|
|
||||||
|
$this->checkForInternalUseOnly();
|
||||||
|
|
||||||
|
/* @var $handler CustomNavElementHandler */
|
||||||
|
$handler = $applicationContext->get[CustomNavElementHandler::class];
|
||||||
|
|
||||||
|
$data = JsonRetriever::getJsonData();
|
||||||
|
$handler->saveCustomNavElement($this->buildElementModel($data, $id), $hesk_settings);
|
||||||
|
|
||||||
|
return http_response_code(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete($id) {
|
||||||
|
global $applicationContext, $hesk_settings;
|
||||||
|
|
||||||
|
$this->checkForInternalUseOnly();
|
||||||
|
|
||||||
|
/* @var $handler CustomNavElementHandler */
|
||||||
|
$handler = $applicationContext->get[CustomNavElementHandler::class];
|
||||||
|
|
||||||
|
$handler->deleteCustomNavElement($id, $hesk_settings);
|
||||||
|
|
||||||
|
return http_response_code(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildElementModel($data, $id = null) {
|
||||||
|
$element = new CustomNavElement();
|
||||||
|
$element->id = $id;
|
||||||
|
$element->place = intval(Helpers::safeArrayGet($data, 'place'));
|
||||||
|
$element->fontIcon = Helpers::safeArrayGet($data, 'fontIcon');
|
||||||
|
$element->imageUrl = Helpers::safeArrayGet($data, 'imageUrl');
|
||||||
|
$element->text = Helpers::safeArrayGet($data, 'text');
|
||||||
|
$element->subtext = Helpers::safeArrayGet($data, 'subtext');
|
||||||
|
$element->url = Helpers::safeArrayGet($data, 'url');
|
||||||
|
$element->sort = intval(Helpers::safeArrayGet($data, 'sort'));
|
||||||
|
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
function print_error($title, $message, $response_code = 500) {
|
function print_error($title, $message, $logId = null, $response_code = 500) {
|
||||||
require_once(__DIR__ . '/output.php');
|
require_once(__DIR__ . '/output.php');
|
||||||
|
|
||||||
$error = array();
|
$error = array();
|
||||||
$error['type'] = 'ERROR';
|
$error['type'] = 'ERROR';
|
||||||
$error['title'] = $title;
|
$error['title'] = $title;
|
||||||
$error['message'] = $message;
|
$error['message'] = $message;
|
||||||
|
$error['logId'] = $logId;
|
||||||
|
|
||||||
print output($error, $response_code);
|
print output($error, $response_code);
|
||||||
return;
|
return;
|
||||||
|
182
api/DataAccess/Navigation/CustomNavElementGateway.php
Normal file
182
api/DataAccess/Navigation/CustomNavElementGateway.php
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DataAccess\Navigation;
|
||||||
|
|
||||||
|
|
||||||
|
use BusinessLogic\Navigation\CustomNavElement;
|
||||||
|
use DataAccess\CommonDao;
|
||||||
|
|
||||||
|
class CustomNavElementGateway extends CommonDao {
|
||||||
|
function getAllCustomNavElements($heskSettings) {
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
$columns = '`t1`.`id`, `t1`.`image_url`, `t1`.`font_icon`, `t1`.`place`, `t1`.`url`, `t1`.`sort`,
|
||||||
|
`t2`.`language`, `t2`.`text`, `t2`.`subtext`';
|
||||||
|
|
||||||
|
$rs = hesk_dbQuery("SELECT {$columns} FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element` AS `t1`
|
||||||
|
INNER JOIN `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element_to_text` AS `t2`
|
||||||
|
ON `t1`.`id` = `t2`.`nav_element_id`
|
||||||
|
ORDER BY `t1`.`place` ASC, `t1`.`sort` ASC");
|
||||||
|
|
||||||
|
$elements = array();
|
||||||
|
|
||||||
|
/* @var $element CustomNavElement */
|
||||||
|
$element = null;
|
||||||
|
$previousId = -1;
|
||||||
|
while ($row = hesk_dbFetchAssoc($rs)) {
|
||||||
|
$id = intval($row['id']);
|
||||||
|
if ($previousId !== $id) {
|
||||||
|
if ($element !== null) {
|
||||||
|
$elements[] = $element;
|
||||||
|
}
|
||||||
|
$element = new CustomNavElement();
|
||||||
|
$element->id = $id;
|
||||||
|
$element->place = intval($row['place']);
|
||||||
|
$element->imageUrl = $row['image_url'];
|
||||||
|
$element->fontIcon = $row['font_icon'];
|
||||||
|
$element->url = $row['url'];
|
||||||
|
$element->sort = $row['sort'];
|
||||||
|
$element->text = array();
|
||||||
|
$element->subtext = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$element->text[$row['language']] = $row['text'];
|
||||||
|
$element->subtext[$row['language']] = $row['subtext'];
|
||||||
|
|
||||||
|
$previousId = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($element !== null) {
|
||||||
|
$elements[] = $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->close();
|
||||||
|
|
||||||
|
return $elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $id int
|
||||||
|
* @param $heskSettings array
|
||||||
|
*/
|
||||||
|
function deleteCustomNavElement($id, $heskSettings) {
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element_to_text`
|
||||||
|
WHERE `nav_element_id` = " . intval($id));
|
||||||
|
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element`
|
||||||
|
WHERE `id` = " . intval($id));
|
||||||
|
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $element CustomNavElement
|
||||||
|
* @param $heskSettings array
|
||||||
|
*/
|
||||||
|
function saveCustomNavElement($element, $heskSettings) {
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
//-- Delete previous records - easier than inserting/updating
|
||||||
|
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element_to_text`
|
||||||
|
WHERE `nav_element_id` = " . intval($element->id));
|
||||||
|
|
||||||
|
$languageTextAndSubtext = array();
|
||||||
|
foreach ($element->text as $key => $text) {
|
||||||
|
$languageTextAndSubtext[$key]['text'] = $text;
|
||||||
|
}
|
||||||
|
foreach ($element->subtext as $key => $subtext) {
|
||||||
|
$languageTextAndSubtext[$key]['subtext'] = $subtext;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($languageTextAndSubtext as $key => $values) {
|
||||||
|
$subtext = 'NULL';
|
||||||
|
if (isset($values['subtext'])) {
|
||||||
|
$subtext = "'" . hesk_dbEscape($values['subtext']) . "'";
|
||||||
|
}
|
||||||
|
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element_to_text`
|
||||||
|
(`nav_element_id`, `language`, `text`, `subtext`) VALUES (" . intval($element->id) . ",
|
||||||
|
'" . hesk_dbEscape($key) . "',
|
||||||
|
'" . hesk_dbEscape($values['text']) . "',
|
||||||
|
" . $subtext . ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
$imageUrl = $element->imageUrl == null ? 'NULL' : "'" . hesk_dbEscape($element->imageUrl) . "'";
|
||||||
|
$fontIcon = $element->fontIcon == null ? 'NULL' : "'" . hesk_dbEscape($element->fontIcon) . "'";
|
||||||
|
hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element`
|
||||||
|
SET `image_url` = {$imageUrl},
|
||||||
|
`font_icon` = {$fontIcon},
|
||||||
|
`url` = '" . hesk_dbEscape($element->url) . "',
|
||||||
|
`sort` = " . intval($element->sort) . ",
|
||||||
|
`place` = " . intval($element->place) .
|
||||||
|
" WHERE `id` = " . intval($element->id));
|
||||||
|
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $element CustomNavElement
|
||||||
|
* @param $heskSettings array
|
||||||
|
* @return CustomNavElement
|
||||||
|
*/
|
||||||
|
function createCustomNavElement($element, $heskSettings) {
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
$rs = hesk_dbQuery("SELECT MAX(`sort`) AS `sort` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element`
|
||||||
|
WHERE `place` = " . intval($element->place));
|
||||||
|
$maxSort = hesk_dbFetchAssoc($rs);
|
||||||
|
$sortValue = intval($maxSort['sort']) + 1;
|
||||||
|
|
||||||
|
$imageUrl = $element->imageUrl == null ? 'NULL' : "'" . hesk_dbEscape($element->imageUrl) . "'";
|
||||||
|
$fontIcon = $element->fontIcon == null ? 'NULL' : "'" . hesk_dbEscape($element->fontIcon) . "'";
|
||||||
|
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element`
|
||||||
|
(`image_url`, `font_icon`, `place`, `sort`, `url`)
|
||||||
|
VALUES ({$imageUrl}, {$fontIcon}, " . intval($element->place) . ", " . $sortValue . ", '" . hesk_dbEscape($element->url) . "')");
|
||||||
|
|
||||||
|
$element->id = hesk_dbInsertID();
|
||||||
|
|
||||||
|
|
||||||
|
$languageTextAndSubtext = array();
|
||||||
|
foreach ($element->text as $key => $text) {
|
||||||
|
$languageTextAndSubtext[$key]['text'] = $text;
|
||||||
|
}
|
||||||
|
foreach ($element->subtext as $key => $subtext) {
|
||||||
|
$languageTextAndSubtext[$key]['subtext'] = $subtext;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($languageTextAndSubtext as $key => $values) {
|
||||||
|
$subtext = 'NULL';
|
||||||
|
if (isset($values['subtext'])) {
|
||||||
|
$subtext = "'" . hesk_dbEscape($values['subtext']) . "'";
|
||||||
|
}
|
||||||
|
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element_to_text`
|
||||||
|
(`nav_element_id`, `language`, `text`, `subtext`) VALUES (" . intval($element->id) . ",
|
||||||
|
'" . hesk_dbEscape($key) . "',
|
||||||
|
'" . hesk_dbEscape($values['text']) . "',
|
||||||
|
" . $subtext . ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->close();
|
||||||
|
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function resortAllElements($heskSettings) {
|
||||||
|
$this->init();
|
||||||
|
|
||||||
|
$rs = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element`
|
||||||
|
ORDER BY `place` ASC, `sort` ASC");
|
||||||
|
|
||||||
|
$sortValue = 10;
|
||||||
|
while ($row = hesk_dbFetchAssoc($rs)) {
|
||||||
|
hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . "custom_nav_element`
|
||||||
|
SET `sort` = " . intval($sortValue) . "
|
||||||
|
WHERE `id` = " . intval($row['id']));
|
||||||
|
|
||||||
|
$sortValue += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
}
|
@ -98,14 +98,14 @@ function exceptionHandler($exception) {
|
|||||||
$userContext, $hesk_settings);
|
$userContext, $hesk_settings);
|
||||||
|
|
||||||
$logIdText = $logId === null ? "Additionally, the error could not be logged! :'(" : "Log ID: {$logId}";
|
$logIdText = $logId === null ? "Additionally, the error could not be logged! :'(" : "Log ID: {$logId}";
|
||||||
print_error("SQL Exception", "Fought an uncaught SQL exception. Check the logs for more information. {$logIdText}");
|
print_error("SQL Exception", "Fought an uncaught SQL exception. Check the logs for more information. {$logIdText}", $logId);
|
||||||
} else {
|
} else {
|
||||||
$logId = tryToLog(getLoggingLocation($exception),
|
$logId = tryToLog(getLoggingLocation($exception),
|
||||||
$exception->getMessage(), $exception->getTraceAsString(),
|
$exception->getMessage(), $exception->getTraceAsString(),
|
||||||
$userContext, $hesk_settings);
|
$userContext, $hesk_settings);
|
||||||
|
|
||||||
$logIdText = $logId === null ? "Additionally, the error could not be logged! :'(" : "Log ID: {$logId}";
|
$logIdText = $logId === null ? "Additionally, the error could not be logged! :'(" : "Log ID: {$logId}";
|
||||||
print_error("Exception Occurred", "Fought an uncaught exception. Check the logs for more information. {$logIdText}");
|
print_error("Exception Occurred", "Fought an uncaught exception. Check the logs for more information. {$logIdText}", $logId);
|
||||||
}
|
}
|
||||||
|
|
||||||
die();
|
die();
|
||||||
@ -186,6 +186,11 @@ Link::all(array(
|
|||||||
/* Internal use only routes */
|
/* Internal use only routes */
|
||||||
// Resend email response
|
// Resend email response
|
||||||
'/v1-internal/staff/tickets/{i}/resend-email' => \Controllers\Tickets\ResendTicketEmailToCustomerController::class,
|
'/v1-internal/staff/tickets/{i}/resend-email' => \Controllers\Tickets\ResendTicketEmailToCustomerController::class,
|
||||||
|
// Custom Navigation
|
||||||
|
'/v1-internal/custom-navigation/all' => \Controllers\Navigation\CustomNavElementController::class . '::getAll',
|
||||||
|
'/v1-internal/custom-navigation' => \Controllers\Navigation\CustomNavElementController::class,
|
||||||
|
'/v1-internal/custom-navigation/{i}' => \Controllers\Navigation\CustomNavElementController::class,
|
||||||
|
'/v1-internal/custom-navigation/{i}/sort/{s}' => \Controllers\Navigation\CustomNavElementController::class . '::sort',
|
||||||
|
|
||||||
// Any URL that doesn't match goes to the 404 handler
|
// Any URL that doesn't match goes to the 404 handler
|
||||||
'404' => 'handle404'
|
'404' => 'handle404'
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.black {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
.red,
|
.red,
|
||||||
.important,
|
.important,
|
||||||
.critical-priority {
|
.critical-priority {
|
||||||
|
@ -291,3 +291,7 @@ div.ticket-info {
|
|||||||
.black {
|
.black {
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#toast-container > div {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
1
css/toastr.min.css
vendored
Normal file
1
css/toastr.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -2143,3 +2143,15 @@ function mfh_get_stars($rating) {
|
|||||||
|
|
||||||
return $markup;
|
return $markup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mfh_get_hidden_fields_for_language($keys) {
|
||||||
|
global $hesklang;
|
||||||
|
|
||||||
|
$output = '<div class="hide">';
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$output .= sprintf('<p id="lang_%s">%s</p>', $key, $hesklang[$key]);
|
||||||
|
}
|
||||||
|
$output .= '</div>';
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
@ -325,7 +325,26 @@ if ($modsForHesk_settings['show_icons']) {
|
|||||||
<a href="<?php echo HESK_PATH; ?>calendar.php"><i class="fa fa-calendar" <?php echo $iconDisplay; ?>></i> <?php echo $hesklang['calendar_title_case']; ?></a>
|
<a href="<?php echo HESK_PATH; ?>calendar.php"><i class="fa fa-calendar" <?php echo $iconDisplay; ?>></i> <?php echo $hesklang['calendar_title_case']; ?></a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php include('custom/header-custom.inc.php'); ?>
|
<?php
|
||||||
|
$customNavRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_nav_element` AS `t1`
|
||||||
|
INNER JOIN `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_nav_element_to_text` AS `t2`
|
||||||
|
ON `t1`.`id` = `t2`.`nav_element_id`
|
||||||
|
AND `t2`.`language` = '" . hesk_dbEscape($hesk_settings['language']) . "'
|
||||||
|
WHERE `t1`.`place` = 2");
|
||||||
|
|
||||||
|
while ($row = hesk_dbFetchAssoc($customNavRs)):
|
||||||
|
?>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $row['url']; ?>">
|
||||||
|
<?php if ($row['image_url'] !== null): ?>
|
||||||
|
<img src="<?php echo $row['image_url']; ?>" alt="<?php echo $row['text']; ?>" <?php echo $iconDisplay; ?>>
|
||||||
|
<?php else: ?>
|
||||||
|
<i class="<?php echo $row['font_icon']; ?>" <?php echo $iconDisplay; ?>></i>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php echo $row['text']; ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php endwhile; ?>
|
||||||
</ul>
|
</ul>
|
||||||
<?php if ($hesk_settings['can_sel_lang']) { ?>
|
<?php if ($hesk_settings['can_sel_lang']) { ?>
|
||||||
<div class="navbar-form navbar-right" role="search" style="margin-right: 20px; min-width: 80px;">
|
<div class="navbar-form navbar-right" role="search" style="margin-right: 20px; min-width: 80px;">
|
||||||
|
@ -60,11 +60,12 @@ $modsForHesk_settings = mfh_getSettings();
|
|||||||
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/bootstrap-colorpicker.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/bootstrap-colorpicker.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
||||||
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/AdminLTE.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/AdminLTE.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
||||||
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/skins/_all-skins.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/skins/_all-skins.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
||||||
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/jquery.fancybox.min.css?v=<?php echo MODS_FOR_HESK_BUILD ?>">
|
||||||
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/toastr.min.css?v=<?php echo MODS_FOR_HESK_BUILD ?>">
|
||||||
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/mods-for-hesk-new.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/mods-for-hesk-new.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
||||||
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/colors.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/colors.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
||||||
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/positions.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/positions.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
||||||
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/displays.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/displays.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
|
||||||
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/jquery.fancybox.min.css?v=<? echo MODS_FOR_HESK_BUILD ?>">
|
|
||||||
<?php if (defined('USE_JQUERY_2')): ?>
|
<?php if (defined('USE_JQUERY_2')): ?>
|
||||||
<script src="<?php echo HESK_PATH; ?>js/jquery-2.2.4.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
<script src="<?php echo HESK_PATH; ?>js/jquery-2.2.4.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
@ -89,6 +90,9 @@ $modsForHesk_settings = mfh_getSettings();
|
|||||||
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/jquery.jgrowl.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/jquery.jgrowl.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
||||||
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-colorpicker.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-colorpicker.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
||||||
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/jquery.slimscroll.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/jquery.slimscroll.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
||||||
|
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/toastr.min.js?v=<?php echo MODS_FOR_HESK_BUILD ?>"></script>
|
||||||
|
<script type="text/javascript" src="<?php echo HESK_PATH; ?>internal-api/js/alerts.js?v=<?php echo MODS_FOR_HESK_BUILD ?>"></script>
|
||||||
|
<script type="text/javascript" src="<?php echo HESK_PATH; ?>internal-api/js/lang.js?v=<?php echo MODS_FOR_HESK_BUILD ?>"></script>
|
||||||
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/jquery.fancybox.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/jquery.fancybox.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
|
||||||
<?php
|
<?php
|
||||||
if (defined('EXTRA_JS')) {
|
if (defined('EXTRA_JS')) {
|
||||||
@ -249,7 +253,11 @@ if (defined('MFH_PAGE_LAYOUT') && MFH_PAGE_LAYOUT == 'TOP_ONLY') {
|
|||||||
?>
|
?>
|
||||||
<body onload="<?php echo $onload;
|
<body onload="<?php echo $onload;
|
||||||
unset($onload); ?>" class="<?php echo $layout_tag ?> fixed js <?php echo $modsForHesk_settings['admin_color_scheme']; ?>">
|
unset($onload); ?>" class="<?php echo $layout_tag ?> fixed js <?php echo $modsForHesk_settings['admin_color_scheme']; ?>">
|
||||||
<span style="display: none" id="heskUrl"><?php echo $hesk_settings['hesk_url']; ?></span>
|
|
||||||
|
<?php // GLOBAL JAVASCRIPT IDs ?>
|
||||||
|
<p style="display: none" id="heskUrl"><?php echo $hesk_settings['hesk_url']; ?></p>
|
||||||
|
<p style="display: none" id="lang_alert_success"><?php echo $hesklang['alert_success']; ?></p>
|
||||||
|
<p style="display: none" id="lang_alert_error"><?php echo $hesklang['alert_error']; ?></p>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
include(HESK_PATH . 'header.txt');
|
include(HESK_PATH . 'header.txt');
|
||||||
|
@ -123,7 +123,26 @@ $mails = mfh_get_mail_headers_for_dropdown($_SESSION['id'], $hesk_settings, $hes
|
|||||||
</li>
|
</li>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
|
|
||||||
|
$customNavRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_nav_element` AS `t1`
|
||||||
|
INNER JOIN `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_nav_element_to_text` AS `t2`
|
||||||
|
ON `t1`.`id` = `t2`.`nav_element_id`
|
||||||
|
AND `t2`.`language` = '" . hesk_dbEscape($hesk_settings['language']) . "'
|
||||||
|
WHERE `t1`.`place` = 3");
|
||||||
|
|
||||||
|
while ($row = hesk_dbFetchAssoc($customNavRs)):
|
||||||
?>
|
?>
|
||||||
|
<li>
|
||||||
|
<a href="<?php echo $row['url']; ?>">
|
||||||
|
<?php if ($row['image_url'] !== null): ?>
|
||||||
|
<img src="<?php echo $row['image_url']; ?>" alt="<?php echo $row['text']; ?>" <?php echo $iconDisplay; ?>>
|
||||||
|
<?php else: ?>
|
||||||
|
<i class="<?php echo $row['font_icon']; ?>" <?php echo $iconDisplay; ?>></i>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php echo $row['text']; ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php endwhile; ?>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<!-- Navbar Right Menu -->
|
<!-- Navbar Right Menu -->
|
||||||
|
31
index.php
31
index.php
@ -1391,8 +1391,39 @@ function print_start()
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif;
|
||||||
|
|
||||||
|
$customNavRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_nav_element` AS `t1`
|
||||||
|
INNER JOIN `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_nav_element_to_text` AS `t2`
|
||||||
|
ON `t1`.`id` = `t2`.`nav_element_id`
|
||||||
|
AND `t2`.`language` = '" . hesk_dbEscape($hesk_settings['language']) . "'
|
||||||
|
WHERE `t1`.`place` = 1");
|
||||||
|
|
||||||
|
while ($row = hesk_dbFetchAssoc($customNavRs)):
|
||||||
|
?>
|
||||||
|
<div class="col-sm-6 col-xs-12">
|
||||||
|
<a href="<?php echo $row['url']; ?>" class="button-link">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-1">
|
||||||
|
<?php if ($row['image_url'] !== null): ?>
|
||||||
|
<img src="<?php echo $row['image_url']; ?>" alt="<?php echo $row['text']; ?>">
|
||||||
|
<?php else: ?>
|
||||||
|
<i class="<?php echo $row['font_icon']; ?> black" style="font-size: 32px"></i>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-xs-11">
|
||||||
|
<b><?php echo $row['text']; ?></b><br>
|
||||||
|
<?php echo $row['subtext']; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<?php endwhile; ?>
|
||||||
|
</div>
|
||||||
<?php
|
<?php
|
||||||
if ($hesk_settings['kb_enable'])
|
if ($hesk_settings['kb_enable'])
|
||||||
{
|
{
|
||||||
|
@ -993,4 +993,19 @@ function execute310Scripts() {
|
|||||||
hesk_dbConnect();
|
hesk_dbConnect();
|
||||||
|
|
||||||
executeQuery("ALTER TABLE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logging` ADD COLUMN `stack_trace` TEXT");
|
executeQuery("ALTER TABLE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logging` ADD COLUMN `stack_trace` TEXT");
|
||||||
|
executeQuery("CREATE TABLE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_nav_element`
|
||||||
|
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
image_url TEXT,
|
||||||
|
font_icon VARCHAR(200),
|
||||||
|
place INT NOT NULL,
|
||||||
|
url VARCHAR(500) NOT NULL,
|
||||||
|
sort INT NOT NULL)");
|
||||||
|
executeQuery("CREATE TABLE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_nav_element_to_text`
|
||||||
|
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
nav_element_id INT NOT NULL,
|
||||||
|
language VARCHAR(200) NOT NULL,
|
||||||
|
text VARCHAR(200) NOT NULL,
|
||||||
|
subtext VARCHAR(200))");
|
||||||
|
|
||||||
|
updateVersion('3.1.0');
|
||||||
}
|
}
|
31
internal-api/js/alerts.js
Normal file
31
internal-api/js/alerts.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
var mfhAlert = {
|
||||||
|
success: success,
|
||||||
|
error: error,
|
||||||
|
errorWithLog: errorWithLog
|
||||||
|
};
|
||||||
|
|
||||||
|
function success(message, title) {
|
||||||
|
if (title === undefined) {
|
||||||
|
title = $('#lang_alert_success').text();
|
||||||
|
}
|
||||||
|
|
||||||
|
toastr.success(message, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(message, title) {
|
||||||
|
if (title === undefined) {
|
||||||
|
title = $('#lang_alert_error').text();
|
||||||
|
}
|
||||||
|
|
||||||
|
toastr.error(message, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorWithLog(message, responseJSON, title) {
|
||||||
|
var displayMessage = message;
|
||||||
|
if (responseJSON !== undefined &&
|
||||||
|
responseJSON.logId !== undefined) {
|
||||||
|
displayMessage += ' (' + responseJSON.logId + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
mfhAlert.error(displayMessage, title);
|
||||||
|
}
|
5
internal-api/js/lang.js
Normal file
5
internal-api/js/lang.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
var mfhLang = {
|
||||||
|
text: function(key) {
|
||||||
|
return $('#lang_' + key).text();
|
||||||
|
}
|
||||||
|
};
|
350
internal-api/js/manage-custom-nav-elements.js
Normal file
350
internal-api/js/manage-custom-nav-elements.js
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
var elements = [];
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
loadTable();
|
||||||
|
bindEditModal();
|
||||||
|
bindCreateModal();
|
||||||
|
bindDeleteButton();
|
||||||
|
bindSortButtons();
|
||||||
|
|
||||||
|
$('[data-toggle="nav-iconpicker"]').iconpicker({
|
||||||
|
iconset: ['fontawesome', 'octicon'],
|
||||||
|
selectedClass: "btn-warning",
|
||||||
|
labelNoIcon: $('#no-icon').text(),
|
||||||
|
searchText: $('#search-icon').text(),
|
||||||
|
labelFooter: $('#footer-icon').text(),
|
||||||
|
resetButton: false,
|
||||||
|
search: false,
|
||||||
|
icon: 'fa fa-adn'
|
||||||
|
});
|
||||||
|
|
||||||
|
$('select[name="place"]').change(function() {
|
||||||
|
var $subtextField = $('#subtext');
|
||||||
|
if (parseInt($(this).val()) === 1) {
|
||||||
|
$subtextField.show();
|
||||||
|
} else {
|
||||||
|
$subtextField.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('select[name="image-type"]').change(function() {
|
||||||
|
var $imageUrl = $('#image-url-group');
|
||||||
|
var $fontIcon = $('#font-icon-group');
|
||||||
|
|
||||||
|
if ($(this).val() === 'image-url') {
|
||||||
|
$imageUrl.show();
|
||||||
|
$fontIcon.hide();
|
||||||
|
} else {
|
||||||
|
$imageUrl.hide();
|
||||||
|
$fontIcon.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('form#manage-nav-element').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var heskUrl = $('#heskUrl').text();
|
||||||
|
|
||||||
|
var $modal = $('#nav-element-modal');
|
||||||
|
|
||||||
|
var place = parseInt($modal.find('select[name="place"]').val());
|
||||||
|
|
||||||
|
var $textLanguages = $modal.find('[data-text-language]');
|
||||||
|
var text = {};
|
||||||
|
$.each($textLanguages, function() {
|
||||||
|
text[$(this).data('text-language')] = $(this).val();
|
||||||
|
});
|
||||||
|
|
||||||
|
var subtext = {};
|
||||||
|
if (place === 1) {
|
||||||
|
var $subtextLanguages = $modal.find('[data-subtext-language]');
|
||||||
|
$.each($subtextLanguages, function() {
|
||||||
|
subtext[$(this).data('subtext-language')] = $(this).val();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var imageUrl = null;
|
||||||
|
var fontIcon = null;
|
||||||
|
if ($modal.find('select[name="image-type"]').val() === 'image-url') {
|
||||||
|
imageUrl = $modal.find('input[name="image-url"]').val();
|
||||||
|
} else {
|
||||||
|
fontIcon = $modal.find('.iconpicker').find('input[type="hidden"]').val();
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = parseInt($modal.find('input[name="id"]').val());
|
||||||
|
var navUrl = $modal.find('input[name="url"]').val();
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
place: place,
|
||||||
|
text: text,
|
||||||
|
subtext: subtext,
|
||||||
|
imageUrl: imageUrl,
|
||||||
|
fontIcon: fontIcon,
|
||||||
|
url: navUrl
|
||||||
|
};
|
||||||
|
|
||||||
|
var url = heskUrl + '/api/v1-internal/custom-navigation/';
|
||||||
|
var method = 'POST';
|
||||||
|
|
||||||
|
if (id !== -1) {
|
||||||
|
url += id;
|
||||||
|
method = 'PUT';
|
||||||
|
}
|
||||||
|
|
||||||
|
$modal.find('#action-buttons').find('.cancel-button').attr('disabled', 'disabled');
|
||||||
|
$modal.find('#action-buttons').find('.save-button').attr('disabled', 'disabled');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
method: method,
|
||||||
|
url: url,
|
||||||
|
headers: { 'X-Internal-Call': true },
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
success: function(data) {
|
||||||
|
if (id === -1) {
|
||||||
|
mfhAlert.success(mfhLang.text('custom_nav_element_created'));
|
||||||
|
} else {
|
||||||
|
mfhAlert.success(mfhLang.text('custom_nav_element_saved'));
|
||||||
|
}
|
||||||
|
$modal.modal('hide');
|
||||||
|
loadTable();
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
mfhAlert.errorWithLog(mfhLang.text('error_saving_custom_nav_element'), data.responseJSON);
|
||||||
|
console.error(data);
|
||||||
|
},
|
||||||
|
complete: function() {
|
||||||
|
$modal.find('#action-buttons').find('.cancel-button').removeAttr('disabled');
|
||||||
|
$modal.find('#action-buttons').find('.save-button').removeAttr('disabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function loadTable() {
|
||||||
|
$('#overlay').show();
|
||||||
|
var heskUrl = $('#heskUrl').text();
|
||||||
|
var notFoundText = mfhLang.text('no_custom_nav_elements_found');
|
||||||
|
var places = [];
|
||||||
|
var $tableBody = $('#table-body');
|
||||||
|
places[1] = mfhLang.text('homepage_block');
|
||||||
|
places[2] = mfhLang.text('customer_navigation');
|
||||||
|
places[3] = mfhLang.text('staff_navigation');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
method: 'GET',
|
||||||
|
url: heskUrl + '/api/v1-internal/custom-navigation/all',
|
||||||
|
headers: { 'X-Internal-Call': true },
|
||||||
|
success: function(data) {
|
||||||
|
$tableBody.html('');
|
||||||
|
elements = [];
|
||||||
|
|
||||||
|
if (data.length === 0) {
|
||||||
|
$('#table-body').append('<tr><td colspan="6">' + notFoundText + '</td></tr>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentPlace = 0;
|
||||||
|
var addedElementToPlace = false;
|
||||||
|
var first = true;
|
||||||
|
var lastElement = null;
|
||||||
|
$.each(data, function() {
|
||||||
|
if (this.place !== currentPlace) {
|
||||||
|
if (lastElement !== null) {
|
||||||
|
//-- Hide the down arrow on the last element
|
||||||
|
$('[data-value="' + lastElement.id + '"]').parent().parent()
|
||||||
|
.find('[data-direction="down"]').css('visibility', 'hidden');
|
||||||
|
lastElement = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#table-body').append('<tr><td colspan="6" class="bg-gray"><i><b>' + places[this.place] + '</b></i></td></tr>');
|
||||||
|
currentPlace = this.place;
|
||||||
|
addedElementToPlace = false;
|
||||||
|
first = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var $template = $($('#nav-element-template').html());
|
||||||
|
|
||||||
|
$template.find('span[data-property="id"]').text(this.id).attr('data-value', this.id);
|
||||||
|
if (this.imageUrl === null) {
|
||||||
|
$template.find('span[data-property="image-or-font"]').html('<i class="' + escape(this.fontIcon) + '"></i>');
|
||||||
|
} else {
|
||||||
|
$template.find('span[data-property="image-or-font"]').text(this.imageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$template.find('span[data-property="url"]').text(this.url);
|
||||||
|
|
||||||
|
var text = '';
|
||||||
|
$.each(this.text, function(key, value) {
|
||||||
|
text += '<li><b>' + escape(key) + ':</b> ' + escape(value) + '</li>';
|
||||||
|
});
|
||||||
|
$template.find('ul[data-property="text"]').html(text);
|
||||||
|
|
||||||
|
var subtext = '-';
|
||||||
|
if (this.place === 1) {
|
||||||
|
subtext = '';
|
||||||
|
$.each(this.subtext, function(key, value) {
|
||||||
|
subtext += '<li><b>' + escape(key) + ':</b> ' + escape(value) + '</li>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$template.find('ul[data-property="subtext"]').html(subtext);
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
$template.find('[data-direction="up"]').css('visibility', 'hidden');
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tableBody.append($template);
|
||||||
|
|
||||||
|
elements[this.id] = this;
|
||||||
|
|
||||||
|
addedElementToPlace = true;
|
||||||
|
lastElement = this;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (lastElement) {
|
||||||
|
//-- Hide the down arrow on the last element
|
||||||
|
$('[data-value="' + lastElement.id + '"]').parent().parent()
|
||||||
|
.find('[data-direction="down"]').css('visibility', 'hidden');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
mfhAlert.errorWithLog(mfhLang.text('failed_to_load_custom_nav_elements'), data.responseJSON);
|
||||||
|
console.error(data);
|
||||||
|
},
|
||||||
|
complete: function() {
|
||||||
|
$('#overlay').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function escape(str) {
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.appendChild(document.createTextNode(str));
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindEditModal() {
|
||||||
|
$(document).on('click', '[data-action="edit"]', function() {
|
||||||
|
var element = elements[$(this).parent().parent().find('[data-property="id"]').text()];
|
||||||
|
var $modal = $('#nav-element-modal');
|
||||||
|
|
||||||
|
$modal.find('#edit-label').show();
|
||||||
|
$modal.find('#create-label').hide();
|
||||||
|
$modal.find('select[name="place"]').val(element.place);
|
||||||
|
$modal.find('input[name="id"]').val(element.id);
|
||||||
|
$modal.find('input[name="url"]').val(element.url);
|
||||||
|
var $textLanguages = $modal.find('[data-text-language]');
|
||||||
|
$.each($textLanguages, function() {
|
||||||
|
var language = $(this).data('text-language');
|
||||||
|
|
||||||
|
$(this).val(element.text[language]);
|
||||||
|
});
|
||||||
|
|
||||||
|
var $subtextLanguages = $modal.find('[data-subtext-language]');
|
||||||
|
$.each($subtextLanguages, function() {
|
||||||
|
var language = $(this).data('subtext-language');
|
||||||
|
|
||||||
|
$(this).val(element.subtext[language]);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (element.place === 1) {
|
||||||
|
$('#subtext').show();
|
||||||
|
} else {
|
||||||
|
$('#subtext').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.imageUrl !== null) {
|
||||||
|
$modal.find('select[name="image-type"]').val('image-url');
|
||||||
|
$modal.find('input[name="image-url"]').val(element.imageUrl);
|
||||||
|
$modal.find('#font-icon-group').hide();
|
||||||
|
$modal.find('#image-url-group').show();
|
||||||
|
} else {
|
||||||
|
$modal.find('select[name="image-type"]').val('font-icon');
|
||||||
|
$('[data-toggle="nav-iconpicker"]').iconpicker('setIcon', element.fontIcon);
|
||||||
|
$modal.find('#font-icon-group').show();
|
||||||
|
$modal.find('#image-url-group').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$modal.modal('show');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindCreateModal() {
|
||||||
|
$('#create-button').click(function() {
|
||||||
|
var $modal = $('#nav-element-modal');
|
||||||
|
$modal.find('#edit-label').hide();
|
||||||
|
$modal.find('#create-label').show();
|
||||||
|
$modal.find('select[name="place"]').val(1);
|
||||||
|
$modal.find('input[name="id"]').val(-1);
|
||||||
|
var $textLanguages = $modal.find('[data-text-language]');
|
||||||
|
$.each($textLanguages, function() {
|
||||||
|
var language = $(this).data('text-language');
|
||||||
|
|
||||||
|
$(this).val('');
|
||||||
|
});
|
||||||
|
|
||||||
|
var $subtextLanguages = $modal.find('[data-subtext-language]');
|
||||||
|
$.each($subtextLanguages, function() {
|
||||||
|
var language = $(this).data('subtext-language');
|
||||||
|
|
||||||
|
$(this).val('');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#subtext').show();
|
||||||
|
|
||||||
|
$modal.find('select[name="image-type"]').val('image-url');
|
||||||
|
$modal.find('input[name="image-url"]').val('');
|
||||||
|
$modal.find('#font-icon-group').hide();
|
||||||
|
$modal.find('#image-url-group').show();
|
||||||
|
$modal.find('input[name="url"]').val('');
|
||||||
|
|
||||||
|
$modal.modal('show');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindDeleteButton() {
|
||||||
|
$(document).on('click', '[data-action="delete"]', function() {
|
||||||
|
$('#overlay').show();
|
||||||
|
|
||||||
|
var heskUrl = $('#heskUrl').text();
|
||||||
|
var element = elements[$(this).parent().parent().find('[data-property="id"]').text()];
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
method: 'DELETE',
|
||||||
|
url: heskUrl + '/api/v1-internal/custom-navigation/' + element.id,
|
||||||
|
headers: { 'X-Internal-Call': true },
|
||||||
|
success: function() {
|
||||||
|
mfhAlert.success(mfhLang.text('custom_nav_element_deleted'));
|
||||||
|
loadTable();
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
$('#overlay').hide();
|
||||||
|
mfhAlert.errorWithLog(mfhLang.text('error_deleting_custom_nav_element'), data.responseJSON);
|
||||||
|
console.error(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindSortButtons() {
|
||||||
|
$(document).on('click', '[data-action="sort"]', function() {
|
||||||
|
$('#overlay').show();
|
||||||
|
var heskUrl = $('#heskUrl').text();
|
||||||
|
var direction = $(this).data('direction');
|
||||||
|
var element = elements[$(this).parent().parent().find('[data-property="id"]').text()];
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
method: 'POST',
|
||||||
|
url: heskUrl + '/api/v1-internal/custom-navigation/' + element.id + '/sort/' + direction,
|
||||||
|
headers: { 'X-Internal-Call': true },
|
||||||
|
success: function() {
|
||||||
|
loadTable();
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
mfhAlert.errorWithLog(mfhLang.text('error_sorting_custom_nav_elements'), data.responseJSON);
|
||||||
|
console.error(data);
|
||||||
|
$('#overlay').hide();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
@ -84,7 +84,11 @@ var loadJquery = function()
|
|||||||
$('[data-hide]').click(function() {
|
$('[data-hide]').click(function() {
|
||||||
var hide = $(this).attr('data-hide');
|
var hide = $(this).attr('data-hide');
|
||||||
$('#' + hide).hide();
|
$('#' + hide).hide();
|
||||||
})
|
});
|
||||||
|
|
||||||
|
//-- Initialize toastr properties
|
||||||
|
toastr.options.progressBar = true;
|
||||||
|
toastr.options.closeButton = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
function refreshBackgroundVolatileItems() {
|
function refreshBackgroundVolatileItems() {
|
||||||
|
2
js/toastr.min.js
vendored
Normal file
2
js/toastr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -52,6 +52,34 @@ $hesklang['resend_email_notification'] = 'Re-send Email Notification';
|
|||||||
$hesklang['email_notification_sent'] = 'Email notification sent!';
|
$hesklang['email_notification_sent'] = 'Email notification sent!';
|
||||||
$hesklang['email_notification_resend_failed'] = 'Error occurred when trying to send notification email.';
|
$hesklang['email_notification_resend_failed'] = 'Error occurred when trying to send notification email.';
|
||||||
$hesklang['edit_category'] = 'Edit Category';
|
$hesklang['edit_category'] = 'Edit Category';
|
||||||
|
$hesklang['custom_nav_menu_elements'] = 'Custom Nav Menu Elements';
|
||||||
|
$hesklang['create_new'] = 'Create New';
|
||||||
|
$hesklang['custom_nav_element_deleted'] = 'Custom Navigation Element Deleted!';
|
||||||
|
$hesklang['no_custom_nav_elements_found'] = 'No custom nav menu elements found';
|
||||||
|
$hesklang['alert_success'] = 'Success'; // Used for alert messages
|
||||||
|
$hesklang['alert_error'] = 'Error'; // Used for alert messages
|
||||||
|
$hesklang['failed_to_load_custom_nav_elements'] = 'Failed to load custom nav elements!';
|
||||||
|
$hesklang['custom_nav_element_deleted'] = 'Custom nav element deleted!';
|
||||||
|
$hesklang['error_deleting_custom_nav_element'] = 'Error deleting custom nav element!';
|
||||||
|
$hesklang['error_sorting_custom_nav_elements'] = 'Error sorting custom nav elements!';
|
||||||
|
$hesklang['custom_nav_element_created'] = 'Custom nav element created!';
|
||||||
|
$hesklang['custom_nav_element_saved'] = 'Custom nav element saved!';
|
||||||
|
$hesklang['homepage_block'] = 'Homepage - Block';
|
||||||
|
$hesklang['customer_navigation'] = 'Customer Navigation';
|
||||||
|
$hesklang['staff_navigation'] = 'Staff Navigation';
|
||||||
|
$hesklang['custom_nav_text'] = 'Text';
|
||||||
|
$hesklang['custom_nav_subtext'] = 'Subtext';
|
||||||
|
$hesklang['image_url_slash_font_icon'] = 'Image URL / Font Icon';
|
||||||
|
$hesklang['edit_custom_nav_element_title_case'] = 'Edit Custom Nav Element';
|
||||||
|
$hesklang['create_custom_nav_element_title_case'] = 'Create Custom Nav Element';
|
||||||
|
$hesklang['place'] = 'Place';
|
||||||
|
$hesklang['image_type'] = 'Image Type';
|
||||||
|
$hesklang['image_url'] = 'Image URL';
|
||||||
|
$hesklang['image_url_help'] = 'The URL of the image you wish to use. For customer/staff navigation, recommended size is <b>16x16px</b>. For the homepage blocks, recommended size is <b>32x32px</b>.';
|
||||||
|
$hesklang['font_icon'] = 'Font Icon';
|
||||||
|
$hesklang['error_saving_custom_nav_element'] = 'Error saving custom nav element!';
|
||||||
|
$hesklang['place_help'] = 'The location of the custom navigation element.';
|
||||||
|
$hesklang['url_help'] = 'The URL where the user should be taken to. Both relative and absolute URLs are supported.';
|
||||||
|
|
||||||
// ADDED OR MODIFIED IN Mods for HESK 3.0.0
|
// ADDED OR MODIFIED IN Mods for HESK 3.0.0
|
||||||
$hesklang['you_have_x_messages'] = 'You have %s new %s'; // %s: Number of new messages, "message" or "messages", depending on #
|
$hesklang['you_have_x_messages'] = 'You have %s new %s'; // %s: Number of new messages, "message" or "messages", depending on #
|
||||||
|
Loading…
x
Reference in New Issue
Block a user