Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - General - Menú avanzado multinivel #208

Open
wants to merge 141 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
141 commits
Select commit Hold shift + click to select a range
7fa2643
wip
juanSTIC Apr 18, 2024
6808c62
wip
juanSTIC Apr 18, 2024
f546b7d
wip
juanSTIC Apr 19, 2024
13ffc31
first ui version
juanSTIC Apr 19, 2024
8292581
move to custom
juanSTIC Apr 22, 2024
34b0096
saving menu
juanSTIC Apr 22, 2024
f62f441
operative version
juanSTIC Apr 23, 2024
b20a632
with smartmenu library
juanSTIC Apr 23, 2024
2893160
previous move to main nav
juanSTIC Apr 24, 2024
1f047b3
main menu set
juanSTIC Apr 24, 2024
cbcad86
wip
juanSTIC Apr 24, 2024
d8e3008
with two files
juanSTIC Apr 29, 2024
593b4a2
renaming
juanSTIC Apr 29, 2024
7e16f5b
fine tunning
juanSTIC Apr 29, 2024
507460d
wip
juanSTIC Apr 30, 2024
69835f2
wip
juanSTIC Apr 30, 2024
40e2693
rename to sm-stic
juanSTIC Apr 30, 2024
e939e7d
stic scss
juanSTIC Apr 30, 2024
afd389a
Merge branch 'develop' into enhancement/multiLevelMenu
juanSTIC Jun 28, 2024
cb9ebe4
css
juanSTIC Jun 28, 2024
1c10845
propuesta css
juanSTIC Jul 4, 2024
3afd0d1
SticCustom
juanSTIC Jul 5, 2024
68a718b
comment
juanSTIC Jul 8, 2024
185652d
ensuree copying between trees
juanSTIC Jul 8, 2024
43f4330
style
juanSTIC Jul 8, 2024
af25cc5
fix restore
juanSTIC Jul 8, 2024
3715707
language files
juanSTIC Jul 9, 2024
3c26883
licence & renaming
juanSTIC Jul 9, 2024
d349372
remove file
juanSTIC Jul 9, 2024
f1b8dda
renaming
juanSTIC Jul 9, 2024
dd6d636
remove blank spaces
juanSTIC Jul 9, 2024
129dd8c
remove blank changes
juanSTIC Jul 9, 2024
c8da9b9
renaming
juanSTIC Jul 9, 2024
72f1064
move menu
juanSTIC Jul 9, 2024
5fc3e98
reinclude option
juanSTIC Jul 9, 2024
98bd9dd
add jstree library
juanSTIC Jul 9, 2024
048144c
add stic custom info
juanSTIC Jul 9, 2024
25ea443
tunning
juanSTIC Jul 9, 2024
0fd81a9
hide empty nodes
juanSTIC Jul 9, 2024
8c9b66b
add js to grouping
juanSTIC Jul 9, 2024
e0b311f
menu options
juanSTIC Jul 10, 2024
59348e7
install script & more
juanSTIC Jul 10, 2024
b05369c
undo git ignore
juanSTIC Jul 10, 2024
f9904d6
add url's
juanSTIC Jul 10, 2024
841d212
tunnig icon width
juanSTIC Jul 10, 2024
78862dc
activadte/deactivate funcionality
juanSTIC Jul 10, 2024
2177d73
enable/disable system
juanSTIC Jul 11, 2024
dbbac56
labels
juanSTIC Jul 11, 2024
c3b22d6
action menu
juanSTIC Jul 11, 2024
06dea9d
remove file
juanSTIC Jul 11, 2024
d4575ee
remove file
juanSTIC Jul 11, 2024
b43ba86
fine tunning
juanSTIC Jul 11, 2024
f917f78
translate comments
juanSTIC Jul 11, 2024
e346dda
config variable names
juanSTIC Jul 19, 2024
0e53b37
remove tabConfig.php
juanSTIC Jul 19, 2024
1d0b64b
tunning
juanSTIC Jul 19, 2024
6052216
move convert logic to controller
juanSTIC Jul 19, 2024
325d8a3
hidden change to legacy
juanSTIC Jul 19, 2024
0c5d652
Improving translation
jalbaiges Aug 28, 2024
009e086
Improving translation
jalbaiges Aug 28, 2024
8f02ba7
Minor fix
jalbaiges Aug 28, 2024
7658d84
Improving translation
jalbaiges Aug 28, 2024
c76832b
Improving translation
jalbaiges Aug 28, 2024
6f0013b
Improving translation
jalbaiges Aug 28, 2024
0574e70
Improving translation
jalbaiges Aug 28, 2024
2fe93a5
Improving translation
jalbaiges Aug 28, 2024
9a8da7d
Improving translation
jalbaiges Aug 28, 2024
387b092
minor fix
jalbaiges Aug 28, 2024
5612fbd
translate string
juanSTIC Sep 2, 2024
a32a67d
fix label
juanSTIC Sep 2, 2024
cc3ba72
change bg hovered node colors
juanSTIC Sep 2, 2024
8d0e9da
hide disabled modules in config page
juanSTIC Sep 2, 2024
6706343
label change
juanSTIC Sep 2, 2024
0a7cc29
label use
juanSTIC Sep 2, 2024
3371b22
more information & some fixes
juanSTIC Sep 2, 2024
142b47d
Improving translation
jalbaiges Sep 2, 2024
3a59542
Improving translation
jalbaiges Sep 2, 2024
051cefb
Improving translation
jalbaiges Sep 2, 2024
7ff830a
Improving translation
jalbaiges Sep 2, 2024
10930c0
Set title CSS class
jalbaiges Sep 2, 2024
376c078
Set main div class
jalbaiges Sep 2, 2024
e7758e9
Set bottom padding
jalbaiges Sep 2, 2024
62bcc91
Undo previous commit
jalbaiges Sep 2, 2024
b8229a9
Remove unneeded class
jalbaiges Sep 2, 2024
956a1f4
Sync with scss file
jalbaiges Sep 2, 2024
464f1ad
Improving translation
jalbaiges Sep 2, 2024
6462f1e
Typo
jalbaiges Sep 2, 2024
11cf25f
Typo++
jalbaiges Sep 2, 2024
882b890
Improving translation
jalbaiges Sep 2, 2024
7207fcf
Improving translation
jalbaiges Sep 2, 2024
b1ce351
Improving translation
jalbaiges Sep 2, 2024
b926f65
Improving translation
jalbaiges Sep 2, 2024
fea164b
https://github.com/SinergiaTIC/SinergiaCRM/pull/208#issuecomment-2362…
juanSTIC Sep 20, 2024
f7bdb33
https://github.com/SinergiaTIC/SinergiaCRM/pull/208#issuecomment-2363…
juanSTIC Sep 20, 2024
f578d80
fix id in favorites link
juanSTIC Sep 20, 2024
d23fa0c
translate action commands & fix css
juanSTIC Sep 20, 2024
0f20bdd
add label
juanSTIC Sep 20, 2024
d527c93
add new labels
juanSTIC Sep 20, 2024
d67153b
fix spaces
juanSTIC Sep 20, 2024
7bd7196
Improving translation
jalbaiges Sep 20, 2024
93ba54b
Improving translation
jalbaiges Sep 20, 2024
e939f3a
Improving translation
jalbaiges Sep 20, 2024
b5c7c2e
set hover timeout to 100ms
juanSTIC Sep 25, 2024
708b540
add as new menu + icon
juanSTIC Sep 25, 2024
3b9d081
organize labels
juanSTIC Sep 25, 2024
32449c9
remove unused code
juanSTIC Sep 25, 2024
fc0690a
more labels
juanSTIC Sep 25, 2024
36f8956
Merge branch 'develop' into enhancement/multiLevelMenu
juanSTIC Sep 25, 2024
c486b94
add new module to default
juanSTIC Sep 25, 2024
63a8978
Comments minor fixes
jalbaiges Sep 26, 2024
bac2ea1
Improving translation
jalbaiges Sep 26, 2024
fa56ce8
Improving translation
jalbaiges Sep 26, 2024
85eb1c7
Improving translation
jalbaiges Sep 26, 2024
4e54066
Improving translation
jalbaiges Sep 26, 2024
63832b8
Improving translation
jalbaiges Oct 1, 2024
ae4cf6a
Improving translation
jalbaiges Oct 1, 2024
ffdcc36
Improving translation
jalbaiges Oct 1, 2024
efeb54a
Minor fix
jalbaiges Oct 1, 2024
03052fc
Improving translation
jalbaiges Oct 1, 2024
510317e
move menu def to custom
juanSTIC Oct 2, 2024
239e33c
move config to administration module
juanSTIC Oct 7, 2024
7f5bccd
fix menu link
juanSTIC Oct 7, 2024
70c7bbd
duplicate change method
juanSTIC Oct 8, 2024
3201723
duplicate labels
juanSTIC Oct 8, 2024
5b7e737
duplicate funcionality & labels
juanSTIC Oct 8, 2024
1267498
two fixes
juanSTIC Oct 8, 2024
27790cb
Improving translation
jalbaiges Oct 8, 2024
1a436c6
Improving translation
jalbaiges Oct 8, 2024
84f204a
Improving translation
jalbaiges Oct 8, 2024
b4b265f
Improving translation
jalbaiges Oct 8, 2024
41f0d24
Improving translation
jalbaiges Oct 8, 2024
b7eb65f
Improving translation
jalbaiges Oct 8, 2024
01649d4
Improving translation
jalbaiges Oct 8, 2024
4fe7d83
Improving translation
jalbaiges Oct 8, 2024
6336976
remove change to legacy options
juanSTIC Oct 8, 2024
0ec48ac
normalize labels
juanSTIC Oct 8, 2024
aa97a71
add icons to all-menu
juanSTIC Oct 9, 2024
30b5306
handle movement between trees
juanSTIC Oct 10, 2024
14d522a
fix change info
juanSTIC Oct 10, 2024
02c9f87
remove file
juanSTIC Oct 10, 2024
a968947
fix create new node unique id
juanSTIC Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 289 additions & 0 deletions SticInclude/SticAdvancedMenu.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
<?php
/**
* This file is part of SinergiaCRM.
* SinergiaCRM is a work developed by SinergiaTIC Association, based on SuiteCRM.
* Copyright (C) 2013 - 2023 SinergiaTIC Association
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SinergiaTIC Association at email address [email protected].
*/

