N°2847 - ActivityPanel: Rework for new UX

- Add MetaModel::GetCaseLogs($sClass) function
- Rename ActivityNewEntryForm to CaseLogEntryForm
- Rework ActivityPanel and CaseLogEntryForm markup / CSS
- Change for 1 CaseLogEntryForm per tab (caselogs and activity) with specific "Add entry..." choices
This commit is contained in:
Molkobain
2020-11-20 16:11:43 +01:00
parent 1e7d4e5c31
commit 7d0f1f46d3
25 changed files with 1027 additions and 537 deletions

View File

@@ -0,0 +1,297 @@
<?php
/*
* @copyright Copyright (C) 2010-2020 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Application\UI\Layout\ActivityPanel\CaseLogEntryForm;
use cmdbAbstractObject;
use Combodo\iTop\Application\UI\Component\Input\RichText\RichText;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu;
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
use Combodo\iTop\Application\UI\UIBlock;
/**
* Class CaseLogEntryForm
*
* @package Combodo\iTop\Application\UI\Layout\ActivityPanel\CaseLogEntryForm
*/
class CaseLogEntryForm extends UIContentBlock
{
// Overloaded constants
public const BLOCK_CODE = 'ibo-caselog-entry-form';
public const HTML_TEMPLATE_REL_PATH = 'layouts/activity-panel/caselog-entry-form/layout';
public const JS_TEMPLATE_REL_PATH = 'layouts/activity-panel/caselog-entry-form/layout';
public const JS_FILES_REL_PATH = [
'js/layouts/activity-panel/caselog-entry-form.js',
];
/** @var string Form is autonomous and can send data on its own */
public const ENUM_SUBMIT_MODE_AUTONOMOUS = 'autonomous';
/** @var string Form is bridged to its host object form */
public const ENUM_SUBMIT_MODE_BRIDGED = 'bridged';
/** @var string Container of the form is a specific caselog tab */
public const ENUM_CONTAINER_TAB_TYPE_CASELOG = 'caselog';
/** @var string Container of the form is the activity tab */
public const ENUM_CONTAINER_TAB_TYPE_ACTIVITY = 'activity';
/** @var string */
public const DEFAULT_SUBMIT_MODE = self::ENUM_SUBMIT_MODE_AUTONOMOUS;
/** @var string */
public const DEFAULT_CONTAINER_TAB_TYPE = self::ENUM_CONTAINER_TAB_TYPE_ACTIVITY;
/**
* @var string Whether the form can send data on its own or if it's bridged with its host object form
* @see static::ENUM_SUBMIT_MODE_XXX
*/
protected $sSubmitMode;
/**
* @var string Whether the form container is a caselog tab or an activity tab
* @see static::ENUM_CONTAINER_TAB_TYPE_XXX
*/
protected $sContainerTabType;
/** @var \Combodo\iTop\Application\UI\Component\Input\RichText\RichText $oTextInput The main input to write a case log entry */
protected $oTextInput;
/** @var \Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu Menu for possible options on the send button */
protected $oSendButtonPopoverMenu;
/** @var array $aMainActionButtons The form main actions (send, cancel, ...) */
protected $aMainActionButtons;
/** @var array $aExtraActionButtons The form extra actions, can be populated through a public API */
protected $aExtraActionButtons;
/**
* CaseLogEntryForm constructor.
*
* @param null $sName
*/
public function __construct($sName = null)
{
parent::__construct($sName);
$this->sSubmitMode = static::DEFAULT_SUBMIT_MODE;
$this->sContainerTabType = static::DEFAULT_CONTAINER_TAB_TYPE;
$this->SetTextInput(new RichText());
$this->aMainActionButtons = [];
$this->aExtraActionButtons = [];
}
/**
* @see $sSubmitMode
*
* @return string
*/
public function GetSubmitMode(): string
{
return $this->sSubmitMode;
}
/**
* @param string $sSubmitMode
* @see $sSubmitMode
*
* @return $this
*/
public function SetSubmitMode(string $sSubmitMode)
{
$this->sSubmitMode = $sSubmitMode;
return $this;
}
/**
* Set the submit mode (autonomous, bridged) from the host object mode (create, edit, view, ...)
* eg. create => bridged, view => autonomous.
*
* @param string $sObjectMode
* @see $sSubmitMode
* @see cmdbAbstractObject::ENUM_OBJECT_MODE_XXX
*
* @return $this
*/
public function SetSubmitModeFromHostObjectMode($sObjectMode)
{
switch ($sObjectMode){
case cmdbAbstractObject::ENUM_OBJECT_MODE_CREATE:
case cmdbAbstractObject::ENUM_OBJECT_MODE_EDIT:
$sSubmitMode = static::ENUM_SUBMIT_MODE_BRIDGED;
break;
case cmdbAbstractObject::ENUM_OBJECT_MODE_VIEW:
case cmdbAbstractObject::ENUM_OBJECT_MODE_STIMULUS:
default:
$sSubmitMode = static::ENUM_SUBMIT_MODE_AUTONOMOUS;
break;
}
$this->SetSubmitMode($sSubmitMode);
return $this;
}
/**
* Return true if the submit mode is autonomous
*
* @see $sSubmitMode
*
* @return bool
*/
public function IsSubmitAutonomous(): bool
{
return $this->GetSubmitMode() === static::ENUM_SUBMIT_MODE_AUTONOMOUS;
}
/**
* @see $sContainerTabType
*
* @return string
*/
public function GetContainerTabType(): string
{
return $this->sContainerTabType;
}
/**
* @param string $sContainerTabType
* @see $sContainerTabType
*
* @return $this
*/
public function SetContainerTabType(string $sContainerTabType)
{
$this->sContainerTabType = $sContainerTabType;
return $this;
}
/**
* @return \Combodo\iTop\Application\UI\Component\Input\RichText\RichText
*/
public function GetTextInput(): RichText
{
return $this->oTextInput;
}
/**
* @param \Combodo\iTop\Application\UI\Component\Input\RichText\RichText $oTextInput
*
* @return $this
*/
public function SetTextInput(RichText $oTextInput)
{
$this->oTextInput = $oTextInput;
return $this;
}
/**
* @return \Combodo\iTop\Application\UI\UIBlock[]
*/
public function GetMainActionButtons()
{
return $this->aMainActionButtons;
}
/**
* Set all main action buttons at once, replacing all existing ones
*
* @param array $aFormActionButtons
* @return $this
*/
public function SetMainActionButtons(array $aFormActionButtons)
{
$this->aMainActionButtons = $aFormActionButtons;
return $this;
}
/**
* @param \Combodo\iTop\Application\UI\UIBlock $oMainActionButton
* @return $this;
*/
public function AddMainActionButtons(UIBlock $oMainActionButton)
{
$this->aMainActionButtons[] = $oMainActionButton;
return $this;
}
/**
* @return \Combodo\iTop\Application\UI\UIBlock[]
*/
public function GetExtraActionButtons()
{
return $this->aExtraActionButtons;
}
/**
* Set all extra action buttons at once, replacing all existing ones
*
* @param array $aExtraActionButtons
* @see $aExtraActionButtons
*
* @return $this
*/
public function SetExtraActionButtons(array $aExtraActionButtons)
{
$this->aExtraActionButtons = $aExtraActionButtons;
return $this;
}
/**
* @param \Combodo\iTop\Application\UI\UIBlock $oExtraActionButton
*
* @return $this;
* @see $aExtraActionButtons
*
*/
public function AddExtraActionButtons(UIBlock $oExtraActionButton)
{
$this->aExtraActionButtons[] = $oExtraActionButton;
return $this;
}
/**
* @return \Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu
*/
public function GetSendButtonPopoverMenu(): PopoverMenu
{
return $this->oSendButtonPopoverMenu;
}
/**
* @param \Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu $oCaseLogSelectionPopOverMenu
* @return $this
*/
public function SetSendButtonPopoverMenu(PopoverMenu $oCaseLogSelectionPopOverMenu)
{
$this->oSendButtonPopoverMenu = $oCaseLogSelectionPopOverMenu;
return $this;
}
/**
* Return true is there is a PopoverMenu for the send button
*
* @return bool
*/
public function HasSendButtonPopoverMenu(): bool
{
return $this->oSendButtonPopoverMenu !== null;
}
/**
* @inheritdoc
*/
public function GetSubBlocks(): array
{
$aSubBlocks = [];
$aSubBlocks[$this->GetTextInput()->GetId()] = $this->GetTextInput();
foreach ($this->GetExtraActionButtons() as $oExtraActionButton)
{
$aSubBlocks[$oExtraActionButton->GetId()] = $oExtraActionButton;
}
foreach ($this->GetMainActionButtons() as $oMainActionButton)
{
$aSubBlocks[$oMainActionButton->GetId()] = $oMainActionButton;
}
$aSubBlocks[$this->GetSendButtonPopoverMenu()->GetId()] = $this->GetSendButtonPopoverMenu();
return $aSubBlocks;
}
}

