N°2847 First iteration for newsroom menu:

* Kept old js widget but refactored/tweak'd it with some of our new conventions
* Added a newsroom menu component extending popupmenu
* Working as in 2.7
Still todo :
* Add variables for scss file
* Use wiget variables for most of js widget
* Correctly place the popup (absolute with <> containers ? poppers.js ? )
* Intialize toggler red bubble when new messages are in
* Replace hardcoded text in usermenu with correct dict entry updated with the nb of new message
* Only allow to open the popup when ajax calls are done
This commit is contained in:
Stephen Abello
2020-08-06 14:35:02 +02:00
parent c9dab08324
commit a5216de232
19 changed files with 427 additions and 82 deletions

View File

@@ -21,3 +21,4 @@
@import "global-search";
@import "popover-menu";
@import "popover-menu-item";
@import "newsroom-menu";

View File

@@ -0,0 +1,88 @@
/*!
* Copyright (C) 2013-2020 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop 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
*/
/* SCSS variables */
// Todo :(
#ibo-navigation-menu--notifications-menu {
flex-flow: column;
.ibo-navigation-menu--notifications--messages-section{
overflow-x: auto;
}
}
.ibo-navigation-menu--notifications--item--image{
width: 20px;
max-height: 20px;
margin: 0 6px;
border-radius: 100%;
}
img.ibo-navigation-menu--notifications--item--image[src=""]{
display: none;
}
img.ibo-navigation-menu--notifications--item--image:not([src=""]) ~ i.ibo-navigation-menu--notifications--item--image
{
display: none;
}
.ibo-navigation-menu--notifications--item--bottom-text{
float: right;
font-size: 12px;
align-self: center;
margin-left: auto;
display: flex;
flex-direction: column;
align-items: center;
}
.ibo-navigation-menu--notifications--item--content{
font-size: 14px;
padding: 0 14px;
img{
max-height: 100px;
padding: 5px;
}
}
.ibo-navigation-menu--notifications-item{
display: flex;
flex-direction: row;
}
.ibo-navigation-menu--notifications--item--new-message-indicator{
width: 10px;
height: 10px;
background-color: $ibo-color-blue-500;
border-radius: 100%;
margin-top: 4px;
}
.ibo-navigation-menu--notifications-show-all-multiple ~ .ibo-popover-menu{
bottom: 0;
.ibo-navigation-menu--notifications--item--new-message-indicator{
display: inline-block;
margin-right: 15px;
}
.ibo-navigation-menu--notifications-show-all-multiple--counter{
@extend %ibo-font-ral-bol-200;
}
}
.ibo-navigation-menu--notifications-dismiss-all--icon{
margin: 0 10px 0 0;
}
.ibo-popover-menu--item--no-message{
text-align: center;
}
.ibo-popover-menu--item--no-message--image{
display: block;
padding: 20px;
}

View File

@@ -45,7 +45,8 @@ $ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !defa
align-self: flex-start;
margin: 0px 0px;
width: 100%;
@extend %ibo-text-truncated-with-ellipsis;
white-space: nowrap;
&:first-child{
border-radius: $ibo-popover-menu--section-border-radius $ibo-popover-menu--section-border-radius 0 0;
}

View File