/**
* Generates an HTML menu from a list of items, filtering out invalid nodes.
*
* This function builds an HTML list for a navigation menu using a recursive
* structure. It filters out menu items that don't correspond to valid modules
* and don't have valid children. It also handles custom URLs embedded in menu items.
* The function relies on global variables to obtain the corresponding texts for
* the menu items and respects configuration for displaying icons and the "All" menu.
*
* @param array $items The menu items to process, each item can contain subitems and custom URLs.
* @param bool $isFirstLevel Indicates if it's the top level of the menu.
* @param array|null $validTabs Array of valid tabs/modules for the current user.
* @return string The generated HTML code for the menu.
*/
function generateMenu($items, $isFirstLevel = true, $validTabs = null)
{
global $app_list_strings, $app_strings, $current_user, $sugar_config;

// Initialize valid tabs if not provided
if ($validTabs === null) {
require_once 'modules/MySettings/TabController.php';
$controller = new TabController();
$validTabs = $controller->get_tabs($current_user)[0];
foreach ($validTabs as $key => $value) {
$validTabs[$key] = $app_list_strings['moduleList'][$key];
}
asort($validTabs);
}

$html = '';
$validItemsCount = 0;

$module = $_REQUEST['module'];
$moduleLabel = $app_list_strings['moduleList'][$module];

$recents = array_slice(getUserModuleRecents($current_user->id, $module), 0, 5);
$favs = array_slice(getUserModuleFavs($current_user->id, $module), 0, 5);

// Add the new menu icon as the first item if it's the first level
if ($isFirstLevel) {
$html .= '<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="glyphicon glyphicon-menu-hamburger"></i>
</a>
<ul class="dropdown-menu" id="actions-area">


<li class="divider"></li>';

if (!empty($recents)) {
$html .= '<li class="dropdown-header" id="recents-area">Recientes</li>';
foreach ($recents as $recent) {
$text = strlen($recent['item_summary']) > 70 ? $recent['item_summary_short'] : $recent['item_summary'];
$html .= "<li style='display:flex;justify-content: space-between;'>
<a style='width:80%' href='index.php?module=$module&action=DetailView&record={$recent['item_id']}' title='{$recent['item_summary']}'>$text</a>
<a style='width:20%' href='index.php?module=$module&action=EditView&record={$recent['item_id']}' title='{$recent['item_summary']}'><i class='glyphicon glyphicon-pencil' aria-hidden='true'></i></a>
</li>";

}
$html .= '<li class="divider"></li>';
}
if (!empty($favs)) {
$html .= '<li class="dropdown-header" id="recents-area">Favoritos</li>';
foreach ($favs as $fav) {
$text = strlen($fav['item_summary']) > 70 ? $fav['item_summary_short'] : $fav['item_summary'];
$html .= "<li style='display:flex;justify-content: space-between;'>
<a style='width:80%' href='index.php?module=$module&action=DetailView&record={$fav['id']}' title='{$fav['item_summary']}'>$text</a>
<a style='width:20%' href='index.php?module=$module&action=DetailView&record={$fav['id']}' title='{$fav['item_summary']}'><i class='glyphicon glyphicon-pencil' aria-hidden='true'></i></a>
</li>";
}
$html .= '<li class="divider"></li>';
}

$html .= '</ul></li>';
$validItemsCount++;
}

foreach ($items as $item) {

$cleanId = preg_replace('/__.*$/', '', $item['id']);

// Get the display text for the menu item
$text = ($app_list_strings['moduleList'][$cleanId] ?? $app_strings[$cleanId] ?? str_replace('_', ' ', $cleanId));

// If item contains URL, extract it and cut text
$itemURL = extractUrl($text);
if ($itemURL) {
$text = str_replace("|{$itemURL}", '', $text);
}

$hasChildren = isset($item['children']) && is_array($item['children']) && !empty($item['children']);
$isValidModule = array_key_exists($cleanId, $validTabs);

// Recursively generate HTML for child items
$childrenHtml = '';
if ($hasChildren) {
$childrenHtml = generateMenu($item['children'], false, $validTabs);
}

// Only include valid modules, items with valid children, or items with custom URLs
if ($isValidModule || !empty($childrenHtml) || $itemURL) {
$validItemsCount++;
$itemHtml = '<li' . ($hasChildren ? ' class="dropdown"' : '') . '>';

if ($isValidModule) {
// Generate link for valid modules
$lowerModule = str_replace('_', '-', strtolower($cleanId));
// Include icon if enabled in configuration
$iconString = $sugar_config['stic_advanced_menu_icons'] ? "<span class='suitepicon suitepicon-module-{$lowerModule}'></span>" : '';
$itemHtml .= "<a href='index.php?module={$cleanId}&action=index'>$iconString $text </a>";
} elseif ($itemURL) {
// Generate external link for items with custom URLs
$itemHtml .= "<a title='$itemURL' target='_blank' href='$itemURL'><span class='glyphicon glyphicon-link'></span> $text </a>";
} elseif ($hasChildren) {
// Generate dropdown toggle for items with children
$itemHtml .= "<a href='#' class='no-link'>" . $text . '</a>';
}

$itemHtml .= $childrenHtml;
$itemHtml .= '</li>';
$html .= $itemHtml;
}
}

// Wrap the menu items in a <ul> if there are valid items or it's the first level
if ($validItemsCount > 0 || $isFirstLevel) {
$menuHtml = $isFirstLevel ? '<ul id="stic-menu" class="sm sm-stic">' : '<ul>';
if ($isFirstLevel) {
// Add home link at the first level
$menuHtml .= '<li><a href="index.php?module=Home&action=index" onclick="window.location.href=this.href; return false;"><i class="glyphicon glyphicon-home"></i></a></li>';
}
$menuHtml .= $html;

// Add the "All" menu if it's the first level and enabled in configuration
if ($isFirstLevel && $sugar_config['stic_advanced_menu_all']) {
$menuHtml .= '<li class="dropdown">';
$menuHtml .= "<a href='#' class='no-link'>{$app_strings['LBL_TABGROUP_ALL']} </a>";
$menuHtml .= '<ul>';
$menuHtml .= '<li><input type="text" id="search-all" placeholder="' . $app_strings['LBL_SEARCH'] . '"></input></li>';
foreach ($validTabs as $key => $value) {
$lowerModule=str_replace('_','-',strtolower($key));
$iconString = $sugar_config['stic_advanced_menu_icons'] ? "<span class='suitepicon suitepicon-module-{$lowerModule}'></span>" : '';
$menuHtml .= "<li><a href='index.php?module={$key}&action=index'> $iconString $value </a></li>";
}
$menuHtml .= '</ul>';
$menuHtml .= '</li>';
}

$menuHtml .= '</ul>';
return $menuHtml;
}

return '';
}

