diff --git a/js/layouts/activity-panel/activity-panel.js b/js/layouts/activity-panel/activity-panel.js index c67e57d9a..0e6f6fafb 100644 --- a/js/layouts/activity-panel/activity-panel.js +++ b/js/layouts/activity-panel/activity-panel.js @@ -45,6 +45,8 @@ $(function() activity_filter: '[data-role="ibo-activity-panel--activity-filter"]', caselog_tab_open_all: '[data-role="ibo-activity-panel--caselog-open-all"]', caselog_tab_close_all: '[data-role="ibo-activity-panel--caselog-close-all"]', + compose_button: '[data-role="ibo-activity-panel--add-caselog-entry-button"]', + caselog_entry_form: '[data-role="ibo-caselog-entry-form"]', entry_group: '[data-role="ibo-activity-panel--entry-group"]', entry: '[data-role="ibo-activity-entry"]', entry_medallion: '[data-role="ibo-activity-entry--medallion"]', @@ -53,6 +55,12 @@ $(function() edits_entry_long_description: '[data-role="ibo-edits-entry--long-description"]', edits_entry_long_description_toggler: '[data-role="ibo-edits-entry--long-description-toggler"]', }, + enums: { + tab_types: { + caselog: 'caselog', + activity: 'activity', + } + }, // the constructor _create: function() @@ -60,6 +68,9 @@ $(function() this.element.addClass('ibo-activity-panel'); this._bindEvents(); this._ReformatDateTimes(); + + // TODO 3.0.0: Modify PopoverMenu so we can pass it the ID of the block triggering the open/close + //$(this.element).find(this.js_selectors.send_choices_picker).popover_menu({toggler: this.js_selectors.send_button}); }, // events bound via _bind are removed automatically // revert other modifications here @@ -72,33 +83,47 @@ $(function() const me = this; const oBodyElem = $('body'); - // Click on the panel collapse/expand toggler + // Tabs title + // - Click on the panel collapse/expand toggler this.element.find(this.js_selectors.panel_size_toggler).on('click', function(oEvent){ me._onPanelSizeTogglerClick(oEvent); }); - // Click on a tab title + // - Click on a tab title this.element.find(this.js_selectors.tab_title).on('click', function(oEvent){ me._onTabTitleClick(oEvent, $(this)); }); - // Change on an activity filter + // Tabs toolbar + // - Change on an activity filter this.element.find(this.js_selectors.activity_filter).on('change', function(){ me._onActivityFilterChange($(this)); }); - // Click on open all case log messages + // - Click on open all case log messages this.element.find(this.js_selectors.caselog_tab_open_all).on('click', function(){ me._onCaseLogOpenAllClick($(this)); }); - // Click on close all case log messages + // - Click on close all case log messages this.element.find(this.js_selectors.caselog_tab_close_all).on('click', function(){ me._onCaseLogCloseAllClick($(this)); }); - // Click on a closed case log message + // Entry form + // - Click on the compose button + this.element.find(this.js_selectors.compose_button).on('click', function(oEvent){ + me._onComposeButtonClick(oEvent); + }); + // - Cancelled form + this.element.on('cancelled_form.caselog_entry_form.itop', function(){ + me._onCancelledEntryForm(); + }); + // - Submitted form + + // Entries + // - Click on a closed case log message this.element.find(this.js_selectors.entry_group).on('click', '.'+this.css_classes.is_closed + ' ' + this.js_selectors.entry_main_information, function(oEvent){ me._onCaseLogClosedMessageClick($(this).closest(me.js_selectors.entry)); }); - // Click on an edits entry's long description toggler + // - Click on an edits entry's long description toggler this.element.find(this.js_selectors.edits_entry_long_description_toggler).on('click', function(oEvent){ me._onEditsLongDescriptionTogglerClick(oEvent, $(this).closest(me.js_selectors.entry)); }); @@ -151,7 +176,7 @@ $(function() }, _onActivityFilterChange: function(oInputElem) { - this._ApplyEntryFilters(); + this._ApplyEntriesFilters(); }, _onCaseLogOpenAllClick: function(oIconElem) { @@ -163,6 +188,34 @@ $(function() const sCaseLogAttCode = oIconElem.closest(this.js_selectors.tab_toggler).attr('data-caselog-attribute-code'); this._CloseAllMessages(sCaseLogAttCode); }, + /** + * @param oEvent {Object} + * @return {void} + * @private + */ + _onComposeButtonClick: function(oEvent) + { + oEvent.preventDefault(); + + const oActiveTabData = this._GetActiveTabData(); + // If on a caselog tab, open its form + if (this.enums.tab_types.caselog === oActiveTabData.type) { + this._ShowCaseLogTab(oActiveTabData.att_code); + this._ShowCaseLogsEntryForms(); + } + // Else if on the activity tab, check which case log tab to go to + else { + // TODO 3.0.0: Make a tab popover menu selection + console.log('TO IMPLEMENT'); + + // If only 1 editbale case log, open this one + // Else, open a popover menu to choose one + } + }, + _onCancelledEntryForm: function() + { + this._HideCaseLogsEntryForms(); + }, _onCaseLogClosedMessageClick: function(oEntryElem) { this._OpenMessage(oEntryElem); @@ -215,19 +268,91 @@ $(function() }); }, // - Helpers on tabs + /** + * @returns {Object} Data on the active tab: + * + * - Its type + * - Optionally, its attribute code + * - Optionally, its rank + * @private + */ + _GetActiveTabData: function() + { + const oTabTogglerElem = this.element.find(this.js_selectors.tab_toggler + '.' + this.css_classes.is_active); + + // Consistency check + if(oTabTogglerElem.length === 0) { + throw 'No active tab, this should not be possible.'; + } + + const sTabType = oTabTogglerElem.attr('data-tab-type'); + let oTabData = { + type: sTabType, + }; + + // Additional data for caselog tab + if (this.enums.tab_types.caselog === sTabType) { + oTabData.att_code = oTabTogglerElem.attr('data-caselog-attribute-code'); + oTabData.rank = oTabTogglerElem.attr('data-caselog-rank'); + } + + return oTabData; + }, + /** + * @returns {Object} Active tab toolbar jQuery element + * @private + */ + _GetActiveTabToolbarElement: function() + { + const oActiveTabData = this._GetActiveTabData(); + let sSelector = this.js_selectors.tab_toolbar + '[data-tab-type="' + oActiveTabData.type + '"]'; + + if (this.enums.tab_types.caselog === oActiveTabData.type) { + sSelector += '[data-caselog-attribute-code="' + oActiveTabData.att_code + '"]'; + } + + return this.element.find(sSelector); + }, _ShowCaseLogTab: function(sCaseLogAttCode) { // Show only entries from this case log - this._HideAllEntries(); - this.element.find(this.js_selectors.entry+'[data-entry-caselog-attribute-code="'+sCaseLogAttCode+'"]').removeClass(this.css_classes.is_hidden); - this._UpdateEntryGroupsVisibility(); + // this._HideAllEntries(); + //this.element.find(this.js_selectors.entry+'[data-entry-caselog-attribute-code="'+sCaseLogAttCode+'"]').removeClass(this.css_classes.is_hidden); + this._ShowAllEntries(); + this._ApplyEntriesFilters(); }, _ShowActivityTab: function() { // Show all entries but regarding the current filters - this._OpenAllMessages(); + //this._OpenAllMessages(); this._ShowAllEntries(); - this._ApplyEntryFilters(); + this._ApplyEntriesFilters(); + }, + /** + * Show all case logs entry forms. + * Event is triggered on the corresponding elements. + * + * @return {void} + * @private + */ + _ShowCaseLogsEntryForms: function() + { + this.element.find(this.js_selectors.caselog_entry_form).trigger('show_form.caselog_entry_form.itop'); + this.element.find(this.js_selectors.compose_button).addClass(this.css_classes.is_hidden); + }, + /** + * Hide all case logs entry forms. + * Event is triggered on the corresponding elements. + * + * @return {void} + * @private + */ + _HideCaseLogsEntryForms: function() + { + this.element.find(this.js_selectors.caselog_entry_form).trigger('hide_form.caselog_entry_form.itop'); + this.element.find(this.js_selectors.compose_button).removeClass(this.css_classes.is_hidden); + + // TODO 3.0.0: Release lock }, // - Helpers on messages _OpenMessage: function(oEntryElem) @@ -250,12 +375,12 @@ $(function() this.element.find(this.js_selectors.entry + sExtraSelector)[sCallback](this.css_classes.is_closed); }, // - Helpers on entries - _ApplyEntryFilters: function() + _ApplyEntriesFilters: function() { const me = this; // For each filter, show/hide corresponding entries - this.element.find(this.js_selectors.activity_filter).each(function(){ + this._GetActiveTabToolbarElement().find(this.js_selectors.activity_filter).each(function(){ const aTargetEntryTypes = $(this).attr('data-target-entry-types').split(' '); const sCallbackMethod = ($(this).prop('checked')) ? '_ShowEntries' : '_HideEntries'; @@ -270,6 +395,8 @@ $(function() $(this).find(me.js_selectors.entry_medallion).removeClass(me.css_classes.is_visible); $(this).find(me.js_selectors.entry + ':visible:last').find(me.js_selectors.entry_medallion).addClass(me.css_classes.is_visible); }); + + this._UpdateEntryGroupsVisibility(); }, _ShowAllEntries: function() { diff --git a/js/layouts/activity-panel/caselog-entry-form.js b/js/layouts/activity-panel/caselog-entry-form.js index 9ece04a2f..b87a4acc5 100644 --- a/js/layouts/activity-panel/caselog-entry-form.js +++ b/js/layouts/activity-panel/caselog-entry-form.js @@ -24,7 +24,6 @@ $(function() { options: { submit_mode: 'autonomous', - target_type: null, text_input_id: '', }, css_classes: @@ -38,7 +37,6 @@ $(function() { activity_panel: '[data-role="ibo-activity-panel"]', activity_panel_toolbar: '[data-role="ibo-activity-panel--tab-toolbar"]', form: '[data-role="ibo-caselog-entry-form"]', // Any caselog entry form - toggler: '[data-role="ibo-activity-panel--add-caselog-entry-button"]', main_actions: '[data-role="ibo-caselog-entry-form--action-buttons--main-actions"]', cancel_button: '[data-role="ibo-caselog-entry-form--action-buttons--main-actions"] [data-role="ibo-button"][name="cancel"]', send_button: '[data-role="ibo-caselog-entry-form--action-buttons--main-actions"] [data-role="ibo-button"][name="send"]', @@ -50,11 +48,6 @@ $(function() { { autonomous: 'autonomous', bridged: 'bridged', - }, - target_type: - { - caselog: 'caselog', - activity: 'activity', } }, @@ -76,19 +69,10 @@ $(function() { } this._bindEvents(); - - // TODO 3.0.0: Modify PopoverMenu so we can pass it the ID of the block triggering the open/close - $(this.element).find(this.js_selectors.send_choices_picker).popover_menu({toggler: this.js_selectors.send_button}); - }, _bindEvents: function() { let me = this; - // Composer toggle - this.element.closest(this.js_selectors.activity_panel).find(this.js_selectors.toggler).on('click', function(oEvent){ - me._ShowEntryForm(); - }); - // Enable send button only when content CKEDITOR.on('instanceReady', function(oEvent){ // Handle only the current CKEditor instance @@ -106,22 +90,23 @@ $(function() { // Form buttons this.element.find(this.js_selectors.cancel_button).on('click', function(oEvent){ - me._HideEntryForm(); + me.element.trigger('cancelled_form.caselog_entry_form.itop'); }); this.element.find(this.js_selectors.send_button).on('click', function(oEvent){ - // Avoid form being submitted - oEvent.preventDefault(); + // TODO 3.0.0: To be refactored next + // // Avoid form being submitted + // oEvent.preventDefault(); + // + // let sCaselogAttCode = me.element.closest(me.js_selectors.activity_panel_toolbar).attr('data-caselog-attribute-code'); + // me._SubmitEntryToCaselog(me._GetInputData(), sCaselogAttCode); + }); - if(me.options.target_type === 'caselog') - { - let sCaselogAttCode = me.element.closest(me.js_selectors.activity_panel_toolbar).attr('data-caselog-attribute-code'); - me._SubmitEntryToCaselog(me._GetInputData(), sCaselogAttCode); - } - else - { - // TODO 3.0.0: Modify public methods of popover_menu to open/close to match other widgets naming conventions - me.element.find(me.js_selectors.send_choices_picker).popover_menu('openPopup'); - } + // Form show/hide + this.element.on('show_form.caselog_entry_form.itop', function(){ + me._ShowEntryForm(); + }); + this.element.on('hide_form.caselog_entry_form.itop', function(){ + me._HideEntryForm(); }); // Caselog selection @@ -165,11 +150,11 @@ $(function() { // - Form _ShowEntryForm: function () { this.element.closest(this.js_selectors.activity_panel).find(this.js_selectors.form).removeClass(this.css_classes.is_closed); - this.element.closest(this.js_selectors.activity_panel).find(this.js_selectors.toggler).addClass(this.css_classes.is_hidden); }, _HideEntryForm: function () { this.element.closest(this.js_selectors.activity_panel).find(this.js_selectors.form).addClass(this.css_classes.is_closed); - this.element.closest(this.js_selectors.activity_panel).find(this.js_selectors.toggler).removeClass(this.css_classes.is_hidden); + + // TODO 3.0.0: This should also clear the form (input, lock, send button, ...) }, // - Bridged form input /** diff --git a/sources/application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryForm.php b/sources/application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryForm.php index ea60792b6..0dcf2b3ea 100644 --- a/sources/application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryForm.php +++ b/sources/application/UI/Base/Layout/ActivityPanel/CaseLogEntryForm/CaseLogEntryForm.php @@ -30,26 +30,15 @@ class CaseLogEntryForm extends UIContentBlock 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\Base\Component\Input\RichText\RichText $oTextInput The main input to write a case log entry */ protected $oTextInput; /** @var \Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu Menu for possible options on the send button */ @@ -68,7 +57,6 @@ class CaseLogEntryForm extends UIContentBlock { parent::__construct($sId); $this->sSubmitMode = static::DEFAULT_SUBMIT_MODE; - $this->sContainerTabType = static::DEFAULT_CONTAINER_TAB_TYPE; $this->SetTextInput(new RichText()); $this->aMainActionButtons = []; $this->aExtraActionButtons = []; @@ -137,28 +125,6 @@ class CaseLogEntryForm extends UIContentBlock 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\Base\Component\Input\RichText\RichText */ diff --git a/templates/base/layouts/activity-panel/caselog-entry-form/layout.html.twig b/templates/base/layouts/activity-panel/caselog-entry-form/layout.html.twig index 3db48e29f..1df849fd2 100644 --- a/templates/base/layouts/activity-panel/caselog-entry-form/layout.html.twig +++ b/templates/base/layouts/activity-panel/caselog-entry-form/layout.html.twig @@ -2,7 +2,6 @@ class="ibo-caselog-entry-form {% if oUIBlock.IsSubmitAutonomous %}ibo-is-closed{% endif %}" data-role="ibo-caselog-entry-form" data-submit-mode="{{ oUIBlock.GetSubmitMode() }}" - data-container-tab-type="{{ oUIBlock.GetContainerTabType() }}" method="post">