View File

@@ -0,0 +1,164 @@
<?php
/*
* @copyright Copyright (C) 2010-2020 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Application\UI\Layout\ActivityPanel\CaseLogEntryFormFactory;
use cmdbAbstractObject;
use Combodo\iTop\Application\UI\Component\Button\Button;
use Combodo\iTop\Application\UI\Component\Button\ButtonFactory;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenuItem\PopoverMenuItemFactory;
use Combodo\iTop\Application\UI\Layout\ActivityPanel\CaseLogEntryForm\CaseLogEntryForm;
use DBObject;
use DBObjectSet;
use Dict;
use MetaModel;
use JSPopupMenuItem;
use UserRights;
/**
* Class CaseLogEntryFormFactory
*
* @internal
* @author Stephen Abello <stephen.abello@combodo.com>
* @author Guillaume Lajarige <guillaume.lajarige@combodo.com>
* @package Combodo\iTop\Application\UI\Layout\ActivityPanel\CaseLogEntryFormFactory
* @since 3.0.0
*/
class CaseLogEntryFormFactory
{
public static function MakeForCaselogTab(DBObject $oObject, string $sCaseLogAttCode, string $sObjectMode = cmdbAbstractObject::DEFAULT_OBJECT_MODE)
{
$oCaseLogEntryForm = new CaseLogEntryForm();
$oCaseLogEntryForm->SetSubmitModeFromHostObjectMode($sObjectMode)
->AddMainActionButtons(static::PrepareCancelButton())
->AddMainActionButtons(static::PrepareSendButton()->SetLabel(Dict::S('UI:Button:AddEntryAndWithChoice')))
->SetSendButtonPopoverMenu(static::PrepareSendActionSelectionPopoverMenu($oObject, $sCaseLogAttCode));
return $oCaseLogEntryForm;
}
public static function MakeForActivityTab(DBObject $oObject, string $sObjectMode = cmdbAbstractObject::DEFAULT_OBJECT_MODE)
{
$oCaseLogEntryForm = new CaseLogEntryForm();
$oCaseLogEntryForm->SetSubmitModeFromHostObjectMode($sObjectMode)
->AddMainActionButtons(static::PrepareCancelButton())
->AddMainActionButtons(static::PrepareSendButton()->SetLabel(Dict::S('UI:Button:AddEntryToWithChoice')));
$oCaseLogEntryForm->SetSendButtonPopoverMenu(static::PrepareTargetCaseLogSelectionPopoverMenu($oObject));
return $oCaseLogEntryForm;
}
/**
* @return \Combodo\iTop\Application\UI\Component\Button\Button
*/
protected static function PrepareCancelButton(): Button
{
return ButtonFactory::MakeForSecondaryAction(Dict::S('UI:Button:Cancel'), 'cancel', 'cancel');
}
/**
* @return \Combodo\iTop\Application\UI\Component\Button\Button
*/
protected static function PrepareSendButton(): Button
{
$oButton = ButtonFactory::MakeForPrimaryAction(Dict::S('UI:Button:Send'), 'send', 'send');
$oButton->SetIconClass('fas fa-paper-plane');
return $oButton;
}
protected static function PrepareSendActionSelectionPopoverMenu(DBObject $oObject, string $sCaseLogAttCode): PopoverMenu
{
$sObjClass = get_class($oObject);
$oMenu = new PopoverMenu();
$sSectionId = 'send-actions';
$oMenu->AddSection($sSectionId);
$sCaseLogEntryFormDataRole = CaseLogEntryForm::BLOCK_CODE;
// Standard, just save
$oMenuItem = PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem(
new JSPopupMenuItem(
CaseLogEntryForm::BLOCK_CODE.'--add-action--'.$sCaseLogAttCode.'--save',
Dict::S('UI:Button:Save'),
<<<JS
$(this).closest('[data-role="{$sCaseLogEntryFormDataRole}"]').trigger('add_to_caselog.caselog_entry_form.itop', {caselog_att_code: '{$sCaseLogAttCode}'});
JS
)
);
$oMenu->AddItem($sSectionId, $oMenuItem);
// Transitions
// Note: This code is inspired from cmdbAbstract::DisplayModifyForm(), it might be better to factorize it
$aTransitions = $oObject->EnumTransitions();
if (!isset($aExtraParams['custom_operation']) && count($aTransitions)) {
$oSetToCheckRights = DBObjectSet::FromObject($oObject);
$aStimuli = Metamodel::EnumStimuli($sObjClass);
foreach ($aTransitions as $sStimulusCode => $aTransitionDef) {
$iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sObjClass,
$sStimulusCode, $oSetToCheckRights) : UR_ALLOWED_NO;
switch ($iActionAllowed) {
case UR_ALLOWED_YES:
$oMenuItem = PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem(
new JSPopupMenuItem(
CaseLogEntryForm::BLOCK_CODE.'--add-action--'.$sCaseLogAttCode.'--stimulus--'.$sStimulusCode,
$aStimuli[$sStimulusCode]->GetLabel(),
<<<JS
$(this).closest('[data-role="{$sCaseLogEntryFormDataRole}"]').trigger('add_to_caselog.caselog_entry_form.itop', {caselog_att_code: '{$sCaseLogAttCode}', stimulus_code: '{$sStimulusCode}'});
JS
)
);
$oMenu->AddItem($sSectionId, $oMenuItem);
break;
}
}
}
return $oMenu;
}
/**
* Return a PopoverMenu with the list of the caselog attributes of $oObject
*
* @param \DBObject $oObject
*
* @return \Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu
* @throws \CoreException
* @throws \Exception
*/
protected static function PrepareTargetCaseLogSelectionPopoverMenu(DBObject $oObject): PopoverMenu
{
$sObjClass = get_class($oObject);
$oMenu = new PopoverMenu();
$sSectionId = 'target-caselogs';
$oMenu->AddSection($sSectionId);
$sCaseLogEntryFormDataRole = CaseLogEntryForm::BLOCK_CODE;
foreach(MetaModel::GetCaseLogs($sObjClass) as $sCaseLogAttCode) {
$oMenuItem = PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem(
new JSPopupMenuItem(
CaseLogEntryForm::BLOCK_CODE.'--target-caselog--'.$sCaseLogAttCode,
MetaModel::GetLabel($sObjClass, $sCaseLogAttCode),
<<<JS
$(this).closest('[data-role="{$sCaseLogEntryFormDataRole}"]').trigger('add_to_caselog.caselog_entry_form.itop', {caselog_att_code: '{$sCaseLogAttCode}'});
JS
)
);
$oMenu->AddItem($sSectionId, $oMenuItem);
}
return $oMenu;
}
}