/**
* Adds text properties to menu items based on their IDs.
*
* This function recursively processes an array of menu items, adding a 'text'
* property to each item based on its 'id'. It uses global string lists to
* find the appropriate text for each menu item.
*
* @param array &$array The array of menu items to process.
*/
function addMenuProperties(&$array)
{

include_once 'modules/MySettings/TabController.php';
$controller = new TabController();
$currentTabs = $controller->get_system_tabs();

global $app_list_strings, $app_strings;
foreach ($array as $key => &$value) {
if (is_array($value)) {
if (isset($value['id'])) {
$cleanValueId = preg_replace('/__.*$/', '', $value['id']);

$value['text'] = ($app_list_strings['moduleList'][$cleanValueId] ?? '');
// Set disabled property if module is disabled
if (!in_array($cleanValueId, $currentTabs) && isset($app_list_strings['moduleList'][$cleanValueId])) {
$value['disabled'] = true;
}
if (empty($value['text'])) {
$value['text'] = $app_strings[$cleanValueId];
}
if (empty($value['text'])) {
$value['text'] = str_replace('_', ' ', $cleanValueId);
}
}
addMenuProperties($value); // Recursively process sub-arrays
}
}
}

/**
* Extracts a URL from the end of a string if preceded by a pipe character ('|').
*
* Matches URLs with or without 'http(s)://' prefix, including domain and optional path.
*
* @param string $string Input string to search for a URL.
* @return string|null Extracted URL if found, null otherwise.
*/
function extractUrl($string)
{
$pattern = '/\|((https?:\/\/)?([a-z0-9\.-]+)(:\d+)?(\/[^?#]*)?(\?[^#]*)?(#.*)?$)/i';

if (preg_match($pattern, $string, $matches)) {
return $matches[1];
}

return null;
}

