diff options
author | ARULNA <arul.nambi@amdocs.com> | 2017-06-02 16:27:25 -0400 |
---|---|---|
committer | ARULNA <arul.nambi@amdocs.com> | 2017-06-02 16:33:14 -0400 |
commit | ca007e933bcd9f63aa77801656ed9dd4142c432c (patch) | |
tree | ce97ed9df8c4fe48a524f0dc1365ad28acef7c46 /src/generic-components/componentManager | |
parent | 42b788b852f0604748828e9e325e4a0f01152c75 (diff) |
Initial coomit for AAI-UI(sparky-fe)
Change-Id: I9f8482824a52bac431c100939899e760c0fa4fdb
Signed-off-by: ARULNA <arul.nambi@amdocs.com>
Diffstat (limited to 'src/generic-components/componentManager')
3 files changed, 459 insertions, 0 deletions
diff --git a/src/generic-components/componentManager/ComponentManager.jsx b/src/generic-components/componentManager/ComponentManager.jsx new file mode 100644 index 0000000..c1e95a4 --- /dev/null +++ b/src/generic-components/componentManager/ComponentManager.jsx @@ -0,0 +1,311 @@ +/* + * ============LICENSE_START=================================================== + * SPARKY (AAI UI service) + * ============================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React, {Component} from 'react'; + +import ComponentManagerContainer from + 'generic-components/componentManager/ComponentManagerContainer.jsx'; +import { + MIN_PANEL_WIDTH, + MIN_PANEL_HEIGHT, + MAX_PANEL_WIDTH, + EDIT_ICON, + LAYOUT_STATIC +} from 'generic-components/componentManager/ComponentManagerConstants.js'; + +var widthProvider = require('react-grid-layout').WidthProvider; +var ReactGridLayout = require('react-grid-layout'); +ReactGridLayout = widthProvider(ReactGridLayout); + +export default class ComponentManager extends Component { + constructor(props) { + super(props); + + if (props.layoutType === LAYOUT_STATIC && + Object.keys(props.layoutFormat).length > 0) { + this.state = { + layout: props.layoutFormat.layout, + panels: props.layoutFormat.panels, + containers: props.layoutFormat.containers + }; + } else { + this.state = { + layout: [], + panels: [], + containers: [] + }; + } + this.onLayoutChange = this.onLayoutChange.bind(this); + } + + createContainer( + containerId, xPos, yPos, width, height, staticLayout = false) { + if (staticLayout) { + return { + id: containerId, + properties: { + x: xPos, + y: yPos, + w: width, + h: height, + isDraggable: false, + isResizable: false + } + }; + } else { + return { + id: containerId, + properties: { + x: xPos, + y: yPos, + w: width, + h: height, + minW: MIN_PANEL_WIDTH, + maxW: MAX_PANEL_WIDTH, + minH: MIN_PANEL_HEIGHT + } + }; + } + } + + createPanel(id, title, panelSource, panelProps, actionList) { + return { + id: id, + title: title, + source: panelSource, + props: panelProps, + actions: actionList + }; + } + + addNewComponent(compProps, containingContainerId) { + let containerId = containingContainerId; + let actionsList = []; + + if (typeof containerId === 'undefined' || containerId === null) { + // new component being added isn't associated with a + // container yet, so create one + containerId = 'container:' + (new Date).getTime(); + let updatedContainerProps = []; + this.state.containers.forEach((containerProps) => { + updatedContainerProps.push(containerProps); + }); + updatedContainerProps.push( + this.createContainer(containerId, 0, Infinity, 12, 2)); + this.setState({containers: updatedContainerProps}); + + actionsList = [ + { + type: 'close', id: containerId, callback: () => { + this.removeExistingComponent(containerId); + } + } + ]; + } else { + // we are updating a static container with a new panel, add the edit + // action so it can be updated moving forward + actionsList = [ + { + type: 'custom', + id: containingContainerId, + icon: EDIT_ICON, + callback: () => { + this.props.addPanelCallback(containingContainerId); + } + } + ]; + } + + let updatedPanelProps = []; + this.state.panels.forEach((panelProp) => { + if (panelProp.id !== containingContainerId) { + // add all existing panels except the one with a + // matching id (this is an edit scenario, will replace + // with new panel below + updatedPanelProps.push(panelProp); + } + }); + updatedPanelProps.push( + this.createPanel( + containerId, + compProps.title, + compProps.visualizationSource, + compProps.visualizationProps, + actionsList)); + this.setState({panels: updatedPanelProps}); + } + + removeExistingComponent(id) { + let updatedPanelProps = this.state.panels.filter((panelProp) => { + return id !== panelProp.id; + }); + this.setState({panels: updatedPanelProps}); + + let updatedContainerProps = this.state.containers.filter( + (containerProp) => { + return id !== containerProp.id; + }); + this.setState({containers: updatedContainerProps}); + } + + getLayoutProperties() { + return { + layout: this.state.layout, + containers: this.state.containers, + panels: this.state.panels + }; + } + + setLayoutProperties(layoutProperties) { + this.setState({ + layout: layoutProperties.layout, + containers: layoutProperties.containers, + panels: layoutProperties.panels + }); + } + + fetchMatchingPanel(containerId) { + let actionsList = []; + let matchingPanel = ( + <ComponentManagerContainer + showHeader={this.props.showHeader} + showTitle={this.props.showTitle} + showBorder={this.props.showBorder} + actions={actionsList}> + {'Please select a visualization'} + </ComponentManagerContainer> + ); + this.state.panels.forEach((panel) => { + if (panel.id === containerId) { + let GeneratedComponent = + this.props.componentPropertiesProvider[panel.source].component.class; + let visProps = panel.props; + matchingPanel = ( + <ComponentManagerContainer + showHeader={this.props.showHeader} + showTitle={this.props.showTitle} + showBorder={this.props.showBorder} + title={panel.title} + actions={panel.actions}> + <GeneratedComponent {...visProps}/> + </ComponentManagerContainer> + ); + } + }); + return matchingPanel; + } + + preparedContainers() { + let containersToRender = []; + + this.state.containers.forEach((container) => { + let matchingPanel = this.fetchMatchingPanel(container.id); + + containersToRender.push(<div key={container.id} + data-grid={{...(container.properties)}}> + {matchingPanel} + </div>); + }); + + return containersToRender; + } + + onLayoutChange(layout) { + this.setState({layout: layout}); + this.props.onLayoutChange(layout); + } + + buildStaticContainers(layoutFormat) { + let staticContainers = []; + let nextRowIndex = 0; + + layoutFormat.layout.forEach((row) => { + let nextColIndex = 0; + let currentTallestContainer = 0; + + row.forEach((col) => { + let containerId = 'container:' + nextRowIndex + '-' + nextColIndex; + let xPos = nextColIndex; + let yPos = nextRowIndex; + let width = 12 * col.width; + let height = col.height; + + nextColIndex = nextColIndex + width; + currentTallestContainer = Math.max(currentTallestContainer, col.height); + + staticContainers.push( + this.createContainer( + containerId, + xPos, + yPos, + width, + height, + true + ) + ); + }); + + nextRowIndex = currentTallestContainer; + }); + + return staticContainers; + } + + componentWillReceiveProps(nextProps) { + if (nextProps.layoutFormat !== this.props.layoutFormat) { + // layout format being passed in are the containers, panels and layout + // for the newly view + this.setState({ + layout: nextProps.layoutFormat.layout, + panels: nextProps.layoutFormat.panels, + containers: nextProps.layoutFormat.containers + }); + } + } + + render() { + + return ( + <div className='component-manager'> + <ReactGridLayout + className='content app-components' + {...this.props} + onLayoutChange={this.onLayoutChange} + layout={this.state.layout}> + {this.preparedContainers()} + </ReactGridLayout> + </div> + ); + } +} +ComponentManager.defaultProps = { + cols: 12, + rewHeight: 100, + onLayoutChange: function () { + }, + showHeader: true, + showTitle: true, + showBorder: true +}; diff --git a/src/generic-components/componentManager/ComponentManagerConstants.js b/src/generic-components/componentManager/ComponentManagerConstants.js new file mode 100644 index 0000000..d7679f9 --- /dev/null +++ b/src/generic-components/componentManager/ComponentManagerConstants.js @@ -0,0 +1,33 @@ +/* + * ============LICENSE_START=================================================== + * SPARKY (AAI UI service) + * ============================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +export const MIN_PANEL_WIDTH = 1; +export const MIN_PANEL_HEIGHT = 1; +export const MAX_PANEL_WIDTH = 12; + +export const EDIT_ICON = 'fa-pencil'; + +export const LAYOUT_STATIC = 'static'; +export const LAYOUT_DYNAMIC = 'dynamic'; diff --git a/src/generic-components/componentManager/ComponentManagerContainer.jsx b/src/generic-components/componentManager/ComponentManagerContainer.jsx new file mode 100644 index 0000000..0bf10f1 --- /dev/null +++ b/src/generic-components/componentManager/ComponentManagerContainer.jsx @@ -0,0 +1,115 @@ +/* + * ============LICENSE_START=================================================== + * SPARKY (AAI UI service) + * ============================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ============================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React, {Component, PropTypes} from 'react'; +import ButtonGroup from 'react-bootstrap/lib/ButtonGroup'; +import Button from 'react-bootstrap/lib/Button'; + +import i18n from 'utils/i18n/i18n'; + +const ICON_CLASS_CLOSE = 'fa fa-times'; + +export default class ComponentManagerContainer extends Component { + + static propType = { + id: PropTypes.string, + title: PropTypes.string, + actions: PropTypes.array, + showHeader: PropTypes.bool, + showTitle: PropTypes.bool, + showBorder: PropTypes.bool, + }; + + static defaultProps = { + id: '', + title: 'Some Title', + actions: [], + showHeader: true, + showTitle: true, + showBorder: true + }; + + constructor(props) { + super(props); + } + + render() { + let { + title, + actions, + children, + showHeader, + showTitle, + showBorder + } = this.props; + let buttons = []; + actions.forEach((action) => { + switch (action.type) { + case 'close': + buttons.push( + <Button + type='submit' + key={action.type} + className='close-button' + onClick={ () => { + action.callback(action.id); + }}> + <i className={ICON_CLASS_CLOSE} aria-hidden='true'></i> + </Button> + ); + break; + case 'custom': + buttons.push( + <Button + type='submit' + key={action.type} + className='custom-button' + onClick={action.callback}> + <i className={'fa ' + action.icon} aria-hidden='true'></i> + </Button> + ); + break; + } + }); + + let containerClass = showBorder + ? 'titled-container titled-container-boarders' + : 'titled-container'; + let headerClass = showHeader ? 'titled-container-header' : 'hidden'; + let titleClass = showTitle ? '' : 'hidden'; + + return ( + <div className={containerClass}> + <ButtonGroup>{buttons}</ButtonGroup> + <div className={headerClass}> + <span className={titleClass}>{i18n(title)}</span> + </div> + <div className='contents'> + {children} + </div> + </div> + ); + } +} |