@@ -14,10 +14,11 @@ import Icon from '../common/icon/icon.js';
1414import PaginationInfo from '../common/pagination/pagination.info.js' ;
1515
1616import deepClone from '../common/helpers/deep.clone.helper.js' ;
17+ import { createCssClassNames } from '../common/helpers/css.class.names' ;
1718import { updateLocationPriority , loadLocation as loadLocationService } from './services/sub.items.service' ;
1819import { bulkAddLocations , bulkDeleteItems , bulkHideLocations , bulkUnhideLocations , bulkMoveLocations } from './services/bulk.service.js' ;
1920
20- const { Translator, ibexa } = window ;
21+ const { Translator, ibexa, Popper , document } = window ;
2122
2223export const ASCENDING_SORT_ORDER = 'ascending' ;
2324const DESCENDING_SORT_ORDER = 'descending' ;
@@ -93,9 +94,17 @@ export default class SubItemsModule extends Component {
9394 this . resizeSubItems = this . resizeSubItems . bind ( this ) ;
9495 this . setColumnsVisibilityInLocalStorage = this . setColumnsVisibilityInLocalStorage . bind ( this ) ;
9596 this . toggleColumnVisibility = this . toggleColumnVisibility . bind ( this ) ;
97+ this . adaptHeaderActions = this . adaptHeaderActions . bind ( this ) ;
98+ this . showMorePanel = this . showMorePanel . bind ( this ) ;
99+ this . hideMorePanel = this . hideMorePanel . bind ( this ) ;
100+ this . renderExtraActions = this . renderExtraActions . bind ( this ) ;
101+ this . renderActionBtnWrapper = this . renderActionBtnWrapper . bind ( this ) ;
96102
97103 this . _refListViewWrapper = React . createRef ( ) ;
98104 this . _refMainContainerWrapper = React . createRef ( ) ;
105+ this . _refAdaptiveItemsWrapper = React . createRef ( ) ;
106+ this . _refAdaptiveItemMoreBtn = React . createRef ( ) ;
107+ this . _refAdaptiveItemMorePanel = React . createRef ( ) ;
99108 this . bulkActionModalContainer = null ;
100109 this . udwContainer = null ;
101110 this . adminUiConfig = getAdminUiConfig ( ) ;
@@ -121,6 +130,8 @@ export default class SubItemsModule extends Component {
121130 sortOrder : sortClauseData . order ,
122131 subItemsWidth : this . calculateSubItemsWidth ( ) ,
123132 columnsVisibility : this . getColumnsVisibilityFromLocalStorage ( ) ,
133+ morePanelVisible : false ,
134+ morePanelVisibleItemsIndexes : [ ] ,
124135 } ;
125136 }
126137
@@ -146,6 +157,15 @@ export default class SubItemsModule extends Component {
146157 if ( ! this . state . activePageItems ) {
147158 this . loadPage ( 0 ) ;
148159 }
160+
161+ this . adaptHeaderActions ( ) ;
162+
163+ const subitemsTab = this . _refMainContainerWrapper . current . closest ( '.ibexa-tab-content__pane' ) ;
164+ const subitemsNavTab = document . querySelector ( `.ibexa-tabs__link[href="#${ subitemsTab . id } "]` ) ;
165+
166+ subitemsNavTab . addEventListener ( 'shown.bs.tab' , ( ) => {
167+ this . popperInstance . forceUpdate ( ) ;
168+ } ) ;
149169 }
150170
151171 componentDidUpdate ( ) {
@@ -180,6 +200,7 @@ export default class SubItemsModule extends Component {
180200 const { subItemsWidth } = this . state ;
181201
182202 if ( calculatedWidth !== subItemsWidth ) {
203+ this . popperInstance . forceUpdate ( ) ;
183204 this . setState ( { subItemsWidth : calculatedWidth } ) ;
184205 }
185206 }
@@ -1120,7 +1141,7 @@ export default class SubItemsModule extends Component {
11201141 renderExtraActions ( action , index ) {
11211142 const Action = action . component ;
11221143
1123- return < Action key = { index } className = "m-sub-items__action" { ...action . attrs } /> ;
1144+ return this . renderActionBtnWrapper ( < Action { ...action . attrs } /> , 'm-sub-items__action' , { key : index } ) ;
11241145 }
11251146
11261147 /**
@@ -1169,34 +1190,46 @@ export default class SubItemsModule extends Component {
11691190 ) ;
11701191 }
11711192
1193+ renderActionBtnWrapper ( btn , extraClasses = '' , extraProps = { } ) {
1194+ return (
1195+ < div className = { `ibexa-adaptive-items__item ${ extraClasses } ` } { ...extraProps } >
1196+ { btn }
1197+ </ div >
1198+ ) ;
1199+ }
1200+
11721201 renderBulkMoveBtn ( disabled ) {
11731202 const label = Translator . trans ( /*@Desc ("Move")*/ 'move_btn.label' , { } , 'ibexa_sub_items' ) ;
11741203
1175- return < ActionButton disabled = { disabled } onClick = { this . onMoveBtnClick } label = { label } type = "move" /> ;
1204+ return this . renderActionBtnWrapper ( < ActionButton disabled = { disabled } onClick = { this . onMoveBtnClick } label = { label } type = "move" /> ) ;
11761205 }
11771206
11781207 renderBulkAddLocationBtn ( disabled ) {
11791208 const label = Translator . trans ( /*@Desc ("Add Locations")*/ 'add_locations_btn.label' , { } , 'ibexa_sub_items' ) ;
11801209
1181- return < ActionButton disabled = { disabled } onClick = { this . onAddLocationsBtnClick } label = { label } type = "create-location" /> ;
1210+ return this . renderActionBtnWrapper (
1211+ < ActionButton disabled = { disabled } onClick = { this . onAddLocationsBtnClick } label = { label } type = "create-location" /> ,
1212+ ) ;
11821213 }
11831214
11841215 renderBulkHideBtn ( disabled ) {
11851216 const label = Translator . trans ( /*@Desc ("Hide")*/ 'hide_locations_btn.label' , { } , 'ibexa_sub_items' ) ;
11861217
1187- return < ActionButton disabled = { disabled } onClick = { this . onHideBtnClick } label = { label } type = "hide" /> ;
1218+ return this . renderActionBtnWrapper ( < ActionButton disabled = { disabled } onClick = { this . onHideBtnClick } label = { label } type = "hide" /> ) ;
11881219 }
11891220
11901221 renderBulkUnhideBtn ( disabled ) {
11911222 const label = Translator . trans ( /*@Desc ("Reveal")*/ 'unhide_locations_btn.label' , { } , 'ibexa_sub_items' ) ;
11921223
1193- return < ActionButton disabled = { disabled } onClick = { this . onUnhideBtnClick } label = { label } type = "reveal" /> ;
1224+ return this . renderActionBtnWrapper (
1225+ < ActionButton disabled = { disabled } onClick = { this . onUnhideBtnClick } label = { label } type = "reveal" /> ,
1226+ ) ;
11941227 }
11951228
11961229 renderBulkDeleteBtn ( disabled ) {
11971230 const label = Translator . trans ( /*@Desc ("Delete")*/ 'trash_btn.label' , { } , 'ibexa_sub_items' ) ;
11981231
1199- return < ActionButton disabled = { disabled } onClick = { this . onDeleteBtnClick } label = { label } type = "trash" /> ;
1232+ return this . renderActionBtnWrapper ( < ActionButton disabled = { disabled } onClick = { this . onDeleteBtnClick } label = { label } type = "trash" /> ) ;
12001233 }
12011234
12021235 renderSpinner ( ) {
@@ -1327,6 +1360,86 @@ export default class SubItemsModule extends Component {
13271360 ) ;
13281361 }
13291362
1363+ hideMorePanel ( ) {
1364+ this . setState (
1365+ ( ) => ( { morePanelVisible : false } ) ,
1366+ ( ) => {
1367+ setTimeout ( ( ) => {
1368+ document . body . removeEventListener ( 'click' , this . hideMorePanel , false ) ;
1369+ } , 1 ) ;
1370+ } ,
1371+ ) ;
1372+ }
1373+
1374+ showMorePanel ( ) {
1375+ this . setState (
1376+ ( ) => ( { morePanelVisible : true } ) ,
1377+ ( ) => {
1378+ setTimeout ( ( ) => {
1379+ document . body . addEventListener ( 'click' , this . hideMorePanel , false ) ;
1380+ } , 1 ) ;
1381+ } ,
1382+ ) ;
1383+ }
1384+
1385+ renderMoreBtn ( actionBtns ) {
1386+ const panelClasses = createCssClassNames ( {
1387+ 'm-sub-items__adaptive-items-popup' : true ,
1388+ 'ibexa-popup-menu' : true ,
1389+ 'ibexa-popup-menu--hidden' : ! this . state . morePanelVisible ,
1390+ } ) ;
1391+ const filteredActionBtns = actionBtns . filter ( ( el , index ) => {
1392+ return this . state . morePanelVisibleItemsIndexes . includes ( index ) ;
1393+ } ) ;
1394+
1395+ return [
1396+ this . renderActionBtnWrapper (
1397+ < ActionButton disabled = { false } onClick = { this . showMorePanel } type = "options" /> ,
1398+ 'ibexa-adaptive-items__item--selector' ,
1399+ { ref : this . _refAdaptiveItemMoreBtn } ,
1400+ ) ,
1401+ ReactDOM . createPortal (
1402+ < div className = { panelClasses } ref = { this . _refAdaptiveItemMorePanel } >
1403+ { filteredActionBtns }
1404+ </ div > ,
1405+ document . body ,
1406+ ) ,
1407+ ] ;
1408+ }
1409+
1410+ adaptHeaderActions ( ) {
1411+ this . popperInstance = new Popper . createPopper ( this . _refAdaptiveItemMoreBtn . current , this . _refAdaptiveItemMorePanel . current , {
1412+ placement : 'bottom-end' ,
1413+ modifiers : [
1414+ {
1415+ name : 'flip' ,
1416+ enabled : true ,
1417+ options : {
1418+ fallbackPlacements : [ 'top-end' ] ,
1419+ boundary : document . body ,
1420+ } ,
1421+ } ,
1422+ ] ,
1423+ } ) ;
1424+
1425+ this . adaptiveItems = new ibexa . core . AdaptiveItems ( {
1426+ itemHiddenClass : 'ibexa-adaptive-items__item--hidden' ,
1427+ container : this . _refAdaptiveItemsWrapper . current ,
1428+ getActiveItem : ( ) => null ,
1429+ onAdapted : ( visibleItems , hiddenItems ) => {
1430+ const adaptiveItemsIterableArr = [ ...this . adaptiveItems . items ] ;
1431+
1432+ const visibleItemsInPanelIndexes = [ ...hiddenItems ] . map ( ( hiddenItem ) => {
1433+ return adaptiveItemsIterableArr . indexOf ( hiddenItem ) ;
1434+ } ) ;
1435+
1436+ this . setState ( ( ) => ( { morePanelVisibleItemsIndexes : visibleItemsInPanelIndexes } ) ) ;
1437+ } ,
1438+ } ) ;
1439+
1440+ this . adaptiveItems . init ( ) ;
1441+ }
1442+
13301443 render ( ) {
13311444 const listTitle = Translator . trans ( /*@Desc ("Sub-items")*/ 'items_list.title' , { } , 'ibexa_sub_items' ) ;
13321445 const { selectedItems, activeView, totalCount, isDuringBulkOperation, activePageItems, subItemsWidth, columnsVisibility } =
@@ -1335,7 +1448,6 @@ export default class SubItemsModule extends Component {
13351448 const isTableViewActive = activeView === VIEW_MODE_TABLE ;
13361449 const pageLoaded = ! ! activePageItems ;
13371450 const bulkBtnDisabled = nothingSelected || ! isTableViewActive || ! pageLoaded ;
1338-
13391451 let bulkHideBtnDisabled = true ;
13401452 let bulkUnhideBtnDisabled = true ;
13411453 let listClassName = 'm-sub-items__list' ;
@@ -1351,20 +1463,30 @@ export default class SubItemsModule extends Component {
13511463 bulkUnhideBtnDisabled = ! selectedItemsValues . some ( ( item ) => ! ! item . hidden ) ;
13521464 }
13531465
1466+ const actionBtns = [
1467+ ...this . props . extraActions . map ( this . renderExtraActions ) ,
1468+ this . renderBulkMoveBtn ( bulkBtnDisabled ) ,
1469+ this . renderBulkAddLocationBtn ( bulkBtnDisabled ) ,
1470+ this . renderBulkHideBtn ( bulkHideBtnDisabled ) ,
1471+ this . renderBulkUnhideBtn ( bulkUnhideBtnDisabled ) ,
1472+ this . renderBulkDeleteBtn ( bulkBtnDisabled ) ,
1473+ ] ;
1474+
13541475 return (
13551476 < div ref = { this . _refMainContainerWrapper } >
13561477 < div className = "m-sub-items" style = { { width : `${ subItemsWidth } px` } } >
13571478 < div className = "ibexa-table-header " >
13581479 < div className = "ibexa-table-header__headline" >
13591480 { listTitle } ({ this . state . totalCount } )
13601481 </ div >
1482+ < div
1483+ className = "ibexa-table-header__actions ibexa-table-header__actions--adaptive ibexa-adaptive-items"
1484+ ref = { this . _refAdaptiveItemsWrapper }
1485+ >
1486+ { actionBtns }
1487+ { this . renderMoreBtn ( actionBtns ) }
1488+ </ div >
13611489 < div className = "ibexa-table-header__actions" >
1362- { this . props . extraActions . map ( this . renderExtraActions ) }
1363- { this . renderBulkMoveBtn ( bulkBtnDisabled ) }
1364- { this . renderBulkAddLocationBtn ( bulkBtnDisabled ) }
1365- { this . renderBulkHideBtn ( bulkHideBtnDisabled ) }
1366- { this . renderBulkUnhideBtn ( bulkUnhideBtnDisabled ) }
1367- { this . renderBulkDeleteBtn ( bulkBtnDisabled ) }
13681490 < ViewColumnsTogglerComponent
13691491 columnsVisibility = { this . filterColumnsVisibility ( columnsVisibility ) }
13701492 toggleColumnVisibility = { this . toggleColumnVisibility }
0 commit comments