function getUserModuleRecents($userId, $module)
{
$tracker = BeanFactory::getBean('Trackers');
$history = $tracker->get_recently_viewed($userId);

$history = array_filter($history, function ($item) use ($module) {
return $item['module_name'] == $module;
});

foreach ($history as $key => $row) {
$history[$key]['item_summary_short'] =
to_html(getTrackerSubstring($row['item_summary'])); //bug 56373 - need to re-HTML-encode
$history[$key]['image'] =
SugarThemeRegistry::current()->getImage(
$row['module_name'],
'border="0" align="absmiddle"',
null,
null,
'.gif',
$row['item_summary']
);
}

return $history;

}
function getUserModuleFavs($userId, $module)
{

$favoritesBean = BeanFactory::getBean('Favorites');
$favs = $favoritesBean->getCurrentUserSidebarFavorites();

$favs = array_filter($favs, function ($item) use ($module) {
return $item['module_name'] == $module;
});

foreach ($favs as $key => $row) {
$history[$key]['item_summary_short'] =
to_html(getTrackerSubstring($row['item_summary'])); //bug 56373 - need to re-HTML-encode
$history[$key]['image'] =
SugarThemeRegistry::current()->getImage(
$row['module_name'],
'border="0" align="absmiddle"',
null,
null,
'.gif',
$row['item_summary']
);
}

return $favs;

}
88 changes: 88 additions & 0 deletions SticInclude/js/SticSmartmenus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* This file is part of SinergiaCRM.
* SinergiaCRM is a work developed by SinergiaTIC Association, based on SuiteCRM.
* Copyright (C) 2013 - 2023 SinergiaTIC Association
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SinergiaTIC Association at email address [email protected].
*/


