import * as React from 'react' ; import { Dispatch } from 'redux' ; import { connect } from 'react-redux' ; import { ASSET_ACTIONS , ASSET_LIST_STYLE , ASSET_SORT_FIELD , IAssetItem , IAssetSearchParams , ISetItem , LIST_ACTION , SET_STATE , SORT_ORDER , } from '../interfaces' ; import { samsApi , superdeskApi } from '../apis' ; import { IApplicationState } from '../store' ; import { isFilterPanelOpen } from '../store/workspace/selectors' ; import { getAssetListStyle , getAssetListTotal , getAssetSearchParams , getAssetSetFilter , getSelectedAssetIds , getSelectedAssetItems , } from '../store/assets/selectors' ; import { getActiveSets , getDisabledSets , getAvailableSetsForDesk } from '../store/sets/selectors' ; import { toggleFilterPanelState } from '../store/workspace/actions' ; import { closeMultiActionBar , deleteAssets , toggleAssetListStyle , updateAssetSearchParamsAndListItems , } from '../store/assets/actions' ; import { Badge , Button , ButtonGroup , Dropdown , IconButton , NavButton , SubNav , Tooltip , } from 'superdesk-ui-framework/react' ; import { IMenuGroup } from 'superdesk-ui-framework/react/components/Dropdown' ; import { ContentBar , SearchBar , SubNavSpacer } from '../ui' ; import { showManageSetsModal } from './sets/manageSetsModal' ; import { AssetTypeFilterButtons } from './assets/assetTypeFilterButtons' ; import { getAssetListSortFieldText } from '../utils/ui' ; import { getBulkActions } from '../utils/assets' ; interface IProps { filterPanelOpen : boolean ; totalAssets : number ; listStyle : ASSET_LIST_STYLE ; searchParams : IAssetSearchParams ; availableSetIds : Array < ISetItem [ '_id' ] > ; activeSets : Array < ISetItem > ; disabledSets : Array < ISetItem > ; currentSet ? : ISetItem ; selectedAssetIds : Array < string > | [ ] ; selectedAssets : Array < IAssetItem > ; toggleFilterPanel ( ) : void ; toggleListStyle ( ) : void ; closeMultiActionBar ( ) : void ; updateAssetSearchParamsAndListItems ( params , listAction ) : void ; deleteMultipleAssets ( ) : void ; } const mapStateToProps = ( state ) => ( { filterPanelOpen : isFilterPanelOpen ( state ) , totalAssets : getAssetListTotal ( state ) , listStyle : getAssetListStyle ( state ) , searchParams : getAssetSearchParams ( state ) , activeSets : getActiveSets ( state ) , disabledSets : getDisabledSets ( state ) , currentSet : getAssetSetFilter ( state ) , selectedAssetIds : getSelectedAssetIds ( state ) , selectedAssets : getSelectedAssetItems ( state ) , availableSetIds : getAvailableSetsForDesk ( state ) , } ) ; const mapDispatchToProps = ( dispatch ) => ( { toggleFilterPanel : ( ) => { dispatch < any > ( toggleFilterPanelState ( ) ) ; } , toggleListStyle : ( ) => { dispatch < any > ( toggleAssetListStyle ( ) ) ; } , updateAssetSearchParamsAndListItems : ( params , listAction ) => { dispatch < any > ( updateAssetSearchParamsAndListItems ( params , listAction ) ) ; } , closeMultiActionBar : ( ) => dispatch ( closeMultiActionBar ( ) ) , deleteMultipleAssets : ( ) => dispatch < any > ( deleteAssets ( ) ) , } ) ; export function downloadCompressedBinary ( asset_ids ) { samsApi . assets . getCompressedBinary ( asset_ids ) ; } export class WorkspaceSubnavComponent extends React . PureComponent < IProps > { subNavMenuActions : Array < IMenuGroup > ; sortFieldOptions : Array < IMenuGroup > ; constructor ( props ) { super ( props ) ; this . subNavMenuActions = this . getSubNavMenuActions ( ) ; this . sortFieldOptions = this . getSortFieldOptions ( ) ; this . toggleSortOrder = this . toggleSortOrder . bind ( this ) ; this . setSearchParamText = this . setSearchParamText . bind ( this ) ; this . onDownloadMultipleAssetsCompressedBinary = this . onDownloadMultipleAssetsCompressedBinary . bind ( this ) ; this . onCloseMultiActionBar = this . onCloseMultiActionBar . bind ( this ) ; this . onDeleteMultipleAssets = this . onDeleteMultipleAssets . bind ( this ) ; } getSubNavMenuActions ( ) { const { gettext } = superdeskApi . localization ; const actions = [ ] ; if ( superdeskApi . privileges . hasPrivilege ( 'sams_manage' ) ) { actions . push ( { label : gettext ( 'Manage Sets' ) , icon : 'folder-open' , onSelect : showManageSetsModal , } ) ; } return actions . length === 0 ? [ ] : [ { type : 'group' , label : gettext ( 'Actions' ) , items : [ 'divider' , ... actions , ] , } ] ; } getSortFieldOptions ( ) { const { gettext } = superdeskApi . localization ; return [ { type : 'group' , label : gettext ( 'Sort By' ) , items : [ { label : gettext ( 'Name' ) , onSelect : ( ) => this . setSortField ( ASSET_SORT_FIELD . NAME ) , } , { label : gettext ( 'Filename' ) , onSelect : ( ) => this . setSortField ( ASSET_SORT_FIELD . FILENAME ) , } , { label : gettext ( 'Created' ) , onSelect : ( ) => this . setSortField ( ASSET_SORT_FIELD . CREATED ) , } , { label : gettext ( 'Updated' ) , onSelect : ( ) => this . setSortField ( ASSET_SORT_FIELD . UPDATED ) , } , { label : gettext ( 'Size' ) , onSelect : ( ) => this . setSortField ( ASSET_SORT_FIELD . SIZE ) , } ] , } ] ; } getMenuItems ( ) { const { gettext } = superdeskApi . localization ; const filterActiveSets = ( set ) => ( this . props . availableSetIds . includes ( set . _id ) ) ; const activeSets = this . props . activeSets . filter ( filterActiveSets ) . map ( ( set ) => ( { label : set . name , onSelect : ( ) => this . setSearchParamSetId ( set . _id ) , } ) ) ; const disabledSets = this . props . disabledSets . filter ( filterActiveSets ) . map ( ( set ) => ( { label : set . name + ' ' + gettext ( '(disabled)' ) , icon : 'lock' , onSelect : ( ) => this . setSearchParamSetId ( set . _id ) , } ) ) ; return [ { type : 'group' , label : gettext ( 'Sets' ) , items : [ 'divider' , { label : gettext ( 'All Sets' ) , onSelect : ( ) => this . setSearchParamSetId ( ) , } , ... activeSets , ... disabledSets , ] , } ] ; } toggleSortOrder ( ) { const sortOrder = this . props . searchParams . sortOrder === SORT_ORDER . ASCENDING ? SORT_ORDER . DESCENDING : SORT_ORDER . ASCENDING ; this . props . updateAssetSearchParamsAndListItems ( { sortOrder : sortOrder } , LIST_ACTION . REPLACE ) ; } setSortField ( field ) { this . props . updateAssetSearchParamsAndListItems ( { sortField : field } , LIST_ACTION . REPLACE ) ; } setSearchParamSetId ( setId ? ) { this . props . updateAssetSearchParamsAndListItems ( { setId : setId } , LIST_ACTION . REPLACE ) ; } setSearchParamText ( searchText ? ) { this . props . updateAssetSearchParamsAndListItems ( { textSearch : searchText } , LIST_ACTION . REPLACE ) ; } onDownloadMultipleAssetsCompressedBinary ( ) { downloadCompressedBinary ( this . props . selectedAssetIds ) ; } onDeleteMultipleAssets ( ) { this . props . deleteMultipleAssets ( ) ; } onCloseMultiActionBar ( ) { this . props . closeMultiActionBar ( ) ; } render ( ) { const { gettext , gettextPlural } = superdeskApi . localization ; const { numberToString } = superdeskApi . helpers ; const items = this . getMenuItems ( ) ; const buttonLabel = this . props . currentSet ?. name ?? gettext ( 'All Sets' ) ; const buttonIcon = this . props . currentSet ?. state === SET_STATE . DISABLED ? 'lock' : undefined ; const sortFieldText = getAssetListSortFieldText ( this . props . searchParams . sortField ) ; return ( < React . Fragment > { ( this . props . selectedAssetIds ?. length !== 0 ) ? ( < SubNav zIndex = { 2 } > < div className = "multi-action-bar" > < button className = "toggle" onClick = { this . props . closeMultiActionBar } > < i className = "icon-chevron-up-thin" / > < /button> < button className = "btn" onClick = { this . props . closeMultiActionBar } > { gettext ( 'cancel' ) } < /button> < span id = "multi-select-count" > { gettextPlural ( this . props . selectedAssetIds ?. length , '{{count}} item selected' , '{{count}} items selected' , { count : this . props . selectedAssetIds ?. length } ) } < /span> < div className = "pull-right" > { getBulkActions ( this . props . selectedAssets , [ { action : ASSET_ACTIONS . DELETE , onSelect : this . onDeleteMultipleAssets , } , { action : ASSET_ACTIONS . DOWNLOAD , onSelect : this . onDownloadMultipleAssetsCompressedBinary , } ] ) . map ( ( action ) => ( < Tooltip key = { action . id } text = { action . label } flow = "down" > < NavButton icon = { action . icon } text = { action . label } onClick = { action . onSelect } / > < /Tooltip>))} < /div> < /div> < /SubNav>) : (<SubNav zIndex={2}> < ButtonGroup align = "inline" > < Dropdown items = { items } > < button className = "sd-navbtn sd-navbtn--textual" data - sd - tooltip = { gettext ( 'Change Set filter' ) } data - flow = "right" > { ! buttonIcon ? null : ( < i className = { `icon-${ buttonIcon }` } / > ) } < span className = "sd-navbtn__text" > { buttonLabel } < /span> < /button> < /Dropdown> < /ButtonGroup> < SearchBar placeholder = { gettext ( 'Search Assets' ) } type = "expanded" focused = { true } onSubmit = { this . setSearchParamText } initialValue = { this . props . searchParams . textSearch } / > < ButtonGroup align = "right" > { this . subNavMenuActions . length === 0 ? null : ( < Dropdown items = { this . subNavMenuActions } > < button className = "sd-navbtn" data - sd - tooltip = { gettext ( 'Manage SAMS' ) } data - flow = "down" > < i className = "icon-dots-vertical" / > < /button> < /Dropdown>)} < Tooltip text = { gettext ( 'Upload New Asset(s)' ) } flow = "left" > < Button type = "primary" icon = "upload" text = "plus-large" shape = "round" iconOnly = { true } onClick = { ( ) => samsApi . assets . showUploadModal ( ) } /> < /Tooltip> < /ButtonGroup> < /SubNav>)} < SubNav zIndex = { 1 } > < ButtonGroup align = "inline" > < Tooltip text = { gettext ( 'Toggle filters' ) } flow = "right" > < NavButton icon = "filter-large" onClick = { this . props . toggleFilterPanel } type = { this . props . filterPanelOpen === true ? 'primary' : 'default' } / > < /Tooltip> < /ButtonGroup> < AssetTypeFilterButtons / > < ButtonGroup align = "right" > < SubNavSpacer noMargin = { true } /> < ContentBar > < Tooltip text = { gettext ( 'Total Assets: {{ total }}' , { total : this . props . totalAssets } ) } flow = "down" > < span className = "sd-margin-r--1" > < span className = "sd-margin-r--1" > { gettext ( 'Total:' ) } < /span> < Badge text = { numberToString ( this . props . totalAssets ) } / > < /span> < /Tooltip> < Dropdown items = { this . sortFieldOptions } > < button className = "dropdown__toggle dropdown-toggle" data - sd - tooltip = { gettext ( 'Sort by: {{ field }}' , { field : sortFieldText } ) } data - flow = "down" > { sortFieldText } < span className = "dropdown__caret" / > < /button> < /Dropdown> < Tooltip key = { this . props . searchParams . sortOrder } text = { this . props . searchParams . sortOrder === 'ascending' ? gettext ( 'Sort order: Ascending' ) : gettext ( 'Sort order: Descending' ) } flow = "down" > < IconButton ariaValue = { this . props . searchParams . sortOrder } onClick = { this . toggleSortOrder } icon = { this . props . searchParams . sortOrder } / > < /Tooltip> < /ContentBar> < Tooltip key = { this . props . listStyle } text = { this . props . listStyle === 'list' ? gettext ( 'Switch to grid view' ) : gettext ( 'Switch to list view' ) } flow = "left" > < NavButton icon = { this . props . listStyle === ASSET_LIST_STYLE . GRID ? 'list-view' : 'grid-view' } onClick = { this . props . toggleListStyle } / > < /Tooltip> < /ButtonGroup> < /SubNav> < /React.Fragment>); } } export const WorkspaceSubnav = connect ( mapStateToProps , mapDispatchToProps ) ( WorkspaceSubnavComponent ) ;