summaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src/sdc-app/onboarding/versionsPage
diff options
context:
space:
mode:
authortalig <talig@amdocs.com>2017-12-20 14:30:43 +0200
committerVitaly Emporopulo <Vitaliy.Emporopulo@amdocs.com>2017-12-21 11:12:33 +0000
commit8e9c0653dd6c6862123c9609ae34e1206d86456e (patch)
tree5eeef00ec0677133baa439ca8d7ffd7aca4804b6 /openecomp-ui/src/sdc-app/onboarding/versionsPage
parent785ebcc95de3e064e843bec04ba7a209d854fc7c (diff)
Add collaboration feature
Issue-ID: SDC-767 Change-Id: I14fb4c1f54086ed03a56a7ff7fab9ecd40381795 Signed-off-by: talig <talig@amdocs.com>
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/versionsPage')
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.js87
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.jsx77
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js90
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageConstants.js27
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageReducer.js42
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/components/PermissionsView.jsx82
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/components/VersionList.jsx129
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreation.js44
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationActionHelper.js79
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationConstants.js28
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationReducer.js44
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationView.jsx249
12 files changed, 978 insertions, 0 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.js b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.js
new file mode 100644
index 0000000000..7b6f27307d
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.js
@@ -0,0 +1,87 @@
+/*!
+ * 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 {connect} from 'react-redux';
+import VersionsPageActionHelper from './VersionsPageActionHelper.js';
+import VersionsPageCreationActionHelper from './creation/VersionsPageCreationActionHelper.js';
+import PermissionsActionHelper from '../permissions/PermissionsActionHelper.js';
+import {onboardingMethod as onboardingMethodType} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import VersionsPageView from './VersionsPage.jsx';
+
+export const mapStateToProps = ({
+ users: {userInfo},
+ versionsPage: {permissions, versionsList},
+ currentScreen: {itemPermission: {isCollaborator}, props: {itemId}},
+ softwareProductList = []
+}) => {
+
+ let {versions, selectedVersion} = versionsList;
+ let {owner, contributors, viewers} = permissions;
+
+ // sorting the version list
+ versions.sort((a,b) => {
+ let statusCompare = b.status.localeCompare(a.status);
+ if (statusCompare === 0) {
+ return b.modificationTime - a.modificationTime;
+ } else {
+ return statusCompare;
+ }
+
+ });
+
+ const curentSoftwareProduct = softwareProductList.find(item => item.id === itemId);
+ return {
+ versions,
+ contributors,
+ viewers,
+ owner,
+ currentUser: userInfo,
+ selectedVersion,
+ isCollaborator,
+ isManual: curentSoftwareProduct && curentSoftwareProduct.onboardingMethod === onboardingMethodType.MANUAL
+ };
+
+};
+
+export const mapActionsToProps = (dispatch, {itemType, itemId, additionalProps}) => {
+ return {
+ onNavigateToVersion({version}) {
+ VersionsPageActionHelper.onNavigateToVersion(dispatch, {version, itemId, itemType, additionalProps});
+ },
+
+ onSelectVersion({version}) {
+ VersionsPageActionHelper.selectVersion(dispatch, {version});
+ },
+
+ onCreateVersion({version}) {
+ VersionsPageCreationActionHelper.open(dispatch, {baseVersion: version, itemId, itemType, additionalProps});
+ },
+
+ onManagePermissions() {
+ PermissionsActionHelper.openPermissonsManager(dispatch, {itemId, askForRights: false});
+ },
+
+ onTreeFullScreen(treeProps) {
+ VersionsPageActionHelper.openTree(dispatch, treeProps);
+ },
+
+ onModalNodeClick({version}) {
+ VersionsPageActionHelper.selectVersionFromModal(dispatch, {version});
+ }
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(VersionsPageView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.jsx b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.jsx
new file mode 100644
index 0000000000..69a34e0a1c
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPage.jsx
@@ -0,0 +1,77 @@
+/*!
+ * 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 VersionList from './components/VersionList.jsx';
+import PermissionsView from './components/PermissionsView.jsx';
+import Tree from 'nfvo-components/tree/Tree.jsx';
+import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+class VersionsPage extends React.Component {
+ state = {
+ showExpanded : false
+ }
+ render() {
+ let { versions, owner, contributors, currentUser, isCollaborator, itemName = '', viewers, onSelectVersion, onNavigateToVersion,
+ onTreeFullScreen, onManagePermissions, onCreateVersion, selectedVersion, onModalNodeClick, isManual} = this.props;
+ return (
+ <div className='versions-page-view'>
+ <div className='versions-page-title'>{i18n('Available Versions - {itemName}', {itemName: itemName})}</div>
+ <PermissionsView
+ owner={owner}
+ contributors={contributors}
+ viewers={viewers}
+ currentUser={currentUser}
+ isManual={isManual}
+ onManagePermissions={onManagePermissions}/>
+ <div className='versions-page-list-and-tree'>
+ <div className='version-tree-wrapper'>
+ <div className='version-tree-title-container'>
+ <div className='version-tree-title'>{i18n('Version Tree')}</div>
+ {this.state.showExpanded && <SVGIcon name='expand' className='version-tree-full-screen' onClick={() => onTreeFullScreen({
+ name: 'versions-tree-popup',
+ width: 798,
+ height: 500,
+ nodes: versions.map(version => ({id: version.id, name: version.name, parent: version.baseId || ''})),
+ onNodeClick: (version) => onModalNodeClick({version}),
+ selectedNodeId: selectedVersion,
+ scrollable: true,
+ toWiden: true
+ })} />}
+ </div>
+ <Tree
+ name={'versions-tree'}
+ width={200}
+ allowScaleWidth={false}
+ nodes={versions.map(version => ({id: version.id, name: version.name, parent: version.baseId || ''}))}
+ onNodeClick={version => onSelectVersion({version})}
+ onRenderedBeyondWidth={() => {this.setState({showExpanded : true});}}
+ selectedNodeId={selectedVersion}/>
+ </div>
+ <VersionList
+ versions={versions}
+ onSelectVersion={onSelectVersion}
+ onNavigateToVersion={onNavigateToVersion}
+ onCreateVersion={onCreateVersion}
+ selectedVersion={selectedVersion}
+ isCollaborator={isCollaborator} />
+ </div>
+ </div>
+ );
+ }
+}
+
+export default VersionsPage;
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js
new file mode 100644
index 0000000000..52868293e2
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js
@@ -0,0 +1,90 @@
+/*!
+ * 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 ItemsHelper from '../../common/helpers/ItemsHelper.js';
+import {actionTypes} from './VersionsPageConstants.js';
+import {itemTypes} from './VersionsPageConstants.js';
+import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
+import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
+
+
+const VersionsPageActionHelper = {
+ fetchVersions(dispatch, {itemType, itemId}) {
+ return ItemsHelper.fetchVersions({itemId}).then(response => {
+ dispatch({
+ type: actionTypes.VERSIONS_LOADED,
+ versions: response.results,
+ itemType,
+ itemId
+ });
+ });
+ },
+
+ selectVersion(dispatch, {version}) {
+ dispatch({
+ type: actionTypes.SELECT_VERSION,
+ versionId: version.id
+ });
+ },
+
+ selectNone(dispatch) {
+ dispatch({ type: actionTypes.SELECT_NONE });
+ },
+
+ onNavigateToVersion(dispatch, {version, itemId, itemType}) {
+ switch (itemType) {
+ case itemTypes.LICENSE_MODEL:
+ ScreensHelper.loadScreen(dispatch, {
+ screen: enums.SCREEN.LICENSE_MODEL_OVERVIEW, screenType: screenTypes.LICENSE_MODEL,
+ props: {licenseModelId: itemId, version}
+ });
+ break;
+ case itemTypes.SOFTWARE_PRODUCT:
+ ScreensHelper.loadScreen(dispatch, {
+ screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
+ props: {softwareProductId: itemId, version}
+ });
+ break;
+ }
+ },
+
+ openTree(dispatch, treeProps) {
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_SHOW,
+ data: {
+ modalComponentName: modalContentMapper.VERSION_TREE,
+ modalComponentProps: treeProps,
+ onDeclined: () => dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_CLOSE
+ }),
+ modalClassName: 'versions-tree-modal',
+ cancelButtonText: i18n('Close'),
+ title: i18n('Version Tree')
+ }
+ });
+ },
+
+ selectVersionFromModal(dispatch, {version}) {
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_CLOSE
+ });
+ this.selectVersion(dispatch, {version});
+ }
+};
+
+export default VersionsPageActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageConstants.js b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageConstants.js
new file mode 100644
index 0000000000..983ab79a14
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageConstants.js
@@ -0,0 +1,27 @@
+/*!
+ * 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 keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+ VERSIONS_LOADED: null,
+ SELECT_VERSION: null,
+ SELECT_NONE: null
+});
+
+export const itemTypes = {
+ LICENSE_MODEL: 'vendor-license-models',
+ SOFTWARE_PRODUCT: 'vendor-software-products'
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageReducer.js b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageReducer.js
new file mode 100644
index 0000000000..9b6fa9f803
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/VersionsPageReducer.js
@@ -0,0 +1,42 @@
+/*!
+ * 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 {actionTypes} from './VersionsPageConstants.js';
+import {combineReducers} from 'redux';
+import VersionsPageCreationReducer from './creation/VersionsPageCreationReducer.js';
+import PermissionsReducer from '../permissions/PermissionsReducer.js';
+import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js';
+
+function VersionsListReducer(state = {}, action) {
+ switch (action.type) {
+ case actionTypes.VERSIONS_LOADED:
+ let {versions, itemType = state.itemType, itemId} = action;
+ return {...state, versions, itemType, itemId};
+ case actionTypes.SELECT_VERSION:
+ return {...state, selectedVersion: action.versionId === state.selectedVersion ? null : action.versionId};
+ case actionTypes.SELECT_NONE:
+ return {...state, selectedVersion: null};
+ default:
+ return state;
+ }
+};
+
+
+
+export default combineReducers({
+ versionCreation: createPlainDataReducer(VersionsPageCreationReducer),
+ versionsList: VersionsListReducer,
+ permissions: PermissionsReducer
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/components/PermissionsView.jsx b/openecomp-ui/src/sdc-app/onboarding/versionsPage/components/PermissionsView.jsx
new file mode 100644
index 0000000000..26f8450f4c
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/components/PermissionsView.jsx
@@ -0,0 +1,82 @@
+/*!
+ * 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';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+
+const maxContributors = 6;
+
+function extraUsersTooltip (extraUsers) {
+ return (
+ <Tooltip className='extra-users-tooltip' id='extra-users-tooltip-id'>
+ {extraUsers.map(extraUser => <div key={extraUser.userId} className='extra-user'>{extraUser.fullName}</div>)}
+ </Tooltip>
+ );
+}
+
+const User = ({user, isCurrentUser, dataTestId}) => (
+ <SVGIcon className={`user-view ${isCurrentUser ? 'current-user' : ''}`} name='user' label={user.fullName} labelPosition='right' color='primary'
+ data-test-id={dataTestId}/>
+);
+
+const Owner = ({owner, isCurrentUser}) => (
+ <div className='owner-view'>
+ <div className='permissions-view-title'>{i18n('Owner')}</div>
+ <User user={owner} isCurrentUser={isCurrentUser} dataTestId='owner'/>
+ </div>
+);
+
+const Contributors = ({contributors, owner, currentUser, onManagePermissions, isManual}) => {
+ let extraUsers = contributors.length - maxContributors;
+ return (
+ <div className='contributors-view'>
+ <div className='permissions-view-title'>{i18n('Contributors')}</div>
+ {contributors.slice(0, maxContributors).map(contributor =>
+ <User key={contributor.userId} user={contributor} isCurrentUser={contributor.userId === currentUser.userId} dataTestId='contributor'/>
+ )}
+ {extraUsers > 0 &&
+ <OverlayTrigger placement='bottom' overlay={extraUsersTooltip(contributors.slice(maxContributors))}>
+ <div className='extra-contributors'>{`+${extraUsers}`}</div>
+ </OverlayTrigger>
+ }
+ {currentUser.userId === owner.userId && !isManual &&
+ <span
+ className='manage-permissions'
+ onClick={onManagePermissions}
+ data-test-id='versions-page-manage-permissions'>
+ {i18n('Manage Permissions')}
+ </span>
+ }
+ </div>
+ );
+};
+
+const PermissionsView = ({owner, contributors, currentUser = {}, onManagePermissions, isManual}) => (
+ <div className='versions-page-permissions-view-wrapper'>
+ <div className='permissions-view-wrapper-title'>{i18n('Permissions')}</div>
+ <div className='permissions-view-content'>
+ <div className='permissions-view'>
+ <Owner owner={owner} isCurrentUser={owner.userId === currentUser.userId} />
+ <Contributors owner={owner} contributors={contributors} currentUser={currentUser} onManagePermissions={onManagePermissions} isManual={isManual}/>
+ </div>
+ </div>
+ </div>
+);
+
+export default PermissionsView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/components/VersionList.jsx b/openecomp-ui/src/sdc-app/onboarding/versionsPage/components/VersionList.jsx
new file mode 100644
index 0000000000..f209d80125
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/components/VersionList.jsx
@@ -0,0 +1,129 @@
+/*!
+ * 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 OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
+
+const formatTime = (time) => {
+ if (!time) { return ''; }
+
+ const date = new Date(time);
+ const options = {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit'
+ };
+ const newDate = date.toLocaleTimeString('en-US', options);
+
+ return newDate;
+};
+
+const DescriptionField = ({ className, text, useTooltip }) => {
+ if (useTooltip) {
+ return (
+ <div className={className}>
+ <OverlayTrigger
+ placement='bottom'
+ overlay={<Tooltip className='version-description-tooltip' id='version-description-tooltip'>{text}</Tooltip>}>
+ <div className='description-text'>{text}</div>
+ </OverlayTrigger>
+ </div>
+ );
+ }
+ return <div className={className}>{text}</div>;
+};
+
+const VersionListItem = ({ data, onSelectVersion, onNavigateToVersion, onCreateVersion, isHeader, isSelected, isCollaborator }) => {
+
+ let {modificationTime, name, status, description, additionalInfo} = data;
+ const modificationText = !isHeader ? formatTime(modificationTime) : i18n('Last Edited On');
+
+ return (
+ <div
+ data-test-id='version-item-row'
+ className={`version-item-row ${isHeader ? 'header-row' : 'clickable'} ${isSelected ? 'selected' : ''}`}
+ onClick={e => {
+ e.stopPropagation();
+ onSelectVersion();
+ onNavigateToVersion();
+ }}>
+ <div className={`version-item-field ${isHeader ? 'header-field item-version' : 'item-version'}`}>{name}</div>
+ <div className={`version-item-field ${isHeader ? 'header-field item-status' : 'item-status'}`}>{status}</div>
+ <div className={`version-item-field ${isHeader ? 'header-field' : 'item-last-edited'}`}>{modificationText}</div>
+ <DescriptionField
+ className={`version-item-field ${isHeader ? 'header-field header-description' : 'item-description'}`}
+ useTooltip={!isHeader && description}
+ text={description} />
+
+ {
+ isHeader ?
+ <div className='version-item-field header-field actions'>{i18n('Actions')}</div>
+ :
+ <div className='version-item-field item-actions'>
+ <div className='version-item-field item-select'>
+ <SVGIcon
+ name='check-circle'
+ data-test-id='versions-page-select-version'
+ onClick={e => {e.stopPropagation(); onNavigateToVersion();}}
+ label={i18n('Go to this Version')}
+ labelPosition='right' />
+ </div>
+ <div className='version-item-field item-create'>
+ {!isHeader && isCollaborator && additionalInfo.OptionalCreationMethods.length > 0 &&
+ <SVGIcon
+ name='plus-circle'
+ data-test-id='versions-page-create-version'
+ onClick={e => { e.stopPropagation(); onCreateVersion(); }}
+ label={i18n('Create New Version')}
+ labelPosition='right'
+ disabled={!isCollaborator} />
+ }
+ </div>
+ </div>
+ }
+
+
+ </div>
+ );
+
+};
+
+const VersionList = ({ versions, onSelectVersion, onNavigateToVersion, onCreateVersion, selectedVersion, isCollaborator }) => (
+ <div className='version-list'>
+ <VersionListItem
+ data={{ name: i18n('Version'), status: i18n('Status'), description: i18n('Description') }}
+ isHeader />
+ <div className='version-list-items'>
+ {versions.map(version =>
+ <VersionListItem
+ key={version.id}
+ data={version}
+ onSelectVersion={() => onSelectVersion({version})}
+ onNavigateToVersion={() => onNavigateToVersion({version})}
+ onCreateVersion={() => onCreateVersion({version})}
+ isSelected={selectedVersion === version.id}
+ isCollaborator={isCollaborator} />
+ )}
+ </div>
+ </div>
+);
+
+export default VersionList;
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreation.js b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreation.js
new file mode 100644
index 0000000000..66c1c79be5
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreation.js
@@ -0,0 +1,44 @@
+/*!
+ * 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 {connect} from 'react-redux';
+import VersionsPageCreationActionHelper from './VersionsPageCreationActionHelper.js';
+import VersionsPageActionHelper from '../VersionsPageActionHelper.js';
+import VersionsPageCreationView from './VersionsPageCreationView.jsx';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import {VERSION_CREATION_FORM_NAME} from './VersionsPageCreationConstants.js';
+
+export const mapStateToProps = ({versionsPage: {versionCreation}}) => {
+ let {genericFieldInfo} = versionCreation;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+
+ return {...versionCreation, isFormValid};
+};
+
+export const mapActionsToProps = (dispatch, {itemId, itemType, additionalProps}) => {
+ return {
+ onDataChanged: (deltaData, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: VERSION_CREATION_FORM_NAME, customValidations}),
+ onCancel: () => VersionsPageCreationActionHelper.close(dispatch),
+ onSubmit: ({baseVersion, payload}) => {
+ VersionsPageCreationActionHelper.close(dispatch);
+ VersionsPageCreationActionHelper.createVersion(dispatch, {baseVersion, itemId, payload}).then(response => {
+ VersionsPageActionHelper.onNavigateToVersion(dispatch, {version: response, itemId, itemType, additionalProps});
+ });
+ },
+ onValidateForm: () => ValidationHelper.validateForm(dispatch, VERSION_CREATION_FORM_NAME)
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(VersionsPageCreationView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationActionHelper.js
new file mode 100644
index 0000000000..bc038689a4
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationActionHelper.js
@@ -0,0 +1,79 @@
+/*!
+ * 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 RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import {actionTypes} from './VersionsPageCreationConstants.js';
+import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
+import {actionTypes as VersionsPageActionTypes} from '../VersionsPageConstants.js';
+
+function baseUrl({itemId, baseVersion}) {
+ const restPrefix = Configuration.get('restPrefix');
+ return `${restPrefix}/v1.0/items/${itemId}/versions/${baseVersion.id}/`;
+}
+
+function createVersion({itemId, baseVersion, payload: {description, creationMethod} }) {
+ return RestAPIUtil.post(baseUrl({itemId, baseVersion}), {description, creationMethod});
+}
+
+
+export default {
+
+ open(dispatch, {itemType, itemId, additionalProps, baseVersion}) {
+ dispatch({
+ type: actionTypes.OPEN
+ });
+
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_SHOW,
+ data: {
+ modalComponentName: modalContentMapper.VERSION_CREATION,
+ modalComponentProps: {itemType, itemId, additionalProps, baseVersion},
+ title: i18n('New Version - From {name}', {name: baseVersion.name})
+ }
+ });
+ },
+
+ close(dispatch){
+ dispatch({
+ type: actionTypes.CLOSE
+ });
+
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_CLOSE
+ });
+ },
+
+ createVersion(dispatch, {itemId, baseVersion, payload}){
+ return createVersion({itemId, baseVersion, payload}).then(result => {
+ return ItemsHelper.fetchVersions({itemId}).then(response => {
+ dispatch({
+ type: VersionsPageActionTypes.VERSIONS_LOADED,
+ versions: response.results,
+ itemId
+ });
+ dispatch({
+ type: actionTypes.VERSION_CREATED,
+ result
+ });
+ return result;
+ });
+ });
+ }
+
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationConstants.js b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationConstants.js
new file mode 100644
index 0000000000..4ce381d4de
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationConstants.js
@@ -0,0 +1,28 @@
+/*!
+ * 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 keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+ OPEN: null,
+ CLOSE: null,
+ VERSION_CREATED: null
+});
+
+export const VERSION_CREATION_FORM_NAME = 'VCREATIONFORM';
+
+export const defaultState = {
+ creationMethod: 'major'
+}; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationReducer.js b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationReducer.js
new file mode 100644
index 0000000000..620cf4717f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationReducer.js
@@ -0,0 +1,44 @@
+/*!
+ * 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 {actionTypes, VERSION_CREATION_FORM_NAME, defaultState} from './VersionsPageCreationConstants.js';
+
+export default (state = {}, action) => {
+ switch (action.type) {
+ case actionTypes.OPEN:
+ return {
+ ...state,
+ formReady: null,
+ formName: VERSION_CREATION_FORM_NAME,
+ data: {...defaultState},
+ genericFieldInfo: {
+ description: {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
+ },
+ creationMethod: {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ }
+ }
+ };
+ case actionTypes.CLOSE:
+ return {};
+ default:
+ return state;
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationView.jsx
new file mode 100644
index 0000000000..caa85fe107
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/versionsPage/creation/VersionsPageCreationView.jsx
@@ -0,0 +1,249 @@
+/*!
+ * 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 PropTypes from 'prop-types';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+
+const VersionPropType = PropTypes.shape({
+ name: PropTypes.string,
+ description: PropTypes.string,
+ creationMethod: PropTypes.string
+});
+
+class VersionsPageCreationView extends React.Component {
+
+ static propTypes = {
+ data: VersionPropType,
+ availableMethods: PropTypes.array,
+ onDataChanged: PropTypes.func.isRequired,
+ onSubmit: PropTypes.func.isRequired,
+ onCancel: PropTypes.func.isRequired
+ };
+
+ render() {
+ let {data = {}, genericFieldInfo, baseVersion, onDataChanged, onCancel} = this.props;
+ let {additionalInfo: {OptionalCreationMethods}} = baseVersion;
+ let {description, creationMethod} = data;
+
+ return (
+ <div className='version-creation-page'>
+ { genericFieldInfo && <Form
+ ref={(validationForm) => this.validationForm = validationForm}
+ hasButtons={true}
+ onSubmit={() => this.submit()}
+ submitButtonText={i18n('Create')}
+ onReset={() => onCancel()}
+ labledButtons={true}
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.validate()}>
+
+ <div className='version-form-row'>
+ <Input
+ label={i18n('Version Category')}
+ value={creationMethod}
+ onChange={e => this.onSelectMethod(e)}
+ type='select'
+ overlayPos='bottom'
+ data-test-id='new-version-category'
+ isValid={genericFieldInfo.creationMethod.isValid}
+ errorText={genericFieldInfo.creationMethod.errorText}
+ isRequired>
+ <option key='' value=''>{i18n('Please select…')}</option>
+ {OptionalCreationMethods.map(method => <option key={method} value={method}>{i18n(method)}</option>)}
+ </Input>
+ </div>
+
+ <div className='version-form-row'>
+ <Input
+ label={i18n('Description')}
+ value={description}
+ type='text'
+ overlayPos='bottom'
+ data-test-id='new-version-description'
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
+ onChange={description => onDataChanged({description})}
+ isRequired />
+ </div>
+
+ </Form> }
+ </div>
+ );
+ }
+
+ onSelectMethod(e) {
+ const selectedIndex = e.target.selectedIndex;
+ const creationMethod = e.target.options[selectedIndex].value;
+ this.props.onDataChanged({creationMethod});
+ }
+
+ submit() {
+ let {baseVersion, data: {description, creationMethod}} = this.props;
+ this.props.onSubmit({baseVersion, payload: {description, creationMethod}});
+ }
+
+ validate() {
+ this.props.onValidateForm();
+ }
+
+}
+
+export default VersionsPageCreationView;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ <div className='software-product-inline-section'>
+ <Input
+ value={name}
+ label={i18n('Name')}
+ isRequired={true}
+ onChange={name => onDataChanged({name},V_CREATION_FORM_NAME, {name: name => this.validateName(name)})}
+ isValid={genericFieldInfo.name.isValid}
+ errorText={genericFieldInfo.name.errorText}
+ type='text'
+ className='field-section'
+ data-test-id='new-vsp-name' />
+ <Input
+ label={i18n('Vendor')}
+ type='select'
+ value={vendorId}
+ isRequired={true}
+ disabled={disableVendor}
+ onChange={e => this.onSelectVendor(e)}
+ isValid={genericFieldInfo.vendorId.isValid}
+ errorText={genericFieldInfo.vendorId.errorText}
+ className='input-options-select'
+ groupClassName='bootstrap-input-options'
+ data-test-id='new-vsp-vendor' >
+ {vendorList.map(vendor =>
+ <option key={vendor.title} value={vendor.enum}>{vendor.title}</option>)}
+ </Input>
+ <Input
+ label={i18n('Category')}
+ type='select'
+ value={subCategory}
+ isRequired={true}
+ onChange={e => this.onSelectSubCategory(e)}
+ isValid={genericFieldInfo.subCategory.isValid}
+ errorText={genericFieldInfo.subCategory.errorText}
+ className='input-options-select'
+ groupClassName='bootstrap-input-options'
+ data-test-id='new-vsp-category' >
+ <option key='' value=''>{i18n('please select…')}</option>
+ {softwareProductCategories.map(category =>
+ category.subcategories &&
+ <optgroup
+ key={category.name}
+ label={category.name}>{category.subcategories.map(sub =>
+ <option key={sub.uniqueId} value={sub.uniqueId}>{`${sub.name} (${category.name})`}</option>)}
+ </optgroup>)
+ }
+ </Input>
+ </div>
+ <div className='software-product-inline-section'>
+ <Input
+ value={description}
+ label={i18n('Description')}
+ isRequired={true}
+ overlayPos='bottom'
+ onChange={description => onDataChanged({description},V_CREATION_FORM_NAME)}
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
+ type='textarea'
+ className='field-section'
+ data-test-id='new-vsp-description' />
+ </div>
+ </div>
+ </Form>}
+ </div>
+ );
+ }
+
+ getAvailableMethodsList() {
+ let {availableMethods} = this.props;
+ return [...availableMethods];
+ }
+
+ onSelectVendor(e) {
+ const selectedIndex = e.target.selectedIndex;
+ const vendorId = e.target.options[selectedIndex].value;
+ this.props.onDataChanged({vendorId},V_CREATION_FORM_NAME);
+ }
+
+ onSelectSubCategory(e) {
+ const selectedIndex = e.target.selectedIndex;
+ const subCategory = e.target.options[selectedIndex].value;
+ let {softwareProductCategories, onDataChanged} = this.props;
+ let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory(subCategory, softwareProductCategories);
+ onDataChanged({category, subCategory},V_CREATION_FORM_NAME);
+ }
+
+ submit() {
+ let {data:softwareProduct, finalizedLicenseModelList} = this.props;
+ softwareProduct.vendorName = finalizedLicenseModelList.find(vendor => vendor.id === softwareProduct.vendorId).name;
+ this.props.onSubmit(softwareProduct);
+ }
+
+ validateName(value) {
+ const {data: {id}, VSPNames} = this.props;
+ const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: VSPNames});
+
+ return !isExists ? {isValid: true, errorText: ''} :
+ {isValid: false, errorText: i18n('Software product by the name \'' + value + '\' already exists. Software product name must be unique')};
+ }
+
+ validate() {
+ this.props.onValidateForm(SP_CREATION_FORM_NAME);
+ }
+}
+
+export default SoftwareProductCreationView;
+*/