mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
iTop Newsroom implementation - painfully merged manually...
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
require_once(APPROOT.'application/newsroomprovider.class.inc.php');
|
||||
|
||||
/**
|
||||
* Management of application plugins
|
||||
*
|
||||
|
||||
@@ -105,6 +105,8 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
$this->add_linked_script('../js/jquery.magnific-popup.min.js');
|
||||
$this->add_linked_script('../js/breadcrumb.js');
|
||||
$this->add_linked_script('../js/moment-with-locales.min.js');
|
||||
$this->add_linked_script('../js/showdown.min.js');
|
||||
$this->add_linked_script('../js/newsroom_menu.js');
|
||||
|
||||
$this->add_dict_entry('UI:FillAllMandatoryFields');
|
||||
|
||||
@@ -257,6 +259,10 @@ EOF;
|
||||
}
|
||||
$this->add_script(
|
||||
<<< EOF
|
||||
function GetUserLanguage()
|
||||
{
|
||||
return $sJSLangShort;
|
||||
}
|
||||
function PrepareWidgets()
|
||||
{
|
||||
// note: each action implemented here must be idempotent,
|
||||
@@ -794,6 +800,69 @@ EOF
|
||||
ApplicationMenu::DisplayMenu($this, $oAppContext->GetAsHash());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the "newsroom" menu at the top-right of the screen
|
||||
*/
|
||||
protected function InitNewsroom()
|
||||
{
|
||||
$sNewsroomInitialImage = '';
|
||||
if (MetaModel::GetConfig()->Get('newsroom_enabled') !== false)
|
||||
{
|
||||
$oUser = UserRights::GetUserObject();
|
||||
/**
|
||||
* @var iNewsroomProvider[] $aProviders
|
||||
*/
|
||||
$aProviders = MetaModel::EnumPlugins('iNewsroomProvider');
|
||||
$aProviderParams = array();
|
||||
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(),
|
||||
'ttl' => $oProvider->GetTTL(),
|
||||
);
|
||||
}
|
||||
}
|
||||
if (count($aProviderParams) > 0)
|
||||
{
|
||||
$sImageUrl= '../images/newsroom_menu.png';
|
||||
$sPlaceholderImageUrl= '../images/news-32x32.png';
|
||||
$aParams = array(
|
||||
'image_url' => $sImageUrl,
|
||||
'placeholder_image_url' => $sPlaceholderImageUrl,
|
||||
'cache_uuid' => 'itop-newsroom-'.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'),
|
||||
),
|
||||
);
|
||||
$sParams = json_encode($aParams);
|
||||
$this->add_ready_script(
|
||||
<<<EOF
|
||||
$('#top-left-newsroom-cell').newsroom_menu($sParams);
|
||||
EOF
|
||||
);
|
||||
$sNewsroomInitialImage = '<img style="opacity:0.4" src="../images/newsroom_menu.png">';
|
||||
}
|
||||
else
|
||||
{
|
||||
// No newsroom menu at all
|
||||
}
|
||||
}
|
||||
// else no newsroom menu
|
||||
return $sNewsroomInitialImage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs (via some echo) the complete HTML page by assembling all its elements
|
||||
*/
|
||||
@@ -891,6 +960,8 @@ EOF
|
||||
);
|
||||
}
|
||||
|
||||
$sNewsRoomInitialImage = $this->InitNewsroom();
|
||||
|
||||
$this->outputCollapsibleSectionInit();
|
||||
|
||||
if ($this->GetOutputFormat() == 'html')
|
||||
@@ -1273,6 +1344,7 @@ EOF;
|
||||
$sHtml .= ' <table id="top-left-buttons-area"><tr>';
|
||||
$sHtml .= ' <td id="top-left-global-search-cell"><div id="global-search-area"><input id="global-search-input" type="text" name="text" placeholder="'.$sDefaultPlaceHolder.'" value="'.$sText.'"></input><div '.$sOnClick.' id="global-search-image"><input type="hidden" name="operation" value="full_text"/></div></div></td>';
|
||||
$sHtml .= ' <td id="top-left-help-cell"><a id="help-link" href="'.$sOnlineHelpUrl.'" target="_blank"><img title="'.Dict::S('UI:Help').'" src="../images/help.png?t='.utils::GetCacheBusterTimestamp().'"/></td>';
|
||||
$sHtml .= ' <td id="top-left-newsroom-cell">'.$sNewsRoomInitialImage.'</td>';
|
||||
$sHtml .= ' <td id="top-left-logoff-cell">'.self::FilterXSS($sLogOffMenu).'</td>';
|
||||
$sHtml .= ' </tr></table></form></div>';
|
||||
$sHtml .= ' </td>';
|
||||
|
||||
143
application/newsroomprovider.class.inc.php
Normal file
143
application/newsroomprovider.class.inc.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2015 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
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* A provider for messages to be displayed in the iTop Newsroom
|
||||
*/
|
||||
interface iNewsroomProvider
|
||||
{
|
||||
/**
|
||||
* Inject the current configuration in the provider
|
||||
* @param Config $oConfig
|
||||
* @return void
|
||||
*/
|
||||
public function SetConfig(Config $oConfig);
|
||||
|
||||
/**
|
||||
* Tells if this provider is enabled for the given user
|
||||
* @param User $oUser The user for who to check if the provider is applicable.
|
||||
* return bool
|
||||
*/
|
||||
public function IsApplicable(User $oUser = null);
|
||||
|
||||
/**
|
||||
* The human readable (localized) label for this provider
|
||||
* @return string
|
||||
*/
|
||||
public function GetLabel();
|
||||
|
||||
/**
|
||||
* The URL to query (from the browser, using jsonp) to fetch all unread messages
|
||||
* @return string
|
||||
*/
|
||||
public function GetFetchURL();
|
||||
|
||||
/**
|
||||
* The URL to navigate to in order to display all messages
|
||||
* @return string
|
||||
*/
|
||||
public function GetViewAllURL();
|
||||
|
||||
/**
|
||||
* The URL to query(from the browser, using jsonp) to mark all unread messages as read
|
||||
* @return string
|
||||
*/
|
||||
public function GetMarkAllAsReadURL();
|
||||
|
||||
/**
|
||||
* Return the URL to configure the preferences for this provider or null is there is nothing to configure
|
||||
* @return string|null
|
||||
*/
|
||||
public function GetPreferencesUrl();
|
||||
|
||||
/**
|
||||
* The duration between to refreshes of the cache (in seconds)
|
||||
* @return int
|
||||
*/
|
||||
public function GetTTL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic implementation of a Newsroom provider, to be overloaded by your own provider implementation
|
||||
*
|
||||
*/
|
||||
abstract class NewsroomProviderBase implements iNewsroomProvider
|
||||
{
|
||||
/**
|
||||
* The current configuration parameters
|
||||
* @var Config
|
||||
*/
|
||||
protected $oConfig;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->oConfig = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see iNewsroomProvider::SetConfig()
|
||||
*/
|
||||
public function SetConfig(Config $oConfig)
|
||||
{
|
||||
$this->oConfig = $oConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see iNewsroomProvider::GetPreferencesUrl()
|
||||
*/
|
||||
public function GetPreferencesUrl()
|
||||
{
|
||||
return null; // No preferences
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see iNewsroomProvider::GetLabel()
|
||||
*/
|
||||
public abstract function GetLabel();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see iNewsroomProvider::GetFetchURL()
|
||||
*/
|
||||
public abstract function GetFetchURL();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see iNewsroomProvider::GetMarkAllURL()
|
||||
*/
|
||||
public abstract function GetMarkAllAsReadURL();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see iNewsroomProvider::GetViewAllURL()
|
||||
*/
|
||||
public abstract function GetViewAllURL();
|
||||
|
||||
public function IsApplicable(User $oUser = null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetTTL()
|
||||
{
|
||||
return 10*60; // Refresh every 10 minutes
|
||||
}
|
||||
}
|
||||
@@ -1142,6 +1142,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'newsroom_enabled' => array(
|
||||
'type' => 'bool',
|
||||
'description' => 'Whether or not the whole newsroom is enabled',
|
||||
'default' => true,
|
||||
'value' => true,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
);
|
||||
|
||||
public function IsProperty($sPropCode)
|
||||
|
||||
@@ -2668,7 +2668,7 @@ abstract class MetaModel
|
||||
|
||||
// Build the list of available extensions
|
||||
//
|
||||
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface');
|
||||
$aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider');
|
||||
foreach($aInterfaces as $sInterface)
|
||||
{
|
||||
self::$m_aExtensionClasses[$sInterface] = array();
|
||||
|
||||
@@ -552,6 +552,9 @@ div.actions_menu > ul > li {
|
||||
padding: 0;
|
||||
height: 25px;
|
||||
}
|
||||
.itop_popup > ul > li > ul, #logOffBtn > ul > li > ul {
|
||||
box-shadow: 3px 3px 5px 0px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.itop_popup li a, #logOffBtn li a {
|
||||
display: block;
|
||||
padding: 5px 12px;
|
||||
@@ -2961,56 +2964,137 @@ table.listResults .originColor {
|
||||
padding-top: 0.3em;
|
||||
border: none;
|
||||
}
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 41px;
|
||||
height: 23px;
|
||||
vertical-align: baseline;
|
||||
#newsroom_menu li span {
|
||||
display: block;
|
||||
padding: 5px 12px;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
#newsroom_menu li li p {
|
||||
text-align: left;
|
||||
margin: 2px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: 0.4s;
|
||||
transition: 0.4s;
|
||||
background-color: transparent;
|
||||
}
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 17px;
|
||||
width: 17px;
|
||||
#newsroom_menu > ul > li > ul {
|
||||
margin-top: 8px;
|
||||
}
|
||||
#newsroom_menu > ul > li > ul > li {
|
||||
display: block;
|
||||
border-bottom: 1px #ddd solid;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
#newsroom_menu > ul > li > ul > li:hover, #newsroom_menu > ul > li > ul > li:hover h1, #newsroom_menu > ul > li > ul > li:hover h2, #newsroom_menu > ul > li > ul > li:hover h3 {
|
||||
background: #ea7d1e;
|
||||
color: #fff;
|
||||
}
|
||||
#newsroom_menu li li:last-of-type {
|
||||
border-bottom: 0;
|
||||
}
|
||||
#newsroom_menu li {
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
}
|
||||
#newsroom_menu li ul {
|
||||
width: 300px;
|
||||
}
|
||||
#top-left-newsroom-cell {
|
||||
padding-right: 11px !important;
|
||||
}
|
||||
#newsroom_menu_icon {
|
||||
position: relative;
|
||||
top: 8px;
|
||||
}
|
||||
#newsroom_menu_counter_container {
|
||||
position: relative;
|
||||
top: -26px;
|
||||
left: 4px;
|
||||
bottom: 3px;
|
||||
background-color: white;
|
||||
-webkit-transition: 0.4s;
|
||||
transition: 0.4s;
|
||||
}
|
||||
input:checked + .slider {
|
||||
background-color: #ea7d1e;
|
||||
#newsroom_menu_counter {
|
||||
display: inline-block;
|
||||
padding: 2px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
width: 12px;
|
||||
box-shadow: 1px 1px 2px 0px #777;
|
||||
font-size: 8pt;
|
||||
background-color: #1c94c4;
|
||||
color: #fff;
|
||||
}
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px #ea7d1e;
|
||||
.newsroom_extra_messages_counter {
|
||||
display: inline-block !important;
|
||||
padding: 2px !important;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
font-size: 8pt;
|
||||
min-width: 12px;
|
||||
background-color: #808080;
|
||||
color: #fff;
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(16px);
|
||||
-ms-transform: translateX(16px);
|
||||
transform: translateX(16px);
|
||||
.newsroom_menu_item > div > img {
|
||||
float: left;
|
||||
width: 32px;
|
||||
max-height: 32px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 34px;
|
||||
#newsroom_menu_dismiss_all, #newsroom_menu_show_all {
|
||||
text-align: center !important;
|
||||
}
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
#newsroom_show_all_submenu {
|
||||
text-align: center;
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
#newsroom_show_all_submenu > ul {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
#newsroom_show_all_submenu > ul > li > ul {
|
||||
margin-top: 8px;
|
||||
}
|
||||
#newsroom_show_all_submenu > ul > li > ul > li {
|
||||
display: block;
|
||||
border-bottom: 1px #ddd solid;
|
||||
padding-left: 5px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
#newsroom_show_all_submenu > ul > li > ul > li:hover {
|
||||
background: #ea7d1e;
|
||||
color: #fff;
|
||||
}
|
||||
#newsroom_show_all_submenu li ul {
|
||||
width: 200px;
|
||||
color: #000;
|
||||
}
|
||||
.no-padding {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.newsroom_menu_item_date {
|
||||
padding: 0 !important;
|
||||
margin-bottom: -10px;
|
||||
font-size: 8pt;
|
||||
text-align: right;
|
||||
margin-top: -2px;
|
||||
margin-right: 5px;
|
||||
color: #fff;
|
||||
}
|
||||
#newsroom_display_size {
|
||||
height: 1em;
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
@@ -628,7 +628,9 @@ div.actions_menu > ul > li {
|
||||
padding: 0;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.itop_popup > ul > li > ul, #logOffBtn > ul > li > ul {
|
||||
box-shadow: 3px 3px 5px 0px rgba(0,0,0,0.5);
|
||||
}
|
||||
.itop_popup li a, #logOffBtn li a {
|
||||
display: block;
|
||||
padding: 5px 12px;
|
||||
@@ -3496,4 +3498,139 @@ input:checked + .slider:before {
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Newsroom menu
|
||||
|
||||
#newsroom_menu li span {
|
||||
display: block;
|
||||
padding: 5px 12px;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#newsroom_menu li li p {
|
||||
text-align: left;
|
||||
margin: 2px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
}
|
||||
#newsroom_menu > ul > li > ul {
|
||||
margin-top: 8px;
|
||||
}
|
||||
#newsroom_menu > ul > li > ul > li {
|
||||
display: block;
|
||||
border-bottom: 1px #ddd solid;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
#newsroom_menu > ul > li > ul > li:hover, #newsroom_menu > ul > li > ul > li:hover h1, #newsroom_menu > ul > li > ul > li:hover h2, #newsroom_menu > ul > li > ul > li:hover h3 {
|
||||
background: $popup-menu-highlight-color;
|
||||
color: $popup-menu-text-higlight-color;
|
||||
}
|
||||
#newsroom_menu li li:last-of-type {
|
||||
border-bottom: 0;
|
||||
}
|
||||
#newsroom_menu li {
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
color: $popup-menu-text-color;
|
||||
}
|
||||
#newsroom_menu li ul {
|
||||
width: 300px;
|
||||
}
|
||||
#top-left-newsroom-cell {
|
||||
padding-right: 11px !important;
|
||||
}
|
||||
#newsroom_menu_icon {
|
||||
position:relative;
|
||||
top:8px;
|
||||
}
|
||||
#newsroom_menu_counter_container {
|
||||
position:relative;
|
||||
top:-26px;
|
||||
left:4px;
|
||||
}
|
||||
#newsroom_menu_counter {
|
||||
display:inline-block;
|
||||
padding:2px;
|
||||
border-radius:8px;
|
||||
text-align:center;
|
||||
width: 12px;
|
||||
box-shadow: 1px 1px 2px 0px $gray;
|
||||
font-size: 8pt;
|
||||
background-color:$complement-color;
|
||||
color: $white;
|
||||
}
|
||||
.newsroom_extra_messages_counter {
|
||||
display:inline-block !important;
|
||||
padding:2px !important;
|
||||
border-radius:8px;
|
||||
text-align:center;
|
||||
font-size: 8pt;
|
||||
min-width: 12px;
|
||||
background-color:$gray-light;
|
||||
color: $white;
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.newsroom_menu_item > div > img {
|
||||
float:left;
|
||||
width:32px;
|
||||
max-height:32px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left:5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
#newsroom_menu_dismiss_all, #newsroom_menu_show_all {
|
||||
text-align: center !important;
|
||||
}
|
||||
#newsroom_show_all_submenu {
|
||||
text-align: center;
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
#newsroom_show_all_submenu > ul {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
#newsroom_show_all_submenu > ul > li > ul {
|
||||
margin-top: 8px;
|
||||
}
|
||||
#newsroom_show_all_submenu > ul > li > ul > li {
|
||||
display: block;
|
||||
border-bottom: 1px #ddd solid;
|
||||
padding-left: 5px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
#newsroom_show_all_submenu > ul > li > ul > li:hover {
|
||||
background: $popup-menu-highlight-color;
|
||||
color: $popup-menu-text-higlight-color;
|
||||
}
|
||||
#newsroom_show_all_submenu li ul {
|
||||
width: 200px;
|
||||
color:#000;
|
||||
}
|
||||
.no-padding {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.newsroom_menu_item_date {
|
||||
padding: 0 !important;
|
||||
margin-bottom: -10px;
|
||||
font-size: 8pt;
|
||||
text-align: right;
|
||||
margin-top: -2px;
|
||||
margin-right: 5px;
|
||||
color: $white;
|
||||
}
|
||||
#newsroom_display_size {
|
||||
height: 1em;
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
@@ -1,46 +1,3 @@
|
||||
#hub_popup_menu li span {
|
||||
display: block;
|
||||
padding: 5px 12px;
|
||||
text-decoration: none;
|
||||
nowidth: 70px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#hub_popup_menu li li p {
|
||||
text-align: left;
|
||||
margin: 2px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
color: #000;
|
||||
}
|
||||
#hub_popup_menu > ul > li > ul {
|
||||
margin-top: 8px;
|
||||
}
|
||||
#hub_popup_menu > ul > li > ul > li {
|
||||
display: block;
|
||||
border-bottom: 1px #ddd solid;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
#hub_popup_menu > ul > li > ul > li:hover {
|
||||
color: #fff;
|
||||
background-color: #E87C1E;
|
||||
}
|
||||
#hub_popup_menu li li:last-of-type {
|
||||
border-bottom: 0;
|
||||
}
|
||||
#hub_popup_menu li {
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
#hub_popup_menu li ul {
|
||||
width: 340px;
|
||||
}
|
||||
#top-left-hub-cell {
|
||||
padding-right: 8px !important;
|
||||
}
|
||||
#hub_launch_container {
|
||||
padding:10px;
|
||||
overflow: visible;
|
||||
@@ -209,7 +166,7 @@
|
||||
#hub_launch_content {
|
||||
width: 100%;
|
||||
}
|
||||
button {
|
||||
#hub_launch_content button {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
box-shadow: 0px 0px 0px 1px transparent inset, 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset;
|
||||
@@ -219,27 +176,27 @@ button {
|
||||
vertical-align: middle;
|
||||
padding: 0;
|
||||
}
|
||||
button.positive {
|
||||
#hub_launch_content button.positive {
|
||||
background-color: rgb(234, 125, 30);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
button:disabled, button[disabled] {
|
||||
#hub_launch_content button:disabled, button[disabled] {
|
||||
background-color: #828487!important;
|
||||
cursor: progress !important;
|
||||
}
|
||||
button > span {
|
||||
#hub_launch_content button > span {
|
||||
display: inline-block;
|
||||
padding: 0.8em;
|
||||
padding-left: 1.3em;
|
||||
padding-right: 1.3em;
|
||||
}
|
||||
button:hover {
|
||||
#hub_launch_content button:hover {
|
||||
background-color: #D0D0D0;
|
||||
}
|
||||
button.positive:hover {
|
||||
#hub_launch_content button.positive:hover {
|
||||
background-color: rgb(221, 113, 27);
|
||||
}
|
||||
button > img {
|
||||
#hub_launch_content button > img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
@@ -249,4 +206,4 @@ button > img {
|
||||
.horiz-spacer {
|
||||
display: inline-block;
|
||||
width: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
<url>https://www.itophub.io</url>
|
||||
<route_landing>/my-instances/landing-from-remote</route_landing>
|
||||
<route_landing_stateless>/stateless-remote-itop/landing-from-remote-stateless</route_landing_stateless>
|
||||
<route_notifications>/api/notifications</route_notifications>
|
||||
<route_fetch_unread_messages>/api/notifications</route_fetch_unread_messages>
|
||||
<route_mark_all_messages_as_read>/api/notifications/mark_all_as_read</route_mark_all_messages_as_read>
|
||||
<route_view_all_messages>/api/notifications/view_all_messages</route_view_all_messages>
|
||||
<setup_url>../pages/exec.php?exec_module=itop-hub-connector&exec_page=launch.php&target=inform_after_setup</setup_url>
|
||||
</parameters>
|
||||
</module_parameters>
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
require_once(APPROOT.'application/newsroomprovider.class.inc.php');
|
||||
|
||||
class HubNewsroomProvider extends NewsroomProviderBase
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see NewsroomProviderBase::GetTTL()
|
||||
*/
|
||||
public function GetTTL()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 15*60; // Update every 15 minutes
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see NewsroomProviderBase::IsApplicable()
|
||||
*/
|
||||
public function IsApplicable(User $oUser = null)
|
||||
{
|
||||
if ($oUser !== null)
|
||||
{
|
||||
return UserRights::IsAdministrator($oUser);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see NewsroomProviderBase::GetLabel()
|
||||
*/
|
||||
public function GetLabel()
|
||||
{
|
||||
return 'iTop Hub'; // No need to translate...
|
||||
}
|
||||
|
||||
public function GetMarkAllAsReadURL()
|
||||
{
|
||||
return $this->MakeURL('route_mark_all_messages_as_read');
|
||||
}
|
||||
|
||||
public function GetFetchURL()
|
||||
{
|
||||
return $this->MakeURL('route_fetch_unread_messages');
|
||||
}
|
||||
|
||||
public function GetViewAllURL()
|
||||
{
|
||||
return $this->MakeURL('route_view_all_messages');
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see NewsroomProviderBase::GetPreferencesUrl()
|
||||
*/
|
||||
public function GetPreferencesUrl()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private function MakeURL($sRouteCode)
|
||||
{
|
||||
$sBaseUrl = $this->oConfig->GetModuleSetting('itop-hub-connector', 'url').MetaModel::GetModuleSetting('itop-hub-connector', $sRouteCode);
|
||||
|
||||
$sParameters = 'uuid[bdd]='.urlencode((string) trim(DBProperty::GetProperty('database_uuid', ''), '{}'));
|
||||
$sParameters .= '&uuid[file]='.urlencode((string) trim(@file_get_contents(APPROOT."data/instance.txt"), "{} \n"));
|
||||
$sParameters .= '&uuid[user]='.urlencode(UserRights::GetUserId());
|
||||
|
||||
return $sBaseUrl.'?'.$sParameters;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,8 @@ SetupWebPage::AddModule(
|
||||
//
|
||||
'datamodel' => array(
|
||||
'menus.php',
|
||||
'model.itop-hub-connector.php'
|
||||
'hubnewsroomprovider.class.inc.php',
|
||||
'model.itop-hub-connector.php'
|
||||
),
|
||||
'webservice' => array(
|
||||
|
||||
|
||||
@@ -1529,3 +1529,17 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Expression:Verb:NOW' => 'jetzt',
|
||||
'Expression:Verb:ISNULL' => ': nicht definiert',
|
||||
));
|
||||
|
||||
//
|
||||
// iTop Newsroom menu
|
||||
//
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'UI:Newsroom:NoNewMessage' => 'Keine neue Nachricht',
|
||||
'UI:Newsroom:MarkAllAsRead' => 'Alle Nachrichten als gelesen markieren',
|
||||
'UI:Newsroom:ViewAllMessages' => 'Alle Nachrichten anzeigen',
|
||||
'UI:Newsroom:Preferences' => 'Newsroom-Einstellungen',
|
||||
'UI:Newsroom:ConfigurationLink' => 'Konfiguration',
|
||||
'UI:Newsroom:ResetCache' => 'Cache zurücksetzen',
|
||||
'UI:Newsroom:DisplayMessagesFor_Provider' => 'Nachrichten von %1$s anzeigen',
|
||||
'UI:Newsroom:DisplayAtMost_X_Messages' => 'Zeigen Sie höchstens %1$s Beiträge im Menü (%2$s) an.',
|
||||
));
|
||||
|
||||
@@ -1550,3 +1550,17 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Expression:Verb:NOW' => 'now',
|
||||
'Expression:Verb:ISNULL' => ': undefined',
|
||||
));
|
||||
|
||||
//
|
||||
// iTop Newsroom menu
|
||||
//
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:Newsroom:NoNewMessage' => 'No new message',
|
||||
'UI:Newsroom:MarkAllAsRead' => 'Mark all as messages read',
|
||||
'UI:Newsroom:ViewAllMessages' => 'View all messages',
|
||||
'UI:Newsroom:Preferences' => 'Newsroom preferences',
|
||||
'UI:Newsroom:ConfigurationLink' => 'Configuration',
|
||||
'UI:Newsroom:ResetCache' => 'Reset cache',
|
||||
'UI:Newsroom:DisplayMessagesFor_Provider' => 'Display messages from %1$s',
|
||||
'UI:Newsroom:DisplayAtMost_X_Messages' => 'Display up to %1$s messages in the %2$s menu.',
|
||||
));
|
||||
|
||||
@@ -1530,3 +1530,17 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Expression:Verb:NOW' => 'maintenant',
|
||||
'Expression:Verb:ISNULL' => ' : non défini',
|
||||
));
|
||||
|
||||
//
|
||||
// iTop Newsroom menu
|
||||
//
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'UI:Newsroom:NoNewMessage' => 'Aucun nouveau message',
|
||||
'UI:Newsroom:MarkAllAsRead' => 'Marquer tous les messages comme lus',
|
||||
'UI:Newsroom:ViewAllMessages' => 'Voir tous les messages',
|
||||
'UI:Newsroom:Preferences' => 'Préférences du centre d\'information',
|
||||
'UI:Newsroom:ConfigurationLink' => 'Configuration',
|
||||
'UI:Newsroom:ResetCache' => 'Ràz du cache',
|
||||
'UI:Newsroom:DisplayMessagesFor_Provider' => 'Afficher les messages de %1$s',
|
||||
'UI:Newsroom:DisplayAtMost_X_Messages' => 'Afficher au plus %1$s messages dans le menu %2$s.',
|
||||
));
|
||||
|
||||
@@ -1549,3 +1549,17 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
|
||||
'Expression:Verb:NOW' => 'nu',
|
||||
'Expression:Verb:ISNULL' => ': ongedefinieerd (NULL)',
|
||||
));
|
||||
|
||||
//
|
||||
// iTop Newsroom menu
|
||||
//
|
||||
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
|
||||
'UI:Newsroom:NoNewMessage' => 'Geen nieuw bericht',
|
||||
'UI:Newsroom:MarkAllAsRead' => 'Markeer alle berichten als gelezen',
|
||||
'UI:Newsroom:ViewAllMessages' => 'Bekijk alle berichten',
|
||||
'UI:Newsroom:Preferences' => 'Newsroom preferences',
|
||||
'UI:Newsroom:ConfigurationLink' => 'Configuratie',
|
||||
'UI:Newsroom:ResetCache' => 'Reset cache',
|
||||
'UI:Newsroom:DisplayMessagesFor_Provider' => 'Bekijk berichten van %1$s',
|
||||
'UI:Newsroom:DisplayAtMost_X_Messages' => 'Toon maximaal %1$s berichten in het %2$s menu.',
|
||||
));
|
||||
|
||||
@@ -1521,3 +1521,17 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Expression:Verb:NOW' => 'now',
|
||||
'Expression:Verb:ISNULL' => ': undefined~~',
|
||||
));
|
||||
|
||||
//
|
||||
// iTop Newsroom menu
|
||||
//
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'UI:Newsroom:NoNewMessage' => 'Нет новых сообщений',
|
||||
'UI:Newsroom:MarkAllAsRead' => 'Отметить все как прочитанные сообщения',
|
||||
'UI:Newsroom:ViewAllMessages' => 'Посмотреть все сообщения',
|
||||
'UI:Newsroom:Preferences' => 'Настройки новостей',
|
||||
'UI:Newsroom:ConfigurationLink' => 'конфигурация',
|
||||
'UI:Newsroom:ResetCache' => 'Сбросить кеш',
|
||||
'UI:Newsroom:DisplayMessagesFor_Provider' => 'Показать сообщения от %1$s',
|
||||
'UI:Newsroom:DisplayAtMost_X_Messages' => 'Отобразите не более %1$s сообщений в меню %2$s.',
|
||||
));
|
||||
|
||||
BIN
images/newsroom_menu.png
Normal file
BIN
images/newsroom_menu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 302 B |
350
js/newsroom_menu.js
Normal file
350
js/newsroom_menu.js
Normal file
@@ -0,0 +1,350 @@
|
||||
$(function()
|
||||
{
|
||||
// the widget definition, where "itop" is the namespace,
|
||||
// "newsroom_menu" the widget name
|
||||
$.widget( "itop.newsroom_menu",
|
||||
{
|
||||
// default options
|
||||
options:
|
||||
{
|
||||
image_url: '',
|
||||
cache_uuid: '',
|
||||
display_limit: 7,
|
||||
placeholder_image_url: '../images/transparent_32_32.png',
|
||||
providers: [],
|
||||
labels: {
|
||||
'no_message': 'No new message',
|
||||
'mark_all_as_read': 'Mark all as read',
|
||||
'view_all': 'View all messages'
|
||||
}
|
||||
},
|
||||
|
||||
// the constructor
|
||||
_create: function()
|
||||
{
|
||||
var me = this;
|
||||
this.aMessageByProvider = [];
|
||||
|
||||
this.element
|
||||
.addClass('itop-newsroom_menu');
|
||||
|
||||
this._load();
|
||||
},
|
||||
|
||||
// called when created, and later when changing options
|
||||
_refresh: function()
|
||||
{
|
||||
},
|
||||
// events bound via _bind are removed automatically
|
||||
// revert other modifications here
|
||||
_destroy: function()
|
||||
{
|
||||
this.element
|
||||
.removeClass('itop-newsroom_menu');
|
||||
},
|
||||
// _setOptions is called with a hash of all options that are changing
|
||||
_setOptions: function()
|
||||
{
|
||||
this._superApply(arguments);
|
||||
},
|
||||
// _setOption is called for each individual option that is changing
|
||||
_setOption: function(key, value)
|
||||
{
|
||||
if (this.options[key] != value)
|
||||
{
|
||||
// If any option changes, clear the cache BEFORE applying the new settings
|
||||
this._clearCache();
|
||||
}
|
||||
|
||||
this._superApply(arguments);
|
||||
},
|
||||
_load: function()
|
||||
{
|
||||
var me = this;
|
||||
setTimeout(function() { me._getAllMessages(); }, 1000);
|
||||
},
|
||||
_getAllMessages: function()
|
||||
{
|
||||
this.aMessageByProvider = [];
|
||||
this._getMessages(0); // start at the first provider (index == 0)
|
||||
},
|
||||
_getMessages: function(idxProvider)
|
||||
{
|
||||
var sKey = this._makeCacheKey(idxProvider);
|
||||
var oJSONData = this._getCachedData(idxProvider);
|
||||
if (oJSONData != null)
|
||||
{
|
||||
this._onMessagesFetched(idxProvider, oJSONData);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._fetchMessages(idxProvider); // Asynchronous
|
||||
}
|
||||
},
|
||||
_fetchMessages: function(idxProvider)
|
||||
{
|
||||
var sUrl = this.options.providers[idxProvider].fetch_url;
|
||||
var me = this;
|
||||
var idx = idxProvider;
|
||||
|
||||
$.ajax({ type: "GET",
|
||||
url: sUrl,
|
||||
async: true,
|
||||
dataType : 'jsonp',
|
||||
crossDomain: true,
|
||||
jsonp: "callback"
|
||||
})
|
||||
.done(function(oJSONData) {
|
||||
me._cacheData(idx, oJSONData);
|
||||
me._onMessagesFetched(idx, oJSONData);
|
||||
}).error(function() {
|
||||
console.warn('Newsroom: failed to fetch data from the web for provider '+idx+' url: '+me.options.providers[idxProvider].fetch_url);
|
||||
me._cacheData(idx, []);
|
||||
me._onMessagesFetched(idx, []);
|
||||
});
|
||||
},
|
||||
_onMessagesFetched: function(idxProvider, oJSONData)
|
||||
{
|
||||
this.aMessageByProvider[idxProvider] = oJSONData;
|
||||
if ((1+idxProvider) < this.options.providers.length)
|
||||
{
|
||||
this._getMessages(idxProvider+1); // Process the next provider
|
||||
}
|
||||
else
|
||||
{
|
||||
this._onAllMessagesFetched(); // All messages retrieved
|
||||
}
|
||||
},
|
||||
_onAllMessagesFetched: function()
|
||||
{
|
||||
var aAllMessages = [];
|
||||
for(k in this.aMessageByProvider)
|
||||
{
|
||||
for(j in this.aMessageByProvider[k])
|
||||
{
|
||||
var oMsg = this.aMessageByProvider[k][j];
|
||||
oMsg.id = ''+oMsg.id; // Stringify
|
||||
oMsg.provider = k;
|
||||
aAllMessages.push(oMsg);
|
||||
}
|
||||
}
|
||||
|
||||
aAllMessages.sort(function(msg1, msg2) {
|
||||
if (msg1.priority < msg2.priority) return -1;
|
||||
if (msg1.priority > msg2.priority) return 1;
|
||||
var oDate1 = new Date(msg1.start_date);
|
||||
var oDate2 = new Date(msg2.start_date);
|
||||
if (oDate1 > oDate2) return -1;
|
||||
if (oDate1 < oDate2) return 1;
|
||||
return 1;
|
||||
});
|
||||
|
||||
this._buildMenu(aAllMessages);
|
||||
},
|
||||
_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><img id="newsroom_menu_icon" src="'+this.options.image_url+'"><ul>';
|
||||
sHtml += '<li class="newsroom_menu_item" id="newsroom_menu_dismiss_all"><i class="fa fa-fw fa-check"></i>'+this.options.labels.mark_all_as_read+'</li>';
|
||||
moment.locale(GetUserLanguage());
|
||||
var aUnreadMessagesByProvider = [];
|
||||
for(var k in this.options.providers)
|
||||
{
|
||||
aUnreadMessagesByProvider[k] = 0;
|
||||
}
|
||||
for(var k in aAllMessages)
|
||||
{
|
||||
var oMessage = aAllMessages[k];
|
||||
aUnreadMessagesByProvider[oMessage.provider]++;
|
||||
if (iCount < this.options.display_limit)
|
||||
{
|
||||
if (oMessage.image !== undefined)
|
||||
{
|
||||
sImageUrl = oMessage.image;
|
||||
}
|
||||
else
|
||||
{
|
||||
sImageUrl = this.options.placeholder_image_url;
|
||||
}
|
||||
var div = document.createElement("div");
|
||||
div.textContent = oMessage.text;
|
||||
var sDescription = div.innerHTML; // Escape HTML entities for XSS prevention
|
||||
var converter = new showdown.Converter();
|
||||
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><img src="'+sImageUrl+'"><p>'+sRichDescription+'</p><div style="clear:both"></div></div></li>';
|
||||
}
|
||||
iCount++;
|
||||
}
|
||||
if (this.options.providers.length == 1)
|
||||
{
|
||||
sHtml += '<li class="newsroom_menu_item" id="newsroom_menu_show_all">'+this.options.labels.view_all+'</li>';
|
||||
}
|
||||
else
|
||||
{
|
||||
sHtml += '<li class="no-padding"><span id="newsroom_show_all_submenu" class="itop_popup toolkit_menu"><ul><li>'+this.options.labels.view_all+' ▾<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>';
|
||||
}
|
||||
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);
|
||||
var me = this;
|
||||
$('#newsroom_menu > ul').popupmenu();
|
||||
$('.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');});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#top-left-newsroom-cell > img').css({opacity: 0.4}).attr('title', this.options.labels.no_message);
|
||||
}
|
||||
|
||||
},
|
||||
_handleClick: function(elem)
|
||||
{
|
||||
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();
|
||||
this._getAllMessages();
|
||||
},
|
||||
_resetUnseenCount: function()
|
||||
{
|
||||
var display = $('#newsroom_menu_counter').css('display');
|
||||
$('#newsroom_menu_counter').fadeOut(500, function() {
|
||||
$(this).css('visibility', 'hidden');
|
||||
$(this).css('display', display);
|
||||
});
|
||||
},
|
||||
clearCache: function(idx)
|
||||
{
|
||||
if (idx == undefined)
|
||||
{
|
||||
for(var k in this.options.providers)
|
||||
{
|
||||
var sKey = this._makeCacheKey(k);
|
||||
localStorage.removeItem(sKey);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var sKey = this._makeCacheKey(idx);
|
||||
localStorage.removeItem(sKey);
|
||||
}
|
||||
},
|
||||
_makeCacheKey: function(idxProvider)
|
||||
{
|
||||
return this.options.cache_uuid+'_'+idxProvider;
|
||||
},
|
||||
_cacheData: function(idxProvider, oJSONData)
|
||||
{
|
||||
var sKey = this._makeCacheKey(idxProvider);
|
||||
var bSuccess = true;
|
||||
var oNow = new Date();
|
||||
var oExpirationDate = new Date(oNow.getTime() + this.options.providers[idxProvider].ttl * 1000);
|
||||
|
||||
var oData = {value: JSON.stringify(oJSONData), expiration_date: oExpirationDate.getTime() };
|
||||
try
|
||||
{
|
||||
localStorage.setItem(sKey, JSON.stringify(oData))
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.warn('Newsroom: Failed to store newsroom messages into local storage !! reason: '+e);
|
||||
bSuccess = false;
|
||||
}
|
||||
return bSuccess;
|
||||
},
|
||||
_getCachedData: function(idxProvider)
|
||||
{
|
||||
var sKey = this._makeCacheKey(idxProvider);
|
||||
var sData = localStorage.getItem(sKey);
|
||||
if (sData == null) return null; // No entry in the local storage cache
|
||||
try
|
||||
{
|
||||
var oData = JSON.parse(sData);
|
||||
var oExpiration = new Date(oData.expiration_date);
|
||||
var oNow = new Date();
|
||||
if (oExpiration < oNow)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return JSON.parse(oData.value);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.warn('Newsroom: Failed to fetch newsroom messages from local storage !! reason: '+e);
|
||||
this.clearCache(idxProvider);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
_markOneMessageAsRead: function(idxProvider, msgId)
|
||||
{
|
||||
// Remove the given message from the cache
|
||||
var aData = this._getCachedData(idxProvider);
|
||||
if (aData !== null)
|
||||
{
|
||||
var aRemainingData = [];
|
||||
for(var k in aData)
|
||||
{
|
||||
var sId = aData[k].id.toString();
|
||||
if(sId !== msgId)
|
||||
{
|
||||
aRemainingData.push(aData[k]);
|
||||
}
|
||||
}
|
||||
this._cacheData(idxProvider, aRemainingData); // Also extends the TTL of the cache
|
||||
}
|
||||
},
|
||||
_markAllMessagesAsRead: function(idxProvider)
|
||||
{
|
||||
this._cacheData(idxProvider, []); //Store an empty list in the cache
|
||||
|
||||
$.ajax({ type: "GET",
|
||||
url: this.options.providers[idxProvider].mark_all_as_read_url,
|
||||
async: true,
|
||||
dataType : 'jsonp',
|
||||
crossDomain: true,
|
||||
jsonp: "callback"
|
||||
})
|
||||
.done(function(oJSONData) {
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
_markAllAsRead: function()
|
||||
{
|
||||
for(var k in this.options.providers)
|
||||
{
|
||||
this._markAllMessagesAsRead(k);
|
||||
}
|
||||
$('#newsroom_menu').html('<img src="'+this.options.image_url+'" style="opacity:0.4" title="'+this.options.labels.no_message+'">');
|
||||
$('#newsroom_menu_counter_container').remove();
|
||||
this._getAllMessages();
|
||||
}
|
||||
});
|
||||
});
|
||||
3
js/showdown.min.js
vendored
Normal file
3
js/showdown.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -296,6 +296,79 @@ EOF
|
||||
);
|
||||
} // if count > 0
|
||||
|
||||
$oP->add('</fieldset>');
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Newsroom
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
$iCountProviders = 0;
|
||||
$oUser = UserRights::GetUserObject();
|
||||
$aProviders = MetaModel::EnumPlugins('iNewsroomProvider');
|
||||
foreach($aProviders as $oProvider)
|
||||
{
|
||||
if ($oProvider->IsApplicable($oUser))
|
||||
{
|
||||
$iCountProviders++;
|
||||
}
|
||||
}
|
||||
|
||||
$bNewsroomEnabled = (MetaModel::GetConfig()->Get('newsroom_enabled') !== false);
|
||||
if ($bNewsroomEnabled && ($iCountProviders > 0))
|
||||
{
|
||||
$oP->add('<fieldset><legend>'.Dict::S('UI:Newsroom:Preferences').'</legend>');
|
||||
|
||||
$oP->add('<form method="post">');
|
||||
$iNewsroomDisplaySize = (int)appUserPreferences::GetPref('newsroom_display_size', 7);
|
||||
|
||||
if ($iNewsroomDisplaySize < 1) $iNewsroomDisplaySize = 1;
|
||||
if ($iNewsroomDisplaySize > 20) $iNewsroomDisplaySize = 20;
|
||||
$sInput = '<input min="1" max="20" id="newsroom_display_size" type="number" size="2" name="newsroom_display_size" value="'.$iNewsroomDisplaySize.'">';
|
||||
$sIcon = '<img src="../images/newsroom_menu.png" style="vertical-align:middle">';
|
||||
$oP->p(Dict::Format('UI:Newsroom:DisplayAtMost_X_Messages', $sInput, $sIcon));
|
||||
|
||||
/**
|
||||
* @var iNewsroomProvider[] $aProviders
|
||||
*/
|
||||
$aProviderParams = array();
|
||||
$iCountProviders = 0;
|
||||
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
foreach($aProviders as $oProvider)
|
||||
{
|
||||
if ($oProvider->IsApplicable($oUser))
|
||||
{
|
||||
$sUrl = $oProvider->GetPreferencesUrl();
|
||||
$sProviderClass = get_class($oProvider);
|
||||
$sPreferencesLink = '';
|
||||
if ($sUrl !== null)
|
||||
{
|
||||
if(substr($sUrl, 0, strlen($sAppRootUrl)) === $sAppRootUrl)
|
||||
{
|
||||
$sTarget = ''; // Internal link, open in the same window
|
||||
}
|
||||
else
|
||||
{
|
||||
$sTarget = ' target="_blank"'; // External link, open in new window
|
||||
}
|
||||
$sPreferencesLink = ' - <a class=".newsroom-configuration-link" href="'.$sUrl.'"'.$sTarget.'>'.Dict::S('UI:Newsroom:ConfigurationLink').'</a>';
|
||||
}
|
||||
$sChecked = appUserPreferences::GetPref('newsroom_provider_'.$sProviderClass, true) ? ' checked="" ' : '';
|
||||
$oP->p('<input type="checkbox" id="newsroom_provider_'.$sProviderClass.'" value="on"'.$sChecked.'name="newsroom_provider_'.$sProviderClass.'"><label for="newsroom_provider_'.$sProviderClass.'"> '.Dict::Format('UI:Newsroom:DisplayMessagesFor_Provider', $oProvider->GetLabel()).'</label> '.$sPreferencesLink);
|
||||
}
|
||||
}
|
||||
|
||||
$oP->p('<button style="float:right" onclick="$(\'.itop-newsroom_menu\').newsroom_menu(\'clearCache\');">'.htmlentities(Dict::S('UI:Newsroom:ResetCache')).'</button>');
|
||||
$oP->add('<input type="hidden" name="operation" value="apply_newsroom_preferences"/>');
|
||||
$oP->add($oAppContext->GetForForm());
|
||||
$oP->add('<p><input type="button" onClick="window.location.href=\''.$sURL.'\'" value="'.Dict::S('UI:Button:Cancel').'"/>');
|
||||
$oP->add(' ');
|
||||
$oP->add('<input type="submit" value="'.Dict::S('UI:Button:Apply').'"/></p>');
|
||||
$oP->add('</form>');
|
||||
$oP->add('</fieldset>');
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Footer
|
||||
@@ -365,6 +438,53 @@ try
|
||||
DisplayPreferences($oPage);
|
||||
break;
|
||||
|
||||
case 'apply_newsroom_preferences':
|
||||
$iCountProviders = 0;
|
||||
$oUser = UserRights::GetUserObject();
|
||||
$aProviders = MetaModel::EnumPlugins('iNewsroomProvider');
|
||||
foreach($aProviders as $oProvider)
|
||||
{
|
||||
if ($oProvider->IsApplicable($oUser))
|
||||
{
|
||||
$iCountProviders++;
|
||||
}
|
||||
}
|
||||
$bNewsroomEnabled = (MetaModel::GetConfig()->Get('newsroom_enabled') !== false);
|
||||
if ($bNewsroomEnabled && ($iCountProviders > 0))
|
||||
{
|
||||
$iNewsroomDisplaySize = (int)utils::ReadParam('newsroom_display_size', 7);
|
||||
if ($iNewsroomDisplaySize < 1) $iNewsroomDisplaySize = 1;
|
||||
if ($iNewsroomDisplaySize > 20) $iNewsroomDisplaySize = 20;
|
||||
$iCurrentDisplaySize = (int)appUserPreferences::GetPref('newsroom_display_size', $iNewsroomDisplaySize);
|
||||
if ($iCurrentDisplaySize != $iNewsroomDisplaySize)
|
||||
{
|
||||
// Save the preference only if it differs from the current (or default) value
|
||||
appUserPreferences::SetPref('newsroom_display_size', $iNewsroomDisplaySize);
|
||||
}
|
||||
}
|
||||
$bProvidersModified = false;
|
||||
foreach($aProviders as $oProvider)
|
||||
{
|
||||
if ($oProvider->IsApplicable($oUser))
|
||||
{
|
||||
$sProviderClass = get_class($oProvider);
|
||||
$bProviderEnabled = (utils::ReadParam('newsroom_provider_'.$sProviderClass, 'off') == 'on');
|
||||
$bCurrentValue = appUserPreferences::GetPref('newsroom_provider_'.$sProviderClass, true);
|
||||
if ($bCurrentValue != $bProviderEnabled)
|
||||
{
|
||||
// Save the preference only if it differs from the current value
|
||||
$bProvidersModified = true;
|
||||
appUserPreferences::SetPref('newsroom_provider_'.$sProviderClass, $bProviderEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($bProvidersModified)
|
||||
{
|
||||
$oPage->add_ready_script('$(".itop-newsroom_menu").newsroom_menu("clearCache");');
|
||||
}
|
||||
DisplayPreferences($oPage);
|
||||
break;
|
||||
|
||||
case 'display':
|
||||
default:
|
||||
$oPage->SetBreadCrumbEntry('ui-tool-preferences', Dict::S('UI:Preferences'), Dict::S('UI:Preferences'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png');
|
||||
|
||||
Reference in New Issue
Block a user