diff options
Diffstat (limited to 'openecomp-ui/src/nfvo-components')
33 files changed, 835 insertions, 372 deletions
diff --git a/openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx b/openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx index 40daeff9c5..c15cd1d0e8 100644 --- a/openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx +++ b/openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx @@ -60,7 +60,7 @@ class SubmitErrorResponse extends Component { return ( <ErrorBlock errorType={i18n('VSP Errors')}> <div> - {errors.length && errors.map(error=>{return (<ErrorMessage error={error.message}/>);})} + {errors.length && errors.map((error, i) => {return (<ErrorMessage key={i} error={error.message}/>);})} </div> </ErrorBlock> ); @@ -71,7 +71,7 @@ class SubmitErrorResponse extends Component { return ( <ErrorBlock errorType={i18n('Components Errors')}> <div> - {errors.validationData.length && errors.validationData.map(item =>{ return (<ComponentError item={item}/>);})} + {errors.validationData.length && errors.validationData.map((item, i) =>{ return (<ComponentError key={i} item={item}/>);})} </div> </ErrorBlock> ); @@ -90,11 +90,10 @@ class SubmitErrorResponse extends Component { const ComponentError = ({item}) => { - let i = 0; return ( <div> <div className='component-name-header'>{item.entityName}</div> - {item.errors.map(error => {return(<ErrorMessage key={i++} error={error}/>);})} + {item.errors.map((error, i) => {return(<ErrorMessage key={i} error={error}/>);})} </div> ); }; @@ -110,7 +109,7 @@ const UploadErrorList = ({items}) => { let errors = []; for (let item of generator) {errors.push( - <div> + <div key={item.header}> <div className='component-name-header'>{item.header}</div> {item.list.map((error, i) => <ErrorMessage key={i} warning={error.level === 'WARNING'} error={error.message}/> )} </div> diff --git a/openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx b/openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx index f4673c1c93..25e7e7e02d 100644 --- a/openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx +++ b/openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import DatePicker from 'react-datepicker'; import moment from 'moment'; import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; @@ -6,10 +7,10 @@ import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; class CustomInput extends React.Component { static propTypes = { - placeHolderText: React.PropTypes.string, - onChange: React.PropTypes.func, - onClick: React.PropTypes.func, - value: React.PropTypes.string + placeHolderText: PropTypes.string, + onChange: PropTypes.func, + onClick: PropTypes.func, + value: PropTypes.string }; render() { @@ -32,16 +33,16 @@ const parseDate = (date, format) => { class Datepicker extends React.Component { static propTypes = { - date: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]), - format: React.PropTypes.string, - onChange: React.PropTypes.func, - selectsStart: React.PropTypes.bool, - selectsEnd: React.PropTypes.bool, - startDate: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]), - endDate: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]), - disabled: React.PropTypes.bool, - label: React.PropTypes.string, - isRequired: React.PropTypes.bool + date: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + format: PropTypes.string, + onChange: PropTypes.func, + selectsStart: PropTypes.bool, + selectsEnd: PropTypes.bool, + startDate: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + endDate: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + disabled: PropTypes.bool, + label: PropTypes.string, + isRequired: PropTypes.bool } render() { let {date, format, onChange, selectsStart = false, startDate = null, endDate = null, selectsEnd = false, diff --git a/openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx b/openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx index 2a0b7d4d2a..3c9ceed0d8 100644 --- a/openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx +++ b/openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx @@ -22,7 +22,8 @@ import NavigationSideBar from 'nfvo-components/panel/NavigationSideBar.jsx'; export default class TabulatedEditor extends React.Component { render() { - const {navigationBarProps, onToggle, onVersionSwitching, onCreate, onSave, onClose, onVersionControllerAction, onNavigate, children, meta} = this.props; + const {navigationBarProps, onToggle, onVersionSwitching, onMoreVersionsClick, onCreate, onSave, onClose, + onVersionControllerAction, onNavigate, children, meta, onManagePermissions, onOpenCommentCommitModal, onOpenPermissions, onOpenRevisionsModal} = this.props; let {versionControllerProps} = this.props; const {className = ''} = React.Children.only(children).props; const child = this.prepareChild(); @@ -42,7 +43,12 @@ export default class TabulatedEditor extends React.Component { <VersionController {...versionControllerProps} onVersionSwitching={version => onVersionSwitching(version, meta)} - callVCAction={(action, version) => onVersionControllerAction(action, version, meta)} + onMoreVersionsClick={onMoreVersionsClick} + onManagePermissions={onManagePermissions} + onOpenCommentCommitModal={onOpenCommentCommitModal} + onOpenPermissions={onOpenPermissions} + onOpenRevisionsModal={onOpenRevisionsModal} + callVCAction={(action, version, comment) => onVersionControllerAction(action, version, comment, meta)} onCreate={onCreate && this.handleCreate} onSave={onSave && this.handleSave}/> <div className={classnames('content-area', `${className}`)}> diff --git a/openecomp-ui/src/nfvo-components/fileupload/DraggableUploadFileBox.jsx b/openecomp-ui/src/nfvo-components/fileupload/DraggableUploadFileBox.jsx index 629b9449a2..5b4e0a8bee 100644 --- a/openecomp-ui/src/nfvo-components/fileupload/DraggableUploadFileBox.jsx +++ b/openecomp-ui/src/nfvo-components/fileupload/DraggableUploadFileBox.jsx @@ -34,11 +34,10 @@ class DraggableUploadFileBox extends Component { render() { let {className, onClick, dataTestId, isReadOnlyMode} = this.props; return ( - <div - className={`${className}${isReadOnlyMode ? ' disabled' : ''}`}> - <div className={`${'drag-text'}${isReadOnlyMode ? ' disabled' : ''}`}>{i18n('Drag & drop for upload')}</div> + <div className={`file-upload-box ${className} ${isReadOnlyMode ? 'disabled' : ''}`}> + <div className={`drag-text ${isReadOnlyMode ? 'disabled' : ''}`}>{i18n('Drag & drop for upload')}</div> <div className='or-text'>{i18n('or')}</div> - <Button type='button' data-test-id={dataTestId} btnType='outline' onClick={onClick} disabled={isReadOnlyMode === true}>{i18n('Select File')}</Button> + <Button type='button' data-test-id={dataTestId} btnType='outline' onClick={onClick} disabled={isReadOnlyMode}>{i18n('Select File')}</Button> </div> ); } diff --git a/openecomp-ui/src/nfvo-components/grid/GridItem.jsx b/openecomp-ui/src/nfvo-components/grid/GridItem.jsx index 8819ab78a3..c62e042bf4 100644 --- a/openecomp-ui/src/nfvo-components/grid/GridItem.jsx +++ b/openecomp-ui/src/nfvo-components/grid/GridItem.jsx @@ -15,8 +15,8 @@ */ import React from 'react'; -const GridItem = ({colSpan = 1, children, stretch = false}) => ( - <div className={`grid-col-${colSpan}`}> +const GridItem = ({colSpan = 1, children, lastColInRow = false, stretch = false, className = ''}) => ( + <div className={`grid-col-${colSpan} ${lastColInRow ? 'last-col-in-row' : ''} ${className}`}> <div className={`grid-item${stretch ? '-stretch' : ''}`}> {children} </div> diff --git a/openecomp-ui/src/nfvo-components/grid/GridSection.jsx b/openecomp-ui/src/nfvo-components/grid/GridSection.jsx index de8a4f3e64..8f4a024fdb 100644 --- a/openecomp-ui/src/nfvo-components/grid/GridSection.jsx +++ b/openecomp-ui/src/nfvo-components/grid/GridSection.jsx @@ -14,11 +14,12 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import classnames from 'classnames'; -const GridSection = ({title, children, className, titleClassName}) => { +const GridSection = ({title, children, className = '', titleClassName, hasLastColSet = false}) => { return ( - <div className={classnames('grid-section', className)}> + <div className={classnames('grid-section', className, {'has-last-col-set': hasLastColSet})}> {title && <div className={`section-title ${titleClassName || ''}`}>{title}</div>} <div className='grid-items'> {children} @@ -28,7 +29,9 @@ const GridSection = ({title, children, className, titleClassName}) => { }; GridSection.propTypes = { - title: React.PropTypes.string, + title: PropTypes.string, + titleClassName: PropTypes.string, + hasLastColSet: PropTypes.bool }; export default GridSection; diff --git a/openecomp-ui/src/nfvo-components/icon/Icon.jsx b/openecomp-ui/src/nfvo-components/icon/Icon.jsx deleted file mode 100644 index 125577664b..0000000000 --- a/openecomp-ui/src/nfvo-components/icon/Icon.jsx +++ /dev/null @@ -1,45 +0,0 @@ -/*! - * Copyright (C) 2017 AT&T Intellectual Property. 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. - */ -import React, { Component, PropTypes } from 'react'; - - -export default class Icon extends Component { - - static propTypes = { - image: PropTypes.string.isRequired, - onClick: PropTypes.func, - label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), - className: PropTypes.string, - iconClassName: PropTypes.string - }; - - static defaultProps = { - label: '', - className: '', - iconClassName: '' - }; - - render() { - let {image, onClick, label, className, iconClassName, ...other} = this.props; - let classes = `icon-component ${className} ${onClick ? 'clickable' : ''}`; - return ( - <div {...other} onClick={onClick} className={classes}> - <span className={`icon ${image} ${iconClassName}`}></span> - <span className='icon-label'>{label}</span> - </div> - ); - } -} diff --git a/openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx b/openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx index eab1d45ef4..82fbe1deed 100644 --- a/openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx +++ b/openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx @@ -14,6 +14,7 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; import Input from 'nfvo-components/input/validation/InputWrapper.jsx'; @@ -76,9 +77,9 @@ class ExpandableInputOpened extends React.Component { class ExpandableInput extends React.Component { static propTypes = { - iconType: React.PropTypes.string, - onChange: React.PropTypes.func, - value: React.PropTypes.string + iconType: PropTypes.string, + onChange: PropTypes.func, + value: PropTypes.string }; state = {showInput: false}; diff --git a/openecomp-ui/src/nfvo-components/input/ToggleInput.jsx b/openecomp-ui/src/nfvo-components/input/ToggleInput.jsx index 23af72a26a..31a8a66d86 100644 --- a/openecomp-ui/src/nfvo-components/input/ToggleInput.jsx +++ b/openecomp-ui/src/nfvo-components/input/ToggleInput.jsx @@ -14,15 +14,16 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; export default class ToggleInput extends React.Component { static propTypes = { - label: React.PropTypes.node, - value: React.PropTypes.bool, - onChange: React.PropTypes.func, - disabled: React.PropTypes.bool + label: PropTypes.node, + value: PropTypes.bool, + onChange: PropTypes.func, + disabled: PropTypes.bool } static defaultProps = { diff --git a/openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx b/openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx index a3be363ba4..a689c50778 100644 --- a/openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx +++ b/openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx @@ -14,6 +14,7 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; import Input from 'nfvo-components/input/validation/InputWrapper.jsx'; @@ -21,17 +22,17 @@ class DualListboxView extends React.Component { static propTypes = { - availableList: React.PropTypes.arrayOf(React.PropTypes.shape({ - id: React.PropTypes.string.isRequired, - name: React.PropTypes.string.isRequired + availableList: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired })), - filterTitle: React.PropTypes.shape({ - left: React.PropTypes.string, - right: React.PropTypes.string + filterTitle: PropTypes.shape({ + left: PropTypes.string, + right: PropTypes.string }), - selectedValuesList: React.PropTypes.arrayOf(React.PropTypes.string), + selectedValuesList: PropTypes.arrayOf(PropTypes.string), - onChange: React.PropTypes.func.isRequired + onChange: PropTypes.func.isRequired }; static defaultProps = { diff --git a/openecomp-ui/src/nfvo-components/input/validation/Form.jsx b/openecomp-ui/src/nfvo-components/input/validation/Form.jsx index 8d53322587..6df0bf9009 100644 --- a/openecomp-ui/src/nfvo-components/input/validation/Form.jsx +++ b/openecomp-ui/src/nfvo-components/input/validation/Form.jsx @@ -15,6 +15,7 @@ */ import React from 'react'; +import PropTypes from 'prop-types'; import ValidationButtons from './ValidationButtons.jsx'; class Form extends React.Component { @@ -31,18 +32,18 @@ class Form extends React.Component { }; static propTypes = { - isValid : React.PropTypes.bool, - formReady : React.PropTypes.bool, - isReadOnlyMode : React.PropTypes.bool, - hasButtons : React.PropTypes.bool, - onSubmit : React.PropTypes.func, - onReset : React.PropTypes.func, - labledButtons: React.PropTypes.bool, - submitButtonText: React.PropTypes.string, - cancelButtonText: React.PropTypes.string, - onValidChange : React.PropTypes.func, - onValidityChanged: React.PropTypes.func, - onValidateForm: React.PropTypes.func + isValid : PropTypes.bool, + formReady : PropTypes.bool, + isReadOnlyMode : PropTypes.bool, + hasButtons : PropTypes.bool, + onSubmit : PropTypes.func, + onReset : PropTypes.func, + labledButtons: PropTypes.bool, + submitButtonText: PropTypes.string, + cancelButtonText: PropTypes.string, + onValidChange : PropTypes.func, + onValidityChanged: PropTypes.func, + onValidateForm: PropTypes.func }; constructor(props) { @@ -124,13 +125,21 @@ class Form extends React.Component { export class TabsForm extends Form { render() { // eslint-disable-next-line no-unused-vars - let {isValid, formReady, onValidateForm, isReadOnlyMode, hasButtons, onSubmit, labledButtons, onValidChange, onValidityChanged, onDataChanged, children, ...formProps} = this.props; + let {submitButtonText, cancelButtonText, isValid, formReady, onValidateForm, isReadOnlyMode, hasButtons, onSubmit, labledButtons, onValidChange, onValidityChanged, onDataChanged, children, + ...formProps} = this.props; return ( <form {...formProps} ref={(form) => this.form = form} onSubmit={event => this.handleFormValidation(event)}> <div className='validation-form-content'> {children} </div> - {hasButtons && <ValidationButtons labledButtons={labledButtons} ref={(buttons) => this.buttons = buttons} isReadOnlyMode={isReadOnlyMode}/>} + {hasButtons && + <ValidationButtons + labledButtons={labledButtons} + submitButtonText={submitButtonText} + cancelButtonText={cancelButtonText} + ref={buttons => this.buttons = buttons} + isReadOnlyMode={isReadOnlyMode}/> + } </form> ); } diff --git a/openecomp-ui/src/nfvo-components/input/validation/Input.jsx b/openecomp-ui/src/nfvo-components/input/validation/Input.jsx index eef8fee1ce..9f0e9acca8 100644 --- a/openecomp-ui/src/nfvo-components/input/validation/Input.jsx +++ b/openecomp-ui/src/nfvo-components/input/validation/Input.jsx @@ -17,7 +17,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import classNames from 'classnames'; import Checkbox from 'react-bootstrap/lib/Checkbox.js'; -import Radio from 'react-bootstrap/lib/Radio.js'; +import Radio from 'sdc-ui/lib/react/Radio.js'; import FormGroup from 'react-bootstrap/lib/FormGroup.js'; import FormControl from 'react-bootstrap/lib/FormControl.js'; import Overlay from 'react-bootstrap/lib/Overlay.js'; @@ -85,7 +85,7 @@ class Input extends React.Component { className={classNames({'required' : isRequired , 'has-error' : !isValid})} onChange={(e)=>this.onChangeCheckBox(e)} disabled={isReadOnlyMode || Boolean(disabled)} - checked={value} + checked={checked} data-test-id={this.props['data-test-id']}>{label}</Checkbox>} {type === 'radio' && @@ -93,9 +93,10 @@ class Input extends React.Component { checked={checked} disabled={isReadOnlyMode || Boolean(disabled)} value={value} - onChange={(e)=>this.onChangeRadio(e)} + onChange={(isChecked)=>this.onChangeRadio(isChecked)} inputRef={(input) => this.input = input} - data-test-id={this.props['data-test-id']}>{label}</Radio>} + label={label} + data-test-id={this.props['data-test-id']} />} {type === 'select' && <FormControl onClick={ (e) => this.optionSelect(e) } componentClass={type} @@ -156,16 +157,17 @@ class Input extends React.Component { onChangeCheckBox(e) { let {onChange} = this.props; + let checked = e.target.checked; this.setState({ - checked: e.target.checked + checked }); - onChange(e.target.checked); + onChange(checked); } - onChangeRadio(e) { + onChangeRadio(isChecked) { let {onChange} = this.props; this.setState({ - checked: e.target.checked + checked: isChecked }); onChange(this.state.value); } diff --git a/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx b/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx index 9b11d27c2b..11b07ba9da 100644 --- a/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx +++ b/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx @@ -14,6 +14,7 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import i18n from 'nfvo-utils/i18n/i18n.js'; import classNames from 'classnames'; @@ -26,27 +27,27 @@ export const other = {OTHER: 'Other'}; class InputOptions extends React.Component { static propTypes = { - values: React.PropTypes.arrayOf(React.PropTypes.shape({ - enum: React.PropTypes.string, - title: React.PropTypes.string + values: PropTypes.arrayOf(PropTypes.shape({ + enum: PropTypes.string, + title: PropTypes.string })), - isEnabledOther: React.PropTypes.bool, - label: React.PropTypes.string, - selectedValue: React.PropTypes.string, - multiSelectedEnum: React.PropTypes.oneOfType([ - React.PropTypes.string, - React.PropTypes.array + isEnabledOther: PropTypes.bool, + label: PropTypes.string, + selectedValue: PropTypes.string, + multiSelectedEnum: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.array ]), - selectedEnum: React.PropTypes.string, - otherValue: React.PropTypes.string, - overlayPos: React.PropTypes.string, - onEnumChange: React.PropTypes.func, - onOtherChange: React.PropTypes.func, - onBlur: React.PropTypes.func, - isRequired: React.PropTypes.bool, - isMultiSelect: React.PropTypes.bool, - isValid: React.PropTypes.bool, - disabled: React.PropTypes.bool + selectedEnum: PropTypes.string, + otherValue: PropTypes.string, + overlayPos: PropTypes.string, + onEnumChange: PropTypes.func, + onOtherChange: PropTypes.func, + onBlur: PropTypes.func, + isRequired: PropTypes.bool, + isMultiSelect: PropTypes.bool, + isValid: PropTypes.bool, + disabled: PropTypes.bool }; state = { diff --git a/openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx b/openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx index 6c8115deee..e440fcda69 100644 --- a/openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx +++ b/openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx @@ -17,7 +17,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import classNames from 'classnames'; import Checkbox from 'react-bootstrap/lib/Checkbox.js'; -import Radio from 'react-bootstrap/lib/Radio.js'; +import Radio from 'sdc-ui/lib/react/Radio.js'; import FormGroup from 'react-bootstrap/lib/FormGroup.js'; import FormControl from 'react-bootstrap/lib/FormControl.js'; @@ -72,8 +72,8 @@ class InputWrapper extends React.Component { disabled={isReadOnlyMode || Boolean(disabled)} value={value} ref={(input) => this.inputWrapper = input} - onChange={(e)=>this.onChangeRadio(e)} - data-test-id={this.props['data-test-id']}>{label}</Radio>} + onChange={(isChecked)=>this.onChangeRadio(isChecked)} label={label} + data-test-id={this.props['data-test-id']} />} {type === 'select' && <FormControl onClick={ (e) => this.optionSelect(e) } componentClass={type} @@ -119,10 +119,10 @@ class InputWrapper extends React.Component { onChange(e.target.checked); } - onChangeRadio(e) { + onChangeRadio(isChecked) { let {onChange} = this.props; this.setState({ - checked: e.target.checked + checked: isChecked }); onChange(this.state.value); } diff --git a/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx b/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx index 6f33536b04..0982c133e6 100644 --- a/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx +++ b/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx @@ -14,6 +14,7 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import {default as SDCTabs} from 'sdc-ui/lib/react/Tabs.js'; import Overlay from 'react-bootstrap/lib/Overlay.js'; @@ -25,7 +26,7 @@ export default class Tabs extends React.Component { static propTypes = { - children: React.PropTypes.node + children: PropTypes.node }; cloneTab(element) { diff --git a/openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx b/openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx index c3808dd2c3..151d3fe859 100644 --- a/openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx +++ b/openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx @@ -21,6 +21,7 @@ * labledButtons - whether or not to use labeled buttons or icons only */ import React from 'react'; +import PropTypes from 'prop-types'; import i18n from 'nfvo-utils/i18n/i18n.js'; import Button from 'sdc-ui/lib/react/Button.js'; import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; @@ -28,10 +29,10 @@ import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; class ValidationButtons extends React.Component { static propTypes = { - labledButtons: React.PropTypes.bool.isRequired, - isReadOnlyMode: React.PropTypes.bool, - submitButtonText: React.PropTypes.string, - cancelButtonText: React.PropTypes.string + labledButtons: PropTypes.bool.isRequired, + isReadOnlyMode: PropTypes.bool, + submitButtonText: PropTypes.string, + cancelButtonText: PropTypes.string }; state = { @@ -45,10 +46,10 @@ class ValidationButtons extends React.Component { <div className='validation-buttons'> {!this.props.isReadOnlyMode ? <div> - <Button type='submit' disabled={!this.state.isValid}>{submitBtn}</Button> - <Button btnType='outline' type='reset'>{closeBtn}</Button> + <Button type='submit' data-test-id='form-submit-button' disabled={!this.state.isValid}>{submitBtn}</Button> + <Button btnType='outline' type='reset' data-test-id='form-close-button'>{closeBtn}</Button> </div> - : <Button btnType='outline' type='reset'>{i18n('Close')}</Button> + : <Button btnType='outline' type='reset' data-test-id='form-close-button'>{i18n('Close')}</Button> } </div> ); diff --git a/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx b/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx index bed304b756..60c559a3d1 100644 --- a/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx +++ b/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx @@ -14,6 +14,7 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import classnames from 'classnames'; import i18n from 'nfvo-utils/i18n/i18n.js'; import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; @@ -22,11 +23,11 @@ import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModal class ListEditorItem extends React.Component { static propTypes = { - onSelect: React.PropTypes.oneOfType([React.PropTypes.func, React.PropTypes.bool]), - onDelete: React.PropTypes.oneOfType([React.PropTypes.func, React.PropTypes.bool]), - onEdit: React.PropTypes.oneOfType([React.PropTypes.func, React.PropTypes.bool]), - children: React.PropTypes.node, - isReadOnlyMode: React.PropTypes.bool + onSelect: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]), + onDelete: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]), + onEdit: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]), + children: PropTypes.node, + isReadOnlyMode: PropTypes.bool }; render() { diff --git a/openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx b/openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx index df7d69b4ff..16823b7dc5 100644 --- a/openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx +++ b/openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx @@ -14,6 +14,7 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import Button from 'sdc-ui/lib/react/Button.js'; import classnames from 'classnames'; import ExpandableInput from 'nfvo-components/input/ExpandableInput.jsx'; @@ -60,15 +61,15 @@ class ListEditorView extends React.Component { }; static propTypes = { - title: React.PropTypes.string, - plusButtonTitle: React.PropTypes.string, - children: React.PropTypes.node, - filterValue: React.PropTypes.string, - onFilter: React.PropTypes.func, - className: React.PropTypes.string, - isReadOnlyMode: React.PropTypes.bool, - placeholder: React.PropTypes.string, - twoColumns: React.PropTypes.bool + title: PropTypes.string, + plusButtonTitle: PropTypes.string, + children: PropTypes.node, + filterValue: PropTypes.string, + onFilter: PropTypes.func, + className: PropTypes.string, + isReadOnlyMode: PropTypes.bool, + placeholder: PropTypes.string, + twoColumns: PropTypes.bool }; render() { diff --git a/openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js b/openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js index 276b05e270..81125c84ba 100644 --- a/openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js +++ b/openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js @@ -2,7 +2,7 @@ import React from 'react'; import {storiesOf, action} from '@kadira/storybook'; import ListEditorView from './ListEditorView.jsx'; import ListEditorItemView from './ListEditorItemView.jsx'; -import ListEditorItemViewField from './ListEditorItemViewField.jsx'; +import ListEditorItemField from './ListEditorItemViewField.jsx'; import {text, number} from '@kadira/storybook-addon-knobs'; import {withKnobs} from '@kadira/storybook-addon-knobs'; @@ -13,12 +13,12 @@ function makeChildren({onEdit = false, onDelete = false} = {}) { key={index} onEdit={onEdit ? onEdit : undefined} onDelete={onDelete ? onDelete : undefined}> - <ListEditorItemViewField> + <ListEditorItemField> <div>{text('field 1', 'Lorum Ipsum')}</div> - </ListEditorItemViewField> - <ListEditorItemViewField> + </ListEditorItemField> + <ListEditorItemField> <div>{text('field 2', 'Lorum Ipsum')}</div> - </ListEditorItemViewField> + </ListEditorItemField> </ListEditorItemView>) ) ); diff --git a/openecomp-ui/src/nfvo-components/loader/Loader.jsx b/openecomp-ui/src/nfvo-components/loader/Loader.jsx index 675b04c8ea..cbfed1b214 100644 --- a/openecomp-ui/src/nfvo-components/loader/Loader.jsx +++ b/openecomp-ui/src/nfvo-components/loader/Loader.jsx @@ -14,6 +14,7 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import {connect} from 'react-redux'; const mapStateToProps = ({loader}) => { @@ -25,7 +26,7 @@ const mapStateToProps = ({loader}) => { class Loader extends React.Component { static propTypes = { - isLoading: React.PropTypes.bool.isRequired + isLoading: PropTypes.bool.isRequired }; static defaultProps = { diff --git a/openecomp-ui/src/nfvo-components/modal/GlobalModal.js b/openecomp-ui/src/nfvo-components/modal/GlobalModal.js index 4e7a1a16a4..a47c42a1fb 100644 --- a/openecomp-ui/src/nfvo-components/modal/GlobalModal.js +++ b/openecomp-ui/src/nfvo-components/modal/GlobalModal.js @@ -15,6 +15,7 @@ */ import React from 'react'; +import PropTypes from 'prop-types'; import {connect} from 'react-redux'; import Modal from 'nfvo-components/modal/Modal.jsx'; @@ -25,7 +26,7 @@ import {actionTypes, typeEnum} from './GlobalModalConstants.js'; const typeClass = { - 'default': 'default', + 'default': 'primary', error: 'negative', warning: 'warning', success: 'positive' @@ -47,11 +48,11 @@ const ModalFooter = ({type, onConfirmed, onDeclined, onClose, confirmationButton return ( <Modal.Footer> <div className='sdc-modal-footer'> - {onConfirmed && <Button color={typeClass[type]} onClick={() => { + {onConfirmed && <Button data-test-id='sdc-modal-confirm-button' color={typeClass[type]} onClick={() => { onConfirmed(); onClose(); }}>{confirmationButtonText}</Button>} - <Button {...myPropsForNoConfirmed} color={typeClass[type]} onClick={onDeclined ? () => { + <Button {...myPropsForNoConfirmed} data-test-id='sdc-modal-cancel-button' btnType='outline' color={typeClass[type]} onClick={onDeclined ? () => { onDeclined(); onClose();} : () => onClose()}> {cancelButtonText} @@ -85,15 +86,15 @@ export const mapActionToProps = (dispatch) => { export class GlobalModalView extends React.Component { static propTypes = { - show: React.PropTypes.bool, - type: React.PropTypes.oneOf(['default', 'error', 'warning', 'success']), - title: React.PropTypes.string, - modalComponentProps: React.PropTypes.object, - modalComponentName: React.PropTypes.string, - onConfirmed: React.PropTypes.func, - onDeclined: React.PropTypes.func, - confirmationButtonText: React.PropTypes.string, - cancelButtonText: React.PropTypes.string + show: PropTypes.bool, + type: PropTypes.oneOf(['default', 'error', 'warning', 'success']), + title: PropTypes.string, + modalComponentProps: PropTypes.object, + modalComponentName: PropTypes.string, + onConfirmed: PropTypes.func, + onDeclined: PropTypes.func, + confirmationButtonText: PropTypes.string, + cancelButtonText: PropTypes.string }; static defaultProps = { @@ -115,7 +116,7 @@ export class GlobalModalView extends React.Component { {ComponentToRender ? <ComponentToRender {...modalComponentProps}/> : msg && typeof msg === 'string' ? - <div> {msg.split('\n').map(txt => <span> {txt} <br/> </span>)} </div> : + <div> {msg.split('\n').map((txt, i) => <span key={i}> {txt} <br/> </span>)} </div> : msg } </Modal.Body> diff --git a/openecomp-ui/src/nfvo-components/overlay/Overlay.jsx b/openecomp-ui/src/nfvo-components/overlay/Overlay.jsx new file mode 100644 index 0000000000..054c1e2852 --- /dev/null +++ b/openecomp-ui/src/nfvo-components/overlay/Overlay.jsx @@ -0,0 +1,40 @@ +/*! + * Copyright (C) 2017 AT&T Intellectual Property. 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. + */ + +import React from 'react'; +import enhanceWithClickOutside from 'react-click-outside'; + +class Overlay extends React.Component { + + handleClickOutside() { + if (this.props.onClose) { + this.props.onClose(); + } + } + + render() { + return ( + <div className='onboarding-overlay'> + <div className='arrow-up'></div> + <div className='arrow-border'/> + {this.props.children} + </div> + ); + } + +}; + +export default enhanceWithClickOutside(Overlay); diff --git a/openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx b/openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx index fb3b71f0c8..02552fcb7e 100644 --- a/openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx +++ b/openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx @@ -14,15 +14,16 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import classnames from 'classnames'; import Collapse from 'react-bootstrap/lib/Collapse.js'; class NavigationSideBar extends React.Component { static PropTypes = { - activeItemId: React.PropTypes.string.isRequired, - onSelect: React.PropTypes.func, - onToggle: React.PropTypes.func, - groups: React.PropTypes.array + activeItemId: PropTypes.string.isRequired, + onSelect: PropTypes.func, + onToggle: PropTypes.func, + groups: PropTypes.array }; constructor(props) { @@ -61,9 +62,9 @@ class NavigationSideBar extends React.Component { class NavigationMenu extends React.Component { static PropTypes = { - activeItemId: React.PropTypes.string.isRequired, - onNavigationItemClick: React.PropTypes.func, - menu: React.PropTypes.array + activeItemId: PropTypes.string.isRequired, + onNavigationItemClick: PropTypes.func, + menu: PropTypes.array }; render() { @@ -80,6 +81,9 @@ function NavigationMenuHeader(props) { return <div className='group-name' data-test-id='navbar-group-name'>{props.title}</div>; } +function getItemDataTestId(itemId) { + return itemId.split('|')[0]; +} function NavigationMenuItems(props) { const {items, activeItemId, onNavigationItemClick} = props; return ( @@ -97,7 +101,7 @@ function NavigationMenuItem(props) { return ( <div className={classnames('navigation-group-item', {'selected-item': item.id === activeItemId})} key={'item_' + item.id}> <NavigationLink item={item} activeItemId={activeItemId} onClick={onNavigationItemClick} /> - {isGroup && <Collapse in={item.expanded} data-test-id={'navigation-group-' + item.id}> + {isGroup && <Collapse in={item.expanded} data-test-id={'navigation-group-' + getItemDataTestId(item.id)}> <div> {item.items.map(subItem => (<NavigationMenuItem key={'menuItem_' + subItem.id} item={subItem} onNavigationItemClick={onNavigationItemClick} activeItemId={activeItemId} />)) } </div> @@ -120,7 +124,7 @@ function NavigationLink(props) { 'hidden': item.hidden })} onClick={(event) => onClick(event, item)} - data-test-id={'navbar-group-item-' + item.id}> + data-test-id={'navbar-group-item-' + getItemDataTestId(item.id)}> {item.name} </div> ); diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx b/openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx index 922db05282..5273785f07 100644 --- a/openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx +++ b/openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx @@ -14,51 +14,66 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionsEnum, statusEnum, statusBarTextMap } from './VersionControllerConstants.js'; -import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; -import Tooltip from 'react-bootstrap/lib/Tooltip.js'; -import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js'; +import {actionsEnum} from './VersionControllerConstants.js'; +import ActionButtons from './components/ActionButtons.jsx'; +import NotificationsView from 'sdc-app/onboarding/userNotifications/NotificationsView.jsx'; class VersionController extends React.Component { static propTypes = { - version: React.PropTypes.object, - viewableVersions: React.PropTypes.array, - onVersionSwitching: React.PropTypes.func, - isCheckedOut: React.PropTypes.bool.isRequired, - status: React.PropTypes.string.isRequired, - callVCAction: React.PropTypes.func, - onSave: React.PropTypes.func, - onClose: React.PropTypes.func, - isFormDataValid: React.PropTypes.bool + version: PropTypes.object, + viewableVersions: PropTypes.array, + onVersionSwitching: PropTypes.func, + callVCAction: PropTypes.func, + onSave: PropTypes.func, + onClose: PropTypes.func, + isFormDataValid: PropTypes.bool, + onOpenCommentCommitModal: PropTypes.func, + isReadOnlyMode: PropTypes.bool + }; + + state = { + showPermissions: false, + showRevisions: false }; render() { - let {status, isCheckedOut, version = {}, viewableVersions = [], onVersionSwitching, callVCAction, onSave, isFormDataValid, onClose} = this.props; - let isCheckedIn = Boolean(status === statusEnum.CHECK_IN_STATUS); - let isLatestVersion = Boolean(version.id === viewableVersions[viewableVersions.length - 1].id); - if (!isLatestVersion) { - status = statusEnum.PREVIOUS_VERSION; - } + let {version = {}, viewableVersions = [], onVersionSwitching, onMoreVersionsClick, callVCAction, onSave, isReadOnlyMode, itemPermission, + isFormDataValid, onClose, onManagePermissions, permissions = {}, userInfo, usersList, itemName, onOpenCommentCommitModal, onOpenRevisionsModal, isManual} = this.props; return ( <div className='version-controller-bar'> <div className='vc-container'> <div className='version-status-container'> - <VersionSelector viewableVersions={viewableVersions} version={version} onVersionSwitching={onVersionSwitching} /> - <StatusBarUpdates status={status}/> + <VersionSelector + viewableVersions={viewableVersions} + version={version} + onVersionSwitching={onVersionSwitching} + onMoreVersionsClick={() => onMoreVersionsClick({itemName, users: usersList})}/> </div> <div className='save-submit-cancel-container'> <ActionButtons onSubmit={callVCAction ? () => this.submit(callVCAction, version) : undefined} - onRevert={callVCAction ? () => this.revertCheckout(callVCAction, version) : undefined} - status={status} - onCheckinCheckout={callVCAction ? () => this.checkinCheckoutVersion(callVCAction, version) : undefined} + onRevert={callVCAction ? () => this.revert(callVCAction, version) : undefined} + onOpenRevisionsModal={onOpenRevisionsModal} onSave={onSave ? () => onSave() : undefined} - isLatestVersion={isLatestVersion} - isCheckedOut={isCheckedOut} - isCheckedIn={isCheckedIn} isFormDataValid={isFormDataValid} version={version}/> + permissions={permissions} + userInfo={userInfo} + onManagePermissions={onManagePermissions} + showPermissions={this.state.showPermissions} + onClosePermissions={()=>this.setState({showPermissions: false})} + onClickPermissions={() => this.onClickPermissions()} + onSync={callVCAction ? () => this.sync(callVCAction, version) : undefined} + onOpenCommentCommitModal={onOpenCommentCommitModal} + onCommit={callVCAction ? (comment) => this.commit(callVCAction, version, comment) : undefined} + isFormDataValid={isFormDataValid} + itemPermissions={itemPermission} + isReadOnlyMode={isReadOnlyMode} + isManual={isManual} /> + <div className='vc-separator'></div> + <NotificationsView /> {onClose && <div className='vc-nav-item-close' onClick={() => onClose()} data-test-id='vc-cancel-btn'> X</div>} </div> </div> @@ -66,116 +81,57 @@ class VersionController extends React.Component { ); } + onClickPermissions() { + let {onOpenPermissions, usersList} = this.props; + let {showPermissions} = this.state; + let promise = showPermissions ? Promise.resolve() : onOpenPermissions({users: usersList}); + promise.then(() => this.setState({showPermissions: !showPermissions})); + } + + submit(callVCAction, version) { const action = actionsEnum.SUBMIT; callVCAction(action, version); } - revertCheckout(callVCAction, version) { - const action = actionsEnum.UNDO_CHECK_OUT; + revert(callVCAction, version) { + const action = actionsEnum.REVERT; callVCAction(action, version); } - checkinCheckoutVersion(callVCAction, version) { - if (this.props.isCheckedOut) { - this.checkin(callVCAction, version); - } - else { - this.checkout(callVCAction, version); - } - } - checkin(callVCAction, version) { - const action = actionsEnum.CHECK_IN; - if (this.props.onSave) { - this.props.onSave().then(()=>{ - callVCAction(action, version); - }); - }else{ - callVCAction(action, version); - } - - } - checkout(callVCAction, version) { - const action = actionsEnum.CHECK_OUT; + sync(callVCAction, version) { + const action = actionsEnum.SYNC; callVCAction(action, version); } -} -class ActionButtons extends React.Component { - static propTypes = { - version: React.PropTypes.object, - onSubmit: React.PropTypes.func, - onRevert: React.PropTypes.func, - onSave: React.PropTypes.func, - isLatestVersion: React.PropTypes.bool, - isCheckedIn: React.PropTypes.bool, - isCheckedOut: React.PropTypes.bool, - isFormDataValid: React.PropTypes.bool - }; - render() { - const {onSubmit, onRevert, onSave, isLatestVersion, isCheckedIn, isCheckedOut, isFormDataValid, version, status, onCheckinCheckout} = this.props; - const [checkinBtnIconSvg, checkinCheckoutBtnTitle] = status === statusEnum.CHECK_OUT_STATUS ? - ['versionControllerLockOpen', i18n('Check In')] : - ['versionControllerLockClosed', i18n('Check Out')]; - const disabled = (isLatestVersion && onCheckinCheckout && status !== statusEnum.LOCK_STATUS) ? false : true; - return ( - <div className='action-buttons'> - <VCButton dataTestId='vc-checkout-btn' onClick={onCheckinCheckout} isDisabled={disabled} - name={checkinBtnIconSvg} tooltipText={checkinCheckoutBtnTitle}/> - {onSubmit && onRevert && - <div className='version-control-buttons'> - <VCButton dataTestId='vc-submit-btn' onClick={onSubmit} isDisabled={!isCheckedIn || !isLatestVersion} - name='versionControllerSubmit' tooltipText={i18n('Submit')}/> - <VCButton dataTestId='vc-revert-btn' onClick={onRevert} isDisabled={!isCheckedOut || version.label === '0.1' || !isLatestVersion} - name='versionControllerRevert' tooltipText={i18n('Revert')}/> - </div> - } - {onSave && - <VCButton dataTestId='vc-save-btn' onClick={() => onSave()} isDisabled={!isCheckedOut || !isFormDataValid || !isLatestVersion} - name='versionControllerSave' tooltipText={i18n('Save')}/> - } - </div> - ); + commit(callVCAction, version, comment) { + const action = actionsEnum.COMMIT; + callVCAction(action, version, comment); } -} - -function StatusBarUpdates({status}) { - return ( - <div className='vc-status'> - <span className='status-text'>{i18n(statusBarTextMap[status])}</span> - </div> - ); -} -function VCButton({name, tooltipText, isDisabled, onClick, dataTestId}) { - let onClickAction = isDisabled ? ()=>{} : onClick; - let disabled = isDisabled ? 'disabled' : ''; + permissions() { - return ( - <OverlayTrigger placement='top' overlay={<Tooltip id='vc-tooltip'>{tooltipText}</Tooltip>}> - <div disabled={disabled} className='action-buttons-svg'> - <SVGIcon data-test-id={dataTestId} disabled={isDisabled} onClick={onClickAction ? onClickAction : undefined} name={name}/> - </div> - </OverlayTrigger> - ); + } } function VersionSelector(props) { - let {version = {}, viewableVersions = [], onVersionSwitching} = props; + let {version = {}, onMoreVersionsClick, viewableVersions = [], onVersionSwitching} = props; const includedVersions = viewableVersions.filter(ver => {return ver.id === version.id;}); return (<div className='version-section-wrapper'> <select className='version-selector' - onChange={ev => onVersionSwitching && onVersionSwitching({id: ev.target.value, label: ev.target.value})} - value={version.label}> + onChange={ev => onVersionSwitching && onVersionSwitching(viewableVersions.find(version => version.id === ev.target.value))} + value={version.id} + data-test-id='vc-versions-select-box'> {viewableVersions && viewableVersions.map(viewVersion => { return ( - <option key={viewVersion.id} value={viewVersion.id} data-test-id='vc-version-option'>{`V ${viewVersion.label}`}</option> + <option key={viewVersion.id} value={viewVersion.id} data-test-id='vc-version-option'>{`V ${viewVersion.name} ${viewVersion.status}`}</option> ); }) } {!includedVersions.length && - <option key={version.id} value={version.id}>{`V ${version.label}`}</option>} + <option key={version.id} value={version.id} data-test-id='vc-selected-version-option'>{`V ${version.name} ${version.status}`}</option>} </select> + <span onClick={onMoreVersionsClick} className='version-selector-more-versions' data-test-id='vc-versions-page-link'>{i18n('Versions Page')}</span> </div>); } diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js index c2548e4fb4..ddb428a1e9 100644 --- a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js +++ b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js @@ -16,26 +16,9 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionsEnum = keyMirror({ - CHECK_IN: 'Checkin', - CHECK_OUT: 'Checkout', - UNDO_CHECK_OUT: 'Undo_Checkout', + REVERT: 'Revert', + SYNC: 'Sync', SUBMIT: 'Submit', + COMMIT: 'Commit', CREATE_PACKAGE: 'Create_Package' }); - -export const statusEnum = keyMirror({ - CHECK_OUT_STATUS: 'Locked', - CHECK_IN_STATUS: 'Available', - SUBMIT_STATUS: 'Final', - LOCK_STATUS: 'LockedByUser', - PREVIOUS_VERSION: 'READ ONLY' -}); - -export const statusBarTextMap = keyMirror({ - 'Locked': 'Checked Out', - 'LockedByUser': 'Locked', - 'Available': 'Checked In', - 'Final': 'Submitted', - 'READ ONLY': 'Locked' -}); - diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerUtils.js b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerUtils.js deleted file mode 100644 index e8c12abec3..0000000000 --- a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerUtils.js +++ /dev/null @@ -1,52 +0,0 @@ -/*! - * Copyright (C) 2017 AT&T Intellectual Property. 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. - */ -import Configuration from 'sdc-app/config/Configuration.js'; -import {statusEnum} from './VersionControllerConstants.js'; - - -const VersionControllerUtils = { - - getCheckOutStatusKindByUserID(status, lockingUser) { - let returnStatus; - let isCheckedOut; - let currentLoginUserID = Configuration.get('UserID'); - if (lockingUser) { - isCheckedOut = currentLoginUserID === lockingUser; - returnStatus = isCheckedOut ? status : statusEnum.LOCK_STATUS; - } else { - isCheckedOut = false; - returnStatus = status; - } - - return { - status: returnStatus, - isCheckedOut - }; - }, - - isCheckedOutByCurrentUser(resource) { - let currentLoginUserID = Configuration.get('UserID'); - return resource.lockingUser !== undefined && resource.lockingUser === currentLoginUserID; - }, - - isReadOnly(resource) { - const {version, viewableVersions = []} = resource; - const latestVersion = viewableVersions[viewableVersions.length - 1]; - return version.id !== latestVersion.id || !VersionControllerUtils.isCheckedOutByCurrentUser(resource); - } -}; - -export default VersionControllerUtils; diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/components/ActionButtons.jsx b/openecomp-ui/src/nfvo-components/panel/versionController/components/ActionButtons.jsx new file mode 100644 index 0000000000..4346a0e5dc --- /dev/null +++ b/openecomp-ui/src/nfvo-components/panel/versionController/components/ActionButtons.jsx @@ -0,0 +1,109 @@ +/*! + * Copyright (C) 2017 AT&T Intellectual Property. 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. + */ +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import enhanceWithClickOutside from 'react-click-outside'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; +import Overlay from 'nfvo-components/overlay/Overlay.jsx'; +import Permissions from './Permissions.jsx'; + +class ClickOutsideWrapper extends Component { + handleClickOutside() { + this.props.onClose(); + } + render() { + return <div>{this.props.children}</div>; + } +} + +const EnhancedClickOutsideWrapper = enhanceWithClickOutside(ClickOutsideWrapper); + +const VCButton = ({name, tooltipText, disabled, onClick, dataTestId}) => { + let onClickAction = disabled ? ()=>{} : onClick; + return ( + <div className={`action-button-wrapper ${disabled ? 'disabled' : 'clickable'}`} onClick={onClickAction}> + <div className='action-buttons-svg'> + <SVGIcon label={tooltipText} labelPosition='bottom' labelClassName='action-button-label' + data-test-id={dataTestId} name={name} disabled={disabled}/> + </div> + </div> + ); +}; + +const Separator = () => (<div className='vc-separator'></div>); + +const SubmitButton = ({onClick, disabled}) => ( + <div onClick={()=>onClick()} data-test-id='vc-submit-btn' className={`vc-submit-button ${disabled ? 'disabled' : ''}`}> + <SVGIcon name='check' iconClassName='vc-v-submit' disabled={disabled} /> + {i18n('Submit')} + </div> +); + + +const ActionButtons = ({isReadOnlyMode, onSubmit, onRevert, onSave, isFormDataValid, onClickPermissions, onSync, onCommit, + onOpenCommentCommitModal, showPermissions, onClosePermissions, permissions, onManagePermissions, userInfo, onOpenRevisionsModal, isManual, + itemPermissions: {isCertified, isCollaborator, isDirty, isOutOfSync, isUpToDate}}) => ( + <div className='action-buttons'> + <EnhancedClickOutsideWrapper onClose={onClosePermissions}> + <VCButton disabled={isManual} dataTestId='vc-permission-btn' onClick={onClickPermissions} + name='version-controller-permissions' tooltipText={i18n('Permissons')} /> + {showPermissions && + <Overlay> + <Permissions userInfo={userInfo} onManagePermissions={onManagePermissions} permissions={permissions} onClosePermissions={onClosePermissions}/> + </Overlay> + } + </EnhancedClickOutsideWrapper> + {isCollaborator && <div className='collaborator-action-buttons'> + <Separator /> + {onSave && <div className='vc-save-section'> + <VCButton dataTestId='vc-save-btn' onClick={() => onSave()} + name='version-controller-save' tooltipText={i18n('Save')} disabled={isReadOnlyMode || !isFormDataValid} /> + <Separator /> + </div> + } + <VCButton dataTestId='vc-sync-btn' onClick={onSync} + name='version-controller-sync' tooltipText={i18n('Sync')} disabled={!isCollaborator || isUpToDate || isCertified} /> + <VCButton dataTestId='vc-commit-btn' onClick={() => onOpenCommentCommitModal({onCommit, title: i18n('Commit')})} + name='version-controller-commit' tooltipText={i18n('Share')} disabled={isReadOnlyMode || !isDirty || isOutOfSync} /> + {onRevert && + <VCButton dataTestId='vc-revert-btn' onClick={onOpenRevisionsModal} + name='version-controller-revert' tooltipText={i18n('Revert')} disabled={isReadOnlyMode || isOutOfSync} /> + } + {onSubmit && (permissions.owner && permissions.owner.userId === userInfo.userId) && + <div className='vc-submit-section'> + <Separator /> + <SubmitButton onClick={onSubmit} + disabled={isReadOnlyMode || isOutOfSync || !isUpToDate || isCertified} /> + </div> + } + </div>} + </div> +); + +ActionButtons.propTypes = { + version: PropTypes.object, + onSubmit: PropTypes.func, + onRevert: PropTypes.func, + onSave: PropTypes.func, + isLatestVersion: PropTypes.bool, + isCheckedIn: PropTypes.bool, + isCheckedOut: PropTypes.bool, + isFormDataValid: PropTypes.bool, + isReadOnlyMode: PropTypes.bool +}; + +export default ActionButtons; diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/components/CommitCommentModal.jsx b/openecomp-ui/src/nfvo-components/panel/versionController/components/CommitCommentModal.jsx new file mode 100644 index 0000000000..600eaeefaa --- /dev/null +++ b/openecomp-ui/src/nfvo-components/panel/versionController/components/CommitCommentModal.jsx @@ -0,0 +1,73 @@ +/*! + * Copyright (C) 2017 AT&T Intellectual Property. 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. + */ + +import React from 'react'; +import {connect} from 'react-redux'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import Form from 'nfvo-components/input/validation/Form.jsx'; +import Input from 'nfvo-components/input/validation/Input.jsx'; +import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import keyMirror from 'nfvo-utils/KeyMirror.js'; + +export const CommitModalType = keyMirror({ + COMMIT: null, + COMMIT_SUBMIT: null + +}); + +export const mapActionToProps = (dispatch) => { + return { + onClose: () => dispatch({ + type: modalActionTypes.GLOBAL_MODAL_CLOSE + }) + }; +}; + +class CommitCommentModal extends React.Component { + + state = { + comment: '' + }; + + render() { + const {onCommit, onClose, type} = this.props; + const [commitButtonText, descriptionText] = type === CommitModalType.COMMIT ? + [i18n('Commit'), i18n('You are about to commit your version')] : + [i18n('Commit & Submit'), i18n('You must commit your changes before the submit')]; + + return ( + <Form + ref='validationForm' + hasButtons={true} + onSubmit={ () => {onCommit(this.state.comment); onClose();} } + onReset={onClose} + submitButtonText={commitButtonText} + labledButtons={true} + isValid={true} + className='comment-commit-form'> + <div className='commit-modal-text'>{descriptionText}</div> + <Input + data-test-id='commit-comment-text' + onChange={comment => this.setState({comment: comment})} + label={i18n('Enter Commit Comment:')} + value={this.state.comment} + type='textarea'/> + </Form> + ); + } +} + +export default connect(null, mapActionToProps)(CommitCommentModal); diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/components/Permissions.jsx b/openecomp-ui/src/nfvo-components/panel/versionController/components/Permissions.jsx new file mode 100644 index 0000000000..952bd4fb58 --- /dev/null +++ b/openecomp-ui/src/nfvo-components/panel/versionController/components/Permissions.jsx @@ -0,0 +1,65 @@ +/*! + * Copyright (C) 2017 AT&T Intellectual Property. 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. + */ + +import React from 'react'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; + +const Contributor = ({name, role, id, userInfo}) => { + + const selected = id === userInfo.userId ? 'selected' : ''; + + return( + <div className='contributor'> + <div className='contributor-content'> + <div className={`contributor-icon-circle ${selected}`}> + <div className={`contributer-icon ${selected}`}> + <SVGIcon name='user'/> + </div> + </div> + <div className='contributer-info'> + <div className='contributer-name'>{name}</div> + <div className='contributer-role'><p>{role}</p></div> + </div> + </div> + </div> + ); +}; + +const Permissions = ({permissions: {owner, contributors}, onManagePermissions, userInfo, onClosePermissions}) => { + + return ( + <div className='permissions-overlay'> + <div className='permissions-overlay-header'> + <h4 className='permissions-overlay-header-title'>{i18n('PERMISSIONS')}</h4> + </div> + <div className='permissions-overlay-content'> + <Contributor userInfo={userInfo} id={owner.userId} key={owner.fullName} name={owner.fullName} role={owner.role}/> + {contributors.map(item => item.userId !== owner.userId && <Contributor userInfo={userInfo} id={item.userId} key={item.fullName} name={item.fullName} role={item.role}/>)} + </div> + <div className='permissions-overlay-footer'> + { + owner.userId === userInfo.userId && + <div onClick={() => { onClosePermissions(); onManagePermissions(); }} className='manage-permissions-btn'> + {i18n('Manage Permissions')} + </div> + } + </div> + </div> + ); +}; + +export default Permissions; diff --git a/openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx b/openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx index 40720c39f4..ca5cb3d765 100644 --- a/openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx +++ b/openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx @@ -14,11 +14,12 @@ * permissions and limitations under the License. */ import React from 'react'; +import PropTypes from 'prop-types'; class ProgressBar extends React.Component { static propTypes = { - label: React.PropTypes.string, - now: React.PropTypes.string.isRequired + label: PropTypes.string, + now: PropTypes.string.isRequired } render() { let {label, now} = this.props; diff --git a/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx b/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx index a03f8441a4..260d39d31c 100644 --- a/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx +++ b/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx @@ -27,12 +27,12 @@ function renderErrorOrCheck({hasError, overlayMsg}) { return <SVGIcon name='checkCircle' color='positive'/>; } -const SelectActionTableRow = ({children, onDelete, hasError, hasErrorIndication, overlayMsg, showDelete}) => ( +const SelectActionTableRow = ({children, actionIcon, onAction, showAction, hasError, hasErrorIndication, overlayMsg}) => ( <div className='select-action-table-row-wrapper'> <div className={`select-action-table-row ${hasError ? 'has-error' : ''}`}> {children} </div> - {onDelete && <SVGIcon color='secondary' name='trashO' data-test-id='select-action-table-delete' onClick={onDelete} iconClassName={(showDelete) ? '' : 'hideDelete'}/>} + {onAction && <SVGIcon color='secondary' name={actionIcon} data-test-id={`select-action-table-${actionIcon}`} onClick={onAction} iconClassName={(showAction) ? '' : 'hideDelete'}/>} {hasErrorIndication && renderErrorOrCheck({hasError, overlayMsg})} </div> ); diff --git a/openecomp-ui/src/nfvo-components/tree/Tree.jsx b/openecomp-ui/src/nfvo-components/tree/Tree.jsx new file mode 100644 index 0000000000..682f3b6d50 --- /dev/null +++ b/openecomp-ui/src/nfvo-components/tree/Tree.jsx @@ -0,0 +1,181 @@ +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import {select} from 'd3-selection'; +import {tree, stratify} from 'd3-hierarchy'; + + +function diagonal(d) { + + const offset = 50; + return 'M' + d.y + ',' + d.x + + 'C' + (d.parent.y + offset) + ',' + d.x + + ' ' + (d.parent.y + offset) + ',' + d.parent.x + + ' ' + d.parent.y + ',' + d.parent.x; +} + +const nodeRadius = 8; +const verticalSpaceBetweenNodes = 70; +const NARROW_HORIZONTAL_SPACES = 47; +const WIDE_HORIZONTAL_SPACES = 65; + +const stratifyFn = stratify().id(d => d.id).parentId(d => d.parent); + +class Tree extends Component { + + // state = { + // startingCoordinates: null, + // isDown: false + // } + + static propTypes = { + name: PropTypes.string, + width: PropTypes.number, + allowScaleWidth: PropTypes.bool, + nodes: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + parent: PropTypes.string + })), + selectedNodeId: PropTypes.string, + onNodeClick: PropTypes.func, + onRenderedBeyondWidth: PropTypes.func + }; + + static defaultProps = { + width: 500, + allowScaleWidth : true, + name: 'default-name' + }; + + render() { + let {width, name, scrollable = false} = this.props; + return ( + <div + className={`tree-view ${name}-container ${scrollable ? 'scrollable' : ''}`}> + <svg width={width} className={name}></svg> + </div> + ); + } + + componentDidMount() { + this.renderTree(); + } + + // handleMouseMove(e) { + // if (!this.state.isDown) { + // return; + // } + // const container = select(`.tree-view.${this.props.name}-container`); + // let coordinates = this.getCoordinates(e); + // container.property('scrollLeft' , container.property('scrollLeft') + coordinates.x - this.state.startingCoordinates.x); + // container.property('scrollTop' , container.property('scrollTop') + coordinates.y - this.state.startingCoordinates.y); + // } + + // handleMouseDown(e) { + // let startingCoordinates = this.getCoordinates(e); + // this.setState({ + // startingCoordinates, + // isDown: true + // }); + // } + + // handleMouseUp() { + // this.setState({ + // startingCorrdinates: null, + // isDown: false + // }); + // } + + // getCoordinates(e) { + // var bounds = e.target.getBoundingClientRect(); + // var x = e.clientX - bounds.left; + // var y = e.clientY - bounds.top; + // return {x, y}; + // } + + componentDidUpdate(prevProps) { + if (this.props.nodes.length !== prevProps.nodes.length || + this.props.selectedNodeId !== prevProps.selectedNodeId) { + console.log('update'); + this.renderTree(); + } + } + + renderTree() { + let {width, nodes, name, allowScaleWidth, selectedNodeId, onRenderedBeyondWidth, toWiden} = this.props; + if (nodes.length > 0) { + + let horizontalSpaceBetweenLeaves = toWiden ? WIDE_HORIZONTAL_SPACES : NARROW_HORIZONTAL_SPACES; + const treeFn = tree().nodeSize([horizontalSpaceBetweenLeaves, verticalSpaceBetweenNodes]);//.size([width - 50, height - 50]) + let root = stratifyFn(nodes).sort((a, b) => a.data.name.localeCompare(b.data.name)); + let svgHeight = verticalSpaceBetweenNodes * root.height + nodeRadius * 6; + + treeFn(root); + + let nodesXValue = root.descendants().map(node => node.x); + let maxX = Math.max(...nodesXValue); + let minX = Math.min(...nodesXValue); + + let svgTempWidth = (maxX - minX) / 30 * (horizontalSpaceBetweenLeaves); + let svgWidth = svgTempWidth < width ? (width - 5) : svgTempWidth; + const svgEL = select(`svg.${name}`); + const container = select(`.tree-view.${name}-container`); + svgEL.html(''); + svgEL.attr('height', svgHeight); + let canvasWidth = width; + if (svgTempWidth > width) { + if (allowScaleWidth) { + canvasWidth = svgTempWidth; + } + // we seems to have a margin of 25px that we can still see with text + if (((svgTempWidth - 25) > width) && onRenderedBeyondWidth !== undefined) { + onRenderedBeyondWidth(); + } + }; + svgEL.attr('width', canvasWidth); + let rootGroup = svgEL.append('g').attr('transform', `translate(${svgWidth / 2 + nodeRadius},${nodeRadius * 4}) rotate(90)`); + + // handle link + rootGroup.selectAll('.link') + .data(root.descendants().slice(1)) + .enter().append('path') + .attr('class', 'link') + .attr('d', diagonal); + + let node = rootGroup.selectAll('.node') + .data(root.descendants()) + .enter().append('g') + .attr('class', node => `node ${node.children ? ' has-children' : ' leaf'} ${node.id === selectedNodeId ? 'selectedNode' : ''} ${this.props.onNodeClick ? 'clickable' : ''}`) + .attr('transform', node => 'translate(' + node.y + ',' + node.x + ')') + .on('click', node => this.onNodeClick(node)); + + node.append('circle').attr('r', nodeRadius).attr('class', 'outer-circle'); + node.append('circle').attr('r', nodeRadius - 3).attr('class', 'inner-circle'); + + node.append('text') + .attr('y', nodeRadius / 4 + 1) + .attr('x', - nodeRadius * 1.8) + .text(node => node.data.name) + .attr('transform', 'rotate(-90)'); + + let selectedNode = selectedNodeId ? root.descendants().find(node => node.id === selectedNodeId) : null; + if (selectedNode) { + + container.property('scrollLeft', (svgWidth / 4) + (svgWidth / 4 - 100) - (selectedNode.x / 30 * horizontalSpaceBetweenLeaves)); + container.property('scrollTop', (selectedNode.y / 100 * verticalSpaceBetweenNodes)); + + } else { + container.property('scrollLeft', (svgWidth / 4) + (svgWidth / 4 - 100)); + } + } + } + + onNodeClick(node) { + if (this.props.onNodeClick) { + this.props.onNodeClick(node.data); + } + } + +} + +export default Tree; diff --git a/openecomp-ui/src/nfvo-components/tree/Tree.stories.js b/openecomp-ui/src/nfvo-components/tree/Tree.stories.js new file mode 100644 index 0000000000..b29920b3ec --- /dev/null +++ b/openecomp-ui/src/nfvo-components/tree/Tree.stories.js @@ -0,0 +1,119 @@ +import React from 'react'; +import {storiesOf} from '@kadira/storybook'; +import {withKnobs} from '@kadira/storybook-addon-knobs'; +import Tree from './Tree.jsx'; +import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; + +const stories = storiesOf('Version Tree', module); +stories.addDecorator(withKnobs); + +const response = { + listCount: 6, + results: [ + { + 'id': '123', + 'name': '1.0', + 'description': 'string', + 'baseId': '', + 'status': 'Draft', + 'creationTime': '2017-06-08T08:55:37.831Z', + 'modificationTime': '2017-06-08T08:55:37.831Z' + }, + { + 'id': '1234', + 'name': '1.1', + 'description': 'string', + 'baseId': '123', + 'status': 'Draft', + 'creationTime': '2017-06-08T08:55:37.831Z', + 'modificationTime': '2017-06-08T08:55:37.831Z' + }, + { + 'id': '12345', + 'name': '2.0', + 'description': 'string', + 'baseId': '123', + 'status': 'Draft', + 'creationTime': '2017-06-08T08:55:37.831Z', + 'modificationTime': '2017-06-08T08:55:37.831Z' + }, + { + 'id': '123456', + 'name': '3.0', + 'description': 'string', + 'baseId': '12345', + 'status': 'Draft', + 'creationTime': '2017-06-08T08:55:37.831Z', + 'modificationTime': '2017-06-08T08:55:37.831Z' + }, + { + 'id': '1234567', + 'name': '1.2', + 'description': 'string', + 'baseId': '1234', + 'status': 'Draft', + 'creationTime': '2017-06-08T08:55:37.831Z', + 'modificationTime': '2017-06-08T08:55:37.831Z' + }, + { + 'id': '12345678', + 'name': '2.1', + 'description': 'string', + 'baseId': '12345', + 'status': 'Draft', + 'creationTime': '2017-06-08T08:55:37.831Z', + 'modificationTime': '2017-06-08T08:55:37.831Z' + }, + { + 'id': '123456789', + 'name': '4.0', + 'description': 'string', + 'baseId': '123456', + 'status': 'Draft', + 'creationTime': '2017-06-08T08:55:37.831Z', + 'modificationTime': '2017-06-08T08:55:37.831Z' + }, + { + 'id': '12345678910', + 'name': '3.1', + 'description': 'string', + 'baseId': '123456', + 'status': 'Draft', + 'creationTime': '2017-06-08T08:55:37.831Z', + 'modificationTime': '2017-06-08T08:55:37.831Z' + } + ] +}; +const divStyle = { width: '200px', borderStyle: 'solid', borderColor: 'black', border: '1px solid black'}; +const tree = response.results.map(item => ({id: item.id, name: item.name, parent: item.baseId})); +const nodeClickHandler = function (node) { + window.alert(node.name); +}; +stories.add('Classic Version Tree', () => ( + <div> + <Tree nodes={tree} onNodeClick={nodeClickHandler} selectedNodeId={'1234'}/> + </div> +)).add('Single Version Tree', () => ( + <div> + <Tree nodes={[tree[0]]} onNodeClick={nodeClickHandler}/> + </div> +)).add('Single Path Version Tree', () => ( + <div> + <Tree nodes={[tree[0], tree[1]]} onNodeClick={nodeClickHandler}/> + </div> +)).add('Empty Tree', () => ( + <div> + <Tree nodes={[]}/> + </div> +)).add('Add Tree in Version Page Frame', () => ( + <div style={divStyle}> + Tree wider than frame<br/><br/><br/> + <Tree + name={'versions-tree'} + width={200} + nodes={tree} + onRenderedBeyondWidth={() => {console.log('rendered beyond width')}} + allowScaleWidth={false} + onNodeClick={nodeClickHandler}/> + </div> +)); |