Commit 996d7911 authored by Benjamin Kott's avatar Benjamin Kott Committed by Anja Leichsenring
Browse files

[FEATURE] Introduce callouts to replace content alerts

In several places alerts (flashmessages) are used to display
context information. We introduce content info boxes and replace
all these places where flashmessages used.

Resolves: #66077
Releases: master
Change-Id: I1b8288c146f4e75cc3d7cde0c89b74196acfd133
Reviewed-on: http://review.typo3.org/38271

Reviewed-by: Jan Helke's avatarJan Helke <typo3@helke.de>
Tested-by: Jan Helke's avatarJan Helke <typo3@helke.de>
Reviewed-by: default avatarAndreas Fernandez <andreas.fernandez@aspedia.de>
Tested-by: default avatarAndreas Fernandez <andreas.fernandez@aspedia.de>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
parent 6d87cf14
......@@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper;
/**
* Script Class for Web > Layout module
......@@ -394,11 +395,11 @@ class PageLayoutController {
$moduleLoader->load($GLOBALS['TBE_MODULES']);
$modules = $moduleLoader->modules;
if (is_array($modules['web']['sub']['list'])) {
$flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, '<p>' . $GLOBALS['LANG']->getLL('goToListModuleMessage') . '</p>
<p>' . IconUtility::getSpriteIcon('actions-system-list-open') . '<a href="javascript:top.goToModule( \'web_list\',1);">' . $GLOBALS['LANG']->getLL('goToListModule') . '
</a>
</p>', '', FlashMessage::INFO);
$content .= $flashMessage->render();
$title = $GLOBALS['LANG']->getLL('goToListModule');
$message = '<p>' . $GLOBALS['LANG']->getLL('goToListModuleMessage') . '</p>';
$message .= '<a class="btn btn-info" href="javascript:top.goToModule( \'web_list\',1);">' . $GLOBALS['LANG']->getLL('goToListModule') . '</a>';
$viewHelper = GeneralUtility::makeInstance(InfoboxViewHelper::class);
$content .= $viewHelper->render($title, $message, InfoboxViewHelper::STATE_INFO);
}
}
// If content from different pid is displayed
......@@ -610,8 +611,11 @@ class PageLayoutController {
');
$body = $this->doc->header($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']);
$flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $GLOBALS['LANG']->getLL('clickAPage_content'), $GLOBALS['LANG']->getLL('clickAPage_header'), FlashMessage::INFO);
$body .= $flashMessage->render();
$title = $GLOBALS['LANG']->getLL('clickAPage_header');
$message = $GLOBALS['LANG']->getLL('clickAPage_content');
$viewHelper = GeneralUtility::makeInstance(\TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper::class);
$body .= $viewHelper->render($title, $message, InfoboxViewHelper::STATE_INFO);
// Setting up the buttons and markers for docheader
$docHeaderButtons = array(
'view' => '',
......
==============================================================
Feature - #66077: Introduce callouts to replace content alerts
==============================================================
Description
===========
In several places alerts (flashmessages) were used to display context information.
We introduce content info boxes and replace all occurences where flashmessages were used.
Impact
======
We introduced a new layout for context information and added a ViewHelper to render the markup.
Examples
========
Simple infobox with a title
.. code-block:: html
<f:be.infobox title="Message title">your box content</f:be.infobox>
All options
<f:be.infobox title="Message title" message="your box content" state="-2" iconName="check" disableIcon="TRUE" />
\ No newline at end of file
<?php
namespace TYPO3\CMS\Fluid\ViewHelpers\Be;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
/**
* View helper for rendering a styled content infobox markup.
*
* = States =
*
* The Infobox provides different context sensitive states that
* can be used to provide an additional visual feedback to the
* to the user to underline the meaning of the information.
*
* Possible values are in range from -2 to 2. Please choose a
* meaningful value from the following list.
*
* -2: Notices (Default)
* -1: Information
* 0: Positive feedback
* 1: Warnings
* 2: Error
*
* = Examples =
*
* <code title="Simple">
* <f:be.infobox title="Message title">your box content</f:be.infobox>
* </code>
*
* <code title="All options">
* <f:be.infobox title="Message title" message="your box content" state="-2" iconName="check" disableIcon="TRUE" />
* </code>
*
* @api
*/
class InfoboxViewHelper extends AbstractViewHelper {
const STATE_NOTICE = -2;
const STATE_INFO = -1;
const STATE_OK = 0;
const STATE_WARNING = 1;
const STATE_ERROR = 2;
/**
* @param string $title The title of the infobox
* @param string $message The message of the infobox, if NULL tag content is used
* @param int $state The state of the box, InfoboxViewHelper::STATE_*
* @param string $iconName The icon name from fontawsome, NULL sets default icon
* @param bool $disableIcon If set to TRUE, the icon is not rendered.
*
* @return string
*/
public function render($title = NULL, $message = NULL, $state = self::STATE_NOTICE, $iconName = NULL, $disableIcon = FALSE) {
if ($message === NULL) {
$message = $this->renderChildren();
}
switch ($state) {
case self::STATE_NOTICE:
$stateClass = 'notice';
$icon = 'lightbulb-o';
break;
case self::STATE_INFO:
$stateClass = 'info';
$icon = 'info';
break;
case self::STATE_OK:
$stateClass = 'success';
$icon = 'check';
break;
case self::STATE_WARNING:
$stateClass = 'warning';
$icon = 'exclamation';
break;
case self::STATE_ERROR:
$stateClass = 'danger';
$icon = 'times';
break;
default:
$stateClass = 'notice';
$icon = 'lightbulb-o';
}
if ($iconName !== NULL) {
$icon = htmlspecialchars($iconName);
}
$iconTemplate = '';
if (!$disableIcon) {
$iconTemplate = '' .
'<div class="media-left">' .
'<span class="fa-stack fa-lg callout-icon">' .
'<i class="fa fa-circle fa-stack-2x"></i>' .
'<i class="fa fa-' . $icon . ' fa-stack-1x"></i>' .
'</span>' .
'</div>';
}
$titleTemplate = '';
if ($title !== NULL) {
$titleTemplate = '<h4 class="callout-title">' . $title . '</h4>';
}
$template = '' .
'<div class="callout callout-' . $stateClass . '">' .
'<div class="media">' .
$iconTemplate .
'<div class="media-body">' .
$titleTemplate .
'<div class="callout-body">' . $message . '</div>' .
'</div>' .
'</div>' .
'</div>';
return $template;
}
}
......@@ -15,6 +15,8 @@ namespace TYPO3\CMS\Func\Controller;
*/
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper;
/**
* Script Class for the Web > Functions module
......@@ -97,13 +99,11 @@ class PageFunctionsController extends \TYPO3\CMS\Backend\Module\BaseScriptClass
$markers['CONTENT'] = $this->content;
} else {
// If no access or if ID == zero
$flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
\TYPO3\CMS\Core\Messaging\FlashMessage::class,
$this->getLanguageService()->getLL('clickAPage_content'),
$this->getLanguageService()->getLL('title'),
\TYPO3\CMS\Core\Messaging\FlashMessage::INFO
);
$this->content = $flashMessage->render();
$title = $this->getLanguageService()->getLL('title');
$message = $this->getLanguageService()->getLL('clickAPage_content');
$viewHelper = GeneralUtility::makeInstance(\TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper::class);
$this->content = $viewHelper->render($title, $message, InfoboxViewHelper::STATE_INFO);
// Setting up the buttons and markers for docheader
$docHeaderButtons = $this->getButtons();
$markers['CSH'] = $docHeaderButtons['csh'];
......
......@@ -67,21 +67,17 @@
</div>
</f:then>
<f:else>
<div class="alert alert-notice">
<div class="message-body">
<f:translate key="administration.statistics.noResultForPage"/>
</div>
</div>
<f:be.infobox>
<f:translate key="administration.statistics.noResultForPage"/>
</f:be.infobox>
</f:else>
</f:if>
</f:then>
<f:else>
<div class="alert alert-info">
<div class="message-body">
<f:translate key="administration.statistics.selectPage"/>
</div>
</div>
<f:be.infobox state="-1">
<f:translate key="administration.statistics.selectPage"/>
</f:be.infobox>
</f:else>
</f:if>
</f:section>
......@@ -112,13 +108,11 @@
</table>
</f:then>
<f:else>
<div class="alert alert-notice">
<div class="message-body">
<f:translate key="administration.statistics.noResult"/>
</div>
</div>
<f:be.infobox state="2">
<f:translate key="administration.statistics.noResult"/>
</f:be.infobox>
</f:else>
</f:if>
</f:section>
<f:section name="Buttons"></f:section>
\ No newline at end of file
<f:section name="Buttons"></f:section>
......@@ -114,11 +114,7 @@
</f:if>
</f:then>
<f:else>
<div class="alert alert-danger">
<div class="message-body">
no record found
</div>
</div>
<f:be.infobox state="2" message="no record found" />
</f:else>
</f:if>
</f:section>
......
......@@ -6,21 +6,16 @@
<f:form action="enableInstallTool" method="post" id="t3-install-form-unlock">
<f:form.hidden name="installToolEnableToken" value="{installToolEnableToken}" />
<div id="container">
<div class="typo3-message message-warning">
<h4>
<f:translate
key="LLL:EXT:install/Resources/Private/Language/BackendModule.xlf:confirmUnlockInstallToolTitle"
/>
</h4>
<f:be.infobox state="-1" title="{f:translate(key: 'LLL:EXT:install/Resources/Private/Language/BackendModule.xlf:confirmUnlockInstallToolTitle')}">
<f:translate
key="LLL:EXT:install/Resources/Private/Language/BackendModule.xlf:confirmUnlockInstallToolMessage"
/>
<button class="btn btn-warning" value="enableInstallTool">
/>
<button class="btn btn-info" value="enableInstallTool">
<f:translate
key="LLL:EXT:install/Resources/Private/Language/BackendModule.xlf:confirmUnlockInstallToolButton"
/>
/>
</button>
</div>
</f:be.infobox>
</div>
</f:form>
</f:section>
......@@ -16,11 +16,8 @@
<h3>{f:translate(key:'checkScript_update_description')}</h3><p>
<code>php {PATH_typo3}cli_dispatch.phpsh lowlevel_refindex -e</code></p>
<div class="alert alert-info">
<div class="message-body">
{f:translate(key:'checkScript_information')}
</div>
</div>
<f:be.infobox state="-1" message="{f:translate(key:'checkScript_information')}" />
<p>{f:translate(key:'checkScript_moreDetails')} <br>
<a href="sysext/lowlevel/HOWTO_clean_up_TYPO3_installations.txt" target="_new">{PATH_typo3}sysext/lowlevel/HOWTO_clean_up_TYPO3_installations.txt</a>
......
......@@ -22,6 +22,7 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\Utility\IconUtility;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper;
use TYPO3\CMS\Saltedpasswords\Salt\SaltFactory;
use TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility;
use TYPO3\CMS\Scheduler\Task\AbstractTask;
......@@ -364,11 +365,11 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
$lastRun = $registry->get('tx_scheduler', 'lastRun');
if (!is_array($lastRun)) {
$message = $this->getLanguageService()->getLL('msg.noLastRun');
$severity = FlashMessage::WARNING;
$severity = InfoboxViewHelper::STATE_WARNING;
} else {
if (empty($lastRun['end']) || empty($lastRun['start']) || empty($lastRun['type'])) {
$message = $this->getLanguageService()->getLL('msg.incompleteLastRun');
$severity = FlashMessage::WARNING;
$severity = InfoboxViewHelper::STATE_WARNING;
} else {
$startDate = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'], $lastRun['start']);
$startTime = date($GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'], $lastRun['start']);
......@@ -380,28 +381,27 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
}
$type = $this->getLanguageService()->getLL('label.' . $label);
$message = sprintf($this->getLanguageService()->getLL('msg.lastRun'), $type, $startDate, $startTime, $endDate, $endTime);
$severity = FlashMessage::INFO;
$severity = InfoboxViewHelper::STATE_INFO;
}
}
/** @var $flashMessage FlashMessage */
$flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $message, '', $severity);
$this->view->assign('lastRun', $flashMessage->render());
$this->view->assign('lastRunMessage', $message);
$this->view->assign('lastRunSeverity', $severity);
// Check CLI user
$checkUser = $this->checkSchedulerUser();
if ($checkUser == -1) {
$link = $this->moduleUri . '&SET[function]=check&CMD=user';
$message = sprintf($this->getLanguageService()->getLL('msg.schedulerUserMissing'), htmlspecialchars($link));
$severity = FlashMessage::ERROR;
$severity = InfoboxViewHelper::STATE_ERROR;
} elseif ($checkUser == 0) {
$message = $this->getLanguageService()->getLL('msg.schedulerUserFoundButDisabled');
$severity = FlashMessage::WARNING;
$severity = InfoboxViewHelper::STATE_WARNING;
} else {
$message = $this->getLanguageService()->getLL('msg.schedulerUserFound');
$severity = FlashMessage::OK;
$severity = InfoboxViewHelper::STATE_OK;
}
$flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $message, '', $severity);
$this->view->assign('cliUser', $flashMessage->render());
$this->view->assign('cliUserMessage', $message);
$this->view->assign('cliUserSeverity', $severity);
// Check if CLI script is executable or not
$script = PATH_typo3 . 'cli_dispatch.phpsh';
......@@ -416,13 +416,13 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
}
if ($isExecutable) {
$message = $this->getLanguageService()->getLL('msg.cliScriptExecutable');
$severity = FlashMessage::OK;
$severity = InfoboxViewHelper::STATE_OK;
} else {
$message = $this->getLanguageService()->getLL('msg.cliScriptNotExecutable');
$severity = FlashMessage::ERROR;
$severity = InfoboxViewHelper::STATE_ERROR;
}
$flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $message, '', $severity);
$this->view->assign('isExecutable', $flashMessage->render());
$this->view->assign('isExecutableMessage', $message);
$this->view->assign('isExecutableSeverity', $severity);
return $this->view->render();
}
......@@ -919,10 +919,6 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
// No tasks defined, display information message
if ($numRows == 0) {
$this->view->setTemplatePathAndFilename($this->backendTemplatePath . 'ListTasksNoTasks.html');
/** @var $flashMessage FlashMessage */
$flashMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessage::class, $this->getLanguageService()->getLL('msg.noTasks'), '', FlashMessage::INFO);
$this->view->assign('message', $flashMessage->render());
return $this->view->render();
} else {
$this->pageRenderer->loadJquery();
......
......@@ -268,7 +268,7 @@
<source>The backend user "_cli_scheduler" exists but is currently disabled.</source>
</trans-unit>
<trans-unit id="msg.schedulerUserMissing" xml:space="preserve">
<source>The backend user "_cli_scheduler" was not found. &lt;a href="%s" title="Click to create the missing user"&gt;Create the user now&lt;/a&gt;.</source>
<source>The backend user "_cli_scheduler" was not found.&lt;br/&gt;&lt;br/&gt; &lt;a href="%s" class="btn btn-danger" title="Click to create the missing user"&gt;Create the user now&lt;/a&gt;</source>
</trans-unit>
<trans-unit id="msg.serverTime" xml:space="preserve">
<source>Current server time is %s.</source>
......
......@@ -2,19 +2,14 @@
<f:translate key="msg.schedulerSetupCheck" />
</p>
<div class="info-block">
<h2><f:translate key="hdg.lastRun" /></h2>
<f:format.raw>{lastRun}</f:format.raw>
</div>
<f:be.infobox title="{f:translate(key: 'hdg.lastRun')}" message="{lastRunMessage}" state="{lastRunSeverity}" />
<div class="info-block">
<h2><f:translate key="hdg.schedulerUser" /></h2>
<f:be.infobox title="{f:translate(key: 'hdg.schedulerUser')}" state="{cliUserSeverity}">
<p><f:translate key="msg.schedulerUser" /></p>
<f:format.raw>{cliUser}</f:format.raw>
</div>
<f:format.raw>{cliUserMessage}</f:format.raw>
</f:be.infobox>
<div class="info-block">
<h2><f:translate key="hdg.cliScript" /></h2>
<f:be.infobox title="{f:translate(key: 'hdg.cliScript')}" state="{isExecutableSeverity}">
<p><f:translate key="msg.cliScript" arguments="{0: script}" /></p>
<f:format.raw>{isExecutable}</f:format.raw>
</div>
\ No newline at end of file
<f:format.raw>{isExecutableMessage}</f:format.raw>
</f:be.infobox>
<f:format.raw>{message}</f:format.raw>
\ No newline at end of file
<f:be.infobox state="-1" message="{f:translate(key: 'msg.noTasks')}">
</f:be.infobox>
......@@ -24,6 +24,9 @@
}
}
}
.media-body {
vertical-align: middle;
}
}
.alert-title {
font-size: 1.12em;
......@@ -74,3 +77,73 @@
}
}
}
//
// Callouts
//
.callout {
background-color: @callout-bg;
border-left: 3px solid @callout-border;
margin: 20px 0;
padding: @callout-padding;
color: @callout-color;
.media {
margin: 0;
.fa-stack {
color: @callout-icon-color;
> .fa:first-child {
color: @callout-border;
}
}
}
.media-body {
vertical-align: middle;
}
}
.callout-icon {
margin-top: -2px;
}
.callout-title {
font-size: 1.3em;
margin: 0 0 0.5em;
}
.callout-body {
> *:last-child {
margin-bottom: 0;
}
}
//
// Callout variants
//
.callout-variant(@background; @border; @text-color; @icon-color) {
background-color: @background;
border-color: @border;
color: @text-color;
.media {
margin: 0;
.fa-stack {
color: @icon-color;
> .fa:first-child {
color: @border;
}
}
}
}
.callout-success {
.callout-variant(@callout-success-bg; @callout-success-border; @callout-success-color; @callout-success-icon-color);
}
.callout-info {
.callout-variant(@callout-info-bg; @callout-info-border; @callout-info-color; @callout-info-icon-color);
}
.callout-warning {
.callout-variant(@callout-warning-bg; @callout-warning-border; @callout-warning-color; @callout-warning-icon-color);
}
.callout-danger {
.callout-variant(@callout-danger-bg; @callout-danger-border; @callout-danger-color; @callout-danger-icon-color);
}
.callout-notice {
.callout-variant(@callout-notice-bg; @callout-notice-border; @callout-notice-color; @callout-notice-icon-color);
}
......@@ -494,7 +494,7 @@
@state-success-border: @brand-success;
@state-info-text: @brand-info;
@state-info-bg: lighten(@brand-info, 35%);
@state-info-bg: lighten(@brand-info, 30%);
@state-info-border: @brand-info;
@state-warning-text: @brand-warning;
......@@ -643,6 +643,43 @@
@alert-notice-border: transparent;
//== Callouts
//
//## Define callouts colors, border radius, and padding.
@callout-padding: 20px;
@callout-color: #333;
@callout-icon-color: #fff;
@callout-bg: #f0f0f0;
@callout-border: #ccc;
@callout-border-radius: 2px;
@callout-success-bg: @state-success-bg;
@callout-success-color: @callout-color;
@callout-success-icon-color: @callout-icon-color;
@callout-success-border: @state-success-border;
@callout-info-bg: @state-info-bg;