@@ -174,7 +174,7 @@ $ibo-navigation-menu--user-picture--image-expanded--size: 72px !default;
.ibo-navigation-menu--bottom-part{
padding: $ibo-navigation-menu--bottom-part--padding-y $ibo-navigation-menu--bottom-part--padding-x;
.ibo-navigation-menu--notifications{
.ibo-navigation-menu--notifications .ibo-navigation-menu--notifications-toggler{
display: none;
}
.ibo-navigation-menu--user-info{

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -43,6 +43,7 @@ $(function()
_create: function()
{
this._bindEvents();
this._closePopup();
},
// events bound via _bind are removed automatically
// revert other modifications here
@@ -67,9 +68,8 @@ $(function()
// Methods
_onBodyClick: function(oEvent)
{
if($(oEvent.target.closest('[data-role="ibo-popover-menu"]')).length === 0 && $(oEvent.target.closest(this.options.toggler)).length === 0)
if($(oEvent.target.closest(this.js_selectors.menu)).length === 0 && $(oEvent.target.closest(this.options.toggler)).length === 0)
{
console.log('a');
this._closePopup();
}
},
@@ -85,5 +85,9 @@ $(function()
{
this._openPopup();
},
closePopup: function()
{
this._closePopup();
},
});
});

View File

@@ -44,7 +44,7 @@ $(function()
menu_filter_clear: '[data-role="ibo-navigation-menu--menu-filter-clear"]',
user_menu_toggler: '[data-role="ibo-navigation-menu--user-menu--toggler"]',
user_menu_container: '[data-role="ibo-navigation-menu--user-menu-container"]',
user_menu: '[data-role="ibo-popover-menu"]'
user_menu: '[data-role="ibo-navigation-menu--user-menu-container"] > [data-role="ibo-popover-menu"]'
},
filter_throttle_timeout: null,

View File

@@ -24,7 +24,18 @@ $(function()
{
var me = this;
this.aMessageByProvider = [];
$(me.element).popover_menu({'toggler': '[data-role="ibo-navigation-menu--notifications-toggler"]'});
$('[data-role="ibo-navigation-menu--notifications-toggler"]').on('click', function(oEvent) {
var oEventTarget = $(oEvent.target);
var aEventTargetPos = oEventTarget.position();
$(me.element).css({
'top': (aEventTargetPos.top + parseInt(oEventTarget.css('marginTop'), 10) - $(me.element).height()) + 'px',
'left': (aEventTargetPos.left + parseInt(oEventTarget.css('marginLeft'), 10) + oEventTarget.width()) + 'px',
'max-height' : (aEventTargetPos.top + parseInt(oEventTarget.css('marginTop'), 10) - 100) + 'px'
});
$(me.element).popover_menu("openPopup");
});
this.element
.addClass('itop-newsroom_menu');
@@ -152,115 +163,158 @@ $(function()
this._buildMenu(aAllMessages);
},
_buildDismissAllSection: function()
{
return '<div class="ibo-popover-menu--section ibo-navigation-menu--notifications-dismiss-all" data-role="ibo-popover-menu--section"><a class="ibo-popover-menu--item" data-role="ibo-navigation-menu--notifications-dismiss-all" ><i class="fas fa-fw fa-check ibo-navigation-menu--notifications-dismiss-all--icon"></i>'+this.options.labels.mark_all_as_read+'</a> <hr class="ibo-popover-menu--item ibo-popover-menu--separator"> </div>';
},
_buildMessageSection: function()
{
return '<div class="ibo-popover-menu--section" data-role="ibo-popover-menu--section">';
},
_buildShowAllMessagesSection: function()
{
return '<div class="ibo-popover-menu--section ibo-navigation-menu--notifications--messages-section" data-role="ibo-popover-menu--section">';
},
_buildMessageItems: function(sId, sText, sImage, sStartDate, sProvider, sUrl)
{
var sNewMessageIndicator = '<div class="ibo-navigation-menu--notifications--item--new-message-indicator"></div>';
sImage = '<img class="ibo-navigation-menu--notifications--item--image" src="'+sImage+'"><i class="ibo-navigation-menu--notifications--item--image '+this.options.placeholder_image_icon+'"></i>';
var div = document.createElement("div");
div.textContent = sText;
var sDescription = div.innerHTML; // Escape HTML entities for XSS prevention
//Todo: make only one converter per loop
var converter = new showdown.Converter({noHeaderId: true});
var sRichDescription = '<div class="ibo-navigation-menu--notifications--item--content">' + converter.makeHtml(sDescription) +'</div>';
var sBottomText = '<span class="ibo-navigation-menu--notifications--item--bottom-text">'+ sImage + '<span>' + this.options.providers[sProvider].label+'</span> <span> ' + moment(sStartDate).fromNow()+'</span></span>';
return '<a class="ibo-popover-menu--item ibo-navigation-menu--notifications-item" data-role="ibo-navigation-menu--notifications-item" data-msg-id="'+sId+'" data-provider-id="'+sProvider+'" href="'+sUrl+'" target="_blank" id="newsroom_menu_item_'+sId+'">' +
sNewMessageIndicator + sRichDescription + sBottomText +'</a>';
},
_buildNoMessageItem: function()
{
return '<div class="ibo-popover-menu--item ibo-popover-menu--item--no-message">' + this.options.labels.no_message + '<img class="ibo-popover-menu--item--no-message--image" src="../images/illustrations/undraw_empty.svg" alt="TODO"/></div>';
},
_buildSingleShowAllMessagesItem: function()
{
return '<a class="ibo-popover-menu--item" data-role="ibo-navigation-menu--notifications-show-all" href="'+me.options.providers[0].view_all_url+'">' + this.options.labels.view_all + '</a>';
},
_buildMultipleShowAllMessagesItem: function(aUnreadMessagesByProvider)
{
var sNewMessageIndicator = '<div class="ibo-navigation-menu--notifications--item--new-message-indicator"></div>';
var sUnreadMessages = ''
for(k in this.options.providers)
{
var sExtraMessages = '';
if (aUnreadMessagesByProvider[k] > 0)
{
sExtraMessages = ' <span class="ibo-navigation-menu--notifications-show-all-multiple--counter">('+aUnreadMessagesByProvider[k]+')</span>'
}
sUnreadMessages += '<a class="ibo-popover-menu--item" data-provider-id="'+k+'" href="'+this.options.providers[k].view_all_url+'" target="_blank">'+ sNewMessageIndicator +this.options.providers[k].label+sExtraMessages+'</a>';
}
return '<a class="ibo-popover-menu--item ibo-navigation-menu--notifications-show-all-multiple" data-role="ibo-navigation-menu--notifications-show-all-multiple" href="#">'+this.options.labels.view_all+'<i class="fas fas-caret-down"></i></a>' +
'<div class="ibo-popover-menu" data-role="ibo-popover-menu"><div class="ibo-popover-menu--section" data-role="ibo-popover-menu--section">'+sUnreadMessages+'</div></div>';
},
_buildMenu: function(aAllMessages)
{
var me = this;
var iTotalCount = aAllMessages.length;
var iCount = 0;
var sHtml = '<span id="newsroom_menu" class="itop_popup toolkit_menu"><ul><li><i id="newsroom_menu_icon" class="top-right-icon icon-additional-arrow '+this.options.image_icon+'"></i><ul>';
sHtml += '<li class="newsroom_menu_item" id="newsroom_menu_dismiss_all"><i class="fas fa-fw fa-check"></i>'+this.options.labels.mark_all_as_read+'</li>';
var sDismissAllSection = this._buildDismissAllSection();
var sMessageSection = this._buildMessageSection();
var sShowAllMessagesSection = this._buildShowAllMessagesSection();
moment.locale(GetUserLanguage());
var aUnreadMessagesByProvider = [];
for(var k in this.options.providers)
{
aUnreadMessagesByProvider[k] = 0;
}
console.log(aAllMessages);
for(var k in aAllMessages)
{
var oMessage = aAllMessages[k];
aUnreadMessagesByProvider[oMessage.provider]++;
if (iCount < this.options.display_limit)
if (iCount < this.options.display_limit + 4)
{
var sImage = '';
if ((oMessage.image !== undefined) && (oMessage.image !== null))
{
sImage = '<img src="'+oMessage.image+'">';
}
else
{
sImage = '<i class="'+this.options.placeholder_image_icon+'"></i>';
}
var div = document.createElement("div");
div.textContent = oMessage.text;
var sDescription = div.innerHTML; // Escape HTML entities for XSS prevention
var converter = new showdown.Converter({noHeaderId: true});
var sRichDescription = converter.makeHtml(sDescription);
sRichDescription += '<span class="newsroom_menu_item_date">'+this.options.providers[oMessage.provider].label+' - '+moment(oMessage.start_date).fromNow()+'</span>';
sHtml += '<li class="newsroom_menu_item" data-msg-id="'+oMessage.id+'" data-provider-id="'+oMessage.provider+'" data-url="'+oMessage.url+'" id="newsroom_menu_item_'+oMessage.id+'"><div>'+sImage+'<p>'+sRichDescription+'</p><div style="clear:both"></div></div></li>';
var sMessageItem = this._buildMessageItems(oMessage.id, oMessage.text, oMessage.image, oMessage.start_date, oMessage.provider, oMessage.url)
//$(sMessageSection).append(sMessageItem);
sMessageSection += sMessageItem;
}
iCount++;
}
if (iCount == 0)
{
sHtml += '<li class="newsroom_menu_item" id="newsroom_no_new_message"><div><p>'+this.options.labels.no_message+'</p><div style="clear:both"></div></div></li>';
var sNoMessageItem = this._buildNoMessageItem();
sMessageSection += sNoMessageItem;
}
sMessageSection += ' <hr class="ibo-popover-menu--item ibo-popover-menu--separator"> </div>';
if (this.options.providers.length == 1)
{
sHtml += '<li class="newsroom_menu_item" id="newsroom_menu_show_all">'+this.options.labels.view_all+'</li>';
var SingleShowAllMessagesItem = this._buildSingleShowAllMessagesItem();
//$(sShowAllMessagesSection).append(SingleShowAllMessagesItem);
sShowAllMessagesSection += SingleShowAllMessagesItem;
sShowAllMessagesSection += '</div>'
}
else
{
sHtml += '<li class="no-padding"><span id="newsroom_show_all_submenu" class="itop_popup toolkit_menu"><ul><li>'+this.options.labels.view_all+'&nbsp;▾<ul>';
for(k in this.options.providers)
{
var sExtraMessages = '';
if (aUnreadMessagesByProvider[k] > 0)
{
sExtraMessages = ' <span class="newsroom_extra_messages_counter">'+aUnreadMessagesByProvider[k]+'</span>'
}
sHtml += '<li class="newsroom_sub_menu_item" data-provider-id="'+k+'">'+this.options.providers[k].label+sExtraMessages+'</li>';
}
sHtml += '</ul></li></ul></li></ul></span>';
var MultipleShowAllMessagesItem = this._buildMultipleShowAllMessagesItem(aUnreadMessagesByProvider);
sShowAllMessagesSection += MultipleShowAllMessagesItem + '</div>'
}
if (iCount > 0)
{
sHtml += '</ul></li></ul></span><div id="newsroom_menu_counter_container"><span id="newsroom_menu_counter">'+iTotalCount+'</span></div></span>';
$(this.element).html(sHtml);
$(this.element).html(sDismissAllSection + sMessageSection + sShowAllMessagesSection);
$('.ibo-navigation-menu--notifications--item--content img').each(function(){
tippy(this, {'content': this.outerHTML, 'placement': 'left', 'trigger': 'mouseenter focus', 'animation':'shift-away-subtle', 'allowHTML': true });
});
var me = this;
$('#newsroom_menu > ul').popupmenu();
$('#newsroom_menu_counter').on('click', function() {setTimeout(function(){ $('#newsroom_menu_icon').trigger('click') }, 10);});
$('.newsroom_menu_item[data-msg-id]').on('click', function(ev) { me._handleClick(this); });
$('#newsroom_menu_dismiss_all').on('click', function(ev) { me._markAllAsRead(); });
if (this.options.providers.length == 1)
{
$('#newsroom_menu_show_all').on('click', function(ev) { window.open(me.options.providers[0].view_all_url, '_blank'); });
}
else
{
$('#newsroom_show_all_submenu > ul').popupmenu();
$('.newsroom_sub_menu_item').on('click', function() { var idx = parseInt($(this).attr('data-provider-id'), 10); window.open(me.options.providers[idx].view_all_url, '_blank');});
}
//$('#newsroom_menu_counter').on('click', function() {setTimeout(function(){ $('#newsroom_menu_icon').trigger('click') }, 10);});
//$('.newsroom_menu_item[data-msg-id]').on('click', function(ev) { me._handleClick(this); });
$('[data-role="ibo-navigation-menu--notifications-item"]').on('click', function(oEvent){
me._handleClick(this);
});
$('[data-role="ibo-navigation-menu--notifications-dismiss-all"]').on('click', function(ev) { me._markAllAsRead(); });
}
else
{
sHtml += '</ul></li></ul></span><div id="newsroom_menu_counter_container"><span id="newsroom_menu_counter" style="visibility:hidden"></span></div></span>';
$(this.element).html(sHtml);
$('#newsroom_menu_dismiss_all').remove();
$(this.element).html(sDismissAllSection + sMessageSection + sShowAllMessagesSection);
var me = this;
$('#newsroom_menu > ul').popupmenu();
$('#top-left-newsroom-cell > img').attr('title', this.options.labels.no_message);
if (this.options.providers.length == 1)
{
$('#newsroom_menu_show_all').on('click', function(ev) { window.open(me.options.providers[0].view_all_url, '_blank'); });
}
else
{
$('#newsroom_show_all_submenu > ul').popupmenu();
$('.newsroom_sub_menu_item').on('click', function() { var idx = parseInt($(this).attr('data-provider-id'), 10); window.open(me.options.providers[idx].view_all_url, '_blank');});
}
}
if (this.options.providers.length != 1)
{
var oElem = $('[data-role="ibo-navigation-menu--notifications-show-all-multiple"]~[data-role="ibo-popover-menu"]');
oElem.popover_menu({'toggler': '[data-role="ibo-navigation-menu--notifications-show-all-multiple"]'});
$('[data-role="ibo-navigation-menu--notifications-show-all-multiple"]').on('click', function(oEvent){
var oEventTarget = $(oEvent.target);
var aEventTargetPos = oEventTarget.position();
oElem.css({
'max-height' : (aEventTargetPos.top + parseInt(oEventTarget.css('marginTop'), 10) - 100) + 'px',
'left': (aEventTargetPos.left + parseInt(oEventTarget.css('marginLeft'), 10) + oEventTarget.width()) + 'px'
});
oElem.popover_menu("openPopup");
});
}
},
_handleClick: function(elem)
{
var me = this;
var idxProvider = $(elem).attr('data-provider-id');
var msgId = $(elem).attr('data-msg-id');
var sUrl = $(elem).attr('data-url');
this._markOneMessageAsRead(idxProvider, msgId);
window.open(sUrl, '_blank');
$('#newsroom_menu').remove();
$('#newsroom_menu_counter_container').remove();
// window.open(sUrl, '_blank');
// $('#newsroom_menu').remove();
// $('#newsroom_menu_counter_container').remove();
$(me.element).popover_menu("closePopup");
this._getAllMessages();
},
_resetUnseenCount: function()

View File

@@ -152,6 +152,8 @@ return array(
'Combodo\\iTop\\Application\\UI\\Component\\GlobalSearch\\GlobalSearch' => $baseDir . '/sources/application/UI/Component/GlobalSearch/GlobalSearch.php',
'Combodo\\iTop\\Application\\UI\\Component\\GlobalSearch\\GlobalSearchFactory' => $baseDir . '/sources/application/UI/Component/GlobalSearch/GlobalSearchFactory.php',
'Combodo\\iTop\\Application\\UI\\Component\\GlobalSearch\\GlobalSearchHelper' => $baseDir . '/sources/application/UI/Component/GlobalSearch/GlobalSearchHelper.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\NewsroomMenu\\NewsroomMenu' => $baseDir . '/sources/application/UI/Component/PopoverMenu/NewsroomMenu/NewsroomMenu.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\NewsroomMenu\\NewsroomMenuFactory' => $baseDir . '/sources/application/UI/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\PopoverMenu' => $baseDir . '/sources/application/UI/Component/PopoverMenu/PopoverMenu.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\PopoverMenuFactory' => $baseDir . '/sources/application/UI/Component/PopoverMenu/PopoverMenuFactory.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\PopoverMenuItem\\JsPopoverMenuItem' => $baseDir . '/sources/application/UI/Component/PopoverMenu/PopoverMenuItem/JsPopoverMenuItem.php',

View File

@@ -13,6 +13,9 @@ class ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {

View File

@@ -382,6 +382,8 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'Combodo\\iTop\\Application\\UI\\Component\\GlobalSearch\\GlobalSearch' => __DIR__ . '/../..' . '/sources/application/UI/Component/GlobalSearch/GlobalSearch.php',
'Combodo\\iTop\\Application\\UI\\Component\\GlobalSearch\\GlobalSearchFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/GlobalSearch/GlobalSearchFactory.php',
'Combodo\\iTop\\Application\\UI\\Component\\GlobalSearch\\GlobalSearchHelper' => __DIR__ . '/../..' . '/sources/application/UI/Component/GlobalSearch/GlobalSearchHelper.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\NewsroomMenu\\NewsroomMenu' => __DIR__ . '/../..' . '/sources/application/UI/Component/PopoverMenu/NewsroomMenu/NewsroomMenu.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\NewsroomMenu\\NewsroomMenuFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/PopoverMenu/NewsroomMenu/NewsroomMenuFactory.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\PopoverMenu' => __DIR__ . '/../..' . '/sources/application/UI/Component/PopoverMenu/PopoverMenu.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\PopoverMenuFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/PopoverMenu/PopoverMenuFactory.php',
'Combodo\\iTop\\Application\\UI\\Component\\PopoverMenu\\PopoverMenuItem\\JsPopoverMenuItem' => __DIR__ . '/../..' . '/sources/application/UI/Component/PopoverMenu/PopoverMenuItem/JsPopoverMenuItem.php',

View File

@@ -0,0 +1,55 @@
<?php
/**
* Copyright (C) 2013-2020 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop 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
*/
namespace Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu;
/**
* Class NewsroomMenu
*
* @author Stephen Abello <stephen.abello@combodo.com>
* @package Combodo\iTop\Application\UI\Component\NewsroomMenu
* @internal
* @since 2.8.0
*/
class NewsroomMenu extends PopoverMenu
{
const HTML_TEMPLATE_REL_PATH = 'components/popover-menu/newsroom-menu/layout';
const JS_TEMPLATE_REL_PATH = 'components/popover-menu/newsroom-menu/layout';
const JS_FILES_REL_PATH = [
'js/components/newsroom-menu.js',
];
/** @var array $aParams */
protected $aParams;
public function SetParams($aParams)
{
$this->aParams = $aParams;
return $this;
}
public function GetParams()
{
return json_encode($this->aParams);
}
}

View File

@@ -0,0 +1,97 @@
<?php
/**
* Copyright (C) 2013-2020 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop 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
*/
namespace Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu;
use appUserPreferences;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu;
use Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu\NewsroomMenu;
use Dict;
use MetaModel;
use UserRights;
/**
* Class NewsroomMenuFactory
*
* @author Stephen Abello <stephen.abello@combodo.com>
* @package Combodo\iTop\Application\UI\Component\NewsroomMenu
* @internal
* @since 2.8.0
*/
class NewsroomMenuFactory
{
/**
* Make a standard NewsroomMenu layout for backoffice pages
*
* @return \Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu\NewsroomMenu
* @throws \CoreException
* @throws \Exception
*/
public static function MakeNewsroomMenuForNavigationMenu()
{
$oMenu = new NewsroomMenu('ibo-navigation-menu--notifications-menu');
$oMenu->SetParams(static::PrepareNewsForNewsroomMenu());
return $oMenu;
}
protected static function PrepareNewsForNewsroomMenu()
{
$aItems = [];
$aProviderParams=[];
$oUser = UserRights::GetUserObject();
/**
* @var iNewsroomProvider[] $aProviders
*/
$aProviders = MetaModel::EnumPlugins('iNewsroomProvider');
foreach($aProviders as $oProvider)
{
$oProvider->SetConfig(MetaModel::GetConfig());
$bProviderEnabled = appUserPreferences::GetPref('newsroom_provider_'.get_class($oProvider),true);
if ($bProviderEnabled && $oProvider->IsApplicable($oUser))
{
$aProviderParams[] = array(
'label' => $oProvider->GetLabel(),
'fetch_url' => $oProvider->GetFetchURL(),
'view_all_url' => $oProvider->GetViewAllURL(),
'mark_all_as_read_url' => $oProvider->GetMarkAllAsReadURL(),
'placeholders' => $oProvider->GetPlaceholders(),
'ttl' => $oProvider->GetTTL(),
);
}
}
$sImageUrl= 'fas fa-comment-dots';
$sPlaceholderImageUrl= 'far fa-envelope';
$aParams = array(
'image_icon' => $sImageUrl,
'placeholder_image_icon' => $sPlaceholderImageUrl,
'cache_uuid' => 'itop-newsroom-'.UserRights::GetUserId().'-'.md5(APPROOT),
'providers' => $aProviderParams,
'display_limit' => (int)appUserPreferences::GetPref('newsroom_display_size', 7),
'labels' => array(
'no_message' => Dict::S('UI:Newsroom:NoNewMessage'),
'mark_all_as_read' => Dict::S('UI:Newsroom:MarkAllAsRead'),
'view_all' => Dict::S('UI:Newsroom:ViewAllMessages'),
),
);
return $aParams;
}
}

View File

@@ -21,8 +21,10 @@ namespace Combodo\iTop\Application\UI\Component\PopoverMenu;
use appUserPreferences;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenuItem\PopoverMenuItemFactory;
use Dict;
use iNewsroomProvider;
use JSPopupMenuItem;
use MetaModel;
use URLPopupMenuItem;
@@ -68,7 +70,7 @@ class PopoverMenuFactory
return $oMenu;
}
/**
* Return the allowed portals items for the current user
*

View File

@@ -24,6 +24,7 @@ use ApplicationContext;
use ApplicationMenu;
use appUserPreferences;
use Combodo\iTop\Application\Branding;
use Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu\NewsroomMenu;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu;
use Combodo\iTop\Application\UI\UIBlock;
use Dict;
@@ -63,6 +64,8 @@ class NavigationMenu extends UIBlock
protected $aUserData;
/** @var \Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu $oUserMenu */
private $oUserMenu;
/** @var \Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu\NewsroomMenu $oNewsroomMenu */
private $oNewsroomMenu;
/** @var bool $bIsExpanded */
protected $bIsExpanded;
@@ -72,14 +75,14 @@ class NavigationMenu extends UIBlock
* @param string|null $sId
* @param \ApplicationContext $oAppContext
* @param \Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu $oUserMenu
* @param \Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu\NewsroomMenu|null $oNewsroomMenu
*
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MySQLException
* @throws \Exception
*/
public function __construct($sId, ApplicationContext $oAppContext, PopoverMenu $oUserMenu)
public function __construct($sId, ApplicationContext $oAppContext, PopoverMenu $oUserMenu, NewsroomMenu $oNewsroomMenu = null)
{
parent::__construct($sId);
@@ -89,6 +92,7 @@ class NavigationMenu extends UIBlock
$this->sAppIconLink = MetaModel::GetConfig()->Get('app_icon_url');
$this->aMenuGroups = ApplicationMenu::GetMenuGroups($oAppContext->GetAsHash());
$this->oUserMenu = $oUserMenu;
$this->oNewsroomMenu = $oNewsroomMenu;
$this->ComputeExpandedState();
$this->ComputeUserData();
@@ -149,6 +153,13 @@ class NavigationMenu extends UIBlock
{
return $this->oUserMenu;
}
/**
* @return \Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu\NewsroomMenu
*/
public function GetNewsroomMenu()
{
return $this->oNewsroomMenu;
}
/**
* Return true if the menu is expanded

View File

@@ -21,7 +21,9 @@ namespace Combodo\iTop\Application\UI\Layout\NavigationMenu;
use ApplicationContext;
use Combodo\iTop\Application\UI\Component\PopoverMenu\NewsroomMenu\NewsroomMenuFactory;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenuFactory;
use MetaModel;
/**
* Class NavigationMenuFactory
@@ -44,10 +46,18 @@ class NavigationMenuFactory
*/
public static function MakeStandard()
{
$oNewsroomMenu = null;
if (MetaModel::GetConfig()->Get('newsroom_enabled'))
{
$oNewsroomMenu = NewsroomMenuFactory::MakeNewsroomMenuForNavigationMenu();
}
return new NavigationMenu(
NavigationMenu::BLOCK_CODE,
new ApplicationContext(),
PopoverMenuFactory::MakeUserMenuForNavigationMenu()
PopoverMenuFactory::MakeUserMenuForNavigationMenu(),
$oNewsroomMenu
);
}
}

View File

@@ -0,0 +1,4 @@
<div data-role="ibo-navigation-menu--notifications-menu--container">
<div {% if oNewsroomMenu.Id is defined %}id="{{ oNewsroomMenu.Id }}"{% endif %} class="ibo-popover-menu" data-role="ibo-popover-menu">
</div>
</div>

View File

@@ -0,0 +1,6 @@
// TODO: We need to find a clean way to launch this script only once the JS scripts are loaded
document.addEventListener("DOMContentLoaded", function(){
setTimeout(function(){
$('#{{ oNewsroomMenu.Id }}').newsroom_menu({{ oNewsroomMenu.Params|raw }});
}, 500);
});

View File

@@ -20,10 +20,12 @@
<div class="ibo-navigation-menu--bottom-part">
{% if oNavigationMenu.IsNewsroomEnabled == true %}
<div class="ibo-navigation-menu--notifications">
<div class="ibo-navigation-menu--notifications-toggler">
<a class="ibo-navigation-menu--notifications-toggler" data-role="ibo-navigation-menu--notifications-toggler">
<i class="fas fa-bell"></i>
</a>
<div class="ibo-navigation-menu--notifications-menu">
{{ render_block(oNavigationMenu.NewsroomMenu) }}
</div>
<div class="ibo-navigation-menu--notifications-menu"></div>
</div>
{% endif %}
<div class="ibo-navigation-menu--user-info">
@@ -42,21 +44,23 @@
<div class="ibo-navigation-menu--user-welcome-message">
<a data-role="ibo-navigation-menu--user-menu--toggler" href="#">
<div class="ibo-navigation-menu--user-welcome-message--text">
{{ oNavigationMenu.UserData.sWelcomeMessage }}
<span class="ibo-navigation-menu--user-welcome-message--toggler" data-role="ibo-navigation-menu--user-menu--toggler">
<i class="fas fa-caret-down"></i>
</span>
<a class="ibo-navigation-menu--user-welcome-message--toggler" data-role="ibo-navigation-menu--user-menu--toggler" href="#">
{{ oNavigationMenu.UserData.sWelcomeMessage }}
<span class="ibo-navigation-menu--user-welcome-message--toggler" data-role="ibo-navigation-menu--user-menu--toggler">
<i class="fas fa-caret-down"></i>
</span>
</a>
</div>
</a>
</div>
{% if oNavigationMenu.IsNewsroomEnabled == true %}
<div class="ibo-navigation-menu--user-notifications">
<div class="ibo-navigation-menu--user-notifications--text">
<a class="ibo-navigation-menu--user-notifications--text" data-role="ibo-navigation-menu--notifications-toggler" href="#">
{{ '0 notification'|dict_s }}
<span class="ibo-navigation-menu--user-notifications--toggler">
<i class="fas fa-bell"></i>
</span>
</div>
</a>
<div class="ibo-navigation-menu--user-notifications-menu"></div>
</div>
{% endif %}