$(document).ready(function() {
// Initialize SmartMenus plugin with specific offsets
$("#stic-menu").smartmenus({
subMenusSubOffsetX: 1,
subMenusSubOffsetY: -8,
showTimeout: 100
});

// Update the menu when the first item is clicked (presumably the menu toggle)
$("#stic-menu > li:first-child > a").on("click", function(e) {
e.preventDefault();
updateActionMenu();
});

// Update the menu on initial page load
updateActionMenu();
});

/**
* Builds the action menu by cloning elements from the sidebar
* @returns {jQuery} A new unordered list containing the action menu items
*/
function buildActionMenu() {
var $newActionMenu = $("<ul>");

// Iterate through each action menu link in the sidebar
$("#actionMenuSidebar ul li.actionmenulinks").each(function() {
var $originalLink = $(this).find("a");
var $icon = $originalLink.find(".side-bar-action-icon span").clone();
var linkText = $originalLink.find(".actionmenulink").text();

// Create a new link with the same attributes as the original
var $newLink = $("<a>")
.attr("href", $originalLink.attr("href"))
.attr("data-action-name", $originalLink.data("action-name"))
.addClass("link-cloned");

// Append the icon and text to the new link
$newLink.append($icon).append(linkText);

// Wrap the new link in a list item and add it to the menu
var $newListItem = $("<li>").append($newLink);
$newActionMenu.append($newListItem);
});

return $newActionMenu;
}

/**
* Updates the action menu in the main navigation
* This function rebuilds the action menu and inserts it into the appropriate area
*/
function updateActionMenu() {
var $newActionMenu = buildActionMenu();
var $actionsArea = $("#stic-menu #actions-area");

// Insert the new action menu at the beginning of the actions area, checking that the action is not being repeated
if ($("#stic-menu #actions-area .link-cloned").length == 0) {
$actionsArea.prepend($newActionMenu.children());
}
// If there are no action items, reduce the opacity of the entire section
if ($actionsArea.find("a").length == 0) {
$actionsArea.closest("li").css("opacity", 0.2);
}
}
Loading
Loading