/** * Created by rburson on 3/30/16. */ import * as React from 'react' import { CvState, CvProps, CvBaseMixin, CvEvent, CvContext, CvViewDesc, CvViewDescProps, CvViewDescCallback, CvActionFiredResult, CvMessage, CvEventType, CvMessageType, CvNavigationResult, CvValueListener } from 'catreact' import {ViewDesc, PaneContext, ViewId, Try, ArrayUtil} from 'catavolt-sdk' import ReactElement = React.ReactElement; export interface CvViewMenuState extends CvState { selectedViewId:ViewId; visible:boolean; } export interface CvViewMenuProps extends CvProps { navigationListeners?:Array<(event:CvEvent)=>void> navTarget?:string; actionListeners?:Array<(event:CvEvent)=>void> paneContext?:PaneContext; viewDescs:Array; openLeft?:boolean; viewSelectionListener?:CvValueListener; viewLoadedListener?:CvValueListener; selectedViewId?:string; } export var CvViewMenuBase = { paneContext: function (nextProps, nextContext):PaneContext { var paneContext:PaneContext = null; if(nextProps && nextProps.paneContext) { paneContext = nextProps.paneContext; } else if(nextContext) { paneContext = this.findPaneContext(nextContext.cvContext.scopeCtx); } else { paneContext = this.props.paneContext || this.findPaneContext(); } return paneContext; }, refresh: function (nextProps, nextContext) { /* * The purpose of this method is to reconcile the selectedView (given as a parameter) * with the server's selectedView */ const paneContext = this.paneContext(nextProps, nextContext); const viewDescs = this.viewDescs(nextProps, nextContext); const selectedView = nextProps && nextProps.selectedViewId ? nextProps.selectedViewId : this.props.selectedViewId; const selectedViewDesc:ViewDesc = ArrayUtil.find(viewDescs, (viewDesc:ViewDesc)=>{ return selectedView == viewDesc.viewId; }); //if state hasn't been set, retrieve from server and set if(!this.state.selectedViewId) { paneContext.getSelectedViewId().onComplete((viewTry: Try) => { if (viewTry.isSuccess) { if (this.isMounted()) { this.setState({selectedViewId: viewTry.success}); } //compare 'requested' view with what the server 'thinks' is the selected view if(selectedViewDesc && selectedViewDesc.viewId != viewTry.success.value) { //try to open the 'requested' view (CvViewDesc as any).openView( selectedViewDesc, paneContext, this.eventRegistry(), this.catavolt(), this.props.actionListeners, [], this.props.navigationListeners, this.props.navTarget, (success:any, error?:any)=>{ if(!error){ this.setState({selectedViewId: new ViewId(selectedViewDesc.viewId)}); this.props.viewLoadedListener && this.props.viewLoadedListener(selectedViewDesc.viewId); } } ); } else { this.props.viewLoadedListener && this.props.viewLoadedListener(viewTry.success.value); } } else { const event: CvEvent = { type: CvEventType.MESSAGE, eventObj: { message: 'Could not get selected view id for ' + paneContext.paneDef.findTitle(), messageObj: viewTry.failure, type: CvMessageType.ERROR } } this.eventRegistry().publish(event, false); } }); } else { this.props.viewLoadedListener && this.props.viewLoadedListener(this.state.selectedViewId.value); } }, viewDescs: function(nextProps, nextContext):Array { if(nextProps && nextProps.viewDescs) { return nextProps.viewDescs; } else { return this.props.viewDescs; } } } /* *************************************************** * Render a Menu *************************************************** */ export var CvDropdownViewMenu = React.createClass({ mixins: [CvBaseMixin, CvViewMenuBase], componentWillMount: function() { if(!this._checkVisibility()) { this.props.viewLoadedListener && this.props.viewLoadedListener('no_view_support'); } }, componentDidMount: function () { if(this.state.visible) { this.refresh(); } }, componentWillReceiveProps: function (nextProps, nextContext) { if(this._checkVisibility(nextProps, nextContext)) { this.refresh(nextProps, nextContext); } }, getDefaultProps: function () { return { paneContext: null, actionListeners: [], navigationListeners: [], navTarget: null, viewDescs: [], openLeft: false, viewSelectionListener: null, viewLoadedListener: null, selectedViewId: null } }, getInitialState: function() { return {selectedViewId: null, visible:true} }, render: function () { if(this.state.visible) { const viewDescs:Array = this.viewDescs(); const selectedViewId:ViewId = this.state.selectedViewId; let buttonText = 'Select View'; if(selectedViewId && selectedViewId.value) { const selectedViewDesc:ViewDesc = ArrayUtil.find(this.viewDescs(), (viewDesc:ViewDesc)=>{ return selectedViewId.value == viewDesc.viewId; }); if(selectedViewDesc) { buttonText = selectedViewDesc.name; } } const itemProps:CvViewDescProps = { paneContext: this.props.paneContext, actionListeners: this.props.actionListeners, navigationListeners: this.props.navigationListeners, navTarget: this.props.navTarget, catavolt: this.props.catavolt, eventRegistry: this.props.eventRegistry }; let viewItemClassName = "dropdown-menu cv-dropdown-menu"; if (this.props.openLeft) viewItemClassName += ' dropdown-menu-right'; const itemRenderer = (cvContext:CvContext, callback:CvViewDescCallback)=> { const viewDesc:ViewDesc = cvContext.scopeCtx.scopeObj; return
  • { if(selectedViewId && (selectedViewId.value != viewDesc.viewId)) { callback.openView((success:any, error?:any)=>{ if(!error){ this.setState({selectedViewId: new ViewId(viewDesc.viewId)}); this.props.viewSelectionListener && this.props.viewSelectionListener(viewDesc.viewId); } }); }}}>{viewDesc.name}
  • }; return (
      {viewDescs.map((viewDesc:ViewDesc)=>{ return })}
    ); } else { return null; } }, _checkVisibility: function(nextProps, nextContext):boolean { const viewDescs:Array = this.viewDescs(nextProps, nextContext); if(!this.catavolt().isFeatureSetAvailable("View_Support") || !viewDescs || viewDescs.length < 2) { if(this.state.visible) { this.setState({visible: false}); } return false; } else { if(!this.state.visible) { this.setState({visible:true}); } return true; } } });