diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments')
15 files changed, 658 insertions, 427 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js index d75d464f9e..6c0631963b 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js @@ -1,17 +1,17 @@ -/*! - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +/* + * Copyright © 2016-2018 European Support Limited * * 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 + * 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. + * 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 { connect } from 'react-redux'; import HeatSetupView from './HeatSetupView.jsx'; @@ -65,6 +65,12 @@ export const mapActionsToProps = (dispatch, {}) => { value, type }), + onToggleVolFilesDisplay: ({ module, value }) => { + HeatSetupActionHelper.toggleVolFilesDisplay(dispatch, { + module, + value + }); + }, onArtifactListChange: artifacts => HeatSetupActionHelper.changeArtifactList(dispatch, artifacts), onAddAllUnassigned: () => diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js index 05ac408fbb..d2eb4e9eda 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js @@ -1,26 +1,28 @@ -/*! - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +/* + * Copyright © 2016-2018 European Support Limited * * 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 + * 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. + * 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 { actionTypes } from './HeatSetupConstants.js'; import isEqual from 'lodash/isEqual.js'; import cloneDeep from 'lodash/cloneDeep.js'; import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; -// import i18n from 'nfvo-utils/i18n/i18n.js'; -// import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; export default { + toggleVolFilesDisplay(dispatch, data) { + dispatch({ type: actionTypes.TOGGLE_VOL_DISPLAY, data }); + }, + addModule(dispatch, isBase) { dispatch({ type: actionTypes.ADD_MODULE, data: { isBase } }); }, @@ -94,7 +96,7 @@ export default { dispatch({ type: modalActionTypes.GLOBAL_MODAL_WARNING, data:{ - msg: i18n(`You have uploaded a new HEAT. If you navigate away or Check-in without proceeding to validation, + msg: i18n(`You have uploaded a new HEAT. If you navigate away or Check-in without proceeding to validation, Old HEAT zip file will be in use. new HEAT will be ignored. Do you want to continue?`), confirmationButtonText: i18n('Continue'), onConfirmed: () => resolve(), diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js index c87e9560f8..33bd7f639f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js @@ -1,17 +1,17 @@ -/*! +/* * Copyright © 2016-2018 European Support Limited * * 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 + * 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. + * 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 keyMirror from 'nfvo-utils/KeyMirror.js'; @@ -30,7 +30,8 @@ export const actionTypes = keyMirror( MANIFEST_LOADED: null, GO_TO_VALIDATION: null, - IN_VALIDATION: null + IN_VALIDATION: null, + TOGGLE_VOL_DISPLAY: null }, 'heatSetup' ); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js index 8840a11c3e..06a7147ec9 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js @@ -1,20 +1,21 @@ -/*! - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +/* + * Copyright © 2016-2018 European Support Limited * * 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 + * 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. + * 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 { actionTypes } from './HeatSetupConstants.js'; import differenceWith from 'lodash/differenceWith.js'; +import cloneDeep from 'lodash/cloneDeep'; const emptyModule = (isBase, currentLength) => ({ name: `${isBase ? 'base_' : 'module_'}${currentLength + 1}`, @@ -65,6 +66,15 @@ function addDeletedModuleFilesToUnassigned(unassigned, deletedModule) { export default (state = {}, action) => { switch (action.type) { + case actionTypes.TOGGLE_VOL_DISPLAY: + let clonedState = cloneDeep(state); + const indexToModify = findModuleIndexByName( + clonedState.modules, + action.data.module.name + ); + let modToModify = clonedState.modules[indexToModify]; + modToModify.showVolFiles = action.data.value; + return clonedState; case actionTypes.MANIFEST_LOADED: return { ...state, diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx index 1d4efd9104..d103d115f6 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx @@ -1,415 +1,26 @@ -/*! - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +/* + * Copyright © 2016-2018 European Support Limited * * 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 + * 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. + * 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 Button from 'sdc-ui/lib/react/Button.js'; -import Tooltip from 'react-bootstrap/lib/Tooltip.js'; -import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js'; -import FormControl from 'react-bootstrap/lib/FormControl.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import SelectInput from 'nfvo-components/input/SelectInput.jsx'; -import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; -import { fileTypes } from './HeatSetupConstants.js'; import { tabsMapping } from '../SoftwareProductAttachmentsConstants.js'; -import { sortable } from 'react-sortable'; - -class ListItem extends Component { - render() { - return <li {...this.props}>{this.props.children}</li>; - } -} - -const SortableListItem = sortable(ListItem); - -class SortableModuleFileList extends Component { - state = { - draggingIndex: null, - data: this.props.modules - }; - - componentWillReceiveProps(nextProps) { - this.setState({ data: nextProps.modules }); - } - - render() { - let { - unassigned, - onModuleRename, - onModuleDelete, - onModuleAdd, - onBaseAdd, - onModuleFileTypeChange, - isBaseExist, - isReadOnlyMode - } = this.props; - const childProps = module => ({ - module, - onModuleRename, - onModuleDelete, - onModuleFileTypeChange: (value, type) => - onModuleFileTypeChange({ module, value, type }), - files: unassigned - }); - let listItems = this.state.data.map(function(item, i) { - return ( - <SortableListItem - key={i} - updateState={data => this.setState(data)} - items={this.state.data} - draggingIndex={this.state.draggingIndex} - sortId={i} - outline="list"> - <ModuleFile - {...childProps(item)} - isReadOnlyMode={this.props.isReadOnlyMode} - /> - </SortableListItem> - ); - }, this); - - return ( - <div - className={`modules-list-wrapper ${ - listItems.length > 0 ? 'modules-list-wrapper-divider' : '' - }`}> - <div className="modules-list-header"> - {!isBaseExist && ( - <div> - <Button - btnType="link" - onClick={onBaseAdd} - disabled={ - isReadOnlyMode || unassigned.length === 0 - }> - {i18n('Add Base')} - </Button> - </div> - )} - <div> - <Button - btnType="link" - onClick={onModuleAdd} - disabled={ - isReadOnlyMode || unassigned.length === 0 - }> - {i18n('Add Module')} - </Button> - </div> - </div> - {listItems.length > 0 && <ul>{listItems}</ul>} - </div> - ); - } -} - -const tooltip = name => <Tooltip id="tooltip-bottom">{name}</Tooltip>; -const UnassignedFileList = props => { - return ( - <div> - <div className="modules-list-header" /> - <div className="unassigned-files"> - <div className="unassigned-files-title"> - {i18n('UNASSIGNED FILES')} - </div> - <div className="unassigned-files-list">{props.children}</div> - </div> - </div> - ); -}; - -const EmptyListContent = props => { - let { heatDataExist } = props; - let displayText = heatDataExist ? 'All Files Are Assigned' : ''; - return ( - <div className="go-to-validation-button-wrapper"> - <div className="all-files-assigned">{i18n(displayText)}</div> - </div> - ); -}; -const UnassignedFile = props => ( - <OverlayTrigger - placement="bottom" - overlay={tooltip(props.name)} - delayShow={1000}> - <li - data-test-id="unassigned-files" - className="unassigned-files-list-item"> - {props.name} - </li> - </OverlayTrigger> -); - -const AddOrDeleteVolumeFiles = ({ - add = true, - onAdd, - onDelete, - isReadOnlyMode -}) => { - const displayText = add ? 'Add Volume Files' : 'Delete Volume Files'; - const action = add ? onAdd : onDelete; - return ( - <Button - disabled={isReadOnlyMode} - onClick={action} - btnType="link" - className="add-or-delete-volumes" - iconName={add ? 'plus' : 'close'}> - {i18n(displayText)} - </Button> - ); -}; - -const SelectWithFileType = ({ type, selected, files, onChange }) => { - let filteredFiledAccordingToType = files.filter( - file => file.label.search(type.regex) > -1 - ); - if (selected) { - filteredFiledAccordingToType = filteredFiledAccordingToType.concat({ - label: selected, - value: selected - }); - } - - return ( - <SelectInput - data-test-id={`${type.label}-list`} - label={type.label} - value={selected} - onChange={value => - value !== selected && onChange(value, type.label) - } - disabled={filteredFiledAccordingToType.length === 0} - placeholder={ - filteredFiledAccordingToType.length === 0 ? '' : undefined - } - clearable={true} - options={filteredFiledAccordingToType} - /> - ); -}; - -class NameEditInput extends Component { - componentDidMount() { - this.input.focus(); - } - - render() { - return ( - <FormControl - {...this.props} - className="name-edit" - inputRef={input => (this.input = input)} - /> - ); - } -} - -class ModuleFile extends Component { - constructor(props) { - super(props); - this.state = { - isInNameEdit: false, - displayVolumes: Boolean(props.module.vol || props.module.volEnv) - }; - } - - handleSubmit(event, name) { - if (event.keyCode === 13) { - this.handleModuleRename(event, name); - } - } - - componentWillReceiveProps(nextProps) { - this.setState({ - displayVolumes: Boolean( - nextProps.module.vol || nextProps.module.volEnv - ) - }); - } - - handleModuleRename(event, name) { - this.setState({ isInNameEdit: false }); - this.props.onModuleRename(name, event.target.value); - } - - deleteVolumeFiles() { - const { onModuleFileTypeChange } = this.props; - onModuleFileTypeChange(null, fileTypes.VOL.label); - onModuleFileTypeChange(null, fileTypes.VOL_ENV.label); - this.setState({ displayVolumes: false }); - } - - renderNameAccordingToEditState() { - const { module: { name } } = this.props; - if (this.state.isInNameEdit) { - return ( - <NameEditInput - defaultValue={name} - onBlur={evt => this.handleModuleRename(evt, name)} - onKeyDown={evt => this.handleSubmit(evt, name)} - /> - ); - } - return <span className="filename-text">{name}</span>; - } - - render() { - const { - module: { name, isBase, yaml, env, vol, volEnv }, - onModuleDelete, - files, - onModuleFileTypeChange, - isReadOnlyMode - } = this.props; - const { displayVolumes } = this.state; - const moduleType = isBase ? 'BASE' : 'MODULE'; - return ( - <div className="modules-list-item" data-test-id="module-item"> - <div className="modules-list-item-controllers"> - <div className="modules-list-item-filename"> - <SVGIcon - name={isBase ? 'base' : 'module'} - color="primary" - iconClassName="heat-setup-module-icon" - /> - <span className="module-title-by-type">{`${moduleType}: `}</span> - <div - className={`text-and-icon ${ - this.state.isInNameEdit ? 'in-edit' : '' - }`}> - {this.renderNameAccordingToEditState()} - {!this.state.isInNameEdit && ( - <SVGIcon - name="pencil" - onClick={() => - this.setState({ isInNameEdit: true }) - } - data-test-id={ - isBase ? 'base-name' : 'module-name' - } - /> - )} - </div> - </div> - <SVGIcon - name="trashO" - onClick={() => onModuleDelete(name)} - data-test-id="module-delete" - /> - </div> - <div className="modules-list-item-selectors"> - <SelectWithFileType - type={fileTypes.YAML} - files={files} - selected={yaml} - onChange={onModuleFileTypeChange} - /> - <SelectWithFileType - type={fileTypes.ENV} - files={files} - selected={env} - onChange={onModuleFileTypeChange} - /> - {displayVolumes && ( - <SelectWithFileType - type={fileTypes.VOL} - files={files} - selected={vol} - onChange={onModuleFileTypeChange} - /> - )} - {displayVolumes && ( - <SelectWithFileType - type={fileTypes.VOL_ENV} - files={files} - selected={volEnv} - onChange={onModuleFileTypeChange} - /> - )} - <AddOrDeleteVolumeFiles - isReadOnlyMode={isReadOnlyMode} - onAdd={() => this.setState({ displayVolumes: true })} - onDelete={() => this.deleteVolumeFiles()} - add={!displayVolumes} - /> - </div> - </div> - ); - } -} - -class ArtifactOrNestedFileList extends Component { - render() { - let { - type, - title, - selected, - options, - onSelectChanged, - onAddAllUnassigned, - isReadOnlyMode, - headerClassName - } = this.props; - return ( - <div - className={`artifact-files ${ - type === 'nested' ? 'nested' : '' - } ${headerClassName} `}> - <div className="artifact-files-header"> - <span> - {type === 'artifact' && ( - <SVGIcon - color="primary" - name="artifacts" - iconClassName="heat-setup-module-icon" - /> - )} - {`${title}`} - </span> - {type === 'artifact' && ( - <Button - disabled={isReadOnlyMode} - btnType="link" - className="add-all-unassigned" - onClick={onAddAllUnassigned}> - {i18n('Add All Unassigned Files')} - </Button> - )} - </div> - {type === 'nested' ? ( - <ul className="nested-list"> - {selected.map(nested => ( - <li key={nested} className="nested-list-item"> - {nested} - </li> - ))} - </ul> - ) : ( - <SelectInput - options={options} - onMultiSelectChanged={onSelectChanged || (() => {})} - value={selected} - clearable={false} - placeholder={i18n('Add Artifact')} - multi - /> - )} - </div> - ); - } -} +import SortableModuleFileList from './components/SortableModuleFileList'; +import UnassignedFile from './components/UnassignedFile'; +import UnassignedFileList from './components/UnassignedFileList'; +import EmptyListContent from './components/EmptyListContent'; +import ArtifactOrNestedFileList from './components/ArtifactOrNestedFileList'; const buildLabelValueObject = str => typeof str === 'string' ? { value: str, label: str } : str; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/AddOrDeleteVolumeFiles.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/AddOrDeleteVolumeFiles.js new file mode 100644 index 0000000000..92a07ae119 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/AddOrDeleteVolumeFiles.js @@ -0,0 +1,40 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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 Button from 'sdc-ui/lib/react/Button.js'; +import i18n from 'nfvo-utils/i18n/i18n.js'; + +const AddOrDeleteVolumeFiles = ({ + add = true, + onAdd, + onDelete, + isReadOnlyMode +}) => { + const displayText = add ? 'Add Volume Files' : 'Delete Volume Files'; + const action = add ? onAdd : onDelete; + return ( + <Button + disabled={isReadOnlyMode} + onClick={action} + btnType="link" + className="add-or-delete-volumes" + iconName={add ? 'plus' : 'close'}> + {i18n(displayText)} + </Button> + ); +}; + +export default AddOrDeleteVolumeFiles; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/ArtifactOrNestedFileList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/ArtifactOrNestedFileList.js new file mode 100644 index 0000000000..c2bbde4c3d --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/ArtifactOrNestedFileList.js @@ -0,0 +1,82 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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 Button from 'sdc-ui/lib/react/Button.js'; +import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; +import SelectInput from 'nfvo-components/input/SelectInput.jsx'; + +const NestedList = ({ selected }) => ( + <ul className="nested-list"> + {selected.map(nested => ( + <li key={nested} className="nested-list-item"> + {nested} + </li> + ))} + </ul> +); + +const ArtifactOrNestedFileList = ({ + type, + title, + selected, + options, + onSelectChanged, + onAddAllUnassigned, + isReadOnlyMode, + headerClassName +}) => ( + <div + className={`artifact-files ${ + type === 'nested' ? 'nested' : '' + } ${headerClassName} `}> + <div className="artifact-files-header"> + <span> + {type === 'artifact' && ( + <SVGIcon + color="primary" + name="artifacts" + iconClassName="heat-setup-module-icon" + /> + )} + {`${title}`} + </span> + {type === 'artifact' && ( + <Button + disabled={isReadOnlyMode} + btnType="link" + className="add-all-unassigned" + onClick={onAddAllUnassigned}> + {i18n('Add All Unassigned Files')} + </Button> + )} + </div> + {type === 'nested' ? ( + <NestedList selected={selected} /> + ) : ( + <SelectInput + options={options} + onMultiSelectChanged={onSelectChanged || (() => {})} + value={selected} + clearable={false} + placeholder={i18n('Add Artifact')} + multi + /> + )} + </div> +); + +export default ArtifactOrNestedFileList; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/EmptyListContent.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/EmptyListContent.js new file mode 100644 index 0000000000..f638d10998 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/EmptyListContent.js @@ -0,0 +1,29 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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'; + +const EmptyListContent = props => { + let { heatDataExist } = props; + let displayText = heatDataExist ? 'All Files Are Assigned' : ''; + return ( + <div className="go-to-validation-button-wrapper"> + <div className="all-files-assigned">{i18n(displayText)}</div> + </div> + ); +}; + +export default EmptyListContent; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/ModuleFile.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/ModuleFile.js new file mode 100644 index 0000000000..5cc74e80df --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/ModuleFile.js @@ -0,0 +1,152 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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 SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; +import NameEditInput from './NameEditInput.js'; +import SelectWithFileType from './SelectWithFileType'; +import { fileTypes } from '../HeatSetupConstants.js'; +import AddOrDeleteVolumeFiles from './AddOrDeleteVolumeFiles'; + +class ModuleFile extends React.Component { + constructor(props) { + super(props); + this.state = { + isInNameEdit: false + }; + } + + handleSubmit(event, name) { + if (event.keyCode === 13) { + this.handleModuleRename(event, name); + } + } + + handleModuleRename(event, name) { + this.setState({ isInNameEdit: false }); + this.props.onModuleRename(name, event.target.value); + } + + deleteVolumeFiles() { + const { onModuleFileTypeChange, onToggleVolFilesDisplay } = this.props; + onModuleFileTypeChange(null, fileTypes.VOL.label); + onModuleFileTypeChange(null, fileTypes.VOL_ENV.label); + onToggleVolFilesDisplay(false); + } + + renderNameAccordingToEditState() { + const { module: { name } } = this.props; + if (this.state.isInNameEdit) { + return ( + <NameEditInput + defaultValue={name} + onBlur={evt => this.handleModuleRename(evt, name)} + onKeyDown={evt => this.handleSubmit(evt, name)} + /> + ); + } + return <span className="filename-text">{name}</span>; + } + + render() { + const { + module: { name, isBase, yaml, env, vol, volEnv }, + onModuleDelete, + files, + onModuleFileTypeChange, + onToggleVolFilesDisplay, + isReadOnlyMode, + displayVolumes + } = this.props; + + //const { displayVolumes } = this.state; + + const moduleType = isBase ? 'BASE' : 'MODULE'; + return ( + <div className="modules-list-item" data-test-id="module-item"> + <div className="modules-list-item-controllers"> + <div className="modules-list-item-filename"> + <SVGIcon + name={isBase ? 'base' : 'module'} + color="primary" + iconClassName="heat-setup-module-icon" + /> + <span className="module-title-by-type">{`${moduleType}: `}</span> + <div + className={`text-and-icon ${ + this.state.isInNameEdit ? 'in-edit' : '' + }`}> + {this.renderNameAccordingToEditState()} + {!this.state.isInNameEdit && ( + <SVGIcon + name="pencil" + onClick={() => + this.setState({ isInNameEdit: true }) + } + data-test-id={ + isBase ? 'base-name' : 'module-name' + } + /> + )} + </div> + </div> + <SVGIcon + name="trashO" + onClick={() => onModuleDelete(name)} + data-test-id="module-delete" + /> + </div> + <div className="modules-list-item-selectors"> + <SelectWithFileType + type={fileTypes.YAML} + files={files} + selected={yaml} + onChange={onModuleFileTypeChange} + /> + <SelectWithFileType + type={fileTypes.ENV} + files={files} + selected={env} + onChange={onModuleFileTypeChange} + /> + {displayVolumes && ( + <SelectWithFileType + type={fileTypes.VOL} + files={files} + selected={vol} + onChange={onModuleFileTypeChange} + /> + )} + {displayVolumes && ( + <SelectWithFileType + type={fileTypes.VOL_ENV} + files={files} + selected={volEnv} + onChange={onModuleFileTypeChange} + /> + )} + <AddOrDeleteVolumeFiles + isReadOnlyMode={isReadOnlyMode} + onAdd={() => onToggleVolFilesDisplay(true)} + onDelete={() => this.deleteVolumeFiles()} + add={!displayVolumes} + /> + </div> + </div> + ); + } +} + +export default ModuleFile; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/NameEditInput.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/NameEditInput.js new file mode 100644 index 0000000000..36821e02c2 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/NameEditInput.js @@ -0,0 +1,35 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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 FormControl from 'react-bootstrap/lib/FormControl.js'; + +class NameEditInput extends React.Component { + componentDidMount() { + this.input.focus(); + } + + render() { + return ( + <FormControl + {...this.props} + className="name-edit" + inputRef={input => (this.input = input)} + /> + ); + } +} + +export default NameEditInput; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SelectWithFileType.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SelectWithFileType.js new file mode 100644 index 0000000000..050c91e431 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SelectWithFileType.js @@ -0,0 +1,48 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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 SelectInput from 'nfvo-components/input/SelectInput.jsx'; + +const SelectWithFileType = ({ type, selected, files, onChange }) => { + let filteredFiledAccordingToType = files.filter( + file => file.label.search(type.regex) > -1 + ); + if (selected) { + filteredFiledAccordingToType = filteredFiledAccordingToType.concat({ + label: selected, + value: selected + }); + } + + return ( + <SelectInput + data-test-id={`${type.label}-list`} + label={type.label} + value={selected} + onChange={value => + value !== selected && onChange(value, type.label) + } + disabled={filteredFiledAccordingToType.length === 0} + placeholder={ + filteredFiledAccordingToType.length === 0 ? '' : undefined + } + clearable={true} + options={filteredFiledAccordingToType} + /> + ); +}; + +export default SelectWithFileType; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SortableListItem.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SortableListItem.js new file mode 100644 index 0000000000..57626438fb --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SortableListItem.js @@ -0,0 +1,21 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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 { sortable } from 'react-sortable'; + +const ListItem = props => <li {...props}>{props.children}</li>; + +export default sortable(ListItem); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SortableModuleFileList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SortableModuleFileList.js new file mode 100644 index 0000000000..f52c251361 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/SortableModuleFileList.js @@ -0,0 +1,126 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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 isEqual from 'lodash/isEqual'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import SortableListItem from './SortableListItem.js'; +import { fileTypes } from '../HeatSetupConstants.js'; + +import Button from 'sdc-ui/lib/react/Button.js'; +import ModuleFile from './ModuleFile.js'; + +class SortableModuleFileList extends React.Component { + state = { + draggingIndex: null, + data: this.props.modules + }; + + componentDidUpdate() { + if (!isEqual(this.state.data, this.props.modules)) { + /* eslint-disable-next-line */ + this.setState({ + data: this.props.modules + }); + } + } + + render() { + let { + unassigned, + onModuleRename, + onModuleDelete, + onModuleAdd, + onBaseAdd, + onModuleFileTypeChange, + onToggleVolFilesDisplay, + isBaseExist, + isReadOnlyMode + } = this.props; + const childProps = module => ({ + module, + onModuleRename, + onModuleDelete, + onModuleFileTypeChange: (value, type) => { + if ( + type === fileTypes.VOL.label || + type === fileTypes.VOL_ENV.label + ) { + onToggleVolFilesDisplay({ module, value: false }); + } + onModuleFileTypeChange({ module, value, type }); + }, + + files: unassigned, + displayVolumes: Boolean( + module.vol || module.volEnv || module.showVolFiles + ), + onToggleVolFilesDisplay: value => + onToggleVolFilesDisplay({ module, value }) + }); + + let listItems = this.state.data.map(function(item, i) { + return ( + <SortableListItem + key={i} + updateState={data => this.setState(data)} + items={this.state.data} + draggingIndex={this.state.draggingIndex} + sortId={i} + outline="list"> + <ModuleFile + {...childProps(item)} + isReadOnlyMode={this.props.isReadOnlyMode} + /> + </SortableListItem> + ); + }, this); + + return ( + <div + className={`modules-list-wrapper ${ + listItems.length > 0 ? 'modules-list-wrapper-divider' : '' + }`}> + <div className="modules-list-header"> + {!isBaseExist && ( + <div> + <Button + btnType="link" + onClick={onBaseAdd} + disabled={ + isReadOnlyMode || unassigned.length === 0 + }> + {i18n('Add Base')} + </Button> + </div> + )} + <div> + <Button + btnType="link" + onClick={onModuleAdd} + disabled={ + isReadOnlyMode || unassigned.length === 0 + }> + {i18n('Add Module')} + </Button> + </div> + </div> + {listItems.length > 0 && <ul>{listItems}</ul>} + </div> + ); + } +} + +export default SortableModuleFileList; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/UnassignedFile.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/UnassignedFile.js new file mode 100644 index 0000000000..770befc0e3 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/UnassignedFile.js @@ -0,0 +1,35 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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 OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js'; +import Tooltip from 'react-bootstrap/lib/Tooltip.js'; + +const tooltip = name => <Tooltip id="tooltip-bottom">{name}</Tooltip>; + +const UnassignedFile = props => ( + <OverlayTrigger + placement="bottom" + overlay={tooltip(props.name)} + delayShow={1000}> + <li + data-test-id="unassigned-files" + className="unassigned-files-list-item"> + {props.name} + </li> + </OverlayTrigger> +); + +export default UnassignedFile; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/UnassignedFileList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/UnassignedFileList.js new file mode 100644 index 0000000000..75fe7cdc8a --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/components/UnassignedFileList.js @@ -0,0 +1,33 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * 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'; + +const UnassignedFileList = props => { + return ( + <div> + <div className="modules-list-header" /> + <div className="unassigned-files"> + <div className="unassigned-files-title"> + {i18n('UNASSIGNED FILES')} + </div> + <div className="unassigned-files-list">{props.children}</div> + </div> + </div> + ); +}; + +export default UnassignedFileList; |