Commit 044a7324 authored by Ghislain Loas's avatar Ghislain Loas

Merge branch...

Merge branch 'dev#58111_ouvrir_automatiquement_la_note_de_version_a_la_premiere_connection_d_un_administrateur' into 'master'

Dev#58111 ouvrir automatiquement la note de version a la premiere connection d un administrateur

See merge request afi/opacce!2517
parents 666372c9 852df007
- ticket #58111 : Administration : notification automatique des nouvelles fonctionnalités à la première connection d'un administrateur.
\ No newline at end of file
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
class Admin_FeatureController extends ZendAfi_Controller_Action { class Admin_FeatureController extends ZendAfi_Controller_Action {
public function indexAction() { public function indexAction() {
$this->view->titre = $this->_('Les fonctionnalités du logiciel Bokeh'); $this->view->titre = $this->_('Les fonctionnalités du logiciel Bokeh');
(new Class_Feature())->stopTracking();
$user = Class_Users::getIdentity(); $user = Class_Users::getIdentity();
$this->view->new_features = (new Class_Feature)->findNewFor($user); $this->view->new_features = (new Class_Feature)->findNewFor($user);
$this->view->checked_features = (new Class_Feature)->findCheckedBy($user); $this->view->checked_features = (new Class_Feature)->findCheckedBy($user);
...@@ -71,4 +72,12 @@ class Admin_FeatureController extends ZendAfi_Controller_Action { ...@@ -71,4 +72,12 @@ class Admin_FeatureController extends ZendAfi_Controller_Action {
$feature->getLabel())); $feature->getLabel()));
$this->_redirectToIndex(); $this->_redirectToIndex();
} }
public function stopTrackingAction() {
if((new Class_Feature())->stopTracking())
$this->_helper->notify($this->_('Vous ne serez plus notifié des nouvelles fonctionnalités jusqu\'à la prochaine mise à jour du logicel.'));
$this->_redirectToIndex();
}
} }
\ No newline at end of file
...@@ -339,7 +339,9 @@ class Class_AdminVarLoader extends Storm_Model_Loader { ...@@ -339,7 +339,9 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
'CNIL_CONSENT_ENABLE' => Class_AdminVar_Meta::newOnOff('Affiche la demande de consentement avant l\'insertion de cookies ou autres traceurs'), 'CNIL_CONSENT_ENABLE' => Class_AdminVar_Meta::newOnOff('Affiche la demande de consentement avant l\'insertion de cookies ou autres traceurs'),
'BUID' => Class_AdminVar_Meta::newRawText($this->_('Identifiant unique (attention: la modification de cette variable impactera les outils de suivi de cette installation)'))->bePrivate(), 'BUID' => Class_AdminVar_Meta::newRawText($this->_('Identifiant unique (attention: la modification de cette variable impactera les outils de suivi de cette installation)'))->bePrivate(),
'STATUS_REPORT_PUSH_URL' => Class_AdminVar_Meta::newRawText($this->_('URL destinataire du rapport d\'état du système (0 pour désactiver)'), ['value' => 'http://pola.afi-sa.net/smile.php'])->bePrivate(), 'STATUS_REPORT_PUSH_URL' => Class_AdminVar_Meta::newRawText($this->_('URL destinataire du rapport d\'état du système (0 pour désactiver)'), ['value' => 'http://pola.afi-sa.net/smile.php'])->bePrivate(),
'STATUS_REPORT_TAGS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des tags à ajouter au rapport d\'état du système'))->bePrivate()]; 'STATUS_REPORT_TAGS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des tags à ajouter au rapport d\'état du système'))->bePrivate(),
'FEATURES_TRACKING_ENABLE' => Class_AdminVar_Meta::newOnOff('Affiche les dernières modifications apportés au logiciel Bokeh', ['value' => 1])->bePrivate()
];
} }
......
...@@ -22,10 +22,14 @@ ...@@ -22,10 +22,14 @@
class Class_Feature { class Class_Feature {
use use
Trait_Translator, Trait_StaticFileSystem,
Trait_StaticFileSystem; Trait_TimeSource,
Trait_Translator;
protected static $_features;
protected static
$_features,
$_cookie_jar;
public function hasNew() { public function hasNew() {
...@@ -108,4 +112,105 @@ class Class_Feature { ...@@ -108,4 +112,105 @@ class Class_Feature {
->setId($id) ->setId($id)
->updateAttributes($feature); ->updateAttributes($feature);
} }
protected function _getCookieJar() {
return static::$_cookie_jar
? static::$_cookie_jar
: new Class_Feature_CookieJar();
}
/** @category testing */
public static function setCookieJar($cookie_jar) {
static::$_cookie_jar = $cookie_jar;
}
public function trackFeatures() {
if(!$this->_isTrackingFeaturesReady())
return;
if(!$features = $this->findNewFor(Class_Users::getIdentity()))
return;
if (isset($_COOKIE[$this->_getCookieJar()->getKey()]))
return;
$session = new Zend_Session_Namespace($this->_getCookieJar()->getKey());
if ($session->features_seen)
return;
$session->features_seen = true;
Class_ScriptLoader::getInstance()
->notify($this->_renderContent($features), false, 10, 'new_features');
}
protected function _isTrackingFeaturesReady() {
if (!Class_AdminVar::get('FEATURES_TRACKING_ENABLE'))
return false;
if(!$user = Class_Users::getIdentity())
return false;
if(!$user->isAdmin())
return false;
return true;
}
protected function _renderContent($features) {
$buttons = [sprintf('<button class="admin-button" onclick="window.open(\'%s\');">%s</button>',
Class_Url::absolute(['module' => 'admin',
'controller' => 'feature',
'action' => 'index'], null, true),
$this->_('En savoir plus')),
sprintf('<button class="admin-button" onclick="window.open(\'%s\', \'_top\')">%s</button>',
Class_Url::absolute(['module' => 'admin',
'controller' => 'feature',
'action' => 'stop-tracking'], null, true),
$this->_('Ne plus m\'avertir'))];
$html_features = [];
foreach($features as $feature)
$html_features[] = sprintf('<li>%s</li>', $feature->getLabel());
$html = [sprintf('<h2>%s</h2>',
$this->_('Nouvelles fonctionnalités depuis votre dernière connexion : ')),
sprintf('<ul>%s</ul>',
implode($html_features)),
sprintf('<div class="button_wrapper">%s</div>',
implode($buttons))];
return sprintf('<div class="features">%s</div>', implode($html));
}
public function stopTracking() {
if(!$this->_isTrackingFeaturesReady())
return;
return $this->_getCookieJar()
->setcookie($this->_getCookieJar()->getKey(),
'1',
$this->getTimeSource()->time() + (3600 * 24 * 30 * 3));
}
} }
class Class_Feature_CookieJar {
public function setcookie() {
call_user_func_array('setcookie', func_get_args());
}
public function getKey() {
return 'tracking_features_' . str_replace('.', '_', BOKEH_RELEASE_NUMBER);
}
}
\ No newline at end of file
...@@ -338,9 +338,11 @@ class Class_ScriptLoader { ...@@ -338,9 +338,11 @@ class Class_ScriptLoader {
public function loadNotificationJS() { public function loadNotificationJS() {
Class_Admin_Skin::current()->renderButtonCssOn($this);
return $this return $this
->addScript(URL_ADMIN_JS.'notification/js/jquery_notification_v.1') ->addScript(URL_ADMIN_JS.'notification/js/jquery_notification_v.1')
->addStyleSheet(URL_ADMIN_JS.'notification/css/jquery_notification') ->addStyleSheet(URL_ADMIN_JS.'notification/css/jquery_notification')
->addAdminStyleSheet('notification')
->addSkinStyleSheet('notification'); ->addSkinStyleSheet('notification');
} }
......
<?php
/**
* Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
*
* BOKEH 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.
*
* There are special exceptions to the terms and conditions of the AGPL as it
* is applied to this software (see README file).
*
* BOKEH 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 BOKEH; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class ZendAfi_Controller_Plugin_FeaturesTracking extends Zend_Controller_Plugin_Abstract {
function preDispatch(Zend_Controller_Request_Abstract $request) {
(new Class_Feature())->trackFeatures();
}
}
...@@ -298,6 +298,7 @@ class Bokeh_Engine { ...@@ -298,6 +298,7 @@ class Bokeh_Engine {
->registerPlugin(new ZendAfi_Controller_Plugin_InspectorGadget()) ->registerPlugin(new ZendAfi_Controller_Plugin_InspectorGadget())
->registerPlugin(new ZendAfi_Controller_Plugin_CnilConsent()) ->registerPlugin(new ZendAfi_Controller_Plugin_CnilConsent())
->registerPlugin(new ZendAfi_Controller_Plugin_Redmine()) ->registerPlugin(new ZendAfi_Controller_Plugin_Redmine())
->registerPlugin(new ZendAfi_Controller_Plugin_FeaturesTracking())
->setParam('useDefaultControllerAlways', false); ->setParam('useDefaultControllerAlways', false);
} }
......
#info_message.new_features {
background: var(--main-text);
height: 100%;
}
#info_message.new_features > div {
background: var(--button);
margin: 10%;
width: 80%;
}
#info_message .features {
text-align: left;
}
#info_message .features ul,
#info_message .features li{
padding: 0 0 1ex 1em;
list-style-type: initial;
}
#info_message .features .button_wrapper {
text-align: center;
}
#info_message.new_features .info_close_btn {
float: right;
}
#info_message.new_features .info_close_btn:after {
content: 'X';
display: block;
}
\ No newline at end of file
...@@ -33,7 +33,9 @@ function showNotification(params){ ...@@ -33,7 +33,9 @@ function showNotification(params){
msgclass = 'info_bg'; // over write the message to information message msgclass = 'info_bg'; // over write the message to information message
} else if(options['type'] == 'warning'){ } else if(options['type'] == 'warning'){
msgclass = 'warn_bg'; // over write the message to warning message msgclass = 'warn_bg'; // over write the message to warning message
} } else {
msgclass = options['type']; // over write class
}
// Parent Div container // Parent Div container
var container = '<div id="info_message" role="alert" class="'+msgclass+'"><div class="center_auto"><div class="info_message_text message_area">'; var container = '<div id="info_message" role="alert" class="'+msgclass+'"><div class="center_auto"><div class="info_message_text message_area">';
......
<?php
/**
* Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
*
* BOKEH 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.
*
* There are special exceptions to the terms and conditions of the AGPL as it
* is applied to this software (see README file).
*
* BOKEH 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 BOKEH; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
abstract class IndexControllerFeaturesTrackingTestCase extends Admin_AbstractControllerTestCase {
protected $_storm_default_to_volatile = true;
protected $_expected_message = 'Nouvelles fonctionnalit\u00e9s depuis votre derni\u00e8re connexion :';
protected $_cookie_jar;
public function setUp() {
parent::setUp();
$this->fixture('Class_AdminVar', ['id' => 'FEATURES_TRACKING_ENABLE',
'valeur' => true]);
Class_Feature::setTimeSource($this->mock()
->whenCalled('time')
->answers(strtotime('2018-02-21 11:51:54')));
Class_Feature::setCookieJar($this->_cookie_jar =
$this->mock()
->whenCalled('setcookie')
->answers(true)
->whenCalled('getKey')
->answers('tracking_features_7_11_20'));
}
public function tearDown() {
Class_Feature::setCookieJar(null);
$_COOKIE = [];
parent::tearDown();
}
}
class IndexControllerFeaturesTrackingFirstVisitTest
extends IndexControllerFeaturesTrackingTestCase {
public function setUp() {
parent::setUp();
$this->dispatch('/', true);
}
/** @test */
public function shouldDisplayNewFeaturesMessage() {
$this->assertXPathContentContains('//script', $this->_expected_message, $this->_response->getBody());
}
}
class IndexControllerFeaturesTrackingTrackingFirstVisitWithAdminVarDisabledTest
extends IndexControllerFeaturesTrackingTestCase {
public function setUp() {
parent::setUp();
$this->fixture('Class_AdminVar', ['id' => 'FEATURES_TRACKING_ENABLE',
'valeur' => false]);
$this->dispatch('/', true);
}
/** @test */
public function shouldNotDisplayNewFeaturesMessage() {
$this->assertNotXPathContentContains('//script', $this->_expected_message);
}
}
class IndexControllerFeaturesTrackingSecondVisitTest
extends IndexControllerFeaturesTrackingTestCase {
public function setUp() {
parent::setUp();
$this->dispatch('/', true);
$this->_response->setBody('');
Class_ScriptLoader::resetInstance();
$this->dispatch('/', true);
}
/** @test */
public function shouldNotDisplayNewFeaturesMessage() {
$this->assertNotXPathContentContains('//script', $this->_expected_message);
}
/** @test */
public function shouldNotSetCookieFor6Months() {
$this->assertFalse($this->_cookie_jar->methodHasBeenCalled('setcookie'));
}
}
class IndexControllerFeaturesTrackingExistingCookieVisitTest
extends IndexControllerFeaturesTrackingTestCase {
public function setUp() {
parent::setUp();
$_COOKIE['tracking_features_7_11_20'] = 1;
$this->dispatch('/', true);
}
/** @test */
public function shouldNotDisplayNewFeaturesMessage() {
$this->assertNotXPathContentContains('//script', $this->_expected_message);
}
}
class IndexControllerFeaturesTrackingUntrackTest
extends IndexControllerFeaturesTrackingTestCase {
public function setUp() {
parent::setUp();
Class_Feature::setCookieJar($this->_cookie_jar = $this->mock()
->whenCalled('setcookie')
->with('tracking_features_7_11_20',
1,
1526986314)
->answers(true)
->whenCalled('getKey')
->answers('tracking_features_7_11_20'));
}
/** @test */
public function stopTrackingActionshouldSetCookie() {
$this->dispatch('/admin/feature/stop-tracking', true);
$this->assertTrue($this->_cookie_jar->methodHasBeenCalled('setcookie'));
}
/** @test */
public function indexActionSetCookie() {
$this->dispatch('/admin/feature/index', true);
$this->assertTrue($this->_cookie_jar->methodHasBeenCalled('setcookie'));
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment